[Scummvm-cvs-logs] SF.net SVN: scummvm:[50390] scummvm/trunk/engines/sci/engine

thebluegr at users.sourceforge.net thebluegr at users.sourceforge.net
Sun Jun 27 22:09:52 CEST 2010


Revision: 50390
          http://scummvm.svn.sourceforge.net/scummvm/?rev=50390&view=rev
Author:   thebluegr
Date:     2010-06-27 20:09:51 +0000 (Sun, 27 Jun 2010)

Log Message:
-----------
SCI: Separated the code for initializing script classes from the code for initializing script objects

Modified Paths:
--------------
    scummvm/trunk/engines/sci/engine/script.cpp
    scummvm/trunk/engines/sci/engine/seg_manager.h

Modified: scummvm/trunk/engines/sci/engine/script.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/script.cpp	2010-06-27 20:02:58 UTC (rev 50389)
+++ scummvm/trunk/engines/sci/engine/script.cpp	2010-06-27 20:09:51 UTC (rev 50390)
@@ -176,94 +176,95 @@
 	}
 }
 
-void SegManager::scriptInitialiseObjectsSci0(SegmentId seg) {
+void SegManager::scriptInitialiseClasses(SegmentId seg) {
 	Script *scr = getScript(seg);
-	bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
 	const byte *seeker = 0;
-	int objType;
-	reg_t addr;
+	uint16 mult = 0;
+	
+	if (getSciVersion() >= SCI_VERSION_1_1) {
+		seeker = scr->_heapStart + 4 + READ_SCI11ENDIAN_UINT16(scr->_heapStart + 2) * 2;
+		mult = 2;
+	} else {
+		seeker = scr->findBlock(SCI_OBJ_CLASS);
+		mult = 1;
+	}
 
-	// The script is initialized in 2 passes. 
-	// Pass 1: creates a lookup table of all used classes
-	// Pass 2: loads classes and objects
+	if (!seeker)
+		return;
 
-	for (uint16 pass = 0; pass <= 1; pass++) {
-		uint16 objLength = 0;
-		seeker = scr->_buf + (oldScriptHeader ? 2 : 0);
+	while (true) {
+		// In SCI0-SCI1, this is the segment type. In SCI11, it's a marker (0x1234)
+		uint16 marker = READ_SCI11ENDIAN_UINT16(seeker);
+		bool isClass;
+		uint16 classpos = seeker - scr->_buf;
+		int16 species;
 
-		do {
-			objType = READ_SCI11ENDIAN_UINT16(seeker);
-			if (!objType)
-				break;
+		if (!marker)
+			break;
 
-			objLength = READ_SCI11ENDIAN_UINT16(seeker + 2);
-			seeker += 4;		// skip header
-			addr = make_reg(seg, seeker - scr->_buf);
+		if (getSciVersion() >= SCI_VERSION_1_1) {
+			isClass = (READ_SCI11ENDIAN_UINT16(seeker + 14) & kInfoFlagClass);	// -info- selector
+			species = READ_SCI11ENDIAN_UINT16(seeker + 10);
+		} else {
+			isClass = (marker == SCI_OBJ_CLASS);
+			species = READ_SCI11ENDIAN_UINT16(seeker + 12);
+			classpos += 12;
+		}
 
-			switch (objType) {
-			case SCI_OBJ_OBJECT:
-			case SCI_OBJ_CLASS:
-				if (pass == 0 && objType == SCI_OBJ_CLASS) {
-					int species = READ_SCI11ENDIAN_UINT16(seeker + 8);	// SCRIPT_OBJECT_MAGIC_OFFSET
+		if (isClass) {
+			// WORKAROUND for an invalid species access in the demo of LSL2
+			if (g_sci->getGameId() == GID_LSL2 && g_sci->isDemo() && species == (int)classTableSize())
+				resizeClassTable(classTableSize() + 1);
 
-					if (species == (int)classTableSize()) {
-						// Happens in the LSL2 demo
-						warning("Applying workaround for an off-by-one invalid species access");
-						resizeClassTable(classTableSize() + 1);
-					} else if (species < 0 || species > (int)classTableSize()) {
-						error("Invalid species %d(0x%x) not in interval "
-								  "[0,%d) while instantiating script at segment %d\n",
-								  species, species, classTableSize(),
-								  seg);
-						return;
-					}
+			if (species < 0 || species >= (int)classTableSize())
+				error("Invalid species %d(0x%x) not in interval [0,%d) while instantiating script %d\n",
+						  species, species, classTableSize(), scr->_nr);
 
-					setClassOffset(species, make_reg(seg, seeker - scr->_buf + 8));
-				} else if (pass == 1) {
-					Object *obj = scr->scriptObjInit(addr);
-					obj->initSpecies(this, addr);
+			setClassOffset(species, make_reg(seg, classpos));
+		}
 
-					if (!obj->initBaseObject(this, addr)) {
-						// Script 202 of KQ5 French has an invalid object
-						warning("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr));
-						scr->scriptObjRemove(addr);
-					}
-				}
-				break;
-
-			default:
-				break;
-			}
-
-			seeker += objLength - 4;
-		} while (objType != 0 && (uint32)(seeker - scr->_buf) < scr->getScriptSize() - 2);
-	}	// for
+		seeker += READ_SCI11ENDIAN_UINT16(seeker + 2) * mult;
+	}
 }
 
-void SegManager::scriptInitialiseObjectsSci11(SegmentId seg) {
+void SegManager::scriptInitialiseObjectsSci0(SegmentId seg) {
 	Script *scr = getScript(seg);
-	const byte *seeker = scr->_heapStart;
-	uint16 entrySize = READ_SCI11ENDIAN_UINT16(seeker + 2) * 2;
-	seeker += entrySize;	// skip first entry
-	seeker += 4;			// skip header
+	bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
+	const byte *seeker = scr->_buf + (oldScriptHeader ? 2 : 0);
 
-	while (READ_SCI11ENDIAN_UINT16(seeker) == SCRIPT_OBJECT_MAGIC_NUMBER) {
-		if (READ_SCI11ENDIAN_UINT16(seeker + 14) & kInfoFlagClass) {	// -info- selector
-			int classpos = seeker - scr->_buf;
-			int species = READ_SCI11ENDIAN_UINT16(seeker + 10);
+	do {
+		uint16 objType = READ_SCI11ENDIAN_UINT16(seeker);
+		if (!objType)
+			break;
 
-			if (species < 0 || species >= (int)_classTable.size()) {
-				error("Invalid species %d(0x%x) not in interval [0,%d) while instantiating script %d",
-				          species, species, _classTable.size(), scr->_nr);
-				return;
+		switch (objType) {
+		case SCI_OBJ_OBJECT:
+		case SCI_OBJ_CLASS:
+			{
+				reg_t addr = make_reg(seg, seeker - scr->_buf + 4);
+				Object *obj = scr->scriptObjInit(addr);
+				obj->initSpecies(this, addr);
+
+				if (!obj->initBaseObject(this, addr)) {
+					// Script 202 of KQ5 French has an invalid object. This is non-fatal.
+					warning("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr));
+					scr->scriptObjRemove(addr);
+				}
 			}
+			break;
 
-			setClassOffset(species, make_reg(seg, classpos));
+		default:
+			break;
 		}
-		seeker += READ_SCI11ENDIAN_UINT16(seeker + 2) * 2;
-	}
 
-	seeker = scr->_heapStart + 4 + READ_SCI11ENDIAN_UINT16(scr->_heapStart + 2) * 2;
+		seeker += READ_SCI11ENDIAN_UINT16(seeker + 2);
+	} while ((uint32)(seeker - scr->_buf) < scr->getScriptSize() - 2);
+}
+
+void SegManager::scriptInitialiseObjectsSci11(SegmentId seg) {
+	Script *scr = getScript(seg);
+	const byte *seeker = scr->_heapStart + 4 + READ_SCI11ENDIAN_UINT16(scr->_heapStart + 2) * 2;
+
 	while (READ_SCI11ENDIAN_UINT16(seeker) == SCRIPT_OBJECT_MAGIC_NUMBER) {
 		reg_t reg = make_reg(seg, seeker - scr->_buf);
 		Object *obj = scr->scriptObjInit(reg);
@@ -311,6 +312,7 @@
 	scr->init(scriptNum, resMan);
 	scr->load(resMan);
 	segMan->scriptInitialiseLocals(segmentId);
+	segMan->scriptInitialiseClasses(segmentId);
 
 	if (getSciVersion() >= SCI_VERSION_1_1) {
 		segMan->scriptInitialiseObjectsSci11(segmentId);

Modified: scummvm/trunk/engines/sci/engine/seg_manager.h
===================================================================
--- scummvm/trunk/engines/sci/engine/seg_manager.h	2010-06-27 20:02:58 UTC (rev 50389)
+++ scummvm/trunk/engines/sci/engine/seg_manager.h	2010-06-27 20:09:51 UTC (rev 50390)
@@ -426,6 +426,7 @@
 	 */
 	reg_t findObjectByName(const Common::String &name, int index = -1);
 
+	void scriptInitialiseClasses(SegmentId seg);
 	void scriptInitialiseObjectsSci0(SegmentId seg);
 	void scriptInitialiseObjectsSci11(SegmentId seg);
 


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list