Skip to content

Commit

Permalink
SCI32: Fix QFG4 inventory leaks across restarts
Browse files Browse the repository at this point in the history
Fixes item properties that weren't getting reset, bug #10768
  • Loading branch information
Vhati committed Dec 11, 2018
1 parent ed7c48e commit a60a7d3
Showing 1 changed file with 138 additions and 1 deletion.
139 changes: 138 additions & 1 deletion engines/sci/engine/script_patches.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,9 @@ static const char *const selectorNameTable[] = {
"plane", // RAMA
"state", // RAMA
"getSubscriberObj", // RAMA
"loop", // QFG4
"setLooper", // QFG4
"value", // QFG4
#endif
NULL
};
Expand Down Expand Up @@ -237,7 +239,9 @@ enum ScriptPatcherSelectors {
SELECTOR_plane,
SELECTOR_state,
SELECTOR_getSubscriberObj,
SELECTOR_setLooper
SELECTOR_loop,
SELECTOR_setLooper,
SELECTOR_value
#endif
};

Expand Down Expand Up @@ -8579,9 +8583,142 @@ static const uint16 qfg4DoubleDoorSoundPatch[] = {
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
//
// We optimize a bunch of global assignments, then reset the item properties.
//
// 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
0x35, 0x01, // ldi 1d
0xb1, 0x90, // sagi (global[144 + 1] = 0)
SIG_ADDTOOFFSET(+40), // ...
0x38, SIG_UINT16(0x013b), // pushi 315
SIG_ADDTOOFFSET(+2), // ... (array index here was typoed)
0xb1, 0x90, // sagi (global[144 + ?] = 315)

0x35, 0x14, // ldi 20d
0xa1, 0xc6, // sag global[198]

0x35, 0x02, // ldi 2d
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
0xa1, 0xc6, // sag global[198]

// (stack up 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
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 },
Expand Down

0 comments on commit a60a7d3

Please sign in to comment.