Mercurial > audlegacy
annotate Plugins/Input/adplug/core/dtm.cpp @ 1458:f12d7e208b43 trunk
[svn] Update FSF address in copyright notices. Update autotools templates.
author | chainsaw |
---|---|
date | Wed, 02 Aug 2006 15:44:07 -0700 |
parents | c71e2ef2dcf4 |
children | 705d4c089fce |
rev | line source |
---|---|
359 | 1 /* |
2 Adplug - Replayer for many OPL2/OPL3 audio file formats. | |
1376
c71e2ef2dcf4
[svn] Security fixes from AdPlug CVS (their July 7 commit shortly before the secunia announcement).
chainsaw
parents:
359
diff
changeset
|
3 Copyright (C) 1999 - 2006 Simon Peter, <dn.tlp@gmx.net>, et al. |
359 | 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 | |
1458
f12d7e208b43
[svn] Update FSF address in copyright notices. Update autotools templates.
chainsaw
parents:
1376
diff
changeset
|
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA |
359 | 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 "dtm.h" | |
26 | |
27 /* -------- Public Methods -------------------------------- */ | |
28 | |
29 CPlayer *CdtmLoader::factory(Copl *newopl) | |
30 { | |
31 return new CdtmLoader(newopl); | |
32 } | |
33 | |
34 bool CdtmLoader::load(const std::string &filename, const CFileProvider &fp) | |
35 { | |
36 binistream *f = fp.open(filename); if(!f) return false; | |
37 const unsigned char conv_inst[11] = { 2,1,10,9,4,3,6,5,0,8,7 }; | |
38 const unsigned short conv_note[12] = { 0x16B, 0x181, 0x198, 0x1B0, 0x1CA, 0x1E5, 0x202, 0x220, 0x241, 0x263, 0x287, 0x2AE }; | |
39 | |
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 | |
1376
c71e2ef2dcf4
[svn] Security fixes from AdPlug CVS (their July 7 commit shortly before the secunia announcement).
chainsaw
parents:
359
diff
changeset
|
64 if(bufstr_length > 80) { |
c71e2ef2dcf4
[svn] Security fixes from AdPlug CVS (their July 7 commit shortly before the secunia announcement).
chainsaw
parents:
359
diff
changeset
|
65 fp.close(f); |
c71e2ef2dcf4
[svn] Security fixes from AdPlug CVS (their July 7 commit shortly before the secunia announcement).
chainsaw
parents:
359
diff
changeset
|
66 return false; |
c71e2ef2dcf4
[svn] Security fixes from AdPlug CVS (their July 7 commit shortly before the secunia announcement).
chainsaw
parents:
359
diff
changeset
|
67 } |
c71e2ef2dcf4
[svn] Security fixes from AdPlug CVS (their July 7 commit shortly before the secunia announcement).
chainsaw
parents:
359
diff
changeset
|
68 |
359 | 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 } |