DIRECTOR: Move current Lingo state into Window-owned struct

The previous arrangement was to copy the bits of Lingo state back and forth from
the Window object to the Lingo instance, and query the window for the
callstack. This refactor consolidates the current Lingo state into a single
struct, owned by the Window object and accessible via a pointer on the
Lingo object.
This commit is contained in:
Scott Percival 2022-11-04 21:19:28 +08:00 committed by Eugene Sandulenko
parent 75231868db
commit 873095c87e
37 changed files with 224 additions and 251 deletions

View File

@ -334,7 +334,7 @@ bool Debugger::cmdFuncs(int argc, const char **argv) {
Lingo *lingo = g_director->getLingo();
Movie *movie = g_director->getCurrentMovie();
Score *score = movie->getScore();
ScriptContext *csc = lingo->_currentScriptContext;
ScriptContext *csc = lingo->_state->context;
if (csc) {
debugPrintf("Functions attached to frame %d:\n", score->getCurrentFrame());
debugPrintf(" %d:", csc->_id);
@ -365,7 +365,7 @@ bool Debugger::cmdFuncs(int argc, const char **argv) {
bool Debugger::cmdBacktrace(int argc, const char **argv) {
Lingo *lingo = g_director->getLingo();
debugPrintf("%s\n", lingo->formatCallStack(lingo->_pc).c_str());
debugPrintf("%s\n", lingo->formatCallStack(lingo->_state->pc).c_str());
return true;
}
@ -375,7 +375,7 @@ bool Debugger::cmdDisasm(int argc, const char **argv) {
if (!strcmp(argv[1], "all")) {
Movie *movie = g_director->getCurrentMovie();
Score *score = movie->getScore();
ScriptContext *csc = lingo->_currentScriptContext;
ScriptContext *csc = lingo->_state->context;
if (csc) {
debugPrintf("Functions attached to frame %d:\n", score->getCurrentFrame());
for (auto &it : csc->_functionHandlers) {
@ -459,7 +459,7 @@ bool Debugger::cmdDisasm(int argc, const char **argv) {
}
} else {
Common::Array<CFrame *> &callstack = g_director->getCurrentWindow()->_callstack;
Common::Array<CFrame *> &callstack = g_lingo->_state->callstack;
if (callstack.size() == 0) {
debugPrintf("Lingo is not executing, nothing to disassemble.\n");
return true;
@ -511,7 +511,7 @@ bool Debugger::cmdBpSet(int argc, const char **argv) {
bp.id = _bpNextId;
bp.type = kBreakpointFunction;
if (argc == 1) {
Common::Array<CFrame *> &callstack = g_director->getCurrentWindow()->_callstack;
Common::Array<CFrame *> &callstack = g_lingo->_state->callstack;
if (callstack.size() == 0) {
debugPrintf("Lingo is not executing, no current function to add breakpoint to.\n");
return true;
@ -527,14 +527,14 @@ bool Debugger::cmdBpSet(int argc, const char **argv) {
}
bp.scriptId = frame->sp.ctx->_id;
bp.funcName = *frame->sp.name;
bp.funcOffset = g_lingo->_pc;
bp.funcOffset = g_lingo->_state->pc;
} else if (argc == 2 || argc == 3) {
Common::String target(argv[1]);
uint splitPoint = target.findFirstOf(":");
if (splitPoint == Common::String::npos) {
if (argc == 2 && atoi(argv[1]) > 0) {
// first and only argument is a number, use as an offset for the current function
Common::Array<CFrame *> &callstack = g_director->getCurrentWindow()->_callstack;
Common::Array<CFrame *> &callstack = g_lingo->_state->callstack;
if (callstack.size() == 0) {
debugPrintf("Lingo is not executing, no current function to add breakpoint to.\n");
return true;
@ -780,7 +780,7 @@ void Debugger::bpUpdateState() {
_bpCheckEntityRead = false;
_bpCheckEntityWrite = false;
Movie *movie = g_director->getCurrentMovie();
Common::Array<CFrame *> &callstack = g_director->getCurrentWindow()->_callstack;
Common::Array<CFrame *> &callstack = g_lingo->_state->callstack;
for (auto &it : _breakpoints) {
if (!it.enabled)
continue;
@ -829,7 +829,7 @@ void Debugger::bpTest(bool forceCheck) {
// Check if there's a funcName/offset or frame/movie match
bool stop = forceCheck;
uint funcOffset = g_lingo->_pc;
uint funcOffset = g_lingo->_state->pc;
Score *score = g_director->getCurrentMovie()->getScore();
uint frameOffset = score->getCurrentFrame();
if (_bpCheckFunc) {

View File

@ -221,6 +221,7 @@ Common::Error DirectorEngine::run() {
_currentWindow = _stage;
_lingo = new Lingo(this);
_lingo->switchStateFromWindow();
if (getGameGID() == GID_TEST) {
_currentWindow->runTests();
@ -248,9 +249,8 @@ Common::Error DirectorEngine::run() {
processEvents();
_currentWindow = _stage;
g_lingo->loadStateFromWindow();
g_lingo->switchStateFromWindow();
loop = _currentWindow->step();
g_lingo->saveStateToWindow();
if (loop) {
FArray *windowList = g_lingo->_windowList.u.farr;
@ -259,9 +259,8 @@ Common::Error DirectorEngine::run() {
continue;
_currentWindow = static_cast<Window *>(windowList->arr[i].u.obj);
g_lingo->loadStateFromWindow();
g_lingo->switchStateFromWindow();
_currentWindow->step();
g_lingo->saveStateToWindow();
}
}

View File

@ -1599,7 +1599,7 @@ void LB::b_quit(int nargs) {
}
void LB::b_return(int nargs) {
CFrame *fp = g_director->getCurrentWindow()->_callstack.back();
CFrame *fp = g_lingo->_state->callstack.back();
Datum retVal;
if (nargs > 0) {
@ -1612,7 +1612,7 @@ void LB::b_return(int nargs) {
g_lingo->pop();
// Do not allow a factory's mNew method to return a value
if (nargs > 0 && !(g_lingo->_currentMe.type == OBJECT && g_lingo->_currentMe.u.obj->getObjType() == kFactoryObj
if (nargs > 0 && !(g_lingo->_state->me.type == OBJECT && g_lingo->_state->me.u.obj->getObjType() == kFactoryObj
&& fp->sp.name->equalsIgnoreCase("mNew"))) {
g_lingo->push(retVal);
}
@ -1773,8 +1773,8 @@ void LB::b_showGlobals(int nargs) {
void LB::b_showLocals(int nargs) {
Common::String local_out = "-- Local Variables --\n";
if (g_lingo->_localvars) {
for (auto it = g_lingo->_localvars->begin(); it != g_lingo->_localvars->end(); it++) {
if (g_lingo->_state->localVars) {
for (auto it = g_lingo->_state->localVars->begin(); it != g_lingo->_state->localVars->end(); it++) {
local_out += it->_key + " = " + it->_value.asString() + "\n";
}
}

View File

@ -347,7 +347,7 @@ Datum Lingo::findVarV4(int varType, const Datum &id) {
case 4: // arg
case 5: // local
{
Common::Array<CFrame *> &callstack = _vm->getCurrentWindow()->_callstack;
Common::Array<CFrame *> &callstack = _state->callstack;
if (callstack.empty()) {
warning("BUILDBOT: findVarV4: no call frame");
return res;
@ -420,7 +420,7 @@ void LC::cb_localcall() {
Datum nargs = g_lingo->pop();
if ((nargs.type == ARGC) || (nargs.type == ARGCNORET)) {
Common::String name = g_lingo->_currentScriptContext->_functionNames[functionId];
Common::String name = g_lingo->_state->context->_functionNames[functionId];
if (debugChannelSet(3, kDebugLingoExec))
printWithArgList(name.c_str(), nargs.u.i, "localcall:");
@ -587,9 +587,9 @@ void LC::cb_theassign() {
// cb_theassign is for setting script/factory-level properties
Common::String name = g_lingo->readString();
Datum value = g_lingo->pop();
if (g_lingo->_currentMe.type == OBJECT) {
if (g_lingo->_currentMe.u.obj->hasProp(name)) {
g_lingo->_currentMe.u.obj->setProp(name, value);
if (g_lingo->_state->me.type == OBJECT) {
if (g_lingo->_state->me.u.obj->hasProp(name)) {
g_lingo->_state->me.u.obj->setProp(name, value);
} else {
warning("cb_theassign: me object has no property '%s'", name.c_str());
}
@ -616,9 +616,9 @@ void LC::cb_theassign2() {
void LC::cb_thepush() {
Common::String name = g_lingo->readString();
if (g_lingo->_currentMe.type == OBJECT) {
if (g_lingo->_currentMe.u.obj->hasProp(name)) {
g_lingo->push(g_lingo->_currentMe.u.obj->getProp(name));
if (g_lingo->_state->me.type == OBJECT) {
if (g_lingo->_state->me.u.obj->hasProp(name)) {
g_lingo->push(g_lingo->_state->me.u.obj->getProp(name));
return;
}
warning("cb_thepush: me object has no property '%s'", name.c_str());

View File

@ -219,54 +219,39 @@ void LC::c_xpop() {
g_lingo->pop();
}
void Lingo::loadStateFromWindow() {
void Lingo::switchStateFromWindow() {
Window *window = _vm->getCurrentWindow();
_pc = window->_retPC;
_currentScript = window->_retScript;
_currentScriptContext = window->_retContext;
_freezeContext = window->_retFreezeContext;
_localvars = window->_retLocalVars;
_currentMe = window->_retMe;
}
void Lingo::saveStateToWindow() {
Window *window = _vm->getCurrentWindow();
window->_retPC = _pc;
window->_retScript = _currentScript;
window->_retContext = _currentScriptContext;
window->_retFreezeContext = _freezeContext;
window->_retLocalVars = _localvars;
window->_retMe = _currentMe;
_state = window->getLingoState();
}
void Lingo::pushContext(const Symbol funcSym, bool allowRetVal, Datum defaultRetVal) {
Common::Array<CFrame *> &callstack = _vm->getCurrentWindow()->_callstack;
Common::Array<CFrame *> &callstack = _state->callstack;
debugC(5, kDebugLingoExec, "Pushing frame %d", callstack.size() + 1);
CFrame *fp = new CFrame;
fp->retPC = g_lingo->_pc;
fp->retScript = g_lingo->_currentScript;
fp->retContext = g_lingo->_currentScriptContext;
fp->retFreezeContext = g_lingo->_freezeContext;
fp->retLocalVars = g_lingo->_localvars;
fp->retMe = g_lingo->_currentMe;
fp->retPC = _state->pc;
fp->retScript = _state->script;
fp->retContext = _state->context;
fp->retFreezeContext = _freezeContext;
fp->retLocalVars = _state->localVars;
fp->retMe = _state->me;
fp->sp = funcSym;
fp->allowRetVal = allowRetVal;
fp->defaultRetVal = defaultRetVal;
g_lingo->_currentScript = funcSym.u.defn;
_state->script = funcSym.u.defn;
if (funcSym.target)
g_lingo->_currentMe = funcSym.target;
_state->me = funcSym.target;
if (funcSym.ctx) {
g_lingo->_currentScriptContext = funcSym.ctx;
*g_lingo->_currentScriptContext->_refCount += 1;
_state->context = funcSym.ctx;
*_state->context->_refCount += 1;
}
g_lingo->_freezeContext = false;
_freezeContext = false;
DatumHash *localvars = g_lingo->_localvars;
DatumHash *localvars = _state->localVars;
if (!funcSym.anonymous) {
// Execute anonymous functions within the current var frame.
localvars = new DatumHash;
@ -278,7 +263,7 @@ void Lingo::pushContext(const Symbol funcSym, bool allowRetVal, Datum defaultRet
int dropSize = symNArgs - funcSym.argNames->size();
warning("%d arg names defined for %d args! Dropping the last %d values", funcSym.argNames->size(), symNArgs, dropSize);
for (int i = 0; i < dropSize; i++) {
g_lingo->pop();
pop();
symNArgs -= 1;
}
} else if ((int)funcSym.argNames->size() > symNArgs) {
@ -287,11 +272,11 @@ void Lingo::pushContext(const Symbol funcSym, bool allowRetVal, Datum defaultRet
for (int i = symNArgs - 1; i >= 0; i--) {
Common::String name = (*funcSym.argNames)[i];
if (!localvars->contains(name)) {
Datum value = g_lingo->pop();
Datum value = pop();
(*localvars)[name] = value;
} else {
warning("Argument %s already defined", name.c_str());
g_lingo->pop();
pop();
}
}
}
@ -305,21 +290,21 @@ void Lingo::pushContext(const Symbol funcSym, bool allowRetVal, Datum defaultRet
}
}
}
g_lingo->_localvars = localvars;
_state->localVars = localvars;
fp->stackSizeBefore = _stack.size();
callstack.push_back(fp);
if (debugChannelSet(2, kDebugLingoExec)) {
g_lingo->printCallStack(0);
printCallStack(0);
}
g_lingo->_pc = 0;
_state->pc = 0;
g_debugger->pushContextHook();
}
void Lingo::popContext(bool aborting) {
Common::Array<CFrame *> &callstack = _vm->getCurrentWindow()->_callstack;
Common::Array<CFrame *> &callstack = _state->callstack;
debugC(5, kDebugLingoExec, "Popping frame %d", callstack.size());
CFrame *fp = callstack.back();
@ -328,7 +313,7 @@ void Lingo::popContext(bool aborting) {
if (_stack.size() == fp->stackSizeBefore + 1) {
if (!fp->allowRetVal) {
debugC(5, kDebugLingoExec, "dropping return value");
g_lingo->pop();
pop();
}
} else if (_stack.size() == fp->stackSizeBefore) {
if (fp->allowRetVal) {
@ -337,14 +322,14 @@ void Lingo::popContext(bool aborting) {
if (fp->defaultRetVal.type == VOID) {
warning("handler %s did not return value", fp->sp.name->c_str());
}
g_lingo->push(fp->defaultRetVal);
push(fp->defaultRetVal);
}
} else if (_stack.size() > fp->stackSizeBefore) {
if (aborting) {
// Since we're aborting execution, we should expect that some extra
// values are left on the stack.
while (_stack.size() > fp->stackSizeBefore) {
g_lingo->pop();
pop();
}
} else {
error("handler %s returned extra %d values", fp->sp.name->c_str(), _stack.size() - fp->stackSizeBefore);
@ -353,25 +338,25 @@ void Lingo::popContext(bool aborting) {
error("handler %s popped extra %d values", fp->sp.name->c_str(), fp->stackSizeBefore - _stack.size());
}
*g_lingo->_currentScriptContext->_refCount -= 1;
if (*g_lingo->_currentScriptContext->_refCount <= 0) {
delete g_lingo->_currentScriptContext;
*_state->context->_refCount -= 1;
if (*_state->context->_refCount <= 0) {
delete _state->context;
}
g_lingo->_currentScript = fp->retScript;
g_lingo->_currentScriptContext = fp->retContext;
g_lingo->_freezeContext = fp->retFreezeContext;
g_lingo->_pc = fp->retPC;
g_lingo->_currentMe = fp->retMe;
_state->script = fp->retScript;
_state->context = fp->retContext;
_freezeContext = fp->retFreezeContext;
_state->pc = fp->retPC;
_state->me = fp->retMe;
// Restore local variables
if (!fp->sp.anonymous) {
g_lingo->cleanLocalVars();
g_lingo->_localvars = fp->retLocalVars;
cleanLocalVars();
_state->localVars = fp->retLocalVars;
}
if (debugChannelSet(2, kDebugLingoExec)) {
g_lingo->printCallStack(g_lingo->_pc);
printCallStack(_state->pc);
}
delete fp;
@ -380,10 +365,10 @@ void Lingo::popContext(bool aborting) {
}
bool Lingo::hasFrozenContext() {
if (g_lingo->_freezeContext)
if (_freezeContext)
return true;
Common::Array<CFrame *> &callstack = _vm->getCurrentWindow()->_callstack;
Common::Array<CFrame *> &callstack = _state->callstack;
for (uint i = 0; i < callstack.size(); i++) {
if (callstack[i]->retFreezeContext)
return true;
@ -1419,14 +1404,14 @@ void LC::c_le() {
void LC::c_jump() {
int jump = g_lingo->readInt();
g_lingo->_pc = g_lingo->_pc + jump - 2;
g_lingo->_state->pc = g_lingo->_state->pc + jump - 2;
}
void LC::c_jumpifz() {
int jump = g_lingo->readInt();
int test = g_lingo->pop().asInt();
if (test == 0) {
g_lingo->_pc = g_lingo->_pc + jump - 2;
g_lingo->_state->pc = g_lingo->_state->pc + jump - 2;
}
}
@ -1642,10 +1627,10 @@ void LC::call(const Symbol &funcSym, int nargs, bool allowRetVal) {
if (target.type != VOID) {
// Only need to update the me obj
// Pushing an entire stack frame is not necessary
Datum retMe = g_lingo->_currentMe;
g_lingo->_currentMe = target;
Datum retMe = g_lingo->_state->me;
g_lingo->_state->me = target;
(*funcSym.u.bltin)(nargs);
g_lingo->_currentMe = retMe;
g_lingo->_state->me = retMe;
} else {
(*funcSym.u.bltin)(nargs);
}
@ -1679,7 +1664,7 @@ void LC::call(const Symbol &funcSym, int nargs, bool allowRetVal) {
}
void LC::c_procret() {
Common::Array<CFrame *> &callstack = g_director->getCurrentWindow()->_callstack;
Common::Array<CFrame *> &callstack = g_lingo->_state->callstack;
if (callstack.size() == 0) {
warning("LC::c_procret(): Call stack underflow");

View File

@ -269,11 +269,11 @@ void Lingo::reloadOpenXLibs() {
void LM::m_new(int nargs) {
// This is usually overridden by a user-defined mNew
g_lingo->printSTUBWithArglist("m_new", nargs);
g_lingo->push(g_lingo->_currentMe);
g_lingo->push(g_lingo->_state->me);
}
void LM::m_dispose(int nargs) {
g_lingo->_currentMe.u.obj->dispose();
g_lingo->_state->me.u.obj->dispose();
}
/* ScriptContext */
@ -418,7 +418,7 @@ Common::String ScriptContext::formatFunctionList(const char *prefix) {
// Object array
void LM::m_get(int nargs) {
ScriptContext *me = static_cast<ScriptContext *>(g_lingo->_currentMe.u.obj);
ScriptContext *me = static_cast<ScriptContext *>(g_lingo->_state->me.u.obj);
Datum indexD = g_lingo->pop();
uint index = MAX(0, indexD.asInt());
if (me->_objArray.contains(index)) {
@ -429,7 +429,7 @@ void LM::m_get(int nargs) {
}
void LM::m_put(int nargs) {
ScriptContext *me = static_cast<ScriptContext *>(g_lingo->_currentMe.u.obj);
ScriptContext *me = static_cast<ScriptContext *>(g_lingo->_state->me.u.obj);
Datum value = g_lingo->pop();
Datum indexD = g_lingo->pop();
uint index = MAX(0, indexD.asInt());
@ -441,7 +441,7 @@ void LM::m_put(int nargs) {
void LM::m_perform(int nargs) {
// Lingo doesn't seem to bother cloning the object when
// mNew is called with mPerform
Datum d(g_lingo->_currentMe);
Datum d(g_lingo->_state->me);
AbstractObject *me = d.u.obj;
Datum methodName = g_lingo->_stack.remove_at(g_lingo->_stack.size() - nargs); // Take method name out of stack
Symbol funcSym = me->getMethod(*methodName.u.s);
@ -457,7 +457,7 @@ void LM::m_describe(int nargs) {
}
void LM::m_instanceRespondsTo(int nargs) {
AbstractObject *me = g_lingo->_currentMe.u.obj;
AbstractObject *me = g_lingo->_state->me.u.obj;
Datum d = g_lingo->pop();
Common::String methodName = d.asString();
@ -474,12 +474,12 @@ void LM::m_messageList(int nargs) {
}
void LM::m_name(int nargs) {
AbstractObject *me = g_lingo->_currentMe.u.obj;
AbstractObject *me = g_lingo->_state->me.u.obj;
g_lingo->push(me->getName());
}
void LM::m_respondsTo(int nargs) {
AbstractObject *me = g_lingo->_currentMe.u.obj;
AbstractObject *me = g_lingo->_state->me.u.obj;
Datum d = g_lingo->pop();
Common::String methodName = d.asString();
@ -580,12 +580,12 @@ bool Window::setField(int field, const Datum &value) {
}
void LM::m_close(int nargs) {
Window *me = static_cast<Window *>(g_lingo->_currentMe.u.obj);
Window *me = static_cast<Window *>(g_lingo->_state->me.u.obj);
me->setVisible(false);
}
void LM::m_forget(int nargs) {
Window *me = static_cast<Window *>(g_lingo->_currentMe.u.obj);
Window *me = static_cast<Window *>(g_lingo->_state->me.u.obj);
FArray *windowList = g_lingo->_windowList.u.farr;
uint i;
@ -613,7 +613,7 @@ void LM::m_forget(int nargs) {
}
void LM::m_open(int nargs) {
Window *me = static_cast<Window *>(g_lingo->_currentMe.u.obj);
Window *me = static_cast<Window *>(g_lingo->_state->me.u.obj);
me->setVisible(true);
}

View File

@ -152,12 +152,9 @@ MenuReference::MenuReference() {
Lingo::Lingo(DirectorEngine *vm) : _vm(vm) {
g_lingo = this;
_currentScript = nullptr;
_currentScriptContext = nullptr;
_state = nullptr;
_currentChannelId = -1;
_globalCounter = 0;
_pc = 0;
_freezeContext = false;
_abort = false;
_expectError = false;
@ -166,8 +163,6 @@ Lingo::Lingo(DirectorEngine *vm) : _vm(vm) {
_floatPrecision = 4;
_floatPrecisionFormat = "%.4f";
_localvars = nullptr;
//kTheEntities
_actorList.type = ARRAY;
_actorList.u.farr = new FArray;
@ -293,8 +288,8 @@ Symbol Lingo::getHandler(const Common::String &name) {
Symbol sym;
// local functions
if (_currentScriptContext && _currentScriptContext->_functionHandlers.contains(name))
return _currentScriptContext->_functionHandlers[name];
if (_state->context && _state->context->_functionHandlers.contains(name))
return _state->context->_functionHandlers[name];
sym = g_director->getCurrentMovie()->getHandler(name);
if (sym.type != VOIDSYM)
@ -366,7 +361,7 @@ void Lingo::printStack(const char *s, uint pc) {
Common::String Lingo::formatCallStack(uint pc) {
Common::String result;
Common::Array<CFrame *> &callstack = _vm->getCurrentWindow()->_callstack;
Common::Array<CFrame *> &callstack = _state->callstack;
if (callstack.size() == 0) {
result += Common::String("End of execution\n");
return result;
@ -402,26 +397,26 @@ void Lingo::printCallStack(uint pc) {
Common::String Lingo::formatFrame() {
Common::String result;
Common::Array<CFrame *> &callstack = _vm->getCurrentWindow()->_callstack;
Common::Array<CFrame *> &callstack = _state->callstack;
if (callstack.size() == 0) {
return Common::String("End of execution");
}
if (_currentScriptContext->_id)
result += Common::String::format("%d:", _currentScriptContext->_id);
if (_state->context->_id)
result += Common::String::format("%d:", _state->context->_id);
CFrame *frame = callstack[callstack.size() - 1];
if (frame->sp.type == VOIDSYM || !frame->sp.name)
result += "[unknown]";
else
result += frame->sp.name->c_str();
result += Common::String::format(" at [%5d]", _pc);
result += Common::String::format(" at [%5d]", _state->pc);
return result;
}
Common::String Lingo::formatCurrentInstruction() {
Common::String instr = decodeInstruction(_currentScript, _pc);
Common::String instr = decodeInstruction(_state->script, _state->pc);
if (instr.empty())
return instr;
return Common::String::format("[%5d]: %s", _pc, instr.c_str());
return Common::String::format("[%5d]: %s", _state->pc, instr.c_str());
}
Common::String Lingo::decodeInstruction(ScriptData *sd, uint pc, uint *newPc) {
@ -546,7 +541,7 @@ Common::String Lingo::formatFunctionBody(Symbol &sym) {
void Lingo::execute() {
uint localCounter = 0;
while (!_abort && !_freezeContext && _currentScript && (*_currentScript)[_pc] != STOP) {
while (!_abort && !_freezeContext && _state->script && (*_state->script)[_state->pc] != STOP) {
if (_globalCounter > 1000 && debugChannelSet(-1, kDebugFewFramesOnly)) {
warning("Lingo::execute(): Stopping due to debug few frames only");
_vm->getCurrentMovie()->getScore()->_playState = kPlayStopped;
@ -561,7 +556,7 @@ void Lingo::execute() {
break;
}
uint current = _pc;
uint current = _state->pc;
if (debugChannelSet(5, kDebugLingoExec))
printStack("Stack before: ", current);
@ -569,19 +564,19 @@ void Lingo::execute() {
if (debugChannelSet(9, kDebugLingoExec)) {
debug("Vars before");
printAllVars();
if (_currentMe.type == OBJECT)
debug("me: %s", _currentMe.asString(true).c_str());
if (_state->me.type == OBJECT)
debug("me: %s", _state->me.asString(true).c_str());
}
if (debugChannelSet(3, kDebugLingoExec)) {
Common::String instr = decodeInstruction(_currentScript, _pc);
Common::String instr = decodeInstruction(_state->script, _state->pc);
debugC(3, kDebugLingoExec, "[%5d]: %s", current, instr.c_str());
}
g_debugger->stepHook();
_pc++;
(*((*_currentScript)[_pc - 1]))();
_state->pc++;
(*((*_state->script)[_state->pc - 1]))();
if (debugChannelSet(5, kDebugLingoExec))
printStack("Stack after: ", current);
@ -594,15 +589,15 @@ void Lingo::execute() {
_globalCounter++;
localCounter++;
if (!_abort && _pc >= (*_currentScript).size()) {
warning("Lingo::execute(): Bad PC (%d)", _pc);
if (!_abort && _state->pc >= (*_state->script).size()) {
warning("Lingo::execute(): Bad PC (%d)", _state->pc);
break;
}
}
if (_abort || _vm->getCurrentMovie()->getScore()->_playState == kPlayStopped) {
// Clean up call stack
while (_vm->getCurrentWindow()->_callstack.size()) {
while (_state->callstack.size()) {
popContext(true);
}
}
@ -672,7 +667,7 @@ void Lingo::resetLingo() {
g_director->_wm->removeMenu();
while (_vm->getCurrentWindow()->_callstack.size()) {
while (_state->callstack.size()) {
popContext(true);
}
@ -1332,9 +1327,9 @@ void Lingo::executeImmediateScripts(Frame *frame) {
// From D5 only explicit event handlers are processed
// Before that you could specify commands which will be executed on mouse up
if (_vm->getVersion() < 500)
g_lingo->processEvent(kEventGeneric, kScoreScript, frame->_sprites[i]->_scriptId, i);
processEvent(kEventGeneric, kScoreScript, frame->_sprites[i]->_scriptId, i);
else
g_lingo->processEvent(kEventMouseUp, kScoreScript, frame->_sprites[i]->_scriptId, i);
processEvent(kEventMouseUp, kScoreScript, frame->_sprites[i]->_scriptId, i);
}
}
}
@ -1366,20 +1361,20 @@ void Lingo::executePerFrameHook(int frame, int subframe) {
void Lingo::cleanLocalVars() {
// Clean up current scope local variables and clean up memory
debugC(3, kDebugLingoExec, "cleanLocalVars: have %d vars", _localvars->size());
debugC(3, kDebugLingoExec, "cleanLocalVars: have %d vars", _state->localVars->size());
g_lingo->_localvars->clear();
delete g_lingo->_localvars;
_state->localVars->clear();
delete _state->localVars;
g_lingo->_localvars = nullptr;
_state->localVars = nullptr;
}
Common::String Lingo::formatAllVars() {
Common::String result;
result += Common::String(" Local vars:\n");
if (_localvars) {
for (DatumHash::iterator i = _localvars->begin(); i != _localvars->end(); ++i) {
if (_state->localVars) {
for (DatumHash::iterator i = _state->localVars->begin(); i != _state->localVars->end(); ++i) {
result += Common::String::format(" %s - [%s] %s\n", (*i)._key.c_str(), (*i)._value.type2str(), (*i)._value.asString(true).c_str());
}
} else {
@ -1387,8 +1382,8 @@ Common::String Lingo::formatAllVars() {
}
result += Common::String("\n");
if (_currentMe.type == OBJECT && _currentMe.u.obj->getObjType() & (kFactoryObj | kScriptObj)) {
ScriptContext *script = static_cast<ScriptContext *>(_currentMe.u.obj);
if (_state->me.type == OBJECT && _state->me.u.obj->getObjType() & (kFactoryObj | kScriptObj)) {
ScriptContext *script = static_cast<ScriptContext *>(_state->me.u.obj);
result += Common::String(" Instance/property vars: \n");
for (DatumHash::iterator i = script->_properties.begin(); i != script->_properties.end(); ++i) {
result += Common::String::format(" %s - [%s] %s\n", (*i)._key.c_str(), (*i)._value.type2str(), (*i)._value.asString(true).c_str());
@ -1409,7 +1404,7 @@ void Lingo::printAllVars() {
}
int Lingo::getInt(uint pc) {
return (int)READ_UINT32(&((*_currentScript)[pc]));
return (int)READ_UINT32(&((*_state->script)[pc]));
}
void Lingo::varAssign(const Datum &var, const Datum &value) {
@ -1417,13 +1412,13 @@ void Lingo::varAssign(const Datum &var, const Datum &value) {
case VARREF:
{
Common::String name = *var.u.s;
if (_localvars && _localvars->contains(name)) {
(*_localvars)[name] = value;
if (_state->localVars && _state->localVars->contains(name)) {
(*_state->localVars)[name] = value;
g_debugger->varWriteHook(name);
return;
}
if (_currentMe.type == OBJECT && _currentMe.u.obj->hasProp(name)) {
_currentMe.u.obj->setProp(name, value);
if (_state->me.type == OBJECT && _state->me.u.obj->hasProp(name)) {
_state->me.u.obj->setProp(name, value);
g_debugger->varWriteHook(name);
return;
}
@ -1441,8 +1436,8 @@ void Lingo::varAssign(const Datum &var, const Datum &value) {
case LOCALREF:
{
Common::String name = *var.u.s;
if (_localvars && _localvars->contains(name)) {
(*_localvars)[name] = value;
if (_state->localVars && _state->localVars->contains(name)) {
(*_state->localVars)[name] = value;
g_debugger->varWriteHook(name);
} else {
warning("varAssign: local variable %s not defined", name.c_str());
@ -1452,8 +1447,8 @@ void Lingo::varAssign(const Datum &var, const Datum &value) {
case PROPREF:
{
Common::String name = *var.u.s;
if (_currentMe.type == OBJECT && _currentMe.u.obj->hasProp(name)) {
_currentMe.u.obj->setProp(name, value);
if (_state->me.type == OBJECT && _state->me.u.obj->hasProp(name)) {
_state->me.u.obj->setProp(name, value);
g_debugger->varWriteHook(name);
} else {
warning("varAssign: property %s not defined", name.c_str());
@ -1536,11 +1531,11 @@ Datum Lingo::varFetch(const Datum &var, bool silent) {
Common::String name = *var.u.s;
g_debugger->varReadHook(name);
if (_localvars && _localvars->contains(name)) {
return (*_localvars)[name];
if (_state->localVars && _state->localVars->contains(name)) {
return (*_state->localVars)[name];
}
if (_currentMe.type == OBJECT && _currentMe.u.obj->hasProp(name)) {
return _currentMe.u.obj->getProp(name);
if (_state->me.type == OBJECT && _state->me.u.obj->hasProp(name)) {
return _state->me.u.obj->getProp(name);
}
if (_globalvars.contains(name)) {
return _globalvars[name];
@ -1566,8 +1561,8 @@ Datum Lingo::varFetch(const Datum &var, bool silent) {
{
Common::String name = *var.u.s;
g_debugger->varReadHook(name);
if (_localvars && _localvars->contains(name)) {
return (*_localvars)[name];
if (_state->localVars && _state->localVars->contains(name)) {
return (*_state->localVars)[name];
}
warning("varFetch: local variable %s not defined", name.c_str());
return result;
@ -1577,8 +1572,8 @@ Datum Lingo::varFetch(const Datum &var, bool silent) {
{
Common::String name = *var.u.s;
g_debugger->varReadHook(name);
if (_currentMe.type == OBJECT && _currentMe.u.obj->hasProp(name)) {
return _currentMe.u.obj->getProp(name);
if (_state->me.type == OBJECT && _state->me.u.obj->hasProp(name)) {
return _state->me.u.obj->getProp(name);
}
warning("varFetch: property %s not defined", name.c_str());
return result;

View File

@ -291,6 +291,15 @@ struct LingoArchive {
void addNamesV4(Common::SeekableReadStreamEndian &stream);
};
struct LingoState {
Common::Array<CFrame *> callstack;
uint pc = 0;
ScriptData *script = nullptr;
ScriptContext *context = nullptr;
DatumHash *localVars = nullptr;
Datum me;
};
class Lingo {
public:
@ -348,8 +357,7 @@ public:
public:
void execute();
void loadStateFromWindow();
void saveStateToWindow();
void switchStateFromWindow();
void pushContext(const Symbol funcSym, bool allowRetVal, Datum defaultRetVal);
void popContext(bool aborting = false);
bool hasFrozenContext();
@ -366,14 +374,14 @@ public:
Common::String formatAllVars();
void printAllVars();
inst readInst() { return getInst(_pc++); }
inst getInst(uint pc) { return (*_currentScript)[pc]; }
int readInt() { return getInt(_pc++); }
inst readInst() { return getInst(_state->pc++); }
inst getInst(uint pc) { return (*_state->script)[pc]; }
int readInt() { return getInt(_state->pc++); }
int getInt(uint pc);
double readFloat() { double d = getFloat(_pc); _pc += calcCodeAlignment(sizeof(double)); return d; }
double getFloat(uint pc) { return *(double *)(&((*_currentScript)[pc])); }
char *readString() { char *s = getString(_pc); _pc += calcStringAlignment(s); return s; }
char *getString(uint pc) { return (char *)(&((*_currentScript)[pc])); }
double readFloat() { double d = getFloat(_state->pc); _state->pc += calcCodeAlignment(sizeof(double)); return d; }
double getFloat(uint pc) { return *(double *)(&((*_state->script)[_state->pc])); }
char *readString() { char *s = getString(_state->pc); _state->pc += calcStringAlignment(s); return s; }
char *getString(uint pc) { return (char *)(&((*_state->script)[_state->pc])); }
void pushVoid();
@ -436,11 +444,9 @@ private:
public:
LingoCompiler *_compiler;
LingoState *_state;
int _currentChannelId;
ScriptContext *_currentScriptContext;
ScriptData *_currentScript;
Datum _currentMe;
bool _freezeContext;
bool _abort;
@ -474,7 +480,6 @@ public:
Common::HashMap<Common::String, Audio::AudioStream *> _audioAliases;
DatumHash _globalvars;
DatumHash *_localvars;
FuncHash _functions;
@ -482,7 +487,6 @@ public:
Common::HashMap<int, LingoV4TheEntity *> _lingoV4TheEntity;
uint _globalCounter;
uint _pc;
StackData _stack;

View File

@ -89,7 +89,7 @@ AiffXObject::AiffXObject(ObjectType ObjectType) :Object<AiffXObject>("AiffXObj")
void AiffXObj::m_new(int nargs) {
g_lingo->printSTUBWithArglist("AiffXObj::new", nargs);
g_lingo->push(g_lingo->_currentMe);
g_lingo->push(g_lingo->_state->me);
}
void AiffXObj::m_duration(int nargs) {

View File

@ -125,7 +125,7 @@ AppleCDXObject::AppleCDXObject(ObjectType ObjectType) :Object<AppleCDXObject>("A
}
void AppleCDXObj::m_new(int nargs) {
g_lingo->push(g_lingo->_currentMe);
g_lingo->push(g_lingo->_state->me);
}
void AppleCDXObj::m_service(int nargs) {

View File

@ -85,7 +85,7 @@ void AskUser::m_new(int nargs) {
warning("AskUser::m_new: expected 0 arguments");
g_lingo->dropStack(nargs);
}
g_lingo->push(g_lingo->_currentMe);
g_lingo->push(g_lingo->_state->me);
}
void AskUser::m_ask(int nargs) {

View File

@ -77,7 +77,7 @@ BarakeObject::BarakeObject(ObjectType ObjectType) :Object<BarakeObject>("BarakeO
}
void BarakeObj::m_new(int nargs) {
g_lingo->push(g_lingo->_currentMe);
g_lingo->push(g_lingo->_state->me);
}
void BarakeObj::m_clear(int nargs) {

View File

@ -234,7 +234,7 @@ void CDROMXObj::m_new(int nargs) {
g_director->_system->getAudioCDManager()->open();
g_lingo->printSTUBWithArglist("CDROMXObj::m_new", nargs);
g_lingo->dropStack(nargs);
g_lingo->push(g_lingo->_currentMe);
g_lingo->push(g_lingo->_state->me);
}
// Returns the name of the XObj
@ -243,7 +243,7 @@ void CDROMXObj::m_name(int nargs) {
}
void CDROMXObj::m_play(int nargs) {
CDROMXObject *me = static_cast<CDROMXObject *>(g_lingo->_currentMe.u.obj);
CDROMXObject *me = static_cast<CDROMXObject *>(g_lingo->_state->me.u.obj);
// This is a request to play the current track from the start,
// which we can't do if there's no track information.
@ -255,7 +255,7 @@ void CDROMXObj::m_play(int nargs) {
}
void CDROMXObj::m_playTrack(int nargs) {
CDROMXObject *me = static_cast<CDROMXObject *>(g_lingo->_currentMe.u.obj);
CDROMXObject *me = static_cast<CDROMXObject *>(g_lingo->_state->me.u.obj);
int track = g_lingo->pop().asInt();
g_director->_system->getAudioCDManager()->play(track, -1, 0, 0);
@ -264,7 +264,7 @@ void CDROMXObj::m_playTrack(int nargs) {
// Name format is "TRACK NN", with one-digit tracks padded with a leading space
void CDROMXObj::m_playName(int nargs) {
CDROMXObject *me = static_cast<CDROMXObject *>(g_lingo->_currentMe.u.obj);
CDROMXObject *me = static_cast<CDROMXObject *>(g_lingo->_state->me.u.obj);
Common::String track = g_lingo->pop().asString();
if (track.size() < 8) {
@ -315,14 +315,14 @@ void CDROMXObj::m_askPlay(int nargs) {
}
void CDROMXObj::m_stepFwd(int nargs) {
CDROMXObject *me = static_cast<CDROMXObject *>(g_lingo->_currentMe.u.obj);
CDROMXObject *me = static_cast<CDROMXObject *>(g_lingo->_state->me.u.obj);
g_director->_system->getAudioCDManager()->play(me->_cdda_status.track + 1, -1, 0, 0);
me->_cdda_status = g_director->_system->getAudioCDManager()->getStatus();
}
void CDROMXObj::m_stepBwd(int nargs) {
CDROMXObject *me = static_cast<CDROMXObject *>(g_lingo->_currentMe.u.obj);
CDROMXObject *me = static_cast<CDROMXObject *>(g_lingo->_state->me.u.obj);
int track = me->_cdda_status.track - 1;
if (track < 1)
@ -333,7 +333,7 @@ void CDROMXObj::m_stepBwd(int nargs) {
}
void CDROMXObj::m_pause(int nargs) {
CDROMXObject *me = static_cast<CDROMXObject *>(g_lingo->_currentMe.u.obj);
CDROMXObject *me = static_cast<CDROMXObject *>(g_lingo->_state->me.u.obj);
// Leaves a trace of the current position so we can resume from it
me->_cdda_status = g_director->_system->getAudioCDManager()->getStatus();
@ -342,7 +342,7 @@ void CDROMXObj::m_pause(int nargs) {
}
void CDROMXObj::m_continue(int nargs) {
CDROMXObject *me = static_cast<CDROMXObject *>(g_lingo->_currentMe.u.obj);
CDROMXObject *me = static_cast<CDROMXObject *>(g_lingo->_state->me.u.obj);
// Can only resume if there's data to resume from
if (me->_cdda_status.track == 0)
@ -353,14 +353,14 @@ void CDROMXObj::m_continue(int nargs) {
}
void CDROMXObj::m_stop(int nargs) {
CDROMXObject *me = static_cast<CDROMXObject *>(g_lingo->_currentMe.u.obj);
CDROMXObject *me = static_cast<CDROMXObject *>(g_lingo->_state->me.u.obj);
g_director->_system->getAudioCDManager()->stop();
me->_cdda_status = g_director->_system->getAudioCDManager()->getStatus();
}
void CDROMXObj::m_stopTrack(int nargs) {
CDROMXObject *me = static_cast<CDROMXObject *>(g_lingo->_currentMe.u.obj);
CDROMXObject *me = static_cast<CDROMXObject *>(g_lingo->_state->me.u.obj);
Datum track = g_lingo->pop();
AudioCDManager::Status status = g_director->_system->getAudioCDManager()->getStatus();
@ -387,7 +387,7 @@ void CDROMXObj::m_stopAbsTime(int nargs) {
}
void CDROMXObj::m_removeStop(int nargs) {
CDROMXObject *me = static_cast<CDROMXObject *>(g_lingo->_currentMe.u.obj);
CDROMXObject *me = static_cast<CDROMXObject *>(g_lingo->_state->me.u.obj);
Datum track = g_lingo->pop();
AudioCDManager::Status status = g_director->_system->getAudioCDManager()->getStatus();
@ -459,7 +459,7 @@ void CDROMXObj::m_currentFormat(int nargs) {
}
void CDROMXObj::m_currentTrack(int nargs) {
CDROMXObject *me = static_cast<CDROMXObject *>(g_lingo->_currentMe.u.obj);
CDROMXObject *me = static_cast<CDROMXObject *>(g_lingo->_state->me.u.obj);
g_lingo->push(Datum(me->_cdda_status.track));
}

View File

@ -114,7 +114,7 @@ EdnoxObject::EdnoxObject(ObjectType ObjectType) :Object<EdnoxObject>("Ednox") {
}
void Ednox::m_new(int nargs) {
g_lingo->push(g_lingo->_currentMe);
g_lingo->push(g_lingo->_state->me);
}
void Ednox::m_dispose(int nargs) {

View File

@ -195,7 +195,7 @@ void FileIO::saveFileError() {
}
void FileIO::m_new(int nargs) {
FileObject *me = static_cast<FileObject *>(g_lingo->_currentMe.u.obj);
FileObject *me = static_cast<FileObject *>(g_lingo->_state->me.u.obj);
Datum d2 = g_lingo->pop();
Datum d1 = g_lingo->pop();
@ -284,13 +284,13 @@ void FileIO::m_new(int nargs) {
me->_filename = new Common::String(filename);
g_lingo->push(g_lingo->_currentMe);
g_lingo->push(g_lingo->_state->me);
}
// Read
void FileIO::m_readChar(int nargs) {
FileObject *me = static_cast<FileObject *>(g_lingo->_currentMe.u.obj);
FileObject *me = static_cast<FileObject *>(g_lingo->_state->me.u.obj);
if (!me->_inStream || me->_inStream->eos() || me->_inStream->err()) {
g_lingo->push(Datum(kErrorEOF));
@ -334,7 +334,7 @@ bool FileIO::charInMatchString(char ch, const Common::String &matchString) {
}
void FileIO::m_readToken(int nargs) {
FileObject *me = static_cast<FileObject *>(g_lingo->_currentMe.u.obj);
FileObject *me = static_cast<FileObject *>(g_lingo->_state->me.u.obj);
Datum d2 = g_lingo->pop();
Datum d1 = g_lingo->pop();
@ -378,7 +378,7 @@ void FileIO::m_readToken(int nargs) {
}
void FileIO::m_readFile(int nargs) {
FileObject *me = static_cast<FileObject *>(g_lingo->_currentMe.u.obj);
FileObject *me = static_cast<FileObject *>(g_lingo->_state->me.u.obj);
if (!me->_inStream || me->_inStream->eos() || me->_inStream->err()) {
g_lingo->push(Datum(""));
@ -398,7 +398,7 @@ void FileIO::m_readFile(int nargs) {
// Write
void FileIO::m_writeChar(int nargs) {
FileObject *me = static_cast<FileObject *>(g_lingo->_currentMe.u.obj);
FileObject *me = static_cast<FileObject *>(g_lingo->_state->me.u.obj);
Datum d = g_lingo->pop();
if (!me->_outStream) {
@ -411,7 +411,7 @@ void FileIO::m_writeChar(int nargs) {
}
void FileIO::m_writeString(int nargs) {
FileObject *me = static_cast<FileObject *>(g_lingo->_currentMe.u.obj);
FileObject *me = static_cast<FileObject *>(g_lingo->_state->me.u.obj);
Datum d = g_lingo->pop();
if (!me->_outStream) {
@ -438,7 +438,7 @@ void FileIO::m_setFinderInfo(int nargs) {
}
void FileIO::m_getPosition(int nargs) {
FileObject *me = static_cast<FileObject *>(g_lingo->_currentMe.u.obj);
FileObject *me = static_cast<FileObject *>(g_lingo->_state->me.u.obj);
if (me->_inStream) {
g_lingo->push(Datum((int)me->_inStream->pos()));
@ -451,7 +451,7 @@ void FileIO::m_getPosition(int nargs) {
}
void FileIO::m_setPosition(int nargs) {
FileObject *me = static_cast<FileObject *>(g_lingo->_currentMe.u.obj);
FileObject *me = static_cast<FileObject *>(g_lingo->_state->me.u.obj);
Datum d = g_lingo->pop();
int pos = d.asInt();
@ -478,7 +478,7 @@ void FileIO::m_setPosition(int nargs) {
}
void FileIO::m_getLength(int nargs) {
FileObject *me = static_cast<FileObject *>(g_lingo->_currentMe.u.obj);
FileObject *me = static_cast<FileObject *>(g_lingo->_state->me.u.obj);
if (me->_inStream) {
g_lingo->push(Datum((int)me->_inStream->size()));
@ -491,7 +491,7 @@ void FileIO::m_getLength(int nargs) {
}
void FileIO::m_fileName(int nargs) {
FileObject *me = static_cast<FileObject *>(g_lingo->_currentMe.u.obj);
FileObject *me = static_cast<FileObject *>(g_lingo->_state->me.u.obj);
if (me->_filename) {
Common::String prefix = g_director->getTargetName() + '-';
@ -522,7 +522,7 @@ void FileIO::m_status(int nargs) {
// Other
void FileIO::m_delete(int nargs) {
FileObject *me = static_cast<FileObject *>(g_lingo->_currentMe.u.obj);
FileObject *me = static_cast<FileObject *>(g_lingo->_state->me.u.obj);
if (me->_filename) {
Common::String filename = *me->_filename;

View File

@ -88,7 +88,7 @@ FlushXObject::FlushXObject(ObjectType ObjectType) :Object<FlushXObject>("FlushXO
}
void FlushXObj::m_new(int nargs) {
g_lingo->push(g_lingo->_currentMe);
g_lingo->push(g_lingo->_state->me);
}
void FlushXObj::m_clearMask(int nargs) {

View File

@ -84,7 +84,7 @@ ProductIdXObject::ProductIdXObject(ObjectType ObjectType) :Object<ProductIdXObje
void GpidXObj::m_new(int nargs) {
g_lingo->printSTUBWithArglist("gpid::new", nargs);
g_lingo->push(g_lingo->_currentMe);
g_lingo->push(g_lingo->_state->me);
}
} // End of namespace Director

View File

@ -110,7 +110,7 @@ JITDraw3XObject::JITDraw3XObject(ObjectType ObjectType) :Object<JITDraw3XObject>
}
void JITDraw3XObj::m_new(int nargs) {
g_lingo->push(g_lingo->_currentMe);
g_lingo->push(g_lingo->_state->me);
}
void JITDraw3XObj::m_dispose(int nargs) {

View File

@ -87,7 +87,7 @@ JourneyWareXINIXObject::JourneyWareXINIXObject(ObjectType ObjectType) :Object<Jo
void JourneyWareXINIXObj::m_new(int nargs) {
g_lingo->printSTUBWithArglist("JWXIni::new", nargs);
g_lingo->push(g_lingo->_currentMe);
g_lingo->push(g_lingo->_state->me);
}
void JourneyWareXINIXObj::m_GetPrivateProfileInt(int nargs) {

View File

@ -75,16 +75,16 @@ LabelDrvXObject::LabelDrvXObject(ObjectType ObjectType) :Object<LabelDrvXObject>
}
void LabelDrvXObj::m_new(int nargs) {
LabelDrvXObject *me = static_cast<LabelDrvXObject *>(g_lingo->_currentMe.u.obj);
LabelDrvXObject *me = static_cast<LabelDrvXObject *>(g_lingo->_state->me.u.obj);
Common::Rect rect;
me->_range = "C";
g_lingo->push(g_lingo->_currentMe);
g_lingo->push(g_lingo->_state->me);
}
void LabelDrvXObj::m_setRange(int nargs) {
LabelDrvXObject *me = static_cast<LabelDrvXObject *>(g_lingo->_currentMe.u.obj);
LabelDrvXObject *me = static_cast<LabelDrvXObject *>(g_lingo->_state->me.u.obj);
Datum d2 = g_lingo->pop();
Datum d1 = g_lingo->pop();
@ -96,7 +96,7 @@ void LabelDrvXObj::m_setRange(int nargs) {
}
void LabelDrvXObj::m_getDrive(int nargs) {
LabelDrvXObject *me = static_cast<LabelDrvXObject *>(g_lingo->_currentMe.u.obj);
LabelDrvXObject *me = static_cast<LabelDrvXObject *>(g_lingo->_state->me.u.obj);
Datum d1 = g_lingo->pop();

View File

@ -91,7 +91,7 @@ MemoryXObject::MemoryXObject(ObjectType ObjectType) :Object<MemoryXObject>("Memo
}
void MemoryXObj::m_new(int nargs) {
g_lingo->push(g_lingo->_currentMe);
g_lingo->push(g_lingo->_state->me);
}
void MemoryXObj::m_clear(int nargs) {

View File

@ -101,7 +101,7 @@ MiscXObject::MiscXObject(ObjectType ObjectType) :Object<MiscXObject>("MiscX") {
}
void MiscX::m_new(int nargs) {
g_lingo->push(g_lingo->_currentMe);
g_lingo->push(g_lingo->_state->me);
}
void MiscX::m_bootName(int nargs) {

View File

@ -106,12 +106,12 @@ MoovXObject::~MoovXObject() {
}
void MoovXObj::m_new(int nargs) {
g_lingo->push(g_lingo->_currentMe);
g_lingo->push(g_lingo->_state->me);
}
void MoovXObj::m_dispose(int nargs) {
debug(5, "MoovXObj::m_dispose");
MoovXObject *me = static_cast<MoovXObject *>(g_lingo->_currentMe.u.obj);
MoovXObject *me = static_cast<MoovXObject *>(g_lingo->_state->me.u.obj);
if (me->_video) {
delete me->_video;
me->_video = nullptr;
@ -130,14 +130,14 @@ void MoovXObj::m_movieInit(int nargs) {
void MoovXObj::m_movieKill(int nargs) {
debug(5, "MoovXObj::m_movieKill");
MoovXObject *me = static_cast<MoovXObject *>(g_lingo->_currentMe.u.obj);
MoovXObject *me = static_cast<MoovXObject *>(g_lingo->_state->me.u.obj);
if (me->_video)
me->_video->stop();
}
void MoovXObj::m_fondler(int nargs) {
MoovXObject *me = static_cast<MoovXObject *>(g_lingo->_currentMe.u.obj);
MoovXObject *me = static_cast<MoovXObject *>(g_lingo->_state->me.u.obj);
debug(10, "MoovXObj::m_fondler");
Graphics::Surface const *frame;
@ -152,7 +152,7 @@ void MoovXObj::m_fondler(int nargs) {
}
void MoovXObj::m_playMovie(int nargs) {
MoovXObject *me = static_cast<MoovXObject *>(g_lingo->_currentMe.u.obj);
MoovXObject *me = static_cast<MoovXObject *>(g_lingo->_state->me.u.obj);
me->_y = g_lingo->pop().asInt();
me->_x = g_lingo->pop().asInt();
@ -189,7 +189,7 @@ void MoovXObj::m_stopMovie(int nargs) {
}
void MoovXObj::m_movieDone(int nargs) {
MoovXObject *me = static_cast<MoovXObject *>(g_lingo->_currentMe.u.obj);
MoovXObject *me = static_cast<MoovXObject *>(g_lingo->_state->me.u.obj);
debug(10, "MoovXObj::m_movieDone");
bool result = (me->_video && !me->_video->endOfVideo());
g_lingo->push(result);

View File

@ -72,7 +72,7 @@ void MoveMouseXObj::m_new(int nargs) {
warning("MoveMouse::m_new: expected 0 arguments");
g_lingo->dropStack(nargs);
}
g_lingo->push(g_lingo->_currentMe);
g_lingo->push(g_lingo->_state->me);
}
void MoveMouseXObj::m_setMouseLoc(int nargs) {

View File

@ -131,7 +131,7 @@ MovieUtilsXObject::MovieUtilsXObject(ObjectType ObjectType) :Object<MovieUtilsXO
void MovUtilsXObj::m_new(int nargs) {
g_lingo->printSTUBWithArglist("MovUtilsXObj::new", nargs);
g_lingo->push(g_lingo->_currentMe);
g_lingo->push(g_lingo->_state->me);
}
} // End of namespace Director

View File

@ -138,7 +138,7 @@ OrthoPlayXObject::OrthoPlayXObject(ObjectType ObjectType) :Object<OrthoPlayXObje
}
void OrthoPlayXObj::m_new(int nargs) {
g_lingo->push(g_lingo->_currentMe);
g_lingo->push(g_lingo->_state->me);
}
void OrthoPlayXObj::m_setSerialPort(int nargs) {

View File

@ -79,7 +79,7 @@ PalXObject::PalXObject(ObjectType ObjectType) :Object<PalXObject>("PalXObj") {
}
void PalXObj::m_new(int nargs) {
PalXObject *me = static_cast<PalXObject *>(g_lingo->_currentMe.u.obj);
PalXObject *me = static_cast<PalXObject *>(g_lingo->_state->me.u.obj);
Common::Rect rect;
rect.bottom = g_lingo->pop().asInt();
@ -88,7 +88,7 @@ void PalXObj::m_new(int nargs) {
rect.left = g_lingo->pop().asInt();
me->_stageWindowCoordinates = rect;
g_lingo->push(g_lingo->_currentMe);
g_lingo->push(g_lingo->_state->me);
}
void PalXObj::m_patchIt(int nargs) {

View File

@ -148,7 +148,7 @@ PopUpMenuXObject::PopUpMenuXObject(ObjectType ObjectType) :Object<PopUpMenuXObje
void PopUpMenuXObj::m_new(int nargs) {
g_lingo->printSTUBWithArglist("PopUpMenuXObj::m_new", nargs);
g_lingo->dropStack(nargs);
g_lingo->push(g_lingo->_currentMe);
g_lingo->push(g_lingo->_state->me);
}
void PopUpMenuXObj::m_appendMenu(int nargs) {

View File

@ -79,7 +79,7 @@ SerialPortXObject::SerialPortXObject(ObjectType ObjectType) :Object<SerialPortXO
void SerialPortXObj::m_new(int nargs) {
g_lingo->printSTUBWithArglist("SerialPortXObj::m_new", nargs);
g_lingo->dropStack(nargs);
g_lingo->push(g_lingo->_currentMe);
g_lingo->push(g_lingo->_state->me);
}
void SerialPortXObj::m_getPortNum(int nargs) {

View File

@ -104,7 +104,7 @@ void SoundJam::m_new(int nargs) {
return;
}
g_lingo->push(g_lingo->_currentMe);
g_lingo->push(g_lingo->_state->me);
}
void SoundJam::m_defineFileSound(int nargs) {
@ -114,7 +114,7 @@ void SoundJam::m_defineFileSound(int nargs) {
}
void SoundJam::m_defineCastSound(int nargs) {
SoundJamObject *me = static_cast<SoundJamObject *>(g_lingo->_currentMe.u.obj);
SoundJamObject *me = static_cast<SoundJamObject *>(g_lingo->_state->me.u.obj);
/* Datum numberOfBeats = */ g_lingo->pop();
CastMemberID castMemberNumber = g_lingo->pop().asMemberID();
@ -129,7 +129,7 @@ void SoundJam::m_defineCastSound(int nargs) {
}
void SoundJam::m_undefineSound(int nargs) {
SoundJamObject *me = static_cast<SoundJamObject *>(g_lingo->_currentMe.u.obj);
SoundJamObject *me = static_cast<SoundJamObject *>(g_lingo->_state->me.u.obj);
int soundID = g_lingo->pop().asInt();
if (soundID < 0) {
@ -160,7 +160,7 @@ void SoundJam::m_startSound(int nargs) {
}
void SoundJam::m_switchNew(int nargs) {
SoundJamObject *me = static_cast<SoundJamObject *>(g_lingo->_currentMe.u.obj);
SoundJamObject *me = static_cast<SoundJamObject *>(g_lingo->_state->me.u.obj);
int soundID = g_lingo->pop().asInt();
if (!me->_soundMap.contains(soundID)) {

View File

@ -156,7 +156,7 @@ void SpaceMgr::m_new(int nargs) {
warning("SpaceMgr::m_new: expected 0 arguments");
g_lingo->dropStack(nargs);
}
g_lingo->push(g_lingo->_currentMe);
g_lingo->push(g_lingo->_state->me);
}
void SpaceMgr::m_dispose(int nargs) {
@ -202,7 +202,7 @@ void SpaceMgr::m_checkForDups(int nargs) {
return;
}
SpaceMgrXObject *me = static_cast<SpaceMgrXObject *>(g_lingo->_currentMe.u.obj);
SpaceMgrXObject *me = static_cast<SpaceMgrXObject *>(g_lingo->_state->me.u.obj);
me->_checkForDups = (arg.u.s->c_str()[0] == 't') || (arg.u.s->c_str()[0] == 'T');
g_lingo->push(Datum(0));
@ -221,7 +221,7 @@ void SpaceMgr::m_parseText(int nargs) {
g_lingo->push(Datum(0));
return;
}
SpaceMgrXObject *me = static_cast<SpaceMgrXObject *>(g_lingo->_currentMe.u.obj);
SpaceMgrXObject *me = static_cast<SpaceMgrXObject *>(g_lingo->_state->me.u.obj);
Common::String result = *text.u.s;
Common::String curSpaceCollection;
@ -310,7 +310,7 @@ void SpaceMgr::m_getCurData(int nargs) {
warning("SpaceMgr::m_getCurData: expected 0 arguments");
g_lingo->dropStack(nargs);
}
SpaceMgrXObject *me = static_cast<SpaceMgrXObject *>(g_lingo->_currentMe.u.obj);
SpaceMgrXObject *me = static_cast<SpaceMgrXObject *>(g_lingo->_state->me.u.obj);
Common::String result;
if (me->_spaceCollections.contains(me->_curSpaceCollection)) {
result += "SPACECOLLECTION " + me->_curSpaceCollection;
@ -351,7 +351,7 @@ void SpaceMgr::m_setCurData(int nargs) {
g_lingo->push(Datum(0));
return;
}
SpaceMgrXObject *me = static_cast<SpaceMgrXObject *>(g_lingo->_currentMe.u.obj);
SpaceMgrXObject *me = static_cast<SpaceMgrXObject *>(g_lingo->_state->me.u.obj);
g_lingo->printSTUBWithArglist("SpaceMgr::m_setCurData", nargs);
Datum view = g_lingo->pop();
Datum node = g_lingo->pop();
@ -391,7 +391,7 @@ void SpaceMgr::m_setCurSpaceCollection(int nargs) {
g_lingo->push(Datum(0));
return;
}
SpaceMgrXObject *me = static_cast<SpaceMgrXObject *>(g_lingo->_currentMe.u.obj);
SpaceMgrXObject *me = static_cast<SpaceMgrXObject *>(g_lingo->_state->me.u.obj);
Datum spaceCollection = g_lingo->pop();
if (spaceCollection.type != STRING) {
warning("SpaceMgr::m_setCurSpaceCollection: expected spaceCollection to be a string, not %s", spaceCollection.type2str());
@ -410,7 +410,7 @@ void SpaceMgr::m_getCurSpaceCollection(int nargs) {
warning("SpaceMgr::m_getCurSpaceCollection: expected 0 arguments");
g_lingo->dropStack(nargs);
}
SpaceMgrXObject *me = static_cast<SpaceMgrXObject *>(g_lingo->_currentMe.u.obj);
SpaceMgrXObject *me = static_cast<SpaceMgrXObject *>(g_lingo->_state->me.u.obj);
Common::String result;
if (!me->_curSpaceCollection.empty()) {
if (me->_spaceCollections.contains(me->_curSpaceCollection)) {
@ -447,7 +447,7 @@ void SpaceMgr::m_setCurSpace(int nargs) {
g_lingo->push(Datum(0));
return;
}
SpaceMgrXObject *me = static_cast<SpaceMgrXObject *>(g_lingo->_currentMe.u.obj);
SpaceMgrXObject *me = static_cast<SpaceMgrXObject *>(g_lingo->_state->me.u.obj);
Datum space = g_lingo->pop();
if (space.type != STRING) {
warning("SpaceMgr::m_setCurSpace: expected space to be a string, not %s", space.type2str());
@ -466,7 +466,7 @@ void SpaceMgr::m_getCurSpace(int nargs) {
warning("SpaceMgr::m_getCurSpace: expected 0 arguments");
g_lingo->dropStack(nargs);
}
SpaceMgrXObject *me = static_cast<SpaceMgrXObject *>(g_lingo->_currentMe.u.obj);
SpaceMgrXObject *me = static_cast<SpaceMgrXObject *>(g_lingo->_state->me.u.obj);
Common::String result;
if (!me->_curSpaceCollection.empty()) {
if (me->_spaceCollections.contains(me->_curSpaceCollection)) {
@ -506,7 +506,7 @@ void SpaceMgr::m_setCurNode(int nargs) {
g_lingo->push(Datum(0));
return;
}
SpaceMgrXObject *me = static_cast<SpaceMgrXObject *>(g_lingo->_currentMe.u.obj);
SpaceMgrXObject *me = static_cast<SpaceMgrXObject *>(g_lingo->_state->me.u.obj);
Datum node = g_lingo->pop();
if (node.type != STRING) {
warning("SpaceMgr::m_setCurNode: expected node to be a string, not %s", node.type2str());
@ -525,7 +525,7 @@ void SpaceMgr::m_getCurNode(int nargs) {
warning("SpaceMgr::m_getCurNode: expected 0 arguments");
g_lingo->dropStack(nargs);
}
SpaceMgrXObject *me = static_cast<SpaceMgrXObject *>(g_lingo->_currentMe.u.obj);
SpaceMgrXObject *me = static_cast<SpaceMgrXObject *>(g_lingo->_state->me.u.obj);
Common::String result;
if (!me->_curView.empty()) {
if (me->_spaceCollections.contains(me->_curSpaceCollection)) {
@ -567,7 +567,7 @@ void SpaceMgr::m_setCurView(int nargs) {
g_lingo->push(Datum(0));
return;
}
SpaceMgrXObject *me = static_cast<SpaceMgrXObject *>(g_lingo->_currentMe.u.obj);
SpaceMgrXObject *me = static_cast<SpaceMgrXObject *>(g_lingo->_state->me.u.obj);
Datum view = g_lingo->pop();
if (view.type != STRING) {
warning("SpaceMgr::m_setCurView: expected view to be a string, not %s", view.type2str());
@ -586,7 +586,7 @@ void SpaceMgr::m_getCurView(int nargs) {
warning("SpaceMgr::m_getCurView: expected 0 arguments");
g_lingo->dropStack(nargs);
}
SpaceMgrXObject *me = static_cast<SpaceMgrXObject *>(g_lingo->_currentMe.u.obj);
SpaceMgrXObject *me = static_cast<SpaceMgrXObject *>(g_lingo->_state->me.u.obj);
Common::String result;
if (!me->_curView.empty()) {
if (me->_spaceCollections.contains(me->_curSpaceCollection)) {

View File

@ -166,7 +166,7 @@ VideodiscXObject::VideodiscXObject(ObjectType ObjectType) :Object<VideodiscXObje
void VideodiscXObj::m_new(int nargs) {
g_lingo->printSTUBWithArglist("VideodiscXObj::m_new", nargs);
g_lingo->dropStack(nargs);
g_lingo->push(g_lingo->_currentMe);
g_lingo->push(g_lingo->_state->me);
}
void VideodiscXObj::m_name(int nargs) {

View File

@ -73,7 +73,7 @@ WidgetXObject::WidgetXObject(ObjectType ObjectType) :Object<WidgetXObject>("Widg
}
void WidgetXObj::m_new(int nargs) {
g_lingo->push(g_lingo->_currentMe);
g_lingo->push(g_lingo->_state->me);
}
void WidgetXObj::m_dispose(int nargs) {

View File

@ -260,7 +260,7 @@ RearWindowXObject::RearWindowXObject(ObjectType ObjectType) :Object<RearWindowXO
void RearWindowXObj::m_new(int nargs) {
Datum d1 = g_lingo->pop();
g_lingo->push(g_lingo->_currentMe);
g_lingo->push(g_lingo->_state->me);
}
void RearWindowXObj::m_getMemoryNeeded(int nargs) {

View File

@ -471,7 +471,7 @@ void Score::update() {
debugC(1, kDebugLoading, "****************************** Current frame: %d, time: %d", _currentFrame, g_system->getMillis(false));
g_debugger->frameHook();
uint initialCallStackSize = _window->_callstack.size();
uint initialCallStackSize = g_lingo->_state->callstack.size();
_lingo->executeImmediateScripts(_frames[_currentFrame]);
@ -508,7 +508,7 @@ void Score::update() {
// If we have more call stack frames than we started with, then we have a newly
// added frozen context. We'll deal with that later.
if (_window->_callstack.size() == initialCallStackSize) {
if (g_lingo->_state->callstack.size() == initialCallStackSize) {
// We may have a frozen Lingo context from func_goto.
// Now that we've entered a new frame, let's unfreeze that context.
if (g_lingo->_freezeContext) {

View File

@ -48,6 +48,7 @@ Window::Window(int id, bool scrollable, bool resizable, bool editable, Graphics:
_stageColor = _wm->_colorBlack;
_puppetTransition = nullptr;
_soundManager = new DirectorSound(this);
_lingoState = new LingoState;
_currentMovie = nullptr;
_mainArchive = nullptr;
@ -60,15 +61,10 @@ Window::Window(int id, bool scrollable, bool resizable, bool editable, Graphics:
_windowType = -1;
_titleVisible = true;
updateBorderType();
_retPC = 0;
_retScript = nullptr;
_retContext = nullptr;
_retFreezeContext = false;
_retLocalVars = nullptr;
}
Window::~Window() {
delete _lingoState;
delete _soundManager;
delete _currentMovie;
if (_puppetTransition)

View File

@ -40,6 +40,7 @@ namespace Director {
class Channel;
class MacArchive;
struct MacShape;
struct LingoState;
struct TransParams {
TransitionType type;
@ -139,6 +140,7 @@ public:
int getWindowType() const { return _windowType; }
void setTitleVisible(bool titleVisible) { _titleVisible = titleVisible; updateBorderType(); };
bool isTitleVisible() { return _titleVisible; };
LingoState *getLingoState() { return _lingoState; };
Datum getStageRect();
void updateBorderType();
@ -191,20 +193,12 @@ public:
Common::List<MovieReference> _movieStack;
bool _newMovieStarted;
// saved Lingo state
Common::Array<CFrame *> _callstack;
uint _retPC;
ScriptData *_retScript;
ScriptContext *_retContext;
bool _retFreezeContext;
DatumHash *_retLocalVars;
Datum _retMe;
private:
uint32 _stageColor;
DirectorEngine *_vm;
DirectorSound *_soundManager;
LingoState *_lingoState;
bool _isStage;
Archive *_mainArchive;
Movie *_currentMovie;