[Scummvm-cvs-logs] scummvm master -> bfab4c4cbe3d857ef6a067440ea17baa8b30ec4d

m-kiewitz m_kiewitz at users.sourceforge.net
Thu May 14 20:32:53 CEST 2015


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
bfab4c4cbe SCI: debug commands scro, scrs and script_said


Commit: bfab4c4cbe3d857ef6a067440ea17baa8b30ec4d
    https://github.com/scummvm/scummvm/commit/bfab4c4cbe3d857ef6a067440ea17baa8b30ec4d
Author: Martin Kiewitz (m_kiewitz at users.sourceforge.net)
Date: 2015-05-14T20:33:21+02:00

Commit Message:
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

Changed paths:
    engines/sci/console.cpp
    engines/sci/console.h
    engines/sci/engine/script.cpp
    engines/sci/engine/script.h



diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp
index dc017a7..c706970 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 00d95b5..8b10912 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 69f5249..fbf00ab 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 fe774ae..3f24bb1 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






More information about the Scummvm-git-logs mailing list