aboutsummaryrefslogtreecommitdiff
path: root/engines/sci
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci')
-rw-r--r--engines/sci/engine/script_patches.cpp136
-rw-r--r--engines/sci/engine/script_patches.h36
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