[Scummvm-cvs-logs] scummvm master -> 0bc9db7872ca163a2a7ccfde74ab0afa4656345c

bluegr md5 at scummvm.org
Sat Mar 12 17:35:06 CET 2011


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:
0bc9db7872 SCI: Added automatic detection for several selectors


Commit: 0bc9db7872ca163a2a7ccfde74ab0afa4656345c
    https://github.com/scummvm/scummvm/commit/0bc9db7872ca163a2a7ccfde74ab0afa4656345c
Author: md5 (md5 at scummvm.org)
Date: 2011-03-12T08:33:32-08:00

Commit Message:
SCI: Added automatic detection for several selectors

This ensures that these selectors will be detected regardless of the game
ID, when they're missing

Changed paths:
    engines/sci/engine/kernel.h
    engines/sci/engine/static_selectors.cpp



diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h
index 202fc40..9a55ef6 100644
--- a/engines/sci/engine/kernel.h
+++ b/engines/sci/engine/kernel.h
@@ -255,6 +255,11 @@ private:
 	Common::StringArray checkStaticSelectorNames();
 
 	/**
+	 * Automatically find specific selectors
+	 */
+	void findSpecificSelectors(Common::StringArray &selectorNames);
+
+	/**
 	 * Maps special selectors.
 	 */
 	void mapSelectors();
diff --git a/engines/sci/engine/static_selectors.cpp b/engines/sci/engine/static_selectors.cpp
index 96507e3..23241de 100644
--- a/engines/sci/engine/static_selectors.cpp
+++ b/engines/sci/engine/static_selectors.cpp
@@ -28,6 +28,7 @@
 
 #include "sci/engine/kernel.h"
 #include "sci/engine/seg_manager.h"
