aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Kiewitz2015-05-14 20:33:21 +0200
committerMartin Kiewitz2015-05-14 20:33:21 +0200
commitbfab4c4cbe3d857ef6a067440ea17baa8b30ec4d (patch)
tree39101ed09bdb030013425ae96e39ec99785df7e5
parentfdfb7775a49ec6b93cbaa720b88fee37e052a86c (diff)
downloadscummvm-rg350-bfab4c4cbe3d857ef6a067440ea17baa8b30ec4d.tar.gz
scummvm-rg350-bfab4c4cbe3d857ef6a067440ea17baa8b30ec4d.tar.bz2
scummvm-rg350-bfab4c4cbe3d857ef6a067440ea17baa8b30ec4d.zip
SCI: debug commands scro, scrs and script_said
implement string collecting for SCI3 implement object offset collecting for SCI0-SCI2 implement said-str offset collecting for SCI0-SCI1 add new debug command scro / script_objects add new debug command script_said string without terminating NUL now a warning the latter happens in qfg2 for amiga room 84
-rw-r--r--engines/sci/console.cpp151
-rw-r--r--engines/sci/console.h3
-rw-r--r--engines/sci/engine/script.cpp259
-rw-r--r--engines/sci/engine/script.h26
4 files changed, 369 insertions, 70 deletions
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp
index dc017a7a70..c7069709d4 100644
--- a/engines/sci/console.cpp
+++ b/engines/sci/console.cpp
@@ -209,8 +209,11 @@ Console::Console(SciEngine *engine) : GUI::Debugger(),
registerCmd("bpe", WRAP_METHOD(Console, cmdBreakpointFunction)); // alias
// VM
registerCmd("script_steps", WRAP_METHOD(Console, cmdScriptSteps));
+ registerCmd("script_objects", WRAP_METHOD(Console, cmdScriptObjects));
+ registerCmd("scro", WRAP_METHOD(Console, cmdScriptObjects));
registerCmd("script_strings", WRAP_METHOD(Console, cmdScriptStrings));
registerCmd("scrs", WRAP_METHOD(Console, cmdScriptStrings));
+ registerCmd("script_said", WRAP_METHOD(Console, cmdScriptSaid));
registerCmd("vm_varlist", WRAP_METHOD(Console, cmdVMVarlist));
registerCmd("vmvarlist", WRAP_METHOD(Console, cmdVMVarlist)); // alias
registerCmd("vl", WRAP_METHOD(Console, cmdVMVarlist)); // alias
@@ -2830,28 +2833,85 @@ bool Console::cmdScriptSteps(int argc, const char **argv) {
return true;
}
-bool Console::cmdScriptStrings(int argc, const char **argv) {
- SegManager *segMan = _engine->_gamestate->_segMan;
+bool Console::cmdScriptObjects(int argc, const char **argv) {
int curScriptNr = -1;
- SegmentId curSegmentNr;
- Common::List<SegmentId> segmentNrList;
- SegmentType curSegmentType = SEG_TYPE_INVALID;
- SegmentObj *curSegmentObj = NULL;
- Script *curScriptObj = NULL;
+ if (argc < 2) {
+ debugPrintf("Shows all objects inside a specified script.\n");
+ debugPrintf("Usage: %s <script number>\n", argv[0]);
+ debugPrintf("Example: %s 999\n", argv[0]);
+ debugPrintf("<script number> may be * to show objects inside all loaded scripts\n");
+ return true;
+ }
+
+ if (strcmp(argv[1], "*") == 0) {
+ // get said-strings of all currently loaded scripts
+ curScriptNr = -1;
+ } else {
+ curScriptNr = atoi(argv[1]);
+ }
+
+ printOffsets(curScriptNr, SCI_SCR_OFFSET_TYPE_OBJECT);
+ return true;
+}
+
+bool Console::cmdScriptStrings(int argc, const char **argv) {
+ int curScriptNr = -1;
if (argc < 2) {
- debugPrintf("Shows the strings inside a specified script.\n");
+ debugPrintf("Shows all strings inside a specified script.\n");
debugPrintf("Usage: %s <script number>\n", argv[0]);
debugPrintf("Example: %s 999\n", argv[0]);
debugPrintf("<script number> may be * to show strings inside all loaded scripts\n");
return true;
}
- segmentNrList.clear();
-
if (strcmp(argv[1], "*") == 0) {
// get strings of all currently loaded scripts
+ curScriptNr = -1;
+ } else {
+ curScriptNr = atoi(argv[1]);
+ }
+
+ printOffsets(curScriptNr, SCI_SCR_OFFSET_TYPE_STRING);
+ return true;
+}
+
+bool Console::cmdScriptSaid(int argc, const char **argv) {
+ int curScriptNr = -1;
+
+ if (argc < 2) {
+ debugPrintf("Shows all said-strings inside a specified script.\n");
+ debugPrintf("Usage: %s <script number>\n", argv[0]);
+ debugPrintf("Example: %s 999\n", argv[0]);
+ debugPrintf("<script number> may be * to show said-strings inside all loaded scripts\n");
+ return true;
+ }
+
+ if (strcmp(argv[1], "*") == 0) {
+ // get said-strings of all currently loaded scripts
+ curScriptNr = -1;
+ } else {
+ curScriptNr = atoi(argv[1]);
+ }
+
+ printOffsets(curScriptNr, SCI_SCR_OFFSET_TYPE_SAID);
+ return true;
+}
+
+void Console::printOffsets(int scriptNr, uint16 showType) {
+ SegManager *segMan = _engine->_gamestate->_segMan;
+ SegmentId curSegmentNr;
+ Common::List<SegmentId> segmentNrList;
+
+ SegmentType curSegmentType = SEG_TYPE_INVALID;
+ SegmentObj *curSegmentObj = NULL;
+ Script *curScriptObj = NULL;
+ const byte *curScriptData = NULL;
+
+ segmentNrList.clear();
+ if (scriptNr < 0) {
+ // get offsets of all currently loaded scripts
for (curSegmentNr = 0; curSegmentNr < segMan->_heap.size(); curSegmentNr++) {
curSegmentObj = segMan->_heap[curSegmentNr];
if (curSegmentObj && curSegmentObj->getType() == SEG_TYPE_SCRIPT) {
@@ -2860,15 +2920,22 @@ bool Console::cmdScriptStrings(int argc, const char **argv) {
}
} else {
- curScriptNr = atoi(argv[1]);
- curSegmentNr = segMan->getScriptSegment(curScriptNr);
+ curSegmentNr = segMan->getScriptSegment(scriptNr);
if (!curSegmentNr) {
- debugPrintf("Script %d is currently not loaded/available\n", curScriptNr);
- return true;
+ debugPrintf("Script %d is currently not loaded/available\n", scriptNr);
+ return;
}
segmentNrList.push_back(curSegmentNr);
}
+ const offsetLookupArrayType *scriptOffsetLookupArray;
+ offsetLookupArrayType::const_iterator arrayIterator;
+ int showTypeCount = 0;
+
+ reg_t objectPos;
+ const char *objectNamePtr = NULL;
+ const byte *stringPtr = NULL;
+
Common::List<SegmentId>::iterator it;
const Common::List<SegmentId>::iterator end = segmentNrList.end();
@@ -2884,15 +2951,61 @@ bool Console::cmdScriptStrings(int argc, const char **argv) {
continue;
curScriptObj = (Script *)curSegmentObj;
- debugPrintf("=== SCRIPT %d from Segment %d ===\n", curScriptObj->getScriptNumber(), curSegmentNr);
- debugN("=== SCRIPT %d from Segment %d ===\n", curScriptObj->getScriptNumber(), curSegmentNr);
+ debugPrintf("=== SCRIPT %d inside Segment %d ===\n", curScriptObj->getScriptNumber(), curSegmentNr);
+ debugN("=== SCRIPT %d inside Segment %d ===\n", curScriptObj->getScriptNumber(), curSegmentNr);
+
+ // now print the list
+ scriptOffsetLookupArray = curScriptObj->getOffsetArray();
+ curScriptData = curScriptObj->getBuf();
+ showTypeCount = 0;
+
+ for (arrayIterator = scriptOffsetLookupArray->begin(); arrayIterator != scriptOffsetLookupArray->end(); arrayIterator++) {
+ if (arrayIterator->type == showType) {
+ switch (showType) {
+ case SCI_SCR_OFFSET_TYPE_OBJECT:
+ objectPos = make_reg(curSegmentNr, arrayIterator->offset);
+ objectNamePtr = segMan->getObjectName(objectPos);
+ debugPrintf(" %03d:%04x: %s\n", arrayIterator->id, arrayIterator->offset, objectNamePtr);
+ debugN(" %03d:%04x: %s\n", arrayIterator->id, arrayIterator->offset, objectNamePtr);
+ break;
+ case SCI_SCR_OFFSET_TYPE_STRING:
+ stringPtr = curScriptData + arrayIterator->offset;
+ debugPrintf(" %03d:%04x: '%s' (size %d)\n", arrayIterator->id, arrayIterator->offset, stringPtr, arrayIterator->stringSize);
+ debugN(" %03d:%04x: '%s' (size %d)\n", arrayIterator->id, arrayIterator->offset, stringPtr, arrayIterator->stringSize);
+ break;
+ case SCI_SCR_OFFSET_TYPE_SAID:
+ debugPrintf(" %03d:%04x:\n", arrayIterator->id, arrayIterator->offset);
+ debugN(" %03d:%04x:\n", arrayIterator->id, arrayIterator->offset);
+ break;
+ default:
+ break;
+ }
+ showTypeCount++;
+ }
+ }
+
+ if (showTypeCount == 0) {
+ switch (showType) {
+ case SCI_SCR_OFFSET_TYPE_OBJECT:
+ debugPrintf(" no objects\n");
+ debugN(" no objects\n");
+ break;
+ case SCI_SCR_OFFSET_TYPE_STRING:
+ debugPrintf(" no strings\n");
+ debugN(" no strings\n");
+ break;
+ case SCI_SCR_OFFSET_TYPE_SAID:
+ debugPrintf(" no said-strings\n");
+ debugN(" no said-strings\n");
+ break;
+ default:
+ break;
+ }
+ }
- // now print the string list
- curScriptObj->debugPrintStrings(this);
debugPrintf("\n");
debugN("\n");
}
- return true;
}
bool Console::cmdBacktrace(int argc, const char **argv) {
diff --git a/engines/sci/console.h b/engines/sci/console.h
index 00d95b511f..8b10912fbe 100644
--- a/engines/sci/console.h
+++ b/engines/sci/console.h
@@ -147,7 +147,9 @@ private:
bool cmdBreakpointFunction(int argc, const char **argv);
// VM
bool cmdScriptSteps(int argc, const char **argv);
+ bool cmdScriptObjects(int argc, const char **argv);
bool cmdScriptStrings(int argc, const char **argv);
+ bool cmdScriptSaid(int argc, const char **argv);
bool cmdVMVarlist(int argc, const char **argv);
bool cmdVMVars(int argc, const char **argv);
bool cmdStack(int argc, const char **argv);
@@ -167,6 +169,7 @@ private:
void printList(List *list);
int printNode(reg_t addr);
void hexDumpReg(const reg_t *data, int len, int regsPerLine = 4, int startOffset = 0, bool isArray = false);
+ void printOffsets(int scriptNr, uint16 showType);
private:
/**
diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp
index 69f52495e0..fbf00abf9b 100644
--- a/engines/sci/engine/script.cpp
+++ b/engines/sci/engine/script.cpp
@@ -65,7 +65,7 @@ void Script::freeScript() {
_lockers = 1;
_markedAsDeleted = false;
_objects.clear();
- _stringLookupList.clear();
+ _offsetLookupArray.clear();
}
void Script::load(int script_nr, ResourceManager *resMan, ScriptPatcher *scriptPatcher) {
@@ -208,39 +208,41 @@ void Script::load(int script_nr, ResourceManager *resMan, ScriptPatcher *scriptP
}
// find all strings of this script
- identifyStrings();
+ identifyOffsets();
}
-void Script::identifyStrings() {
- stringLookupListEntry listEntry;
+void Script::identifyOffsets() {
+ offsetLookupArrayEntry arrayEntry;
byte *scriptDataPtr = NULL;
byte *stringStartPtr = NULL;
byte *stringDataPtr = NULL;
int scriptDataLeft = 0;
int stringDataLeft = 0;
byte stringDataByte = 0;
+ uint16 typeObject_id = 0;
+ uint16 typeString_id = 0;
+ uint16 typeSaid_id = 0;
- _stringLookupList.clear();
- //stringLookupListType _stringLookupList; // Table of string data, that is inside the currently loaded script
-
+ _offsetLookupArray.clear();
if (getSciVersion() < SCI_VERSION_1_1) {
+ // SCI0 + SCI1
scriptDataPtr = _buf;
scriptDataLeft = _bufSize;
- // Go through all SCI_OBJ_STRINGS blocks
+ // Go through all blocks
if (getSciVersion() == SCI_VERSION_0_EARLY) {
if (scriptDataLeft < 2)
- error("Script::identifyStrings(): unexpected end of script");
+ error("Script::identifyOffsets(): unexpected end of script %d", _nr);
scriptDataPtr += 2;
scriptDataLeft -= 2;
}
-
+
uint16 blockType;
uint16 blockSize;
do {
if (scriptDataLeft < 2)
- error("Script::identifyStrings(): unexpected end of script");
+ error("Script::identifyOffsets(): unexpected end of script %d", _nr);
blockType = READ_LE_UINT16(scriptDataPtr);
scriptDataPtr += 2;
@@ -249,29 +251,49 @@ void Script::identifyStrings() {
break;
if (scriptDataLeft < 2)
- error("Script::identifyStrings(): unexpected end of script");
+ error("Script::identifyOffsets(): unexpected end of script %d", _nr);
blockSize = READ_LE_UINT16(scriptDataPtr);
if (blockSize < 4)
- error("Script::identifyStrings(): invalid block size");
+ error("Script::identifyOffsets(): invalid block size in script %d", _nr);
blockSize -= 4; // block size includes block-type UINT16 and block-size UINT16
scriptDataPtr += 2;
scriptDataLeft -= 2;
if (scriptDataLeft < blockSize)
- error("Script::identifyStrings(): invalid block size");
-
- if (blockType == SCI_OBJ_STRINGS) {
+ error("Script::identifyOffsets(): invalid block size in script %d", _nr);
+
+ switch (blockType) {
+ case SCI_OBJ_OBJECT:
+ case SCI_OBJ_CLASS:
+ typeObject_id++;
+ arrayEntry.type = SCI_SCR_OFFSET_TYPE_OBJECT;
+ arrayEntry.id = typeObject_id;
+ arrayEntry.offset = scriptDataPtr - _buf + 8; // Calculate offset inside script data (VM uses +8)
+ arrayEntry.stringSize = 0;
+ _offsetLookupArray.push_back(arrayEntry);
+ break;
+
+ case SCI_OBJ_STRINGS:
// string block detected, we now grab all NUL terminated strings out of this block
stringDataPtr = scriptDataPtr;
stringDataLeft = blockSize;
+ arrayEntry.type = SCI_SCR_OFFSET_TYPE_STRING;
+
do {
if (stringDataLeft < 1) // no more bytes left
break;
stringStartPtr = stringDataPtr;
- listEntry.ptrOffset = stringStartPtr - _buf; // Calculate offset inside script data
+
+ if (stringDataLeft == 1) {
+ // only 1 byte left and that byte is a [00], in that case we also exit
+ stringDataByte = *stringStartPtr;
+ if (stringDataByte == 0x00)
+ break;
+ }
+
// now look for terminating [NUL]
do {
stringDataByte = *stringDataPtr;
@@ -279,13 +301,75 @@ void Script::identifyStrings() {
stringDataLeft--;
if (!stringDataByte) // NUL found, exit this loop
break;
+ if (stringDataLeft < 1) {
+ // no more bytes left
+ warning("Script::identifyOffsets(): string without terminating NUL in script %d", _nr);
+ break;
+ }
+ } while (1);
+
+ if (stringDataByte)
+ break;
+
+ typeString_id++;
+ arrayEntry.id = typeString_id;
+ arrayEntry.offset = stringStartPtr - _buf; // Calculate offset inside script data
+ arrayEntry.stringSize = stringDataPtr - stringStartPtr;
+ _offsetLookupArray.push_back(arrayEntry);
+ } while (1);
+ break;
+
+ case SCI_OBJ_SAID:
+ // said block detected, we now try to find every single said "string" inside this block
+ // said strings are terminated with a 0xFF, the string itself may contain words (2 bytes), where
+ // the second byte of a word may also be a 0xFF.
+ stringDataPtr = scriptDataPtr;
+ stringDataLeft = blockSize;
+
+ arrayEntry.type = SCI_SCR_OFFSET_TYPE_SAID;
+
+ do {
+ if (stringDataLeft < 1) // no more bytes left
+ break;
+
+ stringStartPtr = stringDataPtr;
+ if (stringDataLeft == 1) {
+ // only 1 byte left and that byte is a [00], in that case we also exit
+ // happens in some scripts, for example Conquests of Camelot, script 997
+ // may have been a bug in the compiler or just an intentional filler byte
+ stringDataByte = *stringStartPtr;
+ if (stringDataByte == 0x00)
+ break;
+ }
+
+ // now look for terminating 0xFF
+ do {
+ stringDataByte = *stringDataPtr;
+ stringDataPtr++;
+ stringDataLeft--;
+ if (stringDataByte == 0xFF) // Terminator found, exit this loop
+ break;
if (stringDataLeft < 1) // no more bytes left
- error("Script::identifyStrings(): string without terminating NUL");
+ error("Script::identifyOffsets(): said-string without terminator in script %d", _nr);
+ if (stringDataByte < 0xF0) {
+ // Part of a word, skip second byte
+ stringDataPtr++;
+ stringDataLeft--;
+ if (stringDataLeft < 1) // no more bytes left
+ error("Script::identifyOffsets(): said-string without terminator in script %d", _nr);
+ }
} while (1);
- listEntry.stringSize = stringDataPtr - stringStartPtr;
- _stringLookupList.push_back(listEntry);
+ typeSaid_id++;
+ arrayEntry.id = typeSaid_id;
+ arrayEntry.offset = stringStartPtr - _buf; // Calculate offset inside script data
+ arrayEntry.stringSize = 0;
+ _offsetLookupArray.push_back(arrayEntry);
} while (1);
+ break;
+
+ default:
+ break;
}
scriptDataPtr += blockSize;
@@ -293,20 +377,20 @@ void Script::identifyStrings() {
} while (1);
} else if (getSciVersion() >= SCI_VERSION_1_1 && getSciVersion() <= SCI_VERSION_2_1) {
- // Strings in SCI1.1 come after the object instances
+ // Strings in SCI1.1 up to SCI2 come after the object instances
scriptDataPtr = _heapStart;
scriptDataLeft = _heapSize;
if (scriptDataLeft < 4)
- error("Script::identifyStrings(): unexpected end of script");
+ error("Script::identifyOffsets(): unexpected end of script in script %d", _nr);
uint16 endOfStringOffset = READ_SCI11ENDIAN_UINT16(scriptDataPtr);
uint16 objectStartOffset = READ_SCI11ENDIAN_UINT16(scriptDataPtr + 2) * 2 + 4;
if (scriptDataLeft < objectStartOffset)
- error("Script::identifyStrings(): object start is beyond heap size");
+ error("Script::identifyOffsets(): object start is beyond heap size in script %d", _nr);
if (scriptDataLeft < endOfStringOffset)
- error("Script::identifyStrings(): end of string is beyond heap size");
+ error("Script::identifyOffsets(): end of string is beyond heap size in script %d", _nr);
byte *endOfStringPtr = scriptDataPtr + endOfStringOffset;
@@ -316,10 +400,10 @@ void Script::identifyStrings() {
uint16 blockType;
uint16 blockSize;
- // skip all objects
+ // go through all objects
do {
if (scriptDataLeft < 2)
- error("Script::identifyStrings(): unexpected end of script");
+ error("Script::identifyOffsets(): unexpected end of script %d", _nr);
blockType = READ_SCI11ENDIAN_UINT16(scriptDataPtr);
scriptDataPtr += 2;
@@ -327,15 +411,23 @@ void Script::identifyStrings() {
if (blockType != SCRIPT_OBJECT_MAGIC_NUMBER)
break;
+ // Object found, add offset of object
+ typeObject_id++;
+ arrayEntry.type = SCI_SCR_OFFSET_TYPE_OBJECT;
+ arrayEntry.id = typeObject_id;
+ arrayEntry.offset = scriptDataPtr - _buf - 2; // the VM uses a pointer to the Magic-Number
+ arrayEntry.stringSize = 0;
+ _offsetLookupArray.push_back(arrayEntry);
+
if (scriptDataLeft < 2)
- error("Script::identifyStrings(): unexpected end of script");
+ error("Script::identifyOffsets(): unexpected end of script in script %d", _nr);
blockSize = READ_SCI11ENDIAN_UINT16(scriptDataPtr) * 2;
scriptDataPtr += 2;
scriptDataLeft -= 2;
blockSize -= 4; // blocksize contains UINT16 type and UINT16 size
if (scriptDataLeft < blockSize)
- error("Script::identifyStrings(): invalid block size");
+ error("Script::identifyOffsets(): invalid block size in script %d", _nr);
scriptDataPtr += blockSize;
scriptDataLeft -= blockSize;
@@ -343,17 +435,17 @@ void Script::identifyStrings() {
// now scriptDataPtr points to right at the start of the strings
if (scriptDataPtr > endOfStringPtr)
- error("Script::identifyStrings(): string block / end-of-string block mismatch");
+ error("Script::identifyOffsets(): string block / end-of-string block mismatch in script %d", _nr);
stringDataPtr = scriptDataPtr;
stringDataLeft = endOfStringPtr - scriptDataPtr; // Calculate byte count within string-block
+ arrayEntry.type = SCI_SCR_OFFSET_TYPE_STRING;
do {
if (stringDataLeft < 1) // no more bytes left
break;
stringStartPtr = stringDataPtr;
- listEntry.ptrOffset = stringStartPtr - _buf; // Calculate offset inside script data
// now look for terminating [NUL]
do {
stringDataByte = *stringDataPtr;
@@ -361,35 +453,112 @@ void Script::identifyStrings() {
stringDataLeft--;
if (!stringDataByte) // NUL found, exit this loop
break;
- if (stringDataLeft < 1) // no more bytes left
- error("Script::identifyStrings(): string without terminating NUL");
+ if (stringDataLeft < 1) {
+ // no more bytes left
+ warning("Script::identifyOffsets(): string without terminating NUL in script %d", _nr);
+ break;
+ }
} while (1);
- listEntry.stringSize = stringDataPtr - stringStartPtr;
- _stringLookupList.push_back(listEntry);
+ if (stringDataByte)
+ break;
+
+ typeString_id++;
+ arrayEntry.id = typeString_id;
+ arrayEntry.offset = stringStartPtr - _buf; // Calculate offset inside script data
+ arrayEntry.stringSize = stringDataPtr - stringStartPtr;
+ _offsetLookupArray.push_back(arrayEntry);
} while (1);
} else if (getSciVersion() == SCI_VERSION_3) {
- warning("TODO: identifyStrings(): Implement SCI3 variant");
+ // SCI3
+ uint32 sci3stringOffset = 0;
+ uint32 sci3relocationOffset = 0;
+
+ if (_bufSize < 22)
+ error("Script::identifyOffsets(): script %d smaller than expected SCI3-header", _nr);
+
+ sci3stringOffset = READ_LE_UINT32(_buf + 4);
+ sci3relocationOffset = READ_LE_UINT32(_buf + 8);
+
+ if (sci3relocationOffset > _bufSize)
+ error("Script::identifyOffsets(): relocation offset is beyond end of script %d", _nr);
+
+ if (sci3stringOffset > 0) {
+ // string offset set, we expect strings
+ if (sci3stringOffset > _bufSize)
+ error("Script::identifyOffsets(): string offset is beyond end of script %d", _nr);
+
+ if (sci3relocationOffset < sci3stringOffset)
+ error("Script::identifyOffsets(): string offset points beyond relocation offset in script %d", _nr);
+
+ stringDataPtr = _buf + sci3stringOffset;
+ stringDataLeft = sci3relocationOffset - sci3stringOffset;
+
+ arrayEntry.type = SCI_SCR_OFFSET_TYPE_STRING;
+
+ do {
+ if (stringDataLeft < 1) // no more bytes left
+ break;
+
+ stringStartPtr = stringDataPtr;
+
+ if (stringDataLeft == 1) {
+ // only 1 byte left and that byte is a [00], in that case we also exit
+ stringDataByte = *stringStartPtr;
+ if (stringDataByte == 0x00)
+ break;
+ }
+
+ // now look for terminating [NUL]
+ do {
+ stringDataByte = *stringDataPtr;
+ stringDataPtr++;
+ stringDataLeft--;
+ if (!stringDataByte) // NUL found, exit this loop
+ break;
+ if (stringDataLeft < 1) {
+ // no more bytes left
+ warning("Script::identifyOffsets(): string without terminating NUL in script %d", _nr);
+ break;
+ }
+ } while (1);
+
+ if (stringDataByte)
+ break;
+
+ typeString_id++;
+ arrayEntry.id = typeString_id;
+ arrayEntry.offset = stringStartPtr - _buf; // Calculate offset inside script data
+ arrayEntry.stringSize = stringDataPtr - stringStartPtr;
+ _offsetLookupArray.push_back(arrayEntry);
+ } while (1);
+ }
+
+ // Figure out more stuff in SCI3 scripts
+ warning("TODO: identifyOffsets(): Implement SCI3 variant");
return;
}
}
void Script::debugPrintStrings(Console *con) {
- stringLookupListType::iterator it;
- const stringLookupListType::iterator end = _stringLookupList.end();
+ offsetLookupArrayType::iterator it;
+ const offsetLookupArrayType::iterator end = _offsetLookupArray.end();
byte *stringPtr;
+ int stringCount = 0;
+
+ for (it = _offsetLookupArray.begin(); it != end; ++it) {
+ if (it->type == SCI_SCR_OFFSET_TYPE_STRING) {
+ stringPtr = _buf + it->offset;
+ con->debugPrintf(" %03d:%04x: '%s' (size %d)\n", it->id, it->offset, stringPtr, it->stringSize);
+ debugN(" %03d:%04x: '%s' (size %d)\n", it->id, it->offset, stringPtr, it->stringSize);
+ stringCount++;
+ }
+ }
- if (!_stringLookupList.size()) {
+ if (stringCount == 0) {
con->debugPrintf(" no strings\n");
debugN(" no strings\n");
- return;
- }
-
- for (it = _stringLookupList.begin(); it != end; ++it) {
- stringPtr = _buf + it->ptrOffset;
- con->debugPrintf(" %04x: '%s' (size %d)\n", it->ptrOffset, stringPtr, it->stringSize);
- debugN(" %04x: '%s' (size %d)\n", it->ptrOffset, stringPtr, it->stringSize);
}
}
diff --git a/engines/sci/engine/script.h b/engines/sci/engine/script.h
index fe774aeab5..3f24bb191b 100644
--- a/engines/sci/engine/script.h
+++ b/engines/sci/engine/script.h
@@ -49,12 +49,20 @@ enum ScriptObjectTypes {
typedef Common::HashMap<uint16, Object> ObjMap;
-struct stringLookupListEntry {
- uint16 ptrOffset; // offset of the string
+enum ScriptOffsetEntryTypes {
+ SCI_SCR_OFFSET_TYPE_OBJECT = 0, // classes are handled by this type as well
+ SCI_SCR_OFFSET_TYPE_STRING,
+ SCI_SCR_OFFSET_TYPE_SAID
+};
+
+struct offsetLookupArrayEntry {
+ uint16 type; // type of entry
+ uint16 id; // id of this type, first item inside script data is 1, second item is 2, etc.
+ uint32 offset; // offset of entry within script resource data
uint16 stringSize; // size of string, including terminating [NUL]
};
-typedef Common::List<stringLookupListEntry> stringLookupListType;
+typedef Common::Array<offsetLookupArrayEntry> offsetLookupArrayType;
class Script : public SegmentObj {
private:
@@ -82,7 +90,8 @@ private:
ObjMap _objects; /**< Table for objects, contains property variables */
- stringLookupListType _stringLookupList; // Table of string data, that is inside the currently loaded script
+protected:
+ offsetLookupArrayType _offsetLookupArray; // Table of all elements of currently loaded script, that may get pointed to
public:
int getLocalsOffset() const { return _localsOffset; }
@@ -258,6 +267,11 @@ public:
int getCodeBlockOffsetSci3() { return READ_SCI11ENDIAN_UINT32(_buf); }
/**
+ * Get the offset array
+ */
+ const offsetLookupArrayType *getOffsetArray() { return &_offsetLookupArray; };
+
+ /**
* Print string lookup table (list) to debug console
*/
void debugPrintStrings(Console *con);
@@ -310,9 +324,9 @@ private:
LocalVariables *allocLocalsSegment(SegManager *segMan);
/**
- * Identifies strings within script data and set up lookup-table
+ * Identifies certain offsets within script data and set up lookup-table
*/
- void identifyStrings();
+ void identifyOffsets();
};
} // End of namespace Sci