[Scummvm-git-logs] scummvm master -> 82605cc3ac34f589daf8e01d13cd3a9ec10ead34
sev-
noreply at scummvm.org
Wed Sep 28 15:07:14 UTC 2022
This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
2874f05eb3 DIRECTOR: Implement movie and nextmovie debugger commands
82605cc3ac DIRECTOR: Implement breakpoints
Commit: 2874f05eb3e0cea95e1d473aa0ed43faecc58e3e
https://github.com/scummvm/scummvm/commit/2874f05eb3e0cea95e1d473aa0ed43faecc58e3e
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-28T17:07:07+02:00
Commit Message:
DIRECTOR: Implement movie and nextmovie debugger commands
Changed paths:
engines/director/debugger.cpp
engines/director/debugger.h
engines/director/window.cpp
diff --git a/engines/director/debugger.cpp b/engines/director/debugger.cpp
index 2aceab6a9df..72b21e72b6b 100644
--- a/engines/director/debugger.cpp
+++ b/engines/director/debugger.cpp
@@ -45,6 +45,8 @@ Debugger::Debugger(): GUI::Debugger() {
registerCmd("help", WRAP_METHOD(Debugger, cmdHelp));
registerCmd("version", WRAP_METHOD(Debugger, cmdVersion));
+ registerCmd("movie", WRAP_METHOD(Debugger, cmdMovie));
+ registerCmd("m", WRAP_METHOD(Debugger, cmdMovie));
registerCmd("frame", WRAP_METHOD(Debugger, cmdFrame));
registerCmd("f", WRAP_METHOD(Debugger, cmdFrame));
registerCmd("channels", WRAP_METHOD(Debugger, cmdChannels));
@@ -52,6 +54,8 @@ Debugger::Debugger(): GUI::Debugger() {
registerCmd("cast", WRAP_METHOD(Debugger, cmdCast));
registerCmd("nextframe", WRAP_METHOD(Debugger, cmdNextFrame));
registerCmd("nf", WRAP_METHOD(Debugger, cmdNextFrame));
+ registerCmd("nextmovie", WRAP_METHOD(Debugger, cmdNextMovie));
+ registerCmd("nm", WRAP_METHOD(Debugger, cmdNextMovie));
registerCmd("repl", WRAP_METHOD(Debugger, cmdRepl));
registerCmd("stack", WRAP_METHOD(Debugger, cmdStack));
@@ -70,7 +74,12 @@ Debugger::Debugger(): GUI::Debugger() {
registerCmd("n", WRAP_METHOD(Debugger, cmdNext));
registerCmd("finish", WRAP_METHOD(Debugger, cmdFinish));
registerCmd("fin", WRAP_METHOD(Debugger, cmdFinish));
+ registerCmd("continue", WRAP_METHOD(Debugger, cmdExit));
+ registerCmd("c", WRAP_METHOD(Debugger, cmdExit));
+ _nextFrame = false;
+ _nextFrameCounter = 0;
+ _nextMovie = false;
_step = false;
_stepCounter = 0;
_finish = false;
@@ -99,13 +108,13 @@ bool Debugger::cmdHelp(int argc, const char **argv) {
debugPrintf("--------\n");
debugPrintf("Player:\n");
debugPrintf(" version - Shows the Director version\n");
- //debugPrintf(" movie [moviePath] - Get or sets the current movie\n");
- //debugPrintf(" movieinfo - Show information for the current movie\n");
+ debugPrintf(" movie / m [moviePath] - Get or sets the current movie\n");
+ //debugPrintf(" movieinfo / mi - Show information for the current movie\n");
debugPrintf(" frame / f [frameNum] - Gets or sets the current score frame\n");
debugPrintf(" channels / chan [frameNum] - Shows channel information for a score frame\n");
debugPrintf(" cast [castNum] - Shows the cast list or castNum for the current movie\n");
debugPrintf(" nextframe / nf [n] - Steps forward one or more score frames\n");
- //debugPrintf(" nextmovie / nm - Steps forward until the next change of movie\n");
+ 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");
@@ -119,6 +128,7 @@ bool Debugger::cmdHelp(int argc, const char **argv) {
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");
+ debugPrintf(" continue / c - Continues execution\n");
debugPrintf("\n");
debugPrintf("Breakpoints:\n");
debugPrintf("\n");
@@ -165,6 +175,18 @@ bool Debugger::cmdFrame(int argc, const char **argv) {
return true;
}
+bool Debugger::cmdMovie(int argc, const char **argv) {
+ Lingo *lingo = g_director->getLingo();
+ Movie *movie = g_director->getCurrentMovie();
+ if (argc == 2) {
+ Datum frame, mov(argv[1]);
+ lingo->func_goto(frame, mov);
+ } else {
+ debugPrintf("%s\n", movie->getArchive()->getFileName().c_str());
+ }
+ return true;
+}
+
bool Debugger::cmdChannels(int argc, const char **argv) {
Score *score = g_director->getCurrentMovie()->getScore();
@@ -223,6 +245,11 @@ bool Debugger::cmdNextFrame(int argc, const char **argv) {
return cmdExit(0, nullptr);
}
+bool Debugger::cmdNextMovie(int argc, const char **argv) {
+ _nextMovie = true;
+ return cmdExit(0, nullptr);
+}
+
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));
@@ -413,6 +440,15 @@ void Debugger::frameHook() {
}
}
+void Debugger::movieHook() {
+ if (_nextMovie) {
+ _nextMovie = false;
+ cmdMovie(0, nullptr);
+ attach();
+ g_system->updateScreen();
+ }
+}
+
void Debugger::pushContextHook() {
if (_next)
_nextCounter++;
diff --git a/engines/director/debugger.h b/engines/director/debugger.h
index aa39940a2bb..8f2eec25152 100644
--- a/engines/director/debugger.h
+++ b/engines/director/debugger.h
@@ -34,6 +34,7 @@ public:
void debugLogFile(Common::String logs, bool prompt);
void stepHook();
void frameHook();
+ void movieHook();
void pushContextHook();
void popContextHook();
@@ -41,10 +42,12 @@ private:
bool cmdHelp(int argc, const char **argv);
bool cmdVersion(int argc, const char **argv);
+ bool cmdMovie(int argc, const char **argv);
bool cmdFrame(int argc, const char **argv);
bool cmdChannels(int argc, const char **argv);
bool cmdCast(int argc, const char **argv);
bool cmdNextFrame(int argc, const char **argv);
+ bool cmdNextMovie(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);
@@ -64,6 +67,7 @@ private:
bool _nextFrame;
int _nextFrameCounter;
+ bool _nextMovie;
bool _step;
int _stepCounter;
bool _finish;
diff --git a/engines/director/window.cpp b/engines/director/window.cpp
index 01616ba1819..80e9435d835 100644
--- a/engines/director/window.cpp
+++ b/engines/director/window.cpp
@@ -377,6 +377,7 @@ bool Window::step() {
_nextMovie.frameI = -1;
}
+
if (!debugChannelSet(-1, kDebugCompileOnly) && goodMovie) {
debugC(1, kDebugEvents, "Starting playback of movie '%s'", _currentMovie->getMacName().c_str());
_currentMovie->getScore()->startPlay();
@@ -384,6 +385,7 @@ bool Window::step() {
_currentMovie->getScore()->setCurrentFrame(_startFrame);
_startFrame = -1;
}
+ g_debugger->movieHook();
} else {
return false;
}
Commit: 82605cc3ac34f589daf8e01d13cd3a9ec10ead34
https://github.com/scummvm/scummvm/commit/82605cc3ac34f589daf8e01d13cd3a9ec10ead34
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-28T17:07:07+02:00
Commit Message:
DIRECTOR: Implement breakpoints
Changed paths:
engines/director/debugger.cpp
engines/director/debugger.h
engines/director/lingo/lingo-code.cpp
engines/director/lingo/lingo.cpp
diff --git a/engines/director/debugger.cpp b/engines/director/debugger.cpp
index 72b21e72b6b..a7281c163fd 100644
--- a/engines/director/debugger.cpp
+++ b/engines/director/debugger.cpp
@@ -77,6 +77,17 @@ Debugger::Debugger(): GUI::Debugger() {
registerCmd("continue", WRAP_METHOD(Debugger, cmdExit));
registerCmd("c", WRAP_METHOD(Debugger, cmdExit));
+ registerCmd("bpset", WRAP_METHOD(Debugger, cmdBpSet));
+ registerCmd("b", WRAP_METHOD(Debugger, cmdBpSet));
+ registerCmd("bpmovie", WRAP_METHOD(Debugger, cmdBpMovie));
+ registerCmd("bm", WRAP_METHOD(Debugger, cmdBpMovie));
+ registerCmd("bpframe", WRAP_METHOD(Debugger, cmdBpFrame));
+ registerCmd("bf", WRAP_METHOD(Debugger, cmdBpFrame));
+ registerCmd("bpdel", WRAP_METHOD(Debugger, cmdBpDel));
+ registerCmd("bpenable", WRAP_METHOD(Debugger, cmdBpEnable));
+ registerCmd("bpdisable", WRAP_METHOD(Debugger, cmdBpDisable));
+ registerCmd("bplist", WRAP_METHOD(Debugger, cmdBpList));
+
_nextFrame = false;
_nextFrameCounter = 0;
_nextMovie = false;
@@ -88,6 +99,10 @@ Debugger::Debugger(): GUI::Debugger() {
_nextCounter = 0;
_nextFrame = false;
_nextFrameCounter = 0;
+ _bpNextId = 1;
+ _bpCheckFuncName = false;
+ _bpCheckMoviePath = false;
+ _bpNextMovieMatch = false;
}
Debugger::~Debugger() {
@@ -120,7 +135,7 @@ bool Debugger::cmdHelp(int argc, const char **argv) {
//debugPrintf(" eval [statement] - Evaluates a single Lingo statement\n");
debugPrintf(" repl - Switches to a REPL interface for evaluating Lingo code\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 [scriptId:funcName] - Lists the bytecode disassembly for a script function\n");
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");
@@ -131,16 +146,17 @@ bool Debugger::cmdHelp(int argc, const char **argv) {
debugPrintf(" continue / c - Continues execution\n");
debugPrintf("\n");
debugPrintf("Breakpoints:\n");
- debugPrintf("\n");
- //debugPrintf(" bpset [funcname] - Creates a breakpoint on a Lingo function matching a name\n");
- //debugPrintf(" bpset [funcname] [offset] - Creates a breakpoint on a Lingo function matching a name and offset\n");
- //debugPrintf(" bpset [scriptid:funcname] - Creates a breakpoint on a Lingo function matching a script ID and name\n");
- //debugPrintf(" bpset [scriptid:funcname] [offset] - Creates a breakpoint on a Lingo function matching a script ID, name and offset\n");
- //debugPrintf(" bpframe [frameId] - Create a breakpoint on a frame in the score\n");
- //debugPrintf(" bpdel [n] - Deletes a specific breakpoint\n");
- //debugPrintf(" bpenable [n] - Enables a specific breakpoint\n");
- //debugPrintf(" bpdisable [n] - Disables a specific breakpoint\n");
- //debugPrintf(" bplist - Lists all breakpoints\n");
+ debugPrintf(" bpset / b [funcName] - Creates a breakpoint on a Lingo function matching a name\n");
+ 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(" 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");
+ debugPrintf(" bpenable [n] - Enables a specific breakpoint\n");
+ debugPrintf(" bpdisable [n] - Disables a specific breakpoint\n");
+ debugPrintf(" bplist - Lists all breakpoints\n");
return true;
}
@@ -196,10 +212,10 @@ bool Debugger::cmdChannels(int argc, const char **argv) {
frameId = atoi(argv[1]);
if (frameId >= 1 && frameId <= maxSize) {
- debugPrintf("Channel info for frame %d of %d", frameId, maxSize);
+ debugPrintf("Channel info for frame %d of %d\n", frameId, maxSize);
debugPrintf("%s\n", score->_frames[frameId-1]->formatChannelInfo().c_str());
} else {
- debugPrintf("Must specify a frame number between 1 and %d\n", maxSize);
+ debugPrintf("Must specify a frame number between 1 and %d.\n", maxSize);
}
return true;
}
@@ -393,6 +409,218 @@ bool Debugger::cmdFinish(int argc, const char **argv) {
return cmdExit(0, nullptr);
}
+bool Debugger::cmdBpSet(int argc, const char **argv) {
+ if (argc == 2 || argc == 3) {
+ Breakpoint bp;
+ bp.id = _bpNextId;
+ _bpNextId++;
+ bp.type = kBreakpointFunction;
+ Common::String target(argv[1]);
+ uint splitPoint = target.findFirstOf(":");
+ if (splitPoint == Common::String::npos) {
+ bp.funcName = target;
+ } else {
+ bp.scriptId = atoi(target.substr(0, splitPoint).c_str());
+ bp.funcName = target.substr(splitPoint + 1, Common::String::npos);
+ }
+ if (argc == 3) {
+ bp.funcOffset = atoi(argv[2]);
+ }
+ _breakpoints.push_back(bp);
+ bpUpdateState();
+ debugPrintf("Added %s\n", bp.format().c_str());
+ } else {
+ debugPrintf("Must specify a function name.\n");
+ }
+ return true;
+}
+
+bool Debugger::cmdBpMovie(int argc, const char **argv) {
+ if (argc == 2) {
+ Breakpoint bp;
+ bp.id = _bpNextId;
+ _bpNextId++;
+ bp.type = kBreakpointMovie;
+ bp.moviePath = argv[1];
+ _breakpoints.push_back(bp);
+ bpUpdateState();
+ debugPrintf("Added %s\n", bp.format().c_str());
+ } else {
+ debugPrintf("Must specify a movie path.\n");
+ }
+ return true;
+}
+
+bool Debugger::cmdBpFrame(int argc, const char **argv) {
+ Movie *movie = g_director->getCurrentMovie();
+ if (argc == 2 || argc == 3) {
+ Breakpoint bp;
+ bp.id = _bpNextId;
+ _bpNextId++;
+ bp.type = kBreakpointMovieFrame;
+ Common::String target(argv[1]);
+ if (argc == 3) {
+ bp.moviePath = argv[1];
+ bp.frameOffset = atoi(argv[2]);
+ } else {
+ bp.moviePath = movie->getArchive()->getFileName();
+ bp.frameOffset = atoi(argv[1]);
+ }
+ if (bp.frameOffset == 0) {
+ debugPrintf("Must specify a valid frame ID.\n");
+ return true;
+ }
+ _breakpoints.push_back(bp);
+ bpUpdateState();
+ debugPrintf("Added %s\n", bp.format().c_str());
+ } else {
+ debugPrintf("Must specify a valid frame ID.\n");
+ }
+ return true;
+}
+
+bool Debugger::cmdBpDel(int argc, const char **argv) {
+ if (argc == 2 && atoi(argv[1]) > 0) {
+ bool found = false;
+ for (auto it = _breakpoints.begin(); it != _breakpoints.end(); ++it) {
+ if (it->id == atoi(argv[1])) {
+ it = _breakpoints.erase(it);
+ found = true;
+ bpUpdateState();
+ debugPrintf("Deleted breakpoint %s.\n", argv[1]);
+ break;
+ }
+ }
+ if (!found)
+ debugPrintf("No breakpoint with ID %s.\n", argv[1]);
+ } else {
+ debugPrintf("Must specify a breakpoint ID.\n");
+ }
+ return true;
+}
+
+bool Debugger::cmdBpEnable(int argc, const char **argv) {
+ if (argc == 2 && atoi(argv[1]) > 0) {
+ bool found = false;
+ for (auto it = _breakpoints.begin(); it != _breakpoints.end(); ++it) {
+ if (it->id == atoi(argv[1])) {
+ it->enabled = true;
+ found = true;
+ bpUpdateState();
+ debugPrintf("Enabled breakpoint %s.\n", argv[1]);
+ break;
+ }
+ }
+ if (!found)
+ debugPrintf("No breakpoint with ID %s.\n", argv[1]);
+ } else {
+ debugPrintf("Must specify a breakpoint ID.\n");
+ }
+ return true;
+}
+
+bool Debugger::cmdBpDisable(int argc, const char **argv) {
+ if (argc == 2 && atoi(argv[1]) > 0) {
+ bool found = false;
+ for (auto it = _breakpoints.begin(); it != _breakpoints.end(); ++it) {
+ if (it->id == atoi(argv[1])) {
+ it->enabled = false;
+ found = true;
+ bpUpdateState();
+ debugPrintf("Disabled breakpoint %s.\n", argv[1]);
+ break;
+ }
+ }
+ if (!found)
+ debugPrintf("No breakpoint with ID %s.\n", argv[1]);
+ } else {
+ debugPrintf("Must specify a breakpoint ID.\n");
+ }
+ return true;
+}
+
+bool Debugger::cmdBpList(int argc, const char **argv) {
+ if (_breakpoints.size()) {
+ for (auto &it : _breakpoints) {
+ debugPrintf("%s (%s)\n", it.format().c_str(), it.enabled ? "enabled" : "disabled");
+ }
+ } else {
+ debugPrintf("No breakpoints set.\n");
+ }
+ return true;
+}
+
+void Debugger::bpUpdateState() {
+ _bpCheckFuncName = false;
+ _bpCheckMoviePath = false;
+ _bpNextMovieMatch = false;
+ _bpMatchFuncOffsets.clear();
+ _bpMatchFuncName.clear();
+ _bpMatchMoviePath.clear();
+ _bpMatchFrameOffsets.clear();
+ Movie *movie = g_director->getCurrentMovie();
+ Common::Array<CFrame *> &callstack = g_director->getCurrentWindow()->_callstack;
+ for (auto &it : _breakpoints) {
+ if (!it.enabled)
+ continue;
+ if (it.type == kBreakpointFunction) {
+ _bpCheckFuncName = true;
+ if (!callstack.size())
+ continue;
+ CFrame *head = callstack[callstack.size() - 1];
+ if (!head->sp.name)
+ continue;
+ if (it.funcName.equalsIgnoreCase(*head->sp.name)) {
+ _bpMatchFuncName = it.funcName;
+ _bpMatchFuncOffsets.setVal(it.funcOffset, nullptr);
+ }
+ } else if (it.type == kBreakpointMovie || it.type == kBreakpointMovieFrame) {
+ _bpCheckMoviePath = true;
+ if (it.moviePath.equalsIgnoreCase(movie->getArchive()->getFileName())) {
+ _bpNextMovieMatch |= it.type == kBreakpointMovie;
+ _bpMatchMoviePath = it.moviePath;
+ _bpMatchFrameOffsets.setVal(it.frameOffset, nullptr);
+ }
+ }
+ }
+}
+
+void Debugger::bpTest(bool forceCheck) {
+ bool stop = forceCheck;
+ uint funcOffset = g_lingo->_pc;
+ Score *score = g_director->getCurrentMovie()->getScore();
+ uint frameOffset = score->getCurrentFrame();
+ if (_bpCheckFuncName) {
+ stop |= _bpMatchFuncOffsets.contains(funcOffset);
+ }
+ if (_bpCheckMoviePath) {
+ stop |= _bpMatchFrameOffsets.contains(frameOffset);
+ }
+ if (stop) {
+ debugPrintf("Hit a breakpoint:\n");
+ for (auto &it : _breakpoints) {
+ if (!it.enabled)
+ continue;
+ if (it.type == kBreakpointFunction) {
+ if (it.funcName.equalsIgnoreCase(_bpMatchFuncName) && it.funcOffset == funcOffset)
+ debugPrintf("%s\n", it.format().c_str());
+ } else if (it.type == kBreakpointMovie && _bpNextMovieMatch) {
+ if (it.moviePath.equalsIgnoreCase(_bpMatchMoviePath))
+ debugPrintf("%s\n", it.format().c_str());
+ } else if (it.type == kBreakpointMovieFrame) {
+ if (it.moviePath.equalsIgnoreCase(_bpMatchMoviePath) && it.frameOffset == frameOffset)
+ debugPrintf("%s\n", it.format().c_str());
+ }
+ }
+ // reset all step commands before returning to console
+ _nextMovie = false;
+ _nextFrame = false;
+ cmdScriptFrame(0, nullptr);
+ attach();
+ g_system->updateScreen();
+ }
+}
+
bool Debugger::lingoCommandProcessor(const char *inputOrig) {
if (!strcmp(inputOrig, "lingo off")) {
registerDefaultCmd(nullptr);
@@ -410,6 +638,7 @@ bool Debugger::lingoCommandProcessor(const char *inputOrig) {
}
void Debugger::stepHook() {
+ bpTest();
if (_step && _nextCounter == 0) {
_stepCounter--;
if (_stepCounter == 0) {
@@ -429,6 +658,7 @@ void Debugger::stepHook() {
}
void Debugger::frameHook() {
+ bpTest();
if (_nextFrame) {
_nextFrameCounter--;
if (_nextFrameCounter == 0) {
@@ -441,6 +671,8 @@ void Debugger::frameHook() {
}
void Debugger::movieHook() {
+ bpUpdateState();
+ bpTest(_bpNextMovieMatch);
if (_nextMovie) {
_nextMovie = false;
cmdMovie(0, nullptr);
@@ -454,6 +686,7 @@ void Debugger::pushContextHook() {
_nextCounter++;
if (_finish)
_finishCounter++;
+ bpUpdateState();
}
void Debugger::popContextHook() {
@@ -461,6 +694,25 @@ void Debugger::popContextHook() {
_nextCounter--;
if (_finish)
_finishCounter--;
+ bpUpdateState();
+}
+
+void Debugger::builtinHook(const Symbol &funcSym) {
+ if (!funcSym.name)
+ return;
+ bpUpdateState();
+ bool builtinMatch = false;
+ if (_bpCheckFuncName) {
+ for (auto &it : _breakpoints) {
+ if (it.type != kBreakpointFunction)
+ continue;
+ if (it.funcName.equalsIgnoreCase(*funcSym.name)) {
+ builtinMatch = true;
+ break;
+ }
+ }
+ }
+ bpTest(builtinMatch);
}
void Debugger::debugLogFile(Common::String logs, bool prompt) {
diff --git a/engines/director/debugger.h b/engines/director/debugger.h
index 8f2eec25152..1f99d428bf0 100644
--- a/engines/director/debugger.h
+++ b/engines/director/debugger.h
@@ -22,11 +22,60 @@
#ifndef DIRECTOR_DEBUGGER_H
#define DIRECTOR_DEBUGGER_H
+#include "common/array.h"
+#include "common/str.h"
#include "gui/debugger.h"
#include "director/director.h"
+#include "director/lingo/lingo.h"
namespace Director {
+enum BreakpointType {
+ kBreakpointTypeNull = 0,
+ kBreakpointFunction = 1,
+ kBreakpointMovie = 2,
+ kBreakpointMovieFrame = 3,
+};
+
+struct Breakpoint {
+ bool enabled = true;
+ BreakpointType type = kBreakpointTypeNull;
+ int id = 0;
+
+ uint16 scriptId = 0;
+ Common::String funcName;
+ uint funcOffset = 0;
+ Common::String moviePath;
+ uint frameOffset = 0;
+
+ Common::String format() {
+ Common::String result = Common::String::format("Breakpoint %d, ", id);
+ switch (type) {
+ case kBreakpointFunction:
+ result += "Function ";
+ if (scriptId)
+ result += Common::String::format("%d:", scriptId);
+ result += funcName;
+ if (funcOffset)
+ result += Common::String::format(" [%5d]", funcOffset);
+ break;
+ case kBreakpointMovie:
+ result += "Movie ";
+ result += moviePath;
+ break;
+ case kBreakpointMovieFrame:
+ result += "Movie ";
+ result += moviePath;
+ result += Common::String::format(":%d", frameOffset);
+ break;
+ default:
+ break;
+ }
+ return result;
+ }
+};
+
+
class Debugger : public GUI::Debugger {
public:
Debugger();
@@ -37,6 +86,7 @@ public:
void movieHook();
void pushContextHook();
void popContextHook();
+ void builtinHook(const Symbol &funcSym);
private:
bool cmdHelp(int argc, const char **argv);
@@ -59,6 +109,17 @@ private:
bool cmdNext(int argc, const char **argv);
bool cmdFinish(int argc, const char **argv);
+ bool cmdBpSet(int argc, const char **argv);
+ bool cmdBpMovie(int argc, const char **argv);
+ bool cmdBpFrame(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);
+ bool cmdBpList(int argc, const char **argv);
+
+ void bpUpdateState();
+ void bpTest(bool forceCheck = false);
+
bool lingoCommandProcessor(const char *inputOrig);
@@ -74,6 +135,16 @@ private:
int _finishCounter;
bool _next;
int _nextCounter;
+
+ Common::Array<Breakpoint> _breakpoints;
+ int _bpNextId;
+ bool _bpCheckFuncName;
+ bool _bpCheckMoviePath;
+ bool _bpNextMovieMatch;
+ Common::String _bpMatchFuncName;
+ Common::String _bpMatchMoviePath;
+ Common::HashMap<uint, void *> _bpMatchFuncOffsets;
+ Common::HashMap<uint, void *> _bpMatchFrameOffsets;
};
diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp
index c07dc25fba9..d70e7cf9fda 100644
--- a/engines/director/lingo/lingo-code.cpp
+++ b/engines/director/lingo/lingo-code.cpp
@@ -240,7 +240,6 @@ void Lingo::saveStateToWindow() {
}
void Lingo::pushContext(const Symbol funcSym, bool allowRetVal, Datum defaultRetVal) {
- g_debugger->pushContextHook();
Common::Array<CFrame *> &callstack = _vm->getCurrentWindow()->_callstack;
debugC(5, kDebugLingoExec, "Pushing frame %d", callstack.size() + 1);
@@ -315,6 +314,8 @@ void Lingo::pushContext(const Symbol funcSym, bool allowRetVal, Datum defaultRet
if (debugChannelSet(2, kDebugLingoExec)) {
g_lingo->printCallStack(0);
}
+ g_lingo->_pc = 0;
+ g_debugger->pushContextHook();
}
void Lingo::popContext(bool aborting) {
@@ -1631,6 +1632,7 @@ void LC::call(const Symbol &funcSym, int nargs, bool allowRetVal) {
}
if (funcSym.type != HANDLER) {
+ g_debugger->builtinHook(funcSym);
uint stackSizeBefore = g_lingo->_stack.size() - nargs;
if (target.type != VOID) {
@@ -1670,8 +1672,6 @@ void LC::call(const Symbol &funcSym, int nargs, bool allowRetVal) {
}
g_lingo->pushContext(funcSym, allowRetVal, defaultRetVal);
-
- g_lingo->_pc = 0;
}
void LC::c_procret() {
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index 2c615d041f9..57b23a5b699 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -356,7 +356,7 @@ void Lingo::printStack(const char *s, uint pc) {
Common::String stack(s);
stack += formatStack();
- debugC(5, kDebugLingoExec, "[%3d]: %s", pc, stack.c_str());
+ debugC(5, kDebugLingoExec, "[%5d]: %s", pc, stack.c_str());
}
Common::String Lingo::formatCallStack(uint pc) {
@@ -404,7 +404,7 @@ Common::String Lingo::formatFrame() {
result += "[unknown]";
else
result += frame->sp.name->c_str();
- result += Common::String::format(" at [%3d]", _pc);
+ result += Common::String::format(" at [%5d]", _pc);
return result;
}
@@ -412,7 +412,7 @@ Common::String Lingo::formatCurrentInstruction() {
Common::String instr = decodeInstruction(_currentScript, _pc);
if (instr.empty())
return instr;
- return Common::String::format("[%3d]: %s", _pc, instr.c_str());
+ return Common::String::format("[%5d]: %s", _pc, instr.c_str());
}
Common::String Lingo::decodeInstruction(ScriptData *sd, uint pc, uint *newPc) {
@@ -565,7 +565,7 @@ void Lingo::execute() {
if (debugChannelSet(3, kDebugLingoExec)) {
Common::String instr = decodeInstruction(_currentScript, _pc);
- debugC(3, kDebugLingoExec, "[%3d]: %s", current, instr.c_str());
+ debugC(3, kDebugLingoExec, "[%5d]: %s", current, instr.c_str());
}
g_debugger->stepHook();
More information about the Scummvm-git-logs
mailing list