From 1736467d20279901a7e7f0e4152a2162e129903c Mon Sep 17 00:00:00 2001 From: sluicebox Date: Sat, 28 Sep 2019 16:52:17 -0700 Subject: SCI: Fix HOLYE4 and HOLYE5 Bridge invalid arithmetic Fixes bugs #11163 and #11173. Both games contain the same buggy script. --- engines/sci/engine/script_patches.cpp | 104 ++++++++++++++++++++++++++++++++++ engines/sci/engine/workarounds.cpp | 1 - 2 files changed, 104 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp index f5595908d8..1fb866db05 100644 --- a/engines/sci/engine/script_patches.cpp +++ b/engines/sci/engine/script_patches.cpp @@ -1845,6 +1845,66 @@ static const SciScriptPatcherEntry freddypharkasSignatures[] = { SCI_SIGNATUREENTRY_TERMINATOR }; +// =========================================================================== + +// During Bridge, Declarer_Second_NT:think performs a bitwise or against an +// object due to a script typo. This operation is supposed to be against +// (bridgeHand:highCard):rank but instead it's against bridgeHand:highCard. +// ThirdSeat_Trump:think has a correct version of this. Declarer_Second_NT must +// have just been missing the word "rank" in the original script. +// +// We fix this by inserting the missing rank code. To make room we remove the +// call to self:checkFinCard. It's called immediately before this patch and its +// result is stored in local1 so we just use that. Hoyle5 also has this bug. +// +// Applies to at least: English PC +// Responsible method: Declarer_Second_NT:think +// Fixes bug #11163 +static const uint16 hoyle4SignatureBridgeArithmetic[] = { + 0x36, // push [ bridgeHand:highCard ] + 0x34, SIG_UINT16(0x0f00), // ldi 0f00 + 0x14, // or [ error: bridgeHand:highCard is an object ] + 0x36, // push + 0x63, 0x42, // pToa pard + 0x4a, 0x08, // send 08 [ pard hasCard: theSuitLead (bridgeHand:highCard | 0f00) ] + SIG_MAGICDWORD, + 0x2f, 0x1d, // bt 1d + 0x83, 0x03, // lal 03 + 0x2f, 0x19, // bt 19 + 0x38, SIG_ADDTOOFFSET(+2), // pushi rank + 0x76, // push0 + 0x38, SIG_ADDTOOFFSET(+2), // pushi checkFinCard + 0x78, // push1 + 0x67, 0x48, // pTos theSuitLead + 0x54, 0x06, // self 06 [ self checkFinCard: theSuitLead ] + SIG_END +}; + +static const uint16 hoyle4PatchBridgeArithmetic[] = { + 0x38, PATCH_GETORIGINALUINT16(+17), // pushi rank + 0x76, // push0 + 0x4a, 0x04, // send 04 [ bridgeHand:highCard rank? ] + 0x36, // push + 0x34, PATCH_UINT16(0x0f00), // ldi 0f00 + 0x14, // or + 0x36, // push + 0x63, 0x42, // pToa pard + 0x4a, 0x08, // send 08 [ pard hasCard: theSuitLead ((bridgeHand:highCard):rank | 0f00) ] + 0x2f, 0x17, // bt 17 + 0x83, 0x03, // lal 03 + 0x2f, 0x13, // bt 13 + 0x38, PATCH_GETORIGINALUINT16(+17), // pushi rank + 0x76, // push0 + 0x83, 0x01, // lal 01 [ set to "self checkFinCard: theSuitLead" earlier ] + PATCH_END +}; + +// script, description, signature patch +static const SciScriptPatcherEntry hoyle4Signatures[] = { + { true, 733, "bridge arithmetic against object ", 1, hoyle4SignatureBridgeArithmetic, hoyle4PatchBridgeArithmetic }, + SCI_SIGNATUREENTRY_TERMINATOR +}; + #ifdef ENABLE_SCI32 #pragma mark - #pragma mark Hoyle 5 @@ -2037,6 +2097,45 @@ static const uint16 hoyle5PatchDisableGame[] = { PATCH_END }; +// During Bridge, Declarer_Second_NT:think performs a bitwise or against an +// object due to a script typo. This script bug is also in Hoyle4, see its +// patch notes above for more detail. +// +// Applies to at least: English PC +// Responsible method: Declarer_Second_NT:think +// Fixes bug #11173 +static const uint16 hoyle5SignatureBridgeArithmetic[] = { + 0x36, // push [ bridgeHand:highCard ] + 0x34, SIG_UINT16(0x0f00), // ldi 0f00 + 0x14, // or [ error: bridgeHand:highCard is an object ] + 0x36, // push + 0x63, 0x44, // pToa pard + 0x4a, SIG_UINT16(0x0008), // send 08 [ pard hasCard: theSuitLead (bridgeHand:highCard | 0f00) ] + 0x2f, 0x26, // bt 26 + 0x7e, SIG_ADDTOOFFSET(+2), // line + SIG_MAGICDWORD, + 0x83, 0x03, // lal 03 + 0x2f, 0x1f, // bt 1f + 0x7e, SIG_ADDTOOFFSET(+2), // line + 0x38, // pushi rank + SIG_END +}; + +static const uint16 hoyle5PatchBridgeArithmetic[] = { + 0x38, PATCH_GETORIGINALUINT16(+24), // pushi rank + 0x76, // push0 + 0x4a, PATCH_UINT16(0x0004), // send 04 [ bridgeHand:highCard rank? ] + 0x38, PATCH_UINT16(0x0f00), // pushi 0f00 + 0x14, // or + 0x36, // push + 0x63, 0x44, // pToa pard + 0x4a, PATCH_UINT16(0x0008), // send 08 [ pard hasCard: theSuitLead ((bridgeHand:highCard):rank | 0f00) ] + 0x2f, 0x20, // bt 20 + 0x83, 0x03, // lal 03 + 0x2f, 0x1c, // bt 1c + PATCH_END +}; + // script, description, signature patch static const SciScriptPatcherEntry hoyle5Signatures[] = { { true, 3, "remove kGetTime spin", 1, hoyle5SignatureSpinLoop, hoyle5PatchSpinLoop }, @@ -2045,6 +2144,7 @@ static const SciScriptPatcherEntry hoyle5Signatures[] = { { true, 500, "remove kGetTime spin", 1, hoyle5SignatureSpinLoop, hoyle5PatchSpinLoop }, { true, 64937, "remove kGetTime spin", 1, hoyle5SignatureSpinLoop, hoyle5PatchSpinLoop }, { true, 64908, "disable video benchmarking", 1, sci2BenchmarkSignature, sci2BenchmarkPatch }, + { true, 733, "bridge arithmetic against object ", 1, hoyle5SignatureBridgeArithmetic, hoyle5PatchBridgeArithmetic }, // This entry has been placed so that the broken Poker game is disabled. This game uses an external DLL, PENGIN16.DLL, // which is invoked via kWinDLL. We need to reverse the logic in PENGIN16.DLL and call it directly, in order to get this // game to work properly. Until then, this game entry will be disabled. @@ -2077,6 +2177,7 @@ static const SciScriptPatcherEntry hoyle5BridgeSignatures[] = { { true, 500, "remove kGetTime spin", 1, hoyle5SignatureSpinLoop, hoyle5PatchSpinLoop }, { true, 64937, "remove kGetTime spin", 1, hoyle5SignatureSpinLoop, hoyle5PatchSpinLoop }, { true, 64908, "disable video benchmarking", 1, sci2BenchmarkSignature, sci2BenchmarkPatch }, + { true, 733, "bridge arithmetic against object ", 1, hoyle5SignatureBridgeArithmetic, hoyle5PatchBridgeArithmetic }, { true, 975, "disable Gin Rummy", 1, hoyle5SignatureGinRummy, hoyle5PatchDisableGame }, { true, 975, "disable Cribbage", 1, hoyle5SignatureCribbage, hoyle5PatchDisableGame }, { true, 975, "disable Klondike", 1, hoyle5SignatureKlondike, hoyle5PatchDisableGame }, @@ -16981,6 +17082,9 @@ void ScriptPatcher::processScript(uint16 scriptNr, SciSpan scriptData) { case GID_FREDDYPHARKAS: signatureTable = freddypharkasSignatures; break; + case GID_HOYLE4: + signatureTable = hoyle4Signatures; + break; #ifdef ENABLE_SCI32 case GID_HOYLE5: if (g_sci->getResMan()->testResource(ResourceId(kResourceTypeScript, 100)) && diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index 394a316b80..caf7e595d6 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -80,7 +80,6 @@ const SciWorkaroundEntry arithmeticWorkarounds[] = { { GID_FANMADE, 516, 983, 0, "Wander", "setTarget", NULL, 0, 0, { WORKAROUND_FAKE, 0 } }, // op_mul: The Legend of the Lost Jewel Demo (fan made): called with object as second parameter when attacked by insects - bug #5124 { GID_GK1, 800,64992, 0, "Fwd", "doit", NULL, 0, 0, { WORKAROUND_FAKE, 1 } }, // op_gt: when Mosely finds Gabriel and Grace near the end of the game, compares the Grooper object with 7 { GID_HOYLE4, 700, -1, 1, "Code", "doit", NULL, 0, 0, { WORKAROUND_FAKE, 1 } }, // op_add: while bidding in Bridge, an object ("Bid") is added to an object in another segment ("hand3") - { GID_HOYLE5, 700, 733, 0, "Declarer_Second_NT", "think", NULL, 0, 0, { WORKAROUND_FAKE, 1 } }, // op_or: while playing Bridge - bug #11173 { GID_ICEMAN, 199, 977, 0, "Grooper", "doit", NULL, 0, 0, { WORKAROUND_FAKE, 0 } }, // op_add: While dancing with the girl { GID_MOTHERGOOSE256, -1, 999, 0, "Event", "new", NULL, 0, 0, { WORKAROUND_FAKE, 0 } }, // op_and: constantly during the game (SCI1 version) { GID_MOTHERGOOSE256, -1, 4, 0, "rm004", "doit", NULL, 0, 0, { WORKAROUND_FAKE, 0 } }, // op_or: when going north and reaching the castle (rooms 4 and 37) - bug #5101 -- cgit v1.2.3