diff options
Diffstat (limited to 'engines')
-rw-r--r-- | engines/sci/detection_tables.h | 13 | ||||
-rw-r--r-- | engines/sci/engine/guest_additions.cpp | 92 | ||||
-rw-r--r-- | engines/sci/engine/guest_additions.h | 4 | ||||
-rw-r--r-- | engines/sci/engine/kernel_tables.h | 2 | ||||
-rw-r--r-- | engines/sci/engine/savegame.cpp | 6 |
5 files changed, 98 insertions, 19 deletions
diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index c37dd4fffb..82d3bddc3b 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -1814,10 +1814,9 @@ static const struct ADGameDescription SciGameDescriptions[] = { GUIO_LINKMUSICTOSFX, \ GUIO_LINKSPEECHTOSFX, \ GUIO_NOASPECT) -#define GUIO_KQ7 GUIO4(GUIO_NOASPECT, \ +#define GUIO_KQ7 GUIO3(GUIO_NOASPECT, \ GUIO_LINKMUSICTOSFX, \ - GUIO_LINKSPEECHTOSFX, \ - GAMEOPTION_ORIGINAL_SAVELOAD) + GUIO_LINKSPEECHTOSFX) // King's Quest 7 - English Windows (from the King's Quest Collection) // Executable scanning reports "2.100.002", VERSION file reports "1.4" @@ -2887,7 +2886,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { #define GUIO_MOTHERGOOSEHIRES GUIO4(GUIO_NOSUBTITLES, \ GUIO_NOASPECT, \ GUIO_LINKSPEECHTOSFX, \ - GAMEOPTION_ORIGINAL_SAVELOAD) + GUIO_NOLAUNCHLOAD) // Mixed-Up Mother Goose Deluxe - English Windows/DOS CD (supplied by markcoolio in bug report #2723810) // Executable scanning reports "2.100.002" @@ -3414,12 +3413,11 @@ static const struct ADGameDescription SciGameDescriptions[] = { GUIO_LINKSPEECHTOSFX, \ GUIO_NOASPECT, \ GUIO_NOLAUNCHLOAD) -#define GUIO_PQSWAT GUIO7(GUIO_NOSUBTITLES, \ +#define GUIO_PQSWAT GUIO6(GUIO_NOSUBTITLES, \ GUIO_NOMIDI, \ GUIO_LINKMUSICTOSFX, \ GUIO_LINKSPEECHTOSFX, \ GUIO_NOASPECT, \ - GAMEOPTION_ORIGINAL_SAVELOAD, \ GAMEOPTION_ENABLE_BLACK_LINED_VIDEO) // Police Quest: SWAT - English DOS/Windows Demo (from jvprat) @@ -3946,11 +3944,10 @@ static const struct ADGameDescription SciGameDescriptions[] = { GUIO_LINKSPEECHTOSFX, \ GUIO_LINKMUSICTOSFX, \ GUIO_NOASPECT) -#define GUIO_SHIVERS GUIO6(GUIO_NOMIDI, \ +#define GUIO_SHIVERS GUIO5(GUIO_NOMIDI, \ GUIO_LINKSPEECHTOSFX, \ GUIO_LINKMUSICTOSFX, \ GUIO_NOASPECT, \ - GAMEOPTION_ORIGINAL_SAVELOAD, \ GAMEOPTION_ENABLE_BLACK_LINED_VIDEO) // Shivers - English Windows (from jvprat) diff --git a/engines/sci/engine/guest_additions.cpp b/engines/sci/engine/guest_additions.cpp index 8ac780ac17..57de4e3680 100644 --- a/engines/sci/engine/guest_additions.cpp +++ b/engines/sci/engine/guest_additions.cpp @@ -210,14 +210,20 @@ void GuestAdditions::kDoSoundSetVolumeHook(const reg_t soundObj, const int16 vol } void GuestAdditions::instantiateScriptHook(Script &script) const { - if (getSciVersion() < SCI_VERSION_2) { + if (getSciVersion() < SCI_VERSION_2 || ConfMan.getBool("originalsaveload")) { return; } - // 64990 is the system script containing SRDialog. This script is normally - // used by the main Game object, but it is not loaded immediately, so we - // wait for it to be loaded before patching it - if (!ConfMan.getBool("originalsaveload") && script.getScriptNumber() == 64990) { + if (g_sci->getGameId() == GID_TORIN && script.getScriptNumber() == 64866) { + patchGameSaveRestoreTorin(script); + } else if (script.getScriptNumber() == 64990) { + // 64990 is the system script containing SRDialog. This script is used + // by the main Game object, but it is not loaded immediately, so we wait + // for it to be loaded before patching it. Attempting to preload this + // script early for patching will cause the order of entries in the + // segment table to change (versus save games that are not patched), + // breaking persistent objects (like the control panel in SQ6) which + // require reg_ts created during game startup to always be the same patchGameSaveRestoreSCI32(script); } } @@ -347,8 +353,38 @@ void GuestAdditions::patchGameSaveRestoreSCI32(Script &script) const { } } +static const byte SRTorinPatch[] = { + 0x38, 0x8d, 0x00, // pushi $8d (new) + 0x76, // push0 + 0x51, 0x0f, // class $f (Str) + 0x4a, 0x04, 0x00, // send 4 + 0xa3, 0x01, // sal 1 + 0x76, // push0 + 0x59, 0x01, // &rest 1 + 0x43, kScummVMSaveLoadId, 0x00, 0x00, // callk kScummVMSaveLoad, 0 + 0x48 // ret +}; + +void GuestAdditions::patchGameSaveRestoreTorin(Script &script) const { + const uint16 address = script.validateExportFunc(2, true); + byte *patchPtr = const_cast<byte *>(script.getBuf(address)); + memcpy(patchPtr, SRTorinPatch, sizeof(SRTorinPatch)); + if (g_sci->isBE()) { + SWAP(patchPtr[1], patchPtr[2]); + SWAP(patchPtr[8], patchPtr[9]); + } +} + reg_t GuestAdditions::kScummVMSaveLoad(EngineState *s, int argc, reg_t *argv) const { - const bool isSave = (bool)argv[0].toSint16(); + if (g_sci->getGameId() == GID_TORIN) { + return promptSaveRestoreTorin(s, argc, argv); + } + + return promptSaveRestoreDefault(s, argc, argv); +} + +reg_t GuestAdditions::promptSaveRestoreDefault(EngineState *s, int argc, reg_t *argv) const { + const bool isSave = (argc > 0); int saveNo; if (isSave) { @@ -356,10 +392,10 @@ reg_t GuestAdditions::kScummVMSaveLoad(EngineState *s, int argc, reg_t *argv) co saveNo = dialog.runModalWithCurrentTarget(); if (saveNo != -1) { reg_t descriptionId; - if (_segMan->isObject(argv[1])) { - descriptionId = readSelector(_segMan, argv[1], SELECTOR(data)); + if (_segMan->isObject(argv[0])) { + descriptionId = readSelector(_segMan, argv[0], SELECTOR(data)); } else { - descriptionId = argv[1]; + descriptionId = argv[0]; } SciArray &description = *_segMan->lookupArray(descriptionId); description.fromString(dialog.getResultString()); @@ -380,6 +416,44 @@ reg_t GuestAdditions::kScummVMSaveLoad(EngineState *s, int argc, reg_t *argv) co return make_reg(0, saveNo); } + +reg_t GuestAdditions::promptSaveRestoreTorin(EngineState *s, int argc, reg_t *argv) const { + const bool isSave = (argc > 0 && (bool)argv[0].toSint16()); + int saveNo; + + if (isSave) { + GUI::SaveLoadChooser dialog(_("Save game:"), _("Save"), true); + saveNo = dialog.runModalWithCurrentTarget(); + if (saveNo != -1) { + reg_t descriptionId = s->variables[VAR_LOCAL][1]; + reg_t dataId; + SciArray &description = *_segMan->allocateArray(kArrayTypeString, 0, &dataId); + description.fromString(dialog.getResultString()); + writeSelector(_segMan, descriptionId, SELECTOR(data), dataId); + } + } else { + GUI::SaveLoadChooser dialog(_("Restore game:"), _("Restore"), false); + saveNo = dialog.runModalWithCurrentTarget(); + } + + if (saveNo > 0) { + // The autosave slot in ScummVM takes up slot 0, but in SCI the first + // non-autosave save game number needs to be 0, so reduce the save + // number here to match what would come from the normal SCI save/restore + // dialog. There is additional special code for handling the autosave + // game inside of kRestoreGame32. + --saveNo; + } + + if (saveNo != -1) { + assert(s->variablesMax[VAR_LOCAL] > 2); + s->variables[VAR_LOCAL][2] = make_reg(0, saveNo); + s->variables[VAR_LOCAL][3] = make_reg(0, isSave ? 1 : 0); + } + + return make_reg(0, saveNo != -1); +} + #endif #pragma mark - diff --git a/engines/sci/engine/guest_additions.h b/engines/sci/engine/guest_additions.h index ebb328c901..f9c1691445 100644 --- a/engines/sci/engine/guest_additions.h +++ b/engines/sci/engine/guest_additions.h @@ -148,6 +148,10 @@ public: private: void patchGameSaveRestoreSCI32(Script &script) const; + void patchGameSaveRestoreTorin(Script &script) const; + + reg_t promptSaveRestoreDefault(EngineState *s, int argc, reg_t *argv) const; + reg_t promptSaveRestoreTorin(EngineState *s, int argc, reg_t *argv) const; #endif #pragma mark - diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h index f075da3005..7e3f4a8bff 100644 --- a/engines/sci/engine/kernel_tables.h +++ b/engines/sci/engine/kernel_tables.h @@ -783,7 +783,7 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(Said), SIG_EVERYWHERE, "[r0]", NULL, NULL }, #ifdef ENABLE_SCI32 { "SaveGame", kSaveGame32, SIG_THRU_SCI21EARLY, SIGFOR_ALL, "ri[r0][r0]", NULL, NULL }, - { MAP_CALL(ScummVMSaveLoad), SIG_SCI32, SIGFOR_ALL, "i([ro])", NULL, NULL }, + { MAP_CALL(ScummVMSaveLoad), SIG_SCI32, SIGFOR_ALL, "([iro])([ro0])", NULL, NULL }, #endif { MAP_CALL(SaveGame), SIG_SCI16, SIGFOR_ALL, "[r0]i[r0](r0)", NULL, NULL }, { MAP_CALL(ScriptID), SIG_EVERYWHERE, "[io](i)", NULL, NULL }, diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index d7fe009c9a..17bdebc76d 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -48,6 +48,7 @@ #include "sci/sound/music.h" #ifdef ENABLE_SCI32 +#include "sci/engine/guest_additions.h" #include "sci/graphics/cursor32.h" #include "sci/graphics/frameout.h" #include "sci/graphics/palette32.h" @@ -256,7 +257,6 @@ void SegManager::saveLoadWithSerializer(Common::Serializer &s) { ObjMap objects = scr->getObjectMap(); for (ObjMap::iterator it = objects.begin(); it != objects.end(); ++it) it->_value.syncBaseObject(SciSpan<const byte>(scr->getBuf(it->_value.getPos().getOffset()), scr->getBufSize() - it->_value.getPos().getOffset())); - } // Sync the script's string heap @@ -297,6 +297,10 @@ void SegManager::saveLoadWithSerializer(Common::Serializer &s) { } } } + + if (s.isLoading() && pass == passes) { + g_sci->_guestAdditions->instantiateScriptHook(*scr); + } } } } |