[Scummvm-git-logs] scummvm master -> bd3b24d4376a840b2641faebb5b8e00f4eb59628
sev-
noreply at scummvm.org
Sat Oct 22 17:53:30 UTC 2022
This automated email contains information about 10 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
4ec70de496 DIRECTOR: Add 'console' debug flag
6aa71f2f33 DIRECTOR: Show variable contents in debug output
cadfa5dcc0 DIRECTOR: Hide noisy global definition warning
2e339e3214 DIRECTOR: Include script cast member name in function list
75a0de4110 DIRECTOR: LINGO: Initial XObjs for AskUser and SpaceMgr
f23675ab1d DIRECTOR: LINGO: Add more methods for SpaceMgr XObj
36e6246dde DIRECTOR: Add bpvar command to debugger
4c306fbfd9 DIRECTOR: Fix Lingo REPL mode in debugger
9c3de4c269 DIRECTOR: Make "the pathName" return an absolute path
bd3b24d437 DIRECTOR: Add bpentity command to debugger
Commit: 4ec70de496fbb8bab00a3ec659896160119dadd2
https://github.com/scummvm/scummvm/commit/4ec70de496fbb8bab00a3ec659896160119dadd2
Author: Scott Percival (code at moral.net.au)
Date: 2022-10-22T19:53:22+02:00
Commit Message:
DIRECTOR: Add 'console' debug flag
Changed paths:
engines/director/detection.cpp
engines/director/director.cpp
engines/director/director.h
diff --git a/engines/director/detection.cpp b/engines/director/detection.cpp
index 8eac0465b35..5dc48192ba2 100644
--- a/engines/director/detection.cpp
+++ b/engines/director/detection.cpp
@@ -50,6 +50,7 @@ static const DebugChannelDef debugFlagList[] = {
{Director::kDebug32bpp, "32bpp", "Work in 32bpp mode"},
{Director::kDebugCompile, "compile", "Lingo Compilation"},
{Director::kDebugCompileOnly, "compileonly", "Skip Lingo code execution"},
+ {Director::kDebugConsole, "console", "Open the debug console"},
{Director::kDebugDesktop, "desktop", "Show the Classic Mac desktop"},
{Director::kDebugEndVideo, "endvideo", "Fake that the end of video is reached setting"},
{Director::kDebugEvents, "events", "Event processing"},
diff --git a/engines/director/director.cpp b/engines/director/director.cpp
index 08a3f39daa3..944b5363c1c 100644
--- a/engines/director/director.cpp
+++ b/engines/director/director.cpp
@@ -229,6 +229,11 @@ Common::Error DirectorEngine::run() {
if (err.getCode() != Common::kNoError)
return err;
+ if (debugChannelSet(-1, kDebugConsole)) {
+ g_debugger->attach();
+ g_system->updateScreen();
+ }
+
bool loop = true;
while (loop) {
diff --git a/engines/director/director.h b/engines/director/director.h
index 443329f0eb0..8f48a6b29aa 100644
--- a/engines/director/director.h
+++ b/engines/director/director.h
@@ -88,6 +88,7 @@ enum {
kDebugEndVideo = 1 << 17,
kDebugLingoStrict = 1 << 18,
kDebugSound = 1 << 19,
+ kDebugConsole = 1 << 20,
};
struct MovieReference {
Commit: 6aa71f2f33d28f223ac8a48f9695b591cabcc70e
https://github.com/scummvm/scummvm/commit/6aa71f2f33d28f223ac8a48f9695b591cabcc70e
Author: Scott Percival (code at moral.net.au)
Date: 2022-10-22T19:53:22+02:00
Commit Message:
DIRECTOR: Show variable contents in debug output
Changed paths:
engines/director/debugger.cpp
engines/director/debugger.h
engines/director/lingo/lingo.cpp
engines/director/types.h
diff --git a/engines/director/debugger.cpp b/engines/director/debugger.cpp
index 3a8167f6ded..c770864717b 100644
--- a/engines/director/debugger.cpp
+++ b/engines/director/debugger.cpp
@@ -67,7 +67,8 @@ Debugger::Debugger(): GUI::Debugger() {
registerCmd("bt", WRAP_METHOD(Debugger, cmdBacktrace));
registerCmd("disasm", WRAP_METHOD(Debugger, cmdDisasm));
registerCmd("da", WRAP_METHOD(Debugger, cmdDisasm));
- registerCmd("vars", WRAP_METHOD(Debugger, cmdVars));
+ registerCmd("var", WRAP_METHOD(Debugger, cmdVar));
+ registerCmd("v", WRAP_METHOD(Debugger, cmdVar));
registerCmd("step", WRAP_METHOD(Debugger, cmdStep));
registerCmd("s", WRAP_METHOD(Debugger, cmdStep));
registerCmd("next", WRAP_METHOD(Debugger, cmdNext));
@@ -141,7 +142,7 @@ bool Debugger::cmdHelp(int argc, const char **argv) {
debugPrintf(" stack / st - Lists the elements on the stack\n");
debugPrintf(" scriptframe / sf - Prints the current script frame\n");
debugPrintf(" funcs - Lists all of the functions available in the current script frame\n");
- debugPrintf(" vars - Lists all of the variables available in the current script frame\n");
+ debugPrintf(" var / v - Lists all of the variables available in the current script frame\n");
debugPrintf(" step / s [n] - Steps forward one or more operations\n");
debugPrintf(" next / n [n] - Steps forward one or more operations, skips over calls\n");
debugPrintf(" finish / fin - Steps until the current stack frame returns\n");
@@ -154,7 +155,7 @@ bool Debugger::cmdHelp(int argc, const char **argv) {
debugPrintf(" bpset / b [funcName] [offset] - Creates a breakpoint on a Lingo function matching a name and offset\n");
debugPrintf(" bpset / b [scriptId:funcName] - Creates a breakpoint on a Lingo function matching a script ID and name\n");
debugPrintf(" bpset / b [scriptId:funcName] [offset] - Creates a breakpoint on a Lingo function matching a script ID, name and offset\n");
- debugPrintf(" bpmovie / bf [moviePath] - Create a breakpoint on a switch to a movie\n");
+ debugPrintf(" bpmovie / bm [moviePath] - Create a breakpoint on a switch to a movie\n");
debugPrintf(" bpframe / bf [frameId] - Create a breakpoint on a frame in the score\n");
debugPrintf(" bpframe / bf [moviePath] [frameId] - Create a breakpoint on a frame in the score of a specific movie\n");
debugPrintf(" bpdel [n] - Deletes a specific breakpoint\n");
@@ -434,7 +435,7 @@ bool Debugger::cmdDisasm(int argc, const char **argv) {
return true;
}
-bool Debugger::cmdVars(int argc, const char **argv) {
+bool Debugger::cmdVar(int argc, const char **argv) {
Lingo *lingo = g_director->getLingo();
debugPrintf("%s\n", lingo->formatAllVars().c_str());
return true;
diff --git a/engines/director/debugger.h b/engines/director/debugger.h
index f0e1da5afe1..014819a10bd 100644
--- a/engines/director/debugger.h
+++ b/engines/director/debugger.h
@@ -104,7 +104,7 @@ private:
bool cmdStack(int argc, const char **argv);
bool cmdScriptFrame(int argc, const char **argv);
bool cmdFuncs(int argc, const char **argv);
- bool cmdVars(int argc, const char **argv);
+ bool cmdVar(int argc, const char **argv);
bool cmdStep(int argc, const char **argv);
bool cmdNext(int argc, const char **argv);
bool cmdFinish(int argc, const char **argv);
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index aa2f44c7e9f..d7cef5856df 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -1140,34 +1140,46 @@ const char *Datum::type2str(bool isk) const {
static char res[20];
switch (isk ? u.i : type) {
- case INT:
- return isk ? "#integer" : "INT";
- case FLOAT:
- return isk ? "#float" : "FLOAT";
- case STRING:
- return isk ? "#string" : "STRING";
+ case ARGC:
+ return "ARGC";
+ case ARGCNORET:
+ return "ARGCNORET";
+ case ARRAY:
+ return "ARRAY";
case CASTREF:
return "CASTREF";
- case VOID:
- return isk ? "#void" : "VOID";
- case POINT:
- return isk ? "#point" : "POINT";
- case SYMBOL:
- return isk ? "#symbol" : "SYMBOL";
- case OBJECT:
- return isk ? "#object" : "OBJECT";
- case FIELDREF:
- return "FIELDREF";
case CHUNKREF:
return "CHUNKREF";
- case VARREF:
- return "VARREF";
+ case FIELDREF:
+ return "FIELDREF";
+ case FLOAT:
+ return isk ? "#float" : "FLOAT";
case GLOBALREF:
return "GLOBALREF";
+ case INT:
+ return isk ? "#integer" : "INT";
case LOCALREF:
return "LOCALREF";
+ case MENUREF:
+ return "MENUREF";
+ case OBJECT:
+ return isk ? "#object" : "OBJECT";
+ case PARRAY:
+ return "PARRAY";
+ case POINT:
+ return isk ? "#point" : "POINT";
case PROPREF:
return "PROPREF";
+ case RECT:
+ return "RECT";
+ case STRING:
+ return isk ? "#string" : "STRING";
+ case SYMBOL:
+ return isk ? "#symbol" : "SYMBOL";
+ case VARREF:
+ return "VARREF";
+ case VOID:
+ return isk ? "#void" : "VOID";
default:
snprintf(res, 20, "-- (%d) --", type);
return res;
@@ -1359,28 +1371,28 @@ void Lingo::cleanLocalVars() {
Common::String Lingo::formatAllVars() {
Common::String result;
- result += Common::String(" Local vars: ");
+ result += Common::String(" Local vars:\n");
if (_localvars) {
for (DatumHash::iterator i = _localvars->begin(); i != _localvars->end(); ++i) {
- result += Common::String::format("%s, ", (*i)._key.c_str());
+ result += Common::String::format(" %s - [%s] %s\n", (*i)._key.c_str(), (*i)._value.type2str(), (*i)._value.asString(true).c_str());
}
} else {
- result += Common::String("(no local vars)");
+ result += Common::String(" (no local vars)\n");
}
result += Common::String("\n");
if (_currentMe.type == OBJECT && _currentMe.u.obj->getObjType() & (kFactoryObj | kScriptObj)) {
ScriptContext *script = static_cast<ScriptContext *>(_currentMe.u.obj);
- result += Common::String(" Instance/property vars: ");
+ result += Common::String(" Instance/property vars: \n");
for (DatumHash::iterator i = script->_properties.begin(); i != script->_properties.end(); ++i) {
- result += Common::String("%s, ", (*i)._key.c_str());
+ result += Common::String::format(" %s - [%s] %s\n", (*i)._key.c_str(), (*i)._value.type2str(), (*i)._value.asString(true).c_str());
}
result += Common::String("\n");
}
- result += Common::String(" Global vars: ");
+ result += Common::String(" Global vars:\n");
for (DatumHash::iterator i = _globalvars.begin(); i != _globalvars.end(); ++i) {
- result += Common::String::format("%s, ", (*i)._key.c_str());
+ result += Common::String::format(" %s - [%s] %s\n", (*i)._key.c_str(), (*i)._value.type2str(), (*i)._value.asString(true).c_str());
}
result += Common::String("\n");
return result;
diff --git a/engines/director/types.h b/engines/director/types.h
index 869c360d363..718c04bf145 100644
--- a/engines/director/types.h
+++ b/engines/director/types.h
@@ -337,26 +337,26 @@ enum {
};
enum DatumType {
- ARRAY,
ARGC,
ARGCNORET,
+ ARRAY,
CASTREF,
CHUNKREF,
FIELDREF,
- MENUREF,
FLOAT,
+ GLOBALREF,
INT,
+ LOCALREF,
+ MENUREF,
OBJECT,
PARRAY,
POINT,
+ PROPREF,
+ RECT,
STRING,
SYMBOL,
VARREF,
- GLOBALREF,
- LOCALREF,
- PROPREF,
VOID,
- RECT
};
enum VarType {
Commit: cadfa5dcc0be639119aa5631673d05855096aceb
https://github.com/scummvm/scummvm/commit/cadfa5dcc0be639119aa5631673d05855096aceb
Author: Scott Percival (code at moral.net.au)
Date: 2022-10-22T19:53:22+02:00
Commit Message:
DIRECTOR: Hide noisy global definition warning
Changed paths:
engines/director/lingo/lingo-bytecode.cpp
diff --git a/engines/director/lingo/lingo-bytecode.cpp b/engines/director/lingo/lingo-bytecode.cpp
index 7c3710d3e00..9ca7aab53f3 100644
--- a/engines/director/lingo/lingo-bytecode.cpp
+++ b/engines/director/lingo/lingo-bytecode.cpp
@@ -1101,11 +1101,11 @@ ScriptContext *LingoCompiler::compileLingoV4(Common::SeekableReadStreamEndian &s
int16 index = stream.readSint16();
if (0 <= index && index < (int16)archive->names.size()) {
const char *name = archive->names[index].c_str();
- debugC(5, kDebugLoading, "%d: %s", i, name);
if (!g_lingo->_globalvars.contains(name)) {
g_lingo->_globalvars[name] = Datum();
+ debugC(5, kDebugLoading, "%d: %s", i, name);
} else {
- warning("Global %d (%s) already defined", i, name);
+ debugC(5, kDebugLoading, "%d: %s (already defined)", i, name);
}
} else {
warning("Global %d has unknown name id %d, skipping define", i, index);
Commit: 2e339e3214a1d014db055891c4141856d182c0c5
https://github.com/scummvm/scummvm/commit/2e339e3214a1d014db055891c4141856d182c0c5
Author: Scott Percival (code at moral.net.au)
Date: 2022-10-22T19:53:22+02:00
Commit Message:
DIRECTOR: Include script cast member name in function list
Changed paths:
engines/director/lingo/lingo.cpp
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index d7cef5856df..9c0ce9a19ec 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -277,7 +277,12 @@ Common::String LingoArchive::formatFunctionList(const char *prefix) {
if (scriptContexts[i].size() == 0)
result += Common::String::format("%s [empty]\n", prefix);
for (ScriptContextHash::iterator it = scriptContexts[i].begin(); it != scriptContexts[i].end(); ++it) {
- result += Common::String::format("%s %d:\n", prefix, it->_key);
+ result += Common::String::format("%s %d", prefix, it->_key);
+ CastMemberInfo *cmi = cast->getCastMemberInfo(it->_key);
+ if (cmi && !cmi->name.empty()) {
+ result += Common::String::format(" \"%s\"", cmi->name.c_str());
+ }
+ result += ":\n";
result += (*it->_value).formatFunctionList(Common::String::format("%s ", prefix).c_str());
}
}
Commit: 75a0de4110caf4433d7a83b4eccdf33e17887d1f
https://github.com/scummvm/scummvm/commit/75a0de4110caf4433d7a83b4eccdf33e17887d1f
Author: Scott Percival (code at moral.net.au)
Date: 2022-10-22T19:53:22+02:00
Commit Message:
DIRECTOR: LINGO: Initial XObjs for AskUser and SpaceMgr
Changed paths:
A engines/director/lingo/xlibs/askuser.cpp
A engines/director/lingo/xlibs/askuser.h
A engines/director/lingo/xlibs/spacemgr.cpp
A engines/director/lingo/xlibs/spacemgr.h
engines/director/lingo/lingo-object.cpp
engines/director/module.mk
diff --git a/engines/director/lingo/lingo-object.cpp b/engines/director/lingo/lingo-object.cpp
index 1416d1f493e..03422e2a566 100644
--- a/engines/director/lingo/lingo-object.cpp
+++ b/engines/director/lingo/lingo-object.cpp
@@ -38,6 +38,7 @@
#include "director/lingo/xlibs/aiff.h"
#include "director/lingo/xlibs/applecdxobj.h"
+#include "director/lingo/xlibs/askuser.h"
#include "director/lingo/xlibs/barakeobj.h"
#include "director/lingo/xlibs/cdromxobj.h"
#include "director/lingo/xlibs/fileio.h"
@@ -58,6 +59,7 @@
#include "director/lingo/xlibs/registercomponent.h"
#include "director/lingo/xlibs/serialportxobj.h"
#include "director/lingo/xlibs/soundjam.h"
+#include "director/lingo/xlibs/spacemgr.h"
#include "director/lingo/xlibs/videodiscxobj.h"
#include "director/lingo/xlibs/widgetxobj.h"
#include "director/lingo/xlibs/winxobj.h"
@@ -134,6 +136,7 @@ static struct XLibProto {
} xlibs[] = {
{ AiffXObj::fileNames, AiffXObj::open, AiffXObj::close, kXObj, 400 }, // D4
{ AppleCDXObj::fileNames, AppleCDXObj::open, AppleCDXObj::close, kXObj, 400 }, // D4
+ { AskUser::fileNames, AskUser::open, AskUser::close, kXObj, 400 }, // D4
{ BarakeObj::fileNames, BarakeObj::open, BarakeObj::close, kXObj, 400 }, // D4
{ CDROMXObj::fileNames, CDROMXObj::open, CDROMXObj::close, kXObj, 200 }, // D2
{ FileIO::fileNames, FileIO::open, FileIO::close, kXObj | kXtraObj, 200 }, // D2
@@ -155,6 +158,7 @@ static struct XLibProto {
{ RegisterComponent::fileNames, RegisterComponent::open, RegisterComponent::close, kXObj, 400 }, // D4
{ SerialPortXObj::fileNames, SerialPortXObj::open, SerialPortXObj::close, kXObj, 200 }, // D2
{ SoundJam::fileNames, SoundJam::open, SoundJam::close, kXObj, 400 }, // D4
+ { SpaceMgr::fileNames, SpaceMgr::open, SpaceMgr::close, kXObj, 400 }, // D4
{ WidgetXObj::fileNames, WidgetXObj::open, WidgetXObj::close, kXObj, 400 }, // D4
{ VideodiscXObj::fileNames, VideodiscXObj::open, VideodiscXObj::close, kXObj, 200 }, // D2
{ XPlayAnim::fileNames, XPlayAnim::open, XPlayAnim::close, kXObj, 300 }, // D3
diff --git a/engines/director/lingo/xlibs/askuser.cpp b/engines/director/lingo/xlibs/askuser.cpp
new file mode 100644
index 00000000000..f8c9de09a64
--- /dev/null
+++ b/engines/director/lingo/xlibs/askuser.cpp
@@ -0,0 +1,146 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/system.h"
+#include "director/types.h"
+#include "gui/message.h"
+
+#include "director/director.h"
+#include "director/lingo/lingo.h"
+#include "director/lingo/lingo-object.h"
+#include "director/lingo/xlibs/askuser.h"
+
+namespace Director {
+
+/**************************************************
+ *
+ * USED IN:
+ * DEVO Presents: Adventures of the Smart Patrol
+ *
+ **************************************************/
+/*
+-- AskUser XObject. Copyright 1996 Inscape v1.0 24May96 BDL
+AskUser
+I mNew --Creates a new instance
+X mDispose --Disposes XObject instance
+SSSS mAsk --Data to display in the message box.
+*/
+
+const char *AskUser::xlibName = "AskUser";
+const char *AskUser::fileNames[] = {
+ "AskUser",
+ "ASKUSER",
+ nullptr
+};
+
+static MethodProto xlibMethods[] = {
+ { "new", AskUser::m_new, 0, 0, 400 }, // D4
+ { "ask", AskUser::m_ask, 3, 3, 400 }, // D4
+ { nullptr, nullptr, 0, 0, 0 }
+};
+
+AskUserXObject::AskUserXObject(ObjectType ObjectType) :Object<AskUserXObject>("AskUser") {
+ _objType = ObjectType;
+}
+
+void AskUser::open(int type) {
+ if (type == kXObj) {
+ AskUserXObject::initMethods(xlibMethods);
+ AskUserXObject *xobj = new AskUserXObject(kXObj);
+ g_lingo->exposeXObject(xlibName, xobj);
+ } else if (type == kXtraObj) {
+ // TODO - Implement Xtra
+ }
+}
+
+void AskUser::close(int type) {
+ if (type == kXObj) {
+ AskUserXObject::cleanupMethods();
+ g_lingo->_globalvars[xlibName] = Datum();
+ } else if (type == kXtraObj) {
+ // TODO - Implement Xtra
+ }
+}
+
+void AskUser::m_new(int nargs) {
+ if (nargs != 0) {
+ warning("AskUser::m_new: expected 0 arguments");
+ g_lingo->dropStack(nargs);
+ }
+ g_lingo->push(g_lingo->_currentMe);
+}
+
+void AskUser::m_ask(int nargs) {
+ if (nargs != 3) {
+ warning("AskUser::m_ask: expected 3 arguments");
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum("Ok"));
+ return;
+ }
+ Datum text = g_lingo->pop();
+ Datum caption = g_lingo->pop(); // ScummVM doesn't have a title for message boxes, not used
+ Datum mbType = g_lingo->pop();
+ if (text.type != STRING) {
+ warning("AskUser::m_ask: expected text to be a string, not %s", text.type2str());
+ g_lingo->push(Datum("Ok"));
+ return;
+ }
+ if (mbType.type != STRING) {
+ warning("AskUser::m_ask: expected mbType to be a string, not %s", mbType.type2str());
+ g_lingo->push(Datum("Ok"));
+ return;
+ }
+
+ Common::U32String defaultButton;
+ Common::U32StringArray altButtons;
+
+ if (mbType.u.s->equals("YesNoCancel")) {
+ defaultButton = Common::U32String("Yes");
+ altButtons.push_back(Common::U32String("No"));
+ altButtons.push_back(Common::U32String("Cancel"));
+ } else if (mbType.u.s->equals("YesNo")) {
+ defaultButton = Common::U32String("Yes");
+ altButtons.push_back(Common::U32String("No"));
+ } else if (mbType.u.s->equals("OkCancel")) {
+ defaultButton = Common::U32String("OK");
+ altButtons.push_back(Common::U32String("Cancel"));
+ } else if (mbType.u.s->equals("Ok")) {
+ defaultButton = Common::U32String("OK");
+ } else {
+ warning("AskUser::m_ask: unhandled mbType %s, falling back to Ok", mbType.u.s->c_str());
+ defaultButton = Common::U32String("OK");
+ }
+
+ g_director->_wm->clearHandlingWidgets();
+ GUI::MessageDialog dialog(Common::U32String(text.u.s->c_str()), defaultButton, altButtons);
+ int result = dialog.runModal();
+
+ if (result == GUI::kMessageOK) {
+ g_lingo->push(Datum(Common::String(defaultButton)));
+ } else if ((result >= GUI::kMessageAlt) && (result < GUI::kMessageAlt + (int)altButtons.size())) {
+ g_lingo->push(Datum(Common::String(altButtons[result - GUI::kMessageAlt])));
+ } else {
+ warning("AskUser::m_ask: got unexpected dialog result of %d", result);
+ g_lingo->push(Datum("Ok"));
+ }
+}
+
+}
diff --git a/engines/director/lingo/xlibs/askuser.h b/engines/director/lingo/xlibs/askuser.h
new file mode 100644
index 00000000000..c94f9994f07
--- /dev/null
+++ b/engines/director/lingo/xlibs/askuser.h
@@ -0,0 +1,48 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef DIRECTOR_LINGO_XLIBS_ASKUSER_H
+#define DIRECTOR_LINGO_XLIBS_ASKUSER_H
+
+namespace Director {
+
+class AskUserXObject : public Object<AskUserXObject> {
+public:
+ AskUserXObject(ObjectType objType);
+};
+
+namespace AskUser {
+
+extern const char *xlibName;
+extern const char *fileNames[];
+
+void open(int type);
+void close(int type);
+
+void m_new(int nargs);
+void m_dispose(int nargs);
+void m_ask(int nargs);
+
+} // End of namespace AskUser
+
+} // End of namespace Director
+
+#endif
diff --git a/engines/director/lingo/xlibs/spacemgr.cpp b/engines/director/lingo/xlibs/spacemgr.cpp
new file mode 100644
index 00000000000..37a1ac8fe5c
--- /dev/null
+++ b/engines/director/lingo/xlibs/spacemgr.cpp
@@ -0,0 +1,389 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/system.h"
+
+#include "director/director.h"
+#include "director/lingo/lingo.h"
+#include "director/lingo/lingo-object.h"
+#include "director/lingo/xlibs/spacemgr.h"
+
+namespace Director {
+
+/**************************************************
+ *
+ * USED IN:
+ * DEVO Presents: Adventures of the Smart Patrol
+ *
+ **************************************************/
+/*
+-- SpaceMgr XObject. Copyright 1995 Inscape v1.0b1 10March95 BDL
+SpaceMgr
+I mNew --Creates a new instance
+X mDispose --Disposes XObject instance
+I mLastError --Last error code
+I mMemUsed --RAM occupied by this object and data
+S mListData --List all data
+I mSortAll --Sort internal arrays
+IS mCheckForDups, bool --Set to true to check for Duplicate items before adding an element
+IS mParseText, text --Parse Text into a space structure
+S mGetCurData --List Current data
+ISSSS mSetCurData, sc, s, n, v --pass in names of elements to make current
+ISS mAddSpaceCollection, name, data --Add a Space Collection
+IS mRemoveSpaceCollection, name --Remove a Space Collection
+IS mSetCurSpaceCollection, name --Set current SpaceCollection
+S mGetCurSpaceCollection --Get current SpaceCollection
+SS mGetSpaceCollection, name --Get SpaceCollection with name
+ISS mAddSpace, name, data --Add a Space
+IS mRemoveSpace, name --Remove a Space
+IS mSetCurSpace, name --Set current Space
+S mGetCurSpace --Get current Space
+SS mGetSpace, name --Get Space with name
+ISS mAddNode, name, data --Add a Node
+IS mRemoveNode, name --Remove a Node
+IS mSetCurNode, name --Set current Node
+S mGetCurNode --Get current Node
+SS mGetNode, name --Get Node with name
+ISS mAddView, name, data --Add a View
+IS mRemoveView, name --Remove a View
+IS mSetCurView, name --Set current View
+S mGetCurView --Get current View
+SS mGetView, name --Get View with name
+ISS mAddLocalLink, name, data --Add a link to the current view
+IS mRemoveLocalLink, name --Remove a link from the current View
+I mRemoveLocalLinks --Remove all links from the current View
+SS mGetLocalLink, name --Get link with name from the current view
+S mGetLocalLinks --Get all links from the current view
+ISS mAddGlobalLink, name, data --Add a global link
+IS mRemoveGlobalLink, name --Remove a global link
+SS mGetGlobalLink, name --Get global link with name
+S mGetGlobalLinks --Get list of all global links
+*/
+
+const char *SpaceMgr::xlibName = "SpaceMgr";
+const char *SpaceMgr::fileNames[] = {
+ "SpaceMgr",
+ "SPACEMGR",
+ nullptr
+};
+
+static MethodProto xlibMethods[] = {
+ { "new", SpaceMgr::m_new, 0, 0, 400 }, // D4
+ { "dispose", SpaceMgr::m_dispose, 1, 1, 400 }, // D4
+ { "lastError", SpaceMgr::m_lastError, 0, 0, 400 }, // D4
+ { "memUsed", SpaceMgr::m_memUsed, 0, 0, 400 }, // D4
+ { "listData", SpaceMgr::m_listData, 0, 0, 400 }, // D4
+ { "sortAll", SpaceMgr::m_sortAll, 0, 0, 400 }, // D4
+ { "checkForDups", SpaceMgr::m_checkForDups, 1, 1, 400 }, // D4
+ { "parseText", SpaceMgr::m_parseText, 1, 1, 400 }, // D4
+ { "getCurData", SpaceMgr::m_getCurData, 0, 0, 400 }, // D4
+ { "setCurData", SpaceMgr::m_setCurData, 4, 4, 400 }, // D4
+ { "addSpaceCollection", SpaceMgr::m_addSpaceCollection, 2, 2, 400 }, // D4
+ { "removeSpaceCollection", SpaceMgr::m_removeSpaceCollection, 1, 1, 400 }, // D4
+ { "setCurSpaceCollection", SpaceMgr::m_setCurSpaceCollection, 1, 1, 400 }, // D4
+ { "getCurSpaceCollection", SpaceMgr::m_getCurSpaceCollection, 0, 0, 400 }, // D4
+ { "getSpaceCollection", SpaceMgr::m_getSpaceCollection, 1, 1, 400 }, // D4
+ { "addSpace", SpaceMgr::m_addSpace, 2, 2, 400 }, // D4
+ { "removeSpace", SpaceMgr::m_removeSpace, 1, 1, 400 }, // D4
+ { "setCurSpace", SpaceMgr::m_setCurSpace, 1, 1, 400 }, // D4
+ { "getCurSpace", SpaceMgr::m_getCurSpace, 0, 0, 400 }, // D4
+ { "getSpace", SpaceMgr::m_getSpace, 1, 1, 400 }, // D4
+ { "addNode", SpaceMgr::m_addNode, 2, 2, 400 }, // D4
+ { "removeNode", SpaceMgr::m_removeNode, 1, 1, 400 }, // D4
+ { "setCurNode", SpaceMgr::m_setCurNode, 1, 1, 400 }, // D4
+ { "getCurNode", SpaceMgr::m_getCurNode, 0, 0, 400 }, // D4
+ { "getNode", SpaceMgr::m_getNode, 1, 1, 400 }, // D4
+ { "addView", SpaceMgr::m_addView, 2, 2, 400 }, // D4
+ { "removeView", SpaceMgr::m_removeView, 1, 1, 400 }, // D4
+ { "setCurView", SpaceMgr::m_setCurView, 1, 1, 400 }, // D4
+ { "getCurView", SpaceMgr::m_getCurView, 0, 0, 400 }, // D4
+ { "getView", SpaceMgr::m_getView, 1, 1, 400 }, // D4
+ { "addLocalLink", SpaceMgr::m_addLocalLink, 2, 2, 400 }, // D4
+ { "removeLocalLink", SpaceMgr::m_removeLocalLink, 1, 1, 400 }, // D4
+ { "removeLocalLinks", SpaceMgr::m_removeLocalLinks, 0, 0, 400 }, // D4
+ { "getLocalLink", SpaceMgr::m_getLocalLink, 1, 1, 400 }, // D4
+ { "getLocalLinks", SpaceMgr::m_getLocalLink, 1, 1, 400 }, // D4
+ { "addGlobalLink", SpaceMgr::m_addGlobalLink, 2, 2, 400 }, // D4
+ { "removeGlobalLink", SpaceMgr::m_removeGlobalLink, 1, 1, 400 }, // D4
+ { "getGlobalLink", SpaceMgr::m_getGlobalLink, 1, 1, 400 }, // D4
+ { "getGlobalLinks", SpaceMgr::m_getGlobalLinks, 0, 0, 400 }, // D4
+ { nullptr, nullptr, 0, 0, 0 }
+};
+
+SpaceMgrXObject::SpaceMgrXObject(ObjectType ObjectType) :Object<SpaceMgrXObject>("SpaceMgr") {
+ _objType = ObjectType;
+}
+
+void SpaceMgr::open(int type) {
+ if (type == kXObj) {
+ SpaceMgrXObject::initMethods(xlibMethods);
+ SpaceMgrXObject *xobj = new SpaceMgrXObject(kXObj);
+ g_lingo->exposeXObject(xlibName, xobj);
+ } else if (type == kXtraObj) {
+ // TODO - Implement Xtra
+ }
+}
+
+void SpaceMgr::close(int type) {
+ if (type == kXObj) {
+ SpaceMgrXObject::cleanupMethods();
+ g_lingo->_globalvars[xlibName] = Datum();
+ } else if (type == kXtraObj) {
+ // TODO - Implement Xtra
+ }
+}
+
+void SpaceMgr::m_new(int nargs) {
+ if (nargs != 0) {
+ warning("SpaceMgr::m_new: expected 0 arguments");
+ g_lingo->dropStack(nargs);
+ }
+ g_lingo->push(g_lingo->_currentMe);
+}
+
+void SpaceMgr::m_dispose(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_dispose", nargs);
+ g_lingo->dropStack(nargs);
+}
+
+void SpaceMgr::m_lastError(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_lastError", nargs);
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(0));
+}
+
+void SpaceMgr::m_memUsed(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_memUsed", nargs);
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(0));
+}
+
+void SpaceMgr::m_listData(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_listData", nargs);
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(""));
+}
+
+void SpaceMgr::m_sortAll(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_sortAll", nargs);
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(0));
+}
+
+void SpaceMgr::m_checkForDups(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_checkForDups", nargs);
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(0));
+}
+
+void SpaceMgr::m_parseText(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_parseText", nargs);
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(0));
+}
+
+void SpaceMgr::m_getCurData(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_getCurData", nargs);
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(""));
+}
+
+void SpaceMgr::m_setCurData(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_setCurData", nargs);
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(0));
+}
+
+void SpaceMgr::m_addSpaceCollection(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_addSpaceCollection", nargs);
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(0));
+}
+
+void SpaceMgr::m_removeSpaceCollection(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_removeSpaceCollection", nargs);
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(0));
+}
+
+void SpaceMgr::m_setCurSpaceCollection(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_setCurSpaceCollection", nargs);
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(0));
+}
+
+void SpaceMgr::m_getCurSpaceCollection(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_getCurSpaceCollection", nargs);
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(""));
+}
+
+void SpaceMgr::m_getSpaceCollection(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_getSpaceCollection", nargs);
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(""));
+}
+
+void SpaceMgr::m_addSpace(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_addSpace", nargs);
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(0));
+}
+
+void SpaceMgr::m_removeSpace(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_removeSpace", nargs);
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(0));
+}
+
+void SpaceMgr::m_setCurSpace(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_setCurSpace", nargs);
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(0));
+}
+
+void SpaceMgr::m_getCurSpace(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_getCurSpace", nargs);
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(""));
+}
+
+void SpaceMgr::m_getSpace(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_getSpace", nargs);
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(""));
+}
+
+void SpaceMgr::m_addNode(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_addNode", nargs);
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(0));
+}
+
+void SpaceMgr::m_removeNode(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_removeNode", nargs);
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(0));
+}
+
+void SpaceMgr::m_setCurNode(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_setCurNode", nargs);
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(0));
+}
+
+void SpaceMgr::m_getCurNode(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_getCurNode", nargs);
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(""));
+}
+
+void SpaceMgr::m_getNode(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_getNode", nargs);
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(""));
+}
+
+void SpaceMgr::m_addView(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_addView", nargs);
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(0));
+}
+
+void SpaceMgr::m_removeView(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_removeView", nargs);
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(0));
+}
+
+void SpaceMgr::m_setCurView(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_setCurView", nargs);
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(0));
+}
+
+void SpaceMgr::m_getCurView(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_getCurView", nargs);
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(""));
+}
+
+void SpaceMgr::m_getView(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_getView", nargs);
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(""));
+}
+
+void SpaceMgr::m_addLocalLink(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_addLocalLink", nargs);
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(0));
+}
+
+void SpaceMgr::m_removeLocalLink(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_removeLocalLink", nargs);
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(0));
+}
+
+void SpaceMgr::m_removeLocalLinks(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_removeLocalLinks", nargs);
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(0));
+}
+
+void SpaceMgr::m_getLocalLink(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_getLocalLink", nargs);
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(""));
+}
+
+void SpaceMgr::m_getLocalLinks(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_getLocalLinks", nargs);
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(""));
+}
+
+void SpaceMgr::m_addGlobalLink(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_addGlobalLink", nargs);
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(""));
+}
+
+void SpaceMgr::m_removeGlobalLink(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_removeGlobalLink", nargs);
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(0));
+}
+
+void SpaceMgr::m_getGlobalLink(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_getGlobalLink", nargs);
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(""));
+}
+
+void SpaceMgr::m_getGlobalLinks(int nargs) {
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_getGlobalLinks", nargs);
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(""));
+}
+
+}
diff --git a/engines/director/lingo/xlibs/spacemgr.h b/engines/director/lingo/xlibs/spacemgr.h
new file mode 100644
index 00000000000..182a6dea28e
--- /dev/null
+++ b/engines/director/lingo/xlibs/spacemgr.h
@@ -0,0 +1,84 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef DIRECTOR_LINGO_XLIBS_SPACEMGR_H
+#define DIRECTOR_LINGO_XLIBS_SPACEMGR_H
+
+namespace Director {
+
+class SpaceMgrXObject : public Object<SpaceMgrXObject> {
+public:
+ SpaceMgrXObject(ObjectType objType);
+};
+
+namespace SpaceMgr {
+
+extern const char *xlibName;
+extern const char *fileNames[];
+
+void open(int type);
+void close(int type);
+
+void m_new(int nargs);
+void m_dispose(int nargs);
+void m_lastError(int nargs);
+void m_memUsed(int nargs);
+void m_listData(int nargs);
+void m_sortAll(int nargs);
+void m_checkForDups(int nargs);
+void m_parseText(int nargs);
+void m_getCurData(int nargs);
+void m_setCurData(int nargs);
+void m_addSpaceCollection(int nargs);
+void m_removeSpaceCollection(int nargs);
+void m_setCurSpaceCollection(int nargs);
+void m_getCurSpaceCollection(int nargs);
+void m_getSpaceCollection(int nargs);
+void m_addSpace(int nargs);
+void m_removeSpace(int nargs);
+void m_setCurSpace(int nargs);
+void m_getCurSpace(int nargs);
+void m_getSpace(int nargs);
+void m_addNode(int nargs);
+void m_removeNode(int nargs);
+void m_setCurNode(int nargs);
+void m_getCurNode(int nargs);
+void m_getNode(int nargs);
+void m_addView(int nargs);
+void m_removeView(int nargs);
+void m_setCurView(int nargs);
+void m_getCurView(int nargs);
+void m_getView(int nargs);
+void m_addLocalLink(int nargs);
+void m_removeLocalLink(int nargs);
+void m_removeLocalLinks(int nargs);
+void m_getLocalLink(int nargs);
+void m_getLocalLinks(int nargs);
+void m_addGlobalLink(int nargs);
+void m_removeGlobalLink(int nargs);
+void m_getGlobalLink(int nargs);
+void m_getGlobalLinks(int nargs);
+
+} // End of namespace SpaceMgr
+
+} // End of namespace Director
+
+#endif
diff --git a/engines/director/module.mk b/engines/director/module.mk
index b453005bb6f..8965aa5e63c 100644
--- a/engines/director/module.mk
+++ b/engines/director/module.mk
@@ -41,6 +41,7 @@ MODULE_OBJS = \
lingo/lingo-utils.o \
lingo/xlibs/aiff.o \
lingo/xlibs/applecdxobj.o \
+ lingo/xlibs/askuser.o \
lingo/xlibs/barakeobj.o \
lingo/xlibs/cdromxobj.o \
lingo/xlibs/fileio.o \
@@ -61,6 +62,7 @@ MODULE_OBJS = \
lingo/xlibs/registercomponent.o \
lingo/xlibs/serialportxobj.o \
lingo/xlibs/soundjam.o \
+ lingo/xlibs/spacemgr.o \
lingo/xlibs/videodiscxobj.o \
lingo/xlibs/widgetxobj.o \
lingo/xlibs/winxobj.o \
Commit: f23675ab1d3923e5a8538f6ee15479d373426142
https://github.com/scummvm/scummvm/commit/f23675ab1d3923e5a8538f6ee15479d373426142
Author: Scott Percival (code at moral.net.au)
Date: 2022-10-22T19:53:22+02:00
Commit Message:
DIRECTOR: LINGO: Add more methods for SpaceMgr XObj
Changed paths:
engines/director/detection.cpp
engines/director/director.h
engines/director/lingo/lingo-object.cpp
engines/director/lingo/xlibs/spacemgr.cpp
engines/director/lingo/xlibs/spacemgr.h
diff --git a/engines/director/detection.cpp b/engines/director/detection.cpp
index 5dc48192ba2..0870bca046f 100644
--- a/engines/director/detection.cpp
+++ b/engines/director/detection.cpp
@@ -68,6 +68,7 @@ static const DebugChannelDef debugFlagList[] = {
{Director::kDebugSlow, "slow", "Slow playback"},
{Director::kDebugSound, "sound", "Sound playback"},
{Director::kDebugText, "text", "Text rendering"},
+ {Director::kDebugXObj, "xobj", "XObjects"},
DEBUG_CHANNEL_END
};
diff --git a/engines/director/director.h b/engines/director/director.h
index 8f48a6b29aa..656bd6d560b 100644
--- a/engines/director/director.h
+++ b/engines/director/director.h
@@ -89,6 +89,7 @@ enum {
kDebugLingoStrict = 1 << 18,
kDebugSound = 1 << 19,
kDebugConsole = 1 << 20,
+ kDebugXObj = 1 << 21,
};
struct MovieReference {
diff --git a/engines/director/lingo/lingo-object.cpp b/engines/director/lingo/lingo-object.cpp
index 03422e2a566..158a4ee0604 100644
--- a/engines/director/lingo/lingo-object.cpp
+++ b/engines/director/lingo/lingo-object.cpp
@@ -285,7 +285,7 @@ ScriptContext::ScriptContext(const ScriptContext &sc) : Object<ScriptContext>(sc
ScriptContext::~ScriptContext() {}
Common::String ScriptContext::asString() {
- return Common::String::format("script: #%s %d %p", _name.c_str(), _inheritanceLevel, (void *)this);
+ return Common::String::format("script: %d \"%s\" %d %p", _id, _name.c_str(), _inheritanceLevel, (void *)this);
}
Symbol ScriptContext::define(const Common::String &name, ScriptData *code, Common::Array<Common::String> *argNames, Common::Array<Common::String> *varNames) {
diff --git a/engines/director/lingo/xlibs/spacemgr.cpp b/engines/director/lingo/xlibs/spacemgr.cpp
index 37a1ac8fe5c..1c8750d1591 100644
--- a/engines/director/lingo/xlibs/spacemgr.cpp
+++ b/engines/director/lingo/xlibs/spacemgr.cpp
@@ -189,26 +189,186 @@ void SpaceMgr::m_sortAll(int nargs) {
}
void SpaceMgr::m_checkForDups(int nargs) {
- g_lingo->printSTUBWithArglist("SpaceMgr::m_checkForDups", nargs);
- g_lingo->dropStack(nargs);
+ if (nargs != 1) {
+ warning("SpaceMgr::m_checkForDups: expected 1 argument");
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(0));
+ return;
+ }
+ Datum arg = g_lingo->pop();
+ if (arg.type != STRING) {
+ warning("SpaceMgr::m_checkForDups: expected arg to be a string, not %s", arg.type2str());
+ g_lingo->push(Datum(0));
+ return;
+ }
+
+ SpaceMgrXObject *me = static_cast<SpaceMgrXObject *>(g_lingo->_currentMe.u.obj);
+
+ me->_checkForDups = (arg.u.s->c_str()[0] == 't') || (arg.u.s->c_str()[0] == 'T');
g_lingo->push(Datum(0));
}
void SpaceMgr::m_parseText(int nargs) {
- g_lingo->printSTUBWithArglist("SpaceMgr::m_parseText", nargs);
- g_lingo->dropStack(nargs);
+ if (nargs != 1) {
+ warning("SpaceMgr::m_parseText: expected 1 argument");
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(0));
+ return;
+ }
+ Datum text = g_lingo->pop();
+ if (text.type != STRING) {
+ warning("SpaceMgr::m_parseText: expected text to be a string, not %s", text.type2str());
+ g_lingo->push(Datum(0));
+ return;
+ }
+ SpaceMgrXObject *me = static_cast<SpaceMgrXObject *>(g_lingo->_currentMe.u.obj);
+
+ Common::String result = *text.u.s;
+ Common::String curSpaceCollection;
+ Common::String curSpace;
+ Common::String curNode;
+ Common::String curView;
+ int lastIndex = 0;
+ while (lastIndex < (int)result.size()) {
+ size_t index = result.findFirstOf('\r', lastIndex);
+ if (index == Common::String::npos)
+ index = result.size();
+ int pointer = lastIndex;
+
+ while (pointer < (int)index && result[pointer] == ' ')
+ pointer++;
+ if ((int)result.find("SPACECOLLECTION ", pointer) == pointer) {
+ pointer += 16;
+ while (pointer < (int)index && result[pointer] == ' ')
+ pointer++;
+ curSpaceCollection = result.substr(pointer, index - pointer);
+ curSpace = "";
+ curNode = "";
+ curView = "";
+ if (!(me->_spaceCollections.contains(curSpaceCollection) && me->_checkForDups)) {
+ me->_spaceCollections[curSpaceCollection] = SpaceCollection();
+ }
+ } else if ((int)result.find("SPACE ", pointer) == pointer) {
+ pointer += 6;
+ while (pointer < (int)index && result[pointer] == ' ')
+ pointer++;
+ curSpace = result.substr(pointer, index - pointer);
+ curNode = "";
+ curView = "";
+ SpaceCollection &sc = me->_spaceCollections.getVal(curSpaceCollection);
+ if (!(sc.spaces.contains(curSpaceCollection) && me->_checkForDups)) {
+ sc.spaces[curSpace] = Space();
+ }
+ } else if ((int)result.find("NODE ", pointer) == pointer) {
+ pointer += 5;
+ while (pointer < (int)index && result[pointer] == ' ')
+ pointer++;
+ curNode = result.substr(pointer, index - pointer);
+ curView = "";
+ SpaceCollection &sc = me->_spaceCollections.getVal(curSpaceCollection);
+ Space &s = sc.spaces.getVal(curSpace);
+ if (!(s.nodes.contains(curNode) && me->_checkForDups)) {
+ s.nodes[curNode] = Node();
+ }
+ } else if ((int)result.find("VIEW ", pointer) == pointer) {
+ pointer += 5;
+ while (pointer < (int)index && result[pointer] == ' ')
+ pointer++;
+ int idEnd = pointer;
+ while (idEnd < (int)index && result[idEnd] != ' ')
+ idEnd++;
+ curView = result.substr(pointer, idEnd - pointer);
+ pointer = idEnd;
+ while (pointer < (int)index && result[pointer] != ' ')
+ pointer++;
+ SpaceCollection &sc = me->_spaceCollections.getVal(curSpaceCollection);
+ Space &s = sc.spaces.getVal(curSpace);
+ Node &n = s.nodes.getVal(curNode);
+ if (!(n.views.contains(curView) && me->_checkForDups)) {
+ n.views[curView] = result.substr(pointer, index - pointer);
+ }
+ } else {
+ warning("SpaceMgr::m_parseText: Unhandled instruction %s", result.substr(lastIndex, index).c_str());
+ }
+
+ lastIndex = (int)index + 1;
+ }
+ if (debugLevelSet(5)) {
+ Common::String format = result;
+ for (int i = 0; i < (int)format.size(); i++) {
+ if (format[i] == '\r')
+ format.replace(i, 1, "\n");
+ }
+ debugC(5, kDebugXObj, "SpaceMgr::m_parseText(): %s", format.c_str());
+ }
+
g_lingo->push(Datum(0));
}
void SpaceMgr::m_getCurData(int nargs) {
- g_lingo->printSTUBWithArglist("SpaceMgr::m_getCurData", nargs);
- g_lingo->dropStack(nargs);
- g_lingo->push(Datum(""));
+ if (nargs != 0) {
+ warning("SpaceMgr::m_getCurData: expected 0 arguments");
+ g_lingo->dropStack(nargs);
+ }
+ SpaceMgrXObject *me = static_cast<SpaceMgrXObject *>(g_lingo->_currentMe.u.obj);
+ Common::String result;
+ if (me->_spaceCollections.contains(me->_curSpaceCollection)) {
+ result += "SPACECOLLECTION " + me->_curSpaceCollection;
+ SpaceCollection &sc = me->_spaceCollections.getVal(me->_curSpaceCollection);
+ if (sc.spaces.contains(me->_curSpace)) {
+ result += "\r";
+ result += "SPACE " + me->_curSpace;
+ Space &s = sc.spaces.getVal(me->_curSpace);
+ if (s.nodes.contains(me->_curNode)) {
+ result += "\r";
+ result += "NODE " + me->_curNode;
+ Node &n = s.nodes.getVal(me->_curNode);
+ if (n.views.contains(me->_curView)) {
+ result += "\r";
+ result += "VIEW " + me->_curView;
+ }
+ }
+ }
+ }
+
+ if (debugLevelSet(5)) {
+ Common::String format = result;
+ for (uint i = 0; i < format.size(); i++) {
+ if (format[i] == '\r')
+ format.replace(i, 1, "\n");
+ }
+ debugC(5, kDebugXObj, "SpaceMgr::m_getCurData(): %s", format.c_str());
+ }
+
+ g_lingo->push(Datum(result));
}
void SpaceMgr::m_setCurData(int nargs) {
g_lingo->printSTUBWithArglist("SpaceMgr::m_setCurData", nargs);
- g_lingo->dropStack(nargs);
+ if (nargs != 4) {
+ warning("SpaceMgr::m_setCurData: expected 4 arguments");
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(0));
+ return;
+ }
+ SpaceMgrXObject *me = static_cast<SpaceMgrXObject *>(g_lingo->_currentMe.u.obj);
+ g_lingo->printSTUBWithArglist("SpaceMgr::m_setCurData", nargs);
+ Datum view = g_lingo->pop();
+ Datum node = g_lingo->pop();
+ Datum space = g_lingo->pop();
+ Datum spaceCollection = g_lingo->pop();
+ if (spaceCollection.type != STRING ||
+ space.type != STRING ||
+ node.type != STRING ||
+ view.type != STRING) {
+ warning("SpaceMgr::m_setCurData: expected args to be a string");
+ g_lingo->push(Datum(0));
+ return;
+ }
+ me->_curSpaceCollection = *spaceCollection.u.s;
+ me->_curSpace = *space.u.s;
+ me->_curNode = *node.u.s;
+ me->_curView = *view.u.s;
g_lingo->push(Datum(0));
}
@@ -225,15 +385,41 @@ void SpaceMgr::m_removeSpaceCollection(int nargs) {
}
void SpaceMgr::m_setCurSpaceCollection(int nargs) {
- g_lingo->printSTUBWithArglist("SpaceMgr::m_setCurSpaceCollection", nargs);
- g_lingo->dropStack(nargs);
+ if (nargs != 1) {
+ warning("SpaceMgr::m_setCurSpaceCollection: expected 1 argument");
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(0));
+ return;
+ }
+ SpaceMgrXObject *me = static_cast<SpaceMgrXObject *>(g_lingo->_currentMe.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());
+ g_lingo->push(Datum(0));
+ return;
+
+ }
+ if (!spaceCollection.u.s->empty())
+ me->_curSpaceCollection = *spaceCollection.u.s;
+ debugC(5, kDebugXObj, "SpaceMgr::m_setCurSpaceCollection: %s", spaceCollection.u.s->c_str());
g_lingo->push(Datum(0));
}
void SpaceMgr::m_getCurSpaceCollection(int nargs) {
- g_lingo->printSTUBWithArglist("SpaceMgr::m_getCurSpaceCollection", nargs);
- g_lingo->dropStack(nargs);
- g_lingo->push(Datum(""));
+ if (nargs != 0) {
+ warning("SpaceMgr::m_getCurSpaceCollection: expected 0 arguments");
+ g_lingo->dropStack(nargs);
+ }
+ SpaceMgrXObject *me = static_cast<SpaceMgrXObject *>(g_lingo->_currentMe.u.obj);
+ Common::String result;
+ if (!me->_curSpaceCollection.empty()) {
+ if (me->_spaceCollections.contains(me->_curSpaceCollection)) {
+ result = "SPACECOLLECTION " + me->_curSpaceCollection;
+ }
+ }
+
+ debugC(5, kDebugXObj, "SpaceMgr::m_getCurSpaceCollection: %s", result.c_str());
+ g_lingo->push(Datum(result));
}
void SpaceMgr::m_getSpaceCollection(int nargs) {
@@ -255,15 +441,44 @@ void SpaceMgr::m_removeSpace(int nargs) {
}
void SpaceMgr::m_setCurSpace(int nargs) {
- g_lingo->printSTUBWithArglist("SpaceMgr::m_setCurSpace", nargs);
- g_lingo->dropStack(nargs);
+ if (nargs != 1) {
+ warning("SpaceMgr::m_setCurSpace: expected 1 argument");
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(0));
+ return;
+ }
+ SpaceMgrXObject *me = static_cast<SpaceMgrXObject *>(g_lingo->_currentMe.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());
+ g_lingo->push(Datum(0));
+ return;
+
+ }
+ if (!space.u.s->empty())
+ me->_curSpace = *space.u.s;
+ debugC(5, kDebugXObj, "SpaceMgr::m_setCurSpace: %s", space.u.s->c_str());
g_lingo->push(Datum(0));
}
void SpaceMgr::m_getCurSpace(int nargs) {
- g_lingo->printSTUBWithArglist("SpaceMgr::m_getCurSpace", nargs);
- g_lingo->dropStack(nargs);
- g_lingo->push(Datum(""));
+ if (nargs != 0) {
+ warning("SpaceMgr::m_getCurSpace: expected 0 arguments");
+ g_lingo->dropStack(nargs);
+ }
+ SpaceMgrXObject *me = static_cast<SpaceMgrXObject *>(g_lingo->_currentMe.u.obj);
+ Common::String result;
+ if (!me->_curSpaceCollection.empty()) {
+ if (me->_spaceCollections.contains(me->_curSpaceCollection)) {
+ SpaceCollection &sc = me->_spaceCollections.getVal(me->_curSpaceCollection);
+ if (sc.spaces.contains(me->_curSpace)) {
+ result = "SPACE " + me->_curSpace;
+ }
+ }
+ }
+
+ debugC(5, kDebugXObj, "SpaceMgr::m_getCurSpace: %s", result.c_str());
+ g_lingo->push(Datum(result));
}
void SpaceMgr::m_getSpace(int nargs) {
@@ -285,15 +500,46 @@ void SpaceMgr::m_removeNode(int nargs) {
}
void SpaceMgr::m_setCurNode(int nargs) {
- g_lingo->printSTUBWithArglist("SpaceMgr::m_setCurNode", nargs);
- g_lingo->dropStack(nargs);
+ if (nargs != 1) {
+ warning("SpaceMgr::m_setCurNode: expected 1 argument");
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(0));
+ return;
+ }
+ SpaceMgrXObject *me = static_cast<SpaceMgrXObject *>(g_lingo->_currentMe.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());
+ g_lingo->push(Datum(0));
+ return;
+
+ }
+ if (!node.u.s->empty())
+ me->_curNode = *node.u.s;
+ debugC(5, kDebugXObj, "SpaceMgr::m_setCurNode: %s", node.u.s->c_str());
g_lingo->push(Datum(0));
}
void SpaceMgr::m_getCurNode(int nargs) {
- g_lingo->printSTUBWithArglist("SpaceMgr::m_getCurNode", nargs);
- g_lingo->dropStack(nargs);
- g_lingo->push(Datum(""));
+ if (nargs != 0) {
+ warning("SpaceMgr::m_getCurNode: expected 0 arguments");
+ g_lingo->dropStack(nargs);
+ }
+ SpaceMgrXObject *me = static_cast<SpaceMgrXObject *>(g_lingo->_currentMe.u.obj);
+ Common::String result;
+ if (!me->_curView.empty()) {
+ if (me->_spaceCollections.contains(me->_curSpaceCollection)) {
+ SpaceCollection &sc = me->_spaceCollections.getVal(me->_curSpaceCollection);
+ if (sc.spaces.contains(me->_curSpace)) {
+ Space &s = sc.spaces.getVal(me->_curSpace);
+ if (s.nodes.contains(me->_curNode)) {
+ result = "NODE " + me->_curNode;
+ }
+ }
+ }
+ }
+ debugC(5, kDebugXObj, "SpaceMgr::m_getCurNode: %s", result.c_str());
+ g_lingo->push(Datum(result));
}
void SpaceMgr::m_getNode(int nargs) {
@@ -315,15 +561,50 @@ void SpaceMgr::m_removeView(int nargs) {
}
void SpaceMgr::m_setCurView(int nargs) {
- g_lingo->printSTUBWithArglist("SpaceMgr::m_setCurView", nargs);
- g_lingo->dropStack(nargs);
+ if (nargs != 1) {
+ warning("SpaceMgr::m_setCurView: expected 1 argument");
+ g_lingo->dropStack(nargs);
+ g_lingo->push(Datum(0));
+ return;
+ }
+ SpaceMgrXObject *me = static_cast<SpaceMgrXObject *>(g_lingo->_currentMe.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());
+ g_lingo->push(Datum(0));
+ return;
+
+ }
+ if (!view.u.s->empty())
+ me->_curView = *view.u.s;
+ debugC(5, kDebugXObj, "SpaceMgr::m_setCurView: %s", view.u.s->c_str());
g_lingo->push(Datum(0));
}
void SpaceMgr::m_getCurView(int nargs) {
- g_lingo->printSTUBWithArglist("SpaceMgr::m_getCurView", nargs);
- g_lingo->dropStack(nargs);
- g_lingo->push(Datum(""));
+ if (nargs != 0) {
+ warning("SpaceMgr::m_getCurView: expected 0 arguments");
+ g_lingo->dropStack(nargs);
+ }
+ SpaceMgrXObject *me = static_cast<SpaceMgrXObject *>(g_lingo->_currentMe.u.obj);
+ Common::String result;
+ if (!me->_curView.empty()) {
+ if (me->_spaceCollections.contains(me->_curSpaceCollection)) {
+ SpaceCollection &sc = me->_spaceCollections.getVal(me->_curSpaceCollection);
+ if (sc.spaces.contains(me->_curSpace)) {
+ Space &s = sc.spaces.getVal(me->_curSpace);
+ if (s.nodes.contains(me->_curNode)) {
+ Node &n = s.nodes.getVal(me->_curNode);
+ if (n.views.contains(me->_curView)) {
+ result = "VIEW " + me->_curView + " " + n.views[me->_curView];
+ }
+ }
+ }
+ }
+ }
+
+ debugC(5, kDebugXObj, "SpaceMgr::m_getCurView: %s", result.c_str());
+ g_lingo->push(Datum(result));
}
void SpaceMgr::m_getView(int nargs) {
@@ -386,4 +667,4 @@ void SpaceMgr::m_getGlobalLinks(int nargs) {
g_lingo->push(Datum(""));
}
-}
+} // End of namespace Director
diff --git a/engines/director/lingo/xlibs/spacemgr.h b/engines/director/lingo/xlibs/spacemgr.h
index 182a6dea28e..51744a15388 100644
--- a/engines/director/lingo/xlibs/spacemgr.h
+++ b/engines/director/lingo/xlibs/spacemgr.h
@@ -24,12 +24,19 @@
namespace Director {
-class SpaceMgrXObject : public Object<SpaceMgrXObject> {
-public:
- SpaceMgrXObject(ObjectType objType);
+namespace SpaceMgr {
+
+struct Node {
+ Common::HashMap<Common::String, Common::String> views;
};
-namespace SpaceMgr {
+struct Space {
+ Common::HashMap<Common::String, Node> nodes;
+};
+
+struct SpaceCollection {
+ Common::HashMap<Common::String, Space> spaces;
+};
extern const char *xlibName;
extern const char *fileNames[];
@@ -79,6 +86,18 @@ void m_getGlobalLinks(int nargs);
} // End of namespace SpaceMgr
+class SpaceMgrXObject : public Object<SpaceMgrXObject> {
+public:
+ SpaceMgrXObject(ObjectType objType);
+
+ Common::String _curSpaceCollection;
+ Common::String _curSpace;
+ Common::String _curNode;
+ Common::String _curView;
+ bool _checkForDups = false;
+
+ Common::HashMap<Common::String, SpaceMgr::SpaceCollection> _spaceCollections;
+};
} // End of namespace Director
#endif
Commit: 36e6246ddee3696b2fdc4125ab92959b86d77e91
https://github.com/scummvm/scummvm/commit/36e6246ddee3696b2fdc4125ab92959b86d77e91
Author: Scott Percival (code at moral.net.au)
Date: 2022-10-22T19:53:22+02:00
Commit Message:
DIRECTOR: Add bpvar command to debugger
Changed paths:
engines/director/debugger.cpp
engines/director/debugger.h
engines/director/lingo/lingo.cpp
diff --git a/engines/director/debugger.cpp b/engines/director/debugger.cpp
index c770864717b..8ac8555aa6d 100644
--- a/engines/director/debugger.cpp
+++ b/engines/director/debugger.cpp
@@ -84,6 +84,8 @@ Debugger::Debugger(): GUI::Debugger() {
registerCmd("bm", WRAP_METHOD(Debugger, cmdBpMovie));
registerCmd("bpframe", WRAP_METHOD(Debugger, cmdBpFrame));
registerCmd("bf", WRAP_METHOD(Debugger, cmdBpFrame));
+ registerCmd("bpvar", WRAP_METHOD(Debugger, cmdBpVar));
+ registerCmd("bv", WRAP_METHOD(Debugger, cmdBpVar));
registerCmd("bpdel", WRAP_METHOD(Debugger, cmdBpDel));
registerCmd("bpenable", WRAP_METHOD(Debugger, cmdBpEnable));
registerCmd("bpdisable", WRAP_METHOD(Debugger, cmdBpDisable));
@@ -105,6 +107,8 @@ Debugger::Debugger(): GUI::Debugger() {
_bpCheckMoviePath = false;
_bpNextMovieMatch = false;
_bpMatchScriptId = 0;
+ _bpCheckVarRead = false;
+ _bpCheckVarWrite = false;
}
Debugger::~Debugger() {
@@ -158,6 +162,8 @@ bool Debugger::cmdHelp(int argc, const char **argv) {
debugPrintf(" bpmovie / bm [moviePath] - Create a breakpoint on a switch to a movie\n");
debugPrintf(" bpframe / bf [frameId] - Create a breakpoint on a frame in the score\n");
debugPrintf(" bpframe / bf [moviePath] [frameId] - Create a breakpoint on a frame in the score of a specific movie\n");
+ debugPrintf(" bpvar / bv [varName] - Create a breakpoint on a Lingo variable being read or modified");
+ debugPrintf(" bpvar / bv [varName] [r/w/rw] - Create a breakpoint on a Lingo variable being accessed in a specific way");
debugPrintf(" bpdel [n] - Deletes a specific breakpoint\n");
debugPrintf(" bpenable [n] - Enables a specific breakpoint\n");
debugPrintf(" bpdisable [n] - Disables a specific breakpoint\n");
@@ -553,6 +559,34 @@ bool Debugger::cmdBpMovie(int argc, const char **argv) {
return true;
}
+bool Debugger::cmdBpVar(int argc, const char **argv) {
+ if (argc == 2 || argc == 3) {
+ Breakpoint bp;
+ bp.type = kBreakpointVariable;
+ bp.varName = argv[1];
+ if (argc == 3) {
+ Common::String props = argv[2];
+ bp.varRead = props.contains("r") || props.contains("R");
+ bp.varWrite = props.contains("w") || props.contains("W");
+ if (!(bp.varRead || bp.varWrite)) {
+ debugPrintf("Must specify r, w, or rw.");
+ return true;
+ }
+ } else {
+ bp.varRead = true;
+ bp.varWrite = true;
+ }
+ bp.id = _bpNextId;
+ _bpNextId++;
+ _breakpoints.push_back(bp);
+ bpUpdateState();
+ debugPrintf("Added %s\n", bp.format().c_str());
+ } else {
+ debugPrintf("Must specify a variable.\n");
+ }
+ return true;
+}
+
bool Debugger::cmdBpFrame(int argc, const char **argv) {
Movie *movie = g_director->getCurrentMovie();
if (argc == 2 || argc == 3) {
@@ -661,6 +695,8 @@ void Debugger::bpUpdateState() {
_bpMatchScriptId = 0;
_bpMatchMoviePath.clear();
_bpMatchFrameOffsets.clear();
+ _bpCheckVarRead = false;
+ _bpCheckVarWrite = false;
Movie *movie = g_director->getCurrentMovie();
Common::Array<CFrame *> &callstack = g_director->getCurrentWindow()->_callstack;
for (auto &it : _breakpoints) {
@@ -694,6 +730,9 @@ void Debugger::bpUpdateState() {
_bpMatchMoviePath = it.moviePath;
_bpMatchFrameOffsets.setVal(it.frameOffset, nullptr);
}
+ } else if (it.type == kBreakpointVariable) {
+ _bpCheckVarRead |= it.varRead;
+ _bpCheckVarWrite |= it.varWrite;
}
}
}
@@ -828,6 +867,40 @@ void Debugger::builtinHook(const Symbol &funcSym) {
bpTest(builtinMatch);
}
+void Debugger::varReadHook(const Common::String &name) {
+ if (name.empty())
+ return;
+ if (_bpCheckVarRead) {
+ for (auto &it : _breakpoints) {
+ if (it.type == kBreakpointVariable && it.varRead && it.varName.equalsIgnoreCase(name)) {
+ debugPrintf("Hit a breakpoint:\n");
+ debugPrintf("%s\n", it.format().c_str());
+ cmdScriptFrame(0, nullptr);
+ attach();
+ g_system->updateScreen();
+ break;
+ }
+ }
+ }
+}
+
+void Debugger::varWriteHook(const Common::String &name) {
+ if (name.empty())
+ return;
+ if (_bpCheckVarWrite) {
+ for (auto &it : _breakpoints) {
+ if (it.type == kBreakpointVariable && it.varWrite && it.varName.equalsIgnoreCase(name)) {
+ debugPrintf("Hit a breakpoint:\n");
+ debugPrintf("%s\n", it.format().c_str());
+ cmdScriptFrame(0, nullptr);
+ attach();
+ g_system->updateScreen();
+ break;
+ }
+ }
+ }
+}
+
void Debugger::debugLogFile(Common::String logs, bool prompt) {
if (prompt)
debugPrintf("-- %s", logs.c_str());
diff --git a/engines/director/debugger.h b/engines/director/debugger.h
index 014819a10bd..648bda4c07c 100644
--- a/engines/director/debugger.h
+++ b/engines/director/debugger.h
@@ -35,6 +35,7 @@ enum BreakpointType {
kBreakpointFunction = 1,
kBreakpointMovie = 2,
kBreakpointMovieFrame = 3,
+ kBreakpointVariable = 4,
};
struct Breakpoint {
@@ -47,6 +48,9 @@ struct Breakpoint {
uint funcOffset = 0;
Common::String moviePath;
uint frameOffset = 0;
+ Common::String varName;
+ bool varRead = false;
+ bool varWrite = false;
Common::String format() {
Common::String result = Common::String::format("Breakpoint %d, ", id);
@@ -60,13 +64,13 @@ struct Breakpoint {
result += Common::String::format(" [%5d]", funcOffset);
break;
case kBreakpointMovie:
- result += "Movie ";
- result += moviePath;
+ result += Common::String::format("Movie %s", moviePath.c_str());
break;
case kBreakpointMovieFrame:
- result += "Movie ";
- result += moviePath;
- result += Common::String::format(":%d", frameOffset);
+ result += Common::String::format("Movie %s:%d", moviePath.c_str(), frameOffset);
+ break;
+ case kBreakpointVariable:
+ result += Common::String::format("Variable %s:%s%s", varName.c_str(), varRead ? "r" : "", varWrite ? "w" : "");
break;
default:
break;
@@ -87,6 +91,8 @@ public:
void pushContextHook();
void popContextHook();
void builtinHook(const Symbol &funcSym);
+ void varReadHook(const Common::String &varName);
+ void varWriteHook(const Common::String &varName);
private:
bool cmdHelp(int argc, const char **argv);
@@ -112,6 +118,7 @@ private:
bool cmdBpSet(int argc, const char **argv);
bool cmdBpMovie(int argc, const char **argv);
bool cmdBpFrame(int argc, const char **argv);
+ bool cmdBpVar(int argc, const char **argv);
bool cmdBpDel(int argc, const char **argv);
bool cmdBpEnable(int argc, const char **argv);
bool cmdBpDisable(int argc, const char **argv);
@@ -146,6 +153,8 @@ private:
Common::String _bpMatchMoviePath;
Common::HashMap<uint, void *> _bpMatchFuncOffsets;
Common::HashMap<uint, void *> _bpMatchFrameOffsets;
+ bool _bpCheckVarRead;
+ bool _bpCheckVarWrite;
};
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index 9c0ce9a19ec..2c9302f2fac 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -1418,13 +1418,16 @@ void Lingo::varAssign(const Datum &var, const Datum &value) {
Common::String name = *var.u.s;
if (_localvars && _localvars->contains(name)) {
(*_localvars)[name] = value;
+ g_debugger->varWriteHook(name);
return;
}
if (_currentMe.type == OBJECT && _currentMe.u.obj->hasProp(name)) {
_currentMe.u.obj->setProp(name, value);
+ g_debugger->varWriteHook(name);
return;
}
_globalvars[name] = value;
+ g_debugger->varWriteHook(name);
}
break;
case GLOBALREF:
@@ -1439,6 +1442,7 @@ void Lingo::varAssign(const Datum &var, const Datum &value) {
Common::String name = *var.u.s;
if (_localvars && _localvars->contains(name)) {
(*_localvars)[name] = value;
+ g_debugger->varWriteHook(name);
} else {
warning("varAssign: local variable %s not defined", name.c_str());
}
@@ -1449,6 +1453,7 @@ void Lingo::varAssign(const Datum &var, const Datum &value) {
Common::String name = *var.u.s;
if (_currentMe.type == OBJECT && _currentMe.u.obj->hasProp(name)) {
_currentMe.u.obj->setProp(name, value);
+ g_debugger->varWriteHook(name);
} else {
warning("varAssign: property %s not defined", name.c_str());
}
@@ -1528,6 +1533,7 @@ Datum Lingo::varFetch(const Datum &var, bool silent) {
{
Datum d;
Common::String name = *var.u.s;
+ g_debugger->varReadHook(name);
if (_localvars && _localvars->contains(name)) {
return (*_localvars)[name];
@@ -1547,6 +1553,7 @@ Datum Lingo::varFetch(const Datum &var, bool silent) {
case GLOBALREF:
{
Common::String name = *var.u.s;
+ g_debugger->varReadHook(name);
if (_globalvars.contains(name)) {
return _globalvars[name];
}
@@ -1557,6 +1564,7 @@ Datum Lingo::varFetch(const Datum &var, bool silent) {
case LOCALREF:
{
Common::String name = *var.u.s;
+ g_debugger->varReadHook(name);
if (_localvars && _localvars->contains(name)) {
return (*_localvars)[name];
}
@@ -1567,6 +1575,7 @@ Datum Lingo::varFetch(const Datum &var, bool silent) {
case PROPREF:
{
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);
}
Commit: 4c306fbfd9ac3dc056935dc4f28c090268bde830
https://github.com/scummvm/scummvm/commit/4c306fbfd9ac3dc056935dc4f28c090268bde830
Author: Scott Percival (code at moral.net.au)
Date: 2022-10-22T19:53:22+02:00
Commit Message:
DIRECTOR: Fix Lingo REPL mode in debugger
Changed paths:
engines/director/debugger.cpp
engines/director/debugger.h
engines/director/lingo/lingo-builtins.cpp
diff --git a/engines/director/debugger.cpp b/engines/director/debugger.cpp
index 8ac8555aa6d..d0e5817cc6c 100644
--- a/engines/director/debugger.cpp
+++ b/engines/director/debugger.cpp
@@ -57,6 +57,8 @@ Debugger::Debugger(): GUI::Debugger() {
registerCmd("nextmovie", WRAP_METHOD(Debugger, cmdNextMovie));
registerCmd("nm", WRAP_METHOD(Debugger, cmdNextMovie));
+ registerCmd("print", WRAP_METHOD(Debugger, cmdPrint));
+ registerCmd("p", WRAP_METHOD(Debugger, cmdPrint));
registerCmd("repl", WRAP_METHOD(Debugger, cmdRepl));
registerCmd("stack", WRAP_METHOD(Debugger, cmdStack));
registerCmd("st", WRAP_METHOD(Debugger, cmdStack));
@@ -100,8 +102,8 @@ Debugger::Debugger(): GUI::Debugger() {
_finishCounter = 0;
_next = false;
_nextCounter = 0;
- _nextFrame = false;
- _nextFrameCounter = 0;
+ _lingoEval = false;
+ _lingoReplMode = false;
_bpNextId = 1;
_bpCheckFunc = false;
_bpCheckMoviePath = false;
@@ -138,8 +140,8 @@ bool Debugger::cmdHelp(int argc, const char **argv) {
debugPrintf(" nextmovie / nm - Steps forward until the next change of movie\n");
debugPrintf("\n");
debugPrintf("Lingo execution:\n");
- //debugPrintf(" eval [statement] - Evaluates a single Lingo statement\n");
- debugPrintf(" repl - Switches to a REPL interface for evaluating Lingo code\n");
+ debugPrintf(" print / p [statement] - Evaluates a single Lingo statement\n");
+ debugPrintf(" repl - Switches to a REPL interface for evaluating Lingo statements\n");
debugPrintf(" backtrace / bt - Prints a backtrace of all stack frames\n");
debugPrintf(" disasm / da [scriptId:funcName] - Lists the bytecode disassembly for a script function\n");
debugPrintf(" disasm / da all - Lists the bytecode disassembly for all available script functions\n");
@@ -277,9 +279,24 @@ bool Debugger::cmdNextMovie(int argc, const char **argv) {
return cmdExit(0, nullptr);
}
+bool Debugger::cmdPrint(int argc, const char **argv) {
+ if (argc == 1) {
+ debugPrintf("Missing expression");
+ return true;
+ }
+ Common::String command;
+ for (int i = 1; i < argc; i++) {
+ command += " ";
+ command += argv[i];
+ }
+ command.trim();
+ return lingoEval(command.c_str());
+}
+
bool Debugger::cmdRepl(int argc, const char **argv) {
debugPrintf("Switching to Lingo REPL mode, type 'lingo off' to return to the debug console.\n");
registerDefaultCmd(WRAP_DEFAULTCOMMAND(Debugger, lingoCommandProcessor));
+ _lingoReplMode = true;
debugPrintf(PROMPT);
return true;
}
@@ -738,6 +755,11 @@ void Debugger::bpUpdateState() {
}
void Debugger::bpTest(bool forceCheck) {
+ // don't check for breakpoints if we're in eval mode
+ if (_lingoEval)
+ return;
+
+ // Check if there's a funcName/offset or frame/movie match
bool stop = forceCheck;
uint funcOffset = g_lingo->_pc;
Score *score = g_director->getCurrentMovie()->getScore();
@@ -748,6 +770,8 @@ void Debugger::bpTest(bool forceCheck) {
if (_bpCheckMoviePath) {
stop |= _bpMatchFrameOffsets.contains(frameOffset);
}
+
+ // Print the breakpoints that matched
if (stop) {
debugPrintf("Hit a breakpoint:\n");
for (auto &it : _breakpoints) {
@@ -776,17 +800,30 @@ void Debugger::bpTest(bool forceCheck) {
bool Debugger::lingoCommandProcessor(const char *inputOrig) {
if (!strcmp(inputOrig, "lingo off")) {
registerDefaultCmd(nullptr);
+ _lingoReplMode = false;
return true;
}
+ return lingoEval(inputOrig);
+}
- Common::String expr = Common::String(inputOrig);
+bool Debugger::lingoEval(const char *inputOrig) {
+ Common::String inputSan = inputOrig;
+ inputSan.trim();
+ if (inputSan.empty())
+ return true;
+ Common::String expr = Common::String::format("return %s", inputSan.c_str());
// Compile the code to an anonymous function and call it
ScriptContext *sc = g_lingo->_compiler->compileAnonymous(expr);
+ if (!sc) {
+ debugPrintf("Failed to parse expression!\n%s", _lingoReplMode ? PROMPT : "");
+ return true;
+ }
Symbol sym = sc->_eventHandlers[kEventGeneric];
- LC::call(sym, 0, false);
- g_lingo->execute();
- debugPrintf(PROMPT);
- return true;
+ _lingoEval = true;
+ LC::call(sym, 0, true);
+ _finish = true;
+ _finishCounter = 1;
+ return cmdExit(0, nullptr);
}
void Debugger::stepHook() {
@@ -803,7 +840,13 @@ void Debugger::stepHook() {
}
if (_finish && _finishCounter == 0) {
_finish = false;
- cmdScriptFrame(0, nullptr);
+ if (_lingoEval) {
+ _lingoEval = false;
+ Datum result = g_lingo->pop();
+ debugPrintf("%s\n\n%s", result.asString(true).c_str(), _lingoReplMode ? PROMPT : "");
+ } else {
+ cmdScriptFrame(0, nullptr);
+ }
attach();
g_system->updateScreen();
}
diff --git a/engines/director/debugger.h b/engines/director/debugger.h
index 648bda4c07c..6798671c486 100644
--- a/engines/director/debugger.h
+++ b/engines/director/debugger.h
@@ -104,6 +104,7 @@ private:
bool cmdCast(int argc, const char **argv);
bool cmdNextFrame(int argc, const char **argv);
bool cmdNextMovie(int argc, const char **argv);
+ bool cmdPrint(int argc, const char **argv);
bool cmdRepl(int argc, const char **argv);
bool cmdBacktrace(int argc, const char **argv);
bool cmdDisasm(int argc, const char **argv);
@@ -128,6 +129,7 @@ private:
void bpTest(bool forceCheck = false);
bool lingoCommandProcessor(const char *inputOrig);
+ bool lingoEval(const char *inputOrig);
Common::DumpFile _out;
@@ -142,6 +144,8 @@ private:
int _finishCounter;
bool _next;
int _nextCounter;
+ bool _lingoEval;
+ bool _lingoReplMode;
Common::Array<Breakpoint> _breakpoints;
int _bpNextId;
diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index dad2e4190fc..dcd8602a2f8 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -547,6 +547,11 @@ void LB::b_value(int nargs) {
Common::String code = "return " + expr;
// Compile the code to an anonymous function and call it
ScriptContext *sc = g_lingo->_compiler->compileAnonymous(code);
+ if (!sc) {
+ warning("b_value(): Failed to parse expression \"%s\", returning 0", expr.c_str());
+ g_lingo->push(Datum(0));
+ return;
+ }
Symbol sym = sc->_eventHandlers[kEventGeneric];
LC::call(sym, 0, true);
}
Commit: 9c3de4c269b4edb804a791c21883009d26b67f36
https://github.com/scummvm/scummvm/commit/9c3de4c269b4edb804a791c21883009d26b67f36
Author: Scott Percival (code at moral.net.au)
Date: 2022-10-22T19:53:22+02:00
Commit Message:
DIRECTOR: Make "the pathName" return an absolute path
In Director, Lingo calls to fetch "the pathName" would provide an absolute
path, including the volume. getCurrentPath() originally provided a
relative path, which meant root level would return "". There is at least
one title that checks "the pathName" isn't blank as part of the content
detection routine. Given that from an internal perspective,
getCurrentPath() is always an absolute path from the game root, we can
add a fake drive letter for Windows at the front.
Fixes loading in DEVO Presents: Adventures of the Smart Patrol.
Changed paths:
engines/director/director.cpp
engines/director/director.h
engines/director/lingo/lingo-the.cpp
diff --git a/engines/director/director.cpp b/engines/director/director.cpp
index 944b5363c1c..f3a9dcea0c3 100644
--- a/engines/director/director.cpp
+++ b/engines/director/director.cpp
@@ -148,6 +148,13 @@ DirectorEngine::~DirectorEngine() {
Archive *DirectorEngine::getMainArchive() const { return _currentWindow->getMainArchive(); }
Movie *DirectorEngine::getCurrentMovie() const { return _currentWindow->getCurrentMovie(); }
Common::String DirectorEngine::getCurrentPath() const { return _currentWindow->getCurrentPath(); }
+Common::String DirectorEngine::getCurrentAbsolutePath() {
+ Common::String currentPath = getCurrentPath();
+ Common::String result;
+ result += (getPlatform() == Common::kPlatformWindows) ? "C:\\" : "";
+ result += convertPath(currentPath);
+ return result;
+}
static bool buildbotErrorHandler(const char *msg) { return true; }
diff --git a/engines/director/director.h b/engines/director/director.h
index 656bd6d560b..e6ee3f82ec9 100644
--- a/engines/director/director.h
+++ b/engines/director/director.h
@@ -176,6 +176,7 @@ public:
Movie *getCurrentMovie() const;
void setCurrentMovie(Movie *movie);
Common::String getCurrentPath() const;
+ Common::String getCurrentAbsolutePath();
Common::String getStartupPath() const;
// graphics.cpp
diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp
index d63d73a1426..3864adffef0 100644
--- a/engines/director/lingo/lingo-the.cpp
+++ b/engines/director/lingo/lingo-the.cpp
@@ -708,7 +708,7 @@ Datum Lingo::getTheEntity(int entity, Datum &id, int field) {
case kTheMoviePath:
case kThePathName:
d.type = STRING;
- d.u.s = new Common::String(_vm->getCurrentPath());
+ d.u.s = new Common::String(_vm->getCurrentAbsolutePath());
break;
case kTheMultiSound:
// We always support multiple sound channels!
Commit: bd3b24d4376a840b2641faebb5b8e00f4eb59628
https://github.com/scummvm/scummvm/commit/bd3b24d4376a840b2641faebb5b8e00f4eb59628
Author: Scott Percival (code at moral.net.au)
Date: 2022-10-22T19:53:22+02:00
Commit Message:
DIRECTOR: Add bpentity command to debugger
Changed paths:
engines/director/debugger.cpp
engines/director/debugger.h
engines/director/lingo/lingo-the.cpp
diff --git a/engines/director/debugger.cpp b/engines/director/debugger.cpp
index d0e5817cc6c..de9fedc059f 100644
--- a/engines/director/debugger.cpp
+++ b/engines/director/debugger.cpp
@@ -31,8 +31,9 @@
#include "director/window.h"
#include "director/lingo/lingo.h"
#include "director/lingo/lingo-code.h"
-#include "director/lingo/lingo-object.h"
#include "director/lingo/lingo-codegen.h"
+#include "director/lingo/lingo-object.h"
+#include "director/lingo/lingo-the.h"
namespace Director {
@@ -86,6 +87,8 @@ Debugger::Debugger(): GUI::Debugger() {
registerCmd("bm", WRAP_METHOD(Debugger, cmdBpMovie));
registerCmd("bpframe", WRAP_METHOD(Debugger, cmdBpFrame));
registerCmd("bf", WRAP_METHOD(Debugger, cmdBpFrame));
+ registerCmd("bpentity", WRAP_METHOD(Debugger, cmdBpEntity));
+ registerCmd("be", WRAP_METHOD(Debugger, cmdBpEntity));
registerCmd("bpvar", WRAP_METHOD(Debugger, cmdBpVar));
registerCmd("bv", WRAP_METHOD(Debugger, cmdBpVar));
registerCmd("bpdel", WRAP_METHOD(Debugger, cmdBpDel));
@@ -111,6 +114,8 @@ Debugger::Debugger(): GUI::Debugger() {
_bpMatchScriptId = 0;
_bpCheckVarRead = false;
_bpCheckVarWrite = false;
+ _bpCheckEntityRead = false;
+ _bpCheckEntityWrite = false;
}
Debugger::~Debugger() {
@@ -164,6 +169,10 @@ bool Debugger::cmdHelp(int argc, const char **argv) {
debugPrintf(" bpmovie / bm [moviePath] - Create a breakpoint on a switch to a movie\n");
debugPrintf(" bpframe / bf [frameId] - Create a breakpoint on a frame in the score\n");
debugPrintf(" bpframe / bf [moviePath] [frameId] - Create a breakpoint on a frame in the score of a specific movie\n");
+ debugPrintf(" bpentity / be [entityName] - Create a breakpoint on a Lingo \"the\" entity being read or modified");
+ debugPrintf(" bpentity / be [entityName] [r/w/rw] - Create a breakpoint on a Lingo \"the\" entity being accessed in a specific way");
+ debugPrintf(" bpentity / be [entityName:fieldName] - Create a breakpoint on a Lingo \"the\" field being read or modified");
+ debugPrintf(" bpentity / be [entityName:fieldName] [r/w/rw] - Create a breakpoint on a Lingo \"the\" field being accessed in a specific way");
debugPrintf(" bpvar / bv [varName] - Create a breakpoint on a Lingo variable being read or modified");
debugPrintf(" bpvar / bv [varName] [r/w/rw] - Create a breakpoint on a Lingo variable being accessed in a specific way");
debugPrintf(" bpdel [n] - Deletes a specific breakpoint\n");
@@ -576,6 +585,54 @@ bool Debugger::cmdBpMovie(int argc, const char **argv) {
return true;
}
+bool Debugger::cmdBpEntity(int argc, const char **argv) {
+ if (argc == 2 || argc == 3) {
+ Breakpoint bp;
+ bp.type = kBreakpointEntity;
+ Common::String entityName = Common::String(argv[1]);
+ Common::String fieldName;
+ uint splitPoint = entityName.findFirstOf(":");
+ if (splitPoint != Common::String::npos) {
+ fieldName = entityName.substr(splitPoint + 1, Common::String::npos);
+ entityName = entityName.substr(0, splitPoint);
+ }
+ if (!g_lingo->_theEntities.contains(entityName)) {
+ debugPrintf("Entity %s not found.\n", entityName.c_str());
+ return true;
+ }
+ bp.entity = g_lingo->_theEntities[entityName]->entity;
+ if (!fieldName.empty()) {
+ Common::String target = Common::String::format("%d%s", bp.entity, fieldName.c_str());
+ if (!g_lingo->_theEntityFields.contains(target)) {
+ debugPrintf("Field %s not found for entity %s.\n", fieldName.c_str(), entityName.c_str());
+ return true;
+ }
+ bp.field = g_lingo->_theEntityFields[target]->field;
+ }
+
+ if (argc == 3) {
+ Common::String props = argv[2];
+ bp.varRead = props.contains("r") || props.contains("R");
+ bp.varWrite = props.contains("w") || props.contains("W");
+ if (!(bp.varRead || bp.varWrite)) {
+ debugPrintf("Must specify r, w, or rw.\n");
+ return true;
+ }
+ } else {
+ bp.varRead = true;
+ bp.varWrite = true;
+ }
+ bp.id = _bpNextId;
+ _bpNextId++;
+ _breakpoints.push_back(bp);
+ bpUpdateState();
+ debugPrintf("Added %s\n", bp.format().c_str());
+ } else {
+ debugPrintf("Must specify a variable.\n");
+ }
+ return true;
+}
+
bool Debugger::cmdBpVar(int argc, const char **argv) {
if (argc == 2 || argc == 3) {
Breakpoint bp;
@@ -714,6 +771,8 @@ void Debugger::bpUpdateState() {
_bpMatchFrameOffsets.clear();
_bpCheckVarRead = false;
_bpCheckVarWrite = false;
+ _bpCheckEntityRead = false;
+ _bpCheckEntityWrite = false;
Movie *movie = g_director->getCurrentMovie();
Common::Array<CFrame *> &callstack = g_director->getCurrentWindow()->_callstack;
for (auto &it : _breakpoints) {
@@ -750,6 +809,9 @@ void Debugger::bpUpdateState() {
} else if (it.type == kBreakpointVariable) {
_bpCheckVarRead |= it.varRead;
_bpCheckVarWrite |= it.varWrite;
+ } else if (it.type == kBreakpointEntity) {
+ _bpCheckEntityRead |= it.varRead;
+ _bpCheckEntityWrite |= it.varWrite;
}
}
}
@@ -944,6 +1006,36 @@ void Debugger::varWriteHook(const Common::String &name) {
}
}
+void Debugger::entityReadHook(int entity, int field) {
+ if (_bpCheckEntityRead) {
+ for (auto &it : _breakpoints) {
+ if (it.type == kBreakpointEntity && it.varRead && it.entity == entity && it.field == field) {
+ debugPrintf("Hit a breakpoint:\n");
+ debugPrintf("%s\n", it.format().c_str());
+ cmdScriptFrame(0, nullptr);
+ attach();
+ g_system->updateScreen();
+ break;
+ }
+ }
+ }
+}
+
+void Debugger::entityWriteHook(int entity, int field) {
+ if (_bpCheckEntityWrite) {
+ for (auto &it : _breakpoints) {
+ if (it.type == kBreakpointEntity && it.varWrite && it.entity == entity && it.field == field) {
+ debugPrintf("Hit a breakpoint:\n");
+ debugPrintf("%s\n", it.format().c_str());
+ cmdScriptFrame(0, nullptr);
+ attach();
+ g_system->updateScreen();
+ break;
+ }
+ }
+ }
+}
+
void Debugger::debugLogFile(Common::String logs, bool prompt) {
if (prompt)
debugPrintf("-- %s", logs.c_str());
diff --git a/engines/director/debugger.h b/engines/director/debugger.h
index 6798671c486..a1fa5aea017 100644
--- a/engines/director/debugger.h
+++ b/engines/director/debugger.h
@@ -36,6 +36,7 @@ enum BreakpointType {
kBreakpointMovie = 2,
kBreakpointMovieFrame = 3,
kBreakpointVariable = 4,
+ kBreakpointEntity = 5,
};
struct Breakpoint {
@@ -49,6 +50,8 @@ struct Breakpoint {
Common::String moviePath;
uint frameOffset = 0;
Common::String varName;
+ int entity = 0;
+ int field = 0;
bool varRead = false;
bool varWrite = false;
@@ -64,14 +67,24 @@ struct Breakpoint {
result += Common::String::format(" [%5d]", funcOffset);
break;
case kBreakpointMovie:
- result += Common::String::format("Movie %s", moviePath.c_str());
+ result += "Movie " + moviePath;
break;
case kBreakpointMovieFrame:
result += Common::String::format("Movie %s:%d", moviePath.c_str(), frameOffset);
break;
case kBreakpointVariable:
- result += Common::String::format("Variable %s:%s%s", varName.c_str(), varRead ? "r" : "", varWrite ? "w" : "");
+ result += "Variable "+ varName + ":";
+ result += varRead ? "r" : "";
+ result += varWrite ? "w" : "";
break;
+ case kBreakpointEntity:
+ result += "Entity ";
+ result += g_lingo->entity2str(entity);
+ result += field ? ":" : "";
+ result += field ? g_lingo->field2str(field) : "";
+ result += ":";
+ result += varRead ? "r" : "";
+ result += varWrite ? "w" : "";
default:
break;
}
@@ -93,6 +106,8 @@ public:
void builtinHook(const Symbol &funcSym);
void varReadHook(const Common::String &varName);
void varWriteHook(const Common::String &varName);
+ void entityReadHook(int entity, int field);
+ void entityWriteHook(int entity, int field);
private:
bool cmdHelp(int argc, const char **argv);
@@ -119,6 +134,7 @@ private:
bool cmdBpSet(int argc, const char **argv);
bool cmdBpMovie(int argc, const char **argv);
bool cmdBpFrame(int argc, const char **argv);
+ bool cmdBpEntity(int argc, const char **argv);
bool cmdBpVar(int argc, const char **argv);
bool cmdBpDel(int argc, const char **argv);
bool cmdBpEnable(int argc, const char **argv);
@@ -159,6 +175,8 @@ private:
Common::HashMap<uint, void *> _bpMatchFrameOffsets;
bool _bpCheckVarRead;
bool _bpCheckVarWrite;
+ bool _bpCheckEntityRead;
+ bool _bpCheckEntityWrite;
};
diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp
index 3864adffef0..6f0e4057c1c 100644
--- a/engines/director/lingo/lingo-the.cpp
+++ b/engines/director/lingo/lingo-the.cpp
@@ -372,6 +372,8 @@ Datum Lingo::getTheEntity(int entity, Datum &id, int field) {
return d;
}
+ g_debugger->entityReadHook(entity, field);
+
LingoArchive *mainArchive = movie->getMainLingoArch();
Score *score = movie->getScore();
@@ -1203,6 +1205,7 @@ void Lingo::setTheEntity(int entity, Datum &id, int field, Datum &d) {
default:
warning("Lingo::setTheEntity(): Unprocessed setting field \"%s\" of entity %s", field2str(field), entity2str(entity));
}
+ g_debugger->entityWriteHook(entity, field);
}
int Lingo::getMenuNum() {
More information about the Scummvm-git-logs
mailing list