aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Snover2016-10-13 10:11:24 -0500
committerColin Snover2016-10-20 11:33:08 -0500
commit55222ec06c030a03d288b7ad476c5dbf1444a48b (patch)
tree2034bfbd9b228650a4f302f43bdf0d80063034bf
parent950ee49382ea054ede5b7bb689add98b25075a8b (diff)
downloadscummvm-rg350-55222ec06c030a03d288b7ad476c5dbf1444a48b.tar.gz
scummvm-rg350-55222ec06c030a03d288b7ad476c5dbf1444a48b.tar.bz2
scummvm-rg350-55222ec06c030a03d288b7ad476c5dbf1444a48b.zip
SCI32: Fix zero-offset exports
Exports with a zero offset are supposed to point to the start of the code block in the script hunk, but they were being ignored. This may also apply to SCI1.1 games, but until that can be verified, this fixes the zero-offset in only SCI32 games for now.
-rw-r--r--engines/sci/engine/script.cpp45
-rw-r--r--engines/sci/engine/script.h2
2 files changed, 40 insertions, 7 deletions
diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp
index aef9cb198f..098c2e56c9 100644
--- a/engines/sci/engine/script.cpp
+++ b/engines/sci/engine/script.cpp
@@ -72,6 +72,11 @@ void Script::freeScript() {
_offsetLookupSaidCount = 0;
}
+enum {
+ kSci11NumExportsOffset = 6,
+ kSci11ExportTableOffset = 8
+};
+
void Script::load(int script_nr, ResourceManager *resMan, ScriptPatcher *scriptPatcher) {
freeScript();
@@ -172,10 +177,11 @@ void Script::load(int script_nr, ResourceManager *resMan, ScriptPatcher *scriptP
_localsCount = (READ_LE_UINT16(_buf + _localsOffset - 2) - 4) >> 1; // half block size
}
} else if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1_LATE) {
- if (READ_LE_UINT16(_buf + 1 + 5) > 0) { // does the script have an export table?
- _exportTable = (const uint16 *)(_buf + 1 + 5 + 2);
- _numExports = READ_SCI11ENDIAN_UINT16(_exportTable - 1);
+ _numExports = READ_SCI11ENDIAN_UINT16(_buf + kSci11NumExportsOffset);
+ if (_numExports) {
+ _exportTable = (const uint16 *)(_buf + kSci11ExportTableOffset);
}
+
_localsOffset = _scriptSize + 4;
_localsCount = READ_SCI11ENDIAN_UINT16(_buf + _localsOffset - 2);
} else if (getSciVersion() == SCI_VERSION_3) {
@@ -234,6 +240,7 @@ void Script::identifyOffsets() {
_offsetLookupObjectCount = 0;
_offsetLookupStringCount = 0;
_offsetLookupSaidCount = 0;
+ _codeOffset = 0;
if (getSciVersion() < SCI_VERSION_1_1) {
// SCI0 + SCI1
@@ -392,6 +399,16 @@ void Script::identifyOffsets() {
scriptDataPtr = _heapStart;
scriptDataLeft = _heapSize;
+ enum {
+ kExportSize = 2,
+ kPropertySize = 2,
+ kNumMethodsSize = 2,
+ kPropDictEntrySize = 2,
+ kMethDictEntrySize = 4
+ };
+
+ const byte *hunkPtr = _buf + kSci11ExportTableOffset + _numExports * kExportSize;
+
if (scriptDataLeft < 4)
error("Script::identifyOffsets(): unexpected end of script in script %d", _nr);
@@ -431,11 +448,22 @@ void Script::identifyOffsets() {
if (scriptDataLeft < 2)
error("Script::identifyOffsets(): unexpected end of script in script %d", _nr);
- blockSize = READ_SCI11ENDIAN_UINT16(scriptDataPtr) * 2;
+ const uint16 numProperties = READ_SCI11ENDIAN_UINT16(scriptDataPtr);
+ blockSize = numProperties * kPropertySize;
if (blockSize < 4)
error("Script::identifyOffsets(): invalid block size in script %d", _nr);
scriptDataPtr += 2;
scriptDataLeft -= 2;
+
+ const uint16 scriptNum = READ_SCI11ENDIAN_UINT16(scriptDataPtr + 6);
+
+ if (scriptNum != 0xFFFF) {
+ hunkPtr += numProperties * kPropDictEntrySize;
+ }
+
+ const uint16 numMethods = READ_SCI11ENDIAN_UINT16(hunkPtr);
+ hunkPtr += kNumMethodsSize + numMethods * kMethDictEntrySize;
+
blockSize -= 4; // blocksize contains UINT16 type and UINT16 size
if (scriptDataLeft < blockSize)
error("Script::identifyOffsets(): invalid block size in script %d", _nr);
@@ -444,6 +472,8 @@ void Script::identifyOffsets() {
scriptDataLeft -= blockSize;
} while (1);
+ _codeOffset = hunkPtr - _buf;
+
// now scriptDataPtr points to right at the start of the strings
if (scriptDataPtr > endOfStringPtr)
error("Script::identifyOffsets(): string block / end-of-string block mismatch in script %d", _nr);
@@ -820,9 +850,10 @@ uint32 Script::validateExportFunc(int pubfunct, bool relocSci3) {
}
}
- // Note that it's perfectly normal to return a zero offset, especially in
- // SCI1.1 and newer games. Examples include script 64036 in Torin's Passage,
- // script 64908 in the demo of RAMA and script 1013 in KQ6 floppy.
+ // TODO: Check if this should be done for SCI1.1 games as well
+ if (getSciVersion() >= SCI_VERSION_2 && offset == 0) {
+ offset = _codeOffset;
+ }
if (offset >= _bufSize)
error("Invalid export function pointer");
diff --git a/engines/sci/engine/script.h b/engines/sci/engine/script.h
index 755e2f3698..31f0a9e24d 100644
--- a/engines/sci/engine/script.h
+++ b/engines/sci/engine/script.h
@@ -81,6 +81,8 @@ private:
const byte *_synonyms; /**< Synonyms block or 0 if not present */
uint16 _numSynonyms; /**< Number of entries in the synonyms block */
+ int _codeOffset; /**< The absolute offset of the VM code block */
+
int _localsOffset;
uint16 _localsCount;