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

waltervn at users.sourceforge.net waltervn at users.sourceforge.net
Sun Aug 30 16:53:58 CEST 2009


Revision: 43824
          http://scummvm.svn.sourceforge.net/scummvm/?rev=43824&view=rev
Author:   waltervn
Date:     2009-08-30 14:53:58 +0000 (Sun, 30 Aug 2009)

Log Message:
-----------
SCI: Add lofs detection.

Modified Paths:
--------------
    scummvm/trunk/engines/sci/engine/game.cpp
    scummvm/trunk/engines/sci/engine/kernel.cpp
    scummvm/trunk/engines/sci/engine/kernel.h
    scummvm/trunk/engines/sci/engine/script.cpp
    scummvm/trunk/engines/sci/engine/script.h
    scummvm/trunk/engines/sci/engine/state.cpp
    scummvm/trunk/engines/sci/engine/state.h
    scummvm/trunk/engines/sci/engine/static_selectors.cpp
    scummvm/trunk/engines/sci/engine/vm.cpp
    scummvm/trunk/engines/sci/engine/vm.h
    scummvm/trunk/engines/sci/sci.cpp

Modified: scummvm/trunk/engines/sci/engine/game.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/game.cpp	2009-08-30 10:47:22 UTC (rev 43823)
+++ scummvm/trunk/engines/sci/engine/game.cpp	2009-08-30 14:53:58 UTC (rev 43824)
@@ -226,7 +226,7 @@
 	s->bp_list = NULL; // No breakpoints defined
 	s->have_bp = 0;
 
-	if (((SciEngine*)g_engine)->getKernel()->hasLofsAbsolute())
+	if (s->detectLofsType() == SCI_VERSION_1_MIDDLE)
 		s->segmentManager->setExportWidth(1);
 	else
 		s->segmentManager->setExportWidth(0);

Modified: scummvm/trunk/engines/sci/engine/kernel.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/kernel.cpp	2009-08-30 10:47:22 UTC (rev 43823)
+++ scummvm/trunk/engines/sci/engine/kernel.cpp	2009-08-30 14:53:58 UTC (rev 43824)
@@ -401,16 +401,6 @@
 			features |= kFeatureOldGfxFunctions;
 	}
 
-	// Lofs absolute/relative
-	if (version >= SCI_VERSION_1_MIDDLE && version < SCI_VERSION_1_1) {
-		// Assume all games use absolute lofs
-		features |= kFeatureLofsAbsolute;
-	} else if (version == SCI_VERSION_1_EARLY) {
-		// Use heuristic
-		if (_selectorMap.egoMoveSpeed != -1)
-			features |= kFeatureLofsAbsolute;
-	}
-
 	printf("Kernel auto-detected features:\n");
 
 	printf("Graphics functions: ");
@@ -418,14 +408,6 @@
 		printf("old\n");
 	else
 		printf("new\n");
