1
/* ScummVM - Graphic Adventure Engine
3
* ScummVM is the legal property of its developers, whose names
4
* are too numerous to list here. Please refer to the COPYRIGHT
5
* file distributed with this source distribution.
7
* This program is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU General Public License
9
* as published by the Free Software Foundation; either version 2
10
* of the License, or (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25
#include "audio/softsynth/emumidi.h"
26
#include "common/debug.h"
27
#include "common/error.h"
28
#include "common/scummsys.h"
29
#include "common/system.h"
30
#include "common/textconsole.h"
31
#include "common/types.h"
32
#include "common/util.h"
33
#include "audio/fmopl.h"
34
#include "audio/musicplugin.h"
35
#include "common/translation.h"
41
class MidiDriver_ADLIB;
44
// We use packing for the following two structs, because the code
45
// does simply copy them over from byte streams, without any
46
// serialization. Check AdLibPart::sysEx_customInstrument for an
49
// It might be very well possible, that none of the compilers we support
50
// add any padding bytes at all, since the structs contain only variables
51
// of the type 'byte'. But better safe than sorry.
52
#include "common/pack-start.h"
53
struct InstrumentExtra {
54
byte a, b, c, d, e, f, g, h;
57
struct AdLibInstrument {
58
byte mod_characteristic;
59
byte mod_scalingOutputLevel;
61
byte mod_sustainRelease;
62
byte mod_waveformSelect;
63
byte car_characteristic;
64
byte car_scalingOutputLevel;
66
byte car_sustainRelease;
67
byte car_waveformSelect;
70
InstrumentExtra extra_a;
72
InstrumentExtra extra_b;
75
AdLibInstrument() { memset(this, 0, sizeof(AdLibInstrument)); }
77
#include "common/pack-end.h"
79
class AdLibPart : public MidiChannel {
80
friend class MidiDriver_ADLIB;
83
// AdLibPart *_prev, *_next;
86
byte _pitchbend_factor;
94
AdLibInstrument _part_instr;
97
MidiDriver_ADLIB *_owner;
101
void init(MidiDriver_ADLIB *owner, byte channel);
102
void allocate() { _allocated = true; }
108
_pitchbend_factor = 2;
122
MidiDriver *device();
123
byte getNumber() { return _channel; }
124
void release() { _allocated = false; }
129
void noteOff(byte note);
130
void noteOn(byte note, byte velocity);
131
void programChange(byte program);
132
void pitchBend(int16 bend);
134
// Control Change messages
135
void controlChange(byte control, byte value);
136
void modulationWheel(byte value);
137
void volume(byte value);
138
void panPosition(byte value) { return; } // Not supported
139
void pitchBendFactor(byte value);
140
void detune(byte value);
141
void priority(byte value);
142
void sustain(bool value);
143
void effectLevel(byte value) { return; } // Not supported
144
void chorusLevel(byte value) { return; } // Not supported
148
void sysEx_customInstrument(uint32 type, const byte *instr);
152
// It is assumed that any invocation to AdLibPercussionChannel
153
// will be done through the MidiChannel base class as opposed to the
154
// AdLibPart base class. If this were NOT the case, all the functions
155
// listed below would need to be virtual in AdLibPart as well as MidiChannel.
156
class AdLibPercussionChannel : public AdLibPart {
157
friend class MidiDriver_ADLIB;
160
void init(MidiDriver_ADLIB *owner, byte channel);
163
~AdLibPercussionChannel();
165
void noteOff(byte note);
166
void noteOn(byte note, byte velocity);
167
void programChange(byte program) { }
168
void pitchBend(int16 bend) { }
170
// Control Change messages
171
void modulationWheel(byte value) { }
172
void pitchBendFactor(byte value) { }
173
void detune(byte value) { }
174
void priority(byte value) { }
175
void sustain(bool value) { }
178
void sysEx_customInstrument(uint32 type, const byte *instr);
182
AdLibInstrument *_customInstruments[256];
202
uint16 speed_lo_counter;
207
byte param, flag0x40, flag0x10;
213
AdLibVoice *_next, *_prev;
226
AdLibVoice() { memset(this, 0, sizeof(AdLibVoice)); }
229
struct AdLibSetParams {
233
static const byte channel_mappings[9] = {
239
static const byte channel_mappings_2[9] = {
245
static const AdLibSetParams adlib_setparam_table[] = {
246
{0x40, 0, 63, 63}, // level
247
{0xE0, 2, 0, 0}, // unused
248
{0x40, 6, 192, 0}, // level key scaling
249
{0x20, 0, 15, 0}, // modulator frequency multiple
250
{0x60, 4, 240, 15}, // attack rate
251
{0x60, 0, 15, 15}, // decay rate
252
{0x80, 4, 240, 15}, // sustain level
253
{0x80, 0, 15, 15}, // release rate
254
{0xE0, 0, 3, 0}, // waveformSelect select
255
{0x20, 7, 128, 0}, // amp mod
256
{0x20, 6, 64, 0}, // vib
257
{0x20, 5, 32, 0}, // eg typ
258
{0x20, 4, 16, 0}, // ksr
259
{0xC0, 0, 1, 0}, // decay alg
260
{0xC0, 1, 14, 0} // feedback
263
static const byte param_table_1[16] = {
270
static const uint16 maxval_table[16] = {
271
0x2FF, 0x1F, 0x7, 0x3F,
272
0x0F, 0x0F, 0x0F, 0x3,
273
0x3F, 0x0F, 0x0F, 0x0F,
277
static const uint16 num_steps_table[] = {
288
static const byte note_to_f_num[] = {
289
90, 91, 92, 92, 93, 94, 94, 95,
290
96, 96, 97, 98, 98, 99, 100, 101,
291
101, 102, 103, 104, 104, 105, 106, 107,
292
107, 108, 109, 110, 111, 111, 112, 113,
293
114, 115, 115, 116, 117, 118, 119, 120,
294
121, 121, 122, 123, 124, 125, 126, 127,
295
128, 129, 130, 131, 132, 132, 133, 134,
296
135, 136, 137, 138, 139, 140, 141, 142,
297
143, 145, 146, 147, 148, 149, 150, 151,
298
152, 153, 154, 155, 157, 158, 159, 160,
299
161, 162, 163, 165, 166, 167, 168, 169,
300
171, 172, 173, 174, 176, 177, 178, 180,
301
181, 182, 184, 185, 186, 188, 189, 190,
302
192, 193, 194, 196, 197, 199, 200, 202,
303
203, 205, 206, 208, 209, 211, 212, 214,
304
215, 217, 218, 220, 222, 223, 225, 226,
305
228, 230, 231, 233, 235, 236, 238, 240,
306
242, 243, 245, 247, 249, 251, 252, 254
309
static const byte map_gm_to_fm[128][30] = {
311
{ 0xC2, 0xC5, 0x2B, 0x99, 0x58, 0xC2, 0x1F, 0x1E, 0xC8, 0x7C, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x23 },
312
{ 0x22, 0x53, 0x0E, 0x8A, 0x30, 0x14, 0x06, 0x1D, 0x7A, 0x5C, 0x06, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
313
{ 0x06, 0x00, 0x1C, 0x79, 0x40, 0x02, 0x00, 0x4B, 0x79, 0x58, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
314
{ 0xC2, 0x89, 0x2A, 0x89, 0x49, 0xC2, 0x16, 0x1C, 0xB8, 0x7C, 0x04, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x23 },
315
{ 0xC2, 0x17, 0x3D, 0x6A, 0x00, 0xC4, 0x2E, 0x2D, 0xC9, 0x20, 0x00, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
316
{ 0x06, 0x1E, 0x1C, 0x99, 0x00, 0x02, 0x3A, 0x4C, 0x79, 0x00, 0x0C, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
317
{ 0x84, 0x40, 0x3B, 0x5A, 0x6F, 0x81, 0x0E, 0x3B, 0x5A, 0x7F, 0x0B, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
318
{ 0x84, 0x40, 0x3B, 0x5A, 0x63, 0x81, 0x00, 0x3B, 0x5A, 0x7F, 0x01, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
319
{ 0x8C, 0x80, 0x05, 0xEA, 0x59, 0x82, 0x0A, 0x3C, 0xAA, 0x64, 0x07, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
320
{ 0x85, 0x40, 0x0D, 0xEC, 0x71, 0x84, 0x58, 0x3E, 0xCB, 0x7C, 0x01, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
321
{ 0x8A, 0xC0, 0x0C, 0xDC, 0x50, 0x88, 0x58, 0x3D, 0xDA, 0x7C, 0x01, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
322
{ 0xC9, 0x40, 0x2B, 0x78, 0x42, 0xC2, 0x04, 0x4C, 0x8A, 0x7C, 0x00, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x1A },
323
{ 0x2A, 0x0E, 0x17, 0x89, 0x28, 0x22, 0x0C, 0x1B, 0x09, 0x70, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
324
{ 0xE7, 0x9B, 0x08, 0x08, 0x26, 0xE2, 0x06, 0x0A, 0x08, 0x70, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
325
{ 0xC5, 0x05, 0x00, 0xFC, 0x40, 0x84, 0x00, 0x00, 0xDC, 0x50, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
326
{ 0x86, 0x40, 0x5D, 0x5A, 0x41, 0x81, 0x00, 0x0B, 0x5A, 0x7F, 0x00, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
328
{ 0xED, 0x00, 0x7B, 0xC8, 0x40, 0xE1, 0x99, 0x4A, 0xE9, 0x7E, 0x07, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
329
{ 0xE8, 0x4F, 0x3A, 0xD7, 0x7C, 0xE2, 0x97, 0x49, 0xF9, 0x7D, 0x05, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
330
{ 0xE1, 0x10, 0x2F, 0xF7, 0x7D, 0xF3, 0x45, 0x8F, 0xC7, 0x62, 0x07, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
331
{ 0x01, 0x8C, 0x9F, 0xDA, 0x70, 0xE4, 0x50, 0x9F, 0xDA, 0x6A, 0x09, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
332
{ 0x08, 0xD5, 0x9D, 0xA5, 0x45, 0xE2, 0x3F, 0x9F, 0xD6, 0x49, 0x07, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
333
{ 0xE5, 0x0F, 0x7D, 0xB8, 0x2E, 0xA2, 0x0F, 0x7C, 0xC7, 0x61, 0x04, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
334
{ 0xF2, 0x2A, 0x9F, 0xDB, 0x01, 0xE1, 0x04, 0x8F, 0xD7, 0x62, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
335
{ 0xE4, 0x88, 0x9C, 0x50, 0x64, 0xE2, 0x18, 0x70, 0xC4, 0x7C, 0x0B, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
336
{ 0x02, 0xA3, 0x0D, 0xDA, 0x01, 0xC2, 0x35, 0x5D, 0x58, 0x00, 0x06, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x18 },
337
{ 0x42, 0x55, 0x3E, 0xEB, 0x24, 0xD4, 0x08, 0x0D, 0xA9, 0x71, 0x04, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x18 },
338
{ 0xC2, 0x00, 0x2B, 0x17, 0x51, 0xC2, 0x1E, 0x4D, 0x97, 0x7C, 0x00, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x19 },
339
{ 0xC6, 0x01, 0x2D, 0xA7, 0x44, 0xC2, 0x06, 0x0E, 0xA7, 0x79, 0x06, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
340
{ 0xC2, 0x0C, 0x06, 0x06, 0x55, 0xC2, 0x3F, 0x09, 0x86, 0x7D, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x0A },
341
{ 0xC2, 0x2E, 0x4F, 0x77, 0x00, 0xC4, 0x08, 0x0E, 0x98, 0x59, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
342
{ 0xC2, 0x30, 0x4F, 0xCA, 0x01, 0xC4, 0x0D, 0x0E, 0xB8, 0x7F, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
343
{ 0xC4, 0x29, 0x4F, 0xCA, 0x03, 0xC8, 0x0D, 0x0C, 0xB7, 0x7D, 0x00, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x0B },
345
{ 0xC2, 0x40, 0x3C, 0x96, 0x58, 0xC4, 0xDE, 0x0E, 0xC7, 0x7C, 0x00, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x20 },
346
{ 0x31, 0x13, 0x2D, 0xD7, 0x3C, 0xE2, 0x18, 0x2E, 0xB8, 0x7C, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
347
{ 0x22, 0x86, 0x0D, 0xD7, 0x50, 0xE4, 0x18, 0x5E, 0xB8, 0x7C, 0x06, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x28 },
348
{ 0xF2, 0x0A, 0x0D, 0xD7, 0x40, 0xE4, 0x1F, 0x5E, 0xB8, 0x7C, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
349
{ 0xF2, 0x09, 0x4B, 0xD6, 0x48, 0xE4, 0x1F, 0x1C, 0xB8, 0x7C, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x28 },
350
{ 0x62, 0x11, 0x0C, 0xE6, 0x3C, 0xE4, 0x1F, 0x0C, 0xC8, 0x7C, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
351
{ 0xE2, 0x12, 0x3D, 0xE6, 0x34, 0xE4, 0x1F, 0x7D, 0xB8, 0x7C, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
352
{ 0xE2, 0x13, 0x3D, 0xE6, 0x34, 0xE4, 0x1F, 0x5D, 0xB8, 0x7D, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
353
{ 0xA2, 0x40, 0x5D, 0xBA, 0x3F, 0xE2, 0x00, 0x8F, 0xD8, 0x79, 0x00, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
354
{ 0xE2, 0x40, 0x3D, 0xDA, 0x3B, 0xE1, 0x00, 0x7E, 0xD8, 0x7A, 0x04, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
355
{ 0x62, 0x00, 0x6D, 0xFA, 0x5D, 0xE2, 0x00, 0x8F, 0xC8, 0x79, 0x04, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
356
{ 0xE1, 0x00, 0x4E, 0xDB, 0x4A, 0xE3, 0x18, 0x6F, 0xE9, 0x7E, 0x00, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
357
{ 0xE1, 0x00, 0x4E, 0xDB, 0x66, 0xE2, 0x00, 0x7F, 0xE9, 0x7E, 0x06, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
358
{ 0x02, 0x0F, 0x66, 0xAA, 0x51, 0x02, 0x64, 0x29, 0xF9, 0x7C, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x04 },
359
{ 0x16, 0x4A, 0x04, 0xBA, 0x39, 0xC2, 0x58, 0x2D, 0xCA, 0x7C, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x03 },
360
{ 0x02, 0x00, 0x01, 0x7A, 0x79, 0x02, 0x3F, 0x28, 0xEA, 0x7C, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x02 },
362
{ 0x62, 0x53, 0x9C, 0xBA, 0x31, 0x62, 0x5B, 0xAD, 0xC9, 0x55, 0x04, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
363
{ 0xF2, 0x40, 0x6E, 0xDA, 0x49, 0xE2, 0x13, 0x8F, 0xF9, 0x7D, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
364
{ 0xE2, 0x40, 0x8F, 0xFA, 0x50, 0xF2, 0x04, 0x7F, 0xFA, 0x7D, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
365
{ 0xE4, 0xA0, 0xCE, 0x5B, 0x02, 0xE2, 0x32, 0x7F, 0xFB, 0x3D, 0x04, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
366
{ 0xE6, 0x80, 0x9C, 0x99, 0x42, 0xE2, 0x04, 0x7D, 0x78, 0x60, 0x04, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
367
{ 0xEA, 0xA0, 0xAC, 0x67, 0x02, 0xE2, 0x00, 0x7C, 0x7A, 0x7C, 0x06, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
368
{ 0xE7, 0x94, 0xAD, 0xB7, 0x03, 0xE2, 0x00, 0x7C, 0xBA, 0x7C, 0x00, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
369
{ 0xC3, 0x3F, 0x4B, 0xE9, 0x7E, 0xC1, 0x3F, 0x9B, 0xF9, 0x7F, 0x0B, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x06 },
370
{ 0xB2, 0x20, 0xAD, 0xE9, 0x00, 0x62, 0x05, 0x8F, 0xC8, 0x68, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
371
{ 0xF2, 0x00, 0x8F, 0xFB, 0x50, 0xF6, 0x47, 0x8F, 0xE9, 0x68, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
372
{ 0xF2, 0x00, 0xAF, 0x88, 0x58, 0xF2, 0x54, 0x6E, 0xC9, 0x7C, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
373
{ 0xF2, 0x2A, 0x9F, 0x98, 0x01, 0xE2, 0x84, 0x4E, 0x78, 0x6C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
374
{ 0xE2, 0x02, 0x9F, 0xB8, 0x48, 0x22, 0x89, 0x9F, 0xE8, 0x7C, 0x00, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
375
{ 0xE2, 0x2A, 0x7F, 0xB8, 0x01, 0xE4, 0x00, 0x0D, 0xC5, 0x7C, 0x0C, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
376
{ 0xE4, 0x28, 0x8E, 0xE8, 0x01, 0xF2, 0x00, 0x4D, 0xD6, 0x7D, 0x0C, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
377
{ 0x62, 0x23, 0x8F, 0xEA, 0x00, 0xF2, 0x00, 0x5E, 0xD9, 0x7C, 0x0C, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
379
{ 0xB4, 0x26, 0x6E, 0x98, 0x01, 0x62, 0x00, 0x7D, 0xC8, 0x7D, 0x00, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
380
{ 0xE2, 0x2E, 0x20, 0xD9, 0x01, 0xF2, 0x0F, 0x90, 0xF8, 0x78, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
381
{ 0xE4, 0x28, 0x7E, 0xF8, 0x01, 0xE2, 0x23, 0x8E, 0xE8, 0x7D, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
382
{ 0xB8, 0x28, 0x9E, 0x98, 0x01, 0x62, 0x00, 0x3D, 0xC8, 0x7D, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
383
{ 0x62, 0x00, 0x8E, 0xC9, 0x3D, 0xE6, 0x00, 0x7E, 0xD8, 0x68, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
384
{ 0xE2, 0x00, 0x5F, 0xF9, 0x48, 0xE6, 0x98, 0x8F, 0xF8, 0x7D, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
385
{ 0x62, 0x0C, 0x6E, 0xD8, 0x3D, 0x2A, 0x06, 0x7D, 0xD8, 0x58, 0x04, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
386
{ 0xE4, 0x00, 0x7E, 0x89, 0x38, 0xE6, 0x84, 0x80, 0xF8, 0x68, 0x0C, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
387
{ 0xE4, 0x80, 0x6C, 0xD9, 0x30, 0xE2, 0x00, 0x8D, 0xC8, 0x7C, 0x00, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
388
{ 0xE2, 0x80, 0x88, 0x48, 0x40, 0xE2, 0x0A, 0x7D, 0xA8, 0x7C, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
389
{ 0xE4, 0x00, 0x77, 0xC5, 0x54, 0xE2, 0x00, 0x9E, 0xD7, 0x70, 0x06, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
390
{ 0xE4, 0x80, 0x86, 0xB9, 0x64, 0xE2, 0x05, 0x9F, 0xD7, 0x78, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
391
{ 0xE2, 0x00, 0x68, 0x68, 0x56, 0xE2, 0x08, 0x9B, 0xB3, 0x7C, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
392
{ 0xE4, 0x00, 0xA6, 0x87, 0x41, 0xE2, 0x0A, 0x7E, 0xC9, 0x7C, 0x06, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
393
{ 0xE4, 0x80, 0x9A, 0xB8, 0x48, 0xE2, 0x00, 0x9E, 0xF9, 0x60, 0x09, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
394
{ 0xE2, 0x80, 0x8E, 0x64, 0x68, 0xE2, 0x28, 0x6F, 0x73, 0x7C, 0x01, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
396
{ 0xE8, 0x00, 0x7D, 0x99, 0x54, 0xE6, 0x80, 0x80, 0xF8, 0x7C, 0x0C, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
397
{ 0xE6, 0x00, 0x9F, 0xB9, 0x6D, 0xE1, 0x00, 0x8F, 0xC8, 0x7D, 0x02, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
398
{ 0xE4, 0x00, 0x09, 0x68, 0x4A, 0xE2, 0x2B, 0x9E, 0xF3, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
399
{ 0xC4, 0x00, 0x99, 0xE8, 0x3B, 0xE2, 0x25, 0x6F, 0x93, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
400
{ 0xE6, 0x00, 0x6F, 0xDA, 0x69, 0xE2, 0x05, 0x2F, 0xD8, 0x6A, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
401
{ 0xEC, 0x60, 0x9D, 0xC7, 0x00, 0xE2, 0x21, 0x7F, 0xC9, 0x7C, 0x06, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
402
{ 0xE3, 0x00, 0x0F, 0xF7, 0x7D, 0xE1, 0x3F, 0x0F, 0xA7, 0x01, 0x0D, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
403
{ 0xE4, 0xA9, 0x0F, 0xA8, 0x02, 0xE2, 0x3C, 0x5F, 0xDA, 0x3C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
404
{ 0xE8, 0x40, 0x0D, 0x89, 0x7D, 0xE2, 0x17, 0x7E, 0xD9, 0x7C, 0x07, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
405
{ 0xE1, 0x00, 0xDF, 0x8A, 0x56, 0xE2, 0x5E, 0xCF, 0xBA, 0x7E, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
406
{ 0xE2, 0x00, 0x0B, 0x68, 0x60, 0xE2, 0x01, 0x9E, 0xB8, 0x7C, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
407
{ 0xEA, 0x00, 0xAE, 0xAB, 0x49, 0xE2, 0x00, 0xAE, 0xBA, 0x6C, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
408
{ 0xEB, 0x80, 0x8C, 0xCB, 0x3A, 0xE2, 0x86, 0xAF, 0xCA, 0x7C, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
409
{ 0xE5, 0x40, 0xDB, 0x3B, 0x3C, 0xE2, 0x80, 0xBE, 0xCA, 0x71, 0x00, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
410
{ 0xE4, 0x00, 0x9E, 0xAA, 0x3D, 0xE1, 0x43, 0x0F, 0xBA, 0x7E, 0x04, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
411
{ 0xE7, 0x40, 0xEC, 0xCA, 0x44, 0xE2, 0x03, 0xBF, 0xBA, 0x66, 0x02, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
413
{ 0xEA, 0x00, 0x68, 0xB8, 0x48, 0xE2, 0x0A, 0x8E, 0xB8, 0x7C, 0x0C, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
414
{ 0x61, 0x00, 0xBE, 0x99, 0x7E, 0xE3, 0x40, 0xCF, 0xCA, 0x7D, 0x09, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
415
{ 0xCD, 0x00, 0x0B, 0x00, 0x48, 0xC2, 0x58, 0x0C, 0x00, 0x7C, 0x0C, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x1C },
416
{ 0xE2, 0x00, 0x0E, 0x00, 0x52, 0xE2, 0x58, 0x5F, 0xD0, 0x7D, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
417
{ 0xCC, 0x00, 0x7D, 0xDA, 0x40, 0xC2, 0x00, 0x5E, 0x9B, 0x58, 0x0C, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
418
{ 0xE9, 0xC0, 0xEE, 0xD8, 0x43, 0xE2, 0x05, 0xDD, 0xAA, 0x70, 0x06, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
419
{ 0xDA, 0x00, 0x8F, 0xAC, 0x4A, 0x22, 0x05, 0x8D, 0x8A, 0x75, 0x02, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
420
{ 0x62, 0x8A, 0xCB, 0x7A, 0x74, 0xE6, 0x56, 0xAF, 0xDB, 0x70, 0x02, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
421
{ 0xC2, 0x41, 0xAC, 0x5B, 0x5B, 0xC2, 0x80, 0x0D, 0xCB, 0x7D, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x12 },
422
{ 0x75, 0x00, 0x0E, 0xCB, 0x5A, 0xE2, 0x1E, 0x0A, 0xC9, 0x7D, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x10 },
423
{ 0x41, 0x00, 0x0E, 0xEA, 0x53, 0xC2, 0x00, 0x08, 0xCA, 0x7C, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x07 },
424
{ 0xC1, 0x40, 0x0C, 0x59, 0x6A, 0xC2, 0x80, 0x3C, 0xAB, 0x7C, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x0D },
425
{ 0x4B, 0x00, 0x0A, 0xF5, 0x61, 0xC2, 0x19, 0x0C, 0xE9, 0x7C, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x07 },
426
{ 0x62, 0x00, 0x7F, 0xD8, 0x54, 0xEA, 0x00, 0x8F, 0xD8, 0x7D, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
427
{ 0xE1, 0x00, 0x7F, 0xD9, 0x56, 0xE1, 0x00, 0x8F, 0xD8, 0x7E, 0x06, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
428
{ 0xE1, 0x00, 0x7F, 0xD9, 0x56, 0xE1, 0x00, 0x8F, 0xD8, 0x7E, 0x06, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
430
{ 0xCF, 0x40, 0x09, 0xEA, 0x54, 0xC4, 0x00, 0x0C, 0xDB, 0x64, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x02 },
431
{ 0xCF, 0x40, 0x0C, 0xAA, 0x54, 0xC4, 0x00, 0x18, 0xF9, 0x64, 0x0C, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x02 },
432
{ 0xC9, 0x0E, 0x88, 0xD9, 0x3E, 0xC2, 0x08, 0x1A, 0xEA, 0x6C, 0x0C, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x05 },
433
{ 0x03, 0x00, 0x15, 0x00, 0x64, 0x02, 0x00, 0x08, 0x00, 0x7C, 0x09, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x02 },
434
{ 0x01, 0x00, 0x47, 0xD7, 0x6C, 0x01, 0x3F, 0x0C, 0xFB, 0x7C, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x04 },
435
{ 0x00, 0x00, 0x36, 0x67, 0x7C, 0x01, 0x3F, 0x0E, 0xFA, 0x7C, 0x00, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x05 },
436
{ 0x02, 0x00, 0x36, 0x68, 0x7C, 0x01, 0x3F, 0x0E, 0xFA, 0x7C, 0x00, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x05 },
437
{ 0xCB, 0x00, 0xAF, 0x00, 0x7E, 0xC0, 0x00, 0xC0, 0x06, 0x7F, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x0F },
438
{ 0x05, 0x0D, 0x80, 0xA6, 0x7F, 0x0B, 0x38, 0xA9, 0xD8, 0x00, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x04 },
439
{ 0x0F, 0x00, 0x90, 0xFA, 0x68, 0x06, 0x00, 0xA7, 0x39, 0x54, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x06 },
440
{ 0xC9, 0x15, 0xDD, 0xFF, 0x7C, 0x00, 0x00, 0xE7, 0xFC, 0x6C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x38 },
441
{ 0x48, 0x3C, 0x30, 0xF6, 0x03, 0x0A, 0x38, 0x97, 0xE8, 0x00, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x04 },
442
{ 0x07, 0x80, 0x0B, 0xC8, 0x65, 0x02, 0x3F, 0x0C, 0xEA, 0x7C, 0x0F, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x05 },
443
{ 0x00, 0x21, 0x66, 0x40, 0x03, 0x00, 0x3F, 0x47, 0x00, 0x00, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x02 },
444
{ 0x08, 0x00, 0x0B, 0x3C, 0x7C, 0x08, 0x3F, 0x06, 0xF3, 0x00, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x02 },
445
{ 0x00, 0x3F, 0x4C, 0xFB, 0x00, 0x00, 0x3F, 0x0A, 0xE9, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x05 }
448
static byte gm_percussion_to_fm[39][30] = {
449
{ 0x1A, 0x3F, 0x15, 0x05, 0x7C, 0x02, 0x21, 0x2B, 0xE4, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x06 },
450
{ 0x11, 0x12, 0x04, 0x07, 0x7C, 0x02, 0x23, 0x0B, 0xE5, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x05 },
451
{ 0x0A, 0x3F, 0x0B, 0x01, 0x7C, 0x1F, 0x1C, 0x46, 0xD0, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x01 },
452
{ 0x00, 0x3F, 0x0F, 0x00, 0x7C, 0x10, 0x12, 0x07, 0x00, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x02 },
453
{ 0x0F, 0x3F, 0x0B, 0x00, 0x7C, 0x1F, 0x0F, 0x19, 0xD0, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x02 },
454
{ 0x00, 0x3F, 0x1F, 0x00, 0x7E, 0x1F, 0x16, 0x07, 0x00, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x03 },
455
{ 0x12, 0x3F, 0x05, 0x06, 0x7C, 0x03, 0x1F, 0x4A, 0xD9, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x03 },
456
{ 0xCF, 0x7F, 0x08, 0xFF, 0x7E, 0x00, 0xC7, 0x2D, 0xF7, 0x73, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x02 },
457
{ 0x12, 0x3F, 0x05, 0x06, 0x7C, 0x43, 0x21, 0x0C, 0xE9, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x03 },
458
{ 0xCF, 0x7F, 0x08, 0xCF, 0x7E, 0x00, 0x45, 0x2A, 0xF8, 0x4B, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x0C },
459
{ 0x12, 0x3F, 0x06, 0x17, 0x7C, 0x03, 0x27, 0x0B, 0xE9, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x03 },
460
{ 0xCF, 0x7F, 0x08, 0xCD, 0x7E, 0x00, 0x40, 0x1A, 0x69, 0x63, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x0C },
461
{ 0x13, 0x3F, 0x05, 0x06, 0x7C, 0x03, 0x17, 0x0A, 0xD9, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x03 },
462
{ 0x15, 0x3F, 0x05, 0x06, 0x7C, 0x03, 0x21, 0x0C, 0xE9, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x03 },
463
{ 0xCF, 0x3F, 0x2B, 0xFB, 0x7E, 0xC0, 0x1E, 0x1A, 0xCA, 0x7F, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x10 },
464
{ 0x17, 0x3F, 0x04, 0x09, 0x7C, 0x03, 0x22, 0x0D, 0xE9, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x03 },
465
{ 0xCF, 0x3F, 0x0F, 0x5E, 0x7C, 0xC6, 0x13, 0x00, 0xCA, 0x7F, 0x04, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x03 },
466
{ 0xCF, 0x3F, 0x7E, 0x9D, 0x7C, 0xC8, 0xC0, 0x0A, 0xBA, 0x74, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x06 },
467
{ 0xCF, 0x3F, 0x4D, 0x9F, 0x7C, 0xC6, 0x00, 0x08, 0xDA, 0x5B, 0x04, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x04 },
468
{ 0xCF, 0x3F, 0x5D, 0xAA, 0x7A, 0xC0, 0xA4, 0x67, 0x99, 0x7C, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x02 },
469
{ 0xCF, 0x3F, 0x4A, 0xFD, 0x7C, 0xCF, 0x00, 0x59, 0xEA, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x02 },
470
{ 0x0F, 0x18, 0x0A, 0xFA, 0x57, 0x06, 0x07, 0x06, 0x39, 0x7C, 0x0A, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x02 },
471
{ 0xCF, 0x3F, 0x2B, 0xFC, 0x7C, 0xCC, 0xC6, 0x0B, 0xEA, 0x7F, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x10 },
472
{ 0x05, 0x1A, 0x04, 0x00, 0x7C, 0x12, 0x10, 0x0C, 0xEA, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x07 },
473
{ 0x04, 0x19, 0x04, 0x00, 0x7C, 0x12, 0x10, 0x2C, 0xEA, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x04 },
474
{ 0x04, 0x0A, 0x04, 0x00, 0x6C, 0x01, 0x07, 0x0D, 0xFA, 0x74, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x07 },
475
{ 0x15, 0x14, 0x05, 0x00, 0x7D, 0x01, 0x07, 0x5C, 0xE9, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x05 },
476
{ 0x10, 0x10, 0x05, 0x08, 0x7C, 0x01, 0x08, 0x0D, 0xEA, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x05 },
477
{ 0x11, 0x00, 0x06, 0x87, 0x7F, 0x02, 0x40, 0x09, 0x59, 0x68, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x08 },
478
{ 0x13, 0x26, 0x04, 0x6A, 0x7F, 0x01, 0x00, 0x08, 0x5A, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x08 },
479
{ 0xCF, 0x4E, 0x0C, 0xAA, 0x50, 0xC4, 0x00, 0x18, 0xF9, 0x54, 0x04, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x02 },
480
{ 0xCF, 0x4E, 0x0C, 0xAA, 0x50, 0xC3, 0x00, 0x18, 0xF8, 0x54, 0x04, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x02 },
481
{ 0xCB, 0x3F, 0x8F, 0x00, 0x7E, 0xC5, 0x00, 0x98, 0xD6, 0x5F, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x0D },
482
{ 0x0C, 0x18, 0x87, 0xB3, 0x7F, 0x19, 0x10, 0x55, 0x75, 0x7C, 0x0E, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x02 },
483
{ 0x05, 0x11, 0x15, 0x00, 0x64, 0x02, 0x08, 0x08, 0x00, 0x5C, 0x09, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x02 },
484
{ 0x04, 0x08, 0x15, 0x00, 0x48, 0x01, 0x08, 0x08, 0x00, 0x60, 0x08, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x02 },
485
{ 0xDA, 0x00, 0x53, 0x30, 0x68, 0x07, 0x1E, 0x49, 0xC4, 0x7E, 0x03, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 },
486
{ 0x1C, 0x00, 0x07, 0xBC, 0x6C, 0x0C, 0x14, 0x0B, 0x6A, 0x7E, 0x0B, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x03 },
487
{ 0x0A, 0x0E, 0x7F, 0x00, 0x7D, 0x13, 0x20, 0x28, 0x03, 0x7C, 0x06, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x00 }
490
static const byte gm_percussion_lookup[128] = {
491
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
492
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
493
0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
494
0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0xFF, 0xFF, 0x17, 0x18, 0x19, 0x1A,
495
0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x21, 0x22, 0x23, 0xFF, 0xFF,
496
0x24, 0x25, 0xFF, 0xFF, 0xFF, 0x26, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
497
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
498
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
501
static byte lookup_table[64][32];
503
static const byte volume_table[] = {
522
static int lookup_volume(int a, int b) {
529
if (a < -63 || a > 63) {
530
return b * (a + 1) >> 5;
535
return lookup_table[-a][-b];
537
return -lookup_table[a][-b];
541
return -lookup_table[-a][b];
543
return lookup_table[a][b];
548
static void create_lookup_table() {
552
for (i = 0; i < 64; i++) {
554
for (j = 0; j < 32; j++) {
555
lookup_table[i][j] = sum >> 5;
559
for (i = 0; i < 64; i++)
560
lookup_table[i][0] = 0;
563
////////////////////////////////////////
567
////////////////////////////////////////
569
class MidiDriver_ADLIB : public MidiDriver_Emulated {
570
friend class AdLibPart;
571
friend class AdLibPercussionChannel;
574
MidiDriver_ADLIB(Audio::Mixer *mixer);
579
void send(byte channel, uint32 b); // Supports higher than channel 15
580
uint32 property(int prop, uint32 param);
582
void setPitchBendRange(byte channel, uint range);
583
void sysEx_customInstrument(byte channel, uint32 type, const byte *instr);
585
MidiChannel *allocateChannel();
586
MidiChannel *getPercussionChannel() { return &_percussion; } // Percussion partially supported
590
bool isStereo() const { return false; }
591
int getRate() const { return _mixer->getOutputRate(); }
594
bool _scummSmallHeader; // FIXME: This flag controls a special mode for SCUMM V3 games
597
byte *_adlib_reg_cache;
599
int _adlib_timer_counter;
601
uint16 channel_table_2[9];
605
uint16 curnote_table[9];
606
AdLibVoice _voices[9];
607
AdLibPart _parts[32];
608
AdLibPercussionChannel _percussion;
610
void generateSamples(int16 *buf, int len);
612
void part_key_on(AdLibPart *part, AdLibInstrument *instr, byte note, byte velocity);
613
void part_key_off(AdLibPart *part, byte note);
615
void adlib_key_off(int chan);
616
void adlib_note_on(int chan, byte note, int mod);
617
void adlib_note_on_ex(int chan, byte note, int mod);
618
int adlib_get_reg_value_param(int chan, byte data);
619
void adlib_setup_channel(int chan, AdLibInstrument * instr, byte vol_1, byte vol_2);
620
byte adlib_get_reg_value(byte reg) {
621
return _adlib_reg_cache[reg];
623
void adlib_set_param(int channel, byte param, int value);
624
void adlib_key_onoff(int channel);
625
void adlib_write(byte reg, byte value);
626
void adlib_playnote(int channel, int note);
628
AdLibVoice *allocate_voice(byte pri);
630
void mc_off(AdLibVoice * voice);
632
static void link_mc(AdLibPart *part, AdLibVoice *voice);
633
void mc_inc_stuff(AdLibVoice *voice, Struct10 * s10, Struct11 * s11);
634
void mc_init_stuff(AdLibVoice *voice, Struct10 * s10, Struct11 * s11, byte flags,
635
InstrumentExtra * ie);
637
void struct10_init(Struct10 * s10, InstrumentExtra * ie);
638
static byte struct10_ontimer(Struct10 * s10, Struct11 * s11);
639
static void struct10_setup(Struct10 * s10);
640
static int random_nr(int a);
641
void mc_key_on(AdLibVoice *voice, AdLibInstrument *instr, byte note, byte velocity);
644
// MidiChannel method implementations
646
void AdLibPart::init(MidiDriver_ADLIB *owner, byte channel) {
653
MidiDriver *AdLibPart::device() {
657
void AdLibPart::send(uint32 b) {
658
_owner->send(_channel, b);
661
void AdLibPart::noteOff(byte note) {
663
debug(6, "%10d: noteOff(%d)", tick, note);
665
_owner->part_key_off(this, note);
668
void AdLibPart::noteOn(byte note, byte velocity) {
670
debug(6, "%10d: noteOn(%d,%d)", tick, note, velocity);
672
_owner->part_key_on(this, &_part_instr, note, velocity);
675
void AdLibPart::programChange(byte program) {
681
for (i = 0; i < ARRAYSIZE(map_gm_to_fm[0]); ++i)
682
count += map_gm_to_fm[program][i];
684
warning("No AdLib instrument defined for GM program %d", (int) program);
686
memcpy(&_part_instr, &map_gm_to_fm[program], sizeof(AdLibInstrument));
689
void AdLibPart::pitchBend(int16 bend) {
693
for (voice = _voice; voice; voice = voice->_next) {
694
_owner->adlib_note_on(voice->_channel, voice->_note + _transpose_eff,
695
(_pitchbend * _pitchbend_factor >> 6) + _detune_eff);
699
void AdLibPart::controlChange(byte control, byte value) {
703
break; // Bank select. Not supported
704
case 1: modulationWheel(value); break;
705
case 7: volume(value); break;
706
case 10: break; // Pan position. Not supported.
707
case 16: pitchBendFactor(value); break;
708
case 17: detune(value); break;
709
case 18: priority(value); break;
710
case 64: sustain(value > 0); break;
711
case 91: break; // Effects level. Not supported.
712
case 93: break; // Chorus level. Not supported.
713
case 119: break; // Unknown, used in Simon the Sorcerer 2
714
case 121: // reset all controllers
720
case 123: allNotesOff(); break;
722
warning("AdLib: Unknown control change message %d (%d)", (int) control, (int)value);
726
void AdLibPart::modulationWheel(byte value) {
730
for (voice = _voice; voice; voice = voice->_next) {
731
if (voice->_s10a.active && voice->_s11a.flag0x40)
732
voice->_s10a.modwheel = _modwheel >> 2;
733
if (voice->_s10b.active && voice->_s11b.flag0x40)
734
voice->_s10b.modwheel = _modwheel >> 2;
738
void AdLibPart::volume(byte value) {
742
for (voice = _voice; voice; voice = voice->_next) {
743
_owner->adlib_set_param(voice->_channel, 0, volume_table[lookup_table[voice->_vol_2][_vol_eff >> 2]]);
744
if (voice->_twochan) {
745
_owner->adlib_set_param(voice->_channel, 13, volume_table[lookup_table[voice->_vol_1][_vol_eff >> 2]]);
750
void AdLibPart::pitchBendFactor(byte value) {
753
_pitchbend_factor = value;
754
for (voice = _voice; voice; voice = voice->_next) {
755
_owner->adlib_note_on(voice->_channel, voice->_note + _transpose_eff,
756
(_pitchbend * _pitchbend_factor >> 6) + _detune_eff);
760
void AdLibPart::detune(byte value) {
764
for (voice = _voice; voice; voice = voice->_next) {
765
_owner->adlib_note_on(voice->_channel, voice->_note + _transpose_eff,
766
(_pitchbend * _pitchbend_factor >> 6) + _detune_eff);
770
void AdLibPart::priority(byte value) {
774
void AdLibPart::sustain(bool value) {
779
for (voice = _voice; voice; voice = voice->_next) {
780
if (voice->_waitforpedal)
781
_owner->mc_off(voice);
786
void AdLibPart::allNotesOff() {
788
_owner->mc_off(_voice);
791
void AdLibPart::sysEx_customInstrument(uint32 type, const byte *instr) {
792
if (type == 'ADL ') {
793
AdLibInstrument *i = &_part_instr;
794
memcpy(i, instr, sizeof(AdLibInstrument));
798
// MidiChannel method implementations for percussion
800
AdLibPercussionChannel::~AdLibPercussionChannel() {
801
for (int i = 0; i < ARRAYSIZE(_customInstruments); ++i) {
802
delete _customInstruments[i];
806
void AdLibPercussionChannel::init(MidiDriver_ADLIB *owner, byte channel) {
807
AdLibPart::init(owner, channel);
811
// Initialize the custom instruments data
812
memset(_notes, 0, sizeof(_notes));
813
memset(_customInstruments, 0, sizeof(_customInstruments));
816
void AdLibPercussionChannel::noteOff(byte note) {
817
// Jamieson630: Unless I run into a specific instrument that
818
// may require a key off, I'm going to ignore this message.
819
// The rationale is that a percussion instrument should
820
// fade out of its own accord, and the AdLib instrument
821
// definitions used should follow this rule. Since
822
// percussion voices are allocated at the lowest priority
823
// anyway, we know that "hanging" percussion sounds will
824
// not prevent later musical instruments (or even other
825
// percussion sounds) from playing.
827
_owner->part_key_off(this, note);
831
void AdLibPercussionChannel::noteOn(byte note, byte velocity) {
832
AdLibInstrument *inst = NULL;
834
// The custom instruments have priority over the default mapping
835
inst = _customInstruments[note];
840
// Use the default GM to FM mapping as a fallback as a fallback
841
byte key = gm_percussion_lookup[note];
843
inst = (AdLibInstrument *)&gm_percussion_to_fm[key];
847
debug(2, "No instrument FM definition for GM percussion key %d", (int)note);
851
_owner->part_key_on(this, inst, note, velocity);
854
void AdLibPercussionChannel::sysEx_customInstrument(uint32 type, const byte *instr) {
855
if (type == 'ADLP') {
856
byte note = instr[0];
857
_notes[note] = instr[1];
859
// Allocate memory for the new instruments
860
if (!_customInstruments[note]) {
861
_customInstruments[note] = new AdLibInstrument;
864
// Save the new instrument data
865
_customInstruments[note]->mod_characteristic = instr[2];
866
_customInstruments[note]->mod_scalingOutputLevel = instr[3];
867
_customInstruments[note]->mod_attackDecay = instr[4];
868
_customInstruments[note]->mod_sustainRelease = instr[5];
869
_customInstruments[note]->mod_waveformSelect = instr[6];
870
_customInstruments[note]->car_characteristic = instr[7];
871
_customInstruments[note]->car_scalingOutputLevel = instr[8];
872
_customInstruments[note]->car_attackDecay = instr[9];
873
_customInstruments[note]->car_sustainRelease = instr[10];
874
_customInstruments[note]->car_waveformSelect = instr[11];
875
_customInstruments[note]->feedback = instr[12];
879
// MidiDriver method implementations
881
MidiDriver_ADLIB::MidiDriver_ADLIB(Audio::Mixer *mixer)
882
: MidiDriver_Emulated(mixer) {
885
_scummSmallHeader = false;
887
_adlib_reg_cache = 0;
889
_adlib_timer_counter = 0;
891
for (i = 0; i < ARRAYSIZE(curnote_table); ++i) {
892
curnote_table[i] = 0;
895
for (i = 0; i < ARRAYSIZE(_parts); ++i) {
896
_parts[i].init(this, i + ((i >= 9) ? 1 : 0));
898
_percussion.init(this, 9);
903
int MidiDriver_ADLIB::open() {
905
return MERR_ALREADY_OPEN;
907
MidiDriver_Emulated::open();
912
for (i = 0, voice = _voices; i != ARRAYSIZE(_voices); i++, voice++) {
914
voice->_s11a.s10 = &voice->_s10b;
915
voice->_s11b.s10 = &voice->_s10a;
918
_adlib_reg_cache = (byte *)calloc(256, 1);
920
_opl = makeAdLibOPL(getRate());
922
adlib_write(1, 0x20);
923
adlib_write(8, 0x40);
924
adlib_write(0xBD, 0x00);
925
create_lookup_table();
927
_mixer->playStream(Audio::Mixer::kPlainSoundType, &_mixerSoundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
932
void MidiDriver_ADLIB::close() {
937
_mixer->stopHandle(_mixerSoundHandle);
940
for (i = 0; i < ARRAYSIZE(_voices); ++i) {
941
if (_voices[i]._part)
945
// Turn off the OPL emulation
949
free(_adlib_reg_cache);
952
void MidiDriver_ADLIB::send(uint32 b) {
953
send(b & 0xF, b & 0xFFFFFFF0);
956
void MidiDriver_ADLIB::send(byte chan, uint32 b) {
957
//byte param3 = (byte) ((b >> 24) & 0xFF);
958
byte param2 = (byte) ((b >> 16) & 0xFF);
959
byte param1 = (byte) ((b >> 8) & 0xFF);
960
byte cmd = (byte) (b & 0xF0);
966
part = &_parts[chan];
969
case 0x80:// Note Off
970
part->noteOff(param1);
972
case 0x90: // Note On
973
part->noteOn(param1, param2);
975
case 0xA0: // Aftertouch
976
break; // Not supported.
977
case 0xB0: // Control Change
978
part->controlChange(param1, param2);
980
case 0xC0: // Program Change
981
part->programChange(param1);
983
case 0xD0: // Channel Pressure
984
break; // Not supported.
985
case 0xE0: // Pitch Bend
986
part->pitchBend((param1 | (param2 << 7)) - 0x2000);
989
// We should never get here! SysEx information has to be
990
// sent via high-level semantic methods.
991
warning("MidiDriver_ADLIB: Receiving SysEx command on a send() call");
995
warning("MidiDriver_ADLIB: Unknown send() command 0x%02X", cmd);
999
uint32 MidiDriver_ADLIB::property(int prop, uint32 param) {
1001
case PROP_OLD_ADLIB: // Older games used a different operator volume algorithm
1002
_scummSmallHeader = (param > 0);
1003
if (_scummSmallHeader) {
1016
void MidiDriver_ADLIB::setPitchBendRange(byte channel, uint range) {
1018
AdLibPart *part = &_parts[channel];
1020
part->_pitchbend_factor = range;
1021
for (voice = part->_voice; voice; voice = voice->_next) {
1022
adlib_note_on(voice->_channel, voice->_note + part->_transpose_eff,
1023
(part->_pitchbend * part->_pitchbend_factor >> 6) + part->_detune_eff);
1027
void MidiDriver_ADLIB::sysEx_customInstrument(byte channel, uint32 type, const byte *instr) {
1028
_parts[channel].sysEx_customInstrument(type, instr);
1031
MidiChannel *MidiDriver_ADLIB::allocateChannel() {
1035
for (i = 0; i < ARRAYSIZE(_parts); ++i) {
1037
if (!part->_allocated) {
1045
// All the code brought over from IMuseAdLib
1047
void MidiDriver_ADLIB::adlib_write(byte reg, byte value) {
1048
if (_adlib_reg_cache[reg] == value)
1051
debug(6, "%10d: adlib_write[%x] = %x", tick, reg, value);
1053
_adlib_reg_cache[reg] = value;
1055
OPLWriteReg(_opl, reg, value);
1058
void MidiDriver_ADLIB::generateSamples(int16 *data, int len) {
1059
memset(data, 0, sizeof(int16) * len);
1060
YM3812UpdateOne(_opl, data, len);
1063
void MidiDriver_ADLIB::onTimer() {
1067
_adlib_timer_counter += _timer_p;
1068
while (_adlib_timer_counter >= _timer_q) {
1069
_adlib_timer_counter -= _timer_q;
1074
for (i = 0; i != ARRAYSIZE(_voices); i++, voice++) {
1077
if (voice->_duration && (voice->_duration -= 0x11) <= 0) {
1081
if (voice->_s10a.active) {
1082
mc_inc_stuff(voice, &voice->_s10a, &voice->_s11a);
1084
if (voice->_s10b.active) {
1085
mc_inc_stuff(voice, &voice->_s10b, &voice->_s11b);
1091
void MidiDriver_ADLIB::mc_off(AdLibVoice *voice) {
1094
adlib_key_off(voice->_channel);
1099
voice->_next->_prev = tmp;
1101
tmp->_next = voice->_next;
1103
voice->_part->_voice = voice->_next;
1104
voice->_part = NULL;
1107
void MidiDriver_ADLIB::mc_inc_stuff(AdLibVoice *voice, Struct10 *s10, Struct11 *s11) {
1109
AdLibPart *part = voice->_part;
1111
code = struct10_ontimer(s10, s11);
1114
switch (s11->param) {
1116
voice->_vol_2 = s10->start_value + s11->modify_val;
1117
if (!_scummSmallHeader) {
1118
adlib_set_param(voice->_channel, 0,
1119
volume_table[lookup_table[voice->_vol_2]
1120
[part->_vol_eff >> 2]]);
1122
adlib_set_param(voice->_channel, 0, voice->_vol_2);
1126
voice->_vol_1 = s10->start_value + s11->modify_val;
1127
if (voice->_twochan && !_scummSmallHeader) {
1128
adlib_set_param(voice->_channel, 13,
1129
volume_table[lookup_table[voice->_vol_1]
1130
[part->_vol_eff >> 2]]);
1132
adlib_set_param(voice->_channel, 13, voice->_vol_1);
1136
s11->s10->modwheel = (char)s11->modify_val;
1139
s11->s10->unk3 = (char)s11->modify_val;
1142
adlib_set_param(voice->_channel, s11->param,
1143
s10->start_value + s11->modify_val);
1148
if (code & 2 && s11->flag0x10)
1149
adlib_key_onoff(voice->_channel);
1152
void MidiDriver_ADLIB::adlib_key_off(int chan){
1153
byte reg = chan + 0xB0;
1154
adlib_write(reg, adlib_get_reg_value(reg) & ~0x20);
1157
byte MidiDriver_ADLIB::struct10_ontimer(Struct10 *s10, Struct11 *s11) {
1161
if (s10->count && (s10->count -= 17) <= 0) {
1166
i = s10->cur_val + s10->speed_hi;
1167
s10->speed_lo_counter += s10->speed_lo;
1168
if (s10->speed_lo_counter >= s10->speed_lo_max) {
1169
s10->speed_lo_counter -= s10->speed_lo_max;
1170
i += s10->direction;
1172
if (s10->cur_val != i || s10->modwheel != s10->modwheel_last) {
1174
s10->modwheel_last = s10->modwheel;
1175
i = lookup_volume(i, s10->modwheel_last);
1176
if (i != s11->modify_val) {
1177
s11->modify_val = i;
1182
if (!--s10->num_steps) {
1184
if (s10->active > 4) {
1188
struct10_setup(s10);
1193
struct10_setup(s10);
1200
void MidiDriver_ADLIB::adlib_set_param(int channel, byte param, int value) {
1201
const AdLibSetParams *as;
1204
assert(channel >= 0 && channel < 9);
1207
reg = channel_mappings_2[channel];
1208
} else if (param <= 25) {
1210
reg = channel_mappings[channel];
1211
} else if (param <= 27) {
1214
} else if (param == 28 || param == 29) {
1220
channel_table_2[channel] = value;
1221
adlib_playnote(channel, curnote_table[channel] + value);
1227
as = &adlib_setparam_table[param];
1229
value = as->d - value;
1231
adlib_write(reg, (adlib_get_reg_value(reg) & ~as->c) | (((byte)value) << as->b));
1234
void MidiDriver_ADLIB::adlib_key_onoff(int channel) {
1236
byte reg = channel + 0xB0;
1237
assert(channel >= 0 && channel < 9);
1239
val = adlib_get_reg_value(reg);
1240
adlib_write(reg, val & ~0x20);
1241
adlib_write(reg, val | 0x20);
1244
void MidiDriver_ADLIB::struct10_setup(Struct10 *s10) {
1245
int b, c, d, e, f, g, h;
1249
f = s10->active - 1;
1251
t = s10->table_a[f];
1252
e = num_steps_table[lookup_table[t & 0x7F][b]];
1259
s10->num_steps = s10->speed_lo_max = e;
1263
g = s10->start_value;
1264
t = s10->table_b[f];
1265
d = lookup_volume(c, (t & 0x7F) - 31);
1281
s10->speed_hi = h / e;
1284
s10->direction = -1;
1289
s10->speed_lo = h % e;
1290
s10->speed_lo_counter = 0;
1293
void MidiDriver_ADLIB::adlib_playnote(int channel, int note) {
1294
byte old, oct, notex;
1298
note2 = (note >> 7) - 4;
1299
note2 = (note2 < 128) ? note2 : 0;
1306
notex = note2 % 12 + 3;
1308
old = adlib_get_reg_value(channel + 0xB0);
1316
} else if (oct < old) {
1324
i = (notex << 3) + ((note >> 4) & 0x7);
1325
adlib_write(channel + 0xA0, note_to_f_num[i]);
1326
adlib_write(channel + 0xB0, oct | 0x20);
1329
int MidiDriver_ADLIB::random_nr(int a) {
1330
static byte _rand_seed = 1;
1331
if (_rand_seed & 1) {
1337
return _rand_seed * a >> 8;
1340
void MidiDriver_ADLIB::part_key_off(AdLibPart *part, byte note) {
1343
for (voice = part->_voice; voice; voice = voice->_next) {
1344
if (voice->_note == note) {
1346
voice->_waitforpedal = true;
1353
void MidiDriver_ADLIB::part_key_on(AdLibPart *part, AdLibInstrument *instr, byte note, byte velocity) {
1356
voice = allocate_voice(part->_pri_eff);
1360
link_mc(part, voice);
1361
mc_key_on(voice, instr, note, velocity);
1364
AdLibVoice *MidiDriver_ADLIB::allocate_voice(byte pri) {
1365
AdLibVoice *ac, *best = NULL;
1368
for (i = 0; i < 9; i++) {
1369
if (++_voice_index >= 9)
1371
ac = &_voices[_voice_index];
1375
if (ac->_part->_pri_eff <= pri) {
1376
pri = ac->_part->_pri_eff;
1382
/* SCUMM V3 games don't have note priorities, first comes wins. */
1383
if (_scummSmallHeader)
1391
void MidiDriver_ADLIB::link_mc(AdLibPart *part, AdLibVoice *voice) {
1392
voice->_part = part;
1393
voice->_next = (AdLibVoice *)part->_voice;
1394
part->_voice = voice;
1395
voice->_prev = NULL;
1398
voice->_next->_prev = voice;
1401
void MidiDriver_ADLIB::mc_key_on(AdLibVoice *voice, AdLibInstrument *instr, byte note, byte velocity) {
1402
AdLibPart *part = voice->_part;
1406
voice->_twochan = instr->feedback & 1;
1407
voice->_note = note;
1408
voice->_waitforpedal = false;
1409
voice->_duration = instr->duration;
1410
if (voice->_duration != 0)
1411
voice->_duration *= 63;
1413
if (!_scummSmallHeader)
1414
vol_1 = (instr->mod_scalingOutputLevel & 0x3F) + lookup_table[velocity >> 1][instr->mod_waveformSelect >> 2];
1416
vol_1 = 0x3f - (instr->mod_scalingOutputLevel & 0x3F);
1419
voice->_vol_1 = vol_1;
1421
if (!_scummSmallHeader)
1422
vol_2 = (instr->car_scalingOutputLevel & 0x3F) + lookup_table[velocity >> 1][instr->car_waveformSelect >> 2];
1424
vol_2 = 0x3f - (instr->car_scalingOutputLevel & 0x3F);
1427
voice->_vol_2 = vol_2;
1429
c = part->_vol_eff >> 2;
1431
if (!_scummSmallHeader) {
1432
vol_2 = volume_table[lookup_table[vol_2][c]];
1433
if (voice->_twochan)
1434
vol_1 = volume_table[lookup_table[vol_1][c]];
1437
adlib_setup_channel(voice->_channel, instr, vol_1, vol_2);
1438
adlib_note_on_ex(voice->_channel, part->_transpose_eff + note, part->_detune_eff + (part->_pitchbend * part->_pitchbend_factor >> 6));
1440
if (instr->flags_a & 0x80) {
1441
mc_init_stuff(voice, &voice->_s10a, &voice->_s11a, instr->flags_a, &instr->extra_a);
1443
voice->_s10a.active = 0;
1446
if (instr->flags_b & 0x80) {
1447
mc_init_stuff(voice, &voice->_s10b, &voice->_s11b, instr->flags_b, &instr->extra_b);
1449
voice->_s10b.active = 0;
1453
void MidiDriver_ADLIB::adlib_setup_channel(int chan, AdLibInstrument *instr, byte vol_1, byte vol_2) {
1456
assert(chan >= 0 && chan < 9);
1458
channel = channel_mappings[chan];
1459
adlib_write(channel + 0x20, instr->mod_characteristic);
1460
adlib_write(channel + 0x40, (instr->mod_scalingOutputLevel | 0x3F) - vol_1 );
1461
adlib_write(channel + 0x60, 0xff & (~instr->mod_attackDecay));
1462
adlib_write(channel + 0x80, 0xff & (~instr->mod_sustainRelease));
1463
adlib_write(channel + 0xE0, instr->mod_waveformSelect);
1465
channel = channel_mappings_2[chan];
1466
adlib_write(channel + 0x20, instr->car_characteristic);
1467
adlib_write(channel + 0x40, (instr->car_scalingOutputLevel | 0x3F) - vol_2 );
1468
adlib_write(channel + 0x60, 0xff & (~instr->car_attackDecay));
1469
adlib_write(channel + 0x80, 0xff & (~instr->car_sustainRelease));
1470
adlib_write(channel + 0xE0, instr->car_waveformSelect);
1472
adlib_write((byte)chan + 0xC0, instr->feedback);
1475
void MidiDriver_ADLIB::adlib_note_on_ex(int chan, byte note, int mod)
1478
assert(chan >= 0 && chan < 9);
1479
code = (note << 7) + mod;
1480
curnote_table[chan] = code;
1481
channel_table_2[chan] = 0;
1482
adlib_playnote(chan, code);
1485
void MidiDriver_ADLIB::mc_init_stuff(AdLibVoice *voice, Struct10 * s10,
1486
Struct11 * s11, byte flags, InstrumentExtra * ie) {
1487
AdLibPart *part = voice->_part;
1488
s11->modify_val = 0;
1489
s11->flag0x40 = flags & 0x40;
1490
s10->loop = flags & 0x20;
1491
s11->flag0x10 = flags & 0x10;
1492
s11->param = param_table_1[flags & 0xF];
1493
s10->max_value = maxval_table[flags & 0xF];
1495
if (s11->flag0x40) {
1496
s10->modwheel = part->_modwheel >> 2;
1501
switch (s11->param) {
1503
s10->start_value = voice->_vol_2;
1506
s10->start_value = voice->_vol_1;
1509
s10->start_value = 31;
1510
s11->s10->modwheel = 0;
1513
s10->start_value = 0;
1517
s10->start_value = adlib_get_reg_value_param(voice->_channel, s11->param);
1520
struct10_init(s10, ie);
1523
void MidiDriver_ADLIB::struct10_init(Struct10 *s10, InstrumentExtra *ie) {
1525
if (!_scummSmallHeader) {
1528
s10->cur_val = s10->start_value;
1529
s10->start_value = 0;
1531
s10->modwheel_last = 31;
1535
s10->table_a[0] = ie->b;
1536
s10->table_a[1] = ie->d;
1537
s10->table_a[2] = ie->f;
1538
s10->table_a[3] = ie->g;
1540
s10->table_b[0] = ie->c;
1541
s10->table_b[1] = ie->e;
1542
s10->table_b[2] = 0;
1543
s10->table_b[3] = ie->h;
1545
struct10_setup(s10);
1548
int MidiDriver_ADLIB::adlib_get_reg_value_param(int chan, byte param) {
1549
const AdLibSetParams *as;
1553
assert(chan >= 0 && chan < 9);
1556
channel = channel_mappings_2[chan];
1557
} else if (param <= 25) {
1559
channel = channel_mappings[chan];
1560
} else if (param <= 27) {
1563
} else if (param == 28) {
1565
} else if (param == 29) {
1571
as = &adlib_setparam_table[param];
1572
val = adlib_get_reg_value(channel + as->a);
1581
void MidiDriver_ADLIB::adlib_note_on(int chan, byte note, int mod) {
1583
assert(chan >= 0 && chan < 9);
1584
code = (note << 7) + mod;
1585
curnote_table[chan] = code;
1586
adlib_playnote(chan, (int16) channel_table_2[chan] + code);
1592
class AdLibEmuMusicPlugin : public MusicPluginObject {
1594
const char *getName() const {
1595
return _s("AdLib Emulator");
1598
const char *getId() const {
1602
MusicDevices getDevices() const;
1603
Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;
1606
MusicDevices AdLibEmuMusicPlugin::getDevices() const {
1607
MusicDevices devices;
1608
devices.push_back(MusicDevice(this, "", MT_ADLIB));
1612
Common::Error AdLibEmuMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
1613
*mididriver = new MidiDriver_ADLIB(g_system->getMixer());
1615
return Common::kNoError;
1618
//#if PLUGIN_ENABLED_DYNAMIC(ADLIB)
1619
//REGISTER_PLUGIN_DYNAMIC(ADLIB, PLUGIN_TYPE_MUSIC, AdLibEmuMusicPlugin);
1621
REGISTER_PLUGIN_STATIC(ADLIB, PLUGIN_TYPE_MUSIC, AdLibEmuMusicPlugin);