Skip to content

Commit

Permalink
SCI: Script patch for Mixed Up Mother Goose SCI1
Browse files Browse the repository at this point in the history
+ Mother Goose SCI1.1
Fixes graphic issues when restoring from GMM
Also make the fix ups for Mixed Up Mother Goose, Jones + PQ2
get applied all the time (debugger command not included)
  • Loading branch information
Martin Kiewitz committed Feb 9, 2016
1 parent b335723 commit ccb321a
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 46 deletions.
47 changes: 2 additions & 45 deletions engines/sci/engine/kfile.cpp
Expand Up @@ -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"

Expand Down Expand Up @@ -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);
Expand Down
52 changes: 51 additions & 1 deletion engines/sci/engine/savegame.cpp
Expand Up @@ -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"
Expand Down Expand Up @@ -957,21 +958,70 @@ 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) {
// found a savegame file
gamestate_restore(s, in);
delete in;
if (s->r_acc != make_reg(0, 1)) {
gamestate_afterRestoreFixUp(s, savegameId);
return;
}
}

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;

Expand Down
3 changes: 3 additions & 0 deletions engines/sci/engine/savegame.h
Expand Up @@ -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
Expand Down
85 changes: 85 additions & 0 deletions engines/sci/engine/script_patches.cpp
Expand Up @@ -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
Expand Down

0 comments on commit ccb321a

Please sign in to comment.