[Scummvm-git-logs] scummvm master -> 0906dc324032e0fc8b0cc8562fd3888ed62049d7

djsrv dservilla at gmail.com
Fri Jun 26 01:07:57 UTC 2020


This automated email contains information about 5 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
4dab1f59dd DIRECTOR: LINGO: Fix Object::getMethod
e709661c40 DIRECTOR: LINGO: Remove redundant var methods
16ba15d5b6 DIRECTOR: LINGO Add bytecode instruction 0x02
3157c9775d DIRECTOR: LINGO: Improve Lscr name resolution
0906dc3240 DIRECTOR: LINGO: Improve factory method calls


Commit: 4dab1f59ddf3ab90f71eba674f848e7916e3f960
    https://github.com/scummvm/scummvm/commit/4dab1f59ddf3ab90f71eba674f848e7916e3f960
Author: djsrv (dservilla at gmail.com)
Date: 2020-06-25T20:49:47-04:00

Commit Message:
DIRECTOR: LINGO: Fix Object::getMethod

Changed paths:
    engines/director/lingo/lingo-object.cpp


diff --git a/engines/director/lingo/lingo-object.cpp b/engines/director/lingo/lingo-object.cpp
index 8054613de0..a01d62ed7c 100644
--- a/engines/director/lingo/lingo-object.cpp
+++ b/engines/director/lingo/lingo-object.cpp
@@ -111,7 +111,7 @@ Symbol Object::getMethod(const Common::String &methodName) {
 	}
 
 	// instance method (factory, script object, and Xtra)
