]> 4ch.mooo.com Git - 16.git/blob - 16/adplug/adplug/src/s3m.cpp
wwww~
[16.git] / 16 / adplug / adplug / src / s3m.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  * s3m.c - S3M Player by Simon Peter <dn.tlp@gmx.net>
20  *
21  * BUGS:
22  * Extra Fine Slides (EEx, FEx) & Fine Vibrato (Uxy) are inaccurate
23  */
24
25 #include <cstring>
26 #include "s3m.h"
27
28 const char Cs3mPlayer::chnresolv[] =    // S3M -> adlib channel conversion
29   {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,2,3,4,5,6,7,8,-1,-1,-1,-1,-1,-1,-1};
30
31 const unsigned short Cs3mPlayer::notetable[12] =                // S3M adlib note table
32   {340,363,385,408,432,458,485,514,544,577,611,647};
33
34 const unsigned char Cs3mPlayer::vibratotab[32] =                // vibrato rate table
35   {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1};
36
37 /*** public methods *************************************/
38
39 CPlayer *Cs3mPlayer::factory(Copl *newopl)
40 {
41   return new Cs3mPlayer(newopl);
42 }
43
44 Cs3mPlayer::Cs3mPlayer(Copl *newopl): CPlayer(newopl)
45 {
46   int i,j,k;
47
48   memset(pattern,255,sizeof(pattern));
49   memset(orders,255,sizeof(orders));
50
51   for(i=0;i<99;i++)             // setup pattern
52     for(j=0;j<64;j++)
53       for(k=0;k<32;k++) {
54         pattern[i][j][k].instrument = 0;
55         pattern[i][j][k].info = 0;
56       }
57 }
58
59 bool Cs3mPlayer::load(const std::string &filename, const CFileProvider &fp)
60 {
61   binistream            *f = fp.open(filename); if(!f) return false;
62   unsigned short        insptr[99],pattptr[99];
63   int                   i,row;
64   unsigned char         bufval,bufval2;
65   unsigned short        ppatlen;
66   s3mheader             *checkhead;
67   bool                  adlibins=false;
68
69   // file validation section
70   checkhead = new s3mheader;
71   load_header(f, checkhead);
72   if(checkhead->kennung != 0x1a || checkhead->typ != 16
73      || checkhead->insnum > 99) {
74     delete checkhead; fp.close(f); return false;
75   } else
76     if(strncmp(checkhead->scrm,"SCRM",4)) {
77       delete checkhead; fp.close(f); return false;
78     } else {    // is an adlib module?
79       f->seek(checkhead->ordnum, binio::Add);
80       for(i = 0; i < checkhead->insnum; i++)
81         insptr[i] = f->readInt(2);
82       for(i=0;i<checkhead->insnum;i++) {
83         f->seek(insptr[i]*16);
84         if(f->readInt(1) >= 2) {
85           adlibins = true;
86           break;
87         }
88       }
89       delete checkhead;
90       if(!adlibins) { fp.close(f); return false; }
91     }
92
93   // load section
94   f->seek(0);                   // rewind for load
95   load_header(f, &header);      // read header
96
97   // security check
98   if(header.ordnum > 256 || header.insnum > 99 || header.patnum > 99) {
99     fp.close(f);
100     return false;
101   }
102
103   for(i = 0; i < header.ordnum; i++) orders[i] = f->readInt(1); // read orders
104   for(i = 0; i < header.insnum; i++) insptr[i] = f->readInt(2); // instrument parapointers
105   for(i = 0; i < header.patnum; i++) pattptr[i] = f->readInt(2); // pattern parapointers
106
107   for(i=0;i<header.insnum;i++) {        // load instruments
108     f->seek(insptr[i]*16);
109     inst[i].type = f->readInt(1);
110     f->readString(inst[i].filename, 15);
111     inst[i].d00 = f->readInt(1); inst[i].d01 = f->readInt(1);
112     inst[i].d02 = f->readInt(1); inst[i].d03 = f->readInt(1);
113     inst[i].d04 = f->readInt(1); inst[i].d05 = f->readInt(1);
114     inst[i].d06 = f->readInt(1); inst[i].d07 = f->readInt(1);
115     inst[i].d08 = f->readInt(1); inst[i].d09 = f->readInt(1);
116     inst[i].d0a = f->readInt(1); inst[i].d0b = f->readInt(1);
117     inst[i].volume = f->readInt(1); inst[i].dsk = f->readInt(1);
118     f->ignore(2);
119     inst[i].c2spd = f->readInt(4);
120     f->ignore(12);
121     f->readString(inst[i].name, 28);
122     f->readString(inst[i].scri, 4);
123   }
124
125   for(i=0;i<header.patnum;i++) {        // depack patterns
126     f->seek(pattptr[i]*16);
127     ppatlen = f->readInt(2);
128     unsigned long pattpos = f->pos();
129     for(row=0;(row<64) && (pattpos-pattptr[i]*16<=ppatlen);row++)
130       do {
131         bufval = f->readInt(1);
132         if(bufval & 32) {
133           bufval2 = f->readInt(1);
134           pattern[i][row][bufval & 31].note = bufval2 & 15;
135           pattern[i][row][bufval & 31].oct = (bufval2 & 240) >> 4;
136           pattern[i][row][bufval & 31].instrument = f->readInt(1);
137         }
138         if(bufval & 64)
139           pattern[i][row][bufval & 31].volume = f->readInt(1);
140         if(bufval & 128) {
141           pattern[i][row][bufval & 31].command = f->readInt(1);
142           pattern[i][row][bufval & 31].info = f->readInt(1);
143         }
144       } while(bufval);
145   }
146
147   fp.close(f);
148   rewind(0);
149   return true;          // done
150 }
151
152 bool Cs3mPlayer::update()
153 {
154   unsigned char pattbreak=0,donote;             // remember vars
155   unsigned char pattnr,chan,row,info;   // cache vars
156   signed char           realchan;
157
158   // effect handling (timer dependant)
159   for(realchan=0; realchan<9; realchan++) {
160     info = channel[realchan].info;      // fill infobyte cache
161     switch(channel[realchan].fx) {
162     case 11:
163     case 12: if(channel[realchan].fx == 11)     // dual command: H00 and Dxy
164       vibrato(realchan,channel[realchan].dualinfo);
165     else                                        // dual command: G00 and Dxy
166       tone_portamento(realchan,channel[realchan].dualinfo);
167     case 4: if(info <= 0x0f) {                  // volume slide down
168       if(channel[realchan].vol - info >= 0)
169         channel[realchan].vol -= info;
170       else
171         channel[realchan].vol = 0;
172       }
173       if((info & 0x0f) == 0) {                  // volume slide up
174         if(channel[realchan].vol + (info >> 4) <= 63)
175           channel[realchan].vol += info >> 4;
176         else
177           channel[realchan].vol = 63;
178       }
179       setvolume(realchan);
180       break;
181     case 5: if(info == 0xf0 || info <= 0xe0) {  // slide down
182       slide_down(realchan,info);
183       setfreq(realchan);
184     }
185       break;
186     case 6: if(info == 0xf0 || info <= 0xe0) {  // slide up
187       slide_up(realchan,info);
188       setfreq(realchan);
189     }
190       break;
191     case 7: tone_portamento(realchan,channel[realchan].dualinfo); break;        // tone portamento
192     case 8: vibrato(realchan,channel[realchan].dualinfo); break;        // vibrato
193     case 10: channel[realchan].nextfreq = channel[realchan].freq;       // arpeggio
194       channel[realchan].nextoct = channel[realchan].oct;
195       switch(channel[realchan].trigger) {
196       case 0: channel[realchan].freq = notetable[channel[realchan].note]; break;
197       case 1: if(channel[realchan].note + ((info & 0xf0) >> 4) < 12)
198         channel[realchan].freq = notetable[channel[realchan].note + ((info & 0xf0) >> 4)];
199       else {
200         channel[realchan].freq = notetable[channel[realchan].note + ((info & 0xf0) >> 4) - 12];
201         channel[realchan].oct++;
202       }
203         break;
204       case 2: if(channel[realchan].note + (info & 0x0f) < 12)
205         channel[realchan].freq = notetable[channel[realchan].note + (info & 0x0f)];
206       else {
207         channel[realchan].freq = notetable[channel[realchan].note + (info & 0x0f) - 12];
208         channel[realchan].oct++;
209       }
210         break;
211       }
212       if(channel[realchan].trigger < 2)
213         channel[realchan].trigger++;
214       else
215         channel[realchan].trigger = 0;
216       setfreq(realchan);
217       channel[realchan].freq = channel[realchan].nextfreq;
218       channel[realchan].oct = channel[realchan].nextoct;
219       break;
220     case 21: vibrato(realchan,(unsigned char) (info / 4)); break;       // fine vibrato
221     }
222   }
223
224   if(del) {             // speed compensation
225     del--;
226     return !songend;
227   }
228
229   // arrangement handling
230   pattnr = orders[ord];
231   if(pattnr == 0xff || ord > header.ordnum) {   // "--" end of song
232     songend = 1;                                // set end-flag
233     ord = 0;
234     pattnr = orders[ord];
235     if(pattnr == 0xff)
236       return !songend;
237   }
238   if(pattnr == 0xfe) {          // "++" skip marker
239     ord++; pattnr = orders[ord];
240   }
241
242   // play row
243   row = crow;   // fill row cache
244   for(chan=0;chan<32;chan++) {
245     if(!(header.chanset[chan] & 128))           // resolve S3M -> AdLib channels
246       realchan = chnresolv[header.chanset[chan] & 127];
247     else
248       realchan = -1;            // channel disabled
249     if(realchan != -1) {        // channel playable?
250       // set channel values
251       donote = 0;
252       if(pattern[pattnr][row][chan].note < 14) {
253         // tone portamento
254         if(pattern[pattnr][row][chan].command == 7 || pattern[pattnr][row][chan].command == 12) {
255           channel[realchan].nextfreq = notetable[pattern[pattnr][row][chan].note];
256           channel[realchan].nextoct = pattern[pattnr][row][chan].oct;
257         } else {                                                                                        // normal note
258           channel[realchan].note = pattern[pattnr][row][chan].note;
259           channel[realchan].freq = notetable[pattern[pattnr][row][chan].note];
260           channel[realchan].oct = pattern[pattnr][row][chan].oct;
261           channel[realchan].key = 1;
262           donote = 1;
263         }
264       }
265       if(pattern[pattnr][row][chan].note == 14) {       // key off (is 14 here, cause note is only first 4 bits)
266         channel[realchan].key = 0;
267         setfreq(realchan);
268       }
269       if((channel[realchan].fx != 8 && channel[realchan].fx != 11) &&   // vibrato begins
270          (pattern[pattnr][row][chan].command == 8 || pattern[pattnr][row][chan].command == 11)) {
271         channel[realchan].nextfreq = channel[realchan].freq;
272         channel[realchan].nextoct = channel[realchan].oct;
273       }
274       if(pattern[pattnr][row][chan].note >= 14)
275         if((channel[realchan].fx == 8 || channel[realchan].fx == 11) && // vibrato ends
276            (pattern[pattnr][row][chan].command != 8 && pattern[pattnr][row][chan].command != 11)) {
277           channel[realchan].freq = channel[realchan].nextfreq;
278           channel[realchan].oct = channel[realchan].nextoct;
279           setfreq(realchan);
280         }
281       if(pattern[pattnr][row][chan].instrument) {       // set instrument
282         channel[realchan].inst = pattern[pattnr][row][chan].instrument - 1;
283         if(inst[channel[realchan].inst].volume < 64)
284           channel[realchan].vol = inst[channel[realchan].inst].volume;
285         else
286           channel[realchan].vol = 63;
287         if(pattern[pattnr][row][chan].command != 7)
288           donote = 1;
289       }
290       if(pattern[pattnr][row][chan].volume != 255) {
291         if(pattern[pattnr][row][chan].volume < 64)      // set volume
292           channel[realchan].vol = pattern[pattnr][row][chan].volume;
293         else
294           channel[realchan].vol = 63;
295       }
296       channel[realchan].fx = pattern[pattnr][row][chan].command;        // set command
297       if(pattern[pattnr][row][chan].info)                       // set infobyte
298         channel[realchan].info = pattern[pattnr][row][chan].info;
299
300       // some commands reset the infobyte memory
301       switch(channel[realchan].fx) {
302       case 1:
303       case 2:
304       case 3:
305       case 20:
306         channel[realchan].info = pattern[pattnr][row][chan].info;
307         break;
308       }
309
310       // play note
311       if(donote)
312         playnote(realchan);
313       if(pattern[pattnr][row][chan].volume != 255)      // set volume
314         setvolume(realchan);
315
316       // command handling (row dependant)
317       info = channel[realchan].info;    // fill infobyte cache
318       switch(channel[realchan].fx) {
319       case 1: speed = info; break;      // set speed
320       case 2: if(info <= ord) songend = 1; ord = info; crow = 0; pattbreak = 1; break;  // jump to order
321       case 3: if(!pattbreak) { crow = info; ord++; pattbreak = 1; } break;      // pattern break
322       case 4: if(info > 0xf0) {         // fine volume down
323         if(channel[realchan].vol - (info & 0x0f) >= 0)
324           channel[realchan].vol -= info & 0x0f;
325         else
326           channel[realchan].vol = 0;
327         }
328         if((info & 0x0f) == 0x0f && info >= 0x1f) {     // fine volume up
329           if(channel[realchan].vol + ((info & 0xf0) >> 4) <= 63)
330             channel[realchan].vol += (info & 0xf0) >> 4;
331           else
332             channel[realchan].vol = 63;
333         }
334         setvolume(realchan);
335         break;
336       case 5: if(info > 0xf0)   {                       // fine slide down
337         slide_down(realchan,(unsigned char) (info & 0x0f));
338         setfreq(realchan);
339       }
340         if(info > 0xe0 && info < 0xf0) {                // extra fine slide down
341           slide_down(realchan,(unsigned char) ((info & 0x0f) / 4));
342           setfreq(realchan);
343         }
344         break;
345       case 6: if(info > 0xf0) {                         // fine slide up
346         slide_up(realchan,(unsigned char) (info & 0x0f));
347         setfreq(realchan);
348       }
349         if(info > 0xe0 && info < 0xf0) {                // extra fine slide up
350           slide_up(realchan,(unsigned char) ((info & 0x0f) / 4));
351           setfreq(realchan);
352         }
353         break;
354       case 7:                                                                                                           // tone portamento
355       case 8:   if((channel[realchan].fx == 7 ||        // vibrato (remember info for dual commands)
356                     channel[realchan].fx == 8) && pattern[pattnr][row][chan].info)
357         channel[realchan].dualinfo = info;
358         break;
359       case 10: channel[realchan].trigger = 0; break;    // arpeggio (set trigger)
360       case 19: if(info == 0xb0)                         // set loop start
361         loopstart = row;
362         if(info > 0xb0 && info <= 0xbf) {               // pattern loop
363           if(!loopcnt) {
364             loopcnt = info & 0x0f;
365             crow = loopstart;
366             pattbreak = 1;
367           } else
368             if(--loopcnt > 0) {
369               crow = loopstart;
370               pattbreak = 1;
371             }
372         }
373         if((info & 0xf0) == 0xe0)                       // patterndelay
374           del = speed * (info & 0x0f) - 1;
375         break;
376       case 20: tempo = info; break;                     // set tempo
377       }
378     }
379   }
380
381   if(!del)
382     del = speed - 1;            // speed compensation
383   if(!pattbreak) {              // next row (only if no manual advance)
384     crow++;
385     if(crow > 63) {
386       crow = 0;
387       ord++;
388       loopstart = 0;
389     }
390   }
391
392   return !songend;              // still playing
393 }
394
395 void Cs3mPlayer::rewind(int subsong)
396 {
397   // set basic variables
398   songend = 0; ord = 0; crow = 0; tempo = header.it;
399   speed = header.is; del = 0; loopstart = 0; loopcnt = 0;
400
401   memset(channel,0,sizeof(channel));
402
403   opl->init();                          // reset OPL chip
404   opl->write(1,32);                     // Go to ym3812 mode
405 }
406
407 std::string Cs3mPlayer::gettype()
408 {
409   char filever[5];
410
411   switch(header.cwtv) {         // determine version number
412   case 0x1300: strcpy(filever,"3.00"); break;
413   case 0x1301: strcpy(filever,"3.01"); break;
414   case 0x1303: strcpy(filever,"3.03"); break;
415   case 0x1320: strcpy(filever,"3.20"); break;
416   default: strcpy(filever,"3.??");
417   }
418
419   return (std::string("Scream Tracker ") + filever);
420 }
421
422 float Cs3mPlayer::getrefresh()
423 {
424   return (float) (tempo / 2.5);
425 }
426
427 /*** private methods *************************************/
428
429 void Cs3mPlayer::load_header(binistream *f, s3mheader *h)
430 {
431   int i;
432
433   f->readString(h->name, 28);
434   h->kennung = f->readInt(1); h->typ = f->readInt(1);
435   f->ignore(2);
436   h->ordnum = f->readInt(2); h->insnum = f->readInt(2);
437   h->patnum = f->readInt(2); h->flags = f->readInt(2);
438   h->cwtv = f->readInt(2); h->ffi = f->readInt(2);
439   f->readString(h->scrm, 4);
440   h->gv = f->readInt(1); h->is = f->readInt(1); h->it = f->readInt(1);
441   h->mv = f->readInt(1); h->uc = f->readInt(1); h->dp = f->readInt(1);
442   f->ignore(8);
443   h->special = f->readInt(2);
444   for(i = 0; i < 32; i++) h->chanset[i] = f->readInt(1);
445 }
446
447 void Cs3mPlayer::setvolume(unsigned char chan)
448 {
449   unsigned char op = op_table[chan], insnr = channel[chan].inst;
450
451   opl->write(0x43 + op,(int)(63-((63-(inst[insnr].d03 & 63))/63.0)*channel[chan].vol) + (inst[insnr].d03 & 192));
452   if(inst[insnr].d0a & 1)
453     opl->write(0x40 + op,(int)(63-((63-(inst[insnr].d02 & 63))/63.0)*channel[chan].vol) + (inst[insnr].d02 & 192));
454 }
455
456 void Cs3mPlayer::setfreq(unsigned char chan)
457 {
458   opl->write(0xa0 + chan, channel[chan].freq & 255);
459   if(channel[chan].key)
460     opl->write(0xb0 + chan, (((channel[chan].freq & 768) >> 8) + (channel[chan].oct << 2)) | 32);
461   else
462     opl->write(0xb0 + chan, ((channel[chan].freq & 768) >> 8) + (channel[chan].oct << 2));
463 }
464
465 void Cs3mPlayer::playnote(unsigned char chan)
466 {
467   unsigned char op = op_table[chan], insnr = channel[chan].inst;
468
469   opl->write(0xb0 + chan, 0);   // stop old note
470
471   // set instrument data
472   opl->write(0x20 + op, inst[insnr].d00);
473   opl->write(0x23 + op, inst[insnr].d01);
474   opl->write(0x40 + op, inst[insnr].d02);
475   opl->write(0x43 + op, inst[insnr].d03);
476   opl->write(0x60 + op, inst[insnr].d04);
477   opl->write(0x63 + op, inst[insnr].d05);
478   opl->write(0x80 + op, inst[insnr].d06);
479   opl->write(0x83 + op, inst[insnr].d07);
480   opl->write(0xe0 + op, inst[insnr].d08);
481   opl->write(0xe3 + op, inst[insnr].d09);
482   opl->write(0xc0 + chan, inst[insnr].d0a);
483
484   // set frequency & play
485   channel[chan].key = 1;
486   setfreq(chan);
487 }
488
489 void Cs3mPlayer::slide_down(unsigned char chan, unsigned char amount)
490 {
491   if(channel[chan].freq - amount > 340)
492     channel[chan].freq -= amount;
493   else
494     if(channel[chan].oct > 0) {
495       channel[chan].oct--;
496       channel[chan].freq = 684;
497     } else
498       channel[chan].freq = 340;
499 }
500
501 void Cs3mPlayer::slide_up(unsigned char chan, unsigned char amount)
502 {
503   if(channel[chan].freq + amount < 686)
504     channel[chan].freq += amount;
505   else
506     if(channel[chan].oct < 7) {
507       channel[chan].oct++;
508       channel[chan].freq = 341;
509     } else
510       channel[chan].freq = 686;
511 }
512
513 void Cs3mPlayer::vibrato(unsigned char chan, unsigned char info)
514 {
515   unsigned char i,speed,depth;
516
517   speed = info >> 4;
518   depth = (info & 0x0f) / 2;
519
520   for(i=0;i<speed;i++) {
521     channel[chan].trigger++;
522     while(channel[chan].trigger >= 64)
523       channel[chan].trigger -= 64;
524     if(channel[chan].trigger >= 16 && channel[chan].trigger < 48)
525       slide_down(chan,(unsigned char) (vibratotab[channel[chan].trigger - 16] / (16-depth)));
526     if(channel[chan].trigger < 16)
527       slide_up(chan,(unsigned char) (vibratotab[channel[chan].trigger + 16] / (16-depth)));
528     if(channel[chan].trigger >= 48)
529       slide_up(chan,(unsigned char) (vibratotab[channel[chan].trigger - 48] / (16-depth)));
530   }
531   setfreq(chan);
532 }
533
534 void Cs3mPlayer::tone_portamento(unsigned char chan, unsigned char info)
535 {
536   if(channel[chan].freq + (channel[chan].oct << 10) < channel[chan].nextfreq +
537      (channel[chan].nextoct << 10))
538     slide_up(chan,info);
539   if(channel[chan].freq + (channel[chan].oct << 10) > channel[chan].nextfreq +
540      (channel[chan].nextoct << 10))
541     slide_down(chan,info);
542   setfreq(chan);
543 }