2 * Adplug - Replayer for many OPL2/OPL3 audio file formats.
3 * Copyright (C) 1999 - 2006 Simon Peter, <dn.tlp@gmx.net>, et al.
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.
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.
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
19 * ksm.cpp - KSM Player for AdPlug by Simon Peter <dn.tlp@gmx.net>
27 const unsigned int CksmPlayer::adlibfreq[63] = {
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,
36 /*** public methods **************************************/
38 CPlayer *CksmPlayer::factory(Copl *newopl)
40 return new CksmPlayer(newopl);
43 bool CksmPlayer::load(const std::string &filename, const CFileProvider &fp)
47 char *fn = new char[filename.length() + 9];
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());
55 AdPlug_LogWrite("*** CksmPlayer::load(,\"%s\") ***\n", filename.c_str());
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] == '\\')
62 strcpy(fn + i + 1, "insts.dat");
63 AdPlug_LogWrite("Instruments file: \"%s\"\n", fn);
67 AdPlug_LogWrite("Couldn't open instruments file! Aborting!\n");
68 AdPlug_LogWrite("--- CksmPlayer::load ---\n");
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);
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);
94 AdPlug_LogWrite("--- CksmPlayer::load ---\n");
98 bool CksmPlayer::update()
100 int quanter,chan,drumnum,freq,track,volevel,volval;
101 unsigned int i,j,bufnum;
102 unsigned long temp,templong;
105 if (count >= countstop)
108 while (count >= countstop)
110 templong = note[nownote];
111 track = (int)((templong>>8)&15);
112 if ((templong&192) == 0)
116 while ((i < numchans) &&
117 ((chanfreq[i] != (templong&63)) ||
118 (chantrack[i] != ((templong>>8)&15))))
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++;
131 volevel = trvol[track];
132 if ((templong&192) == 128)
138 if ((templong&192) == 192)
148 for(j=0;j<numchans;j++)
149 if ((countstop - chanage[j] >= temp) && (chantrack[j] == track))
151 temp = countstop - chanage[j];
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;
173 else if ((drumstat&32) > 0)
175 freq = adlibfreq[templong&63];
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;
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++;
194 if ((track == 11) || (track == 12) || (track == 14))
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++;
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++;
208 databuf[bufnum] = (char)0, bufnum++;
209 databuf[bufnum] = (unsigned char)(0xbd); bufnum++;
210 databuf[bufnum] = (unsigned char)(drumstat); bufnum++;
214 if (nownote >= numnotes) {
218 templong = note[nownote];
220 count = (templong>>12)-1;
221 quanter = (240/trquant[(templong>>8)&15]);
222 countstop = (((templong>>12)+(quanter>>1)) / quanter) * quanter;
224 for(i=0;i<bufnum;i+=3)
225 opl->write(databuf[i+1],databuf[i+2]);
230 void CksmPlayer::rewind(int subsong)
233 unsigned char instbuf[11];
234 unsigned long templong;
237 opl->init(); opl->write(1,32); opl->write(4,0); opl->write(8,0); opl->write(0xbd,drumstat);
239 if (trchan[11] == 1) {
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]);
245 instbuf[i] = inst[trinst[12]][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]);
252 instbuf[i] = inst[trinst[14]][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]);
260 for(i=0;i<numchans;i++)
267 if ((trchan[i] > 0) && (j < numchans))
270 while ((j < numchans) && (k > 0))
277 for(i=0;i<numchans;i++)
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]);
287 count = (templong>>12)-1;
288 countstop = (templong>>12)-1;
292 std::string CksmPlayer::getinstrument(unsigned int n)
295 return std::string(instname[trinst[n]]);
297 return std::string();
300 /*** private methods *************************************/
302 void CksmPlayer::loadinsts(binistream *f)
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);
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)
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);
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);