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

thebluegr at users.sourceforge.net thebluegr at users.sourceforge.net
Wed Oct 21 10:28:40 CEST 2009


Revision: 45297
          http://scummvm.svn.sourceforge.net/scummvm/?rev=45297&view=rev
Author:   thebluegr
Date:     2009-10-21 08:28:39 +0000 (Wed, 21 Oct 2009)

Log Message:
-----------
Fixed the bug where ego would not walk properly after he's swapped in LSL5 (from Larry to Patti and vice versa)

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

Modified: scummvm/trunk/engines/sci/engine/vm.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/vm.cpp	2009-10-21 01:23:05 UTC (rev 45296)
+++ scummvm/trunk/engines/sci/engine/vm.cpp	2009-10-21 08:28:39 UTC (rev 45297)
@@ -142,9 +142,39 @@
 		return default_value;
 }
 
-static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, int index, int line, reg_t value) {
-	if (!validate_variable(r, stack_base, type, max, index, line))
+static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, int index, int line, reg_t value, SegManager *segMan, Kernel *kernel) {
+	if (!validate_variable(r, stack_base, type, max, index, line)) {
+
+		// This code is needed to work around a probable script bug, or a limitation of the
+		// original SCI engine, which can be observed in LSL5.
+		// In some games, ego walks via the "Grooper" object, in particular its "stopGroop" child.
+		// In LSL5, during the game, ego is swapped from Larry to Patti. When this happens in the
+		// original interpreter, the new actor is loaded in the same memory location as the old
+		// one, therefore the client variable in the stopGroop object points to the new actor.
+		// This is probably why the reference of the stopGroop object is never updated (which
+		// is why I mentioned that this is either a script bug or some kind of limitation).
+		// In our implementation, each new object is loaded in a different memory location, and
+		// we can't overwrite the old one. This means that in our implementation, whenever ego is
+		// changed, we need to update the "client" variable of the stopGroop object, which points
+		// to ego, to the new ego object. If this is not done, ego's movement will not be updated
+		// properly, so the result is unpredictable (for example in LSL5, Patti spins around instead
+		// of walking)
+		if (index == 0 && type == VAR_GLOBAL) {	// global 0 is ego
+			reg_t stopGroopPos = segMan->findObjectByName("stopGroop");
+			if (!stopGroopPos.isNull()) {	// does the game have a stopGroop object?
+				// Notify the stopGroop object that Ego changed
+				Object *stopGroopObj = segMan->getObject(stopGroopPos);
+				// Find the "client" member variable, and update it
+				ObjVarRef varp;
+				if (lookup_selector(segMan, stopGroopPos, kernel->_selectorCache.client, &varp, NULL) == kSelectorVariable) {
+					reg_t *clientVar = varp.getPointer(segMan);
+					*clientVar = value;
+				}
+			}
+		}
+
 		r[index] = value;
+	}
 }
 
 #else
@@ -155,13 +185,13 @@
 #  define signed_validate_arithmetic(r) ((int) ((r).offset) & 0x8000 ? (signed) ((r).offset) - 65536 : ((r).offset))
 #  define validate_variable(r, sb, t, m, i, l)
 #  define validate_read_var(r, sb, t, m, i, l) ((r)[i])
-#  define validate_write_var(r, sb, t, m, i, l, v) ((r)[i] = (v))
+#  define validate_write_var(r, sb, t, m, i, l, v, sm, k) ((r)[i] = (v))
 #  define validate_property(o, p) ((o)->_variables[p])
 
 #endif
 
 #define READ_VAR(type, index, def) validate_read_var(scriptState.variables[type], s->stack_base, type, scriptState.variables_max[type], index, __LINE__, def)
-#define WRITE_VAR(type, index, value) validate_write_var(scriptState.variables[type], s->stack_base, type, scriptState.variables_max[type], index, __LINE__, value)
+#define WRITE_VAR(type, index, value) validate_write_var(scriptState.variables[type], s->stack_base, type, scriptState.variables_max[type], index, __LINE__, value, s->_segMan, s->_kernel)
 #define WRITE_VAR16(type, index, value) WRITE_VAR(type, index, make_reg(0, value));
 
 #define ACC_ARITHMETIC_L(op) make_reg(0, (op validate_arithmetic(s->r_acc)))


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