|
359
|
1 /*
|
|
|
2 * Adplug - Replayer for many OPL2/OPL3 audio file formats.
|
|
|
3 * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al.
|
|
|
4 *
|
|
|
5 * This library is free software; you can redistribute it and/or
|
|
|
6 * modify it under the terms of the GNU Lesser General Public
|
|
|
7 * License as published by the Free Software Foundation; either
|
|
|
8 * version 2.1 of the License, or (at your option) any later version.
|
|
|
9 *
|
|
|
10 * This library is distributed in the hope that it will be useful,
|
|
|
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
13 * Lesser General Public License for more details.
|
|
|
14 *
|
|
|
15 * You should have received a copy of the GNU Lesser General Public
|
|
|
16 * License along with this library; if not, write to the Free Software
|
|
|
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
18 *
|
|
|
19 * mtk.cpp - MPU-401 Trakker Loader by Simon Peter (dn.tlp@gmx.net)
|
|
|
20 */
|
|
|
21
|
|
|
22 #include "mtk.h"
|
|
|
23
|
|
|
24 /*** public methods **************************************/
|
|
|
25
|
|
|
26 CPlayer *CmtkLoader::factory(Copl *newopl)
|
|
|
27 {
|
|
|
28 return new CmtkLoader(newopl);
|
|
|
29 }
|
|
|
30
|
|
|
31 bool CmtkLoader::load(const std::string &filename, const CFileProvider &fp)
|
|
|
32 {
|
|
|
33 binistream *f = fp.open(filename); if(!f) return false;
|
|
|
34 struct {
|
|
|
35 char id[18];
|
|
|
36 unsigned short crc,size;
|
|
|
37 } header;
|
|
|
38 struct mtkdata {
|
|
|
39 char songname[34],composername[34],instname[0x80][34];
|
|
|
40 unsigned char insts[0x80][12],order[0x80],dummy,patterns[0x32][0x40][9];
|
|
|
41 } *data;
|
|
|
42 unsigned char *cmp,*org;
|
|
|
43 unsigned int i;
|
|
|
44 unsigned long cmpsize,cmpptr=0,orgptr=0;
|
|
|
45 unsigned short ctrlbits=0,ctrlmask=0,cmd,cnt,offs;
|
|
|
46
|
|
|
47 // read header
|
|
|
48 f->readString(header.id, 18);
|
|
|
49 header.crc = f->readInt(2);
|
|
|
50 header.size = f->readInt(2);
|
|
|
51
|
|
|
52 // file validation section
|
|
|
53 if(strncmp(header.id,"mpu401tr\x92kk\xeer@data",18))
|
|
|
54 { fp.close(f); return false; }
|
|
|
55
|
|
|
56 // load section
|
|
|
57 cmpsize = fp.filesize(f) - 22;
|
|
|
58 cmp = new unsigned char[cmpsize];
|
|
|
59 org = new unsigned char[header.size];
|
|
|
60 for(i = 0; i < cmpsize; i++) cmp[i] = f->readInt(1);
|
|
|
61 fp.close(f);
|
|
|
62
|
|
|
63 while(cmpptr < cmpsize) { // decompress
|
|
|
64 ctrlmask >>= 1;
|
|
|
65 if(!ctrlmask) {
|
|
|
66 ctrlbits = cmp[cmpptr] + (cmp[cmpptr + 1] << 8);
|
|
|
67 cmpptr += 2;
|
|
|
68 ctrlmask = 0x8000;
|
|
|
69 }
|
|
|
70 if(!(ctrlbits & ctrlmask)) { // uncompressed data
|
|
|
71 org[orgptr] = cmp[cmpptr];
|
|
|
72 orgptr++; cmpptr++;
|
|
|
73 continue;
|
|
|
74 }
|
|
|
75
|
|
|
76 // compressed data
|
|
|
77 cmd = (cmp[cmpptr] >> 4) & 0x0f;
|
|
|
78 cnt = cmp[cmpptr] & 0x0f;
|
|
|
79 cmpptr++;
|
|
|
80 switch(cmd) {
|
|
|
81 case 0: cnt += 3; memset(&org[orgptr],cmp[cmpptr],cnt); cmpptr++; orgptr += cnt; break;
|
|
|
82 case 1: cnt += (cmp[cmpptr] << 4) + 19; memset(&org[orgptr],cmp[++cmpptr],cnt); cmpptr++; orgptr += cnt; break;
|
|
|
83 case 2: offs = (cnt+3) + (cmp[cmpptr] << 4); cnt = cmp[++cmpptr] + 16; cmpptr++;
|
|
|
84 memcpy(&org[orgptr],&org[orgptr - offs],cnt); orgptr += cnt; break;
|
|
|
85 default: offs = (cnt+3) + (cmp[cmpptr++] << 4); memcpy(&org[orgptr],&org[orgptr-offs],cmd); orgptr += cmd; break;
|
|
|
86 }
|
|
|
87 }
|
|
|
88 delete [] cmp;
|
|
|
89 data = (struct mtkdata *) org;
|
|
|
90
|
|
|
91 // convert to HSC replay data
|
|
|
92 memset(title,0,34); strncpy(title,data->songname+1,33);
|
|
|
93 memset(composer,0,34); strncpy(composer,data->composername+1,33);
|
|
|
94 memset(instname,0,0x80*34);
|
|
|
95 for(i=0;i<0x80;i++)
|
|
|
96 strncpy(instname[i],data->instname[i]+1,33);
|
|
|
97 memcpy(instr,data->insts,0x80 * 12);
|
|
|
98 memcpy(song,data->order,0x80);
|
|
|
99 memcpy(patterns,data->patterns,header.size-6084);
|
|
|
100 for (i=0;i<128;i++) { // correct instruments
|
|
|
101 instr[i][2] ^= (instr[i][2] & 0x40) << 1;
|
|
|
102 instr[i][3] ^= (instr[i][3] & 0x40) << 1;
|
|
|
103 instr[i][11] >>= 4; // make unsigned
|
|
|
104 }
|
|
|
105
|
|
|
106 delete [] org;
|
|
|
107 rewind(0);
|
|
|
108 return true;
|
|
|
109 }
|