-	if ((type | (kFactoryObj & kScriptObj & kXtraObj)) && ctx->_functionHandlers.contains(methodName)) {
+	if ((type & (kFactoryObj | kScriptObj | kXtraObj)) && ctx->_functionHandlers.contains(methodName)) {
 		return ctx->_functionHandlers[methodName];
 	}
 
@@ -122,13 +122,17 @@ Symbol Object::getMethod(const Common::String &methodName) {
 			return ctx->_functionHandlers[shortName];
 		}
 		// predefined method (factory and XObject)
-		if (g_lingo->_methods.contains(shortName) && (type & g_lingo->_methods[shortName].type)) {
-			return g_lingo->_methods[shortName];
+		if (g_lingo->_methods.contains(shortName) && (type & g_lingo->_methods[shortName].targetType)) {
+			Symbol sym = g_lingo->_methods[shortName];
+			sym.ctx = ctx;
+			return sym;
 		}
 	} else if (type & (kScriptObj | kXtraObj)) {
 		// predefined method (script object and Xtra)
-		if (g_lingo->_methods.contains(methodName) && (type & g_lingo->_methods[methodName].type)) {
-			return g_lingo->_methods[methodName];
+		if (g_lingo->_methods.contains(methodName) && (type & g_lingo->_methods[methodName].targetType)) {
+			Symbol sym = g_lingo->_methods[methodName];
+			sym.ctx = ctx;
+			return sym;
 		}
 
 		// ancestor method


Commit: e709661c40aa0bfcc544117d0ca80a42102b0683
    https://github.com/scummvm/scummvm/commit/e709661c40aa0bfcc544117d0ca80a42102b0683
Author: djsrv (dservilla at gmail.com)
Date: 2020-06-25T20:53:33-04:00

Commit Message:
DIRECTOR: LINGO: Remove redundant var methods

Changed paths:
    engines/director/lingo/lingo-codegen.cpp
    engines/director/lingo/lingo-object.cpp
    engines/director/lingo/lingo.cpp
    engines/director/lingo/lingo.h


diff --git a/engines/director/lingo/lingo-codegen.cpp b/engines/director/lingo/lingo-codegen.cpp
index eaa3ac2269..cc938267df 100644
--- a/engines/director/lingo/lingo-codegen.cpp
+++ b/engines/director/lingo/lingo-codegen.cpp
@@ -275,7 +275,7 @@ void Lingo::varCreate(const Common::String &name, bool global, DatumHash *localv
 		if (global)
 			warning("varCreate: variable %s is local, not global", name.c_str());
 		return;
-	} else if (_currentMe.type == OBJECT && _currentMe.u.obj->hasVar(name)) {
+	} else if (_currentMe.type == OBJECT && _currentMe.u.obj->hasProp(name)) {
 		if (global)
 			warning("varCreate: variable %s is instance or property, not global", name.c_str());
 		return;
diff --git a/engines/director/lingo/lingo-object.cpp b/engines/director/lingo/lingo-object.cpp
index a01d62ed7c..1806695834 100644
--- a/engines/director/lingo/lingo-object.cpp
+++ b/engines/director/lingo/lingo-object.cpp
@@ -146,51 +146,16 @@ Symbol Object::getMethod(const Common::String &methodName) {
 	return Symbol();
 }
 
-// Variable access (e.g. `put variable`, within a method)
-
-bool Object::hasVar(const Common::String &varName) {
-	if (disposed) {
-		error("Variable '%s' accessed on disposed object <%s>", varName.c_str(), Datum(this).asString(true).c_str());
-	}
-	if (properties.contains(varName)) {
-		return true;
-	}
-	if (type & (kScriptObj | kXtraObj)) {
-		if (properties.contains("ancestor") && properties["ancestor"].type == OBJECT
-				&& (properties["ancestor"].u.obj->type & (kScriptObj | kXtraObj))) {
-			return properties["ancestor"].u.obj->hasVar(varName);
-		}
-	}
-	return false;
-}
-
-Datum &Object::getVar(const Common::String &varName) {
-	if (disposed) {
-		error("Variable '%s' accessed on disposed object <%s>", varName.c_str(), Datum(this).asString(true).c_str());
-	}
-	if (properties.contains(varName)) {
-		return properties[varName];
-	}
-	if (type & (kScriptObj | kXtraObj)) {
-		if (properties.contains("ancestor") && properties["ancestor"].type == OBJECT
-				&& (properties["ancestor"].u.obj->type & (kScriptObj | kXtraObj))) {
-			debugC(3, kDebugLingoExec, "Getting var '%s' from ancestor: <%s>", varName.c_str(), properties["ancestor"].asString(true).c_str());
-			return properties["ancestor"].u.obj->getVar(varName);
-		}
-	}
-	return properties[varName]; // return new variable
-}
-
-// Property access (e.g. `put the property of object`)
+// Property access
 
 bool Object::hasProp(const Common::String &propName) {
 	if (disposed) {
 		error("Property '%s' accessed on disposed object <%s>", propName.c_str(), Datum(this).asString(true).c_str());
 	}
+	if (properties.contains(propName)) {
+		return true;
+	}
 	if (type & (kScriptObj | kXtraObj)) {
-		if (properties.contains(propName)) {
-			return true;
-		}
 		if (properties.contains("ancestor") && properties["ancestor"].type == OBJECT
 				&& (properties["ancestor"].u.obj->type & (kScriptObj | kXtraObj))) {
 			return properties["ancestor"].u.obj->hasProp(propName);
@@ -203,10 +168,10 @@ Datum &Object::getProp(const Common::String &propName) {
 	if (disposed) {
 		error("Property '%s' accessed on disposed object <%s>", propName.c_str(), Datum(this).asString(true).c_str());
 	}
+	if (properties.contains(propName)) {
+		return properties[propName];
+	}
 	if (type & (kScriptObj | kXtraObj)) {
-		if (properties.contains(propName)) {
-			return properties[propName];
-		}
 		if (properties.contains("ancestor") && properties["ancestor"].type == OBJECT
 				&& (properties["ancestor"].u.obj->type & (kScriptObj | kXtraObj))) {
 			debugC(3, kDebugLingoExec, "Getting prop '%s' from ancestor: <%s>", propName.c_str(), properties["ancestor"].asString(true).c_str());
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index 3737ecbf19..7e41fc81df 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -1155,8 +1155,8 @@ void Lingo::varAssign(Datum &var, Datum &value, bool global, DatumHash *localvar
 			d = &(*localvars)[name];
 			if (global)
 				warning("varAssign: variable %s is local, not global", name.c_str());
-		} else if (_currentMe.type == OBJECT && _currentMe.u.obj->hasVar(name)) {
-			d = &_currentMe.u.obj->getVar(name);
+		} else if (_currentMe.type == OBJECT && _currentMe.u.obj->hasProp(name)) {
+			d = &_currentMe.u.obj->getProp(name);
 			if (global)
 				warning("varAssign: variable %s is instance or property, not global", name.c_str());
 		} else if (_globalvars.contains(name)) {
@@ -1220,8 +1220,8 @@ Datum Lingo::varFetch(Datum &var, bool global, DatumHash *localvars) {
 			d = &(*localvars)[name];
 			if (global)
 				warning("varFetch: variable %s is local, not global", name.c_str());
-		} else if (_currentMe.type == OBJECT && _currentMe.u.obj->hasVar(name)) {
-			d = &_currentMe.u.obj->getVar(name);
+		} else if (_currentMe.type == OBJECT && _currentMe.u.obj->hasProp(name)) {
+			d = &_currentMe.u.obj->getProp(name);
 			if (global)
 				warning("varFetch: variable %s is instance or property, not global", name.c_str());
 		} else if (_globalvars.contains(name)) {
diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index a2d0781abd..fc69d149bb 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -316,8 +316,6 @@ struct Object {
 
 	virtual Object *clone();
 	Symbol getMethod(const Common::String &methodName);
-	bool hasVar(const Common::String &varName);
-	Datum &getVar(const Common::String &varName);
 	bool hasProp(const Common::String &propName);
 	Datum &getProp(const Common::String &propName);
 };


Commit: 16ba15d5b6876608be08b3d12f451c0d922e9835
    https://github.com/scummvm/scummvm/commit/16ba15d5b6876608be08b3d12f451c0d922e9835
Author: djsrv (dservilla at gmail.com)
Date: 2020-06-25T20:54:28-04:00

Commit Message:
DIRECTOR: LINGO Add bytecode instruction 0x02

This just seems to be procret but for methods.

Changed paths:
    engines/director/lingo/lingo-bytecode.cpp


diff --git a/engines/director/lingo/lingo-bytecode.cpp b/engines/director/lingo/lingo-bytecode.cpp
index 95e73da06a..568cdc2b45 100644
--- a/engines/director/lingo/lingo-bytecode.cpp
+++ b/engines/director/lingo/lingo-bytecode.cpp
@@ -38,6 +38,7 @@ namespace Director {
 
 static LingoV4Bytecode lingoV4[] = {
 	{ 0x01, LC::c_procret,		"" },
+	{ 0x02, LC::c_procret,		"" },
 	{ 0x03, LC::cb_zeropush,	"" },
 	{ 0x04, LC::c_mul,			"" },
 	{ 0x05, LC::c_add,			"" },


Commit: 3157c9775d584833ef38e08ee2b931aba63a5179
    https://github.com/scummvm/scummvm/commit/3157c9775d584833ef38e08ee2b931aba63a5179
Author: djsrv (dservilla at gmail.com)
Date: 2020-06-25T21:01:51-04:00

Commit Message:
DIRECTOR: LINGO: Improve Lscr name resolution

Changed paths:
    engines/director/lingo/lingo-bytecode.cpp


diff --git a/engines/director/lingo/lingo-bytecode.cpp b/engines/director/lingo/lingo-bytecode.cpp
index 568cdc2b45..7f80c812a7 100644
--- a/engines/director/lingo/lingo-bytecode.cpp
+++ b/engines/director/lingo/lingo-bytecode.cpp
@@ -892,8 +892,8 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, int archiveIn
 	debugC(5, kDebugLoading, "Lscr property list:");
 	stream.seek(propertiesOffset);
 	for (uint16 i = 0; i < propertiesCount; i++) {
-		uint16 index = stream.readUint16();
-		if (index < _archives[_assemblyArchive].names.size()) {
+		int16 index = stream.readSint16();
+		if (0 <= index && index < (int16)_archives[_assemblyArchive].names.size()) {
 			const char *name = _archives[_assemblyArchive].names[index].c_str();
 			debugC(5, kDebugLoading, "%d: %s", i, name);
 			if (scriptFlags & kScriptFlagFactoryDef) {
@@ -915,8 +915,8 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, int archiveIn
 	debugC(5, kDebugLoading, "Lscr globals list:");
 	stream.seek(globalsOffset);
 	for (uint16 i = 0; i < globalsCount; i++) {
-		uint16 index = stream.readUint16();
-		if (index < _archives[_assemblyArchive].names.size()) {
+		int16 index = stream.readSint16();
+		if (0 <= index && index < (int16)_archives[_assemblyArchive].names.size()) {
 			const char *name = _archives[_assemblyArchive].names[index].c_str();
 			debugC(5, kDebugLoading, "%d: %s", i, name);
 			if (!_globalvars.contains(name)) {
@@ -1092,7 +1092,7 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, int archiveIn
 			stream.hexdump(0x2a);
 		}
 
-		uint16 nameIndex = stream.readUint16();
+		int16 nameIndex = stream.readUint16();
 		stream.readUint16();
 		uint32 length = stream.readUint32();
 		uint32 startOffset = stream.readUint32();
@@ -1129,15 +1129,27 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, int archiveIn
 			debugC(5, kDebugLoading, "Function %d argument list:", i);
 			uint16 namePointer = argOffset - codeStoreOffset;
 			for (int j = 0; j < argCount; j++) {
-				uint16 index = (uint16)READ_BE_UINT16(&codeStore[namePointer]);
+				int16 index = READ_BE_INT16(&codeStore[namePointer]);
 				namePointer += 2;
 				Common::String name;
-				if (index < _archives[_assemblyArchive].names.size()) {
+				if (0 <= index && index < (int16)_archives[_assemblyArchive].names.size()) {
 					name = _archives[_assemblyArchive].names[index];
+					argMap[j] = index;
+				} else if (j == 0 && (scriptFlags & kScriptFlagFactoryDef)) {
+					name = "me";
+
+					// find or add "me" in the names list
+					for (index = 0; index < (int16)_archives[_assemblyArchive].names.size(); index++) {
+						if (_archives[_assemblyArchive].names[index].equalsIgnoreCase(name))
+							break;
+					}
+					if (index == (int16)_archives[_assemblyArchive].names.size())
+						_archives[_assemblyArchive].names.push_back(name);
+
 					argMap[j] = index;
 				} else {
 					name = Common::String::format("arg_%d", j);
-					warning("Argument has unknown name id %d, using name %s", j, name.c_str());
+					warning("Argument has unknown name id %d, using name %s", index, name.c_str());
 				}
 				debugC(5, kDebugLoading, "%d: %s", j, name.c_str());
 				argNames->push_back(name);
@@ -1155,10 +1167,10 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, int archiveIn
 			debugC(5, kDebugLoading, "Function %d variable list:", i);
 			uint16 namePointer = varOffset - codeStoreOffset;
 			for (int j = 0; j < varCount; j++) {
-				uint16 index = (uint16)READ_BE_UINT16(&codeStore[namePointer]);
+				int16 index = READ_BE_INT16(&codeStore[namePointer]);
 				namePointer += 2;
 				Common::String name;
-				if (index < _archives[_assemblyArchive].names.size()) {
+				if (0 <= index && index < (int16)_archives[_assemblyArchive].names.size()) {
 					name = _archives[_assemblyArchive].names[index];
 					varMap[j] = index;
 				} else {
@@ -1345,7 +1357,7 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, int archiveIn
 
 		// Attach to handlers
 		Symbol sym;
-		if (nameIndex < _archives[_assemblyArchive].names.size()) {
+		if (0 <= nameIndex && nameIndex < (int16)_archives[_assemblyArchive].names.size()) {
 			debugC(5, kDebugLoading, "Function %d binding: %s()", i, _archives[_assemblyArchive].names[nameIndex].c_str());
 			sym = g_lingo->define(_archives[_assemblyArchive].names[nameIndex], argCount, _currentAssembly, argNames, varNames);
 		} else {
@@ -1360,7 +1372,7 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, int archiveIn
 		}
 
 		if (!skipdump && ConfMan.getBool("dump_scripts")) {
-			if (nameIndex < _archives[_assemblyArchive].names.size())
+			if (0 <= nameIndex && nameIndex < (int16)_archives[_assemblyArchive].names.size())
 				out.writeString(Common::String::format("function %s, %d args\n", _archives[_assemblyArchive].names[nameIndex].c_str(), argCount));
 			else
 				out.writeString(Common::String::format("<noname>, %d args\n", argCount));


Commit: 0906dc324032e0fc8b0cc8562fd3888ed62049d7
    https://github.com/scummvm/scummvm/commit/0906dc324032e0fc8b0cc8562fd3888ed62049d7
Author: djsrv (dservilla at gmail.com)
Date: 2020-06-25T21:04:00-04:00

Commit Message:
DIRECTOR: LINGO: Improve factory method calls

Changed paths:
    engines/director/lingo/lingo-bytecode.cpp
    engines/director/lingo/lingo-code.cpp
    engines/director/lingo/lingo-gr.y


diff --git a/engines/director/lingo/lingo-bytecode.cpp b/engines/director/lingo/lingo-bytecode.cpp
index 7f80c812a7..9af4a8b702 100644
--- a/engines/director/lingo/lingo-bytecode.cpp
+++ b/engines/director/lingo/lingo-bytecode.cpp
@@ -311,68 +311,105 @@ void LC::cb_localcall() {
 
 void LC::cb_objectcall() {
 	g_lingo->readInt();
-	Datum object = g_lingo->pop();
+	Datum d = g_lingo->pop();
 	Datum nargs = g_lingo->pop();
-	if (object.type != SYMBOL) {
-		warning("cb_objectcall: first arg should be of type SYMBOL, not %s", object.type2str());
-	} else if ((nargs.type != ARGC) && (nargs.type != ARGCNORET)) {
-		warning("cb_objectcall: second arg should be of type ARGC or ARGCNORET, not %s", nargs.type2str());
-	} else {
-		// first, try looking up an object with that name
-		object.type = VAR;
-		Datum target = g_lingo->varFetch(object);
-
-		StackData args;
-		if (target.type == OBJECT) {
-			// last arg on the stack is the method name
-			nargs.u.i -= 1;
-		}
 
-		for (int i = 0; i < nargs.u.i; i++) {
-			Datum arg = g_lingo->pop();
-			// for some reason, strings that are sent to here are actually variable names???
-			// other constants (e.g. ints) are fine.
-			if (arg.type == STRING) {
-				Datum varTest(arg);
-				varTest.type = VAR;
-				varTest = g_lingo->varFetch(varTest);
-				if (varTest.type != VOID)
-					arg = varTest;
-			}
-			args.push_back(arg);
-		}
+	Object *target;
 
-		if (target.type == OBJECT) {
-			Datum methodName = g_lingo->pop();
-			Symbol method = target.u.obj->getMethod(methodName.asString());
-			if (method.type != VOID) {
-				for (int i = 0; i < nargs.u.i; i++) {
-					g_lingo->push(args.back());
-					args.pop_back();
-				}
-				LC::call(method, nargs.u.i);
-			} else {
-				warning("cb_objectcall: object %s has no method named %s", object.u.s->c_str(), methodName.asString().c_str());
-			}
+	if (d.type == INT) {
+		if (g_lingo->_callstack.empty()) {
+			warning("cb_objectcall: no call frame");
+		}
+		Common::Array<Common::String> *varNames = g_lingo->_callstack.back()->sp.varNames;
+		if ((d.asInt() % 6 == 0) && varNames && (d.asInt() / 6 < (int)varNames->size())) {
+			d = (*varNames)[d.asInt() / 6];
+			d.type = SYMBOL;
+		} else {
+			warning("cb_objectcall: invalid variable ID %d", d.asInt());
 			return;
 		}
+	}
 
-		// if there's nothing, try calling a function with that name
-		Symbol func = g_lingo->getHandler(*object.u.s);
-		if (func.type != VOID) {
-			for (int i = 0; i < nargs.u.i; i++) {
+	if (d.type != SYMBOL) {
+		warning("cb_objectcall: first arg should be of type SYMBOL or INT, not %s", d.type2str());
+		return;
+	}
+
+	// try to fetch target
+	d.type = VAR;
+	Datum val = g_lingo->varFetch(d);
+	if (val.type == OBJECT) {
+		target = val.u.obj;
+	} else {
+		warning("cb_objectcall: target is not an object");
+	}
+
+	if ((nargs.type != ARGC) && (nargs.type != ARGCNORET)) {
+		warning("cb_objectcall: second arg should be of type ARGC or ARGCNORET, not %s", nargs.type2str());
+		return;
+	}
+
+	StackData args;
+	if (target) {
+		// last arg on the stack is the method name
+		nargs.u.i -= 1;
+	}
+
+	for (int i = 0; i < nargs.u.i; i++) {
+		Datum arg = g_lingo->pop();
+		// for some reason, strings that are sent to here are actually variable names???
+		// other constants (e.g. ints) are fine.
+		if (arg.type == STRING) {
+			Datum varTest(arg);
+			varTest.type = VAR;
+			varTest = g_lingo->varFetch(varTest);
+			if (varTest.type != VOID)
+				arg = varTest;
+		}
+		args.push_back(arg);
+	}
+
+	Datum methodName;
+	if (target) {
+		methodName = g_lingo->pop();
+		if (methodName.u.s->equalsIgnoreCase("mNew")) {
+			target = target->clone();
+		}
+		Symbol method = target->getMethod(methodName.asString());
+		if (method.type != VOID) {
+			if (target->type == kFactoryObj && method.type == HANDLER) {
+				// For kFactoryObj handlers the target is the first argument
+				g_lingo->push(method.ctx->_target); // reference-counted datum
+				nargs.u.i += 1;
+			}
+			while (args.size()) {
 				g_lingo->push(args.back());
 				args.pop_back();
 			}
+			LC::call(method, nargs.u.i);
+			return;
+		}
 
-			LC::call(func, nargs.u.i);
-		} else {
-			warning("cb_objectcall: could not find object or function with name %s", object.u.s->c_str());
-			// Push a VOID to the stack if function is supposed to return
-			if (nargs.type == ARGC)
-				g_lingo->push(Datum());
+		warning("cb_objectcall: target has no method named %s", methodName.asString().c_str());
+	}
 
+	// if there's nothing, try calling a function with that name
+	Symbol func = g_lingo->getHandler(*d.u.s);
+	if (func.type != VOID) {
+		if (target) {
+			g_lingo->push(methodName);
+		}
+		while (args.size()) {
+			g_lingo->push(args.back());
+			args.pop_back();
 		}
+
+		LC::call(func, nargs.u.i);
+	} else {
+		warning("cb_objectcall: could not find object or function with name %s", d.u.s->c_str());
+		// Push a VOID to the stack if function is supposed to return
+		if (nargs.type == ARGC)
+			g_lingo->push(Datum());
 	}
 }
 
@@ -514,7 +551,6 @@ void LC::cb_objectfieldpush() {
 void LC::cb_objectpush() {
 	int nameId = g_lingo->readInt();
 	Common::String name = g_lingo->getName(nameId);
-	warning("STUB: cb_objectpush(%s)", name.c_str());
 	Datum result(name);
 	result.type = SYMBOL;
 	g_lingo->push(result);
diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp
index 6efc74773b..8c0a1e7169 100644
--- a/engines/director/lingo/lingo-code.cpp
+++ b/engines/director/lingo/lingo-code.cpp
@@ -224,7 +224,7 @@ void Lingo::pushContext(const Symbol funcSym, bool preserveVarFrame) {
 	g_lingo->_currentScript = funcSym.u.defn;
 	if (funcSym.ctx) {
 		g_lingo->_currentScriptContext = funcSym.ctx;
-		g_lingo->_currentMe = funcSym.ctx->_target;
+		g_lingo->_currentMe = funcSym.ctx->_target; // reference-counted datum
 	}
 	g_lingo->_archiveIndex = funcSym.archiveIndex;
 
@@ -1338,7 +1338,7 @@ void LC::call(const Common::String &name, int nargs) {
 			if (funcSym.type != VOID) {
 				if (target->type == kScriptObj && funcSym.type == HANDLER) {
 					// For kScriptObj handlers the target is the first argument
-					g_lingo->_stack[g_lingo->_stack.size() - nargs] = funcSym.ctx->_target;
+					g_lingo->_stack[g_lingo->_stack.size() - nargs] = funcSym.ctx->_target; // reference-counted datum
 				} else {
 					// Otherwise, take the target object out of the stack
 					g_lingo->_stack.remove_at(g_lingo->_stack.size() - nargs);
@@ -1361,12 +1361,19 @@ void LC::call(const Common::String &name, int nargs) {
 		if (d.type == OBJECT && (d.u.obj->type & (kFactoryObj | kXObj))) {
 			debugC(3, kDebugLingoExec, "Method called on object: <%s>", d.asString(true).c_str());
 			Object *target = d.u.obj;
-			Datum methodName = g_lingo->_stack.remove_at(g_lingo->_stack.size() - nargs); // Take method name out of stack
-			nargs -= 1;
+			Datum methodName = g_lingo->_stack[g_lingo->_stack.size() - nargs];
 			if (methodName.u.s->equalsIgnoreCase("mNew")) {
 				target = target->clone();
 			}
 			funcSym = target->getMethod(*methodName.u.s);
+			if (target->type == kScriptObj && funcSym.type == HANDLER) {
+				// For kFactoryObj handlers the target is the first argument
+				g_lingo->_stack[g_lingo->_stack.size() - nargs] = funcSym.ctx->_target; // reference-counted datum
+			} else {
+				// Otherwise, take the methodName out of the stack
+				g_lingo->_stack.remove_at(g_lingo->_stack.size() - nargs);
+				nargs -= 1;
+			}
 		}
 	}
 
@@ -1413,7 +1420,7 @@ void LC::call(const Symbol &funcSym, int nargs) {
 
 		Datum target;
 		if (funcSym.ctx) {
-			target = funcSym.ctx->_target;
+			target = funcSym.ctx->_target; // reference-counted datum
 		}
 
 		if (target.type == OBJECT) {
diff --git a/engines/director/lingo/lingo-gr.y b/engines/director/lingo/lingo-gr.y
index c1776ba5b5..c1b0be66bd 100644
--- a/engines/director/lingo/lingo-gr.y
+++ b/engines/director/lingo/lingo-gr.y
@@ -774,10 +774,10 @@ defn: tMACRO { startDef(); } ID { g_lingo->_currentFactory = NULL; }
 		endDef();
 		delete $ID; }
 	| tFACTORY ID	{ g_lingo->codeFactory(*$ID); delete $ID; }
-	| tMETHOD { startDef(); }
+	| tMETHOD { startDef(); (*g_lingo->_methodVars)["me"] = kVarArgument; }
 			lbl argdef '\n' argstore stmtlist 		{
 		g_lingo->code1(LC::c_procret);
-		g_lingo->codeDefine(*$tMETHOD, $lbl, $argdef, g_lingo->_currentFactory);
+		g_lingo->codeDefine(*$tMETHOD, $lbl, $argdef + 1, g_lingo->_currentFactory);
 		endDef();
 		delete $tMETHOD; }
 	| on lbl argdef '\n' argstore stmtlist ENDCLAUSE endargdef {	// D3




More information about the Scummvm-git-logs mailing list