aboutsummaryrefslogtreecommitdiff
path: root/engines/scumm/imuse
diff options
context:
space:
mode:
Diffstat (limited to 'engines/scumm/imuse')
-rw-r--r--engines/scumm/imuse/imuse.cpp69
-rw-r--r--engines/scumm/imuse/imuse.h2
-rw-r--r--engines/scumm/imuse/imuse_internal.h3
-rw-r--r--engines/scumm/imuse/imuse_part.cpp15
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) {