-
-	if (version < SCI_VERSION_1_1) {
-		printf("lofs parameters: ");
-		if (features & kFeatureLofsAbsolute)
-			printf("absolute\n");
-		else
-			printf("relative\n");
-	}
 }
 
 void Kernel::loadSelectorNames() {

Modified: scummvm/trunk/engines/sci/engine/kernel.h
===================================================================
--- scummvm/trunk/engines/sci/engine/kernel.h	2009-08-30 10:47:22 UTC (rev 43823)
+++ scummvm/trunk/engines/sci/engine/kernel.h	2009-08-30 14:53:58 UTC (rev 43824)
@@ -54,8 +54,7 @@
 
 enum AutoDetectedFeatures {
 	kFeatureOldScriptHeader = 1 << 0,
-	kFeatureOldGfxFunctions = 1 << 1,
-	kFeatureLofsAbsolute    = 1 << 2
+	kFeatureOldGfxFunctions = 1 << 1
 };
 
 class Kernel {
@@ -95,13 +94,6 @@
 	 */
 	bool usesOldGfxFunctions() const { return (features & kFeatureOldGfxFunctions); }
 
-	/**
-	 * Applies to all SCI1 versions after 1.000.200
-	 * In late SCI1 versions, the argument of lofs[as] instructions
-	 * is absolute rather than relative.
-	 */
-	bool hasLofsAbsolute() const { return (features & kFeatureLofsAbsolute); }
-
 	// Script dissection/dumping functions
 	void dissectScript(int scriptNumber, Vocabulary *vocab);
 	void dumpScriptObject(char *data, int seeker, int objsize);

Modified: scummvm/trunk/engines/sci/engine/script.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/script.cpp	2009-08-30 10:47:22 UTC (rev 43823)
+++ scummvm/trunk/engines/sci/engine/script.cpp	2009-08-30 14:53:58 UTC (rev 43824)
@@ -88,14 +88,16 @@
 };
 #undef END
 
-void script_adjust_opcode_formats(SciVersion version) {
+void script_adjust_opcode_formats(EngineState *s) {
 	// TODO: Check that this is correct
-	if ((version >= SCI_VERSION_1_1) || ((SciEngine*)g_engine)->getKernel()->hasLofsAbsolute()) {
+	if (s->detectLofsType() != SCI_VERSION_0_EARLY) {
 		g_opcode_formats[op_lofsa][0] = Script_Offset;
 		g_opcode_formats[op_lofss][0] = Script_Offset;
 	}
-	
+
 #ifdef ENABLE_SCI32
+	SciVersion version = s->resourceManager->sciVersion();
+
 	// In SCI32, some arguments are now words instead of bytes
 	if (version >= SCI_VERSION_2) {
 		g_opcode_formats[op_calle][2] = Script_Word;
@@ -240,7 +242,6 @@
 	FIND_SELECTOR(subtitleLang);
 	FIND_SELECTOR(parseLang);
 	FIND_SELECTOR(motionCue);
-	FIND_SELECTOR(egoMoveSpeed);
 	FIND_SELECTOR(setCursor);
 }
 

Modified: scummvm/trunk/engines/sci/engine/script.h
===================================================================
--- scummvm/trunk/engines/sci/engine/script.h	2009-08-30 10:47:22 UTC (rev 43823)
+++ scummvm/trunk/engines/sci/engine/script.h	2009-08-30 14:53:58 UTC (rev 43824)
@@ -202,7 +202,7 @@
 
 extern opcode_format g_opcode_formats[128][4];
 
-void script_adjust_opcode_formats(SciVersion version);
+void script_adjust_opcode_formats(EngineState *s);
 
 void script_free_breakpoints(EngineState *s);
 

Modified: scummvm/trunk/engines/sci/engine/state.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/state.cpp	2009-08-30 10:47:22 UTC (rev 43823)
+++ scummvm/trunk/engines/sci/engine/state.cpp	2009-08-30 14:53:58 UTC (rev 43824)
@@ -25,6 +25,7 @@
 
 #include "sci/engine/state.h"
 #include "sci/engine/vm.h"
+#include "sci/engine/script.h"
 #include "sci/console.h" // For parse_reg_t
 
 namespace Sci {
@@ -121,6 +122,7 @@
 
 	_setCursorType = SCI_VERSION_AUTODETECT;
 	_doSoundType = SCI_VERSION_AUTODETECT;
+	_lofsType = SCI_VERSION_AUTODETECT;
 }
 
 EngineState::~EngineState() {
@@ -334,10 +336,133 @@
 				_setCursorType = SCI_VERSION_0_EARLY;
 		}
 
-		debugC(0, kDebugLevelGraphics, "Detected SetCursor type: %s", ((SciEngine *)g_engine)->getSciVersionDesc(_setCursorType).c_str());
+		debugC(1, kDebugLevelGraphics, "Detected SetCursor type: %s", ((SciEngine *)g_engine)->getSciVersionDesc(_setCursorType).c_str());
 	}
 
 	return _setCursorType;
 }
 
+SciVersion EngineState::detectLofsType() {
+	if (_lofsType == SCI_VERSION_AUTODETECT) {
+		SciVersion version = segmentManager->sciVersion(); // FIXME: for VM_OBJECT_READ_FUNCTION
+
+		// This detection only works (and is only needed) pre-SCI1.1
+		if (version >= SCI_VERSION_1_1) {
+			_lofsType = SCI_VERSION_1_1;
+			return _lofsType;
+		}
+
+		reg_t gameClass;
+		Object *obj = NULL;
+
+		if (!parse_reg_t(this, "?Game", &gameClass))
+			obj = obj_get(segmentManager, gameClass);
+
+		bool couldBeAbs = true;
+		bool couldBeRel = true;
+
+		// Check methods of the Game class for lofs operations
+		if (obj) {
+			for (int m = 0; m < obj->methods_nr; m++) {
+				reg_t fptr = VM_OBJECT_READ_FUNCTION(obj, m);
+
+				Script *script = segmentManager->getScript(fptr.segment);
+
+				if ((script == NULL) || (script->buf == NULL))
+					continue;
+
+				uint offset = fptr.offset;
+				bool done = false;
+
+				while (!done) {
+					// Read opcode
+					if (offset >= script->buf_size)
+						break;
+
+					byte opcode = script->buf[offset++];
+					byte opnumber = opcode >> 1;
+
+					if ((opnumber == 0x39) || (opnumber == 0x3a)) {
+						uint16 lofs;
+
+						// Load lofs operand
+						if (opcode & 1) {
+							if (offset >= script->buf_size)
+								break;
+							lofs = script->buf[offset++];
+						} else {
+							if (offset + 1 >= script->buf_size)
+								break;
+							lofs = READ_LE_UINT16(script->buf + offset);
+							offset += 2;
+						}
+
+						// Check for going out of bounds when interpreting as abs/rel
+						if (lofs >= script->buf_size)
+							couldBeAbs = false;
+
+						if ((signed)offset + (int16)lofs < 0)
+							couldBeRel = false;
+
+						if ((signed)offset + (int16)lofs >= (signed)script->buf_size)
+							couldBeRel = false;
+
+						continue;
+					}
+
+					// Skip operands for non-lofs opcodes
+					for (int i = 0; g_opcode_formats[opnumber][i]; i++) {
+						switch (g_opcode_formats[opnumber][i]) {
+						case Script_Byte:
+						case Script_SByte:
+							offset++;
+							break;
+						case Script_Word:
+						case Script_SWord:
+							offset += 2;
+							break;
+						case Script_Variable:
+						case Script_Property:
+						case Script_Local:
+						case Script_Temp:
+						case Script_Global:
+						case Script_Param:
+						case Script_SVariable:
+						case Script_SRelative:
+						case Script_Offset:
+							offset++;
+							if (!(opcode & 1))
+								offset++;
+							break;
+						case Script_End:
+							done = true;
+							break;
+						case Script_Invalid:
+						default:
+							warning("opcode %02x: Invalid", opcode);
+						}
+					}
+				}
+			}
+		}
+
+		if (couldBeRel == couldBeAbs) {
+			warning("Lofs detection failed, taking an educated guess");
+
+			if (version >= SCI_VERSION_1_MIDDLE)
+				_lofsType = SCI_VERSION_1_MIDDLE;
+
+			_lofsType = SCI_VERSION_0_EARLY;
+		} else if (couldBeAbs) {
+			_lofsType = SCI_VERSION_1_MIDDLE;
+		} else {
+			_lofsType = SCI_VERSION_0_EARLY;
+		}
+
+		debugC(1, kDebugLevelVM, "Detected Lofs type: %s", ((SciEngine *)g_engine)->getSciVersionDesc(_lofsType).c_str());
+	}
+
+	return _lofsType;
+}
+
 } // End of namespace Sci

Modified: scummvm/trunk/engines/sci/engine/state.h
===================================================================
--- scummvm/trunk/engines/sci/engine/state.h	2009-08-30 10:47:22 UTC (rev 43823)
+++ scummvm/trunk/engines/sci/engine/state.h	2009-08-30 14:53:58 UTC (rev 43824)
@@ -274,16 +274,22 @@
 
 	/**
 	 * Autodetects the DoSound type
-	 * @return DoSound type
+	 * @return DoSound type, SCI_VERSION_0_EARLY / SCI_VERSION_1_EARLY / SCI_VERSION_1_LATE
 	 */
 	SciVersion detectDoSoundType();
 
 	/**
 	 * Autodetects the SetCursor type
-	 * @return SetCursor type
+	 * @return SetCursor type, SCI_VERSION_0_EARLY / SCI_VERSION_1_1
 	 */
 	SciVersion detectSetCursorType();
 
+	/**
+	 * Autodetects the Lofs type
+	 * @return Lofs type, SCI_VERSION_0_EARLY / SCI_VERSION_1_MIDDLE / SCI_VERSION_1_1
+	 */
+	SciVersion detectLofsType();
+
 	/* Debugger data: */
 	Breakpoint *bp_list;   /**< List of breakpoints */
 	int have_bp;  /**< Bit mask specifying which types of breakpoints are used in bp_list */
@@ -314,7 +320,7 @@
 
 	Common::String getLanguageString(const char *str, kLanguage lang) const;
 private:
-	SciVersion _doSoundType, _setCursorType;
+	SciVersion _doSoundType, _setCursorType, _lofsType;
 	kLanguage charToLanguage(const char c) const;
 	int methodChecksum(reg_t objAddress, Selector sel, int offset, uint size) const;
 };

