diff options
author | Colin Snover | 2017-02-22 12:38:07 -0600 |
---|---|---|
committer | Colin Snover | 2017-04-23 13:07:25 -0500 |
commit | a799cb3462a220afcd705c74291075f98520d87c (patch) | |
tree | b5ac536e8532cec31e0462f6b43fe27df0ce808c | |
parent | fc02b34215f218d2e0a0f20990654b120f52efd0 (diff) | |
download | scummvm-rg350-a799cb3462a220afcd705c74291075f98520d87c.tar.gz scummvm-rg350-a799cb3462a220afcd705c74291075f98520d87c.tar.bz2 scummvm-rg350-a799cb3462a220afcd705c74291075f98520d87c.zip |
SCI: Fix SCI3 exports
Export functions may be relocated above 64k in SCI3, but exports
that do not have an entry in the relocation table must be handled
the same as SCI1.1-2.1.
-rw-r--r-- | engines/sci/engine/guest_additions.cpp | 2 | ||||
-rw-r--r-- | engines/sci/engine/kscripts.cpp | 2 | ||||
-rw-r--r-- | engines/sci/engine/script.cpp | 21 | ||||
-rw-r--r-- | engines/sci/engine/script.h | 5 |
4 files changed, 19 insertions, 11 deletions
diff --git a/engines/sci/engine/guest_additions.cpp b/engines/sci/engine/guest_additions.cpp index 4a3afcdca9..6ed2cd901a 100644 --- a/engines/sci/engine/guest_additions.cpp +++ b/engines/sci/engine/guest_additions.cpp @@ -397,7 +397,7 @@ static const byte SRTorinPatch[] = { }; void GuestAdditions::patchGameSaveRestoreTorin(Script &script) const { - const uint16 address = script.validateExportFunc(2, true); + const uint32 address = script.validateExportFunc(2, true); byte *patchPtr = const_cast<byte *>(script.getBuf(address)); memcpy(patchPtr, SRTorinPatch, sizeof(SRTorinPatch)); if (g_sci->isBE()) { diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp index 30a1fab71a..98c35fcb49 100644 --- a/engines/sci/engine/kscripts.cpp +++ b/engines/sci/engine/kscripts.cpp @@ -246,7 +246,7 @@ reg_t kScriptID(EngineState *s, int argc, reg_t *argv) { return NULL_REG; } - uint16 address = scr->validateExportFunc(index, true); + uint32 address = scr->validateExportFunc(index, true); // Point to the heap for SCI1.1 - SCI2.1 games if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1_LATE) diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index fa17dc0419..cd75a97969 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -505,6 +505,7 @@ void Script::identifyOffsets() { if (_buf->size() < 22) error("Script::identifyOffsets(): script %d smaller than expected SCI3-header", _nr); + _codeOffset = _buf->getUint32LEAt(0); sci3StringOffset = _buf->getUint32LEAt(4); sci3RelocationOffset = _buf->getUint32LEAt(8); @@ -796,23 +797,29 @@ uint32 Script::validateExportFunc(int pubfunct, bool relocSci3) { if (exportsAreWide) pubfunct *= 2; - uint32 offset; + int offset; if (getSciVersion() != SCI_VERSION_3) { offset = _exports.getUint16SEAt(pubfunct); } else { - if (!relocSci3) - offset = _exports.getUint16SEAt(pubfunct) + getCodeBlockOffsetSci3(); - else - offset = relocateOffsetSci3(pubfunct * 2 + 22); + if (!relocSci3) { + offset = _exports.getUint16SEAt(pubfunct) + getCodeBlockOffset(); + } else { + offset = relocateOffsetSci3(pubfunct * sizeof(uint16) + /* header size */ 22); + // Some offsets below 0xFFFF are left as-is in the export table, + // e.g. Lighthouse script 64990 + if (offset == -1) { + offset = _exports.getUint16SEAt(pubfunct) + getCodeBlockOffset(); + } + } } // TODO: Check if this should be done for SCI1.1 games as well if (getSciVersion() >= SCI_VERSION_2 && offset == 0) { - offset = _codeOffset; + offset = getCodeBlockOffset(); } - if (offset >= _buf->size()) + if (offset == -1 || offset >= (int)_buf->size()) error("Invalid export function pointer"); return offset; diff --git a/engines/sci/engine/script.h b/engines/sci/engine/script.h index 2be3fd0264..f63b312647 100644 --- a/engines/sci/engine/script.h +++ b/engines/sci/engine/script.h @@ -260,9 +260,10 @@ public: int relocateOffsetSci3(uint32 offset) const; /** - * Gets an offset to the beginning of the code block in a SCI3 script + * Gets an offset to the beginning of the code block in a SCI1.1 or later + * script */ - int getCodeBlockOffsetSci3() { return _buf->getInt32SEAt(0); } + int getCodeBlockOffset() { return _codeOffset; } /** * Get the offset array |