diff --git a/engines/sci/engine/guest_additions.cpp b/engines/sci/engine/guest_additions.cpp index 4a3afcdca92b..6ed2cd901a4f 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(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 30a1fab71a32..98c35fcb497f 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 fa17dc041948..cd75a9796941 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 2be3fd026466..f63b31264705 100644 --- a/engines/sci/engine/script.h +++ b/engines/sci/engine/script.h @@ -260,9 +260,10 @@ class Script : public SegmentObj { 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