From 029eeeb803eaef861e74765f69e2fabddf0ec7a7 Mon Sep 17 00:00:00 2001 From: Colin Snover Date: Thu, 14 Sep 2017 20:42:42 -0500 Subject: SCI32: Fix Phant2 "auto-save" The game has a feature where it will automatically create a save game when you quit the game through the in-game control panel (or when you die, for some reason). Unfortunately, due to bad programming, this automatic save would just overwrite whatever was in save slot 1 (slot 0 in the original interpreter). Find this attempt to auto-save the game and redirect it to the auto-save slot. This might not be totally correct, but it is at least better than destroying a save game. Fixes Trac#10201. --- engines/sci/engine/guest_additions.cpp | 11 ++--------- engines/sci/engine/kfile.cpp | 10 +++++----- engines/sci/engine/selector.cpp | 1 + engines/sci/engine/selector.h | 1 + engines/sci/engine/state.cpp | 12 ++++++++++++ engines/sci/engine/state.h | 5 +++++ 6 files changed, 26 insertions(+), 14 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/guest_additions.cpp b/engines/sci/engine/guest_additions.cpp index 90d797aee9..e74a5d6e3f 100644 --- a/engines/sci/engine/guest_additions.cpp +++ b/engines/sci/engine/guest_additions.cpp @@ -263,15 +263,8 @@ bool GuestAdditions::kGetEventHook() const { // cause loading to fail if the save game contains a saved Robot state, // because the Robot will try to restore itself into a game plane which does // not exist yet - if (g_sci->getGameId() == GID_LIGHTHOUSE) { - Common::List::const_iterator it; - for (it = _state->_executionStack.begin(); it != _state->_executionStack.end(); ++it) { - const ExecStack &call = *it; - const reg_t gameObject = g_sci->getGameObject(); - if (call.sendp == gameObject && call.debugSelector == SELECTOR(init)) { - return false; - } - } + if (g_sci->getGameId() == GID_LIGHTHOUSE && _state->callInStack(g_sci->getGameObject(), SELECTOR(init))) { + return false; } #endif diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index 79e1894532..3b8420849a 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -1227,12 +1227,12 @@ reg_t kSaveGame32(EngineState *s, int argc, reg_t *argv) { saveNo += kSaveIdShift; } - if (g_sci->getGameId() == GID_LIGHTHOUSE && gameName == "rst") { + if (g_sci->getGameId() == GID_PHANTASMAGORIA2 && s->callInStack(g_sci->getGameObject(), SELECTOR(bookMark))) { + saveNo = kAutoSaveId; + } else if (g_sci->getGameId() == GID_LIGHTHOUSE && gameName == "rst") { saveNo = kNewGameId; - } - - // Auto-save system used by QFG4 - if (g_sci->getGameId() == GID_QFG4) { + } else if (g_sci->getGameId() == GID_QFG4) { + // Auto-save system used by QFG4 reg_t autoSaveNameId; SciArray &autoSaveName = *s->_segMan->allocateArray(kArrayTypeString, 0, &autoSaveNameId); MessageTuple autoSaveNameTuple(0, 0, 16, 1); diff --git a/engines/sci/engine/selector.cpp b/engines/sci/engine/selector.cpp index 971802affb..d310b0fafd 100644 --- a/engines/sci/engine/selector.cpp +++ b/engines/sci/engine/selector.cpp @@ -226,6 +226,7 @@ void Kernel::mapSelectors() { FIND_SELECTOR(scratch); FIND_SELECTOR(num); FIND_SELECTOR(reallyRestore); + FIND_SELECTOR(bookMark); #endif } diff --git a/engines/sci/engine/selector.h b/engines/sci/engine/selector.h index e2afa74c7a..977411429a 100644 --- a/engines/sci/engine/selector.h +++ b/engines/sci/engine/selector.h @@ -183,6 +183,7 @@ struct SelectorCache { Selector scratch; // for Phant2 save/load patching Selector num; // for Phant2 restore from launcher Selector reallyRestore; // for Phant2 restore from launcher + Selector bookMark; // for Phant2 auto-save #endif }; diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index 7e7be9923c..731f6b7e07 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -423,4 +423,16 @@ SciCallOrigin EngineState::getCurrentCallOrigin() const { return reply; } +bool EngineState::callInStack(const reg_t object, const Selector selector) const { + Common::List::const_iterator it; + for (it = _executionStack.begin(); it != _executionStack.end(); ++it) { + const ExecStack &call = *it; + if (call.sendp == object && call.debugSelector == selector) { + return true; + } + } + + return false; +} + } // End of namespace Sci diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index 57839ab04e..b02ace8aaf 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -224,6 +224,11 @@ public: * Finds and returns the origin of the current call. */ SciCallOrigin getCurrentCallOrigin() const; + + /** + * Determines whether the given object method is in the current stack. + */ + bool callInStack(const reg_t object, const Selector selector) const; }; } // End of namespace Sci -- cgit v1.2.3