2002-11-21 19:06:42 +00:00
|
|
|
/* ScummVM - Scumm Interpreter
|
|
|
|
* Copyright (C) 2001/2002 The ScummVM project
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*
|
|
|
|
* $Header$
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "stdafx.h"
|
2002-11-21 19:17:00 +00:00
|
|
|
#include "sound/mididrv.h"
|
|
|
|
#include "sound/fmopl.h"
|
|
|
|
#include "sound/mixer.h"
|
2002-11-21 19:06:42 +00:00
|
|
|
#include "common/engine.h" // for warning/error/debug
|
|
|
|
#include "common/util.h"
|
|
|
|
|
|
|
|
class MidiDriver_ADLIB;
|
|
|
|
struct MidiChannelAdl;
|
|
|
|
|
|
|
|
struct InstrumentExtra {
|
|
|
|
byte a, b, c, d, e, f, g, h;
|
|
|
|
};
|
|
|
|
|
2002-12-18 13:22:40 +00:00
|
|
|
struct AdlibInstrument {
|
2002-11-21 19:06:42 +00:00
|
|
|
byte flags_1;
|
|
|
|
byte oplvl_1;
|
|
|
|
byte atdec_1;
|
|
|
|
byte sustrel_1;
|
|
|
|
byte waveform_1;
|
|
|
|
byte flags_2;
|
|
|
|
byte oplvl_2;
|
|
|
|
byte atdec_2;
|
|
|
|
byte sustrel_2;
|
|
|
|
byte waveform_2;
|
|
|
|
byte feedback;
|
|
|
|
byte flags_a;
|
|
|
|
InstrumentExtra extra_a;
|
|
|
|
byte flags_b;
|
|
|
|
InstrumentExtra extra_b;
|
|
|
|
byte duration;
|
|
|
|
};
|
|
|
|
|
2002-11-26 16:54:58 +00:00
|
|
|
class AdlibPart : public MidiChannel {
|
2002-11-26 20:14:12 +00:00
|
|
|
friend class MidiDriver_ADLIB;
|
2002-11-26 16:54:58 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
// AdlibPart *_prev, *_next;
|
2002-11-21 19:06:42 +00:00
|
|
|
MidiChannelAdl *_mc;
|
|
|
|
int16 _pitchbend;
|
|
|
|
byte _pitchbend_factor;
|
|
|
|
int8 _transpose_eff;
|
|
|
|
byte _vol_eff;
|
|
|
|
int8 _detune_eff;
|
|
|
|
byte _modwheel;
|
|
|
|
bool _pedal;
|
|
|
|
byte _program;
|
|
|
|
byte _pri_eff;
|
2002-12-18 13:22:40 +00:00
|
|
|
AdlibInstrument _part_instr;
|
2002-11-26 16:54:58 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
MidiDriver_ADLIB *_owner;
|
|
|
|
bool _allocated;
|
|
|
|
byte _channel;
|
|
|
|
|
2002-12-18 07:48:02 +00:00
|
|
|
void init (MidiDriver_ADLIB *owner, byte channel);
|
2002-11-26 16:54:58 +00:00
|
|
|
void allocate() { _allocated = true; }
|
|
|
|
|
|
|
|
public:
|
2002-12-18 07:53:45 +00:00
|
|
|
MidiDriver *device();
|
2002-12-18 07:48:02 +00:00
|
|
|
byte getNumber() { return _channel; }
|
2002-11-26 16:54:58 +00:00
|
|
|
void release() { _allocated = false; }
|
|
|
|
|
|
|
|
// Regular messages
|
|
|
|
void noteOff (byte note);
|
|
|
|
void noteOn (byte note, byte velocity);
|
|
|
|
void programChange (byte program);
|
|
|
|
void pitchBend (int16 bend);
|
|
|
|
|
|
|
|
// Control Change messages
|
|
|
|
void controlChange (byte control, byte value);
|
|
|
|
void modulationWheel (byte value);
|
|
|
|
void volume (byte value);
|
|
|
|
void panPosition (byte value) { return; } // Not supported
|
|
|
|
void pitchBendFactor (byte value);
|
|
|
|
void detune (byte value);
|
|
|
|
void priority (byte value);
|
|
|
|
void sustain (bool value);
|
|
|
|
void effectLevel (byte value) { return; } // Not supported
|
|
|
|
void chorusLevel (byte value) { return; } // Not supported
|
|
|
|
void allNotesOff();
|
|
|
|
|
|
|
|
// SysEx messages
|
|
|
|
void sysEx_customInstrument (uint32 type, byte *instr);
|
2002-11-21 19:06:42 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct Struct10 {
|
|
|
|
byte active;
|
|
|
|
int16 cur_val;
|
|
|
|
int16 count;
|
|
|
|
uint16 param;
|
|
|
|
int16 start_value;
|
|
|
|
byte loop;
|
|
|
|
byte table_a[4];
|
|
|
|
byte table_b[4];
|
|
|
|
int8 unk3;
|
|
|
|
int8 modwheel;
|
|
|
|
int8 modwheel_last;
|
|
|
|
uint16 speed_lo_max;
|
|
|
|
uint16 num_steps;
|
|
|
|
int16 speed_hi;
|
|
|
|
int8 direction;
|
|
|
|
uint16 speed_lo;
|
|
|
|
uint16 speed_lo_counter;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct Struct11 {
|
|
|
|
int16 modify_val;
|
|
|
|
byte param, flag0x40, flag0x10;
|
|
|
|
Struct10 *s10;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct MidiChannelAdl {
|
|
|
|
AdlibPart *_part;
|
|
|
|
MidiChannelAdl *_next, *_prev;
|
|
|
|
byte _waitforpedal;
|
|
|
|
byte _note;
|
|
|
|
byte _channel;
|
|
|
|
byte _twochan;
|
|
|
|
byte _vol_1, _vol_2;
|
|
|
|
int16 _duration;
|
|
|
|
|
|
|
|
Struct10 _s10a;
|
|
|
|
Struct11 _s11a;
|
|
|
|
Struct10 _s10b;
|
|
|
|
Struct11 _s11b;
|
|
|
|
|
|
|
|
MidiChannelAdl() : _part (0), _next(0), _prev(0) {}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct AdlibSetParams {
|
|
|
|
byte a, b, c, d;
|
|
|
|
};
|
|
|
|
|
|
|
|
static const byte channel_mappings[9] = {
|
|
|
|
0, 1, 2, 8,
|
|
|
|
9, 10, 16, 17,
|
|
|
|
18
|
|
|
|
};
|
|
|
|
|
|
|
|
static const byte channel_mappings_2[9] = {
|
|
|
|
3, 4, 5, 11,
|
|
|
|
12, 13, 19, 20,
|
|
|
|
21
|
|
|
|
};
|
|
|
|
|
|
|
|
static const AdlibSetParams adlib_setparam_table[] = {
|
|
|
|
{0x40, 0, 63, 63}, // level
|
|
|
|
{0xE0, 2, 0, 0}, // unused
|
|
|
|
{0x40, 6, 192, 0}, // level key scaling
|
|
|
|
{0x20, 0, 15, 0}, // modulator frequency multiple
|
|
|
|
{0x60, 4, 240, 15}, // attack rate
|
|
|
|
{0x60, 0, 15, 15}, // decay rate
|
|
|
|
{0x80, 4, 240, 15}, // sustain level
|
|
|
|
{0x80, 0, 15, 15}, // release rate
|
|
|
|
{0xE0, 0, 3, 0}, // waveform select
|
|
|
|
{0x20, 7, 128, 0}, // amp mod
|
|
|
|
{0x20, 6, 64, 0}, // vib
|
|
|
|
{0x20, 5, 32, 0}, // eg typ
|
|
|
|
{0x20, 4, 16, 0}, // ksr
|
|
|
|
{0xC0, 0, 1, 0}, // decay alg
|
|
|
|
{0xC0, 1, 14, 0} // feedback
|
|
|
|
};
|
|
|
|
|
|
|
|
const byte param_table_1[16] = {
|
|
|
|
29, 28, 27, 0,
|
|
|
|
3, 4, 7, 8,
|
|
|
|
13, 16, 17, 20,
|
|
|
|
21, 30, 31, 0
|
|
|
|
};
|
|
|
|
|
|
|
|
const uint16 param_table_2[16] = {
|
|
|
|
0x2FF, 0x1F, 0x7, 0x3F,
|
|
|
|
0x0F, 0x0F, 0x0F, 0x3,
|
|
|
|
0x3F, 0x0F, 0x0F, 0x0F,
|
|
|
|
0x3, 0x3E, 0x1F, 0
|
|
|
|
};
|
|
|
|
|
|
|
|
static const uint16 num_steps_table[] = {
|
|
|
|
1, 2, 4, 5,
|
|
|
|
6, 7, 8, 9,
|
|
|
|
10, 12, 14, 16,
|
|
|
|
18, 21, 24, 30,
|
|
|
|
36, 50, 64, 82,
|
|
|
|
100, 136, 160, 192,
|
|
|
|
240, 276, 340, 460,
|
|
|
|
600, 860, 1200, 1600
|
|
|
|
};
|
|
|
|
|
|
|
|
static const byte octave_numbers[] = {
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0, 1, 1, 1, 1,
|
|
|
|
1, 1, 1, 1, 1, 1, 1, 1,
|
|
|
|
2, 2, 2, 2, 2, 2, 2, 2,
|
|
|
|
2, 2, 2, 2, 3, 3, 3, 3,
|
|
|
|
3, 3, 3, 3, 3, 3, 3, 3,
|
|
|
|
4, 4, 4, 4, 4, 4, 4, 4,
|
|
|
|
4, 4, 4, 4, 5, 5, 5, 5,
|
|
|
|
5, 5, 5, 5, 5, 5, 5, 5,
|
|
|
|
6, 6, 6, 6, 6, 6, 6, 6,
|
|
|
|
6, 6, 6, 6, 7, 7, 7, 7,
|
|
|
|
7, 7, 7, 7, 7, 7, 7, 7,
|
|
|
|
7, 7, 7, 7, 7, 7, 7, 7,
|
|
|
|
7, 7, 7, 7, 7, 7, 7, 7,
|
|
|
|
7, 7, 7, 7, 7, 7, 7, 7,
|
|
|
|
7, 7, 7, 7, 7, 7, 7, 7
|
|
|
|
};
|
|
|
|
|
|
|
|
static const byte note_numbers[] = {
|
|
|
|
3, 4, 5, 6, 7, 8, 9, 10,
|
|
|
|
11, 12, 13, 14, 3, 4, 5, 6,
|
|
|
|
7, 8, 9, 10, 11, 12, 13, 14,
|
|
|
|
3, 4, 5, 6, 7, 8, 9, 10,
|
|
|
|
11, 12, 13, 14, 3, 4, 5, 6,
|
|
|
|
7, 8, 9, 10, 11, 12, 13, 14,
|
|
|
|
3, 4, 5, 6, 7, 8, 9, 10,
|
|
|
|
11, 12, 13, 14, 3, 4, 5, 6,
|
|
|
|
7, 8, 9, 10, 11, 12, 13, 14,
|
|
|
|
3, 4, 5, 6, 7, 8, 9, 10,
|
|
|
|
11, 12, 13, 14, 3, 4, 5, 6,
|
|
|
|
7, 8, 9, 10, 11, 12, 13, 14,
|
|
|
|
3, 4, 5, 6, 7, 8, 9, 10,
|
|
|
|
11, 12, 13, 14, 3, 4, 5, 6,
|
|
|
|
7, 8, 9, 10, 11, 12, 13, 14,
|
|
|
|
3, 4, 5, 6, 7, 8, 9, 10
|
|
|
|
};
|
|
|
|
|
|
|
|
static const byte note_to_f_num[] = {
|
|
|
|
90, 91, 92, 92, 93, 94, 94, 95,
|
|
|
|
96, 96, 97, 98, 98, 99, 100, 101,
|
|
|
|
101, 102, 103, 104, 104, 105, 106, 107,
|
|
|
|
107, 108, 109, 110, 111, 111, 112, 113,
|
|
|
|
114, 115, 115, 116, 117, 118, 119, 120,
|
|
|
|
121, 121, 122, 123, 124, 125, 126, 127,
|
|
|
|
128, 129, 130, 131, 132, 132, 133, 134,
|
|
|
|
135, 136, 137, 138, 139, 140, 141, 142,
|
|
|
|
143, 145, 146, 147, 148, 149, 150, 151,
|
|
|
|
152, 153, 154, 155, 157, 158, 159, 160,
|
|
|
|
161, 162, 163, 165, 166, 167, 168, 169,
|
|
|
|
171, 172, 173, 174, 176, 177, 178, 180,
|
|
|
|
181, 182, 184, 185, 186, 188, 189, 190,
|
|
|
|
192, 193, 194, 196, 197, 199, 200, 202,
|
|
|
|
203, 205, 206, 208, 209, 211, 212, 214,
|
|
|
|
215, 217, 218, 220, 222, 223, 225, 226,
|
|
|
|
228, 230, 231, 233, 235, 236, 238, 240,
|
|
|
|
242, 243, 245, 247, 249, 251, 252, 254,
|
|
|
|
};
|
|
|
|
|
|
|
|
static byte map_gm_to_fm [128][30] = {
|
|
|
|
// DERIVED FROM DAY OF THE TENTACLE
|
|
|
|
// 00
|
|
|
|
{ 0x2F, 0x0B, 0x08, 0x78, 0x16, 0x24, 0x22, 0x0B, 0x9A, 0x34, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0x2F, 0x0B, 0x08, 0x78, 0x16, 0x24, 0x22, 0x0B, 0x9A, 0x34, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Extrapolated
|
|
|
|
{ 0x84, 0x40, 0x3B, 0x5A, 0x63, 0x81, 0x00, 0x3B, 0x5A, 0x7F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0x2F, 0x0B, 0x08, 0x78, 0x16, 0x24, 0x22, 0x0B, 0x9A, 0x34, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Extrapolated
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0x84, 0x40, 0x3B, 0x5A, 0x63, 0x81, 0x00, 0x3B, 0x5A, 0x7F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0x2F, 0x0B, 0x08, 0x78, 0x16, 0x24, 0x22, 0x0B, 0x9A, 0x34, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Extrapolated
|
|
|
|
{ 0x85, 0x80, 0x05, 0xEA, 0x3D, 0x84, 0x18, 0x3C, 0xAA, 0x7C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0xE2, 0x00, 0x6C, 0x77, 0x7D, 0xE4, 0x40, 0x7D, 0xA7, 0x66, 0x07, 0xA1, 0x00, 0x02, 0x1E, 0x01, 0x20, 0x01, 0x01, 0x1F, 0xAC, 0x00, 0x04, 0x24, 0x02, 0x21, 0x02, 0x02, 0x21, 0x00 },
|
|
|
|
// 10
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0xC9, 0x40, 0x3A, 0x78, 0x5E, 0xC2, 0x00, 0x4D, 0x9A, 0x7C, 0x00, 0xA1, 0xA0, 0x08, 0x1F, 0x05, 0x1E, 0x02, 0x05, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0x28, 0x1D, 0x19, 0x68, 0x02, 0x22, 0x35, 0x09, 0x08, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Extrapolated
|
|
|
|
{ 0x28, 0x1D, 0x19, 0x68, 0x02, 0x22, 0x35, 0x09, 0x08, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0xC6, 0x40, 0x3B, 0x78, 0x5E, 0xC2, 0x00, 0x4D, 0x9A, 0x7C, 0x00, 0xA1, 0xA0, 0x08, 0x1F, 0x05, 0x1E, 0x02, 0x05, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Extrapolated
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0xE2, 0x00, 0x6C, 0x77, 0x7D, 0xE4, 0x40, 0x7D, 0xA7, 0x66, 0x07, 0xA1, 0x00, 0x02, 0x1E, 0x01, 0x20, 0x01, 0x01, 0x1F, 0xAC, 0x00, 0x04, 0x24, 0x02, 0x21, 0x02, 0x02, 0x21, 0x00 },
|
|
|
|
{ 0xE2, 0x28, 0x38, 0xE8, 0x02, 0xE6, 0x33, 0x0B, 0xF9, 0x00, 0x08, 0xA1, 0x00, 0x02, 0x1E, 0x02, 0x20, 0x00, 0x02, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Extrapolated
|
|
|
|
{ 0xE2, 0x28, 0x38, 0xE8, 0x02, 0xE6, 0x33, 0x0B, 0xF9, 0x00, 0x08, 0xA1, 0x00, 0x02, 0x1E, 0x02, 0x20, 0x00, 0x02, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0xE2, 0x00, 0x6C, 0x77, 0x7D, 0xE4, 0x40, 0x7D, 0xA7, 0x66, 0x07, 0xA1, 0x00, 0x02, 0x1E, 0x01, 0x20, 0x01, 0x01, 0x1F, 0xAC, 0x00, 0x04, 0x24, 0x02, 0x21, 0x02, 0x02, 0x21, 0x00 },
|
|
|
|
// 20
|
|
|
|
{ 0x85, 0x80, 0x05, 0xEA, 0x3D, 0x84, 0x18, 0x3C, 0xAA, 0x7C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Extrapolated
|
|
|
|
{ 0x85, 0x80, 0x05, 0xEA, 0x3D, 0x84, 0x18, 0x3C, 0xAA, 0x7C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Extrapolated
|
|
|
|
{ 0x85, 0x80, 0x05, 0xEA, 0x3D, 0x84, 0x18, 0x3C, 0xAA, 0x7C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0xC6, 0x00, 0x2E, 0xC7, 0x59, 0xC2, 0x06, 0x0E, 0xA7, 0x7D, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Extrapolated
|
|
|
|
{ 0xC6, 0x00, 0x2E, 0xC7, 0x59, 0xC2, 0x06, 0x0E, 0xA7, 0x7D, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Extrapolated
|
|
|
|
{ 0xC6, 0x00, 0x2E, 0xC7, 0x59, 0xC2, 0x06, 0x0E, 0xA7, 0x7D, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0xC6, 0x00, 0x2E, 0xC7, 0x59, 0xC2, 0x06, 0x0E, 0xA7, 0x7D, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0x84, 0x40, 0x3B, 0x5A, 0x63, 0x81, 0x00, 0x3B, 0x5A, 0x7F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
// 30
|
|
|
|
{ 0xC6, 0x00, 0x2E, 0xC7, 0x59, 0xC2, 0x06, 0x0E, 0xA7, 0x7D, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0x31, 0x0C, 0x2D, 0xD7, 0x40, 0x62, 0x18, 0x2E, 0xB8, 0x7C, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x01, 0x1C, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00 },
|
|
|
|
{ 0x22, 0x19, 0x79, 0x67, 0x00, 0x22, 0x3F, 0x2A, 0xC6, 0x02, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0x31, 0x0C, 0x2D, 0xD7, 0x40, 0x62, 0x18, 0x2E, 0xB8, 0x7C, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x01, 0x1C, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00 },
|
|
|
|
{ 0x31, 0x0C, 0x2D, 0xD7, 0x40, 0x62, 0x18, 0x2E, 0xB8, 0x7C, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x01, 0x1C, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00 },
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0x31, 0x0C, 0x2D, 0xD7, 0x40, 0x62, 0x18, 0x2E, 0xB8, 0x7C, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x01, 0x1C, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00 },
|
|
|
|
{ 0x31, 0x0C, 0x2D, 0xD7, 0x40, 0x62, 0x18, 0x2E, 0xB8, 0x7C, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x01, 0x1C, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00 }, // Extrapolated
|
|
|
|
// 40
|
|
|
|
{ 0xE2, 0x15, 0x7B, 0xB5, 0x02, 0xE1, 0x33, 0xAF, 0xF4, 0x36, 0x08, 0xA1, 0x00, 0x04, 0x1E, 0x04, 0x1F, 0x00, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0xC6, 0x00, 0x2E, 0xC7, 0x59, 0xC2, 0x06, 0x0E, 0xA7, 0x7D, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0xF4, 0x40, 0x9F, 0xFA, 0x61, 0xE2, 0x13, 0x7F, 0xFA, 0x7D, 0x02, 0x21, 0x00, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x35, 0x00 },
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0x02, 0x00, 0x67, 0xAA, 0x65, 0x02, 0x64, 0x28, 0xF9, 0x7C, 0x08, 0x81, 0x00, 0x04, 0x1D, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0x02, 0x40, 0x04, 0x9A, 0x55, 0xC2, 0x4B, 0x2B, 0xCB, 0x7C, 0x06, 0x41, 0x00, 0x00, 0x20, 0x06, 0x1C, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0x02, 0x0C, 0x03, 0x6A, 0x7D, 0x02, 0x00, 0x23, 0xEA, 0x7C, 0x02, 0x81, 0x00, 0x02, 0x20, 0x01, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0xF4, 0x40, 0x9F, 0xFA, 0x61, 0xE2, 0x13, 0x7F, 0xFA, 0x7D, 0x02, 0x21, 0x00, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x35, 0x00 },
|
|
|
|
{ 0xF4, 0x40, 0x9F, 0xFA, 0x61, 0xE2, 0x13, 0x7F, 0xFA, 0x7D, 0x02, 0x21, 0x00, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x35, 0x00 },
|
|
|
|
// 50
|
|
|
|
{ 0xF4, 0x40, 0x9F, 0xFA, 0x61, 0xE2, 0x13, 0x7F, 0xFA, 0x7D, 0x02, 0x21, 0x00, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x35, 0x00 },
|
|
|
|
{ 0x02, 0x00, 0x67, 0xAA, 0x65, 0x02, 0x64, 0x28, 0xF9, 0x7C, 0x08, 0x81, 0x00, 0x04, 0x1D, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0xE1, 0x00, 0xCE, 0xD9, 0x4E, 0xE2, 0x00, 0x8F, 0x99, 0x65, 0x0E, 0x01, 0x00, 0x01, 0x1F, 0x00, 0x1E, 0x01, 0x01, 0x20, 0x01, 0x00, 0x00, 0x1F, 0x06, 0x1E, 0x00, 0x06, 0x1F, 0x00 },
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0xE2, 0x00, 0xCE, 0xD9, 0x4C, 0xE2, 0x00, 0x8F, 0x99, 0x64, 0x0E, 0x81, 0x10, 0x00, 0x1E, 0x05, 0x1F, 0x12, 0x00, 0x1F, 0x01, 0x00, 0x00, 0x1F, 0x06, 0x1E, 0x00, 0x06, 0x1F, 0x00 },
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0xB2, 0x25, 0xAD, 0xE9, 0x00, 0x62, 0x00, 0x8F, 0xC8, 0x7C, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0xF2, 0x00, 0xAF, 0xFA, 0x5C, 0xF2, 0x56, 0x9F, 0xEA, 0x7C, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0xF2, 0x00, 0xAF, 0xFA, 0x5C, 0xF2, 0x56, 0x9F, 0xEA, 0x7C, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0xB2, 0x25, 0xAD, 0xE9, 0x00, 0x62, 0x00, 0x8F, 0xC8, 0x7C, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
// 60
|
|
|
|
{ 0xE2, 0x02, 0x9F, 0xB8, 0x48, 0x22, 0x89, 0x9F, 0xE8, 0x7C, 0x00, 0x81, 0x00, 0x01, 0x1E, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0xB2, 0x25, 0xAD, 0xE9, 0x00, 0x62, 0x00, 0x8F, 0xC8, 0x7C, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Extrapolated
|
|
|
|
{ 0xE4, 0x28, 0x7E, 0xF8, 0x01, 0xE2, 0x23, 0x8E, 0xE8, 0x7D, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Extrapolated
|
|
|
|
{ 0xE4, 0x28, 0x7E, 0xF8, 0x01, 0xE2, 0x23, 0x8E, 0xE8, 0x7D, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0xE4, 0x28, 0x7E, 0xF8, 0x01, 0xE2, 0x23, 0x8E, 0xE8, 0x7D, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0x31, 0x0C, 0x2D, 0xD7, 0x40, 0x62, 0x18, 0x2E, 0xB8, 0x7C, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x01, 0x1C, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00 },
|
|
|
|
{ 0x22, 0x10, 0x7E, 0xD8, 0x35, 0x2A, 0x2E, 0x8E, 0xD8, 0x7C, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0xE4, 0x28, 0x7E, 0xF8, 0x01, 0xE2, 0x23, 0x8E, 0xE8, 0x7D, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
// 70
|
|
|
|
{ 0x22, 0x10, 0x7E, 0xD8, 0x35, 0x2A, 0x2E, 0x8E, 0xD8, 0x7C, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0xE4, 0x08, 0x7E, 0x99, 0x28, 0xE6, 0x16, 0x80, 0xF8, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0xE4, 0x23, 0x8F, 0xF9, 0x7C, 0xE2, 0x18, 0x9F, 0x88, 0x7C, 0x01, 0x01, 0x04, 0x00, 0x1E, 0x00, 0x1F, 0x06, 0x05, 0x1F, 0x03, 0x29, 0x01, 0x1F, 0x02, 0x21, 0x01, 0x02, 0x1F, 0x00 },
|
|
|
|
{ 0xE4, 0x23, 0x8F, 0xF9, 0x7C, 0xE2, 0x18, 0x9F, 0x88, 0x7C, 0x01, 0x01, 0x04, 0x00, 0x1E, 0x00, 0x1F, 0x06, 0x05, 0x1F, 0x03, 0x29, 0x01, 0x1F, 0x02, 0x21, 0x01, 0x02, 0x1F, 0x00 },
|
|
|
|
{ 0xE4, 0x23, 0x8F, 0xF9, 0x7C, 0xE2, 0x18, 0x9F, 0x88, 0x7C, 0x01, 0x01, 0x04, 0x00, 0x1E, 0x00, 0x1F, 0x06, 0x05, 0x1F, 0x03, 0x29, 0x01, 0x1F, 0x02, 0x21, 0x01, 0x02, 0x1F, 0x00 },
|
|
|
|
{ 0x2A, 0x1E, 0x98, 0xA9, 0x00, 0x62, 0x00, 0x9F, 0xB9, 0x7C, 0x00, 0x01, 0x00, 0x01, 0x1E, 0x00, 0x1F, 0x01, 0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0x2A, 0x1E, 0x98, 0xA9, 0x00, 0x62, 0x00, 0x9F, 0xB9, 0x7C, 0x00, 0x01, 0x00, 0x01, 0x1E, 0x00, 0x1F, 0x01, 0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0x62, 0xA8, 0x9D, 0x84, 0x44, 0x62, 0x23, 0x7F, 0xD5, 0x4C, 0x03, 0xA1, 0x00, 0x01, 0x1E, 0x02, 0x21, 0x01, 0x01, 0x20, 0xA8, 0x00, 0x01, 0x24, 0x06, 0x20, 0x04, 0x03, 0x24, 0x00 },
|
|
|
|
{ 0xE4, 0x28, 0x7E, 0xF8, 0x01, 0xE2, 0x23, 0x8E, 0xE8, 0x7D, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
// 80
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0xE4, 0x08, 0x7E, 0x99, 0x28, 0xE6, 0x16, 0x80, 0xF8, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0xE4, 0x28, 0x7E, 0xF8, 0x01, 0xE2, 0x23, 0x8E, 0xE8, 0x7D, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0x22, 0x10, 0x7E, 0xD8, 0x35, 0x2A, 0x2E, 0x8E, 0xD8, 0x7C, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0xE4, 0x07, 0x05, 0xAA, 0x7C, 0xE2, 0x50, 0xBE, 0xC8, 0x7D, 0x07, 0x01, 0x00, 0x03, 0x1E, 0x01, 0x1E, 0x00, 0x00, 0x1E, 0xA8, 0x00, 0x01, 0x20, 0x06, 0x23, 0x04, 0x03, 0x20, 0x00 },
|
|
|
|
{ 0x85, 0x80, 0x05, 0xEA, 0x3D, 0x84, 0x18, 0x3C, 0xAA, 0x7C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0xB2, 0x25, 0xAD, 0xE9, 0x00, 0x62, 0x00, 0x8F, 0xC8, 0x7C, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
// 90
|
|
|
|
{ 0xF2, 0x00, 0xAF, 0xFA, 0x5C, 0xF2, 0x56, 0x9F, 0xEA, 0x7C, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0xE2, 0x02, 0x9F, 0xB8, 0x48, 0x22, 0x89, 0x9F, 0xE8, 0x7C, 0x00, 0x81, 0x00, 0x01, 0x1E, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0xB2, 0x25, 0xAD, 0xE9, 0x00, 0x62, 0x00, 0x8F, 0xC8, 0x7C, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0xE2, 0x00, 0xCE, 0xD9, 0x4C, 0xE2, 0x00, 0x8F, 0x99, 0x64, 0x0E, 0x81, 0x10, 0x00, 0x1E, 0x05, 0x1F, 0x12, 0x00, 0x1F, 0x01, 0x00, 0x00, 0x1F, 0x06, 0x1E, 0x00, 0x06, 0x1F, 0x00 },
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0xC9, 0x40, 0x3A, 0x38, 0x5E, 0xC2, 0x00, 0x4C, 0xAA, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0xC9, 0x40, 0x3A, 0x78, 0x5E, 0xC2, 0x00, 0x4D, 0x9A, 0x7C, 0x00, 0xA1, 0xA0, 0x08, 0x1F, 0x05, 0x1E, 0x02, 0x05, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
// 100
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0xC9, 0x40, 0x3A, 0x38, 0x5E, 0xC2, 0x00, 0x4C, 0xAA, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Extrapolated
|
|
|
|
{ 0xC9, 0x40, 0x3A, 0x78, 0x5E, 0xC2, 0x00, 0x4D, 0x9A, 0x7C, 0x00, 0xA1, 0xA0, 0x08, 0x1F, 0x05, 0x1E, 0x02, 0x05, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Extrapolated
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0xC6, 0x00, 0x2E, 0xC7, 0x59, 0xC2, 0x06, 0x0E, 0xA7, 0x7D, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
// 110
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0x02, 0x0C, 0x03, 0x6A, 0x7D, 0x02, 0x00, 0x23, 0xEA, 0x7C, 0x02, 0x81, 0x00, 0x02, 0x20, 0x01, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0xCF, 0x3B, 0x2A, 0xFE, 0x7E, 0xC0, 0xC0, 0x0C, 0xEB, 0x63, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 }, // Extrapolated
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0x02, 0x0C, 0x03, 0x6A, 0x7D, 0x02, 0x00, 0x23, 0xEA, 0x7C, 0x02, 0x81, 0x00, 0x02, 0x20, 0x01, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0x0F, 0x10, 0x10, 0x09, 0x49, 0x02, 0x12, 0x07, 0x9A, 0x7C, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0xCF, 0x3B, 0x2A, 0xFE, 0x7E, 0xC0, 0xC0, 0x0C, 0xEB, 0x63, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 },
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
// 120
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0xCF, 0x40, 0x0A, 0x30, 0x5C, 0xCF, 0x00, 0x0D, 0x80, 0x7C, 0x00, 0xA0, 0x00, 0x0F, 0x1E, 0x0F, 0x20, 0x00, 0x0B, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // Unknown
|
|
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } // Unknown
|
|
|
|
};
|
|
|
|
|
|
|
|
static byte lookup_table[64][32];
|
|
|
|
const byte volume_table[] = {
|
|
|
|
0, 4, 7, 11,
|
|
|
|
13, 16, 18, 20,
|
|
|
|
22, 24, 26, 27,
|
|
|
|
29, 30, 31, 33,
|
|
|
|
34, 35, 36, 37,
|
|
|
|
38, 39, 40, 41,
|
|
|
|
42, 43, 44, 44,
|
|
|
|
45, 46, 47, 47,
|
|
|
|
48, 49, 49, 50,
|
|
|
|
51, 51, 52, 53,
|
|
|
|
53, 54, 54, 55,
|
|
|
|
55, 56, 56, 57,
|
|
|
|
57, 58, 58, 59,
|
|
|
|
59, 60, 60, 60,
|
|
|
|
61, 61, 62, 62,
|
|
|
|
62, 63, 63, 63
|
|
|
|
};
|
|
|
|
|
|
|
|
static int lookup_volume(int a, int b)
|
|
|
|
{
|
|
|
|
if (b == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (b == 31)
|
|
|
|
return a;
|
|
|
|
|
|
|
|
if (a < -63 || a > 63) {
|
|
|
|
return b * (a + 1) >> 5;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (b < 0) {
|
|
|
|
if (a < 0) {
|
|
|
|
return lookup_table[-a][-b];
|
|
|
|
} else {
|
|
|
|
return -lookup_table[a][-b];
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (a < 0) {
|
|
|
|
return -lookup_table[-a][b];
|
|
|
|
} else {
|
|
|
|
return lookup_table[a][b];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void create_lookup_table()
|
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
int sum;
|
|
|
|
|
|
|
|
for (i = 0; i < 64; i++) {
|
|
|
|
sum = i;
|
|
|
|
for (j = 0; j < 32; j++) {
|
|
|
|
lookup_table[i][j] = sum >> 5;
|
|
|
|
sum += i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (i = 0; i < 64; i++)
|
|
|
|
lookup_table[i][0] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef void TimerCallback (void *);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Adlib MIDI driver
|
|
|
|
//
|
|
|
|
////////////////////////////////////////
|
|
|
|
|
|
|
|
class MidiDriver_ADLIB : public MidiDriver {
|
2002-11-26 20:14:12 +00:00
|
|
|
friend class AdlibPart;
|
2002-11-26 16:54:58 +00:00
|
|
|
|
2002-11-21 19:06:42 +00:00
|
|
|
public:
|
|
|
|
MidiDriver_ADLIB();
|
|
|
|
|
2002-12-11 16:09:58 +00:00
|
|
|
int open();
|
2002-11-21 19:06:42 +00:00
|
|
|
void close();
|
|
|
|
void send(uint32 b);
|
2002-12-01 15:51:29 +00:00
|
|
|
uint32 property (int prop, uint32 param);
|
|
|
|
|
2002-11-21 19:06:42 +00:00
|
|
|
void setPitchBendRange (byte channel, uint range);
|
|
|
|
void sysEx_customInstrument (byte channel, uint32 type, byte *instr);
|
|
|
|
|
|
|
|
void setTimerCallback (void *timer_param, void (*timer_proc) (void *));
|
|
|
|
uint32 getBaseTempo() {
|
|
|
|
#ifdef _WIN32_WCE
|
|
|
|
return 0x1D9000 * 2; // Sampled down to 11 kHz
|
|
|
|
#else //_WIN32_WCE
|
|
|
|
return 0x1D9000;
|
|
|
|
#endif //_WIN32_WCE
|
|
|
|
}
|
|
|
|
|
2002-11-26 16:54:58 +00:00
|
|
|
MidiChannel *allocateChannel();
|
|
|
|
MidiChannel *getPercussionChannel() { return NULL; } // Percussion currently not supported
|
|
|
|
|
2002-11-21 19:06:42 +00:00
|
|
|
private:
|
2002-12-11 16:09:58 +00:00
|
|
|
bool _isOpen;
|
2002-12-01 15:51:29 +00:00
|
|
|
bool _game_SmallHeader;
|
2002-11-21 19:06:42 +00:00
|
|
|
|
|
|
|
FM_OPL *_opl;
|
|
|
|
byte *_adlib_reg_cache;
|
|
|
|
SoundMixer *_mixer;
|
|
|
|
|
|
|
|
TimerCallback *_timer_proc;
|
|
|
|
void *_timer_param;
|
|
|
|
|
|
|
|
int _adlib_timer_counter;
|
|
|
|
|
|
|
|
uint16 channel_table_2[9];
|
|
|
|
int _midichan_index;
|
|
|
|
int _next_tick;
|
|
|
|
uint16 curnote_table[9];
|
|
|
|
MidiChannelAdl _midi_channels[9];
|
2002-11-26 16:54:58 +00:00
|
|
|
AdlibPart _parts[32];
|
|
|
|
|
|
|
|
void sysEx_customInstrument (AdlibPart *part, uint32 type, byte *instr);
|
2002-11-21 19:06:42 +00:00
|
|
|
|
|
|
|
void generate_samples(int16 *buf, int len);
|
|
|
|
void on_timer();
|
2002-12-18 13:22:40 +00:00
|
|
|
void part_set_instrument (AdlibPart *part, AdlibInstrument * instr);
|
2002-11-26 16:54:58 +00:00
|
|
|
void part_key_on (AdlibPart *part, byte note, byte velocity);
|
|
|
|
void part_key_off (AdlibPart *part, byte note);
|
2002-11-21 19:06:42 +00:00
|
|
|
|
|
|
|
void adlib_key_off(int chan);
|
|
|
|
void adlib_note_on(int chan, byte note, int mod);
|
|
|
|
void adlib_note_on_ex(int chan, byte note, int mod);
|
|
|
|
int adlib_read_param(int chan, byte data);
|
2002-12-18 13:22:40 +00:00
|
|
|
void adlib_setup_channel(int chan, AdlibInstrument * instr, byte vol_1, byte vol_2);
|
2002-11-21 19:06:42 +00:00
|
|
|
byte adlib_read(byte port) {
|
|
|
|
return _adlib_reg_cache[port];
|
|
|
|
}
|
|
|
|
void adlib_set_param(int channel, byte param, int value);
|
|
|
|
void adlib_key_onoff(int channel);
|
|
|
|
void adlib_write(byte port, byte value);
|
|
|
|
void adlib_playnote(int channel, int note);
|
|
|
|
|
|
|
|
MidiChannelAdl *allocate_midichan(byte pri);
|
|
|
|
|
|
|
|
void reset_tick();
|
|
|
|
void mc_off(MidiChannelAdl * mc);
|
|
|
|
|
|
|
|
static void link_mc (AdlibPart *part, MidiChannelAdl *mc);
|
2002-11-26 16:54:58 +00:00
|
|
|
void mc_inc_stuff(MidiChannelAdl *mc, Struct10 * s10, Struct11 * s11);
|
|
|
|
void mc_init_stuff(MidiChannelAdl *mc, Struct10 * s10, Struct11 * s11, byte flags,
|
|
|
|
InstrumentExtra * ie);
|
2002-11-21 19:06:42 +00:00
|
|
|
|
|
|
|
static void struct10_init(Struct10 * s10, InstrumentExtra * ie);
|
|
|
|
static byte struct10_ontimer(Struct10 * s10, Struct11 * s11);
|
|
|
|
static void struct10_setup(Struct10 * s10);
|
|
|
|
static int random_nr(int a);
|
|
|
|
void mc_key_on (MidiChannelAdl * mc, byte note, byte velocity);
|
|
|
|
|
|
|
|
static void premix_proc(void *param, int16 *buf, uint len);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
2002-11-26 16:54:58 +00:00
|
|
|
// MidiChannel method implementations
|
|
|
|
|
2002-12-18 07:48:02 +00:00
|
|
|
void AdlibPart::init (MidiDriver_ADLIB *owner, byte channel) {
|
2002-11-26 16:54:58 +00:00
|
|
|
_owner = owner;
|
2002-12-18 07:48:02 +00:00
|
|
|
_channel = channel;
|
2002-11-26 16:54:58 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2002-12-18 07:53:45 +00:00
|
|
|
MidiDriver *AdlibPart::device()
|
|
|
|
{
|
|
|
|
return _owner;
|
|
|
|
}
|
|
|
|
|
2002-11-26 16:54:58 +00:00
|
|
|
void AdlibPart::noteOff (byte note)
|
|
|
|
{
|
|
|
|
_owner->part_key_off (this, note);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AdlibPart::noteOn (byte note, byte velocity)
|
|
|
|
{
|
|
|
|
_owner->part_key_on (this, note, velocity);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AdlibPart::programChange (byte program)
|
|
|
|
{
|
|
|
|
if (program > 127) return;
|
|
|
|
|
|
|
|
uint i;
|
|
|
|
uint count = 0;
|
|
|
|
for (i = 0; i < ARRAYSIZE(map_gm_to_fm[0]); ++i)
|
|
|
|
count += map_gm_to_fm[program][i];
|
|
|
|
if (!count)
|
|
|
|
warning ("No Adlib instrument defined for GM program %d", (int) program);
|
|
|
|
_program = program;
|
2002-12-18 13:22:40 +00:00
|
|
|
_owner->part_set_instrument (this, (AdlibInstrument *) &map_gm_to_fm [program]);
|
2002-11-26 16:54:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void AdlibPart::pitchBend (int16 bend)
|
|
|
|
{
|
|
|
|
MidiChannelAdl *mc;
|
|
|
|
|
|
|
|
_pitchbend = bend;
|
|
|
|
for (mc = _mc; mc; mc = mc->_next) {
|
|
|
|
_owner->adlib_note_on(mc->_channel, mc->_note + _transpose_eff,
|
|
|
|
(_pitchbend * _pitchbend_factor >> 6) + _detune_eff);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void AdlibPart::controlChange (byte control, byte value)
|
|
|
|
{
|
|
|
|
switch (control) {
|
|
|
|
case 1: modulationWheel (value); break;
|
|
|
|
case 7: volume (value); break;
|
|
|
|
case 10: break; // Pan position. Not supported.
|
|
|
|
case 16: pitchBendFactor (value); break;
|
|
|
|
case 17: detune (value); break;
|
|
|
|
case 18: priority (value); break;
|
|
|
|
case 64: sustain (value > 0); break;
|
|
|
|
case 91: break; // Effects level. Not supported.
|
|
|
|
case 93: break; // Chorus level. Not supported.
|
2003-02-10 11:51:23 +00:00
|
|
|
case 119: break; // Unknown, used in Simon the Sorcerer 2
|
|
|
|
case 121: break; // Unknown, used in Simon the Sorcerer 1
|
2002-11-26 16:54:58 +00:00
|
|
|
case 123: allNotesOff(); break;
|
|
|
|
default:
|
|
|
|
warning ("Adlib: Unknown control change message %d", (int) control);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void AdlibPart::modulationWheel (byte value)
|
|
|
|
{
|
|
|
|
MidiChannelAdl *mc;
|
|
|
|
|
|
|
|
_modwheel = value;
|
|
|
|
for (mc = _mc; mc; mc = mc->_next) {
|
|
|
|
if (mc->_s10a.active && mc->_s11a.flag0x40)
|
|
|
|
mc->_s10a.modwheel = _modwheel >> 2;
|
|
|
|
if (mc->_s10b.active && mc->_s11b.flag0x40)
|
|
|
|
mc->_s10b.modwheel = _modwheel >> 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void AdlibPart::volume (byte value)
|
|
|
|
{
|
|
|
|
MidiChannelAdl *mc;
|
|
|
|
|
|
|
|
_vol_eff = value;
|
|
|
|
for (mc = _mc; mc; mc = mc->_next) {
|
|
|
|
_owner->adlib_set_param(mc->_channel, 0, volume_table[lookup_table[mc->_vol_2][_vol_eff >> 2]]);
|
|
|
|
if (mc->_twochan) {
|
|
|
|
_owner->adlib_set_param(mc->_channel, 13, volume_table[lookup_table[mc->_vol_1][_vol_eff >> 2]]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void AdlibPart::pitchBendFactor (byte value)
|
|
|
|
{
|
|
|
|
MidiChannelAdl *mc;
|
|
|
|
|
|
|
|
_pitchbend_factor = value;
|
|
|
|
for (mc = _mc; mc; mc = mc->_next) {
|
|
|
|
_owner->adlib_note_on(mc->_channel, mc->_note + _transpose_eff,
|
|
|
|
(_pitchbend * _pitchbend_factor >> 6) + _detune_eff);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void AdlibPart::detune (byte value)
|
|
|
|
{
|
|
|
|
MidiChannelAdl *mc;
|
|
|
|
|
|
|
|
_detune_eff = value;
|
|
|
|
for (mc = _mc; mc; mc = mc->_next) {
|
|
|
|
_owner->adlib_note_on(mc->_channel, mc->_note + _transpose_eff,
|
|
|
|
(_pitchbend * _pitchbend_factor >> 6) + _detune_eff);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void AdlibPart::priority (byte value)
|
|
|
|
{
|
|
|
|
_pri_eff = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
void AdlibPart::sustain (bool value)
|
|
|
|
{
|
|
|
|
MidiChannelAdl *mc;
|
|
|
|
|
|
|
|
_pedal = value;
|
|
|
|
if (!value) {
|
|
|
|
for (mc = _mc; mc; mc = mc->_next) {
|
|
|
|
if (mc->_waitforpedal)
|
|
|
|
_owner->mc_off(mc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void AdlibPart::allNotesOff()
|
|
|
|
{
|
|
|
|
while (_mc)
|
|
|
|
_owner->mc_off (_mc);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AdlibPart::sysEx_customInstrument (uint32 type, byte *instr)
|
|
|
|
{
|
|
|
|
_owner->sysEx_customInstrument (this, type, instr);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2002-11-21 19:06:42 +00:00
|
|
|
// MidiDriver method implementations
|
|
|
|
|
|
|
|
MidiDriver_ADLIB::MidiDriver_ADLIB()
|
|
|
|
{
|
|
|
|
uint i;
|
|
|
|
for (i = 0; i < ARRAYSIZE(_parts); ++i) {
|
2002-12-18 07:48:02 +00:00
|
|
|
_parts[i].init (this, i);
|
2002-11-21 19:06:42 +00:00
|
|
|
}
|
2002-12-01 15:51:29 +00:00
|
|
|
_game_SmallHeader = false;
|
2002-12-11 16:09:58 +00:00
|
|
|
_isOpen = false;
|
2002-11-21 19:06:42 +00:00
|
|
|
}
|
|
|
|
|
2002-12-11 16:09:58 +00:00
|
|
|
int MidiDriver_ADLIB::open ()
|
2002-11-21 19:06:42 +00:00
|
|
|
{
|
2002-12-11 16:09:58 +00:00
|
|
|
if (_isOpen)
|
2002-11-21 19:06:42 +00:00
|
|
|
return MERR_ALREADY_OPEN;
|
2002-12-11 16:09:58 +00:00
|
|
|
_isOpen = true;
|
2002-11-21 19:06:42 +00:00
|
|
|
|
|
|
|
int i;
|
|
|
|
MidiChannelAdl *mc;
|
2003-01-29 21:28:37 +00:00
|
|
|
int env_bits = g_system->property(OSystem::PROP_GET_FMOPL_ENV_BITS, NULL);
|
|
|
|
int eg_ent = g_system->property(OSystem::PROP_GET_FMOPL_EG_ENT, NULL);
|
2002-11-21 19:06:42 +00:00
|
|
|
|
|
|
|
for (i = 0, mc = _midi_channels; i != ARRAYSIZE(_midi_channels); i++, mc++) {
|
|
|
|
mc->_channel = i;
|
|
|
|
mc->_s11a.s10 = &mc->_s10b;
|
|
|
|
mc->_s11b.s10 = &mc->_s10a;
|
|
|
|
}
|
|
|
|
|
|
|
|
_adlib_reg_cache = (byte *)calloc(256, 1);
|
|
|
|
|
2003-01-29 21:28:37 +00:00
|
|
|
OPLBuildTables((env_bits ? env_bits : FMOPL_ENV_BITS_HQ), (eg_ent ? eg_ent : FMOPL_EG_ENT_HQ));
|
|
|
|
|
2002-11-21 19:06:42 +00:00
|
|
|
_opl = OPLCreate(OPL_TYPE_YM3812, 3579545, g_system->property(OSystem::PROP_GET_SAMPLE_RATE, 0));
|
|
|
|
|
|
|
|
adlib_write(1, 0x20);
|
|
|
|
adlib_write(8, 0x40);
|
|
|
|
adlib_write(0xBD, 0x00);
|
|
|
|
create_lookup_table();
|
|
|
|
|
|
|
|
_mixer = g_mixer;
|
|
|
|
_mixer->setupPremix(this, premix_proc);
|
2002-12-11 16:09:58 +00:00
|
|
|
|
2002-11-21 19:06:42 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MidiDriver_ADLIB::close()
|
|
|
|
{
|
2002-11-21 19:19:14 +00:00
|
|
|
uint i;
|
2002-11-21 19:06:42 +00:00
|
|
|
for (i = 0; i < ARRAYSIZE(_midi_channels); ++i) {
|
|
|
|
if (_midi_channels [i]._part)
|
|
|
|
mc_off (&_midi_channels [i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Detach the premix callback handler
|
|
|
|
_mixer->setupPremix (0, 0);
|
2002-12-11 16:09:58 +00:00
|
|
|
|
|
|
|
_isOpen = false;
|
2002-11-21 19:06:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MidiDriver_ADLIB::send (uint32 b)
|
|
|
|
{
|
2002-11-21 19:19:14 +00:00
|
|
|
//byte param3 = (byte) ((b >> 24) & 0xFF);
|
2002-11-21 19:06:42 +00:00
|
|
|
byte param2 = (byte) ((b >> 16) & 0xFF);
|
|
|
|
byte param1 = (byte) ((b >> 8) & 0xFF);
|
|
|
|
byte cmd = (byte) (b & 0xF0);
|
|
|
|
byte chan = (byte) (b & 0x0F);
|
|
|
|
AdlibPart *part = &_parts [chan];
|
|
|
|
|
|
|
|
switch (cmd) {
|
|
|
|
case 0x80:// Note Off
|
2002-11-26 16:54:58 +00:00
|
|
|
part_key_off (part, param1); break;
|
2002-11-21 19:06:42 +00:00
|
|
|
case 0x90: // Note On
|
2002-11-26 16:54:58 +00:00
|
|
|
part_key_on (part, param1, param2); break;
|
2002-11-21 19:06:42 +00:00
|
|
|
case 0xA0: // Aftertouch
|
2002-11-26 16:54:58 +00:00
|
|
|
break; // Not supported.
|
2002-11-21 19:06:42 +00:00
|
|
|
case 0xB0: // Control Change
|
2002-11-26 16:54:58 +00:00
|
|
|
part->controlChange (param1, param2); break;
|
2002-11-21 19:06:42 +00:00
|
|
|
case 0xC0: // Program Change
|
2002-11-26 16:54:58 +00:00
|
|
|
if (chan != 9)
|
|
|
|
part->programChange (param1);
|
2002-11-21 19:06:42 +00:00
|
|
|
break;
|
|
|
|
case 0xD0: // Channel Pressure
|
2002-11-26 16:54:58 +00:00
|
|
|
break; // Not supported.
|
2002-11-21 19:06:42 +00:00
|
|
|
case 0xE0: // Pitch Bend
|
2002-11-26 16:54:58 +00:00
|
|
|
part->pitchBend ((param1 | (param2 << 7)) - 0x2000); break;
|
2002-11-21 19:06:42 +00:00
|
|
|
case 0xF0: // SysEx
|
|
|
|
// We should never get here! SysEx information has to be
|
|
|
|
// sent via high-level semantic methods.
|
|
|
|
warning ("MidiDriver_ADLIB: Receiving SysEx command on a send() call");
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
warning ("MidiDriver_ADLIB: Unknown send() command 0x%02X", cmd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-12-01 15:51:29 +00:00
|
|
|
uint32 MidiDriver_ADLIB::property (int prop, uint32 param)
|
|
|
|
{
|
|
|
|
switch (prop) {
|
|
|
|
case PROP_SMALLHEADER: // Indicates older game, use different operator volume algorithm
|
|
|
|
_game_SmallHeader = (param > 0);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2002-11-21 19:06:42 +00:00
|
|
|
void MidiDriver_ADLIB::setPitchBendRange (byte channel, uint range)
|
|
|
|
{
|
|
|
|
MidiChannelAdl *mc;
|
|
|
|
AdlibPart *part = &_parts [channel];
|
|
|
|
|
|
|
|
part->_pitchbend_factor = range;
|
|
|
|
for (mc = part->_mc; mc; mc = mc->_next) {
|
|
|
|
adlib_note_on(mc->_channel, mc->_note + part->_transpose_eff,
|
|
|
|
(part->_pitchbend * part->_pitchbend_factor >> 6) + part->_detune_eff);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MidiDriver_ADLIB::sysEx_customInstrument (byte channel, uint32 type, byte *instr)
|
2002-11-26 16:54:58 +00:00
|
|
|
{
|
|
|
|
sysEx_customInstrument (&_parts [channel], type, instr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MidiDriver_ADLIB::sysEx_customInstrument (AdlibPart *part, uint32 type, byte *instr)
|
2002-11-21 19:06:42 +00:00
|
|
|
{
|
|
|
|
if (type == 'ADL ') {
|
2002-12-18 13:22:40 +00:00
|
|
|
AdlibInstrument *i = &part->_part_instr;
|
|
|
|
memcpy(i, instr, sizeof(AdlibInstrument));
|
2002-11-21 19:06:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MidiDriver_ADLIB::setTimerCallback (void *timer_param, void (*timer_proc) (void *))
|
|
|
|
{
|
|
|
|
_timer_proc = (TimerCallback *) timer_proc;
|
|
|
|
_timer_param = timer_param;
|
|
|
|
}
|
|
|
|
|
2002-11-26 16:54:58 +00:00
|
|
|
MidiChannel *MidiDriver_ADLIB::allocateChannel()
|
|
|
|
{
|
|
|
|
AdlibPart *part;
|
|
|
|
uint i;
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAYSIZE(_parts); ++i) {
|
|
|
|
part = &_parts[i];
|
|
|
|
if (!part->_allocated) {
|
|
|
|
part->allocate();
|
|
|
|
return (part);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2002-11-21 19:06:42 +00:00
|
|
|
MidiDriver *MidiDriver_ADLIB_create()
|
|
|
|
{
|
|
|
|
return new MidiDriver_ADLIB();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// All the code brought over from IMuseAdlib
|
|
|
|
|
|
|
|
void MidiDriver_ADLIB::premix_proc(void *param, int16 *buf, uint len)
|
|
|
|
{
|
|
|
|
((MidiDriver_ADLIB *) param)->generate_samples(buf, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MidiDriver_ADLIB::adlib_write(byte port, byte value)
|
|
|
|
{
|
|
|
|
if (_adlib_reg_cache[port] == value)
|
|
|
|
return;
|
|
|
|
_adlib_reg_cache[port] = value;
|
|
|
|
|
|
|
|
OPLWriteReg(_opl, port, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MidiDriver_ADLIB::generate_samples(int16 *data, int len)
|
|
|
|
{
|
|
|
|
int step;
|
|
|
|
|
|
|
|
if (!_opl) {
|
|
|
|
memset(data, 0, len * sizeof(int16));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
do {
|
|
|
|
step = len;
|
|
|
|
if (step > _next_tick)
|
|
|
|
step = _next_tick;
|
|
|
|
YM3812UpdateOne(_opl, data, step);
|
|
|
|
|
|
|
|
if (!(_next_tick -= step)) {
|
|
|
|
if (_timer_proc)
|
|
|
|
(*_timer_proc) (_timer_param);
|
|
|
|
on_timer();
|
|
|
|
reset_tick();
|
|
|
|
}
|
|
|
|
data += step;
|
|
|
|
} while (len -= step);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MidiDriver_ADLIB::reset_tick()
|
|
|
|
{
|
|
|
|
_next_tick = 88;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MidiDriver_ADLIB::on_timer()
|
|
|
|
{
|
|
|
|
MidiChannelAdl *mc;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
_adlib_timer_counter += 0xD69;
|
|
|
|
while (_adlib_timer_counter >= 0x411B) {
|
|
|
|
_adlib_timer_counter -= 0x411B;
|
|
|
|
mc = _midi_channels;
|
|
|
|
for (i = 0; i != ARRAYSIZE(_midi_channels); i++, mc++) {
|
|
|
|
if (!mc->_part)
|
|
|
|
continue;
|
|
|
|
if (mc->_duration && (mc->_duration -= 0x11) <= 0) {
|
|
|
|
mc_off(mc);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (mc->_s10a.active) {
|
|
|
|
mc_inc_stuff(mc, &mc->_s10a, &mc->_s11a);
|
|
|
|
}
|
|
|
|
if (mc->_s10b.active) {
|
|
|
|
mc_inc_stuff(mc, &mc->_s10b, &mc->_s11b);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MidiDriver_ADLIB::mc_off(MidiChannelAdl * mc2)
|
|
|
|
{
|
|
|
|
MidiChannelAdl *mc = (MidiChannelAdl *)mc2, *tmp;
|
|
|
|
|
|
|
|
adlib_key_off(mc->_channel);
|
|
|
|
|
|
|
|
tmp = mc->_prev;
|
|
|
|
|
|
|
|
if (mc->_next)
|
|
|
|
mc->_next->_prev = tmp;
|
|
|
|
if (tmp)
|
|
|
|
tmp->_next = mc->_next;
|
|
|
|
else
|
|
|
|
mc->_part->_mc = mc->_next;
|
|
|
|
mc->_part = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MidiDriver_ADLIB::mc_inc_stuff(MidiChannelAdl *mc, Struct10 * s10, Struct11 * s11)
|
|
|
|
{
|
|
|
|
byte code;
|
|
|
|
AdlibPart *part = mc->_part;
|
|
|
|
|
|
|
|
code = struct10_ontimer(s10, s11);
|
|
|
|
|
|
|
|
if (code & 1) {
|
|
|
|
switch (s11->param) {
|
|
|
|
case 0:
|
|
|
|
mc->_vol_2 = s10->start_value + s11->modify_val;
|
2002-11-26 16:54:58 +00:00
|
|
|
adlib_set_param(mc->_channel, 0,
|
|
|
|
volume_table[lookup_table[mc->_vol_2]
|
|
|
|
[part->_vol_eff >> 2]]);
|
2002-11-21 19:06:42 +00:00
|
|
|
break;
|
|
|
|
case 13:
|
|
|
|
mc->_vol_1 = s10->start_value + s11->modify_val;
|
|
|
|
if (mc->_twochan) {
|
2002-11-26 16:54:58 +00:00
|
|
|
adlib_set_param(mc->_channel, 13,
|
|
|
|
volume_table[lookup_table[mc->_vol_1]
|
|
|
|
[part->_vol_eff >> 2]]);
|
2002-11-21 19:06:42 +00:00
|
|
|
} else {
|
2002-11-26 16:54:58 +00:00
|
|
|
adlib_set_param(mc->_channel, 13, mc->_vol_1);
|
2002-11-21 19:06:42 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 30:
|
|
|
|
s11->s10->modwheel = (char)s11->modify_val;
|
|
|
|
break;
|
|
|
|
case 31:
|
|
|
|
s11->s10->unk3 = (char)s11->modify_val;
|
|
|
|
break;
|
|
|
|
default:
|
2002-11-26 16:54:58 +00:00
|
|
|
adlib_set_param(mc->_channel, s11->param,
|
|
|
|
s10->start_value + s11->modify_val);
|
2002-11-21 19:06:42 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (code & 2 && s11->flag0x10)
|
2002-11-26 16:54:58 +00:00
|
|
|
adlib_key_onoff(mc->_channel);
|
2002-11-21 19:06:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MidiDriver_ADLIB::adlib_key_off(int chan)
|
|
|
|
{
|
|
|
|
byte port = chan + 0xB0;
|
|
|
|
adlib_write(port, adlib_read(port) & ~0x20);
|
|
|
|
}
|
|
|
|
|
|
|
|
byte MidiDriver_ADLIB::struct10_ontimer(Struct10 * s10, Struct11 * s11)
|
|
|
|
{
|
|
|
|
byte result = 0;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (s10->count && (s10->count -= 17) <= 0) {
|
|
|
|
s10->active = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
i = s10->cur_val + s10->speed_hi;
|
|
|
|
s10->speed_lo_counter += s10->speed_lo;
|
|
|
|
if (s10->speed_lo_counter >= s10->speed_lo_max) {
|
|
|
|
s10->speed_lo_counter -= s10->speed_lo_max;
|
|
|
|
i += s10->direction;
|
|
|
|
}
|
|
|
|
if (s10->cur_val != i || s10->modwheel != s10->modwheel_last) {
|
|
|
|
s10->cur_val = i;
|
|
|
|
s10->modwheel_last = s10->modwheel;
|
|
|
|
i = lookup_volume(i, s10->modwheel_last);
|
|
|
|
if (i != s11->modify_val) {
|
|
|
|
s11->modify_val = i;
|
|
|
|
result = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!--s10->num_steps) {
|
|
|
|
s10->active++;
|
|
|
|
if (s10->active > 4) {
|
|
|
|
if (s10->loop) {
|
|
|
|
s10->active = 1;
|
|
|
|
result |= 2;
|
|
|
|
struct10_setup(s10);
|
|
|
|
} else {
|
|
|
|
s10->active = 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
struct10_setup(s10);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MidiDriver_ADLIB::adlib_set_param(int channel, byte param, int value)
|
|
|
|
{
|
|
|
|
const AdlibSetParams *as;
|
|
|
|
byte port;
|
|
|
|
|
|
|
|
assert(channel >= 0 && channel < 9);
|
|
|
|
|
|
|
|
if (param <= 12) {
|
|
|
|
port = channel_mappings_2[channel];
|
|
|
|
} else if (param <= 25) {
|
|
|
|
param -= 13;
|
|
|
|
port = channel_mappings[channel];
|
|
|
|
} else if (param <= 27) {
|
|
|
|
param -= 13;
|
|
|
|
port = channel;
|
|
|
|
} else if (param == 28 || param == 29) {
|
|
|
|
if (param == 28)
|
|
|
|
value -= 15;
|
|
|
|
else
|
|
|
|
value -= 383;
|
|
|
|
value <<= 4;
|
|
|
|
channel_table_2[channel] = value;
|
|
|
|
adlib_playnote(channel, curnote_table[channel] + value);
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
as = &adlib_setparam_table[param];
|
|
|
|
if (as->d)
|
|
|
|
value = as->d - value;
|
|
|
|
port += as->a;
|
|
|
|
adlib_write(port, (adlib_read(port) & ~as->c) | (((byte)value) << as->b));
|
|
|
|
}
|
|
|
|
|
|
|
|
void MidiDriver_ADLIB::adlib_key_onoff(int channel)
|
|
|
|
{
|
|
|
|
byte val;
|
|
|
|
byte port = channel + 0xB0;
|
|
|
|
assert(channel >= 0 && channel < 9);
|
|
|
|
|
|
|
|
val = adlib_read(port);
|
|
|
|
adlib_write(port, val & ~0x20);
|
|
|
|
adlib_write(port, val | 0x20);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MidiDriver_ADLIB::struct10_setup(Struct10 * s10)
|
|
|
|
{
|
|
|
|
int b, c, d, e, f, g, h;
|
|
|
|
byte t;
|
|
|
|
|
|
|
|
b = s10->unk3;
|
|
|
|
f = s10->active - 1;
|
|
|
|
|
|
|
|
t = s10->table_a[f];
|
|
|
|
e = num_steps_table[lookup_table[t & 0x7F][b]];
|
|
|
|
if (t & 0x80) {
|
|
|
|
e = random_nr(e);
|
|
|
|
}
|
|
|
|
if (e == 0)
|
|
|
|
e++;
|
|
|
|
|
|
|
|
s10->num_steps = s10->speed_lo_max = e;
|
|
|
|
|
|
|
|
if (f != 2) {
|
|
|
|
c = s10->param;
|
|
|
|
g = s10->start_value;
|
|
|
|
t = s10->table_b[f];
|
|
|
|
d = lookup_volume(c, (t & 0x7F) - 31);
|
|
|
|
if (t & 0x80) {
|
|
|
|
d = random_nr(d);
|
|
|
|
}
|
|
|
|
if (d + g > c) {
|
|
|
|
h = c - g;
|
|
|
|
} else {
|
|
|
|
h = d;
|
|
|
|
if (d + g < 0)
|
|
|
|
h = -g;
|
|
|
|
}
|
|
|
|
h -= s10->cur_val;
|
|
|
|
} else {
|
|
|
|
h = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
s10->speed_hi = h / e;
|
|
|
|
if (h < 0) {
|
|
|
|
h = -h;
|
|
|
|
s10->direction = -1;
|
|
|
|
} else {
|
|
|
|
s10->direction = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
s10->speed_lo = h % e;
|
|
|
|
s10->speed_lo_counter = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MidiDriver_ADLIB::adlib_playnote(int channel, int note)
|
|
|
|
{
|
|
|
|
byte old, oct, notex;
|
|
|
|
int note2;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
note2 = (note >> 7) - 4;
|
|
|
|
|
|
|
|
oct = octave_numbers[note2] << 2;
|
|
|
|
notex = note_numbers[note2];
|
|
|
|
|
|
|
|
old = adlib_read(channel + 0xB0);
|
|
|
|
if (old & 0x20) {
|
|
|
|
old &= ~0x20;
|
|
|
|
if (oct > old) {
|
|
|
|
if (notex < 6) {
|
|
|
|
notex += 12;
|
|
|
|
oct -= 4;
|
|
|
|
}
|
|
|
|
} else if (oct < old) {
|
|
|
|
if (notex > 11) {
|
|
|
|
notex -= 12;
|
|
|
|
oct += 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
i = (notex << 3) + ((note >> 4) & 0x7);
|
|
|
|
adlib_write(channel + 0xA0, note_to_f_num[i]);
|
|
|
|
adlib_write(channel + 0xB0, oct | 0x20);
|
|
|
|
}
|
|
|
|
|
|
|
|
int MidiDriver_ADLIB::random_nr(int a)
|
|
|
|
{
|
|
|
|
static byte _rand_seed = 1;
|
|
|
|
if (_rand_seed & 1) {
|
|
|
|
_rand_seed >>= 1;
|
|
|
|
_rand_seed ^= 0xB8;
|
|
|
|
} else {
|
|
|
|
_rand_seed >>= 1;
|
|
|
|
}
|
|
|
|
return _rand_seed * a >> 8;
|
|
|
|
}
|
|
|
|
|
2002-11-26 16:54:58 +00:00
|
|
|
void MidiDriver_ADLIB::part_key_off (AdlibPart *part, byte note)
|
2002-11-21 19:06:42 +00:00
|
|
|
{
|
|
|
|
MidiChannelAdl *mc;
|
|
|
|
|
2002-11-26 16:54:58 +00:00
|
|
|
for (mc = part->_mc; mc; mc = mc->_next) {
|
2002-11-21 19:06:42 +00:00
|
|
|
if (mc->_note == note) {
|
|
|
|
if (part->_pedal)
|
|
|
|
mc->_waitforpedal = true;
|
|
|
|
else
|
|
|
|
mc_off(mc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-11-26 16:54:58 +00:00
|
|
|
void MidiDriver_ADLIB::part_key_on (AdlibPart *part, byte note, byte velocity)
|
2002-11-21 19:06:42 +00:00
|
|
|
{
|
|
|
|
MidiChannelAdl *mc;
|
|
|
|
|
|
|
|
mc = allocate_midichan(part->_pri_eff);
|
|
|
|
if (!mc)
|
|
|
|
return;
|
|
|
|
|
|
|
|
link_mc(part, mc);
|
|
|
|
mc_key_on(mc, note, velocity);
|
|
|
|
}
|
|
|
|
|
|
|
|
MidiChannelAdl *MidiDriver_ADLIB::allocate_midichan(byte pri)
|
|
|
|
{
|
|
|
|
MidiChannelAdl *ac, *best = NULL;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < 9; i++) {
|
|
|
|
if (++_midichan_index >= 9)
|
|
|
|
_midichan_index = 0;
|
|
|
|
ac = &_midi_channels[_midichan_index];
|
|
|
|
if (!ac->_part)
|
|
|
|
return ac;
|
|
|
|
if (!ac->_next) {
|
|
|
|
if (ac->_part->_pri_eff <= pri) {
|
|
|
|
pri = ac->_part->_pri_eff;
|
|
|
|
best = ac;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (best)
|
|
|
|
mc_off(best);
|
|
|
|
return best;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MidiDriver_ADLIB::link_mc (AdlibPart *part, MidiChannelAdl *mc)
|
|
|
|
{
|
|
|
|
mc->_part = part;
|
|
|
|
mc->_next = (MidiChannelAdl *)part->_mc;
|
|
|
|
part->_mc = mc;
|
|
|
|
mc->_prev = NULL;
|
|
|
|
|
|
|
|
if (mc->_next)
|
|
|
|
mc->_next->_prev = mc;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MidiDriver_ADLIB::mc_key_on (MidiChannelAdl * mc2, byte note, byte velocity)
|
|
|
|
{
|
|
|
|
MidiChannelAdl *mc = (MidiChannelAdl *)mc2;
|
|
|
|
AdlibPart *part = mc->_part;
|
2002-12-18 13:22:40 +00:00
|
|
|
AdlibInstrument *instr = &part->_part_instr;
|
2002-11-21 19:06:42 +00:00
|
|
|
int c;
|
|
|
|
byte vol_1, vol_2;
|
|
|
|
|
|
|
|
mc->_twochan = instr->feedback & 1;
|
|
|
|
mc->_note = note;
|
|
|
|
mc->_waitforpedal = false;
|
|
|
|
mc->_duration = instr->duration;
|
|
|
|
if (mc->_duration != 0)
|
|
|
|
mc->_duration *= 63;
|
|
|
|
|
|
|
|
vol_1 = (instr->oplvl_1 & 0x3F) + lookup_table[velocity >> 1][instr->waveform_1 >> 2];
|
|
|
|
if (vol_1 > 0x3F)
|
|
|
|
vol_1 = 0x3F;
|
|
|
|
mc->_vol_1 = vol_1;
|
|
|
|
|
|
|
|
vol_2 = (instr->oplvl_2 & 0x3F) + lookup_table[velocity >> 1][instr->waveform_2 >> 2];
|
|
|
|
if (vol_2 > 0x3F)
|
|
|
|
vol_2 = 0x3F;
|
|
|
|
mc->_vol_2 = vol_2;
|
|
|
|
|
|
|
|
c = part->_vol_eff >> 2;
|
|
|
|
|
|
|
|
vol_2 = volume_table[lookup_table[vol_2][c]];
|
|
|
|
if (mc->_twochan)
|
|
|
|
vol_1 = volume_table[lookup_table[vol_1][c]];
|
|
|
|
|
|
|
|
adlib_setup_channel(mc->_channel, instr, vol_1, vol_2);
|
|
|
|
adlib_note_on_ex(mc->_channel, part->_transpose_eff + note, part->_detune_eff + (part->_pitchbend * part->_pitchbend_factor >> 6));
|
|
|
|
|
|
|
|
if (instr->flags_a & 0x80) {
|
|
|
|
mc_init_stuff(mc, &mc->_s10a, &mc->_s11a, instr->flags_a, &instr->extra_a);
|
|
|
|
} else {
|
|
|
|
mc->_s10a.active = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (instr->flags_b & 0x80) {
|
|
|
|
mc_init_stuff(mc, &mc->_s10b, &mc->_s11b, instr->flags_b, &instr->extra_b);
|
|
|
|
} else {
|
|
|
|
mc->_s10b.active = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-12-18 13:22:40 +00:00
|
|
|
void MidiDriver_ADLIB::adlib_setup_channel(int chan, AdlibInstrument * instr, byte vol_1, byte vol_2)
|
2002-11-21 19:06:42 +00:00
|
|
|
{
|
|
|
|
byte port;
|
|
|
|
|
|
|
|
assert(chan >= 0 && chan < 9);
|
|
|
|
|
|
|
|
port = channel_mappings[chan];
|
|
|
|
adlib_write(port + 0x20, instr->flags_1);
|
|
|
|
|
2002-12-01 15:51:29 +00:00
|
|
|
if (!_game_SmallHeader ||(instr->feedback & 1))
|
2002-11-21 19:06:42 +00:00
|
|
|
adlib_write(port + 0x40, (instr->oplvl_1 | 0x3F) - vol_1 );
|
|
|
|
else
|
|
|
|
adlib_write(port + 0x40, instr->oplvl_1);
|
|
|
|
|
|
|
|
adlib_write(port + 0x60, 0xff & (~instr->atdec_1));
|
|
|
|
adlib_write(port + 0x80, 0xff & (~instr->sustrel_1));
|
|
|
|
adlib_write(port + 0xE0, instr->waveform_1);
|
|
|
|
|
|
|
|
port = channel_mappings_2[chan];
|
|
|
|
adlib_write(port + 0x20, instr->flags_2);
|
|
|
|
adlib_write(port + 0x40, (instr->oplvl_2 | 0x3F) - vol_2 );
|
|
|
|
adlib_write(port + 0x60, 0xff & (~instr->atdec_2));
|
|
|
|
adlib_write(port + 0x80, 0xff & (~instr->sustrel_2));
|
|
|
|
adlib_write(port + 0xE0, instr->waveform_2);
|
|
|
|
|
|
|
|
adlib_write((byte)chan + 0xC0, instr->feedback);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MidiDriver_ADLIB::adlib_note_on_ex(int chan, byte note, int mod)
|
|
|
|
{
|
|
|
|
int code;
|
|
|
|
assert(chan >= 0 && chan < 9);
|
|
|
|
code = (note << 7) + mod;
|
|
|
|
curnote_table[chan] = code;
|
|
|
|
channel_table_2[chan] = 0;
|
|
|
|
adlib_playnote(chan, code);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MidiDriver_ADLIB::mc_init_stuff (MidiChannelAdl *mc, Struct10 * s10,
|
|
|
|
Struct11 * s11, byte flags, InstrumentExtra * ie)
|
|
|
|
{
|
|
|
|
AdlibPart *part = mc->_part;
|
|
|
|
|
|
|
|
s11->modify_val = 0;
|
|
|
|
s11->flag0x40 = flags & 0x40;
|
|
|
|
s10->loop = flags & 0x20;
|
|
|
|
s11->flag0x10 = flags & 0x10;
|
|
|
|
s11->param = param_table_1[flags & 0xF];
|
|
|
|
s10->param = param_table_2[flags & 0xF];
|
|
|
|
s10->unk3 = 31;
|
|
|
|
if (s11->flag0x40) {
|
|
|
|
s10->modwheel = part->_modwheel >> 2;
|
|
|
|
} else {
|
|
|
|
s10->modwheel = 31;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (s11->param) {
|
|
|
|
case 0:
|
|
|
|
s10->start_value = mc->_vol_2;
|
|
|
|
break;
|
|
|
|
case 13:
|
|
|
|
s10->start_value = mc->_vol_1;
|
|
|
|
break;
|
|
|
|
case 30:
|
|
|
|
s10->start_value = 31;
|
|
|
|
s11->s10->modwheel = 0;
|
|
|
|
break;
|
|
|
|
case 31:
|
|
|
|
s10->start_value = 0;
|
|
|
|
s11->s10->unk3 = 0;
|
|
|
|
break;
|
|
|
|
default:
|
2002-11-26 16:54:58 +00:00
|
|
|
s10->start_value = adlib_read_param(mc->_channel, s11->param);
|
2002-11-21 19:06:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct10_init(s10, ie);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MidiDriver_ADLIB::struct10_init(Struct10 * s10, InstrumentExtra * ie)
|
|
|
|
{
|
|
|
|
s10->active = 1;
|
|
|
|
s10->cur_val = 0;
|
|
|
|
s10->modwheel_last = 31;
|
|
|
|
s10->count = ie->a;
|
|
|
|
if (s10->count)
|
|
|
|
s10->count *= 63;
|
|
|
|
s10->table_a[0] = ie->b;
|
|
|
|
s10->table_a[1] = ie->d;
|
|
|
|
s10->table_a[2] = ie->f;
|
|
|
|
s10->table_a[3] = ie->g;
|
|
|
|
|
|
|
|
s10->table_b[0] = ie->c;
|
|
|
|
s10->table_b[1] = ie->e;
|
|
|
|
s10->table_b[2] = 0;
|
|
|
|
s10->table_b[3] = ie->h;
|
|
|
|
|
|
|
|
struct10_setup(s10);
|
|
|
|
}
|
|
|
|
|
|
|
|
int MidiDriver_ADLIB::adlib_read_param(int chan, byte param)
|
|
|
|
{
|
|
|
|
const AdlibSetParams *as;
|
|
|
|
byte val;
|
|
|
|
byte port;
|
|
|
|
|
|
|
|
assert(chan >= 0 && chan < 9);
|
|
|
|
|
|
|
|
if (param <= 12) {
|
|
|
|
port = channel_mappings_2[chan];
|
|
|
|
} else if (param <= 25) {
|
|
|
|
param -= 13;
|
|
|
|
port = channel_mappings[chan];
|
|
|
|
} else if (param <= 27) {
|
|
|
|
param -= 13;
|
|
|
|
port = chan;
|
|
|
|
} else if (param == 28) {
|
|
|
|
return 0xF;
|
|
|
|
} else if (param == 29) {
|
|
|
|
return 0x17F;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
as = &adlib_setparam_table[param];
|
|
|
|
val = adlib_read(port + as->a);
|
|
|
|
val &= as->c;
|
|
|
|
val >>= as->b;
|
|
|
|
if (as->d)
|
|
|
|
val = as->d - val;
|
|
|
|
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MidiDriver_ADLIB::adlib_note_on(int chan, byte note, int mod)
|
|
|
|
{
|
|
|
|
int code;
|
|
|
|
assert(chan >= 0 && chan < 9);
|
|
|
|
code = (note << 7) + mod;
|
|
|
|
curnote_table[chan] = code;
|
|
|
|
adlib_playnote(chan, channel_table_2[chan] + code);
|
|
|
|
}
|
|
|
|
|
2002-12-18 13:22:40 +00:00
|
|
|
void MidiDriver_ADLIB::part_set_instrument(AdlibPart *part, AdlibInstrument * instr)
|
2002-11-21 19:06:42 +00:00
|
|
|
{
|
2002-12-18 13:22:40 +00:00
|
|
|
AdlibInstrument *i = &part->_part_instr;
|
|
|
|
memcpy(i, instr, sizeof(AdlibInstrument));
|
2002-11-21 19:06:42 +00:00
|
|
|
}
|