From f0c1d8dcc46b77895ad85b3cdaaf3b81e497b0d8 Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Fri, 16 Nov 2012 07:49:17 +0100 Subject: SCUMM: Add hack to preserve savegame compatibility with Mac MI1 For old savegames, we now use a "dummy" iMUSE objet to skip the old iMUSE save state. I had hoped to be able to do this without making any changes to the iMUSE code itself, but I was unable to. Also added note about how the save state for the new music will not quite work if the mixer output rate changes. Personally, I'm not too worried about that. It breaks, but it shouldn't break badly. --- engines/scumm/imuse/imuse.cpp | 13 +++++++++++-- engines/scumm/imuse/imuse.h | 2 +- engines/scumm/imuse/imuse_internal.h | 2 +- engines/scumm/player_mac.cpp | 10 +++++++++- 4 files changed, 22 insertions(+), 5 deletions(-) (limited to 'engines/scumm') diff --git a/engines/scumm/imuse/imuse.cpp b/engines/scumm/imuse/imuse.cpp index 016ba89e7b..b69ce552bc 100644 --- a/engines/scumm/imuse/imuse.cpp +++ b/engines/scumm/imuse/imuse.cpp @@ -363,7 +363,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 +440,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(); 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..6be564a517 100644 --- a/engines/scumm/imuse/imuse_internal.h +++ b/engines/scumm/imuse/imuse_internal.h @@ -518,7 +518,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/player_mac.cpp b/engines/scumm/player_mac.cpp index 7b0f671f6d..cd1df51938 100644 --- a/engines/scumm/player_mac.cpp +++ b/engines/scumm/player_mac.cpp @@ -26,6 +26,7 @@ #include "gui/message.h" #include "scumm/player_mac.h" #include "scumm/scumm.h" +#include "scumm/imuse/imuse.h" namespace Scumm { @@ -101,7 +102,8 @@ void Player_Mac::saveLoadWithSerializer(Serializer *ser) { Common::StackLock lock(_mutex); if (ser->getVersion() < VER(94)) { if (_vm->_game.id == GID_MONKEY && ser->isLoading()) { - // TODO: Skip old iMUSE save/load information + IMuse *dummyImuse = IMuse::create(_vm->_system, NULL, NULL); + dummyImuse->save_or_load(ser, _vm, false); } } else { static const SaveLoadEntry musicEntries[] = { @@ -109,6 +111,12 @@ void Player_Mac::saveLoadWithSerializer(Serializer *ser) { MKEND() }; + // Note: This will fail slightly when loading a savegame if + // the mixer output rate has changed, because the pitch + // modifier and remaining samples were calculated from it. As + // a result, the first note to be played will be out of tune, + // and the channels will probably be slightly out of sync. + static const SaveLoadEntry channelEntries[] = { MKLINE(Channel, _pos, sleUint16, VER(94)), MKLINE(Channel, _pitchModifier, sleInt32, VER(94)), -- cgit v1.2.3