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

waltervn at users.sourceforge.net waltervn at users.sourceforge.net
Sun Aug 30 03:37:52 CEST 2009


Revision: 43812
          http://scummvm.svn.sourceforge.net/scummvm/?rev=43812&view=rev
Author:   waltervn
Date:     2009-08-30 01:37:52 +0000 (Sun, 30 Aug 2009)

Log Message:
-----------
SCI: Add SetCursor detection. Cleanup.

Modified Paths:
--------------
    scummvm/trunk/engines/sci/engine/kgraphics.cpp
    scummvm/trunk/engines/sci/engine/ksound.cpp
    scummvm/trunk/engines/sci/engine/script.cpp
    scummvm/trunk/engines/sci/engine/state.cpp
    scummvm/trunk/engines/sci/engine/state.h
    scummvm/trunk/engines/sci/engine/vm.h

Modified: scummvm/trunk/engines/sci/engine/kgraphics.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/kgraphics.cpp	2009-08-30 01:37:27 UTC (rev 43811)
+++ scummvm/trunk/engines/sci/engine/kgraphics.cpp	2009-08-30 01:37:52 UTC (rev 43812)
@@ -301,82 +301,62 @@
 	return retval;
 }
 
-reg_t kSetCursor(EngineState *s, int funct_nr, int argc, reg_t *argv) {
-	SciVersion version = s->resourceManager->sciVersion();
+static reg_t kSetCursorSci0(EngineState *s, int funct_nr, int argc, reg_t *argv) {
+	uint16 cursor = argv[0].toSint16();
 
+	if ((argc >= 2) && (argv[1].toSint16() == 0))
+		cursor = GFXOP_NO_POINTER;
+
+	GFX_ASSERT(gfxop_set_pointer_cursor(s->gfx_state, cursor));
+
+	// Set pointer position, if requested
+	if (argc >= 4) {
+		Common::Point newPos = Common::Point(argv[2].toSint16() + s->port->_bounds.x, argv[3].toSint16() + s->port->_bounds.y);
+		GFX_ASSERT(gfxop_set_pointer_position(s->gfx_state, newPos));
+	}
+
+	return s->r_acc;
+}
+
+static reg_t kSetCursorSci11(EngineState *s, int funct_nr, int argc, reg_t *argv) {
+	Common::Point *hotspot = NULL;
+
 	switch (argc) {
-	case 1 :
-		if (version < SCI_VERSION_1_LATE) {
-			GFX_ASSERT(gfxop_set_pointer_cursor(s->gfx_state, argv[0].toSint16()));
-		} else if (version < SCI_VERSION_1_1) {
-			if (argv[0].toSint16() <= 1) {
-				// Newer (SCI1.1) semantics: show/hide cursor
-				CursorMan.showMouse(argv[0].toSint16() != 0);
-			} else {
-				// Pre-SCI1.1: set cursor according to the first parameter
-				GFX_ASSERT(gfxop_set_pointer_cursor(s->gfx_state, argv[0].toSint16()));
-			}
-		} else  {
-			// SCI1.1: Show/hide cursor
-			CursorMan.showMouse(argv[0].toSint16() != 0);
-		}
+	case 1:
+		CursorMan.showMouse(argv[0].toSint16() != 0);
 		break;
-	case 2 :
-		if (version < SCI_VERSION_1_LATE) {
-			GFX_ASSERT(gfxop_set_pointer_cursor(s->gfx_state, 
-						argv[1].toSint16() == 0 ? GFXOP_NO_POINTER : argv[0].toSint16()));
-		} else if (version < SCI_VERSION_1_1) {
-			// Pre-SCI1.1: set cursor according to the first parameter, and toggle its
-			// visibility based on the second parameter
-			// Some late SCI1 games actually use the SCI1.1 version of this call (EcoQuest 1
-			// and KQ5 CD, but I haven't seen this case happen), but we can determine the
-			// semantics from the second parameter passed.
-			// Rationale: with the older behavior, the second parameter can either be 0 
-			// (hide cursor) or 1/-1 (show cursor). This could be problematic if the engine
-			// tries to place the cursor at (x, 0) or (x, 1), but no SCI1 game does that, as
-			// this would open the menu on top. LSL5 is an exception, as the game can open
-			// the menu when the player presses a button during the intro, but the cursor is
-			// not placed on (x, 0) or (x, 1)
-			if (argv[1].toSint16() <= 1) {
-				GFX_ASSERT(gfxop_set_pointer_cursor(s->gfx_state, 
-							argv[1].toSint16() == 0 ? GFXOP_NO_POINTER : argv[0].toSint16()));
-			} else {	// newer (SCI1.1) semantics: set pointer position
-				GFX_ASSERT(gfxop_set_pointer_position(s->gfx_state, 
-							Common::Point(argv[0].toUint16(), argv[1].toUint16())));
-			}
-		} else {
-			// SCI1.1 and newer: set pointer position
-			GFX_ASSERT(gfxop_set_pointer_position(s->gfx_state, 
-						Common::Point(argv[0].toUint16(), argv[1].toUint16())));
-		}
+	case 2:
+		GFX_ASSERT(gfxop_set_pointer_position(s->gfx_state, 
+				   Common::Point(argv[0].toUint16(), argv[1].toUint16())));
 		break;
-	case 4 :
-		GFX_ASSERT(gfxop_set_pointer_cursor(s->gfx_state, 
-					argv[0].toUint16() == 0 ? GFXOP_NO_POINTER : argv[0].toSint16()));
-
-		// Set pointer position, if requested
-		if (argc > 2) {
-			Common::Point newPos = Common::Point(argv[2].toSint16() + s->port->_bounds.x, argv[3].toSint16() + s->port->_bounds.y);
-			GFX_ASSERT(gfxop_set_pointer_position(s->gfx_state, newPos));
-		}
+	case 5:
+	case 9:
+		hotspot = new Common::Point(argv[3].toSint16(), argv[4].toSint16());
+		// Fallthrough
+	case 3:
+		GFX_ASSERT(gfxop_set_pointer_view(s->gfx_state, argv[0].toUint16(), argv[1].toUint16(), argv[2].toUint16(), hotspot));
+		if (hotspot)
+			delete hotspot;
 		break;
-	case 3 :
-	case 5 :
-	case 9 :
-		if (argc > 3) {
-			Common::Point hotspot = Common::Point(argv[3].toSint16(), argv[4].toSint16());
-			GFX_ASSERT(gfxop_set_pointer_view(s->gfx_state, argv[0].toUint16(), argv[1].toUint16(), argv[2].toUint16(), &hotspot));
-		} else {
-			GFX_ASSERT(gfxop_set_pointer_view(s->gfx_state, argv[0].toUint16(), argv[1].toUint16(), argv[2].toUint16(), NULL));
-		}
-		break;
 	default :
-		error("kSetCursor: Unhandled case: %d arguments given", argc);
+		warning("kSetCursor: Unhandled case: %d arguments given", argc);
 		break;
 	}
 	return s->r_acc;
 }
 
+reg_t kSetCursor(EngineState *s, int funct_nr, int argc, reg_t *argv) {
+	switch (s->detectSetCursorType()) {
+	case SCI_VERSION_0_EARLY:
+		return kSetCursorSci0(s, funct_nr, argc, argv);
+	case SCI_VERSION_1_1:
+		return kSetCursorSci11(s, funct_nr, argc, argv);
+	default:
+		warning("Unknown SetCursor type");
+		return NULL_REG;
+	}
+}
+
 reg_t kMoveCursor(EngineState *s, int funct_nr, int argc, reg_t *argv) {
 	Common::Point newPos;
 

Modified: scummvm/trunk/engines/sci/engine/ksound.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/ksound.cpp	2009-08-30 01:37:27 UTC (rev 43811)
+++ scummvm/trunk/engines/sci/engine/ksound.cpp	2009-08-30 01:37:52 UTC (rev 43812)
@@ -206,7 +206,7 @@
 }
 
 
-reg_t kDoSoundSci0(EngineState *s, int funct_nr, int argc, reg_t *argv) {
+static reg_t kDoSoundSci0(EngineState *s, int funct_nr, int argc, reg_t *argv) {
 	SegManager *segManager = s->segmentManager;
 	reg_t obj = (argc > 1) ? argv[1] : NULL_REG;
 	uint16 command = argv[0].toUint16();
@@ -386,7 +386,7 @@
 }
 
 
-reg_t kDoSoundSci1Early(EngineState *s, int funct_nr, int argc, reg_t *argv) {
+static reg_t kDoSoundSci1Early(EngineState *s, int funct_nr, int argc, reg_t *argv) {
 	SegManager *segManager = s->segmentManager;
 	uint16 command = argv[0].toUint16();
 	reg_t obj = (argc > 1) ? argv[1] : NULL_REG;
@@ -677,7 +677,7 @@
 	return s->r_acc;
 }
 
-reg_t kDoSoundSci1Late(EngineState *s, int funct_nr, int argc, reg_t *argv) {
+static reg_t kDoSoundSci1Late(EngineState *s, int funct_nr, int argc, reg_t *argv) {
 	SegManager *segManager = s->segmentManager;
 	uint16 command = argv[0].toUint16();
 	reg_t obj = (argc > 1) ? argv[1] : NULL_REG;
@@ -994,11 +994,11 @@
  */
 reg_t kDoSound(EngineState *s, int funct_nr, int argc, reg_t *argv) {
 	switch(s->detectDoSoundType()) {
-	case EngineState::kDoSoundTypeSci0:
+	case SCI_VERSION_0_EARLY:
 		return kDoSoundSci0(s, funct_nr, argc, argv);
-	case EngineState::kDoSoundTypeSci1Early:
+	case SCI_VERSION_1_EARLY:
 		return kDoSoundSci1Early(s, funct_nr, argc, argv);
-	case EngineState::kDoSoundTypeSci1Late:
+	case SCI_VERSION_1_LATE:
 		return kDoSoundSci1Late(s, funct_nr, argc, argv);
 	default:
 		warning("Unknown DoSound type");

Modified: scummvm/trunk/engines/sci/engine/script.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/script.cpp	2009-08-30 01:37:27 UTC (rev 43811)
+++ scummvm/trunk/engines/sci/engine/script.cpp	2009-08-30 01:37:52 UTC (rev 43812)
@@ -241,6 +241,7 @@
 	FIND_SELECTOR(parseLang);
 	FIND_SELECTOR(motionCue);
 	FIND_SELECTOR(egoMoveSpeed);
+	FIND_SELECTOR(setCursor);
 }
 
 void Kernel::dumpScriptObject(char *data, int seeker, int objsize) {

Modified: scummvm/trunk/engines/sci/engine/state.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/state.cpp	2009-08-30 01:37:27 UTC (rev 43811)
+++ scummvm/trunk/engines/sci/engine/state.cpp	2009-08-30 01:37:52 UTC (rev 43812)
@@ -119,7 +119,8 @@
 
 	speedThrottler = new SpeedThrottler(res->sciVersion());
 
-	_doSoundType = kDoSoundTypeUnknown;
+	_setCursorType = SCI_VERSION_AUTODETECT;
+	_doSoundType = SCI_VERSION_AUTODETECT;
 }
 
 EngineState::~EngineState() {
@@ -246,78 +247,97 @@
 	return retval;
 }
 
-EngineState::DoSoundType EngineState::detectDoSoundType() {
-	if (_doSoundType == kDoSoundTypeUnknown) {
-		reg_t soundClass;
-		const uint checkBytes = 6; // Number of bytes to check
+int EngineState::methodChecksum(reg_t objAddress, Selector sel, int offset, uint size) const {
+	reg_t fptr;
 
-		if (!parse_reg_t(this, "?Sound", &soundClass)) {
-			reg_t fptr;
+	Object *obj = obj_get(segmentManager, objAddress);
+	SelectorType selType = lookup_selector(this->segmentManager, objAddress, sel, NULL, &fptr);
 
-			Object *obj = obj_get(segmentManager, soundClass);
-			SelectorType sel = lookup_selector(this->segmentManager, soundClass, ((SciEngine*)g_engine)->getKernel()->_selectorMap.play, NULL, &fptr);
+	if (!obj || (selType != kSelectorMethod))
+		return -1;
 
-			if (obj && (sel == kSelectorMethod)) {
-				Script *script = segmentManager->getScript(fptr.segment);
+	Script *script = segmentManager->getScript(fptr.segment);
 
-				if (fptr.offset > checkBytes) {
-					// Go to the last portion of Sound::init, should be right before the play function
-					fptr.offset -= checkBytes;
-					byte *buf = script->buf + fptr.offset;
+	if (!script->buf || (fptr.offset + offset < 0))
+		return -1;
 
-					// Check the call to DoSound's INIT_HANDLE function.
-					// It's either subfunction 0, 5 or 6, depending on the version of DoSound.
-					uint sum = 0;
-					for (uint i = 0; i < checkBytes; i++)
-						sum += buf[i];
+	fptr.offset += offset;
 
-					switch(sum) {
-					case 0x1B2: // SCI0
-					case 0x1AE: // SCI01
-						_doSoundType = kDoSoundTypeSci0;
-						break;
-					case 0x13D:
-						_doSoundType = kDoSoundTypeSci1Early;
-						break;
-					case 0x13E:
+	if (fptr.offset + size > script->buf_size)
+		return -1;
+
+	byte *buf = script->buf + fptr.offset;
+
+	uint sum = 0;
+	for (uint i = 0; i < size; i++)
+		sum += buf[i];
+
+	return sum;
+}
+
+SciVersion EngineState::detectDoSoundType() {
+	if (_doSoundType == SCI_VERSION_AUTODETECT) {
+		reg_t soundClass;
+
+		if (!parse_reg_t(this, "?Sound", &soundClass)) {
+			int sum = methodChecksum(soundClass, ((SciEngine *)g_engine)->getKernel()->_selectorMap.play, -6, 6);
+
+			switch(sum) {
+			case 0x1B2: // SCI0
+			case 0x1AE: // SCI01
+				_doSoundType = SCI_VERSION_0_EARLY;
+				break;
+			case 0x13D:
+				_doSoundType = SCI_VERSION_1_EARLY;
+				break;
+			case 0x13E:
 #ifdef ENABLE_SCI32
-					case 0x14B:
+			case 0x14B:
 #endif
-						_doSoundType = kDoSoundTypeSci1Late;
-					}
-				}
+				_doSoundType = SCI_VERSION_1_LATE;
 			}
 		}
 
-		if (_doSoundType == kDoSoundTypeUnknown) {
+		if (_doSoundType == SCI_VERSION_AUTODETECT) {
 			warning("DoSound detection failed, taking an educated guess");
 
 			if (resourceManager->sciVersion() >= SCI_VERSION_1_MIDDLE)
-				_doSoundType = kDoSoundTypeSci1Late;
+				_doSoundType = SCI_VERSION_1_LATE;
 			else if (resourceManager->sciVersion() > SCI_VERSION_01)
-				_doSoundType = kDoSoundTypeSci1Early;
+				_doSoundType = SCI_VERSION_1_EARLY;
 			else
-				_doSoundType = kDoSoundTypeSci0;
+				_doSoundType = SCI_VERSION_0_EARLY;
 		}
 
-		debugCN(1, kDebugLevelSound, "Detected DoSound type: ");
+		debugC(1, kDebugLevelSound, "Detected DoSound type: %s", ((SciEngine *)g_engine)->getSciVersionDesc(_doSoundType).c_str());
+	}
 
-		switch(_doSoundType) {
-		case kDoSoundTypeSci0:
-			debugC(1, kDebugLevelSound, "SCI0");
-			break;
-		case kDoSoundTypeSci1Early:
-			debugC(1, kDebugLevelSound, "SCI1 Early");
-			break;
-		case kDoSoundTypeSci1Late:
-			debugC(1, kDebugLevelSound, "SCI1 Late");
-			break;
-		default:
-			break;
+	return _doSoundType;
+}
+
+SciVersion EngineState::detectSetCursorType() {
+	if (_setCursorType == SCI_VERSION_AUTODETECT) {
+		int sum = methodChecksum(game_obj, ((SciEngine *)g_engine)->getKernel()->_selectorMap.setCursor, 0, 21);
+
+		if ((sum == 0x4D5) || (sum == 0x552)) {
+			// Standard setCursor
+			_setCursorType = SCI_VERSION_0_EARLY;
+		} else if (sum != -1) {
+			// Assume that others use fancy cursors
+			_setCursorType = SCI_VERSION_1_1;
+		} else {
+			warning("SetCursor detection failed, taking an educated guess");
+
+			if (resourceManager->sciVersion() >= SCI_VERSION_1_1)
+				_setCursorType = SCI_VERSION_1_1;
+			else
+				_setCursorType = SCI_VERSION_0_EARLY;
 		}
+
+		debugC(0, kDebugLevelGraphics, "Detected SetCursor type: %s", ((SciEngine *)g_engine)->getSciVersionDesc(_setCursorType).c_str());
 	}
 
-	return _doSoundType;
+	return _setCursorType;
 }
 
 } // End of namespace Sci

Modified: scummvm/trunk/engines/sci/engine/state.h
===================================================================
--- scummvm/trunk/engines/sci/engine/state.h	2009-08-30 01:37:27 UTC (rev 43811)
+++ scummvm/trunk/engines/sci/engine/state.h	2009-08-30 01:37:52 UTC (rev 43812)
@@ -164,13 +164,6 @@
 	EngineState(ResourceManager *res, uint32 flags);
 	virtual ~EngineState();
 
-	enum DoSoundType {
-		kDoSoundTypeUnknown,
-		kDoSoundTypeSci0,
-		kDoSoundTypeSci1Early,
-		kDoSoundTypeSci1Late
-	};
-
 	virtual void saveLoadWithSerializer(Common::Serializer &ser);
 
 	kLanguage getLanguage();
@@ -283,8 +276,14 @@
 	 * Autodetects the DoSound type
 	 * @return DoSound type
 	 */
-	DoSoundType detectDoSoundType();
+	SciVersion detectDoSoundType();
 
+	/**
+	 * Autodetects the SetCursor type
+	 * @return SetCursor type
+	 */
+	SciVersion detectSetCursorType();
+
 	/* Debugger data: */
 	Breakpoint *bp_list;   /**< List of breakpoints */
 	int have_bp;  /**< Bit mask specifying which types of breakpoints are used in bp_list */
@@ -315,8 +314,9 @@
 
 	Common::String getLanguageString(const char *str, kLanguage lang) const;
 private:
-	DoSoundType _doSoundType;
+	SciVersion _doSoundType, _setCursorType;
 	kLanguage charToLanguage(const char c) const;
+	int methodChecksum(reg_t objAddress, Selector sel, int offset, uint size) const;
 };
 
 /**

Modified: scummvm/trunk/engines/sci/engine/vm.h
===================================================================
--- scummvm/trunk/engines/sci/engine/vm.h	2009-08-30 01:37:27 UTC (rev 43811)
+++ scummvm/trunk/engines/sci/engine/vm.h	2009-08-30 01:37:52 UTC (rev 43812)
@@ -200,6 +200,8 @@
 	Selector printLang; /**< Used for i18n */
 	Selector subtitleLang;
 	Selector parseLang;
+
+	Selector setCursor; /** For autodetection */
 };
 
 // A reference to an object's variable.


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