[Scummvm-git-logs] scummvm master -> 112d534b014e2b62d63982b75b3b71b52093cffd

moralrecordings code at moral.net.au
Sun Jan 19 16:19:54 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:
c715b9646a DIRECTOR: LINGO: Split out helper methods varFetch and varAssign
84557806ec DIRECTOR: LINGO: Initialise global list in bytecode
27552ede73 DIRECTOR: LINGO: Only trigger script on kEventNone for v3 and below
7d11a2aa38 DIRECTOR: LINGO: Fix REFERENCE support in varFetch and varAssign
112d534b01 DIRECTOR: LINGO: Allow alignTypes to convert numerics from strings


Commit: c715b9646a1519bda343e52f7964bbe054ef162b
    https://github.com/scummvm/scummvm/commit/c715b9646a1519bda343e52f7964bbe054ef162b
Author: Scott Percival (code at moral.net.au)
Date: 2020-01-20T00:14:54+08:00

Commit Message:
DIRECTOR: LINGO: Split out helper methods varFetch and varAssign

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


diff --git a/engines/director/lingo/lingo-bytecode.cpp b/engines/director/lingo/lingo-bytecode.cpp
index 4654ed3..7967802 100644
--- a/engines/director/lingo/lingo-bytecode.cpp
+++ b/engines/director/lingo/lingo-bytecode.cpp
@@ -60,7 +60,7 @@ static LingoV4Bytecode lingoV4[] = {
 	{ 0x1b, LC::cb_field,		"" },
 	{ 0x1c, LC::c_tell,			"" },
 	{ 0x1d, LC::c_telldone,		"" },
-	{ 0x1e, LC::cb_array,		"" },
+	{ 0x1e, LC::cb_list,		"" },
 	{ 0x41, LC::c_intpush,		"b" },
 	{ 0x42, LC::c_argcnoretpush,"b" },
 	{ 0x43, LC::c_argcpush,		"b" },
@@ -253,17 +253,17 @@ void LC::cb_v4assign() {
 		}
 		break;
 	default:
-		warning("cb_v4putvalue: unknown operator %d", op);
+		warning("cb_v4assign: unknown operator %d", op);
 		break;
 	}
 }
 
 
