aboutsummaryrefslogtreecommitdiff
path: root/engines/sci
diff options
context:
space:
mode:
authorColin Snover2017-07-27 22:31:12 -0500
committerColin Snover2017-07-30 19:10:50 -0500
commit49e8f057144b0a212af380525717a96a152569bc (patch)
treefc2c7fdd01d58e906fbf81d00cd23711b88ebc38 /engines/sci
parent325fd1a3efdbeaaf01a61a9905d40cc91ad9f6c3 (diff)
downloadscummvm-rg350-49e8f057144b0a212af380525717a96a152569bc.tar.gz
scummvm-rg350-49e8f057144b0a212af380525717a96a152569bc.tar.bz2
scummvm-rg350-49e8f057144b0a212af380525717a96a152569bc.zip
SCI32: Implement Phant2 save/load integration
Diffstat (limited to 'engines/sci')
-rw-r--r--engines/sci/engine/guest_additions.cpp49
-rw-r--r--engines/sci/engine/guest_additions.h11
-rw-r--r--engines/sci/engine/kernel_tables.h2
-rw-r--r--engines/sci/engine/selector.cpp2
-rw-r--r--engines/sci/engine/selector.h2
-rw-r--r--engines/sci/engine/vm.h1
6 files changed, 66 insertions, 1 deletions
diff --git a/engines/sci/engine/guest_additions.cpp b/engines/sci/engine/guest_additions.cpp
index 6b9b98d83d..373a1e9c13 100644
--- a/engines/sci/engine/guest_additions.cpp
+++ b/engines/sci/engine/guest_additions.cpp
@@ -233,6 +233,8 @@ void GuestAdditions::instantiateScriptHook(Script &script, const bool ignoreDela
script.getScriptNumber() == 64866) {
patchGameSaveRestoreTorin(script);
+ } else if (g_sci->getGameId() == GID_PHANTASMAGORIA2 && script.getScriptNumber() == 64978) {
+ patchGameSaveRestorePhant2(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
@@ -412,7 +414,31 @@ void GuestAdditions::patchGameSaveRestoreTorin(Script &script) const {
}
}
+void GuestAdditions::patchGameSaveRestorePhant2(Script &script) const {
+ const ObjMap &objects = script.getObjectMap();
+ for (ObjMap::const_iterator it = objects.begin(); it != objects.end(); ++it) {
+ const Object &obj = it->_value;
+
+ if (strncmp(_segMan->derefString(obj.getNameSelector()), "srGetGame", 9) != 0) {
+ continue;
+ }
+
+ int methodIndex = obj.funcSelectorPosition(SELECTOR(init));
+ if (methodIndex == -1) {
+ continue;
+ }
+
+ byte *scriptData = const_cast<byte *>(script.getBuf(obj.getFunction(methodIndex).getOffset()));
+ memcpy(scriptData, SRDialogPatch, sizeof(SRDialogPatch));
+ break;
+ }
+}
+
reg_t GuestAdditions::kScummVMSaveLoad(EngineState *s, int argc, reg_t *argv) const {
+ if (g_sci->getGameId() == GID_PHANTASMAGORIA2) {
+ return promptSaveRestorePhant2(s, argc, argv);
+ }
+
if (g_sci->getGameId() == GID_LSL7 || g_sci->getGameId() == GID_TORIN) {
return promptSaveRestoreTorin(s, argc, argv);
}
@@ -446,6 +472,29 @@ reg_t GuestAdditions::promptSaveRestoreTorin(EngineState *s, int argc, reg_t *ar
return make_reg(0, saveNo != -1);
}
+reg_t GuestAdditions::promptSaveRestorePhant2(EngineState *s, int argc, reg_t *argv) const {
+ assert(argc == 2);
+ const bool isSave = argv[1].toSint16() == 0;
+ const int saveNo = runSaveRestore(isSave, argv[0], s->_delayedRestoreGameId);
+
+ // Clear the highlighted state of the button so if the same control panel is
+ // opened again it does not appear to be opened to the save/load panels
+ reg_t button;
+ if (isSave) {
+ button = _segMan->findObjectByName("saveButton");
+ } else {
+ button = _segMan->findObjectByName("loadButton");
+ }
+ writeSelectorValue(_segMan, button, SELECTOR(cel), 0);
+
+ // This causes the control panel to quit its internal event loop and hide
+ // itself
+ const reg_t controlPanel = s->variables[VAR_GLOBAL][kGlobalVarPhant2ControlPanel];
+ writeSelector(_segMan, controlPanel, SELECTOR(scratch), TRUE_REG);
+
+ return make_reg(0, saveNo);
+}
+
int GuestAdditions::runSaveRestore(const bool isSave, reg_t outDescription, const int forcedSaveNo) const {
int saveNo;
Common::String descriptionString;
diff --git a/engines/sci/engine/guest_additions.h b/engines/sci/engine/guest_additions.h
index 657fa52318..eed1ee3154 100644
--- a/engines/sci/engine/guest_additions.h
+++ b/engines/sci/engine/guest_additions.h
@@ -188,6 +188,11 @@ private:
void patchGameSaveRestoreTorin(Script &script) const;
/**
+ * Patches the ScummVM save/load dialogue into Phant2.
+ */
+ void patchGameSaveRestorePhant2(Script &script) const;
+
+ /**
* Prompts for a save game and returns it to game scripts using default
* SRDialog game class semantics.
*/
@@ -200,6 +205,12 @@ private:
reg_t promptSaveRestoreTorin(EngineState *s, int argc, reg_t *argv) const;
/**
+ * Prompts for a save game and returns it to game scripts using Phant2's
+ * custom ControlPanel class semantics.
+ */
+ reg_t promptSaveRestorePhant2(EngineState *s, int argc, reg_t *argv) const;
+
+ /**
* Prompts the user to save or load a game.
*
* @param isSave If true, the prompt is for saving.
diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h
index bd3184a900..c65356470a 100644
--- a/engines/sci/engine/kernel_tables.h
+++ b/engines/sci/engine/kernel_tables.h
@@ -779,7 +779,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, "([iro])([ro0])", NULL, NULL },
+ { MAP_CALL(ScummVMSaveLoad), SIG_SCI32, SIGFOR_ALL, "([iro])([iro])", 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/selector.cpp b/engines/sci/engine/selector.cpp
index 889590fc8b..e99f734272 100644
--- a/engines/sci/engine/selector.cpp
+++ b/engines/sci/engine/selector.cpp
@@ -222,6 +222,8 @@ void Kernel::mapSelectors() {
FIND_SELECTOR(move);
FIND_SELECTOR(eachElementDo);
FIND_SELECTOR(physicalBar);
+ FIND_SELECTOR(init);
+ FIND_SELECTOR(scratch);
#endif
}
diff --git a/engines/sci/engine/selector.h b/engines/sci/engine/selector.h
index 850a5dc0ec..d26a0d740f 100644
--- a/engines/sci/engine/selector.h
+++ b/engines/sci/engine/selector.h
@@ -179,6 +179,8 @@ struct SelectorCache {
Selector move; // for Phant2 volume sync
Selector eachElementDo; // for Phant2 volume sync
Selector physicalBar; // for Phant2 volume sync
+ Selector init; // for Phant2 save/load patching
+ Selector scratch; // for Phant2 save/load patching
#endif
};
diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h
index e92929e7ea..a8ac7b180f 100644
--- a/engines/sci/engine/vm.h
+++ b/engines/sci/engine/vm.h
@@ -170,6 +170,7 @@ enum GlobalVar {
// Phant2 labels its volume slider as "music volume" but it is actually
// a master volume that affects both music *and* sound effects
kGlobalVarPhant2MasterVolume = 236, // 0 to 127
+ kGlobalVarPhant2ControlPanel = 250,
kGlobalVarShivers1Score = 349
};