aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorColin Snover2017-02-04 12:10:36 -0600
committerColin Snover2017-04-22 13:01:35 -0500
commit1ed185bbbb59891a906e316956f8b09419094ef3 (patch)
tree9a0a62d6d1396f98b1b274b7efc2f00edcb93164 /engines
parent6f75bed90cdf36878f26cc1e091483efcc8091c8 (diff)
downloadscummvm-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')
-rw-r--r--engines/sci/engine/guest_additions.cpp97
-rw-r--r--engines/sci/engine/guest_additions.h29
-rw-r--r--engines/sci/engine/kevent.cpp5
-rw-r--r--engines/sci/engine/kgraphics.cpp5
-rw-r--r--engines/sci/engine/savegame.cpp27
-rw-r--r--engines/sci/engine/savegame.h3
-rw-r--r--engines/sci/engine/selector.cpp1
-rw-r--r--engines/sci/engine/selector.h1
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+