diff options
Diffstat (limited to 'engines')
-rw-r--r-- | engines/sci/engine/script_patches.cpp | 136 | ||||
-rw-r--r-- | engines/sci/engine/script_patches.h | 36 |
2 files changed, 126 insertions, 46 deletions
diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp index 5f374c2c63..cf3a981347 100644 --- a/engines/sci/engine/script_patches.cpp +++ b/engines/sci/engine/script_patches.cpp @@ -103,6 +103,7 @@ static const char *const selectorNameTable[] = { "modNum", // King's Quest 6 CD / Laura Bow 2 CD for audio+text support "cycler", // Space Quest 4 / system selector "setLoop", // Laura Bow 1 Colonel's Bequest + "ignoreActors", // Laura Bow 1 Colonel's Bequest #ifdef ENABLE_SCI32 "newWith", // SCI2 array script "scrollSelections", // GK2 @@ -135,7 +136,8 @@ enum ScriptPatcherSelectors { SELECTOR_startAudio, SELECTOR_modNum, SELECTOR_cycler, - SELECTOR_setLoop + SELECTOR_setLoop, + SELECTOR_ignoreActors #ifdef ENABLE_SCI32 , SELECTOR_newWith, @@ -554,14 +556,12 @@ static const uint16 freddypharkasSignatureIntroScaling[] = { static const uint16 freddypharkasPatchIntroScaling[] = { // remove setLoop(), objects in heap are already prepared, saves 5 bytes 0x38, - PATCH_GETORIGINALBYTE(+6), - PATCH_GETORIGINALBYTE(+7), // pushi (setStep) + PATCH_GETORIGINALUINT16(+6), // pushi (setStep) 0x7a, // push2 0x39, 0x05, // pushi 05 0x3c, // dup 0x72, - PATCH_GETORIGINALBYTE(+13), - PATCH_GETORIGINALBYTE(+14), // lofsa (view) + PATCH_GETORIGINALUINT16(+13), // lofsa (view) 0x4a, 0x18, // send 18 - adjusted 0x35, 0x0a, // ldi 0a 0xa3, 0x02, // sal local[2] @@ -1314,8 +1314,7 @@ static const uint16 kq6PatchInventoryStackFix[] = { 0x12, // and 0x65, 0x30, // aTop state 0x38, // pushi "show" - PATCH_GETORIGINALBYTE(+22), - PATCH_GETORIGINALBYTE(+23), + PATCH_GETORIGINALUINT16(+22), 0x78, // push1 0x87, 0x00, // lap param[0] 0x31, 0x04, // bnt [call show using global 0] @@ -1600,8 +1599,7 @@ static const uint16 kq6CDPatchAudioTextSupport3[] = { 0x65, 0x12, // aTop dialog // followed by original addText-calling code 0x38, - PATCH_GETORIGINALBYTE(+95), - PATCH_GETORIGINALBYTE(+96), // pushi addText + PATCH_GETORIGINALUINT16(+95), // pushi (addText) 0x78, // push1 0x8f, 0x02, // lsp param[2] 0x59, 0x03, // &rest 03 @@ -1949,8 +1947,7 @@ static const uint16 kq7PatchSubtitleFix3[] = { PATCH_ADDTOOFFSET(+2), // skip over "pToa initialized code" 0x2f, 0x0c, // bt [skip init code] - saved 1 byte 0x38, - PATCH_GETORIGINALBYTE(+6), - PATCH_GETORIGINALBYTE(+7), // pushi (init) + PATCH_GETORIGINALUINT16(+6), // pushi (init) 0x76, // push0 0x54, PATCH_UINT16(0x0004), // self 04 // additionally set background color here (5 bytes) @@ -2488,12 +2485,79 @@ static const uint16 laurabow1PatchArmorOilingArmFix[] = { PATCH_END }; +// When you tell Lilly about Gertie in room 35, Lilly will then walk to the left and off the screen. +// In case Laura (ego) is in the way, the whole game will basically block and you won't be able +// to do anything except saving + restoring the game. +// +// If this happened already, the player can enter +// "send Lillian ignoreActors 1" inside the debugger to fix this situation. +// +// This issue is very difficult to solve, because Lilly also walks diagonally after walking to the left right +// under the kitchen table. This means that even if we added a few more rectangle checks, there could still be +// spots, where the game would block. +// +// Also the mover "PathOut" is used for Lillian instead of the regular "MoveTo", which would avoid other +// actors by itself. +// +// So instead we set Lilly to ignore other actors during that cutscene, which is the least invasive solution. +// +// Applies to at least: English PC Floppy, English Amiga Floppy, English Atari ST Floppy +// Responsible method: goSee::changeState(1) in script 236 +// Fixes bug: (happened during GOG Let's Play) +static const uint16 laurabow1SignatureTellLillyAboutGerieBlockingFix1[] = { + 0x7a, // puah2 + SIG_MAGICDWORD, + 0x38, SIG_UINT16(0x00c1), // pushi 00C1h + 0x38, SIG_UINT16(0x008f), // pushi 008Fh + 0x38, SIG_SELECTOR16(ignoreActors), // pushi (ignoreActors) + 0x78, // push1 + 0x76, // push0 + SIG_END +}; + +static const uint16 laurabow1PatchTellLillyAboutGertieBlockingFix1[] = { + PATCH_ADDTOOFFSET(+11), // skip over until push0 + 0x78, // push1 (change push0 to push1) + PATCH_END +}; + +// a second patch to call Lillian::ignoreActors(1) on goSee::changeState(9) in script 236 +static const uint16 laurabow1SignatureTellLillyAboutGerieBlockingFix2[] = { + 0x3c, // dup + 0x35, 0x09, // ldi 09 + 0x1a, // eq? + 0x30, SIG_UINT16(0x003f), // bnt [ret] + 0x39, SIG_ADDTOOFFSET(+1), // pushi (view) + 0x78, // push1 + 0x38, SIG_UINT16(0x0203), // pushi 203h (515d) + 0x38, SIG_ADDTOOFFSET(+2), // pushi (posn) + 0x7a, // push2 + 0x38, SIG_UINT16(0x00c9), // pushi C9h (201d) + SIG_MAGICDWORD, + 0x38, SIG_UINT16(0x0084), // pushi 84h (132d) + 0x72, SIG_ADDTOOFFSET(+2), // lofsa Lillian (different offsets for different platforms) + 0x4a, 0x0e, // send 0Eh + SIG_END +}; + +static const uint16 laurabow1PatchTellLillyAboutGertieBlockingFix2[] = { + 0x38, PATCH_SELECTOR16(ignoreActors), // pushi (ignoreActors) + 0x78, // push1 + 0x76, // push0 + 0x33, 0x00, // ldi 00 (waste 2 bytes) + PATCH_ADDTOOFFSET(+19), // skip over until send + 0x4a, 0x14, // send 14h + PATCH_END +}; + // script, description, signature patch static const SciScriptPatcherEntry laurabow1Signatures[] = { - { true, 4, "easter egg view fix", 1, laurabow1SignatureEasterEggViewFix, laurabow1PatchEasterEggViewFix }, - { true, 37, "armor open visor fix", 1, laurabow1SignatureArmorOpenVisorFix, laurabow1PatchArmorOpenVisorFix }, - { true, 37, "armor move to fix", 2, laurabow1SignatureArmorMoveToFix, laurabow1PatchArmorMoveToFix }, - { true, 37, "allowing input, after oiling arm", 1, laurabow1SignatureArmorOilingArmFix, laurabow1PatchArmorOilingArmFix }, + { true, 4, "easter egg view fix", 1, laurabow1SignatureEasterEggViewFix, laurabow1PatchEasterEggViewFix }, + { true, 37, "armor open visor fix", 1, laurabow1SignatureArmorOpenVisorFix, laurabow1PatchArmorOpenVisorFix }, + { true, 37, "armor move to fix", 2, laurabow1SignatureArmorMoveToFix, laurabow1PatchArmorMoveToFix }, + { true, 37, "allowing input, after oiling arm", 1, laurabow1SignatureArmorOilingArmFix, laurabow1PatchArmorOilingArmFix }, + { true, 236, "tell Lilly about Gertie blocking fix 1/2", 1, laurabow1SignatureTellLillyAboutGerieBlockingFix1, laurabow1PatchTellLillyAboutGertieBlockingFix1 }, + { true, 236, "tell Lilly about Gertie blocking fix 2/2", 1, laurabow1SignatureTellLillyAboutGerieBlockingFix2, laurabow1PatchTellLillyAboutGertieBlockingFix2 }, SCI_SIGNATUREENTRY_TERMINATOR }; @@ -2702,9 +2766,7 @@ static const uint16 laurabow2SignatureMuseumPartyFixEnteringSouth2[] = { static const uint16 laurabow2PatchMuseumPartyFixEnteringSouth2[] = { 0x38, // pushi - PATCH_GETORIGINALBYTEADJUST(96, -1), - PATCH_GETORIGINALBYTE(97), // get handsOff code and subtract 1 from it to get handsOn - // we should be able to not care about SCI-platform byte order, because Laura Bow 2 was only released for PC. + PATCH_GETORIGINALUINT16ADJUST(+96, -1), // get handsOff code and ubstract 1 from it to get handsOn PATCH_END }; @@ -4035,8 +4097,7 @@ static const uint16 qfg3PatchMissingPoints1[] = { PATCH_UINT16(0xFFD6), // -42 "Greet" PATCH_UINT16(0xFFB0), // -80 "Say Good-bye" PATCH_UINT16(0x03E7), // 999 END MARKER - PATCH_GETORIGINALBYTE(+28), // local[$aa][0].low - PATCH_GETORIGINALBYTE(+29), // local[$aa][0].high + PATCH_GETORIGINALUINT16(+28), // local[$aa][0] PATCH_END }; @@ -4937,14 +4998,6 @@ void ScriptPatcher::applyPatch(const SciScriptPatcherEntry *patchEntry, byte *sc break; } case PATCH_CODE_GETORIGINALBYTE: { - // get original byte from script - if (patchValue >= orgDataSize) - error("Script-Patcher: can not get requested original byte from script"); - scriptData[offset] = orgData[patchValue]; - offset++; - break; - } - case PATCH_CODE_GETORIGINALBYTEADJUST: { // get original byte from script and adjust it if (patchValue >= orgDataSize) error("Script-Patcher: can not get requested original byte from script"); @@ -4955,6 +5008,30 @@ void ScriptPatcher::applyPatch(const SciScriptPatcherEntry *patchEntry, byte *sc offset++; break; } + case PATCH_CODE_GETORIGINALUINT16: { + // get original byte from script and adjust it + if ((patchValue >= orgDataSize) || (((uint32)patchValue + 1) >= orgDataSize)) + error("Script-Patcher: can not get requested original uint16 from script"); + uint16 orgUINT16; + int16 adjustValue; + + if (!_isMacSci11) { + orgUINT16 = orgData[patchValue] | (orgData[patchValue + 1] << 8); + } else { + orgUINT16 = orgData[patchValue + 1] | (orgData[patchValue] << 8); + } + patchData++; adjustValue = (int16)(*patchData); + orgUINT16 += adjustValue; + if (!_isMacSci11) { + scriptData[offset] = orgUINT16 & 0xFF; + scriptData[offset + 1] = orgUINT16 >> 8; + } else { + scriptData[offset] = orgUINT16 >> 8; + scriptData[offset + 1] = orgUINT16 & 0xFF; + } + offset += 2; + break; + } case PATCH_CODE_UINT16: case PATCH_CODE_SELECTOR16: { byte byte1; @@ -5230,7 +5307,8 @@ void ScriptPatcher::calculateMagicDWordAndVerify(const char *signatureDescriptio } break; } - case PATCH_CODE_GETORIGINALBYTEADJUST: { + case PATCH_CODE_GETORIGINALBYTE: + case PATCH_CODE_GETORIGINALUINT16: { signatureData++; // skip over extra uint16 break; } diff --git a/engines/sci/engine/script_patches.h b/engines/sci/engine/script_patches.h index f95806a3f3..b5797be847 100644 --- a/engines/sci/engine/script_patches.h +++ b/engines/sci/engine/script_patches.h @@ -44,23 +44,25 @@ namespace Sci { #define SIG_UINT16(_value_) SIG_CODE_UINT16 | ((_value_) & 0xFF), ((_value_) >> 8) #define SIG_CODE_BYTE 0x0000 -#define PATCH_END SIG_END -#define PATCH_COMMANDMASK SIG_COMMANDMASK -#define PATCH_VALUEMASK SIG_VALUEMASK -#define PATCH_BYTEMASK SIG_BYTEMASK -#define PATCH_CODE_ADDTOOFFSET SIG_CODE_ADDTOOFFSET -#define PATCH_ADDTOOFFSET(_offset_) SIG_CODE_ADDTOOFFSET | (_offset_) -#define PATCH_CODE_GETORIGINALBYTE 0xD000 -#define PATCH_GETORIGINALBYTE(_offset_) PATCH_CODE_GETORIGINALBYTE | (_offset_) -#define PATCH_CODE_GETORIGINALBYTEADJUST 0xC000 -#define PATCH_GETORIGINALBYTEADJUST(_offset_, _adjustValue_) PATCH_CODE_GETORIGINALBYTEADJUST | (_offset_), (uint16)(_adjustValue_) -#define PATCH_CODE_SELECTOR16 SIG_CODE_SELECTOR16 -#define PATCH_SELECTOR16(_selectorID_) SIG_CODE_SELECTOR16 | SELECTOR_##_selectorID_ -#define PATCH_CODE_SELECTOR8 SIG_CODE_SELECTOR8 -#define PATCH_SELECTOR8(_selectorID_) SIG_CODE_SELECTOR8 | SELECTOR_##_selectorID_ -#define PATCH_CODE_UINT16 SIG_CODE_UINT16 -#define PATCH_UINT16(_value_) SIG_CODE_UINT16 | ((_value_) & 0xFF), ((_value_) >> 8) -#define PATCH_CODE_BYTE SIG_CODE_BYTE +#define PATCH_END SIG_END +#define PATCH_COMMANDMASK SIG_COMMANDMASK +#define PATCH_VALUEMASK SIG_VALUEMASK +#define PATCH_BYTEMASK SIG_BYTEMASK +#define PATCH_CODE_ADDTOOFFSET SIG_CODE_ADDTOOFFSET +#define PATCH_ADDTOOFFSET(_offset_) SIG_CODE_ADDTOOFFSET | (_offset_) +#define PATCH_CODE_GETORIGINALBYTE 0xC000 +#define PATCH_GETORIGINALBYTE(_offset_) PATCH_CODE_GETORIGINALBYTE | (_offset_), 0 +#define PATCH_GETORIGINALBYTEADJUST(_offset_, _adjustValue_) PATCH_CODE_GETORIGINALBYTE | (_offset_), (uint16)(_adjustValue_) +#define PATCH_CODE_GETORIGINALUINT16 0xD000 +#define PATCH_GETORIGINALUINT16(_offset_) PATCH_CODE_GETORIGINALUINT16 | (_offset_), 0 +#define PATCH_GETORIGINALUINT16ADJUST(_offset_, _adjustValue_) PATCH_CODE_GETORIGINALUINT16 | (_offset_), (uint16)(_adjustValue_) +#define PATCH_CODE_SELECTOR16 SIG_CODE_SELECTOR16 +#define PATCH_SELECTOR16(_selectorID_) SIG_CODE_SELECTOR16 | SELECTOR_##_selectorID_ +#define PATCH_CODE_SELECTOR8 SIG_CODE_SELECTOR8 +#define PATCH_SELECTOR8(_selectorID_) SIG_CODE_SELECTOR8 | SELECTOR_##_selectorID_ +#define PATCH_CODE_UINT16 SIG_CODE_UINT16 +#define PATCH_UINT16(_value_) SIG_CODE_UINT16 | ((_value_) & 0xFF), ((_value_) >> 8) +#define PATCH_CODE_BYTE SIG_CODE_BYTE // defines maximum scratch area for getting original bytes from unpatched script data #define PATCH_VALUELIMIT 4096 |