[Scummvm-git-logs] scummvm master -> fe86d41701bb9ba081eb462cb3696b1a047d1760
sev-
noreply at scummvm.org
Tue Sep 20 18:17:15 UTC 2022
This automated email contains information about 8 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
3d9cf67233 DIRECTOR: Implement frame and nextframe debugger commands
8d29dec888 DIRECTOR: Implement channels debugger command
5c5929737d DIRECTOR: Implement cast debugger command
c56d9056d4 DIRECTOR: Initial implementation of funcs debugger command
31472c30e2 DIRECTOR: LINGO: Split out disassembly formatting code
c1ebb4d52d DIRECTOR: Implement funcs debugger command
29cc573d96 DIRECTOR: Update scriptframe command to include cast ID
fe86d41701 DIRECTOR: Implement disasm debugger command
Commit: 3d9cf6723395639451f416c5815e9c2750d54ccb
https://github.com/scummvm/scummvm/commit/3d9cf6723395639451f416c5815e9c2750d54ccb
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-20T20:17:06+02:00
Commit Message:
DIRECTOR: Implement frame and nextframe debugger commands
Changed paths:
engines/director/debugger.cpp
engines/director/debugger.h
engines/director/score.cpp
diff --git a/engines/director/debugger.cpp b/engines/director/debugger.cpp
index 4be61ea778d..9c133d1425a 100644
--- a/engines/director/debugger.cpp
+++ b/engines/director/debugger.cpp
@@ -22,6 +22,8 @@
#include "common/language.h"
#include "director/director.h"
#include "director/debugger.h"
+#include "director/movie.h"
+#include "director/score.h"
#include "director/lingo/lingo.h"
#include "director/lingo/lingo-code.h"
#include "director/lingo/lingo-object.h"
@@ -38,6 +40,10 @@ Debugger::Debugger(): GUI::Debugger() {
registerCmd("help", WRAP_METHOD(Debugger, cmdHelp));
registerCmd("version", WRAP_METHOD(Debugger, cmdVersion));
+ registerCmd("frame", WRAP_METHOD(Debugger, cmdFrame));
+ registerCmd("f", WRAP_METHOD(Debugger, cmdFrame));
+ registerCmd("nextframe", WRAP_METHOD(Debugger, cmdNextFrame));
+ registerCmd("nf", WRAP_METHOD(Debugger, cmdNextFrame));
registerCmd("repl", WRAP_METHOD(Debugger, cmdRepl));
registerCmd("stack", WRAP_METHOD(Debugger, cmdStack));
@@ -82,9 +88,11 @@ bool Debugger::cmdHelp(int argc, const char **argv) {
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(" scoreframe [frameNum] - Gets or sets the current score frame\n");
- //debugPrintf(" channels [frameNum] - Shows channel information for a score frame\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 - Shows the cast list 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("\n");
debugPrintf("Lingo execution:\n");
//debugPrintf(" eval [statement] - Evaluates a single Lingo statement\n");
@@ -93,6 +101,7 @@ bool Debugger::cmdHelp(int argc, const char **argv) {
//debugPrintf(" disasm [function] - 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");
debugPrintf(" vars - 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");
@@ -101,7 +110,11 @@ bool Debugger::cmdHelp(int argc, const char **argv) {
debugPrintf("Breakpoints:\n");
debugPrintf("\n");
//debugPrintf(" bpset [funcname:n] - Creates a breakpoint on a Lingo script\n");
- //debugPrintf(" bpdel [n] - Deletes a specific breakpoint \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");
return true;
}
@@ -119,6 +132,33 @@ bool Debugger::cmdVersion(int argc, const char **argv) {
return true;
}
+bool Debugger::cmdFrame(int argc, const char **argv) {
+ Lingo *lingo = g_director->getLingo();
+ Score *score = g_director->getCurrentMovie()->getScore();
+ if (argc == 2 && atoi(argv[1]) > 0) {
+ Datum frame, movie;
+ if (atoi(argv[1]) > 0) {
+ frame = Datum(atoi(argv[1]));
+ } else {
+ frame = Datum(argv[1]);
+ }
+ lingo->func_goto(frame, movie);
+ } else {
+ debugPrintf("%d\n", score->getCurrentFrame());
+ }
+ return true;
+}
+
+bool Debugger::cmdNextFrame(int argc, const char **argv) {
+ _nextFrame = true;
+ if (argc == 2 && atoi(argv[1]) > 0) {
+ _nextFrameCounter = atoi(argv[1]);
+ } else {
+ _nextFrameCounter = 1;
+ }
+ 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));
@@ -214,6 +254,18 @@ void Debugger::stepHook() {
}
}
+void Debugger::frameHook() {
+ if (_nextFrame) {
+ _nextFrameCounter--;
+ if (_nextFrameCounter == 0) {
+ _nextFrame = false;
+ cmdFrame(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 fa6f9fef183..5af429d71c6 100644
--- a/engines/director/debugger.h
+++ b/engines/director/debugger.h
@@ -33,6 +33,7 @@ public:
~Debugger();
void debugLogFile(Common::String logs, bool prompt);
void stepHook();
+ void frameHook();
void pushContextHook();
void popContextHook();
@@ -40,6 +41,8 @@ private:
bool cmdHelp(int argc, const char **argv);
bool cmdVersion(int argc, const char **argv);
+ bool cmdFrame(int argc, const char **argv);
+ bool cmdNextFrame(int argc, const char **argv);
bool cmdRepl(int argc, const char **argv);
bool cmdBacktrace(int argc, const char **argv);
bool cmdStack(int argc, const char **argv);
@@ -55,6 +58,8 @@ private:
Common::DumpFile _out;
Common::String _outName;
+ bool _nextFrame;
+ int _nextFrameCounter;
bool _step;
int _stepCounter;
bool _finish;
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index 923c97f0cba..140a9a86305 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -413,6 +413,7 @@ void Score::update() {
}
debugC(1, kDebugImages, "****************************** Current frame: %d", _currentFrame);
+ g_debugger->frameHook();
uint initialCallStackSize = _window->_callstack.size();
Commit: 8d29dec888e8b1287cea20490e3c5abb7f0226a2
https://github.com/scummvm/scummvm/commit/8d29dec888e8b1287cea20490e3c5abb7f0226a2
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-20T20:17:06+02:00
Commit Message:
DIRECTOR: Implement channels debugger command
Changed paths:
engines/director/debugger.cpp
engines/director/debugger.h
engines/director/frame.cpp
engines/director/frame.h
engines/director/lingo/lingo.cpp
diff --git a/engines/director/debugger.cpp b/engines/director/debugger.cpp
index 9c133d1425a..fe996da4fd6 100644
--- a/engines/director/debugger.cpp
+++ b/engines/director/debugger.cpp
@@ -22,6 +22,7 @@
#include "common/language.h"
#include "director/director.h"
#include "director/debugger.h"
+#include "director/frame.h"
#include "director/movie.h"
#include "director/score.h"
#include "director/lingo/lingo.h"
@@ -42,6 +43,8 @@ Debugger::Debugger(): GUI::Debugger() {
registerCmd("version", WRAP_METHOD(Debugger, cmdVersion));
registerCmd("frame", WRAP_METHOD(Debugger, cmdFrame));
registerCmd("f", WRAP_METHOD(Debugger, cmdFrame));
+ registerCmd("channels", WRAP_METHOD(Debugger, cmdChannels));
+ registerCmd("chan", WRAP_METHOD(Debugger, cmdChannels));
registerCmd("nextframe", WRAP_METHOD(Debugger, cmdNextFrame));
registerCmd("nf", WRAP_METHOD(Debugger, cmdNextFrame));
@@ -89,7 +92,7 @@ bool Debugger::cmdHelp(int argc, const char **argv) {
//debugPrintf(" movie [moviePath] - Get or sets the current movie\n");
//debugPrintf(" movieinfo - 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(" channels / chan [frameNum] - Shows channel information for a score frame\n");
//debugPrintf(" cast - Shows the cast list 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");
@@ -149,6 +152,23 @@ bool Debugger::cmdFrame(int argc, const char **argv) {
return true;
}
+bool Debugger::cmdChannels(int argc, const char **argv) {
+ Lingo *lingo = g_director->getLingo();
+ Score *score = g_director->getCurrentMovie()->getScore();
+
+ int maxSize = (int)score->_frames.size();
+ int frameId = score->getCurrentFrame();
+ if (argc == 2)
+ frameId = atoi(argv[1]);
+
+ if (frameId >= 1 && 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);
+ }
+ return true;
+}
+
bool Debugger::cmdNextFrame(int argc, const char **argv) {
_nextFrame = true;
if (argc == 2 && atoi(argv[1]) > 0) {
diff --git a/engines/director/debugger.h b/engines/director/debugger.h
index 5af429d71c6..1f3712478e8 100644
--- a/engines/director/debugger.h
+++ b/engines/director/debugger.h
@@ -42,6 +42,7 @@ private:
bool cmdVersion(int argc, const char **argv);
bool cmdFrame(int argc, const char **argv);
+ bool cmdChannels(int argc, const char **argv);
bool cmdNextFrame(int argc, const char **argv);
bool cmdRepl(int argc, const char **argv);
bool cmdBacktrace(int argc, const char **argv);
diff --git a/engines/director/frame.cpp b/engines/director/frame.cpp
index 2304945f9de..540f6a9aa36 100644
--- a/engines/director/frame.cpp
+++ b/engines/director/frame.cpp
@@ -263,22 +263,6 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
// Script
}
- debugC(4, kDebugLoading, "TMPO: tempo: %d, skipFrameFlag: %d, blend: %d",
- _tempo, _skipFrameFlag, _blend);
- if (_palette.paletteId) {
- debugC(4, kDebugLoading, "PAL: paletteId: %d, firstColor: %d, lastColor: %d, flags: %d, cycleCount: %d, speed: %d, frameCount: %d, fade: %d, delay: %d, style: %d",
- _palette.paletteId, _palette.firstColor, _palette.lastColor, _palette.flags,
- _palette.cycleCount, _palette.speed, _palette.frameCount,
- _palette.fade, _palette.delay, _palette.style);
- } else {
- debugC(4, kDebugLoading, "PAL: paletteId: 000");
- }
- debugC(4, kDebugLoading, "TRAN: transType: %d, transDuration: %d, transChunkSize: %d",
- _transType, _transDuration, _transChunkSize);
- debugC(4, kDebugLoading, "SND: 1 sound1: %d, soundType1: %d", _sound1.member, _soundType1);
- debugC(4, kDebugLoading, "SND: 2 sound2: %d, soundType2: %d", _sound2.member, _soundType2);
- debugC(4, kDebugLoading, "LSCR: actionId: %d", _actionId.member);
-
_transChunkSize = CLIP<byte>(_transChunkSize, 0, 128);
_transDuration = CLIP<uint16>(_transDuration, 0, 32000); // restrict to 32 secs
@@ -388,19 +372,48 @@ void Frame::readChannels(Common::ReadStreamEndian *stream, uint16 version) {
sprite._trails = 0;
sprite._moveable = ((sprite._colorcode & 0x80) == 0x80);
+ }
+
+ if (debugChannelSet(4, kDebugLoading)) {
+ debugC(4, kDebugLoading, "%s", formatChannelInfo().c_str());
+ }
+}
+Common::String Frame::formatChannelInfo() {
+ Common::String result;
+ result += Common::String::format("TMPO: tempo: %d, skipFrameFlag: %d, blend: %d\n",
+ _tempo, _skipFrameFlag, _blend);
+ if (_palette.paletteId) {
+ result += Common::String::format("PAL: paletteId: %d, firstColor: %d, lastColor: %d, flags: %d, cycleCount: %d, speed: %d, frameCount: %d, fade: %d, delay: %d, style: %d\n",
+ _palette.paletteId, _palette.firstColor, _palette.lastColor, _palette.flags,
+ _palette.cycleCount, _palette.speed, _palette.frameCount,
+ _palette.fade, _palette.delay, _palette.style);
+ } else {
+ result += Common::String::format("PAL: paletteId: 000\n");
+ }
+ result += Common::String::format("TRAN: transType: %d, transDuration: %d, transChunkSize: %d\n",
+ _transType, _transDuration, _transChunkSize);
+ result += Common::String::format("SND: 1 sound1: %d, soundType1: %d\n", _sound1.member, _soundType1);
+ result += Common::String::format("SND: 2 sound2: %d, soundType2: %d\n", _sound2.member, _soundType2);
+ result += Common::String::format("LSCR: actionId: %d\n", _actionId.member);
+
+ for (int i = 0; i < _numChannels; i++) {
+ Sprite &sprite = *_sprites[i + 1];
if (sprite._castId.member) {
- debugC(4, kDebugLoading, "CH: %-3d castId: %s [inkData:%02x [ink: %x trails: %d line: %d], %dx%d@%d,%d type: %d fg: %d bg: %d] script: %s, flags2: %x, unk2: %x, unk3: %x",
+ result += Common::String::format("CH: %-3d castId: %s [inkData:%02x [ink: %x trails: %d line: %d], %dx%d@%d,%d type: %d fg: %d bg: %d] script: %s, flags2: %x, unk2: %x, unk3: %x\n",
i + 1, sprite._castId.asString().c_str(), sprite._inkData,
sprite._ink, sprite._trails, sprite._thickness, sprite._width, sprite._height,
sprite._startPoint.x, sprite._startPoint.y,
sprite._spriteType, sprite._foreColor, sprite._backColor, sprite._scriptId.asString().c_str(), sprite._colorcode, sprite._blendAmount, sprite._unk3);
} else {
- debugC(4, kDebugLoading, "CH: %-3d castId: 000", i + 1);
+ result += Common::String::format("CH: %-3d castId: 000\n", i + 1);
}
}
+
+ return result;
}
+
void Frame::readMainChannels(Common::SeekableReadStreamEndian &stream, uint16 offset, uint16 size) {
uint16 finishPosition = offset + size;
diff --git a/engines/director/frame.h b/engines/director/frame.h
index c4d262744f6..d66f45da71d 100644
--- a/engines/director/frame.h
+++ b/engines/director/frame.h
@@ -96,6 +96,8 @@ public:
void executeImmediateScripts();
+ Common::String formatChannelInfo();
+
private:
void readPaletteInfo(Common::SeekableReadStreamEndian &stream);
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index 002d2dca5e7..6b0345c2ecf 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -462,7 +462,7 @@ Common::String Lingo::decodeInstruction(ScriptData *sd, uint pc, uint *newPc) {
void Lingo::execute() {
uint localCounter = 0;
- while (!_abort && !_freezeContext && (*_currentScript)[_pc] != STOP) {
+ while (!_abort && !_freezeContext && _currentScript && (*_currentScript)[_pc] != STOP) {
if (_globalCounter > 1000 && debugChannelSet(-1, kDebugFewFramesOnly)) {
warning("Lingo::execute(): Stopping due to debug few frames only");
_vm->getCurrentMovie()->getScore()->_playState = kPlayStopped;
Commit: 5c5929737d87e8e8fafc7e103005bce5cf90658c
https://github.com/scummvm/scummvm/commit/5c5929737d87e8e8fafc7e103005bce5cf90658c
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-20T20:17:06+02:00
Commit Message:
DIRECTOR: Implement cast debugger command
Changed paths:
engines/director/cast.cpp
engines/director/cast.h
engines/director/debugger.cpp
engines/director/debugger.h
diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp
index 263fe46a221..5be60224349 100644
--- a/engines/director/cast.cpp
+++ b/engines/director/cast.cpp
@@ -1499,4 +1499,22 @@ void Cast::loadVWTL(Common::SeekableReadStreamEndian &stream) {
}
+Common::String Cast::formatCastSummary() {
+ Common::String result;
+ Common::Array<int> castIds;
+ for (auto it = _loadedCast->begin(); it != _loadedCast->end(); ++it) {
+ castIds.push_back(it->_key);
+ }
+ Common::sort(castIds.begin(), castIds.end());
+ for (auto it = castIds.begin(); it != castIds.end(); ++it) {
+ CastMember *castMember = getCastMember(*it);
+ CastMemberInfo *castMemberInfo = getCastMemberInfo(*it);
+ result += Common::String::format("%d: type=%s, name=\"%s\"\n",
+ *it, castTypeToString(castMember->_type).c_str(),
+ castMemberInfo ? castMemberInfo->name.c_str() : ""
+ );
+ }
+ return result;
+}
+
} // End of namespace Director
diff --git a/engines/director/cast.h b/engines/director/cast.h
index ba5db9b3b65..35951561f0c 100644
--- a/engines/director/cast.h
+++ b/engines/director/cast.h
@@ -122,6 +122,8 @@ public:
Common::CodePage getFileEncoding();
Common::U32String decodeString(const Common::String &str);
+ Common::String formatCastSummary();
+
private:
void loadScriptText(Common::SeekableReadStreamEndian &stream, uint16 id);
void loadFontMap(Common::SeekableReadStreamEndian &stream);
diff --git a/engines/director/debugger.cpp b/engines/director/debugger.cpp
index fe996da4fd6..d3ac6ca2c55 100644
--- a/engines/director/debugger.cpp
+++ b/engines/director/debugger.cpp
@@ -22,6 +22,8 @@
#include "common/language.h"
#include "director/director.h"
#include "director/debugger.h"
+#include "director/cast.h"
+#include "director/castmember.h"
#include "director/frame.h"
#include "director/movie.h"
#include "director/score.h"
@@ -29,6 +31,7 @@
#include "director/lingo/lingo-code.h"
#include "director/lingo/lingo-object.h"
#include "director/lingo/lingo-codegen.h"
+#include "director/util.h"
namespace Director {
@@ -45,6 +48,7 @@ Debugger::Debugger(): GUI::Debugger() {
registerCmd("f", WRAP_METHOD(Debugger, cmdFrame));
registerCmd("channels", WRAP_METHOD(Debugger, cmdChannels));
registerCmd("chan", WRAP_METHOD(Debugger, cmdChannels));
+ registerCmd("cast", WRAP_METHOD(Debugger, cmdCast));
registerCmd("nextframe", WRAP_METHOD(Debugger, cmdNextFrame));
registerCmd("nf", WRAP_METHOD(Debugger, cmdNextFrame));
@@ -93,7 +97,7 @@ bool Debugger::cmdHelp(int argc, const char **argv) {
//debugPrintf(" movieinfo - 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 - Shows the cast list for the current movie\n");
+ debugPrintf(" cast - Shows the cast list 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("\n");
@@ -153,7 +157,6 @@ bool Debugger::cmdFrame(int argc, const char **argv) {
}
bool Debugger::cmdChannels(int argc, const char **argv) {
- Lingo *lingo = g_director->getLingo();
Score *score = g_director->getCurrentMovie()->getScore();
int maxSize = (int)score->_frames.size();
@@ -169,6 +172,27 @@ bool Debugger::cmdChannels(int argc, const char **argv) {
return true;
}
+bool Debugger::cmdCast(int argc, const char **argv) {
+ Cast *cast = g_director->getCurrentMovie()->getCast();
+ Cast *sharedCast = g_director->getCurrentMovie()->getSharedCast();
+
+ debugPrintf("Cast:\n");
+ if (cast) {
+ debugPrintf("%s\n", cast->formatCastSummary().c_str());
+ } else {
+ debugPrintf("not found!\n");
+ }
+ debugPrintf("\n");
+ debugPrintf("Shared cast:\n");
+ if (sharedCast) {
+ debugPrintf("%s\n", sharedCast->formatCastSummary().c_str());
+ } else {
+ debugPrintf("not found!\n");
+ }
+ debugPrintf("\n");
+ return true;
+}
+
bool Debugger::cmdNextFrame(int argc, const char **argv) {
_nextFrame = true;
if (argc == 2 && atoi(argv[1]) > 0) {
diff --git a/engines/director/debugger.h b/engines/director/debugger.h
index 1f3712478e8..5f48ccf735f 100644
--- a/engines/director/debugger.h
+++ b/engines/director/debugger.h
@@ -43,6 +43,7 @@ private:
bool cmdVersion(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 cmdRepl(int argc, const char **argv);
bool cmdBacktrace(int argc, const char **argv);
Commit: c56d9056d4d4c35929f4062d3ead0e7a3d72f407
https://github.com/scummvm/scummvm/commit/c56d9056d4d4c35929f4062d3ead0e7a3d72f407
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-20T20:17:06+02:00
Commit Message:
DIRECTOR: Initial implementation of funcs debugger command
Changed paths:
engines/director/debugger.cpp
engines/director/debugger.h
diff --git a/engines/director/debugger.cpp b/engines/director/debugger.cpp
index d3ac6ca2c55..7d9628afd10 100644
--- a/engines/director/debugger.cpp
+++ b/engines/director/debugger.cpp
@@ -57,6 +57,7 @@ Debugger::Debugger(): GUI::Debugger() {
registerCmd("st", WRAP_METHOD(Debugger, cmdStack));
registerCmd("scriptframe", WRAP_METHOD(Debugger, cmdScriptFrame));
registerCmd("sf", WRAP_METHOD(Debugger, cmdScriptFrame));
+ registerCmd("funcs", WRAP_METHOD(Debugger, cmdFuncs));
registerCmd("backtrace", WRAP_METHOD(Debugger, cmdBacktrace));
registerCmd("bt", WRAP_METHOD(Debugger, cmdBacktrace));
registerCmd("vars", WRAP_METHOD(Debugger, cmdVars));
@@ -108,7 +109,7 @@ bool Debugger::cmdHelp(int argc, const char **argv) {
//debugPrintf(" disasm [function] - 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");
+ 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(" step / s [n] - Steps forward one or more operations\n");
debugPrintf(" next / n [n] - Steps forward one or more operations, skips over calls\n");
@@ -224,6 +225,59 @@ bool Debugger::cmdScriptFrame(int argc, const char **argv) {
return true;
}
+bool Debugger::cmdFuncs(int argc, const char **argv) {
+ Lingo *lingo = g_director->getLingo();
+ ScriptContext *csc = lingo->_currentScriptContext;
+ debugPrintf("Frame functions:\n");
+ if (csc) {
+ Common::Array<Common::String> names;
+ for (auto it = csc->_functionHandlers.begin(); it != csc->_functionHandlers.end(); ++it) {
+ names.push_back(it->_key);
+ }
+ Common::sort(names.begin(), names.end());
+ for (auto it = names.begin(); it != names.end(); ++it) {
+ debugPrintf("%s\n", it->c_str());
+ }
+ } else {
+ debugPrintf("not found!\n");
+ }
+ debugPrintf("\n");
+ Movie *movie = g_director->getCurrentMovie();
+ debugPrintf("Cast functions:\n");
+ Cast *cast = movie->getCast();
+ if (cast && cast->_lingoArchive) {
+ SymbolHash *fh = &cast->_lingoArchive->functionHandlers;
+ Common::Array<Common::String> names;
+ for (auto it = fh->begin(); it != fh->end(); ++it) {
+ names.push_back(it->_key);
+ }
+ Common::sort(names.begin(), names.end());
+ for (auto it = names.begin(); it != names.end(); ++it) {
+ debugPrintf("%s\n", it->c_str());
+ }
+ } else {
+ debugPrintf("not found!\n");
+ }
+ debugPrintf("\n");
+ debugPrintf("Shared cast functions:\n");
+ Cast *sharedCast = movie->getSharedCast();
+ if (sharedCast && sharedCast->_lingoArchive) {
+ SymbolHash *fh = &sharedCast->_lingoArchive->functionHandlers;
+ Common::Array<Common::String> names;
+ for (auto it = fh->begin(); it != fh->end(); ++it) {
+ names.push_back(it->_key);
+ }
+ Common::sort(names.begin(), names.end());
+ for (auto it = names.begin(); it != names.end(); ++it) {
+ debugPrintf("%s\n", it->c_str());
+ }
+ } else {
+ debugPrintf("not found!\n");
+ }
+ debugPrintf("\n");
+ return true;
+}
+
bool Debugger::cmdBacktrace(int argc, const char **argv) {
Lingo *lingo = g_director->getLingo();
debugPrintf("%s\n", lingo->formatCallStack(lingo->_pc).c_str());
diff --git a/engines/director/debugger.h b/engines/director/debugger.h
index 5f48ccf735f..dc7ce365607 100644
--- a/engines/director/debugger.h
+++ b/engines/director/debugger.h
@@ -49,6 +49,7 @@ private:
bool cmdBacktrace(int argc, const char **argv);
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 cmdStep(int argc, const char **argv);
bool cmdNext(int argc, const char **argv);
Commit: 31472c30e23d26a2ce0e8af6d9c591bb68c4df4b
https://github.com/scummvm/scummvm/commit/31472c30e23d26a2ce0e8af6d9c591bb68c4df4b
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-20T20:17:06+02:00
Commit Message:
DIRECTOR: LINGO: Split out disassembly formatting code
Changed paths:
engines/director/lingo/lingo-bytecode.cpp
engines/director/lingo/lingo.cpp
engines/director/lingo/lingo.h
diff --git a/engines/director/lingo/lingo-bytecode.cpp b/engines/director/lingo/lingo-bytecode.cpp
index b4f44e47698..3da39f5c5d8 100644
--- a/engines/director/lingo/lingo-bytecode.cpp
+++ b/engines/director/lingo/lingo-bytecode.cpp
@@ -1573,27 +1573,7 @@ ScriptContext *LingoCompiler::compileLingoV4(Common::SeekableReadStreamEndian &s
}
if (!skipdump && ConfMan.getBool("dump_scripts")) {
- if (0 <= nameIndex && nameIndex < (int16)archive->names.size()) {
- Common::String res = Common::String::format("function %s, %d args", archive->names[nameIndex].c_str(), argCount);
- if (argCount != 0)
- res += ": ";
- for (int argIndex = 0; argIndex < argCount; argIndex++) {
- res += (*argNames)[argIndex].c_str();
- if (argIndex < (argCount - 1))
- res += ", ";
- }
- res += "\n";
- out.writeString(res.c_str());
- } else {
- out.writeString(Common::String::format("<noname>, %d args\n", argCount));
- }
- uint pc = 0;
- while (pc < _currentAssembly->size()) {
- uint spc = pc;
- Common::String instr = g_lingo->decodeInstruction(_currentAssembly, pc, &pc);
- out.writeString(Common::String::format("[%5d] %s\n", spc, instr.c_str()));
- }
- out.writeString(Common::String::format("<end code>\n\n"));
+ out.writeString(g_lingo->decodeFunctionSym(sym));
}
_assemblyContext->_functionNames.push_back(*sym.name);
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index 6b0345c2ecf..de29f6c14bd 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -381,13 +381,13 @@ Common::String Lingo::formatFrame() {
}
Common::String Lingo::decodeInstruction(ScriptData *sd, uint pc, uint *newPc) {
- Symbol sym;
+ void *opcodeFunc;
Common::String res;
- sym.u.func = (*sd)[pc++];
- if (_functions.contains((void *)sym.u.s)) {
- res = _functions[(void *)sym.u.s]->name;
- const char *pars = _functions[(void *)sym.u.s]->proto;
+ opcodeFunc = (void *)(*sd)[pc++];
+ if (_functions.contains(opcodeFunc)) {
+ res = _functions[opcodeFunc]->name;
+ const char *pars = _functions[opcodeFunc]->proto;
inst i;
uint start = pc;
@@ -403,11 +403,10 @@ Common::String Lingo::decodeInstruction(ScriptData *sd, uint pc, uint *newPc) {
}
case 'f':
{
- Datum d;
i = (*sd)[pc++];
- d.u.f = *(double *)(&i);
+ double d = *(double *)(&i);
- res += Common::String::format(" %f", d.u.f);
+ res += Common::String::format(" %f", d);
break;
}
case 'o':
@@ -443,7 +442,7 @@ Common::String Lingo::decodeInstruction(ScriptData *sd, uint pc, uint *newPc) {
break;
}
default:
- warning("decodeInstruction: Unknown parameter type: %c", pars[-1]);
+ warning("Lingo::decodeInstruction(): Unknown parameter type: %c", pars[-1]);
}
if (*pars)
@@ -459,6 +458,35 @@ Common::String Lingo::decodeInstruction(ScriptData *sd, uint pc, uint *newPc) {
return res;
}
+Common::String Lingo::decodeScript(ScriptData *sd) {
+ uint pc = 0;
+ Common::String result;
+ while (pc < sd->size()) {
+ result += Common::String::format("[%5d] ", pc);
+ result += Common::String::format("%s\n", Lingo::decodeInstruction(sd, pc, &pc).c_str());
+ }
+ return result;
+}
+
+Common::String Lingo::decodeFunctionSym(Symbol &sym) {
+ Common::String result;
+ if (sym.type != HANDLER)
+ return result;
+ if (sym.name && sym.name->size())
+ result += Common::String::format("%s(", sym.name->c_str());
+ else
+ result += "<unknown>(";
+ for (int i = 0; i < sym.nargs; i++) {
+ result += (*sym.argNames)[i].c_str();
+ if (i < (sym.nargs - 1))
+ result += ", ";
+ }
+ result += ")\n";
+ result += decodeScript(sym.u.defn);
+ result += "\n";
+ return result;
+}
+
void Lingo::execute() {
uint localCounter = 0;
diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index c81ad351fa8..18f48535a46 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -307,6 +307,8 @@ public:
void printCallStack(uint pc);
Common::String formatFrame();
Common::String decodeInstruction(ScriptData *sd, uint pc, uint *newPC = NULL);
+ Common::String decodeScript(ScriptData *sd);
+ Common::String decodeFunctionSym(Symbol &sym);
void reloadBuiltIns();
void initBuiltIns();
Commit: c1ebb4d52d1677bf6c564824e5b097d97478c225
https://github.com/scummvm/scummvm/commit/c1ebb4d52d1677bf6c564824e5b097d97478c225
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-20T20:17:06+02:00
Commit Message:
DIRECTOR: Implement funcs debugger command
Changed paths:
engines/director/debugger.cpp
engines/director/lingo/lingo-bytecode.cpp
engines/director/lingo/lingo-codegen.cpp
engines/director/lingo/lingo-object.cpp
engines/director/lingo/lingo-object.h
engines/director/lingo/lingo.cpp
engines/director/lingo/lingo.h
engines/director/util.cpp
diff --git a/engines/director/debugger.cpp b/engines/director/debugger.cpp
index 7d9628afd10..6f721e0526a 100644
--- a/engines/director/debugger.cpp
+++ b/engines/director/debugger.cpp
@@ -106,7 +106,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 [function] - Lists the bytecode disassembly for a script function\n");
+ //debugPrintf(" disasm [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");
@@ -117,7 +117,10 @@ bool Debugger::cmdHelp(int argc, const char **argv) {
debugPrintf("\n");
debugPrintf("Breakpoints:\n");
debugPrintf("\n");
- //debugPrintf(" bpset [funcname:n] - Creates a breakpoint on a Lingo script\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");
@@ -166,6 +169,7 @@ 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("%s\n", score->_frames[frameId-1]->formatChannelInfo().c_str());
} else {
debugPrintf("Must specify a frame number between 1 and %d\n", maxSize);
@@ -181,14 +185,14 @@ bool Debugger::cmdCast(int argc, const char **argv) {
if (cast) {
debugPrintf("%s\n", cast->formatCastSummary().c_str());
} else {
- debugPrintf("not found!\n");
+ debugPrintf("[empty]\n");
}
debugPrintf("\n");
debugPrintf("Shared cast:\n");
if (sharedCast) {
debugPrintf("%s\n", sharedCast->formatCastSummary().c_str());
} else {
- debugPrintf("not found!\n");
+ debugPrintf("[empty]\n");
}
debugPrintf("\n");
return true;
@@ -230,49 +234,26 @@ bool Debugger::cmdFuncs(int argc, const char **argv) {
ScriptContext *csc = lingo->_currentScriptContext;
debugPrintf("Frame functions:\n");
if (csc) {
- Common::Array<Common::String> names;
- for (auto it = csc->_functionHandlers.begin(); it != csc->_functionHandlers.end(); ++it) {
- names.push_back(it->_key);
- }
- Common::sort(names.begin(), names.end());
- for (auto it = names.begin(); it != names.end(); ++it) {
- debugPrintf("%s\n", it->c_str());
- }
+ debugPrintf("%s", csc->formatFunctionList(" ").c_str());
} else {
- debugPrintf("not found!\n");
+ debugPrintf(" [empty]\n");
}
debugPrintf("\n");
Movie *movie = g_director->getCurrentMovie();
debugPrintf("Cast functions:\n");
Cast *cast = movie->getCast();
if (cast && cast->_lingoArchive) {
- SymbolHash *fh = &cast->_lingoArchive->functionHandlers;
- Common::Array<Common::String> names;
- for (auto it = fh->begin(); it != fh->end(); ++it) {
- names.push_back(it->_key);
- }
- Common::sort(names.begin(), names.end());
- for (auto it = names.begin(); it != names.end(); ++it) {
- debugPrintf("%s\n", it->c_str());
- }
+ debugPrintf("%s", cast->_lingoArchive->formatFunctionList(" ").c_str());
} else {
- debugPrintf("not found!\n");
+ debugPrintf(" [empty]\n");
}
debugPrintf("\n");
debugPrintf("Shared cast functions:\n");
Cast *sharedCast = movie->getSharedCast();
if (sharedCast && sharedCast->_lingoArchive) {
- SymbolHash *fh = &sharedCast->_lingoArchive->functionHandlers;
- Common::Array<Common::String> names;
- for (auto it = fh->begin(); it != fh->end(); ++it) {
- names.push_back(it->_key);
- }
- Common::sort(names.begin(), names.end());
- for (auto it = names.begin(); it != names.end(); ++it) {
- debugPrintf("%s\n", it->c_str());
- }
+ debugPrintf("%s", sharedCast->_lingoArchive->formatFunctionList(" ").c_str());
} else {
- debugPrintf("not found!\n");
+ debugPrintf(" [empty]\n");
}
debugPrintf("\n");
return true;
diff --git a/engines/director/lingo/lingo-bytecode.cpp b/engines/director/lingo/lingo-bytecode.cpp
index 3da39f5c5d8..90b143077d3 100644
--- a/engines/director/lingo/lingo-bytecode.cpp
+++ b/engines/director/lingo/lingo-bytecode.cpp
@@ -1573,7 +1573,7 @@ ScriptContext *LingoCompiler::compileLingoV4(Common::SeekableReadStreamEndian &s
}
if (!skipdump && ConfMan.getBool("dump_scripts")) {
- out.writeString(g_lingo->decodeFunctionSym(sym));
+ out.writeString(g_lingo->decodeFunctionBody(sym));
}
_assemblyContext->_functionNames.push_back(*sym.name);
diff --git a/engines/director/lingo/lingo-codegen.cpp b/engines/director/lingo/lingo-codegen.cpp
index b182a65e724..cab87207e6b 100644
--- a/engines/director/lingo/lingo-codegen.cpp
+++ b/engines/director/lingo/lingo-codegen.cpp
@@ -178,7 +178,7 @@ ScriptContext *LingoCompiler::compileLingo(const Common::U32String &code, LingoA
currentFunc.type = HANDLER;
currentFunc.u.defn = _currentAssembly;
Common::String typeStr = Common::String(scriptType2str(type));
- currentFunc.name = new Common::String("[" + typeStr + " " + _assemblyContext->getName() + "]");
+ currentFunc.name = new Common::String("scummvm_" + typeStr + "_" + _assemblyContext->getName());
currentFunc.ctx = _assemblyContext;
currentFunc.anonymous = anonymous;
Common::Array<Common::String> *argNames = new Common::Array<Common::String>;
@@ -204,15 +204,18 @@ ScriptContext *LingoCompiler::compileLingo(const Common::U32String &code, LingoA
currentFunc.argNames = argNames;
currentFunc.varNames = varNames;
+ _assemblyContext->_functionHandlers[*currentFunc.name] = currentFunc;
_assemblyContext->_eventHandlers[kEventGeneric] = currentFunc;
} else {
delete _currentAssembly;
}
// Register this context's functions with the containing archive.
- for (SymbolHash::iterator it = _assemblyContext->_functionHandlers.begin(); it != _assemblyContext->_functionHandlers.end(); ++it) {
- if (!_assemblyArchive->functionHandlers.contains(it->_key)) {
- _assemblyArchive->functionHandlers[it->_key] = it->_value;
+ if (_assemblyArchive) {
+ for (SymbolHash::iterator it = _assemblyContext->_functionHandlers.begin(); it != _assemblyContext->_functionHandlers.end(); ++it) {
+ if (!_assemblyArchive->functionHandlers.contains(it->_key)) {
+ _assemblyArchive->functionHandlers[it->_key] = it->_value;
+ }
}
}
diff --git a/engines/director/lingo/lingo-object.cpp b/engines/director/lingo/lingo-object.cpp
index 61e80d073ee..70c013daf7e 100644
--- a/engines/director/lingo/lingo-object.cpp
+++ b/engines/director/lingo/lingo-object.cpp
@@ -294,12 +294,7 @@ Symbol ScriptContext::define(const Common::String &name, ScriptData *code, Commo
sym.ctx = this;
if (debugChannelSet(1, kDebugCompile)) {
- uint pc = 0;
- while (pc < sym.u.defn->size()) {
- uint spc = pc;
- Common::String instr = g_lingo->decodeInstruction(sym.u.defn, pc, &pc);
- debugC(1, kDebugCompile, "[%5d] %s", spc, instr.c_str());
- }
+ debugC(1, kDebugCompile, "%s", g_lingo->decodeFunctionBody(sym).c_str());
debugC(1, kDebugCompile, "<end define code>");
}
@@ -387,6 +382,15 @@ bool ScriptContext::setProp(const Common::String &propName, const Datum &value)
return false;
}
+Common::String ScriptContext::formatFunctionList(const char *prefix) {
+ Common::String result;
+ for (auto it = _functionHandlers.begin(); it != _functionHandlers.end(); ++it) {
+ result += Common::String::format("%s%s\n", prefix, g_lingo->decodeFunctionName(it->_value).c_str());
+ }
+ return result;
+}
+
+
// Object array
void LM::m_get(int nargs) {
diff --git a/engines/director/lingo/lingo-object.h b/engines/director/lingo/lingo-object.h
index a8cc87c15f0..cb65915aaec 100644
--- a/engines/director/lingo/lingo-object.h
+++ b/engines/director/lingo/lingo-object.h
@@ -221,6 +221,8 @@ public:
bool setProp(const Common::String &propName, const Datum &value) override;
Symbol define(const Common::String &name, ScriptData *code, Common::Array<Common::String> *argNames, Common::Array<Common::String> *varNames);
+
+ Common::String formatFunctionList(const char *prefix);
};
namespace LM {
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index de29f6c14bd..b937b6a5509 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -261,6 +261,20 @@ Common::String LingoArchive::getName(uint16 id) {
return result;
}
+Common::String LingoArchive::formatFunctionList(const char *prefix) {
+ Common::String result;
+ for (int i = 0; i <= kMaxScriptType; i++) {
+ result += Common::String::format("%s%s:\n", prefix, scriptType2str((ScriptType)i));
+ 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 += (*it->_value).formatFunctionList(Common::String::format("%s ", prefix).c_str());
+ }
+ }
+ return result;
+}
+
Symbol Lingo::getHandler(const Common::String &name) {
Symbol sym;
@@ -468,7 +482,7 @@ Common::String Lingo::decodeScript(ScriptData *sd) {
return result;
}
-Common::String Lingo::decodeFunctionSym(Symbol &sym) {
+Common::String Lingo::decodeFunctionName(Symbol &sym) {
Common::String result;
if (sym.type != HANDLER)
return result;
@@ -481,7 +495,16 @@ Common::String Lingo::decodeFunctionSym(Symbol &sym) {
if (i < (sym.nargs - 1))
result += ", ";
}
- result += ")\n";
+ result += ")";
+ return result;
+}
+
+Common::String Lingo::decodeFunctionBody(Symbol &sym) {
+ Common::String result;
+ if (sym.type != HANDLER)
+ return result;
+ result += decodeFunctionName(sym);
+ result += "\n";
result += decodeScript(sym.u.defn);
result += "\n";
return result;
diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index 18f48535a46..b0db50268df 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -281,6 +281,7 @@ struct LingoArchive {
ScriptContext *getScriptContext(ScriptType type, uint16 id);
Common::String getName(uint16 id);
+ Common::String formatFunctionList(const char *prefix);
void addCode(const Common::U32String &code, ScriptType type, uint16 id, const char *scriptName = nullptr);
void removeCode(ScriptType type, uint16 id);
@@ -308,7 +309,8 @@ public:
Common::String formatFrame();
Common::String decodeInstruction(ScriptData *sd, uint pc, uint *newPC = NULL);
Common::String decodeScript(ScriptData *sd);
- Common::String decodeFunctionSym(Symbol &sym);
+ Common::String decodeFunctionName(Symbol &sym);
+ Common::String decodeFunctionBody(Symbol &sym);
void reloadBuiltIns();
void initBuiltIns();
diff --git a/engines/director/util.cpp b/engines/director/util.cpp
index 632acebac8b..de0691d4091 100644
--- a/engines/director/util.cpp
+++ b/engines/director/util.cpp
@@ -27,6 +27,7 @@
#include "common/tokenizer.h"
#include "common/zlib.h"
+#include "director/types.h"
#include "graphics/macgui/macwindowmanager.h"
#include "graphics/macgui/macfontmanager.h"
@@ -1025,7 +1026,7 @@ Common::String utf8ToPrintable(const Common::String &str) {
Common::String castTypeToString(const CastType &type) {
Common::String res;
- switch(type) {
+ switch (type) {
case kCastBitmap:
res = "bitmap";
break;
Commit: 29cc573d967871f74710018aa36853c594d02584
https://github.com/scummvm/scummvm/commit/29cc573d967871f74710018aa36853c594d02584
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-20T20:17:06+02:00
Commit Message:
DIRECTOR: Update scriptframe command to include cast ID
Changed paths:
engines/director/lingo/lingo-bytecode.cpp
engines/director/lingo/lingo-object.cpp
engines/director/lingo/lingo.cpp
engines/director/lingo/lingo.h
diff --git a/engines/director/lingo/lingo-bytecode.cpp b/engines/director/lingo/lingo-bytecode.cpp
index 90b143077d3..e030d353970 100644
--- a/engines/director/lingo/lingo-bytecode.cpp
+++ b/engines/director/lingo/lingo-bytecode.cpp
@@ -1573,7 +1573,7 @@ ScriptContext *LingoCompiler::compileLingoV4(Common::SeekableReadStreamEndian &s
}
if (!skipdump && ConfMan.getBool("dump_scripts")) {
- out.writeString(g_lingo->decodeFunctionBody(sym));
+ out.writeString(g_lingo->formatFunctionBody(sym));
}
_assemblyContext->_functionNames.push_back(*sym.name);
diff --git a/engines/director/lingo/lingo-object.cpp b/engines/director/lingo/lingo-object.cpp
index 70c013daf7e..bb09f58e712 100644
--- a/engines/director/lingo/lingo-object.cpp
+++ b/engines/director/lingo/lingo-object.cpp
@@ -294,7 +294,7 @@ Symbol ScriptContext::define(const Common::String &name, ScriptData *code, Commo
sym.ctx = this;
if (debugChannelSet(1, kDebugCompile)) {
- debugC(1, kDebugCompile, "%s", g_lingo->decodeFunctionBody(sym).c_str());
+ debugC(1, kDebugCompile, "%s", g_lingo->formatFunctionBody(sym).c_str());
debugC(1, kDebugCompile, "<end define code>");
}
@@ -385,7 +385,7 @@ bool ScriptContext::setProp(const Common::String &propName, const Datum &value)
Common::String ScriptContext::formatFunctionList(const char *prefix) {
Common::String result;
for (auto it = _functionHandlers.begin(); it != _functionHandlers.end(); ++it) {
- result += Common::String::format("%s%s\n", prefix, g_lingo->decodeFunctionName(it->_value).c_str());
+ result += Common::String::format("%s%s\n", prefix, g_lingo->formatFunctionName(it->_value).c_str());
}
return result;
}
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index b937b6a5509..8aa58341742 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -383,17 +383,26 @@ void Lingo::printCallStack(uint pc) {
}
Common::String Lingo::formatFrame() {
+ Common::String result;
Common::Array<CFrame *> &callstack = _vm->getCurrentWindow()->_callstack;
if (callstack.size() == 0) {
return Common::String("End of execution");
}
+ if (_currentScriptContext->_id)
+ result += Common::String::format("%d:", _currentScriptContext->_id);
CFrame *frame = callstack[callstack.size() - 1];
- const char *funcName = frame->sp.type == VOIDSYM ? "[unknown]" : frame->sp.name->c_str();
- Common::String result = Common::String::format("%s:%d\n", funcName, _pc);
- result += Common::String::format("[%3d]: %s", _pc, decodeInstruction(_currentScript, _pc).c_str());
+ if (frame->sp.type == VOIDSYM || !frame->sp.name)
+ result += "[unknown]";
+ else
+ result += frame->sp.name->c_str();
+ result += Common::String::format(" at [%3d]", _pc);
return result;
}
+Common::String Lingo::formatCurrentInstruction() {
+ return Common::String::format("[%3d]: %s", _pc, decodeInstruction(_currentScript, _pc).c_str());
+}
+
Common::String Lingo::decodeInstruction(ScriptData *sd, uint pc, uint *newPc) {
void *opcodeFunc;
Common::String res;
@@ -482,7 +491,7 @@ Common::String Lingo::decodeScript(ScriptData *sd) {
return result;
}
-Common::String Lingo::decodeFunctionName(Symbol &sym) {
+Common::String Lingo::formatFunctionName(Symbol &sym) {
Common::String result;
if (sym.type != HANDLER)
return result;
@@ -499,11 +508,11 @@ Common::String Lingo::decodeFunctionName(Symbol &sym) {
return result;
}
-Common::String Lingo::decodeFunctionBody(Symbol &sym) {
+Common::String Lingo::formatFunctionBody(Symbol &sym) {
Common::String result;
if (sym.type != HANDLER)
return result;
- result += decodeFunctionName(sym);
+ result += formatFunctionName(sym);
result += "\n";
result += decodeScript(sym.u.defn);
result += "\n";
diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index b0db50268df..9b5992e68fb 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -307,10 +307,11 @@ public:
Common::String formatCallStack(uint pc);
void printCallStack(uint pc);
Common::String formatFrame();
+ Common::String formatCurrentInstruction();
Common::String decodeInstruction(ScriptData *sd, uint pc, uint *newPC = NULL);
Common::String decodeScript(ScriptData *sd);
- Common::String decodeFunctionName(Symbol &sym);
- Common::String decodeFunctionBody(Symbol &sym);
+ Common::String formatFunctionName(Symbol &sym);
+ Common::String formatFunctionBody(Symbol &sym);
void reloadBuiltIns();
void initBuiltIns();
Commit: fe86d41701bb9ba081eb462cb3696b1a047d1760
https://github.com/scummvm/scummvm/commit/fe86d41701bb9ba081eb462cb3696b1a047d1760
Author: Scott Percival (code at moral.net.au)
Date: 2022-09-20T20:17:06+02:00
Commit Message:
DIRECTOR: Implement disasm debugger command
Changed paths:
engines/director/debugger.cpp
engines/director/debugger.h
engines/director/lingo/lingo.cpp
engines/director/lingo/lingo.h
diff --git a/engines/director/debugger.cpp b/engines/director/debugger.cpp
index 6f721e0526a..00866cc00dc 100644
--- a/engines/director/debugger.cpp
+++ b/engines/director/debugger.cpp
@@ -27,11 +27,12 @@
#include "director/frame.h"
#include "director/movie.h"
#include "director/score.h"
+#include "director/util.h"
+#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/util.h"
namespace Director {
@@ -60,6 +61,8 @@ Debugger::Debugger(): GUI::Debugger() {
registerCmd("funcs", WRAP_METHOD(Debugger, cmdFuncs));
registerCmd("backtrace", WRAP_METHOD(Debugger, cmdBacktrace));
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("step", WRAP_METHOD(Debugger, cmdStep));
registerCmd("s", WRAP_METHOD(Debugger, cmdStep));
@@ -106,7 +109,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 [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");
@@ -225,21 +228,24 @@ bool Debugger::cmdStack(int argc, const char **argv) {
bool Debugger::cmdScriptFrame(int argc, const char **argv) {
Lingo *lingo = g_director->getLingo();
debugPrintf("%s\n", lingo->formatFrame().c_str());
- debugPrintf("\n");
+ debugPrintf("%s\n", lingo->formatCurrentInstruction().c_str());
return true;
}
bool Debugger::cmdFuncs(int argc, const char **argv) {
Lingo *lingo = g_director->getLingo();
+ Movie *movie = g_director->getCurrentMovie();
+ Score *score = movie->getScore();
ScriptContext *csc = lingo->_currentScriptContext;
- debugPrintf("Frame functions:\n");
if (csc) {
- debugPrintf("%s", csc->formatFunctionList(" ").c_str());
+ debugPrintf("Functions attached to frame %d:\n", score->getCurrentFrame());
+ debugPrintf(" %d:", csc->_id);
+ debugPrintf("%s", csc->formatFunctionList(" ").c_str());
} else {
+ debugPrintf("Functions attached to frame %d:\n", score->getCurrentFrame());
debugPrintf(" [empty]\n");
}
debugPrintf("\n");
- Movie *movie = g_director->getCurrentMovie();
debugPrintf("Cast functions:\n");
Cast *cast = movie->getCast();
if (cast && cast->_lingoArchive) {
@@ -265,6 +271,56 @@ bool Debugger::cmdBacktrace(int argc, const char **argv) {
return true;
}
+bool Debugger::cmdDisasm(int argc, const char **argv) {
+ Lingo *lingo = g_director->getLingo();
+ if (argc == 2) {
+ Common::String target(argv[1]);
+ uint splitPoint = target.findFirstOf(":");
+ if (splitPoint == Common::String::npos) {
+ debugPrintf("Must provide target in format scriptid:funcname.\n");
+ return true;
+ }
+ Common::String scriptIdStr = target.substr(0, splitPoint);
+ int scriptId = atoi(scriptIdStr.c_str());
+ if (!scriptId) {
+ debugPrintf("Invalid scriptid, must be an integer.\n");
+ return true;
+ }
+
+ Common::String funcName = target.substr(splitPoint + 1, Common::String::npos);
+ Movie *movie = g_director->getCurrentMovie();
+ Cast *cast = movie->getCast();
+ if (cast && cast->_lingoArchive) {
+ ScriptContext *ctx = cast->_lingoArchive->findScriptContext(scriptId);
+ if (ctx && ctx->_functionHandlers.contains(funcName)) {
+ debugPrintf("%s\n", lingo->formatFunctionBody(ctx->_functionHandlers[funcName]).c_str());
+ return true;
+ }
+ }
+ Cast *sharedCast = movie->getSharedCast();
+ if (sharedCast && sharedCast->_lingoArchive) {
+ ScriptContext *ctx = sharedCast->_lingoArchive->findScriptContext(scriptId);
+ if (ctx && ctx->_functionHandlers.contains(funcName)) {
+ debugPrintf("%s\n", lingo->formatFunctionBody(ctx->_functionHandlers[funcName]).c_str());
+ return true;
+ }
+ }
+
+ } else {
+ Common::Array<CFrame *> &callstack = g_director->getCurrentWindow()->_callstack;
+ if (callstack.size() == 0) {
+ debugPrintf("Lingo is not executing, nothing to disassemble.\n");
+ return true;
+ } else {
+ CFrame *frame = callstack[callstack.size() - 1];
+ debugPrintf("%s\n", lingo->formatFunctionBody(frame->sp).c_str());
+ return true;
+ }
+ }
+ debugPrintf("Script not found.\n");
+ return true;
+}
+
bool Debugger::cmdVars(int argc, const char **argv) {
Lingo *lingo = g_director->getLingo();
debugPrintf("%s\n", lingo->formatAllVars().c_str());
diff --git a/engines/director/debugger.h b/engines/director/debugger.h
index dc7ce365607..aa39940a2bb 100644
--- a/engines/director/debugger.h
+++ b/engines/director/debugger.h
@@ -47,6 +47,7 @@ private:
bool cmdNextFrame(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);
bool cmdStack(int argc, const char **argv);
bool cmdScriptFrame(int argc, const char **argv);
bool cmdFuncs(int argc, const char **argv);
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index 8aa58341742..c7f219f57c7 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -251,6 +251,15 @@ ScriptContext *LingoArchive::getScriptContext(ScriptType type, uint16 id) {
return scriptContexts[type][id];
}
+ScriptContext *LingoArchive::findScriptContext(uint16 id) {
+ for (int i = 0; i < kMaxScriptType + 1; i++) {
+ if (scriptContexts[i].contains(id)) {
+ return scriptContexts[i][id];
+ }
+ }
+ return nullptr;
+}
+
Common::String LingoArchive::getName(uint16 id) {
Common::String result;
if (id >= names.size()) {
@@ -400,12 +409,17 @@ Common::String Lingo::formatFrame() {
}
Common::String Lingo::formatCurrentInstruction() {
- return Common::String::format("[%3d]: %s", _pc, decodeInstruction(_currentScript, _pc).c_str());
+ Common::String instr = decodeInstruction(_currentScript, _pc);
+ if (instr.empty())
+ return instr;
+ return Common::String::format("[%3d]: %s", _pc, instr.c_str());
}
Common::String Lingo::decodeInstruction(ScriptData *sd, uint pc, uint *newPc) {
void *opcodeFunc;
Common::String res;
+ if (!sd || pc >= sd->size())
+ return res;
opcodeFunc = (void *)(*sd)[pc++];
if (_functions.contains(opcodeFunc)) {
@@ -512,10 +526,11 @@ Common::String Lingo::formatFunctionBody(Symbol &sym) {
Common::String result;
if (sym.type != HANDLER)
return result;
+ if (sym.ctx && sym.ctx->_id)
+ result += Common::String::format("%d:", sym.ctx->_id);
result += formatFunctionName(sym);
result += "\n";
result += decodeScript(sym.u.defn);
- result += "\n";
return result;
}
diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index 9b5992e68fb..c7014a54590 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -280,6 +280,7 @@ struct LingoArchive {
SymbolHash functionHandlers;
ScriptContext *getScriptContext(ScriptType type, uint16 id);
+ ScriptContext *findScriptContext(uint16 id);
Common::String getName(uint16 id);
Common::String formatFunctionList(const char *prefix);
More information about the Scummvm-git-logs
mailing list