[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