diff options
-rw-r--r-- | engines/sci/engine/kfile.cpp | 47 | ||||
-rw-r--r-- | engines/sci/engine/savegame.cpp | 52 | ||||
-rw-r--r-- | engines/sci/engine/savegame.h | 3 | ||||
-rw-r--r-- | engines/sci/engine/script_patches.cpp | 85 |
4 files changed, 141 insertions, 46 deletions
diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index 979fa95a42..f155fe75cb 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -37,7 +37,6 @@ #include "sci/engine/state.h" #include "sci/engine/kernel.h" #include "sci/engine/savegame.h" -#include "sci/graphics/menu.h" #include "sci/sound/audio.h" #include "sci/console.h" @@ -907,50 +906,8 @@ reg_t kRestoreGame(EngineState *s, int argc, reg_t *argv) { gamestate_restore(s, in); delete in; - switch (g_sci->getGameId()) { - case GID_MOTHERGOOSE: - // WORKAROUND: Mother Goose SCI0 - // Script 200 / rm200::newRoom will set global C5h directly right after creating a child to the - // current number of children plus 1. - // We can't trust that global, that's why we set the actual savedgame id right here directly after - // restoring a saved game. - // If we didn't, the game would always save to a new slot - s->variables[VAR_GLOBAL][0xC5].setOffset(SAVEGAMEID_OFFICIALRANGE_START + savegameId); - break; - case GID_MOTHERGOOSE256: - // WORKAROUND: Mother Goose SCI1/SCI1.1 does some weird things for - // saving a previously restored game. - // We set the current savedgame-id directly and remove the script - // code concerning this via script patch. - s->variables[VAR_GLOBAL][0xB3].setOffset(SAVEGAMEID_OFFICIALRANGE_START + savegameId); - break; - case GID_JONES: - // HACK: The code that enables certain menu items isn't called when a game is restored from the - // launcher, or the "Restore game" option in the game's main menu - bugs #6537 and #6723. - // These menu entries are disabled when the game is launched, and are enabled when a new game is - // started. The code for enabling these entries is is all in script 1, room1::init, but that code - // path is never followed in these two cases (restoring game from the menu, or restoring a game - // from the ScummVM launcher). Thus, we perform the calls to enable the menus ourselves here. - // These two are needed when restoring from the launcher - // FIXME: The original interpreter saves and restores the menu state, so these attributes - // are automatically reset there. We may want to do the same. - g_sci->_gfxMenu->kernelSetAttribute(257 >> 8, 257 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Sierra -> About Jones - g_sci->_gfxMenu->kernelSetAttribute(258 >> 8, 258 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Sierra -> Help - // The rest are normally enabled from room1::init - g_sci->_gfxMenu->kernelSetAttribute(769 >> 8, 769 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Options -> Delete current player - g_sci->_gfxMenu->kernelSetAttribute(513 >> 8, 513 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Game -> Save Game - g_sci->_gfxMenu->kernelSetAttribute(515 >> 8, 515 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Game -> Restore Game - g_sci->_gfxMenu->kernelSetAttribute(1025 >> 8, 1025 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Status -> Statistics - g_sci->_gfxMenu->kernelSetAttribute(1026 >> 8, 1026 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Status -> Goals - break; - case GID_PQ2: - // HACK: Same as above - enable the save game menu option when loading in PQ2 (bug #6875). - // It gets disabled in the game's death screen. - g_sci->_gfxMenu->kernelSetAttribute(2, 1, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Game -> Save Game - break; - default: - break; - } + gamestate_afterRestoreFixUp(s, savegameId); + } else { s->r_acc = TRUE_REG; warning("Savegame #%d not found", savegameId); diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 165c147c1c..fcf951e4f2 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -39,6 +39,7 @@ #include "sci/engine/vm_types.h" #include "sci/engine/script.h" // for SCI_OBJ_EXPORTS and SCI_OBJ_SYNONYMS #include "sci/graphics/helpers.h" +#include "sci/graphics/menu.h" #include "sci/graphics/palette.h" #include "sci/graphics/ports.h" #include "sci/graphics/screen.h" @@ -957,7 +958,8 @@ bool gamestate_save(EngineState *s, Common::WriteStream *fh, const Common::Strin extern void showScummVMDialog(const Common::String &message); void gamestate_delayedrestore(EngineState *s) { - Common::String fileName = g_sci->getSavegameName(s->_delayedRestoreGameId); + int savegameId = s->_delayedRestoreGameId; // delayedRestoreGameId gets destroyed within gamestate_restore()! + Common::String fileName = g_sci->getSavegameName(savegameId); Common::SeekableReadStream *in = g_sci->getSaveFileManager()->openForLoading(fileName); if (in) { @@ -965,6 +967,7 @@ void gamestate_delayedrestore(EngineState *s) { gamestate_restore(s, in); delete in; if (s->r_acc != make_reg(0, 1)) { + gamestate_afterRestoreFixUp(s, savegameId); return; } } @@ -972,6 +975,53 @@ void gamestate_delayedrestore(EngineState *s) { error("Restoring gamestate '%s' failed", fileName.c_str()); } +void gamestate_afterRestoreFixUp(EngineState *s, int savegameId) { + switch (g_sci->getGameId()) { + case GID_MOTHERGOOSE: + // WORKAROUND: Mother Goose SCI0 + // Script 200 / rm200::newRoom will set global C5h directly right after creating a child to the + // current number of children plus 1. + // We can't trust that global, that's why we set the actual savedgame id right here directly after + // restoring a saved game. + // If we didn't, the game would always save to a new slot + s->variables[VAR_GLOBAL][0xC5].setOffset(SAVEGAMEID_OFFICIALRANGE_START + savegameId); + break; + case GID_MOTHERGOOSE256: + // WORKAROUND: Mother Goose SCI1/SCI1.1 does some weird things for + // saving a previously restored game. + // We set the current savedgame-id directly and remove the script + // code concerning this via script patch. + s->variables[VAR_GLOBAL][0xB3].setOffset(SAVEGAMEID_OFFICIALRANGE_START + savegameId); + break; + case GID_JONES: + // HACK: The code that enables certain menu items isn't called when a game is restored from the + // launcher, or the "Restore game" option in the game's main menu - bugs #6537 and #6723. + // These menu entries are disabled when the game is launched, and are enabled when a new game is + // started. The code for enabling these entries is is all in script 1, room1::init, but that code + // path is never followed in these two cases (restoring game from the menu, or restoring a game + // from the ScummVM launcher). Thus, we perform the calls to enable the menus ourselves here. + // These two are needed when restoring from the launcher + // FIXME: The original interpreter saves and restores the menu state, so these attributes + // are automatically reset there. We may want to do the same. + g_sci->_gfxMenu->kernelSetAttribute(257 >> 8, 257 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Sierra -> About Jones + g_sci->_gfxMenu->kernelSetAttribute(258 >> 8, 258 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Sierra -> Help + // The rest are normally enabled from room1::init + g_sci->_gfxMenu->kernelSetAttribute(769 >> 8, 769 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Options -> Delete current player + g_sci->_gfxMenu->kernelSetAttribute(513 >> 8, 513 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Game -> Save Game + g_sci->_gfxMenu->kernelSetAttribute(515 >> 8, 515 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Game -> Restore Game + g_sci->_gfxMenu->kernelSetAttribute(1025 >> 8, 1025 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Status -> Statistics + g_sci->_gfxMenu->kernelSetAttribute(1026 >> 8, 1026 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Status -> Goals + break; + case GID_PQ2: + // HACK: Same as above - enable the save game menu option when loading in PQ2 (bug #6875). + // It gets disabled in the game's death screen. + g_sci->_gfxMenu->kernelSetAttribute(2, 1, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Game -> Save Game + break; + default: + break; + } +} + void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { SavegameMetadata meta; diff --git a/engines/sci/engine/savegame.h b/engines/sci/engine/savegame.h index bb555434c9..459e992e24 100644 --- a/engines/sci/engine/savegame.h +++ b/engines/sci/engine/savegame.h @@ -87,6 +87,9 @@ bool gamestate_save(EngineState *s, Common::WriteStream *save, const Common::Str // does a delayed saved game restore, used by ScummVM game menu - see detection.cpp / SciEngine::loadGameState() void gamestate_delayedrestore(EngineState *s); +// does a few fixups right after restoring a saved game +void gamestate_afterRestoreFixUp(EngineState *s, int savegameId); + /** * Restores a game state from a directory. * @param s An older state from the same game diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp index f732950c18..dac5c17a23 100644 --- a/engines/sci/engine/script_patches.cpp +++ b/engines/sci/engine/script_patches.cpp @@ -1842,15 +1842,100 @@ static const SciScriptPatcherEntry laurabow2Signatures[] = { // MG::replay somewhat calculates the savedgame-id used when saving again // this doesn't work right and we remove the code completely. // We set the savedgame-id directly right after restoring in kRestoreGame. +// We also draw the background picture in here instead. +// This Mixed Up Mother Goose draws the background picture before restoring, +// instead of doing it properly in MG::replay. This fixes graphic issues, +// when restoring from GMM. static const uint16 mothergoose256SignatureReplay[] = { + 0x7a, // push2 + 0x78, // push1 + 0x5b, 0x00, 0xbe, // lea global[BEh] + 0x36, // push + 0x43, 0x70, 0x04, // callk MemorySegment + 0x7a, // push2 + 0x5b, 0x00, 0xbe, // lea global[BEh] + 0x36, // push + 0x76, // push0 + 0x43, 0x62, 0x04, // callk StrAt + 0xa1, 0xaa, // sag global[AAh] + 0x7a, // push2 + 0x5b, 0x00, 0xbe, // lea global[BEh] + 0x36, // push + 0x78, // push1 + 0x43, 0x62, 0x04, // callk StrAt + 0x36, // push + 0x35, 0x20, // ldi 20 + 0x04, // sub + 0xa1, SIG_ADDTOOFFSET(+1), // sag global[57h] -> FM-Towns [9Dh] + // 35 bytes + 0x39, 0x03, // pushi 03 + 0x89, SIG_ADDTOOFFSET(+1), // lsg global[1Dh] -> FM-Towns [1Eh] + 0x76, // push0 + 0x7a, // push2 + 0x5b, 0x00, 0xbe, // lea global[BEh] + 0x36, // push + 0x7a, // push2 + 0x43, 0x62, 0x04, // callk StrAt + 0x36, // push + 0x35, 0x01, // ldi 01 + 0x04, // sub + 0x36, // push + 0x43, 0x62, 0x06, // callk StrAt + // 22 bytes + 0x7a, // push2 + 0x5b, 0x00, 0xbe, // lea global[BE] + 0x36, // push + 0x39, 0x03, // pushi 03 + 0x43, 0x62, 0x04, // callk StrAt + // 10 bytes 0x36, // push 0x35, SIG_MAGICDWORD, 0x20, // ldi 20 0x04, // sub 0xa1, 0xb3, // sag global[b3] + // 6 bytes SIG_END }; static const uint16 mothergoose256PatchReplay[] = { + 0x39, 0x06, // pushi 06 + 0x76, // push0 + 0x76, // push0 + 0x38, PATCH_UINT16(200), // pushi 200d + 0x38, PATCH_UINT16(320), // pushi 320d + 0x76, // push0 + 0x76, // push0 + 0x43, 0x15, 0x0c, // callk SetPort -> set picture port to full screen + // 15 bytes + 0x39, 0x04, // pushi 04 + 0x3c, // dup + 0x76, // push0 + 0x38, PATCH_UINT16(255), // pushi 255d + 0x76, // push0 + 0x43, 0x6f, 0x08, // callk Palette -> set intensity to 0 for all colors + // 11 bytes + 0x7a, // push2 + 0x38, PATCH_UINT16(800), // pushi 800 + 0x76, // push0 + 0x43, 0x08, 0x04, // callk DrawPic -> draw picture 800 + // 8 bytes + 0x39, 0x06, // pushi 06 + 0x39, 0x0c, // pushi 0Ch + 0x76, // push0 + 0x76, // push0 + 0x38, PATCH_UINT16(200), // push 200 + 0x38, PATCH_UINT16(320), // push 320 + 0x78, // push1 + 0x43, 0x6c, 0x0c, // callk Graph -> send everything to screen + // 16 bytes + 0x39, 0x06, // pushi 06 + 0x76, // push0 + 0x76, // push0 + 0x38, PATCH_UINT16(156), // pushi 156d + 0x38, PATCH_UINT16(258), // pushi 258d + 0x39, 0x03, // pushi 03 + 0x39, 0x04, // pushi 04 + 0x43, 0x15, 0x0c, // callk SetPort -> set picture port back + // 17 bytes 0x34, PATCH_UINT16(0x0000), // ldi 0000 (dummy) 0x34, PATCH_UINT16(0x0000), // ldi 0000 (dummy) PATCH_END |