[Scummvm-cvs-logs] scummvm master -> dbc8d3c530dd12cbe2cea4d9099f0ec05fedf6d0
clone2727
clone2727 at gmail.com
Thu Jul 9 07:34:55 CEST 2015
This automated email contains information about 42 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
6f01600e12 AUDIO: Fix abuse of driver IDs in OPL code.
2fa1ce51dd GUI: Simplify OPL option code a bit.
f1f29302f5 AUDIO: Remove the legacy OPL API
2e8f9dcec9 AUDIO: Remove the sample rate configuration from the OPL code
b9307ef1a4 AUDIO: Introduce a callback to the OPL code
0bb13b358e SCUMM: Use the built-in OPL timer for Player_AD
ed8830fcc8 AUDIO: Use the built-in OPL timer for MidiDriver_ADLIB
24add3c745 SCI: Use the built-in OPL timer
984cd9b018 CINE: Use the built-in OPL timer
3c7c217f44 CRUISE: Use the built-in OPL timer
5803dffead KYRA: Use the built-in OPL timer
b638efe0fa PARALLACTION: Use the built-in OPL timer
b122ec2790 SKY: Use the built-in OPL timer
4a4ad97fd3 QUEEN: Use the built-in OPL timer
5024ae136a TSAGE: Use the built-in OPL timer
4c6724c5fa MADS: Use the built-in OPL timer
cc6e304af1 AUDIO: Limit the DOSBox start(0) hack to only being called once
5b06eef159 AUDIO: Allow for changing the OPL timer rate
73e8ac2a9b GOB: Use the built-in OPL timer
dcb75fcaf1 SHERLOCK: Use the built-in OPL timer
0c5d40e94c AGOS: Use the built-in OPL timer
22d985f3c2 AUDIO: Use the built-in OPL timer for MidiDriver_Miles_AdLib
f7c785b37b SKY: Implement original music volume handling
e31da911c9 GOB: Implement custom AdLib volume control
b367ea548d QUEEN: Implement original music volume handling
dce05c520b AUDIO: Be consistent with calling stop() in OPL destructors
8bcbcd6c16 AUDIO: Change callback frequency without restarting the audio stream
bed9da8b9d AUDIO: Remove all AudioStream access to OPL
4d56585112 AUDIO: Add a class representing a real OPL
a45ff5a6a9 CONFIGURE: Ensure the USE_ALSA define ends up in config.mk
40820eebf5 AUDIO: Add experimental hardware OPL support using ALSA
b630eca437 AUDIO: Fix bug in ALSA AdLib driver
beed23c441 AUDIO: List OPL3 support for ALSA AdLib driver
82f585871b SCI: Check OPL init return code
56c0238f9b SCI: Delete OPL when init fails
be345083a0 AUDIO: Update 2nd operator panning for AdLib register 0xc0
1bdcf6e836 AUDIO: Reset ALSA AdLib on exit
1287a56429 AUDIO: Fix ALSA AdLib OPL2 waveform mask
f0606aa8f1 AUDIO: Reset OPL registers in ALSA driver
fde8abf8cc AUDIO: Move the common AdLib MidiDriver out of softsynth
bb8132beb8 AUDIO: Move ALSA OPL 'driver' out of softsynth
dbc8d3c530 Merge pull request #600 from clone2727/opl_alsa
Commit: 6f01600e12ba14acde8a6557716783861dc014d1
https://github.com/scummvm/scummvm/commit/6f01600e12ba14acde8a6557716783861dc014d1
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2015-07-07T20:19:41-04:00
Commit Message:
AUDIO: Fix abuse of driver IDs in OPL code.
If the driver id did not match the array index, the wrong driver entry would
be accessed causing a crash in the worst case.
Changed paths:
audio/fmopl.cpp
audio/fmopl.h
diff --git a/audio/fmopl.cpp b/audio/fmopl.cpp
index 30229ea..00e49ef 100644
--- a/audio/fmopl.cpp
+++ b/audio/fmopl.cpp
@@ -63,6 +63,15 @@ Config::DriverId Config::parse(const Common::String &name) {
return -1;
}
+const Config::EmulatorDescription *Config::findDriver(DriverId id) {
+ for (int i = 0; _drivers[i].name; ++i) {
+ if (_drivers[i].id == id)
+ return &_drivers[i];
+ }
+
+ return 0;
+}
+
Config::DriverId Config::detect(OplType type) {
uint32 flags = 0;
switch (type) {
@@ -90,8 +99,11 @@ Config::DriverId Config::detect(OplType type) {
// When a valid driver is selected, check whether it supports
// the requested OPL chip.
if (drv != -1 && drv != kAuto) {
+ const EmulatorDescription *driverDesc = findDriver(drv);
// If the chip is supported, just use the driver.
- if ((flags & _drivers[drv].flags)) {
+ if (!driverDesc) {
+ warning("The selected OPL driver %d could not be found", drv);
+ } else if ((flags & driverDesc->flags)) {
return drv;
} else {
// Else we will output a warning and just
diff --git a/audio/fmopl.h b/audio/fmopl.h
index 85ac606..28dd456 100644
--- a/audio/fmopl.h
+++ b/audio/fmopl.h
@@ -71,6 +71,12 @@ public:
static DriverId parse(const Common::String &name);
/**
+ * @return The driver description for the given id or 0 in case it is not
+ * available.
+ */
+ static const EmulatorDescription *findDriver(DriverId id);
+
+ /**
* Detects a driver for the specific type.
*
* @return Returns a valid driver id on success, -1 otherwise.
Commit: 2fa1ce51dd3cb00eef289094fe9f660c237254bc
https://github.com/scummvm/scummvm/commit/2fa1ce51dd3cb00eef289094fe9f660c237254bc
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2015-07-07T20:19:42-04:00
Commit Message:
GUI: Simplify OPL option code a bit.
Changed paths:
gui/options.cpp
diff --git a/gui/options.cpp b/gui/options.cpp
index 726b89d..ba247e5 100644
--- a/gui/options.cpp
+++ b/gui/options.cpp
@@ -445,11 +445,9 @@ void OptionsDialog::close() {
if (_oplPopUp) {
if (_enableAudioSettings) {
- const OPL::Config::EmulatorDescription *ed = OPL::Config::getAvailable();
- while (ed->name && ed->id != (int)_oplPopUp->getSelectedTag())
- ++ed;
+ const OPL::Config::EmulatorDescription *ed = OPL::Config::findDriver(_oplPopUp->getSelectedTag());
- if (ed->name)
+ if (ed)
ConfMan.set("opl_driver", ed->name, _domain);
else
ConfMan.removeKey("opl_driver", _domain);
Commit: f1f29302f5401c4782985cec4d47d069b99036ee
https://github.com/scummvm/scummvm/commit/f1f29302f5401c4782985cec4d47d069b99036ee
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-07-07T20:19:42-04:00
Commit Message:
AUDIO: Remove the legacy OPL API
Changed paths:
audio/fmopl.cpp
audio/fmopl.h
engines/cine/sound.cpp
engines/cruise/sound.cpp
engines/kyra/sound_adlib.cpp
engines/mads/nebular/sound_nebular.cpp
engines/mads/nebular/sound_nebular.h
engines/mads/sound.cpp
engines/mads/sound.h
engines/queen/midiadlib.cpp
engines/sky/music/adlibchannel.cpp
engines/sky/music/adlibchannel.h
engines/sky/music/adlibmusic.cpp
engines/sky/music/adlibmusic.h
engines/tsage/sound.cpp
engines/tsage/sound.h
diff --git a/audio/fmopl.cpp b/audio/fmopl.cpp
index 00e49ef..3ee5573 100644
--- a/audio/fmopl.cpp
+++ b/audio/fmopl.cpp
@@ -174,40 +174,3 @@ OPL *Config::create(DriverId driver, OplType type) {
bool OPL::_hasInstance = false;
} // End of namespace OPL
-
-void OPLDestroy(FM_OPL *OPL) {
- delete OPL;
-}
-
-void OPLResetChip(FM_OPL *OPL) {
- OPL->reset();
-}
-
-void OPLWrite(FM_OPL *OPL, int a, int v) {
- OPL->write(a, v);
-}
-
-unsigned char OPLRead(FM_OPL *OPL, int a) {
- return OPL->read(a);
-}
-
-void OPLWriteReg(FM_OPL *OPL, int r, int v) {
- OPL->writeReg(r, v);
-}
-
-void YM3812UpdateOne(FM_OPL *OPL, int16 *buffer, int length) {
- OPL->readBuffer(buffer, length);
-}
-
-FM_OPL *makeAdLibOPL(int rate) {
- FM_OPL *opl = OPL::Config::create();
-
- if (opl) {
- if (!opl->init(rate)) {
- delete opl;
- opl = 0;
- }
- }
-
- return opl;
-}
diff --git a/audio/fmopl.h b/audio/fmopl.h
index 28dd456..b8dbdc1 100644
--- a/audio/fmopl.h
+++ b/audio/fmopl.h
@@ -165,23 +165,4 @@ public:
} // End of namespace OPL
-// Legacy API
-// !You should not write any new code using the legacy API!
-typedef OPL::OPL FM_OPL;
-
-void OPLDestroy(FM_OPL *OPL);
-
-void OPLResetChip(FM_OPL *OPL);
-void OPLWrite(FM_OPL *OPL, int a, int v);
-unsigned char OPLRead(FM_OPL *OPL, int a);
-void OPLWriteReg(FM_OPL *OPL, int r, int v);
-void YM3812UpdateOne(FM_OPL *OPL, int16 *buffer, int length);
-
-/**
- * Legacy factory to create an AdLib (OPL2) chip.
- *
- * !You should not write any new code using the legacy API!
- */
-FM_OPL *makeAdLibOPL(int rate);
-
#endif
diff --git a/engines/cine/sound.cpp b/engines/cine/sound.cpp
index 069a478..8da6dba 100644
--- a/engines/cine/sound.cpp
+++ b/engines/cine/sound.cpp
@@ -128,7 +128,7 @@ protected:
UpdateCallback _upCb;
void *_upRef;
- FM_OPL *_opl;
+ OPL::OPL *_opl;
int _sampleRate;
Audio::Mixer *_mixer;
Audio::SoundHandle _soundHandle;
@@ -282,8 +282,12 @@ void PCSoundDriver::resetChannel(int channel) {
AdLibSoundDriver::AdLibSoundDriver(Audio::Mixer *mixer)
: _upCb(0), _upRef(0), _mixer(mixer) {
+
_sampleRate = _mixer->getOutputRate();
- _opl = makeAdLibOPL(_sampleRate);
+ _opl = OPL::Config::create();
+ if (!_opl || !_opl->init(_sampleRate))
+ error("Failed to create OPL");
+
memset(_channelsVolumeTable, 0, sizeof(_channelsVolumeTable));
memset(_instrumentsTable, 0, sizeof(_instrumentsTable));
initCard();
@@ -292,7 +296,7 @@ AdLibSoundDriver::AdLibSoundDriver(Audio::Mixer *mixer)
AdLibSoundDriver::~AdLibSoundDriver() {
_mixer->stopHandle(_soundHandle);
- OPLDestroy(_opl);
+ delete _opl;
}
void AdLibSoundDriver::setUpdateCallback(UpdateCallback upCb, void *ref) {
@@ -322,23 +326,23 @@ void AdLibSoundDriver::stopChannel(int channel) {
channel = 6;
}
if (ins->mode == 0 || channel == 6) {
- OPLWriteReg(_opl, 0xB0 | channel, 0);
+ _opl->writeReg(0xB0 | channel, 0);
}
if (ins->mode != 0) {
_vibrato &= ~(1 << (10 - ins->channel));
- OPLWriteReg(_opl, 0xBD, _vibrato);
+ _opl->writeReg(0xBD, _vibrato);
}
}
void AdLibSoundDriver::stopAll() {
int i;
for (i = 0; i < 18; ++i) {
- OPLWriteReg(_opl, 0x40 | _operatorsTable[i], 63);
+ _opl->writeReg(0x40 | _operatorsTable[i], 63);
}
for (i = 0; i < 9; ++i) {
- OPLWriteReg(_opl, 0xB0 | i, 0);
+ _opl->writeReg(0xB0 | i, 0);
}
- OPLWriteReg(_opl, 0xBD, 0);
+ _opl->writeReg(0xBD, 0);
}
int AdLibSoundDriver::readBuffer(int16 *buffer, const int numSamples) {
@@ -348,26 +352,26 @@ int AdLibSoundDriver::readBuffer(int16 *buffer, const int numSamples) {
void AdLibSoundDriver::initCard() {
_vibrato = 0x20;
- OPLWriteReg(_opl, 0xBD, _vibrato);
- OPLWriteReg(_opl, 0x08, 0x40);
+ _opl->writeReg(0xBD, _vibrato);
+ _opl->writeReg(0x08, 0x40);
static const int oplRegs[] = { 0x40, 0x60, 0x80, 0x20, 0xE0 };
for (int i = 0; i < 9; ++i) {
- OPLWriteReg(_opl, 0xB0 | i, 0);
+ _opl->writeReg(0xB0 | i, 0);
}
for (int i = 0; i < 9; ++i) {
- OPLWriteReg(_opl, 0xC0 | i, 0);
+ _opl->writeReg(0xC0 | i, 0);
}
for (int j = 0; j < 5; j++) {
for (int i = 0; i < 18; ++i) {
- OPLWriteReg(_opl, oplRegs[j] | _operatorsTable[i], 0);
+ _opl->writeReg(oplRegs[j] | _operatorsTable[i], 0);
}
}
- OPLWriteReg(_opl, 1, 0x20);
- OPLWriteReg(_opl, 1, 0);
+ _opl->writeReg(1, 0x20);
+ _opl->writeReg(1, 0);
}
void AdLibSoundDriver::update(int16 *buf, int len) {
@@ -379,7 +383,7 @@ void AdLibSoundDriver::update(int16 *buf, int len) {
}
samplesLeft -= count;
len -= count;
- YM3812UpdateOne(_opl, buf, count);
+ _opl->readBuffer(buf, count);
if (samplesLeft == 0) {
if (_upCb) {
(*_upCb)(_upRef);
@@ -408,32 +412,32 @@ void AdLibSoundDriver::setupInstrument(const byte *data, int channel) {
if (ins->mode == 0 || ins->channel == 6) {
reg = &ins->regMod;
- OPLWriteReg(_opl, 0x20 | mod, reg->vibrato);
+ _opl->writeReg(0x20 | mod, reg->vibrato);
if (reg->freqMod) {
tmp = reg->outputLevel & 0x3F;
} else {
tmp = (63 - (reg->outputLevel & 0x3F)) * _channelsVolumeTable[channel];
tmp = 63 - (2 * tmp + 127) / (2 * 127);
}
- OPLWriteReg(_opl, 0x40 | mod, tmp | (reg->keyScaling << 6));
- OPLWriteReg(_opl, 0x60 | mod, reg->attackDecay);
- OPLWriteReg(_opl, 0x80 | mod, reg->sustainRelease);
+ _opl->writeReg(0x40 | mod, tmp | (reg->keyScaling << 6));
+ _opl->writeReg(0x60 | mod, reg->attackDecay);
+ _opl->writeReg(0x80 | mod, reg->sustainRelease);
if (ins->mode != 0) {
- OPLWriteReg(_opl, 0xC0 | ins->channel, reg->feedbackStrength);
+ _opl->writeReg(0xC0 | ins->channel, reg->feedbackStrength);
} else {
- OPLWriteReg(_opl, 0xC0 | channel, reg->feedbackStrength);
+ _opl->writeReg(0xC0 | channel, reg->feedbackStrength);
}
- OPLWriteReg(_opl, 0xE0 | mod, ins->waveSelectMod);
+ _opl->writeReg(0xE0 | mod, ins->waveSelectMod);
}
reg = &ins->regCar;
- OPLWriteReg(_opl, 0x20 | car, reg->vibrato);
+ _opl->writeReg(0x20 | car, reg->vibrato);
tmp = (63 - (reg->outputLevel & 0x3F)) * _channelsVolumeTable[channel];
tmp = 63 - (2 * tmp + 127) / (2 * 127);
- OPLWriteReg(_opl, 0x40 | car, tmp | (reg->keyScaling << 6));
- OPLWriteReg(_opl, 0x60 | car, reg->attackDecay);
- OPLWriteReg(_opl, 0x80 | car, reg->sustainRelease);
- OPLWriteReg(_opl, 0xE0 | car, ins->waveSelectCar);
+ _opl->writeReg(0x40 | car, tmp | (reg->keyScaling << 6));
+ _opl->writeReg(0x60 | car, reg->attackDecay);
+ _opl->writeReg(0x80 | car, reg->sustainRelease);
+ _opl->writeReg(0xE0 | car, ins->waveSelectCar);
}
void AdLibSoundDriver::loadRegisterInstrument(const byte *data, AdLibRegisterSoundInstrument *reg) {
@@ -490,16 +494,16 @@ void AdLibSoundDriverINS::setChannelFrequency(int channel, int frequency) {
if (channel == 6)
oct = 0;
freq = _freqTable[note % 12];
- OPLWriteReg(_opl, 0xA0 | channel, freq);
+ _opl->writeReg(0xA0 | channel, freq);
freq = (oct << 2) | ((freq & 0x300) >> 8);
if (ins->mode == 0) {
freq |= 0x20;
}
- OPLWriteReg(_opl, 0xB0 | channel, freq);
+ _opl->writeReg(0xB0 | channel, freq);
}
if (ins->mode != 0) {
_vibrato |= 1 << (10 - ins->channel);
- OPLWriteReg(_opl, 0xBD, _vibrato);
+ _opl->writeReg(0xBD, _vibrato);
}
}
@@ -515,16 +519,16 @@ void AdLibSoundDriverINS::playSample(const byte *data, int size, int channel, in
if (ins->mode == 0 || channel == 6) {
uint16 note = 12;
int freq = _freqTable[note % 12];
- OPLWriteReg(_opl, 0xA0 | channel, freq);
+ _opl->writeReg(0xA0 | channel, freq);
freq = ((note / 12) << 2) | ((freq & 0x300) >> 8);
if (ins->mode == 0) {
freq |= 0x20;
}
- OPLWriteReg(_opl, 0xB0 | channel, freq);
+ _opl->writeReg(0xB0 | channel, freq);
}
if (ins->mode != 0) {
_vibrato |= 1 << (10 - ins->channel);
- OPLWriteReg(_opl, 0xBD, _vibrato);
+ _opl->writeReg(0xBD, _vibrato);
}
}
@@ -562,15 +566,15 @@ void AdLibSoundDriverADL::setChannelFrequency(int channel, int frequency) {
}
freq = _freqTable[note % 12];
- OPLWriteReg(_opl, 0xA0 | channel, freq);
+ _opl->writeReg(0xA0 | channel, freq);
freq = (oct << 2) | ((freq & 0x300) >> 8);
if (ins->mode == 0) {
freq |= 0x20;
}
- OPLWriteReg(_opl, 0xB0 | channel, freq);
+ _opl->writeReg(0xB0 | channel, freq);
if (ins->mode != 0) {
_vibrato |= 1 << (10 - channel);
- OPLWriteReg(_opl, 0xBD, _vibrato);
+ _opl->writeReg(0xBD, _vibrato);
}
}
@@ -580,11 +584,11 @@ void AdLibSoundDriverADL::playSample(const byte *data, int size, int channel, in
setupInstrument(data, channel);
AdLibSoundInstrument *ins = &_instrumentsTable[channel];
if (ins->mode != 0 && ins->channel == 6) {
- OPLWriteReg(_opl, 0xB0 | channel, 0);
+ _opl->writeReg(0xB0 | channel, 0);
}
if (ins->mode != 0) {
_vibrato &= ~(1 << (10 - ins->channel));
- OPLWriteReg(_opl, 0xBD, _vibrato);
+ _opl->writeReg(0xBD, _vibrato);
}
if (ins->mode != 0) {
channel = ins->channel;
@@ -599,15 +603,15 @@ void AdLibSoundDriverADL::playSample(const byte *data, int size, int channel, in
note = ins->amDepth;
}
int freq = _freqTable[note % 12];
- OPLWriteReg(_opl, 0xA0 | channel, freq);
+ _opl->writeReg(0xA0 | channel, freq);
freq = ((note / 12) << 2) | ((freq & 0x300) >> 8);
if (ins->mode == 0) {
freq |= 0x20;
}
- OPLWriteReg(_opl, 0xB0 | channel, freq);
+ _opl->writeReg(0xB0 | channel, freq);
if (ins->mode != 0) {
_vibrato |= 1 << (10 - channel);
- OPLWriteReg(_opl, 0xBD, _vibrato);
+ _opl->writeReg(0xBD, _vibrato);
}
}
diff --git a/engines/cruise/sound.cpp b/engines/cruise/sound.cpp
index 0b0fab8..0bf9bf7 100644
--- a/engines/cruise/sound.cpp
+++ b/engines/cruise/sound.cpp
@@ -135,7 +135,7 @@ public:
void adjustVolume(int channel, int volume);
protected:
- FM_OPL *_opl;
+ OPL::OPL *_opl;
int _sampleRate;
Audio::Mixer *_mixer;
Audio::SoundHandle _soundHandle;
@@ -303,7 +303,9 @@ void PCSoundDriver::syncSounds() {
AdLibSoundDriver::AdLibSoundDriver(Audio::Mixer *mixer)
: _mixer(mixer) {
_sampleRate = _mixer->getOutputRate();
- _opl = makeAdLibOPL(_sampleRate);
+ _opl = OPL::Config::create();
+ if (!_opl || !_opl->init(_sampleRate))
+ error("Failed to create OPL");
for (int i = 0; i < 5; ++i) {
_channelsVolumeTable[i].original = 0;
@@ -319,7 +321,7 @@ AdLibSoundDriver::AdLibSoundDriver(Audio::Mixer *mixer)
AdLibSoundDriver::~AdLibSoundDriver() {
_mixer->stopHandle(_soundHandle);
- OPLDestroy(_opl);
+ delete _opl;
}
void AdLibSoundDriver::syncSounds() {
@@ -368,22 +370,22 @@ void AdLibSoundDriver::stopChannel(int channel) {
channel = 6;
}
if (ins->mode == 0 || channel == 6) {
- OPLWriteReg(_opl, 0xB0 | channel, 0);
+ _opl->writeReg(0xB0 | channel, 0);
}
if (ins->mode != 0) {
_vibrato &= ~(1 << (10 - ins->channel));
- OPLWriteReg(_opl, 0xBD, _vibrato);
+ _opl->writeReg(0xBD, _vibrato);
}
}
void AdLibSoundDriver::stopAll() {
for (int i = 0; i < 18; ++i)
- OPLWriteReg(_opl, 0x40 | _operatorsTable[i], 63);
+ _opl->writeReg(0x40 | _operatorsTable[i], 63);
for (int i = 0; i < 9; ++i)
- OPLWriteReg(_opl, 0xB0 | i, 0);
+ _opl->writeReg(0xB0 | i, 0);
- OPLWriteReg(_opl, 0xBD, 0);
+ _opl->writeReg(0xBD, 0);
}
int AdLibSoundDriver::readBuffer(int16 *buffer, const int numSamples) {
@@ -393,26 +395,26 @@ int AdLibSoundDriver::readBuffer(int16 *buffer, const int numSamples) {
void AdLibSoundDriver::initCard() {
_vibrato = 0x20;
- OPLWriteReg(_opl, 0xBD, _vibrato);
- OPLWriteReg(_opl, 0x08, 0x40);
+ _opl->writeReg(0xBD, _vibrato);
+ _opl->writeReg(0x08, 0x40);
static const int oplRegs[] = { 0x40, 0x60, 0x80, 0x20, 0xE0 };
for (int i = 0; i < 9; ++i) {
- OPLWriteReg(_opl, 0xB0 | i, 0);
+ _opl->writeReg(0xB0 | i, 0);
}
for (int i = 0; i < 9; ++i) {
- OPLWriteReg(_opl, 0xC0 | i, 0);
+ _opl->writeReg(0xC0 | i, 0);
}
for (int j = 0; j < 5; j++) {
for (int i = 0; i < 18; ++i) {
- OPLWriteReg(_opl, oplRegs[j] | _operatorsTable[i], 0);
+ _opl->writeReg(oplRegs[j] | _operatorsTable[i], 0);
}
}
- OPLWriteReg(_opl, 1, 0x20);
- OPLWriteReg(_opl, 1, 0);
+ _opl->writeReg(1, 0x20);
+ _opl->writeReg(1, 0);
}
void AdLibSoundDriver::update(int16 *buf, int len) {
@@ -424,7 +426,7 @@ void AdLibSoundDriver::update(int16 *buf, int len) {
}
samplesLeft -= count;
len -= count;
- YM3812UpdateOne(_opl, buf, count);
+ _opl->readBuffer(buf, count);
if (samplesLeft == 0) {
if (_upCb) {
(*_upCb)(_upRef);
@@ -457,32 +459,32 @@ void AdLibSoundDriver::setupInstrument(const AdLibSoundInstrument *ins, int chan
if (ins->mode == 0 || ins->channel == 6) {
reg = &ins->regMod;
- OPLWriteReg(_opl, 0x20 | mod, reg->vibrato);
+ _opl->writeReg(0x20 | mod, reg->vibrato);
if (reg->freqMod) {
tmp = reg->outputLevel & 0x3F;
} else {
tmp = (63 - (reg->outputLevel & 0x3F)) * _channelsVolumeTable[channel].adjusted;
tmp = 63 - (2 * tmp + 127) / (2 * 127);
}
- OPLWriteReg(_opl, 0x40 | mod, tmp | (reg->keyScaling << 6));
- OPLWriteReg(_opl, 0x60 | mod, reg->attackDecay);
- OPLWriteReg(_opl, 0x80 | mod, reg->sustainRelease);
+ _opl->writeReg(0x40 | mod, tmp | (reg->keyScaling << 6));
+ _opl->writeReg(0x60 | mod, reg->attackDecay);
+ _opl->writeReg(0x80 | mod, reg->sustainRelease);
if (ins->mode != 0) {
- OPLWriteReg(_opl, 0xC0 | ins->channel, reg->feedbackStrength);
+ _opl->writeReg(0xC0 | ins->channel, reg->feedbackStrength);
} else {
- OPLWriteReg(_opl, 0xC0 | channel, reg->feedbackStrength);
+ _opl->writeReg(0xC0 | channel, reg->feedbackStrength);
}
- OPLWriteReg(_opl, 0xE0 | mod, ins->waveSelectMod);
+ _opl->writeReg(0xE0 | mod, ins->waveSelectMod);
}
reg = &ins->regCar;
- OPLWriteReg(_opl, 0x20 | car, reg->vibrato);
+ _opl->writeReg(0x20 | car, reg->vibrato);
tmp = (63 - (reg->outputLevel & 0x3F)) * _channelsVolumeTable[channel].adjusted;
tmp = 63 - (2 * tmp + 127) / (2 * 127);
- OPLWriteReg(_opl, 0x40 | car, tmp | (reg->keyScaling << 6));
- OPLWriteReg(_opl, 0x60 | car, reg->attackDecay);
- OPLWriteReg(_opl, 0x80 | car, reg->sustainRelease);
- OPLWriteReg(_opl, 0xE0 | car, ins->waveSelectCar);
+ _opl->writeReg(0x40 | car, tmp | (reg->keyScaling << 6));
+ _opl->writeReg(0x60 | car, reg->attackDecay);
+ _opl->writeReg(0x80 | car, reg->sustainRelease);
+ _opl->writeReg(0xE0 | car, ins->waveSelectCar);
}
void AdLibSoundDriver::loadRegisterInstrument(const byte *data, AdLibRegisterSoundInstrument *reg) {
@@ -551,15 +553,15 @@ void AdLibSoundDriverADL::setChannelFrequency(int channel, int frequency) {
}
freq = _freqTable[note % 12];
- OPLWriteReg(_opl, 0xA0 | channel, freq);
+ _opl->writeReg(0xA0 | channel, freq);
freq = ((note / 12) << 2) | ((freq & 0x300) >> 8);
if (ins->mode == 0) {
freq |= 0x20;
}
- OPLWriteReg(_opl, 0xB0 | channel, freq);
+ _opl->writeReg(0xB0 | channel, freq);
if (ins->mode != 0) {
_vibrato |= 1 << (10 - channel);
- OPLWriteReg(_opl, 0xBD, _vibrato);
+ _opl->writeReg(0xBD, _vibrato);
}
}
@@ -570,11 +572,11 @@ void AdLibSoundDriverADL::playSample(const byte *data, int size, int channel, in
setupInstrument(data, channel);
AdLibSoundInstrument *ins = &_instrumentsTable[channel];
if (ins->mode != 0 && ins->channel == 6) {
- OPLWriteReg(_opl, 0xB0 | channel, 0);
+ _opl->writeReg(0xB0 | channel, 0);
}
if (ins->mode != 0) {
_vibrato &= ~(1 << (10 - ins->channel));
- OPLWriteReg(_opl, 0xBD, _vibrato);
+ _opl->writeReg(0xBD, _vibrato);
}
if (ins->mode != 0) {
channel = ins->channel;
@@ -589,15 +591,15 @@ void AdLibSoundDriverADL::playSample(const byte *data, int size, int channel, in
note = ins->amDepth;
}
int freq = _freqTable[note % 12];
- OPLWriteReg(_opl, 0xA0 | channel, freq);
+ _opl->writeReg(0xA0 | channel, freq);
freq = ((note / 12) << 2) | ((freq & 0x300) >> 8);
if (ins->mode == 0) {
freq |= 0x20;
}
- OPLWriteReg(_opl, 0xB0 | channel, freq);
+ _opl->writeReg(0xB0 | channel, freq);
if (ins->mode != 0) {
_vibrato |= 1 << (10 - channel);
- OPLWriteReg(_opl, 0xBD, _vibrato);
+ _opl->writeReg(0xBD, _vibrato);
}
}
diff --git a/engines/kyra/sound_adlib.cpp b/engines/kyra/sound_adlib.cpp
index c0e0f67..203931f 100644
--- a/engines/kyra/sound_adlib.cpp
+++ b/engines/kyra/sound_adlib.cpp
@@ -88,7 +88,7 @@ public:
int32 render = MIN(samplesLeft, _samplesTillCallback);
samplesLeft -= render;
_samplesTillCallback -= render;
- YM3812UpdateOne(_adlib, buffer, render);
+ _adlib->readBuffer(buffer, render);
buffer += render;
}
return numSamples;
@@ -365,7 +365,7 @@ private:
uint8 _unkValue19;
uint8 _unkValue20;
- FM_OPL *_adlib;
+ OPL::OPL *_adlib;
uint8 *_soundData;
uint32 _soundDataSize;
@@ -427,8 +427,9 @@ AdLibDriver::AdLibDriver(Audio::Mixer *mixer, int version) {
_mixer = mixer;
- _adlib = makeAdLibOPL(getRate());
- assert(_adlib);
+ _adlib = OPL::Config::create();
+ if (!_adlib || !_adlib->init(getRate()))
+ error("Failed to create OPL");
memset(_channels, 0, sizeof(_channels));
_soundData = 0;
@@ -471,7 +472,7 @@ AdLibDriver::AdLibDriver(Audio::Mixer *mixer, int version) {
AdLibDriver::~AdLibDriver() {
_mixer->stopHandle(_soundHandle);
- OPLDestroy(_adlib);
+ delete _adlib;
_adlib = 0;
}
@@ -877,7 +878,7 @@ void AdLibDriver::resetAdLibState() {
// New calling style: writeOPL(0xAB, 0xCD)
void AdLibDriver::writeOPL(byte reg, byte val) {
- OPLWriteReg(_adlib, reg, val);
+ _adlib->writeReg(reg, val);
}
void AdLibDriver::initChannel(Channel &channel) {
diff --git a/engines/mads/nebular/sound_nebular.cpp b/engines/mads/nebular/sound_nebular.cpp
index 240c18f..b0a0938 100644
--- a/engines/mads/nebular/sound_nebular.cpp
+++ b/engines/mads/nebular/sound_nebular.cpp
@@ -21,6 +21,7 @@
*/
#include "audio/audiostream.h"
+#include "audio/fmopl.h"
#include "audio/decoders/raw.h"
#include "common/algorithm.h"
#include "common/debug.h"
@@ -156,7 +157,7 @@ AdlibSample::AdlibSample(Common::SeekableReadStream &s) {
/*-----------------------------------------------------------------------*/
-ASound::ASound(Audio::Mixer *mixer, FM_OPL *opl, const Common::String &filename, int dataOffset) {
+ASound::ASound(Audio::Mixer *mixer, OPL::OPL *opl, const Common::String &filename, int dataOffset) {
// Open up the appropriate sound file
if (!_soundFile.open(filename))
error("Could not open file - %s", filename.c_str());
@@ -984,7 +985,7 @@ const ASound1::CommandPtr ASound1::_commandList[42] = {
&ASound1::command40, &ASound1::command41
};
-ASound1::ASound1(Audio::Mixer *mixer, FM_OPL *opl)
+ASound1::ASound1(Audio::Mixer *mixer, OPL::OPL *opl)
: ASound(mixer, opl, "asound.001", 0x1520) {
_cmd23Toggle = false;
@@ -1285,7 +1286,7 @@ const ASound2::CommandPtr ASound2::_commandList[44] = {
&ASound2::command40, &ASound2::command41, &ASound2::command42, &ASound2::command43
};
-ASound2::ASound2(Audio::Mixer *mixer, FM_OPL *opl) : ASound(mixer, opl, "asound.002", 0x15E0) {
+ASound2::ASound2(Audio::Mixer *mixer, OPL::OPL *opl) : ASound(mixer, opl, "asound.002", 0x15E0) {
_command12Param = 0xFD;
// Load sound samples
@@ -1656,7 +1657,7 @@ const ASound3::CommandPtr ASound3::_commandList[61] = {
&ASound3::command60
};
-ASound3::ASound3(Audio::Mixer *mixer, FM_OPL *opl) : ASound(mixer, opl, "asound.003", 0x15B0) {
+ASound3::ASound3(Audio::Mixer *mixer, OPL::OPL *opl) : ASound(mixer, opl, "asound.003", 0x15B0) {
_command39Flag = false;
// Load sound samples
@@ -2060,7 +2061,7 @@ const ASound4::CommandPtr ASound4::_commandList[61] = {
&ASound4::command60
};
-ASound4::ASound4(Audio::Mixer *mixer, FM_OPL *opl) : ASound(mixer, opl, "asound.004", 0x14F0) {
+ASound4::ASound4(Audio::Mixer *mixer, OPL::OPL *opl) : ASound(mixer, opl, "asound.004", 0x14F0) {
// Load sound samples
_soundFile.seek(_dataOffset + 0x122);
for (int i = 0; i < 210; ++i)
@@ -2316,7 +2317,7 @@ const ASound5::CommandPtr ASound5::_commandList[42] = {
&ASound5::command40, &ASound5::command41
};
-ASound5::ASound5(Audio::Mixer *mixer, FM_OPL *opl) : ASound(mixer, opl, "asound.002", 0x15E0) {
+ASound5::ASound5(Audio::Mixer *mixer, OPL::OPL *opl) : ASound(mixer, opl, "asound.002", 0x15E0) {
// Load sound samples
_soundFile.seek(_dataOffset + 0x144);
for (int i = 0; i < 164; ++i)
@@ -2557,7 +2558,7 @@ const ASound6::CommandPtr ASound6::_commandList[30] = {
&ASound6::nullCommand, &ASound6::command29
};
-ASound6::ASound6(Audio::Mixer *mixer, FM_OPL *opl) : ASound(mixer, opl, "asound.006", 0x1390) {
+ASound6::ASound6(Audio::Mixer *mixer, OPL::OPL *opl) : ASound(mixer, opl, "asound.006", 0x1390) {
// Load sound samples
_soundFile.seek(_dataOffset + 0x122);
for (int i = 0; i < 200; ++i)
@@ -2713,7 +2714,7 @@ const ASound7::CommandPtr ASound7::_commandList[38] = {
&ASound7::command36, &ASound7::command37
};
-ASound7::ASound7(Audio::Mixer *mixer, FM_OPL *opl) : ASound(mixer, opl, "asound.007", 0x1460) {
+ASound7::ASound7(Audio::Mixer *mixer, OPL::OPL *opl) : ASound(mixer, opl, "asound.007", 0x1460) {
// Load sound samples
_soundFile.seek(_dataOffset + 0x122);
for (int i = 0; i < 214; ++i)
@@ -2919,7 +2920,7 @@ const ASound8::CommandPtr ASound8::_commandList[38] = {
&ASound8::command36, &ASound8::command37
};
-ASound8::ASound8(Audio::Mixer *mixer, FM_OPL *opl) : ASound(mixer, opl, "asound.008", 0x1490) {
+ASound8::ASound8(Audio::Mixer *mixer, OPL::OPL *opl) : ASound(mixer, opl, "asound.008", 0x1490) {
// Load sound samples
_soundFile.seek(_dataOffset + 0x122);
for (int i = 0; i < 174; ++i)
@@ -3175,7 +3176,7 @@ const ASound9::CommandPtr ASound9::_commandList[52] = {
&ASound9::command48, &ASound9::command49, &ASound9::command50, &ASound9::command51
};
-ASound9::ASound9(Audio::Mixer *mixer, FM_OPL *opl) : ASound(mixer, opl, "asound.009", 0x16F0) {
+ASound9::ASound9(Audio::Mixer *mixer, OPL::OPL *opl) : ASound(mixer, opl, "asound.009", 0x16F0) {
_v1 = _v2 = 0;
_soundPtr = nullptr;
diff --git a/engines/mads/nebular/sound_nebular.h b/engines/mads/nebular/sound_nebular.h
index 9bc1a49..e095632 100644
--- a/engines/mads/nebular/sound_nebular.h
+++ b/engines/mads/nebular/sound_nebular.h
@@ -28,9 +28,12 @@
#include "common/mutex.h"
#include "common/queue.h"
#include "audio/audiostream.h"
-#include "audio/fmopl.h"
#include "audio/mixer.h"
+namespace OPL {
+class OPL;
+}
+
namespace MADS {
class SoundManager;
@@ -273,7 +276,7 @@ protected:
int nullCommand() { return 0; }
public:
Audio::Mixer *_mixer;
- FM_OPL *_opl;
+ OPL::OPL *_opl;
Audio::SoundHandle _soundHandle;
AdlibChannel _channels[ADLIB_CHANNEL_COUNT];
AdlibChannel *_activeChannelPtr;
@@ -318,7 +321,7 @@ public:
* @param filename Specifies the adlib sound player file to use
* @param dataOffset Offset in the file of the data segment
*/
- ASound(Audio::Mixer *mixer, FM_OPL *opl, const Common::String &filename, int dataOffset);
+ ASound(Audio::Mixer *mixer, OPL::OPL *opl, const Common::String &filename, int dataOffset);
/**
* Destructor
@@ -433,7 +436,7 @@ private:
void command111213();
int command2627293032();
public:
- ASound1(Audio::Mixer *mixer, FM_OPL *opl);
+ ASound1(Audio::Mixer *mixer, OPL::OPL *opl);
virtual int command(int commandId, int param);
};
@@ -485,7 +488,7 @@ private:
void command9Randomize();
void command9Apply(byte *data, int val, int incr);
public:
- ASound2(Audio::Mixer *mixer, FM_OPL *opl);
+ ASound2(Audio::Mixer *mixer, OPL::OPL *opl);
virtual int command(int commandId, int param);
};
@@ -545,7 +548,7 @@ private:
void command9Randomize();
void command9Apply(byte *data, int val, int incr);
public:
- ASound3(Audio::Mixer *mixer, FM_OPL *opl);
+ ASound3(Audio::Mixer *mixer, OPL::OPL *opl);
virtual int command(int commandId, int param);
};
@@ -583,7 +586,7 @@ private:
void method1();
public:
- ASound4(Audio::Mixer *mixer, FM_OPL *opl);
+ ASound4(Audio::Mixer *mixer, OPL::OPL *opl);
virtual int command(int commandId, int param);
};
@@ -629,7 +632,7 @@ private:
int command42();
int command43();
public:
- ASound5(Audio::Mixer *mixer, FM_OPL *opl);
+ ASound5(Audio::Mixer *mixer, OPL::OPL *opl);
virtual int command(int commandId, int param);
};
@@ -658,7 +661,7 @@ private:
int command25();
int command29();
public:
- ASound6(Audio::Mixer *mixer, FM_OPL *opl);
+ ASound6(Audio::Mixer *mixer, OPL::OPL *opl);
virtual int command(int commandId, int param);
};
@@ -690,7 +693,7 @@ private:
int command36();
int command37();
public:
- ASound7(Audio::Mixer *mixer, FM_OPL *opl);
+ ASound7(Audio::Mixer *mixer, OPL::OPL *opl);
virtual int command(int commandId, int param);
};
@@ -733,7 +736,7 @@ private:
void method1(byte *pData);
void adjustRange(byte *pData, byte v, int incr);
public:
- ASound8(Audio::Mixer *mixer, FM_OPL *opl);
+ ASound8(Audio::Mixer *mixer, OPL::OPL *opl);
virtual int command(int commandId, int param);
};
@@ -792,7 +795,7 @@ private:
int command59();
int command60();
public:
- ASound9(Audio::Mixer *mixer, FM_OPL *opl);
+ ASound9(Audio::Mixer *mixer, OPL::OPL *opl);
virtual int command(int commandId, int param);
};
diff --git a/engines/mads/sound.cpp b/engines/mads/sound.cpp
index 7b9388e..09bc3a3 100644
--- a/engines/mads/sound.cpp
+++ b/engines/mads/sound.cpp
@@ -21,6 +21,7 @@
*/
#include "audio/audiostream.h"
+#include "audio/fmopl.h"
#include "audio/decoders/raw.h"
#include "common/memstream.h"
#include "mads/sound.h"
diff --git a/engines/mads/sound.h b/engines/mads/sound.h
index 16128f8..9882f65 100644
--- a/engines/mads/sound.h
+++ b/engines/mads/sound.h
@@ -37,7 +37,7 @@ class SoundManager {
private:
MADSEngine *_vm;
Audio::Mixer *_mixer;
- FM_OPL *_opl;
+ OPL::OPL *_opl;
Nebular::ASound *_driver;
bool _pollSoundEnabled;
bool _soundPollFlag;
diff --git a/engines/queen/midiadlib.cpp b/engines/queen/midiadlib.cpp
index 25175c2..6bf0d59 100644
--- a/engines/queen/midiadlib.cpp
+++ b/engines/queen/midiadlib.cpp
@@ -81,7 +81,7 @@ private:
void adlibSetChannel0x20(int channel);
void adlibSetChannel0xE0(int channel);
- FM_OPL *_opl;
+ OPL::OPL *_opl;
int _midiNumberOfChannels;
int _adlibNoteMul;
int _adlibWaveformSelect;
@@ -121,7 +121,10 @@ private:
int AdLibMidiDriver::open() {
MidiDriver_Emulated::open();
- _opl = makeAdLibOPL(getRate());
+ _opl = OPL::Config::create();
+ if (!_opl || !_opl->init(getRate()))
+ error("Failed to create OPL");
+
adlibSetupCard();
for (int i = 0; i < 11; ++i) {
_adlibChannelsVolume[i] = 0;
@@ -134,7 +137,7 @@ int AdLibMidiDriver::open() {
void AdLibMidiDriver::close() {
_mixer->stopHandle(_mixerSoundHandle);
- OPLDestroy(_opl);
+ delete _opl;
}
void AdLibMidiDriver::send(uint32 b) {
@@ -194,7 +197,7 @@ void AdLibMidiDriver::metaEvent(byte type, byte *data, uint16 length) {
void AdLibMidiDriver::generateSamples(int16 *data, int len) {
memset(data, 0, sizeof(int16) * len);
- YM3812UpdateOne(_opl, data, len);
+ _opl->readBuffer(data, len);
}
void AdLibMidiDriver::handleSequencerSpecificMetaEvent1(int channel, const uint8 *data) {
@@ -238,7 +241,7 @@ void AdLibMidiDriver::handleMidiEvent0x90_NoteOn(int channel, int param1, int pa
}
void AdLibMidiDriver::adlibWrite(uint8 port, uint8 value) {
- OPLWriteReg(_opl, port, value);
+ _opl->writeReg(port, value);
}
void AdLibMidiDriver::adlibSetupCard() {
diff --git a/engines/sky/music/adlibchannel.cpp b/engines/sky/music/adlibchannel.cpp
index 8400fef..b57f20f 100644
--- a/engines/sky/music/adlibchannel.cpp
+++ b/engines/sky/music/adlibchannel.cpp
@@ -29,7 +29,7 @@
namespace Sky {
-AdLibChannel::AdLibChannel(FM_OPL *opl, uint8 *pMusicData, uint16 startOfData) {
+AdLibChannel::AdLibChannel(OPL::OPL *opl, uint8 *pMusicData, uint16 startOfData) {
_opl = opl;
_musicData = pMusicData;
_channelData.loopPoint = startOfData;
@@ -95,7 +95,7 @@ void AdLibChannel::updateVolume(uint16 pVolume) {
*/
void AdLibChannel::setRegister(uint8 regNum, uint8 value) {
if (_adlibRegMirror[regNum] != value) {
- OPLWriteReg (_opl, regNum, value);
+ _opl->writeReg(regNum, value);
_adlibRegMirror[regNum] = value;
}
}
diff --git a/engines/sky/music/adlibchannel.h b/engines/sky/music/adlibchannel.h
index 80dae93..240dd5c 100644
--- a/engines/sky/music/adlibchannel.h
+++ b/engines/sky/music/adlibchannel.h
@@ -60,13 +60,13 @@ typedef struct {
class AdLibChannel : public ChannelBase {
public:
- AdLibChannel (FM_OPL *opl, uint8 *pMusicData, uint16 startOfData);
+ AdLibChannel (OPL::OPL *opl, uint8 *pMusicData, uint16 startOfData);
virtual ~AdLibChannel();
virtual uint8 process(uint16 aktTime);
virtual void updateVolume(uint16 pVolume);
virtual bool isActive();
private:
- FM_OPL *_opl;
+ OPL::OPL *_opl;
uint8 *_musicData;
AdLibChannelType _channelData;
diff --git a/engines/sky/music/adlibmusic.cpp b/engines/sky/music/adlibmusic.cpp
index dd64c5b..2b73cb1 100644
--- a/engines/sky/music/adlibmusic.cpp
+++ b/engines/sky/music/adlibmusic.cpp
@@ -22,6 +22,7 @@
#include "common/endian.h"
+#include "common/textconsole.h"
#include "sky/music/adlibmusic.h"
#include "sky/music/adlibchannel.h"
@@ -34,14 +35,16 @@ AdLibMusic::AdLibMusic(Audio::Mixer *pMixer, Disk *pDisk) : MusicBase(pMixer, pD
_driverFileBase = 60202;
_sampleRate = pMixer->getOutputRate();
- _opl = makeAdLibOPL(_sampleRate);
+ _opl = OPL::Config::create();
+ if (!_opl || !_opl->init(_sampleRate))
+ error("Failed to create OPL");
_mixer->playStream(Audio::Mixer::kMusicSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
}
AdLibMusic::~AdLibMusic() {
- OPLDestroy(_opl);
_mixer->stopHandle(_soundHandle);
+ delete _opl;
}
int AdLibMusic::readBuffer(int16 *data, const int numSamples) {
@@ -61,7 +64,7 @@ int AdLibMusic::readBuffer(int16 *data, const int numSamples) {
render = (remaining > _nextMusicPoll) ? _nextMusicPoll : remaining;
remaining -= render;
_nextMusicPoll -= render;
- YM3812UpdateOne(_opl, data, render);
+ _opl->readBuffer(data, render);
data += render;
if (_nextMusicPoll == 0) {
pollMusic();
@@ -102,7 +105,7 @@ void AdLibMusic::setupChannels(uint8 *channelData) {
void AdLibMusic::startDriver() {
uint16 cnt = 0;
while (_initSequence[cnt] || _initSequence[cnt + 1]) {
- OPLWriteReg (_opl, _initSequence[cnt], _initSequence[cnt + 1]);
+ _opl->writeReg(_initSequence[cnt], _initSequence[cnt + 1]);
cnt += 2;
}
}
diff --git a/engines/sky/music/adlibmusic.h b/engines/sky/music/adlibmusic.h
index 886eef0..9a0796d 100644
--- a/engines/sky/music/adlibmusic.h
+++ b/engines/sky/music/adlibmusic.h
@@ -25,7 +25,10 @@
#include "sky/music/musicbase.h"
#include "audio/audiostream.h"
-#include "audio/fmopl.h"
+
+namespace OPL {
+class OPL;
+}
namespace Sky {
@@ -42,7 +45,7 @@ public:
virtual void setVolume(uint16 param);
private:
- FM_OPL *_opl;
+ OPL::OPL *_opl;
Audio::SoundHandle _soundHandle;
uint8 *_initSequence;
uint32 _sampleRate, _nextMusicPoll;
diff --git a/engines/tsage/sound.cpp b/engines/tsage/sound.cpp
index b95b614..455b58d 100644
--- a/engines/tsage/sound.cpp
+++ b/engines/tsage/sound.cpp
@@ -20,9 +20,9 @@
*
*/
+#include "audio/fmopl.h"
#include "audio/decoders/raw.h"
#include "common/config-manager.h"
-#include "audio/decoders/raw.h"
#include "audio/audiostream.h"
#include "tsage/core.h"
#include "tsage/globals.h"
diff --git a/engines/tsage/sound.h b/engines/tsage/sound.h
index 49558b4..c222a6e 100644
--- a/engines/tsage/sound.h
+++ b/engines/tsage/sound.h
@@ -27,12 +27,15 @@
#include "common/mutex.h"
#include "common/queue.h"
#include "audio/audiostream.h"
-#include "audio/fmopl.h"
#include "audio/mixer.h"
#include "common/list.h"
#include "tsage/saveload.h"
#include "tsage/core.h"
+namespace OPL {
+class OPL;
+}
+
namespace TsAGE {
class Sound;
@@ -450,7 +453,7 @@ class AdlibSoundDriver: public SoundDriver, Audio::AudioStream {
private:
GroupData _groupData;
Audio::Mixer *_mixer;
- FM_OPL *_opl;
+ OPL::OPL *_opl;
Audio::SoundHandle _soundHandle;
int _sampleRate;
byte _portContents[256];
Commit: 2e8f9dcec93653f1bd1f115662f9fcf3a5581fd8
https://github.com/scummvm/scummvm/commit/2e8f9dcec93653f1bd1f115662f9fcf3a5581fd8
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-07-07T20:19:42-04:00
Commit Message:
AUDIO: Remove the sample rate configuration from the OPL code
Changed paths:
audio/fmopl.h
audio/miles_adlib.cpp
audio/softsynth/adlib.cpp
audio/softsynth/opl/dosbox.cpp
audio/softsynth/opl/dosbox.h
audio/softsynth/opl/mame.cpp
audio/softsynth/opl/mame.h
engines/agos/drivers/accolade/adlib.cpp
engines/cine/sound.cpp
engines/cruise/sound.cpp
engines/gob/sound/adlib.cpp
engines/kyra/sound_adlib.cpp
engines/mads/nebular/sound_nebular.cpp
engines/mads/nebular/sound_nebular.h
engines/mads/sound.cpp
engines/parallaction/adlib.cpp
engines/queen/midiadlib.cpp
engines/sci/sound/drivers/adlib.cpp
engines/scumm/players/player_ad.cpp
engines/sherlock/scalpel/drivers/adlib.cpp
engines/sky/music/adlibmusic.cpp
engines/tsage/sound.cpp
diff --git a/audio/fmopl.h b/audio/fmopl.h
index b8dbdc1..aaa8edd 100644
--- a/audio/fmopl.h
+++ b/audio/fmopl.h
@@ -108,10 +108,9 @@ public:
/**
* Initializes the OPL emulator.
*
- * @param rate output sample rate
* @return true on success, false on failure
*/
- virtual bool init(int rate) = 0;
+ virtual bool init() = 0;
/**
* Reinitializes the OPL emulator
diff --git a/audio/miles_adlib.cpp b/audio/miles_adlib.cpp
index 903b0a9..4560a81 100644
--- a/audio/miles_adlib.cpp
+++ b/audio/miles_adlib.cpp
@@ -298,8 +298,6 @@ MidiDriver_Miles_AdLib::~MidiDriver_Miles_AdLib() {
}
int MidiDriver_Miles_AdLib::open() {
- int rate = _mixer->getOutputRate();
-
if (_modeOPL3) {
// Try to create OPL3 first
_opl = OPL::Config::create(OPL::Config::kOpl3);
@@ -319,7 +317,7 @@ int MidiDriver_Miles_AdLib::open() {
return -1;
}
- _opl->init(rate);
+ _opl->init();
MidiDriver_Emulated::open();
diff --git a/audio/softsynth/adlib.cpp b/audio/softsynth/adlib.cpp
index 9851934..49e69ec 100644
--- a/audio/softsynth/adlib.cpp
+++ b/audio/softsynth/adlib.cpp
@@ -1434,7 +1434,7 @@ int MidiDriver_ADLIB::open() {
_opl3Mode = false;
}
#endif
- _opl->init(getRate());
+ _opl->init();
_regCache = (byte *)calloc(256, 1);
diff --git a/audio/softsynth/opl/dosbox.cpp b/audio/softsynth/opl/dosbox.cpp
index 5c3d833..bcc73a9 100644
--- a/audio/softsynth/opl/dosbox.cpp
+++ b/audio/softsynth/opl/dosbox.cpp
@@ -32,6 +32,7 @@
#include "dosbox.h"
#include "dbopl.h"
+#include "audio/mixer.h"
#include "common/system.h"
#include "common/scummsys.h"
#include "common/util.h"
@@ -156,7 +157,7 @@ void OPL::free() {
_emulator = 0;
}
-bool OPL::init(int rate) {
+bool OPL::init() {
free();
memset(&_reg, 0, sizeof(_reg));
@@ -167,19 +168,19 @@ bool OPL::init(int rate) {
return false;
DBOPL::InitTables();
- _emulator->Setup(rate);
+ _rate = g_system->getMixer()->getOutputRate();
+ _emulator->Setup(_rate);
if (_type == Config::kDualOpl2) {
// Setup opl3 mode in the hander
_emulator->WriteReg(0x105, 1);
}
- _rate = rate;
return true;
}
void OPL::reset() {
- init(_rate);
+ init();
}
void OPL::write(int port, int val) {
diff --git a/audio/softsynth/opl/dosbox.h b/audio/softsynth/opl/dosbox.h
index 513a49f..d3df6ba 100644
--- a/audio/softsynth/opl/dosbox.h
+++ b/audio/softsynth/opl/dosbox.h
@@ -87,7 +87,7 @@ public:
OPL(Config::OplType type);
~OPL();
- bool init(int rate);
+ bool init();
void reset();
void write(int a, int v);
diff --git a/audio/softsynth/opl/mame.cpp b/audio/softsynth/opl/mame.cpp
index da75ba7..1a5810f 100644
--- a/audio/softsynth/opl/mame.cpp
+++ b/audio/softsynth/opl/mame.cpp
@@ -31,6 +31,8 @@
#include "mame.h"
+#include "audio/mixer.h"
+#include "common/system.h"
#include "common/textconsole.h"
#include "common/util.h"
@@ -50,11 +52,11 @@ OPL::~OPL() {
_opl = 0;
}
-bool OPL::init(int rate) {
+bool OPL::init() {
if (_opl)
MAME::OPLDestroy(_opl);
- _opl = MAME::makeAdLibOPL(rate);
+ _opl = MAME::makeAdLibOPL(g_system->getMixer()->getOutputRate());
return (_opl != 0);
}
diff --git a/audio/softsynth/opl/mame.h b/audio/softsynth/opl/mame.h
index bd479d9..080cc6d 100644
--- a/audio/softsynth/opl/mame.h
+++ b/audio/softsynth/opl/mame.h
@@ -181,7 +181,7 @@ public:
OPL() : _opl(0) {}
~OPL();
- bool init(int rate);
+ bool init();
void reset();
void write(int a, int v);
diff --git a/engines/agos/drivers/accolade/adlib.cpp b/engines/agos/drivers/accolade/adlib.cpp
index 11edc7c..61f209b 100644
--- a/engines/agos/drivers/accolade/adlib.cpp
+++ b/engines/agos/drivers/accolade/adlib.cpp
@@ -213,8 +213,6 @@ MidiDriver_Accolade_AdLib::~MidiDriver_Accolade_AdLib() {
}
int MidiDriver_Accolade_AdLib::open() {
- int rate = _mixer->getOutputRate();
-
// debugC(kDebugLevelAdLibDriver, "AdLib: starting driver");
_opl = OPL::Config::create(OPL::Config::kOpl2);
@@ -222,7 +220,7 @@ int MidiDriver_Accolade_AdLib::open() {
if (!_opl)
return -1;
- _opl->init(rate);
+ _opl->init();
MidiDriver_Emulated::open();
diff --git a/engines/cine/sound.cpp b/engines/cine/sound.cpp
index 8da6dba..2ac0f91 100644
--- a/engines/cine/sound.cpp
+++ b/engines/cine/sound.cpp
@@ -285,7 +285,7 @@ AdLibSoundDriver::AdLibSoundDriver(Audio::Mixer *mixer)
_sampleRate = _mixer->getOutputRate();
_opl = OPL::Config::create();
- if (!_opl || !_opl->init(_sampleRate))
+ if (!_opl || !_opl->init())
error("Failed to create OPL");
memset(_channelsVolumeTable, 0, sizeof(_channelsVolumeTable));
diff --git a/engines/cruise/sound.cpp b/engines/cruise/sound.cpp
index 0bf9bf7..1f49604 100644
--- a/engines/cruise/sound.cpp
+++ b/engines/cruise/sound.cpp
@@ -304,7 +304,7 @@ AdLibSoundDriver::AdLibSoundDriver(Audio::Mixer *mixer)
: _mixer(mixer) {
_sampleRate = _mixer->getOutputRate();
_opl = OPL::Config::create();
- if (!_opl || !_opl->init(_sampleRate))
+ if (!_opl || !_opl->init())
error("Failed to create OPL");
for (int i = 0; i < 5; ++i) {
diff --git a/engines/gob/sound/adlib.cpp b/engines/gob/sound/adlib.cpp
index 65b43ca..b92e20b 100644
--- a/engines/gob/sound/adlib.cpp
+++ b/engines/gob/sound/adlib.cpp
@@ -136,7 +136,7 @@ void AdLib::createOPL() {
}
_opl = OPL::Config::create(OPL::Config::parse(oplDriver), OPL::Config::kOpl2);
- if (!_opl || !_opl->init(_rate)) {
+ if (!_opl || !_opl->init()) {
delete _opl;
error("Could not create an AdLib emulator");
diff --git a/engines/kyra/sound_adlib.cpp b/engines/kyra/sound_adlib.cpp
index 203931f..ad3395b 100644
--- a/engines/kyra/sound_adlib.cpp
+++ b/engines/kyra/sound_adlib.cpp
@@ -428,7 +428,7 @@ AdLibDriver::AdLibDriver(Audio::Mixer *mixer, int version) {
_mixer = mixer;
_adlib = OPL::Config::create();
- if (!_adlib || !_adlib->init(getRate()))
+ if (!_adlib || !_adlib->init())
error("Failed to create OPL");
memset(_channels, 0, sizeof(_channels));
diff --git a/engines/mads/nebular/sound_nebular.cpp b/engines/mads/nebular/sound_nebular.cpp
index b0a0938..10cbc73 100644
--- a/engines/mads/nebular/sound_nebular.cpp
+++ b/engines/mads/nebular/sound_nebular.cpp
@@ -211,7 +211,7 @@ ASound::ASound(Audio::Mixer *mixer, OPL::OPL *opl, const Common::String &filenam
_mixer = mixer;
_opl = opl;
- _opl->init(getRate());
+ _opl->init();
_mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1,
Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
@@ -861,6 +861,10 @@ int ASound::readBuffer(int16 *buffer, const int numSamples) {
return numSamples;
}
+int ASound::getRate() const {
+ return g_system->getMixer()->getOutputRate();
+}
+
void ASound::setVolume(int volume) {
_masterVolume = volume;
if (!volume)
diff --git a/engines/mads/nebular/sound_nebular.h b/engines/mads/nebular/sound_nebular.h
index e095632..8c1d7f8 100644
--- a/engines/mads/nebular/sound_nebular.h
+++ b/engines/mads/nebular/sound_nebular.h
@@ -385,7 +385,7 @@ public:
/**
* Return sample rate
*/
- virtual int getRate() const { return 11025; }
+ virtual int getRate() const;
/**
* Set the volume
diff --git a/engines/mads/sound.cpp b/engines/mads/sound.cpp
index 09bc3a3..4a35edb 100644
--- a/engines/mads/sound.cpp
+++ b/engines/mads/sound.cpp
@@ -40,7 +40,7 @@ SoundManager::SoundManager(MADSEngine *vm, Audio::Mixer *mixer) {
_masterVolume = 255;
_opl = OPL::Config::create();
- _opl->init(11025);
+ _opl->init();
// Validate sound files
switch (_vm->getGameID()) {
diff --git a/engines/parallaction/adlib.cpp b/engines/parallaction/adlib.cpp
index 7c1dd16..a2defa9 100644
--- a/engines/parallaction/adlib.cpp
+++ b/engines/parallaction/adlib.cpp
@@ -351,7 +351,7 @@ int AdLibDriver::open() {
MidiDriver_Emulated::open();
_opl = OPL::Config::create();
- _opl->init(getRate());
+ _opl->init();
_opl->writeReg(0x1, 0x20); // set bit 5 (enable all waveforms)
// Reset the OPL registers.
diff --git a/engines/queen/midiadlib.cpp b/engines/queen/midiadlib.cpp
index 6bf0d59..369ac99 100644
--- a/engines/queen/midiadlib.cpp
+++ b/engines/queen/midiadlib.cpp
@@ -122,7 +122,7 @@ private:
int AdLibMidiDriver::open() {
MidiDriver_Emulated::open();
_opl = OPL::Config::create();
- if (!_opl || !_opl->init(getRate()))
+ if (!_opl || !_opl->init())
error("Failed to create OPL");
adlibSetupCard();
diff --git a/engines/sci/sound/drivers/adlib.cpp b/engines/sci/sound/drivers/adlib.cpp
index fcfda2f..3c95381 100644
--- a/engines/sci/sound/drivers/adlib.cpp
+++ b/engines/sci/sound/drivers/adlib.cpp
@@ -215,8 +215,6 @@ static const int ym3812_note[13] = {
};
int MidiDriver_AdLib::openAdLib(bool isSCI0) {
- int rate = _mixer->getOutputRate();
-
_stereo = STEREO;
debug(3, "ADLIB: Starting driver in %s mode", (isSCI0 ? "SCI0" : "SCI1"));
@@ -233,7 +231,7 @@ int MidiDriver_AdLib::openAdLib(bool isSCI0) {
if (!_opl)
return -1;
- _opl->init(rate);
+ _opl->init();
setRegister(0xBD, 0);
setRegister(0x08, 0);
diff --git a/engines/scumm/players/player_ad.cpp b/engines/scumm/players/player_ad.cpp
index adcda68..b22180b 100644
--- a/engines/scumm/players/player_ad.cpp
+++ b/engines/scumm/players/player_ad.cpp
@@ -38,7 +38,7 @@ namespace Scumm {
Player_AD::Player_AD(ScummEngine *scumm, Audio::Mixer *mixer)
: _vm(scumm), _mixer(mixer), _rate(mixer->getOutputRate()) {
_opl2 = OPL::Config::create();
- if (!_opl2->init(_rate)) {
+ if (!_opl2->init()) {
error("Could not initialize OPL2 emulator");
}
diff --git a/engines/sherlock/scalpel/drivers/adlib.cpp b/engines/sherlock/scalpel/drivers/adlib.cpp
index 91641fc..3c5a655 100644
--- a/engines/sherlock/scalpel/drivers/adlib.cpp
+++ b/engines/sherlock/scalpel/drivers/adlib.cpp
@@ -285,8 +285,6 @@ private:
};
int MidiDriver_SH_AdLib::open() {
- int rate = _mixer->getOutputRate();
-
debugC(kDebugLevelAdLibDriver, "AdLib: starting driver");
_opl = OPL::Config::create(OPL::Config::kOpl2);
@@ -294,7 +292,7 @@ int MidiDriver_SH_AdLib::open() {
if (!_opl)
return -1;
- _opl->init(rate);
+ _opl->init();
MidiDriver_Emulated::open();
diff --git a/engines/sky/music/adlibmusic.cpp b/engines/sky/music/adlibmusic.cpp
index 2b73cb1..e410b3f 100644
--- a/engines/sky/music/adlibmusic.cpp
+++ b/engines/sky/music/adlibmusic.cpp
@@ -36,7 +36,7 @@ AdLibMusic::AdLibMusic(Audio::Mixer *pMixer, Disk *pDisk) : MusicBase(pMixer, pD
_sampleRate = pMixer->getOutputRate();
_opl = OPL::Config::create();
- if (!_opl || !_opl->init(_sampleRate))
+ if (!_opl || !_opl->init())
error("Failed to create OPL");
_mixer->playStream(Audio::Mixer::kMusicSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
diff --git a/engines/tsage/sound.cpp b/engines/tsage/sound.cpp
index 455b58d..6ff983e 100644
--- a/engines/tsage/sound.cpp
+++ b/engines/tsage/sound.cpp
@@ -2746,7 +2746,7 @@ AdlibSoundDriver::AdlibSoundDriver(): SoundDriver() {
_sampleRate = _mixer->getOutputRate();
_opl = OPL::Config::create();
assert(_opl);
- _opl->init(_sampleRate);
+ _opl->init();
_samplesTillCallback = 0;
_samplesTillCallbackRemainder = 0;
Commit: b9307ef1a4420ef61aa35c747d2f3f11875d3b72
https://github.com/scummvm/scummvm/commit/b9307ef1a4420ef61aa35c747d2f3f11875d3b72
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-07-07T20:19:42-04:00
Commit Message:
AUDIO: Introduce a callback to the OPL code
Currently unused, but ready to be hooked up to various classes using it.
Changed paths:
audio/fmopl.cpp
audio/fmopl.h
audio/softsynth/opl/dosbox.cpp
audio/softsynth/opl/dosbox.h
audio/softsynth/opl/mame.cpp
audio/softsynth/opl/mame.h
diff --git a/audio/fmopl.cpp b/audio/fmopl.cpp
index 3ee5573..c9cb104 100644
--- a/audio/fmopl.cpp
+++ b/audio/fmopl.cpp
@@ -22,10 +22,12 @@
#include "audio/fmopl.h"
+#include "audio/mixer.h"
#include "audio/softsynth/opl/dosbox.h"
#include "audio/softsynth/opl/mame.h"
#include "common/config-manager.h"
+#include "common/system.h"
#include "common/textconsole.h"
#include "common/translation.h"
@@ -171,6 +173,80 @@ OPL *Config::create(DriverId driver, OplType type) {
}
}
+void OPL::start(TimerCallback *callback, int timerFrequency) {
+ _callback.reset(callback);
+ startCallbacks(timerFrequency);
+}
+
+void OPL::stop() {
+ stopCallbacks();
+ _callback.reset();
+}
+
bool OPL::_hasInstance = false;
+EmulatedOPL::EmulatedOPL() :
+ _nextTick(0),
+ _samplesPerTick(0),
+ _baseFreq(0) {
+}
+
+EmulatedOPL::~EmulatedOPL() {
+ // Stop callbacks, just in case. If it's still playing at this
+ // point, there's probably a bigger issue, though.
+ stopCallbacks();
+}
+
+int EmulatedOPL::readBuffer(int16 *buffer, const int numSamples) {
+ const int stereoFactor = isStereo() ? 2 : 1;
+ int len = numSamples / stereoFactor;
+ int step;
+
+ do {
+ step = len;
+ if (step > (_nextTick >> FIXP_SHIFT))
+ step = (_nextTick >> FIXP_SHIFT);
+
+ generateSamples(buffer, step * stereoFactor);
+
+ _nextTick -= step << FIXP_SHIFT;
+ if (!(_nextTick >> FIXP_SHIFT)) {
+ if (_callback && _callback->isValid())
+ (*_callback)();
+
+ _nextTick += _samplesPerTick;
+ }
+
+ buffer += step * stereoFactor;
+ len -= step;
+ } while (len);
+
+ return numSamples;
+}
+
+int EmulatedOPL::getRate() const {
+ return g_system->getMixer()->getOutputRate();
+}
+
+void EmulatedOPL::startCallbacks(int timerFrequency) {
+ _baseFreq = timerFrequency;
+ assert(_baseFreq != 0);
+
+ int d = getRate() / _baseFreq;
+ int r = getRate() % _baseFreq;
+
+ // This is equivalent to (getRate() << FIXP_SHIFT) / BASE_FREQ
+ // but less prone to arithmetic overflow.
+
+ _samplesPerTick = (d << FIXP_SHIFT) + (r << FIXP_SHIFT) / _baseFreq;
+
+ // TODO: Eventually start mixer playback here
+ //g_system->getMixer()->playStream(Audio::Mixer::kPlainSoundType, _handle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
+}
+
+void EmulatedOPL::stopCallbacks() {
+ // TODO: Eventually stop mixer playback here
+ //g_system->getMixer()->stopHandle(*_handle);
+}
+
} // End of namespace OPL
diff --git a/audio/fmopl.h b/audio/fmopl.h
index aaa8edd..0e2e2b2 100644
--- a/audio/fmopl.h
+++ b/audio/fmopl.h
@@ -23,6 +23,8 @@
#ifndef AUDIO_FMOPL_H
#define AUDIO_FMOPL_H
+#include "common/func.h"
+#include "common/ptr.h"
#include "common/scummsys.h"
namespace Common {
@@ -98,6 +100,8 @@ private:
static const EmulatorDescription _drivers[];
};
+typedef Common::Functor0<void> TimerCallback;
+
class OPL {
private:
static bool _hasInstance;
@@ -154,12 +158,83 @@ public:
* So if you request 4 samples from a stereo OPL, you will get
* a total of two left channel and two right channel samples.
*/
- virtual void readBuffer(int16 *buffer, int length) = 0;
+ virtual int readBuffer(int16 *buffer, const int numSamples) = 0;
/**
* Returns whether the setup OPL mode is stereo or not
*/
virtual bool isStereo() const = 0;
+
+ /**
+ * Start the OPL with callbacks.
+ */
+ void start(TimerCallback *callback, int timerFrequency = kDefaultCallbackFrequency);
+
+ /**
+ * Stop the OPL
+ */
+ void stop();
+
+ enum {
+ /**
+ * The default callback frequency that start() uses
+ */
+ kDefaultCallbackFrequency = 250
+ };
+
+protected:
+ /**
+ * Start the callbacks.
+ */
+ virtual void startCallbacks(int timerFrequency) = 0;
+
+ /**
+ * Stop the callbacks.
+ */
+ virtual void stopCallbacks() = 0;
+
+ /**
+ * The functor for callbacks.
+ */
+ Common::ScopedPtr<TimerCallback> _callback;
+};
+
+class EmulatedOPL : public OPL {
+public:
+ EmulatedOPL();
+ virtual ~EmulatedOPL();
+
+ // OPL API
+ int readBuffer(int16 *buffer, const int numSamples);
+
+ int getRate() const;
+
+protected:
+ // OPL API
+ void startCallbacks(int timerFrequency);
+ void stopCallbacks();
+
+ /**
+ * Read up to 'length' samples.
+ *
+ * Data will be in native endianess, 16 bit per sample, signed.
+ * For stereo OPL, buffer will be filled with interleaved
+ * left and right channel samples, starting with a left sample.
+ * Furthermore, the samples in the left and right are summed up.
+ * So if you request 4 samples from a stereo OPL, you will get
+ * a total of two left channel and two right channel samples.
+ */
+ virtual void generateSamples(int16 *buffer, int numSamples) = 0;
+
+private:
+ int _baseFreq;
+
+ enum {
+ FIXP_SHIFT = 16
+ };
+
+ int _nextTick;
+ int _samplesPerTick;
};
} // End of namespace OPL
diff --git a/audio/softsynth/opl/dosbox.cpp b/audio/softsynth/opl/dosbox.cpp
index bcc73a9..f6f17c5 100644
--- a/audio/softsynth/opl/dosbox.cpp
+++ b/audio/softsynth/opl/dosbox.cpp
@@ -153,6 +153,7 @@ OPL::~OPL() {
}
void OPL::free() {
+ stopCallbacks();
delete _emulator;
_emulator = 0;
}
@@ -176,6 +177,9 @@ bool OPL::init() {
_emulator->WriteReg(0x105, 1);
}
+ // FIXME: Remove this once EmulatedOPL is actually controlling playback
+ start(0);
+
return true;
}
@@ -308,7 +312,7 @@ void OPL::dualWrite(uint8 index, uint8 reg, uint8 val) {
_emulator->WriteReg(fullReg, val);
}
-void OPL::readBuffer(int16 *buffer, int length) {
+void OPL::generateSamples(int16 *buffer, int length) {
// For stereo OPL cards, we divide the sample count by 2,
// to match stereo AudioStream behavior.
if (_type != Config::kOpl2)
diff --git a/audio/softsynth/opl/dosbox.h b/audio/softsynth/opl/dosbox.h
index d3df6ba..c52f067 100644
--- a/audio/softsynth/opl/dosbox.h
+++ b/audio/softsynth/opl/dosbox.h
@@ -69,7 +69,7 @@ namespace DBOPL {
struct Chip;
} // end of namespace DBOPL
-class OPL : public ::OPL::OPL {
+class OPL : public ::OPL::EmulatedOPL {
private:
Config::OplType _type;
uint _rate;
@@ -95,8 +95,10 @@ public:
void writeReg(int r, int v);
- void readBuffer(int16 *buffer, int length);
bool isStereo() const { return _type != Config::kOpl2; }
+
+protected:
+ void generateSamples(int16 *buffer, int length);
};
} // End of namespace DOSBox
diff --git a/audio/softsynth/opl/mame.cpp b/audio/softsynth/opl/mame.cpp
index 1a5810f..fe23d30 100644
--- a/audio/softsynth/opl/mame.cpp
+++ b/audio/softsynth/opl/mame.cpp
@@ -48,15 +48,22 @@ namespace OPL {
namespace MAME {
OPL::~OPL() {
+ stopCallbacks();
MAME::OPLDestroy(_opl);
_opl = 0;
}
bool OPL::init() {
- if (_opl)
+ if (_opl) {
+ stopCallbacks();
MAME::OPLDestroy(_opl);
+ }
_opl = MAME::makeAdLibOPL(g_system->getMixer()->getOutputRate());
+
+ // FIXME: Remove this once EmulatedOPL is actually controlling playback
+ start(0);
+
return (_opl != 0);
}
@@ -76,7 +83,7 @@ void OPL::writeReg(int r, int v) {
MAME::OPLWriteReg(_opl, r, v);
}
-void OPL::readBuffer(int16 *buffer, int length) {
+void OPL::generateSamples(int16 *buffer, int length) {
MAME::YM3812UpdateOne(_opl, buffer, length);
}
diff --git a/audio/softsynth/opl/mame.h b/audio/softsynth/opl/mame.h
index 080cc6d..67d80bb 100644
--- a/audio/softsynth/opl/mame.h
+++ b/audio/softsynth/opl/mame.h
@@ -174,7 +174,7 @@ void YM3812UpdateOne(FM_OPL *OPL, int16 *buffer, int length);
FM_OPL *makeAdLibOPL(int rate);
// OPL API implementation
-class OPL : public ::OPL::OPL {
+class OPL : public ::OPL::EmulatedOPL {
private:
FM_OPL *_opl;
public:
@@ -189,8 +189,10 @@ public:
void writeReg(int r, int v);
- void readBuffer(int16 *buffer, int length);
bool isStereo() const { return false; }
+
+protected:
+ void generateSamples(int16 *buffer, int length);
};
} // End of namespace MAME
Commit: 0bb13b358e1126f25bd8e6053da2b4343269252f
https://github.com/scummvm/scummvm/commit/0bb13b358e1126f25bd8e6053da2b4343269252f
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-07-07T20:19:42-04:00
Commit Message:
SCUMM: Use the built-in OPL timer for Player_AD
Changed paths:
engines/scumm/players/player_ad.cpp
engines/scumm/players/player_ad.h
diff --git a/engines/scumm/players/player_ad.cpp b/engines/scumm/players/player_ad.cpp
index b22180b..ea59a22 100644
--- a/engines/scumm/players/player_ad.cpp
+++ b/engines/scumm/players/player_ad.cpp
@@ -42,19 +42,12 @@ Player_AD::Player_AD(ScummEngine *scumm, Audio::Mixer *mixer)
error("Could not initialize OPL2 emulator");
}
- _samplesPerCallback = _rate / AD_CALLBACK_FREQUENCY;
- _samplesPerCallbackRemainder = _rate % AD_CALLBACK_FREQUENCY;
- _samplesTillCallback = 0;
- _samplesTillCallbackRemainder = 0;
-
memset(_registerBackUpTable, 0, sizeof(_registerBackUpTable));
writeReg(0x01, 0x00);
writeReg(0xBD, 0x00);
writeReg(0x08, 0x00);
writeReg(0x01, 0x20);
- _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
-
_engineMusicTimer = 0;
_soundPlaying = -1;
@@ -78,6 +71,9 @@ Player_AD::Player_AD(ScummEngine *scumm, Audio::Mixer *mixer)
_musicVolume = _sfxVolume = 255;
_isSeeking = false;
+
+ _opl2->start(new Common::Functor0Mem<void, Player_AD>(this, &Player_AD::onTimer), AD_CALLBACK_FREQUENCY);
+ _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
}
Player_AD::~Player_AD() {
@@ -244,36 +240,18 @@ void Player_AD::saveLoadWithSerializer(Serializer *ser) {
}
}
-int Player_AD::readBuffer(int16 *buffer, const int numSamples) {
+void Player_AD::onTimer() {
Common::StackLock lock(_mutex);
- int len = numSamples;
-
- while (len > 0) {
- if (!_samplesTillCallback) {
- if (_curOffset) {
- updateMusic();
- }
-
- updateSfx();
-
- _samplesTillCallback = _samplesPerCallback;
- _samplesTillCallbackRemainder += _samplesPerCallbackRemainder;
- if (_samplesTillCallbackRemainder >= AD_CALLBACK_FREQUENCY) {
- ++_samplesTillCallback;
- _samplesTillCallbackRemainder -= AD_CALLBACK_FREQUENCY;
- }
- }
-
- const int samplesToRead = MIN(len, _samplesTillCallback);
- _opl2->readBuffer(buffer, samplesToRead);
-
- buffer += samplesToRead;
- len -= samplesToRead;
- _samplesTillCallback -= samplesToRead;
+ if (_curOffset) {
+ updateMusic();
}
- return numSamples;
+ updateSfx();
+}
+
+int Player_AD::readBuffer(int16 *buffer, const int numSamples) {
+ return _opl2->readBuffer(buffer, numSamples);
}
void Player_AD::setupVolume() {
diff --git a/engines/scumm/players/player_ad.h b/engines/scumm/players/player_ad.h
index 63a8503..9662b08 100644
--- a/engines/scumm/players/player_ad.h
+++ b/engines/scumm/players/player_ad.h
@@ -62,6 +62,9 @@ public:
virtual bool endOfData() const { return false; }
virtual int getRate() const { return _rate; }
+ // Timer callback
+ void onTimer();
+
private:
ScummEngine *const _vm;
Common::Mutex _mutex;
@@ -75,11 +78,6 @@ private:
OPL::OPL *_opl2;
- int _samplesPerCallback;
- int _samplesPerCallbackRemainder;
- int _samplesTillCallback;
- int _samplesTillCallbackRemainder;
-
int _soundPlaying;
int32 _engineMusicTimer;
Commit: ed8830fcc807f9620185e143558f90f9b2cb8aea
https://github.com/scummvm/scummvm/commit/ed8830fcc807f9620185e143558f90f9b2cb8aea
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-07-07T20:19:43-04:00
Commit Message:
AUDIO: Use the built-in OPL timer for MidiDriver_ADLIB
Changed paths:
audio/softsynth/adlib.cpp
diff --git a/audio/softsynth/adlib.cpp b/audio/softsynth/adlib.cpp
index 49e69ec..c7b5297 100644
--- a/audio/softsynth/adlib.cpp
+++ b/audio/softsynth/adlib.cpp
@@ -948,9 +948,12 @@ public:
// AudioStream API
+ int readBuffer(int16 *data, const int numSamples);
bool isStereo() const { return _opl->isStereo(); }
int getRate() const { return _mixer->getOutputRate(); }
+ virtual void setTimerCallback(void *timerParam, Common::TimerManager::TimerProc timerProc);
+
private:
bool _scummSmallHeader; // FIXME: This flag controls a special mode for SCUMM V3 games
#ifdef ENABLE_OPL3
@@ -963,6 +966,9 @@ private:
byte *_regCacheSecondary;
#endif
+ Common::TimerManager::TimerProc _adlibTimerProc;
+ void *_adlibTimerParam;
+
int _timerCounter;
uint16 _channelTable2[9];
@@ -1403,6 +1409,8 @@ MidiDriver_ADLIB::MidiDriver_ADLIB(Audio::Mixer *mixer)
_timerIncrease = 0xD69;
_timerThreshold = 0x411B;
_opl = 0;
+ _adlibTimerProc = 0;
+ _adlibTimerParam = 0;
}
int MidiDriver_ADLIB::open() {
@@ -1452,6 +1460,7 @@ int MidiDriver_ADLIB::open() {
}
#endif
+ _opl->start(new Common::Functor0Mem<void, MidiDriver_ADLIB>(this, &MidiDriver_ADLIB::onTimer));
_mixer->playStream(Audio::Mixer::kPlainSoundType, &_mixerSoundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
return 0;
@@ -1617,13 +1626,17 @@ void MidiDriver_ADLIB::adlibWriteSecondary(byte reg, byte value) {
#endif
void MidiDriver_ADLIB::generateSamples(int16 *data, int len) {
- if (_opl->isStereo()) {
- len *= 2;
- }
- _opl->readBuffer(data, len);
+ // Dummy implementation until we no longer inherit from MidiDriver_Emulated
+}
+
+int MidiDriver_ADLIB::readBuffer(int16 *data, const int numSamples) {
+ return _opl->readBuffer(data, numSamples);
}
void MidiDriver_ADLIB::onTimer() {
+ if (_adlibTimerProc)
+ (*_adlibTimerProc)(_adlibTimerParam);
+
_timerCounter += _timerIncrease;
while (_timerCounter >= _timerThreshold) {
_timerCounter -= _timerThreshold;
@@ -1655,6 +1668,11 @@ void MidiDriver_ADLIB::onTimer() {
}
}
+void MidiDriver_ADLIB::setTimerCallback(void *timerParam, Common::TimerManager::TimerProc timerProc) {
+ _adlibTimerProc = timerProc;
+ _adlibTimerParam = timerParam;
+}
+
void MidiDriver_ADLIB::mcOff(AdLibVoice *voice) {
AdLibVoice *tmp;
Commit: 24add3c7457f5a13f659b9f2e5c8c8f46ef785c4
https://github.com/scummvm/scummvm/commit/24add3c7457f5a13f659b9f2e5c8c8f46ef785c4
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-07-07T20:19:43-04:00
Commit Message:
SCI: Use the built-in OPL timer
Changed paths:
engines/sci/sound/drivers/adlib.cpp
diff --git a/engines/sci/sound/drivers/adlib.cpp b/engines/sci/sound/drivers/adlib.cpp
index 3c95381..7035435 100644
--- a/engines/sci/sound/drivers/adlib.cpp
+++ b/engines/sci/sound/drivers/adlib.cpp
@@ -61,11 +61,15 @@ public:
MidiChannel *getPercussionChannel() { return NULL; }
// AudioStream
+ int readBuffer(int16 *data, const int numSamples);
bool isStereo() const { return _stereo; }
int getRate() const { return _mixer->getOutputRate(); }
// MidiDriver_Emulated
void generateSamples(int16 *buf, int len);
+ void setTimerCallback(void *timerParam, Common::TimerManager::TimerProc timerProc);
+
+ void onTimer();
void setVolume(byte volume);
void playSwitch(bool play);
@@ -140,6 +144,9 @@ private:
byte *_rhythmKeyMap;
Common::Array<AdLibPatch> _patches;
+ Common::TimerManager::TimerProc _adlibTimerProc;
+ void *_adlibTimerParam;
+
void loadInstrument(const byte *ins);
void voiceOn(int voice, int note, int velocity);
void voiceOff(int voice);
@@ -239,6 +246,7 @@ int MidiDriver_AdLib::openAdLib(bool isSCI0) {
MidiDriver_Emulated::open();
+ _opl->start(new Common::Functor0Mem<void, MidiDriver_AdLib>(this, &MidiDriver_AdLib::onTimer));
_mixer->playStream(Audio::Mixer::kPlainSoundType, &_mixerSoundHandle, this, -1, _mixer->kMaxChannelVolume, 0, DisposeAfterUse::NO);
return 0;
@@ -323,10 +331,22 @@ void MidiDriver_AdLib::send(uint32 b) {
}
}
+int MidiDriver_AdLib::readBuffer(int16 *data, const int numSamples) {
+ return _opl->readBuffer(data, numSamples);
+}
+
void MidiDriver_AdLib::generateSamples(int16 *data, int len) {
- if (isStereo())
- len <<= 1;
- _opl->readBuffer(data, len);
+ // Dummy implementation
+}
+
+void MidiDriver_AdLib::setTimerCallback(void *timerParam, Common::TimerManager::TimerProc timerProc) {
+ _adlibTimerProc = timerProc;
+ _adlibTimerParam = timerParam;
+}
+
+void MidiDriver_AdLib::onTimer() {
+ if (_adlibTimerProc)
+ (*_adlibTimerProc)(_adlibTimerParam);
// Increase the age of the notes
for (int i = 0; i < kVoices; i++) {
Commit: 984cd9b01875ae1cfcf6fb6fa12293e9e125a73b
https://github.com/scummvm/scummvm/commit/984cd9b01875ae1cfcf6fb6fa12293e9e125a73b
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-07-07T20:19:43-04:00
Commit Message:
CINE: Use the built-in OPL timer
Changed paths:
engines/cine/sound.cpp
diff --git a/engines/cine/sound.cpp b/engines/cine/sound.cpp
index 2ac0f91..a20ad5d 100644
--- a/engines/cine/sound.cpp
+++ b/engines/cine/sound.cpp
@@ -119,7 +119,7 @@ public:
virtual int getRate() const { return _sampleRate; }
void initCard();
- void update(int16 *buf, int len);
+ void onTimer();
void setupInstrument(const byte *data, int channel);
void loadRegisterInstrument(const byte *data, AdLibRegisterSoundInstrument *reg);
virtual void loadInstrument(const byte *data, AdLibSoundInstrument *asi) = 0;
@@ -291,6 +291,7 @@ AdLibSoundDriver::AdLibSoundDriver(Audio::Mixer *mixer)
memset(_channelsVolumeTable, 0, sizeof(_channelsVolumeTable));
memset(_instrumentsTable, 0, sizeof(_instrumentsTable));
initCard();
+ _opl->start(new Common::Functor0Mem<void, AdLibSoundDriver>(this, &AdLibSoundDriver::onTimer), 50);
_mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
}
@@ -346,8 +347,7 @@ void AdLibSoundDriver::stopAll() {
}
int AdLibSoundDriver::readBuffer(int16 *buffer, const int numSamples) {
- update(buffer, numSamples);
- return numSamples;
+ return _opl->readBuffer(buffer, numSamples);
}
void AdLibSoundDriver::initCard() {
@@ -374,23 +374,9 @@ void AdLibSoundDriver::initCard() {
_opl->writeReg(1, 0);
}
-void AdLibSoundDriver::update(int16 *buf, int len) {
- static int samplesLeft = 0;
- while (len != 0) {
- int count = samplesLeft;
- if (count > len) {
- count = len;
- }
- samplesLeft -= count;
- len -= count;
- _opl->readBuffer(buf, count);
- if (samplesLeft == 0) {
- if (_upCb) {
- (*_upCb)(_upRef);
- }
- samplesLeft = _sampleRate / 50;
- }
- buf += count;
+void AdLibSoundDriver::onTimer() {
+ if (_upCb) {
+ (*_upCb)(_upRef);
}
}
Commit: 3c7c217f4418d3ce9865f8950462a5e9dc0a9ef9
https://github.com/scummvm/scummvm/commit/3c7c217f4418d3ce9865f8950462a5e9dc0a9ef9
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-07-07T20:19:43-04:00
Commit Message:
CRUISE: Use the built-in OPL timer
Changed paths:
engines/cruise/sound.cpp
diff --git a/engines/cruise/sound.cpp b/engines/cruise/sound.cpp
index 1f49604..7d48e6e 100644
--- a/engines/cruise/sound.cpp
+++ b/engines/cruise/sound.cpp
@@ -125,7 +125,7 @@ public:
virtual int getRate() const { return _sampleRate; }
void initCard();
- void update(int16 *buf, int len);
+ void onTimer();
void setupInstrument(const byte *data, int channel);
void setupInstrument(const AdLibSoundInstrument *ins, int channel);
void loadRegisterInstrument(const byte *data, AdLibRegisterSoundInstrument *reg);
@@ -313,10 +313,12 @@ AdLibSoundDriver::AdLibSoundDriver(Audio::Mixer *mixer)
}
memset(_instrumentsTable, 0, sizeof(_instrumentsTable));
initCard();
- _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
_musicVolume = ConfMan.getBool("music_mute") ? 0 : MIN(255, ConfMan.getInt("music_volume"));
_sfxVolume = ConfMan.getBool("sfx_mute") ? 0 : MIN(255, ConfMan.getInt("sfx_volume"));
+
+ _opl->start(new Common::Functor0Mem<void, AdLibSoundDriver>(this, &AdLibSoundDriver::onTimer), 50);
+ _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
}
AdLibSoundDriver::~AdLibSoundDriver() {
@@ -389,8 +391,7 @@ void AdLibSoundDriver::stopAll() {
}
int AdLibSoundDriver::readBuffer(int16 *buffer, const int numSamples) {
- update(buffer, numSamples);
- return numSamples;
+ return _opl->readBuffer(buffer, numSamples);
}
void AdLibSoundDriver::initCard() {
@@ -417,23 +418,9 @@ void AdLibSoundDriver::initCard() {
_opl->writeReg(1, 0);
}
-void AdLibSoundDriver::update(int16 *buf, int len) {
- static int samplesLeft = 0;
- while (len != 0) {
- int count = samplesLeft;
- if (count > len) {
- count = len;
- }
- samplesLeft -= count;
- len -= count;
- _opl->readBuffer(buf, count);
- if (samplesLeft == 0) {
- if (_upCb) {
- (*_upCb)(_upRef);
- }
- samplesLeft = _sampleRate / 50;
- }
- buf += count;
+void AdLibSoundDriver::onTimer() {
+ if (_upCb) {
+ (*_upCb)(_upRef);
}
}
Commit: 5803dffead8cdf51bac64f00d095e5f5604d9e27
https://github.com/scummvm/scummvm/commit/5803dffead8cdf51bac64f00d095e5f5604d9e27
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-07-07T20:19:43-04:00
Commit Message:
KYRA: Use the built-in OPL timer
Changed paths:
engines/kyra/sound_adlib.cpp
diff --git a/engines/kyra/sound_adlib.cpp b/engines/kyra/sound_adlib.cpp
index ad3395b..999bd96 100644
--- a/engines/kyra/sound_adlib.cpp
+++ b/engines/kyra/sound_adlib.cpp
@@ -72,28 +72,10 @@ public:
// AudioStream API
int readBuffer(int16 *buffer, const int numSamples) {
- int32 samplesLeft = numSamples;
- memset(buffer, 0, sizeof(int16) * numSamples);
- while (samplesLeft) {
- if (!_samplesTillCallback) {
- callback();
- _samplesTillCallback = _samplesPerCallback;
- _samplesTillCallbackRemainder += _samplesPerCallbackRemainder;
- if (_samplesTillCallbackRemainder >= CALLBACKS_PER_SECOND) {
- _samplesTillCallback++;
- _samplesTillCallbackRemainder -= CALLBACKS_PER_SECOND;
- }
- }
-
- int32 render = MIN(samplesLeft, _samplesTillCallback);
- samplesLeft -= render;
- _samplesTillCallback -= render;
- _adlib->readBuffer(buffer, render);
- buffer += render;
- }
- return numSamples;
+ return _adlib->readBuffer(buffer, numSamples);
}
+
bool isStereo() const { return false; }
bool endOfData() const { return false; }
int getRate() const { return _mixer->getOutputRate(); }
@@ -334,11 +316,6 @@ private:
// _unkTable2_2[] - One of the tables in _unkTable2[]
// _unkTable2_3[] - One of the tables in _unkTable2[]
- int32 _samplesPerCallback;
- int32 _samplesPerCallbackRemainder;
- int32 _samplesTillCallback;
- int32 _samplesTillCallbackRemainder;
-
int _curChannel;
uint8 _soundTrigger;
@@ -452,13 +429,6 @@ AdLibDriver::AdLibDriver(Audio::Mixer *mixer, int version) {
_tablePtr1 = _tablePtr2 = 0;
- _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
-
- _samplesPerCallback = getRate() / CALLBACKS_PER_SECOND;
- _samplesPerCallbackRemainder = getRate() % CALLBACKS_PER_SECOND;
- _samplesTillCallback = 0;
- _samplesTillCallbackRemainder = 0;
-
_syncJumpMask = 0;
_musicVolume = 0;
@@ -468,6 +438,9 @@ AdLibDriver::AdLibDriver(Audio::Mixer *mixer, int version) {
_programQueueStart = _programQueueEnd = 0;
_retrySounds = false;
+
+ _adlib->start(new Common::Functor0Mem<void, AdLibDriver>(this, &AdLibDriver::callback), CALLBACKS_PER_SECOND);
+ _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
}
AdLibDriver::~AdLibDriver() {
Commit: b638efe0fad55e18513a9c0453100c0d3b9dd8c3
https://github.com/scummvm/scummvm/commit/b638efe0fad55e18513a9c0453100c0d3b9dd8c3
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-07-07T20:19:43-04:00
Commit Message:
PARALLACTION: Use the built-in OPL timer
Changed paths:
engines/parallaction/adlib.cpp
diff --git a/engines/parallaction/adlib.cpp b/engines/parallaction/adlib.cpp
index a2defa9..302530b 100644
--- a/engines/parallaction/adlib.cpp
+++ b/engines/parallaction/adlib.cpp
@@ -285,8 +285,13 @@ public:
bool isStereo() const { return false; }
int getRate() const { return _mixer->getOutputRate(); }
+ int readBuffer(int16 *data, const int numSamples);
- void generateSamples(int16 *buf, int len);
+ void generateSamples(int16 *buf, int len) {}
+ virtual void setTimerCallback(void *timerParam, Common::TimerManager::TimerProc timerProc) {
+ _adlibTimerProc = timerProc;
+ _adlibTimerParam = timerParam;
+ }
protected:
OPL::OPL *_opl;
@@ -320,6 +325,12 @@ protected:
void muteMelodicVoice(uint8 voice);
void initVoices();
+
+private:
+ void onTimer();
+
+ Common::TimerManager::TimerProc _adlibTimerProc;
+ void *_adlibTimerParam;
};
MidiDriver *createAdLibDriver() {
@@ -364,6 +375,7 @@ int AdLibDriver::open() {
initVoices();
+ _opl->start(new Common::Functor0Mem<void, AdLibDriver>(this, &AdLibDriver::onTimer));
_mixer->playStream(Audio::Mixer::kMusicSoundType, &_mixerSoundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
return 0;
}
@@ -777,9 +789,13 @@ MidiChannel *AdLibDriver::allocateChannel() {
return NULL;
}
-void AdLibDriver::generateSamples(int16 *buf, int len) {
- memset(buf, 0, sizeof(int16) * len);
- _opl->readBuffer(buf, len);
+int AdLibDriver::readBuffer(int16 *data, const int numSamples) {
+ return _opl->readBuffer(data, numSamples);
+}
+
+void AdLibDriver::onTimer() {
+ if (_adlibTimerProc)
+ (*_adlibTimerProc)(_adlibTimerParam);
}
void AdLibDriver::initVoices() {
Commit: b122ec279073a003ce4fb1dd0cd652e3393c18e0
https://github.com/scummvm/scummvm/commit/b122ec279073a003ce4fb1dd0cd652e3393c18e0
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-07-07T20:19:44-04:00
Commit Message:
SKY: Use the built-in OPL timer
Changed paths:
engines/sky/music/adlibmusic.cpp
engines/sky/music/adlibmusic.h
diff --git a/engines/sky/music/adlibmusic.cpp b/engines/sky/music/adlibmusic.cpp
index e410b3f..c13d615 100644
--- a/engines/sky/music/adlibmusic.cpp
+++ b/engines/sky/music/adlibmusic.cpp
@@ -39,6 +39,7 @@ AdLibMusic::AdLibMusic(Audio::Mixer *pMixer, Disk *pDisk) : MusicBase(pMixer, pD
if (!_opl || !_opl->init())
error("Failed to create OPL");
+ _opl->start(new Common::Functor0Mem<void, AdLibMusic>(this, &AdLibMusic::onTimer), 50);
_mixer->playStream(Audio::Mixer::kMusicSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
}
@@ -48,31 +49,12 @@ AdLibMusic::~AdLibMusic() {
}
int AdLibMusic::readBuffer(int16 *data, const int numSamples) {
- if (_musicData == NULL) {
- // no music loaded
- memset(data, 0, numSamples * sizeof(int16));
- } else if ((_currentMusic == 0) || (_numberOfChannels == 0)) {
- // music loaded but not played as of yet
- memset(data, 0, numSamples * sizeof(int16));
- // poll anyways as pollMusic() can activate the music
+ return _opl->readBuffer(data, numSamples);
+}
+
+void AdLibMusic::onTimer() {
+ if (_musicData != NULL)
pollMusic();
- _nextMusicPoll = _sampleRate / 50;
- } else {
- uint32 render;
- uint remaining = numSamples;
- while (remaining) {
- render = (remaining > _nextMusicPoll) ? _nextMusicPoll : remaining;
- remaining -= render;
- _nextMusicPoll -= render;
- _opl->readBuffer(data, render);
- data += render;
- if (_nextMusicPoll == 0) {
- pollMusic();
- _nextMusicPoll = _sampleRate / 50;
- }
- }
- }
- return numSamples;
}
void AdLibMusic::setupPointers() {
@@ -90,7 +72,6 @@ void AdLibMusic::setupPointers() {
_musicDataLoc = READ_LE_UINT16(_musicData + 0x1201);
_initSequence = _musicData + 0xE91;
}
- _nextMusicPoll = 0;
}
void AdLibMusic::setupChannels(uint8 *channelData) {
@@ -112,6 +93,7 @@ void AdLibMusic::startDriver() {
void AdLibMusic::setVolume(uint16 param) {
_musicVolume = param;
+ // FIXME: This is bad. There's no real volume control here.
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, 2 * param);
}
diff --git a/engines/sky/music/adlibmusic.h b/engines/sky/music/adlibmusic.h
index 9a0796d..fe2e5ac 100644
--- a/engines/sky/music/adlibmusic.h
+++ b/engines/sky/music/adlibmusic.h
@@ -48,12 +48,14 @@ private:
OPL::OPL *_opl;
Audio::SoundHandle _soundHandle;
uint8 *_initSequence;
- uint32 _sampleRate, _nextMusicPoll;
+ uint32 _sampleRate;
virtual void setupPointers();
virtual void setupChannels(uint8 *channelData);
virtual void startDriver();
void premixerCall(int16 *buf, uint len);
+
+ void onTimer();
};
} // End of namespace Sky
Commit: 4a4ad97fd3747f2bca749960e3e894cfc90c5f68
https://github.com/scummvm/scummvm/commit/4a4ad97fd3747f2bca749960e3e894cfc90c5f68
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-07-07T20:19:44-04:00
Commit Message:
QUEEN: Use the built-in OPL timer
Changed paths:
engines/queen/midiadlib.cpp
diff --git a/engines/queen/midiadlib.cpp b/engines/queen/midiadlib.cpp
index 369ac99..4797e5d 100644
--- a/engines/queen/midiadlib.cpp
+++ b/engines/queen/midiadlib.cpp
@@ -41,8 +41,10 @@ public:
void metaEvent(byte type, byte *data, uint16 length);
MidiChannel *allocateChannel() { return 0; }
MidiChannel *getPercussionChannel() { return 0; }
+ void setTimerCallback(void *timerParam, Common::TimerManager::TimerProc timerProc);
// AudioStream
+ int readBuffer(int16 *data, const int numSamples);
bool isStereo() const { return false; }
int getRate() const { return _mixer->getOutputRate(); }
@@ -81,6 +83,8 @@ private:
void adlibSetChannel0x20(int channel);
void adlibSetChannel0xE0(int channel);
+ void onTimer();
+
OPL::OPL *_opl;
int _midiNumberOfChannels;
int _adlibNoteMul;
@@ -100,6 +104,9 @@ private:
uint16 _adlibChannelsVolume[11];
uint16 _adlibMetaSequenceData[28];
+ Common::TimerManager::TimerProc _adlibTimerProc;
+ void *_adlibTimerParam;
+
static const uint8 _adlibChannelsMappingTable1[];
static const uint8 _adlibChannelsNoFeedback[];
static const uint8 _adlibChannelsMappingTable2[];
@@ -131,6 +138,8 @@ int AdLibMidiDriver::open() {
adlibSetNoteVolume(i, 0);
adlibTurnNoteOff(i);
}
+
+ _opl->start(new Common::Functor0Mem<void, AdLibMidiDriver>(this, &AdLibMidiDriver::onTimer));
_mixer->playStream(Audio::Mixer::kMusicSoundType, &_mixerSoundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
return 0;
}
@@ -196,8 +205,21 @@ void AdLibMidiDriver::metaEvent(byte type, byte *data, uint16 length) {
}
void AdLibMidiDriver::generateSamples(int16 *data, int len) {
- memset(data, 0, sizeof(int16) * len);
- _opl->readBuffer(data, len);
+ // Dummy implementation
+}
+
+int AdLibMidiDriver::readBuffer(int16 *data, const int numSamples) {
+ return _opl->readBuffer(data, numSamples);
+}
+
+void AdLibMidiDriver::setTimerCallback(void *timerParam, Common::TimerManager::TimerProc timerProc) {
+ _adlibTimerProc = timerProc;
+ _adlibTimerParam = timerParam;
+}
+
+void AdLibMidiDriver::onTimer() {
+ if (_adlibTimerProc)
+ (*_adlibTimerProc)(_adlibTimerParam);
}
void AdLibMidiDriver::handleSequencerSpecificMetaEvent1(int channel, const uint8 *data) {
Commit: 5024ae136a73d90b1d5a450aed0f990f226e3056
https://github.com/scummvm/scummvm/commit/5024ae136a73d90b1d5a450aed0f990f226e3056
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-07-07T20:19:44-04:00
Commit Message:
TSAGE: Use the built-in OPL timer
Changed paths:
engines/tsage/sound.cpp
engines/tsage/sound.h
diff --git a/engines/tsage/sound.cpp b/engines/tsage/sound.cpp
index 6ff983e..ddfaa0a 100644
--- a/engines/tsage/sound.cpp
+++ b/engines/tsage/sound.cpp
@@ -2748,13 +2748,6 @@ AdlibSoundDriver::AdlibSoundDriver(): SoundDriver() {
assert(_opl);
_opl->init();
- _samplesTillCallback = 0;
- _samplesTillCallbackRemainder = 0;
- _samplesPerCallback = getRate() / CALLBACKS_PER_SECOND;
- _samplesPerCallbackRemainder = getRate() % CALLBACKS_PER_SECOND;
-
- _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
-
Common::fill(_channelVoiced, _channelVoiced + ADLIB_CHANNEL_COUNT, false);
memset(_channelVolume, 0, ADLIB_CHANNEL_COUNT * sizeof(int));
memset(_v4405E, 0, ADLIB_CHANNEL_COUNT * sizeof(int));
@@ -2772,6 +2765,9 @@ AdlibSoundDriver::AdlibSoundDriver(): SoundDriver() {
_channelVoiced[i] = false;
_pitchBlend[i] = 0;
}
+
+ _opl->start(new Common::Functor0Mem<void, AdlibSoundDriver>(this, &AdlibSoundDriver::onTimer), CALLBACKS_PER_SECOND);
+ _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
}
AdlibSoundDriver::~AdlibSoundDriver() {
@@ -3019,33 +3015,16 @@ void AdlibSoundDriver::setFrequency(int channel) {
((dataWord >> 8) & 3) | (var2 << 2));
}
-int AdlibSoundDriver::readBuffer(int16 *buffer, const int numSamples) {
+int AdlibSoundDriver::readBuffer(int16 *data, const int numSamples) {
+ return _opl->readBuffer(data, numSamples);
+}
+
+void AdlibSoundDriver::onTimer() {
Common::StackLock slock1(SoundManager::sfManager()._serverDisabledMutex);
Common::StackLock slock2(SoundManager::sfManager()._serverSuspendedMutex);
- int32 samplesLeft = numSamples;
- memset(buffer, 0, sizeof(int16) * numSamples);
- while (samplesLeft) {
- if (!_samplesTillCallback) {
- SoundManager::sfUpdateCallback(NULL);
- flush();
-
- _samplesTillCallback = _samplesPerCallback;
- _samplesTillCallbackRemainder += _samplesPerCallbackRemainder;
- if (_samplesTillCallbackRemainder >= CALLBACKS_PER_SECOND) {
- _samplesTillCallback++;
- _samplesTillCallbackRemainder -= CALLBACKS_PER_SECOND;
- }
- }
-
- int32 render = MIN<int>(samplesLeft, _samplesTillCallback);
- samplesLeft -= render;
- _samplesTillCallback -= render;
-
- _opl->readBuffer(buffer, render);
- buffer += render;
- }
- return numSamples;
+ SoundManager::sfUpdateCallback(NULL);
+ flush();
}
/*--------------------------------------------------------------------------*/
diff --git a/engines/tsage/sound.h b/engines/tsage/sound.h
index c222a6e..7ea1e65 100644
--- a/engines/tsage/sound.h
+++ b/engines/tsage/sound.h
@@ -460,10 +460,6 @@ private:
const byte *_patchData;
int _masterVolume;
Common::Queue<RegisterValue> _queue;
- int _samplesTillCallback;
- int _samplesTillCallbackRemainder;
- int _samplesPerCallback;
- int _samplesPerCallbackRemainder;
bool _channelVoiced[ADLIB_CHANNEL_COUNT];
int _channelVolume[ADLIB_CHANNEL_COUNT];
@@ -499,12 +495,13 @@ public:
virtual void setPitch(int channel, int pitchBlend);
// AudioStream interface
- virtual int readBuffer(int16 *buffer, const int numSamples);
+ virtual int readBuffer(int16 *data, const int numSamples);
virtual bool isStereo() const { return false; }
virtual bool endOfData() const { return false; }
virtual int getRate() const { return _sampleRate; }
- void update(int16 *buf, int len);
+private:
+ void onTimer();
};
class SoundBlasterDriver: public SoundDriver {
Commit: 4c6724c5faabad1618e5d538ec27a1c334ed4c6e
https://github.com/scummvm/scummvm/commit/4c6724c5faabad1618e5d538ec27a1c334ed4c6e
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-07-07T20:19:44-04:00
Commit Message:
MADS: Use the built-in OPL timer
Changed paths:
engines/mads/nebular/sound_nebular.cpp
engines/mads/nebular/sound_nebular.h
diff --git a/engines/mads/nebular/sound_nebular.cpp b/engines/mads/nebular/sound_nebular.cpp
index 10cbc73..0a1c1ea 100644
--- a/engines/mads/nebular/sound_nebular.cpp
+++ b/engines/mads/nebular/sound_nebular.cpp
@@ -189,11 +189,6 @@ ASound::ASound(Audio::Mixer *mixer, OPL::OPL *opl, const Common::String &filenam
_randomSeed = 1234;
_amDep = _vibDep = _splitPoint = true;
- _samplesTillCallback = 0;
- _samplesTillCallbackRemainder = 0;
- _samplesPerCallback = getRate() / CALLBACKS_PER_SECOND;
- _samplesPerCallbackRemainder = getRate() % CALLBACKS_PER_SECOND;
-
for (int i = 0; i < 11; ++i) {
_channelData[i]._field0 = 0;
_channelData[i]._freqMask = 0;
@@ -211,15 +206,15 @@ ASound::ASound(Audio::Mixer *mixer, OPL::OPL *opl, const Common::String &filenam
_mixer = mixer;
_opl = opl;
- _opl->init();
- _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1,
- Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
-
// Initialize the Adlib
adlibInit();
// Reset the adlib
command0();
+
+ _opl->start(new Common::Functor0Mem<void, ASound>(this, &ASound::onTimer), CALLBACKS_PER_SECOND);
+ _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1,
+ Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
}
ASound::~ASound() {
@@ -833,32 +828,14 @@ void ASound::updateFNumber() {
write2(8, hiReg, val2);
}
-int ASound::readBuffer(int16 *buffer, const int numSamples) {
- Common::StackLock slock(_driverMutex);
-
- int32 samplesLeft = numSamples;
- memset(buffer, 0, sizeof(int16) * numSamples);
- while (samplesLeft) {
- if (!_samplesTillCallback) {
- poll();
- flush();
-
- _samplesTillCallback = _samplesPerCallback;
- _samplesTillCallbackRemainder += _samplesPerCallbackRemainder;
- if (_samplesTillCallbackRemainder >= CALLBACKS_PER_SECOND) {
- _samplesTillCallback++;
- _samplesTillCallbackRemainder -= CALLBACKS_PER_SECOND;
- }
- }
-
- int32 render = MIN<int>(samplesLeft, _samplesTillCallback);
- samplesLeft -= render;
- _samplesTillCallback -= render;
+int ASound::readBuffer(int16 *data, const int numSamples) {
+ return _opl->readBuffer(data, numSamples);
+}
- _opl->readBuffer(buffer, render);
- buffer += render;
- }
- return numSamples;
+void ASound::onTimer() {
+ Common::StackLock slock(_driverMutex);
+ poll();
+ flush();
}
int ASound::getRate() const {
diff --git a/engines/mads/nebular/sound_nebular.h b/engines/mads/nebular/sound_nebular.h
index 8c1d7f8..1267914 100644
--- a/engines/mads/nebular/sound_nebular.h
+++ b/engines/mads/nebular/sound_nebular.h
@@ -195,6 +195,11 @@ private:
void processSample();
void updateFNumber();
+
+ /**
+ * Timer function for OPL
+ */
+ void onTimer();
protected:
int _commandParam;
@@ -309,10 +314,6 @@ public:
int _activeChannelReg;
int _v11;
bool _amDep, _vibDep, _splitPoint;
- int _samplesPerCallback;
- int _samplesPerCallbackRemainder;
- int _samplesTillCallback;
- int _samplesTillCallbackRemainder;
public:
/**
* Constructor
Commit: cc6e304af1b7021c7ee471f55c0674dac1bfb253
https://github.com/scummvm/scummvm/commit/cc6e304af1b7021c7ee471f55c0674dac1bfb253
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-07-07T20:19:44-04:00
Commit Message:
AUDIO: Limit the DOSBox start(0) hack to only being called once
Changed paths:
audio/softsynth/opl/dosbox.cpp
diff --git a/audio/softsynth/opl/dosbox.cpp b/audio/softsynth/opl/dosbox.cpp
index f6f17c5..09200c7 100644
--- a/audio/softsynth/opl/dosbox.cpp
+++ b/audio/softsynth/opl/dosbox.cpp
@@ -178,7 +178,8 @@ bool OPL::init() {
}
// FIXME: Remove this once EmulatedOPL is actually controlling playback
- start(0);
+ if (!_callback)
+ start(0);
return true;
}
Commit: 5b06eef1597ce701a4f6d16854be077b952d29f7
https://github.com/scummvm/scummvm/commit/5b06eef1597ce701a4f6d16854be077b952d29f7
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-07-07T20:19:44-04:00
Commit Message:
AUDIO: Allow for changing the OPL timer rate
Changed paths:
audio/fmopl.cpp
audio/fmopl.h
diff --git a/audio/fmopl.cpp b/audio/fmopl.cpp
index c9cb104..07c5b44 100644
--- a/audio/fmopl.cpp
+++ b/audio/fmopl.cpp
@@ -183,6 +183,14 @@ void OPL::stop() {
_callback.reset();
}
+void OPL::setCallbackFrequency(int timerFrequency) {
+ if (!isRunning())
+ return;
+
+ stopCallbacks();
+ startCallbacks(timerFrequency);
+}
+
bool OPL::_hasInstance = false;
EmulatedOPL::EmulatedOPL() :
@@ -249,4 +257,10 @@ void EmulatedOPL::stopCallbacks() {
//g_system->getMixer()->stopHandle(*_handle);
}
+bool EmulatedOPL::isRunning() const {
+ // TODO
+ //return g_system->getMixer()->isSoundHandleActive(*_handle);
+ return true;
+}
+
} // End of namespace OPL
diff --git a/audio/fmopl.h b/audio/fmopl.h
index 0e2e2b2..243cd29 100644
--- a/audio/fmopl.h
+++ b/audio/fmopl.h
@@ -175,6 +175,17 @@ public:
*/
void stop();
+ /**
+ * Is the OPL running?
+ */
+ virtual bool isRunning() const = 0;
+
+ /**
+ * Change the callback frequency. This has no effect if start()
+ * has not already been called.
+ */
+ void setCallbackFrequency(int timerFrequency);
+
enum {
/**
* The default callback frequency that start() uses
@@ -206,6 +217,7 @@ public:
// OPL API
int readBuffer(int16 *buffer, const int numSamples);
+ bool isRunning() const;
int getRate() const;
Commit: 73e8ac2a9b51fc4d278c87677b815f1f6c308775
https://github.com/scummvm/scummvm/commit/73e8ac2a9b51fc4d278c87677b815f1f6c308775
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-07-07T20:19:45-04:00
Commit Message:
GOB: Use the built-in OPL timer
Changed paths:
engines/gob/sound/adlib.cpp
engines/gob/sound/adlib.h
engines/gob/sound/adlplayer.cpp
engines/gob/sound/adlplayer.h
engines/gob/sound/musplayer.cpp
engines/gob/sound/musplayer.h
diff --git a/engines/gob/sound/adlib.cpp b/engines/gob/sound/adlib.cpp
index b92e20b..20fbced 100644
--- a/engines/gob/sound/adlib.cpp
+++ b/engines/gob/sound/adlib.cpp
@@ -93,7 +93,7 @@ const uint16 AdLib::kHihatParams [kParamCount] = {
0, 1, 0, 15, 11, 0, 7, 5, 0, 0, 0, 0, 0, 0 };
-AdLib::AdLib(Audio::Mixer &mixer) : _mixer(&mixer), _opl(0),
+AdLib::AdLib(Audio::Mixer &mixer, int callbackFreq) : _mixer(&mixer), _opl(0),
_toPoll(0), _repCount(0), _first(true), _playing(false), _ended(true) {
_rate = _mixer->getOutputRate();
@@ -103,6 +103,7 @@ AdLib::AdLib(Audio::Mixer &mixer) : _mixer(&mixer), _opl(0),
createOPL();
initOPL();
+ _opl->start(new Common::Functor0Mem<void, AdLib>(this, &AdLib::onTimer), callbackFreq);
_mixer->playStream(Audio::Mixer::kMusicSoundType, &_handle,
this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
}
@@ -144,38 +145,34 @@ void AdLib::createOPL() {
}
int AdLib::readBuffer(int16 *buffer, const int numSamples) {
+ return _opl->readBuffer(buffer, numSamples);
+}
+
+void AdLib::onTimer() {
Common::StackLock slock(_mutex);
- // Nothing to do, fill with silence
- if (!_playing) {
- memset(buffer, 0, numSamples * sizeof(int16));
- return numSamples;
+ // Nothing to do
+ if (!_playing)
+ return;
+
+ // Check if there's anything to do on this step
+ // If not, decrease the poll number and move on
+ if (_toPoll > 0) {
+ _toPoll--;
+ return;
}
- // Read samples from the OPL, polling in more music when necessary
- uint32 samples = numSamples;
- while (samples && _playing) {
- if (_toPoll) {
- const uint32 render = MIN(samples, _toPoll);
-
- _opl->readBuffer(buffer, render);
-
- buffer += render;
- samples -= render;
- _toPoll -= render;
-
- } else {
- // Song ended, fill the rest with silence
- if (_ended) {
- memset(buffer, 0, samples * sizeof(int16));
- samples = 0;
- break;
- }
-
- // Poll more music
- _toPoll = pollMusic(_first);
- _first = false;
+ // Poll until we have to delay until the next poll
+ while (_toPoll == 0 && _playing) {
+ // Song ended, break out
+ if (_ended) {
+ _toPoll = 0;
+ break;
}
+
+ // Poll more music
+ _toPoll = pollMusic(_first);
+ _first = false;
}
// Song ended, loop if requested
@@ -195,8 +192,6 @@ int AdLib::readBuffer(int16 *buffer, const int numSamples) {
} else
_playing = false;
}
-
- return numSamples;
}
bool AdLib::isStereo() const {
@@ -204,7 +199,7 @@ bool AdLib::isStereo() const {
}
bool AdLib::endOfData() const {
- return !_playing;
+ return false;
}
bool AdLib::endOfStream() const {
@@ -231,10 +226,6 @@ void AdLib::setRepeating(int32 repCount) {
_repCount = repCount;
}
-uint32 AdLib::getSamplesPerSecond() const {
- return _rate * (isStereo() ? 2 : 1);
-}
-
void AdLib::startPlay() {
Common::StackLock slock(_mutex);
@@ -639,4 +630,8 @@ void AdLib::setFreq(uint8 voice, uint16 note, bool on) {
writeOPL(0xB0 + voice, value);
}
+void AdLib::setTimerFrequency(int timerFrequency) {
+ _opl->setCallbackFrequency(timerFrequency);
+}
+
} // End of namespace Gob
diff --git a/engines/gob/sound/adlib.h b/engines/gob/sound/adlib.h
index 8071249..6a62152 100644
--- a/engines/gob/sound/adlib.h
+++ b/engines/gob/sound/adlib.h
@@ -37,7 +37,7 @@ namespace Gob {
/** Base class for a player of an AdLib music format. */
class AdLib : public Audio::AudioStream {
public:
- AdLib(Audio::Mixer &mixer);
+ AdLib(Audio::Mixer &mixer, int callbackFrequency);
virtual ~AdLib();
bool isPlaying() const; ///< Are we currently playing?
@@ -120,8 +120,6 @@ protected:
static const int kOPLMidC = 48; ///< A mid C for the OPL.
- /** Return the number of samples per second. */
- uint32 getSamplesPerSecond() const;
/** Write a value into an OPL register. */
void writeOPL(byte reg, byte val);
@@ -135,7 +133,7 @@ protected:
/** The callback function that's called for polling more AdLib commands.
*
* @param first Is this the first poll since the start of the song?
- * @return The number of samples until the next poll.
+ * @return The number of ticks until the next poll.
*/
virtual uint32 pollMusic(bool first) = 0;
@@ -207,6 +205,11 @@ protected:
/** Switch a voice off. */
void noteOff(uint8 voice);
+ /**
+ * Set the OPL timer frequency
+ */
+ void setTimerFrequency(int timerFrequency);
+
private:
static const uint8 kOperatorType [kOperatorCount];
static const uint8 kOperatorOffset[kOperatorCount];
@@ -300,6 +303,11 @@ private:
void changePitch(uint8 voice, uint16 pitchBend);
void setFreq(uint8 voice, uint16 note, bool on);
+
+ /**
+ * Callback function for OPL
+ */
+ void onTimer();
};
} // End of namespace Gob
diff --git a/engines/gob/sound/adlplayer.cpp b/engines/gob/sound/adlplayer.cpp
index 384a928..e5a2760 100644
--- a/engines/gob/sound/adlplayer.cpp
+++ b/engines/gob/sound/adlplayer.cpp
@@ -28,7 +28,7 @@
namespace Gob {
-ADLPlayer::ADLPlayer(Audio::Mixer &mixer) : AdLib(mixer),
+ADLPlayer::ADLPlayer(Audio::Mixer &mixer) : AdLib(mixer, 1000),
_songData(0), _songDataSize(0), _playPos(0) {
}
@@ -135,14 +135,7 @@ uint32 ADLPlayer::pollMusic(bool first) {
if (delay & 0x80)
delay = ((delay & 3) << 8) | *_playPos++;
- return getSampleDelay(delay);
-}
-
-uint32 ADLPlayer::getSampleDelay(uint16 delay) const {
- if (delay == 0)
- return 0;
-
- return ((uint32)delay * getSamplesPerSecond()) / 1000;
+ return delay;
}
void ADLPlayer::rewind() {
diff --git a/engines/gob/sound/adlplayer.h b/engines/gob/sound/adlplayer.h
index 3edd238..bd43cc0 100644
--- a/engines/gob/sound/adlplayer.h
+++ b/engines/gob/sound/adlplayer.h
@@ -76,8 +76,6 @@ private:
bool readHeader (Common::SeekableReadStream &adl, int &timbreCount);
bool readTimbres (Common::SeekableReadStream &adl, int timbreCount);
bool readSongData(Common::SeekableReadStream &adl);
-
- uint32 getSampleDelay(uint16 delay) const;
};
} // End of namespace Gob
diff --git a/engines/gob/sound/musplayer.cpp b/engines/gob/sound/musplayer.cpp
index 7001a57..bf90d44 100644
--- a/engines/gob/sound/musplayer.cpp
+++ b/engines/gob/sound/musplayer.cpp
@@ -27,7 +27,7 @@
namespace Gob {
-MUSPlayer::MUSPlayer(Audio::Mixer &mixer) : AdLib(mixer),
+MUSPlayer::MUSPlayer(Audio::Mixer &mixer) : AdLib(mixer, 60),
_songData(0), _songDataSize(0), _playPos(0), _songID(0) {
}
@@ -43,15 +43,6 @@ void MUSPlayer::unload() {
unloadMUS();
}
-uint32 MUSPlayer::getSampleDelay(uint16 delay) const {
- if (delay == 0)
- return 0;
-
- uint32 freq = (_ticksPerBeat * _tempo) / 60;
-
- return ((uint32)delay * getSamplesPerSecond()) / freq;
-}
-
void MUSPlayer::skipToTiming() {
while (*_playPos < 0x80)
_playPos++;
@@ -67,7 +58,7 @@ uint32 MUSPlayer::pollMusic(bool first) {
}
if (first)
- return getSampleDelay(*_playPos++);
+ return *_playPos++;
uint16 delay = 0;
while (delay == 0) {
@@ -100,6 +91,7 @@ uint32 MUSPlayer::pollMusic(bool first) {
uint32 denom = *_playPos++;
_tempo = _baseTempo * num + ((_baseTempo * denom) >> 7);
+ setTimerFrequency((_ticksPerBeat * _tempo) / 60);
_playPos++;
} else {
@@ -182,7 +174,7 @@ uint32 MUSPlayer::pollMusic(bool first) {
delay += *_playPos++;
}
- return getSampleDelay(delay);
+ return delay;
}
void MUSPlayer::rewind() {
@@ -193,6 +185,8 @@ void MUSPlayer::rewind() {
setPercussionMode(_soundMode != 0);
setPitchRange(_pitchBendRange);
+
+ setTimerFrequency((_ticksPerBeat * _tempo) / 60);
}
bool MUSPlayer::loadSND(Common::SeekableReadStream &snd) {
diff --git a/engines/gob/sound/musplayer.h b/engines/gob/sound/musplayer.h
index c76c5aa..7c1189b 100644
--- a/engines/gob/sound/musplayer.h
+++ b/engines/gob/sound/musplayer.h
@@ -97,7 +97,6 @@ private:
bool readMUSHeader(Common::SeekableReadStream &mus);
bool readMUSSong (Common::SeekableReadStream &mus);
- uint32 getSampleDelay(uint16 delay) const;
void setInstrument(uint8 voice, uint8 instrument);
void skipToTiming();
Commit: dcb75fcaf12ebf194e0b68e841c3eee9739e4d1e
https://github.com/scummvm/scummvm/commit/dcb75fcaf12ebf194e0b68e841c3eee9739e4d1e
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-07-07T20:19:45-04:00
Commit Message:
SHERLOCK: Use the built-in OPL timer
Changed paths:
engines/sherlock/scalpel/drivers/adlib.cpp
diff --git a/engines/sherlock/scalpel/drivers/adlib.cpp b/engines/sherlock/scalpel/drivers/adlib.cpp
index 3c5a655..033b474 100644
--- a/engines/sherlock/scalpel/drivers/adlib.cpp
+++ b/engines/sherlock/scalpel/drivers/adlib.cpp
@@ -219,7 +219,8 @@ uint16 frequencyLookUpTable[SHERLOCK_ADLIB_NOTES_COUNT] = {
class MidiDriver_SH_AdLib : public MidiDriver_Emulated {
public:
MidiDriver_SH_AdLib(Audio::Mixer *mixer)
- : MidiDriver_Emulated(mixer), _masterVolume(15), _opl(0) {
+ : MidiDriver_Emulated(mixer), _masterVolume(15), _opl(0),
+ _adlibTimerProc(0), _adlibTimerParam(0) {
memset(_voiceChannelMapping, 0, sizeof(_voiceChannelMapping));
}
virtual ~MidiDriver_SH_AdLib() { }
@@ -232,6 +233,7 @@ public:
MidiChannel *getPercussionChannel() { return NULL; }
// AudioStream
+ int readBuffer(int16 *data, const int numSamples);
bool isStereo() const { return false; }
int getRate() const { return _mixer->getOutputRate(); }
int getPolyphony() const { return SHERLOCK_ADLIB_VOICES_COUNT; }
@@ -240,6 +242,8 @@ public:
// MidiDriver_Emulated
void generateSamples(int16 *buf, int len);
+ virtual void setTimerCallback(void *timerParam, Common::TimerManager::TimerProc timerProc);
+
void setVolume(byte volume);
virtual uint32 property(int prop, uint32 param);
@@ -261,16 +265,17 @@ private:
OPL::OPL *_opl;
int _masterVolume;
+ Common::TimerManager::TimerProc _adlibTimerProc;
+ void *_adlibTimerParam;
+
// points to a MIDI channel for each of the new voice channels
byte _voiceChannelMapping[SHERLOCK_ADLIB_VOICES_COUNT];
// stores information about all FM voice channels
adlib_ChannelEntry _channels[SHERLOCK_ADLIB_VOICES_COUNT];
-protected:
void onTimer();
-private:
void resetAdLib();
void resetAdLibOperatorRegisters(byte baseRegister, byte value);
void resetAdLibFMVoiceChannelRegisters(byte baseRegister, byte value);
@@ -296,6 +301,7 @@ int MidiDriver_SH_AdLib::open() {
MidiDriver_Emulated::open();
+ _opl->start(new Common::Functor0Mem<void, MidiDriver_SH_AdLib>(this, &MidiDriver_SH_AdLib::onTimer));
_mixer->playStream(Audio::Mixer::kPlainSoundType, &_mixerSoundHandle, this, -1, _mixer->kMaxChannelVolume, 0, DisposeAfterUse::NO);
return 0;
@@ -316,6 +322,12 @@ void MidiDriver_SH_AdLib::setVolume(byte volume) {
// original driver did this before MIDI data processing on each tick
// we do it atm after MIDI data processing
void MidiDriver_SH_AdLib::onTimer() {
+ if (_adlibTimerProc)
+ (*_adlibTimerProc)(_adlibTimerParam);
+
+ // this should/must get called per tick
+ // original driver did this before MIDI data processing on each tick
+ // we do it atm after MIDI data processing
for (byte FMvoiceChannel = 0; FMvoiceChannel < SHERLOCK_ADLIB_VOICES_COUNT; FMvoiceChannel++) {
if (_channels[FMvoiceChannel].inUse) {
_channels[FMvoiceChannel].inUseTimer++;
@@ -416,7 +428,11 @@ void MidiDriver_SH_AdLib::send(uint32 b) {
}
void MidiDriver_SH_AdLib::generateSamples(int16 *data, int len) {
- _opl->readBuffer(data, len);
+ // Dummy implementation until we no longer inherit from MidiDriver_Emulated
+}
+
+int MidiDriver_SH_AdLib::readBuffer(int16 *data, const int numSamples) {
+ return _opl->readBuffer(data, numSamples);
}
void MidiDriver_SH_AdLib::noteOn(byte MIDIchannel, byte note, byte velocity) {
@@ -625,6 +641,11 @@ uint32 MidiDriver_SH_AdLib::property(int prop, uint32 param) {
return 0;
}
+void MidiDriver_SH_AdLib::setTimerCallback(void *timerParam, Common::TimerManager::TimerProc timerProc) {
+ _adlibTimerProc = timerProc;
+ _adlibTimerParam = timerParam;
+}
+
MidiDriver *MidiDriver_SH_AdLib_create() {
return new MidiDriver_SH_AdLib(g_system->getMixer());
}
Commit: 0c5d40e94c6f10d63763a72c70d06fe2fa15de29
https://github.com/scummvm/scummvm/commit/0c5d40e94c6f10d63763a72c70d06fe2fa15de29
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-07-07T20:19:45-04:00
Commit Message:
AGOS: Use the built-in OPL timer
Changed paths:
engines/agos/drivers/accolade/adlib.cpp
diff --git a/engines/agos/drivers/accolade/adlib.cpp b/engines/agos/drivers/accolade/adlib.cpp
index 61f209b..33a7595 100644
--- a/engines/agos/drivers/accolade/adlib.cpp
+++ b/engines/agos/drivers/accolade/adlib.cpp
@@ -125,6 +125,7 @@ public:
MidiChannel *getPercussionChannel() { return NULL; }
// AudioStream
+ int readBuffer(int16 *data, const int numSamples);
bool isStereo() const { return false; }
int getRate() const { return _mixer->getOutputRate(); }
int getPolyphony() const { return AGOS_ADLIB_VOICES_COUNT; }
@@ -138,6 +139,8 @@ public:
bool setupInstruments(byte *instrumentData, uint16 instrumentDataSize, bool useMusicDrvFile);
+ void setTimerCallback(void *timerParam, Common::TimerManager::TimerProc timerProc);
+
private:
bool _musicDrvMode;
@@ -170,16 +173,17 @@ private:
OPL::OPL *_opl;
int _masterVolume;
+ Common::TimerManager::TimerProc _adlibTimerProc;
+ void *_adlibTimerParam;
+
// points to a MIDI channel for each of the new voice channels
byte _voiceChannelMapping[AGOS_ADLIB_VOICES_COUNT];
// stores information about all FM voice channels
ChannelEntry _channels[AGOS_ADLIB_VOICES_COUNT];
-protected:
void onTimer();
-private:
void resetAdLib();
void resetAdLibOperatorRegisters(byte baseRegister, byte value);
void resetAdLibFMVoiceChannelRegisters(byte baseRegister, byte value);
@@ -193,7 +197,8 @@ private:
};
MidiDriver_Accolade_AdLib::MidiDriver_Accolade_AdLib(Audio::Mixer *mixer)
- : MidiDriver_Emulated(mixer), _masterVolume(15), _opl(0) {
+ : MidiDriver_Emulated(mixer), _masterVolume(15), _opl(0),
+ _adlibTimerProc(0), _adlibTimerParam(0) {
memset(_channelMapping, 0, sizeof(_channelMapping));
memset(_instrumentMapping, 0, sizeof(_instrumentMapping));
memset(_instrumentVolumeAdjust, 0, sizeof(_instrumentVolumeAdjust));
@@ -224,6 +229,7 @@ int MidiDriver_Accolade_AdLib::open() {
MidiDriver_Emulated::open();
+ _opl->start(new Common::Functor0Mem<void, MidiDriver_Accolade_AdLib>(this, &MidiDriver_Accolade_AdLib::onTimer));
_mixer->playStream(Audio::Mixer::kPlainSoundType, &_mixerSoundHandle, this, -1, _mixer->kMaxChannelVolume, 0, DisposeAfterUse::NO);
resetAdLib();
@@ -269,6 +275,8 @@ void MidiDriver_Accolade_AdLib::setVolume(byte volume) {
}
void MidiDriver_Accolade_AdLib::onTimer() {
+ if (_adlibTimerProc)
+ (*_adlibTimerProc)(_adlibTimerParam);
}
void MidiDriver_Accolade_AdLib::resetAdLib() {
@@ -367,7 +375,16 @@ void MidiDriver_Accolade_AdLib::send(uint32 b) {
}
void MidiDriver_Accolade_AdLib::generateSamples(int16 *data, int len) {
- _opl->readBuffer(data, len);
+ // Dummy implementation until we no longer inherit from MidiDriver_Emulated
+}
+
+int MidiDriver_Accolade_AdLib::readBuffer(int16 *data, const int numSamples) {
+ return _opl->readBuffer(data, numSamples);
+}
+
+void MidiDriver_Accolade_AdLib::setTimerCallback(void *timerParam, Common::TimerManager::TimerProc timerProc) {
+ _adlibTimerProc = timerProc;
+ _adlibTimerParam = timerParam;
}
void MidiDriver_Accolade_AdLib::noteOn(byte FMvoiceChannel, byte note, byte velocity) {
Commit: 22d985f3c265162419ab8c65dd47b48ac385f463
https://github.com/scummvm/scummvm/commit/22d985f3c265162419ab8c65dd47b48ac385f463
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-07-07T20:19:45-04:00
Commit Message:
AUDIO: Use the built-in OPL timer for MidiDriver_Miles_AdLib
Changed paths:
audio/miles_adlib.cpp
diff --git a/audio/miles_adlib.cpp b/audio/miles_adlib.cpp
index 4560a81..7f3f05a 100644
--- a/audio/miles_adlib.cpp
+++ b/audio/miles_adlib.cpp
@@ -129,6 +129,7 @@ public:
MidiChannel *getPercussionChannel() { return NULL; }
// AudioStream
+ int readBuffer(int16 *data, const int numSamples);
bool isStereo() const { return _modeStereo; }
int getRate() const { return _mixer->getOutputRate(); }
int getPolyphony() const { return _modePhysicalFmVoicesCount; }
@@ -140,6 +141,8 @@ public:
void setVolume(byte volume);
virtual uint32 property(int prop, uint32 param);
+ void setTimerCallback(void *timerParam, Common::TimerManager::TimerProc timerProc);
+
private:
bool _modeOPL3;
byte _modePhysicalFmVoicesCount;
@@ -222,6 +225,9 @@ private:
OPL::OPL *_opl;
int _masterVolume;
+ Common::TimerManager::TimerProc _adlibTimerProc;
+ void *_adlibTimerParam;
+
// stores information about all MIDI channels (not the actual OPL FM voice channels!)
MidiChannelEntry _midiChannels[MILES_MIDI_CHANNEL_COUNT];
@@ -238,10 +244,8 @@ private:
bool circularPhysicalAssignment;
byte circularPhysicalAssignmentFmVoice;
-protected:
void onTimer();
-private:
void resetData();
void resetAdLib();
void resetAdLibOperatorRegisters(byte baseRegister, byte value);
@@ -272,7 +276,8 @@ private:
};
MidiDriver_Miles_AdLib::MidiDriver_Miles_AdLib(Audio::Mixer *mixer, InstrumentEntry *instrumentTablePtr, uint16 instrumentTableCount)
- : MidiDriver_Emulated(mixer), _masterVolume(15), _opl(0) {
+ : MidiDriver_Emulated(mixer), _masterVolume(15), _opl(0),
+ _adlibTimerProc(0), _adlibTimerParam(0) {
_instrumentTablePtr = instrumentTablePtr;
_instrumentTableCount = instrumentTableCount;
@@ -321,6 +326,7 @@ int MidiDriver_Miles_AdLib::open() {
MidiDriver_Emulated::open();
+ _opl->start(new Common::Functor0Mem<void, MidiDriver_Miles_AdLib>(this, &MidiDriver_Miles_AdLib::onTimer));
_mixer->playStream(Audio::Mixer::kPlainSoundType, &_mixerSoundHandle, this, -1, _mixer->kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
resetAdLib();
@@ -340,6 +346,8 @@ void MidiDriver_Miles_AdLib::setVolume(byte volume) {
}
void MidiDriver_Miles_AdLib::onTimer() {
+ if (_adlibTimerProc)
+ (*_adlibTimerProc)(_adlibTimerParam);
}
void MidiDriver_Miles_AdLib::resetData() {
@@ -437,10 +445,16 @@ void MidiDriver_Miles_AdLib::send(uint32 b) {
}
void MidiDriver_Miles_AdLib::generateSamples(int16 *data, int len) {
- if (_modeStereo)
- len *= 2;
+ // Dummy implementation until we no longer inherit from MidiDriver_Emulated
+}
+
+int MidiDriver_Miles_AdLib::readBuffer(int16 *data, const int numSamples) {
+ return _opl->readBuffer(data, numSamples);
+}
- _opl->readBuffer(data, len);
+void MidiDriver_Miles_AdLib::setTimerCallback(void *timerParam, Common::TimerManager::TimerProc timerProc) {
+ _adlibTimerProc = timerProc;
+ _adlibTimerParam = timerParam;
}
int16 MidiDriver_Miles_AdLib::searchFreeVirtualFmVoiceChannel() {
Commit: f7c785b37b5fb00029ebb04362f8a733f556e3dd
https://github.com/scummvm/scummvm/commit/f7c785b37b5fb00029ebb04362f8a733f556e3dd
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2015-07-07T20:19:45-04:00
Commit Message:
SKY: Implement original music volume handling
Changed paths:
engines/sky/music/adlibchannel.cpp
engines/sky/music/adlibchannel.h
engines/sky/music/adlibmusic.cpp
diff --git a/engines/sky/music/adlibchannel.cpp b/engines/sky/music/adlibchannel.cpp
index b57f20f..c7acb9b 100644
--- a/engines/sky/music/adlibchannel.cpp
+++ b/engines/sky/music/adlibchannel.cpp
@@ -45,6 +45,8 @@ AdLibChannel::AdLibChannel(OPL::OPL *opl, uint8 *pMusicData, uint16 startOfData)
_channelData.frequency = 0;
_channelData.instrumentData = NULL;
+ _musicVolume = 128;
+
uint16 instrumentDataLoc;
if (SkyEngine::_systemVars.gameVersion == 109) {
@@ -86,7 +88,7 @@ bool AdLibChannel::isActive() {
}
void AdLibChannel::updateVolume(uint16 pVolume) {
- // Do nothing. The mixer handles the music volume for us.
+ _musicVolume = pVolume;
}
/* This class uses the same area for the register mirror as the original
@@ -208,6 +210,8 @@ void AdLibChannel::setupChannelVolume(uint8 volume) {
uint32 resVol = ((volume + 1) * (_channelData.instrumentData->totOutLev_Op2 + 1)) << 1;
resVol &= 0xFFFF;
resVol *= (_channelData.channelVolume + 1) << 1;
+ resVol >>= 8;
+ resVol *= _musicVolume << 1;
resVol >>= 16;
assert(resVol < 0x81);
resultOp = ((_channelData.instrumentData->scalingLevel << 6) & 0xC0) | _opOutputTable[resVol];
@@ -216,6 +220,8 @@ void AdLibChannel::setupChannelVolume(uint8 volume) {
resVol = ((volume + 1) * (_channelData.instrumentData->totOutLev_Op1 + 1)) << 1;
resVol &= 0xFFFF;
resVol *= (_channelData.channelVolume + 1) << 1;
+ resVol >>= 8;
+ resVol *= _musicVolume << 1;
resVol >>= 16;
} else
resVol = _channelData.instrumentData->totOutLev_Op1;
diff --git a/engines/sky/music/adlibchannel.h b/engines/sky/music/adlibchannel.h
index 240dd5c..4504e3b 100644
--- a/engines/sky/music/adlibchannel.h
+++ b/engines/sky/music/adlibchannel.h
@@ -68,6 +68,7 @@ public:
private:
OPL::OPL *_opl;
uint8 *_musicData;
+ uint16 _musicVolume;
AdLibChannelType _channelData;
InstrumentStruct *_instruments;
diff --git a/engines/sky/music/adlibmusic.cpp b/engines/sky/music/adlibmusic.cpp
index c13d615..3607dfb 100644
--- a/engines/sky/music/adlibmusic.cpp
+++ b/engines/sky/music/adlibmusic.cpp
@@ -40,7 +40,7 @@ AdLibMusic::AdLibMusic(Audio::Mixer *pMixer, Disk *pDisk) : MusicBase(pMixer, pD
error("Failed to create OPL");
_opl->start(new Common::Functor0Mem<void, AdLibMusic>(this, &AdLibMusic::onTimer), 50);
- _mixer->playStream(Audio::Mixer::kMusicSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
+ _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
}
AdLibMusic::~AdLibMusic() {
@@ -93,8 +93,8 @@ void AdLibMusic::startDriver() {
void AdLibMusic::setVolume(uint16 param) {
_musicVolume = param;
- // FIXME: This is bad. There's no real volume control here.
- _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, 2 * param);
+ for (uint8 cnt = 0; cnt < _numberOfChannels; cnt++)
+ _channels[cnt]->updateVolume(_musicVolume);
}
bool AdLibMusic::isStereo() const {
Commit: e31da911c98824b746d8804a63df9695216bc08e
https://github.com/scummvm/scummvm/commit/e31da911c98824b746d8804a63df9695216bc08e
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2015-07-07T20:19:45-04:00
Commit Message:
GOB: Implement custom AdLib volume control
Changed paths:
engines/gob/gob.cpp
engines/gob/sound/adlib.cpp
engines/gob/sound/adlib.h
engines/gob/sound/sound.cpp
engines/gob/sound/sound.h
diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp
index 5ab3271..24bdb85 100644
--- a/engines/gob/gob.cpp
+++ b/engines/gob/gob.cpp
@@ -389,6 +389,9 @@ void GobEngine::syncSoundSettings() {
Engine::syncSoundSettings();
_init->updateConfig();
+
+ if (_sound)
+ _sound->adlibSyncVolume();
}
void GobEngine::pauseGame() {
diff --git a/engines/gob/sound/adlib.cpp b/engines/gob/sound/adlib.cpp
index 20fbced..866eecf 100644
--- a/engines/gob/sound/adlib.cpp
+++ b/engines/gob/sound/adlib.cpp
@@ -37,6 +37,28 @@ static const int kPitchTomToSnare = 7;
static const int kPitchSnareDrum = kPitchTom + kPitchTomToSnare;
+// Attenuation map for GUI volume slider
+// Note: no volume control in the original engine
+const uint8 AdLib::kVolumeTable[Audio::Mixer::kMaxMixerVolume + 1] = {
+ 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 62, 61, 59, 57, 56, 55,
+ 53, 52, 51, 50, 49, 48, 47, 46, 46, 45, 44, 43, 43, 42, 41, 41,
+ 40, 39, 39, 38, 38, 37, 37, 36, 36, 35, 35, 34, 34, 33, 33, 33,
+ 32, 32, 31, 31, 31, 30, 30, 30, 29, 29, 29, 28, 28, 28, 27, 27,
+ 27, 26, 26, 26, 26, 25, 25, 25, 24, 24, 24, 24, 23, 23, 23, 23,
+ 22, 22, 22, 22, 21, 21, 21, 21, 21, 20, 20, 20, 20, 19, 19, 19,
+ 19, 19, 18, 18, 18, 18, 18, 18, 17, 17, 17, 17, 17, 16, 16, 16,
+ 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 13,
+ 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11,
+ 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9,
+ 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
+ 0
+};
+
// Is the operator a modulator (0) or a carrier (1)?
const uint8 AdLib::kOperatorType[kOperatorCount] = {
0, 0, 0, 1, 1, 1,
@@ -94,7 +116,7 @@ const uint16 AdLib::kHihatParams [kParamCount] = {
AdLib::AdLib(Audio::Mixer &mixer, int callbackFreq) : _mixer(&mixer), _opl(0),
- _toPoll(0), _repCount(0), _first(true), _playing(false), _ended(true) {
+ _toPoll(0), _repCount(0), _first(true), _playing(false), _ended(true), _volume(0) {
_rate = _mixer->getOutputRate();
@@ -103,8 +125,10 @@ AdLib::AdLib(Audio::Mixer &mixer, int callbackFreq) : _mixer(&mixer), _opl(0),
createOPL();
initOPL();
+ syncVolume();
+
_opl->start(new Common::Functor0Mem<void, AdLib>(this, &AdLib::onTimer), callbackFreq);
- _mixer->playStream(Audio::Mixer::kMusicSoundType, &_handle,
+ _mixer->playStream(Audio::Mixer::kPlainSoundType, &_handle,
this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
}
@@ -433,6 +457,13 @@ void AdLib::writeKeyScaleLevelVolume(uint8 oper) {
volume = (63 - (_operatorParams[oper][kParamLevel] & 0x3F)) * _operatorVolume[oper];
volume = 63 - ((2 * volume + kMaxVolume) / (2 * kMaxVolume));
+ // Adjust carriers for GUI volume slider
+ if (kOperatorType[oper] == 1) {
+ volume += kVolumeTable[_volume];
+ if (volume > 63)
+ volume = 63;
+ }
+
uint8 keyScale = _operatorParams[oper][kParamKeyScaleLevel] << 6;
writeOPL(0x40 + kOperatorOffset[oper], volume | keyScale);
@@ -634,4 +665,19 @@ void AdLib::setTimerFrequency(int timerFrequency) {
_opl->setCallbackFrequency(timerFrequency);
}
+void AdLib::syncVolume() {
+ Common::StackLock slock(_mutex);
+
+ bool mute = false;
+ if (ConfMan.hasKey("mute"))
+ mute = ConfMan.getBool("mute");
+
+ _volume = (mute ? 0 : ConfMan.getInt("music_volume"));
+
+ if (_playing) {
+ for(int i = 0; i < kOperatorCount; i++)
+ writeKeyScaleLevelVolume(i);
+ }
+}
+
} // End of namespace Gob
diff --git a/engines/gob/sound/adlib.h b/engines/gob/sound/adlib.h
index 6a62152..2c83b15 100644
--- a/engines/gob/sound/adlib.h
+++ b/engines/gob/sound/adlib.h
@@ -53,6 +53,7 @@ public:
void startPlay();
void stopPlay();
+ void syncVolume();
// AudioStream API
int readBuffer(int16 *buffer, const int numSamples);
@@ -211,6 +212,8 @@ protected:
void setTimerFrequency(int timerFrequency);
private:
+ static const uint8 kVolumeTable[Audio::Mixer::kMaxMixerVolume + 1];
+
static const uint8 kOperatorType [kOperatorCount];
static const uint8 kOperatorOffset[kOperatorCount];
static const uint8 kOperatorVoice [kOperatorCount];
@@ -235,6 +238,8 @@ private:
Common::Mutex _mutex;
+ int _volume;
+
uint32 _rate;
uint32 _toPoll;
diff --git a/engines/gob/sound/sound.cpp b/engines/gob/sound/sound.cpp
index d2b2d3d..9b19b9c 100644
--- a/engines/gob/sound/sound.cpp
+++ b/engines/gob/sound/sound.cpp
@@ -425,6 +425,16 @@ int32 Sound::adlibGetRepeating() const {
return false;
}
+void Sound::adlibSyncVolume() {
+ if (!_hasAdLib)
+ return;
+
+ if (_adlPlayer)
+ _adlPlayer->syncVolume();
+ if (_mdyPlayer)
+ _mdyPlayer->syncVolume();
+}
+
void Sound::adlibSetRepeating(int32 repCount) {
if (!_hasAdLib)
return;
diff --git a/engines/gob/sound/sound.h b/engines/gob/sound/sound.h
index c959959..6ebc323 100644
--- a/engines/gob/sound/sound.h
+++ b/engines/gob/sound/sound.h
@@ -96,6 +96,7 @@ public:
int32 adlibGetRepeating() const;
void adlibSetRepeating(int32 repCount);
+ void adlibSyncVolume();
// Infogrames
Commit: b367ea548d7c129e14fec6164ebe5610d3edeb46
https://github.com/scummvm/scummvm/commit/b367ea548d7c129e14fec6164ebe5610d3edeb46
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2015-07-07T20:19:46-04:00
Commit Message:
QUEEN: Implement original music volume handling
Changed paths:
A engines/queen/midiadlib.h
engines/queen/midiadlib.cpp
engines/queen/music.cpp
diff --git a/engines/queen/midiadlib.cpp b/engines/queen/midiadlib.cpp
index 4797e5d..457767a 100644
--- a/engines/queen/midiadlib.cpp
+++ b/engines/queen/midiadlib.cpp
@@ -23,109 +23,10 @@
#include "common/endian.h"
#include "common/textconsole.h"
-#include "audio/fmopl.h"
-#include "audio/softsynth/emumidi.h"
+#include "engines/queen/midiadlib.h"
namespace Queen {
-class AdLibMidiDriver : public MidiDriver_Emulated {
-public:
-
- AdLibMidiDriver(Audio::Mixer *mixer) : MidiDriver_Emulated(mixer) { _adlibWaveformSelect = 0; }
- ~AdLibMidiDriver() {}
-
- // MidiDriver
- int open();
- void close();
- void send(uint32 b);
- void metaEvent(byte type, byte *data, uint16 length);
- MidiChannel *allocateChannel() { return 0; }
- MidiChannel *getPercussionChannel() { return 0; }
- void setTimerCallback(void *timerParam, Common::TimerManager::TimerProc timerProc);
-
- // AudioStream
- int readBuffer(int16 *data, const int numSamples);
- bool isStereo() const { return false; }
- int getRate() const { return _mixer->getOutputRate(); }
-
- // MidiDriver_Emulated
- void generateSamples(int16 *buf, int len);
-
-private:
-
- void handleMidiEvent0x90_NoteOn(int channel, int param1, int param2);
- void handleSequencerSpecificMetaEvent1(int channel, const uint8 *data);
- void handleSequencerSpecificMetaEvent2(uint8 value);
- void handleSequencerSpecificMetaEvent3(uint8 value);
-
- void adlibWrite(uint8 port, uint8 value);
- void adlibSetupCard();
- void adlibSetupChannels(int fl);
- void adlibResetAmpVibratoRhythm(int am, int vib, int kso);
- void adlibResetChannels();
- void adlibSetAmpVibratoRhythm();
- void adlibSetCSMKeyboardSplit();
- void adlibSetNoteMul(int mul);
- void adlibSetWaveformSelect(int fl);
- void adlibSetPitchBend(int channel, int range);
- void adlibPlayNote(int channel);
- uint8 adlibPlayNoteHelper(int channel, int note1, int note2, int oct);
- void adlibTurnNoteOff(int channel);
- void adlibTurnNoteOn(int channel, int note);
- void adlibSetupChannelFromSequence(int channel, const uint8 *src, int fl);
- void adlibSetupChannel(int channel, const uint16 *src, int fl);
- void adlibSetNoteVolume(int channel, int volume);
- void adlibSetupChannelHelper(int channel);
- void adlibSetChannel0x40(int channel);
- void adlibSetChannel0xC0(int channel);
- void adlibSetChannel0x60(int channel);
- void adlibSetChannel0x80(int channel);
- void adlibSetChannel0x20(int channel);
- void adlibSetChannel0xE0(int channel);
-
- void onTimer();
-
- OPL::OPL *_opl;
- int _midiNumberOfChannels;
- int _adlibNoteMul;
- int _adlibWaveformSelect;
- int _adlibAMDepthEq48;
- int _adlibVibratoDepthEq14;
- int _adlibRhythmEnabled;
- int _adlibKeyboardSplitOn;
- int _adlibVibratoRhythm;
- uint8 _midiChannelsFreqTable[9];
- uint8 _adlibChannelsLevelKeyScalingTable[11];
- uint8 _adlibSetupChannelSequence1[14 * 18];
- uint16 _adlibSetupChannelSequence2[14];
- int16 _midiChannelsNote2Table[9];
- uint8 _midiChannelsNote1Table[9];
- uint8 _midiChannelsOctTable[9];
- uint16 _adlibChannelsVolume[11];
- uint16 _adlibMetaSequenceData[28];
-
- Common::TimerManager::TimerProc _adlibTimerProc;
- void *_adlibTimerParam;
-
- static const uint8 _adlibChannelsMappingTable1[];
- static const uint8 _adlibChannelsNoFeedback[];
- static const uint8 _adlibChannelsMappingTable2[];
- static const uint8 _adlibChannelsMappingTable3[];
- static const uint8 _adlibChannelsKeyScalingTable1[];
- static const uint8 _adlibChannelsKeyScalingTable2[];
- static const uint8 _adlibChannelsVolumeTable[];
- static const uint8 _adlibInitSequenceData1[];
- static const uint8 _adlibInitSequenceData2[];
- static const uint8 _adlibInitSequenceData3[];
- static const uint8 _adlibInitSequenceData4[];
- static const uint8 _adlibInitSequenceData5[];
- static const uint8 _adlibInitSequenceData6[];
- static const uint8 _adlibInitSequenceData7[];
- static const uint8 _adlibInitSequenceData8[];
- static const int16 _midiChannelsNoteTable[];
- static const int16 _midiNoteFreqTable[];
-};
-
int AdLibMidiDriver::open() {
MidiDriver_Emulated::open();
_opl = OPL::Config::create();
@@ -140,7 +41,7 @@ int AdLibMidiDriver::open() {
}
_opl->start(new Common::Functor0Mem<void, AdLibMidiDriver>(this, &AdLibMidiDriver::onTimer));
- _mixer->playStream(Audio::Mixer::kMusicSoundType, &_mixerSoundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
+ _mixer->playStream(Audio::Mixer::kPlainSoundType, &_mixerSoundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
return 0;
}
@@ -176,6 +77,11 @@ void AdLibMidiDriver::send(uint32 b) {
}
}
+void AdLibMidiDriver::setVolume(uint32 volume) {
+ for (int i = 0; i < _midiNumberOfChannels; ++i)
+ adlibSetChannelVolume(i, volume * 64 / 256 + 64);
+}
+
void AdLibMidiDriver::metaEvent(byte type, byte *data, uint16 length) {
int event = 0;
if (length > 4 && READ_BE_UINT32(data) == 0x3F00) {
@@ -278,6 +184,7 @@ void AdLibMidiDriver::adlibSetupCard() {
_midiChannelsFreqTable[i] = 0;
}
memset(_adlibChannelsLevelKeyScalingTable, 127, 11);
+ memset(_adlibChannelsVolumeTable, 128, 11);
adlibSetupChannels(0);
adlibResetAmpVibratoRhythm(0, 0, 0);
adlibSetNoteMul(1);
@@ -473,6 +380,11 @@ void AdLibMidiDriver::adlibSetNoteVolume(int channel, int volume) {
}
}
+void AdLibMidiDriver::adlibSetChannelVolume(int channel, uint8 volume) {
+ if (channel < (_adlibRhythmEnabled ? 11 : 9))
+ _adlibChannelsVolumeTable[channel] = volume;
+}
+
void AdLibMidiDriver::adlibSetupChannelHelper(int channel) {
adlibSetAmpVibratoRhythm();
adlibSetCSMKeyboardSplit();
@@ -583,10 +495,6 @@ const uint8 AdLibMidiDriver::_adlibChannelsKeyScalingTable2[] = {
0, 3, 1, 4, 2, 5, 6, 9, 7, 10, 8, 11, 12, 15, 16, 255, 14, 255, 17, 255, 13, 255
};
-const uint8 AdLibMidiDriver::_adlibChannelsVolumeTable[] = {
- 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128
-};
-
const uint8 AdLibMidiDriver::_adlibInitSequenceData1[] = {
1, 1, 3, 15, 5, 0, 1, 3, 15, 0, 0, 0, 1, 0
};
@@ -642,8 +550,4 @@ const int16 AdLibMidiDriver::_midiNoteFreqTable[] = {
-363, -361, -359, -356, -354, -351, -349, -347, -344, -342, -339, -337
};
-MidiDriver *C_Player_CreateAdLibMidiDriver(Audio::Mixer *mixer) {
- return new AdLibMidiDriver(mixer);
-}
-
} // End of namespace Queen
diff --git a/engines/queen/midiadlib.h b/engines/queen/midiadlib.h
new file mode 100644
index 0000000..d559025
--- /dev/null
+++ b/engines/queen/midiadlib.h
@@ -0,0 +1,130 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "audio/fmopl.h"
+#include "audio/mididrv.h"
+#include "audio/softsynth/emumidi.h"
+
+namespace Queen {
+
+class AdLibMidiDriver : public MidiDriver_Emulated {
+public:
+
+ AdLibMidiDriver(Audio::Mixer *mixer) : MidiDriver_Emulated(mixer) { _adlibWaveformSelect = 0; }
+ ~AdLibMidiDriver() {}
+
+ // MidiDriver
+ int open();
+ void close();
+ void send(uint32 b);
+ void metaEvent(byte type, byte *data, uint16 length);
+ MidiChannel *allocateChannel() { return 0; }
+ MidiChannel *getPercussionChannel() { return 0; }
+ void setTimerCallback(void *timerParam, Common::TimerManager::TimerProc timerProc);
+
+ // AudioStream
+ int readBuffer(int16 *data, const int numSamples);
+ bool isStereo() const { return false; }
+ int getRate() const { return _mixer->getOutputRate(); }
+
+ // MidiDriver_Emulated
+ void generateSamples(int16 *buf, int len);
+
+ void setVolume(uint32 volume);
+
+private:
+
+ void handleMidiEvent0x90_NoteOn(int channel, int param1, int param2);
+ void handleSequencerSpecificMetaEvent1(int channel, const uint8 *data);
+ void handleSequencerSpecificMetaEvent2(uint8 value);
+ void handleSequencerSpecificMetaEvent3(uint8 value);
+
+ void adlibWrite(uint8 port, uint8 value);
+ void adlibSetupCard();
+ void adlibSetupChannels(int fl);
+ void adlibResetAmpVibratoRhythm(int am, int vib, int kso);
+ void adlibResetChannels();
+ void adlibSetAmpVibratoRhythm();
+ void adlibSetCSMKeyboardSplit();
+ void adlibSetNoteMul(int mul);
+ void adlibSetWaveformSelect(int fl);
+ void adlibSetPitchBend(int channel, int range);
+ void adlibPlayNote(int channel);
+ uint8 adlibPlayNoteHelper(int channel, int note1, int note2, int oct);
+ void adlibTurnNoteOff(int channel);
+ void adlibTurnNoteOn(int channel, int note);
+ void adlibSetupChannelFromSequence(int channel, const uint8 *src, int fl);
+ void adlibSetupChannel(int channel, const uint16 *src, int fl);
+ void adlibSetChannelVolume(int channel, uint8 volume);
+ void adlibSetNoteVolume(int channel, int volume);
+ void adlibSetupChannelHelper(int channel);
+ void adlibSetChannel0x40(int channel);
+ void adlibSetChannel0xC0(int channel);
+ void adlibSetChannel0x60(int channel);
+ void adlibSetChannel0x80(int channel);
+ void adlibSetChannel0x20(int channel);
+ void adlibSetChannel0xE0(int channel);
+
+ void onTimer();
+
+ OPL::OPL *_opl;
+ int _midiNumberOfChannels;
+ int _adlibNoteMul;
+ int _adlibWaveformSelect;
+ int _adlibAMDepthEq48;
+ int _adlibVibratoDepthEq14;
+ int _adlibRhythmEnabled;
+ int _adlibKeyboardSplitOn;
+ int _adlibVibratoRhythm;
+ uint8 _midiChannelsFreqTable[9];
+ uint8 _adlibChannelsLevelKeyScalingTable[11];
+ uint8 _adlibSetupChannelSequence1[14 * 18];
+ uint16 _adlibSetupChannelSequence2[14];
+ int16 _midiChannelsNote2Table[9];
+ uint8 _midiChannelsNote1Table[9];
+ uint8 _midiChannelsOctTable[9];
+ uint16 _adlibChannelsVolume[11];
+ uint16 _adlibMetaSequenceData[28];
+ uint8 _adlibChannelsVolumeTable[11];
+
+ Common::TimerManager::TimerProc _adlibTimerProc;
+ void *_adlibTimerParam;
+
+ static const uint8 _adlibChannelsMappingTable1[];
+ static const uint8 _adlibChannelsNoFeedback[];
+ static const uint8 _adlibChannelsMappingTable2[];
+ static const uint8 _adlibChannelsMappingTable3[];
+ static const uint8 _adlibChannelsKeyScalingTable1[];
+ static const uint8 _adlibChannelsKeyScalingTable2[];
+ static const uint8 _adlibInitSequenceData1[];
+ static const uint8 _adlibInitSequenceData2[];
+ static const uint8 _adlibInitSequenceData3[];
+ static const uint8 _adlibInitSequenceData4[];
+ static const uint8 _adlibInitSequenceData5[];
+ static const uint8 _adlibInitSequenceData6[];
+ static const uint8 _adlibInitSequenceData7[];
+ static const uint8 _adlibInitSequenceData8[];
+ static const int16 _midiChannelsNoteTable[];
+ static const int16 _midiNoteFreqTable[];
+};
+
+} // End of namespace Queen
diff --git a/engines/queen/music.cpp b/engines/queen/music.cpp
index 93d6527..600956a 100644
--- a/engines/queen/music.cpp
+++ b/engines/queen/music.cpp
@@ -23,6 +23,7 @@
#include "common/config-manager.h"
#include "common/events.h"
+#include "queen/midiadlib.h"
#include "queen/music.h"
#include "queen/queen.h"
#include "queen/resource.h"
@@ -33,8 +34,6 @@
namespace Queen {
-extern MidiDriver *C_Player_CreateAdLibMidiDriver(Audio::Mixer *);
-
MidiMusic::MidiMusic(QueenEngine *vm)
: _isPlaying(false), _isLooping(false),
_randomLoop(false), _masterVolume(192),
@@ -69,7 +68,7 @@ MidiMusic::MidiMusic(QueenEngine *vm)
// if (READ_LE_UINT16(_musicData + 2) != infoOffset) {
// defaultAdLibVolume = _musicData[infoOffset];
// }
- _driver = C_Player_CreateAdLibMidiDriver(vm->_mixer);
+ _driver = new AdLibMidiDriver(g_system->getMixer());
} else {
_driver = MidiDriver::createMidi(dev);
if (_nativeMT32) {
@@ -117,6 +116,9 @@ void MidiMusic::setVolume(int volume) {
if (_channelsTable[i])
_channelsTable[i]->volume(_channelsVolume[i] * _masterVolume / 255);
}
+
+ if (_adlib)
+ static_cast<AdLibMidiDriver*>(_driver)->setVolume(volume);
}
void MidiMusic::playSong(uint16 songNum) {
Commit: dce05c520b2e1f273f395c986573f532ee698921
https://github.com/scummvm/scummvm/commit/dce05c520b2e1f273f395c986573f532ee698921
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-07-07T20:19:46-04:00
Commit Message:
AUDIO: Be consistent with calling stop() in OPL destructors
Changed paths:
audio/fmopl.cpp
audio/softsynth/opl/dosbox.cpp
audio/softsynth/opl/mame.cpp
diff --git a/audio/fmopl.cpp b/audio/fmopl.cpp
index 07c5b44..638da6c 100644
--- a/audio/fmopl.cpp
+++ b/audio/fmopl.cpp
@@ -201,8 +201,10 @@ EmulatedOPL::EmulatedOPL() :
EmulatedOPL::~EmulatedOPL() {
// Stop callbacks, just in case. If it's still playing at this
- // point, there's probably a bigger issue, though.
- stopCallbacks();
+ // point, there's probably a bigger issue, though. The subclass
+ // needs to call stop() or the pointer can still use be used in
+ // the mixer thread at the same time.
+ stop();
}
int EmulatedOPL::readBuffer(int16 *buffer, const int numSamples) {
diff --git a/audio/softsynth/opl/dosbox.cpp b/audio/softsynth/opl/dosbox.cpp
index 09200c7..6e8b4a9 100644
--- a/audio/softsynth/opl/dosbox.cpp
+++ b/audio/softsynth/opl/dosbox.cpp
@@ -149,11 +149,11 @@ OPL::OPL(Config::OplType type) : _type(type), _rate(0), _emulator(0) {
}
OPL::~OPL() {
+ stop();
free();
}
void OPL::free() {
- stopCallbacks();
delete _emulator;
_emulator = 0;
}
diff --git a/audio/softsynth/opl/mame.cpp b/audio/softsynth/opl/mame.cpp
index fe23d30..d43f638 100644
--- a/audio/softsynth/opl/mame.cpp
+++ b/audio/softsynth/opl/mame.cpp
@@ -48,7 +48,7 @@ namespace OPL {
namespace MAME {
OPL::~OPL() {
- stopCallbacks();
+ stop();
MAME::OPLDestroy(_opl);
_opl = 0;
}
Commit: 8bcbcd6c167e8e7169f006da459f3cbe450a4a59
https://github.com/scummvm/scummvm/commit/8bcbcd6c167e8e7169f006da459f3cbe450a4a59
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-07-07T20:19:47-04:00
Commit Message:
AUDIO: Change callback frequency without restarting the audio stream
Changed paths:
audio/fmopl.cpp
audio/fmopl.h
diff --git a/audio/fmopl.cpp b/audio/fmopl.cpp
index 638da6c..9af7aff 100644
--- a/audio/fmopl.cpp
+++ b/audio/fmopl.cpp
@@ -183,14 +183,6 @@ void OPL::stop() {
_callback.reset();
}
-void OPL::setCallbackFrequency(int timerFrequency) {
- if (!isRunning())
- return;
-
- stopCallbacks();
- startCallbacks(timerFrequency);
-}
-
bool OPL::_hasInstance = false;
EmulatedOPL::EmulatedOPL() :
@@ -239,6 +231,17 @@ int EmulatedOPL::getRate() const {
}
void EmulatedOPL::startCallbacks(int timerFrequency) {
+ setCallbackFrequency(timerFrequency);
+ // TODO: Eventually start mixer playback here
+ //g_system->getMixer()->playStream(Audio::Mixer::kPlainSoundType, _handle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
+}
+
+void EmulatedOPL::stopCallbacks() {
+ // TODO: Eventually stop mixer playback here
+ //g_system->getMixer()->stopHandle(*_handle);
+}
+
+void EmulatedOPL::setCallbackFrequency(int timerFrequency) {
_baseFreq = timerFrequency;
assert(_baseFreq != 0);
@@ -249,20 +252,6 @@ void EmulatedOPL::startCallbacks(int timerFrequency) {
// but less prone to arithmetic overflow.
_samplesPerTick = (d << FIXP_SHIFT) + (r << FIXP_SHIFT) / _baseFreq;
-
- // TODO: Eventually start mixer playback here
- //g_system->getMixer()->playStream(Audio::Mixer::kPlainSoundType, _handle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
-}
-
-void EmulatedOPL::stopCallbacks() {
- // TODO: Eventually stop mixer playback here
- //g_system->getMixer()->stopHandle(*_handle);
-}
-
-bool EmulatedOPL::isRunning() const {
- // TODO
- //return g_system->getMixer()->isSoundHandleActive(*_handle);
- return true;
}
} // End of namespace OPL
diff --git a/audio/fmopl.h b/audio/fmopl.h
index 243cd29..8baa9aa 100644
--- a/audio/fmopl.h
+++ b/audio/fmopl.h
@@ -176,15 +176,10 @@ public:
void stop();
/**
- * Is the OPL running?
+ * Change the callback frequency. This must only be called from a
+ * timer proc.
*/
- virtual bool isRunning() const = 0;
-
- /**
- * Change the callback frequency. This has no effect if start()
- * has not already been called.
- */
- void setCallbackFrequency(int timerFrequency);
+ virtual void setCallbackFrequency(int timerFrequency) = 0;
enum {
/**
@@ -218,6 +213,7 @@ public:
// OPL API
int readBuffer(int16 *buffer, const int numSamples);
bool isRunning() const;
+ void setCallbackFrequency(int timerFrequency);
int getRate() const;
Commit: bed9da8b9dbbaa19d317f71663e42875c1717fda
https://github.com/scummvm/scummvm/commit/bed9da8b9dbbaa19d317f71663e42875c1717fda
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-07-07T20:19:47-04:00
Commit Message:
AUDIO: Remove all AudioStream access to OPL
Changed paths:
audio/fmopl.cpp
audio/fmopl.h
audio/miles_adlib.cpp
audio/softsynth/adlib.cpp
audio/softsynth/opl/dosbox.cpp
audio/softsynth/opl/mame.cpp
engines/agos/drivers/accolade/adlib.cpp
engines/cine/sound.cpp
engines/cruise/sound.cpp
engines/gob/sound/adlib.cpp
engines/gob/sound/adlib.h
engines/gob/sound/musplayer.cpp
engines/kyra/sound_adlib.cpp
engines/mads/nebular/sound_nebular.cpp
engines/mads/nebular/sound_nebular.h
engines/parallaction/adlib.cpp
engines/queen/midiadlib.cpp
engines/queen/midiadlib.h
engines/queen/music.cpp
engines/sci/sound/drivers/adlib.cpp
engines/scumm/players/player_ad.cpp
engines/scumm/players/player_ad.h
engines/sherlock/scalpel/drivers/adlib.cpp
engines/sky/music/adlibmusic.cpp
engines/sky/music/adlibmusic.h
engines/tsage/sound.cpp
engines/tsage/sound.h
diff --git a/audio/fmopl.cpp b/audio/fmopl.cpp
index 9af7aff..4bc902e 100644
--- a/audio/fmopl.cpp
+++ b/audio/fmopl.cpp
@@ -188,7 +188,8 @@ bool OPL::_hasInstance = false;
EmulatedOPL::EmulatedOPL() :
_nextTick(0),
_samplesPerTick(0),
- _baseFreq(0) {
+ _baseFreq(0),
+ _handle(new Audio::SoundHandle()) {
}
EmulatedOPL::~EmulatedOPL() {
@@ -197,6 +198,8 @@ EmulatedOPL::~EmulatedOPL() {
// needs to call stop() or the pointer can still use be used in
// the mixer thread at the same time.
stop();
+
+ delete _handle;
}
int EmulatedOPL::readBuffer(int16 *buffer, const int numSamples) {
@@ -232,13 +235,11 @@ int EmulatedOPL::getRate() const {
void EmulatedOPL::startCallbacks(int timerFrequency) {
setCallbackFrequency(timerFrequency);
- // TODO: Eventually start mixer playback here
- //g_system->getMixer()->playStream(Audio::Mixer::kPlainSoundType, _handle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
+ g_system->getMixer()->playStream(Audio::Mixer::kPlainSoundType, _handle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
}
void EmulatedOPL::stopCallbacks() {
- // TODO: Eventually stop mixer playback here
- //g_system->getMixer()->stopHandle(*_handle);
+ g_system->getMixer()->stopHandle(*_handle);
}
void EmulatedOPL::setCallbackFrequency(int timerFrequency) {
diff --git a/audio/fmopl.h b/audio/fmopl.h
index 8baa9aa..091e0bd 100644
--- a/audio/fmopl.h
+++ b/audio/fmopl.h
@@ -23,10 +23,16 @@
#ifndef AUDIO_FMOPL_H
#define AUDIO_FMOPL_H
+#include "audio/audiostream.h"
+
#include "common/func.h"
#include "common/ptr.h"
#include "common/scummsys.h"
+namespace Audio {
+class SoundHandle;
+}
+
namespace Common {
class String;
}
@@ -149,23 +155,6 @@ public:
virtual void writeReg(int r, int v) = 0;
/**
- * Read up to 'length' samples.
- *
- * Data will be in native endianess, 16 bit per sample, signed.
- * For stereo OPL, buffer will be filled with interleaved
- * left and right channel samples, starting with a left sample.
- * Furthermore, the samples in the left and right are summed up.
- * So if you request 4 samples from a stereo OPL, you will get
- * a total of two left channel and two right channel samples.
- */
- virtual int readBuffer(int16 *buffer, const int numSamples) = 0;
-
- /**
- * Returns whether the setup OPL mode is stereo or not
- */
- virtual bool isStereo() const = 0;
-
- /**
* Start the OPL with callbacks.
*/
void start(TimerCallback *callback, int timerFrequency = kDefaultCallbackFrequency);
@@ -205,17 +194,18 @@ protected:
Common::ScopedPtr<TimerCallback> _callback;
};
-class EmulatedOPL : public OPL {
+class EmulatedOPL : public OPL, protected Audio::AudioStream {
public:
EmulatedOPL();
virtual ~EmulatedOPL();
// OPL API
- int readBuffer(int16 *buffer, const int numSamples);
- bool isRunning() const;
void setCallbackFrequency(int timerFrequency);
+ // AudioStream API
+ int readBuffer(int16 *buffer, const int numSamples);
int getRate() const;
+ bool endOfData() const { return false; }
protected:
// OPL API
@@ -243,6 +233,8 @@ private:
int _nextTick;
int _samplesPerTick;
+
+ Audio::SoundHandle *_handle;
};
} // End of namespace OPL
diff --git a/audio/miles_adlib.cpp b/audio/miles_adlib.cpp
index 7f3f05a..bf5c9d4 100644
--- a/audio/miles_adlib.cpp
+++ b/audio/miles_adlib.cpp
@@ -116,9 +116,9 @@ uint16 milesAdLibVolumeSensitivityTable[] = {
};
-class MidiDriver_Miles_AdLib : public MidiDriver_Emulated {
+class MidiDriver_Miles_AdLib : public MidiDriver {
public:
- MidiDriver_Miles_AdLib(Audio::Mixer *mixer, InstrumentEntry *instrumentTablePtr, uint16 instrumentTableCount);
+ MidiDriver_Miles_AdLib(InstrumentEntry *instrumentTablePtr, uint16 instrumentTableCount);
virtual ~MidiDriver_Miles_AdLib();
// MidiDriver
@@ -128,15 +128,8 @@ public:
MidiChannel *allocateChannel() { return NULL; }
MidiChannel *getPercussionChannel() { return NULL; }
- // AudioStream
- int readBuffer(int16 *data, const int numSamples);
- bool isStereo() const { return _modeStereo; }
- int getRate() const { return _mixer->getOutputRate(); }
- int getPolyphony() const { return _modePhysicalFmVoicesCount; }
- bool hasRhythmChannel() const { return false; }
-
- // MidiDriver_Emulated
- void generateSamples(int16 *buf, int len);
+ bool isOpen() const { return _isOpen; }
+ uint32 getBaseTempo() { return 1000000 / OPL::OPL::kDefaultCallbackFrequency; }
void setVolume(byte volume);
virtual uint32 property(int prop, uint32 param);
@@ -228,6 +221,8 @@ private:
Common::TimerManager::TimerProc _adlibTimerProc;
void *_adlibTimerParam;
+ bool _isOpen;
+
// stores information about all MIDI channels (not the actual OPL FM voice channels!)
MidiChannelEntry _midiChannels[MILES_MIDI_CHANNEL_COUNT];
@@ -275,9 +270,9 @@ private:
void pitchBendChange(byte MIDIchannel, byte parameter1, byte parameter2);
};
-MidiDriver_Miles_AdLib::MidiDriver_Miles_AdLib(Audio::Mixer *mixer, InstrumentEntry *instrumentTablePtr, uint16 instrumentTableCount)
- : MidiDriver_Emulated(mixer), _masterVolume(15), _opl(0),
- _adlibTimerProc(0), _adlibTimerParam(0) {
+MidiDriver_Miles_AdLib::MidiDriver_Miles_AdLib(InstrumentEntry *instrumentTablePtr, uint16 instrumentTableCount)
+ : _masterVolume(15), _opl(0),
+ _adlibTimerProc(0), _adlibTimerParam(0), _isOpen(false) {
_instrumentTablePtr = instrumentTablePtr;
_instrumentTableCount = instrumentTableCount;
@@ -324,10 +319,9 @@ int MidiDriver_Miles_AdLib::open() {
_opl->init();
- MidiDriver_Emulated::open();
+ _isOpen = true;
_opl->start(new Common::Functor0Mem<void, MidiDriver_Miles_AdLib>(this, &MidiDriver_Miles_AdLib::onTimer));
- _mixer->playStream(Audio::Mixer::kPlainSoundType, &_mixerSoundHandle, this, -1, _mixer->kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
resetAdLib();
@@ -335,9 +329,8 @@ int MidiDriver_Miles_AdLib::open() {
}
void MidiDriver_Miles_AdLib::close() {
- _mixer->stopHandle(_mixerSoundHandle);
-
delete _opl;
+ _isOpen = false;
}
void MidiDriver_Miles_AdLib::setVolume(byte volume) {
@@ -444,14 +437,6 @@ void MidiDriver_Miles_AdLib::send(uint32 b) {
}
}
-void MidiDriver_Miles_AdLib::generateSamples(int16 *data, int len) {
- // Dummy implementation until we no longer inherit from MidiDriver_Emulated
-}
-
-int MidiDriver_Miles_AdLib::readBuffer(int16 *data, const int numSamples) {
- return _opl->readBuffer(data, numSamples);
-}
-
void MidiDriver_Miles_AdLib::setTimerCallback(void *timerParam, Common::TimerManager::TimerProc timerProc) {
_adlibTimerProc = timerProc;
_adlibTimerParam = timerParam;
@@ -1283,7 +1268,7 @@ MidiDriver *MidiDriver_Miles_AdLib_create(const Common::String &filenameAdLib, c
// Free instrument file/stream data
delete[] streamDataPtr;
- return new MidiDriver_Miles_AdLib(g_system->getMixer(), instrumentTablePtr, instrumentTableCount);
+ return new MidiDriver_Miles_AdLib(instrumentTablePtr, instrumentTableCount);
}
} // End of namespace Audio
diff --git a/audio/softsynth/adlib.cpp b/audio/softsynth/adlib.cpp
index c7b5297..f609164 100644
--- a/audio/softsynth/adlib.cpp
+++ b/audio/softsynth/adlib.cpp
@@ -927,18 +927,20 @@ static void createLookupTable() {
//
////////////////////////////////////////
-class MidiDriver_ADLIB : public MidiDriver_Emulated {
+class MidiDriver_ADLIB : public MidiDriver {
friend class AdLibPart;
friend class AdLibPercussionChannel;
public:
- MidiDriver_ADLIB(Audio::Mixer *mixer);
+ MidiDriver_ADLIB();
int open();
void close();
void send(uint32 b);
void send(byte channel, uint32 b); // Supports higher than channel 15
uint32 property(int prop, uint32 param);
+ bool isOpen() const { return _isOpen; }
+ uint32 getBaseTempo() { return 1000000 / OPL::OPL::kDefaultCallbackFrequency; }
void setPitchBendRange(byte channel, uint range);
void sysEx_customInstrument(byte channel, uint32 type, const byte *instr);
@@ -946,12 +948,6 @@ public:
MidiChannel *allocateChannel();
MidiChannel *getPercussionChannel() { return &_percussion; } // Percussion partially supported
-
- // AudioStream API
- int readBuffer(int16 *data, const int numSamples);
- bool isStereo() const { return _opl->isStereo(); }
- int getRate() const { return _mixer->getOutputRate(); }
-
virtual void setTimerCallback(void *timerParam, Common::TimerManager::TimerProc timerProc);
private:
@@ -980,7 +976,8 @@ private:
AdLibPart _parts[32];
AdLibPercussionChannel _percussion;
- void generateSamples(int16 *buf, int len);
+ bool _isOpen;
+
void onTimer();
void partKeyOn(AdLibPart *part, const AdLibInstrument *instr, byte note, byte velocity, const AdLibInstrument *second, byte pan);
void partKeyOff(AdLibPart *part, byte note);
@@ -1382,8 +1379,7 @@ void AdLibPercussionChannel::sysEx_customInstrument(uint32 type, const byte *ins
// MidiDriver method implementations
-MidiDriver_ADLIB::MidiDriver_ADLIB(Audio::Mixer *mixer)
- : MidiDriver_Emulated(mixer) {
+MidiDriver_ADLIB::MidiDriver_ADLIB() {
uint i;
_scummSmallHeader = false;
@@ -1411,13 +1407,14 @@ MidiDriver_ADLIB::MidiDriver_ADLIB(Audio::Mixer *mixer)
_opl = 0;
_adlibTimerProc = 0;
_adlibTimerParam = 0;
+ _isOpen = false;
}
int MidiDriver_ADLIB::open() {
if (_isOpen)
return MERR_ALREADY_OPEN;
- MidiDriver_Emulated::open();
+ _isOpen = true;
int i;
AdLibVoice *voice;
@@ -1461,8 +1458,6 @@ int MidiDriver_ADLIB::open() {
#endif
_opl->start(new Common::Functor0Mem<void, MidiDriver_ADLIB>(this, &MidiDriver_ADLIB::onTimer));
- _mixer->playStream(Audio::Mixer::kPlainSoundType, &_mixerSoundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
-
return 0;
}
@@ -1471,7 +1466,8 @@ void MidiDriver_ADLIB::close() {
return;
_isOpen = false;
- _mixer->stopHandle(_mixerSoundHandle);
+ // Stop the OPL timer
+ _opl->stop();
uint i;
for (i = 0; i < ARRAYSIZE(_voices); ++i) {
@@ -1625,14 +1621,6 @@ void MidiDriver_ADLIB::adlibWriteSecondary(byte reg, byte value) {
}
#endif
-void MidiDriver_ADLIB::generateSamples(int16 *data, int len) {
- // Dummy implementation until we no longer inherit from MidiDriver_Emulated
-}
-
-int MidiDriver_ADLIB::readBuffer(int16 *data, const int numSamples) {
- return _opl->readBuffer(data, numSamples);
-}
-
void MidiDriver_ADLIB::onTimer() {
if (_adlibTimerProc)
(*_adlibTimerProc)(_adlibTimerParam);
@@ -2318,7 +2306,7 @@ MusicDevices AdLibEmuMusicPlugin::getDevices() const {
}
Common::Error AdLibEmuMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
- *mididriver = new MidiDriver_ADLIB(g_system->getMixer());
+ *mididriver = new MidiDriver_ADLIB();
return Common::kNoError;
}
diff --git a/audio/softsynth/opl/dosbox.cpp b/audio/softsynth/opl/dosbox.cpp
index 6e8b4a9..3d90ec9 100644
--- a/audio/softsynth/opl/dosbox.cpp
+++ b/audio/softsynth/opl/dosbox.cpp
@@ -177,10 +177,6 @@ bool OPL::init() {
_emulator->WriteReg(0x105, 1);
}
- // FIXME: Remove this once EmulatedOPL is actually controlling playback
- if (!_callback)
- start(0);
-
return true;
}
diff --git a/audio/softsynth/opl/mame.cpp b/audio/softsynth/opl/mame.cpp
index d43f638..696169b 100644
--- a/audio/softsynth/opl/mame.cpp
+++ b/audio/softsynth/opl/mame.cpp
@@ -61,9 +61,6 @@ bool OPL::init() {
_opl = MAME::makeAdLibOPL(g_system->getMixer()->getOutputRate());
- // FIXME: Remove this once EmulatedOPL is actually controlling playback
- start(0);
-
return (_opl != 0);
}
diff --git a/engines/agos/drivers/accolade/adlib.cpp b/engines/agos/drivers/accolade/adlib.cpp
index 33a7595..d227106 100644
--- a/engines/agos/drivers/accolade/adlib.cpp
+++ b/engines/agos/drivers/accolade/adlib.cpp
@@ -112,9 +112,9 @@ const uint16 frequencyLookUpTableMusicDrv[12] = {
//
// I have currently not implemented dynamic channel allocation.
-class MidiDriver_Accolade_AdLib : public MidiDriver_Emulated {
+class MidiDriver_Accolade_AdLib : public MidiDriver {
public:
- MidiDriver_Accolade_AdLib(Audio::Mixer *mixer);
+ MidiDriver_Accolade_AdLib();
virtual ~MidiDriver_Accolade_AdLib();
// MidiDriver
@@ -124,15 +124,8 @@ public:
MidiChannel *allocateChannel() { return NULL; }
MidiChannel *getPercussionChannel() { return NULL; }
- // AudioStream
- int readBuffer(int16 *data, const int numSamples);
- bool isStereo() const { return false; }
- int getRate() const { return _mixer->getOutputRate(); }
- int getPolyphony() const { return AGOS_ADLIB_VOICES_COUNT; }
- bool hasRhythmChannel() const { return false; }
-
- // MidiDriver_Emulated
- void generateSamples(int16 *buf, int len);
+ bool isOpen() const { return _isOpen; }
+ uint32 getBaseTempo() { return 1000000 / OPL::OPL::kDefaultCallbackFrequency; }
void setVolume(byte volume);
virtual uint32 property(int prop, uint32 param);
@@ -176,6 +169,8 @@ private:
Common::TimerManager::TimerProc _adlibTimerProc;
void *_adlibTimerParam;
+ bool _isOpen;
+
// points to a MIDI channel for each of the new voice channels
byte _voiceChannelMapping[AGOS_ADLIB_VOICES_COUNT];
@@ -196,9 +191,9 @@ private:
void noteOff(byte FMvoiceChannel, byte note, bool dontCheckNote);
};
-MidiDriver_Accolade_AdLib::MidiDriver_Accolade_AdLib(Audio::Mixer *mixer)
- : MidiDriver_Emulated(mixer), _masterVolume(15), _opl(0),
- _adlibTimerProc(0), _adlibTimerParam(0) {
+MidiDriver_Accolade_AdLib::MidiDriver_Accolade_AdLib()
+ : _masterVolume(15), _opl(0),
+ _adlibTimerProc(0), _adlibTimerParam(0), _isOpen(false) {
memset(_channelMapping, 0, sizeof(_channelMapping));
memset(_instrumentMapping, 0, sizeof(_instrumentMapping));
memset(_instrumentVolumeAdjust, 0, sizeof(_instrumentVolumeAdjust));
@@ -227,10 +222,9 @@ int MidiDriver_Accolade_AdLib::open() {
_opl->init();
- MidiDriver_Emulated::open();
+ _isOpen = true;
_opl->start(new Common::Functor0Mem<void, MidiDriver_Accolade_AdLib>(this, &MidiDriver_Accolade_AdLib::onTimer));
- _mixer->playStream(Audio::Mixer::kPlainSoundType, &_mixerSoundHandle, this, -1, _mixer->kMaxChannelVolume, 0, DisposeAfterUse::NO);
resetAdLib();
@@ -264,9 +258,8 @@ int MidiDriver_Accolade_AdLib::open() {
}
void MidiDriver_Accolade_AdLib::close() {
- _mixer->stopHandle(_mixerSoundHandle);
-
delete _opl;
+ _isOpen = false;
}
void MidiDriver_Accolade_AdLib::setVolume(byte volume) {
@@ -374,14 +367,6 @@ void MidiDriver_Accolade_AdLib::send(uint32 b) {
}
}
-void MidiDriver_Accolade_AdLib::generateSamples(int16 *data, int len) {
- // Dummy implementation until we no longer inherit from MidiDriver_Emulated
-}
-
-int MidiDriver_Accolade_AdLib::readBuffer(int16 *data, const int numSamples) {
- return _opl->readBuffer(data, numSamples);
-}
-
void MidiDriver_Accolade_AdLib::setTimerCallback(void *timerParam, Common::TimerManager::TimerProc timerProc) {
_adlibTimerProc = timerProc;
_adlibTimerParam = timerParam;
@@ -886,7 +871,7 @@ MidiDriver *MidiDriver_Accolade_AdLib_create(Common::String driverFilename) {
if (!driverData)
error("ACCOLADE-ADLIB: error during readDriver()");
- MidiDriver_Accolade_AdLib *driver = new MidiDriver_Accolade_AdLib(g_system->getMixer());
+ MidiDriver_Accolade_AdLib *driver = new MidiDriver_Accolade_AdLib();
if (driver) {
if (!driver->setupInstruments(driverData, driverDataSize, isMusicDrvFile)) {
delete driver;
diff --git a/engines/cine/sound.cpp b/engines/cine/sound.cpp
index a20ad5d..0c788b8 100644
--- a/engines/cine/sound.cpp
+++ b/engines/cine/sound.cpp
@@ -101,7 +101,7 @@ struct AdLibSoundInstrument {
byte amDepth;
};
-class AdLibSoundDriver : public PCSoundDriver, Audio::AudioStream {
+class AdLibSoundDriver : public PCSoundDriver {
public:
AdLibSoundDriver(Audio::Mixer *mixer);
virtual ~AdLibSoundDriver();
@@ -112,12 +112,6 @@ public:
virtual void stopChannel(int channel);
virtual void stopAll();
- // AudioStream interface
- virtual int readBuffer(int16 *buffer, const int numSamples);
- virtual bool isStereo() const { return false; }
- virtual bool endOfData() const { return false; }
- virtual int getRate() const { return _sampleRate; }
-
void initCard();
void onTimer();
void setupInstrument(const byte *data, int channel);
@@ -129,9 +123,7 @@ protected:
void *_upRef;
OPL::OPL *_opl;
- int _sampleRate;
Audio::Mixer *_mixer;
- Audio::SoundHandle _soundHandle;
byte _vibrato;
int _channelsVolumeTable[4];
@@ -283,7 +275,6 @@ void PCSoundDriver::resetChannel(int channel) {
AdLibSoundDriver::AdLibSoundDriver(Audio::Mixer *mixer)
: _upCb(0), _upRef(0), _mixer(mixer) {
- _sampleRate = _mixer->getOutputRate();
_opl = OPL::Config::create();
if (!_opl || !_opl->init())
error("Failed to create OPL");
@@ -292,11 +283,9 @@ AdLibSoundDriver::AdLibSoundDriver(Audio::Mixer *mixer)
memset(_instrumentsTable, 0, sizeof(_instrumentsTable));
initCard();
_opl->start(new Common::Functor0Mem<void, AdLibSoundDriver>(this, &AdLibSoundDriver::onTimer), 50);
- _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
}
AdLibSoundDriver::~AdLibSoundDriver() {
- _mixer->stopHandle(_soundHandle);
delete _opl;
}
@@ -346,10 +335,6 @@ void AdLibSoundDriver::stopAll() {
_opl->writeReg(0xBD, 0);
}
-int AdLibSoundDriver::readBuffer(int16 *buffer, const int numSamples) {
- return _opl->readBuffer(buffer, numSamples);
-}
-
void AdLibSoundDriver::initCard() {
_vibrato = 0x20;
_opl->writeReg(0xBD, _vibrato);
diff --git a/engines/cruise/sound.cpp b/engines/cruise/sound.cpp
index 7d48e6e..f57435f 100644
--- a/engines/cruise/sound.cpp
+++ b/engines/cruise/sound.cpp
@@ -108,7 +108,7 @@ struct VolumeEntry {
int adjusted;
};
-class AdLibSoundDriver : public PCSoundDriver, Audio::AudioStream {
+class AdLibSoundDriver : public PCSoundDriver {
public:
AdLibSoundDriver(Audio::Mixer *mixer);
virtual ~AdLibSoundDriver();
@@ -118,12 +118,6 @@ public:
virtual void stopChannel(int channel);
virtual void stopAll();
- // AudioStream interface
- virtual int readBuffer(int16 *buffer, const int numSamples);
- virtual bool isStereo() const { return false; }
- virtual bool endOfData() const { return false; }
- virtual int getRate() const { return _sampleRate; }
-
void initCard();
void onTimer();
void setupInstrument(const byte *data, int channel);
@@ -136,9 +130,7 @@ public:
protected:
OPL::OPL *_opl;
- int _sampleRate;
Audio::Mixer *_mixer;
- Audio::SoundHandle _soundHandle;
byte _vibrato;
VolumeEntry _channelsVolumeTable[5];
@@ -302,7 +294,6 @@ void PCSoundDriver::syncSounds() {
AdLibSoundDriver::AdLibSoundDriver(Audio::Mixer *mixer)
: _mixer(mixer) {
- _sampleRate = _mixer->getOutputRate();
_opl = OPL::Config::create();
if (!_opl || !_opl->init())
error("Failed to create OPL");
@@ -318,11 +309,9 @@ AdLibSoundDriver::AdLibSoundDriver(Audio::Mixer *mixer)
_sfxVolume = ConfMan.getBool("sfx_mute") ? 0 : MIN(255, ConfMan.getInt("sfx_volume"));
_opl->start(new Common::Functor0Mem<void, AdLibSoundDriver>(this, &AdLibSoundDriver::onTimer), 50);
- _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
}
AdLibSoundDriver::~AdLibSoundDriver() {
- _mixer->stopHandle(_soundHandle);
delete _opl;
}
@@ -390,10 +379,6 @@ void AdLibSoundDriver::stopAll() {
_opl->writeReg(0xBD, 0);
}
-int AdLibSoundDriver::readBuffer(int16 *buffer, const int numSamples) {
- return _opl->readBuffer(buffer, numSamples);
-}
-
void AdLibSoundDriver::initCard() {
_vibrato = 0x20;
_opl->writeReg(0xBD, _vibrato);
diff --git a/engines/gob/sound/adlib.cpp b/engines/gob/sound/adlib.cpp
index 866eecf..995cc48 100644
--- a/engines/gob/sound/adlib.cpp
+++ b/engines/gob/sound/adlib.cpp
@@ -118,8 +118,6 @@ const uint16 AdLib::kHihatParams [kParamCount] = {
AdLib::AdLib(Audio::Mixer &mixer, int callbackFreq) : _mixer(&mixer), _opl(0),
_toPoll(0), _repCount(0), _first(true), _playing(false), _ended(true), _volume(0) {
- _rate = _mixer->getOutputRate();
-
initFreqs();
createOPL();
@@ -128,13 +126,9 @@ AdLib::AdLib(Audio::Mixer &mixer, int callbackFreq) : _mixer(&mixer), _opl(0),
syncVolume();
_opl->start(new Common::Functor0Mem<void, AdLib>(this, &AdLib::onTimer), callbackFreq);
- _mixer->playStream(Audio::Mixer::kPlainSoundType, &_handle,
- this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
}
AdLib::~AdLib() {
- _mixer->stopHandle(_handle);
-
delete _opl;
}
@@ -168,10 +162,6 @@ void AdLib::createOPL() {
}
}
-int AdLib::readBuffer(int16 *buffer, const int numSamples) {
- return _opl->readBuffer(buffer, numSamples);
-}
-
void AdLib::onTimer() {
Common::StackLock slock(_mutex);
@@ -218,22 +208,6 @@ void AdLib::onTimer() {
}
}
-bool AdLib::isStereo() const {
- return _opl->isStereo();
-}
-
-bool AdLib::endOfData() const {
- return false;
-}
-
-bool AdLib::endOfStream() const {
- return false;
-}
-
-int AdLib::getRate() const {
- return _rate;
-}
-
bool AdLib::isPlaying() const {
return _playing;
}
diff --git a/engines/gob/sound/adlib.h b/engines/gob/sound/adlib.h
index 2c83b15..28ebf9d 100644
--- a/engines/gob/sound/adlib.h
+++ b/engines/gob/sound/adlib.h
@@ -35,7 +35,7 @@ namespace OPL {
namespace Gob {
/** Base class for a player of an AdLib music format. */
-class AdLib : public Audio::AudioStream {
+class AdLib {
public:
AdLib(Audio::Mixer &mixer, int callbackFrequency);
virtual ~AdLib();
@@ -55,13 +55,6 @@ public:
void stopPlay();
void syncVolume();
-// AudioStream API
- int readBuffer(int16 *buffer, const int numSamples);
- bool isStereo() const;
- bool endOfData() const;
- bool endOfStream() const;
- int getRate() const;
-
protected:
enum kVoice {
kVoiceMelody0 = 0,
@@ -233,7 +226,6 @@ private:
Audio::Mixer *_mixer;
- Audio::SoundHandle _handle;
OPL::OPL *_opl;
Common::Mutex _mutex;
diff --git a/engines/gob/sound/musplayer.cpp b/engines/gob/sound/musplayer.cpp
index bf90d44..2c0330e 100644
--- a/engines/gob/sound/musplayer.cpp
+++ b/engines/gob/sound/musplayer.cpp
@@ -57,8 +57,12 @@ uint32 MUSPlayer::pollMusic(bool first) {
return 0;
}
- if (first)
+ if (first) {
+ // Set the timer frequency on first run.
+ // Do not set it in rewind() for thread safety reasons.
+ setTimerFrequency((_ticksPerBeat * _tempo) / 60);
return *_playPos++;
+ }
uint16 delay = 0;
while (delay == 0) {
@@ -185,8 +189,6 @@ void MUSPlayer::rewind() {
setPercussionMode(_soundMode != 0);
setPitchRange(_pitchBendRange);
-
- setTimerFrequency((_ticksPerBeat * _tempo) / 60);
}
bool MUSPlayer::loadSND(Common::SeekableReadStream &snd) {
diff --git a/engines/kyra/sound_adlib.cpp b/engines/kyra/sound_adlib.cpp
index 999bd96..1d741d8 100644
--- a/engines/kyra/sound_adlib.cpp
+++ b/engines/kyra/sound_adlib.cpp
@@ -55,7 +55,7 @@
namespace Kyra {
-class AdLibDriver : public Audio::AudioStream {
+class AdLibDriver {
public:
AdLibDriver(Audio::Mixer *mixer, int version);
~AdLibDriver();
@@ -70,16 +70,6 @@ public:
void callback();
- // AudioStream API
- int readBuffer(int16 *buffer, const int numSamples) {
- return _adlib->readBuffer(buffer, numSamples);
- }
-
-
- bool isStereo() const { return false; }
- bool endOfData() const { return false; }
- int getRate() const { return _mixer->getOutputRate(); }
-
void setSyncJumpMask(uint16 mask) { _syncJumpMask = mask; }
void setMusicVolume(uint8 volume);
@@ -388,7 +378,6 @@ private:
Common::Mutex _mutex;
Audio::Mixer *_mixer;
- Audio::SoundHandle _soundHandle;
uint8 _musicVolume, _sfxVolume;
@@ -440,11 +429,9 @@ AdLibDriver::AdLibDriver(Audio::Mixer *mixer, int version) {
_retrySounds = false;
_adlib->start(new Common::Functor0Mem<void, AdLibDriver>(this, &AdLibDriver::callback), CALLBACKS_PER_SECOND);
- _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
}
AdLibDriver::~AdLibDriver() {
- _mixer->stopHandle(_soundHandle);
delete _adlib;
_adlib = 0;
}
diff --git a/engines/mads/nebular/sound_nebular.cpp b/engines/mads/nebular/sound_nebular.cpp
index 0a1c1ea..711f82a 100644
--- a/engines/mads/nebular/sound_nebular.cpp
+++ b/engines/mads/nebular/sound_nebular.cpp
@@ -213,16 +213,12 @@ ASound::ASound(Audio::Mixer *mixer, OPL::OPL *opl, const Common::String &filenam
command0();
_opl->start(new Common::Functor0Mem<void, ASound>(this, &ASound::onTimer), CALLBACKS_PER_SECOND);
- _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1,
- Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
}
ASound::~ASound() {
Common::List<CachedDataEntry>::iterator i;
for (i = _dataCache.begin(); i != _dataCache.end(); ++i)
delete[] (*i)._data;
-
- _mixer->stopHandle(_soundHandle);
}
void ASound::validate() {
@@ -828,20 +824,12 @@ void ASound::updateFNumber() {
write2(8, hiReg, val2);
}
-int ASound::readBuffer(int16 *data, const int numSamples) {
- return _opl->readBuffer(data, numSamples);
-}
-
void ASound::onTimer() {
Common::StackLock slock(_driverMutex);
poll();
flush();
}
-int ASound::getRate() const {
- return g_system->getMixer()->getOutputRate();
-}
-
void ASound::setVolume(int volume) {
_masterVolume = volume;
if (!volume)
diff --git a/engines/mads/nebular/sound_nebular.h b/engines/mads/nebular/sound_nebular.h
index 1267914..2b80b08 100644
--- a/engines/mads/nebular/sound_nebular.h
+++ b/engines/mads/nebular/sound_nebular.h
@@ -145,7 +145,7 @@ struct CachedDataEntry {
/**
* Base class for the sound player resource files
*/
-class ASound : public Audio::AudioStream {
+class ASound {
private:
Common::List<CachedDataEntry> _dataCache;
uint16 _randomSeed;
@@ -282,7 +282,6 @@ protected:
public:
Audio::Mixer *_mixer;
OPL::OPL *_opl;
- Audio::SoundHandle _soundHandle;
AdlibChannel _channels[ADLIB_CHANNEL_COUNT];
AdlibChannel *_activeChannelPtr;
AdlibChannelData _channelData[11];
@@ -367,27 +366,6 @@ public:
*/
CachedDataEntry &getCachedData(byte *pData);
- // AudioStream interface
- /**
- * Main buffer read
- */
- virtual int readBuffer(int16 *buffer, const int numSamples);
-
- /**
- * Mono sound only
- */
- virtual bool isStereo() const { return false; }
-
- /**
- * Data is continuously pushed, so definitive end
- */
- virtual bool endOfData() const { return false; }
-
- /**
- * Return sample rate
- */
- virtual int getRate() const;
-
/**
* Set the volume
*/
diff --git a/engines/parallaction/adlib.cpp b/engines/parallaction/adlib.cpp
index 302530b..568ad19 100644
--- a/engines/parallaction/adlib.cpp
+++ b/engines/parallaction/adlib.cpp
@@ -25,7 +25,7 @@
#include "audio/fmopl.h"
#include "audio/mpu401.h"
-#include "audio/softsynth/emumidi.h"
+#include "audio/mididrv.h"
namespace Parallaction {
@@ -270,11 +270,13 @@ struct MelodicVoice {
int8 _octave;
};
-class AdLibDriver : public MidiDriver_Emulated {
+class AdLibDriver : public MidiDriver {
public:
- AdLibDriver(Audio::Mixer *mixer) : MidiDriver_Emulated(mixer) {
+ AdLibDriver(Audio::Mixer *mixer) {
for (uint i = 0; i < 16; ++i)
_channels[i].init(this, i);
+
+ _isOpen = false;
}
int open();
@@ -282,12 +284,9 @@ public:
void send(uint32 b);
MidiChannel *allocateChannel();
MidiChannel *getPercussionChannel() { return &_channels[9]; }
+ bool isOpen() const { return _isOpen; }
+ uint32 getBaseTempo() { return 1000000 / OPL::OPL::kDefaultCallbackFrequency; }
- bool isStereo() const { return false; }
- int getRate() const { return _mixer->getOutputRate(); }
- int readBuffer(int16 *data, const int numSamples);
-
- void generateSamples(int16 *buf, int len) {}
virtual void setTimerCallback(void *timerParam, Common::TimerManager::TimerProc timerProc) {
_adlibTimerProc = timerProc;
_adlibTimerParam = timerParam;
@@ -331,6 +330,7 @@ private:
Common::TimerManager::TimerProc _adlibTimerProc;
void *_adlibTimerParam;
+ bool _isOpen;
};
MidiDriver *createAdLibDriver() {
@@ -359,7 +359,7 @@ int AdLibDriver::open() {
if (_isOpen)
return MERR_ALREADY_OPEN;
- MidiDriver_Emulated::open();
+ _isOpen = true;
_opl = OPL::Config::create();
_opl->init();
@@ -376,7 +376,6 @@ int AdLibDriver::open() {
initVoices();
_opl->start(new Common::Functor0Mem<void, AdLibDriver>(this, &AdLibDriver::onTimer));
- _mixer->playStream(Audio::Mixer::kMusicSoundType, &_mixerSoundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
return 0;
}
@@ -385,7 +384,6 @@ void AdLibDriver::close() {
return;
_isOpen = false;
- _mixer->stopHandle(_mixerSoundHandle);
delete _opl;
}
@@ -789,10 +787,6 @@ MidiChannel *AdLibDriver::allocateChannel() {
return NULL;
}
-int AdLibDriver::readBuffer(int16 *data, const int numSamples) {
- return _opl->readBuffer(data, numSamples);
-}
-
void AdLibDriver::onTimer() {
if (_adlibTimerProc)
(*_adlibTimerProc)(_adlibTimerParam);
diff --git a/engines/queen/midiadlib.cpp b/engines/queen/midiadlib.cpp
index 457767a..f5bc0f4 100644
--- a/engines/queen/midiadlib.cpp
+++ b/engines/queen/midiadlib.cpp
@@ -28,7 +28,7 @@
namespace Queen {
int AdLibMidiDriver::open() {
- MidiDriver_Emulated::open();
+ _isOpen = true;
_opl = OPL::Config::create();
if (!_opl || !_opl->init())
error("Failed to create OPL");
@@ -41,12 +41,10 @@ int AdLibMidiDriver::open() {
}
_opl->start(new Common::Functor0Mem<void, AdLibMidiDriver>(this, &AdLibMidiDriver::onTimer));
- _mixer->playStream(Audio::Mixer::kPlainSoundType, &_mixerSoundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
return 0;
}
void AdLibMidiDriver::close() {
- _mixer->stopHandle(_mixerSoundHandle);
delete _opl;
}
@@ -110,14 +108,6 @@ void AdLibMidiDriver::metaEvent(byte type, byte *data, uint16 length) {
warning("Unhandled meta event %d len %d", event, length);
}
-void AdLibMidiDriver::generateSamples(int16 *data, int len) {
- // Dummy implementation
-}
-
-int AdLibMidiDriver::readBuffer(int16 *data, const int numSamples) {
- return _opl->readBuffer(data, numSamples);
-}
-
void AdLibMidiDriver::setTimerCallback(void *timerParam, Common::TimerManager::TimerProc timerProc) {
_adlibTimerProc = timerProc;
_adlibTimerParam = timerParam;
diff --git a/engines/queen/midiadlib.h b/engines/queen/midiadlib.h
index d559025..8692e51 100644
--- a/engines/queen/midiadlib.h
+++ b/engines/queen/midiadlib.h
@@ -22,14 +22,17 @@
#include "audio/fmopl.h"
#include "audio/mididrv.h"
-#include "audio/softsynth/emumidi.h"
namespace Queen {
-class AdLibMidiDriver : public MidiDriver_Emulated {
+class AdLibMidiDriver : public MidiDriver {
public:
- AdLibMidiDriver(Audio::Mixer *mixer) : MidiDriver_Emulated(mixer) { _adlibWaveformSelect = 0; }
+ AdLibMidiDriver() {
+ _adlibWaveformSelect = 0;
+ _isOpen = false;
+ }
+
~AdLibMidiDriver() {}
// MidiDriver
@@ -40,14 +43,8 @@ public:
MidiChannel *allocateChannel() { return 0; }
MidiChannel *getPercussionChannel() { return 0; }
void setTimerCallback(void *timerParam, Common::TimerManager::TimerProc timerProc);
-
- // AudioStream
- int readBuffer(int16 *data, const int numSamples);
- bool isStereo() const { return false; }
- int getRate() const { return _mixer->getOutputRate(); }
-
- // MidiDriver_Emulated
- void generateSamples(int16 *buf, int len);
+ bool isOpen() const { return _isOpen; }
+ uint32 getBaseTempo() { return 1000000 / OPL::OPL::kDefaultCallbackFrequency; }
void setVolume(uint32 volume);
@@ -74,8 +71,8 @@ private:
void adlibTurnNoteOn(int channel, int note);
void adlibSetupChannelFromSequence(int channel, const uint8 *src, int fl);
void adlibSetupChannel(int channel, const uint16 *src, int fl);
- void adlibSetChannelVolume(int channel, uint8 volume);
void adlibSetNoteVolume(int channel, int volume);
+ void adlibSetChannelVolume(int channel, uint8 volume);
void adlibSetupChannelHelper(int channel);
void adlibSetChannel0x40(int channel);
void adlibSetChannel0xC0(int channel);
@@ -106,6 +103,7 @@ private:
uint16 _adlibMetaSequenceData[28];
uint8 _adlibChannelsVolumeTable[11];
+ bool _isOpen;
Common::TimerManager::TimerProc _adlibTimerProc;
void *_adlibTimerParam;
diff --git a/engines/queen/music.cpp b/engines/queen/music.cpp
index 600956a..9f74aab 100644
--- a/engines/queen/music.cpp
+++ b/engines/queen/music.cpp
@@ -68,7 +68,7 @@ MidiMusic::MidiMusic(QueenEngine *vm)
// if (READ_LE_UINT16(_musicData + 2) != infoOffset) {
// defaultAdLibVolume = _musicData[infoOffset];
// }
- _driver = new AdLibMidiDriver(g_system->getMixer());
+ _driver = new AdLibMidiDriver();
} else {
_driver = MidiDriver::createMidi(dev);
if (_nativeMT32) {
diff --git a/engines/sci/sound/drivers/adlib.cpp b/engines/sci/sound/drivers/adlib.cpp
index 7035435..aac8a0d 100644
--- a/engines/sci/sound/drivers/adlib.cpp
+++ b/engines/sci/sound/drivers/adlib.cpp
@@ -27,7 +27,7 @@
#include "common/textconsole.h"
#include "audio/fmopl.h"
-#include "audio/softsynth/emumidi.h"
+#include "audio/mididrv.h"
#include "sci/resource.h"
#include "sci/sound/drivers/mididriver.h"
@@ -43,30 +43,27 @@ namespace Sci {
// FIXME: We don't seem to be sending the polyphony init data, so disable this for now
#define ADLIB_DISABLE_VOICE_MAPPING
-class MidiDriver_AdLib : public MidiDriver_Emulated {
+class MidiDriver_AdLib : public MidiDriver {
public:
enum {
kVoices = 9,
kRhythmKeys = 62
};
- MidiDriver_AdLib(Audio::Mixer *mixer) : MidiDriver_Emulated(mixer), _playSwitch(true), _masterVolume(15), _rhythmKeyMap(0), _opl(0) { }
+ MidiDriver_AdLib(Audio::Mixer *mixer) :_playSwitch(true), _masterVolume(15), _rhythmKeyMap(0), _opl(0), _isOpen(false) { }
virtual ~MidiDriver_AdLib() { }
// MidiDriver
+ int open() { return -1; } // Dummy implementation (use openAdLib)
int openAdLib(bool isSCI0);
void close();
void send(uint32 b);
MidiChannel *allocateChannel() { return NULL; }
MidiChannel *getPercussionChannel() { return NULL; }
+ bool isOpen() const { return _isOpen; }
+ uint32 getBaseTempo() { return 1000000 / OPL::OPL::kDefaultCallbackFrequency; }
- // AudioStream
- int readBuffer(int16 *data, const int numSamples);
- bool isStereo() const { return _stereo; }
- int getRate() const { return _mixer->getOutputRate(); }
-
- // MidiDriver_Emulated
- void generateSamples(int16 *buf, int len);
+ // MidiDriver
void setTimerCallback(void *timerParam, Common::TimerManager::TimerProc timerProc);
void onTimer();
@@ -137,6 +134,7 @@ private:
bool _stereo;
bool _isSCI0;
OPL::OPL *_opl;
+ bool _isOpen;
bool _playSwitch;
int _masterVolume;
Channel _channels[MIDI_CHANNELS];
@@ -227,7 +225,7 @@ int MidiDriver_AdLib::openAdLib(bool isSCI0) {
debug(3, "ADLIB: Starting driver in %s mode", (isSCI0 ? "SCI0" : "SCI1"));
_isSCI0 = isSCI0;
- _opl = OPL::Config::create(isStereo() ? OPL::Config::kDualOpl2 : OPL::Config::kOpl2);
+ _opl = OPL::Config::create(_stereo ? OPL::Config::kDualOpl2 : OPL::Config::kOpl2);
// Try falling back to mono, thus plain OPL2 emualtor, when no Dual OPL2 is available.
if (!_opl && _stereo) {
@@ -244,17 +242,14 @@ int MidiDriver_AdLib::openAdLib(bool isSCI0) {
setRegister(0x08, 0);
setRegister(0x01, 0x20);
- MidiDriver_Emulated::open();
+ _isOpen = true;
_opl->start(new Common::Functor0Mem<void, MidiDriver_AdLib>(this, &MidiDriver_AdLib::onTimer));
- _mixer->playStream(Audio::Mixer::kPlainSoundType, &_mixerSoundHandle, this, -1, _mixer->kMaxChannelVolume, 0, DisposeAfterUse::NO);
return 0;
}
void MidiDriver_AdLib::close() {
- _mixer->stopHandle(_mixerSoundHandle);
-
delete _opl;
delete[] _rhythmKeyMap;
}
@@ -331,14 +326,6 @@ void MidiDriver_AdLib::send(uint32 b) {
}
}
-int MidiDriver_AdLib::readBuffer(int16 *data, const int numSamples) {
- return _opl->readBuffer(data, numSamples);
-}
-
-void MidiDriver_AdLib::generateSamples(int16 *data, int len) {
- // Dummy implementation
-}
-
void MidiDriver_AdLib::setTimerCallback(void *timerParam, Common::TimerManager::TimerProc timerProc) {
_adlibTimerProc = timerProc;
_adlibTimerParam = timerParam;
@@ -702,7 +689,7 @@ void MidiDriver_AdLib::setVelocityReg(int regOffset, int velocity, int kbScaleLe
if (!_playSwitch)
velocity = 0;
- if (isStereo()) {
+ if (_stereo) {
int velLeft = velocity;
int velRight = velocity;
@@ -752,7 +739,7 @@ void MidiDriver_AdLib::setRegister(int reg, int value, int channels) {
_opl->write(0x221, value);
}
- if (isStereo()) {
+ if (_stereo) {
if (channels & kRightChannel) {
_opl->write(0x222, reg);
_opl->write(0x223, value);
diff --git a/engines/scumm/players/player_ad.cpp b/engines/scumm/players/player_ad.cpp
index ea59a22..5c0d443 100644
--- a/engines/scumm/players/player_ad.cpp
+++ b/engines/scumm/players/player_ad.cpp
@@ -36,7 +36,7 @@ namespace Scumm {
#define AD_CALLBACK_FREQUENCY 472
Player_AD::Player_AD(ScummEngine *scumm, Audio::Mixer *mixer)
- : _vm(scumm), _mixer(mixer), _rate(mixer->getOutputRate()) {
+ : _vm(scumm), _mixer(mixer) {
_opl2 = OPL::Config::create();
if (!_opl2->init()) {
error("Could not initialize OPL2 emulator");
@@ -73,12 +73,9 @@ Player_AD::Player_AD(ScummEngine *scumm, Audio::Mixer *mixer)
_isSeeking = false;
_opl2->start(new Common::Functor0Mem<void, Player_AD>(this, &Player_AD::onTimer), AD_CALLBACK_FREQUENCY);
- _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
}
Player_AD::~Player_AD() {
- _mixer->stopHandle(_soundHandle);
-
stopAllSounds();
Common::StackLock lock(_mutex);
delete _opl2;
@@ -250,10 +247,6 @@ void Player_AD::onTimer() {
updateSfx();
}
-int Player_AD::readBuffer(int16 *buffer, const int numSamples) {
- return _opl2->readBuffer(buffer, numSamples);
-}
-
void Player_AD::setupVolume() {
// Setup the correct volume
_musicVolume = CLIP<int>(ConfMan.getInt("music_volume"), 0, Audio::Mixer::kMaxChannelVolume);
diff --git a/engines/scumm/players/player_ad.h b/engines/scumm/players/player_ad.h
index 9662b08..b8cd8dc 100644
--- a/engines/scumm/players/player_ad.h
+++ b/engines/scumm/players/player_ad.h
@@ -41,7 +41,7 @@ class ScummEngine;
/**
* Sound output for v3/v4 AdLib data.
*/
-class Player_AD : public MusicEngine, public Audio::AudioStream {
+class Player_AD : public MusicEngine {
public:
Player_AD(ScummEngine *scumm, Audio::Mixer *mixer);
virtual ~Player_AD();
@@ -56,12 +56,6 @@ public:
virtual void saveLoadWithSerializer(Serializer *ser);
- // AudioStream API
- virtual int readBuffer(int16 *buffer, const int numSamples);
- virtual bool isStereo() const { return false; }
- virtual bool endOfData() const { return false; }
- virtual int getRate() const { return _rate; }
-
// Timer callback
void onTimer();
@@ -69,8 +63,6 @@ private:
ScummEngine *const _vm;
Common::Mutex _mutex;
Audio::Mixer *const _mixer;
- const int _rate;
- Audio::SoundHandle _soundHandle;
void setupVolume();
int _musicVolume;
diff --git a/engines/sherlock/scalpel/drivers/adlib.cpp b/engines/sherlock/scalpel/drivers/adlib.cpp
index 033b474..29a39f0 100644
--- a/engines/sherlock/scalpel/drivers/adlib.cpp
+++ b/engines/sherlock/scalpel/drivers/adlib.cpp
@@ -216,11 +216,11 @@ uint16 frequencyLookUpTable[SHERLOCK_ADLIB_NOTES_COUNT] = {
0x1DE6, 0x1E03, 0x1E22, 0x1E42, 0x1E65, 0x1E89
};
-class MidiDriver_SH_AdLib : public MidiDriver_Emulated {
+class MidiDriver_SH_AdLib : public MidiDriver {
public:
MidiDriver_SH_AdLib(Audio::Mixer *mixer)
- : MidiDriver_Emulated(mixer), _masterVolume(15), _opl(0),
- _adlibTimerProc(0), _adlibTimerParam(0) {
+ : _masterVolume(15), _opl(0),
+ _adlibTimerProc(0), _adlibTimerParam(0), _isOpen(false) {
memset(_voiceChannelMapping, 0, sizeof(_voiceChannelMapping));
}
virtual ~MidiDriver_SH_AdLib() { }
@@ -231,17 +231,12 @@ public:
void send(uint32 b);
MidiChannel *allocateChannel() { return NULL; }
MidiChannel *getPercussionChannel() { return NULL; }
+ bool isOpen() const { return _isOpen; }
+ uint32 getBaseTempo() { return 1000000 / OPL::OPL::kDefaultCallbackFrequency; }
- // AudioStream
- int readBuffer(int16 *data, const int numSamples);
- bool isStereo() const { return false; }
- int getRate() const { return _mixer->getOutputRate(); }
int getPolyphony() const { return SHERLOCK_ADLIB_VOICES_COUNT; }
bool hasRhythmChannel() const { return false; }
- // MidiDriver_Emulated
- void generateSamples(int16 *buf, int len);
-
virtual void setTimerCallback(void *timerParam, Common::TimerManager::TimerProc timerProc);
void setVolume(byte volume);
@@ -268,6 +263,8 @@ private:
Common::TimerManager::TimerProc _adlibTimerProc;
void *_adlibTimerParam;
+ bool _isOpen;
+
// points to a MIDI channel for each of the new voice channels
byte _voiceChannelMapping[SHERLOCK_ADLIB_VOICES_COUNT];
@@ -299,16 +296,16 @@ int MidiDriver_SH_AdLib::open() {
_opl->init();
- MidiDriver_Emulated::open();
+ _isOpen = true;
_opl->start(new Common::Functor0Mem<void, MidiDriver_SH_AdLib>(this, &MidiDriver_SH_AdLib::onTimer));
- _mixer->playStream(Audio::Mixer::kPlainSoundType, &_mixerSoundHandle, this, -1, _mixer->kMaxChannelVolume, 0, DisposeAfterUse::NO);
return 0;
}
void MidiDriver_SH_AdLib::close() {
- _mixer->stopHandle(_mixerSoundHandle);
+ // Stop the OPL timer
+ _opl->stop();
delete _opl;
}
@@ -427,14 +424,6 @@ void MidiDriver_SH_AdLib::send(uint32 b) {
}
}
-void MidiDriver_SH_AdLib::generateSamples(int16 *data, int len) {
- // Dummy implementation until we no longer inherit from MidiDriver_Emulated
-}
-
-int MidiDriver_SH_AdLib::readBuffer(int16 *data, const int numSamples) {
- return _opl->readBuffer(data, numSamples);
-}
-
void MidiDriver_SH_AdLib::noteOn(byte MIDIchannel, byte note, byte velocity) {
int16 oldestInUseChannel = -1;
uint16 oldestInUseTimer = 0;
diff --git a/engines/sky/music/adlibmusic.cpp b/engines/sky/music/adlibmusic.cpp
index 3607dfb..be5e7b2 100644
--- a/engines/sky/music/adlibmusic.cpp
+++ b/engines/sky/music/adlibmusic.cpp
@@ -33,25 +33,18 @@ namespace Sky {
AdLibMusic::AdLibMusic(Audio::Mixer *pMixer, Disk *pDisk) : MusicBase(pMixer, pDisk) {
_driverFileBase = 60202;
- _sampleRate = pMixer->getOutputRate();
_opl = OPL::Config::create();
if (!_opl || !_opl->init())
error("Failed to create OPL");
_opl->start(new Common::Functor0Mem<void, AdLibMusic>(this, &AdLibMusic::onTimer), 50);
- _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
}
AdLibMusic::~AdLibMusic() {
- _mixer->stopHandle(_soundHandle);
delete _opl;
}
-int AdLibMusic::readBuffer(int16 *data, const int numSamples) {
- return _opl->readBuffer(data, numSamples);
-}
-
void AdLibMusic::onTimer() {
if (_musicData != NULL)
pollMusic();
@@ -97,16 +90,4 @@ void AdLibMusic::setVolume(uint16 param) {
_channels[cnt]->updateVolume(_musicVolume);
}
-bool AdLibMusic::isStereo() const {
- return false;
-}
-
-bool AdLibMusic::endOfData() const {
- return false;
-}
-
-int AdLibMusic::getRate() const {
- return _sampleRate;
-}
-
} // End of namespace Sky
diff --git a/engines/sky/music/adlibmusic.h b/engines/sky/music/adlibmusic.h
index fe2e5ac..7b51f2d 100644
--- a/engines/sky/music/adlibmusic.h
+++ b/engines/sky/music/adlibmusic.h
@@ -32,21 +32,16 @@ class OPL;
namespace Sky {
-class AdLibMusic : public Audio::AudioStream, public MusicBase {
+class AdLibMusic : public MusicBase {
public:
AdLibMusic(Audio::Mixer *pMixer, Disk *pDisk);
~AdLibMusic();
// AudioStream API
- int readBuffer(int16 *buffer, const int numSamples);
- bool isStereo() const;
- bool endOfData() const;
- int getRate() const;
virtual void setVolume(uint16 param);
private:
OPL::OPL *_opl;
- Audio::SoundHandle _soundHandle;
uint8 *_initSequence;
uint32 _sampleRate;
virtual void setupPointers();
diff --git a/engines/tsage/sound.cpp b/engines/tsage/sound.cpp
index ddfaa0a..0d3fb55 100644
--- a/engines/tsage/sound.cpp
+++ b/engines/tsage/sound.cpp
@@ -2743,7 +2743,6 @@ AdlibSoundDriver::AdlibSoundDriver(): SoundDriver() {
_groupData._pData = &adlib_group_data[0];
_mixer = g_vm->_mixer;
- _sampleRate = _mixer->getOutputRate();
_opl = OPL::Config::create();
assert(_opl);
_opl->init();
@@ -2767,12 +2766,10 @@ AdlibSoundDriver::AdlibSoundDriver(): SoundDriver() {
}
_opl->start(new Common::Functor0Mem<void, AdlibSoundDriver>(this, &AdlibSoundDriver::onTimer), CALLBACKS_PER_SECOND);
- _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
}
AdlibSoundDriver::~AdlibSoundDriver() {
DEALLOCATE(_patchData);
- _mixer->stopHandle(_soundHandle);
delete _opl;
}
@@ -3015,10 +3012,6 @@ void AdlibSoundDriver::setFrequency(int channel) {
((dataWord >> 8) & 3) | (var2 << 2));
}
-int AdlibSoundDriver::readBuffer(int16 *data, const int numSamples) {
- return _opl->readBuffer(data, numSamples);
-}
-
void AdlibSoundDriver::onTimer() {
Common::StackLock slock1(SoundManager::sfManager()._serverDisabledMutex);
Common::StackLock slock2(SoundManager::sfManager()._serverSuspendedMutex);
diff --git a/engines/tsage/sound.h b/engines/tsage/sound.h
index 7ea1e65..68755a4 100644
--- a/engines/tsage/sound.h
+++ b/engines/tsage/sound.h
@@ -449,13 +449,11 @@ public:
#define ADLIB_CHANNEL_COUNT 9
-class AdlibSoundDriver: public SoundDriver, Audio::AudioStream {
+class AdlibSoundDriver: public SoundDriver {
private:
GroupData _groupData;
Audio::Mixer *_mixer;
OPL::OPL *_opl;
- Audio::SoundHandle _soundHandle;
- int _sampleRate;
byte _portContents[256];
const byte *_patchData;
int _masterVolume;
@@ -494,12 +492,6 @@ public:
virtual void proc38(int channel, int cmd, int value);
virtual void setPitch(int channel, int pitchBlend);
- // AudioStream interface
- virtual int readBuffer(int16 *data, const int numSamples);
- virtual bool isStereo() const { return false; }
- virtual bool endOfData() const { return false; }
- virtual int getRate() const { return _sampleRate; }
-
private:
void onTimer();
};
Commit: 4d5658511228328a9e56d32448f9b598ecda696c
https://github.com/scummvm/scummvm/commit/4d5658511228328a9e56d32448f9b598ecda696c
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-07-07T20:19:47-04:00
Commit Message:
AUDIO: Add a class representing a real OPL
Changed paths:
audio/fmopl.cpp
audio/fmopl.h
diff --git a/audio/fmopl.cpp b/audio/fmopl.cpp
index 4bc902e..b0b3273 100644
--- a/audio/fmopl.cpp
+++ b/audio/fmopl.cpp
@@ -29,6 +29,7 @@
#include "common/config-manager.h"
#include "common/system.h"
#include "common/textconsole.h"
+#include "common/timer.h"
#include "common/translation.h"
namespace OPL {
@@ -185,6 +186,63 @@ void OPL::stop() {
bool OPL::_hasInstance = false;
+RealOPL::RealOPL() : _baseFreq(0), _remainingTicks(0) {
+}
+
+RealOPL::~RealOPL() {
+ // Stop callbacks, just in case. If it's still playing at this
+ // point, there's probably a bigger issue, though. The subclass
+ // needs to call stop() or the pointer can still use be used in
+ // the mixer thread at the same time.
+ stop();
+}
+
+void RealOPL::setCallbackFrequency(int timerFrequency) {
+ stopCallbacks();
+ startCallbacks(timerFrequency);
+}
+
+void RealOPL::startCallbacks(int timerFrequency) {
+ _baseFreq = timerFrequency;
+ assert(_baseFreq > 0);
+
+ // We can't request more a timer faster than 100Hz. We'll handle this by calling
+ // the proc multiple times in onTimer() later on.
+ if (timerFrequency > kMaxFreq)
+ timerFrequency = kMaxFreq;
+
+ _remainingTicks = 0;
+ g_system->getTimerManager()->installTimerProc(timerProc, 1000000 / timerFrequency, this, "RealOPL");
+}
+
+void RealOPL::stopCallbacks() {
+ g_system->getTimerManager()->removeTimerProc(timerProc);
+ _baseFreq = 0;
+ _remainingTicks = 0;
+}
+
+void RealOPL::timerProc(void *refCon) {
+ static_cast<RealOPL *>(refCon)->onTimer();
+}
+
+void RealOPL::onTimer() {
+ uint callbacks = 1;
+
+ if (_baseFreq > kMaxFreq) {
+ // We run faster than our max, so run the callback multiple
+ // times to approximate the actual timer callback frequency.
+ uint totalTicks = _baseFreq + _remainingTicks;
+ callbacks = totalTicks / kMaxFreq;
+ _remainingTicks = totalTicks % kMaxFreq;
+ }
+
+ // Call the callback multiple times. The if is on the inside of the
+ // loop in case the callback removes itself.
+ for (uint i = 0; i < callbacks; i++)
+ if (_callback && _callback->isValid())
+ (*_callback)();
+}
+
EmulatedOPL::EmulatedOPL() :
_nextTick(0),
_samplesPerTick(0),
diff --git a/audio/fmopl.h b/audio/fmopl.h
index 091e0bd..ba0872d 100644
--- a/audio/fmopl.h
+++ b/audio/fmopl.h
@@ -106,8 +106,14 @@ private:
static const EmulatorDescription _drivers[];
};
+/**
+ * The type of the OPL timer callback functor.
+ */
typedef Common::Functor0<void> TimerCallback;
+/**
+ * A representation of a Yamaha OPL chip.
+ */
class OPL {
private:
static bool _hasInstance;
@@ -194,6 +200,43 @@ protected:
Common::ScopedPtr<TimerCallback> _callback;
};
+/**
+ * An OPL that represents a real OPL, as opposed to an emulated one.
+ *
+ * This will use an actual timer instead of using one calculated from
+ * the number of samples in an AudioStream::readBuffer call.
+ */
+class RealOPL : public OPL {
+public:
+ RealOPL();
+ virtual ~RealOPL();
+
+ // OPL API
+ void setCallbackFrequency(int timerFrequency);
+
+protected:
+ // OPL API
+ void startCallbacks(int timerFrequency);
+ void stopCallbacks();
+
+private:
+ static void timerProc(void *refCon);
+ void onTimer();
+
+ uint _baseFreq;
+ uint _remainingTicks;
+
+ enum {
+ kMaxFreq = 100
+ };
+};
+
+/**
+ * An OPL that represents an emulated OPL.
+ *
+ * This will send callbacks based on the number of samples
+ * decoded in readBuffer().
+ */
class EmulatedOPL : public OPL, protected Audio::AudioStream {
public:
EmulatedOPL();
Commit: a45ff5a6a94e6ace8528ac6bb157f7045f43c3b4
https://github.com/scummvm/scummvm/commit/a45ff5a6a94e6ace8528ac6bb157f7045f43c3b4
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-07-07T20:19:47-04:00
Commit Message:
CONFIGURE: Ensure the USE_ALSA define ends up in config.mk
Changed paths:
configure
diff --git a/configure b/configure
index 78f147f..48dfdbd 100755
--- a/configure
+++ b/configure
@@ -3556,7 +3556,7 @@ if test "$_alsa" = yes ; then
LIBS="$LIBS $ALSA_LIBS -lasound"
INCLUDES="$INCLUDES $ALSA_CFLAGS"
fi
-define_in_config_h_if_yes "$_alsa" 'USE_ALSA'
+define_in_config_if_yes "$_alsa" 'USE_ALSA'
echo "$_alsa"
#
Commit: 40820eebf561d1a7c35f07151d534253ad2a7ea5
https://github.com/scummvm/scummvm/commit/40820eebf561d1a7c35f07151d534253ad2a7ea5
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2015-07-07T20:19:47-04:00
Commit Message:
AUDIO: Add experimental hardware OPL support using ALSA
Changed paths:
A audio/softsynth/opl/alsa.cpp
audio/fmopl.cpp
audio/module.mk
diff --git a/audio/fmopl.cpp b/audio/fmopl.cpp
index b0b3273..ded4506 100644
--- a/audio/fmopl.cpp
+++ b/audio/fmopl.cpp
@@ -34,12 +34,21 @@
namespace OPL {
+// Factory functions
+
+#ifdef USE_ALSA
+namespace ALSA {
+ OPL *create(Config::OplType type);
+} // End of namespace ALSA
+#endif // USE_ALSA
+
// Config implementation
enum OplEmulator {
kAuto = 0,
kMame = 1,
- kDOSBox = 2
+ kDOSBox = 2,
+ kALSA = 3
};
OPL::OPL() {
@@ -54,6 +63,9 @@ const Config::EmulatorDescription Config::_drivers[] = {
#ifndef DISABLE_DOSBOX_OPL
{ "db", _s("DOSBox OPL emulator"), kDOSBox, kFlagOpl2 | kFlagDualOpl2 | kFlagOpl3 },
#endif
+#ifdef USE_ALSA
+ { "alsa", _s("ALSA Direct FM"), kALSA, kFlagOpl2 | kFlagDualOpl2 },
+#endif
{ 0, 0, 0, 0 }
};
@@ -166,6 +178,11 @@ OPL *Config::create(DriverId driver, OplType type) {
return new DOSBox::OPL(type);
#endif
+#ifdef USE_ALSA
+ case kALSA:
+ return ALSA::create(type);
+#endif
+
default:
warning("Unsupported OPL emulator %d", driver);
// TODO: Maybe we should add some dummy emulator too, which just outputs
diff --git a/audio/module.mk b/audio/module.mk
index abbeed6..1539163 100644
--- a/audio/module.mk
+++ b/audio/module.mk
@@ -58,6 +58,11 @@ MODULE_OBJS := \
softsynth/sid.o \
softsynth/wave6581.o
+ifdef USE_ALSA
+MODULE_OBJS += \
+ softsynth/opl/alsa.o
+endif
+
ifndef USE_ARM_SOUND_ASM
MODULE_OBJS += \
rate.o
diff --git a/audio/softsynth/opl/alsa.cpp b/audio/softsynth/opl/alsa.cpp
new file mode 100644
index 0000000..7ca433d
--- /dev/null
+++ b/audio/softsynth/opl/alsa.cpp
@@ -0,0 +1,339 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/* OPL implementation for hardware OPL using ALSA Direct FM API.
+ *
+ * Caveats and limitations:
+ * - Pretends to be a softsynth (emitting silence).
+ * - Dual OPL2 mode requires OPL3 hardware.
+ * - Every register write leads to a series of register writes on the hardware,
+ * due to the lack of direct register access in the ALSA Direct FM API.
+ * - No timers
+ */
+
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+#include "common/scummsys.h"
+
+#include "common/debug.h"
+#include "common/str.h"
+#include "audio/fmopl.h"
+
+#include <sys/ioctl.h>
+#include <alsa/asoundlib.h>
+#include <sound/asound_fm.h>
+
+namespace OPL {
+namespace ALSA {
+
+class OPL : public ::OPL::RealOPL {
+private:
+ enum {
+ kOpl2Voices = 9,
+ kVoices = 18,
+ kOpl2Operators = 18,
+ kOperators = 36
+ };
+
+ Config::OplType _type;
+ int _iface;
+ snd_hwdep_t *_opl;
+ snd_dm_fm_voice _oper[kOperators];
+ snd_dm_fm_note _voice[kVoices];
+ snd_dm_fm_params _params;
+ int index[2];
+ static const int voiceToOper0[kVoices];
+ static const int regOffsetToOper[0x20];
+
+ void writeOplReg(int c, int r, int v);
+ void clear();
+
+public:
+ OPL(Config::OplType type);
+ ~OPL();
+
+ bool init();
+ void reset();
+
+ void write(int a, int v);
+ byte read(int a);
+
+ void writeReg(int r, int v);
+};
+
+const int OPL::voiceToOper0[OPL::kVoices] =
+ { 0, 1, 2, 6, 7, 8, 12, 13, 14, 18, 19, 20, 24, 25, 26, 30, 31, 32 };
+
+const int OPL::regOffsetToOper[0x20] =
+ { 0, 1, 2, 3, 4, 5, -1, -1, 6, 7, 8, 9, 10, 11, -1, -1,
+ 12, 13, 14, 15, 16, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
+
+OPL::OPL(Config::OplType type) : _type(type), _opl(nullptr), _iface(0) {
+}
+
+OPL::~OPL() {
+ stop();
+
+ if (_opl)
+ snd_hwdep_close(_opl);
+}
+
+void OPL::clear() {
+ index[0] = index[1] = 0;
+
+ memset(_oper, 0, sizeof(_oper));
+ memset(_voice, 0, sizeof(_voice));
+ memset(&_params, 0, sizeof(_params));
+
+ for (int i = 0; i < kOperators; ++i) {
+ _oper[i].op = (i / 3) % 2;
+ _oper[i].voice = (i / 6) * 3 + (i % 3);
+ }
+
+ for (int i = 0; i < kVoices; ++i)
+ _voice[i].voice = i;
+
+ // For OPL3 hardware we need to set up the panning in OPL2 modes
+ if (_iface == SND_HWDEP_IFACE_OPL3) {
+ if (_type == Config::kDualOpl2) {
+ for (int i = 0; i < kOpl2Operators; ++i)
+ _oper[i].left = 1; // FIXME below
+ for (int i = kOpl2Operators; i < kOperators; ++i)
+ _oper[i].right = 1;
+ } else if (_type == Config::kOpl2) {
+ for (int i = 0; i < kOpl2Operators; ++i) {
+ _oper[i].left = 1;
+ _oper[i].right = 1;
+ }
+ }
+ }
+}
+
+bool OPL::init() {
+ clear();
+
+ int card = -1;
+ snd_ctl_t *ctl;
+ snd_hwdep_info_t *info;
+ snd_hwdep_info_alloca(&info);
+
+ int iface = SND_HWDEP_IFACE_OPL3;
+ if (_type == Config::kOpl2)
+ iface = SND_HWDEP_IFACE_OPL2;
+
+ // Look for OPL hwdep interface
+ while (!snd_card_next(&card) && card >= 0) {
+ int dev = -1;
+ Common::String name = Common::String::format("hw:%d", card);
+
+ if (snd_ctl_open(&ctl, name.c_str(), 0) < 0)
+ continue;
+
+ while (!snd_ctl_hwdep_next_device(ctl, &dev) && dev >= 0) {
+ name = Common::String::format("hw:%d,%d", card, dev);
+
+ if (snd_hwdep_open(&_opl, name.c_str(), SND_HWDEP_OPEN_WRITE) < 0)
+ continue;
+
+ if (!snd_hwdep_info(_opl, info)) {
+ int found = snd_hwdep_info_get_iface(info);
+ // OPL3 can be used for (Dual) OPL2 mode
+ if (found == iface || found == SND_HWDEP_IFACE_OPL3) {
+ snd_ctl_close(ctl);
+ _iface = found;
+ reset();
+ return true;
+ }
+ }
+
+ // Wrong interface, try next device
+ snd_hwdep_close(_opl);
+ _opl = nullptr;
+ }
+
+ snd_ctl_close(ctl);
+ }
+
+ return false;
+}
+
+void OPL::reset() {
+ snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_RESET, nullptr);
+ if (_iface != SND_HWDEP_IFACE_OPL2)
+ snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_MODE, (void *)SNDRV_DM_FM_MODE_OPL3);
+ clear();
+}
+
+void OPL::write(int port, int val) {
+ val &= 0xff;
+ int chip = (port & 2) >> 1;
+
+ if (port & 1) {
+ switch(_type) {
+ case Config::kOpl2:
+ writeOplReg(0, index[0], val);
+ break;
+ case Config::kDualOpl2:
+ if (port & 8) {
+ writeOplReg(0, index[0], val);
+ writeOplReg(1, index[1], val);
+ } else
+ writeOplReg(chip, index[chip], val);
+ break;
+ case Config::kOpl3:
+ writeOplReg(chip, index[chip], val);
+ }
+ } else {
+ switch(_type) {
+ case Config::kOpl2:
+ index[0] = val;
+ break;
+ case Config::kDualOpl2:
+ if (port & 8) {
+ index[0] = val;
+ index[1] = val;
+ } else
+ index[chip] = val;
+ break;
+ case Config::kOpl3:
+ index[chip] = val;
+ }
+ }
+}
+
+byte OPL::read(int port) {
+ return 0;
+}
+
+void OPL::writeReg(int r, int v) {
+ switch (_type) {
+ case Config::kOpl2:
+ writeOplReg(0, r, v);
+ break;
+ case Config::kDualOpl2:
+ writeOplReg(0, r, v);
+ writeOplReg(1, r, v);
+ break;
+ case Config::kOpl3:
+ writeOplReg(r >= 100, r & 0xff, v);
+ }
+}
+
+void OPL::writeOplReg(int c, int r, int v) {
+ if (r == 0x04 && c == 1 && _type == Config::kOpl3) {
+ snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_CONNECTION, reinterpret_cast<void *>(v & 0x3f));
+ } else if (r == 0x08 && c == 0) {
+ _params.kbd_split = (v >> 6) & 0x1;
+ snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_PARAMS, (void *)&_params);
+ } else if (r == 0xbd && c == 0) {
+ _params.hihat = v & 0x1;
+ _params.cymbal = (v >> 1) & 0x1;
+ _params.tomtom = (v >> 2) & 0x1;
+ _params.snare = (v >> 3) & 0x1;
+ _params.bass = (v >> 4) & 0x1;
+ _params.rhythm = (v >> 5) & 0x1;
+ _params.vib_depth = (v >> 6) & 0x1;
+ _params.am_depth = (v >> 7) & 0x1;
+ snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_PARAMS, (void *)&_params);
+ } else if (r < 0xa0 || r >= 0xe0) {
+ // Operator
+ int idx = regOffsetToOper[r & 0x1f];
+
+ if (idx == -1)
+ return;
+
+ if (c == 1)
+ idx += kOpl2Operators;
+
+ switch (r & 0xf0) {
+ case 0x20:
+ case 0x30:
+ _oper[idx].harmonic = v & 0xf;
+ _oper[idx].kbd_scale = (v >> 4) & 0x1;
+ _oper[idx].do_sustain = (v >> 5) & 0x1;
+ _oper[idx].vibrato = (v >> 6) & 0x1;
+ _oper[idx].am = (v >> 7) & 0x1;
+ snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_VOICE, (void *)&_oper[idx]);
+ break;
+ case 0x40:
+ case 0x50:
+ _oper[idx].volume = ~v & 0x3f;
+ _oper[idx].scale_level = (v >> 6) & 0x3;
+ snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_VOICE, (void *)&_oper[idx]);
+ break;
+ case 0x60:
+ case 0x70:
+ _oper[idx].decay = v & 0xf;
+ _oper[idx].attack = (v >> 4) & 0xf;
+ snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_VOICE, (void *)&_oper[idx]);
+ break;
+ case 0x80:
+ case 0x90:
+ _oper[idx].release = v & 0xf;
+ _oper[idx].sustain = (v >> 4) & 0xf;
+ snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_VOICE, (void *)&_oper[idx]);
+ break;
+ case 0xe0:
+ case 0xf0:
+ _oper[idx].waveform = v & 0x7;
+ snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_VOICE, (void *)&_oper[idx]);
+ }
+ } else {
+ // Voice
+ int idx = r & 0xf;
+
+ if (idx >= kOpl2Voices)
+ return;
+
+ if (c == 1)
+ idx += kOpl2Voices;
+
+ int opIdx = voiceToOper0[idx];
+
+ switch (r & 0xf0) {
+ case 0xa0:
+ _voice[idx].fnum = (_voice[idx].fnum & 0x300) | (v & 0xff);
+ snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_PLAY_NOTE, (void *)&_voice[idx]);
+ break;
+ case 0xb0:
+ _voice[idx].fnum = ((v << 8) & 0x300) | (_voice[idx].fnum & 0xff);
+ _voice[idx].octave = (v >> 2) & 0x7;
+ _voice[idx].key_on = (v >> 5) & 0x1;
+ snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_PLAY_NOTE, (void *)&_voice[idx]);
+ break;
+ case 0xc0:
+ _oper[opIdx].connection = _oper[opIdx + 3].connection = v & 0x1;
+ _oper[opIdx].feedback = _oper[opIdx + 3].feedback = (v >> 1) & 0x7;
+ if (_type == Config::kOpl3) {
+ _oper[opIdx].left = (v >> 4) & 0x1;
+ _oper[opIdx].right = (v >> 5) & 0x1;
+ }
+ snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_VOICE, (void *)&_oper[opIdx]);
+ }
+ }
+}
+
+OPL *create(Config::OplType type) {
+ return new OPL(type);
+}
+
+} // End of namespace ALSA
+} // End of namespace OPL
Commit: b630eca437a7800c14984bb65dc5cb5c5bc28597
https://github.com/scummvm/scummvm/commit/b630eca437a7800c14984bb65dc5cb5c5bc28597
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2015-07-07T20:19:47-04:00
Commit Message:
AUDIO: Fix bug in ALSA AdLib driver
Thanks clone2727
Changed paths:
audio/softsynth/opl/alsa.cpp
diff --git a/audio/softsynth/opl/alsa.cpp b/audio/softsynth/opl/alsa.cpp
index 7ca433d..8fea0fd 100644
--- a/audio/softsynth/opl/alsa.cpp
+++ b/audio/softsynth/opl/alsa.cpp
@@ -233,7 +233,7 @@ void OPL::writeReg(int r, int v) {
writeOplReg(1, r, v);
break;
case Config::kOpl3:
- writeOplReg(r >= 100, r & 0xff, v);
+ writeOplReg(r >= 0x100, r & 0xff, v);
}
}
Commit: beed23c441b5b36e7081589a004c7ab9bb253829
https://github.com/scummvm/scummvm/commit/beed23c441b5b36e7081589a004c7ab9bb253829
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2015-07-07T20:19:47-04:00
Commit Message:
AUDIO: List OPL3 support for ALSA AdLib driver
Thanks clone2727
Changed paths:
audio/fmopl.cpp
diff --git a/audio/fmopl.cpp b/audio/fmopl.cpp
index ded4506..cc00ace 100644
--- a/audio/fmopl.cpp
+++ b/audio/fmopl.cpp
@@ -64,7 +64,7 @@ const Config::EmulatorDescription Config::_drivers[] = {
{ "db", _s("DOSBox OPL emulator"), kDOSBox, kFlagOpl2 | kFlagDualOpl2 | kFlagOpl3 },
#endif
#ifdef USE_ALSA
- { "alsa", _s("ALSA Direct FM"), kALSA, kFlagOpl2 | kFlagDualOpl2 },
+ { "alsa", _s("ALSA Direct FM"), kALSA, kFlagOpl2 | kFlagDualOpl2 | kFlagOpl3 },
#endif
{ 0, 0, 0, 0 }
};
Commit: 82f585871bdb435d6f30d7005456dba0fb90c985
https://github.com/scummvm/scummvm/commit/82f585871bdb435d6f30d7005456dba0fb90c985
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2015-07-07T20:19:48-04:00
Commit Message:
SCI: Check OPL init return code
Changed paths:
engines/sci/sound/drivers/adlib.cpp
diff --git a/engines/sci/sound/drivers/adlib.cpp b/engines/sci/sound/drivers/adlib.cpp
index aac8a0d..da222fb 100644
--- a/engines/sci/sound/drivers/adlib.cpp
+++ b/engines/sci/sound/drivers/adlib.cpp
@@ -236,7 +236,8 @@ int MidiDriver_AdLib::openAdLib(bool isSCI0) {
if (!_opl)
return -1;
- _opl->init();
+ if (!_opl->init())
+ return -1;
setRegister(0xBD, 0);
setRegister(0x08, 0);
Commit: 56c0238f9bc5f013cae0d487ef88dae3c29f6305
https://github.com/scummvm/scummvm/commit/56c0238f9bc5f013cae0d487ef88dae3c29f6305
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2015-07-07T20:19:48-04:00
Commit Message:
SCI: Delete OPL when init fails
Changed paths:
engines/sci/sound/drivers/adlib.cpp
diff --git a/engines/sci/sound/drivers/adlib.cpp b/engines/sci/sound/drivers/adlib.cpp
index da222fb..4f557be 100644
--- a/engines/sci/sound/drivers/adlib.cpp
+++ b/engines/sci/sound/drivers/adlib.cpp
@@ -236,8 +236,11 @@ int MidiDriver_AdLib::openAdLib(bool isSCI0) {
if (!_opl)
return -1;
- if (!_opl->init())
+ if (!_opl->init()) {
+ delete _opl;
+ _opl = nullptr;
return -1;
+ }
setRegister(0xBD, 0);
setRegister(0x08, 0);
Commit: be345083a03a110d9f6ebc9310152bf079dfab7e
https://github.com/scummvm/scummvm/commit/be345083a03a110d9f6ebc9310152bf079dfab7e
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2015-07-07T20:19:48-04:00
Commit Message:
AUDIO: Update 2nd operator panning for AdLib register 0xc0
Changed paths:
audio/softsynth/opl/alsa.cpp
diff --git a/audio/softsynth/opl/alsa.cpp b/audio/softsynth/opl/alsa.cpp
index 8fea0fd..934fb34 100644
--- a/audio/softsynth/opl/alsa.cpp
+++ b/audio/softsynth/opl/alsa.cpp
@@ -323,8 +323,8 @@ void OPL::writeOplReg(int c, int r, int v) {
_oper[opIdx].connection = _oper[opIdx + 3].connection = v & 0x1;
_oper[opIdx].feedback = _oper[opIdx + 3].feedback = (v >> 1) & 0x7;
if (_type == Config::kOpl3) {
- _oper[opIdx].left = (v >> 4) & 0x1;
- _oper[opIdx].right = (v >> 5) & 0x1;
+ _oper[opIdx].left = _oper[opIdx + 3].left = (v >> 4) & 0x1;
+ _oper[opIdx].right = _oper[opIdx + 3].right = (v >> 5) & 0x1;
}
snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_VOICE, (void *)&_oper[opIdx]);
}
Commit: 1bdcf6e83647a9509598d49bae6ddec1fbd25715
https://github.com/scummvm/scummvm/commit/1bdcf6e83647a9509598d49bae6ddec1fbd25715
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2015-07-07T20:19:48-04:00
Commit Message:
AUDIO: Reset ALSA AdLib on exit
Changed paths:
audio/softsynth/opl/alsa.cpp
diff --git a/audio/softsynth/opl/alsa.cpp b/audio/softsynth/opl/alsa.cpp
index 934fb34..bb15719 100644
--- a/audio/softsynth/opl/alsa.cpp
+++ b/audio/softsynth/opl/alsa.cpp
@@ -92,8 +92,10 @@ OPL::OPL(Config::OplType type) : _type(type), _opl(nullptr), _iface(0) {
OPL::~OPL() {
stop();
- if (_opl)
+ if (_opl) {
+ snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_RESET, nullptr);
snd_hwdep_close(_opl);
+ }
}
void OPL::clear() {
Commit: 1287a56429d0cd85567daa130fc6518ee2030b70
https://github.com/scummvm/scummvm/commit/1287a56429d0cd85567daa130fc6518ee2030b70
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2015-07-07T20:19:48-04:00
Commit Message:
AUDIO: Fix ALSA AdLib OPL2 waveform mask
Changed paths:
audio/softsynth/opl/alsa.cpp
diff --git a/audio/softsynth/opl/alsa.cpp b/audio/softsynth/opl/alsa.cpp
index bb15719..79ff589 100644
--- a/audio/softsynth/opl/alsa.cpp
+++ b/audio/softsynth/opl/alsa.cpp
@@ -295,7 +295,7 @@ void OPL::writeOplReg(int c, int r, int v) {
break;
case 0xe0:
case 0xf0:
- _oper[idx].waveform = v & 0x7;
+ _oper[idx].waveform = v & (_type == Config::kOpl3 ? 0x7 : 0x3);
snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_VOICE, (void *)&_oper[idx]);
}
} else {
Commit: f0606aa8f131b72bf76e08a82f6deb5016d5d8bb
https://github.com/scummvm/scummvm/commit/f0606aa8f131b72bf76e08a82f6deb5016d5d8bb
Author: Walter van Niftrik (walter at vanniftrik-it.nl)
Date: 2015-07-07T20:19:48-04:00
Commit Message:
AUDIO: Reset OPL registers in ALSA driver
Changed paths:
audio/softsynth/opl/alsa.cpp
diff --git a/audio/softsynth/opl/alsa.cpp b/audio/softsynth/opl/alsa.cpp
index 79ff589..6b9e48e 100644
--- a/audio/softsynth/opl/alsa.cpp
+++ b/audio/softsynth/opl/alsa.cpp
@@ -179,9 +179,17 @@ bool OPL::init() {
void OPL::reset() {
snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_RESET, nullptr);
- if (_iface != SND_HWDEP_IFACE_OPL2)
+ if (_iface == SND_HWDEP_IFACE_OPL3)
snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_MODE, (void *)SNDRV_DM_FM_MODE_OPL3);
+
clear();
+
+ // Sync up with the hardware
+ snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_PARAMS, (void *)&_params);
+ for (uint i = 0; i < (_iface == SND_HWDEP_IFACE_OPL3 ? kVoices : kOpl2Voices); ++i)
+ snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_PLAY_NOTE, (void *)&_voice[i]);
+ for (uint i = 0; i < (_iface == SND_HWDEP_IFACE_OPL3 ? kOperators : kOpl2Operators); ++i)
+ snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_VOICE, (void *)&_oper[i]);
}
void OPL::write(int port, int val) {
Commit: fde8abf8ccea92efec16a83dc4fa6b872f9cc6d2
https://github.com/scummvm/scummvm/commit/fde8abf8ccea92efec16a83dc4fa6b872f9cc6d2
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-07-07T20:19:49-04:00
Commit Message:
AUDIO: Move the common AdLib MidiDriver out of softsynth
Changed paths:
A audio/adlib.cpp
R audio/softsynth/adlib.cpp
audio/module.mk
diff --git a/audio/adlib.cpp b/audio/adlib.cpp
new file mode 100644
index 0000000..f609164
--- /dev/null
+++ b/audio/adlib.cpp
@@ -0,0 +1,2318 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "audio/softsynth/emumidi.h"
+#include "common/debug.h"
+#include "common/error.h"
+#include "common/scummsys.h"
+#include "common/system.h"
+#include "common/textconsole.h"
+#include "common/types.h"
+#include "common/util.h"
+#include "audio/fmopl.h"
+#include "audio/musicplugin.h"
+#include "common/translation.h"
+
+#ifdef DEBUG_ADLIB
+static int g_tick;
+#endif
+
+// Only include OPL3 when we actually have an AdLib emulator builtin, which
+// supports OPL3.
+#ifndef DISABLE_DOSBOX_OPL
+#define ENABLE_OPL3
+#endif
+
+class MidiDriver_ADLIB;
+struct AdLibVoice;
+
+// We use packing for the following two structs, because the code
+// does simply copy them over from byte streams, without any
+// serialization. Check AdLibPart::sysEx_customInstrument for an
+// example of this.
+//
+// It might be very well possible, that none of the compilers we support
+// add any padding bytes at all, since the structs contain only variables
+// of the type 'byte'. But better safe than sorry.
+#include "common/pack-start.h"
+struct InstrumentExtra {
+ byte a, b, c, d, e, f, g, h;
+} PACKED_STRUCT;
+
+struct AdLibInstrument {
+ byte modCharacteristic;
+ byte modScalingOutputLevel;
+ byte modAttackDecay;
+ byte modSustainRelease;
+ byte modWaveformSelect;
+ byte carCharacteristic;
+ byte carScalingOutputLevel;
+ byte carAttackDecay;
+ byte carSustainRelease;
+ byte carWaveformSelect;
+ byte feedback;
+ byte flagsA;
+ InstrumentExtra extraA;
+ byte flagsB;
+ InstrumentExtra extraB;
+ byte duration;
+} PACKED_STRUCT;
+#include "common/pack-end.h"
+
+class AdLibPart : public MidiChannel {
+ friend class MidiDriver_ADLIB;
+
+protected:
+// AdLibPart *_prev, *_next;
+ AdLibVoice *_voice;
+ int16 _pitchBend;
+ byte _pitchBendFactor;
+ //int8 _transposeEff;
+ byte _volEff;
+ int8 _detuneEff;
+ byte _modWheel;
+ bool _pedal;
+ byte _program;
+ byte _priEff;
+ byte _pan;
+ AdLibInstrument _partInstr;
+#ifdef ENABLE_OPL3
+ AdLibInstrument _partInstrSecondary;
+#endif
+
+protected:
+ MidiDriver_ADLIB *_owner;
+ bool _allocated;
+ byte _channel;
+
+ void init(MidiDriver_ADLIB *owner, byte channel);
+ void allocate() { _allocated = true; }
+
+public:
+ AdLibPart() {
+ _voice = 0;
+ _pitchBend = 0;
+ _pitchBendFactor = 2;
+ //_transposeEff = 0;
+ _volEff = 0;
+ _detuneEff = 0;
+ _modWheel = 0;
+ _pedal = 0;
+ _program = 0;
+ _priEff = 0;
+ _pan = 64;
+
+ _owner = 0;
+ _allocated = false;
+ _channel = 0;
+
+ memset(&_partInstr, 0, sizeof(_partInstr));
+#ifdef ENABLE_OPL3
+ memset(&_partInstrSecondary, 0, sizeof(_partInstrSecondary));
+#endif
+ }
+
+ MidiDriver *device();
+ byte getNumber() { return _channel; }
+ void release() { _allocated = false; }
+
+ void send(uint32 b);
+
+ // 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);
+ 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, const byte *instr);
+};
+
+// FYI (Jamieson630)
+// It is assumed that any invocation to AdLibPercussionChannel
+// will be done through the MidiChannel base class as opposed to the
+// AdLibPart base class. If this were NOT the case, all the functions
+// listed below would need to be virtual in AdLibPart as well as MidiChannel.
+class AdLibPercussionChannel : public AdLibPart {
+ friend class MidiDriver_ADLIB;
+
+protected:
+ void init(MidiDriver_ADLIB *owner, byte channel);
+
+public:
+ ~AdLibPercussionChannel();
+
+ void noteOff(byte note);
+ void noteOn(byte note, byte velocity);
+ void programChange(byte program) { }
+
+ // Control Change messages
+ void modulationWheel(byte value) { }
+ void pitchBendFactor(byte value) { }
+ void detune(byte value) { }
+ void priority(byte value) { }
+ void sustain(bool value) { }
+
+ // SysEx messages
+ void sysEx_customInstrument(uint32 type, const byte *instr);
+
+private:
+ byte _notes[256];
+ AdLibInstrument *_customInstruments[256];
+};
+
+struct Struct10 {
+ byte active;
+ int16 curVal;
+ int16 count;
+ uint16 maxValue;
+ int16 startValue;
+ byte loop;
+ byte tableA[4];
+ byte tableB[4];
+ int8 unk3;
+ int8 modWheel;
+ int8 modWheelLast;
+ uint16 speedLoMax;
+ uint16 numSteps;
+ int16 speedHi;
+ int8 direction;
+ uint16 speedLo;
+ uint16 speedLoCounter;
+};
+
+struct Struct11 {
+ int16 modifyVal;
+ byte param, flag0x40, flag0x10;
+ Struct10 *s10;
+};
+
+struct AdLibVoice {
+ AdLibPart *_part;
+ AdLibVoice *_next, *_prev;
+ byte _waitForPedal;
+ byte _note;
+ byte _channel;
+ byte _twoChan;
+ byte _vol1, _vol2;
+ int16 _duration;
+
+ Struct10 _s10a;
+ Struct11 _s11a;
+ Struct10 _s10b;
+ Struct11 _s11b;
+
+#ifdef ENABLE_OPL3
+ byte _secTwoChan;
+ byte _secVol1, _secVol2;
+#endif
+
+ AdLibVoice() { memset(this, 0, sizeof(AdLibVoice)); }
+};
+
+struct AdLibSetParams {
+ byte registerBase;
+ byte shift;
+ byte mask;
+ byte inversion;
+};
+
+static const byte g_operator1Offsets[9] = {
+ 0, 1, 2, 8,
+ 9, 10, 16, 17,
+ 18
+};
+
+static const byte g_operator2Offsets[9] = {
+ 3, 4, 5, 11,
+ 12, 13, 19, 20,
+ 21
+};
+
+static const AdLibSetParams g_setParamTable[] = {
+ {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}, // waveformSelect 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
+};
+
+static const byte g_paramTable1[16] = {
+ 29, 28, 27, 0,
+ 3, 4, 7, 8,
+ 13, 16, 17, 20,
+ 21, 30, 31, 0
+};
+
+static const uint16 g_maxValTable[16] = {
+ 0x2FF, 0x1F, 0x7, 0x3F,
+ 0x0F, 0x0F, 0x0F, 0x3,
+ 0x3F, 0x0F, 0x0F, 0x0F,
+ 0x3, 0x3E, 0x1F, 0
+};
+
+static const uint16 g_numStepsTable[] = {
+ 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 g_noteFrequencies[] = {
+ 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 const AdLibInstrument g_gmInstruments[128] = {
+ // 0x00
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ // 0x10
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ // 0x20
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ // 0x30
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ // 0x40
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ // 0x50
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ // 0x60
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ // 0x70
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 }
+};
+
+static AdLibInstrument g_gmPercussionInstruments[39] = {
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 }
+};
+
+#ifdef ENABLE_OPL3
+static const AdLibInstrument g_gmInstrumentsOPL3[128][2] = {
+ { { 0xC2, 0xC2, 0x0A, 0x6B, 0xA0, 0xC2, 0x08, 0x0D, 0x88, 0xC8, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x23 },
+ { 0x02, 0x00, 0x0C, 0x78, 0x61, 0x04, 0x4C, 0x0B, 0x9A, 0xC8, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x23 } },
+ { { 0x22, 0x53, 0x0E, 0x8A, 0x60, 0x14, 0x06, 0x1D, 0x7A, 0xB8, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0x22, 0x5A, 0x0E, 0x8A, 0x40, 0x14, 0x2F, 0x0E, 0x7A, 0x88, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0x06, 0x00, 0x1C, 0x79, 0x70, 0x02, 0x00, 0x4B, 0x79, 0xA8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0x06, 0x00, 0x1A, 0x79, 0x60, 0x02, 0x00, 0x4C, 0xA9, 0xC8, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xC2, 0x80, 0x0B, 0x89, 0x90, 0xC2, 0x06, 0x1B, 0xA8, 0xB0, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x23 },
+ { 0x04, 0x28, 0x5D, 0xB8, 0x01, 0x02, 0x00, 0x3C, 0x70, 0x88, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xC2, 0x17, 0x3D, 0x6A, 0x00, 0xC4, 0x2E, 0x2D, 0xC9, 0x40, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xC2, 0x17, 0x3D, 0x6A, 0x00, 0xC4, 0x2E, 0x2D, 0xC9, 0x40, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 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 },
+ { 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 } },
+ { { 0x84, 0x40, 0x3B, 0x5A, 0x63, 0x81, 0x00, 0x3B, 0x5A, 0xD3, 0x0B, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0x87, 0x40, 0x3A, 0x5A, 0x94, 0x82, 0x04, 0x3D, 0x59, 0xAC, 0x09, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0x84, 0x40, 0x3B, 0x5A, 0xC3, 0x81, 0x00, 0x3B, 0x5A, 0xFB, 0x01, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0x84, 0x40, 0x3B, 0x5A, 0xC3, 0x81, 0x00, 0x3B, 0x5A, 0xFB, 0x01, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0x8C, 0x80, 0x05, 0xEA, 0xA9, 0x82, 0x04, 0x3D, 0xAA, 0xB0, 0x07, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0x8C, 0x80, 0x06, 0x98, 0xA9, 0x86, 0x10, 0x36, 0x7A, 0xFD, 0x07, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0x85, 0x40, 0x0D, 0xEC, 0xE1, 0x84, 0x58, 0x3E, 0xCB, 0xF8, 0x01, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0x84, 0x40, 0x0D, 0xEB, 0xE0, 0x84, 0x48, 0x3E, 0xCA, 0xC0, 0x05, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0x8A, 0xC0, 0x0C, 0xDC, 0xA0, 0x88, 0x58, 0x3D, 0xDA, 0xF8, 0x01, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0x8A, 0xC0, 0x0C, 0xDC, 0xA0, 0x88, 0x58, 0x3D, 0xDA, 0xF8, 0x01, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xC9, 0x40, 0x2B, 0x78, 0x8A, 0xC2, 0x0A, 0x4C, 0x8A, 0xF8, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x1A },
+ { 0xCA, 0x40, 0x47, 0xCA, 0xB4, 0xC2, 0x00, 0x57, 0x8A, 0xB8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x1A } },
+ { { 0x2A, 0x0E, 0x17, 0x89, 0x50, 0x22, 0x0C, 0x1B, 0x09, 0xE0, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0x2A, 0x1A, 0x19, 0x8A, 0x00, 0x22, 0x38, 0x0B, 0x0A, 0x00, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE7, 0x9B, 0x08, 0x08, 0x4A, 0xE2, 0x06, 0x0A, 0x08, 0xE0, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xE7, 0x9B, 0x08, 0x08, 0x4A, 0xE2, 0x2F, 0x0A, 0x08, 0x68, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xC5, 0x0A, 0x05, 0xDC, 0xB8, 0x84, 0x06, 0x00, 0xEC, 0xC0, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0x09, 0x10, 0x04, 0x5B, 0xA5, 0x02, 0x08, 0x00, 0xEC, 0x70, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0x86, 0x40, 0x5D, 0x5A, 0x81, 0x81, 0x00, 0x0B, 0x5A, 0xFB, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0x86, 0x40, 0x5D, 0x5A, 0x81, 0x81, 0x00, 0x0B, 0x5A, 0xFB, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xED, 0x0F, 0x5B, 0xC8, 0xC8, 0xE2, 0x9F, 0x4A, 0xE9, 0xF9, 0x07, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xE6, 0x40, 0x0A, 0xA7, 0x64, 0xE2, 0x8B, 0x6A, 0x79, 0xB1, 0x01, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE8, 0x4F, 0x3A, 0xD7, 0xF8, 0xE2, 0x97, 0x49, 0xF9, 0xF9, 0x05, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xC9, 0x02, 0x16, 0x9A, 0xAB, 0xC4, 0x15, 0x46, 0xBA, 0xF8, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE1, 0x08, 0x2F, 0xF7, 0xE1, 0xF3, 0x42, 0x8F, 0xC7, 0xC2, 0x07, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xE3, 0x00, 0x2D, 0xF7, 0xC1, 0xE4, 0x40, 0x7F, 0xC7, 0xD2, 0x09, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0x01, 0x8C, 0x9F, 0xDA, 0xE8, 0xE4, 0x50, 0x9F, 0xDA, 0xF2, 0x09, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0x02, 0x80, 0x9F, 0xDA, 0x00, 0xE3, 0x50, 0x9F, 0xD9, 0xFA, 0x03, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0x08, 0xD5, 0x9D, 0xA5, 0x89, 0xE2, 0x3F, 0x9F, 0xD6, 0x91, 0x07, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0x08, 0xD5, 0x9D, 0xA5, 0x89, 0xE2, 0x3F, 0x9F, 0xD6, 0x91, 0x07, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE5, 0x0F, 0x7D, 0xB8, 0x5A, 0xA2, 0x0C, 0x7C, 0xC7, 0xC1, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0x06, 0x4C, 0xAC, 0x56, 0x31, 0x02, 0x08, 0x8D, 0x46, 0xDC, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xF2, 0x2A, 0x9F, 0xDB, 0x01, 0xE1, 0x04, 0x8F, 0xD7, 0xC2, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xF2, 0x00, 0x9F, 0xDB, 0xA9, 0xE1, 0x00, 0x8F, 0xD7, 0xBA, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE4, 0x88, 0x9C, 0x50, 0xC8, 0xE2, 0x18, 0x70, 0xC4, 0xF8, 0x0B, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xE6, 0x00, 0x9C, 0x50, 0xB0, 0xE4, 0x00, 0x70, 0xC4, 0xA0, 0x07, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 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 },
+ { 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 } },
+ { { 0x42, 0x53, 0x3E, 0xEB, 0x48, 0xD4, 0x05, 0x1D, 0xA9, 0xC9, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x18 },
+ { 0x42, 0x54, 0x6F, 0xEB, 0x61, 0xD4, 0x02, 0x2E, 0xA9, 0xC8, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x18 } },
+ { { 0xC2, 0x00, 0x59, 0x17, 0xB1, 0xC2, 0x1E, 0x6D, 0x98, 0xF8, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x19 },
+ { 0xC2, 0x00, 0x08, 0xB3, 0x99, 0xC2, 0x06, 0x2B, 0x58, 0xFA, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x19 } },
+ { { 0xC6, 0x01, 0x2D, 0xA7, 0x88, 0xC2, 0x08, 0x0E, 0xA7, 0xC1, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xC4, 0x00, 0x2D, 0xA7, 0x91, 0xC2, 0x02, 0x0E, 0xA7, 0xD1, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xC2, 0x0C, 0x06, 0x06, 0xA9, 0xC2, 0x3F, 0x08, 0xB8, 0xF9, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x0A },
+ { 0xC1, 0x00, 0x68, 0x50, 0xB8, 0xC2, 0x00, 0x48, 0x84, 0xF8, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x0A } },
+ { { 0xC2, 0x2E, 0x4F, 0x77, 0x00, 0xC4, 0x08, 0x0E, 0x98, 0xB1, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xC2, 0x2F, 0x6F, 0x79, 0x00, 0xC8, 0x0F, 0x5E, 0x98, 0xB9, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xC2, 0x30, 0x4F, 0xCA, 0x01, 0xC4, 0x0D, 0x0E, 0xB8, 0xFB, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xC2, 0x30, 0x4F, 0xCA, 0x01, 0xC4, 0x0D, 0x0E, 0xB8, 0xFB, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xC4, 0x29, 0x4F, 0xCA, 0x03, 0xC8, 0x0D, 0x0C, 0xB7, 0xF9, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x0B },
+ { 0xC4, 0x29, 0x4F, 0xCA, 0x03, 0xC8, 0x0D, 0x0C, 0xB7, 0xF9, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x0B } },
+ { { 0xC2, 0x41, 0x3D, 0x96, 0x88, 0xC4, 0xCA, 0x0E, 0xC7, 0xF8, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x20 },
+ { 0xC2, 0x04, 0x58, 0xC9, 0x90, 0xC2, 0x94, 0x2C, 0xB9, 0xF0, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x20 } },
+ { { 0x31, 0x13, 0x2D, 0xD7, 0x78, 0xE2, 0x18, 0x2E, 0xB8, 0xF8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0x31, 0x13, 0x2D, 0xD7, 0x78, 0xE2, 0x18, 0x2E, 0xB8, 0xF8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0x22, 0x86, 0x0D, 0xD7, 0xA0, 0xE4, 0x18, 0x5E, 0xB8, 0xF8, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x28 },
+ { 0x22, 0x86, 0x0D, 0xD7, 0xA0, 0xE4, 0x18, 0x5E, 0xB8, 0xF8, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x28 } },
+ { { 0xF2, 0x0A, 0x0D, 0xD7, 0x80, 0xE4, 0x1F, 0x5E, 0xB8, 0xF8, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xD2, 0x06, 0x9A, 0xD7, 0xA0, 0xC2, 0x1F, 0x59, 0xB8, 0xF8, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xF2, 0x09, 0x4B, 0xD6, 0x90, 0xE4, 0x1F, 0x1C, 0xB8, 0xF8, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x28 },
+ { 0xF2, 0x09, 0x4B, 0xD6, 0x90, 0xE4, 0x1F, 0x1C, 0xB8, 0xF8, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x28 } },
+ { { 0x62, 0x11, 0x0C, 0xE6, 0x78, 0xE4, 0x1F, 0x0C, 0xC8, 0xF8, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0x62, 0x11, 0x0C, 0xE6, 0x78, 0xE4, 0x1F, 0x0C, 0xC8, 0xF8, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE2, 0x12, 0x3D, 0xE6, 0x68, 0xE4, 0x1F, 0x7D, 0xB8, 0xF8, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xE2, 0x12, 0x3D, 0xE6, 0x68, 0xE4, 0x1F, 0x7D, 0xB8, 0xF8, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE2, 0x13, 0x3D, 0xE6, 0x68, 0xE4, 0x1F, 0x5D, 0xB8, 0xF9, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xE2, 0x13, 0x3D, 0xE6, 0x68, 0xE4, 0x1F, 0x5D, 0xB8, 0xF9, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xA2, 0x40, 0x5D, 0xBA, 0x7B, 0xE2, 0x00, 0x8F, 0xD8, 0xF1, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xA2, 0x40, 0x5D, 0xBA, 0x7B, 0xE2, 0x00, 0x8F, 0xD8, 0xF1, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE2, 0x40, 0x3D, 0xDA, 0x73, 0xE1, 0x00, 0x7E, 0xD8, 0xF2, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xE2, 0x40, 0x3D, 0xDA, 0x73, 0xE1, 0x00, 0x7E, 0xD8, 0xF2, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0x62, 0x00, 0x6D, 0xFA, 0xB9, 0xE2, 0x00, 0x8F, 0xC8, 0xF1, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0x62, 0x00, 0x6D, 0xFA, 0xB9, 0xE2, 0x00, 0x8F, 0xC8, 0xF1, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE1, 0x00, 0x4E, 0xDB, 0x92, 0xE3, 0x18, 0x6F, 0xE9, 0xFA, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xE1, 0x00, 0x4E, 0xDB, 0xCA, 0xE2, 0x00, 0x6F, 0xE9, 0xFA, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE1, 0x00, 0x4E, 0xDB, 0xCA, 0xE2, 0x00, 0x7F, 0xE9, 0xFA, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xE1, 0x00, 0x4E, 0xDB, 0xCA, 0xE2, 0x00, 0x7F, 0xE9, 0xFA, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0x02, 0x0F, 0x66, 0xAA, 0xA1, 0x02, 0x64, 0x29, 0xF9, 0xF8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x04 },
+ { 0x02, 0x00, 0x65, 0xAA, 0xF1, 0x02, 0x4A, 0x28, 0xF9, 0xF8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x04 } },
+ { { 0x16, 0x4A, 0x04, 0xBA, 0x71, 0xC2, 0x48, 0x2E, 0xCA, 0xF0, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 },
+ { 0x14, 0xC0, 0x66, 0x08, 0x90, 0xC2, 0x48, 0x2C, 0x0A, 0xA0, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 } },
+ { { 0x02, 0x0A, 0x01, 0x7A, 0xB1, 0x02, 0x12, 0x2A, 0xEA, 0xF8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0x02, 0x06, 0x75, 0x05, 0xB1, 0x01, 0x3F, 0x28, 0xEA, 0xF9, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x16 } },
+ { { 0x62, 0x53, 0x9C, 0xBA, 0x61, 0x62, 0x5A, 0xAD, 0xCA, 0xC1, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xF2, 0x40, 0x9F, 0x8A, 0x98, 0xE2, 0x11, 0x7F, 0xB8, 0xFA, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xF2, 0x40, 0x6E, 0xDA, 0x91, 0xE2, 0x13, 0x8F, 0xF9, 0xF9, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xF2, 0x40, 0x6E, 0xDA, 0x91, 0xE2, 0x13, 0x8F, 0xF9, 0xF9, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE2, 0x40, 0x8F, 0xFA, 0xA0, 0xF2, 0x04, 0x7F, 0xFA, 0xF9, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xE2, 0x40, 0x8F, 0xFA, 0xA0, 0xF2, 0x04, 0x7F, 0xFA, 0xF9, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE4, 0xA0, 0xCE, 0x5B, 0x02, 0xE2, 0x32, 0x7F, 0xFB, 0x79, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xE4, 0xA0, 0xCE, 0x5B, 0x02, 0xE2, 0x32, 0x7F, 0xFB, 0x79, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE6, 0x80, 0x9C, 0x99, 0x82, 0xE2, 0x04, 0x8D, 0x78, 0xC0, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xE0, 0x44, 0x8A, 0xA9, 0x5B, 0xE1, 0x06, 0x8D, 0x79, 0xBA, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE8, 0xA0, 0xAC, 0x67, 0x02, 0xE2, 0x06, 0x7C, 0x7A, 0xF8, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xEA, 0xA0, 0xAC, 0x67, 0x02, 0xE2, 0x00, 0x7C, 0x7A, 0xF8, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE7, 0x94, 0xAD, 0xB7, 0x03, 0xE2, 0x00, 0x7C, 0xBA, 0xF8, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xE7, 0x94, 0xAD, 0xB7, 0x03, 0xE2, 0x00, 0x7C, 0xBA, 0xF8, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xC3, 0x3F, 0x4B, 0xE9, 0xFA, 0xC1, 0x3F, 0x9B, 0xF9, 0xFB, 0x0B, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x06 },
+ { 0xC3, 0x3F, 0x4B, 0xE9, 0xFA, 0xC1, 0x3F, 0x9B, 0xF9, 0xFB, 0x0B, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x06 } },
+ { { 0xB2, 0x20, 0xAD, 0xE9, 0x00, 0x62, 0x05, 0x8F, 0xC8, 0xD0, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xB2, 0x25, 0xAD, 0xE9, 0x00, 0x62, 0x00, 0x8F, 0xC8, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xF2, 0x02, 0xAF, 0xFB, 0x90, 0xF6, 0x54, 0x8F, 0xE9, 0xF8, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xE2, 0x00, 0x9F, 0xFA, 0xB0, 0xF2, 0x58, 0x7F, 0xEA, 0xF8, 0x02, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xF2, 0x00, 0xAF, 0x88, 0xA8, 0xF2, 0x46, 0x6E, 0xC9, 0xE0, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xD2, 0x00, 0x7B, 0x88, 0xA8, 0xD2, 0x4C, 0x69, 0xE9, 0xF8, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xF2, 0x2A, 0x9F, 0x98, 0x01, 0xE2, 0x8F, 0x4E, 0x78, 0xC0, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xD2, 0x02, 0x85, 0x89, 0xC8, 0xD2, 0x94, 0x77, 0x49, 0xF9, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE2, 0x02, 0x9F, 0xB8, 0x90, 0x22, 0x8A, 0x9F, 0xE8, 0xF8, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xC2, 0x00, 0x86, 0xB8, 0x98, 0x02, 0x8F, 0x89, 0xE8, 0xF9, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE2, 0x2A, 0x7F, 0xB8, 0x01, 0xE4, 0x00, 0x0D, 0xC5, 0xF8, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xE2, 0x2A, 0x7F, 0xB8, 0x01, 0xE4, 0x00, 0x0D, 0xC5, 0xF8, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE4, 0x28, 0x8E, 0xE8, 0x01, 0xF2, 0x00, 0x4D, 0xD6, 0xF9, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xE4, 0x28, 0x8E, 0xE8, 0x01, 0xF2, 0x00, 0x4D, 0xD6, 0xF9, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0x62, 0x23, 0x8F, 0xEA, 0x00, 0xF2, 0x00, 0x5E, 0xD9, 0xF8, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0x62, 0x23, 0x8F, 0xEA, 0x00, 0xF2, 0x00, 0x5E, 0xD9, 0xF8, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xB4, 0x26, 0x6E, 0x98, 0x01, 0x62, 0x00, 0x7D, 0xC8, 0xF9, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xB4, 0x26, 0x6E, 0x98, 0x01, 0x62, 0x00, 0x7D, 0xC8, 0xF9, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE2, 0x2E, 0x20, 0xD9, 0x01, 0xF2, 0x1A, 0x90, 0xF8, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xD2, 0x10, 0x69, 0x18, 0xCF, 0xD4, 0x14, 0x5B, 0x04, 0xFD, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE4, 0x28, 0x7E, 0xF8, 0x01, 0xE2, 0x23, 0x8E, 0xE8, 0xF9, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xE4, 0x28, 0x7E, 0xF8, 0x01, 0xE2, 0x23, 0x8E, 0xE8, 0xF9, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xB8, 0x28, 0x9E, 0x98, 0x01, 0x62, 0x00, 0x3D, 0xC8, 0xF9, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xB8, 0x28, 0x9E, 0x98, 0x01, 0x62, 0x00, 0x3D, 0xC8, 0xF9, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0x62, 0x00, 0x8E, 0xC9, 0x79, 0xE6, 0x00, 0x7E, 0xD8, 0xD0, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0x62, 0x00, 0x8E, 0xC9, 0x79, 0xE6, 0x00, 0x7E, 0xD8, 0xD0, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE2, 0x00, 0x5F, 0xF9, 0x88, 0xE4, 0x9E, 0x8F, 0xF8, 0xF9, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xC2, 0x00, 0x97, 0xF9, 0x90, 0xC9, 0x80, 0x69, 0x98, 0xA0, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0x62, 0x0C, 0x6E, 0xD8, 0x79, 0x2A, 0x09, 0x7D, 0xD8, 0xC0, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0x02, 0x04, 0x8A, 0xD8, 0x80, 0x0C, 0x12, 0x85, 0xD8, 0xF8, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE4, 0x00, 0x7E, 0x89, 0x70, 0xE6, 0x8F, 0x80, 0xF8, 0xF0, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xC4, 0x00, 0x67, 0x59, 0x70, 0xC6, 0x8A, 0x77, 0xA8, 0xF8, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE4, 0x80, 0x6C, 0xD9, 0x60, 0xE2, 0x00, 0x8D, 0xC8, 0xF8, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xE4, 0x80, 0x6C, 0xD9, 0x60, 0xE2, 0x00, 0x8D, 0xC8, 0xF8, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE2, 0x80, 0x88, 0x48, 0x98, 0xE2, 0x1E, 0x8E, 0xC9, 0xF8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xF2, 0x40, 0xA8, 0xB9, 0x80, 0xE2, 0x0C, 0x89, 0x09, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE4, 0x00, 0x77, 0xC5, 0xA8, 0xE2, 0x00, 0x9E, 0xD7, 0xE0, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xE4, 0x00, 0x77, 0xC5, 0xA8, 0xE2, 0x00, 0x9E, 0xD7, 0xE0, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE4, 0x80, 0x86, 0xB9, 0xA8, 0xE2, 0x14, 0x9F, 0xD7, 0xB0, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xC2, 0x80, 0x94, 0x09, 0x78, 0xC2, 0x00, 0x97, 0x97, 0xF8, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE2, 0x00, 0x68, 0x68, 0xAA, 0xE2, 0x0A, 0x9B, 0xB3, 0xF8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xC2, 0x00, 0x86, 0x68, 0xA0, 0xC2, 0x00, 0x77, 0x47, 0xE0, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE4, 0x00, 0xA6, 0x87, 0x81, 0xE2, 0x0A, 0x7E, 0xC9, 0xF8, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xE2, 0x00, 0x89, 0x40, 0x79, 0xE2, 0x00, 0x7E, 0xC9, 0x90, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE4, 0x80, 0xAA, 0xB8, 0x90, 0xE2, 0x00, 0x9E, 0xF9, 0xC0, 0x09, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xE6, 0x80, 0x9D, 0xB8, 0x51, 0xE2, 0x00, 0x9E, 0xF9, 0xA0, 0x01, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE2, 0x80, 0x8E, 0x64, 0xD0, 0xE2, 0x28, 0x6F, 0x73, 0xF8, 0x01, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xE2, 0x80, 0x8E, 0x64, 0xD0, 0xE2, 0x28, 0x6F, 0x73, 0xF8, 0x01, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE8, 0x00, 0x7D, 0x99, 0xA8, 0xE6, 0x80, 0x80, 0xF8, 0xF8, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xE8, 0x00, 0x7D, 0x99, 0xA8, 0xE6, 0x80, 0x80, 0xF8, 0xF8, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE6, 0x00, 0x9F, 0xB9, 0xD9, 0xE1, 0x00, 0x8F, 0xC8, 0xF9, 0x02, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xE6, 0x00, 0x9F, 0xB9, 0xD9, 0xE1, 0x00, 0x8F, 0xC8, 0xF9, 0x02, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE4, 0x00, 0x09, 0x68, 0x92, 0xE2, 0x2B, 0x9E, 0xF3, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xE4, 0x00, 0x09, 0x68, 0x92, 0xE2, 0x2B, 0x9E, 0xF3, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xC4, 0x00, 0x99, 0xE8, 0x73, 0xE2, 0x25, 0x6F, 0x93, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xC4, 0x00, 0x99, 0xE8, 0x73, 0xE2, 0x25, 0x6F, 0x93, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE6, 0x00, 0x6F, 0xDA, 0xC9, 0xE2, 0x05, 0x2F, 0xD8, 0xAA, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xE2, 0x00, 0x4F, 0xDA, 0xC8, 0xE2, 0x00, 0x0F, 0xD8, 0xD0, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xEC, 0x60, 0x9D, 0xC7, 0x00, 0xE2, 0x21, 0x7F, 0xC9, 0xF8, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xEC, 0x60, 0x9D, 0xC7, 0x00, 0xE2, 0x21, 0x7F, 0xC9, 0xF8, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE3, 0x00, 0x0F, 0xF7, 0xF9, 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 },
+ { 0xE3, 0x00, 0x0F, 0xF7, 0xF9, 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 } },
+ { { 0xE4, 0xA9, 0x0F, 0xA8, 0x02, 0xE2, 0x3C, 0x5F, 0xDA, 0x78, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xE4, 0xA9, 0x0F, 0xA8, 0x02, 0xE2, 0x3C, 0x5F, 0xDA, 0x78, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE8, 0x40, 0x0D, 0x89, 0xF9, 0xE2, 0x17, 0x7E, 0xD9, 0xF8, 0x07, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xE8, 0x40, 0x0D, 0x89, 0xF9, 0xE2, 0x17, 0x7E, 0xD9, 0xF8, 0x07, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE1, 0x00, 0xDF, 0x8A, 0xAA, 0xE2, 0x5E, 0xCF, 0xBA, 0xFA, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xE1, 0x00, 0xDF, 0x8A, 0xAA, 0xE2, 0x5E, 0xCF, 0xBA, 0xFA, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE2, 0x00, 0x0B, 0x68, 0xC0, 0xE2, 0x01, 0x9E, 0xB8, 0xF8, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xE2, 0x00, 0x0B, 0x68, 0xC0, 0xE2, 0x01, 0x9E, 0xB8, 0xF8, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xEA, 0x00, 0xAE, 0xAB, 0x91, 0xE2, 0x00, 0xAE, 0xBA, 0xD8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xEA, 0x00, 0xAE, 0xAB, 0x91, 0xE2, 0x00, 0xAE, 0xBA, 0xD8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xEB, 0x80, 0x8C, 0xCB, 0x72, 0xE2, 0x86, 0xAF, 0xCA, 0xF8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xEB, 0xC3, 0x9C, 0xCB, 0xA2, 0xE2, 0x4C, 0xAE, 0xCA, 0xFA, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE5, 0x40, 0xDB, 0x3B, 0x78, 0xE2, 0x80, 0xBE, 0xCA, 0xE1, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xE2, 0x80, 0x8E, 0xCB, 0xC0, 0xE2, 0x90, 0xAE, 0xCA, 0xFB, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE4, 0x00, 0x9E, 0xAA, 0x79, 0xE1, 0x43, 0x0F, 0xBA, 0xFA, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xE4, 0x00, 0x9E, 0xAA, 0x79, 0xE1, 0x43, 0x0F, 0xBA, 0xFA, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE7, 0x40, 0xEB, 0xCA, 0x80, 0xE2, 0x03, 0xBF, 0xBA, 0xC2, 0x02, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xE3, 0x80, 0xDB, 0xCA, 0x40, 0xE2, 0x08, 0xDF, 0xBA, 0xC1, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xEA, 0x00, 0x68, 0xB8, 0x90, 0xE2, 0x0A, 0x8E, 0xB8, 0xF8, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xEA, 0x00, 0x68, 0xB8, 0x90, 0xE2, 0x0A, 0x8E, 0xB8, 0xF8, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0x61, 0x00, 0xBE, 0x99, 0xFA, 0xE3, 0x40, 0xCF, 0xCA, 0xF9, 0x09, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0x62, 0x00, 0xCE, 0x9A, 0xA8, 0xE2, 0x45, 0xCF, 0xCA, 0xA0, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xCD, 0x00, 0x0B, 0x00, 0x90, 0xC2, 0x58, 0x0C, 0x00, 0xF8, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x1C },
+ { 0xCD, 0x00, 0x0B, 0x00, 0x90, 0xC2, 0x58, 0x0C, 0x00, 0xF8, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x1C } },
+ { { 0xE2, 0x00, 0x0E, 0x00, 0xA2, 0xE2, 0x58, 0x5F, 0xD0, 0xF9, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xE2, 0x00, 0x0E, 0x00, 0xA2, 0xE2, 0x58, 0x5F, 0xD0, 0xF9, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xEC, 0x00, 0x7D, 0xDA, 0x80, 0xE2, 0x00, 0x5E, 0x9B, 0xA8, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xE6, 0x0A, 0x4C, 0xC9, 0x60, 0xE2, 0x07, 0x0C, 0x7A, 0xB8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE9, 0xC0, 0xEE, 0xD8, 0x83, 0xE2, 0x05, 0xDD, 0xAA, 0xE0, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xED, 0x48, 0xDE, 0xD8, 0xB4, 0xE1, 0x00, 0xDD, 0xAA, 0xA9, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xDA, 0x00, 0x8F, 0xAC, 0x92, 0x22, 0x05, 0x8D, 0x8A, 0xE9, 0x02, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xEF, 0x00, 0x8C, 0xAA, 0x67, 0x25, 0x00, 0x9D, 0xAB, 0xC1, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0x62, 0x82, 0xCB, 0x7A, 0xD8, 0xE6, 0x56, 0xAF, 0xDB, 0xE0, 0x02, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0x62, 0x84, 0xBB, 0xAA, 0xCA, 0xCF, 0x41, 0xAC, 0xDA, 0xF8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xC2, 0x41, 0xAC, 0xBB, 0xBB, 0xC2, 0x85, 0x0E, 0xCB, 0xF9, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x12 },
+ { 0xC2, 0x03, 0x6A, 0x5B, 0xA4, 0xC2, 0x0D, 0x2A, 0xBB, 0xFC, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x12 } },
+ { { 0x75, 0x00, 0x0E, 0xBB, 0xB2, 0xE2, 0x1E, 0x0A, 0xA9, 0xF9, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x10 },
+ { 0x62, 0x00, 0x04, 0x9A, 0xE8, 0xE2, 0x00, 0x0A, 0x48, 0xFD, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x10 } },
+ { { 0x41, 0x00, 0x0E, 0xEA, 0xA3, 0xC2, 0x00, 0x08, 0xCA, 0xF8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x07 },
+ { 0x41, 0x00, 0x0E, 0xEA, 0xA3, 0xC2, 0x00, 0x08, 0xCA, 0xF8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x07 } },
+ { { 0xC1, 0x40, 0x0C, 0x59, 0xD2, 0xC2, 0x80, 0x3C, 0xAB, 0xF8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x0D },
+ { 0xC1, 0x40, 0x0C, 0x59, 0xD2, 0xC2, 0x80, 0x3C, 0xAB, 0xF8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x0D } },
+ { { 0x4B, 0x00, 0x0A, 0xF5, 0xC1, 0xC2, 0x19, 0x0C, 0xE9, 0xF8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x07 },
+ { 0x4B, 0x00, 0x0A, 0xF5, 0xC1, 0xC2, 0x19, 0x0C, 0xE9, 0xF8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x07 } },
+ { { 0x62, 0x00, 0x7F, 0xD8, 0xA8, 0xEA, 0x00, 0x8F, 0xD8, 0xF9, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0x62, 0x00, 0x7F, 0xD8, 0xA8, 0xEA, 0x00, 0x8F, 0xD8, 0xF9, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE1, 0x00, 0x7F, 0xD9, 0xAA, 0xE1, 0x00, 0x8F, 0xD8, 0xFA, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xE1, 0x00, 0x7F, 0xD9, 0xAA, 0xE1, 0x00, 0x8F, 0xD8, 0xFA, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xE1, 0x00, 0x7F, 0xD9, 0xAA, 0xE1, 0x00, 0x8F, 0xD8, 0xFA, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xE1, 0x00, 0x7F, 0xD9, 0xAA, 0xE1, 0x00, 0x8F, 0xD8, 0xFA, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0xCF, 0x40, 0x09, 0xEA, 0xA8, 0xC4, 0x00, 0x0C, 0xDB, 0xC8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 },
+ { 0xCF, 0x40, 0x09, 0xEA, 0xA8, 0xC4, 0x00, 0x0C, 0xDB, 0xC8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 } },
+ { { 0xCF, 0x40, 0x0C, 0xAA, 0xA8, 0xC4, 0x00, 0x18, 0xF9, 0xC8, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 },
+ { 0xCF, 0x40, 0x0C, 0xAA, 0xA8, 0xC4, 0x00, 0x18, 0xF9, 0xC8, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 } },
+ { { 0xC9, 0x0C, 0x88, 0xD9, 0x6A, 0xC2, 0x14, 0x3A, 0xEA, 0xF8, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x05 },
+ { 0xC5, 0x00, 0x98, 0xD9, 0x92, 0xC1, 0x16, 0x6E, 0xF9, 0xE8, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x05 } },
+ { { 0x03, 0x00, 0x15, 0x00, 0xC8, 0x02, 0x00, 0x08, 0x00, 0xF8, 0x09, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 },
+ { 0x03, 0x00, 0x15, 0x00, 0xC8, 0x02, 0x00, 0x08, 0x00, 0xF8, 0x09, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 } },
+ { { 0x01, 0x0C, 0x44, 0xE6, 0xE8, 0x01, 0x3F, 0x0C, 0xEA, 0xF8, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x04 },
+ { 0x02, 0x3F, 0x05, 0x08, 0xF8, 0x03, 0x3F, 0x3C, 0xF9, 0xF8, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x06 } },
+ { { 0x00, 0x00, 0x36, 0x67, 0xF8, 0x01, 0x3F, 0x0E, 0xFA, 0xF8, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x05 },
+ { 0x00, 0x00, 0x36, 0x67, 0xF8, 0x01, 0x3F, 0x0E, 0xFA, 0xF8, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x05 } },
+ { { 0x02, 0x00, 0x36, 0x68, 0xF8, 0x01, 0x3F, 0x0E, 0xFA, 0xF8, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x05 },
+ { 0x02, 0x00, 0x36, 0x68, 0xF8, 0x01, 0x3F, 0x0E, 0xFA, 0xF8, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x05 } },
+ { { 0xCB, 0x00, 0xAF, 0x00, 0xFA, 0xC0, 0x00, 0xC0, 0x06, 0xFB, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x0F },
+ { 0xCB, 0x00, 0xAF, 0x00, 0xFA, 0xC0, 0x00, 0xC0, 0x06, 0xFB, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x0F } },
+ { { 0x05, 0x0D, 0x80, 0xA6, 0xFB, 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 },
+ { 0x05, 0x0D, 0x80, 0xA6, 0xFB, 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 } },
+ { { 0x0F, 0x00, 0x90, 0xFA, 0xD0, 0x06, 0x00, 0xA7, 0x39, 0xA8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x06 },
+ { 0x0F, 0x00, 0x90, 0xFA, 0xD0, 0x06, 0x00, 0xA7, 0x39, 0xA8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x06 } },
+ { { 0xC9, 0x15, 0xDD, 0xFF, 0xF8, 0x00, 0x00, 0xE7, 0xFC, 0xD8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x38 },
+ { 0xC9, 0x15, 0xDD, 0xFF, 0xF8, 0x00, 0x00, 0xE7, 0xFC, 0xD8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x38 } },
+ { { 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 },
+ { 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 } },
+ { { 0x07, 0x80, 0x0B, 0xC8, 0xC9, 0x02, 0x3F, 0x0C, 0xEA, 0xF8, 0x0F, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x05 },
+ { 0x07, 0x80, 0x0B, 0xC8, 0xC9, 0x02, 0x3F, 0x0C, 0xEA, 0xF8, 0x0F, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x05 } },
+ { { 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 },
+ { 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 } },
+ { { 0x08, 0x00, 0x0B, 0x3C, 0xF8, 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 },
+ { 0x08, 0x00, 0x0B, 0x3C, 0xF8, 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 } },
+ { { 0x00, 0x3F, 0x4C, 0xFB, 0x00, 0x00, 0x3F, 0x0A, 0xE9, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x05 },
+ { 0x00, 0x3F, 0x4C, 0xFB, 0x00, 0x00, 0x3F, 0x0A, 0xE9, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x05 } }
+};
+
+static const AdLibInstrument g_gmPercussionInstrumentsOPL3[39][2] = {
+ { { 0x1A, 0x3F, 0x15, 0x05, 0xF8, 0x02, 0x21, 0x2B, 0xE4, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x06 },
+ { 0x11, 0x18, 0x15, 0x00, 0xF8, 0x12, 0x00, 0x2B, 0x03, 0xF8, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x06 } },
+ { { 0x11, 0x12, 0x04, 0x07, 0xF8, 0x02, 0x18, 0x0B, 0xE5, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x05 },
+ { 0x11, 0x28, 0x06, 0x04, 0xF8, 0x02, 0x1E, 0x1B, 0x02, 0xF8, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x05 } },
+ { { 0x0A, 0x3F, 0x0B, 0x01, 0xF8, 0x1F, 0x13, 0x46, 0xD0, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x01 },
+ { 0x04, 0x18, 0x06, 0x01, 0xB0, 0x10, 0x00, 0x07, 0x00, 0x90, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x01 } },
+ { { 0x00, 0x3F, 0x0F, 0x00, 0xF8, 0x10, 0x0A, 0x07, 0x00, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 },
+ { 0x02, 0x14, 0x04, 0x00, 0xC0, 0x11, 0x08, 0x07, 0x00, 0xC6, 0x02, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 } },
+ { { 0x0F, 0x3F, 0x0B, 0x00, 0xF8, 0x1F, 0x07, 0x19, 0xD0, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 },
+ { 0x0E, 0x32, 0x76, 0x03, 0xF8, 0x1F, 0x0F, 0x77, 0xD4, 0xFC, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 } },
+ { { 0x00, 0x3F, 0x1F, 0x00, 0xFA, 0x1F, 0x0C, 0x07, 0x00, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 },
+ { 0x07, 0x11, 0x13, 0x00, 0xA0, 0x13, 0x00, 0x07, 0x00, 0xC8, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 } },
+ { { 0x12, 0x3F, 0x05, 0x06, 0xF8, 0x03, 0x16, 0x4A, 0xD9, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 },
+ { 0x02, 0x22, 0x05, 0xB6, 0xF8, 0x04, 0x0A, 0x59, 0x03, 0xF8, 0x0B, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 } },
+ { { 0xCF, 0x7F, 0x08, 0xFF, 0xFA, 0x00, 0xC0, 0x2D, 0xF7, 0xE3, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 },
+ { 0xD2, 0x7F, 0x04, 0x0F, 0xFA, 0x10, 0xCD, 0x24, 0x07, 0xFB, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 } },
+ { { 0x12, 0x3F, 0x05, 0x06, 0xF8, 0x43, 0x17, 0x0C, 0xE9, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 },
+ { 0x12, 0x13, 0x09, 0x96, 0xF8, 0x44, 0x0A, 0x07, 0x03, 0xF8, 0x07, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 } },
+ { { 0xCF, 0x7F, 0x08, 0xCF, 0xFA, 0x00, 0x40, 0x2A, 0xF8, 0x8B, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x0C },
+ { 0xCF, 0x7F, 0x05, 0x07, 0xFA, 0x00, 0x40, 0x25, 0x08, 0xC3, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x0C } },
+ { { 0x12, 0x3F, 0x06, 0x17, 0xF8, 0x03, 0x1D, 0x0B, 0xE9, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 },
+ { 0x12, 0x1A, 0x08, 0x96, 0xF8, 0x44, 0x00, 0x08, 0x03, 0xF8, 0x05, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 } },
+ { { 0xCF, 0x7F, 0x08, 0xCD, 0xFA, 0x00, 0x40, 0x1A, 0x69, 0xB3, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x0C },
+ { 0xCD, 0x3F, 0x36, 0x05, 0xFC, 0x0F, 0x47, 0x46, 0x06, 0xDF, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x0C } },
+ { { 0x13, 0x3F, 0x05, 0x06, 0xF8, 0x03, 0x0D, 0x0A, 0xD9, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 },
+ { 0x12, 0x14, 0x09, 0x96, 0xF8, 0x44, 0x02, 0x07, 0x03, 0xF8, 0x07, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 } },
+ { { 0x15, 0x3F, 0x05, 0x06, 0xF8, 0x03, 0x16, 0x0C, 0xE9, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 },
+ { 0x12, 0x00, 0x07, 0x96, 0xE8, 0x44, 0x02, 0x08, 0x03, 0xF8, 0x07, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 } },
+ { { 0xCF, 0x3F, 0x2B, 0xFB, 0xFA, 0xC0, 0x16, 0x1A, 0xCA, 0xFB, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x10 },
+ { 0xCF, 0x3F, 0x2B, 0xFB, 0xFA, 0xC0, 0x1E, 0x1A, 0xCA, 0xFB, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x10 } },
+ { { 0x17, 0x3F, 0x04, 0x09, 0xF8, 0x03, 0x18, 0x0D, 0xE9, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 },
+ { 0x12, 0x00, 0x07, 0x96, 0xF8, 0x44, 0x02, 0x08, 0xF9, 0xF8, 0x01, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 } },
+ { { 0xCF, 0x3F, 0x0F, 0x5E, 0xF8, 0xC6, 0x0C, 0x00, 0xCA, 0xFB, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 },
+ { 0xCF, 0x3F, 0x04, 0x57, 0xF8, 0xC5, 0x13, 0x06, 0x05, 0xFF, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 } },
+ { { 0xCF, 0x3F, 0x7E, 0x9D, 0xF8, 0xC8, 0xC0, 0x0A, 0xBA, 0xD0, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x06 },
+ { 0xCF, 0x3F, 0x77, 0x09, 0xF8, 0xC2, 0xC0, 0x08, 0xB5, 0xEA, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x06 } },
+ { { 0xCF, 0x3F, 0x4D, 0x9F, 0xF8, 0xC6, 0x00, 0x08, 0xDA, 0xAB, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x04 },
+ { 0xCF, 0x3F, 0x47, 0x06, 0xF8, 0xCD, 0x00, 0x07, 0x05, 0xB3, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x04 } },
+ { { 0xCF, 0x3F, 0x5D, 0xAA, 0xF2, 0xC0, 0x8A, 0x67, 0x99, 0xF8, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 },
+ { 0xCF, 0x3F, 0x9A, 0x69, 0xF8, 0xCF, 0x88, 0x88, 0x48, 0xFA, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 } },
+ { { 0xCF, 0x3F, 0x4A, 0xFD, 0xF8, 0xCF, 0x00, 0x59, 0xEA, 0xD8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 },
+ { 0xCF, 0x3F, 0x48, 0x06, 0xF8, 0xCF, 0x00, 0x54, 0x04, 0xF9, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 } },
+ { { 0x0F, 0x18, 0x0A, 0xFA, 0xAB, 0x06, 0x06, 0x06, 0x39, 0xF8, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 },
+ { 0x03, 0x18, 0x04, 0x09, 0xAC, 0x05, 0x07, 0x08, 0x07, 0xF8, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 } },
+ { { 0xCF, 0x3F, 0x2B, 0xFC, 0xF8, 0xCC, 0xC4, 0x0B, 0xEA, 0xFB, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x10 },
+ { 0xCF, 0x3F, 0x25, 0x06, 0xF8, 0xCC, 0xD7, 0x05, 0x02, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x10 } },
+ { { 0x05, 0x1A, 0x04, 0x00, 0xF8, 0x12, 0x08, 0x0C, 0xEA, 0xE0, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x07 },
+ { 0x01, 0x00, 0x09, 0x08, 0x40, 0x13, 0x00, 0x2A, 0x0A, 0xD8, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x07 } },
+ { { 0x04, 0x19, 0x04, 0x00, 0xF8, 0x12, 0x08, 0x2C, 0xEA, 0xE0, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x04 },
+ { 0x04, 0x00, 0x07, 0x08, 0x40, 0x12, 0x00, 0x29, 0x08, 0xE0, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x04 } },
+ { { 0x04, 0x0A, 0x04, 0x00, 0xD8, 0x01, 0x02, 0x0D, 0xFA, 0xE0, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x07 },
+ { 0x04, 0x00, 0x03, 0x09, 0x93, 0x02, 0x00, 0x28, 0x09, 0xE8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x07 } },
+ { { 0x15, 0x14, 0x05, 0x00, 0xF9, 0x01, 0x03, 0x5C, 0xE9, 0xD8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x05 },
+ { 0x05, 0x00, 0x03, 0x03, 0x49, 0x02, 0x00, 0x58, 0x08, 0xE0, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x05 } },
+ { { 0x10, 0x10, 0x05, 0x08, 0xF8, 0x01, 0x03, 0x0D, 0xEA, 0xE8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x05 },
+ { 0x10, 0x00, 0x0C, 0x0C, 0x48, 0x02, 0x00, 0x08, 0xB9, 0xE0, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x05 } },
+ { { 0x11, 0x00, 0x06, 0x87, 0xFB, 0x02, 0x40, 0x09, 0x59, 0xC0, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x08 },
+ { 0x15, 0x00, 0x04, 0x87, 0xFB, 0x02, 0x40, 0x09, 0x59, 0xD0, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x08 } },
+ { { 0x13, 0x26, 0x04, 0x6A, 0xFB, 0x01, 0x00, 0x08, 0x5A, 0xE0, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x08 },
+ { 0x12, 0x26, 0x03, 0x6A, 0xFB, 0x02, 0x00, 0x06, 0x5A, 0xC0, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x08 } },
+ { { 0xCF, 0x4D, 0x0C, 0xAA, 0xA0, 0xC4, 0x00, 0x18, 0xF9, 0x90, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 },
+ { 0xCF, 0x4E, 0x05, 0xA6, 0xA0, 0xC6, 0x00, 0x16, 0xF8, 0x60, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 } },
+ { { 0xCF, 0x4D, 0x0C, 0xAA, 0xA0, 0xC3, 0x00, 0x18, 0xF8, 0x98, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 },
+ { 0xCF, 0x4E, 0x06, 0xAA, 0xA0, 0xC5, 0x00, 0x19, 0xF9, 0x90, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 } },
+ { { 0xCB, 0x3F, 0x8F, 0x00, 0xFA, 0xC5, 0x06, 0x98, 0xD6, 0xBB, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x0D },
+ { 0xC0, 0x00, 0xF0, 0x00, 0x00, 0xC0, 0x00, 0xF0, 0x00, 0x00, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x0D } },
+ { { 0x0C, 0x18, 0x87, 0xB3, 0xFB, 0x19, 0x0B, 0x55, 0x75, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 },
+ { 0x0C, 0x18, 0x87, 0xB3, 0xFB, 0x1B, 0x10, 0x57, 0x75, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 } },
+ { { 0x05, 0x11, 0x15, 0x00, 0xC8, 0x02, 0x00, 0x08, 0x00, 0xA8, 0x09, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 },
+ { 0x02, 0x11, 0x13, 0x00, 0xC8, 0x02, 0x00, 0x05, 0x00, 0x80, 0x09, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 } },
+ { { 0x04, 0x08, 0x15, 0x00, 0x90, 0x01, 0x00, 0x08, 0x00, 0xC0, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 },
+ { 0x03, 0x08, 0x14, 0x00, 0x90, 0x02, 0x00, 0x07, 0x00, 0xA8, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 } },
+ { { 0xDA, 0x00, 0x53, 0x30, 0xC0, 0x07, 0x10, 0x49, 0xC4, 0xDA, 0x03, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0xD2, 0x00, 0x56, 0x30, 0x90, 0x06, 0x00, 0x46, 0x56, 0x62, 0x09, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
+ { { 0x1C, 0x00, 0x07, 0xBC, 0xC8, 0x0C, 0x0A, 0x0B, 0x6A, 0xF2, 0x0B, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 },
+ { 0x18, 0x00, 0x07, 0xBC, 0x88, 0x09, 0x00, 0x0B, 0x6A, 0xBA, 0x0B, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 } },
+ { { 0x0A, 0x0E, 0x7F, 0x00, 0xF9, 0x13, 0x16, 0x28, 0x03, 0xF8, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
+ { 0x01, 0x0E, 0x54, 0x00, 0xF9, 0x15, 0x03, 0x27, 0x03, 0xF8, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } }
+};
+#endif
+
+static const byte g_gmPercussionInstrumentMap[128] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0xFF, 0xFF, 0x17, 0x18, 0x19, 0x1A,
+ 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x21, 0x22, 0x23, 0xFF, 0xFF,
+ 0x24, 0x25, 0xFF, 0xFF, 0xFF, 0x26, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+static byte g_volumeLookupTable[64][32];
+
+static const byte g_volumeTable[] = {
+ 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 lookupVolume(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 g_volumeLookupTable[-a][-b];
+ } else {
+ return -g_volumeLookupTable[a][-b];
+ }
+ } else {
+ if (a < 0) {
+ return -g_volumeLookupTable[-a][b];
+ } else {
+ return g_volumeLookupTable[a][b];
+ }
+ }
+}
+
+static void createLookupTable() {
+ int i, j;
+ int sum;
+
+ for (i = 0; i < 64; i++) {
+ sum = i;
+ for (j = 0; j < 32; j++) {
+ g_volumeLookupTable[i][j] = sum >> 5;
+ sum += i;
+ }
+ }
+ for (i = 0; i < 64; i++)
+ g_volumeLookupTable[i][0] = 0;
+}
+
+////////////////////////////////////////
+//
+// AdLib MIDI driver
+//
+////////////////////////////////////////
+
+class MidiDriver_ADLIB : public MidiDriver {
+ friend class AdLibPart;
+ friend class AdLibPercussionChannel;
+
+public:
+ MidiDriver_ADLIB();
+
+ int open();
+ void close();
+ void send(uint32 b);
+ void send(byte channel, uint32 b); // Supports higher than channel 15
+ uint32 property(int prop, uint32 param);
+ bool isOpen() const { return _isOpen; }
+ uint32 getBaseTempo() { return 1000000 / OPL::OPL::kDefaultCallbackFrequency; }
+
+ void setPitchBendRange(byte channel, uint range);
+ void sysEx_customInstrument(byte channel, uint32 type, const byte *instr);
+
+ MidiChannel *allocateChannel();
+ MidiChannel *getPercussionChannel() { return &_percussion; } // Percussion partially supported
+
+ virtual void setTimerCallback(void *timerParam, Common::TimerManager::TimerProc timerProc);
+
+private:
+ bool _scummSmallHeader; // FIXME: This flag controls a special mode for SCUMM V3 games
+#ifdef ENABLE_OPL3
+ bool _opl3Mode;
+#endif
+
+ OPL::OPL *_opl;
+ byte *_regCache;
+#ifdef ENABLE_OPL3
+ byte *_regCacheSecondary;
+#endif
+
+ Common::TimerManager::TimerProc _adlibTimerProc;
+ void *_adlibTimerParam;
+
+ int _timerCounter;
+
+ uint16 _channelTable2[9];
+ int _voiceIndex;
+ int _timerIncrease;
+ int _timerThreshold;
+ uint16 _curNotTable[9];
+ AdLibVoice _voices[9];
+ AdLibPart _parts[32];
+ AdLibPercussionChannel _percussion;
+
+ bool _isOpen;
+
+ void onTimer();
+ void partKeyOn(AdLibPart *part, const AdLibInstrument *instr, byte note, byte velocity, const AdLibInstrument *second, byte pan);
+ void partKeyOff(AdLibPart *part, byte note);
+
+ void adlibKeyOff(int chan);
+ void adlibNoteOn(int chan, byte note, int mod);
+ void adlibNoteOnEx(int chan, byte note, int mod);
+ int adlibGetRegValueParam(int chan, byte data);
+ void adlibSetupChannel(int chan, const AdLibInstrument *instr, byte vol1, byte vol2);
+#ifdef ENABLE_OPL3
+ void adlibSetupChannelSecondary(int chan, const AdLibInstrument *instr, byte vol1, byte vol2, byte pan);
+#endif
+ byte adlibGetRegValue(byte reg) {
+ return _regCache[reg];
+ }
+#ifdef ENABLE_OPL3
+ byte adlibGetRegValueSecondary(byte reg) {
+ return _regCacheSecondary[reg];
+ }
+#endif
+ void adlibSetParam(int channel, byte param, int value, bool primary = true);
+ void adlibKeyOnOff(int channel);
+ void adlibWrite(byte reg, byte value);
+#ifdef ENABLE_OPL3
+ void adlibWriteSecondary(byte reg, byte value);
+#endif
+ void adlibPlayNote(int channel, int note);
+
+ AdLibVoice *allocateVoice(byte pri);
+
+ void mcOff(AdLibVoice *voice);
+
+ static void linkMc(AdLibPart *part, AdLibVoice *voice);
+ void mcIncStuff(AdLibVoice *voice, Struct10 *s10, Struct11 *s11);
+ void mcInitStuff(AdLibVoice *voice, Struct10 *s10, Struct11 *s11, byte flags,
+ const InstrumentExtra *ie);
+
+ void struct10Init(Struct10 *s10, const InstrumentExtra *ie);
+ static byte struct10OnTimer(Struct10 *s10, Struct11 *s11);
+ static void struct10Setup(Struct10 *s10);
+ static int randomNr(int a);
+ void mcKeyOn(AdLibVoice *voice, const AdLibInstrument *instr, byte note, byte velocity, const AdLibInstrument *second, byte pan);
+};
+
+// MidiChannel method implementations
+
+void AdLibPart::init(MidiDriver_ADLIB *owner, byte channel) {
+ _owner = owner;
+ _channel = channel;
+ _priEff = 127;
+ programChange(0);
+}
+
+MidiDriver *AdLibPart::device() {
+ return _owner;
+}
+
+void AdLibPart::send(uint32 b) {
+ _owner->send(_channel, b);
+}
+
+void AdLibPart::noteOff(byte note) {
+#ifdef DEBUG_ADLIB
+ debug(6, "%10d: noteOff(%d)", g_tick, note);
+#endif
+ _owner->partKeyOff(this, note);
+}
+
+void AdLibPart::noteOn(byte note, byte velocity) {
+#ifdef DEBUG_ADLIB
+ debug(6, "%10d: noteOn(%d,%d)", g_tick, note, velocity);
+#endif
+ _owner->partKeyOn(this, &_partInstr, note, velocity,
+#ifdef ENABLE_OPL3
+ &_partInstrSecondary,
+#else
+ NULL,
+#endif
+ _pan);
+}
+
+void AdLibPart::programChange(byte program) {
+ if (program > 127)
+ return;
+
+ /*
+ uint i;
+ uint count = 0;
+ for (i = 0; i < ARRAYSIZE(g_gmInstruments[0]); ++i)
+ count += g_gmInstruments[program][i];
+ if (!count)
+ warning("No AdLib instrument defined for GM program %d", (int)program);
+ */
+ _program = program;
+#ifdef ENABLE_OPL3
+ if (!_owner->_opl3Mode) {
+#endif
+ memcpy(&_partInstr, &g_gmInstruments[program], sizeof(AdLibInstrument));
+#ifdef ENABLE_OPL3
+ } else {
+ memcpy(&_partInstr, &g_gmInstrumentsOPL3[program][0], sizeof(AdLibInstrument));
+ memcpy(&_partInstrSecondary, &g_gmInstrumentsOPL3[program][1], sizeof(AdLibInstrument));
+ }
+#endif
+}
+
+void AdLibPart::pitchBend(int16 bend) {
+ AdLibVoice *voice;
+
+ _pitchBend = bend;
+ for (voice = _voice; voice; voice = voice->_next) {
+#ifdef ENABLE_OPL3
+ if (!_owner->_opl3Mode) {
+#endif
+ _owner->adlibNoteOn(voice->_channel, voice->_note/* + _transposeEff*/,
+ (_pitchBend * _pitchBendFactor >> 6) + _detuneEff);
+#ifdef ENABLE_OPL3
+ } else {
+ _owner->adlibNoteOn(voice->_channel, voice->_note, _pitchBend >> 1);
+ }
+#endif
+ }
+}
+
+void AdLibPart::controlChange(byte control, byte value) {
+ switch (control) {
+ case 0:
+ case 32:
+ // Bank select. Not supported
+ break;
+ case 1:
+ modulationWheel(value);
+ break;
+ case 7:
+ volume(value);
+ break;
+ case 10:
+ panPosition(value);
+ break;
+ case 16:
+ pitchBendFactor(value);
+ break;
+ case 17:
+ detune(value);
+ break;
+ case 18:
+ priority(value);
+ break;
+ case 64:
+ sustain(value > 0);
+ break;
+ case 91:
+ // Effects level. Not supported.
+ break;
+ case 93:
+ // Chorus level. Not supported.
+ break;
+ case 119:
+ // Unknown, used in Simon the Sorcerer 2
+ break;
+ case 121:
+ // reset all controllers
+ modulationWheel(0);
+ pitchBendFactor(0);
+ detune(0);
+ sustain(0);
+ break;
+ case 123:
+ allNotesOff();
+ break;
+ default:
+ warning("AdLib: Unknown control change message %d (%d)", (int)control, (int)value);
+ }
+}
+
+void AdLibPart::modulationWheel(byte value) {
+ AdLibVoice *voice;
+
+ _modWheel = value;
+ for (voice = _voice; voice; voice = voice->_next) {
+ if (voice->_s10a.active && voice->_s11a.flag0x40)
+ voice->_s10a.modWheel = _modWheel >> 2;
+ if (voice->_s10b.active && voice->_s11b.flag0x40)
+ voice->_s10b.modWheel = _modWheel >> 2;
+ }
+}
+
+void AdLibPart::volume(byte value) {
+ AdLibVoice *voice;
+
+ _volEff = value;
+ for (voice = _voice; voice; voice = voice->_next) {
+#ifdef ENABLE_OPL3
+ if (!_owner->_opl3Mode) {
+#endif
+ _owner->adlibSetParam(voice->_channel, 0, g_volumeTable[g_volumeLookupTable[voice->_vol2][_volEff >> 2]]);
+ if (voice->_twoChan) {
+ _owner->adlibSetParam(voice->_channel, 13, g_volumeTable[g_volumeLookupTable[voice->_vol1][_volEff >> 2]]);
+ }
+#ifdef ENABLE_OPL3
+ } else {
+ _owner->adlibSetParam(voice->_channel, 0, g_volumeTable[((voice->_vol2 + 1) * _volEff) >> 7], true);
+ _owner->adlibSetParam(voice->_channel, 0, g_volumeTable[((voice->_secVol2 + 1) * _volEff) >> 7], false);
+ if (voice->_twoChan) {
+ _owner->adlibSetParam(voice->_channel, 13, g_volumeTable[((voice->_vol1 + 1) * _volEff) >> 7], true);
+ }
+ if (voice->_secTwoChan) {
+ _owner->adlibSetParam(voice->_channel, 13, g_volumeTable[((voice->_secVol1 + 1) * _volEff) >> 7], false);
+ }
+ }
+#endif
+ }
+}
+
+void AdLibPart::panPosition(byte value) {
+ _pan = value;
+}
+
+void AdLibPart::pitchBendFactor(byte value) {
+#ifdef ENABLE_OPL3
+ // Not supported in OPL3 mode.
+ if (_owner->_opl3Mode) {
+ return;
+ }
+#endif
+
+ AdLibVoice *voice;
+
+ _pitchBendFactor = value;
+ for (voice = _voice; voice; voice = voice->_next) {
+ _owner->adlibNoteOn(voice->_channel, voice->_note/* + _transposeEff*/,
+ (_pitchBend * _pitchBendFactor >> 6) + _detuneEff);
+ }
+}
+
+void AdLibPart::detune(byte value) {
+ // Sam&Max's OPL3 driver uses this for a completly different purpose. It
+ // is related to voice allocation. We ignore this for now.
+ // TODO: We probably need to look how the interpreter side of Sam&Max's
+ // iMuse version handles all this too. Implementing the driver side here
+ // would be not that hard.
+#ifdef ENABLE_OPL3
+ if (_owner->_opl3Mode) {
+ //_maxNotes = value;
+ return;
+ }
+#endif
+
+ AdLibVoice *voice;
+
+ _detuneEff = value;
+ for (voice = _voice; voice; voice = voice->_next) {
+ _owner->adlibNoteOn(voice->_channel, voice->_note/* + _transposeEff*/,
+ (_pitchBend * _pitchBendFactor >> 6) + _detuneEff);
+ }
+}
+
+void AdLibPart::priority(byte value) {
+ _priEff = value;
+}
+
+void AdLibPart::sustain(bool value) {
+ AdLibVoice *voice;
+
+ _pedal = value;
+ if (!value) {
+ for (voice = _voice; voice; voice = voice->_next) {
+ if (voice->_waitForPedal)
+ _owner->mcOff(voice);
+ }
+ }
+}
+
+void AdLibPart::allNotesOff() {
+ while (_voice)
+ _owner->mcOff(_voice);
+}
+
+void AdLibPart::sysEx_customInstrument(uint32 type, const byte *instr) {
+ // Sam&Max allows for instrument overwrites, but we will not support it
+ // until we can find any track actually using it.
+#ifdef ENABLE_OPL3
+ if (_owner->_opl3Mode) {
+ warning("AdLibPart::sysEx_customInstrument: Used in OPL3 mode");
+ return;
+ }
+#endif
+
+ if (type == 'ADL ') {
+ memcpy(&_partInstr, instr, sizeof(AdLibInstrument));
+ }
+}
+
+// MidiChannel method implementations for percussion
+
+AdLibPercussionChannel::~AdLibPercussionChannel() {
+ for (int i = 0; i < ARRAYSIZE(_customInstruments); ++i) {
+ delete _customInstruments[i];
+ }
+}
+
+void AdLibPercussionChannel::init(MidiDriver_ADLIB *owner, byte channel) {
+ AdLibPart::init(owner, channel);
+ _priEff = 0;
+ _volEff = 127;
+
+ // Initialize the custom instruments data
+ memset(_notes, 0, sizeof(_notes));
+ memset(_customInstruments, 0, sizeof(_customInstruments));
+}
+
+void AdLibPercussionChannel::noteOff(byte note) {
+ if (_customInstruments[note]) {
+ note = _notes[note];
+ }
+
+ // This used to ignore note off events, since the builtin percussion
+ // instrument data has a duration value, which causes the percussion notes
+ // to stop automatically. This is not the case for (Groovie's) custom
+ // percussion instruments though. Also the OPL3 driver of Sam&Max actually
+ // does not handle the duration value, so we need it there too.
+ _owner->partKeyOff(this, note);
+}
+
+void AdLibPercussionChannel::noteOn(byte note, byte velocity) {
+ const AdLibInstrument *inst = NULL;
+ const AdLibInstrument *sec = NULL;
+
+ // The custom instruments have priority over the default mapping
+ // We do not support custom instruments in OPL3 mode though.
+#ifdef ENABLE_OPL3
+ if (!_owner->_opl3Mode) {
+#endif
+ inst = _customInstruments[note];
+ if (inst)
+ note = _notes[note];
+#ifdef ENABLE_OPL3
+ }
+#endif
+
+ if (!inst) {
+ // Use the default GM to FM mapping as a fallback
+ byte key = g_gmPercussionInstrumentMap[note];
+ if (key != 0xFF) {
+#ifdef ENABLE_OPL3
+ if (!_owner->_opl3Mode) {
+#endif
+ inst = &g_gmPercussionInstruments[key];
+#ifdef ENABLE_OPL3
+ } else {
+ inst = &g_gmPercussionInstrumentsOPL3[key][0];
+ sec = &g_gmPercussionInstrumentsOPL3[key][1];
+ }
+#endif
+ }
+ }
+
+ if (!inst) {
+ debug(2, "No instrument FM definition for GM percussion key %d", (int)note);
+ return;
+ }
+
+ _owner->partKeyOn(this, inst, note, velocity, sec, _pan);
+}
+
+void AdLibPercussionChannel::sysEx_customInstrument(uint32 type, const byte *instr) {
+ // We do not allow custom instruments in OPL3 mode right now.
+#ifdef ENABLE_OPL3
+ if (_owner->_opl3Mode) {
+ warning("AdLibPercussionChannel::sysEx_customInstrument: Used in OPL3 mode");
+ return;
+ }
+#endif
+
+ if (type == 'ADLP') {
+ byte note = instr[0];
+ _notes[note] = instr[1];
+
+ // Allocate memory for the new instruments
+ if (!_customInstruments[note]) {
+ _customInstruments[note] = new AdLibInstrument;
+ memset(_customInstruments[note], 0, sizeof(AdLibInstrument));
+ }
+
+ // Save the new instrument data
+ _customInstruments[note]->modCharacteristic = instr[2];
+ _customInstruments[note]->modScalingOutputLevel = instr[3];
+ _customInstruments[note]->modAttackDecay = instr[4];
+ _customInstruments[note]->modSustainRelease = instr[5];
+ _customInstruments[note]->modWaveformSelect = instr[6];
+ _customInstruments[note]->carCharacteristic = instr[7];
+ _customInstruments[note]->carScalingOutputLevel = instr[8];
+ _customInstruments[note]->carAttackDecay = instr[9];
+ _customInstruments[note]->carSustainRelease = instr[10];
+ _customInstruments[note]->carWaveformSelect = instr[11];
+ _customInstruments[note]->feedback = instr[12];
+ }
+}
+
+// MidiDriver method implementations
+
+MidiDriver_ADLIB::MidiDriver_ADLIB() {
+ uint i;
+
+ _scummSmallHeader = false;
+#ifdef ENABLE_OPL3
+ _opl3Mode = false;
+#endif
+
+ _regCache = 0;
+#ifdef ENABLE_OPL3
+ _regCacheSecondary = 0;
+#endif
+
+ _timerCounter = 0;
+ _voiceIndex = -1;
+ for (i = 0; i < ARRAYSIZE(_curNotTable); ++i) {
+ _curNotTable[i] = 0;
+ }
+
+ for (i = 0; i < ARRAYSIZE(_parts); ++i) {
+ _parts[i].init(this, i + ((i >= 9) ? 1 : 0));
+ }
+ _percussion.init(this, 9);
+ _timerIncrease = 0xD69;
+ _timerThreshold = 0x411B;
+ _opl = 0;
+ _adlibTimerProc = 0;
+ _adlibTimerParam = 0;
+ _isOpen = false;
+}
+
+int MidiDriver_ADLIB::open() {
+ if (_isOpen)
+ return MERR_ALREADY_OPEN;
+
+ _isOpen = true;
+
+ int i;
+ AdLibVoice *voice;
+
+ for (i = 0, voice = _voices; i != ARRAYSIZE(_voices); i++, voice++) {
+ voice->_channel = i;
+ voice->_s11a.s10 = &voice->_s10b;
+ voice->_s11b.s10 = &voice->_s10a;
+ }
+
+ // Try to use OPL3 when requested.
+#ifdef ENABLE_OPL3
+ if (_opl3Mode) {
+ _opl = OPL::Config::create(OPL::Config::kOpl3);
+ }
+
+ // Initialize plain OPL2 when no OPL3 is intiailized already.
+ if (!_opl) {
+#endif
+ _opl = OPL::Config::create();
+#ifdef ENABLE_OPL3
+ _opl3Mode = false;
+ }
+#endif
+ _opl->init();
+
+ _regCache = (byte *)calloc(256, 1);
+
+ adlibWrite(8, 0x40);
+ adlibWrite(0xBD, 0x00);
+#ifdef ENABLE_OPL3
+ if (!_opl3Mode) {
+#endif
+ adlibWrite(1, 0x20);
+ createLookupTable();
+#ifdef ENABLE_OPL3
+ } else {
+ _regCacheSecondary = (byte *)calloc(256, 1);
+ adlibWriteSecondary(5, 1);
+ }
+#endif
+
+ _opl->start(new Common::Functor0Mem<void, MidiDriver_ADLIB>(this, &MidiDriver_ADLIB::onTimer));
+ return 0;
+}
+
+void MidiDriver_ADLIB::close() {
+ if (!_isOpen)
+ return;
+ _isOpen = false;
+
+ // Stop the OPL timer
+ _opl->stop();
+
+ uint i;
+ for (i = 0; i < ARRAYSIZE(_voices); ++i) {
+ if (_voices[i]._part)
+ mcOff(&_voices[i]);
+ }
+
+ // Turn off the OPL emulation
+ delete _opl;
+ _opl = 0;
+
+ free(_regCache);
+#ifdef ENABLE_OPL3
+ free(_regCacheSecondary);
+#endif
+}
+
+void MidiDriver_ADLIB::send(uint32 b) {
+ send(b & 0xF, b & 0xFFFFFFF0);
+}
+
+void MidiDriver_ADLIB::send(byte chan, uint32 b) {
+ //byte param3 = (byte) ((b >> 24) & 0xFF);
+ byte param2 = (byte)((b >> 16) & 0xFF);
+ byte param1 = (byte)((b >> 8) & 0xFF);
+ byte cmd = (byte)(b & 0xF0);
+
+ AdLibPart *part;
+ if (chan == 9)
+ part = &_percussion;
+ else
+ part = &_parts[chan];
+
+ switch (cmd) {
+ case 0x80:// Note Off
+ part->noteOff(param1);
+ break;
+ case 0x90: // Note On
+ part->noteOn(param1, param2);
+ break;
+ case 0xA0: // Aftertouch
+ break; // Not supported.
+ case 0xB0: // Control Change
+ part->controlChange(param1, param2);
+ break;
+ case 0xC0: // Program Change
+ part->programChange(param1);
+ break;
+ case 0xD0: // Channel Pressure
+ break; // Not supported.
+ case 0xE0: // Pitch Bend
+ part->pitchBend((param1 | (param2 << 7)) - 0x2000);
+ break;
+ 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);
+ }
+}
+
+uint32 MidiDriver_ADLIB::property(int prop, uint32 param) {
+ switch (prop) {
+ case PROP_OLD_ADLIB: // Older games used a different operator volume algorithm
+ _scummSmallHeader = (param > 0);
+ if (_scummSmallHeader) {
+ _timerIncrease = 473;
+ _timerThreshold = 1000;
+ } else {
+ _timerIncrease = 0xD69;
+ _timerThreshold = 0x411B;
+ }
+ return 1;
+
+ case PROP_SCUMM_OPL3: // Sam&Max OPL3 support.
+#ifdef ENABLE_OPL3
+ _opl3Mode = (param > 0);
+#endif
+ return 1;
+ }
+
+ return 0;
+}
+
+void MidiDriver_ADLIB::setPitchBendRange(byte channel, uint range) {
+#ifdef ENABLE_OPL3
+ // Not supported in OPL3 mode.
+ if (_opl3Mode) {
+ return;
+ }
+#endif
+
+ AdLibVoice *voice;
+ AdLibPart *part = &_parts[channel];
+
+ part->_pitchBendFactor = range;
+ for (voice = part->_voice; voice; voice = voice->_next) {
+ adlibNoteOn(voice->_channel, voice->_note/* + part->_transposeEff*/,
+ (part->_pitchBend * part->_pitchBendFactor >> 6) + part->_detuneEff);
+ }
+}
+
+void MidiDriver_ADLIB::sysEx_customInstrument(byte channel, uint32 type, const byte *instr) {
+ _parts[channel].sysEx_customInstrument(type, instr);
+}
+
+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;
+}
+
+// All the code brought over from IMuseAdLib
+
+void MidiDriver_ADLIB::adlibWrite(byte reg, byte value) {
+ if (_regCache[reg] == value) {
+ return;
+ }
+#ifdef DEBUG_ADLIB
+ debug(6, "%10d: adlibWrite[%x] = %x", g_tick, reg, value);
+#endif
+ _regCache[reg] = value;
+
+ _opl->writeReg(reg, value);
+}
+
+#ifdef ENABLE_OPL3
+void MidiDriver_ADLIB::adlibWriteSecondary(byte reg, byte value) {
+ assert(_opl3Mode);
+
+ if (_regCacheSecondary[reg] == value) {
+ return;
+ }
+#ifdef DEBUG_ADLIB
+ debug(6, "%10d: adlibWriteSecondary[%x] = %x", g_tick, reg, value);
+#endif
+ _regCacheSecondary[reg] = value;
+
+ _opl->writeReg(reg | 0x100, value);
+}
+#endif
+
+void MidiDriver_ADLIB::onTimer() {
+ if (_adlibTimerProc)
+ (*_adlibTimerProc)(_adlibTimerParam);
+
+ _timerCounter += _timerIncrease;
+ while (_timerCounter >= _timerThreshold) {
+ _timerCounter -= _timerThreshold;
+#ifdef DEBUG_ADLIB
+ g_tick++;
+#endif
+ // Sam&Max's OPL3 driver does not have any timer handling like this.
+#ifdef ENABLE_OPL3
+ if (!_opl3Mode) {
+#endif
+ AdLibVoice *voice = _voices;
+ for (int i = 0; i != ARRAYSIZE(_voices); i++, voice++) {
+ if (!voice->_part)
+ continue;
+ if (voice->_duration && (voice->_duration -= 0x11) <= 0) {
+ mcOff(voice);
+ return;
+ }
+ if (voice->_s10a.active) {
+ mcIncStuff(voice, &voice->_s10a, &voice->_s11a);
+ }
+ if (voice->_s10b.active) {
+ mcIncStuff(voice, &voice->_s10b, &voice->_s11b);
+ }
+ }
+#ifdef ENABLE_OPL3
+ }
+#endif
+ }
+}
+
+void MidiDriver_ADLIB::setTimerCallback(void *timerParam, Common::TimerManager::TimerProc timerProc) {
+ _adlibTimerProc = timerProc;
+ _adlibTimerParam = timerParam;
+}
+
+void MidiDriver_ADLIB::mcOff(AdLibVoice *voice) {
+ AdLibVoice *tmp;
+
+ adlibKeyOff(voice->_channel);
+
+ tmp = voice->_prev;
+
+ if (voice->_next)
+ voice->_next->_prev = tmp;
+ if (tmp)
+ tmp->_next = voice->_next;
+ else
+ voice->_part->_voice = voice->_next;
+ voice->_part = NULL;
+}
+
+void MidiDriver_ADLIB::mcIncStuff(AdLibVoice *voice, Struct10 *s10, Struct11 *s11) {
+ byte code;
+ AdLibPart *part = voice->_part;
+
+ code = struct10OnTimer(s10, s11);
+
+ if (code & 1) {
+ switch (s11->param) {
+ case 0:
+ voice->_vol2 = s10->startValue + s11->modifyVal;
+ if (!_scummSmallHeader) {
+ adlibSetParam(voice->_channel, 0,
+ g_volumeTable[g_volumeLookupTable[voice->_vol2]
+ [part->_volEff >> 2]]);
+ } else {
+ adlibSetParam(voice->_channel, 0, voice->_vol2);
+ }
+ break;
+ case 13:
+ voice->_vol1 = s10->startValue + s11->modifyVal;
+ if (voice->_twoChan && !_scummSmallHeader) {
+ adlibSetParam(voice->_channel, 13,
+ g_volumeTable[g_volumeLookupTable[voice->_vol1]
+ [part->_volEff >> 2]]);
+ } else {
+ adlibSetParam(voice->_channel, 13, voice->_vol1);
+ }
+ break;
+ case 30:
+ s11->s10->modWheel = (char)s11->modifyVal;
+ break;
+ case 31:
+ s11->s10->unk3 = (char)s11->modifyVal;
+ break;
+ default:
+ adlibSetParam(voice->_channel, s11->param,
+ s10->startValue + s11->modifyVal);
+ break;
+ }
+ }
+
+ if (code & 2 && s11->flag0x10)
+ adlibKeyOnOff(voice->_channel);
+}
+
+void MidiDriver_ADLIB::adlibKeyOff(int chan) {
+ byte reg = chan + 0xB0;
+ adlibWrite(reg, adlibGetRegValue(reg) & ~0x20);
+#ifdef ENABLE_OPL3
+ if (_opl3Mode) {
+ adlibWriteSecondary(reg, adlibGetRegValueSecondary(reg) & ~0x20);
+ }
+#endif
+}
+
+byte MidiDriver_ADLIB::struct10OnTimer(Struct10 *s10, Struct11 *s11) {
+ byte result = 0;
+ int i;
+
+ if (s10->count && (s10->count -= 17) <= 0) {
+ s10->active = 0;
+ return 0;
+ }
+
+ i = s10->curVal + s10->speedHi;
+ s10->speedLoCounter += s10->speedLo;
+ if (s10->speedLoCounter >= s10->speedLoMax) {
+ s10->speedLoCounter -= s10->speedLoMax;
+ i += s10->direction;
+ }
+ if (s10->curVal != i || s10->modWheel != s10->modWheelLast) {
+ s10->curVal = i;
+ s10->modWheelLast = s10->modWheel;
+ i = lookupVolume(i, s10->modWheelLast);
+ if (i != s11->modifyVal) {
+ s11->modifyVal = i;
+ result = 1;
+ }
+ }
+
+ if (!--s10->numSteps) {
+ s10->active++;
+ if (s10->active > 4) {
+ if (s10->loop) {
+ s10->active = 1;
+ result |= 2;
+ struct10Setup(s10);
+ } else {
+ s10->active = 0;
+ }
+ } else {
+ struct10Setup(s10);
+ }
+ }
+
+ return result;
+}
+
+void MidiDriver_ADLIB::adlibSetParam(int channel, byte param, int value, bool primary) {
+ const AdLibSetParams *as;
+ byte reg;
+
+ assert(channel >= 0 && channel < 9);
+#ifdef ENABLE_OPL3
+ assert(!_opl3Mode || (param == 0 || param == 13));
+#endif
+
+ if (param <= 12) {
+ reg = g_operator2Offsets[channel];
+ } else if (param <= 25) {
+ param -= 13;
+ reg = g_operator1Offsets[channel];
+ } else if (param <= 27) {
+ param -= 13;
+ reg = channel;
+ } else if (param == 28 || param == 29) {
+ if (param == 28)
+ value -= 15;
+ else
+ value -= 383;
+ value <<= 4;
+ _channelTable2[channel] = value;
+ adlibPlayNote(channel, _curNotTable[channel] + value);
+ return;
+ } else {
+ return;
+ }
+
+ as = &g_setParamTable[param];
+ if (as->inversion)
+ value = as->inversion - value;
+ reg += as->registerBase;
+#ifdef ENABLE_OPL3
+ if (primary) {
+#endif
+ adlibWrite(reg, (adlibGetRegValue(reg) & ~as->mask) | (((byte)value) << as->shift));
+#ifdef ENABLE_OPL3
+ } else {
+ adlibWriteSecondary(reg, (adlibGetRegValueSecondary(reg) & ~as->mask) | (((byte)value) << as->shift));
+ }
+#endif
+}
+
+void MidiDriver_ADLIB::adlibKeyOnOff(int channel) {
+#ifdef ENABLE_OPL3
+ assert(!_opl3Mode);
+#endif
+
+ byte val;
+ byte reg = channel + 0xB0;
+ assert(channel >= 0 && channel < 9);
+
+ val = adlibGetRegValue(reg);
+ adlibWrite(reg, val & ~0x20);
+ adlibWrite(reg, val | 0x20);
+}
+
+void MidiDriver_ADLIB::struct10Setup(Struct10 *s10) {
+ int b, c, d, e, f, g, h;
+ byte t;
+
+ b = s10->unk3;
+ f = s10->active - 1;
+
+ t = s10->tableA[f];
+ e = g_numStepsTable[g_volumeLookupTable[t & 0x7F][b]];
+ if (t & 0x80) {
+ e = randomNr(e);
+ }
+ if (e == 0)
+ e++;
+
+ s10->numSteps = s10->speedLoMax = e;
+
+ if (f != 2) {
+ c = s10->maxValue;
+ g = s10->startValue;
+ t = s10->tableB[f];
+ d = lookupVolume(c, (t & 0x7F) - 31);
+ if (t & 0x80) {
+ d = randomNr(d);
+ }
+ if (d + g > c) {
+ h = c - g;
+ } else {
+ h = d;
+ if (d + g < 0)
+ h = -g;
+ }
+ h -= s10->curVal;
+ } else {
+ h = 0;
+ }
+
+ s10->speedHi = h / e;
+ if (h < 0) {
+ h = -h;
+ s10->direction = -1;
+ } else {
+ s10->direction = 1;
+ }
+
+ s10->speedLo = h % e;
+ s10->speedLoCounter = 0;
+}
+
+void MidiDriver_ADLIB::adlibPlayNote(int channel, int note) {
+ byte old, oct, notex;
+ int note2;
+ int i;
+
+ note2 = (note >> 7) - 4;
+ note2 = (note2 < 128) ? note2 : 0;
+
+ oct = (note2 / 12);
+ if (oct > 7)
+ oct = 7 << 2;
+ else
+ oct <<= 2;
+ notex = note2 % 12 + 3;
+
+ old = adlibGetRegValue(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);
+ adlibWrite(channel + 0xA0, g_noteFrequencies[i]);
+ adlibWrite(channel + 0xB0, oct | 0x20);
+}
+
+int MidiDriver_ADLIB::randomNr(int a) {
+ static byte _randSeed = 1;
+ if (_randSeed & 1) {
+ _randSeed >>= 1;
+ _randSeed ^= 0xB8;
+ } else {
+ _randSeed >>= 1;
+ }
+ return _randSeed * a >> 8;
+}
+
+void MidiDriver_ADLIB::partKeyOff(AdLibPart *part, byte note) {
+ AdLibVoice *voice;
+
+ for (voice = part->_voice; voice; voice = voice->_next) {
+ if (voice->_note == note) {
+ if (part->_pedal)
+ voice->_waitForPedal = true;
+ else
+ mcOff(voice);
+ }
+ }
+}
+
+void MidiDriver_ADLIB::partKeyOn(AdLibPart *part, const AdLibInstrument *instr, byte note, byte velocity, const AdLibInstrument *second, byte pan) {
+ AdLibVoice *voice;
+
+ voice = allocateVoice(part->_priEff);
+ if (!voice)
+ return;
+
+ linkMc(part, voice);
+ mcKeyOn(voice, instr, note, velocity, second, pan);
+}
+
+AdLibVoice *MidiDriver_ADLIB::allocateVoice(byte pri) {
+ AdLibVoice *ac, *best = NULL;
+ int i;
+
+ for (i = 0; i < 9; i++) {
+ if (++_voiceIndex >= 9)
+ _voiceIndex = 0;
+ ac = &_voices[_voiceIndex];
+ if (!ac->_part)
+ return ac;
+ if (!ac->_next) {
+ if (ac->_part->_priEff <= pri) {
+ pri = ac->_part->_priEff;
+ best = ac;
+ }
+ }
+ }
+
+ /* SCUMM V3 games don't have note priorities, first comes wins. */
+ if (_scummSmallHeader)
+ return NULL;
+
+ if (best)
+ mcOff(best);
+ return best;
+}
+
+void MidiDriver_ADLIB::linkMc(AdLibPart *part, AdLibVoice *voice) {
+ voice->_part = part;
+ voice->_next = (AdLibVoice *)part->_voice;
+ part->_voice = voice;
+ voice->_prev = NULL;
+
+ if (voice->_next)
+ voice->_next->_prev = voice;
+}
+
+void MidiDriver_ADLIB::mcKeyOn(AdLibVoice *voice, const AdLibInstrument *instr, byte note, byte velocity, const AdLibInstrument *second, byte pan) {
+ AdLibPart *part = voice->_part;
+ byte vol1, vol2;
+#ifdef ENABLE_OPL3
+ byte secVol1 = 0, secVol2 = 0;
+#endif
+
+ voice->_twoChan = instr->feedback & 1;
+ voice->_note = note;
+ voice->_waitForPedal = false;
+ voice->_duration = instr->duration;
+ if (voice->_duration != 0)
+ voice->_duration *= 63;
+
+ if (!_scummSmallHeader) {
+#ifdef ENABLE_OPL3
+ if (_opl3Mode)
+ vol1 = (instr->modScalingOutputLevel & 0x3F) + (velocity * ((instr->modWaveformSelect >> 3) + 1)) / 64;
+ else
+#endif
+ vol1 = (instr->modScalingOutputLevel & 0x3F) + g_volumeLookupTable[velocity >> 1][instr->modWaveformSelect >> 2];
+ } else {
+ vol1 = 0x3f - (instr->modScalingOutputLevel & 0x3F);
+ }
+ if (vol1 > 0x3F)
+ vol1 = 0x3F;
+ voice->_vol1 = vol1;
+
+ if (!_scummSmallHeader) {
+#ifdef ENABLE_OPL3
+ if (_opl3Mode)
+ vol2 = (instr->carScalingOutputLevel & 0x3F) + (velocity * ((instr->carWaveformSelect >> 3) + 1)) / 64;
+ else
+#endif
+ vol2 = (instr->carScalingOutputLevel & 0x3F) + g_volumeLookupTable[velocity >> 1][instr->carWaveformSelect >> 2];
+ } else {
+ vol2 = 0x3f - (instr->carScalingOutputLevel & 0x3F);
+ }
+ if (vol2 > 0x3F)
+ vol2 = 0x3F;
+ voice->_vol2 = vol2;
+
+#ifdef ENABLE_OPL3
+ if (_opl3Mode) {
+ voice->_secTwoChan = second->feedback & 1;
+ secVol1 = (second->modScalingOutputLevel & 0x3F) + (velocity * ((second->modWaveformSelect >> 3) + 1)) / 64;
+ if (secVol1 > 0x3F) {
+ secVol1 = 0x3F;
+ }
+ voice->_secVol1 = secVol1;
+ secVol2 = (second->carScalingOutputLevel & 0x3F) + (velocity * ((second->carWaveformSelect >> 3) + 1)) / 64;
+ if (secVol2 > 0x3F) {
+ secVol2 = 0x3F;
+ }
+ voice->_secVol2 = secVol2;
+ }
+#endif
+
+ if (!_scummSmallHeader) {
+#ifdef ENABLE_OPL3
+ if (!_opl3Mode) {
+#endif
+ int c = part->_volEff >> 2;
+ vol2 = g_volumeTable[g_volumeLookupTable[vol2][c]];
+ if (voice->_twoChan)
+ vol1 = g_volumeTable[g_volumeLookupTable[vol1][c]];
+#ifdef ENABLE_OPL3
+ } else {
+ vol2 = g_volumeTable[((vol2 + 1) * part->_volEff) >> 7];
+ secVol2 = g_volumeTable[((secVol2 + 1) * part->_volEff) >> 7];
+ if (voice->_twoChan)
+ vol1 = g_volumeTable[((vol1 + 1) * part->_volEff) >> 7];
+ if (voice->_secTwoChan)
+ secVol1 = g_volumeTable[((secVol1 + 1) * part->_volEff) >> 7];
+ }
+#endif
+ }
+
+ adlibSetupChannel(voice->_channel, instr, vol1, vol2);
+#ifdef ENABLE_OPL3
+ if (!_opl3Mode) {
+#endif
+ adlibNoteOnEx(voice->_channel, /*part->_transposeEff + */note, part->_detuneEff + (part->_pitchBend * part->_pitchBendFactor >> 6));
+
+ if (instr->flagsA & 0x80) {
+ mcInitStuff(voice, &voice->_s10a, &voice->_s11a, instr->flagsA, &instr->extraA);
+ } else {
+ voice->_s10a.active = 0;
+ }
+
+ if (instr->flagsB & 0x80) {
+ mcInitStuff(voice, &voice->_s10b, &voice->_s11b, instr->flagsB, &instr->extraB);
+ } else {
+ voice->_s10b.active = 0;
+ }
+#ifdef ENABLE_OPL3
+ } else {
+ adlibSetupChannelSecondary(voice->_channel, second, secVol1, secVol2, pan);
+ adlibNoteOnEx(voice->_channel, note, part->_pitchBend >> 1);
+ }
+#endif
+}
+
+void MidiDriver_ADLIB::adlibSetupChannel(int chan, const AdLibInstrument *instr, byte vol1, byte vol2) {
+ assert(chan >= 0 && chan < 9);
+
+ byte channel = g_operator1Offsets[chan];
+ adlibWrite(channel + 0x20, instr->modCharacteristic);
+ adlibWrite(channel + 0x40, (instr->modScalingOutputLevel | 0x3F) - vol1);
+ adlibWrite(channel + 0x60, 0xff & (~instr->modAttackDecay));
+ adlibWrite(channel + 0x80, 0xff & (~instr->modSustainRelease));
+ adlibWrite(channel + 0xE0, instr->modWaveformSelect);
+
+ channel = g_operator2Offsets[chan];
+ adlibWrite(channel + 0x20, instr->carCharacteristic);
+ adlibWrite(channel + 0x40, (instr->carScalingOutputLevel | 0x3F) - vol2);
+ adlibWrite(channel + 0x60, 0xff & (~instr->carAttackDecay));
+ adlibWrite(channel + 0x80, 0xff & (~instr->carSustainRelease));
+ adlibWrite(channel + 0xE0, instr->carWaveformSelect);
+
+ adlibWrite((byte)chan + 0xC0, instr->feedback
+#ifdef ENABLE_OPL3
+ | (_opl3Mode ? 0x30 : 0)
+#endif
+ );
+}
+
+#ifdef ENABLE_OPL3
+void MidiDriver_ADLIB::adlibSetupChannelSecondary(int chan, const AdLibInstrument *instr, byte vol1, byte vol2, byte pan) {
+ assert(chan >= 0 && chan < 9);
+ assert(_opl3Mode);
+
+ byte channel = g_operator1Offsets[chan];
+ adlibWriteSecondary(channel + 0x20, instr->modCharacteristic);
+ adlibWriteSecondary(channel + 0x40, (instr->modScalingOutputLevel | 0x3F) - vol1);
+ adlibWriteSecondary(channel + 0x60, 0xff & (~instr->modAttackDecay));
+ adlibWriteSecondary(channel + 0x80, 0xff & (~instr->modSustainRelease));
+ adlibWriteSecondary(channel + 0xE0, instr->modWaveformSelect);
+
+ channel = g_operator2Offsets[chan];
+ adlibWriteSecondary(channel + 0x20, instr->carCharacteristic);
+ adlibWriteSecondary(channel + 0x40, (instr->carScalingOutputLevel | 0x3F) - vol2);
+ adlibWriteSecondary(channel + 0x60, 0xff & (~instr->carAttackDecay));
+ adlibWriteSecondary(channel + 0x80, 0xff & (~instr->carSustainRelease));
+ adlibWriteSecondary(channel + 0xE0, instr->carWaveformSelect);
+
+ // The original uses the following (strange) behavior:
+#if 0
+ if (instr->feedback | (pan > 64)) {
+ adlibWriteSecondary((byte)chan + 0xC0, 0x20);
+ } else {
+ adlibWriteSecondary((byte)chan + 0xC0, 0x10);
+ }
+#else
+ adlibWriteSecondary((byte)chan + 0xC0, instr->feedback | ((pan > 64) ? 0x20 : 0x10));
+#endif
+}
+#endif
+
+void MidiDriver_ADLIB::mcInitStuff(AdLibVoice *voice, Struct10 *s10,
+ Struct11 *s11, byte flags, const InstrumentExtra *ie) {
+ AdLibPart *part = voice->_part;
+ s11->modifyVal = 0;
+ s11->flag0x40 = flags & 0x40;
+ s10->loop = flags & 0x20;
+ s11->flag0x10 = flags & 0x10;
+ s11->param = g_paramTable1[flags & 0xF];
+ s10->maxValue = g_maxValTable[flags & 0xF];
+ s10->unk3 = 31;
+ if (s11->flag0x40) {
+ s10->modWheel = part->_modWheel >> 2;
+ } else {
+ s10->modWheel = 31;
+ }
+
+ switch (s11->param) {
+ case 0:
+ s10->startValue = voice->_vol2;
+ break;
+ case 13:
+ s10->startValue = voice->_vol1;
+ break;
+ case 30:
+ s10->startValue = 31;
+ s11->s10->modWheel = 0;
+ break;
+ case 31:
+ s10->startValue = 0;
+ s11->s10->unk3 = 0;
+ break;
+ default:
+ s10->startValue = adlibGetRegValueParam(voice->_channel, s11->param);
+ }
+
+ struct10Init(s10, ie);
+}
+
+void MidiDriver_ADLIB::struct10Init(Struct10 *s10, const InstrumentExtra *ie) {
+ s10->active = 1;
+ if (!_scummSmallHeader) {
+ s10->curVal = 0;
+ } else {
+ s10->curVal = s10->startValue;
+ s10->startValue = 0;
+ }
+ s10->modWheelLast = 31;
+ s10->count = ie->a;
+ if (s10->count)
+ s10->count *= 63;
+ s10->tableA[0] = ie->b;
+ s10->tableA[1] = ie->d;
+ s10->tableA[2] = ie->f;
+ s10->tableA[3] = ie->g;
+
+ s10->tableB[0] = ie->c;
+ s10->tableB[1] = ie->e;
+ s10->tableB[2] = 0;
+ s10->tableB[3] = ie->h;
+
+ struct10Setup(s10);
+}
+
+int MidiDriver_ADLIB::adlibGetRegValueParam(int chan, byte param) {
+ const AdLibSetParams *as;
+ byte val;
+ byte channel;
+
+ assert(chan >= 0 && chan < 9);
+
+ if (param <= 12) {
+ channel = g_operator2Offsets[chan];
+ } else if (param <= 25) {
+ param -= 13;
+ channel = g_operator1Offsets[chan];
+ } else if (param <= 27) {
+ param -= 13;
+ channel = chan;
+ } else if (param == 28) {
+ return 0xF;
+ } else if (param == 29) {
+ return 0x17F;
+ } else {
+ return 0;
+ }
+
+ as = &g_setParamTable[param];
+ val = adlibGetRegValue(channel + as->registerBase);
+ val &= as->mask;
+ val >>= as->shift;
+ if (as->inversion)
+ val = as->inversion - val;
+
+ return val;
+}
+
+void MidiDriver_ADLIB::adlibNoteOn(int chan, byte note, int mod) {
+#ifdef ENABLE_OPL3
+ if (_opl3Mode) {
+ adlibNoteOnEx(chan, note, mod);
+ return;
+ }
+#endif
+
+ assert(chan >= 0 && chan < 9);
+ int code = (note << 7) + mod;
+ _curNotTable[chan] = code;
+ adlibPlayNote(chan, (int16)_channelTable2[chan] + code);
+}
+
+void MidiDriver_ADLIB::adlibNoteOnEx(int chan, byte note, int mod) {
+ assert(chan >= 0 && chan < 9);
+
+#ifdef ENABLE_OPL3
+ if (_opl3Mode) {
+ const int noteAdjusted = note + (mod >> 8) - 7;
+ const int pitchAdjust = (mod >> 5) & 7;
+
+ adlibWrite(0xA0 + chan, g_noteFrequencies[(noteAdjusted % 12) * 8 + pitchAdjust + 6 * 8]);
+ adlibWriteSecondary(0xA0 + chan, g_noteFrequencies[(noteAdjusted % 12) * 8 + pitchAdjust + 6 * 8]);
+ adlibWrite(0xB0 + chan, (CLIP(noteAdjusted / 12, 0, 7) << 2) | 0x20);
+ adlibWriteSecondary(0xB0 + chan, (CLIP(noteAdjusted / 12, 0, 7) << 2) | 0x20);
+ } else {
+#endif
+ int code = (note << 7) + mod;
+ _curNotTable[chan] = code;
+ _channelTable2[chan] = 0;
+ adlibPlayNote(chan, code);
+#ifdef ENABLE_OPL3
+ }
+#endif
+}
+
+// Plugin interface
+
+class AdLibEmuMusicPlugin : public MusicPluginObject {
+public:
+ const char *getName() const {
+ return _s("AdLib Emulator");
+ }
+
+ const char *getId() const {
+ return "adlib";
+ }
+
+ MusicDevices getDevices() const;
+ Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;
+};
+
+MusicDevices AdLibEmuMusicPlugin::getDevices() const {
+ MusicDevices devices;
+ devices.push_back(MusicDevice(this, "", MT_ADLIB));
+ return devices;
+}
+
+Common::Error AdLibEmuMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
+ *mididriver = new MidiDriver_ADLIB();
+
+ return Common::kNoError;
+}
+
+//#if PLUGIN_ENABLED_DYNAMIC(ADLIB)
+ //REGISTER_PLUGIN_DYNAMIC(ADLIB, PLUGIN_TYPE_MUSIC, AdLibEmuMusicPlugin);
+//#else
+ REGISTER_PLUGIN_STATIC(ADLIB, PLUGIN_TYPE_MUSIC, AdLibEmuMusicPlugin);
+//#endif
diff --git a/audio/module.mk b/audio/module.mk
index 1539163..7743c49 100644
--- a/audio/module.mk
+++ b/audio/module.mk
@@ -1,6 +1,7 @@
MODULE := audio
MODULE_OBJS := \
+ adlib.o \
audiostream.o \
fmopl.o \
mididrv.o \
@@ -39,7 +40,6 @@ MODULE_OBJS := \
mods/rjp1.o \
mods/soundfx.o \
mods/tfmx.o \
- softsynth/adlib.o \
softsynth/cms.o \
softsynth/opl/dbopl.o \
softsynth/opl/dosbox.o \
diff --git a/audio/softsynth/adlib.cpp b/audio/softsynth/adlib.cpp
deleted file mode 100644
index f609164..0000000
--- a/audio/softsynth/adlib.cpp
+++ /dev/null
@@ -1,2318 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "audio/softsynth/emumidi.h"
-#include "common/debug.h"
-#include "common/error.h"
-#include "common/scummsys.h"
-#include "common/system.h"
-#include "common/textconsole.h"
-#include "common/types.h"
-#include "common/util.h"
-#include "audio/fmopl.h"
-#include "audio/musicplugin.h"
-#include "common/translation.h"
-
-#ifdef DEBUG_ADLIB
-static int g_tick;
-#endif
-
-// Only include OPL3 when we actually have an AdLib emulator builtin, which
-// supports OPL3.
-#ifndef DISABLE_DOSBOX_OPL
-#define ENABLE_OPL3
-#endif
-
-class MidiDriver_ADLIB;
-struct AdLibVoice;
-
-// We use packing for the following two structs, because the code
-// does simply copy them over from byte streams, without any
-// serialization. Check AdLibPart::sysEx_customInstrument for an
-// example of this.
-//
-// It might be very well possible, that none of the compilers we support
-// add any padding bytes at all, since the structs contain only variables
-// of the type 'byte'. But better safe than sorry.
-#include "common/pack-start.h"
-struct InstrumentExtra {
- byte a, b, c, d, e, f, g, h;
-} PACKED_STRUCT;
-
-struct AdLibInstrument {
- byte modCharacteristic;
- byte modScalingOutputLevel;
- byte modAttackDecay;
- byte modSustainRelease;
- byte modWaveformSelect;
- byte carCharacteristic;
- byte carScalingOutputLevel;
- byte carAttackDecay;
- byte carSustainRelease;
- byte carWaveformSelect;
- byte feedback;
- byte flagsA;
- InstrumentExtra extraA;
- byte flagsB;
- InstrumentExtra extraB;
- byte duration;
-} PACKED_STRUCT;
-#include "common/pack-end.h"
-
-class AdLibPart : public MidiChannel {
- friend class MidiDriver_ADLIB;
-
-protected:
-// AdLibPart *_prev, *_next;
- AdLibVoice *_voice;
- int16 _pitchBend;
- byte _pitchBendFactor;
- //int8 _transposeEff;
- byte _volEff;
- int8 _detuneEff;
- byte _modWheel;
- bool _pedal;
- byte _program;
- byte _priEff;
- byte _pan;
- AdLibInstrument _partInstr;
-#ifdef ENABLE_OPL3
- AdLibInstrument _partInstrSecondary;
-#endif
-
-protected:
- MidiDriver_ADLIB *_owner;
- bool _allocated;
- byte _channel;
-
- void init(MidiDriver_ADLIB *owner, byte channel);
- void allocate() { _allocated = true; }
-
-public:
- AdLibPart() {
- _voice = 0;
- _pitchBend = 0;
- _pitchBendFactor = 2;
- //_transposeEff = 0;
- _volEff = 0;
- _detuneEff = 0;
- _modWheel = 0;
- _pedal = 0;
- _program = 0;
- _priEff = 0;
- _pan = 64;
-
- _owner = 0;
- _allocated = false;
- _channel = 0;
-
- memset(&_partInstr, 0, sizeof(_partInstr));
-#ifdef ENABLE_OPL3
- memset(&_partInstrSecondary, 0, sizeof(_partInstrSecondary));
-#endif
- }
-
- MidiDriver *device();
- byte getNumber() { return _channel; }
- void release() { _allocated = false; }
-
- void send(uint32 b);
-
- // 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);
- 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, const byte *instr);
-};
-
-// FYI (Jamieson630)
-// It is assumed that any invocation to AdLibPercussionChannel
-// will be done through the MidiChannel base class as opposed to the
-// AdLibPart base class. If this were NOT the case, all the functions
-// listed below would need to be virtual in AdLibPart as well as MidiChannel.
-class AdLibPercussionChannel : public AdLibPart {
- friend class MidiDriver_ADLIB;
-
-protected:
- void init(MidiDriver_ADLIB *owner, byte channel);
-
-public:
- ~AdLibPercussionChannel();
-
- void noteOff(byte note);
- void noteOn(byte note, byte velocity);
- void programChange(byte program) { }
-
- // Control Change messages
- void modulationWheel(byte value) { }
- void pitchBendFactor(byte value) { }
- void detune(byte value) { }
- void priority(byte value) { }
- void sustain(bool value) { }
-
- // SysEx messages
- void sysEx_customInstrument(uint32 type, const byte *instr);
-
-private:
- byte _notes[256];
- AdLibInstrument *_customInstruments[256];
-};
-
-struct Struct10 {
- byte active;
- int16 curVal;
- int16 count;
- uint16 maxValue;
- int16 startValue;
- byte loop;
- byte tableA[4];
- byte tableB[4];
- int8 unk3;
- int8 modWheel;
- int8 modWheelLast;
- uint16 speedLoMax;
- uint16 numSteps;
- int16 speedHi;
- int8 direction;
- uint16 speedLo;
- uint16 speedLoCounter;
-};
-
-struct Struct11 {
- int16 modifyVal;
- byte param, flag0x40, flag0x10;
- Struct10 *s10;
-};
-
-struct AdLibVoice {
- AdLibPart *_part;
- AdLibVoice *_next, *_prev;
- byte _waitForPedal;
- byte _note;
- byte _channel;
- byte _twoChan;
- byte _vol1, _vol2;
- int16 _duration;
-
- Struct10 _s10a;
- Struct11 _s11a;
- Struct10 _s10b;
- Struct11 _s11b;
-
-#ifdef ENABLE_OPL3
- byte _secTwoChan;
- byte _secVol1, _secVol2;
-#endif
-
- AdLibVoice() { memset(this, 0, sizeof(AdLibVoice)); }
-};
-
-struct AdLibSetParams {
- byte registerBase;
- byte shift;
- byte mask;
- byte inversion;
-};
-
-static const byte g_operator1Offsets[9] = {
- 0, 1, 2, 8,
- 9, 10, 16, 17,
- 18
-};
-
-static const byte g_operator2Offsets[9] = {
- 3, 4, 5, 11,
- 12, 13, 19, 20,
- 21
-};
-
-static const AdLibSetParams g_setParamTable[] = {
- {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}, // waveformSelect 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
-};
-
-static const byte g_paramTable1[16] = {
- 29, 28, 27, 0,
- 3, 4, 7, 8,
- 13, 16, 17, 20,
- 21, 30, 31, 0
-};
-
-static const uint16 g_maxValTable[16] = {
- 0x2FF, 0x1F, 0x7, 0x3F,
- 0x0F, 0x0F, 0x0F, 0x3,
- 0x3F, 0x0F, 0x0F, 0x0F,
- 0x3, 0x3E, 0x1F, 0
-};
-
-static const uint16 g_numStepsTable[] = {
- 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 g_noteFrequencies[] = {
- 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 const AdLibInstrument g_gmInstruments[128] = {
- // 0x00
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- // 0x10
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- // 0x20
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- // 0x30
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- // 0x40
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- // 0x50
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- // 0x60
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- // 0x70
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 }
-};
-
-static AdLibInstrument g_gmPercussionInstruments[39] = {
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 },
- { 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 }
-};
-
-#ifdef ENABLE_OPL3
-static const AdLibInstrument g_gmInstrumentsOPL3[128][2] = {
- { { 0xC2, 0xC2, 0x0A, 0x6B, 0xA0, 0xC2, 0x08, 0x0D, 0x88, 0xC8, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x23 },
- { 0x02, 0x00, 0x0C, 0x78, 0x61, 0x04, 0x4C, 0x0B, 0x9A, 0xC8, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x23 } },
- { { 0x22, 0x53, 0x0E, 0x8A, 0x60, 0x14, 0x06, 0x1D, 0x7A, 0xB8, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0x22, 0x5A, 0x0E, 0x8A, 0x40, 0x14, 0x2F, 0x0E, 0x7A, 0x88, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0x06, 0x00, 0x1C, 0x79, 0x70, 0x02, 0x00, 0x4B, 0x79, 0xA8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0x06, 0x00, 0x1A, 0x79, 0x60, 0x02, 0x00, 0x4C, 0xA9, 0xC8, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xC2, 0x80, 0x0B, 0x89, 0x90, 0xC2, 0x06, 0x1B, 0xA8, 0xB0, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x23 },
- { 0x04, 0x28, 0x5D, 0xB8, 0x01, 0x02, 0x00, 0x3C, 0x70, 0x88, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xC2, 0x17, 0x3D, 0x6A, 0x00, 0xC4, 0x2E, 0x2D, 0xC9, 0x40, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xC2, 0x17, 0x3D, 0x6A, 0x00, 0xC4, 0x2E, 0x2D, 0xC9, 0x40, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 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 },
- { 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 } },
- { { 0x84, 0x40, 0x3B, 0x5A, 0x63, 0x81, 0x00, 0x3B, 0x5A, 0xD3, 0x0B, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0x87, 0x40, 0x3A, 0x5A, 0x94, 0x82, 0x04, 0x3D, 0x59, 0xAC, 0x09, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0x84, 0x40, 0x3B, 0x5A, 0xC3, 0x81, 0x00, 0x3B, 0x5A, 0xFB, 0x01, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0x84, 0x40, 0x3B, 0x5A, 0xC3, 0x81, 0x00, 0x3B, 0x5A, 0xFB, 0x01, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0x8C, 0x80, 0x05, 0xEA, 0xA9, 0x82, 0x04, 0x3D, 0xAA, 0xB0, 0x07, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0x8C, 0x80, 0x06, 0x98, 0xA9, 0x86, 0x10, 0x36, 0x7A, 0xFD, 0x07, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0x85, 0x40, 0x0D, 0xEC, 0xE1, 0x84, 0x58, 0x3E, 0xCB, 0xF8, 0x01, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0x84, 0x40, 0x0D, 0xEB, 0xE0, 0x84, 0x48, 0x3E, 0xCA, 0xC0, 0x05, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0x8A, 0xC0, 0x0C, 0xDC, 0xA0, 0x88, 0x58, 0x3D, 0xDA, 0xF8, 0x01, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0x8A, 0xC0, 0x0C, 0xDC, 0xA0, 0x88, 0x58, 0x3D, 0xDA, 0xF8, 0x01, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xC9, 0x40, 0x2B, 0x78, 0x8A, 0xC2, 0x0A, 0x4C, 0x8A, 0xF8, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x1A },
- { 0xCA, 0x40, 0x47, 0xCA, 0xB4, 0xC2, 0x00, 0x57, 0x8A, 0xB8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x1A } },
- { { 0x2A, 0x0E, 0x17, 0x89, 0x50, 0x22, 0x0C, 0x1B, 0x09, 0xE0, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0x2A, 0x1A, 0x19, 0x8A, 0x00, 0x22, 0x38, 0x0B, 0x0A, 0x00, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE7, 0x9B, 0x08, 0x08, 0x4A, 0xE2, 0x06, 0x0A, 0x08, 0xE0, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xE7, 0x9B, 0x08, 0x08, 0x4A, 0xE2, 0x2F, 0x0A, 0x08, 0x68, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xC5, 0x0A, 0x05, 0xDC, 0xB8, 0x84, 0x06, 0x00, 0xEC, 0xC0, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0x09, 0x10, 0x04, 0x5B, 0xA5, 0x02, 0x08, 0x00, 0xEC, 0x70, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0x86, 0x40, 0x5D, 0x5A, 0x81, 0x81, 0x00, 0x0B, 0x5A, 0xFB, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0x86, 0x40, 0x5D, 0x5A, 0x81, 0x81, 0x00, 0x0B, 0x5A, 0xFB, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xED, 0x0F, 0x5B, 0xC8, 0xC8, 0xE2, 0x9F, 0x4A, 0xE9, 0xF9, 0x07, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xE6, 0x40, 0x0A, 0xA7, 0x64, 0xE2, 0x8B, 0x6A, 0x79, 0xB1, 0x01, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE8, 0x4F, 0x3A, 0xD7, 0xF8, 0xE2, 0x97, 0x49, 0xF9, 0xF9, 0x05, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xC9, 0x02, 0x16, 0x9A, 0xAB, 0xC4, 0x15, 0x46, 0xBA, 0xF8, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE1, 0x08, 0x2F, 0xF7, 0xE1, 0xF3, 0x42, 0x8F, 0xC7, 0xC2, 0x07, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xE3, 0x00, 0x2D, 0xF7, 0xC1, 0xE4, 0x40, 0x7F, 0xC7, 0xD2, 0x09, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0x01, 0x8C, 0x9F, 0xDA, 0xE8, 0xE4, 0x50, 0x9F, 0xDA, 0xF2, 0x09, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0x02, 0x80, 0x9F, 0xDA, 0x00, 0xE3, 0x50, 0x9F, 0xD9, 0xFA, 0x03, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0x08, 0xD5, 0x9D, 0xA5, 0x89, 0xE2, 0x3F, 0x9F, 0xD6, 0x91, 0x07, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0x08, 0xD5, 0x9D, 0xA5, 0x89, 0xE2, 0x3F, 0x9F, 0xD6, 0x91, 0x07, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE5, 0x0F, 0x7D, 0xB8, 0x5A, 0xA2, 0x0C, 0x7C, 0xC7, 0xC1, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0x06, 0x4C, 0xAC, 0x56, 0x31, 0x02, 0x08, 0x8D, 0x46, 0xDC, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xF2, 0x2A, 0x9F, 0xDB, 0x01, 0xE1, 0x04, 0x8F, 0xD7, 0xC2, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xF2, 0x00, 0x9F, 0xDB, 0xA9, 0xE1, 0x00, 0x8F, 0xD7, 0xBA, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE4, 0x88, 0x9C, 0x50, 0xC8, 0xE2, 0x18, 0x70, 0xC4, 0xF8, 0x0B, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xE6, 0x00, 0x9C, 0x50, 0xB0, 0xE4, 0x00, 0x70, 0xC4, 0xA0, 0x07, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 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 },
- { 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 } },
- { { 0x42, 0x53, 0x3E, 0xEB, 0x48, 0xD4, 0x05, 0x1D, 0xA9, 0xC9, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x18 },
- { 0x42, 0x54, 0x6F, 0xEB, 0x61, 0xD4, 0x02, 0x2E, 0xA9, 0xC8, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x18 } },
- { { 0xC2, 0x00, 0x59, 0x17, 0xB1, 0xC2, 0x1E, 0x6D, 0x98, 0xF8, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x19 },
- { 0xC2, 0x00, 0x08, 0xB3, 0x99, 0xC2, 0x06, 0x2B, 0x58, 0xFA, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x19 } },
- { { 0xC6, 0x01, 0x2D, 0xA7, 0x88, 0xC2, 0x08, 0x0E, 0xA7, 0xC1, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xC4, 0x00, 0x2D, 0xA7, 0x91, 0xC2, 0x02, 0x0E, 0xA7, 0xD1, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xC2, 0x0C, 0x06, 0x06, 0xA9, 0xC2, 0x3F, 0x08, 0xB8, 0xF9, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x0A },
- { 0xC1, 0x00, 0x68, 0x50, 0xB8, 0xC2, 0x00, 0x48, 0x84, 0xF8, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x0A } },
- { { 0xC2, 0x2E, 0x4F, 0x77, 0x00, 0xC4, 0x08, 0x0E, 0x98, 0xB1, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xC2, 0x2F, 0x6F, 0x79, 0x00, 0xC8, 0x0F, 0x5E, 0x98, 0xB9, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xC2, 0x30, 0x4F, 0xCA, 0x01, 0xC4, 0x0D, 0x0E, 0xB8, 0xFB, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xC2, 0x30, 0x4F, 0xCA, 0x01, 0xC4, 0x0D, 0x0E, 0xB8, 0xFB, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xC4, 0x29, 0x4F, 0xCA, 0x03, 0xC8, 0x0D, 0x0C, 0xB7, 0xF9, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x0B },
- { 0xC4, 0x29, 0x4F, 0xCA, 0x03, 0xC8, 0x0D, 0x0C, 0xB7, 0xF9, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x0B } },
- { { 0xC2, 0x41, 0x3D, 0x96, 0x88, 0xC4, 0xCA, 0x0E, 0xC7, 0xF8, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x20 },
- { 0xC2, 0x04, 0x58, 0xC9, 0x90, 0xC2, 0x94, 0x2C, 0xB9, 0xF0, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x20 } },
- { { 0x31, 0x13, 0x2D, 0xD7, 0x78, 0xE2, 0x18, 0x2E, 0xB8, 0xF8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0x31, 0x13, 0x2D, 0xD7, 0x78, 0xE2, 0x18, 0x2E, 0xB8, 0xF8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0x22, 0x86, 0x0D, 0xD7, 0xA0, 0xE4, 0x18, 0x5E, 0xB8, 0xF8, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x28 },
- { 0x22, 0x86, 0x0D, 0xD7, 0xA0, 0xE4, 0x18, 0x5E, 0xB8, 0xF8, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x28 } },
- { { 0xF2, 0x0A, 0x0D, 0xD7, 0x80, 0xE4, 0x1F, 0x5E, 0xB8, 0xF8, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xD2, 0x06, 0x9A, 0xD7, 0xA0, 0xC2, 0x1F, 0x59, 0xB8, 0xF8, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xF2, 0x09, 0x4B, 0xD6, 0x90, 0xE4, 0x1F, 0x1C, 0xB8, 0xF8, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x28 },
- { 0xF2, 0x09, 0x4B, 0xD6, 0x90, 0xE4, 0x1F, 0x1C, 0xB8, 0xF8, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x28 } },
- { { 0x62, 0x11, 0x0C, 0xE6, 0x78, 0xE4, 0x1F, 0x0C, 0xC8, 0xF8, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0x62, 0x11, 0x0C, 0xE6, 0x78, 0xE4, 0x1F, 0x0C, 0xC8, 0xF8, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE2, 0x12, 0x3D, 0xE6, 0x68, 0xE4, 0x1F, 0x7D, 0xB8, 0xF8, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xE2, 0x12, 0x3D, 0xE6, 0x68, 0xE4, 0x1F, 0x7D, 0xB8, 0xF8, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE2, 0x13, 0x3D, 0xE6, 0x68, 0xE4, 0x1F, 0x5D, 0xB8, 0xF9, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xE2, 0x13, 0x3D, 0xE6, 0x68, 0xE4, 0x1F, 0x5D, 0xB8, 0xF9, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xA2, 0x40, 0x5D, 0xBA, 0x7B, 0xE2, 0x00, 0x8F, 0xD8, 0xF1, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xA2, 0x40, 0x5D, 0xBA, 0x7B, 0xE2, 0x00, 0x8F, 0xD8, 0xF1, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE2, 0x40, 0x3D, 0xDA, 0x73, 0xE1, 0x00, 0x7E, 0xD8, 0xF2, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xE2, 0x40, 0x3D, 0xDA, 0x73, 0xE1, 0x00, 0x7E, 0xD8, 0xF2, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0x62, 0x00, 0x6D, 0xFA, 0xB9, 0xE2, 0x00, 0x8F, 0xC8, 0xF1, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0x62, 0x00, 0x6D, 0xFA, 0xB9, 0xE2, 0x00, 0x8F, 0xC8, 0xF1, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE1, 0x00, 0x4E, 0xDB, 0x92, 0xE3, 0x18, 0x6F, 0xE9, 0xFA, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xE1, 0x00, 0x4E, 0xDB, 0xCA, 0xE2, 0x00, 0x6F, 0xE9, 0xFA, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE1, 0x00, 0x4E, 0xDB, 0xCA, 0xE2, 0x00, 0x7F, 0xE9, 0xFA, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xE1, 0x00, 0x4E, 0xDB, 0xCA, 0xE2, 0x00, 0x7F, 0xE9, 0xFA, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0x02, 0x0F, 0x66, 0xAA, 0xA1, 0x02, 0x64, 0x29, 0xF9, 0xF8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x04 },
- { 0x02, 0x00, 0x65, 0xAA, 0xF1, 0x02, 0x4A, 0x28, 0xF9, 0xF8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x04 } },
- { { 0x16, 0x4A, 0x04, 0xBA, 0x71, 0xC2, 0x48, 0x2E, 0xCA, 0xF0, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 },
- { 0x14, 0xC0, 0x66, 0x08, 0x90, 0xC2, 0x48, 0x2C, 0x0A, 0xA0, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 } },
- { { 0x02, 0x0A, 0x01, 0x7A, 0xB1, 0x02, 0x12, 0x2A, 0xEA, 0xF8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0x02, 0x06, 0x75, 0x05, 0xB1, 0x01, 0x3F, 0x28, 0xEA, 0xF9, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x16 } },
- { { 0x62, 0x53, 0x9C, 0xBA, 0x61, 0x62, 0x5A, 0xAD, 0xCA, 0xC1, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xF2, 0x40, 0x9F, 0x8A, 0x98, 0xE2, 0x11, 0x7F, 0xB8, 0xFA, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xF2, 0x40, 0x6E, 0xDA, 0x91, 0xE2, 0x13, 0x8F, 0xF9, 0xF9, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xF2, 0x40, 0x6E, 0xDA, 0x91, 0xE2, 0x13, 0x8F, 0xF9, 0xF9, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE2, 0x40, 0x8F, 0xFA, 0xA0, 0xF2, 0x04, 0x7F, 0xFA, 0xF9, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xE2, 0x40, 0x8F, 0xFA, 0xA0, 0xF2, 0x04, 0x7F, 0xFA, 0xF9, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE4, 0xA0, 0xCE, 0x5B, 0x02, 0xE2, 0x32, 0x7F, 0xFB, 0x79, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xE4, 0xA0, 0xCE, 0x5B, 0x02, 0xE2, 0x32, 0x7F, 0xFB, 0x79, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE6, 0x80, 0x9C, 0x99, 0x82, 0xE2, 0x04, 0x8D, 0x78, 0xC0, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xE0, 0x44, 0x8A, 0xA9, 0x5B, 0xE1, 0x06, 0x8D, 0x79, 0xBA, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE8, 0xA0, 0xAC, 0x67, 0x02, 0xE2, 0x06, 0x7C, 0x7A, 0xF8, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xEA, 0xA0, 0xAC, 0x67, 0x02, 0xE2, 0x00, 0x7C, 0x7A, 0xF8, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE7, 0x94, 0xAD, 0xB7, 0x03, 0xE2, 0x00, 0x7C, 0xBA, 0xF8, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xE7, 0x94, 0xAD, 0xB7, 0x03, 0xE2, 0x00, 0x7C, 0xBA, 0xF8, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xC3, 0x3F, 0x4B, 0xE9, 0xFA, 0xC1, 0x3F, 0x9B, 0xF9, 0xFB, 0x0B, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x06 },
- { 0xC3, 0x3F, 0x4B, 0xE9, 0xFA, 0xC1, 0x3F, 0x9B, 0xF9, 0xFB, 0x0B, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x06 } },
- { { 0xB2, 0x20, 0xAD, 0xE9, 0x00, 0x62, 0x05, 0x8F, 0xC8, 0xD0, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xB2, 0x25, 0xAD, 0xE9, 0x00, 0x62, 0x00, 0x8F, 0xC8, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xF2, 0x02, 0xAF, 0xFB, 0x90, 0xF6, 0x54, 0x8F, 0xE9, 0xF8, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xE2, 0x00, 0x9F, 0xFA, 0xB0, 0xF2, 0x58, 0x7F, 0xEA, 0xF8, 0x02, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xF2, 0x00, 0xAF, 0x88, 0xA8, 0xF2, 0x46, 0x6E, 0xC9, 0xE0, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xD2, 0x00, 0x7B, 0x88, 0xA8, 0xD2, 0x4C, 0x69, 0xE9, 0xF8, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xF2, 0x2A, 0x9F, 0x98, 0x01, 0xE2, 0x8F, 0x4E, 0x78, 0xC0, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xD2, 0x02, 0x85, 0x89, 0xC8, 0xD2, 0x94, 0x77, 0x49, 0xF9, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE2, 0x02, 0x9F, 0xB8, 0x90, 0x22, 0x8A, 0x9F, 0xE8, 0xF8, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xC2, 0x00, 0x86, 0xB8, 0x98, 0x02, 0x8F, 0x89, 0xE8, 0xF9, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE2, 0x2A, 0x7F, 0xB8, 0x01, 0xE4, 0x00, 0x0D, 0xC5, 0xF8, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xE2, 0x2A, 0x7F, 0xB8, 0x01, 0xE4, 0x00, 0x0D, 0xC5, 0xF8, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE4, 0x28, 0x8E, 0xE8, 0x01, 0xF2, 0x00, 0x4D, 0xD6, 0xF9, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xE4, 0x28, 0x8E, 0xE8, 0x01, 0xF2, 0x00, 0x4D, 0xD6, 0xF9, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0x62, 0x23, 0x8F, 0xEA, 0x00, 0xF2, 0x00, 0x5E, 0xD9, 0xF8, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0x62, 0x23, 0x8F, 0xEA, 0x00, 0xF2, 0x00, 0x5E, 0xD9, 0xF8, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xB4, 0x26, 0x6E, 0x98, 0x01, 0x62, 0x00, 0x7D, 0xC8, 0xF9, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xB4, 0x26, 0x6E, 0x98, 0x01, 0x62, 0x00, 0x7D, 0xC8, 0xF9, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE2, 0x2E, 0x20, 0xD9, 0x01, 0xF2, 0x1A, 0x90, 0xF8, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xD2, 0x10, 0x69, 0x18, 0xCF, 0xD4, 0x14, 0x5B, 0x04, 0xFD, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE4, 0x28, 0x7E, 0xF8, 0x01, 0xE2, 0x23, 0x8E, 0xE8, 0xF9, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xE4, 0x28, 0x7E, 0xF8, 0x01, 0xE2, 0x23, 0x8E, 0xE8, 0xF9, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xB8, 0x28, 0x9E, 0x98, 0x01, 0x62, 0x00, 0x3D, 0xC8, 0xF9, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xB8, 0x28, 0x9E, 0x98, 0x01, 0x62, 0x00, 0x3D, 0xC8, 0xF9, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0x62, 0x00, 0x8E, 0xC9, 0x79, 0xE6, 0x00, 0x7E, 0xD8, 0xD0, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0x62, 0x00, 0x8E, 0xC9, 0x79, 0xE6, 0x00, 0x7E, 0xD8, 0xD0, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE2, 0x00, 0x5F, 0xF9, 0x88, 0xE4, 0x9E, 0x8F, 0xF8, 0xF9, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xC2, 0x00, 0x97, 0xF9, 0x90, 0xC9, 0x80, 0x69, 0x98, 0xA0, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0x62, 0x0C, 0x6E, 0xD8, 0x79, 0x2A, 0x09, 0x7D, 0xD8, 0xC0, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0x02, 0x04, 0x8A, 0xD8, 0x80, 0x0C, 0x12, 0x85, 0xD8, 0xF8, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE4, 0x00, 0x7E, 0x89, 0x70, 0xE6, 0x8F, 0x80, 0xF8, 0xF0, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xC4, 0x00, 0x67, 0x59, 0x70, 0xC6, 0x8A, 0x77, 0xA8, 0xF8, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE4, 0x80, 0x6C, 0xD9, 0x60, 0xE2, 0x00, 0x8D, 0xC8, 0xF8, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xE4, 0x80, 0x6C, 0xD9, 0x60, 0xE2, 0x00, 0x8D, 0xC8, 0xF8, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE2, 0x80, 0x88, 0x48, 0x98, 0xE2, 0x1E, 0x8E, 0xC9, 0xF8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xF2, 0x40, 0xA8, 0xB9, 0x80, 0xE2, 0x0C, 0x89, 0x09, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE4, 0x00, 0x77, 0xC5, 0xA8, 0xE2, 0x00, 0x9E, 0xD7, 0xE0, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xE4, 0x00, 0x77, 0xC5, 0xA8, 0xE2, 0x00, 0x9E, 0xD7, 0xE0, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE4, 0x80, 0x86, 0xB9, 0xA8, 0xE2, 0x14, 0x9F, 0xD7, 0xB0, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xC2, 0x80, 0x94, 0x09, 0x78, 0xC2, 0x00, 0x97, 0x97, 0xF8, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE2, 0x00, 0x68, 0x68, 0xAA, 0xE2, 0x0A, 0x9B, 0xB3, 0xF8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xC2, 0x00, 0x86, 0x68, 0xA0, 0xC2, 0x00, 0x77, 0x47, 0xE0, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE4, 0x00, 0xA6, 0x87, 0x81, 0xE2, 0x0A, 0x7E, 0xC9, 0xF8, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xE2, 0x00, 0x89, 0x40, 0x79, 0xE2, 0x00, 0x7E, 0xC9, 0x90, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE4, 0x80, 0xAA, 0xB8, 0x90, 0xE2, 0x00, 0x9E, 0xF9, 0xC0, 0x09, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xE6, 0x80, 0x9D, 0xB8, 0x51, 0xE2, 0x00, 0x9E, 0xF9, 0xA0, 0x01, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE2, 0x80, 0x8E, 0x64, 0xD0, 0xE2, 0x28, 0x6F, 0x73, 0xF8, 0x01, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xE2, 0x80, 0x8E, 0x64, 0xD0, 0xE2, 0x28, 0x6F, 0x73, 0xF8, 0x01, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE8, 0x00, 0x7D, 0x99, 0xA8, 0xE6, 0x80, 0x80, 0xF8, 0xF8, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xE8, 0x00, 0x7D, 0x99, 0xA8, 0xE6, 0x80, 0x80, 0xF8, 0xF8, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE6, 0x00, 0x9F, 0xB9, 0xD9, 0xE1, 0x00, 0x8F, 0xC8, 0xF9, 0x02, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xE6, 0x00, 0x9F, 0xB9, 0xD9, 0xE1, 0x00, 0x8F, 0xC8, 0xF9, 0x02, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE4, 0x00, 0x09, 0x68, 0x92, 0xE2, 0x2B, 0x9E, 0xF3, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xE4, 0x00, 0x09, 0x68, 0x92, 0xE2, 0x2B, 0x9E, 0xF3, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xC4, 0x00, 0x99, 0xE8, 0x73, 0xE2, 0x25, 0x6F, 0x93, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xC4, 0x00, 0x99, 0xE8, 0x73, 0xE2, 0x25, 0x6F, 0x93, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE6, 0x00, 0x6F, 0xDA, 0xC9, 0xE2, 0x05, 0x2F, 0xD8, 0xAA, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xE2, 0x00, 0x4F, 0xDA, 0xC8, 0xE2, 0x00, 0x0F, 0xD8, 0xD0, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xEC, 0x60, 0x9D, 0xC7, 0x00, 0xE2, 0x21, 0x7F, 0xC9, 0xF8, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xEC, 0x60, 0x9D, 0xC7, 0x00, 0xE2, 0x21, 0x7F, 0xC9, 0xF8, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE3, 0x00, 0x0F, 0xF7, 0xF9, 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 },
- { 0xE3, 0x00, 0x0F, 0xF7, 0xF9, 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 } },
- { { 0xE4, 0xA9, 0x0F, 0xA8, 0x02, 0xE2, 0x3C, 0x5F, 0xDA, 0x78, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xE4, 0xA9, 0x0F, 0xA8, 0x02, 0xE2, 0x3C, 0x5F, 0xDA, 0x78, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE8, 0x40, 0x0D, 0x89, 0xF9, 0xE2, 0x17, 0x7E, 0xD9, 0xF8, 0x07, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xE8, 0x40, 0x0D, 0x89, 0xF9, 0xE2, 0x17, 0x7E, 0xD9, 0xF8, 0x07, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE1, 0x00, 0xDF, 0x8A, 0xAA, 0xE2, 0x5E, 0xCF, 0xBA, 0xFA, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xE1, 0x00, 0xDF, 0x8A, 0xAA, 0xE2, 0x5E, 0xCF, 0xBA, 0xFA, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE2, 0x00, 0x0B, 0x68, 0xC0, 0xE2, 0x01, 0x9E, 0xB8, 0xF8, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xE2, 0x00, 0x0B, 0x68, 0xC0, 0xE2, 0x01, 0x9E, 0xB8, 0xF8, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xEA, 0x00, 0xAE, 0xAB, 0x91, 0xE2, 0x00, 0xAE, 0xBA, 0xD8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xEA, 0x00, 0xAE, 0xAB, 0x91, 0xE2, 0x00, 0xAE, 0xBA, 0xD8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xEB, 0x80, 0x8C, 0xCB, 0x72, 0xE2, 0x86, 0xAF, 0xCA, 0xF8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xEB, 0xC3, 0x9C, 0xCB, 0xA2, 0xE2, 0x4C, 0xAE, 0xCA, 0xFA, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE5, 0x40, 0xDB, 0x3B, 0x78, 0xE2, 0x80, 0xBE, 0xCA, 0xE1, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xE2, 0x80, 0x8E, 0xCB, 0xC0, 0xE2, 0x90, 0xAE, 0xCA, 0xFB, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE4, 0x00, 0x9E, 0xAA, 0x79, 0xE1, 0x43, 0x0F, 0xBA, 0xFA, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xE4, 0x00, 0x9E, 0xAA, 0x79, 0xE1, 0x43, 0x0F, 0xBA, 0xFA, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE7, 0x40, 0xEB, 0xCA, 0x80, 0xE2, 0x03, 0xBF, 0xBA, 0xC2, 0x02, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xE3, 0x80, 0xDB, 0xCA, 0x40, 0xE2, 0x08, 0xDF, 0xBA, 0xC1, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xEA, 0x00, 0x68, 0xB8, 0x90, 0xE2, 0x0A, 0x8E, 0xB8, 0xF8, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xEA, 0x00, 0x68, 0xB8, 0x90, 0xE2, 0x0A, 0x8E, 0xB8, 0xF8, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0x61, 0x00, 0xBE, 0x99, 0xFA, 0xE3, 0x40, 0xCF, 0xCA, 0xF9, 0x09, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0x62, 0x00, 0xCE, 0x9A, 0xA8, 0xE2, 0x45, 0xCF, 0xCA, 0xA0, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xCD, 0x00, 0x0B, 0x00, 0x90, 0xC2, 0x58, 0x0C, 0x00, 0xF8, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x1C },
- { 0xCD, 0x00, 0x0B, 0x00, 0x90, 0xC2, 0x58, 0x0C, 0x00, 0xF8, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x1C } },
- { { 0xE2, 0x00, 0x0E, 0x00, 0xA2, 0xE2, 0x58, 0x5F, 0xD0, 0xF9, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xE2, 0x00, 0x0E, 0x00, 0xA2, 0xE2, 0x58, 0x5F, 0xD0, 0xF9, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xEC, 0x00, 0x7D, 0xDA, 0x80, 0xE2, 0x00, 0x5E, 0x9B, 0xA8, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xE6, 0x0A, 0x4C, 0xC9, 0x60, 0xE2, 0x07, 0x0C, 0x7A, 0xB8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE9, 0xC0, 0xEE, 0xD8, 0x83, 0xE2, 0x05, 0xDD, 0xAA, 0xE0, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xED, 0x48, 0xDE, 0xD8, 0xB4, 0xE1, 0x00, 0xDD, 0xAA, 0xA9, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xDA, 0x00, 0x8F, 0xAC, 0x92, 0x22, 0x05, 0x8D, 0x8A, 0xE9, 0x02, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xEF, 0x00, 0x8C, 0xAA, 0x67, 0x25, 0x00, 0x9D, 0xAB, 0xC1, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0x62, 0x82, 0xCB, 0x7A, 0xD8, 0xE6, 0x56, 0xAF, 0xDB, 0xE0, 0x02, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0x62, 0x84, 0xBB, 0xAA, 0xCA, 0xCF, 0x41, 0xAC, 0xDA, 0xF8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xC2, 0x41, 0xAC, 0xBB, 0xBB, 0xC2, 0x85, 0x0E, 0xCB, 0xF9, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x12 },
- { 0xC2, 0x03, 0x6A, 0x5B, 0xA4, 0xC2, 0x0D, 0x2A, 0xBB, 0xFC, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x12 } },
- { { 0x75, 0x00, 0x0E, 0xBB, 0xB2, 0xE2, 0x1E, 0x0A, 0xA9, 0xF9, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x10 },
- { 0x62, 0x00, 0x04, 0x9A, 0xE8, 0xE2, 0x00, 0x0A, 0x48, 0xFD, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x10 } },
- { { 0x41, 0x00, 0x0E, 0xEA, 0xA3, 0xC2, 0x00, 0x08, 0xCA, 0xF8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x07 },
- { 0x41, 0x00, 0x0E, 0xEA, 0xA3, 0xC2, 0x00, 0x08, 0xCA, 0xF8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x07 } },
- { { 0xC1, 0x40, 0x0C, 0x59, 0xD2, 0xC2, 0x80, 0x3C, 0xAB, 0xF8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x0D },
- { 0xC1, 0x40, 0x0C, 0x59, 0xD2, 0xC2, 0x80, 0x3C, 0xAB, 0xF8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x0D } },
- { { 0x4B, 0x00, 0x0A, 0xF5, 0xC1, 0xC2, 0x19, 0x0C, 0xE9, 0xF8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x07 },
- { 0x4B, 0x00, 0x0A, 0xF5, 0xC1, 0xC2, 0x19, 0x0C, 0xE9, 0xF8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x07 } },
- { { 0x62, 0x00, 0x7F, 0xD8, 0xA8, 0xEA, 0x00, 0x8F, 0xD8, 0xF9, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0x62, 0x00, 0x7F, 0xD8, 0xA8, 0xEA, 0x00, 0x8F, 0xD8, 0xF9, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE1, 0x00, 0x7F, 0xD9, 0xAA, 0xE1, 0x00, 0x8F, 0xD8, 0xFA, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xE1, 0x00, 0x7F, 0xD9, 0xAA, 0xE1, 0x00, 0x8F, 0xD8, 0xFA, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xE1, 0x00, 0x7F, 0xD9, 0xAA, 0xE1, 0x00, 0x8F, 0xD8, 0xFA, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xE1, 0x00, 0x7F, 0xD9, 0xAA, 0xE1, 0x00, 0x8F, 0xD8, 0xFA, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0xCF, 0x40, 0x09, 0xEA, 0xA8, 0xC4, 0x00, 0x0C, 0xDB, 0xC8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 },
- { 0xCF, 0x40, 0x09, 0xEA, 0xA8, 0xC4, 0x00, 0x0C, 0xDB, 0xC8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 } },
- { { 0xCF, 0x40, 0x0C, 0xAA, 0xA8, 0xC4, 0x00, 0x18, 0xF9, 0xC8, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 },
- { 0xCF, 0x40, 0x0C, 0xAA, 0xA8, 0xC4, 0x00, 0x18, 0xF9, 0xC8, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 } },
- { { 0xC9, 0x0C, 0x88, 0xD9, 0x6A, 0xC2, 0x14, 0x3A, 0xEA, 0xF8, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x05 },
- { 0xC5, 0x00, 0x98, 0xD9, 0x92, 0xC1, 0x16, 0x6E, 0xF9, 0xE8, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x05 } },
- { { 0x03, 0x00, 0x15, 0x00, 0xC8, 0x02, 0x00, 0x08, 0x00, 0xF8, 0x09, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 },
- { 0x03, 0x00, 0x15, 0x00, 0xC8, 0x02, 0x00, 0x08, 0x00, 0xF8, 0x09, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 } },
- { { 0x01, 0x0C, 0x44, 0xE6, 0xE8, 0x01, 0x3F, 0x0C, 0xEA, 0xF8, 0x0C, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x04 },
- { 0x02, 0x3F, 0x05, 0x08, 0xF8, 0x03, 0x3F, 0x3C, 0xF9, 0xF8, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x06 } },
- { { 0x00, 0x00, 0x36, 0x67, 0xF8, 0x01, 0x3F, 0x0E, 0xFA, 0xF8, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x05 },
- { 0x00, 0x00, 0x36, 0x67, 0xF8, 0x01, 0x3F, 0x0E, 0xFA, 0xF8, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x05 } },
- { { 0x02, 0x00, 0x36, 0x68, 0xF8, 0x01, 0x3F, 0x0E, 0xFA, 0xF8, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x05 },
- { 0x02, 0x00, 0x36, 0x68, 0xF8, 0x01, 0x3F, 0x0E, 0xFA, 0xF8, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x05 } },
- { { 0xCB, 0x00, 0xAF, 0x00, 0xFA, 0xC0, 0x00, 0xC0, 0x06, 0xFB, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x0F },
- { 0xCB, 0x00, 0xAF, 0x00, 0xFA, 0xC0, 0x00, 0xC0, 0x06, 0xFB, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x0F } },
- { { 0x05, 0x0D, 0x80, 0xA6, 0xFB, 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 },
- { 0x05, 0x0D, 0x80, 0xA6, 0xFB, 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 } },
- { { 0x0F, 0x00, 0x90, 0xFA, 0xD0, 0x06, 0x00, 0xA7, 0x39, 0xA8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x06 },
- { 0x0F, 0x00, 0x90, 0xFA, 0xD0, 0x06, 0x00, 0xA7, 0x39, 0xA8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x06 } },
- { { 0xC9, 0x15, 0xDD, 0xFF, 0xF8, 0x00, 0x00, 0xE7, 0xFC, 0xD8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x38 },
- { 0xC9, 0x15, 0xDD, 0xFF, 0xF8, 0x00, 0x00, 0xE7, 0xFC, 0xD8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x38 } },
- { { 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 },
- { 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 } },
- { { 0x07, 0x80, 0x0B, 0xC8, 0xC9, 0x02, 0x3F, 0x0C, 0xEA, 0xF8, 0x0F, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x05 },
- { 0x07, 0x80, 0x0B, 0xC8, 0xC9, 0x02, 0x3F, 0x0C, 0xEA, 0xF8, 0x0F, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x05 } },
- { { 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 },
- { 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 } },
- { { 0x08, 0x00, 0x0B, 0x3C, 0xF8, 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 },
- { 0x08, 0x00, 0x0B, 0x3C, 0xF8, 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 } },
- { { 0x00, 0x3F, 0x4C, 0xFB, 0x00, 0x00, 0x3F, 0x0A, 0xE9, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x05 },
- { 0x00, 0x3F, 0x4C, 0xFB, 0x00, 0x00, 0x3F, 0x0A, 0xE9, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x05 } }
-};
-
-static const AdLibInstrument g_gmPercussionInstrumentsOPL3[39][2] = {
- { { 0x1A, 0x3F, 0x15, 0x05, 0xF8, 0x02, 0x21, 0x2B, 0xE4, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x06 },
- { 0x11, 0x18, 0x15, 0x00, 0xF8, 0x12, 0x00, 0x2B, 0x03, 0xF8, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x06 } },
- { { 0x11, 0x12, 0x04, 0x07, 0xF8, 0x02, 0x18, 0x0B, 0xE5, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x05 },
- { 0x11, 0x28, 0x06, 0x04, 0xF8, 0x02, 0x1E, 0x1B, 0x02, 0xF8, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x05 } },
- { { 0x0A, 0x3F, 0x0B, 0x01, 0xF8, 0x1F, 0x13, 0x46, 0xD0, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x01 },
- { 0x04, 0x18, 0x06, 0x01, 0xB0, 0x10, 0x00, 0x07, 0x00, 0x90, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x01 } },
- { { 0x00, 0x3F, 0x0F, 0x00, 0xF8, 0x10, 0x0A, 0x07, 0x00, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 },
- { 0x02, 0x14, 0x04, 0x00, 0xC0, 0x11, 0x08, 0x07, 0x00, 0xC6, 0x02, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 } },
- { { 0x0F, 0x3F, 0x0B, 0x00, 0xF8, 0x1F, 0x07, 0x19, 0xD0, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 },
- { 0x0E, 0x32, 0x76, 0x03, 0xF8, 0x1F, 0x0F, 0x77, 0xD4, 0xFC, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 } },
- { { 0x00, 0x3F, 0x1F, 0x00, 0xFA, 0x1F, 0x0C, 0x07, 0x00, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 },
- { 0x07, 0x11, 0x13, 0x00, 0xA0, 0x13, 0x00, 0x07, 0x00, 0xC8, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 } },
- { { 0x12, 0x3F, 0x05, 0x06, 0xF8, 0x03, 0x16, 0x4A, 0xD9, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 },
- { 0x02, 0x22, 0x05, 0xB6, 0xF8, 0x04, 0x0A, 0x59, 0x03, 0xF8, 0x0B, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 } },
- { { 0xCF, 0x7F, 0x08, 0xFF, 0xFA, 0x00, 0xC0, 0x2D, 0xF7, 0xE3, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 },
- { 0xD2, 0x7F, 0x04, 0x0F, 0xFA, 0x10, 0xCD, 0x24, 0x07, 0xFB, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 } },
- { { 0x12, 0x3F, 0x05, 0x06, 0xF8, 0x43, 0x17, 0x0C, 0xE9, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 },
- { 0x12, 0x13, 0x09, 0x96, 0xF8, 0x44, 0x0A, 0x07, 0x03, 0xF8, 0x07, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 } },
- { { 0xCF, 0x7F, 0x08, 0xCF, 0xFA, 0x00, 0x40, 0x2A, 0xF8, 0x8B, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x0C },
- { 0xCF, 0x7F, 0x05, 0x07, 0xFA, 0x00, 0x40, 0x25, 0x08, 0xC3, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x0C } },
- { { 0x12, 0x3F, 0x06, 0x17, 0xF8, 0x03, 0x1D, 0x0B, 0xE9, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 },
- { 0x12, 0x1A, 0x08, 0x96, 0xF8, 0x44, 0x00, 0x08, 0x03, 0xF8, 0x05, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 } },
- { { 0xCF, 0x7F, 0x08, 0xCD, 0xFA, 0x00, 0x40, 0x1A, 0x69, 0xB3, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x0C },
- { 0xCD, 0x3F, 0x36, 0x05, 0xFC, 0x0F, 0x47, 0x46, 0x06, 0xDF, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x0C } },
- { { 0x13, 0x3F, 0x05, 0x06, 0xF8, 0x03, 0x0D, 0x0A, 0xD9, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 },
- { 0x12, 0x14, 0x09, 0x96, 0xF8, 0x44, 0x02, 0x07, 0x03, 0xF8, 0x07, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 } },
- { { 0x15, 0x3F, 0x05, 0x06, 0xF8, 0x03, 0x16, 0x0C, 0xE9, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 },
- { 0x12, 0x00, 0x07, 0x96, 0xE8, 0x44, 0x02, 0x08, 0x03, 0xF8, 0x07, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 } },
- { { 0xCF, 0x3F, 0x2B, 0xFB, 0xFA, 0xC0, 0x16, 0x1A, 0xCA, 0xFB, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x10 },
- { 0xCF, 0x3F, 0x2B, 0xFB, 0xFA, 0xC0, 0x1E, 0x1A, 0xCA, 0xFB, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x10 } },
- { { 0x17, 0x3F, 0x04, 0x09, 0xF8, 0x03, 0x18, 0x0D, 0xE9, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 },
- { 0x12, 0x00, 0x07, 0x96, 0xF8, 0x44, 0x02, 0x08, 0xF9, 0xF8, 0x01, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 } },
- { { 0xCF, 0x3F, 0x0F, 0x5E, 0xF8, 0xC6, 0x0C, 0x00, 0xCA, 0xFB, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 },
- { 0xCF, 0x3F, 0x04, 0x57, 0xF8, 0xC5, 0x13, 0x06, 0x05, 0xFF, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 } },
- { { 0xCF, 0x3F, 0x7E, 0x9D, 0xF8, 0xC8, 0xC0, 0x0A, 0xBA, 0xD0, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x06 },
- { 0xCF, 0x3F, 0x77, 0x09, 0xF8, 0xC2, 0xC0, 0x08, 0xB5, 0xEA, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x06 } },
- { { 0xCF, 0x3F, 0x4D, 0x9F, 0xF8, 0xC6, 0x00, 0x08, 0xDA, 0xAB, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x04 },
- { 0xCF, 0x3F, 0x47, 0x06, 0xF8, 0xCD, 0x00, 0x07, 0x05, 0xB3, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x04 } },
- { { 0xCF, 0x3F, 0x5D, 0xAA, 0xF2, 0xC0, 0x8A, 0x67, 0x99, 0xF8, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 },
- { 0xCF, 0x3F, 0x9A, 0x69, 0xF8, 0xCF, 0x88, 0x88, 0x48, 0xFA, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 } },
- { { 0xCF, 0x3F, 0x4A, 0xFD, 0xF8, 0xCF, 0x00, 0x59, 0xEA, 0xD8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 },
- { 0xCF, 0x3F, 0x48, 0x06, 0xF8, 0xCF, 0x00, 0x54, 0x04, 0xF9, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 } },
- { { 0x0F, 0x18, 0x0A, 0xFA, 0xAB, 0x06, 0x06, 0x06, 0x39, 0xF8, 0x0A, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 },
- { 0x03, 0x18, 0x04, 0x09, 0xAC, 0x05, 0x07, 0x08, 0x07, 0xF8, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 } },
- { { 0xCF, 0x3F, 0x2B, 0xFC, 0xF8, 0xCC, 0xC4, 0x0B, 0xEA, 0xFB, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x10 },
- { 0xCF, 0x3F, 0x25, 0x06, 0xF8, 0xCC, 0xD7, 0x05, 0x02, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x10 } },
- { { 0x05, 0x1A, 0x04, 0x00, 0xF8, 0x12, 0x08, 0x0C, 0xEA, 0xE0, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x07 },
- { 0x01, 0x00, 0x09, 0x08, 0x40, 0x13, 0x00, 0x2A, 0x0A, 0xD8, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x07 } },
- { { 0x04, 0x19, 0x04, 0x00, 0xF8, 0x12, 0x08, 0x2C, 0xEA, 0xE0, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x04 },
- { 0x04, 0x00, 0x07, 0x08, 0x40, 0x12, 0x00, 0x29, 0x08, 0xE0, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x04 } },
- { { 0x04, 0x0A, 0x04, 0x00, 0xD8, 0x01, 0x02, 0x0D, 0xFA, 0xE0, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x07 },
- { 0x04, 0x00, 0x03, 0x09, 0x93, 0x02, 0x00, 0x28, 0x09, 0xE8, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x07 } },
- { { 0x15, 0x14, 0x05, 0x00, 0xF9, 0x01, 0x03, 0x5C, 0xE9, 0xD8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x05 },
- { 0x05, 0x00, 0x03, 0x03, 0x49, 0x02, 0x00, 0x58, 0x08, 0xE0, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x05 } },
- { { 0x10, 0x10, 0x05, 0x08, 0xF8, 0x01, 0x03, 0x0D, 0xEA, 0xE8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x05 },
- { 0x10, 0x00, 0x0C, 0x0C, 0x48, 0x02, 0x00, 0x08, 0xB9, 0xE0, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x05 } },
- { { 0x11, 0x00, 0x06, 0x87, 0xFB, 0x02, 0x40, 0x09, 0x59, 0xC0, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x08 },
- { 0x15, 0x00, 0x04, 0x87, 0xFB, 0x02, 0x40, 0x09, 0x59, 0xD0, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x08 } },
- { { 0x13, 0x26, 0x04, 0x6A, 0xFB, 0x01, 0x00, 0x08, 0x5A, 0xE0, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x08 },
- { 0x12, 0x26, 0x03, 0x6A, 0xFB, 0x02, 0x00, 0x06, 0x5A, 0xC0, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x08 } },
- { { 0xCF, 0x4D, 0x0C, 0xAA, 0xA0, 0xC4, 0x00, 0x18, 0xF9, 0x90, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 },
- { 0xCF, 0x4E, 0x05, 0xA6, 0xA0, 0xC6, 0x00, 0x16, 0xF8, 0x60, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 } },
- { { 0xCF, 0x4D, 0x0C, 0xAA, 0xA0, 0xC3, 0x00, 0x18, 0xF8, 0x98, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 },
- { 0xCF, 0x4E, 0x06, 0xAA, 0xA0, 0xC5, 0x00, 0x19, 0xF9, 0x90, 0x04, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 } },
- { { 0xCB, 0x3F, 0x8F, 0x00, 0xFA, 0xC5, 0x06, 0x98, 0xD6, 0xBB, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x0D },
- { 0xC0, 0x00, 0xF0, 0x00, 0x00, 0xC0, 0x00, 0xF0, 0x00, 0x00, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x0D } },
- { { 0x0C, 0x18, 0x87, 0xB3, 0xFB, 0x19, 0x0B, 0x55, 0x75, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 },
- { 0x0C, 0x18, 0x87, 0xB3, 0xFB, 0x1B, 0x10, 0x57, 0x75, 0xF8, 0x0E, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 } },
- { { 0x05, 0x11, 0x15, 0x00, 0xC8, 0x02, 0x00, 0x08, 0x00, 0xA8, 0x09, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 },
- { 0x02, 0x11, 0x13, 0x00, 0xC8, 0x02, 0x00, 0x05, 0x00, 0x80, 0x09, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 } },
- { { 0x04, 0x08, 0x15, 0x00, 0x90, 0x01, 0x00, 0x08, 0x00, 0xC0, 0x08, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 },
- { 0x03, 0x08, 0x14, 0x00, 0x90, 0x02, 0x00, 0x07, 0x00, 0xA8, 0x00, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x02 } },
- { { 0xDA, 0x00, 0x53, 0x30, 0xC0, 0x07, 0x10, 0x49, 0xC4, 0xDA, 0x03, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0xD2, 0x00, 0x56, 0x30, 0x90, 0x06, 0x00, 0x46, 0x56, 0x62, 0x09, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } },
- { { 0x1C, 0x00, 0x07, 0xBC, 0xC8, 0x0C, 0x0A, 0x0B, 0x6A, 0xF2, 0x0B, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 },
- { 0x18, 0x00, 0x07, 0xBC, 0x88, 0x09, 0x00, 0x0B, 0x6A, 0xBA, 0x0B, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x03 } },
- { { 0x0A, 0x0E, 0x7F, 0x00, 0xF9, 0x13, 0x16, 0x28, 0x03, 0xF8, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 },
- { 0x01, 0x0E, 0x54, 0x00, 0xF9, 0x15, 0x03, 0x27, 0x03, 0xF8, 0x06, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, 0x00 } }
-};
-#endif
-
-static const byte g_gmPercussionInstrumentMap[128] = {
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
- 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0xFF, 0xFF, 0x17, 0x18, 0x19, 0x1A,
- 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x21, 0x22, 0x23, 0xFF, 0xFF,
- 0x24, 0x25, 0xFF, 0xFF, 0xFF, 0x26, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
-};
-
-static byte g_volumeLookupTable[64][32];
-
-static const byte g_volumeTable[] = {
- 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 lookupVolume(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 g_volumeLookupTable[-a][-b];
- } else {
- return -g_volumeLookupTable[a][-b];
- }
- } else {
- if (a < 0) {
- return -g_volumeLookupTable[-a][b];
- } else {
- return g_volumeLookupTable[a][b];
- }
- }
-}
-
-static void createLookupTable() {
- int i, j;
- int sum;
-
- for (i = 0; i < 64; i++) {
- sum = i;
- for (j = 0; j < 32; j++) {
- g_volumeLookupTable[i][j] = sum >> 5;
- sum += i;
- }
- }
- for (i = 0; i < 64; i++)
- g_volumeLookupTable[i][0] = 0;
-}
-
-////////////////////////////////////////
-//
-// AdLib MIDI driver
-//
-////////////////////////////////////////
-
-class MidiDriver_ADLIB : public MidiDriver {
- friend class AdLibPart;
- friend class AdLibPercussionChannel;
-
-public:
- MidiDriver_ADLIB();
-
- int open();
- void close();
- void send(uint32 b);
- void send(byte channel, uint32 b); // Supports higher than channel 15
- uint32 property(int prop, uint32 param);
- bool isOpen() const { return _isOpen; }
- uint32 getBaseTempo() { return 1000000 / OPL::OPL::kDefaultCallbackFrequency; }
-
- void setPitchBendRange(byte channel, uint range);
- void sysEx_customInstrument(byte channel, uint32 type, const byte *instr);
-
- MidiChannel *allocateChannel();
- MidiChannel *getPercussionChannel() { return &_percussion; } // Percussion partially supported
-
- virtual void setTimerCallback(void *timerParam, Common::TimerManager::TimerProc timerProc);
-
-private:
- bool _scummSmallHeader; // FIXME: This flag controls a special mode for SCUMM V3 games
-#ifdef ENABLE_OPL3
- bool _opl3Mode;
-#endif
-
- OPL::OPL *_opl;
- byte *_regCache;
-#ifdef ENABLE_OPL3
- byte *_regCacheSecondary;
-#endif
-
- Common::TimerManager::TimerProc _adlibTimerProc;
- void *_adlibTimerParam;
-
- int _timerCounter;
-
- uint16 _channelTable2[9];
- int _voiceIndex;
- int _timerIncrease;
- int _timerThreshold;
- uint16 _curNotTable[9];
- AdLibVoice _voices[9];
- AdLibPart _parts[32];
- AdLibPercussionChannel _percussion;
-
- bool _isOpen;
-
- void onTimer();
- void partKeyOn(AdLibPart *part, const AdLibInstrument *instr, byte note, byte velocity, const AdLibInstrument *second, byte pan);
- void partKeyOff(AdLibPart *part, byte note);
-
- void adlibKeyOff(int chan);
- void adlibNoteOn(int chan, byte note, int mod);
- void adlibNoteOnEx(int chan, byte note, int mod);
- int adlibGetRegValueParam(int chan, byte data);
- void adlibSetupChannel(int chan, const AdLibInstrument *instr, byte vol1, byte vol2);
-#ifdef ENABLE_OPL3
- void adlibSetupChannelSecondary(int chan, const AdLibInstrument *instr, byte vol1, byte vol2, byte pan);
-#endif
- byte adlibGetRegValue(byte reg) {
- return _regCache[reg];
- }
-#ifdef ENABLE_OPL3
- byte adlibGetRegValueSecondary(byte reg) {
- return _regCacheSecondary[reg];
- }
-#endif
- void adlibSetParam(int channel, byte param, int value, bool primary = true);
- void adlibKeyOnOff(int channel);
- void adlibWrite(byte reg, byte value);
-#ifdef ENABLE_OPL3
- void adlibWriteSecondary(byte reg, byte value);
-#endif
- void adlibPlayNote(int channel, int note);
-
- AdLibVoice *allocateVoice(byte pri);
-
- void mcOff(AdLibVoice *voice);
-
- static void linkMc(AdLibPart *part, AdLibVoice *voice);
- void mcIncStuff(AdLibVoice *voice, Struct10 *s10, Struct11 *s11);
- void mcInitStuff(AdLibVoice *voice, Struct10 *s10, Struct11 *s11, byte flags,
- const InstrumentExtra *ie);
-
- void struct10Init(Struct10 *s10, const InstrumentExtra *ie);
- static byte struct10OnTimer(Struct10 *s10, Struct11 *s11);
- static void struct10Setup(Struct10 *s10);
- static int randomNr(int a);
- void mcKeyOn(AdLibVoice *voice, const AdLibInstrument *instr, byte note, byte velocity, const AdLibInstrument *second, byte pan);
-};
-
-// MidiChannel method implementations
-
-void AdLibPart::init(MidiDriver_ADLIB *owner, byte channel) {
- _owner = owner;
- _channel = channel;
- _priEff = 127;
- programChange(0);
-}
-
-MidiDriver *AdLibPart::device() {
- return _owner;
-}
-
-void AdLibPart::send(uint32 b) {
- _owner->send(_channel, b);
-}
-
-void AdLibPart::noteOff(byte note) {
-#ifdef DEBUG_ADLIB
- debug(6, "%10d: noteOff(%d)", g_tick, note);
-#endif
- _owner->partKeyOff(this, note);
-}
-
-void AdLibPart::noteOn(byte note, byte velocity) {
-#ifdef DEBUG_ADLIB
- debug(6, "%10d: noteOn(%d,%d)", g_tick, note, velocity);
-#endif
- _owner->partKeyOn(this, &_partInstr, note, velocity,
-#ifdef ENABLE_OPL3
- &_partInstrSecondary,
-#else
- NULL,
-#endif
- _pan);
-}
-
-void AdLibPart::programChange(byte program) {
- if (program > 127)
- return;
-
- /*
- uint i;
- uint count = 0;
- for (i = 0; i < ARRAYSIZE(g_gmInstruments[0]); ++i)
- count += g_gmInstruments[program][i];
- if (!count)
- warning("No AdLib instrument defined for GM program %d", (int)program);
- */
- _program = program;
-#ifdef ENABLE_OPL3
- if (!_owner->_opl3Mode) {
-#endif
- memcpy(&_partInstr, &g_gmInstruments[program], sizeof(AdLibInstrument));
-#ifdef ENABLE_OPL3
- } else {
- memcpy(&_partInstr, &g_gmInstrumentsOPL3[program][0], sizeof(AdLibInstrument));
- memcpy(&_partInstrSecondary, &g_gmInstrumentsOPL3[program][1], sizeof(AdLibInstrument));
- }
-#endif
-}
-
-void AdLibPart::pitchBend(int16 bend) {
- AdLibVoice *voice;
-
- _pitchBend = bend;
- for (voice = _voice; voice; voice = voice->_next) {
-#ifdef ENABLE_OPL3
- if (!_owner->_opl3Mode) {
-#endif
- _owner->adlibNoteOn(voice->_channel, voice->_note/* + _transposeEff*/,
- (_pitchBend * _pitchBendFactor >> 6) + _detuneEff);
-#ifdef ENABLE_OPL3
- } else {
- _owner->adlibNoteOn(voice->_channel, voice->_note, _pitchBend >> 1);
- }
-#endif
- }
-}
-
-void AdLibPart::controlChange(byte control, byte value) {
- switch (control) {
- case 0:
- case 32:
- // Bank select. Not supported
- break;
- case 1:
- modulationWheel(value);
- break;
- case 7:
- volume(value);
- break;
- case 10:
- panPosition(value);
- break;
- case 16:
- pitchBendFactor(value);
- break;
- case 17:
- detune(value);
- break;
- case 18:
- priority(value);
- break;
- case 64:
- sustain(value > 0);
- break;
- case 91:
- // Effects level. Not supported.
- break;
- case 93:
- // Chorus level. Not supported.
- break;
- case 119:
- // Unknown, used in Simon the Sorcerer 2
- break;
- case 121:
- // reset all controllers
- modulationWheel(0);
- pitchBendFactor(0);
- detune(0);
- sustain(0);
- break;
- case 123:
- allNotesOff();
- break;
- default:
- warning("AdLib: Unknown control change message %d (%d)", (int)control, (int)value);
- }
-}
-
-void AdLibPart::modulationWheel(byte value) {
- AdLibVoice *voice;
-
- _modWheel = value;
- for (voice = _voice; voice; voice = voice->_next) {
- if (voice->_s10a.active && voice->_s11a.flag0x40)
- voice->_s10a.modWheel = _modWheel >> 2;
- if (voice->_s10b.active && voice->_s11b.flag0x40)
- voice->_s10b.modWheel = _modWheel >> 2;
- }
-}
-
-void AdLibPart::volume(byte value) {
- AdLibVoice *voice;
-
- _volEff = value;
- for (voice = _voice; voice; voice = voice->_next) {
-#ifdef ENABLE_OPL3
- if (!_owner->_opl3Mode) {
-#endif
- _owner->adlibSetParam(voice->_channel, 0, g_volumeTable[g_volumeLookupTable[voice->_vol2][_volEff >> 2]]);
- if (voice->_twoChan) {
- _owner->adlibSetParam(voice->_channel, 13, g_volumeTable[g_volumeLookupTable[voice->_vol1][_volEff >> 2]]);
- }
-#ifdef ENABLE_OPL3
- } else {
- _owner->adlibSetParam(voice->_channel, 0, g_volumeTable[((voice->_vol2 + 1) * _volEff) >> 7], true);
- _owner->adlibSetParam(voice->_channel, 0, g_volumeTable[((voice->_secVol2 + 1) * _volEff) >> 7], false);
- if (voice->_twoChan) {
- _owner->adlibSetParam(voice->_channel, 13, g_volumeTable[((voice->_vol1 + 1) * _volEff) >> 7], true);
- }
- if (voice->_secTwoChan) {
- _owner->adlibSetParam(voice->_channel, 13, g_volumeTable[((voice->_secVol1 + 1) * _volEff) >> 7], false);
- }
- }
-#endif
- }
-}
-
-void AdLibPart::panPosition(byte value) {
- _pan = value;
-}
-
-void AdLibPart::pitchBendFactor(byte value) {
-#ifdef ENABLE_OPL3
- // Not supported in OPL3 mode.
- if (_owner->_opl3Mode) {
- return;
- }
-#endif
-
- AdLibVoice *voice;
-
- _pitchBendFactor = value;
- for (voice = _voice; voice; voice = voice->_next) {
- _owner->adlibNoteOn(voice->_channel, voice->_note/* + _transposeEff*/,
- (_pitchBend * _pitchBendFactor >> 6) + _detuneEff);
- }
-}
-
-void AdLibPart::detune(byte value) {
- // Sam&Max's OPL3 driver uses this for a completly different purpose. It
- // is related to voice allocation. We ignore this for now.
- // TODO: We probably need to look how the interpreter side of Sam&Max's
- // iMuse version handles all this too. Implementing the driver side here
- // would be not that hard.
-#ifdef ENABLE_OPL3
- if (_owner->_opl3Mode) {
- //_maxNotes = value;
- return;
- }
-#endif
-
- AdLibVoice *voice;
-
- _detuneEff = value;
- for (voice = _voice; voice; voice = voice->_next) {
- _owner->adlibNoteOn(voice->_channel, voice->_note/* + _transposeEff*/,
- (_pitchBend * _pitchBendFactor >> 6) + _detuneEff);
- }
-}
-
-void AdLibPart::priority(byte value) {
- _priEff = value;
-}
-
-void AdLibPart::sustain(bool value) {
- AdLibVoice *voice;
-
- _pedal = value;
- if (!value) {
- for (voice = _voice; voice; voice = voice->_next) {
- if (voice->_waitForPedal)
- _owner->mcOff(voice);
- }
- }
-}
-
-void AdLibPart::allNotesOff() {
- while (_voice)
- _owner->mcOff(_voice);
-}
-
-void AdLibPart::sysEx_customInstrument(uint32 type, const byte *instr) {
- // Sam&Max allows for instrument overwrites, but we will not support it
- // until we can find any track actually using it.
-#ifdef ENABLE_OPL3
- if (_owner->_opl3Mode) {
- warning("AdLibPart::sysEx_customInstrument: Used in OPL3 mode");
- return;
- }
-#endif
-
- if (type == 'ADL ') {
- memcpy(&_partInstr, instr, sizeof(AdLibInstrument));
- }
-}
-
-// MidiChannel method implementations for percussion
-
-AdLibPercussionChannel::~AdLibPercussionChannel() {
- for (int i = 0; i < ARRAYSIZE(_customInstruments); ++i) {
- delete _customInstruments[i];
- }
-}
-
-void AdLibPercussionChannel::init(MidiDriver_ADLIB *owner, byte channel) {
- AdLibPart::init(owner, channel);
- _priEff = 0;
- _volEff = 127;
-
- // Initialize the custom instruments data
- memset(_notes, 0, sizeof(_notes));
- memset(_customInstruments, 0, sizeof(_customInstruments));
-}
-
-void AdLibPercussionChannel::noteOff(byte note) {
- if (_customInstruments[note]) {
- note = _notes[note];
- }
-
- // This used to ignore note off events, since the builtin percussion
- // instrument data has a duration value, which causes the percussion notes
- // to stop automatically. This is not the case for (Groovie's) custom
- // percussion instruments though. Also the OPL3 driver of Sam&Max actually
- // does not handle the duration value, so we need it there too.
- _owner->partKeyOff(this, note);
-}
-
-void AdLibPercussionChannel::noteOn(byte note, byte velocity) {
- const AdLibInstrument *inst = NULL;
- const AdLibInstrument *sec = NULL;
-
- // The custom instruments have priority over the default mapping
- // We do not support custom instruments in OPL3 mode though.
-#ifdef ENABLE_OPL3
- if (!_owner->_opl3Mode) {
-#endif
- inst = _customInstruments[note];
- if (inst)
- note = _notes[note];
-#ifdef ENABLE_OPL3
- }
-#endif
-
- if (!inst) {
- // Use the default GM to FM mapping as a fallback
- byte key = g_gmPercussionInstrumentMap[note];
- if (key != 0xFF) {
-#ifdef ENABLE_OPL3
- if (!_owner->_opl3Mode) {
-#endif
- inst = &g_gmPercussionInstruments[key];
-#ifdef ENABLE_OPL3
- } else {
- inst = &g_gmPercussionInstrumentsOPL3[key][0];
- sec = &g_gmPercussionInstrumentsOPL3[key][1];
- }
-#endif
- }
- }
-
- if (!inst) {
- debug(2, "No instrument FM definition for GM percussion key %d", (int)note);
- return;
- }
-
- _owner->partKeyOn(this, inst, note, velocity, sec, _pan);
-}
-
-void AdLibPercussionChannel::sysEx_customInstrument(uint32 type, const byte *instr) {
- // We do not allow custom instruments in OPL3 mode right now.
-#ifdef ENABLE_OPL3
- if (_owner->_opl3Mode) {
- warning("AdLibPercussionChannel::sysEx_customInstrument: Used in OPL3 mode");
- return;
- }
-#endif
-
- if (type == 'ADLP') {
- byte note = instr[0];
- _notes[note] = instr[1];
-
- // Allocate memory for the new instruments
- if (!_customInstruments[note]) {
- _customInstruments[note] = new AdLibInstrument;
- memset(_customInstruments[note], 0, sizeof(AdLibInstrument));
- }
-
- // Save the new instrument data
- _customInstruments[note]->modCharacteristic = instr[2];
- _customInstruments[note]->modScalingOutputLevel = instr[3];
- _customInstruments[note]->modAttackDecay = instr[4];
- _customInstruments[note]->modSustainRelease = instr[5];
- _customInstruments[note]->modWaveformSelect = instr[6];
- _customInstruments[note]->carCharacteristic = instr[7];
- _customInstruments[note]->carScalingOutputLevel = instr[8];
- _customInstruments[note]->carAttackDecay = instr[9];
- _customInstruments[note]->carSustainRelease = instr[10];
- _customInstruments[note]->carWaveformSelect = instr[11];
- _customInstruments[note]->feedback = instr[12];
- }
-}
-
-// MidiDriver method implementations
-
-MidiDriver_ADLIB::MidiDriver_ADLIB() {
- uint i;
-
- _scummSmallHeader = false;
-#ifdef ENABLE_OPL3
- _opl3Mode = false;
-#endif
-
- _regCache = 0;
-#ifdef ENABLE_OPL3
- _regCacheSecondary = 0;
-#endif
-
- _timerCounter = 0;
- _voiceIndex = -1;
- for (i = 0; i < ARRAYSIZE(_curNotTable); ++i) {
- _curNotTable[i] = 0;
- }
-
- for (i = 0; i < ARRAYSIZE(_parts); ++i) {
- _parts[i].init(this, i + ((i >= 9) ? 1 : 0));
- }
- _percussion.init(this, 9);
- _timerIncrease = 0xD69;
- _timerThreshold = 0x411B;
- _opl = 0;
- _adlibTimerProc = 0;
- _adlibTimerParam = 0;
- _isOpen = false;
-}
-
-int MidiDriver_ADLIB::open() {
- if (_isOpen)
- return MERR_ALREADY_OPEN;
-
- _isOpen = true;
-
- int i;
- AdLibVoice *voice;
-
- for (i = 0, voice = _voices; i != ARRAYSIZE(_voices); i++, voice++) {
- voice->_channel = i;
- voice->_s11a.s10 = &voice->_s10b;
- voice->_s11b.s10 = &voice->_s10a;
- }
-
- // Try to use OPL3 when requested.
-#ifdef ENABLE_OPL3
- if (_opl3Mode) {
- _opl = OPL::Config::create(OPL::Config::kOpl3);
- }
-
- // Initialize plain OPL2 when no OPL3 is intiailized already.
- if (!_opl) {
-#endif
- _opl = OPL::Config::create();
-#ifdef ENABLE_OPL3
- _opl3Mode = false;
- }
-#endif
- _opl->init();
-
- _regCache = (byte *)calloc(256, 1);
-
- adlibWrite(8, 0x40);
- adlibWrite(0xBD, 0x00);
-#ifdef ENABLE_OPL3
- if (!_opl3Mode) {
-#endif
- adlibWrite(1, 0x20);
- createLookupTable();
-#ifdef ENABLE_OPL3
- } else {
- _regCacheSecondary = (byte *)calloc(256, 1);
- adlibWriteSecondary(5, 1);
- }
-#endif
-
- _opl->start(new Common::Functor0Mem<void, MidiDriver_ADLIB>(this, &MidiDriver_ADLIB::onTimer));
- return 0;
-}
-
-void MidiDriver_ADLIB::close() {
- if (!_isOpen)
- return;
- _isOpen = false;
-
- // Stop the OPL timer
- _opl->stop();
-
- uint i;
- for (i = 0; i < ARRAYSIZE(_voices); ++i) {
- if (_voices[i]._part)
- mcOff(&_voices[i]);
- }
-
- // Turn off the OPL emulation
- delete _opl;
- _opl = 0;
-
- free(_regCache);
-#ifdef ENABLE_OPL3
- free(_regCacheSecondary);
-#endif
-}
-
-void MidiDriver_ADLIB::send(uint32 b) {
- send(b & 0xF, b & 0xFFFFFFF0);
-}
-
-void MidiDriver_ADLIB::send(byte chan, uint32 b) {
- //byte param3 = (byte) ((b >> 24) & 0xFF);
- byte param2 = (byte)((b >> 16) & 0xFF);
- byte param1 = (byte)((b >> 8) & 0xFF);
- byte cmd = (byte)(b & 0xF0);
-
- AdLibPart *part;
- if (chan == 9)
- part = &_percussion;
- else
- part = &_parts[chan];
-
- switch (cmd) {
- case 0x80:// Note Off
- part->noteOff(param1);
- break;
- case 0x90: // Note On
- part->noteOn(param1, param2);
- break;
- case 0xA0: // Aftertouch
- break; // Not supported.
- case 0xB0: // Control Change
- part->controlChange(param1, param2);
- break;
- case 0xC0: // Program Change
- part->programChange(param1);
- break;
- case 0xD0: // Channel Pressure
- break; // Not supported.
- case 0xE0: // Pitch Bend
- part->pitchBend((param1 | (param2 << 7)) - 0x2000);
- break;
- 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);
- }
-}
-
-uint32 MidiDriver_ADLIB::property(int prop, uint32 param) {
- switch (prop) {
- case PROP_OLD_ADLIB: // Older games used a different operator volume algorithm
- _scummSmallHeader = (param > 0);
- if (_scummSmallHeader) {
- _timerIncrease = 473;
- _timerThreshold = 1000;
- } else {
- _timerIncrease = 0xD69;
- _timerThreshold = 0x411B;
- }
- return 1;
-
- case PROP_SCUMM_OPL3: // Sam&Max OPL3 support.
-#ifdef ENABLE_OPL3
- _opl3Mode = (param > 0);
-#endif
- return 1;
- }
-
- return 0;
-}
-
-void MidiDriver_ADLIB::setPitchBendRange(byte channel, uint range) {
-#ifdef ENABLE_OPL3
- // Not supported in OPL3 mode.
- if (_opl3Mode) {
- return;
- }
-#endif
-
- AdLibVoice *voice;
- AdLibPart *part = &_parts[channel];
-
- part->_pitchBendFactor = range;
- for (voice = part->_voice; voice; voice = voice->_next) {
- adlibNoteOn(voice->_channel, voice->_note/* + part->_transposeEff*/,
- (part->_pitchBend * part->_pitchBendFactor >> 6) + part->_detuneEff);
- }
-}
-
-void MidiDriver_ADLIB::sysEx_customInstrument(byte channel, uint32 type, const byte *instr) {
- _parts[channel].sysEx_customInstrument(type, instr);
-}
-
-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;
-}
-
-// All the code brought over from IMuseAdLib
-
-void MidiDriver_ADLIB::adlibWrite(byte reg, byte value) {
- if (_regCache[reg] == value) {
- return;
- }
-#ifdef DEBUG_ADLIB
- debug(6, "%10d: adlibWrite[%x] = %x", g_tick, reg, value);
-#endif
- _regCache[reg] = value;
-
- _opl->writeReg(reg, value);
-}
-
-#ifdef ENABLE_OPL3
-void MidiDriver_ADLIB::adlibWriteSecondary(byte reg, byte value) {
- assert(_opl3Mode);
-
- if (_regCacheSecondary[reg] == value) {
- return;
- }
-#ifdef DEBUG_ADLIB
- debug(6, "%10d: adlibWriteSecondary[%x] = %x", g_tick, reg, value);
-#endif
- _regCacheSecondary[reg] = value;
-
- _opl->writeReg(reg | 0x100, value);
-}
-#endif
-
-void MidiDriver_ADLIB::onTimer() {
- if (_adlibTimerProc)
- (*_adlibTimerProc)(_adlibTimerParam);
-
- _timerCounter += _timerIncrease;
- while (_timerCounter >= _timerThreshold) {
- _timerCounter -= _timerThreshold;
-#ifdef DEBUG_ADLIB
- g_tick++;
-#endif
- // Sam&Max's OPL3 driver does not have any timer handling like this.
-#ifdef ENABLE_OPL3
- if (!_opl3Mode) {
-#endif
- AdLibVoice *voice = _voices;
- for (int i = 0; i != ARRAYSIZE(_voices); i++, voice++) {
- if (!voice->_part)
- continue;
- if (voice->_duration && (voice->_duration -= 0x11) <= 0) {
- mcOff(voice);
- return;
- }
- if (voice->_s10a.active) {
- mcIncStuff(voice, &voice->_s10a, &voice->_s11a);
- }
- if (voice->_s10b.active) {
- mcIncStuff(voice, &voice->_s10b, &voice->_s11b);
- }
- }
-#ifdef ENABLE_OPL3
- }
-#endif
- }
-}
-
-void MidiDriver_ADLIB::setTimerCallback(void *timerParam, Common::TimerManager::TimerProc timerProc) {
- _adlibTimerProc = timerProc;
- _adlibTimerParam = timerParam;
-}
-
-void MidiDriver_ADLIB::mcOff(AdLibVoice *voice) {
- AdLibVoice *tmp;
-
- adlibKeyOff(voice->_channel);
-
- tmp = voice->_prev;
-
- if (voice->_next)
- voice->_next->_prev = tmp;
- if (tmp)
- tmp->_next = voice->_next;
- else
- voice->_part->_voice = voice->_next;
- voice->_part = NULL;
-}
-
-void MidiDriver_ADLIB::mcIncStuff(AdLibVoice *voice, Struct10 *s10, Struct11 *s11) {
- byte code;
- AdLibPart *part = voice->_part;
-
- code = struct10OnTimer(s10, s11);
-
- if (code & 1) {
- switch (s11->param) {
- case 0:
- voice->_vol2 = s10->startValue + s11->modifyVal;
- if (!_scummSmallHeader) {
- adlibSetParam(voice->_channel, 0,
- g_volumeTable[g_volumeLookupTable[voice->_vol2]
- [part->_volEff >> 2]]);
- } else {
- adlibSetParam(voice->_channel, 0, voice->_vol2);
- }
- break;
- case 13:
- voice->_vol1 = s10->startValue + s11->modifyVal;
- if (voice->_twoChan && !_scummSmallHeader) {
- adlibSetParam(voice->_channel, 13,
- g_volumeTable[g_volumeLookupTable[voice->_vol1]
- [part->_volEff >> 2]]);
- } else {
- adlibSetParam(voice->_channel, 13, voice->_vol1);
- }
- break;
- case 30:
- s11->s10->modWheel = (char)s11->modifyVal;
- break;
- case 31:
- s11->s10->unk3 = (char)s11->modifyVal;
- break;
- default:
- adlibSetParam(voice->_channel, s11->param,
- s10->startValue + s11->modifyVal);
- break;
- }
- }
-
- if (code & 2 && s11->flag0x10)
- adlibKeyOnOff(voice->_channel);
-}
-
-void MidiDriver_ADLIB::adlibKeyOff(int chan) {
- byte reg = chan + 0xB0;
- adlibWrite(reg, adlibGetRegValue(reg) & ~0x20);
-#ifdef ENABLE_OPL3
- if (_opl3Mode) {
- adlibWriteSecondary(reg, adlibGetRegValueSecondary(reg) & ~0x20);
- }
-#endif
-}
-
-byte MidiDriver_ADLIB::struct10OnTimer(Struct10 *s10, Struct11 *s11) {
- byte result = 0;
- int i;
-
- if (s10->count && (s10->count -= 17) <= 0) {
- s10->active = 0;
- return 0;
- }
-
- i = s10->curVal + s10->speedHi;
- s10->speedLoCounter += s10->speedLo;
- if (s10->speedLoCounter >= s10->speedLoMax) {
- s10->speedLoCounter -= s10->speedLoMax;
- i += s10->direction;
- }
- if (s10->curVal != i || s10->modWheel != s10->modWheelLast) {
- s10->curVal = i;
- s10->modWheelLast = s10->modWheel;
- i = lookupVolume(i, s10->modWheelLast);
- if (i != s11->modifyVal) {
- s11->modifyVal = i;
- result = 1;
- }
- }
-
- if (!--s10->numSteps) {
- s10->active++;
- if (s10->active > 4) {
- if (s10->loop) {
- s10->active = 1;
- result |= 2;
- struct10Setup(s10);
- } else {
- s10->active = 0;
- }
- } else {
- struct10Setup(s10);
- }
- }
-
- return result;
-}
-
-void MidiDriver_ADLIB::adlibSetParam(int channel, byte param, int value, bool primary) {
- const AdLibSetParams *as;
- byte reg;
-
- assert(channel >= 0 && channel < 9);
-#ifdef ENABLE_OPL3
- assert(!_opl3Mode || (param == 0 || param == 13));
-#endif
-
- if (param <= 12) {
- reg = g_operator2Offsets[channel];
- } else if (param <= 25) {
- param -= 13;
- reg = g_operator1Offsets[channel];
- } else if (param <= 27) {
- param -= 13;
- reg = channel;
- } else if (param == 28 || param == 29) {
- if (param == 28)
- value -= 15;
- else
- value -= 383;
- value <<= 4;
- _channelTable2[channel] = value;
- adlibPlayNote(channel, _curNotTable[channel] + value);
- return;
- } else {
- return;
- }
-
- as = &g_setParamTable[param];
- if (as->inversion)
- value = as->inversion - value;
- reg += as->registerBase;
-#ifdef ENABLE_OPL3
- if (primary) {
-#endif
- adlibWrite(reg, (adlibGetRegValue(reg) & ~as->mask) | (((byte)value) << as->shift));
-#ifdef ENABLE_OPL3
- } else {
- adlibWriteSecondary(reg, (adlibGetRegValueSecondary(reg) & ~as->mask) | (((byte)value) << as->shift));
- }
-#endif
-}
-
-void MidiDriver_ADLIB::adlibKeyOnOff(int channel) {
-#ifdef ENABLE_OPL3
- assert(!_opl3Mode);
-#endif
-
- byte val;
- byte reg = channel + 0xB0;
- assert(channel >= 0 && channel < 9);
-
- val = adlibGetRegValue(reg);
- adlibWrite(reg, val & ~0x20);
- adlibWrite(reg, val | 0x20);
-}
-
-void MidiDriver_ADLIB::struct10Setup(Struct10 *s10) {
- int b, c, d, e, f, g, h;
- byte t;
-
- b = s10->unk3;
- f = s10->active - 1;
-
- t = s10->tableA[f];
- e = g_numStepsTable[g_volumeLookupTable[t & 0x7F][b]];
- if (t & 0x80) {
- e = randomNr(e);
- }
- if (e == 0)
- e++;
-
- s10->numSteps = s10->speedLoMax = e;
-
- if (f != 2) {
- c = s10->maxValue;
- g = s10->startValue;
- t = s10->tableB[f];
- d = lookupVolume(c, (t & 0x7F) - 31);
- if (t & 0x80) {
- d = randomNr(d);
- }
- if (d + g > c) {
- h = c - g;
- } else {
- h = d;
- if (d + g < 0)
- h = -g;
- }
- h -= s10->curVal;
- } else {
- h = 0;
- }
-
- s10->speedHi = h / e;
- if (h < 0) {
- h = -h;
- s10->direction = -1;
- } else {
- s10->direction = 1;
- }
-
- s10->speedLo = h % e;
- s10->speedLoCounter = 0;
-}
-
-void MidiDriver_ADLIB::adlibPlayNote(int channel, int note) {
- byte old, oct, notex;
- int note2;
- int i;
-
- note2 = (note >> 7) - 4;
- note2 = (note2 < 128) ? note2 : 0;
-
- oct = (note2 / 12);
- if (oct > 7)
- oct = 7 << 2;
- else
- oct <<= 2;
- notex = note2 % 12 + 3;
-
- old = adlibGetRegValue(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);
- adlibWrite(channel + 0xA0, g_noteFrequencies[i]);
- adlibWrite(channel + 0xB0, oct | 0x20);
-}
-
-int MidiDriver_ADLIB::randomNr(int a) {
- static byte _randSeed = 1;
- if (_randSeed & 1) {
- _randSeed >>= 1;
- _randSeed ^= 0xB8;
- } else {
- _randSeed >>= 1;
- }
- return _randSeed * a >> 8;
-}
-
-void MidiDriver_ADLIB::partKeyOff(AdLibPart *part, byte note) {
- AdLibVoice *voice;
-
- for (voice = part->_voice; voice; voice = voice->_next) {
- if (voice->_note == note) {
- if (part->_pedal)
- voice->_waitForPedal = true;
- else
- mcOff(voice);
- }
- }
-}
-
-void MidiDriver_ADLIB::partKeyOn(AdLibPart *part, const AdLibInstrument *instr, byte note, byte velocity, const AdLibInstrument *second, byte pan) {
- AdLibVoice *voice;
-
- voice = allocateVoice(part->_priEff);
- if (!voice)
- return;
-
- linkMc(part, voice);
- mcKeyOn(voice, instr, note, velocity, second, pan);
-}
-
-AdLibVoice *MidiDriver_ADLIB::allocateVoice(byte pri) {
- AdLibVoice *ac, *best = NULL;
- int i;
-
- for (i = 0; i < 9; i++) {
- if (++_voiceIndex >= 9)
- _voiceIndex = 0;
- ac = &_voices[_voiceIndex];
- if (!ac->_part)
- return ac;
- if (!ac->_next) {
- if (ac->_part->_priEff <= pri) {
- pri = ac->_part->_priEff;
- best = ac;
- }
- }
- }
-
- /* SCUMM V3 games don't have note priorities, first comes wins. */
- if (_scummSmallHeader)
- return NULL;
-
- if (best)
- mcOff(best);
- return best;
-}
-
-void MidiDriver_ADLIB::linkMc(AdLibPart *part, AdLibVoice *voice) {
- voice->_part = part;
- voice->_next = (AdLibVoice *)part->_voice;
- part->_voice = voice;
- voice->_prev = NULL;
-
- if (voice->_next)
- voice->_next->_prev = voice;
-}
-
-void MidiDriver_ADLIB::mcKeyOn(AdLibVoice *voice, const AdLibInstrument *instr, byte note, byte velocity, const AdLibInstrument *second, byte pan) {
- AdLibPart *part = voice->_part;
- byte vol1, vol2;
-#ifdef ENABLE_OPL3
- byte secVol1 = 0, secVol2 = 0;
-#endif
-
- voice->_twoChan = instr->feedback & 1;
- voice->_note = note;
- voice->_waitForPedal = false;
- voice->_duration = instr->duration;
- if (voice->_duration != 0)
- voice->_duration *= 63;
-
- if (!_scummSmallHeader) {
-#ifdef ENABLE_OPL3
- if (_opl3Mode)
- vol1 = (instr->modScalingOutputLevel & 0x3F) + (velocity * ((instr->modWaveformSelect >> 3) + 1)) / 64;
- else
-#endif
- vol1 = (instr->modScalingOutputLevel & 0x3F) + g_volumeLookupTable[velocity >> 1][instr->modWaveformSelect >> 2];
- } else {
- vol1 = 0x3f - (instr->modScalingOutputLevel & 0x3F);
- }
- if (vol1 > 0x3F)
- vol1 = 0x3F;
- voice->_vol1 = vol1;
-
- if (!_scummSmallHeader) {
-#ifdef ENABLE_OPL3
- if (_opl3Mode)
- vol2 = (instr->carScalingOutputLevel & 0x3F) + (velocity * ((instr->carWaveformSelect >> 3) + 1)) / 64;
- else
-#endif
- vol2 = (instr->carScalingOutputLevel & 0x3F) + g_volumeLookupTable[velocity >> 1][instr->carWaveformSelect >> 2];
- } else {
- vol2 = 0x3f - (instr->carScalingOutputLevel & 0x3F);
- }
- if (vol2 > 0x3F)
- vol2 = 0x3F;
- voice->_vol2 = vol2;
-
-#ifdef ENABLE_OPL3
- if (_opl3Mode) {
- voice->_secTwoChan = second->feedback & 1;
- secVol1 = (second->modScalingOutputLevel & 0x3F) + (velocity * ((second->modWaveformSelect >> 3) + 1)) / 64;
- if (secVol1 > 0x3F) {
- secVol1 = 0x3F;
- }
- voice->_secVol1 = secVol1;
- secVol2 = (second->carScalingOutputLevel & 0x3F) + (velocity * ((second->carWaveformSelect >> 3) + 1)) / 64;
- if (secVol2 > 0x3F) {
- secVol2 = 0x3F;
- }
- voice->_secVol2 = secVol2;
- }
-#endif
-
- if (!_scummSmallHeader) {
-#ifdef ENABLE_OPL3
- if (!_opl3Mode) {
-#endif
- int c = part->_volEff >> 2;
- vol2 = g_volumeTable[g_volumeLookupTable[vol2][c]];
- if (voice->_twoChan)
- vol1 = g_volumeTable[g_volumeLookupTable[vol1][c]];
-#ifdef ENABLE_OPL3
- } else {
- vol2 = g_volumeTable[((vol2 + 1) * part->_volEff) >> 7];
- secVol2 = g_volumeTable[((secVol2 + 1) * part->_volEff) >> 7];
- if (voice->_twoChan)
- vol1 = g_volumeTable[((vol1 + 1) * part->_volEff) >> 7];
- if (voice->_secTwoChan)
- secVol1 = g_volumeTable[((secVol1 + 1) * part->_volEff) >> 7];
- }
-#endif
- }
-
- adlibSetupChannel(voice->_channel, instr, vol1, vol2);
-#ifdef ENABLE_OPL3
- if (!_opl3Mode) {
-#endif
- adlibNoteOnEx(voice->_channel, /*part->_transposeEff + */note, part->_detuneEff + (part->_pitchBend * part->_pitchBendFactor >> 6));
-
- if (instr->flagsA & 0x80) {
- mcInitStuff(voice, &voice->_s10a, &voice->_s11a, instr->flagsA, &instr->extraA);
- } else {
- voice->_s10a.active = 0;
- }
-
- if (instr->flagsB & 0x80) {
- mcInitStuff(voice, &voice->_s10b, &voice->_s11b, instr->flagsB, &instr->extraB);
- } else {
- voice->_s10b.active = 0;
- }
-#ifdef ENABLE_OPL3
- } else {
- adlibSetupChannelSecondary(voice->_channel, second, secVol1, secVol2, pan);
- adlibNoteOnEx(voice->_channel, note, part->_pitchBend >> 1);
- }
-#endif
-}
-
-void MidiDriver_ADLIB::adlibSetupChannel(int chan, const AdLibInstrument *instr, byte vol1, byte vol2) {
- assert(chan >= 0 && chan < 9);
-
- byte channel = g_operator1Offsets[chan];
- adlibWrite(channel + 0x20, instr->modCharacteristic);
- adlibWrite(channel + 0x40, (instr->modScalingOutputLevel | 0x3F) - vol1);
- adlibWrite(channel + 0x60, 0xff & (~instr->modAttackDecay));
- adlibWrite(channel + 0x80, 0xff & (~instr->modSustainRelease));
- adlibWrite(channel + 0xE0, instr->modWaveformSelect);
-
- channel = g_operator2Offsets[chan];
- adlibWrite(channel + 0x20, instr->carCharacteristic);
- adlibWrite(channel + 0x40, (instr->carScalingOutputLevel | 0x3F) - vol2);
- adlibWrite(channel + 0x60, 0xff & (~instr->carAttackDecay));
- adlibWrite(channel + 0x80, 0xff & (~instr->carSustainRelease));
- adlibWrite(channel + 0xE0, instr->carWaveformSelect);
-
- adlibWrite((byte)chan + 0xC0, instr->feedback
-#ifdef ENABLE_OPL3
- | (_opl3Mode ? 0x30 : 0)
-#endif
- );
-}
-
-#ifdef ENABLE_OPL3
-void MidiDriver_ADLIB::adlibSetupChannelSecondary(int chan, const AdLibInstrument *instr, byte vol1, byte vol2, byte pan) {
- assert(chan >= 0 && chan < 9);
- assert(_opl3Mode);
-
- byte channel = g_operator1Offsets[chan];
- adlibWriteSecondary(channel + 0x20, instr->modCharacteristic);
- adlibWriteSecondary(channel + 0x40, (instr->modScalingOutputLevel | 0x3F) - vol1);
- adlibWriteSecondary(channel + 0x60, 0xff & (~instr->modAttackDecay));
- adlibWriteSecondary(channel + 0x80, 0xff & (~instr->modSustainRelease));
- adlibWriteSecondary(channel + 0xE0, instr->modWaveformSelect);
-
- channel = g_operator2Offsets[chan];
- adlibWriteSecondary(channel + 0x20, instr->carCharacteristic);
- adlibWriteSecondary(channel + 0x40, (instr->carScalingOutputLevel | 0x3F) - vol2);
- adlibWriteSecondary(channel + 0x60, 0xff & (~instr->carAttackDecay));
- adlibWriteSecondary(channel + 0x80, 0xff & (~instr->carSustainRelease));
- adlibWriteSecondary(channel + 0xE0, instr->carWaveformSelect);
-
- // The original uses the following (strange) behavior:
-#if 0
- if (instr->feedback | (pan > 64)) {
- adlibWriteSecondary((byte)chan + 0xC0, 0x20);
- } else {
- adlibWriteSecondary((byte)chan + 0xC0, 0x10);
- }
-#else
- adlibWriteSecondary((byte)chan + 0xC0, instr->feedback | ((pan > 64) ? 0x20 : 0x10));
-#endif
-}
-#endif
-
-void MidiDriver_ADLIB::mcInitStuff(AdLibVoice *voice, Struct10 *s10,
- Struct11 *s11, byte flags, const InstrumentExtra *ie) {
- AdLibPart *part = voice->_part;
- s11->modifyVal = 0;
- s11->flag0x40 = flags & 0x40;
- s10->loop = flags & 0x20;
- s11->flag0x10 = flags & 0x10;
- s11->param = g_paramTable1[flags & 0xF];
- s10->maxValue = g_maxValTable[flags & 0xF];
- s10->unk3 = 31;
- if (s11->flag0x40) {
- s10->modWheel = part->_modWheel >> 2;
- } else {
- s10->modWheel = 31;
- }
-
- switch (s11->param) {
- case 0:
- s10->startValue = voice->_vol2;
- break;
- case 13:
- s10->startValue = voice->_vol1;
- break;
- case 30:
- s10->startValue = 31;
- s11->s10->modWheel = 0;
- break;
- case 31:
- s10->startValue = 0;
- s11->s10->unk3 = 0;
- break;
- default:
- s10->startValue = adlibGetRegValueParam(voice->_channel, s11->param);
- }
-
- struct10Init(s10, ie);
-}
-
-void MidiDriver_ADLIB::struct10Init(Struct10 *s10, const InstrumentExtra *ie) {
- s10->active = 1;
- if (!_scummSmallHeader) {
- s10->curVal = 0;
- } else {
- s10->curVal = s10->startValue;
- s10->startValue = 0;
- }
- s10->modWheelLast = 31;
- s10->count = ie->a;
- if (s10->count)
- s10->count *= 63;
- s10->tableA[0] = ie->b;
- s10->tableA[1] = ie->d;
- s10->tableA[2] = ie->f;
- s10->tableA[3] = ie->g;
-
- s10->tableB[0] = ie->c;
- s10->tableB[1] = ie->e;
- s10->tableB[2] = 0;
- s10->tableB[3] = ie->h;
-
- struct10Setup(s10);
-}
-
-int MidiDriver_ADLIB::adlibGetRegValueParam(int chan, byte param) {
- const AdLibSetParams *as;
- byte val;
- byte channel;
-
- assert(chan >= 0 && chan < 9);
-
- if (param <= 12) {
- channel = g_operator2Offsets[chan];
- } else if (param <= 25) {
- param -= 13;
- channel = g_operator1Offsets[chan];
- } else if (param <= 27) {
- param -= 13;
- channel = chan;
- } else if (param == 28) {
- return 0xF;
- } else if (param == 29) {
- return 0x17F;
- } else {
- return 0;
- }
-
- as = &g_setParamTable[param];
- val = adlibGetRegValue(channel + as->registerBase);
- val &= as->mask;
- val >>= as->shift;
- if (as->inversion)
- val = as->inversion - val;
-
- return val;
-}
-
-void MidiDriver_ADLIB::adlibNoteOn(int chan, byte note, int mod) {
-#ifdef ENABLE_OPL3
- if (_opl3Mode) {
- adlibNoteOnEx(chan, note, mod);
- return;
- }
-#endif
-
- assert(chan >= 0 && chan < 9);
- int code = (note << 7) + mod;
- _curNotTable[chan] = code;
- adlibPlayNote(chan, (int16)_channelTable2[chan] + code);
-}
-
-void MidiDriver_ADLIB::adlibNoteOnEx(int chan, byte note, int mod) {
- assert(chan >= 0 && chan < 9);
-
-#ifdef ENABLE_OPL3
- if (_opl3Mode) {
- const int noteAdjusted = note + (mod >> 8) - 7;
- const int pitchAdjust = (mod >> 5) & 7;
-
- adlibWrite(0xA0 + chan, g_noteFrequencies[(noteAdjusted % 12) * 8 + pitchAdjust + 6 * 8]);
- adlibWriteSecondary(0xA0 + chan, g_noteFrequencies[(noteAdjusted % 12) * 8 + pitchAdjust + 6 * 8]);
- adlibWrite(0xB0 + chan, (CLIP(noteAdjusted / 12, 0, 7) << 2) | 0x20);
- adlibWriteSecondary(0xB0 + chan, (CLIP(noteAdjusted / 12, 0, 7) << 2) | 0x20);
- } else {
-#endif
- int code = (note << 7) + mod;
- _curNotTable[chan] = code;
- _channelTable2[chan] = 0;
- adlibPlayNote(chan, code);
-#ifdef ENABLE_OPL3
- }
-#endif
-}
-
-// Plugin interface
-
-class AdLibEmuMusicPlugin : public MusicPluginObject {
-public:
- const char *getName() const {
- return _s("AdLib Emulator");
- }
-
- const char *getId() const {
- return "adlib";
- }
-
- MusicDevices getDevices() const;
- Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;
-};
-
-MusicDevices AdLibEmuMusicPlugin::getDevices() const {
- MusicDevices devices;
- devices.push_back(MusicDevice(this, "", MT_ADLIB));
- return devices;
-}
-
-Common::Error AdLibEmuMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
- *mididriver = new MidiDriver_ADLIB();
-
- return Common::kNoError;
-}
-
-//#if PLUGIN_ENABLED_DYNAMIC(ADLIB)
- //REGISTER_PLUGIN_DYNAMIC(ADLIB, PLUGIN_TYPE_MUSIC, AdLibEmuMusicPlugin);
-//#else
- REGISTER_PLUGIN_STATIC(ADLIB, PLUGIN_TYPE_MUSIC, AdLibEmuMusicPlugin);
-//#endif
Commit: bb8132beb82a4f5d5a3f8db0fb9dec08b2965b72
https://github.com/scummvm/scummvm/commit/bb8132beb82a4f5d5a3f8db0fb9dec08b2965b72
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-07-07T20:41:30-04:00
Commit Message:
AUDIO: Move ALSA OPL 'driver' out of softsynth
Might eventually be worth moving to backends/
Changed paths:
A audio/alsa_opl.cpp
R audio/softsynth/opl/alsa.cpp
audio/module.mk
diff --git a/audio/alsa_opl.cpp b/audio/alsa_opl.cpp
new file mode 100644
index 0000000..6b9e48e
--- /dev/null
+++ b/audio/alsa_opl.cpp
@@ -0,0 +1,349 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/* OPL implementation for hardware OPL using ALSA Direct FM API.
+ *
+ * Caveats and limitations:
+ * - Pretends to be a softsynth (emitting silence).
+ * - Dual OPL2 mode requires OPL3 hardware.
+ * - Every register write leads to a series of register writes on the hardware,
+ * due to the lack of direct register access in the ALSA Direct FM API.
+ * - No timers
+ */
+
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+#include "common/scummsys.h"
+
+#include "common/debug.h"
+#include "common/str.h"
+#include "audio/fmopl.h"
+
+#include <sys/ioctl.h>
+#include <alsa/asoundlib.h>
+#include <sound/asound_fm.h>
+
+namespace OPL {
+namespace ALSA {
+
+class OPL : public ::OPL::RealOPL {
+private:
+ enum {
+ kOpl2Voices = 9,
+ kVoices = 18,
+ kOpl2Operators = 18,
+ kOperators = 36
+ };
+
+ Config::OplType _type;
+ int _iface;
+ snd_hwdep_t *_opl;
+ snd_dm_fm_voice _oper[kOperators];
+ snd_dm_fm_note _voice[kVoices];
+ snd_dm_fm_params _params;
+ int index[2];
+ static const int voiceToOper0[kVoices];
+ static const int regOffsetToOper[0x20];
+
+ void writeOplReg(int c, int r, int v);
+ void clear();
+
+public:
+ OPL(Config::OplType type);
+ ~OPL();
+
+ bool init();
+ void reset();
+
+ void write(int a, int v);
+ byte read(int a);
+
+ void writeReg(int r, int v);
+};
+
+const int OPL::voiceToOper0[OPL::kVoices] =
+ { 0, 1, 2, 6, 7, 8, 12, 13, 14, 18, 19, 20, 24, 25, 26, 30, 31, 32 };
+
+const int OPL::regOffsetToOper[0x20] =
+ { 0, 1, 2, 3, 4, 5, -1, -1, 6, 7, 8, 9, 10, 11, -1, -1,
+ 12, 13, 14, 15, 16, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
+
+OPL::OPL(Config::OplType type) : _type(type), _opl(nullptr), _iface(0) {
+}
+
+OPL::~OPL() {
+ stop();
+
+ if (_opl) {
+ snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_RESET, nullptr);
+ snd_hwdep_close(_opl);
+ }
+}
+
+void OPL::clear() {
+ index[0] = index[1] = 0;
+
+ memset(_oper, 0, sizeof(_oper));
+ memset(_voice, 0, sizeof(_voice));
+ memset(&_params, 0, sizeof(_params));
+
+ for (int i = 0; i < kOperators; ++i) {
+ _oper[i].op = (i / 3) % 2;
+ _oper[i].voice = (i / 6) * 3 + (i % 3);
+ }
+
+ for (int i = 0; i < kVoices; ++i)
+ _voice[i].voice = i;
+
+ // For OPL3 hardware we need to set up the panning in OPL2 modes
+ if (_iface == SND_HWDEP_IFACE_OPL3) {
+ if (_type == Config::kDualOpl2) {
+ for (int i = 0; i < kOpl2Operators; ++i)
+ _oper[i].left = 1; // FIXME below
+ for (int i = kOpl2Operators; i < kOperators; ++i)
+ _oper[i].right = 1;
+ } else if (_type == Config::kOpl2) {
+ for (int i = 0; i < kOpl2Operators; ++i) {
+ _oper[i].left = 1;
+ _oper[i].right = 1;
+ }
+ }
+ }
+}
+
+bool OPL::init() {
+ clear();
+
+ int card = -1;
+ snd_ctl_t *ctl;
+ snd_hwdep_info_t *info;
+ snd_hwdep_info_alloca(&info);
+
+ int iface = SND_HWDEP_IFACE_OPL3;
+ if (_type == Config::kOpl2)
+ iface = SND_HWDEP_IFACE_OPL2;
+
+ // Look for OPL hwdep interface
+ while (!snd_card_next(&card) && card >= 0) {
+ int dev = -1;
+ Common::String name = Common::String::format("hw:%d", card);
+
+ if (snd_ctl_open(&ctl, name.c_str(), 0) < 0)
+ continue;
+
+ while (!snd_ctl_hwdep_next_device(ctl, &dev) && dev >= 0) {
+ name = Common::String::format("hw:%d,%d", card, dev);
+
+ if (snd_hwdep_open(&_opl, name.c_str(), SND_HWDEP_OPEN_WRITE) < 0)
+ continue;
+
+ if (!snd_hwdep_info(_opl, info)) {
+ int found = snd_hwdep_info_get_iface(info);
+ // OPL3 can be used for (Dual) OPL2 mode
+ if (found == iface || found == SND_HWDEP_IFACE_OPL3) {
+ snd_ctl_close(ctl);
+ _iface = found;
+ reset();
+ return true;
+ }
+ }
+
+ // Wrong interface, try next device
+ snd_hwdep_close(_opl);
+ _opl = nullptr;
+ }
+
+ snd_ctl_close(ctl);
+ }
+
+ return false;
+}
+
+void OPL::reset() {
+ snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_RESET, nullptr);
+ if (_iface == SND_HWDEP_IFACE_OPL3)
+ snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_MODE, (void *)SNDRV_DM_FM_MODE_OPL3);
+
+ clear();
+
+ // Sync up with the hardware
+ snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_PARAMS, (void *)&_params);
+ for (uint i = 0; i < (_iface == SND_HWDEP_IFACE_OPL3 ? kVoices : kOpl2Voices); ++i)
+ snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_PLAY_NOTE, (void *)&_voice[i]);
+ for (uint i = 0; i < (_iface == SND_HWDEP_IFACE_OPL3 ? kOperators : kOpl2Operators); ++i)
+ snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_VOICE, (void *)&_oper[i]);
+}
+
+void OPL::write(int port, int val) {
+ val &= 0xff;
+ int chip = (port & 2) >> 1;
+
+ if (port & 1) {
+ switch(_type) {
+ case Config::kOpl2:
+ writeOplReg(0, index[0], val);
+ break;
+ case Config::kDualOpl2:
+ if (port & 8) {
+ writeOplReg(0, index[0], val);
+ writeOplReg(1, index[1], val);
+ } else
+ writeOplReg(chip, index[chip], val);
+ break;
+ case Config::kOpl3:
+ writeOplReg(chip, index[chip], val);
+ }
+ } else {
+ switch(_type) {
+ case Config::kOpl2:
+ index[0] = val;
+ break;
+ case Config::kDualOpl2:
+ if (port & 8) {
+ index[0] = val;
+ index[1] = val;
+ } else
+ index[chip] = val;
+ break;
+ case Config::kOpl3:
+ index[chip] = val;
+ }
+ }
+}
+
+byte OPL::read(int port) {
+ return 0;
+}
+
+void OPL::writeReg(int r, int v) {
+ switch (_type) {
+ case Config::kOpl2:
+ writeOplReg(0, r, v);
+ break;
+ case Config::kDualOpl2:
+ writeOplReg(0, r, v);
+ writeOplReg(1, r, v);
+ break;
+ case Config::kOpl3:
+ writeOplReg(r >= 0x100, r & 0xff, v);
+ }
+}
+
+void OPL::writeOplReg(int c, int r, int v) {
+ if (r == 0x04 && c == 1 && _type == Config::kOpl3) {
+ snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_CONNECTION, reinterpret_cast<void *>(v & 0x3f));
+ } else if (r == 0x08 && c == 0) {
+ _params.kbd_split = (v >> 6) & 0x1;
+ snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_PARAMS, (void *)&_params);
+ } else if (r == 0xbd && c == 0) {
+ _params.hihat = v & 0x1;
+ _params.cymbal = (v >> 1) & 0x1;
+ _params.tomtom = (v >> 2) & 0x1;
+ _params.snare = (v >> 3) & 0x1;
+ _params.bass = (v >> 4) & 0x1;
+ _params.rhythm = (v >> 5) & 0x1;
+ _params.vib_depth = (v >> 6) & 0x1;
+ _params.am_depth = (v >> 7) & 0x1;
+ snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_PARAMS, (void *)&_params);
+ } else if (r < 0xa0 || r >= 0xe0) {
+ // Operator
+ int idx = regOffsetToOper[r & 0x1f];
+
+ if (idx == -1)
+ return;
+
+ if (c == 1)
+ idx += kOpl2Operators;
+
+ switch (r & 0xf0) {
+ case 0x20:
+ case 0x30:
+ _oper[idx].harmonic = v & 0xf;
+ _oper[idx].kbd_scale = (v >> 4) & 0x1;
+ _oper[idx].do_sustain = (v >> 5) & 0x1;
+ _oper[idx].vibrato = (v >> 6) & 0x1;
+ _oper[idx].am = (v >> 7) & 0x1;
+ snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_VOICE, (void *)&_oper[idx]);
+ break;
+ case 0x40:
+ case 0x50:
+ _oper[idx].volume = ~v & 0x3f;
+ _oper[idx].scale_level = (v >> 6) & 0x3;
+ snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_VOICE, (void *)&_oper[idx]);
+ break;
+ case 0x60:
+ case 0x70:
+ _oper[idx].decay = v & 0xf;
+ _oper[idx].attack = (v >> 4) & 0xf;
+ snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_VOICE, (void *)&_oper[idx]);
+ break;
+ case 0x80:
+ case 0x90:
+ _oper[idx].release = v & 0xf;
+ _oper[idx].sustain = (v >> 4) & 0xf;
+ snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_VOICE, (void *)&_oper[idx]);
+ break;
+ case 0xe0:
+ case 0xf0:
+ _oper[idx].waveform = v & (_type == Config::kOpl3 ? 0x7 : 0x3);
+ snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_VOICE, (void *)&_oper[idx]);
+ }
+ } else {
+ // Voice
+ int idx = r & 0xf;
+
+ if (idx >= kOpl2Voices)
+ return;
+
+ if (c == 1)
+ idx += kOpl2Voices;
+
+ int opIdx = voiceToOper0[idx];
+
+ switch (r & 0xf0) {
+ case 0xa0:
+ _voice[idx].fnum = (_voice[idx].fnum & 0x300) | (v & 0xff);
+ snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_PLAY_NOTE, (void *)&_voice[idx]);
+ break;
+ case 0xb0:
+ _voice[idx].fnum = ((v << 8) & 0x300) | (_voice[idx].fnum & 0xff);
+ _voice[idx].octave = (v >> 2) & 0x7;
+ _voice[idx].key_on = (v >> 5) & 0x1;
+ snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_PLAY_NOTE, (void *)&_voice[idx]);
+ break;
+ case 0xc0:
+ _oper[opIdx].connection = _oper[opIdx + 3].connection = v & 0x1;
+ _oper[opIdx].feedback = _oper[opIdx + 3].feedback = (v >> 1) & 0x7;
+ if (_type == Config::kOpl3) {
+ _oper[opIdx].left = _oper[opIdx + 3].left = (v >> 4) & 0x1;
+ _oper[opIdx].right = _oper[opIdx + 3].right = (v >> 5) & 0x1;
+ }
+ snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_VOICE, (void *)&_oper[opIdx]);
+ }
+ }
+}
+
+OPL *create(Config::OplType type) {
+ return new OPL(type);
+}
+
+} // End of namespace ALSA
+} // End of namespace OPL
diff --git a/audio/module.mk b/audio/module.mk
index 7743c49..9e002d5 100644
--- a/audio/module.mk
+++ b/audio/module.mk
@@ -60,7 +60,7 @@ MODULE_OBJS := \
ifdef USE_ALSA
MODULE_OBJS += \
- softsynth/opl/alsa.o
+ alsa_opl.o
endif
ifndef USE_ARM_SOUND_ASM
diff --git a/audio/softsynth/opl/alsa.cpp b/audio/softsynth/opl/alsa.cpp
deleted file mode 100644
index 6b9e48e..0000000
--- a/audio/softsynth/opl/alsa.cpp
+++ /dev/null
@@ -1,349 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-/* OPL implementation for hardware OPL using ALSA Direct FM API.
- *
- * Caveats and limitations:
- * - Pretends to be a softsynth (emitting silence).
- * - Dual OPL2 mode requires OPL3 hardware.
- * - Every register write leads to a series of register writes on the hardware,
- * due to the lack of direct register access in the ALSA Direct FM API.
- * - No timers
- */
-
-#define FORBIDDEN_SYMBOL_ALLOW_ALL
-#include "common/scummsys.h"
-
-#include "common/debug.h"
-#include "common/str.h"
-#include "audio/fmopl.h"
-
-#include <sys/ioctl.h>
-#include <alsa/asoundlib.h>
-#include <sound/asound_fm.h>
-
-namespace OPL {
-namespace ALSA {
-
-class OPL : public ::OPL::RealOPL {
-private:
- enum {
- kOpl2Voices = 9,
- kVoices = 18,
- kOpl2Operators = 18,
- kOperators = 36
- };
-
- Config::OplType _type;
- int _iface;
- snd_hwdep_t *_opl;
- snd_dm_fm_voice _oper[kOperators];
- snd_dm_fm_note _voice[kVoices];
- snd_dm_fm_params _params;
- int index[2];
- static const int voiceToOper0[kVoices];
- static const int regOffsetToOper[0x20];
-
- void writeOplReg(int c, int r, int v);
- void clear();
-
-public:
- OPL(Config::OplType type);
- ~OPL();
-
- bool init();
- void reset();
-
- void write(int a, int v);
- byte read(int a);
-
- void writeReg(int r, int v);
-};
-
-const int OPL::voiceToOper0[OPL::kVoices] =
- { 0, 1, 2, 6, 7, 8, 12, 13, 14, 18, 19, 20, 24, 25, 26, 30, 31, 32 };
-
-const int OPL::regOffsetToOper[0x20] =
- { 0, 1, 2, 3, 4, 5, -1, -1, 6, 7, 8, 9, 10, 11, -1, -1,
- 12, 13, 14, 15, 16, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
-
-OPL::OPL(Config::OplType type) : _type(type), _opl(nullptr), _iface(0) {
-}
-
-OPL::~OPL() {
- stop();
-
- if (_opl) {
- snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_RESET, nullptr);
- snd_hwdep_close(_opl);
- }
-}
-
-void OPL::clear() {
- index[0] = index[1] = 0;
-
- memset(_oper, 0, sizeof(_oper));
- memset(_voice, 0, sizeof(_voice));
- memset(&_params, 0, sizeof(_params));
-
- for (int i = 0; i < kOperators; ++i) {
- _oper[i].op = (i / 3) % 2;
- _oper[i].voice = (i / 6) * 3 + (i % 3);
- }
-
- for (int i = 0; i < kVoices; ++i)
- _voice[i].voice = i;
-
- // For OPL3 hardware we need to set up the panning in OPL2 modes
- if (_iface == SND_HWDEP_IFACE_OPL3) {
- if (_type == Config::kDualOpl2) {
- for (int i = 0; i < kOpl2Operators; ++i)
- _oper[i].left = 1; // FIXME below
- for (int i = kOpl2Operators; i < kOperators; ++i)
- _oper[i].right = 1;
- } else if (_type == Config::kOpl2) {
- for (int i = 0; i < kOpl2Operators; ++i) {
- _oper[i].left = 1;
- _oper[i].right = 1;
- }
- }
- }
-}
-
-bool OPL::init() {
- clear();
-
- int card = -1;
- snd_ctl_t *ctl;
- snd_hwdep_info_t *info;
- snd_hwdep_info_alloca(&info);
-
- int iface = SND_HWDEP_IFACE_OPL3;
- if (_type == Config::kOpl2)
- iface = SND_HWDEP_IFACE_OPL2;
-
- // Look for OPL hwdep interface
- while (!snd_card_next(&card) && card >= 0) {
- int dev = -1;
- Common::String name = Common::String::format("hw:%d", card);
-
- if (snd_ctl_open(&ctl, name.c_str(), 0) < 0)
- continue;
-
- while (!snd_ctl_hwdep_next_device(ctl, &dev) && dev >= 0) {
- name = Common::String::format("hw:%d,%d", card, dev);
-
- if (snd_hwdep_open(&_opl, name.c_str(), SND_HWDEP_OPEN_WRITE) < 0)
- continue;
-
- if (!snd_hwdep_info(_opl, info)) {
- int found = snd_hwdep_info_get_iface(info);
- // OPL3 can be used for (Dual) OPL2 mode
- if (found == iface || found == SND_HWDEP_IFACE_OPL3) {
- snd_ctl_close(ctl);
- _iface = found;
- reset();
- return true;
- }
- }
-
- // Wrong interface, try next device
- snd_hwdep_close(_opl);
- _opl = nullptr;
- }
-
- snd_ctl_close(ctl);
- }
-
- return false;
-}
-
-void OPL::reset() {
- snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_RESET, nullptr);
- if (_iface == SND_HWDEP_IFACE_OPL3)
- snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_MODE, (void *)SNDRV_DM_FM_MODE_OPL3);
-
- clear();
-
- // Sync up with the hardware
- snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_PARAMS, (void *)&_params);
- for (uint i = 0; i < (_iface == SND_HWDEP_IFACE_OPL3 ? kVoices : kOpl2Voices); ++i)
- snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_PLAY_NOTE, (void *)&_voice[i]);
- for (uint i = 0; i < (_iface == SND_HWDEP_IFACE_OPL3 ? kOperators : kOpl2Operators); ++i)
- snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_VOICE, (void *)&_oper[i]);
-}
-
-void OPL::write(int port, int val) {
- val &= 0xff;
- int chip = (port & 2) >> 1;
-
- if (port & 1) {
- switch(_type) {
- case Config::kOpl2:
- writeOplReg(0, index[0], val);
- break;
- case Config::kDualOpl2:
- if (port & 8) {
- writeOplReg(0, index[0], val);
- writeOplReg(1, index[1], val);
- } else
- writeOplReg(chip, index[chip], val);
- break;
- case Config::kOpl3:
- writeOplReg(chip, index[chip], val);
- }
- } else {
- switch(_type) {
- case Config::kOpl2:
- index[0] = val;
- break;
- case Config::kDualOpl2:
- if (port & 8) {
- index[0] = val;
- index[1] = val;
- } else
- index[chip] = val;
- break;
- case Config::kOpl3:
- index[chip] = val;
- }
- }
-}
-
-byte OPL::read(int port) {
- return 0;
-}
-
-void OPL::writeReg(int r, int v) {
- switch (_type) {
- case Config::kOpl2:
- writeOplReg(0, r, v);
- break;
- case Config::kDualOpl2:
- writeOplReg(0, r, v);
- writeOplReg(1, r, v);
- break;
- case Config::kOpl3:
- writeOplReg(r >= 0x100, r & 0xff, v);
- }
-}
-
-void OPL::writeOplReg(int c, int r, int v) {
- if (r == 0x04 && c == 1 && _type == Config::kOpl3) {
- snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_CONNECTION, reinterpret_cast<void *>(v & 0x3f));
- } else if (r == 0x08 && c == 0) {
- _params.kbd_split = (v >> 6) & 0x1;
- snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_PARAMS, (void *)&_params);
- } else if (r == 0xbd && c == 0) {
- _params.hihat = v & 0x1;
- _params.cymbal = (v >> 1) & 0x1;
- _params.tomtom = (v >> 2) & 0x1;
- _params.snare = (v >> 3) & 0x1;
- _params.bass = (v >> 4) & 0x1;
- _params.rhythm = (v >> 5) & 0x1;
- _params.vib_depth = (v >> 6) & 0x1;
- _params.am_depth = (v >> 7) & 0x1;
- snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_PARAMS, (void *)&_params);
- } else if (r < 0xa0 || r >= 0xe0) {
- // Operator
- int idx = regOffsetToOper[r & 0x1f];
-
- if (idx == -1)
- return;
-
- if (c == 1)
- idx += kOpl2Operators;
-
- switch (r & 0xf0) {
- case 0x20:
- case 0x30:
- _oper[idx].harmonic = v & 0xf;
- _oper[idx].kbd_scale = (v >> 4) & 0x1;
- _oper[idx].do_sustain = (v >> 5) & 0x1;
- _oper[idx].vibrato = (v >> 6) & 0x1;
- _oper[idx].am = (v >> 7) & 0x1;
- snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_VOICE, (void *)&_oper[idx]);
- break;
- case 0x40:
- case 0x50:
- _oper[idx].volume = ~v & 0x3f;
- _oper[idx].scale_level = (v >> 6) & 0x3;
- snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_VOICE, (void *)&_oper[idx]);
- break;
- case 0x60:
- case 0x70:
- _oper[idx].decay = v & 0xf;
- _oper[idx].attack = (v >> 4) & 0xf;
- snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_VOICE, (void *)&_oper[idx]);
- break;
- case 0x80:
- case 0x90:
- _oper[idx].release = v & 0xf;
- _oper[idx].sustain = (v >> 4) & 0xf;
- snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_VOICE, (void *)&_oper[idx]);
- break;
- case 0xe0:
- case 0xf0:
- _oper[idx].waveform = v & (_type == Config::kOpl3 ? 0x7 : 0x3);
- snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_VOICE, (void *)&_oper[idx]);
- }
- } else {
- // Voice
- int idx = r & 0xf;
-
- if (idx >= kOpl2Voices)
- return;
-
- if (c == 1)
- idx += kOpl2Voices;
-
- int opIdx = voiceToOper0[idx];
-
- switch (r & 0xf0) {
- case 0xa0:
- _voice[idx].fnum = (_voice[idx].fnum & 0x300) | (v & 0xff);
- snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_PLAY_NOTE, (void *)&_voice[idx]);
- break;
- case 0xb0:
- _voice[idx].fnum = ((v << 8) & 0x300) | (_voice[idx].fnum & 0xff);
- _voice[idx].octave = (v >> 2) & 0x7;
- _voice[idx].key_on = (v >> 5) & 0x1;
- snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_PLAY_NOTE, (void *)&_voice[idx]);
- break;
- case 0xc0:
- _oper[opIdx].connection = _oper[opIdx + 3].connection = v & 0x1;
- _oper[opIdx].feedback = _oper[opIdx + 3].feedback = (v >> 1) & 0x7;
- if (_type == Config::kOpl3) {
- _oper[opIdx].left = _oper[opIdx + 3].left = (v >> 4) & 0x1;
- _oper[opIdx].right = _oper[opIdx + 3].right = (v >> 5) & 0x1;
- }
- snd_hwdep_ioctl(_opl, SNDRV_DM_FM_IOCTL_SET_VOICE, (void *)&_oper[opIdx]);
- }
- }
-}
-
-OPL *create(Config::OplType type) {
- return new OPL(type);
-}
-
-} // End of namespace ALSA
-} // End of namespace OPL
Commit: dbc8d3c530dd12cbe2cea4d9099f0ec05fedf6d0
https://github.com/scummvm/scummvm/commit/dbc8d3c530dd12cbe2cea4d9099f0ec05fedf6d0
Author: clone2727 (clone2727 at gmail.com)
Date: 2015-07-09T01:32:53-04:00
Commit Message:
Merge pull request #600 from clone2727/opl_alsa
Add support for OPL output through ALSA
Changed paths:
A audio/adlib.cpp
A audio/alsa_opl.cpp
A engines/queen/midiadlib.h
R audio/softsynth/adlib.cpp
audio/fmopl.cpp
audio/fmopl.h
audio/miles_adlib.cpp
audio/module.mk
audio/softsynth/opl/dosbox.cpp
audio/softsynth/opl/dosbox.h
audio/softsynth/opl/mame.cpp
audio/softsynth/opl/mame.h
configure
engines/agos/drivers/accolade/adlib.cpp
engines/cine/sound.cpp
engines/cruise/sound.cpp
engines/gob/gob.cpp
engines/gob/sound/adlib.cpp
engines/gob/sound/adlib.h
engines/gob/sound/adlplayer.cpp
engines/gob/sound/adlplayer.h
engines/gob/sound/musplayer.cpp
engines/gob/sound/musplayer.h
engines/gob/sound/sound.cpp
engines/gob/sound/sound.h
engines/kyra/sound_adlib.cpp
engines/mads/nebular/sound_nebular.cpp
engines/mads/nebular/sound_nebular.h
engines/mads/sound.cpp
engines/mads/sound.h
engines/parallaction/adlib.cpp
engines/queen/midiadlib.cpp
engines/queen/music.cpp
engines/sci/sound/drivers/adlib.cpp
engines/scumm/players/player_ad.cpp
engines/scumm/players/player_ad.h
engines/sherlock/scalpel/drivers/adlib.cpp
engines/sky/music/adlibchannel.cpp
engines/sky/music/adlibchannel.h
engines/sky/music/adlibmusic.cpp
engines/sky/music/adlibmusic.h
engines/tsage/sound.cpp
engines/tsage/sound.h
gui/options.cpp
More information about the Scummvm-git-logs
mailing list