+#include "sci/engine/vm.h"
 
 namespace Sci {
 
@@ -118,6 +119,33 @@ static const SelectorRemap sciSelectorRemap[] = {
 	{ SCI_VERSION_NONE,             SCI_VERSION_NONE,            0,   0 }
 };
 
+struct ClassReference {
+	int script;
+	const char *className;
+	const char *selectorName;
+	SelectorType selectorType;
+	uint selectorOffset;
+};
+
+// For variable selectors, we ignore the global selectors and start off from
+// the object's selectors (i.e. from the name selector onwards). Thus, the
+// following are not taken into consideration when calculating the indices of
+// variable selectors in this array:
+// SCI0 - SCI1: species, superClass, -info-
+// SCI1.1: -objID-, -size-, -propDict-, -methDict-, -classScript-, -script-,
+//         -super-, -info-
+static const ClassReference classReferences[] = {
+	{   0, "Character",         "say",   kSelectorMethod,  5 },	// Crazy Nick's Soft Picks
+	{ 928,  "Narrator",         "say",   kSelectorMethod,  4 },
+	{ 928,  "Narrator",   "startText",   kSelectorMethod,  5 },
+	{ 929,      "Sync",    "syncTime", kSelectorVariable,  1 },
+	{ 929,      "Sync",     "syncCue", kSelectorVariable,  2 },
+	{ 981, "SysWindow",        "open",   kSelectorMethod,  1 },
+	{ 999,    "Script",        "init",   kSelectorMethod,  0 },
+	{ 999,    "Script",     "dispose",   kSelectorMethod,  2 },
+	{ 999,    "Script", "changeState",   kSelectorMethod,  3 }
+};
+
 Common::StringArray Kernel::checkStaticSelectorNames() {
 	Common::StringArray names;
 	const int offset = (getSciVersion() < SCI_VERSION_1_1) ? 3 : 0;
@@ -158,133 +186,115 @@ Common::StringArray Kernel::checkStaticSelectorNames() {
 				names[i] = sci11Selectors[i - count - countSci1];
 		}
 
-		// Now, we need to find out selectors which keep changing place...
-		// We do that by dissecting game objects, and looking for selectors at
-		// specified locations.
+		findSpecificSelectors(names);
 
-		// We need to initialize script 0 here, to make sure that it's always
-		// located at segment 1.
-		_segMan->instantiateScript(0);
-
-		// The Actor class contains the init, xLast and yLast selectors, which
-		// we reference directly. It's always in script 998, so we need to
-		// explicitly load it here.
-		if (_resMan->testResource(ResourceId(kResourceTypeScript, 998))) {
-			_segMan->instantiateScript(998);
-
-			const Object *actorClass = _segMan->getObject(_segMan->findObjectByName("Actor"));
-
-			if (actorClass) {
-				// The init selector is always the first function
-				int initSelectorPos = actorClass->getFuncSelector(0);
+#ifdef ENABLE_SCI32
+	} else {
+		// SCI2+
+		for (int i = 0; i < count; i++)
+			names[i] = sci2Selectors[i];
+#endif
+	}
 
-				if (names.size() < (uint32)initSelectorPos + 2)
-					names.resize((uint32)initSelectorPos + 2);
+	for (const SelectorRemap *selectorRemap = sciSelectorRemap; selectorRemap->slot; ++selectorRemap) {
+		if (getSciVersion() >= selectorRemap->minVersion && getSciVersion() <= selectorRemap->maxVersion) {
+			const uint32 slot = selectorRemap->slot;
+			if (slot >= names.size())
+				names.resize(slot + 1);
+			names[slot] = selectorRemap->name;
+		}
+	}
 
-				names[initSelectorPos] = "init";
-				// dispose comes right after init
-				names[initSelectorPos + 1] = "dispose";
+	return names;
+}
 
-				if ((getSciVersion() >= SCI_VERSION_1_EGA_ONLY)) {
-					// Find the xLast and yLast selectors, used in kDoBresen
+void Kernel::findSpecificSelectors(Common::StringArray &selectorNames) {
+	// Now, we need to find out selectors which keep changing place...
+	// We do that by dissecting game objects, and looking for selectors at
+	// specified locations.
 
-					// xLast and yLast always come between illegalBits and xStep
-					int illegalBitsSelectorPos = actorClass->locateVarSelector(_segMan, 15 + offset);	// illegalBits
-					int xStepSelectorPos = actorClass->locateVarSelector(_segMan, 51 + offset);	// xStep
-					if (xStepSelectorPos - illegalBitsSelectorPos != 3) {
-						error("illegalBits and xStep selectors aren't found in "
-							  "known locations. illegalBits = %d, xStep = %d",
-							  illegalBitsSelectorPos, xStepSelectorPos);
-					}
+	// We need to initialize script 0 here, to make sure that it's always
+	// located at segment 1.
+	_segMan->instantiateScript(0);
 
-					int xLastSelectorPos = actorClass->getVarSelector(illegalBitsSelectorPos + 1);
-					int yLastSelectorPos = actorClass->getVarSelector(illegalBitsSelectorPos + 2);
+	// The Actor class contains the init, xLast and yLast selectors, which
+	// we reference directly. It's always in script 998, so we need to
+	// explicitly load it here.
+	if ((getSciVersion() >= SCI_VERSION_1_EGA_ONLY)) {
+		if (_resMan->testResource(ResourceId(kResourceTypeScript, 998))) {
+			_segMan->instantiateScript(998);
 
-					if (names.size() < (uint32)yLastSelectorPos + 1)
-						names.resize((uint32)yLastSelectorPos + 1);
+			const Object *actorClass = _segMan->getObject(_segMan->findObjectByName("Actor"));
 
-					names[xLastSelectorPos] = "xLast";
-					names[yLastSelectorPos] = "yLast";
-				}	// if ((getSciVersion() >= SCI_VERSION_1_EGA_ONLY))
+			if (actorClass) {
+				// Find the xLast and yLast selectors, used in kDoBresen
+
+				const int offset = (getSciVersion() < SCI_VERSION_1_1) ? 3 : 0;
+				// xLast and yLast always come between illegalBits and xStep
+				int illegalBitsSelectorPos = actorClass->locateVarSelector(_segMan, 15 + offset);	// illegalBits
+				int xStepSelectorPos = actorClass->locateVarSelector(_segMan, 51 + offset);	// xStep
+				if (xStepSelectorPos - illegalBitsSelectorPos != 3) {
+					error("illegalBits and xStep selectors aren't found in "
+							"known locations. illegalBits = %d, xStep = %d",
+							illegalBitsSelectorPos, xStepSelectorPos);
+				}
+
+				int xLastSelectorPos = actorClass->getVarSelector(illegalBitsSelectorPos + 1);
+				int yLastSelectorPos = actorClass->getVarSelector(illegalBitsSelectorPos + 2);
+
+				if (selectorNames.size() < (uint32)yLastSelectorPos + 1)
+					selectorNames.resize((uint32)yLastSelectorPos + 1);
+
+				selectorNames[xLastSelectorPos] = "xLast";
+				selectorNames[yLastSelectorPos] = "yLast";
 			}	// if (actorClass)
 
 			_segMan->uninstantiateScript(998);
 		}	// if (_resMan->testResource(ResourceId(kResourceTypeScript, 998)))
+	}	// if ((getSciVersion() >= SCI_VERSION_1_EGA_ONLY))
+
+	// Find selectors from specific classes
+
+	for (int i = 0; i < ARRAYSIZE(classReferences); i++) {
+		if (!_resMan->testResource(ResourceId(kResourceTypeScript, classReferences[i].script)))
+			continue;
 
-		if (_resMan->testResource(ResourceId(kResourceTypeScript, 981))) {
-			// The SysWindow class contains the open selectors, which we
-			// reference directly. It's always in script 981, so we need to
-			// explicitly load it here
-			_segMan->instantiateScript(981);
+		_segMan->instantiateScript(classReferences[i].script);
 
-			const Object *sysWindowClass = _segMan->getObject(_segMan->findObjectByName("SysWindow"));
+		const Object *targetClass = _segMan->getObject(_segMan->findObjectByName(classReferences[i].className));
+		int targetSelectorPos = 0;
+		uint selectorOffset = classReferences[i].selectorOffset;
 
-			if (sysWindowClass) {
-				if (sysWindowClass->getMethodCount() < 2)
-					error("The SysWindow class has less than 2 methods");
+		if (targetClass) {
+			if (classReferences[i].selectorType == kSelectorMethod) {
+				if (targetClass->getMethodCount() < selectorOffset + 1)
+					error("The %s class has less than %d methods (%d)", 
+							classReferences[i].className, selectorOffset + 1, 
+							targetClass->getMethodCount());
 
-				// The open selector is always the second function
-				int openSelectorPos = sysWindowClass->getFuncSelector(1);
+				targetSelectorPos = targetClass->getFuncSelector(selectorOffset);
+			} else {
+				// Add the global selectors to the selector ID
+				selectorOffset += (getSciVersion() <= SCI_VERSION_1_LATE) ? 3 : 8;
 
-				if (names.size() < (uint32)openSelectorPos + 1)
-					names.resize((uint32)openSelectorPos + 1);
+				if (targetClass->getVarCount() < selectorOffset + 1)
+					error("The %s class has less than %d variables (%d)", 
+							classReferences[i].className, selectorOffset + 1,
+							targetClass->getVarCount());
 
-				names[openSelectorPos] = "open";
+				targetSelectorPos = targetClass->getVarSelector(selectorOffset);
 			}
 
-			_segMan->uninstantiateScript(981);
-		}	// if (_resMan->testResource(ResourceId(kResourceTypeScript, 981)))
-
-		if (g_sci->getGameId() == GID_HOYLE4) {
-			// The demo of Hoyle 4 is one of the few demos with lip syncing and no selector vocabulary.
-			// This needs two selectors, "syncTime" and "syncCue", which keep changing positions in each
-			// game. Usually, games with speech and lip sync have a selector vocabulary, so we don't need
-			// to set these two selectors, but we need for Hoyle...
-			if (names.size() < 276)
-				names.resize(276);
-
-			names[274] = "syncTime";
-			names[275] = "syncCue";
-		} else if (g_sci->getGameId() == GID_PEPPER) {
-			// Same as above for the non-interactive demo of Pepper
-			if (names.size() < 539)
-				names.resize(539);
-
-			names[263] = "syncTime";
-			names[264] = "syncCue";
-			names[538] = "startText";
-		} else if (g_sci->getGameId() == GID_LAURABOW2) {
-			// The floppy of version needs the changeState selector set to match up with the
-			// CD version's workarounds.
-			if (names.size() < 251)
-				names.resize(251);
-
-			names[144] = "changeState";
-		} else if (g_sci->getGameId() == GID_CNICK_KQ) {
-			if (names.size() < 447)
-				names.resize(447);
-
-			names[446] = "say";
-		}
+			if (selectorNames.size() < (uint32)targetSelectorPos + 1)
+				selectorNames.resize((uint32)targetSelectorPos + 1);
 
-#ifdef ENABLE_SCI32
-	} else {
-		// SCI2+
-		for (int i = 0; i < count; i++)
-			names[i] = sci2Selectors[i];
-#endif
-	}
 
-	for (const SelectorRemap *selectorRemap = sciSelectorRemap; selectorRemap->slot; ++selectorRemap) {
-		if (getSciVersion() >= selectorRemap->minVersion && getSciVersion() <= selectorRemap->maxVersion) {
-			const uint32 slot = selectorRemap->slot;
-			if (slot >= names.size())
-				names.resize(slot + 1);
-			names[slot] = selectorRemap->name;
+			selectorNames[targetSelectorPos] = classReferences[i].selectorName;
 		}
 	}
 
-	return names;
+	// Reset the segment manager
+	_segMan->resetSegMan();
 }
 
 } // End of namespace Sci






More information about the Scummvm-git-logs mailing list