aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Snover2017-10-08 19:25:10 -0500
committerColin Snover2017-10-08 19:25:54 -0500
commitbb02d730b4b21cd38045c3be76ad39ea61c65803 (patch)
tree620133992b597970ba53459d3d57fe0a2828e615
parentbd94bbc3e309c8107688640023b95d7601651e05 (diff)
downloadscummvm-rg350-bb02d730b4b21cd38045c3be76ad39ea61c65803.tar.gz
scummvm-rg350-bb02d730b4b21cd38045c3be76ad39ea61c65803.tar.bz2
scummvm-rg350-bb02d730b4b21cd38045c3be76ad39ea61c65803.zip
SCI32: Fix crash restoring save from endgame of RAMA
Fixes Trac#10263.
-rw-r--r--engines/sci/engine/script_patches.cpp38
1 files changed, 33 insertions, 5 deletions
diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp
index bc4974955b..d12a961cf4 100644
--- a/engines/sci/engine/script_patches.cpp
+++ b/engines/sci/engine/script_patches.cpp
@@ -148,6 +148,7 @@ static const char *const selectorNameTable[] = {
"priority", // RAMA
"plane", // RAMA
"state", // RAMA
+ "getSubscriberObj", // RAMA
#endif
NULL
};
@@ -219,7 +220,8 @@ enum ScriptPatcherSelectors {
SELECTOR_saveFilePtr,
SELECTOR_priority,
SELECTOR_plane,
- SELECTOR_state
+ SELECTOR_state,
+ SELECTOR_getSubscriberObj
#endif
};
@@ -6642,6 +6644,31 @@ static const uint16 ramaSerializeRegTPatch1[] = {
PATCH_END
};
+// When restoring a NukeTimer client, the game makes a self-call to
+// `NukeTimer::getSubscriberObj` from `NukeTimer::serialize`, but forgets to
+// pass a required argument. In SSCI this happens to work because the value on
+// the stack where the first argument should be is the `getSubscriberObj`
+// selector, so it evaluates to true, but currently ScummVM defaults
+// uninitialised param reads to 0 so the game was following the wrong path and
+// breaking.
+// Applies to at least: US English
+static const uint16 ramaNukeTimerSignature[] = {
+ 0x7e, SIG_ADDTOOFFSET(+2), // line whatever
+ SIG_MAGICDWORD,
+ 0x38, SIG_SELECTOR16(getSubscriberObj), // pushi $3ca (getSubscriberObj)
+ 0x76, // push0
+ 0x54, SIG_UINT16(0x04), // self 4
+ SIG_END
+};
+
+static const uint16 ramaNukeTimerPatch[] = {
+ 0x38, PATCH_SELECTOR16(getSubscriberObj), // pushi $3ca (getSubscriberObj)
+ 0x78, // push1
+ 0x38, PATCH_UINT16(0x01), // pushi 1 (wasting bytes)
+ 0x54, PATCH_UINT16(0x06), // self 6
+ PATCH_END
+};
+
// When opening a datacube on the pocket computer, `DocReader::init` will try
// to perform arithmetic on a pointer to `thighComputer::plane` and then use the
// resulting value as the priority for the DocReader. This happened to work in
@@ -6687,10 +6714,11 @@ static const uint16 ramaChangeDirPatch[] = {
};
static const SciScriptPatcherEntry ramaSignatures[] = {
- { true, 55, "fix bad DocReader::init priority calculation", 1, ramaDocReaderInitSignature, ramaDocReaderInitPatch },
- { true, 85, "fix SaveManager to use normal readWord calls", 1, ramaSerializeRegTSignature1, ramaSerializeRegTPatch1 },
- { true, 64908, "disable video benchmarking", 1, ramaBenchmarkSignature, ramaBenchmarkPatch },
- { true, 64990, "disable change directory button", 1, ramaChangeDirSignature, ramaChangeDirPatch },
+ { true, 55, "fix bad DocReader::init priority calculation", 1, ramaDocReaderInitSignature, ramaDocReaderInitPatch },
+ { true, 85, "fix SaveManager to use normal readWord calls", 1, ramaSerializeRegTSignature1, ramaSerializeRegTPatch1 },
+ { true, 201, "fix crash restoring save games using NukeTimer", 1, ramaNukeTimerSignature, ramaNukeTimerPatch },
+ { true, 64908, "disable video benchmarking", 1, ramaBenchmarkSignature, ramaBenchmarkPatch },
+ { true, 64990, "disable change directory button", 1, ramaChangeDirSignature, ramaChangeDirPatch },
SCI_SIGNATUREENTRY_TERMINATOR
};