diff options
-rw-r--r-- | engines/sci/engine/script.cpp | 30 | ||||
-rw-r--r-- | engines/sci/engine/script.h | 6 | ||||
-rw-r--r-- | engines/sci/engine/vm.cpp | 23 |
3 files changed, 28 insertions, 31 deletions
diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index 897ceccad3..80aaedfece 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -385,7 +385,7 @@ void Script::setLockers(int lockers) { _lockers = lockers; } -uint16 Script::validateExportFunc(int pubfunct, bool relocate) { +uint16 Script::validateExportFunc(int pubfunct, bool relocateSci3) { bool exportsAreWide = (g_sci->_features->detectLofsType() == SCI_VERSION_1_MIDDLE); if (_numExports <= pubfunct) { @@ -398,15 +398,15 @@ uint16 Script::validateExportFunc(int pubfunct, bool relocate) { uint16 offset; - if (getSciVersion() != SCI_VERSION_3 || !relocate) { + if (getSciVersion() != SCI_VERSION_3) { offset = READ_SCI11ENDIAN_UINT16(_exportTable + pubfunct); } else { - offset = relocateOffsetSci3(pubfunct * 2 + 22); + if (!relocateSci3) + offset = READ_SCI11ENDIAN_UINT16(_exportTable + pubfunct) + getCodeBlockOffsetSci3(); + else + offset = relocateOffsetSci3(pubfunct * 2 + 22); } - if (offset >= _bufSize) - error("Invalid export function pointer"); - // Check if the offset found points to a second export table (e.g. script 912 // in Camelot and script 306 in KQ4). Such offsets are usually small (i.e. < 10), // thus easily distinguished from actual code offsets. @@ -419,11 +419,23 @@ uint16 Script::validateExportFunc(int pubfunct, bool relocate) { if (secondExportTable) { secondExportTable += 3; // skip header plus 2 bytes (secondExportTable is a uint16 pointer) offset = READ_SCI11ENDIAN_UINT16(secondExportTable + pubfunct); - if (offset >= _bufSize) - error("Invalid export function pointer"); } } + if (!offset) { +#ifdef ENABLE_SCI32 + // WORKAROUNDS for invalid (empty) exports + if (g_sci->getGameId() == GID_TORIN && _nr == 64036) { + } else if (g_sci->getGameId() == GID_RAMA && _nr == 64908) { + } else +#endif + error("Request for invalid exported function 0x%x of script %d", pubfunct, _nr); + return NULL; + } + + if (offset >= _bufSize) + error("Invalid export function pointer"); + return offset; } @@ -551,7 +563,7 @@ void Script::initializeClasses(SegManager *segMan) { if (getSciVersion() <= SCI_VERSION_1_LATE && !marker) break; - if (getSciVersion() >= SCI_VERSION_1_1 && marker != 0x1234) + if (getSciVersion() >= SCI_VERSION_1_1 && marker != SCRIPT_OBJECT_MAGIC_NUMBER) break; if (getSciVersion() <= SCI_VERSION_1_LATE) { diff --git a/engines/sci/engine/script.h b/engines/sci/engine/script.h index 0c99f13235..9747f072c5 100644 --- a/engines/sci/engine/script.h +++ b/engines/sci/engine/script.h @@ -197,11 +197,11 @@ public: * Validate whether the specified public function is exported by * the script in the specified segment. * @param pubfunct Index of the function to validate - * @param relocate Decide whether to relocate this public function or not + * @param relocateSci3 Decide whether to relocate this SCI3 public function or not * @return NULL if the public function is invalid, its * offset into the script's segment otherwise */ - uint16 validateExportFunc(int pubfunct, bool relocate); + uint16 validateExportFunc(int pubfunct, bool relocateSci3); /** * Marks the script as deleted. @@ -249,7 +249,7 @@ public: /** * Gets an offset to the beginning of the code block in a SCI3 script */ - int getCodeBlockOffset() { return READ_SCI11ENDIAN_UINT32(_buf); } + int getCodeBlockOffsetSci3() { return READ_SCI11ENDIAN_UINT32(_buf); } private: /** diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 89f59eaa14..a42606a6a6 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -225,30 +225,15 @@ ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackP scr = s->_segMan->getScript(seg); } - int temp = scr->validateExportFunc(pubfunct, false); - - if (getSciVersion() == SCI_VERSION_3) - temp += scr->getCodeBlockOffset(); - - if (!temp) { -#ifdef ENABLE_SCI32 - if (g_sci->getGameId() == GID_TORIN && script == 64036) { - // Script 64036 in Torin's Passage is empty and contains an invalid - // (empty) export - } else if (g_sci->getGameId() == GID_RAMA && script == 64908) { - // Script 64908 in the demo of RAMA contains an invalid (empty) - // export - } else -#endif - error("Request for invalid exported function 0x%x of script %d", pubfunct, script); + uint32 exportAddr = scr->validateExportFunc(pubfunct, false); + if (!exportAddr) return NULL; - } - + // Check if a breakpoint is set on this method g_sci->checkExportBreakpoint(script, pubfunct); ExecStack xstack(calling_obj, calling_obj, sp, argc, argp, - seg, make_reg(seg, temp), -1, pubfunct, -1, + seg, make_reg(seg, exportAddr), -1, pubfunct, -1, s->_executionStack.size() - 1, EXEC_STACK_TYPE_CALL); s->_executionStack.push_back(xstack); return &(s->_executionStack.back()); |