aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
Diffstat (limited to 'engines')
-rw-r--r--engines/sci/engine/script_patches.cpp117
1 files changed, 117 insertions, 0 deletions
diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp
index 5d8f730cb5..07604da5ce 100644
--- a/engines/sci/engine/script_patches.cpp
+++ b/engines/sci/engine/script_patches.cpp
@@ -103,6 +103,7 @@ static const char *const selectorNameTable[] = {
"setStep", // system selector
"cycleSpeed", // system selector
"handsOff", // system selector
+ "handsOn", // system selector
"localize", // Freddy Pharkas
"put", // Police Quest 1 VGA
"say", // Quest For Glory 1 VGA
@@ -181,6 +182,7 @@ enum ScriptPatcherSelectors {
SELECTOR_setStep,
SELECTOR_cycleSpeed,
SELECTOR_handsOff,
+ SELECTOR_handsOn,
SELECTOR_localize,
SELECTOR_put,
SELECTOR_say,
@@ -8025,6 +8027,110 @@ static const uint16 qfg4SetScalerPatch[] = {
PATCH_END
};
+// The castle's crest-operated bookshelf has an unconditional HAND message
+// which always says, "you haven't found the trigger yet," even after it's
+// open.
+//
+// We schedule the walk-out script (sLeaveSecretly) at the end of the opening
+// script (sSecret) to force hero to leave immediately, preventing any
+// interaction with an open bookshelf.
+//
+// An automatic exit is consistent with the other bookshelf passage rooms:
+// Chandelier (662) and EXIT (661).
+//
+// Clobbers Glory::handsOn() and sSecret::dispose() to do Room::setScript().
+// Both of them are made redundant by setScript's built-in disposal and
+// sLeaveSecretly's immediate use of Glory::handsOff().
+//
+// This patch has two variants, toggled to match the detected edition with
+// enablePatch() below. Aside from the patched lofsa value, they are identical.
+//
+// Applies to at least: English CD
+// Responsible method: sSecret::changeState(4) in script 663
+// Fixes bug: #10756
+static const uint16 qfg4CrestBookshelfCDSignature[] = {
+ SIG_MAGICDWORD,
+ 0x4a, SIG_UINT16(0x003e), // send 3e
+ 0x36, // push
+ SIG_ADDTOOFFSET(+5), // ...
+ 0x38, SIG_SELECTOR16(handsOn), // pushi handsOn (begin clobbering)
+ 0x76, // push0
+ 0x81, 0x01, // lag global[1] (Glory)
+ 0x4a, SIG_UINT16(0x0004), // send 04
+ 0x38, SIG_SELECTOR16(dispose), // pushi dispose
+ 0x76, // push0
+ 0x54, SIG_UINT16(0x0004), // self 04
+ SIG_END
+};
+
+static const uint16 qfg4CrestBookshelfCDPatch[] = {
+ PATCH_ADDTOOFFSET(+9),
+ 0x38, PATCH_SELECTOR16(setScript), // pushi setScript
+ 0x78, // push1
+ 0x72, PATCH_UINT16(0x01a4), // lofsa sLeaveSecretly
+ 0x36, // push
+ 0x81, 0x02, // lag global[2] (rm663)
+ 0x4a, PATCH_UINT16(0x0006), // send 06
+ 0x34, PATCH_UINT16(0x0000), // ldi 0 (waste 3 bytes)
+ PATCH_END
+};
+
+// Applies to at least: English floppy, German floppy
+static const uint16 qfg4CrestBookshelfFloppySignature[] = {
+ SIG_MAGICDWORD,
+ 0x4a, SIG_UINT16(0x003e), // send 3e
+ 0x36, // push
+ SIG_ADDTOOFFSET(+5), // ...
+ 0x38, SIG_SELECTOR16(handsOn), // pushi handsOn (begin clobbering)
+ 0x76, // push0
+ 0x81, 0x01, // lag global[1] (Glory)
+ 0x4a, SIG_UINT16(0x0004), // send 04
+ 0x38, SIG_SELECTOR16(dispose), // pushi dispose
+ 0x76, // push0
+ 0x54, SIG_UINT16(0x0004), // self 04
+ SIG_END
+};
+
+static const uint16 qfg4CrestBookshelfFloppyPatch[] = {
+ PATCH_ADDTOOFFSET(+9),
+ 0x38, PATCH_SELECTOR16(setScript), // pushi setScript
+ 0x78, // push1
+ 0x72, PATCH_UINT16(0x018c), // lofsa sLeaveSecretly
+ 0x36, // push
+ 0x81, 0x02, // lag global[2] (rm663)
+ 0x4a, PATCH_UINT16(0x0006), // send 06
+ 0x34, PATCH_UINT16(0x0000), // ldi 0 (waste 3 bytes)
+ PATCH_END
+};
+
+// Modifies room 663's sLeaveSecretly to avoid obstacles.
+//
+// Originally intended to start when hero arrives at a doorMat region, room
+// 663's walk-out script (sLeaveSecretly) ignores obstacles. The crest
+// bookshelf patch repurposes this script and requires collision detection to
+// exit properly, walking around the open bookshelf.
+//
+// Class numbers for MoveTo and PolyPath differ between CD vs floppy editions.
+// Their intervals happen to be the same, so we simply offset whatever is
+// there.
+//
+// Applies to at least: English CD, English floppy, German floppy
+// Responsible method: sLeaveSecretly::changeState(1) in script 663
+// Fixes bug: #10756
+static const uint16 qfg4CrestBookshelfMotionSignature[] = {
+ 0x51, SIG_ADDTOOFFSET(+1), // class MoveTo
+ 0x36, // push
+ SIG_MAGICDWORD,
+ 0x39, 0x1d, // pushi x = 29d
+ 0x38, SIG_UINT16(0x0097), // pushi y = 151d
+ SIG_END
+};
+
+static const uint16 qfg4CrestBookshelfMotionPatch[] = {
+ 0x51, PATCH_GETORIGINALBYTEADJUST(+1, +6), // class PolyPath
+ PATCH_END
+};
+
// The castle's great hall has a doorMat region that intermittently sends hero
// back to the room they just left (the barrel room) the instant they arrive.
//
@@ -8133,6 +8239,9 @@ static const SciScriptPatcherEntry qfg4Signatures[] = {
{ true, 545, "fix setLooper calls (1/2)", 5, qg4SetLooperSignature1, qg4SetLooperPatch1 },
{ true, 630, "fix great hall entry from barrel room", 1, qfg4GreatHallEntrySignature, qfg4GreatHallEntryPatch },
{ true, 633, "fix stairway pathfinding", 1, qfg4StairwayPathfindingSignature, qfg4StairwayPathfindingPatch },
+ { false, 663, "CD: fix crest bookshelf", 1, qfg4CrestBookshelfCDSignature, qfg4CrestBookshelfCDPatch },
+ { false, 663, "Floppy: fix crest bookshelf", 1, qfg4CrestBookshelfFloppySignature, qfg4CrestBookshelfFloppyPatch },
+ { true, 663, "CD/Floppy: fix crest bookshelf motion", 1, qfg4CrestBookshelfMotionSignature, qfg4CrestBookshelfMotionPatch },
{ true, 800, "fix setScaler calls", 1, qfg4SetScalerSignature, qfg4SetScalerPatch },
{ true, 803, "fix sliding down slope", 1, qfg4SlidingDownSlopeSignature, qfg4SlidingDownSlopePatch },
{ true, 810, "fix conditional void calls", 1, qfg4ConditionalVoidSignature, qfg4ConditionalVoidPatch },
@@ -9936,6 +10045,14 @@ void ScriptPatcher::processScript(uint16 scriptNr, SciSpan<byte> scriptData) {
enablePatch(signatureTable, "CD: audio + text support");
}
break;
+ case GID_QFG4:
+ // Chooses between similar signatures that patch with a different lofsa address
+ if (g_sci->isCD()) {
+ enablePatch(signatureTable, "CD: fix crest bookshelf");
+ } else {
+ enablePatch(signatureTable, "Floppy: fix crest bookshelf");
+ }
+ break;
default:
break;
}