]> 4ch.mooo.com Git - 16.git/blob - 16/adplug/adplug/src/hsc.cpp
wwww~
[16.git] / 16 / adplug / adplug / src / hsc.cpp
1 /*
2  * Adplug - Replayer for many OPL2/OPL3 audio file formats.
3  * Copyright (C) 1999 - 2004 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  * hsc.cpp - HSC Player by Simon Peter <dn.tlp@gmx.net>
20  */
21
22 #include <string.h>
23
24 #include "hsc.h"
25 #include "debug.h"
26
27 /*** public methods **************************************/
28
29 CPlayer *ChscPlayer::factory(Copl *newopl)
30 {
31   return new ChscPlayer(newopl);
32 }
33
34 bool ChscPlayer::load(const std::string &filename, const CFileProvider &fp)
35 {
36   binistream    *f = fp.open(filename);
37   int           i;
38
39   // file validation section
40   if(!f || !fp.extension(filename, ".hsc") || fp.filesize(f) > 59187) {
41     AdPlug_LogWrite("ChscPlayer::load(\"%s\"): Not a HSC file!\n", filename.c_str());
42     fp.close(f);
43     return false;
44   }
45
46   // load section
47   for(i=0;i<128*12;i++)         // load instruments
48     *((unsigned char *)instr + i) = f->readInt(1);
49   for (i=0;i<128;i++) {                 // correct instruments
50     instr[i][2] ^= (instr[i][2] & 0x40) << 1;
51     instr[i][3] ^= (instr[i][3] & 0x40) << 1;
52     instr[i][11] >>= 4;                 // slide
53   }
54   for(i=0;i<51;i++) song[i] = f->readInt(1);    // load tracklist
55   for(i=0;i<50*64*9;i++)                        // load patterns
56     *((char *)patterns + i) = f->readInt(1);
57
58   fp.close(f);
59   rewind(0);                                    // rewind module
60   return true;
61 }
62
63 bool ChscPlayer::update()
64 {
65   // general vars
66   unsigned char         chan,pattnr,note,effect,eff_op,inst,vol,Okt,db;
67   unsigned short        Fnr;
68   unsigned long         pattoff;
69
70   del--;                      // player speed handling
71   if(del)
72     return !songend;            // nothing done
73
74   if(fadein)                                    // fade-in handling
75     fadein--;
76
77   pattnr = song[songpos];
78   if(pattnr == 0xff) {                  // arrangement handling
79     songend = 1;                                // set end-flag
80     songpos = 0;
81     pattnr = song[songpos];
82   } else
83     if ((pattnr & 128) && (pattnr <= 0xb1)) { // goto pattern "nr"
84       songpos = song[songpos] & 127;
85       pattpos = 0;
86       pattnr = song[songpos];
87       songend = 1;
88     }
89
90   pattoff = pattpos*9;
91   for (chan=0;chan<9;chan++) {                  // handle all channels
92     note = patterns[pattnr][pattoff].note;
93     effect = patterns[pattnr][pattoff].effect;
94     pattoff++;
95
96     if(note & 128) {                    // set instrument
97       setinstr(chan,effect);
98       continue;
99     }
100     eff_op = effect & 0x0f;
101     inst = channel[chan].inst;
102     if(note)
103       channel[chan].slide = 0;
104
105     switch (effect & 0xf0) {                    // effect handling
106     case 0:                                                             // global effect
107       /* The following fx are unimplemented on purpose:
108        * 02 - Slide Mainvolume up
109        * 03 - Slide Mainvolume down (here: fade in)
110        * 04 - Set Mainvolume to 0
111        *
112        * This is because i've never seen any HSC modules using the fx this way.
113        * All modules use the fx the way, i've implemented it.
114        */
115       switch(eff_op) {
116       case 1: pattbreak++; break;       // jump to next pattern
117       case 3: fadein = 31; break;       // fade in (divided by 2)
118       case 5: mode6 = 1; break; // 6 voice mode on
119       case 6: mode6 = 0; break; // 6 voice mode off
120       }
121       break;
122     case 0x20:
123     case 0x10:                              // manual slides
124       if (effect & 0x10) {
125         channel[chan].freq += eff_op;
126         channel[chan].slide += eff_op;
127       } else {
128         channel[chan].freq -= eff_op;
129         channel[chan].slide -= eff_op;
130       }
131       if(!note)
132         setfreq(chan,channel[chan].freq);
133       break;
134     case 0x50:                                                  // set percussion instrument (unimplemented)
135       break;
136     case 0x60:                                                  // set feedback
137       opl->write(0xc0 + chan, (instr[channel[chan].inst][8] & 1) + (eff_op << 1));
138       break;
139     case 0xa0:                              // set carrier volume
140       vol = eff_op << 2;
141       opl->write(0x43 + op_table[chan], vol | (instr[channel[chan].inst][2] & ~63));
142       break;
143     case 0xb0:                              // set modulator volume
144       vol = eff_op << 2;
145       if (instr[inst][8] & 1)
146         opl->write(0x40 + op_table[chan], vol | (instr[channel[chan].inst][3] & ~63));
147       else
148         opl->write(0x40 + op_table[chan],vol | (instr[inst][3] & ~63));
149       break;
150     case 0xc0:                              // set instrument volume
151       db = eff_op << 2;
152       opl->write(0x43 + op_table[chan], db | (instr[channel[chan].inst][2] & ~63));
153       if (instr[inst][8] & 1)
154         opl->write(0x40 + op_table[chan], db | (instr[channel[chan].inst][3] & ~63));
155       break;
156     case 0xd0: pattbreak++; songpos = eff_op; songend = 1; break;       // position jump
157     case 0xf0:                                                  // set speed
158       speed = eff_op;
159       del = ++speed;
160       break;
161     }
162
163     if(fadein)                                          // fade-in volume setting
164       setvolume(chan,fadein*2,fadein*2);
165
166     if(!note)                                           // note handling
167       continue;
168     note--;
169
170     if ((note == 0x7f-1) || ((note/12) & ~7)) {    // pause (7fh)
171       adl_freq[chan] &= ~32;
172       opl->write(0xb0 + chan,adl_freq[chan]);
173       continue;
174     }
175
176     // play the note
177     if(mtkmode)         // imitate MPU-401 Trakker bug
178       note--;
179     Okt = ((note/12) & 7) << 2;
180     Fnr = note_table[(note % 12)] + instr[inst][11] + channel[chan].slide;
181     channel[chan].freq = Fnr;
182     if(!mode6 || chan < 6)
183       adl_freq[chan] = Okt | 32;
184     else
185       adl_freq[chan] = Okt;             // never set key for drums
186     opl->write(0xb0 + chan, 0);
187     setfreq(chan,Fnr);
188     if(mode6) {
189       switch(chan) {            // play drums
190       case 6: opl->write(0xbd,bd & ~16); bd |= 48; break;       // bass drum
191       case 7: opl->write(0xbd,bd & ~1); bd |= 33; break;        // hihat
192       case 8: opl->write(0xbd,bd & ~2); bd |= 34; break;        // cymbal
193       }
194       opl->write(0xbd,bd);
195     }
196   }
197
198   del = speed;          // player speed-timing
199   if(pattbreak) {               // do post-effect handling
200     pattpos=0;                  // pattern break!
201     pattbreak=0;
202     songpos++;
203     songpos %= 50;
204     if(!songpos)
205       songend = 1;
206   } else {
207     pattpos++;
208     pattpos &= 63;              // advance in pattern data
209     if (!pattpos) {
210       songpos++;
211       songpos %= 50;
212       if(!songpos)
213         songend = 1;
214     }
215   }
216   return !songend;              // still playing
217 }
218
219 void ChscPlayer::rewind(int subsong)
220 {
221   int i;                                                                // counter
222
223   // rewind HSC player
224   pattpos = 0; songpos = 0; pattbreak = 0; speed = 2;
225   del = 1; songend = 0; mode6 = 0; bd = 0; fadein = 0;
226
227   opl->init();                                          // reset OPL chip
228   opl->write(1,32); opl->write(8,128); opl->write(0xbd,0);
229
230   for(i=0;i<9;i++)
231     setinstr((char) i,(char) i);        // init channels
232 }
233
234 unsigned int ChscPlayer::getpatterns()
235 {
236   unsigned char poscnt,pattcnt=0;
237
238   // count patterns
239   for(poscnt=0;poscnt<51 && song[poscnt] != 0xff;poscnt++)
240     if(song[poscnt] > pattcnt)
241       pattcnt = song[poscnt];
242
243   return (pattcnt+1);
244 }
245
246 unsigned int ChscPlayer::getorders()
247 {
248   unsigned char poscnt;
249
250   // count positions
251   for(poscnt=0;poscnt<51;poscnt++)
252     if(song[poscnt] == 0xff)
253       break;
254
255   return poscnt;
256 }
257
258 unsigned int ChscPlayer::getinstruments()
259 {
260   unsigned char instcnt,instnum=0,i;
261   bool          isinst;
262
263   // count instruments
264   for(instcnt=0;instcnt<128;instcnt++) {
265     isinst = false;
266     for(i=0;i<12;i++)
267       if(instr[instcnt][i])
268         isinst = true;
269     if(isinst)
270       instnum++;
271   }
272
273   return instnum;
274 }
275
276 /*** private methods *************************************/
277
278 void ChscPlayer::setfreq(unsigned char chan, unsigned short freq)
279 {
280   adl_freq[chan] = (adl_freq[chan] & ~3) | (freq >> 8);
281
282   opl->write(0xa0 + chan, freq & 0xff);
283   opl->write(0xb0 + chan, adl_freq[chan]);
284 }
285
286 void ChscPlayer::setvolume(unsigned char chan, int volc, int volm)
287 {
288   unsigned char *ins = instr[channel[chan].inst];
289   char          op = op_table[chan];
290
291   opl->write(0x43 + op,volc | (ins[2] & ~63));
292   if (ins[8] & 1)                                                       // carrier
293     opl->write(0x40 + op,volm | (ins[3] & ~63));
294   else
295     opl->write(0x40 + op, ins[3]);              // modulator
296 }
297
298 void ChscPlayer::setinstr(unsigned char chan, unsigned char insnr)
299 {
300   unsigned char *ins = instr[insnr];
301   char          op = op_table[chan];
302
303   channel[chan].inst = insnr;           // set internal instrument
304   opl->write(0xb0 + chan,0);                    // stop old note
305
306   // set instrument
307   opl->write(0xc0 + chan, ins[8]);
308   opl->write(0x23 + op, ins[0]);        // carrier
309   opl->write(0x20 + op, ins[1]);        // modulator
310   opl->write(0x63 + op, ins[4]);        // bits 0..3 = decay; 4..7 = attack
311   opl->write(0x60 + op, ins[5]);
312   opl->write(0x83 + op, ins[6]);        // 0..3 = release; 4..7 = sustain
313   opl->write(0x80 + op, ins[7]);
314   opl->write(0xe3 + op, ins[9]);        // bits 0..1 = Wellenform
315   opl->write(0xe0 + op, ins[10]);
316   setvolume(chan, ins[2] & 63, ins[3] & 63);
317 }