aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/sci/engine/script.cpp39
-rw-r--r--engines/sci/engine/script.h2
2 files changed, 17 insertions, 24 deletions
diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp
index a8cee1f393..520275c55c 100644
--- a/engines/sci/engine/script.cpp
+++ b/engines/sci/engine/script.cpp
@@ -162,7 +162,11 @@ void Script::load(int script_nr, ResourceManager *resMan, ScriptPatcher *scriptP
scriptPatcher->processScript(_nr, outBuffer);
if (getSciVersion() <= SCI_VERSION_1_LATE) {
- SciSpan<const uint16> exportTable = findBlockSCI0(SCI_OBJ_EXPORTS).subspan<const uint16>(0);
+ // Some buggy game scripts contain two export tables (e.g. script 912
+ // in Camelot and script 306 in KQ4); in these scripts, the first table
+ // is broken, so we ignore it and use the last one instead
+ // Fixes bugs #3039785 and #3037595.
+ SciSpan<const uint16> exportTable = findBlockSCI0(SCI_OBJ_EXPORTS, true).subspan<const uint16>(0);
if (exportTable) {
// The export table is after the block header (4 bytes / 2 uint16s)
// and the number of exports (2 bytes / 1 uint16).
@@ -818,21 +822,6 @@ uint32 Script::validateExportFunc(int pubfunct, bool relocSci3) {
offset = relocateOffsetSci3(pubfunct * 2 + 22);
}
- // 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.
- // This only makes sense for SCI0-SCI1, as the export table in SCI1.1+ games
- // is located at a specific address, thus findBlockSCI0() won't work.
- // Fixes bugs #3039785 and #3037595.
- if (offset < 10 && getSciVersion() <= SCI_VERSION_1_LATE) {
- const SciSpan<const uint16> secondExportTable = findBlockSCI0(SCI_OBJ_EXPORTS, 0).subspan<const uint16>(0);
-
- if (secondExportTable) {
- // 3 skips header plus 2 bytes (secondExportTable is a uint16 pointer)
- offset = secondExportTable.getUint16SEAt(3 + pubfunct);
- }
- }
-
// TODO: Check if this should be done for SCI1.1 games as well
if (getSciVersion() >= SCI_VERSION_2 && offset == 0) {
offset = _codeOffset;
@@ -844,11 +833,12 @@ uint32 Script::validateExportFunc(int pubfunct, bool relocSci3) {
return offset;
}
-SciSpan<const byte> Script::findBlockSCI0(ScriptObjectTypes type, int startBlockIndex) {
- SciSpan<const byte> buf = *_buf;
+SciSpan<const byte> Script::findBlockSCI0(ScriptObjectTypes type, bool findLastBlock) {
+ SciSpan<const byte> foundBlock;
+
bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
- int blockIndex = 0;
+ SciSpan<const byte> buf = *_buf;
if (oldScriptHeader)
buf += 2;
@@ -862,15 +852,18 @@ SciSpan<const byte> Script::findBlockSCI0(ScriptObjectTypes type, int startBlock
const int blockSize = buf.getUint16LEAt(2);
assert(blockSize > 0);
- if (blockType == type && blockIndex > startBlockIndex) {
- return buf.subspan(0, blockSize, Common::String::format("%s, %s block", _buf->name().c_str(), sciObjectTypeNames[type]));
+ if (blockType == type) {
+ foundBlock = buf.subspan(0, blockSize, Common::String::format("%s, %s block", _buf->name().c_str(), sciObjectTypeNames[type]));;
+
+ if (!findLastBlock) {
+ break;
+ }
}
buf += blockSize;
- blockIndex++;
}
- return SciSpan<const byte>();
+ return foundBlock;
}
// memory operations
diff --git a/engines/sci/engine/script.h b/engines/sci/engine/script.h
index 52b58eec2e..01f3e788b7 100644
--- a/engines/sci/engine/script.h
+++ b/engines/sci/engine/script.h
@@ -246,7 +246,7 @@ public:
* Finds the pointer where a block of a specific type starts from,
* in SCI0 - SCI1 games
*/
- SciSpan<const byte> findBlockSCI0(ScriptObjectTypes type, int startBlockIndex = -1);
+ SciSpan<const byte> findBlockSCI0(ScriptObjectTypes type, bool findLastBlock = false);
/**
* Syncs the string heap of a script. Used when saving/loading.