diff options
author | Eugene Sandulenko | 2005-04-13 00:11:49 +0000 |
---|---|---|
committer | Eugene Sandulenko | 2005-04-13 00:11:49 +0000 |
commit | bdbd56406c20dfa7425a71de22999cc92065ce77 (patch) | |
tree | 0b3cc6d6c63ecac48ac9fed8170004a00cab195d /scumm | |
parent | 3536cd0aa2d9ade01d7f5bf0c19c6a573739a398 (diff) | |
download | scummvm-rg350-bdbd56406c20dfa7425a71de22999cc92065ce77.tar.gz scummvm-rg350-bdbd56406c20dfa7425a71de22999cc92065ce77.tar.bz2 scummvm-rg350-bdbd56406c20dfa7425a71de22999cc92065ce77.zip |
Patches #1164217 "Updated GS Support + Percussion Remapping Patch" and
#1181750 "Updated Native MIDI documentation". Thanks _tom a lot.
svn-id: r17571
Diffstat (limited to 'scumm')
-rw-r--r-- | scumm/imuse.cpp | 165 | ||||
-rw-r--r-- | scumm/imuse.h | 1 | ||||
-rw-r--r-- | scumm/imuse_internal.h | 3 | ||||
-rw-r--r-- | scumm/scumm.cpp | 5 | ||||
-rw-r--r-- | scumm/scumm.h | 1 |
5 files changed, 172 insertions, 3 deletions
diff --git a/scumm/imuse.cpp b/scumm/imuse.cpp index 2f12865ff1..1777eb5247 100644 --- a/scumm/imuse.cpp +++ b/scumm/imuse.cpp @@ -46,6 +46,8 @@ namespace Scumm { IMuseInternal::IMuseInternal() : _native_mt32(false), +_enable_gs(false), +_sc55(false), _midi_adlib(0), _midi_native(0), _base_sounds(0), @@ -1071,11 +1073,24 @@ uint32 IMuseInternal::property(int prop, uint32 value) { case IMuse::PROP_NATIVE_MT32: _native_mt32 = (value > 0); - Instrument::nativeMT32(value > 0); - if (value > 0 && _midi_native) + Instrument::nativeMT32(_native_mt32); + if (_midi_native && _native_mt32) initMT32(_midi_native); break; + case IMuse::PROP_GS: + _enable_gs = (value > 0); + + // If True Roland MT-32 is not selected, run in GM or GS mode. + // If it is selected, change the Roland GS synth to MT-32 mode. + if (_midi_native && !_native_mt32) + initGM(_midi_native); + else if (_midi_native && _native_mt32 && _enable_gs) { + _sc55 = true; + initGM(_midi_native); + } + break; + case IMuse::PROP_LIMIT_PLAYERS: if (value > 0 && value <= ARRAYSIZE(_players)) _player_limit = (int) value; @@ -1171,12 +1186,156 @@ void IMuseInternal::initMT32(MidiDriver *midi) { midi->sysEx(buffer, 31); g_system->delayMillis (250); - // Setup rythm part + // Map percussion to notes 24 - 34 without reverb memcpy(&buffer[4], "\x03\x01\x10\x40\x64\x07\x00\x4a\x64\x06\x00\x41\x64\x07\x00\x4b\x64\x08\x00\x45\x64\x06\x00\x44\x64\x0b\x00\x51\x64\x05\x00\x43\x64\x08\x00\x50\x64\x07\x00\x42\x64\x03\x00\x4c\x64\x07\x00\x44", 48); midi->sysEx(buffer, 52); g_system->delayMillis (250); } +void IMuseInternal::initGM(MidiDriver *midi) { + byte buffer[11]; + + // General MIDI System On message + // Resets all GM devices to default settings + memcpy(&buffer[0], "\xF0\x7E\x7F\x09\x01\xF7", 6); + midi->sysEx(buffer, 6); + debug(2, "GM SysEx: GM System On"); + g_system->delayMillis (200); + + if (_enable_gs) { + + // All GS devices recognize the GS Reset command, + // even with Roland's ID. It is impractical to + // support other manufacturers' devices for + // further GS settings, as there are limitless + // numbers of them out there that would each + // require individual SysEx commands with unique IDs. + + // Roland GS SysEx ID + memcpy(&buffer[0], "\xF0\x41\x10\x42\x12", 5); + + // GS Reset + memcpy(&buffer[5], "\x40\x00\x7F\x00\x41\xF7", 6); + midi->sysEx(buffer, 11); + debug(2, "GS SysEx: GS Reset"); + g_system->delayMillis (200); + + if (_sc55) { + + // This mode is for GS devices that support an MT-32-compatible + // Map, such as the Roland Sound Canvas line of modules. It + // will allow them to work with True MT-32 mode, but will + // obviously still ignore MT-32 SysEx (and thus custom + // instruments). + + // Set Channels 1-16 to SC-55 Map, then CM-64/32L Variation + for (int i = 0; i < 16; ++i) { + midi->send(( 127 << 16) | (0 << 8) | (0xB0 | i)); + midi->send(( 1 << 16) | (32 << 8) | (0xB0 | i)); + midi->send(( 0 << 16) | (0 << 8) | (0xC0 | i)); + } + debug(2, "GS Program Change: CM-64/32L Map Selected"); + + // Set Percussion Channel to SC-55 Map (CC#32, 01H), then + // Switch Drum Map to CM-64/32L (MT-32 Compatible Drums) + midi->getPercussionChannel()->controlChange(0, 0); + midi->getPercussionChannel()->controlChange(32, 1); + midi->send (127 << 8 | 0xC0 | 9); + debug(2, "GS Program Change: Drum Map is CM-64/32L"); + + } + + // Set Master Chorus to 0. The MT-32 has no chorus capability. + memcpy(&buffer[5], "\x40\x01\x3A\x00\x05\xF7", 6); + midi->sysEx(buffer, 11); + debug(2, "GS SysEx: Master Chorus Level is 0"); + + // Set Channels 1-16 Reverb to 64, which is the + // equivalent of MT-32 default Reverb Level 5 + for (int i = 0; i < 16; ++i) + midi->send(( 64 << 16) | (91 << 8) | (0xB0 | i)); + debug(2, "GM Controller 91 Change: Channels 1-16 Reverb Level is 64"); + + // Set Channels 1-16 Pitch Bend Sensitivity to + // 12 semitones; then lock the RPN by setting null. + for (int i = 0; i < 16; ++i) { + midi->send(( 0 << 16) | (100 << 8) | (0xB0 | i)); + midi->send(( 0 << 16) | (101 << 8) | (0xB0 | i)); + midi->send(( 12 << 16) | (6 << 8) | (0xB0 | i)); + midi->send(( 0 << 16) | (38 << 8) | (0xB0 | i)); + midi->send(( 127 << 16) | (100 << 8) | (0xB0 | i)); + midi->send(( 127 << 16) | (101 << 8) | (0xB0 | i)); + } + debug(2, "GM Controller 6 Change: Channels 1-16 Pitch Bend Sensitivity is 12 semitones"); + + // Set channels 1-16 Mod. LFO1 Pitch Depth to 4 + memcpy(&buffer[5], "\x40\x20\x04\x04\x18\xF7", 6); + midi->sysEx(buffer, 11); + memcpy(&buffer[5], "\x40\x21\x04\x04\x17\xF7", 6); + midi->sysEx(buffer, 11); + memcpy(&buffer[5], "\x40\x22\x04\x04\x16\xF7", 6); + midi->sysEx(buffer, 11); + memcpy(&buffer[5], "\x40\x23\x04\x04\x15\xF7", 6); + midi->sysEx(buffer, 11); + memcpy(&buffer[5], "\x40\x24\x04\x04\x14\xF7", 6); + midi->sysEx(buffer, 11); + memcpy(&buffer[5], "\x40\x25\x04\x04\x13\xF7", 6); + midi->sysEx(buffer, 11); + memcpy(&buffer[5], "\x40\x26\x04\x04\x12\xF7", 6); + midi->sysEx(buffer, 11); + memcpy(&buffer[5], "\x40\x27\x04\x04\x11\xF7", 6); + midi->sysEx(buffer, 11); + memcpy(&buffer[5], "\x40\x28\x04\x04\x10\xF7", 6); + midi->sysEx(buffer, 11); + memcpy(&buffer[5], "\x40\x29\x04\x04\x0F\xF7", 6); + midi->sysEx(buffer, 11); + memcpy(&buffer[5], "\x40\x2A\x04\x04\x0E\xF7", 6); + midi->sysEx(buffer, 11); + memcpy(&buffer[5], "\x40\x2B\x04\x04\x0D\xF7", 6); + midi->sysEx(buffer, 11); + memcpy(&buffer[5], "\x40\x2C\x04\x04\x0C\xF7", 6); + midi->sysEx(buffer, 11); + memcpy(&buffer[5], "\x40\x2D\x04\x04\x0B\xF7", 6); + midi->sysEx(buffer, 11); + memcpy(&buffer[5], "\x40\x2E\x04\x04\x0A\xF7", 6); + midi->sysEx(buffer, 11); + memcpy(&buffer[5], "\x40\x2F\x04\x04\x09\xF7", 6); + midi->sysEx(buffer, 11); + debug(2, "GS SysEx: Channels 1-16 Mod. LFO1 Pitch Depth Level is 4"); + + // Set Percussion Channel Expression to 80 + midi->getPercussionChannel()->controlChange(11, 80); + debug(2, "GM Controller 11 Change: Percussion Channel Expression Level is 80"); + + // Turn off Percussion Channel Rx. Expression so that + // Expression cannot be modified. I don't know why, but + // Roland does it this way. + memcpy(&buffer[5], "\x40\x10\x0E\x00\x22\xF7", 6); + midi->sysEx(buffer, 11); + debug(2, "GS SysEx: Percussion Channel Rx. Expression is OFF"); + + // Change Reverb Character to 0. I don't think this + // sounds most like MT-32, but apparently Roland does. + memcpy(&buffer[5], "\x40\x01\x31\x00\x0E\xF7", 6); + midi->sysEx(buffer, 11); + debug(2, "GS SysEx: Reverb Character is 0"); + + // Change Reverb Pre-LF to 4, which is similar to + // what MT-32 reverb does. + memcpy(&buffer[5], "\x40\x01\x32\x04\x09\xF7", 6); + midi->sysEx(buffer, 11); + debug(2, "GS SysEx: Reverb Pre-LF is 4"); + + // Change Reverb Time to 106; the decay on Hall 2 + // Reverb is too fast compared to the MT-32's + memcpy(&buffer[5], "\x40\x01\x34\x6A\x21\xF7", 6); + midi->sysEx(buffer, 11); + debug(2, "GS SysEx: Reverb Time is 106"); + + } + +} + void IMuseInternal::init_queue() { _queue_adding = false; _queue_pos = 0; diff --git a/scumm/imuse.h b/scumm/imuse.h index a9da34247b..cb78db7b5f 100644 --- a/scumm/imuse.h +++ b/scumm/imuse.h @@ -52,6 +52,7 @@ public: enum { PROP_TEMPO_BASE, PROP_NATIVE_MT32, + PROP_GS, PROP_LIMIT_PLAYERS, PROP_RECYCLE_PLAYERS, PROP_DIRECT_PASSTHROUGH diff --git a/scumm/imuse_internal.h b/scumm/imuse_internal.h index 04414ead08..a0e05db9fb 100644 --- a/scumm/imuse_internal.h +++ b/scumm/imuse_internal.h @@ -346,6 +346,8 @@ class IMuseInternal { protected: bool _native_mt32; + bool _enable_gs; + bool _sc55; MidiDriver *_midi_adlib; MidiDriver *_midi_native; @@ -392,6 +394,7 @@ protected: void handle_marker(uint id, byte data); int get_channel_volume(uint a); void initMidiDriver(MidiDriver *midi); + void initGM(MidiDriver *midi); void initMT32(MidiDriver *midi); void init_players(); void init_parts(); diff --git a/scumm/scumm.cpp b/scumm/scumm.cpp index 98d968a8c7..bacc0a1020 100644 --- a/scumm/scumm.cpp +++ b/scumm/scumm.cpp @@ -1672,6 +1672,10 @@ void ScummEngine_v99he::scummInit() { void ScummEngine::setupMusic(int midi) { _midiDriver = MidiDriver::detectMusicDriver(midi); _native_mt32 = (ConfMan.getBool("native_mt32") || (_midiDriver == MD_MT32)); + if ((_gameId == GID_TENTACLE) || (_gameId == GID_SAMNMAX)) + _enable_gs = false; + else + _enable_gs = ConfMan.getBool("enable_gs"); #ifndef __GP32__ //ph0x FIXME, "quick dirty hack" /* Bind the mixer to the system => mixer will be invoked @@ -1720,6 +1724,7 @@ void ScummEngine::setupMusic(int midi) { if (ConfMan.hasKey("tempo")) _imuse->property(IMuse::PROP_TEMPO_BASE, ConfMan.getInt("tempo")); _imuse->property(IMuse::PROP_NATIVE_MT32, _native_mt32); + _imuse->property(IMuse::PROP_GS, _enable_gs); if (_features & GF_HUMONGOUS || midi == MDT_TOWNS) { _imuse->property(IMuse::PROP_LIMIT_PLAYERS, 1); _imuse->property(IMuse::PROP_RECYCLE_PLAYERS, 1); diff --git a/scumm/scumm.h b/scumm/scumm.h index b8e2ed8e11..fd80ab2118 100644 --- a/scumm/scumm.h +++ b/scumm/scumm.h @@ -1111,6 +1111,7 @@ protected: int _tempMusic; int _saveSound; bool _native_mt32; + bool _enable_gs; int _midi; int _midiDriver; // Use the MD_ values from mididrv.h bool _copyProtection; |