diff options
| -rw-r--r-- | engines/sci/engine/script_patches.cpp | 127 | 
1 files changed, 127 insertions, 0 deletions
| diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp index 8a901e3b90..3df6a7d785 100644 --- a/engines/sci/engine/script_patches.cpp +++ b/engines/sci/engine/script_patches.cpp @@ -11708,6 +11708,129 @@ static const uint16 qfg4FighterSpearPatch[] = {  	PATCH_END  }; +// Clicking Do on the inn door in room 260 from certain coordinates crashes the +//  CD version. This is one of several related crashes where the Grooper or +//  Grycler classes send a selector to a non-object in only the CD version. +// +// The inn door script isn't buggy, and neither are Grooper or Grycler. Instead, +//  Sierra "upgraded" the core Cycle classes in the CD version with drastically +//  different behavior after the game was already written for the first ones. +//  It's unclear what they were attempting to accomplish, but the conspicuous +//  regressions include hero stuttering when walking on every screen, the runes +//  dial refusing to spin a full rotation, random crashes at the inn door and +//  on the slippery path in room 800, and probably other problems. Meanwhile +//  GK1, a relatively stable SCI32 game released at the same time, used the same +//  Cycle classes in all its versions as QFG4 floppy without motion problems. +// +// The crashes result from complex motion edge cases but involve hero ending up +//  without a cycler at the wrong moment. These can be avoided by adding a call +//  to hero:normalize to reset a lot of state and set hero:cycler to StopWalk +//  and hero:looper to stopGroop. This is a bit of a kitchen-sink solution but +//  it does the job without side effects and only requires 4 bytes. +// +// We prevent the inn door crash by calling hero:normalize in sInInnDoor. +// +// Applies to: English CD +// Responsible method: sInInnDoor:changeState(1) +// Fixes bug: #10760 +static const uint16 qfg4InnDoorCDSignature[] = { +	0x30, SIG_MAGICDWORD,               // bnt 000e [ state 2 ] +	      SIG_UINT16(0x000e), +	0x38, SIG_UINT16(0x0111),           // pushi setHeading [ hard-coded for CD ] +	0x7a,                               // push2 +	0x76,                               // push0 +	0x7c,                               // pushSelf +	0x81, 0x00,                         // lag 00 +	0x4a, SIG_UINT16(0x0008),           // send 08  [ hero setHeading: 0 self ] +	0x32, SIG_UINT16(0x00c3),           // jmp 00c3 [ end of method ] +	SIG_END, +}; + +static const uint16 qfg4InnDoorCDPatch[] = { +	0x31, 0x0f,                         // bnt 0f [ state 2 ] +	0x38, PATCH_SELECTOR16(normalize),  // pushi normalize +	0x76,                               // push0 +	0x38, PATCH_UINT16(0x0111),         // pushi setHeading [ hard-coded for CD ] +	0x7a,                               // push2 +	0x76,                               // push0 +	0x7c,                               // pushSelf +	0x81, 0x00,                         // lag 00 +	0x4a, PATCH_UINT16(0x000c),         // send 0c [ hero normalize: setHeading: 0 self ] +	PATCH_END +}; + +// Walking around the base of the slippery slope in room 800 can crash the CD +//  version in either the Grooper or Grycler classes. See the inn door patch +//  above for details on these regressions and their solution. +// +// The script sSlippery runs when walking up the slope and sWalksDown runs when +//  walking down. Both are vulnerable to Grooper/Grycler crashes and both can be +//  fixed by adding hero:normalize calls. +// +// We also include a version of the sWalksDown patch for the instruction sizes +//  in the NRS patch, which is important as that ships with the GOG version. +// +// Applies to: English CD +// Responsible methods: sSlippery:changeState(0), sWalksDown:changeState(0) +// Fixes bug: #10747 +static const uint16 qfg4WalkUpSlopeCDSignature[] = { +	SIG_MAGICDWORD, +	0x38, SIG_UINT16(0x0142),           // pushi setMotion [ hard-coded for CD ] +	0x78,                               // push1 +	0x76,                               // push0 +	SIG_ADDTOOFFSET(+8), +	0x4a, SIG_UINT16(0x000e),           // send 0e [ hero setMotion: 0 ... ] +	SIG_END, +}; + +static const uint16 qfg4WalkUpSlopeCDPatch[] = { +	0x38, PATCH_SELECTOR16(normalize),  // pushi normalize +	0x39, 0x00,                         // pushi 00 +	PATCH_ADDTOOFFSET(+8), +	0x4a, PATCH_UINT16(0x000c),         // send 0c [ hero normalize: ... ] +	PATCH_END +}; + +static const uint16 qfg4WalkDownSlopeCDSignature[] = { +	0x3c,                               // dup +	0x35, SIG_MAGICDWORD, 0x00,         // ldi 00 +	0x1a,                               // eq? +	0x31, 0x1e,                         // bnt 1e [ state 1 ] +	0x38, SIG_UINT16(0x0218),           // pushi handsOff [ hard-coded for CD ] +	SIG_ADDTOOFFSET(+15), +	0x4a, SIG_UINT16(0x0008),           // send 08 [ hero setStep: ... ] +	SIG_END, +}; + +static const uint16 qfg4WalkDownSlopeCDPatch[] = { +	0x2f, 0x22,                         // bt 22 [ state 1 ] +	0x38, PATCH_SELECTOR16(normalize),  // pushi normalize +	0x76,                               // push0 +	PATCH_ADDTOOFFSET(+18), +	0x4a, PATCH_UINT16(0x000c),         // send 0c [ hero normalize: setStep: ... ] +	PATCH_END +}; + +static const uint16 qfg4WalkDownSlopeNrsSignature[] = { +	0x3c,                               // dup +	0x35, SIG_MAGICDWORD, 0x00,         // ldi 00 +	0x1a,                               // eq? +	0x30, SIG_UINT16(0x001f),           // bnt 001f [ state 1 ] +	0x38, SIG_UINT16(0x0218),           // pushi handsOff [ hard-coded for CD ] +	SIG_ADDTOOFFSET(+15), +	0x4a, SIG_UINT16(0x0008),           // send 08 [ hero setStep: ... ] +	SIG_END, +}; + +static const uint16 qfg4WalkDownSlopeNrsPatch[] = { +	0x2e, PATCH_UINT16(0x0023),         // bt 0023 [ state 1 ] +	0x38, PATCH_SELECTOR16(normalize),  // pushi normalize +	0x76,                               // push0 +	PATCH_ADDTOOFFSET(+18), +	0x4a, PATCH_UINT16(0x000c),         // send 0c [ hero normalize: setStep: ... ] +	PATCH_END +}; +  // The NRS fan-patch for wraiths has a bug which locks up the game. This occurs  //  when a wraith initializes while game time is greater than $7fff. The patch  //  throttles wraith:doit to execute no more than once per game tick, which it @@ -11860,6 +11983,7 @@ static const SciScriptPatcherEntry qfg4Signatures[] = {  	{  true,    53, "NRS: fix wraith lockup",                      1, qfg4WraithLockupNrsSignature,  qfg4WraithLockupNrsPatch },  	{  true,    83, "fix incorrect array type",                    1, qfg4TrapArrayTypeSignature,    qfg4TrapArrayTypePatch },  	{  true,   250, "fix hectapus death lockup",                   1, qfg4HectapusDeathSignature,    qfg4HectapusDeathPatch }, +	{  true,   260, "CD: fix inn door crash",                      1, qfg4InnDoorCDSignature,        qfg4InnDoorCDPatch },  	{  true,   270, "fix town gate after a staff dream",           1, qfg4DreamGateSignature,        qfg4DreamGatePatch },  	{  true,   270, "fix town gate doormat at night",              1, qfg4TownGateDoormatSignature,  qfg4TownGateDoormatPatch },  	{  true,   320, "fix pathfinding at the inn",                  1, qfg4InnPathfindingSignature,   qfg4InnPathfindingPatch }, @@ -11916,6 +12040,9 @@ static const SciScriptPatcherEntry qfg4Signatures[] = {  	{  true,   801, "fix runes puzzle (1/2)",                      1, qfg4RunesPuzzleSignature1,     qfg4RunesPuzzlePatch1 },  	{  true,   801, "fix runes puzzle (2/2)",                      1, qfg4RunesPuzzleSignature2,     qfg4RunesPuzzlePatch2 },  	{  true,   803, "fix sliding down slope",                      1, qfg4SlidingDownSlopeSignature, qfg4SlidingDownSlopePatch }, +	{  true,   803, "CD: fix walking up slippery slope",           1, qfg4WalkUpSlopeCDSignature,    qfg4WalkUpSlopeCDPatch }, +	{  true,   803, "CD: fix walking down slippery slope",         1, qfg4WalkDownSlopeCDSignature,  qfg4WalkDownSlopeCDPatch }, +	{  true,   803, "NRS: fix walking down slippery slope",        1, qfg4WalkDownSlopeNrsSignature, qfg4WalkDownSlopeNrsPatch },  	{  true,   820, "fix rabbit combat",                           1, qfg4RabbitCombatSignature,     qfg4RabbitCombatPatch },  	{  true,   810, "fix conditional void calls",                  1, qfg4ConditionalVoidSignature,  qfg4ConditionalVoidPatch },  	{  true,   830, "fix conditional void calls",                  2, qfg4ConditionalVoidSignature,  qfg4ConditionalVoidPatch }, | 
