[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