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  * mkj.cpp - MKJamz Player, by Simon Peter <dn.tlp@gmx.net>
20  */
21 
22 #include <string.h>
23 #include <assert.h>
24 
25 #include "mkj.h"
26 #include "debug.h"
27 
factory(Copl * newopl)28 CPlayer *CmkjPlayer::factory(Copl *newopl)
29 {
30   return new CmkjPlayer(newopl);
31 }
32 
load(const char * filename,const CFileProvider & fp)33 bool CmkjPlayer::load(const char *filename, const CFileProvider &fp)
34 {
35   binistream *f = fp.open(filename); if(!f) return false;
36   char	id[6];
37   float	ver;
38   int	i, j;
39   short	inst[8];
40 
41   // file validation
42   f->readString(id, 6);
43   if(strncmp(id,"MKJamz",6)) { fp.close(f); return false; }
44   ver = f->readFloat(binio::Single);
45   if(ver > 1.12) { fp.close(f); return false; }
46 
47   // load
48   maxchannel = f->readInt(2);
49   opl->init(); opl->write(1, 32);
50   for(i = 0; i < maxchannel; i++) {
51     for(j = 0; j < 8; j++) inst[j] = f->readInt(2);
52     opl->write(0x20+op_table[i],inst[4]);
53     opl->write(0x23+op_table[i],inst[0]);
54     opl->write(0x40+op_table[i],inst[5]);
55     opl->write(0x43+op_table[i],inst[1]);
56     opl->write(0x60+op_table[i],inst[6]);
57     opl->write(0x63+op_table[i],inst[2]);
58     opl->write(0x80+op_table[i],inst[7]);
59     opl->write(0x83+op_table[i],inst[3]);
60   }
61   maxnotes = f->readInt(2);
62   songbuf = new short [(maxchannel+1)*maxnotes];
63   for(i = 0; i < maxchannel; i++) channel[i].defined = f->readInt(2);
64   for(i = 0; i < (maxchannel + 1) * maxnotes; i++)
65     songbuf[i] = f->readInt(2);
66 
67   AdPlug_LogWrite("CmkjPlayer::load(\"%s\"): loaded file ver %.2f, %d channels,"
68 		  " %d notes/channel.\n", filename, ver, maxchannel,
69 		  maxnotes);
70   fp.close(f);
71   rewind(0);
72   return true;
73 }
74 
update()75 bool CmkjPlayer::update()
76 {
77   int c, i;
78   short note;
79 
80   for(c = 0; c < maxchannel; c++) {
81     if(!channel[c].defined)	// skip if channel is disabled
82       continue;
83 
84     if(channel[c].pstat) {
85       channel[c].pstat--;
86       continue;
87     }
88 
89     opl->write(0xb0 + c, 0);	// key off
90     do {
91       assert(channel[c].songptr < (maxchannel + 1) * maxnotes);
92       note = songbuf[channel[c].songptr];
93       if(channel[c].songptr - c > maxchannel)
94 	if(note && note < 250)
95 	  channel[c].pstat = channel[c].speed;
96       switch(note) {
97 	// normal notes
98       case 68: opl->write(0xa0 + c,0x81); opl->write(0xb0 + c,0x21 + 4 * channel[c].octave); break;
99       case 69: opl->write(0xa0 + c,0xb0); opl->write(0xb0 + c,0x21 + 4 * channel[c].octave); break;
100       case 70: opl->write(0xa0 + c,0xca); opl->write(0xb0 + c,0x21 + 4 * channel[c].octave); break;
101       case 71: opl->write(0xa0 + c,0x2); opl->write(0xb0 + c,0x22 + 4 * channel[c].octave); break;
102       case 65: opl->write(0xa0 + c,0x41); opl->write(0xb0 + c,0x22 + 4 * channel[c].octave); break;
103       case 66: opl->write(0xa0 + c,0x87); opl->write(0xb0 + c,0x22 + 4 * channel[c].octave); break;
104       case 67: opl->write(0xa0 + c,0xae); opl->write(0xb0 + c,0x22 + 4 * channel[c].octave); break;
105       case 17: opl->write(0xa0 + c,0x6b); opl->write(0xb0 + c,0x21 + 4 * channel[c].octave); break;
106       case 18: opl->write(0xa0 + c,0x98); opl->write(0xb0 + c,0x21 + 4 * channel[c].octave); break;
107       case 20: opl->write(0xa0 + c,0xe5); opl->write(0xb0 + c,0x21 + 4 * channel[c].octave); break;
108       case 21: opl->write(0xa0 + c,0x20); opl->write(0xb0 + c,0x22 + 4 * channel[c].octave); break;
109       case 15: opl->write(0xa0 + c,0x63); opl->write(0xb0 + c,0x22 + 4 * channel[c].octave); break;
110       case 255:	// delay
111 	channel[c].songptr += maxchannel;
112 	channel[c].pstat = songbuf[channel[c].songptr];
113 	break;
114       case 254:	// set octave
115 	channel[c].songptr += maxchannel;
116 	channel[c].octave = songbuf[channel[c].songptr];
117 	break;
118       case 253:	// set speed
119 	channel[c].songptr += maxchannel;
120 	channel[c].speed = songbuf[channel[c].songptr];
121 	break;
122       case 252:	// set waveform
123 	channel[c].songptr += maxchannel;
124 	channel[c].waveform = songbuf[channel[c].songptr] - 300;
125 	if(c > 2)
126 	  opl->write(0xe0 + c + (c+6),channel[c].waveform);
127 	else
128 	  opl->write(0xe0 + c,channel[c].waveform);
129 	break;
130       case 251:	// song end
131 	for(i = 0; i < maxchannel; i++) channel[i].songptr = i;
132 	songend = true;
133 	return false;
134       }
135 
136       if(channel[c].songptr - c < maxnotes)
137 	channel[c].songptr += maxchannel;
138       else
139 	channel[c].songptr = c;
140     } while(!channel[c].pstat);
141   }
142 
143   return !songend;
144 }
145 
rewind(int subsong)146 void CmkjPlayer::rewind(int subsong)
147 {
148   int i;
149 
150   for(i = 0; i < maxchannel; i++) {
151     channel[i].pstat = 0;
152     channel[i].speed = 0;
153     channel[i].waveform = 0;
154     channel[i].songptr = i;
155     channel[i].octave = 4;
156   }
157 
158   songend = false;
159 }
160 
getrefresh()161 float CmkjPlayer::getrefresh()
162 {
163   return 100.0f;
164 }
165