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

thebluegr at users.sourceforge.net thebluegr at users.sourceforge.net
Tue Aug 18 12:01:18 CEST 2009


Revision: 43504
          http://scummvm.svn.sourceforge.net/scummvm/?rev=43504&view=rev
Author:   thebluegr
Date:     2009-08-18 10:01:18 +0000 (Tue, 18 Aug 2009)

Log Message:
-----------
- Added game ID detection to the fallback detector. We still need to map some of Sierra's internal IDs to our own ones
- The class table is now created in the segment manager constructor

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

Modified: scummvm/trunk/engines/sci/detection.cpp
===================================================================
--- scummvm/trunk/engines/sci/detection.cpp	2009-08-18 09:12:41 UTC (rev 43503)
+++ scummvm/trunk/engines/sci/detection.cpp	2009-08-18 10:01:18 UTC (rev 43504)
@@ -27,6 +27,7 @@
 #include "base/plugins.h"
 
 #include "sci/sci.h"
+#include "sci/engine/kernel.h"
 #include "sci/exereader.h"
 #include "sci/engine/seg_manager.h"
 
@@ -3047,8 +3048,12 @@
 		Common::String filename = file->getName();
 		filename.toLowercase();
 
-		if (filename.contains("resource.map") || filename.contains("resmap.000"))
+		if (filename.contains("resource.map") || filename.contains("resmap.000")) {
+			// resource.map is located in the same directory as the other resource files,
+			// therefore add the directory here, so that the game files can be opened later on
+			Common::File::addDefaultDirectory(file->getParent().getPath());
 			foundResMap = true;
+		}
 
 		if (filename.contains("resource.000") || filename.contains("resource.001")
 			|| filename.contains("ressci.000") || filename.contains("ressci.001"))
@@ -3081,24 +3086,30 @@
 		return 0;
 
 	// Set some defaults
-	s_fallbackDesc.desc.gameid = "sci";
 	s_fallbackDesc.desc.extra = "";
 	s_fallbackDesc.desc.language = Common::UNK_LANG;
 	s_fallbackDesc.desc.platform = exePlatform;
 	s_fallbackDesc.desc.flags = ADGF_NO_FLAGS;
 
-#if 0
 	// Determine the game id
-	// TODO
 	ResourceManager *resMgr = new ResourceManager();
 	SciVersion version = resMgr->sciVersion();
-	SegManager *segManager = new SegManager(resMgr, version);
+	Kernel *kernel = new Kernel(resMgr);
+	SegManager *segManager = new SegManager(resMgr, version, kernel->hasOldScriptHeader());
+	if (!script_instantiate(resMgr, segManager, version, kernel->hasOldScriptHeader(), 0)) {
+		warning("fallbackDetect(): Could not instantiate script 0");
+		return 0;
+	}
 	reg_t game_obj = script_lookup_export(segManager, 0, 0);
 	Common::String gameName = obj_get_name(segManager,version, game_obj);
 	debug(2, " \"%s\" at %04x:%04x", gameName.c_str(), PRINT_REG(game_obj));
+	gameName.toLowercase();
+	// TODO: Sierra's game IDs are not always the same as our own ones, we need to map them
+	// accordingly here
+	s_fallbackDesc.desc.gameid = strdup(gameName.c_str());
+	delete kernel;
 	delete segManager;
 	delete resMgr;
-#endif
 
 	printf("If this is *NOT* a fan-modified version (in particular, not a fan-made\n");
 	printf("translation), please, report the data above, including the following\n");

Modified: scummvm/trunk/engines/sci/engine/game.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/game.cpp	2009-08-18 09:12:41 UTC (rev 43503)
+++ scummvm/trunk/engines/sci/engine/game.cpp	2009-08-18 10:01:18 UTC (rev 43504)
@@ -188,157 +188,10 @@
 	return 0;
 }
 