-void LC::cb_array() {
+void LC::cb_list() {
 	Datum nargs = g_lingo->pop();
 	if ((nargs.type == ARGC) || (nargs.type == ARGCNORET)) {
 		Datum result;
-		warning("STUB: cb_array()");
+		warning("STUB: cb_list()");
 
 		for (int i = 0; i < nargs.u.i; i++)
 			g_lingo->pop();
@@ -271,7 +271,7 @@ void LC::cb_array() {
 		result.type = VOID;
 		g_lingo->push(result);
 	} else {
-		warning("cb_array: first arg should be of type ARGC or ARGCNORET, not %s", nargs.type2str());
+		warning("cb_list: first arg should be of type ARGC or ARGCNORET, not %s", nargs.type2str());
 	}
 }
 
@@ -297,14 +297,15 @@ void LC::cb_globalpush() {
 
 	Symbol *s = g_lingo->lookupVar(name.c_str(), false);
 	if (!s) {
-		warning("Global %s not found", name.c_str());
+		warning("Variable %s not found", name.c_str());
 	} else if (s && !s->global) {
 		warning("Variable %s is local, not global", name.c_str());
 	}
 
-	Datum result;
-	result.type = VOID;
-	warning("STUB: cb_globalpush %s", name.c_str());
+	Datum target;
+	target.type = VAR;
+	target.u.sym = s;
+	Datum result = g_lingo->varFetch(target);
 	g_lingo->push(result);
 }
 
@@ -315,13 +316,18 @@ void LC::cb_globalassign() {
 
 	Symbol *s = g_lingo->lookupVar(name.c_str(), false);
 	if (!s) {
-		warning("Global %s not found", name.c_str());
+		warning("Variable %s not found", name.c_str());
+		g_lingo->pop();
+		return;
 	} else if (s && !s->global) {
 		warning("Variable %s is local, not global", name.c_str());
 	}
 
-	warning("STUB: cb_globalassign %s", name.c_str());
-	g_lingo->pop();
+	Datum target;
+	target.type = VAR;
+	target.u.sym = s;
+	Datum source = g_lingo->pop();
+	g_lingo->varAssign(target, source);
 }
 
 
@@ -336,9 +342,10 @@ void LC::cb_varpush() {
 		warning("Variable %s is global, not local", name.c_str());
 	}
 
-	Datum result;
-	result.type = VOID;
-	warning("STUB: cb_varpush %s", name.c_str());
+	Datum target;
+	target.type = VAR;
+	target.u.sym = s;
+	Datum result = g_lingo->varFetch(target);
 	g_lingo->push(result);
 }
 
@@ -350,12 +357,17 @@ void LC::cb_varassign() {
 	Symbol *s = g_lingo->lookupVar(name.c_str(), false);
 	if (!s) {
 		warning("Variable %s not found", name.c_str());
+		g_lingo->pop();
+		return;
 	} else if (s && s->global) {
 		warning("Variable %s is global, not local", name.c_str());
 	}
 
-	warning("STUB: cb_varassign %s", name.c_str());
-	g_lingo->pop();
+	Datum target;
+	target.type = VAR;
+	target.u.sym = s;
+	Datum source = g_lingo->pop();
+	g_lingo->varAssign(target, source);
 }
 
 
diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp
index 06d0027..55196e4 100644
--- a/engines/director/lingo/lingo-code.cpp
+++ b/engines/director/lingo/lingo-code.cpp
@@ -137,11 +137,11 @@ static struct FuncDescr {
 	{ LC::c_wordOf,			"c_wordOf",			"" },	// D3
 	{ LC::c_wordToOf,		"c_wordToOf",		"" },	// D3
 	{ LC::c_xpop,			"c_xpop",			""  },
-	{ LC::cb_array,			"cb_array",			"" },
 	{ LC::cb_call,			"cb_call",			"i" },
 	{ LC::cb_field,			"cb_field",			"" },
 	{ LC::cb_globalassign,	"cb_globalassign",	"i" },
 	{ LC::cb_globalpush,	"cb_globalpush",	"i" },
+	{ LC::cb_list,			"cb_list",			"" },
 	{ LC::cb_localcall,		"cb_localcall",		"i" },
 	{ LC::cb_unk,			"cb_unk",			"i" },
 	{ LC::cb_unk1,			"cb_unk1",			"ii" },
@@ -366,11 +366,6 @@ void LC::c_assign() {
 	d1 = g_lingo->pop();
 	d2 = g_lingo->pop();
 
-	if (d1.type != VAR && d1.type != REFERENCE) {
-		warning("assignment to non-variable");
-		return;
-	}
-
 	if (d1.type == REFERENCE) {
 		Score *score = g_director->getCurrentScore();
 		if (!score->_loadedCast->contains(d1.u.i)) {
@@ -390,38 +385,7 @@ void LC::c_assign() {
 		return;
 	}
 
-	if (d1.u.sym->type != INT && d1.u.sym->type != VOID &&
-			d1.u.sym->type != FLOAT && d1.u.sym->type != STRING) {
-		warning("assignment to non-variable '%s'", d1.u.sym->name.c_str());
-		return;
-	}
-
-	if ((d1.u.sym->type == STRING || d1.u.sym->type == VOID) && d1.u.sym->u.s) // Free memory if needed
-		delete d1.u.sym->u.s;
-
-	if (d1.u.sym->type == POINT || d1.u.sym->type == RECT || d1.u.sym->type == ARRAY)
-		delete d1.u.sym->u.farr;
-
-	if (d2.type == INT) {
-		d1.u.sym->u.i = d2.u.i;
-	} else if (d2.type == FLOAT) {
-		d1.u.sym->u.f = d2.u.f;
-	} else if (d2.type == STRING) {
-		d1.u.sym->u.s = new Common::String(*d2.u.s);
-		delete d2.u.s;
-	} else if (d2.type == POINT) {
-		d1.u.sym->u.farr = new FloatArray(*d2.u.farr);
-		delete d2.u.farr;
-	} else if (d2.type == SYMBOL) {
-		d1.u.sym->u.i = d2.u.i;
-	} else if (d2.type == OBJECT) {
-		d1.u.sym->u.s = d2.u.s;
-	} else {
-		warning("c_assign: unhandled type: %s", d2.type2str());
-		d1.u.sym->u.s = d2.u.s;
-	}
-
-	d1.u.sym->type = d2.type;
+	g_lingo->varAssign(d1, d2);
 }
 
 bool LC::verify(Symbol *s) {
@@ -457,22 +421,7 @@ void LC::c_eval() {
 	if (!LC::verify(d.u.sym))
 		return;
 
-	d.type = d.u.sym->type;
-
-	if (d.u.sym->type == INT)
-		d.u.i = d.u.sym->u.i;
-	else if (d.u.sym->type == FLOAT)
-		d.u.f = d.u.sym->u.f;
-	else if (d.u.sym->type == STRING)
-		d.u.s = new Common::String(*d.u.sym->u.s);
-	else if (d.u.sym->type == POINT)
-		d.u.farr = d.u.sym->u.farr;
-	else if (d.u.sym->type == SYMBOL)
-		d.u.i = d.u.sym->u.i;
-	else if (d.u.sym->type == VOID)
-		d.u.s = new Common::String(d.u.sym->name);
-	else
-		warning("c_eval: unhandled type: %s", d.type2str());
+	d = g_lingo->varFetch(d);
 
 	g_lingo->push(d);
 }
diff --git a/engines/director/lingo/lingo-code.h b/engines/director/lingo/lingo-code.h
index 15c74b6..9e48ccc 100644
--- a/engines/director/lingo/lingo-code.h
+++ b/engines/director/lingo/lingo-code.h
@@ -130,11 +130,11 @@ namespace LC {
 	void cb_unk2();
 
 	// bytecode-related instructions
-	void cb_array();
 	void cb_call();
 	void cb_field();
 	void cb_globalassign();
 	void cb_globalpush();
+	void cb_list();
 	void cb_localcall();
 	void cb_varassign();
 	void cb_varpush();
diff --git a/engines/director/lingo/lingo-codegen.cpp b/engines/director/lingo/lingo-codegen.cpp
index 704f20a..f2f25da 100644
--- a/engines/director/lingo/lingo-codegen.cpp
+++ b/engines/director/lingo/lingo-codegen.cpp
@@ -479,6 +479,76 @@ void Lingo::processIf(int startlabel, int endlabel, int finalElse) {
 	}
 }
 
+void Lingo::varAssign(Datum &var, Datum &value) {
+	if (var.type != VAR && var.type != REFERENCE) {
+		warning("varAssign: assignment to non-variable");
+		return;
+	}
+
+	if (var.u.sym->type != INT && var.u.sym->type != VOID &&
+			var.u.sym->type != FLOAT && var.u.sym->type != STRING) {
+		warning("varAssign: assignment to non-variable '%s'", var.u.sym->name.c_str());
+		return;
+	}
+
+	if ((var.u.sym->type == STRING || var.u.sym->type == VOID) && var.u.sym->u.s) // Free memory if needed
+		delete var.u.sym->u.s;
+
+	if (var.u.sym->type == POINT || var.u.sym->type == RECT || var.u.sym->type == ARRAY)
+		delete var.u.sym->u.farr;
+
+	if (value.type == INT) {
+		var.u.sym->u.i = value.u.i;
+	} else if (value.type == FLOAT) {
+		var.u.sym->u.f = value.u.f;
+	} else if (value.type == STRING) {
+		var.u.sym->u.s = new Common::String(*value.u.s);
+		delete value.u.s;
+	} else if (value.type == POINT) {
+		var.u.sym->u.farr = new FloatArray(*value.u.farr);
+		delete value.u.farr;
+	} else if (value.type == SYMBOL) {
+		var.u.sym->u.i = value.u.i;
+	} else if (value.type == OBJECT) {
+		var.u.sym->u.s = value.u.s;
+	} else {
+		warning("varAssign: unhandled type: %s", value.type2str());
+		var.u.sym->u.s = value.u.s;
+	}
+
+	var.u.sym->type = value.type;
+}
+
+Datum Lingo::varFetch(Datum &var) {
+	Datum result;
+	result.type = VOID;
+	if (var.type != VAR && var.type != REFERENCE) {
+		warning("varFetch: fetch from non-variable");
+		return result;
+	}
+
+	result.type = var.u.sym->type;
+
+	if (result.u.sym->type == INT)
+		result.u.i = var.u.sym->u.i;
+	else if (var.u.sym->type == FLOAT)
+		result.u.f = var.u.sym->u.f;
+	else if (var.u.sym->type == STRING)
+		result.u.s = new Common::String(*var.u.sym->u.s);
+	else if (var.u.sym->type == POINT)
+		result.u.farr = var.u.sym->u.farr;
+	else if (var.u.sym->type == SYMBOL)
+		result.u.i = var.u.sym->u.i;
+	else if (var.u.sym->type == VOID)
+		result.u.s = new Common::String(var.u.sym->name);
+	else {
+		warning("varFetch: unhandled type: %s", var.type2str());
+		result.type = VOID;
+	}
+
+	return result;
+}
+
 void Lingo::codeFactory(Common::String &name) {
 	_currentFactory = name;
 
diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index 44ea261..39d6d8a 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -196,6 +196,8 @@ public:
 	Symbol *define(Common::String &s, int nargs, ScriptData *code);
 	Symbol *define(Common::String &s, int start, int nargs, Common::String *prefix = NULL, int end = -1, bool removeCode = true);
 	void processIf(int elselabel, int endlabel, int finalElse);
+	void varAssign(Datum &var, Datum &value);
+	Datum varFetch(Datum &var);
 
 	int alignTypes(Datum &d1, Datum &d2);
 


Commit: 84557806ec8c89aefcbcdbfe68dc1dc352896c8f
    https://github.com/scummvm/scummvm/commit/84557806ec8c89aefcbcdbfe68dc1dc352896c8f
Author: Scott Percival (code at moral.net.au)
Date: 2020-01-20T00:14:54+08:00

Commit Message:
DIRECTOR: LINGO: Initialise global list in bytecode

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


diff --git a/engines/director/lingo/lingo-bytecode.cpp b/engines/director/lingo/lingo-bytecode.cpp
index 7967802..ea31ecd 100644
--- a/engines/director/lingo/lingo-bytecode.cpp
+++ b/engines/director/lingo/lingo-bytecode.cpp
@@ -33,7 +33,7 @@ namespace Director {
 
 static LingoV4Bytecode lingoV4[] = {
 	{ 0x01, LC::c_procret,		"" },
-	{ 0x03, LC::c_voidpush,		"" },
+	{ 0x03, LC::cb_zeropush,	"" },
 	{ 0x04, LC::c_mul,			"" },
 	{ 0x05, LC::c_add,			"" },
 	{ 0x06, LC::c_sub,			"" },
@@ -294,10 +294,14 @@ void LC::cb_call() {
 void LC::cb_globalpush() {
 	int nameId = g_lingo->readInt();
 	Common::String name = g_lingo->_namelist[nameId];
+	Datum result;
+	result.type = VOID;
 
 	Symbol *s = g_lingo->lookupVar(name.c_str(), false);
 	if (!s) {
 		warning("Variable %s not found", name.c_str());
+		g_lingo->push(result);
+		return;
 	} else if (s && !s->global) {
 		warning("Variable %s is local, not global", name.c_str());
 	}
@@ -305,7 +309,7 @@ void LC::cb_globalpush() {
 	Datum target;
 	target.type = VAR;
 	target.u.sym = s;
-	Datum result = g_lingo->varFetch(target);
+	result = g_lingo->varFetch(target);
 	g_lingo->push(result);
 }
 
@@ -334,10 +338,14 @@ void LC::cb_globalassign() {
 void LC::cb_varpush() {
 	int nameId = g_lingo->readInt();
 	Common::String name = g_lingo->_namelist[nameId];
+	Datum result;
+	result.type = VOID;
 
 	Symbol *s = g_lingo->lookupVar(name.c_str(), false);
 	if (!s) {
 		warning("Variable %s not found", name.c_str());
+		g_lingo->push(result);
+		return;
 	} else if (s && s->global) {
 		warning("Variable %s is global, not local", name.c_str());
 	}
@@ -345,7 +353,7 @@ void LC::cb_varpush() {
 	Datum target;
 	target.type = VAR;
 	target.u.sym = s;
-	Datum result = g_lingo->varFetch(target);
+	result = g_lingo->varFetch(target);
 	g_lingo->push(result);
 }
 
@@ -520,6 +528,13 @@ void LC::cb_v4theentityassign() {
 	}
 }
 
+void LC::cb_zeropush() {
+	Datum d;
+	d.u.i = 0;
+	d.type = INT;
+	g_lingo->push(d);
+}
+
 void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, ScriptType type, uint16 id) {
 	debugC(1, kDebugLingoCompile, "Add V4 bytecode for type %s with id %d", scriptType2str(type), id);
 
@@ -550,8 +565,8 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, ScriptType ty
 	for (uint32 i = 0; i < 0x2e; i++) {
 		stream.readByte();
 	}
-	/*uint16 globalsOffset = */stream.readUint16();
-	/*uint16 globalsCount = */stream.readUint16();
+	uint16 globalsOffset = stream.readUint16();
+	uint16 globalsCount = stream.readUint16();
 	// unk3
 	for (uint32 i = 0; i < 0x4; i++) {
 		stream.readByte();
@@ -567,6 +582,20 @@ void Lingo::addCodeV4(Common::SeekableSubReadStreamEndian &stream, ScriptType ty
 	stream.readUint16();
 	/*uint16 constsBase = */stream.readUint16();
 
+	// initialise each global variable
+	debugC(5, kDebugLoading, "Lscr globals list:");
+	stream.seek(globalsOffset);
+	for (uint16 i = 0; i < globalsCount; i++) {
+		uint16 nameIndex = stream.readUint16();
+		if (nameIndex < _namelist.size()) {
+			const char *name = _namelist[nameIndex].c_str();
+			debugC(5, kDebugLoading, "%d: %s", i, name);
+			Symbol *s = g_lingo->lookupVar(name, true, true);
+		} else {
+			warning("Global %d has unknown name id %d, skipping define", i, nameIndex);
+		}
+	}
+
 	// preload all the constants!
 	// these are stored as a reference table of 6 byte entries, followed by a storage area.
 
diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp
index 55196e4..d101213 100644
--- a/engines/director/lingo/lingo-code.cpp
+++ b/engines/director/lingo/lingo-code.cpp
@@ -152,6 +152,7 @@ static struct FuncDescr {
 	{ LC::cb_v4theentitypush,"cb_v4theentitypush","i" },
 	{ LC::cb_v4theentitynamepush,"cb_v4theentitynamepush","i" },
 	{ LC::cb_v4theentityassign,"cb_v4theentityassign","i" },
+	{ LC::cb_zeropush,		"cb_zeropush",		"" },
 	{ 0, 0, 0 }
 };
 
diff --git a/engines/director/lingo/lingo-code.h b/engines/director/lingo/lingo-code.h
index 9e48ccc..e02fc91 100644
--- a/engines/director/lingo/lingo-code.h
+++ b/engines/director/lingo/lingo-code.h
@@ -142,6 +142,7 @@ namespace LC {
 	void cb_v4theentitypush();
 	void cb_v4theentitynamepush();
 	void cb_v4theentityassign();
+	void cb_zeropush();
 
 } // End of namespace LC
 
diff --git a/engines/director/lingo/lingo-codegen.cpp b/engines/director/lingo/lingo-codegen.cpp
index f2f25da..7db1de1 100644
--- a/engines/director/lingo/lingo-codegen.cpp
+++ b/engines/director/lingo/lingo-codegen.cpp
@@ -511,6 +511,8 @@ void Lingo::varAssign(Datum &var, Datum &value) {
 		var.u.sym->u.i = value.u.i;
 	} else if (value.type == OBJECT) {
 		var.u.sym->u.s = value.u.s;
+	} else if (value.type == VOID) {
+		var.u.sym->u.i = 0;
 	} else {
 		warning("varAssign: unhandled type: %s", value.type2str());
 		var.u.sym->u.s = value.u.s;
@@ -529,7 +531,7 @@ Datum Lingo::varFetch(Datum &var) {
 
 	result.type = var.u.sym->type;
 
-	if (result.u.sym->type == INT)
+	if (var.u.sym->type == INT)
 		result.u.i = var.u.sym->u.i;
 	else if (var.u.sym->type == FLOAT)
 		result.u.f = var.u.sym->u.f;
@@ -540,7 +542,7 @@ Datum Lingo::varFetch(Datum &var) {
 	else if (var.u.sym->type == SYMBOL)
 		result.u.i = var.u.sym->u.i;
 	else if (var.u.sym->type == VOID)
-		result.u.s = new Common::String(var.u.sym->name);
+		result.u.i = 0;
 	else {
 		warning("varFetch: unhandled type: %s", var.type2str());
 		result.type = VOID;


Commit: 27552ede73907bf4c07dd4fd0c5290e214270ad1
    https://github.com/scummvm/scummvm/commit/27552ede73907bf4c07dd4fd0c5290e214270ad1
Author: Scott Percival (code at moral.net.au)
Date: 2020-01-20T00:14:54+08:00

Commit Message:
DIRECTOR: LINGO: Only trigger script on kEventNone for v3 and below

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


diff --git a/engines/director/lingo/lingo-events.cpp b/engines/director/lingo/lingo-events.cpp
index ab3b62a..cc4d040 100644
--- a/engines/director/lingo/lingo-events.cpp
+++ b/engines/director/lingo/lingo-events.cpp
@@ -319,7 +319,7 @@ void Lingo::processEvent(LEvent event, ScriptType st, int entityId) {
 	if (_handlers.contains(ENTITY_INDEX(event, entityId))) {
 		debugC(1, kDebugEvents, "Lingo::processEvent(%s, %s, %d), _eventHandler", _eventHandlerTypes[event], scriptType2str(st), entityId);
 		executeHandler(_eventHandlerTypes[event]); // D4+ Events
-	} else if (event == kEventNone && _scriptContexts[st].contains(entityId)) {
+	} else if (_vm->getVersion() < 4 && event == kEventNone && _scriptContexts[st].contains(entityId)) {
 		debugC(1, kDebugEvents, "Lingo::processEvent(%s, %s, %d), script", _eventHandlerTypes[event], scriptType2str(st), entityId);
 
 		executeScript(st, entityId, 0); // D3 list of scripts.


Commit: 7d11a2aa383cafffcb9f8d5cdc1244dd05eb4500
    https://github.com/scummvm/scummvm/commit/7d11a2aa383cafffcb9f8d5cdc1244dd05eb4500
Author: Scott Percival (code at moral.net.au)
Date: 2020-01-20T00:14:54+08:00

Commit Message:
DIRECTOR: LINGO: Fix REFERENCE support in varFetch and varAssign

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


diff --git a/engines/director/lingo/lingo-bytecode.cpp b/engines/director/lingo/lingo-bytecode.cpp
index ea31ecd..9627931 100644
--- a/engines/director/lingo/lingo-bytecode.cpp
+++ b/engines/director/lingo/lingo-bytecode.cpp
@@ -220,6 +220,9 @@ void LC::cb_unk2() {
 
 void LC::cb_field() {
 	LB::b_field(1);
+	Datum field = g_lingo->pop();
+	Datum result = g_lingo->varFetch(field);
+	g_lingo->push(result);
 }
 
 
@@ -248,7 +251,7 @@ void LC::cb_v4assign() {
 	case 0x16:
 		// put value into field textVar
 		{
-			LC::cb_field();
+			LB::b_field(1);
 			LC::c_assign();
 		}
 		break;
diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp
index d101213..8980419 100644
--- a/engines/director/lingo/lingo-code.cpp
+++ b/engines/director/lingo/lingo-code.cpp
@@ -367,25 +367,6 @@ void LC::c_assign() {
 	d1 = g_lingo->pop();
 	d2 = g_lingo->pop();
 
-	if (d1.type == REFERENCE) {
-		Score *score = g_director->getCurrentScore();
-		if (!score->_loadedCast->contains(d1.u.i)) {
-			if (!score->_loadedCast->contains(d1.u.i - score->_castIDoffset)) {
-				warning("c_assign: Unknown REFERENCE %d", d1.u.i);
-				g_lingo->pushVoid();
-				return;
-			} else {
-				d1.u.i -= score->_castIDoffset;
-			}
-		}
-
-		d2.toString();
-
-		((TextCast *)score->_loadedCast->getVal(d1.u.i))->setText(d2.u.s->c_str());
-
-		return;
-	}
-
 	g_lingo->varAssign(d1, d2);
 }
 
diff --git a/engines/director/lingo/lingo-codegen.cpp b/engines/director/lingo/lingo-codegen.cpp
index 7db1de1..cc78fba 100644
--- a/engines/director/lingo/lingo-codegen.cpp
+++ b/engines/director/lingo/lingo-codegen.cpp
@@ -44,6 +44,8 @@
 // THIS SOFTWARE.
 
 #include "director/director.h"
+#include "director/cast.h"
+#include "director/score.h"
 #include "director/lingo/lingo.h"
 #include "director/lingo/lingo-builtins.h"
 #include "director/lingo/lingo-code.h"
@@ -485,40 +487,70 @@ void Lingo::varAssign(Datum &var, Datum &value) {
 		return;
 	}
 
-	if (var.u.sym->type != INT && var.u.sym->type != VOID &&
-			var.u.sym->type != FLOAT && var.u.sym->type != STRING) {
-		warning("varAssign: assignment to non-variable '%s'", var.u.sym->name.c_str());
-		return;
-	}
+	if (var.type == VAR) {
+		Symbol *sym = var.u.sym;
+		if (!sym) {
+			warning("varAssign: symbol not defined");
+			return;
+		}
 
-	if ((var.u.sym->type == STRING || var.u.sym->type == VOID) && var.u.sym->u.s) // Free memory if needed
-		delete var.u.sym->u.s;
-
-	if (var.u.sym->type == POINT || var.u.sym->type == RECT || var.u.sym->type == ARRAY)
-		delete var.u.sym->u.farr;
-
-	if (value.type == INT) {
-		var.u.sym->u.i = value.u.i;
-	} else if (value.type == FLOAT) {
-		var.u.sym->u.f = value.u.f;
-	} else if (value.type == STRING) {
-		var.u.sym->u.s = new Common::String(*value.u.s);
-		delete value.u.s;
-	} else if (value.type == POINT) {
-		var.u.sym->u.farr = new FloatArray(*value.u.farr);
-		delete value.u.farr;
-	} else if (value.type == SYMBOL) {
-		var.u.sym->u.i = value.u.i;
-	} else if (value.type == OBJECT) {
-		var.u.sym->u.s = value.u.s;
-	} else if (value.type == VOID) {
-		var.u.sym->u.i = 0;
-	} else {
-		warning("varAssign: unhandled type: %s", value.type2str());
-		var.u.sym->u.s = value.u.s;
-	}
+		if (sym->type != INT && sym->type != VOID &&
+				sym->type != FLOAT && sym->type != STRING) {
+			warning("varAssign: assignment to non-variable '%s'", sym->name.c_str());
+			return;
+		}
 
-	var.u.sym->type = value.type;
+		if ((sym->type == STRING || sym->type == VOID) && sym->u.s) // Free memory if needed
+			delete var.u.sym->u.s;
+
+		if (sym->type == POINT || sym->type == RECT || sym->type == ARRAY)
+			delete var.u.sym->u.farr;
+
+		sym->type = value.type;
+		if (value.type == INT) {
+			sym->u.i = value.u.i;
+		} else if (value.type == FLOAT) {
+			sym->u.f = value.u.f;
+		} else if (value.type == STRING) {
+			sym->u.s = new Common::String(*value.u.s);
+			delete value.u.s;
+		} else if (value.type == POINT) {
+			sym->u.farr = new FloatArray(*value.u.farr);
+			delete value.u.farr;
+		} else if (value.type == SYMBOL) {
+			sym->u.i = value.u.i;
+		} else if (value.type == OBJECT) {
+			sym->u.s = value.u.s;
+		} else if (value.type == VOID) {
+			sym->u.i = 0;
+		} else {
+			warning("varAssign: unhandled type: %s", value.type2str());
+			sym->u.s = value.u.s;
+		}
+	} else if (var.type == REFERENCE) {
+		Score *score = g_director->getCurrentScore();
+		if (!score->_loadedCast->contains(var.u.i)) {
+			if (!score->_loadedCast->contains(var.u.i - score->_castIDoffset)) {
+				warning("varAssign: Unknown REFERENCE %d", var.u.i);
+				return;
+			} else {
+				var.u.i -= score->_castIDoffset;
+			}
+		}
+		Cast *cast = score->_loadedCast->getVal(var.u.i);
+		if (cast) {
+			switch (cast->_type) {
+			case kCastText:
+				value.toString();
+				((TextCast *)cast)->setText(value.u.s->c_str());
+				delete value.u.s;
+				break;
+			default:
+				warning("varAssign: Unhandled cast type %s", tag2str(cast->_type));
+				break;
+			}
+		}
+	}
 }
 
 Datum Lingo::varFetch(Datum &var) {
@@ -529,23 +561,55 @@ Datum Lingo::varFetch(Datum &var) {
 		return result;
 	}
 
-	result.type = var.u.sym->type;
-
-	if (var.u.sym->type == INT)
-		result.u.i = var.u.sym->u.i;
-	else if (var.u.sym->type == FLOAT)
-		result.u.f = var.u.sym->u.f;
-	else if (var.u.sym->type == STRING)
-		result.u.s = new Common::String(*var.u.sym->u.s);
-	else if (var.u.sym->type == POINT)
-		result.u.farr = var.u.sym->u.farr;
-	else if (var.u.sym->type == SYMBOL)
-		result.u.i = var.u.sym->u.i;
-	else if (var.u.sym->type == VOID)
-		result.u.i = 0;
-	else {
-		warning("varFetch: unhandled type: %s", var.type2str());
-		result.type = VOID;
+	if (var.type == VAR) {
+		Symbol *sym = var.u.sym;
+		if (!sym) {
+			warning("varFetch: symbol not defined");
+			return result;
+		}
+
+		result.type = sym->type;
+
+		if (sym->type == INT)
+			result.u.i = sym->u.i;
+		else if (sym->type == FLOAT)
+			result.u.f = sym->u.f;
+		else if (sym->type == STRING)
+			result.u.s = new Common::String(*sym->u.s);
+		else if (sym->type == POINT)
+			result.u.farr = sym->u.farr;
+		else if (sym->type == SYMBOL)
+			result.u.i = var.u.sym->u.i;
+		else if (sym->type == VOID)
+			result.u.i = 0;
+		else {
+			warning("varFetch: unhandled type: %s", var.type2str());
+			result.type = VOID;
+		}
+
+	} else if (var.type == REFERENCE) {
+		Score *score = g_director->getCurrentScore();
+		if (!score->_loadedCast->contains(var.u.i)) {
+			if (!score->_loadedCast->contains(var.u.i - score->_castIDoffset)) {
+				warning("varFetch: Unknown REFERENCE %d", var.u.i);
+				return result;
+			} else {
+				var.u.i -= score->_castIDoffset;
+			}
+		}
+		Cast *cast = score->_loadedCast->getVal(var.u.i);
+		if (cast) {
+			switch (cast->_type) {
+			case kCastText:
+				result.type = STRING;
+				result.u.s = new Common::String(((TextCast *)cast)->_ptext);
+				break;
+			default:
+				warning("varFetch: Unhandled cast type %s", tag2str(cast->_type));
+				break;
+			}
+		}
+
 	}
 
 	return result;


Commit: 112d534b014e2b62d63982b75b3b71b52093cffd
    https://github.com/scummvm/scummvm/commit/112d534b014e2b62d63982b75b3b71b52093cffd
Author: Scott Percival (code at moral.net.au)
Date: 2020-01-20T00:14:54+08:00

Commit Message:
DIRECTOR: LINGO: Allow alignTypes to convert numerics from strings

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


diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index 08c038c..8f66ff9 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -290,12 +290,50 @@ void Lingo::restartLingo() {
 }
 
 int Lingo::alignTypes(Datum &d1, Datum &d2) {
-	int opType = INT;
+	int opType = VOID;
+
+	if (d1.type == STRING) {
+		char *endPtr = 0;
+		int i = strtol(d1.u.s->c_str(), &endPtr, 10);
+		if (*endPtr == 0) {
+			d1.type = INT;
+			d1.u.i = i;
+		} else {
+			double d = strtod(d1.u.s->c_str(), &endPtr);
+			if (*endPtr == 0) {
+				d1.type = FLOAT;
+				d1.u.f = d;
+			} else {
+				warning("Unable to parse '%s' as a number", d1.u.s->c_str());
+			}
+		}
+	}
+	if (d2.type == STRING) {
+		char *endPtr = 0;
+		int i = strtol(d2.u.s->c_str(), &endPtr, 10);
+		if (*endPtr == 0) {
+			d2.type = INT;
+			d2.u.i = i;
+		} else {
+			double d = strtod(d2.u.s->c_str(), &endPtr);
+			if (*endPtr == 0) {
+				d2.type = FLOAT;
+				d2.u.f = d;
+			} else {
+				warning("Unable to parse '%s' as a number", d2.u.s->c_str());
+			}
+		}
+	}
+
 
 	if (d1.type == FLOAT || d2.type == FLOAT) {
 		opType = FLOAT;
 		d1.toFloat();
 		d2.toFloat();
+	} else if (d1.type == INT && d2.type == INT) {
+		opType = INT;
+	} else {
+		warning("No numeric type alignment available");
 	}
 
 	return opType;
@@ -307,7 +345,16 @@ int Datum::toInt() {
 		toString();
 		// fallthrough
 	case STRING:
-		u.i = atoi(u.s->c_str());
+		{
+			char *endPtr = 0;
+			int result = strtol(u.s->c_str(), &endPtr, 10);
+			if (*endPtr == 0) {
+				u.i = result;
+			} else {
+				warning("Invalid int '%s'", u.s->c_str());
+				u.i = 0;
+			}
+		}
 		break;
 	case VOID:
 		u.i = 0;
@@ -333,7 +380,16 @@ double Datum::toFloat() {
 		toString();
 		// fallthrough
 	case STRING:
-		u.f = atof(u.s->c_str());
+		{
+			char *endPtr = 0;
+			double result = strtod(u.s->c_str(), &endPtr);
+			if (*endPtr == 0) {
+				u.f = result;
+			} else {
+				warning("Invalid float '%s'", u.s->c_str());
+				u.f = 0.0;
+			}
+		}
 		break;
 	case VOID:
 		u.f = 0.0;




More information about the Scummvm-git-logs mailing list