diff options
-rw-r--r-- | base/gameDetector.cpp | 10 | ||||
-rw-r--r-- | doc/05_01.tex | 5 | ||||
-rw-r--r-- | doc/07_03.tex | 30 | ||||
-rw-r--r-- | doc/08.tex | 6 | ||||
-rw-r--r-- | gui/launcher.cpp | 31 | ||||
-rw-r--r-- | gui/options.cpp | 87 | ||||
-rw-r--r-- | gui/options.h | 10 | ||||
-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 | ||||
-rw-r--r-- | sound/mididrv.h | 2 |
13 files changed, 320 insertions, 36 deletions
diff --git a/base/gameDetector.cpp b/base/gameDetector.cpp index bd0920a9ab..c7fb0aceb8 100644 --- a/base/gameDetector.cpp +++ b/base/gameDetector.cpp @@ -92,10 +92,11 @@ static const char USAGE_STRING[] = " --platform=WORD Specify version of game (allowed values: amiga,\n" " atari, fmtowns, nes, mac, pc, windows)\n" " --savepath=PATH Path to where savegames are stored\n" - " --soundfont=FILE Select the SoundFont for MIDI playback. (Only\n" - " supported by some MIDI drivers.)\n" + " --soundfont=FILE Select the SoundFont for MIDI playback (Only\n" + " supported by some MIDI drivers)\n" " --multi-midi Enable combination Adlib and native MIDI\n" " --native-mt32 True Roland MT-32 (disable GM emulation)\n" + " --enable-gs Enable Roland GS mode for MIDI playback\n" " --output-rate=RATE Select output sample rate in Hz (e.g. 22050)\n" " --aspect-ratio Enable aspect ratio correction\n" " --render-mode=MODE Enable additional render modes (cga, ega, hercGreen,\n" @@ -136,6 +137,7 @@ GameDetector::GameDetector() { ConfMan.registerDefault("multi_midi", false); ConfMan.registerDefault("native_mt32", false); + ConfMan.registerDefault("enable_gs", false); // ConfMan.registerDefault("music_driver", ???); ConfMan.registerDefault("cdrom", 0); @@ -486,6 +488,10 @@ void GameDetector::parseCommandLine(int argc, char **argv) { ConfMan.set("native_mt32", cmdValue, kTransientDomain); END_OPTION + DO_LONG_OPTION_BOOL("enable-gs") + ConfMan.set("enable_gs", cmdValue, kTransientDomain); + END_OPTION + DO_LONG_OPTION_BOOL("aspect-ratio") ConfMan.set("aspect_ratio", cmdValue, kTransientDomain); END_OPTION diff --git a/doc/05_01.tex b/doc/05_01.tex index 2afc462e53..ebd671b7a6 100644 --- a/doc/05_01.tex +++ b/doc/05_01.tex @@ -36,9 +36,10 @@ Usage: scummvm [OPTIONS]... [GAME]\\ &atari, fmtowns, mac, pc, windows)\\ --savepath=PATH &Path to where savegames are stored\\ --multi-midi &Enable combination of Adlib and native MIDI\\ - --soundfont &Select the SoundFont for MIDI playback. (Only\\ - &supported by some MIDI drivers.)\\ + --soundfont &Select the SoundFont for MIDI playback (Only\\ + &supported by some MIDI drivers)\\ --native-mt32 &True Roland MT-32 (disable GM emulation)\\ + --enable-gs &Enable Roland GS mode for MIDI playback\\ --output-rate=RATE &Select output sample rate in Hz (e.g. 22050)\\ --aspect-ratio &Enable aspect ratio correction\\ --render-mode=MODE &Enable additional render modes (cga, ega, hercGreen, hercAmber, amiga)\\ diff --git a/doc/07_03.tex b/doc/07_03.tex index 347a2bd427..bd754bf9ee 100644 --- a/doc/07_03.tex +++ b/doc/07_03.tex @@ -9,3 +9,33 @@ Use the appropriate -e<mode> command line option from the list above to select your preferred MIDI device. For example, if you wish to use the Windows MIDI driver, use the -ewindows option. + +\subsubsection{Using MIDI options to customize Native MIDI output} +ScummVM supports a variety of MIDI modes, depending on the capabilities +of your MIDI device. + +If --native-mt32 is specified, ScummVM will treat your device as a real +MT-32. Because the instrument mappings and system exclusive commands of +the MT-32 vary from those of General MIDI devices, you should only +enable this option if you are using an actual Roland MT-32, LAPC-I, CM-64, +CM-32L, CM-500, or GS device with an MT-32 map. + +If --enable-gs is specified, ScummVM will initialize your GS-compatible +device with settings that mimic the MT-32's reverb, (lack of) chorus, +pitch bend sensitivity, etc. If it is specified in conjunction with +--native-mt32, ScummVM will select the MT-32-compatible map and drumset on +your GS device. This setting works better than default GM or GS emulation +with games that do not have custom instrument mappings (Loom and Monkey1). +You should only specify both settings if you are using a GS device that +has an MT-32 map, such as an SC-55, SC-88, SC-88 Pro, SC-8820, SC-8850, etc. +Please note that --enable-gs is automatically disabled in both DOTT and +Samnmax, since they use General MIDI natively. + +If neither of the above settings is enabled, ScummVM will initialize your +device in General MIDI mode and use GM emulation in games with MT-32 +soundtracks. + +Some games contain sound effects that are exclusive to the Adlib soundtrack. +For these games, you may wish to specify --multi-midi in order to combine +MIDI music with Adlib sound effects. + diff --git a/doc/08.tex b/doc/08.tex index 56e829415d..84cdf3285f 100644 --- a/doc/08.tex +++ b/doc/08.tex @@ -102,11 +102,15 @@ The following keywords are recognized: & supported by some MIDI drivers.)\\ native\_mt32 &bool If true, disable GM emulation and assume that\\ & there is a true Roland MT-32 available.\\ + enable\_gs &bool If true, enable Roland GS-specific features to\\ + & enhance GM emulation. If native\_mt32 is also\\ + & true, the GS device will select an MT-32 map\\ + & to play the correct instruments.\\ sfx\_volume &number The sfx volume setting (0-255)\\ tempo &number The music tempo (50-200) (default: 100)\\ speech\_volume &number The speech volume setting (0-255)\\ \\ - copy\_protection&bool Enable copy protection in SCUMM games ,when\\ + copy\_protection&bool Enable copy protection in SCUMM games, when\\ & ScummVM disables it by default.\\ demo\_mode &bool Start demo in Maniac Mansion\\ alt\_intro &bool Use alternative intro for CD versions of \\ diff --git a/gui/launcher.cpp b/gui/launcher.cpp index e9b784ef45..67b562dfd8 100644 --- a/gui/launcher.cpp +++ b/gui/launcher.cpp @@ -61,6 +61,7 @@ enum { kCmdGlobalGraphicsOverride = 'OGFX', kCmdGlobalAudioOverride = 'OSFX', + kCmdGlobalMIDIOverride = 'OMID', kCmdGlobalVolumeOverride = 'OVOL', kCmdExtraBrowser = 'PEXT', @@ -128,6 +129,7 @@ protected: CheckboxWidget *_globalGraphicsOverride; CheckboxWidget *_globalAudioOverride; + CheckboxWidget *_globalMIDIOverride; CheckboxWidget *_globalVolumeOverride; }; @@ -215,7 +217,7 @@ EditGameDialog::EditGameDialog(const String &domain, GameSettings target) yoffset += 18; // - // 2) The graphics tab + // 3) The graphics tab // tab->addTab("Gfx"); yoffset = vBorder; @@ -226,7 +228,7 @@ EditGameDialog::EditGameDialog(const String &domain, GameSettings target) yoffset = addGraphicControls(tab, yoffset); // - // 3) The audio tab + // 4) The audio tab // tab->addTab("Audio"); yoffset = vBorder; @@ -234,10 +236,21 @@ EditGameDialog::EditGameDialog(const String &domain, GameSettings target) _globalAudioOverride = new CheckboxWidget(tab, x, yoffset, w, 16, "Override global audio settings", kCmdGlobalAudioOverride); yoffset += 16; + yoffset = addAudioControls(tab, yoffset); + + // + // 5) The MIDI tab + // + tab->addTab("MIDI"); + yoffset = vBorder; + + _globalMIDIOverride = new CheckboxWidget(tab, x, yoffset, w, 16, "Override global MIDI settings", kCmdGlobalMIDIOverride); + yoffset += 16; + yoffset = addMIDIControls(tab, yoffset); // - // 3) The volume tab + // 6) The volume tab // tab->addTab("Volume"); yoffset = vBorder; @@ -269,10 +282,14 @@ void EditGameDialog::open() { _globalGraphicsOverride->setState(e); e = ConfMan.hasKey("music_driver", _domain) || - ConfMan.hasKey("multi_midi", _domain) || - ConfMan.hasKey("native_mt32", _domain); + ConfMan.hasKey("subtitles", _domain); _globalAudioOverride->setState(e); + e = ConfMan.hasKey("multi_midi", _domain) || + ConfMan.hasKey("native_mt32", _domain)|| + ConfMan.hasKey("enable_gs", _domain); + _globalMIDIOverride->setState(e); + e = ConfMan.hasKey("music_volume", _domain) || ConfMan.hasKey("sfx_volume", _domain) || ConfMan.hasKey("speech_volume", _domain); @@ -342,6 +359,10 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat setAudioSettingsState(data != 0); draw(); break; + case kCmdGlobalMIDIOverride: + setMIDISettingsState(data != 0); + draw(); + break; case kCmdGlobalVolumeOverride: setVolumeSettingsState(data != 0); draw(); diff --git a/gui/options.cpp b/gui/options.cpp index 040fafc9d0..1544730c89 100644 --- a/gui/options.cpp +++ b/gui/options.cpp @@ -78,7 +78,9 @@ OptionsDialog::OptionsDialog(const String &domain, int x, int y, int w, int h) _enableGraphicSettings(false), _gfxPopUp(0), _renderModePopUp(0), _fullscreenCheckbox(0), _aspectCheckbox(0), _enableAudioSettings(false), - _multiMidiCheckbox(0), _mt32Checkbox(0), _subCheckbox(0), + _subCheckbox(0), + _enableMIDISettings(false), + _multiMidiCheckbox(0), _mt32Checkbox(0), _enableGSCheckbox(0), _enableVolumeSettings(false), _musicVolumeSlider(0), _musicVolumeLabel(0), _sfxVolumeSlider(0), _sfxVolumeLabel(0), @@ -131,7 +133,7 @@ void OptionsDialog::open() { #endif } - if (_multiMidiCheckbox) { + if (_subCheckbox) { // Music driver const MidiDriverDescription *md = MidiDriver::getAvailableMidiDrivers(); int i = 0; @@ -145,15 +147,22 @@ void OptionsDialog::open() { } _midiPopUp->setSelected(md->name ? i : 0); + // Subtitles setting + _subCheckbox->setState(ConfMan.getBool("subtitles", _domain)); + } + + if (_multiMidiCheckbox) { + // Multi midi setting _multiMidiCheckbox->setState(ConfMan.getBool("multi_midi", _domain)); // Native mt32 setting _mt32Checkbox->setState(ConfMan.getBool("native_mt32", _domain)); - // Subtitles setting - _subCheckbox->setState(ConfMan.getBool("subtitles", _domain)); + // GS extensions setting + _enableGSCheckbox->setState(ConfMan.getBool("enable_gs", _domain)); } + if (_musicVolumeSlider) { int vol; @@ -204,10 +213,8 @@ void OptionsDialog::close() { } } - if (_multiMidiCheckbox) { + if (_subCheckbox) { if (_enableAudioSettings) { - ConfMan.set("multi_midi", _multiMidiCheckbox->getState(), _domain); - ConfMan.set("native_mt32", _mt32Checkbox->getState(), _domain); ConfMan.set("subtitles", _subCheckbox->getState(), _domain); const MidiDriverDescription *md = MidiDriver::getAvailableMidiDrivers(); while (md->name && md->id != (int)_midiPopUp->getSelectedTag()) @@ -217,13 +224,23 @@ void OptionsDialog::close() { else ConfMan.removeKey("music_driver", _domain); } else { - ConfMan.removeKey("multi_midi", _domain); - ConfMan.removeKey("native_mt32", _domain); ConfMan.removeKey("music_driver", _domain); ConfMan.removeKey("subtitles", _domain); } } + if (_multiMidiCheckbox) { + if (_enableMIDISettings) { + ConfMan.set("multi_midi", _multiMidiCheckbox->getState(), _domain); + ConfMan.set("native_mt32", _mt32Checkbox->getState(), _domain); + ConfMan.set("enable_gs", _enableGSCheckbox->getState(), _domain); + } else { + ConfMan.removeKey("multi_midi", _domain); + ConfMan.removeKey("native_mt32", _domain); + ConfMan.removeKey("enable_gs", _domain); + } + } + // Save config file ConfMan.flushToDisk(); } @@ -269,9 +286,15 @@ void OptionsDialog::setAudioSettingsState(bool enabled) { _enableAudioSettings = enabled; _midiPopUp->setEnabled(enabled); + _subCheckbox->setEnabled(enabled); +} + +void OptionsDialog::setMIDISettingsState(bool enabled) { + _enableMIDISettings = enabled; + _multiMidiCheckbox->setEnabled(enabled); _mt32Checkbox->setEnabled(enabled); - _subCheckbox->setEnabled(enabled); + _enableGSCheckbox->setEnabled(enabled); } void OptionsDialog::setVolumeSettingsState(bool enabled) { @@ -330,13 +353,13 @@ int OptionsDialog::addGraphicControls(GuiObject *boss, int yoffset) { return yoffset; } -int OptionsDialog::addMIDIControls(GuiObject *boss, int yoffset) { +int OptionsDialog::addAudioControls(GuiObject *boss, int yoffset) { const int x = 10; const int w = _w - 20; // The MIDI mode popup & a label _midiPopUp = new PopUpWidget(boss, x-5, yoffset, w+5, kLineHeight, "Music driver: ", 100); - yoffset += 16; + yoffset += 18; // Populate it const MidiDriverDescription *md = MidiDriver::getAvailableMidiDrivers(); @@ -345,25 +368,39 @@ int OptionsDialog::addMIDIControls(GuiObject *boss, int yoffset) { md++; } + // Subtitles on/off + _subCheckbox = new CheckboxWidget(boss, x, yoffset, w, 16, "Display subtitles"); + yoffset += 16; + + yoffset += 18; + + _enableAudioSettings = true; + + return yoffset; +} + +int OptionsDialog::addMIDIControls(GuiObject *boss, int yoffset) { + const int x = 10; + const int w = _w - 20; + // SoundFont new ButtonWidget(boss, x, yoffset, kButtonWidth + 14, 16, "SoundFont: ", kChooseSoundFontCmd, 0); _soundFont = new StaticTextWidget(boss, x + kButtonWidth + 20, yoffset + 3, _w - (x + kButtonWidth + 20) - 10, kLineHeight, "None", kTextAlignLeft); - yoffset += 18; - + // Multi midi setting _multiMidiCheckbox = new CheckboxWidget(boss, x, yoffset, w, 16, "Mixed Adlib/MIDI mode"); - yoffset += 15; + yoffset += 16; // Native mt32 setting _mt32Checkbox = new CheckboxWidget(boss, x, yoffset, w, 16, "True Roland MT-32 (disable GM emulation)"); - yoffset += 15; + yoffset += 16; - // Subtitles on/off - _subCheckbox = new CheckboxWidget(boss, x, yoffset, w, 16, "Display subtitles"); - yoffset += 15; + // GS Extensions setting + _enableGSCheckbox = new CheckboxWidget(boss, x, yoffset, w, 16, "Enable Roland GS Mode"); + yoffset += 16; - _enableAudioSettings = true; + _enableMIDISettings = true; return yoffset; } @@ -417,13 +454,19 @@ GlobalOptionsDialog::GlobalOptionsDialog(GameDetector &detector) // tab->addTab("Audio"); yoffset = vBorder; - yoffset = addMIDIControls(tab, yoffset); + yoffset = addAudioControls(tab, yoffset); yoffset = addVolumeControls(tab, yoffset); // TODO: cd drive setting + // + // 3) The MIDI tab + // + tab->addTab("MIDI"); + yoffset = vBorder; + yoffset = addMIDIControls(tab, yoffset); // - // 3) The miscellaneous tab + // 4) The miscellaneous tab // tab->addTab("Paths"); yoffset = vBorder; diff --git a/gui/options.h b/gui/options.h index 5797a62494..cbe6817be1 100644 --- a/gui/options.h +++ b/gui/options.h @@ -59,11 +59,13 @@ protected: StaticTextWidget *_soundFont; int addGraphicControls(GuiObject *boss, int yoffset); + int addAudioControls(GuiObject *boss, int yoffset); int addMIDIControls(GuiObject *boss, int yoffset); int addVolumeControls(GuiObject *boss, int yoffset); void setGraphicSettingsState(bool enabled); void setAudioSettingsState(bool enabled); + void setMIDISettingsState(bool enabled); void setVolumeSettingsState(bool enabled); private: @@ -81,9 +83,15 @@ private: // bool _enableAudioSettings; PopUpWidget *_midiPopUp; + CheckboxWidget *_subCheckbox; + + // + // MIDI controls + // + bool _enableMIDISettings; CheckboxWidget *_multiMidiCheckbox; CheckboxWidget *_mt32Checkbox; - CheckboxWidget *_subCheckbox; + CheckboxWidget *_enableGSCheckbox; // // Volume controls 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; diff --git a/sound/mididrv.h b/sound/mididrv.h index 3f9db6a664..af538d096a 100644 --- a/sound/mididrv.h +++ b/sound/mididrv.h @@ -137,6 +137,8 @@ public: send(( 0 << 16) | (100 << 8) | (0xB0 | channel)); send((range << 16) | ( 6 << 8) | (0xB0 | channel)); send(( 0 << 16) | ( 38 << 8) | (0xB0 | channel)); + send(( 127 << 16) | (101 << 8) | (0xB0 | channel)); + send(( 127 << 16) | (100 << 8) | (0xB0 | channel)); } virtual void sysEx (byte *msg, uint16 length) { } |