[Scummvm-git-logs] scummvm master -> 63a3542684e859c9af94de22db5092ae8294e12e
scemino
noreply at scummvm.org
Tue May 28 18:46:54 UTC 2024
This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
ee77c261aa DIRECTOR: Fix script offsets in imgui
63a3542684 DIRECTOR: Add stepping at lingo byte codes level
Commit: ee77c261aad271e8dcd801ac4c417403c03081c1
https://github.com/scummvm/scummvm/commit/ee77c261aad271e8dcd801ac4c417403c03081c1
Author: scemino (scemino74 at gmail.com)
Date: 2024-05-28T20:45:35+02:00
Commit Message:
DIRECTOR: Fix script offsets in imgui
Changed paths:
engines/director/debugtools.cpp
engines/director/lingo/lingo-bytecode.cpp
engines/director/lingo/lingo-object.h
diff --git a/engines/director/debugtools.cpp b/engines/director/debugtools.cpp
index 1b00f1e175f..ed0d45c430f 100644
--- a/engines/director/debugtools.cpp
+++ b/engines/director/debugtools.cpp
@@ -80,6 +80,7 @@ typedef struct ImGuiScript {
Common::String handlerId;
Common::String handlerName;
Common::String moviePath;
+ Common::Array<uint32> byteOffsets;
bool isMethod = false;
bool isGenericEvent = false;
@@ -468,10 +469,10 @@ ImGuiScript toImGuiScript(CastMemberID id, const Common::String &handlerId) {
static void setScriptToDisplay(const ImGuiScript &script);
-static Director::Breakpoint *getBreakpoint(const Common::String &handlerName, int pc) {
+static Director::Breakpoint *getBreakpoint(const Common::String &handlerName, uint16 scriptId, uint pc) {
auto &bps = g_lingo->getBreakpoints();
for (uint i = 0; i < bps.size(); i++) {
- if (bps[i].type == kBreakpointFunction && bps[i].funcName == handlerName && (int)bps[i].funcOffset == pc) {
+ if (bps[i].type == kBreakpointFunction && bps[i].scriptId == scriptId && bps[i].funcName == handlerName && bps[i].funcOffset == pc) {
return &bps[i];
}
}
@@ -1537,14 +1538,15 @@ private:
ImGui::Text("%s", (s + code).c_str());
}
- void renderLine(uint pc) const {
+ void renderLine(uint p) const {
+ uint pc = _script.byteOffsets[p];
ImDrawList *dl = ImGui::GetWindowDrawList();
ImVec2 pos = ImGui::GetCursorScreenPos();
const ImVec2 mid(pos.x + 7, pos.y + 7);
ImVec4 color = _state->_colors._bp_color_disabled;
- Director::Breakpoint *bp = getBreakpoint(_script.handlerName, pc);
+ Director::Breakpoint *bp = getBreakpoint(_script.handlerId, _script.id.member, pc);
if (bp)
color = _state->_colors._bp_color_enabled;
@@ -1556,7 +1558,8 @@ private:
} else {
Director::Breakpoint newBp;
newBp.type = kBreakpointFunction;
- newBp.funcName = _script.handlerName;
+ newBp.scriptId = _script.id.member;
+ newBp.funcName = _script.handlerId;
newBp.funcOffset = pc;
g_lingo->addBreakpoint(newBp);
color = _state->_colors._bp_color_enabled;
@@ -2423,7 +2426,7 @@ static void renderCastScript(Symbol &sym) {
color = _state->_colors._bp_color_disabled;
- Director::Breakpoint *bp = getBreakpoint(handlerName, pc);
+ Director::Breakpoint *bp = getBreakpoint(handlerName, sym.ctx->_id, pc);
if (bp)
color = _state->_colors._bp_color_enabled;
@@ -2646,6 +2649,7 @@ static void showFuncList() {
if (ImGui::Selectable(function.c_str())) {
CastMemberID memberID(scriptContext._key, cast._key);
ImGuiScript script = toImGuiScript(memberID, functionHandler._key);
+ script.byteOffsets = scriptContext._value->_functionByteOffsets[script.handlerId];
script.moviePath = movie->getArchive()->getPathName().toString();
script.handlerName = getHandlerName(functionHandler._value);
setScriptToDisplay(script);
@@ -2683,6 +2687,7 @@ static void showFuncList() {
if (ImGui::Selectable(function.c_str())) {
CastMemberID memberID(scriptContext._key, SHARED_CAST_LIB);
ImGuiScript script = toImGuiScript(memberID, functionHandler._key);
+ script.byteOffsets = scriptContext._value->_functionByteOffsets[script.handlerId];
script.moviePath = movie->getArchive()->getPathName().toString();
script.handlerName = getHandlerName(functionHandler._value);
setScriptToDisplay(script);
diff --git a/engines/director/lingo/lingo-bytecode.cpp b/engines/director/lingo/lingo-bytecode.cpp
index 452aef9d4fb..afc5ff4e168 100644
--- a/engines/director/lingo/lingo-bytecode.cpp
+++ b/engines/director/lingo/lingo-bytecode.cpp
@@ -1399,6 +1399,7 @@ ScriptContext *LingoCompiler::compileLingoV4(Common::SeekableReadStreamEndian &s
uint32 pointer = startOffset - codeStoreOffset;
Common::Array<uint32> offsetList;
Common::Array<uint32> jumpList;
+ Common::Array<uint32> byteOffsets;
// Size of an entry in the consts index.
int constEntrySize = 0;
@@ -1418,6 +1419,7 @@ ScriptContext *LingoCompiler::compileLingoV4(Common::SeekableReadStreamEndian &s
// Opcode for pushing a value from the constants table.
// Rewrite these to inline the constant into our bytecode.
offsetList.push_back(_currentAssembly->size());
+ byteOffsets.push_back(_currentAssembly->size());
int arg = 0;
if (opcode == 0x84) {
arg = (uint16)READ_BE_UINT16(&codeStore[pointer]);
@@ -1450,8 +1452,11 @@ ScriptContext *LingoCompiler::compileLingoV4(Common::SeekableReadStreamEndian &s
if (opcode == 0x84) {
offsetList.push_back(_currentAssembly->size());
offsetList.push_back(_currentAssembly->size());
+ byteOffsets.push_back(_currentAssembly->size());
+ byteOffsets.push_back(_currentAssembly->size());
} else {
offsetList.push_back(_currentAssembly->size());
+ byteOffsets.push_back(_currentAssembly->size());
}
switch (constant.type) {
case INT:
@@ -1469,6 +1474,7 @@ ScriptContext *LingoCompiler::compileLingoV4(Common::SeekableReadStreamEndian &s
}
} else if (g_lingo->_lingoV4.contains(opcode)) {
offsetList.push_back(_currentAssembly->size());
+ byteOffsets.push_back(_currentAssembly->size());
code1(g_lingo->_lingoV4[opcode]->func);
size_t argc = strlen(g_lingo->_lingoV4[opcode]->proto);
@@ -1480,12 +1486,14 @@ ScriptContext *LingoCompiler::compileLingoV4(Common::SeekableReadStreamEndian &s
case 'b':
// read one uint8 as an argument
offsetList.push_back(_currentAssembly->size());
+ byteOffsets.push_back(_currentAssembly->size());
arg = (uint8)codeStore[pointer];
pointer += 1;
break;
case 'B':
// read one int8 as an argument
offsetList.push_back(_currentAssembly->size());
+ byteOffsets.push_back(_currentAssembly->size());
arg = (int8)codeStore[pointer];
pointer += 1;
break;
@@ -1493,6 +1501,8 @@ ScriptContext *LingoCompiler::compileLingoV4(Common::SeekableReadStreamEndian &s
// read one uint16 as an argument
offsetList.push_back(_currentAssembly->size());
offsetList.push_back(_currentAssembly->size());
+ byteOffsets.push_back(_currentAssembly->size());
+ byteOffsets.push_back(_currentAssembly->size());
arg = (uint16)READ_BE_UINT16(&codeStore[pointer]);
pointer += 2;
break;
@@ -1500,6 +1510,8 @@ ScriptContext *LingoCompiler::compileLingoV4(Common::SeekableReadStreamEndian &s
// read one int16 as an argument
offsetList.push_back(_currentAssembly->size());
offsetList.push_back(_currentAssembly->size());
+ byteOffsets.push_back(_currentAssembly->size());
+ byteOffsets.push_back(_currentAssembly->size());
arg = (int16)READ_BE_INT16(&codeStore[pointer]);
pointer += 2;
break;
@@ -1555,24 +1567,30 @@ ScriptContext *LingoCompiler::compileLingoV4(Common::SeekableReadStreamEndian &s
if (opcode < 0x40) { // 1 byte instruction
debugC(5, kDebugCompile, "Unimplemented opcode: 0x%02x", opcode);
offsetList.push_back(_currentAssembly->size());
+ byteOffsets.push_back(_currentAssembly->size());
code1(LC::cb_unk);
codeInt(opcode);
} else if (opcode < 0x80) { // 2 byte instruction
debugC(5, kDebugCompile, "Unimplemented opcode: 0x%02x (%d)", opcode, (uint)codeStore[pointer]);
offsetList.push_back(_currentAssembly->size());
+ byteOffsets.push_back(_currentAssembly->size());
code1(LC::cb_unk1);
codeInt(opcode);
offsetList.push_back(_currentAssembly->size());
+ byteOffsets.push_back(_currentAssembly->size());
codeInt((uint)codeStore[pointer]);
pointer += 1;
} else { // 3 byte instruction
debugC(5, kDebugCompile, "Unimplemented opcode: 0x%02x (%d, %d)", opcode, (uint)codeStore[pointer], (uint)codeStore[pointer+1]);
offsetList.push_back(_currentAssembly->size());
+ byteOffsets.push_back(_currentAssembly->size());
code1(LC::cb_unk2);
codeInt(opcode);
offsetList.push_back(_currentAssembly->size());
+ byteOffsets.push_back(_currentAssembly->size());
codeInt((uint)codeStore[pointer]);
offsetList.push_back(_currentAssembly->size());
+ byteOffsets.push_back(_currentAssembly->size());
codeInt((uint)codeStore[pointer+1]);
pointer += 2;
}
@@ -1622,6 +1640,8 @@ ScriptContext *LingoCompiler::compileLingoV4(Common::SeekableReadStreamEndian &s
sym.varNames = varNames;
}
+ _assemblyContext->_functionByteOffsets[functionName] = byteOffsets;
+
if (!skipdump && ConfMan.getBool("dump_scripts")) {
out.writeString(g_lingo->formatFunctionBody(sym));
}
diff --git a/engines/director/lingo/lingo-object.h b/engines/director/lingo/lingo-object.h
index 53f60a1da0d..f0c7547b0d3 100644
--- a/engines/director/lingo/lingo-object.h
+++ b/engines/director/lingo/lingo-object.h
@@ -210,6 +210,7 @@ public:
ScriptType _scriptType;
int _id;
Common::Array<Common::String> _functionNames; // used by cb_localcall
+ Common::HashMap<Common::String, Common::Array<uint32>> _functionByteOffsets;
SymbolHash _functionHandlers;
Common::HashMap<uint32, Symbol> _eventHandlers;
Common::Array<Datum> _constants;
Commit: 63a3542684e859c9af94de22db5092ae8294e12e
https://github.com/scummvm/scummvm/commit/63a3542684e859c9af94de22db5092ae8294e12e
Author: scemino (scemino74 at gmail.com)
Date: 2024-05-28T20:45:35+02:00
Commit Message:
DIRECTOR: Add stepping at lingo byte codes level
Changed paths:
engines/director/debugtools.cpp
engines/director/lingo/lingo.cpp
engines/director/lingo/lingo.h
diff --git a/engines/director/debugtools.cpp b/engines/director/debugtools.cpp
index ed0d45c430f..ad9c41d9642 100644
--- a/engines/director/debugtools.cpp
+++ b/engines/director/debugtools.cpp
@@ -88,6 +88,7 @@ typedef struct ImGuiScript {
Common::StringArray propertyNames;
Common::StringArray globalNames;
Common::SharedPtr<LingoDec::HandlerNode> root;
+ Common::Array<LingoDec::Bytecode> bytecodeArray;
bool operator==(const ImGuiScript &c) const {
return moviePath == c.moviePath && score == c.score && id == c.id && handlerId == c.handlerId;
@@ -377,6 +378,7 @@ typedef struct ImGuiState {
ImVec4 _bp_color_disabled = ImVec4(0.9f, 0.08f, 0.0f, 0.0f);
ImVec4 _bp_color_enabled = ImVec4(0.9f, 0.08f, 0.0f, 1.0f);
ImVec4 _bp_color_hover = ImVec4(0.42f, 0.17f, 0.13f, 1.0f);
+ ImVec4 _current_statement = ImColor(IM_COL32(0xFF, 0xFF, 0x00, 0xFF));
ImVec4 _line_color = ImVec4(0.44f, 0.44f, 0.44f, 1.0f);
ImVec4 _call_color = ImColor(IM_COL32(0xFF, 0xC5, 0x5C, 0xFF));
ImVec4 _builtin_color = ImColor(IM_COL32(0x60, 0x7C, 0xFF, 0xFF));
@@ -428,17 +430,23 @@ typedef struct ImGuiState {
ImGuiState *_state = nullptr;
const LingoDec::Handler *getHandler(CastMemberID id, const Common::String &handlerId) {
- Director::Movie *movie = g_director->getCurrentMovie();
- const Director::Cast *cast = movie->getCast(id);
- if (!cast->_lingodec)
- return nullptr;
-
- Common::SharedPtr<LingoDec::Node> node;
- for (auto it : cast->_lingodec->scripts) {
- for (const LingoDec::Handler &h : it.second->handlers) {
- if (h.name != handlerId)
+ const Director::Movie *movie = g_director->getCurrentMovie();
+ const Cast *targets[2] = {movie->getCast(), movie->getSharedCast()};
+ for (int i = 0; i < 2; i++) {
+ const Cast *cast = targets[i];
+ if (!cast)
+ continue;
+ const ScriptContext *ctx = cast->_lingoArchive->findScriptContext(id.member);
+ if (!ctx || !ctx->_functionHandlers.contains(handlerId))
+ continue;
+ for (auto p : cast->_lingodec->scripts) {
+ if (p.second->castID != id.member)
continue;
- return &h;
+ for (const LingoDec::Handler &handler : p.second->handlers) {
+ if (handler.name == handlerId) {
+ return &handler;
+ }
+ }
}
}
return nullptr;
@@ -453,6 +461,7 @@ ImGuiScript toImGuiScript(CastMemberID id, const Common::String &handlerId) {
if (!handler)
return result;
+ result.bytecodeArray = handler->bytecodeArray;
result.root = handler->ast.root;
result.isGenericEvent = handler->isGenericEvent;
result.argumentNames = handler->argumentNames;
@@ -481,11 +490,15 @@ static Director::Breakpoint *getBreakpoint(const Common::String &handlerName, ui
class RenderScriptVisitor : public LingoDec::NodeVisitor {
public:
- explicit RenderScriptVisitor(ImGuiScript &script, bool showByteCode) : _script(script), _showByteCode(showByteCode) {}
+ explicit RenderScriptVisitor(ImGuiScript &script, bool showByteCode) : _script(script), _showByteCode(showByteCode) {
+ Common::Array<CFrame *> &callstack = g_lingo->_state->callstack;
+ if (!callstack.empty()) {
+ CFrame *head = callstack[callstack.size() - 1];
+ _isScriptInDebug = (head->sp.ctx->_id == script.id.member) && (*head->sp.name == script.handlerId);
+ }
+ }
virtual void visit(const LingoDec::HandlerNode &node) override {
- _handler = node.handler;
-
if (_showByteCode) {
byteCode(node);
return;
@@ -537,9 +550,9 @@ public:
virtual void visit(const LingoDec::CallNode &node) override {
int32 obj = 0;
- for (uint i = 0; i < _handler->bytecodeArray.size(); i++) {
- if (node._startOffset == _handler->bytecodeArray[i].pos) {
- obj = _handler->bytecodeArray[i].obj;
+ for (uint i = 0; i < _script.bytecodeArray.size(); i++) {
+ if (node._startOffset == _script.bytecodeArray[i].pos) {
+ obj = _script.bytecodeArray[i].obj;
break;
}
}
@@ -1452,7 +1465,7 @@ private:
}
}
- void byteCode(const LingoDec::HandlerNode &node) const {
+ void byteCode(const LingoDec::HandlerNode &node) {
LingoDec::Handler *handler = node.handler;
bool isMethod = handler->script->isFactory();
@@ -1523,13 +1536,13 @@ private:
}
}
- void write(uint32 offset, const Common::String &code, ImVec4 color = ImVec4(1, 1, 1, 1)) const {
+ void write(uint32 offset, const Common::String &code, ImVec4 color = ImVec4(1, 1, 1, 1)) {
renderLine(offset);
renderIndentation();
ImGui::TextColored(color, "%s", code.c_str());
}
- void writeByteCode(uint32 offset, const Common::String &code) const {
+ void writeByteCode(uint32 offset, const Common::String &code) {
renderLine(offset);
Common::String s;
for (int i = 0; i < _indent; i++) {
@@ -1538,19 +1551,34 @@ private:
ImGui::Text("%s", (s + code).c_str());
}
- void renderLine(uint p) const {
+ void renderLine(uint p) {
+ bool showCurrentStatement = false;
+ p = MIN(p, _script.byteOffsets.size() - 1);
uint pc = _script.byteOffsets[p];
+
+ if (_isScriptInDebug && g_lingo->_exec._state == kPause) {
+ // check current statement
+ if (!_currentStatementDisplayed) {
+ if (g_lingo->_state->pc <= pc) {
+ showCurrentStatement = true;
+ _currentStatementDisplayed = true;
+ }
+ }
+ }
+
ImDrawList *dl = ImGui::GetWindowDrawList();
- ImVec2 pos = ImGui::GetCursorScreenPos();
+ const ImVec2 pos = ImGui::GetCursorScreenPos();
+ const float width = ImGui::GetContentRegionAvail().x;
const ImVec2 mid(pos.x + 7, pos.y + 7);
ImVec4 color = _state->_colors._bp_color_disabled;
-
- Director::Breakpoint *bp = getBreakpoint(_script.handlerId, _script.id.member, pc);
+ const Director::Breakpoint *bp = getBreakpoint(_script.handlerId, _script.id.member, pc);
if (bp)
color = _state->_colors._bp_color_enabled;
ImGui::InvisibleButton("Line", ImVec2(16, ImGui::GetFontSize()));
+
+ // click on breakpoint column?
if (ImGui::IsItemClicked(0)) {
if (color == _state->_colors._bp_color_enabled) {
g_lingo->delBreakpoint(bp->id);
@@ -1570,15 +1598,28 @@ private:
color = _state->_colors._bp_color_hover;
}
+ // draw breakpoint
if (!bp || bp->enabled)
dl->AddCircleFilled(mid, 4.0f, ImColor(color));
else
dl->AddCircle(mid, 4.0f, ImColor(_state->_colors._line_color));
+
+ // draw current statement
+ if (showCurrentStatement) {
+ dl->AddQuadFilled(ImVec2(pos.x, pos.y + 4.f), ImVec2(pos.x + 9.f, pos.y + 4.f), ImVec2(pos.x + 9.f, pos.y + 10.f), ImVec2(pos.x, pos.y + 10.f), ImColor(_state->_colors._current_statement));
+ dl->AddTriangleFilled(ImVec2(pos.x + 8.f, pos.y), ImVec2(pos.x + 14.f, pos.y + 7.f), ImVec2(pos.x + 8.f, pos.y + 14.f), ImColor(_state->_colors._current_statement));
+ if (!ImGui::IsItemVisible()) {
+ ImGui::SetScrollHereY(0.5f);
+ }
+ dl->AddRectFilled(ImVec2(pos.x + 16.f, pos.y), ImVec2(pos.x + width, pos.y + 16.f), ImColor(IM_COL32(0xFF, 0xFF, 0x00, 0x20)), 0.4f);
+ }
+ // draw separator
dl->AddLine(ImVec2(pos.x + 16.0f, pos.y), ImVec2(pos.x + 16.0f, pos.y + 17), ImColor(_state->_colors._line_color));
ImGui::SetItemTooltip("Click to add a breakpoint");
-
ImGui::SameLine();
+
+ // draw offset
ImGui::Text("[%5d] ", pc);
ImGui::SameLine();
}
@@ -1612,7 +1653,8 @@ private:
bool _showByteCode = false;
bool _dot = false;
int _indent = 0;
- LingoDec::Handler *_handler = nullptr;
+ bool _currentStatementDisplayed = false;
+ bool _isScriptInDebug = false;
};
static void showControlPanel() {
@@ -1686,8 +1728,10 @@ static void showControlPanel() {
p = ImGui::GetCursorScreenPos();
ImGui::InvisibleButton("Stop", buttonSize);
- if (ImGui::IsItemClicked(0))
+ if (ImGui::IsItemClicked(0)) {
score->_playState = kPlayPaused;
+ g_lingo->_exec._state = kPause;
+ }
if (ImGui::IsItemHovered())
dl->AddRectFilled(ImVec2(p.x + bgX1, p.y + bgX1), ImVec2(p.x + bgX2, p.y + bgX2), bgcolor, 3.0f, ImDrawFlags_RoundCornersAll);
@@ -1724,8 +1768,11 @@ static void showControlPanel() {
p = ImGui::GetCursorScreenPos();
ImGui::InvisibleButton("Play", buttonSize);
- if (ImGui::IsItemClicked(0))
+ if (ImGui::IsItemClicked(0)) {
score->_playState = kPlayStarted;
+ g_lingo->_exec._step = -1;
+ g_lingo->_exec._state = kRunning;
+ }
if (ImGui::IsItemHovered())
dl->AddRectFilled(ImVec2(p.x + bgX1, p.y + bgX1), ImVec2(p.x + bgX2, p.y + bgX2), bgcolor, 3.0f, ImDrawFlags_RoundCornersAll);
@@ -1758,8 +1805,13 @@ static void showControlPanel() {
p = ImGui::GetCursorScreenPos();
ImGui::InvisibleButton("Step Over", buttonSize);
- if (ImGui::IsItemClicked(0))
+ if (ImGui::IsItemClicked(0)) {
score->_playState = kPlayStarted;
+ g_lingo->_exec._state = kRunning;
+ g_lingo->_exec._step = -1;
+ g_lingo->_exec._next._enabled = true;
+ g_lingo->_exec._next._stackSize = g_lingo->_state->callstack.size();
+ }
if (ImGui::IsItemHovered())
dl->AddRectFilled(ImVec2(p.x + bgX1, p.y + bgX1), ImVec2(p.x + bgX2, p.y + bgX2), bgcolor, 3.0f, ImDrawFlags_RoundCornersAll);
@@ -1778,8 +1830,11 @@ static void showControlPanel() {
p = ImGui::GetCursorScreenPos();
ImGui::InvisibleButton("Step Into", buttonSize);
- if (ImGui::IsItemClicked(0))
+ if (ImGui::IsItemClicked(0)) {
score->_playState = kPlayStarted;
+ g_lingo->_exec._step = 1;
+ g_lingo->_exec._state = kRunning;
+ }
if (ImGui::IsItemHovered())
dl->AddRectFilled(ImVec2(p.x + bgX1, p.y + bgX1), ImVec2(p.x + bgX2, p.y + bgX2), bgcolor, 3.0f, ImDrawFlags_RoundCornersAll);
@@ -1797,8 +1852,13 @@ static void showControlPanel() {
p = ImGui::GetCursorScreenPos();
ImGui::InvisibleButton("Step Out", buttonSize);
- if (ImGui::IsItemClicked(0))
+ if (ImGui::IsItemClicked(0)) {
score->_playState = kPlayStarted;
+ g_lingo->_exec._state = kRunning;
+ g_lingo->_exec._step = -1;
+ g_lingo->_exec._next._enabled = true;
+ g_lingo->_exec._next._stackSize = g_lingo->_state->callstack.size() - 1;
+ }
if (ImGui::IsItemHovered())
dl->AddRectFilled(ImVec2(p.x + bgX1, p.y + bgX1), ImVec2(p.x + bgX2, p.y + bgX2), bgcolor, 3.0f, ImDrawFlags_RoundCornersAll);
@@ -2257,6 +2317,10 @@ static void addScriptCastToDisplay(CastMemberID &id) {
static void setScriptToDisplay(const ImGuiScript &script) {
uint index = _state->_functions._scripts.size();
+ if (index && _state->_functions._scripts[index - 1] == script) {
+ _state->_functions._showScript = true;
+ return;
+ }
_state->_functions._scripts.push_back(script);
_state->_functions._current = index;
_state->_functions._showScript = true;
@@ -2516,7 +2580,29 @@ static void displayScriptCasts() {
}
}
+static void updateCurrentScript() {
+ if (g_lingo->_exec._state != kPause)
+ return;
+
+ Common::Array<CFrame *> &callstack = g_lingo->_state->callstack;
+ if (callstack.empty())
+ return;
+
+ // show current script of the current stack frame
+ CFrame *head = callstack[callstack.size() - 1];
+ Director::Movie *movie = g_director->getCurrentMovie();
+ ScriptContext *scriptContext = head->sp.ctx;
+ int castLibID = movie->getCast()->_castLibID;
+ ImGuiScript script = toImGuiScript(CastMemberID(head->sp.ctx->_id, castLibID), *head->sp.name);
+ script.byteOffsets = scriptContext->_functionByteOffsets[script.handlerId];
+ script.moviePath = movie->getArchive()->getPathName().toString();
+ script.handlerName = head->sp.ctx->_id ? Common::String::format("%d:%s", head->sp.ctx->_id, script.handlerId.c_str()) : script.handlerId;
+ setScriptToDisplay(script);
+}
+
static void displayScripts() {
+ updateCurrentScript();
+
if (!_state->_functions._showScript)
return;
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index 8a17269e925..fc71f98d71c 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -617,6 +617,24 @@ bool Lingo::execute() {
uint localCounter = 0;
while (!_abort && !_freezeState && _state->script && (*_state->script)[_state->pc] != STOP) {
+ if(_exec._next._enabled && _state->callstack.size() == _exec._next._stackSize) {
+ // we reach the next statement -> pause the execution
+ _exec._state = kPause;
+ _exec._next._enabled = false;
+ }
+ if(!_exec._step || _exec._state == kPause) {
+ // if execution is in pause -> poll event + update screen
+ _exec._state = kPause;
+ Common::EventManager *eventMan = g_system->getEventManager();
+ while (_exec._state == kPause && !eventMan->shouldQuit() && (!g_engine || !eventMan->shouldReturnToLauncher())) {
+ Common::Event event;
+ while (eventMan->pollEvent(event)) {
+ }
+ g_system->delayMillis(10);
+ g_system->updateScreen();
+ }
+ }
+
if (_globalCounter > 1000 && debugChannelSet(-1, kDebugFewFramesOnly)) {
warning("Lingo::execute(): Stopping due to debug few frames only");
_vm->getCurrentMovie()->getScore()->_playState = kPlayStopped;
@@ -656,6 +674,7 @@ bool Lingo::execute() {
}
g_debugger->stepHook();
+ if (_exec._step > 0) _exec._step--;
_state->pc++;
(*((*_state->script)[_state->pc - 1]))();
diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index f1dd15b3217..663e498c8fb 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -337,6 +337,11 @@ struct LingoState {
~LingoState();
};
+enum LingoExecState {
+ kRunning,
+ kPause,
+};
+
class Lingo {
public:
@@ -551,6 +556,15 @@ public:
Datum _windowList;
Symbol _currentInputEvent;
+ struct {
+ LingoExecState _state = kRunning;
+ int _step = -1;
+ struct {
+ uint _stackSize = 0;
+ bool _enabled = false;
+ } _next;
+ } _exec;
+
public:
void executeImmediateScripts(Frame *frame);
void executePerFrameHook(int frame, int subframe);
More information about the Scummvm-git-logs
mailing list