]> 4ch.mooo.com Git - 16.git/blob - 16/adplug/adplug-2.2.1/src/dtm.cpp
Please enter the commit message for your changes. Lines starting
[16.git] / 16 / adplug / adplug-2.2.1 / src / dtm.cpp
1 /*
2   Adplug - Replayer for many OPL2/OPL3 audio file formats.
3   Copyright (C) 1999 - 2006 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   dtm.cpp - DTM loader by Riven the Mage <riven@ok.ru>
20 */
21 /*
22   NOTE: Panning (Ex) effect is ignored.
23 */
24
25 #include <cstring>
26 #include "dtm.h"
27
28 /* -------- Public Methods -------------------------------- */
29
30 CPlayer *CdtmLoader::factory(Copl *newopl)
31 {
32   return new CdtmLoader(newopl);
33 }
34
35 bool CdtmLoader::load(const std::string &filename, const CFileProvider &fp)
36 {
37   binistream *f = fp.open(filename); if(!f) return false;
38   const unsigned char conv_inst[11] = { 2,1,10,9,4,3,6,5,0,8,7 };
39   const unsigned short conv_note[12] = { 0x16B, 0x181, 0x198, 0x1B0, 0x1CA, 0x1E5, 0x202, 0x220, 0x241, 0x263, 0x287, 0x2AE };
40   int i,j,k,t=0;
41
42   // read header
43   f->readString(header.id, 12);
44   header.version = f->readInt(1);
45   f->readString(header.title, 20); f->readString(header.author, 20);
46   header.numpat = f->readInt(1); header.numinst = f->readInt(1);
47
48   // signature exists ? good version ?
49   if(memcmp(header.id,"DeFy DTM ",9) || header.version != 0x10)
50     { fp.close (f); return false; }
51
52   header.numinst++;
53
54   // load description
55   memset(desc,0,80*16);
56
57   char bufstr[80];
58
59   for (i=0;i<16;i++)
60     {
61       // get line length
62       unsigned char bufstr_length = f->readInt(1);
63
64       if(bufstr_length > 80) {
65         fp.close(f);
66         return false;
67       }
68
69       // read line
70       if (bufstr_length)
71         {
72           f->readString(bufstr,bufstr_length);
73
74           for (j=0;j<bufstr_length;j++)
75             if (!bufstr[j])
76               bufstr[j] = 0x20;
77
78           bufstr[bufstr_length] = 0;
79
80           strcat(desc,bufstr);
81         }
82
83       strcat(desc,"\n");
84     }
85
86   // init CmodPlayer
87   realloc_instruments(header.numinst);
88   realloc_order(100);
89   realloc_patterns(header.numpat,64,9);
90   init_notetable(conv_note);
91   init_trackord();
92
93   // load instruments
94   for (i=0;i<header.numinst;i++)
95     {
96       unsigned char name_length = f->readInt(1);
97
98       if (name_length)
99         f->readString(instruments[i].name, name_length);
100
101       instruments[i].name[name_length] = 0;
102
103       for(j = 0; j < 12; j++)
104         instruments[i].data[j] = f->readInt(1);
105
106       for (j=0;j<11;j++)
107         inst[i].data[conv_inst[j]] = instruments[i].data[j];
108     }
109
110   // load order
111   for(i = 0; i < 100; i++) order[i] = f->readInt(1);
112
113   nop = header.numpat;
114
115   unsigned char *pattern = new unsigned char [0x480];
116
117   // load tracks
118   for (i=0;i<nop;i++)
119     {
120       unsigned short packed_length;
121
122       packed_length = f->readInt(2);
123
124       unsigned char *packed_pattern = new unsigned char [packed_length];
125
126       for(j = 0; j < packed_length; j++)
127         packed_pattern[j] = f->readInt(1);
128
129       long unpacked_length = unpack_pattern(packed_pattern,packed_length,pattern,0x480);
130
131       delete [] packed_pattern;
132
133       if (!unpacked_length)
134         {
135           delete pattern;
136           fp.close(f);
137           return false;
138         }
139
140       // convert pattern
141       for (j=0;j<9;j++)
142         {
143           for (k=0;k<64;k++)
144             {
145               dtm_event *event = (dtm_event *)&pattern[(k*9+j)*2];
146
147               // instrument
148               if (event->byte0 == 0x80)
149                 {
150                   if (event->byte1 <= 0x80)
151                     tracks[t][k].inst = event->byte1 + 1;
152                 }
153
154               // note + effect
155               else
156                 {
157                   tracks[t][k].note = event->byte0;
158
159                   if ((event->byte0 != 0) && (event->byte0 != 127))
160                     tracks[t][k].note++;
161
162                   // convert effects
163                   switch (event->byte1 >> 4)
164                     {
165                     case 0x0: // pattern break
166                       if ((event->byte1 & 15) == 1)
167                         tracks[t][k].command = 13;
168                       break;
169
170                     case 0x1: // freq. slide up
171                       tracks[t][k].command = 28;
172                       tracks[t][k].param1 = event->byte1 & 15;
173                       break;
174
175                     case 0x2: // freq. slide down
176                       tracks[t][k].command = 28;
177                       tracks[t][k].param2 = event->byte1 & 15;
178                       break;
179
180                     case 0xA: // set carrier volume
181                     case 0xC: // set instrument volume
182                       tracks[t][k].command = 22;
183                       tracks[t][k].param1 = (0x3F - (event->byte1 & 15)) >> 4;
184                       tracks[t][k].param2 = (0x3F - (event->byte1 & 15)) & 15;
185                       break;
186
187                     case 0xB: // set modulator volume
188                       tracks[t][k].command = 21;
189                       tracks[t][k].param1 = (0x3F - (event->byte1 & 15)) >> 4;
190                       tracks[t][k].param2 = (0x3F - (event->byte1 & 15)) & 15;
191                       break;
192
193                     case 0xE: // set panning
194                       break;
195
196                     case 0xF: // set speed
197                       tracks[t][k].command = 13;
198                       tracks[t][k].param2 = event->byte1 & 15;
199                       break;
200                     }
201                 }
202             }
203
204           t++;
205         }
206     }
207
208   delete [] pattern;
209   fp.close(f);
210
211   // order length
212   for (i=0;i<100;i++)
213     {
214       if (order[i] >= 0x80)
215         {
216           length = i;
217
218           if (order[i] == 0xFF)
219             restartpos = 0;
220           else
221             restartpos = order[i] - 0x80;
222
223           break;
224         }
225     }
226
227   // initial speed
228   initspeed = 2;
229
230   rewind(0);
231
232   return true;
233 }
234
235 void CdtmLoader::rewind(int subsong)
236 {
237   CmodPlayer::rewind(subsong);
238
239   // default instruments
240   for (int i=0;i<9;i++)
241     {
242       channel[i].inst = i;
243
244       channel[i].vol1 = 63 - (inst[i].data[10] & 63);
245       channel[i].vol2 = 63 - (inst[i].data[9] & 63);
246     }
247 }
248
249 float CdtmLoader::getrefresh()
250 {
251   return 18.2f;
252 }
253
254 std::string CdtmLoader::gettype()
255 {
256   return std::string("DeFy Adlib Tracker");
257 }
258
259 std::string CdtmLoader::gettitle()
260 {
261   return std::string(header.title);
262 }
263
264 std::string CdtmLoader::getauthor()
265 {
266   return std::string(header.author);
267 }
268
269 std::string CdtmLoader::getdesc()
270 {
271   return std::string(desc);
272 }
273
274 std::string CdtmLoader::getinstrument(unsigned int n)
275 {
276   return std::string(instruments[n].name);
277 }
278
279 unsigned int CdtmLoader::getinstruments()
280 {
281   return header.numinst;
282 }
283
284 /* -------- Private Methods ------------------------------- */
285
286 long CdtmLoader::unpack_pattern(unsigned char *ibuf, long ilen, unsigned char *obuf, long olen)
287 {
288   unsigned char *input = ibuf;
289   unsigned char *output = obuf;
290
291   long input_length = 0;
292   long output_length = 0;
293
294   unsigned char repeat_byte, repeat_counter;
295
296   // RLE
297   while (input_length < ilen)
298     {
299       repeat_byte = input[input_length++];
300
301       if ((repeat_byte & 0xF0) == 0xD0)
302         {
303           repeat_counter = repeat_byte & 15;
304           repeat_byte = input[input_length++];
305         }
306       else
307         repeat_counter = 1;
308
309       for (int i=0;i<repeat_counter;i++)
310         {
311           if (output_length < olen)
312             output[output_length++] = repeat_byte;
313         }
314     }
315
316   return output_length;
317 }