diff options
Diffstat (limited to 'engines/scumm/imuse')
-rw-r--r-- | engines/scumm/imuse/imuse.cpp | 69 | ||||
-rw-r--r-- | engines/scumm/imuse/imuse.h | 2 | ||||
-rw-r--r-- | engines/scumm/imuse/imuse_internal.h | 3 | ||||
-rw-r--r-- | engines/scumm/imuse/imuse_part.cpp | 15 |
4 files changed, 51 insertions, 38 deletions
diff --git a/engines/scumm/imuse/imuse.cpp b/engines/scumm/imuse/imuse.cpp index 016ba89e7b..12ebfef9b7 100644 --- a/engines/scumm/imuse/imuse.cpp +++ b/engines/scumm/imuse/imuse.cpp @@ -46,7 +46,6 @@ namespace Scumm { IMuseInternal::IMuseInternal() : _native_mt32(false), _enable_gs(false), - _sc55(false), _midi_adlib(NULL), _midi_native(NULL), _sysex(NULL), @@ -363,7 +362,7 @@ void IMuseInternal::pause(bool paused) { _paused = paused; } -int IMuseInternal::save_or_load(Serializer *ser, ScummEngine *scumm) { +int IMuseInternal::save_or_load(Serializer *ser, ScummEngine *scumm, bool fixAfterLoad) { Common::StackLock lock(_mutex, "IMuseInternal::save_or_load()"); const SaveLoadEntry mainEntries[] = { MKLINE(IMuseInternal, _queue_end, sleUint8, VER(8)), @@ -440,7 +439,16 @@ int IMuseInternal::save_or_load(Serializer *ser, ScummEngine *scumm) { for (i = 0; i < 8; ++i) ser->saveLoadEntries(0, volumeFaderEntries); - if (ser->isLoading()) { + // Normally, we have to fix up the data structures after loading a + // saved game. But there are cases where we don't. For instance, The + // Macintosh version of Monkey Island 1 used to convert the Mac0 music + // resources to General MIDI and play it through iMUSE as a rough + // approximation. Now it has its own player, but old savegame still + // have the iMUSE data in them. We have to skip that data, using a + // dummy iMUSE object, but since the resource is no longer recognizable + // to iMUSE, the fixup fails hard. So yes, this is a bit of a hack. + + if (ser->isLoading() && fixAfterLoad) { // Load all sounds that we need fix_players_after_load(scumm); fix_parts_after_load(); @@ -486,12 +494,9 @@ uint32 IMuseInternal::property(int prop, uint32 value) { 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; + // GS Mode emulates MT-32 on a GS device, so _native_mt32 should always be true + if (_midi_native && _enable_gs) { + _native_mt32 = true; initGM(_midi_native); } break; @@ -1490,7 +1495,7 @@ void IMuseInternal::initGM(MidiDriver *midi) { if (_enable_gs) { // All GS devices recognize the GS Reset command, - // even with Roland's ID. It is impractical to + // even using 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 @@ -1504,30 +1509,28 @@ void IMuseInternal::initGM(MidiDriver *midi) { midi->sysEx(buffer, 9); debug(2, "GS SysEx: GS Reset"); _system->delayMillis(200); + + // Set global Master Tune to 442.0kHz, as on the MT-32 + memcpy(&buffer[4], "\x40\x00\x00\x00\x04\x04\x0F\x29", 8); + midi->sysEx(buffer, 12); + debug(2, "GS SysEx: Master Tune set to 442.0kHz"); - 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 (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"); + // Note: All Roland GS devices support CM-64/32L maps + // Set Channels 1-16 to SC-55 Map, then CM-64/32L Variation + for (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[4], "\x40\x01\x3A\x00\x05", 5); @@ -1732,10 +1735,10 @@ void IMuseInternal::copyGlobalInstrument(byte slot, Instrument *dest) { // In case we have an valid instrument set up, copy it to the part. _global_instruments[slot].copy_to(dest); } else if (_pcSpeaker) { - debug(0, "Trying to use non-existant global PC Speaker instrument %d", slot); + debug(0, "Trying to use non-existent global PC Speaker instrument %d", slot); dest->pcspk(defaultInstr); } else { - debug(0, "Trying to use non-existant global AdLib instrument %d", slot); + debug(0, "Trying to use non-existent global AdLib instrument %d", slot); dest->adlib(defaultInstr); } } diff --git a/engines/scumm/imuse/imuse.h b/engines/scumm/imuse/imuse.h index 23449e470b..cce5309229 100644 --- a/engines/scumm/imuse/imuse.h +++ b/engines/scumm/imuse/imuse.h @@ -62,7 +62,7 @@ public: public: virtual void on_timer(MidiDriver *midi) = 0; virtual void pause(bool paused) = 0; - virtual int save_or_load(Serializer *ser, ScummEngine *scumm) = 0; + virtual int save_or_load(Serializer *ser, ScummEngine *scumm, bool fixAfterLoad = true) = 0; virtual bool get_sound_active(int sound) const = 0; virtual int32 doCommand(int numargs, int args[]) = 0; virtual int clear_queue() = 0; diff --git a/engines/scumm/imuse/imuse_internal.h b/engines/scumm/imuse/imuse_internal.h index 846e2d7545..d17d4ed28b 100644 --- a/engines/scumm/imuse/imuse_internal.h +++ b/engines/scumm/imuse/imuse_internal.h @@ -390,7 +390,6 @@ class IMuseInternal : public IMuse { protected: bool _native_mt32; bool _enable_gs; - bool _sc55; MidiDriver *_midi_adlib; MidiDriver *_midi_native; TimerCallbackInfo _timer_info_adlib; @@ -518,7 +517,7 @@ protected: public: // IMuse interface void pause(bool paused); - int save_or_load(Serializer *ser, ScummEngine *scumm); + int save_or_load(Serializer *ser, ScummEngine *scumm, bool fixAfterLoad = true); bool get_sound_active(int sound) const; int32 doCommand(int numargs, int args[]); uint32 property(int prop, uint32 value); diff --git a/engines/scumm/imuse/imuse_part.cpp b/engines/scumm/imuse/imuse_part.cpp index 89c16a8bb5..5e928f3d44 100644 --- a/engines/scumm/imuse/imuse_part.cpp +++ b/engines/scumm/imuse/imuse_part.cpp @@ -111,8 +111,19 @@ void Part::saveLoadWithSerializer(Serializer *ser) { } void Part::set_detune(int8 detune) { - _detune_eff = clamp((_detune = detune) + _player->getDetune(), -128, 127); - sendPitchBend(); + // Sam&Max does not have detune, so we just ignore this here. We still get + // this called, since Sam&Max uses the same controller for a different + // purpose. + if (_se->_game_id == GID_SAMNMAX) { +#if 0 + if (_mc) { + _mc->controlChange(17, detune + 0x40); + } +#endif + } else { + _detune_eff = clamp((_detune = detune) + _player->getDetune(), -128, 127); + sendPitchBend(); + } } void Part::pitchBend(int16 value) { |