diff options
author | Martin Kiewitz | 2010-08-06 18:54:58 +0000 |
---|---|---|
committer | Martin Kiewitz | 2010-08-06 18:54:58 +0000 |
commit | 753c431937ce3cb080b24c6a79f5e90548bfe431 (patch) | |
tree | a9856a95159b2a27f5607220d4753be15c4f9d82 /engines | |
parent | 993c8b70f29a90ecfc9b663836302af7f50afd2b (diff) | |
download | scummvm-rg350-753c431937ce3cb080b24c6a79f5e90548bfe431.tar.gz scummvm-rg350-753c431937ce3cb080b24c6a79f5e90548bfe431.tar.bz2 scummvm-rg350-753c431937ce3cb080b24c6a79f5e90548bfe431.zip |
SCI: adding script patching
including a patch for hoyle 4 and commenting out the workaround code inside kDisposeWindow
svn-id: r51795
Diffstat (limited to 'engines')
-rw-r--r-- | engines/sci/engine/script.cpp | 62 | ||||
-rw-r--r-- | engines/sci/engine/script.h | 5 | ||||
-rw-r--r-- | engines/sci/graphics/ports.cpp | 8 |
3 files changed, 63 insertions, 12 deletions
diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index 17ea7cf782..7c5442cc06 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -119,6 +119,13 @@ void Script::init(int script_nr, ResourceManager *resMan) { // - then another counter of bytes (0 for EOS) // - if not EOS, an adjust offset and the actual bytes // - rinse and repeat + + +// this here gets called on entry and when going out of game windows +// uEvt::port will not get changed after kDisposeWindow but a bit later, so +// we would get an invalid port handle to a kSetPort call. We just patch in +// resetting of the port selector. We destroy the stop/fade code in there, +// it seems it isn't used at all in the game. const byte hoyle4SignaturePortFix[] = { 28, 0x39, 0x09, // pushi 09 @@ -132,14 +139,22 @@ const byte hoyle4SignaturePortFix[] = { 0x38, 0xbc, 0x02, // pushi 02bc 0x38, 0x20, 0x03, // pushi 0320 0x46, // calle [xxxx] [xxxx] [xx] - 13, +5, // [skip 5 bytes] + 43, +5, // [skip 5 bytes] 0x30, 0x27, 0x00, // bnt 0027 -> end of routine 0x87, 0x00, // lap 00 0x30, 0x19, 0x00, // bnt 0019 -> fade out 0x87, 0x01, // lap 01 0x30, 0x14, 0x00, // bnt 0014 -> fade out - // [...] - 10, +20, // [skip 20 bytes] + 0x38, 0xa7, 0x00, // pushi 00a7 + 0x76, // push0 + 0x80, 0x29, 0x01, // lag 0129 + 0x4a, 0x04, // send 04 (song::stop) + 0x39, 0x27, // pushi 27 + 0x78, // push1 + 0x8f, 0x01, // lsp 01 + 0x51, 0x54, // class 54 + 0x4a, 0x06, // send 06 (PlaySong::play) + 0x33, 0x09, // jmp 09 -> end of routine 0x38, 0xaa, 0x00, // pushi 00aa 0x76, // push0 0x80, 0x29, 0x01, // lag 0129 @@ -148,8 +163,23 @@ const byte hoyle4SignaturePortFix[] = { 0 }; -const int16 hoyle4PatchPortFix[] = { - 0 +#define PATCH_END 0xFFFF +#define PATCH_ADDTOOFFSET 0x8000 +#define PATCH_GETORIGINALBYTE 0x4000 + +const uint16 hoyle4PatchPortFix[] = { + PATCH_ADDTOOFFSET | +33, + 0x38, 0x31, 0x01, // pushi 0131 (selector curEvent) + 0x76, // push0 + 0x80, 0x50, 0x00, // lag 0050 (global var 80h, "User") + 0x4a, 0x04, // send 04 (read User::curEvent) + + 0x38, 0x93, 0x00, // pushi 0093 (selector port) + 0x78, // push1 + 0x78, // push1 + 0x4a, 0x06, // send 06 (write 0 to that object::port) + 0x48, // ret + PATCH_END }; // script, description, magic DWORD, adjust @@ -158,6 +188,25 @@ const SciScriptSignature hoyle4Signatures[] = { { 0, NULL, 0, 0, NULL, NULL } }; +// will actually patch previously found signature area +void Script::applyPatch(const uint16 *patch, byte *scriptData, const uint32 scriptSize, int32 signatureOffset) { + int32 offset = signatureOffset; + uint16 patchWord = *patch; + + while (patchWord != PATCH_END) { + if (patchWord & PATCH_ADDTOOFFSET) { + offset += patchWord & ~PATCH_ADDTOOFFSET; + } else if (patchWord & PATCH_GETORIGINALBYTE) { + // TODO: implement this + } else { + scriptData[offset] = patchWord & 0xFF; + offset++; + } + patch++; + patchWord = *patch; + } +} + // will return -1 if no match was found, otherwise an offset to the start of the signature match int32 Script::findSignature(const SciScriptSignature *signature, const byte *scriptData, const uint32 scriptSize) { if (scriptSize < 4) // we need to find a DWORD, so less than 4 bytes is not okay @@ -196,7 +245,7 @@ int32 Script::findSignature(const SciScriptSignature *signature, const byte *scr return -1; } -void Script::matchSignatureAndPatch(uint16 scriptNr, const byte *scriptData, const uint32 scriptSize) { +void Script::matchSignatureAndPatch(uint16 scriptNr, byte *scriptData, const uint32 scriptSize) { if (g_sci->getGameId() == GID_HOYLE4) { const SciScriptSignature *signatureTable = hoyle4Signatures; while (signatureTable->data) { @@ -204,6 +253,7 @@ void Script::matchSignatureAndPatch(uint16 scriptNr, const byte *scriptData, con if (foundOffset != -1) { // found, so apply the patch warning("matched %s on script %d offset %d", signatureTable->description, scriptNr, foundOffset); + applyPatch(signatureTable->patch, scriptData, scriptSize, foundOffset); } signatureTable++; } diff --git a/engines/sci/engine/script.h b/engines/sci/engine/script.h index 8334cc838c..4e38c68954 100644 --- a/engines/sci/engine/script.h +++ b/engines/sci/engine/script.h @@ -37,7 +37,7 @@ struct SciScriptSignature { uint32 magicDWord; int magicOffset; const byte *data; - const int16 *patch; + const uint16 *patch; }; struct EngineState; @@ -109,8 +109,9 @@ public: void init(int script_nr, ResourceManager *resMan); void load(ResourceManager *resMan); - void matchSignatureAndPatch(uint16 scriptNr, const byte *scriptData, const uint32 scriptSize); + void matchSignatureAndPatch(uint16 scriptNr, byte *scriptData, const uint32 scriptSize); int32 findSignature(const SciScriptSignature *signature, const byte *scriptData, const uint32 scriptSize); + void applyPatch(const uint16 *patch, byte *scriptData, const uint32 scriptSize, int32 signatureOffset); virtual bool isValidOffset(uint16 offset) const; virtual SegmentRef dereference(reg_t pointer); diff --git a/engines/sci/graphics/ports.cpp b/engines/sci/graphics/ports.cpp index 2e9128cda6..76a60cbbab 100644 --- a/engines/sci/graphics/ports.cpp +++ b/engines/sci/graphics/ports.cpp @@ -250,10 +250,10 @@ void GfxPorts::kernelDisposeWindow(uint16 windowId, bool reanimate) { // and iconReplay // or inside GameControls::hide (script 978) which is called to // actually remove the window - reg_t eventObject = _segMan->findObjectByName("uEvt"); - if (!eventObject.isNull()) { - writeSelectorValue(_segMan, eventObject, SELECTOR(port), 0); - } + //reg_t eventObject = _segMan->findObjectByName("uEvt"); + //if (!eventObject.isNull()) { + // writeSelectorValue(_segMan, eventObject, SELECTOR(port), 0); + //} } } |