Modified: scummvm/trunk/engines/sci/engine/static_selectors.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/static_selectors.cpp	2009-08-30 10:47:22 UTC (rev 43823)
+++ scummvm/trunk/engines/sci/engine/static_selectors.cpp	2009-08-30 14:53:58 UTC (rev 43824)
@@ -120,7 +120,7 @@
 	{          "cue", 136 }, {        "owner", 150 }, {       "setVol", 156 },
 	{    "completed", 210 }, {    "motionCue", 213 }, {       "cycler", 215 },
 	{    "setTarget", 221 }, {     "distance", 224 }, {    "canBeHere", 232 },
-	{     "syncTime", 247 }, {      "syncCue", 248 }, { "egoMoveSpeed", 370 }
+	{     "syncTime", 247 }, {      "syncCue", 248 }
 };
 
 // Taken from Space Quest 1 VGA (Demo)
@@ -133,7 +133,7 @@
 	{     "moveDone", 100 }, {         "init", 103 }, {      "dispose", 104 },
 	{       "caller", 133 }, {          "cue", 135 }, {        "owner", 149 },
 	{        "flags", 150 }, {    "completed", 207 }, {    "motionCue", 210 },
-	{       "cycler", 212 }, {     "distance", 221 }, { "egoMoveSpeed", 357 }
+	{       "cycler", 212 }, {     "distance", 221 }
 };
 
 // A macro for loading one of the above tables in the function below

