]> 4ch.mooo.com Git - 16.git/blob - 16/adplug/adplug-2.2.1/src/ksm.cpp
Please enter the commit message for your changes. Lines starting
[16.git] / 16 / adplug / adplug-2.2.1 / src / ksm.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  * 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 {
100   int quanter,chan,drumnum,freq,track,volevel,volval;
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;
115
116               while ((i < numchans) &&
117                      ((chanfreq[i] != (templong&63)) ||
118                       (chantrack[i] != ((templong>>8)&15))))
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 }