aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorVhati2018-12-19 01:18:24 -0500
committerFilippos Karapetis2018-12-19 08:18:24 +0200
commita520c6e544dabe967d1950696499af4ff458b2c2 (patch)
tree8bfb251faef6b8b147208378bb7f7569cf33c5ee /engines
parent94509bbf916dcc67704789a1ce5e833dc34d5250 (diff)
downloadscummvm-rg350-a520c6e544dabe967d1950696499af4ff458b2c2.tar.gz
scummvm-rg350-a520c6e544dabe967d1950696499af4ff458b2c2.tar.bz2
scummvm-rg350-a520c6e544dabe967d1950696499af4ff458b2c2.zip
SCI32: Fix QFG4 inventory leaks across restarts (#1440)
Fixes item properties that weren't getting reset, bug #10768
Diffstat (limited to 'engines')
-rw-r--r--engines/sci/engine/script_patches.cpp146
1 files changed, 145 insertions, 1 deletions
diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp
index ecc835444b..89ed9cbadd 100644
--- a/engines/sci/engine/script_patches.cpp
+++ b/engines/sci/engine/script_patches.cpp
@@ -156,7 +156,9 @@ static const char *const selectorNameTable[] = {
"plane", // RAMA
"state", // RAMA
"getSubscriberObj", // RAMA
+ "loop", // QFG4
"setLooper", // QFG4
+ "value", // QFG4
#endif
NULL
};
@@ -237,7 +239,9 @@ enum ScriptPatcherSelectors {
SELECTOR_plane,
SELECTOR_state,
SELECTOR_getSubscriberObj,
- SELECTOR_setLooper
+ SELECTOR_loop,
+ SELECTOR_setLooper,
+ SELECTOR_value
#endif
};
@@ -8697,9 +8701,149 @@ static const uint16 qfg4DreamGatePatch[] = {
PATCH_END
};
+// Some inventory item properties leak across restarts. Most conspicuously, the
+// torch icon appears pre-lit after a restart, if it had been lit before.
+//
+// script 16 - thePiepan (item #28): loop, cel, value
+// script 35 - theBroom (item #39): cel, value
+// script 35 - theTorch (item #44): cel
+//
+// Glory::restart() tries to revert a bunch of globals to their original state.
+// Each value was individually loaded into acc and assigned (ldi+sag, ldi+sag,
+// ldi+sag, etc).
+//
+// One range of globals could be distilled to multiples of 45. We optimize
+// those with a loop. Another range was arbitrary. We stack up those values all
+// at once, then loop over the stack to pop(), assign, and do the next global.
+// We use the freed bytes to reset the 3 items' properties with a subroutine.
+//
+// Applies to at least: English CD, English floppy, German floppy
+// Responsible method: Glory::restart() in script 0
+// Fixes bug: #10768
+static const uint16 qfg4RestartSignature[] = {
+ SIG_MAGICDWORD,
+ 0x76, // push0 (this range is multiples of 45)
+ 0x35, 0x01, // ldi 1d
+ 0xb1, 0x90, // sagi (global[144 + 1] = 0)
+ SIG_ADDTOOFFSET(+40), // ...
+ 0x38, SIG_UINT16(0x013b), // pushi 315
+ SIG_ADDTOOFFSET(+2), // ldi ?? (array index here was typoed)
+ 0xb1, 0x90, // sagi (global[144 + ?] = 315)
+
+ 0x35, 0x14, // ldi 20d (this assignment doesn't fit a pattern)
+ 0xa1, 0xc6, // sag global[198]
+
+ 0x35, 0x02, // ldi 2d (this range has arbitrary values)
+ 0xa0, SIG_UINT16(0x016f), // sag global[367]
+ SIG_ADDTOOFFSET(+95), // ...
+ 0x35, 0x0a, // ldi 10d
+ 0xa0, SIG_UINT16(0x0183), // sag global[387]
+ SIG_END
+};
+
+static const uint16 qfg4RestartPatch[] = {
+ // (loop to assign multiples of 45)
+ 0x76, // push0
+ 0xad, 0x00, // sst temp[0]
+ //
+ 0x8d, 0x00, // lst temp[0] (global[144 + n+1] = n*45)
+ 0x35, 0x08, // ldi 8
+ 0x22, // lt?
+ 0x31, 0x0c, // bnt 12d [end the loop]
+ 0x8d, 0x00, // lst temp[0]
+ 0x35, 0x2d, // ldi 45d
+ 0x06, // mul
+ 0x36, // push (temp[0] * 45)
+ 0xc5, 0x00, // +at temp[0]
+ 0xb1, 0x90, // sagi global[144]
+ 0x33, 0xed, // jmp [-19] (loop)
+ // (that loop freed +30 bytes)
+
+ 0x35, 0x14, // ldi 20d (leave this assignment as-is)
+ 0xa1, 0xc6, // sag global[198]
+
+ // (stack up arbitrary values; then loop to assign them)
+ 0x7a, // push2 (global[367] = 2)
+ 0x3c, // dup (global[368] = 2)
+ 0x39, 0x03, // pushi 3d (global[369] = 3)
+ 0x3c, // dup (global[370] = 3)
+ 0x3c, // dup (global[371] = 3)
+ 0x39, 0x04, // pushi 4d (global[372] = 4)
+ 0x39, 0x05, // pushi 5d (global[373] = 5)
+ 0x3c, // dup (global[374] = 5)
+ 0x39, 0x06, // pushi 6d (global[375] = 6)
+ 0x39, 0x07, // pushi 7d (global[376] = 7)
+ 0x39, 0x08, // pushi 8d (global[377] = 8)
+ 0x3c, // dup (global[378] = 8)
+ 0x39, 0x05, // pushi 5d (global[379] = 5)
+ 0x39, 0x0a, // pushi 10d (global[380] = 10)
+ 0x39, 0x0f, // pushi 15d (global[381] = 15)
+ 0x39, 0x14, // pushi 20d (global[382] = 20)
+ 0x39, 0x06, // pushi 6d (global[383] = 6)
+ 0x39, 0x08, // pushi 8d (global[384] = 8)
+ 0x39, 0x07, // pushi 7d (global[385] = 7)
+ 0x39, 0x0a, // pushi 10d (global[386] = 10)
+ 0x3c, // dup (global[387] = 10)
+ //
+ 0x39, 0x15, // pushi 21d (pop() and set, backward from 20 to 0)
+ 0xad, 0x00, // sst temp[0]
+ //
+ 0xed, 0x00, // -st temp[0]
+ 0x35, 0x00, // ldi 0
+ 0x20, // ge?
+ 0x31, 0x07, // bnt 7d (end the loop)
+ 0x85, 0x00, // lat temp[0]
+ 0xb8, PATCH_UINT16(0x016f), // ssgi 367d (global[367 + n] = pop())
+ 0x33, 0xf2, // jmp [-14] (loop)
+ // (that loop freed +52 bytes)
+
+ // (reset properties for a few items)
+ 0x33, 0x1f, // jmp 31d (skip subroutine declaration)
+ 0x38, PATCH_SELECTOR16(loop), // pushi loop
+ 0x78, // push1
+ 0x8f, 0x02, // lsp[2] (loop varies)
+ 0x38, PATCH_SELECTOR16(cel), // pushi cel
+ 0x78, // push1
+ 0x8f, 0x03, // lsp[3] (cel varies)
+ 0x38, PATCH_SELECTOR16(value), // pushi value (weight)
+ 0x78, // push1
+ 0x7a, // push2 (these items all weigh 2)
+ //
+ 0x39, 0x4b, // pushi at
+ 0x78, // push1
+ 0x8f, 0x01, // lsp[1]
+ 0x81, 0x09, // global[9] (gloryInv)
+ 0x4a, PATCH_UINT16(0x0006), // send 06
+ //
+ 0x4a, PATCH_UINT16(0x0012), // send 18d
+ 0x48, // ret
+
+ 0x39, 0x03, // pushi 3d (call has 3 args)
+ 0x39, 0x1c, // pushi 28d (thePiePan)
+ 0x7a, // push2 (loop)
+ 0x39, 0x0a, // pushi 10d (cel)
+ 0x40, PATCH_UINT16(0xffd5), PATCH_UINT16(0x0006), // call 6d [-43]
+
+ 0x39, 0x03, // pushi 3d (call has 3 args)
+ 0x39, 0x27, // pushi 39d (theBroom)
+ 0x39, 0x0a, // pushi 10d (loop)
+ 0x76, // push0 (cel)
+ 0x40, PATCH_UINT16(0xffc9), PATCH_UINT16(0x0006), // call 6d [-55]
+
+ 0x39, 0x03, // pushi 3d (call has 3 args)
+ 0x39, 0x2c, // pushi 44d (theTorch)
+ 0x39, 0x08, // pushi 8d (loop)
+ 0x39, 0x09, // pushi 9d (cel)
+ 0x40, PATCH_UINT16(0xffbc), PATCH_UINT16(0x0006), // call 6d [-68]
+
+ 0x33, 0x0a, // jmp 10d (skip waste bytes)
+ PATCH_END
+};
+
// script, description, signature patch
static const SciScriptPatcherEntry qfg4Signatures[] = {
{ true, 0, "prevent autosave from deleting save games", 1, qg4AutosaveSignature, qg4AutosavePatch },
+ { true, 0, "fix inventory leaks across restarts", 1, qfg4RestartSignature, qfg4RestartPatch },
{ true, 1, "disable volume reset on startup", 1, sci2VolumeResetSignature, sci2VolumeResetPatch },
{ true, 1, "disable video benchmarking", 1, qfg4BenchmarkSignature, qfg4BenchmarkPatch },
{ true, 7, "fix consecutive moonrises", 1, qfg4MoonriseSignature, qfg4MoonrisePatch },