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

waltervn at users.sourceforge.net waltervn at users.sourceforge.net
Mon Aug 24 03:59:58 CEST 2009


Revision: 43680
          http://scummvm.svn.sourceforge.net/scummvm/?rev=43680&view=rev
Author:   waltervn
Date:     2009-08-24 01:59:58 +0000 (Mon, 24 Aug 2009)

Log Message:
-----------
SCI: Read class table from vocab resource instead of scanning. This fixes
several "invalid selector" VM crashes caused by duplicate classes.

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

Modified: scummvm/trunk/engines/sci/engine/seg_manager.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/seg_manager.cpp	2009-08-23 22:51:57 UTC (rev 43679)
+++ scummvm/trunk/engines/sci/engine/seg_manager.cpp	2009-08-24 01:59:58 UTC (rev 43680)
@@ -71,10 +71,7 @@
 
 	int result = 0;
 
-	if (version >= SCI_VERSION_1_1)
-		result = createSci11ClassTable();
-	else
-		result = createSci0ClassTable();
+	result = createClassTable();
 
 	if (result)
 		error("SegManager: Failed to initialize class table");
@@ -692,7 +689,6 @@
 				return;
 			}
 
-			_classtable[species].script = scr->nr;
 			_classtable[species].reg.segment = seg;
 			_classtable[species].reg.offset = classpos;
 		}
@@ -916,137 +912,24 @@
 	return 0; // OK
 }
 