Modified: scummvm/trunk/engines/sci/engine/vm.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/vm.cpp	2009-08-30 10:47:22 UTC (rev 43823)
+++ scummvm/trunk/engines/sci/engine/vm.cpp	2009-08-30 14:53:58 UTC (rev 43824)
@@ -1160,13 +1160,15 @@
 		case 0x39: // lofsa
 			s->r_acc.segment = scriptState.xs->addr.pc.segment;
 
-			if (s->resourceManager->sciVersion() >= SCI_VERSION_1_1) {
+			switch (s->detectLofsType()) {
+			case SCI_VERSION_1_1:
 				s->r_acc.offset = opparams[0] + local_script->script_size;
-			} else {
-				if (((SciEngine*)g_engine)->getKernel()->hasLofsAbsolute())
-					s->r_acc.offset = opparams[0];
-				else
-					s->r_acc.offset = scriptState.xs->addr.pc.offset + opparams[0];
+				break;
+			case SCI_VERSION_1_MIDDLE:
+				s->r_acc.offset = opparams[0];
+				break;
+			default:
+				s->r_acc.offset = scriptState.xs->addr.pc.offset + opparams[0];
 			}
 
 #ifndef DISABLE_VALIDATIONS
@@ -1180,13 +1182,15 @@
 		case 0x3a: // lofss
 			r_temp.segment = scriptState.xs->addr.pc.segment;
 
-			if (s->resourceManager->sciVersion() >= SCI_VERSION_1_1) {
+			switch (s->detectLofsType()) {
+			case SCI_VERSION_1_1:
 				r_temp.offset = opparams[0] + local_script->script_size;
-			} else {
-				if (((SciEngine*)g_engine)->getKernel()->hasLofsAbsolute())
-					r_temp.offset = opparams[0];
-				else
-					r_temp.offset = scriptState.xs->addr.pc.offset + opparams[0];
+				break;
+			case SCI_VERSION_1_MIDDLE:
+				r_temp.offset = opparams[0];
+				break;
+			default:
+				r_temp.offset = scriptState.xs->addr.pc.offset + opparams[0];
 			}
 
 #ifndef DISABLE_VALIDATIONS

Modified: scummvm/trunk/engines/sci/engine/vm.h
===================================================================
--- scummvm/trunk/engines/sci/engine/vm.h	2009-08-30 10:47:22 UTC (rev 43823)
+++ scummvm/trunk/engines/sci/engine/vm.h	2009-08-30 14:53:58 UTC (rev 43824)
@@ -190,7 +190,6 @@
 	Selector flags;
 
 	Selector motionCue;	/**< Used to determine if a game is using old gfx functions or not */
-	Selector egoMoveSpeed;	/**< Used to determine if a game is using absolute lofs parameters */
 
 	Selector points; /**< Used by AvoidPath() */
 

Modified: scummvm/trunk/engines/sci/sci.cpp
===================================================================
--- scummvm/trunk/engines/sci/sci.cpp	2009-08-30 10:47:22 UTC (rev 43823)
+++ scummvm/trunk/engines/sci/sci.cpp	2009-08-30 14:53:58 UTC (rev 43824)
@@ -136,7 +136,6 @@
 
 	_kernel = new Kernel(_resourceManager);
 	_vocabulary = new Vocabulary(_resourceManager);
-	script_adjust_opcode_formats(_resourceManager->sciVersion());
 
 	_gamestate = new EngineState(_resourceManager, flags);
 
@@ -149,6 +148,8 @@
 		return Common::kUnknownError;
 	}
 
+	script_adjust_opcode_formats(_gamestate);
+
 	// Set the savegame dir (actually, we set it to a fake value,
 	// since we cannot let the game control where saves are stored)
 	script_set_gamestate_save_dir(_gamestate, "/");


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