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