-int SegManager::createSci11ClassTable() {
-	int scriptnr;
-	unsigned int seeker_offset;
-	char *seeker_ptr;
-	int classnr;
-
+int SegManager::createClassTable() {
 	Resource *vocab996 = _resMgr->findResource(ResourceId(kResourceTypeVocab, 996), 1);
 
 	if (!vocab996)
-		_classtable.resize(20);
-	else
-		_classtable.resize(vocab996->size >> 2);
+		error("SegManager: failed to open vocab 996");
 
-	for (scriptnr = 0; scriptnr < 1000; scriptnr++) {
-		Resource *heap = _resMgr->findResource(ResourceId(kResourceTypeHeap, scriptnr), 0);
+	int totalClasses = vocab996->size >> 2;
+	_classtable.resize(totalClasses);
 
-		if (heap) {
-			int global_vars = READ_LE_UINT16(heap->data + 2);
+	for (uint16 classNr = 0; classNr < totalClasses; classNr++) {
+		uint16 scriptNr = READ_LE_UINT16(vocab996->data + classNr * 4 + 2);
 
-			seeker_ptr = (char*)heap->data + 4 + global_vars * 2;
-			seeker_offset = 4 + global_vars * 2;
-
-			while (READ_LE_UINT16((byte*)seeker_ptr) == SCRIPT_OBJECT_MAGIC_NUMBER) {
-				if (READ_LE_UINT16((byte*)seeker_ptr + 14) & SCRIPT_INFO_CLASS) {
-					classnr = READ_LE_UINT16((byte*)seeker_ptr + 10);
-					if (classnr >= (int)_classtable.size()) {
-						if (classnr >= SCRIPT_MAX_CLASSTABLE_SIZE) {
-							warning("Invalid class number 0x%x in script.%d(0x%x), offset %04x",
-							        classnr, scriptnr, scriptnr, seeker_offset);
-							return 1;
-						}
-
-						_classtable.resize(classnr + 1); // Adjust maximum number of entries
-					}
-
-					_classtable[classnr].reg.offset = seeker_offset;
-					_classtable[classnr].reg.segment = 0;
-					_classtable[classnr].script = scriptnr;
-				}
-
-				seeker_ptr += READ_LE_UINT16((byte*)seeker_ptr + 2) * 2;
-				seeker_offset += READ_LE_UINT16((byte*)seeker_ptr + 2) * 2;
-			}
-		}
+		_classtable[classNr].reg = NULL_REG;
+		_classtable[classNr].script = scriptNr;
 	}
 
 	_resMgr->unlockResource(vocab996);
-	vocab996 = NULL;
-	return 0;
-}
 
-int SegManager::createSci0ClassTable() {
-	int scriptnr;
-	unsigned int seeker;
-	int classnr;
-	int magic_offset; // For strange scripts in older SCI versions
-
-	Resource *vocab996 = _resMgr->findResource(ResourceId(kResourceTypeVocab, 996), 1);
-	SciVersion version = _version;	// for the offset defines
-
-	if (!vocab996)
-		_classtable.resize(20);
-	else
-		_classtable.resize(vocab996->size >> 2);
-
-	for (scriptnr = 0; scriptnr < 1000; scriptnr++) {
-		int objtype = 0;
-		Resource *script = _resMgr->findResource(ResourceId(kResourceTypeScript, scriptnr), 0);
-
-		if (script) {
-			if (version == SCI_VERSION_0_EARLY)	// check if we got an old script header
-				magic_offset = seeker = 2;
-			else
-				magic_offset = seeker = 0;
-
-			do {
-				while (seeker < script->size)	{
-					unsigned int lastseeker = seeker;
-					objtype = (int16)READ_LE_UINT16(script->data + seeker);
-					if (objtype == SCI_OBJ_CLASS || objtype == SCI_OBJ_TERMINATOR)
-						break;
-					seeker += (int16)READ_LE_UINT16(script->data + seeker + 2);
-					if (seeker <= lastseeker) {
-						_classtable.clear();
-						error("Script version is invalid");
-					}
-				}
-
-				if (objtype == SCI_OBJ_CLASS) {
-					int sugg_script;
-
-					seeker -= SCRIPT_OBJECT_MAGIC_OFFSET; // Adjust position; script home is base +8 bytes
-
-					classnr = (int16)READ_LE_UINT16(script->data + seeker + 4 + SCRIPT_SPECIES_OFFSET);
-					if (classnr >= (int)_classtable.size()) {
-
-						if (classnr >= SCRIPT_MAX_CLASSTABLE_SIZE) {
-							warning("Invalid class number 0x%x in script.%d(0x%x), offset %04x",
-							        classnr, scriptnr, scriptnr, seeker);
-							return 1;
-						}
-
-						_classtable.resize(classnr + 1); // Adjust maximum number of entries
-					}
-
-					// Map the class ID to the script the corresponding class is contained in
-					// The script number is found in vocab.996, if it exists
-					if (!vocab996 || (uint32)classnr >= vocab996->size >> 2)
-						sugg_script = -1;
-					else
-						sugg_script = (int16)READ_LE_UINT16(vocab996->data + 2 + (classnr << 2));
-
-					// First, test whether the script hasn't been claimed, or if it's been claimed by the wrong script
-
-					if (sugg_script == -1 || scriptnr == sugg_script /*|| !s->_classtable[classnr].reg.segment*/)  {
-						// Now set the home script of the class
-						_classtable[classnr].reg.offset = seeker + 4 - magic_offset;
-						_classtable[classnr].reg.segment = 0;
-						_classtable[classnr].script = scriptnr;
-					}
-
-					seeker += SCRIPT_OBJECT_MAGIC_OFFSET; // Re-adjust position
-					seeker += (int16)READ_LE_UINT16(script->data + seeker + 2); // Move to next
-				}
-
-			} while (objtype != SCI_OBJ_TERMINATOR && seeker <= script->size);
-
-		}
-	}
-	_resMgr->unlockResource(vocab996);
-	vocab996 = NULL;
 	return 0;
 }
 

Modified: scummvm/trunk/engines/sci/engine/seg_manager.h
===================================================================
--- scummvm/trunk/engines/sci/engine/seg_manager.h	2009-08-23 22:51:57 UTC (rev 43679)
+++ scummvm/trunk/engines/sci/engine/seg_manager.h	2009-08-24 01:59:58 UTC (rev 43680)
@@ -360,8 +360,7 @@
 	LocalVariables *allocLocalsSegment(Script *scr, int count);
 	MemObject *memObjAllocate(SegmentId segid, int hash_id, MemObjectType type);
 	int deallocate(SegmentId seg, bool recursive);
-	int createSci0ClassTable();
-	int createSci11ClassTable();
+	int createClassTable();
 
 	Hunk *alloc_Hunk(reg_t *);
 

Modified: scummvm/trunk/engines/sci/engine/vm.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/vm.cpp	2009-08-23 22:51:57 UTC (rev 43679)
+++ scummvm/trunk/engines/sci/engine/vm.cpp	2009-08-24 01:59:58 UTC (rev 43680)
@@ -312,13 +312,6 @@
 		ObjVarRef varp;
 		switch (lookup_selector(s, send_obj, selector, &varp, &funcp)) {
 		case kSelectorNone:
-			// WORKAROUND: LSL6 tries to access the invalid 'keep' selector of the game object.
-			// FIXME: Find out if this is a game bug.
-			if ((s->_gameName == "LSL6") && (selector == 0x18c)) {
-				debug("LSL6 detected, continuing...");
-				break;
-			}
-
 			error("Send to invalid selector 0x%x of object at %04x:%04x", 0xffff & selector, PRINT_REG(send_obj));
 
 			break;
@@ -1660,7 +1653,6 @@
 				return 1;
 			}
 
-			segManager->_classtable[species].script = script_nr;
 			segManager->_classtable[species].reg = addr;
 			segManager->_classtable[species].reg.offset = classpos;
 			// Set technical class position-- into the block allocated for it


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