-int create_class_table_sci11(EngineState *s) {
-	int scriptnr;
-	unsigned int seeker_offset;
-	char *seeker_ptr;
-	int classnr;
-
-	Resource *vocab996 = s->resmgr->findResource(ResourceId(kResourceTypeVocab, 996), 1);
-
-	if (!vocab996)
-		s->seg_manager->_classtable.resize(20);
-	else
-		s->seg_manager->_classtable.resize(vocab996->size >> 2);
-
-	for (scriptnr = 0; scriptnr < 1000; scriptnr++) {
-		Resource *heap = s->resmgr->findResource(ResourceId(kResourceTypeHeap, scriptnr), 0);
-
-		if (heap) {
-			int global_vars = READ_LE_UINT16(heap->data + 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)s->seg_manager->_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;
-						}
-
-						s->seg_manager->_classtable.resize(classnr + 1); // Adjust maximum number of entries
-					}
-
-					s->seg_manager->_classtable[classnr].reg.offset = seeker_offset;
-					s->seg_manager->_classtable[classnr].reg.segment = 0;
-					s->seg_manager->_classtable[classnr].script = scriptnr;
-				}
-
-				seeker_ptr += READ_LE_UINT16((byte*)seeker_ptr + 2) * 2;
-				seeker_offset += READ_LE_UINT16((byte*)seeker_ptr + 2) * 2;
-			}
-		}
-	}
-
-	s->resmgr->unlockResource(vocab996);
-	vocab996 = NULL;
-	return 0;
-}
-
-static int create_class_table_sci0(EngineState *s) {
-	int scriptnr;
-	unsigned int seeker;
-	int classnr;
-	int magic_offset; // For strange scripts in older SCI versions
-
-	Resource *vocab996 = s->resmgr->findResource(ResourceId(kResourceTypeVocab, 996), 1);
-	SciVersion version = s->_version;	// for the offset defines
-
-	if (!vocab996)
-		s->seg_manager->_classtable.resize(20);
-	else
-		s->seg_manager->_classtable.resize(vocab996->size >> 2);
-
-	for (scriptnr = 0; scriptnr < 1000; scriptnr++) {
-		int objtype = 0;
-		Resource *script = s->resmgr->findResource(ResourceId(kResourceTypeScript, scriptnr), 0);
-
-		if (script) {
-			if (((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader())
-				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) {
-						s->seg_manager->_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)s->seg_manager->_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;
-						}
-
-						s->seg_manager->_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
-						s->seg_manager->_classtable[classnr].reg.offset = seeker + 4 - magic_offset;
-						s->seg_manager->_classtable[classnr].reg.segment = 0;
-						s->seg_manager->_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);
-
-		}
-	}
-	s->resmgr->unlockResource(vocab996);
-	vocab996 = NULL;
-	return 0;
-}
-
 // Architectural stuff: Init/Unintialize engine
 int script_init_engine(EngineState *s) {
-	int result;
-
 	s->kernel_opt_flags = 0;
-	s->seg_manager = new SegManager(s->resmgr, s->_version);
-
-	if (s->_version >= SCI_VERSION_1_1)
-		result = create_class_table_sci11(s);
-	else
-		result = create_class_table_sci0(s);
-
-	if (result) {
-		debug(2, "Failed to initialize class table");
-		return 1;
-	}
-
+	s->seg_manager = new SegManager(s->resmgr, s->_version, ((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader());
 	s->gc_countdown = GC_INTERVAL - 1;
 
 	SegmentId script_000_segment = s->seg_manager->getSegment(0, SCRIPT_GET_LOCK);
@@ -441,7 +294,7 @@
 	s->stack_base = stack->entries;
 	s->stack_top = s->stack_base + VM_STACK_SIZE;
 
-	if (!script_instantiate(s->resmgr, s->seg_manager, s->_version, 0)) {
+	if (!script_instantiate(s->resmgr, s->seg_manager, s->_version, ((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader(), 0)) {
 		warning("game_init(): Could not instantiate script 0");
 		return 1;
 	}

Modified: scummvm/trunk/engines/sci/engine/savegame.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/savegame.cpp	2009-08-18 09:12:41 UTC (rev 43503)
+++ scummvm/trunk/engines/sci/engine/savegame.cpp	2009-08-18 10:01:18 UTC (rev 43504)
@@ -219,7 +219,7 @@
 	if (s.isLoading()) {
 		// FIXME: Do in-place loading at some point, instead of creating a new EngineState instance from scratch.
 		delete obj;
-		obj = new SegManager(resMgr, version);
+		obj = new SegManager(resMgr, version, ((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader());
 	}
 
 	obj->saveLoadWithSerializer(s);

Modified: scummvm/trunk/engines/sci/engine/seg_manager.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/seg_manager.cpp	2009-08-18 09:12:41 UTC (rev 43503)
+++ scummvm/trunk/engines/sci/engine/seg_manager.cpp	2009-08-18 10:01:18 UTC (rev 43504)
@@ -52,7 +52,7 @@
 
 #define INVALID_SCRIPT_ID -1
 
-SegManager::SegManager(ResourceManager *resMgr, SciVersion version) {
+SegManager::SegManager(ResourceManager *resMgr, SciVersion version, bool oldScriptHeader) {
 	id_seg_map = new IntMapper();
 	reserved_id = INVALID_SCRIPT_ID;
 	id_seg_map->checkKey(reserved_id, true);	// reserve entry 0 for INVALID_SCRIPT_ID
@@ -68,6 +68,17 @@
 	exports_wide = 0;
 	_version = version;
 	_resMgr = resMgr;
+	_oldScriptHeader = oldScriptHeader;
+
+	int result = 0;
+
+	if (version >= SCI_VERSION_1_1)
+		result = createSci11ClassTable();
+	else
+		result = createSci0ClassTable();
+
+	if (result)
+		error("SegManager: Failed to initialize class table");
 }
 
 // Destroy the object, free the memorys if allocated before
@@ -139,7 +150,7 @@
 	if (!script || (_version >= SCI_VERSION_1_1 && !heap)) {
 		error("SegManager::setScriptSize: failed to load %s", !script ? "script" : "heap");
 	}
-	if (((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader()) {
+	if (_oldScriptHeader) {
 		scr.buf_size = script->size + READ_LE_UINT16(script->data) * 2;
 		//locals_size = READ_LE_UINT16(script->data) * 2;
 	} else if (_version < SCI_VERSION_1_1) {
@@ -434,7 +445,7 @@
 	SegmentId segment;
 
 	if ((load & SCRIPT_GET_LOAD) == SCRIPT_GET_LOAD)
-		script_instantiate(_resMgr, this, _version, script_nr);
+		script_instantiate(_resMgr, this, _version, _oldScriptHeader, script_nr);
 
 	segment = segGet(script_nr);
 
@@ -906,5 +917,138 @@
 	return 0; // OK
 }
 
+int SegManager::createSci11ClassTable() {
+	int scriptnr;
+	unsigned int seeker_offset;
+	char *seeker_ptr;
+	int classnr;
 
+	Resource *vocab996 = _resMgr->findResource(ResourceId(kResourceTypeVocab, 996), 1);
+
+	if (!vocab996)
+		_classtable.resize(20);
+	else
+		_classtable.resize(vocab996->size >> 2);
+
+	for (scriptnr = 0; scriptnr < 1000; scriptnr++) {
+		Resource *heap = _resMgr->findResource(ResourceId(kResourceTypeHeap, scriptnr), 0);
+
+		if (heap) {
+			int global_vars = READ_LE_UINT16(heap->data + 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;
+			}
+		}
+	}
+
+	_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 (_oldScriptHeader)
+				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;
+}
+
 } // End of namespace Sci

Modified: scummvm/trunk/engines/sci/engine/seg_manager.h
===================================================================
--- scummvm/trunk/engines/sci/engine/seg_manager.h	2009-08-18 09:12:41 UTC (rev 43503)
+++ scummvm/trunk/engines/sci/engine/seg_manager.h	2009-08-18 10:01:18 UTC (rev 43504)
@@ -58,7 +58,7 @@
 	/**
 	 * Initialize the segment manager
 	 */
-	SegManager(ResourceManager *resMgr, SciVersion version);
+	SegManager(ResourceManager *resMgr, SciVersion version, bool oldScriptHeader);
 
 	/**
 	 * Deallocate all memory associated with the segment manager
@@ -342,6 +342,7 @@
 
 private:
 	IntMapper *id_seg_map; ///< id - script id; seg - index of heap
+	bool _oldScriptHeader;
 public: // TODO: make private
 	Common::Array<MemObject *> _heap;
 	int reserved_id;
@@ -360,6 +361,8 @@
 	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();
 
 	Hunk *alloc_Hunk(reg_t *);
 

Modified: scummvm/trunk/engines/sci/engine/vm.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/vm.cpp	2009-08-18 09:12:41 UTC (rev 43503)
+++ scummvm/trunk/engines/sci/engine/vm.cpp	2009-08-18 10:01:18 UTC (rev 43504)
@@ -208,7 +208,7 @@
 	Script *scr = s->seg_manager->getScriptIfLoaded(seg);
 
 	if (!scr)  // Script not present yet?
-		seg = script_instantiate(s->resmgr, s->seg_manager, s->_version, script);
+		seg = script_instantiate(s->resmgr, s->seg_manager, s->_version, ((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader(), script);
 	else
 		scr->unmarkDeleted();
 
@@ -1573,7 +1573,7 @@
 	return seg_id;
 }
 
-int script_instantiate_sci0(ResourceManager *resMgr, SegManager *segManager, SciVersion version, int script_nr) {
+int script_instantiate_sci0(ResourceManager *resMgr, SegManager *segManager, SciVersion version, bool oldScriptHeader, int script_nr) {
 	int objtype;
 	unsigned int objlength;
 	reg_t reg;
@@ -1593,7 +1593,7 @@
 
 	Script *scr = segManager->getScript(seg_id);
 
-	if (((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader()) {
+	if (oldScriptHeader) {
 		//
 		int locals_nr = READ_LE_UINT16(script->data);
 
@@ -1761,11 +1761,11 @@
 	return seg_id;
 }
 
-int script_instantiate(ResourceManager *resMgr, SegManager *segManager, SciVersion version, int script_nr) {
+int script_instantiate(ResourceManager *resMgr, SegManager *segManager, SciVersion version, bool oldScriptHeader, int script_nr) {
 	if (version >= SCI_VERSION_1_1)
 		return script_instantiate_sci11(resMgr, segManager, version, script_nr);
 	else
-		return script_instantiate_sci0(resMgr, segManager, version, script_nr);
+		return script_instantiate_sci0(resMgr, segManager, version, oldScriptHeader, script_nr);
 }
 
 void script_uninstantiate_sci0(SegManager *segManager, SciVersion version, int script_nr, SegmentId seg) {

Modified: scummvm/trunk/engines/sci/engine/vm.h
===================================================================
--- scummvm/trunk/engines/sci/engine/vm.h	2009-08-18 09:12:41 UTC (rev 43503)
+++ scummvm/trunk/engines/sci/engine/vm.h	2009-08-18 10:01:18 UTC (rev 43504)
@@ -489,7 +489,7 @@
  * @param[in] script_nr		The script number to load
  * @return					The script's segment ID or 0 if out of heap
  */
-int script_instantiate(ResourceManager *resMgr, SegManager *segManager, SciVersion version, int script_nr);
+int script_instantiate(ResourceManager *resMgr, SegManager *segManager, SciVersion version, bool oldScriptHeader, int script_nr);
 
 /**
  * Decreases the numer of lockers of a script and unloads it if that number


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