Skip to content

Commit

Permalink
SCUMM: Add hack to preserve savegame compatibility with Mac MI1
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Torbjörn Andersson committed Nov 16, 2012
1 parent f784d68 commit f0c1d8d
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 5 deletions.
13 changes: 11 additions & 2 deletions engines/scumm/imuse/imuse.cpp
Expand Up @@ -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)),
Expand Down Expand Up @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion engines/scumm/imuse/imuse.h
Expand Up @@ -62,7 +62,7 @@ class IMuse : public MusicEngine {
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;
Expand Down
2 changes: 1 addition & 1 deletion engines/scumm/imuse/imuse_internal.h
Expand Up @@ -518,7 +518,7 @@ class IMuseInternal : public IMuse {
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);
Expand Down
10 changes: 9 additions & 1 deletion engines/scumm/player_mac.cpp
Expand Up @@ -26,6 +26,7 @@
#include "gui/message.h"
#include "scumm/player_mac.h"
#include "scumm/scumm.h"
#include "scumm/imuse/imuse.h"

namespace Scumm {

Expand Down Expand Up @@ -101,14 +102,21 @@ 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[] = {
MKLINE(Player_Mac, _soundPlaying, sleInt16, VER(94)),
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)),
Expand Down

0 comments on commit f0c1d8d

Please sign in to comment.