diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp index e0ec7e847181..d83a7d3f07c4 100644 --- a/engines/director/lingo/lingo-code.cpp +++ b/engines/director/lingo/lingo-code.cpp @@ -52,12 +52,30 @@ namespace Director { void Lingo::execute(int pc) { - for(_pc = pc; (*_currentScript)[_pc] != STOP;) { + for(_pc = pc; (*_currentScript)[_pc] != STOP && !_returning;) { _pc++; (*((*_currentScript)[_pc - 1]))(); } } +Symbol *Lingo::lookupVar(const char *name) { + Symbol *sym; + + if (!_vars.contains(name)) { // Create variable if it was not defined + sym = new Symbol; + sym->name = (char *)calloc(strlen(name) + 1, 1); + Common::strlcpy(sym->name, name, strlen(name) + 1); + sym->type = VOID; + sym->u.val = 0; + + _vars[name] = sym; + } else { + sym = g_lingo->_vars[name]; + } + + return sym; +} + void Lingo::push(Datum d) { _stack.push_back(d); } @@ -90,23 +108,10 @@ void Lingo::c_constpush() { } void Lingo::c_varpush() { - Datum d; - Symbol *sym; char *name = (char *)&(*g_lingo->_currentScript)[g_lingo->_pc]; + Datum d; - if (!g_lingo->_vars.contains(name)) { // Create variable if it was not defined - sym = new Symbol; - sym->name = (char *)calloc(strlen(name) + 1, 1); - Common::strlcpy(sym->name, name, strlen(name) + 1); - sym->type = VOID; - sym->u.val = 0; - - g_lingo->_vars[name] = sym; - } else { - sym = g_lingo->_vars[name]; - } - - d.sym = sym; + d.sym = g_lingo->lookupVar(name); g_lingo->_pc += g_lingo->calcStringAlignment(name); @@ -259,15 +264,15 @@ void Lingo::c_repeatwhilecode(void) { while (d.val) { g_lingo->execute(body); /* body */ - if (0 /* returning */) + if (g_lingo->_returning) break; g_lingo->execute(savepc + 2); /* condition */ d = g_lingo->pop(); } - //if (!returning) - g_lingo->_pc = end; /* next stmt */ + if (!g_lingo->_returning) + g_lingo->_pc = end; /* next stmt */ } void Lingo::c_repeatwithcode(void) { @@ -278,22 +283,28 @@ void Lingo::c_repeatwithcode(void) { int finish = READ_LE_UINT32(&(*g_lingo->_currentScript)[savepc + 2]); int body = READ_LE_UINT32(&(*g_lingo->_currentScript)[savepc + 3]); int end = READ_LE_UINT32(&(*g_lingo->_currentScript)[savepc + 4]); - Common::String counter((char *)&(*g_lingo->_currentScript)[savepc + 5]); + Common::String countername((char *)&(*g_lingo->_currentScript)[savepc + 5]); + Symbol *counter = g_lingo->lookupVar(countername.c_str()); g_lingo->execute(init); /* condition */ d = g_lingo->pop(); + counter->u.val = d.val; - while (d.val) { + while (true) { g_lingo->execute(body); /* body */ - if (0 /* returning */) + if (g_lingo->_returning) break; + counter->u.val++; g_lingo->execute(finish); /* condition */ d = g_lingo->pop(); + + if (counter->u.val > d.val) + break; } - //if (!returning) - g_lingo->_pc = end; /* next stmt */ + if (!g_lingo->_returning) + g_lingo->_pc = end; /* next stmt */ } void Lingo::c_ifcode() { @@ -304,12 +315,9 @@ void Lingo::c_ifcode() { int elsep = READ_LE_UINT32(&(*g_lingo->_currentScript)[savepc + 1]); int end = READ_LE_UINT32(&(*g_lingo->_currentScript)[savepc + 2]); - warning("cond: %d end: %d then: %d elesp: %d", savepc + 3, end, then, elsep); - g_lingo->execute(savepc + 3); /* condition */ d = g_lingo->pop(); - warning("res: %d", d.val); if (d.val) { g_lingo->execute(then); @@ -317,8 +325,8 @@ void Lingo::c_ifcode() { g_lingo->execute(elsep); } - //if (!returning) - g_lingo->_pc = end; /* next stmt */ + if (!g_lingo->_returning) + g_lingo->_pc = end; /* next stmt */ } //************************ diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp index fee23d1e346a..2575a2b5000f 100644 --- a/engines/director/lingo/lingo.cpp +++ b/engines/director/lingo/lingo.cpp @@ -132,6 +132,7 @@ void Lingo::executeScript(ScriptType type, uint16 id) { _currentScript = _scripts[type][id]; _pc = 0; + _returning = false; execute(_pc); } diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h index cca423a83814..01fb6cceae32 100644 --- a/engines/director/lingo/lingo.h +++ b/engines/director/lingo/lingo.h @@ -119,6 +119,7 @@ class Lingo { public: void execute(int pc); + Symbol *lookupVar(const char *name); static void c_xpop(); static void c_printtop(); @@ -155,6 +156,7 @@ class Lingo { public: ScriptData *_currentScript; + bool _returning; private: int parse(const char *code);