Mercurial > audlegacy
annotate Plugins/Input/adplug/core/ksm.cpp @ 1459:705d4c089fce trunk
[svn] Fix postal code.
author | chainsaw |
---|---|
date | Wed, 02 Aug 2006 16:00:13 -0700 |
parents | f12d7e208b43 |
children |
rev | line source |
---|---|
359 | 1 /* |
2 * Adplug - Replayer for many OPL2/OPL3 audio file formats. | |
1280
6ad7eb96dd26
[svn] Sync with upstream. This adds Westwood ADL format support.
chainsaw
parents:
792
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 | |
1459 | 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
359 | 18 * |
19 * ksm.cpp - KSM Player for AdPlug by Simon Peter <dn.tlp@gmx.net> | |
20 */ | |
21 | |
22 #include <string.h> | |
23 | |
24 #include "ksm.h" | |
25 #include "debug.h" | |
26 | |
27 const unsigned int CksmPlayer::adlibfreq[63] = { | |
28 0, | |
29 2390,2411,2434,2456,2480,2506,2533,2562,2592,2625,2659,2695, | |
30 3414,3435,3458,3480,3504,3530,3557,3586,3616,3649,3683,3719, | |
31 4438,4459,4482,4504,4528,4554,4581,4610,4640,4673,4707,4743, | |
32 5462,5483,5506,5528,5552,5578,5605,5634,5664,5697,5731,5767, | |
33 6486,6507,6530,6552,6576,6602,6629,6658,6688,6721,6755,6791, | |
34 7510}; | |
35 | |
36 /*** public methods **************************************/ | |
37 | |
38 CPlayer *CksmPlayer::factory(Copl *newopl) | |
39 { | |
40 return new CksmPlayer(newopl); | |
41 } | |
42 | |
43 bool CksmPlayer::load(const std::string &filename, const CFileProvider &fp) | |
44 { | |
45 binistream *f; | |
46 int i; | |
47 char *fn = new char[filename.length() + 9]; | |
48 | |
49 // file validation section | |
50 if(!fp.extension(filename, ".ksm")) { | |
51 AdPlug_LogWrite("CksmPlayer::load(,\"%s\"): File doesn't have '.ksm' " | |
52 "extension! Rejected!\n", filename.c_str()); | |
53 return false; | |
54 } | |
55 AdPlug_LogWrite("*** CksmPlayer::load(,\"%s\") ***\n", filename.c_str()); | |
56 | |
57 // Load instruments from 'insts.dat' | |
58 strcpy(fn, filename.c_str()); | |
59 for(i = strlen(fn) - 1; i >= 0; i--) | |
60 if(fn[i] == '/' || fn[i] == '\\') | |
61 break; | |
62 strcpy(fn + i + 1, "insts.dat"); | |
63 AdPlug_LogWrite("Instruments file: \"%s\"\n", fn); | |
64 f = fp.open(fn); | |
65 delete [] fn; | |
66 if(!f) { | |
67 AdPlug_LogWrite("Couldn't open instruments file! Aborting!\n"); | |
68 AdPlug_LogWrite("--- CksmPlayer::load ---\n"); | |
69 return false; | |
70 } | |
71 loadinsts(f); | |
72 fp.close(f); | |
73 | |
74 f = fp.open(filename); if(!f) return false; | |
75 for(i = 0; i < 16; i++) trinst[i] = f->readInt(1); | |
76 for(i = 0; i < 16; i++) trquant[i] = f->readInt(1); | |
77 for(i = 0; i < 16; i++) trchan[i] = f->readInt(1); | |
78 f->ignore(16); | |
79 for(i = 0; i < 16; i++) trvol[i] = f->readInt(1); | |
80 numnotes = f->readInt(2); | |
81 note = new unsigned long [numnotes]; | |
82 for(i = 0; i < numnotes; i++) note[i] = f->readInt(4); | |
83 fp.close(f); | |
84 | |
85 if(!trchan[11]) { | |
86 drumstat = 0; | |
87 numchans = 9; | |
88 } else { | |
89 drumstat = 32; | |
90 numchans = 6; | |
91 } | |
92 | |
93 rewind(0); | |
94 AdPlug_LogWrite("--- CksmPlayer::load ---\n"); | |
95 return true; | |
96 } | |
97 | |
98 bool CksmPlayer::update() | |
99 { | |
1280
6ad7eb96dd26
[svn] Sync with upstream. This adds Westwood ADL format support.
chainsaw
parents:
792
diff
changeset
|
100 int quanter,chan,drumnum,freq,track,volevel,volval; |
359 | 101 unsigned int i,j,bufnum; |
102 unsigned long temp,templong; | |
103 | |
104 count++; | |
105 if (count >= countstop) | |
106 { | |
107 bufnum = 0; | |
108 while (count >= countstop) | |
109 { | |
110 templong = note[nownote]; | |
111 track = (int)((templong>>8)&15); | |
112 if ((templong&192) == 0) | |
113 { | |
114 i = 0; | |
1280
6ad7eb96dd26
[svn] Sync with upstream. This adds Westwood ADL format support.
chainsaw
parents:
792
diff
changeset
|
115 |
6ad7eb96dd26
[svn] Sync with upstream. This adds Westwood ADL format support.
chainsaw
parents:
792
diff
changeset
|
116 while ((i < numchans) && |
6ad7eb96dd26
[svn] Sync with upstream. This adds Westwood ADL format support.
chainsaw
parents:
792
diff
changeset
|
117 ((chanfreq[i] != (templong&63)) || |
6ad7eb96dd26
[svn] Sync with upstream. This adds Westwood ADL format support.
chainsaw
parents:
792
diff
changeset
|
118 (chantrack[i] != ((templong>>8)&15)))) |
359 | 119 i++; |
120 if (i < numchans) | |
121 { | |
122 databuf[bufnum] = (char)0; bufnum++; | |
123 databuf[bufnum] = (unsigned char)(0xb0+i); bufnum++; | |
124 databuf[bufnum] = (unsigned char)((adlibfreq[templong&63]>>8)&223); bufnum++; | |
125 chanfreq[i] = 0; | |
126 chanage[i] = 0; | |
127 } | |
128 } | |
129 else | |
130 { | |
131 volevel = trvol[track]; | |
132 if ((templong&192) == 128) | |
133 { | |
134 volevel -= 4; | |
135 if (volevel < 0) | |
136 volevel = 0; | |
137 } | |
138 if ((templong&192) == 192) | |
139 { | |
140 volevel += 4; | |
141 if (volevel > 63) | |
142 volevel = 63; | |
143 } | |
144 if (track < 11) | |
145 { | |
146 temp = 0; | |
147 i = numchans; | |
148 for(j=0;j<numchans;j++) | |
149 if ((countstop - chanage[j] >= temp) && (chantrack[j] == track)) | |
150 { | |
151 temp = countstop - chanage[j]; | |
152 i = j; | |
153 } | |
154 if (i < numchans) | |
155 { | |
156 databuf[bufnum] = (char)0, bufnum++; | |
157 databuf[bufnum] = (unsigned char)(0xb0+i); bufnum++; | |
158 databuf[bufnum] = (unsigned char)0; bufnum++; | |
159 volval = (inst[trinst[track]][1]&192)+(volevel^63); | |
160 databuf[bufnum] = (char)0, bufnum++; | |
161 databuf[bufnum] = (unsigned char)(0x40+op_table[i]+3); bufnum++; | |
162 databuf[bufnum] = (unsigned char)volval; bufnum++; | |
163 databuf[bufnum] = (char)0, bufnum++; | |
164 databuf[bufnum] = (unsigned char)(0xa0+i); bufnum++; | |
165 databuf[bufnum] = (unsigned char)(adlibfreq[templong&63]&255); bufnum++; | |
166 databuf[bufnum] = (char)0, bufnum++; | |
167 databuf[bufnum] = (unsigned char)(0xb0+i); bufnum++; | |
168 databuf[bufnum] = (unsigned char)((adlibfreq[templong&63]>>8)|32); bufnum++; | |
169 chanfreq[i] = templong&63; | |
170 chanage[i] = countstop; | |
171 } | |
172 } | |
173 else if ((drumstat&32) > 0) | |
174 { | |
175 freq = adlibfreq[templong&63]; | |
176 switch(track) | |
177 { | |
178 case 11: drumnum = 16; chan = 6; freq -= 2048; break; | |
179 case 12: drumnum = 8; chan = 7; freq -= 2048; break; | |
180 case 13: drumnum = 4; chan = 8; break; | |
181 case 14: drumnum = 2; chan = 8; break; | |
182 case 15: drumnum = 1; chan = 7; freq -= 2048; break; | |
183 } | |
184 databuf[bufnum] = (char)0, bufnum++; | |
185 databuf[bufnum] = (unsigned char)(0xa0+chan); bufnum++; | |
186 databuf[bufnum] = (unsigned char)(freq&255); bufnum++; | |
187 databuf[bufnum] = (char)0, bufnum++; | |
188 databuf[bufnum] = (unsigned char)(0xb0+chan); bufnum++; | |
189 databuf[bufnum] = (unsigned char)((freq>>8)&223); bufnum++; | |
190 databuf[bufnum] = (char)0, bufnum++; | |
191 databuf[bufnum] = (unsigned char)(0xbd); bufnum++; | |
192 databuf[bufnum] = (unsigned char)(drumstat&(255-drumnum)); bufnum++; | |
193 drumstat |= drumnum; | |
194 if ((track == 11) || (track == 12) || (track == 14)) | |
195 { | |
196 volval = (inst[trinst[track]][1]&192)+(volevel^63); | |
197 databuf[bufnum] = (char)0, bufnum++; | |
198 databuf[bufnum] = (unsigned char)(0x40+op_table[chan]+3); bufnum++; | |
199 databuf[bufnum] = (unsigned char)(volval); bufnum++; | |
200 } | |
201 else | |
202 { | |
203 volval = (inst[trinst[track]][6]&192)+(volevel^63); | |
204 databuf[bufnum] = (char)0, bufnum++; | |
205 databuf[bufnum] = (unsigned char)(0x40+op_table[chan]); bufnum++; | |
206 databuf[bufnum] = (unsigned char)(volval); bufnum++; | |
207 } | |
208 databuf[bufnum] = (char)0, bufnum++; | |
209 databuf[bufnum] = (unsigned char)(0xbd); bufnum++; | |
210 databuf[bufnum] = (unsigned char)(drumstat); bufnum++; | |
211 } | |
212 } | |
213 nownote++; | |
214 if (nownote >= numnotes) { | |
215 nownote = 0; | |
216 songend = true; | |
217 } | |
218 templong = note[nownote]; | |
219 if (nownote == 0) | |
220 count = (templong>>12)-1; | |
221 quanter = (240/trquant[(templong>>8)&15]); | |
222 countstop = (((templong>>12)+(quanter>>1)) / quanter) * quanter; | |
223 } | |
224 for(i=0;i<bufnum;i+=3) | |
225 opl->write(databuf[i+1],databuf[i+2]); | |
226 } | |
227 return !songend; | |
228 } | |
229 | |
230 void CksmPlayer::rewind(int subsong) | |
231 { | |
232 unsigned int i,j,k; | |
233 unsigned char instbuf[11]; | |
234 unsigned long templong; | |
235 | |
236 songend = false; | |
237 opl->init(); opl->write(1,32); opl->write(4,0); opl->write(8,0); opl->write(0xbd,drumstat); | |
238 | |
239 if (trchan[11] == 1) { | |
240 for(i=0;i<11;i++) | |
241 instbuf[i] = inst[trinst[11]][i]; | |
242 instbuf[1] = ((instbuf[1]&192)|(trvol[11])^63); | |
243 setinst(6,instbuf[0],instbuf[1],instbuf[2],instbuf[3],instbuf[4],instbuf[5],instbuf[6],instbuf[7],instbuf[8],instbuf[9],instbuf[10]); | |
244 for(i=0;i<5;i++) | |
245 instbuf[i] = inst[trinst[12]][i]; | |
246 for(i=5;i<11;i++) | |
247 instbuf[i] = inst[trinst[15]][i]; | |
248 instbuf[1] = ((instbuf[1]&192)|(trvol[12])^63); | |
249 instbuf[6] = ((instbuf[6]&192)|(trvol[15])^63); | |
250 setinst(7,instbuf[0],instbuf[1],instbuf[2],instbuf[3],instbuf[4],instbuf[5],instbuf[6],instbuf[7],instbuf[8],instbuf[9],instbuf[10]); | |
251 for(i=0;i<5;i++) | |
252 instbuf[i] = inst[trinst[14]][i]; | |
253 for(i=5;i<11;i++) | |
254 instbuf[i] = inst[trinst[13]][i]; | |
255 instbuf[1] = ((instbuf[1]&192)|(trvol[14])^63); | |
256 instbuf[6] = ((instbuf[6]&192)|(trvol[13])^63); | |
257 setinst(8,instbuf[0],instbuf[1],instbuf[2],instbuf[3],instbuf[4],instbuf[5],instbuf[6],instbuf[7],instbuf[8],instbuf[9],instbuf[10]); | |
258 } | |
259 | |
260 for(i=0;i<numchans;i++) | |
261 { | |
262 chantrack[i] = 0; | |
263 chanage[i] = 0; | |
264 } | |
265 j = 0; | |
266 for(i=0;i<16;i++) | |
267 if ((trchan[i] > 0) && (j < numchans)) | |
268 { | |
269 k = trchan[i]; | |
270 while ((j < numchans) && (k > 0)) | |
271 { | |
272 chantrack[j] = i; | |
273 k--; | |
274 j++; | |
275 } | |
276 } | |
277 for(i=0;i<numchans;i++) | |
278 { | |
279 for(j=0;j<11;j++) | |
280 instbuf[j] = inst[trinst[chantrack[i]]][j]; | |
281 instbuf[1] = ((instbuf[1]&192)|(63-trvol[chantrack[i]])); | |
282 setinst(i,instbuf[0],instbuf[1],instbuf[2],instbuf[3],instbuf[4],instbuf[5],instbuf[6],instbuf[7],instbuf[8],instbuf[9],instbuf[10]); | |
283 chanfreq[i] = 0; | |
284 } | |
285 k = 0; | |
286 templong = *note; | |
287 count = (templong>>12)-1; | |
288 countstop = (templong>>12)-1; | |
289 nownote = 0; | |
290 } | |
291 | |
292 std::string CksmPlayer::getinstrument(unsigned int n) | |
293 { | |
294 if(trchan[n]) | |
295 return std::string(instname[trinst[n]]); | |
296 else | |
297 return std::string(); | |
298 } | |
299 | |
300 /*** private methods *************************************/ | |
301 | |
302 void CksmPlayer::loadinsts(binistream *f) | |
303 { | |
304 int i, j; | |
305 | |
306 for(i = 0; i < 256; i++) { | |
307 f->readString(instname[i], 20); | |
308 for(j = 0; j < 11; j++) inst[i][j] = f->readInt(1); | |
309 f->ignore(2); | |
310 } | |
311 } | |
312 | |
313 void CksmPlayer::setinst(int chan, | |
314 unsigned char v0,unsigned char v1,unsigned char v2, | |
315 unsigned char v3,unsigned char v4,unsigned char v5, | |
316 unsigned char v6,unsigned char v7,unsigned char v8, | |
317 unsigned char v9,unsigned char v10) | |
318 { | |
319 int offs; | |
320 | |
321 opl->write(0xa0+chan,0); | |
322 opl->write(0xb0+chan,0); | |
323 opl->write(0xc0+chan,v10); | |
324 offs = op_table[chan]; | |
325 opl->write(0x20+offs,v5); | |
326 opl->write(0x40+offs,v6); | |
327 opl->write(0x60+offs,v7); | |
328 opl->write(0x80+offs,v8); | |
329 opl->write(0xe0+offs,v9); | |
330 offs+=3; | |
331 opl->write(0x20+offs,v0); | |
332 opl->write(0x40+offs,v1); | |
333 opl->write(0x60+offs,v2); | |
334 opl->write(0x80+offs,v3); | |
335 opl->write(0xe0+offs,v4); | |
336 } |