aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine/script_patches.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/engine/script_patches.cpp')
-rw-r--r--engines/sci/engine/script_patches.cpp372
1 files changed, 372 insertions, 0 deletions
diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp
index e4f8371448..5d741300c4 100644
--- a/engines/sci/engine/script_patches.cpp
+++ b/engines/sci/engine/script_patches.cpp
@@ -183,6 +183,7 @@ static const char *const selectorNameTable[] = {
"getCursor", // QFG4
"heading", // QFG4
"moveSpeed", // QFG4
+ "register", // QFG4
"sayMessage", // QFG4
"setCursor", // QFG4
"setLooper", // QFG4
@@ -296,6 +297,7 @@ enum ScriptPatcherSelectors {
SELECTOR_getCursor,
SELECTOR_heading,
SELECTOR_moveSpeed,
+ SELECTOR_register,
SELECTOR_sayMessage,
SELECTOR_setCursor,
SELECTOR_setLooper,
@@ -12723,6 +12725,368 @@ static const uint16 qfg4LookDungeonPatch[] = {
PATCH_END
};
+// When approaching the door to the great hall in staircase room 627 at night,
+// the message "You hear voices..." continues to occur even after witnessing
+// the argument between Katrina and Ad Avis in the floppy version. This is due
+// to not testing flag 112, which is set by the argument scene, and was fixed
+// in the CD version. We add the missing flag test.
+//
+// This incomplete logic to determine if Katrina and Ad Avis are in the great
+// hall is duplicated throughout this script. Although Sierra fixed this
+// instance in the CD version, it's the only one they fixed, while adding more
+// that lack the flag test. We fix those bugs in subsequent patches.
+//
+// Applies to: English Floppy, German Floppy
+// Responsible method: sDisplay:changeState(0)
+// Fixes bug: #10799
+static const uint16 qfg4ArgumentMessageFloppySignature[] = {
+ SIG_MAGICDWORD,
+ 0x83, 0x02, // lal 02 [ message already said? ]
+ 0x30, SIG_UINT16(0x0013), // bnt 0013 [ say message ]
+ 0x38, SIG_SELECTOR16(handsOn), // pushi handsOn
+ 0x76, // push0
+ 0x81, 0x01, // lag 01
+ 0x4a, SIG_UINT16(0x0004), // send 04 [ Glory handsOn: ]
+ 0x38, SIG_SELECTOR16(dispose), // pushi dispose
+ 0x76, // push0
+ 0x54, SIG_UINT16(0x0004), // self 04
+ 0x32, SIG_UINT16(0x0079), // jmp 0079 [ end of method ]
+ SIG_ADDTOOFFSET(+38),
+ 0x38, SIG_SELECTOR16(dispose), // pushi dispose
+ 0x76, // push0
+ 0x54, SIG_UINT16(0x0004), // self 04 [ self dispose: ]
+ 0x32, SIG_UINT16(0x0049), // jmp 0049 [ end of method ]
+ SIG_END,
+};
+
+static const uint16 qfg4ArgumentMessageFloppyPatch[] = {
+ PATCH_ADDTOOFFSET(+2),
+ 0x2f, 0x09, // bt 09 [ skip message if already said ]
+ 0x78, // push1
+ 0x39, 0x70, // pushi 70 [ flag 112 ]
+ 0x45, 0x04, PATCH_UINT16(0x0002), // callb proc0_4 02 [ has argument occurred? ]
+ 0x31, 0x0b, // bnt 0b [ say message ]
+ 0x38, PATCH_SELECTOR16(handsOn), // pushi handsOn
+ 0x76, // push0
+ 0x81, 0x01, // lag 01
+ 0x4a, PATCH_UINT16(0x0004), // send 04 [ Glory handsOn: ]
+ 0x33, 0x26, // jmp 26 [ self dispose:, end of method ]
+ PATCH_END,
+};
+
+// The great hall door options in room 627 are incorrect at night after Katrina
+// and Ad Avis argue. rm620Code:init is missing a flag test to prevent the
+// argument options from reoccurring. We add the missing flag test.
+//
+// Applies to: All versions
+// Responsible methods: rm620Code:init
+// Fixes bug: #10799
+static const uint16 qfg4Room627DoorOptionsSignature[] = {
+ 0x89, 0x0b, // lsg 0b [ room number ]
+ SIG_ADDTOOFFSET(+28),
+ 0x39, 0x05, // pushi 05 [ argument door options ]
+ 0x72, SIG_ADDTOOFFSET(+2), // lofsa doorTopTeller
+ 0x4a, SIG_UINT16(0x000e), // send 0e [ doorTopTeller init: pUpperDoor 620 8 155 5 ]
+ SIG_MAGICDWORD,
+ 0x33, 0x19, // jmp 19
+ 0x38, SIG_SELECTOR16(init), // pushi init
+ 0x38, SIG_UINT16(0x0005), // pushi 0005
+ 0x72, SIG_ADDTOOFFSET(+2), // lofsa pUpperDoor
+ 0x36, // push
+ 0x38, SIG_UINT16(0x026c), // pushi 026c
+ 0x39, 0x08, // pushi 08
+ 0x38, SIG_UINT16(0x009b), // pushi 009b
+ 0x78, // push1 [ normal door options ]
+ 0x72, SIG_ADDTOOFFSET(+2), // lofsa doorTopTeller
+ 0x4a, SIG_UINT16(0x000e), // send 0e [ doorTopTeller init: pUpperDoor 620 8 155 1 ]
+ SIG_END
+};
+
+static const uint16 qfg4Room627DoorOptionsPatch[] = {
+ 0x33, 0x0a, // jmp 0a
+ PATCH_ADDTOOFFSET(+28),
+ 0x89, 0x0b, // lsg 0b [ room number ]
+ 0x34, PATCH_UINT16(0x0273), // ldi 627d
+ 0x1a, // eq?
+ 0x31, 0x14, // bnt 14 [ normal door options ]
+ 0x81, 0x79, // lag 79 [ night ]
+ 0x31, 0x10, // bnt 10 [ normal door options ]
+ 0x78, // push1
+ 0x39, 0x70, // pushi 70 [ flag 112 ]
+ 0x45, 0x04, PATCH_UINT16(0x0002), // callb proc0_4 02 [ has argument occurred? ]
+ 0x2f, 0x07, // bt 07 [ normal door options ]
+ 0x39, 0x05, // pushi 05
+ 0x33, 0x04, // jmp 04 [ argument door options ]
+ PATCH_END
+};
+
+// The responses to the great hall door options in room 627 have problems. The
+// floppy version is missing message handlers for Open Door and Knock on Door
+// during the argument and so the door doesn't open. The CD version displays
+// the wrong Knock on Door message. All versions fail to test flag 112 to see
+// if the argument has already occurred.
+//
+// We fix all of this with a two part patch. First, sListened:register now
+// controls which message is displayed before the door opens. This allows
+// doorTopTeller:sayMessage to specify the correct message before running it.
+// To add flag tests, new message handlers, and set sListened:register, we take
+// advantage of identical message handlers in doorTopTeller:sayMessage. These
+// provide plenty of room for new code that then jumps into another handler to
+// continue and complete the work.
+//
+// Applies to: All versions
+// Responsible methods: sListened:changeState(0), doorTopTeller:sayMessage
+// Fixes bug: #10799
+static const uint16 qfg4Room627DoorResponsesSignature1[] = {
+ 0x65, SIG_ADDTOOFFSET(+17), // aTop state
+ 0x38, SIG_SELECTOR16(say), // pushi say
+ 0x38, SIG_UINT16(0x0006), // pushi 0006
+ 0x39, 0x08, // pushi 08
+ 0x38, SIG_UINT16(0x009b), // pushi 009b
+ 0x39, SIG_MAGICDWORD, 0x09, // pushi 09
+ 0x78, // push1
+ 0x7c, // pushSelf
+ 0x38, SIG_UINT16(0x026c), // pushi 026c
+ 0x81, 0x5b, // lag 5b
+ 0x4a, SIG_UINT16(0x0010), // send 10 [ gloryMessager say: 8 155 9 1 self 620 ]
+ 0x32, // jmp ... [ end of method ]
+ SIG_END
+};
+
+static const uint16 qfg4Room627DoorResponsesPatch1[] = {
+ PATCH_ADDTOOFFSET(+21),
+ 0x39, 0x06, // pushi 06
+ 0x39, 0x08, // pushi 08
+ 0x38, PATCH_UINT16(0x009b), // pushi 009b
+ 0x39, 0x09, // pushi 09
+ 0x63, PATCH_GETORIGINALBYTEADJUST(+1, 0x10), // pToa register
+ 0x02, // add
+ 0x36, // push
+ 0x78, // push1
+ 0x7c, // pushSelf
+ 0x38, PATCH_UINT16(0x026c), // pushi 026c
+ 0x81, 0x5b, // lag 5b
+ 0x4a, PATCH_UINT16(0x0010), // send 10 [ gloryMessager say: 8 155 (9 + register) 1 self 620 ]
+ PATCH_END
+};
+
+static const uint16 qfg4Room627DoorResponsesFloppySignature2[] = {
+ // Pick Lock (no argument) - missing flag check
+ SIG_MAGICDWORD,
+ 0x30, SIG_UINT16(0x0072), // bnt 0072 [ next message handler ]
+ 0x81, 0x79, // lag 79 [ night ]
+ 0x30, SIG_UINT16(0x0028), // bnt 0028
+ 0x89, 0x0b, // lsg 0b [ room number ]
+ 0x34, SIG_UINT16(0x0273), // ldi 627d
+ 0x1a, // eq?
+ 0x30, SIG_UINT16(0x001f), // bnt 001f
+ 0x38, SIG_UINT16(0x00fe), // pushi clean [ hard-coded for floppy ]
+ 0x76, // push0
+ 0x54, SIG_UINT16(0x0004), // self 04
+ 0x78, // push1
+ 0x39, 0x71, // pushi 71
+ 0x45, 0x02, SIG_UINT16(0x0002), // callb proc0_2 02
+ 0x38, SIG_SELECTOR16(setScript), // pushi setScript
+ 0x78, // push1
+ 0x72, SIG_UINT16(0x0082), // lofsa sListened
+ 0x36, // push
+ 0x72, SIG_UINT16(0x01ae), // lofsa pUpperDoor
+ 0x4a, SIG_UINT16(0x0006), // send 06 [ pUpperDoor setScript: sListened ]
+ 0x32, SIG_UINT16(0x0131), // jmp 0131
+ 0x38, SIG_UINT16(0x0338), // pushi trySkill [ hard-coded for floppy ]
+ 0x7a, // push2
+ 0x39, 0x09, // pushi 09
+ 0x88, SIG_UINT16(0x01a6), // lsg 01a6
+ 0x81, 0x00, // lag 00
+ 0x4a, SIG_UINT16(0x0008), // send 08 [ hero trySkill: 9 global422 ]
+ SIG_ADDTOOFFSET(+0xe4),
+ // Open Door (no argument) - missing flag check
+ 0x78, // push1
+ 0x39, 0x71, // pushi 71
+ 0x45, 0x02, SIG_UINT16(0x0002), // callb proc0_2 02
+ 0x38, SIG_UINT16(0x00fe), // pushi clean [ hard-coded for floppy ]
+ 0x76, // push0
+ 0x54, SIG_UINT16(0x0004), // self 04
+ SIG_END
+};
+
+static const uint16 qfg4Room627DoorResponsesFloppyPatch2[] = {
+ // Pick Lock (no argument) - missing flag check
+ 0x30, PATCH_UINT16(0x001a), // bnt 001a [ next message handler ]
+ PATCH_ADDTOOFFSET(+2),
+ 0x30, PATCH_UINT16(0x00a1), // bnt 00a1 [ normal pick lock code in duplicate handler ]
+ PATCH_ADDTOOFFSET(+6),
+ 0x30, PATCH_UINT16(0x0098), // bnt 0098 [ normal pick lock code in duplicate handler ]
+ 0x78, // push1
+ 0x39, 0x70, // pushi 70 [ flag 112 ]
+ 0x45, 0x04, PATCH_UINT16(0x0002), // callb proc0_4 02 [ has argument occurred? ]
+ 0x2e, PATCH_UINT16(0x008e), // bt 008e [ normal pick lock code in duplicate handler ]
+ 0x33, 0x6d, // jmp 6d [ continue argument code in duplicate handler ]
+ // Open Door (argument) - missing from floppy
+ 0x3c, // dup
+ 0x35, 0x0a, // ldi 0a
+ 0x1a, // eq?
+ 0x31, 0x07, // bnt 07 [ next message handler ]
+ 0x38, PATCH_SELECTOR16(register), // pushi register
+ 0x78, // push1
+ 0x78, // push1 [ "Ignoring the voices, you fling the door open..." ]
+ 0x33, 0x0b, // jmp 0b
+ // Knock on Door (argument) - missing from floppy
+ 0x3c, // dup
+ 0x35, 0x0b, // ldi 0b
+ 0x1a, // eq?
+ 0x31, 0x45, // bnt 45 [ next message handler ]
+ 0x38, PATCH_SELECTOR16(register), // pushi register
+ 0x78, // push1
+ 0x7a, // push2 [ "Very polite of you. The door opens to your knock..." ]
+ 0x72, PATCH_UINT16(0x0082), // lofsa sListened
+ 0x4a, PATCH_UINT16(0x0006), // send 0006 [ sListened register: 1 or 2 ]
+ 0x32, PATCH_UINT16(0x004c), // jmp 004c [ continue argument code in duplicate handler ]
+ PATCH_ADDTOOFFSET(+0xe4),
+ // Open Door (no argument) - missing flag check
+ 0x78, // push1
+ 0x39, 0x70, // pushi 70 [ flag 112 ]
+ 0x45, 0x04, PATCH_UINT16(0x0002), // callb proc0_4 02 [ has argument occurred? ]
+ 0x2f, 0x16, // bt 16 [ skip argument code if argument occurred ]
+ 0x32, PATCH_UINT16(0xff5c), // jmp ff5c [ continue argument code in duplicate handler ]
+ PATCH_END
+};
+
+static const uint16 qfg4Room627DoorResponsesCDSignature2[] = {
+ // Pick Lock (no argument) - missing flag check
+ 0x38, SIG_UINT16(0x0101), // pushi clean [ hard-coded for CD ]
+ 0x76, // push0
+ SIG_MAGICDWORD,
+ 0x54, SIG_UINT16(0x0004), // self 04
+ 0x78, // push1
+ 0x39, 0x71, // pushi 71
+ 0x45, 0x02, SIG_UINT16(0x0002), // callb proc0_2 02
+ SIG_ADDTOOFFSET(+0x13b),
+ // Open Door (no argument) - missing flag check
+ 0x78, // push1
+ 0x39, 0x71, // pushi 71
+ 0x45, 0x02, SIG_UINT16(0x0002), // callb proc0_2 02
+ 0x38, SIG_UINT16(0x0101), // pushi clean [ hard-coded for CD ]
+ 0x76, // push0
+ 0x54, SIG_UINT16(0x0004), // self 04
+ SIG_ADDTOOFFSET(+0x7c),
+ // Knock on Door (argument) - wrong message (CD regression)
+ 0x78, // push1
+ 0x39, 0x71, // pushi 71
+ 0x45, 0x02, SIG_UINT16(0x0002), // callb proc0_2 02
+ 0x38, SIG_UINT16(0x0101), // pushi clean [ hard-coded for CD ]
+ 0x76, // push0
+ 0x54, SIG_UINT16(0x0004), // self 04
+ SIG_END
+};
+
+static const uint16 qfg4Room627DoorResponsesCDPatch2[] = {
+ // Pick Lock (no argument) - missing flag check
+ 0x78, // push1
+ 0x39, 0x70, // pushi 70 [ flag 112 ]
+ 0x45, 0x04, PATCH_UINT16(0x0002), // callb proc0_4 02 [ has argument occurred? ]
+ 0x2f, 0x16, // bt 16 [ skip argument code if argument occurred ]
+ 0x32, PATCH_UINT16(0x0089), // jmp 0089 [ continue argument code in duplicate handler ]
+ PATCH_ADDTOOFFSET(+0x13d),
+ // Open Door (no argument) - missing flag check
+ 0x78, // push1
+ 0x39, 0x70, // pushi 70 [ flag 112 ]
+ 0x45, 0x04, PATCH_UINT16(0x0002), // callb proc0_4 02 [ has argument occurred? ]
+ 0x2f, 0x16, // bt 16 [ skip argument code if argument occurred ]
+ 0x32, PATCH_UINT16(0xff40), // jmp ff40 [ continue argument code in duplicate handler ]
+ PATCH_ADDTOOFFSET(+0x7e),
+ // Knock on Door (argument) - wrong message (CD regression)
+ 0x38, PATCH_SELECTOR16(register), // pushi register
+ 0x78, // push1
+ 0x7a, // push2 [ "Very polite of you. The door opens to your knock..." ]
+ 0x72, PATCH_UINT16(0x00b6), // lofsa sListened
+ 0x4a, PATCH_UINT16(0x0006), // send 0006 [ sListened register: 2 ]
+ 0x32, PATCH_UINT16(0xfeb4), // jmp feb4 [ continue argument code in duplicate handler ]
+ PATCH_END
+};
+
+// When entering the great hall from room 627 while Katrina and Ad Avis argue,
+// room 627 says that the door squeaks even if it was oiled. The flag tests are
+// incorrect and out of sync with the logic in the great hall that plays the
+// squeak that kills ego. This logic had other bugs in the floppy version,
+// including setting an incorrect flag, and this patch fixes those too. The end
+// result is that the squeak message isn't displayed if the oiled flag is set.
+//
+// Applies to: All versions
+// Responsible methods: sListened:changeState(2), sListened2:changeState(2) (CD)
+// Fixes bug: #10799
+static const uint16 qfg4Room627SqueakFloppySignature[] = {
+ 0x89, 0x7d, // lsg 7d [ character type ]
+ 0x35, SIG_MAGICDWORD, 0x02, // ldi 02 [ thief ]
+ 0x1a, // eq? [ is thief? ]
+ 0x31, 0x08, // bnt 08 [ skip oil test if thief (incorrect, removed from CD) ]
+ 0x78, // push1
+ 0x39, 0x72, // pushi 72 [ flag 114 ]
+ 0x45, 0x04, SIG_UINT16(0x0002), // callb proc0_4 02 [ is door oiled? ]
+ 0x18, // not
+ 0x2f, 0x07, // bt 07 [ squeak message ]
+ 0x78, // push1
+ 0x39, 0x71, // pushi 71 [ flag 113 ]
+ 0x45, 0x04, SIG_UINT16(0x0002), // callb proc0_4 02 [ selected action other than listening? (incorrect) ]
+ 0x31, 0x33, // bnt 33 [ skip squeak message ]
+ SIG_ADDTOOFFSET(+20),
+ 0x78, // push1
+ 0x39, 0x71, // pushi 71 [ flag 113 ]
+ 0x45, 0x02, SIG_UINT16(0x0002), // callb proc0_2 02 [ set flag 113 (incorrect, removed from CD) ]
+ SIG_END,
+};
+
+static const uint16 qfg4Room627SqueakFloppyPatch[] = {
+ 0x33, 0x05, // jmp 05 [ skip thief test, always test oil flag ]
+ PATCH_ADDTOOFFSET(+15),
+ 0x32, PATCH_UINT16(0x0039), // jmp 0039 [ skip squeak message if door has been oiled ]
+ PATCH_ADDTOOFFSET(+26),
+ 0x32, PATCH_UINT16(0x0004), // jmp 0004 [ don't set flag 113 ]
+ PATCH_END,
+};
+
+static const uint16 qfg4Room627SqueakCDSignature[] = {
+ 0x78, // push1
+ 0x39, 0x72, // pushi 72 [ flag 114 ]
+ 0x45, 0x04, SIG_UINT16(0x0002), // callb proc0_4 02 [ is door oiled? ]
+ SIG_MAGICDWORD,
+ 0x18, // not
+ 0x2f, 0x07, // bt 07 [ squeak message ]
+ 0x78, // push1
+ 0x39, 0x71, // pushi 71 [ flag 113 ]
+ 0x45, 0x04, SIG_UINT16(0x0002), // callb proc0_4 02 [ selected action other than listening? (incorrect) ]
+ 0x31, 0x2c, // bnt 2c [ skip squeak message ]
+ SIG_END,
+};
+
+static const uint16 qfg4Room627SqueakCDPatch[] = {
+ PATCH_ADDTOOFFSET(+10),
+ 0x32, PATCH_UINT16(0x0032), // jmp 0032 [ skip squeak message if door has been oiled ]
+ PATCH_END,
+};
+
+// Looking through the keyhole in room 627 into the great hall responds with a
+// generic message instead of the specific room description. sPeepingTom only
+// says the great hall message at night, which isn't relevant, and didn't work
+// since doorTeller wouldn't offer the keyhole option at night due to a missing
+// flag check which we fix. We restore the message by removing the night test.
+//
+// Applies to: All versions
+// Responsible method: sPeepingTom:changeState(1)
+// Fixes bug: #10799
+static const uint16 qfg4GreatHallKeyholeSignature[] = {
+ SIG_MAGICDWORD,
+ 0x81, 0x79, // lag 79 [ night ]
+ 0x31, 0x1a, // bnt 1a [ skip keyhole message during day ]
+ 0x38, SIG_SELECTOR16(say), // pushi say
+ SIG_END
+};
+
+static const uint16 qfg4GreatHallKeyholePatch[] = {
+ 0x33, 0x02, // jmp 02 [ say keyhole message regardless of time ]
+ PATCH_END
+};
+
// script, description, signature patch
static const SciScriptPatcherEntry qfg4Signatures[] = {
{ true, 0, "prevent autosave from deleting save games", 1, qfg4AutosaveSignature, qfg4AutosavePatch },
@@ -12773,6 +13137,14 @@ static const SciScriptPatcherEntry qfg4Signatures[] = {
{ true, 600, "fix passable closed gate after geas", 1, qfg4DungeonGateSignature, qfg4DungeonGatePatch },
{ true, 630, "fix great hall entry from barrel room", 1, qfg4GreatHallEntrySignature, qfg4GreatHallEntryPatch },
{ true, 633, "fix stairway pathfinding", 1, qfg4StairwayPathfindingSignature, qfg4StairwayPathfindingPatch },
+ { true, 633, "Floppy: fix argument message", 1, qfg4ArgumentMessageFloppySignature, qfg4ArgumentMessageFloppyPatch },
+ { true, 633, "fix room 627 door options", 1, qfg4Room627DoorOptionsSignature, qfg4Room627DoorOptionsPatch },
+ { true, 633, "fix room 627 door responses (1/2)", 1, qfg4Room627DoorResponsesSignature1, qfg4Room627DoorResponsesPatch1 },
+ { true, 633, "Floppy: fix room 627 door responses (2/2)", 1, qfg4Room627DoorResponsesFloppySignature2, qfg4Room627DoorResponsesFloppyPatch2 },
+ { true, 633, "CD: fix room 627 door responses (2/2)", 1, qfg4Room627DoorResponsesCDSignature2, qfg4Room627DoorResponsesCDPatch2 },
+ { true, 633, "Floppy: fix room 627 door squeak", 1, qfg4Room627SqueakFloppySignature, qfg4Room627SqueakFloppyPatch },
+ { true, 633, "CD: fix room 627 door squeak", 2, qfg4Room627SqueakCDSignature, qfg4Room627SqueakCDPatch },
+ { true, 633, "fix great hall keyhole message", 1, qfg4GreatHallKeyholeSignature, qfg4GreatHallKeyholePatch },
{ true, 643, "fix iron safe's east door sending hero west", 1, qfg4SafeDoorEastSignature, qfg4SafeDoorEastPatch },
{ true, 643, "fix iron safe's door oil flags", 1, qfg4SafeDoorOilSignature, qfg4SafeDoorOilPatch },
{ true, 644, "fix castle door open message for rogue", 2, qfg4StuckDoorSignature, qfg4StuckDoorPatch },