diff options
author | Colin Snover | 2017-02-04 12:10:36 -0600 |
---|---|---|
committer | Colin Snover | 2017-04-22 13:01:35 -0500 |
commit | 1ed185bbbb59891a906e316956f8b09419094ef3 (patch) | |
tree | 9a0a62d6d1396f98b1b274b7efc2f00edcb93164 /engines/sci | |
parent | 6f75bed90cdf36878f26cc1e091483efcc8091c8 (diff) | |
download | scummvm-rg350-1ed185bbbb59891a906e316956f8b09419094ef3.tar.gz scummvm-rg350-1ed185bbbb59891a906e316956f8b09419094ef3.tar.bz2 scummvm-rg350-1ed185bbbb59891a906e316956f8b09419094ef3.zip |
SCI: Implement delayed restore for SCI32 and move implementations to GuestAdditions
Diffstat (limited to 'engines/sci')
-rw-r--r-- | engines/sci/engine/guest_additions.cpp | 97 | ||||
-rw-r--r-- | engines/sci/engine/guest_additions.h | 29 | ||||
-rw-r--r-- | engines/sci/engine/kevent.cpp | 5 | ||||
-rw-r--r-- | engines/sci/engine/kgraphics.cpp | 5 | ||||
-rw-r--r-- | engines/sci/engine/savegame.cpp | 27 | ||||
-rw-r--r-- | engines/sci/engine/savegame.h | 3 | ||||
-rw-r--r-- | engines/sci/engine/selector.cpp | 1 | ||||
-rw-r--r-- | engines/sci/engine/selector.h | 1 |
8 files changed, 124 insertions, 44 deletions
diff --git a/engines/sci/engine/guest_additions.cpp b/engines/sci/engine/guest_additions.cpp index 57de4e3680..0ef6d99eaa 100644 --- a/engines/sci/engine/guest_additions.cpp +++ b/engines/sci/engine/guest_additions.cpp @@ -23,9 +23,11 @@ #include "audio/mixer.h" #include "common/config-manager.h" #include "common/gui_options.h" +#include "common/savefile.h" #include "sci/engine/features.h" #include "sci/engine/guest_additions.h" #include "sci/engine/kernel.h" +#include "sci/engine/savegame.h" #include "sci/engine/state.h" #include "sci/engine/vm.h" #ifdef ENABLE_SCI32 @@ -209,8 +211,16 @@ void GuestAdditions::kDoSoundSetVolumeHook(const reg_t soundObj, const int16 vol } } -void GuestAdditions::instantiateScriptHook(Script &script) const { - if (getSciVersion() < SCI_VERSION_2 || ConfMan.getBool("originalsaveload")) { +void GuestAdditions::instantiateScriptHook(Script &script, const bool ignoreDelayedRestore) const { + if (getSciVersion() < SCI_VERSION_2) { + return; + } + + // If there is a delayed restore, we still want to patch the script so + // that the automatic return of the game ID works, but we do not want to + // patch the scripts that get restored + if (ConfMan.getBool("originalsaveload") && + (ignoreDelayedRestore || _state->_delayedRestoreGameId == -1)) { return; } @@ -228,10 +238,30 @@ void GuestAdditions::instantiateScriptHook(Script &script) const { } } +void GuestAdditions::segManSaveLoadScriptHook(Script &script) const { + instantiateScriptHook(script, true); +} + +bool GuestAdditions::kGetEventHook() const { + if (_state->_delayedRestoreGameId != -1) { + g_sci->_guestAdditions->restoreFromLauncher(); + return true; + } + return false; +} + +bool GuestAdditions::kWaitHook() const { + if (_state->_delayedRestoreGameId != -1) { + g_sci->_guestAdditions->restoreFromLauncher(); + return true; + } + return false; +} + #endif #pragma mark - -#pragma mark Save & restore +#pragma mark Integrated save & restore void GuestAdditions::patchGameSaveRestore() const { if (ConfMan.getBool("originalsaveload") || getSciVersion() >= SCI_VERSION_2) @@ -401,8 +431,12 @@ reg_t GuestAdditions::promptSaveRestoreDefault(EngineState *s, int argc, reg_t * description.fromString(dialog.getResultString()); } } else { - GUI::SaveLoadChooser dialog(_("Restore game:"), _("Restore"), false); - saveNo = dialog.runModalWithCurrentTarget(); + if (s->_delayedRestoreGameId != -1) { + saveNo = s->_delayedRestoreGameId; + } else { + GUI::SaveLoadChooser dialog(_("Restore game:"), _("Restore"), false); + saveNo = dialog.runModalWithCurrentTarget(); + } } if (saveNo > 0) { @@ -432,8 +466,12 @@ reg_t GuestAdditions::promptSaveRestoreTorin(EngineState *s, int argc, reg_t *ar writeSelector(_segMan, descriptionId, SELECTOR(data), dataId); } } else { - GUI::SaveLoadChooser dialog(_("Restore game:"), _("Restore"), false); - saveNo = dialog.runModalWithCurrentTarget(); + if (s->_delayedRestoreGameId != -1) { + saveNo = s->_delayedRestoreGameId; + } else { + GUI::SaveLoadChooser dialog(_("Restore game:"), _("Restore"), false); + saveNo = dialog.runModalWithCurrentTarget(); + } } if (saveNo > 0) { @@ -457,6 +495,51 @@ reg_t GuestAdditions::promptSaveRestoreTorin(EngineState *s, int argc, reg_t *ar #endif #pragma mark - +#pragma mark Restore from launcher + +void GuestAdditions::restoreFromLauncher() const { + assert(_state->_delayedRestoreGameId != -1); + +#ifdef ENABLE_SCI32 + if (getSciVersion() >= SCI_VERSION_2) { + // In SQ6, delayed restore should not happen until room 100 (the Sierra + // logo & main menu room) is loaded, otherwise the game scripts will try + // to make calls to the subtitles window, which does not exist until + // after the main menu. The game scripts check if the current room is + // 100 and avoids making calls to the subtitles window if it is. + if (g_sci->getGameId() == GID_SQ6 && + _state->variables[VAR_GLOBAL][kGlobalVarCurrentRoomNo] != make_reg(0, 100)) { + + return; + } + + // When `Game::restore` is invoked, it will call to `Restore::doit` + // which will automatically return the `_delayedRestoreGameId` instead + // of prompting the user for a save game + invokeSelector(g_sci->getGameObject(), SELECTOR(restore)); + } else { +#else + { +#endif + int savegameId = _state->_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(_state, in); + delete in; + if (_state->r_acc != make_reg(0, 1)) { + gamestate_afterRestoreFixUp(_state, savegameId); + return; + } + } + + error("Restoring gamestate '%s' failed", fileName.c_str()); + } +} + +#pragma mark - #pragma mark Message type sync void GuestAdditions::syncMessageTypeFromScummVM() const { diff --git a/engines/sci/engine/guest_additions.h b/engines/sci/engine/guest_additions.h index f9c1691445..bf4866b9d5 100644 --- a/engines/sci/engine/guest_additions.h +++ b/engines/sci/engine/guest_additions.h @@ -126,11 +126,26 @@ public: /** * Guest additions hook for SegManager::instantiateScript. */ - void instantiateScriptHook(Script &script) const; + void instantiateScriptHook(Script &script, const bool ignoreDelayedRestore = false) const; + + /** + * Guest additions hook for SegManager::saveLoadWithSerializer. + */ + void segManSaveLoadScriptHook(Script &script) const; #endif + /** + * Guest additions hook for kGetEvent. + */ + bool kGetEventHook() const; + + /** + * Guest additions hook for kWait. + */ + bool kWaitHook() const; + #pragma mark - -#pragma mark Save & restore +#pragma mark Integrated save & restore public: /** @@ -155,6 +170,16 @@ private: #endif #pragma mark - +#pragma mark Restore from launcher + +private: + /** + * Invokes the game's restore mechanism to load a save game that was + * selected from the ScummVM launcher. + */ + void restoreFromLauncher() const; + +#pragma mark - #pragma mark Message type sync private: diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp index e290878b71..18205a4219 100644 --- a/engines/sci/engine/kevent.cpp +++ b/engines/sci/engine/kevent.cpp @@ -24,6 +24,7 @@ #include "sci/sci.h" #include "sci/engine/features.h" +#include "sci/engine/guest_additions.h" #include "sci/engine/kernel.h" #include "sci/engine/savegame.h" #include "sci/engine/selector.h" @@ -76,9 +77,7 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) { curEvent = g_sci->getEventManager()->getSciEvent(mask); - if (s->_delayedRestoreGameId != -1) { - // delayed restore game from ScummVM menu got triggered - gamestate_delayedrestore(s); + if (g_sci->_guestAdditions->kGetEventHook()) { return NULL_REG; } diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index a025a8869d..ffb9042b02 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -32,6 +32,7 @@ #include "sci/event.h" #include "sci/resource.h" #include "sci/engine/features.h" +#include "sci/engine/guest_additions.h" #include "sci/engine/savegame.h" #include "sci/engine/state.h" #include "sci/engine/selector.h" @@ -397,9 +398,7 @@ reg_t kWait(EngineState *s, int argc, reg_t *argv) { s->wait(sleep_time); - if (s->_delayedRestoreGameId != -1) { - // delayed restore game from ScummVM menu got triggered - gamestate_delayedrestore(s); + if (g_sci->_guestAdditions->kWaitHook()) { return NULL_REG; } diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 17bdebc76d..057d590b78 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -299,7 +299,7 @@ void SegManager::saveLoadWithSerializer(Common::Serializer &s) { } if (s.isLoading() && pass == passes) { - g_sci->_guestAdditions->instantiateScriptHook(*scr); + g_sci->_guestAdditions->segManSaveLoadScriptHook(*scr); } } } @@ -1094,24 +1094,6 @@ bool gamestate_save(EngineState *s, Common::WriteStream *fh, const Common::Strin extern void showScummVMDialog(const Common::String &message); -void gamestate_delayedrestore(EngineState *s) { - 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: @@ -1256,13 +1238,6 @@ void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { if (g_sci->_gfxPorts) g_sci->_gfxPorts->saveLoadWithSerializer(ser); - // SCI32: - // Current planes/screen elements of freshly loaded VM are re-added by scripts in [gameID]::replay - // We don't have to do that in here. - // But we may have to do it ourselves in case we ever implement some soft-error handling in case - // a saved game can't be restored. That way we can restore the game screen. - // see _gfxFrameout->syncWithScripts() - Vocabulary *voc = g_sci->getVocabulary(); if (ser.getVersion() >= 30 && voc) voc->saveLoadWithSerializer(ser); diff --git a/engines/sci/engine/savegame.h b/engines/sci/engine/savegame.h index a75db25bf9..274df25dc2 100644 --- a/engines/sci/engine/savegame.h +++ b/engines/sci/engine/savegame.h @@ -97,9 +97,6 @@ struct SavegameMetadata { */ bool gamestate_save(EngineState *s, Common::WriteStream *save, const Common::String &savename, const Common::String &version); -// 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); diff --git a/engines/sci/engine/selector.cpp b/engines/sci/engine/selector.cpp index 8a1a9e76d4..5bfc73b801 100644 --- a/engines/sci/engine/selector.cpp +++ b/engines/sci/engine/selector.cpp @@ -90,6 +90,7 @@ void Kernel::mapSelectors() { FIND_SELECTOR(message); // edit FIND_SELECTOR(play); + FIND_SELECTOR(restore); FIND_SELECTOR(number); FIND_SELECTOR(handle); // nodePtr FIND_SELECTOR(client); diff --git a/engines/sci/engine/selector.h b/engines/sci/engine/selector.h index d8c0bf711b..f2e4ec0b7f 100644 --- a/engines/sci/engine/selector.h +++ b/engines/sci/engine/selector.h @@ -63,6 +63,7 @@ struct SelectorCache { Selector message; ///< Used by GetEvent // edit Selector play; ///< Play function (first function to be called) + Selector restore; Selector number; Selector handle; ///< Replaced by nodePtr in SCI1+ Selector nodePtr; ///< Replaces handle in SCI1+ |