[Scummvm-git-logs] scummvm master -> a4c054604456a2134b9543ad8b822f84447bdefb
sev-
noreply at scummvm.org
Sat Feb 28 15:10:37 UTC 2026
This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
1466f4253f SCUMM: EDITOR: Add loadGame method to ScummEditor
a4c0546044 SCUMM: EDITOR: Introduce Explorer window
Commit: 1466f4253fa9974521666e70e13ec218ce1ea323
https://github.com/scummvm/scummvm/commit/1466f4253fa9974521666e70e13ec218ce1ea323
Author: Sebastien Ronsse (sronsse at gmail.com)
Date: 2026-02-28T16:10:32+01:00
Commit Message:
SCUMM: EDITOR: Add loadGame method to ScummEditor
Changed paths:
engines/scumm/debugger/editor.cpp
engines/scumm/debugger/editor.h
diff --git a/engines/scumm/debugger/editor.cpp b/engines/scumm/debugger/editor.cpp
index afaf2746744..1d60d43c27a 100644
--- a/engines/scumm/debugger/editor.cpp
+++ b/engines/scumm/debugger/editor.cpp
@@ -23,8 +23,10 @@
#include "common/config-manager.h"
#include "common/formats/json.h"
+#include "common/hash-str.h"
#include "common/savefile.h"
+#include "scumm/resource.h"
#include "scumm/scumm.h"
#include "scumm/debugger/editor.h"
@@ -41,6 +43,8 @@ static const char *colorNames[] = {"Label", "Property", "Warning", "Error"};
ScummEditor::ScummEditor(ScummEngine *engine)
: _engine(engine),
_gameName(ConfMan.get("gameid")),
+ _gamePath(ConfMan.get("path")),
+ _resource(engine->_game.version),
_showSettings(false) {
// Specify default colors
_colors.resize(Editor::kColorCount);
@@ -49,9 +53,32 @@ ScummEditor::ScummEditor(ScummEngine *engine)
_colors[Editor::kColorWarning] = ImVec4(0.710f, 0.537f, 0.000f, 1.0f); // SOL_YELLOW
_colors[Editor::kColorError] = ImVec4(0.863f, 0.196f, 0.184f, 1.0f); // SOL_RED
+ loadGame();
loadState();
}
+void ScummEditor::loadGame() {
+ // Add index file
+ _resource.addFile(_gamePath.join(_engine->generateFilename(0)), _engine->getEncByte(0));
+
+ // Find data files
+ Common::HashMap<Common::String, bool, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> files;
+ for (int i = 1; i < _engine->_numRooms; ++i) {
+ // Skip invalid rooms
+ if (_engine->_res->_types[rtRoom][i]._roomno == 0)
+ continue;
+
+ // Skip duplicates
+ Common::String filename = _engine->generateFilename(i).toString();
+ if (files.contains(filename))
+ continue;
+
+ // Add data file
+ _resource.addFile(_gamePath.join(filename), _engine->getEncByte(i));
+ files[filename] = true;
+ }
+}
+
void ScummEditor::loadState() {
// Read from save file
Common::InSaveFile *stream = g_engine->getSaveFileManager()->openForLoading(saveStateFileName);
diff --git a/engines/scumm/debugger/editor.h b/engines/scumm/debugger/editor.h
index dd91269a192..4fb8eaeea6b 100644
--- a/engines/scumm/debugger/editor.h
+++ b/engines/scumm/debugger/editor.h
@@ -27,6 +27,8 @@
#include "common/array.h"
#include "common/str.h"
+#include "scumm/debugger/resource.h"
+
namespace Scumm {
class ScummEngine;
@@ -47,10 +49,15 @@ class ScummEditor {
private:
ScummEngine *_engine;
Common::String _gameName;
+ Common::Path _gamePath;
+
+ Editor::Resource _resource;
Common::Array<ImVec4> _colors;
bool _showSettings;
+ void loadGame();
+
void loadState();
void saveState();
Commit: a4c054604456a2134b9543ad8b822f84447bdefb
https://github.com/scummvm/scummvm/commit/a4c054604456a2134b9543ad8b822f84447bdefb
Author: Sebastien Ronsse (sronsse at gmail.com)
Date: 2026-02-28T16:10:32+01:00
Commit Message:
SCUMM: EDITOR: Introduce Explorer window
Changed paths:
A engines/scumm/debugger/explorer.cpp
A engines/scumm/debugger/explorer.h
engines/scumm/debugger/editor.cpp
engines/scumm/debugger/editor.h
engines/scumm/module.mk
diff --git a/engines/scumm/debugger/editor.cpp b/engines/scumm/debugger/editor.cpp
index 1d60d43c27a..08f3f109bcc 100644
--- a/engines/scumm/debugger/editor.cpp
+++ b/engines/scumm/debugger/editor.cpp
@@ -32,6 +32,7 @@
#include "scumm/debugger/editor.h"
#define ICON_EDITOR ICON_MS_CONSTRUCTION
+#define ICON_EXPLORER ICON_MS_DATABASE
#define ICON_SETTINGS ICON_MS_SETTINGS
namespace Scumm {
@@ -45,7 +46,9 @@ ScummEditor::ScummEditor(ScummEngine *engine)
_gameName(ConfMan.get("gameid")),
_gamePath(ConfMan.get("path")),
_resource(engine->_game.version),
- _showSettings(false) {
+ _explorer(&_resource, _colors),
+ _showSettings(false),
+ _showExplorer(true) {
// Specify default colors
_colors.resize(Editor::kColorCount);
_colors[Editor::kColorLabel] = ImVec4(0.149f, 0.545f, 0.824f, 1.0f); // SOL_BLUE
@@ -97,6 +100,12 @@ void ScummEditor::loadState() {
if (!state)
return;
+ // Load window visibility
+ if (state->asObject().contains("Windows")) {
+ int64 flags = state->asObject()["Windows"]->asIntegerNumber();
+ _showExplorer = flags & (1 << 0);
+ }
+
// Load colors
if (state->asObject().contains("Colors")) {
const Common::JSONObject &colors = state->asObject()["Colors"]->asObject();
@@ -111,6 +120,10 @@ void ScummEditor::loadState() {
}
}
+ // Load editor states
+ if (state->asObject().contains("Explorer"))
+ _explorer.loadState(state->asObject()["Explorer"]->asObject());
+
// Load ImGui layout
if (state->asObject().contains("IniSettings")) {
const char *iniSettings = state->asObject()["IniSettings"]->asString().c_str();
@@ -139,6 +152,12 @@ void ScummEditor::loadState() {
void ScummEditor::saveState() {
Common::JSONObject json;
+ // Save window visibility
+ int64 flags = 0;
+ if (_showExplorer)
+ flags |= (1 << 0);
+ json["Windows"] = new Common::JSONValue((long long int)flags);
+
// Save colors
Common::JSONObject colors;
for (uint i = 0; i < _colors.size(); ++i) {
@@ -151,6 +170,9 @@ void ScummEditor::saveState() {
}
json["Colors"] = new Common::JSONValue(colors);
+ // Save editor states
+ json["Explorer"] = new Common::JSONValue(_explorer.saveState());
+
// Save layout
const char *iniSettings = ImGui::SaveIniSettingsToMemory();
json["IniSettings"] = new Common::JSONValue(iniSettings);
@@ -187,6 +209,9 @@ void ScummEditor::showSettings() {
for (uint i = 0; i < _colors.size(); ++i)
ImGui::ColorEdit4(colorNames[i], &_colors[i].x);
+ // Show editor settings
+ _explorer.showSettings();
+
// ImGui settings
if (ImGui::CollapsingHeader("ImGui", ImGuiTreeNodeFlags_DefaultOpen)) {
ImGuiStyle &style = ImGui::GetStyle();
@@ -198,7 +223,7 @@ void ScummEditor::showSettings() {
}
void ScummEditor::render() {
- ImGui::DockSpaceOverViewport(0, ImGui::GetMainViewport(), ImGuiDockNodeFlags_PassthruCentralNode);
+ ImGuiID dockSpaceId = ImGui::DockSpaceOverViewport(0, ImGui::GetMainViewport(), ImGuiDockNodeFlags_PassthruCentralNode);
// Menu bar
if (ImGui::BeginMainMenuBar()) {
@@ -211,12 +236,18 @@ void ScummEditor::render() {
ImGui::EndMenu();
}
if (ImGui::BeginMenu("View")) {
+ ImGui::MenuItem(ICON_EXPLORER " Explorer", nullptr, &_showExplorer);
+ ImGui::Separator();
ImGui::MenuItem(ICON_SETTINGS " Settings", nullptr, &_showSettings);
ImGui::EndMenu();
}
ImGui::EndMainMenuBar();
}
+ // Editor windows
+ if (_showExplorer)
+ _explorer.render(ICON_EXPLORER, dockSpaceId, &_showExplorer);
+
// Settings window
if (_showSettings)
showSettings();
diff --git a/engines/scumm/debugger/editor.h b/engines/scumm/debugger/editor.h
index 4fb8eaeea6b..f2012a4f832 100644
--- a/engines/scumm/debugger/editor.h
+++ b/engines/scumm/debugger/editor.h
@@ -27,6 +27,7 @@
#include "common/array.h"
#include "common/str.h"
+#include "scumm/debugger/explorer.h"
#include "scumm/debugger/resource.h"
namespace Scumm {
@@ -52,9 +53,11 @@ private:
Common::Path _gamePath;
Editor::Resource _resource;
+ Editor::Explorer _explorer;
Common::Array<ImVec4> _colors;
bool _showSettings;
+ bool _showExplorer;
void loadGame();
diff --git a/engines/scumm/debugger/explorer.cpp b/engines/scumm/debugger/explorer.cpp
new file mode 100644
index 00000000000..0a3123e61d6
--- /dev/null
+++ b/engines/scumm/debugger/explorer.cpp
@@ -0,0 +1,223 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/formats/json.h"
+#include "common/str.h"
+
+#include "backends/imgui/imgui.h"
+#include "backends/imgui/components/imgui_memory_editor.h"
+
+#include "scumm/debugger/editor.h"
+#include "scumm/debugger/explorer.h"
+#include "scumm/debugger/file.h"
+
+namespace Scumm {
+
+namespace Editor {
+
+static const char *explorerColorNames[] = {"Data", "Zero"};
+
+Explorer::Explorer(Resource *resource, Common::Array<ImVec4> &colors)
+ : _resource(resource),
+ _colors(colors) {
+ // Specify default colors
+ _explorerColors.resize(kColorCount);
+ _explorerColors[kColorData] = ImVec4(0.165f, 0.631f, 0.596f, 1.0f); // SOL_CYAN
+ _explorerColors[kColorZero] = ImVec4(0.345f, 0.431f, 0.459f, 1.0f); // SOL_BASE01
+}
+
+void Explorer::renderTab(int fileIndex) {
+ // Ensure resource contains valid blocks
+ const Common::Array<Block> &blocks = _resource->getBlocks(fileIndex);
+ if (blocks.empty()) {
+ ImGui::TextColored(_colors[kColorError], "No blocks!");
+ return;
+ }
+
+ // Initialize block selection
+ _selectedBlocks.resize(fileIndex + 1, -1);
+ if (_selectedBlocks[fileIndex] >= (int)blocks.size())
+ _selectedBlocks[fileIndex] = -1;
+
+ // Render block tree and data
+ renderTree(blocks, _selectedBlocks[fileIndex]);
+ ImGui::SameLine();
+ renderBlock(fileIndex);
+}
+
+void Explorer::renderTree(const Common::Array<Block> &blocks, int &selectedBlock) {
+ ImGui::BeginChild("BlockTree", ImVec2(350, 0), ImGuiChildFlags_Borders | ImGuiChildFlags_ResizeX);
+
+ // Find and render root blocks
+ for (uint i = 0; i < blocks.size(); ++i)
+ if (blocks[i].parent == -1)
+ renderTreeNode(blocks, i, selectedBlock);
+
+ ImGui::EndChild();
+}
+
+void Explorer::renderTreeNode(const Common::Array<Block> &blocks, int blockIndex, int &selectedBlock) {
+ const Block &block = blocks[blockIndex];
+
+ // Setup flags
+ ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_SpanAvailWidth;
+ if (block.children.empty())
+ flags |= ImGuiTreeNodeFlags_Leaf;
+ if (selectedBlock == blockIndex)
+ flags |= ImGuiTreeNodeFlags_Selected;
+
+ // Render node
+ Common::String label = Common::String::format("%s [0x%08X]", tag2str(block.tag), block.offset);
+ bool nodeOpen = ImGui::TreeNodeEx((void *)(intptr_t)blockIndex, flags, label.c_str());
+ if (ImGui::IsItemClicked())
+ selectedBlock = blockIndex;
+
+ // Render children
+ if (nodeOpen) {
+ for (uint i = 0; i < block.children.size(); ++i)
+ renderTreeNode(blocks, block.children[i], selectedBlock);
+ ImGui::TreePop();
+ }
+}
+
+void Explorer::renderBlock(int fileIndex) {
+ const Common::Array<Block> &blocks = _resource->getBlocks(fileIndex);
+
+ ImGui::BeginChild("BlockContents", ImVec2(0, 0), ImGuiChildFlags_Borders, ImGuiWindowFlags_NoScrollbar);
+
+ // Render selected block
+ if (_selectedBlocks[fileIndex] != -1) {
+ const Block &block = blocks[_selectedBlocks[fileIndex]];
+
+ // Info section
+ ImGui::SeparatorText("Block Info");
+ if (ImGui::BeginTable("BlockInfo", 2, ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_NoHostExtendX | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit)) {
+ ImGui::TableSetupColumn("Property");
+ ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_WidthFixed, 0.0f);
+ ImGui::TableNextRow();
+ ImGui::TableNextColumn();
+ ImGui::TextColored(_colors[kColorLabel], "Tag");
+ ImGui::TableNextColumn();
+ ImGui::TextColored(_colors[kColorProperty], "%s", tag2str(block.tag));
+ ImGui::TableNextRow();
+ ImGui::TableNextColumn();
+ ImGui::TextColored(_colors[kColorLabel], "Size");
+ ImGui::TableNextColumn();
+ ImGui::TextColored(_colors[kColorProperty], "%u", block.size);
+ ImGui::TableNextRow();
+ ImGui::TableNextColumn();
+ ImGui::TextColored(_colors[kColorLabel], "Offset");
+ ImGui::TableNextColumn();
+ ImGui::TextColored(_colors[kColorProperty], "0x%08X", block.offset);
+ ImGui::TableNextRow();
+ ImGui::TableNextColumn();
+ ImGui::TextColored(_colors[kColorLabel], "Children");
+ ImGui::TableNextColumn();
+ ImGui::TextColored(_colors[kColorProperty], "%u", block.children.size());
+ ImGui::EndTable();
+ }
+
+ // Prepare memory editor
+ struct ReadFnData { File *file; uint32 baseOffset; };
+ ReadFnData readFnData = {_resource->getFile(fileIndex), block.offset};
+ MemoryEditor memEdit;
+ memEdit.ReadOnly = true;
+ memEdit.OptShowOptions = false;
+ memEdit.UserData = &readFnData;
+ memEdit.ReadFn = [](const ImU8 *, size_t off, void *userData) -> ImU8 {
+ ReadFnData *data = static_cast<ReadFnData *>(userData);
+ data->file->seek(data->baseOffset + off);
+ return data->file->readByte();
+ };
+
+ // Data section
+ ImGui::SeparatorText("Block Data");
+ ImGui::PushStyleColor(ImGuiCol_Text, _explorerColors[kColorData]);
+ ImGui::PushStyleColor(ImGuiCol_TextDisabled, _explorerColors[kColorZero]);
+ memEdit.DrawContents(nullptr, block.size, block.offset);
+ ImGui::PopStyleColor(2);
+ } else {
+ // No block selected
+ ImGui::TextDisabled("Select a block.");
+ }
+
+ ImGui::EndChild();
+}
+
+void Explorer::loadState(const Common::JSONObject &json) {
+ // Load colors
+ if (json.contains("Colors")) {
+ const Common::JSONObject &colors = json["Colors"]->asObject();
+ for (uint i = 0; i < _explorerColors.size(); ++i)
+ if (colors.contains(explorerColorNames[i])) {
+ const Common::JSONArray &arr = colors[explorerColorNames[i]]->asArray();
+ _explorerColors[i].x = (float)arr[0]->asNumber();
+ _explorerColors[i].y = (float)arr[1]->asNumber();
+ _explorerColors[i].z = (float)arr[2]->asNumber();
+ _explorerColors[i].w = (float)arr[3]->asNumber();
+ }
+ }
+}
+
+Common::JSONObject Explorer::saveState() const {
+ Common::JSONObject obj;
+
+ // Save colors
+ Common::JSONObject colors;
+ for (uint i = 0; i < _explorerColors.size(); ++i) {
+ Common::JSONArray arr;
+ arr.push_back(new Common::JSONValue((float)_explorerColors[i].x));
+ arr.push_back(new Common::JSONValue((float)_explorerColors[i].y));
+ arr.push_back(new Common::JSONValue((float)_explorerColors[i].z));
+ arr.push_back(new Common::JSONValue((float)_explorerColors[i].w));
+ colors[explorerColorNames[i]] = new Common::JSONValue(arr);
+ }
+ obj["Colors"] = new Common::JSONValue(colors);
+
+ return obj;
+}
+
+void Explorer::showSettings() {
+ if (ImGui::CollapsingHeader("Explorer", ImGuiTreeNodeFlags_DefaultOpen))
+ for (uint i = 0; i < _explorerColors.size(); ++i)
+ ImGui::ColorEdit4(explorerColorNames[i], &_explorerColors[i].x);
+}
+
+void Explorer::render(const char *icon, ImGuiID dockSpaceId, bool *open) {
+ ImGui::SetNextWindowDockID(dockSpaceId, ImGuiCond_FirstUseEver);
+ Common::String title = Common::String::format("%s Explorer", icon);
+ if (ImGui::Begin(title.c_str(), open))
+ if (ImGui::BeginTabBar("ExplorerTabs")) {
+ for (int i = 0; i < _resource->getFileCount(); ++i)
+ if (ImGui::BeginTabItem(_resource->getFile(i)->getPath().baseName().c_str())) {
+ ImGui::PushID(i);
+ renderTab(i);
+ ImGui::PopID();
+ ImGui::EndTabItem();
+ }
+ ImGui::EndTabBar();
+ }
+ ImGui::End();
+}
+
+} // End of namespace Editor
+
+} // End of namespace Scumm
diff --git a/engines/scumm/debugger/explorer.h b/engines/scumm/debugger/explorer.h
new file mode 100644
index 00000000000..6b04fccecec
--- /dev/null
+++ b/engines/scumm/debugger/explorer.h
@@ -0,0 +1,69 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef SCUMM_EDITOR_EXPLORER_H
+#define SCUMM_EDITOR_EXPLORER_H
+
+#include "common/array.h"
+#include "common/formats/json.h"
+
+#include "scumm/debugger/resource.h"
+
+namespace Scumm {
+
+namespace Editor {
+
+class Explorer {
+private:
+ enum {
+ kColorData,
+ kColorZero,
+ kColorCount
+ };
+
+ Resource *_resource;
+
+ Common::Array<ImVec4> &_colors;
+ Common::Array<ImVec4> _explorerColors;
+
+ Common::Array<int> _selectedBlocks;
+
+ void renderTab(int fileIndex);
+ void renderTree(const Common::Array<Block> &blocks, int &selectedBlock);
+ void renderTreeNode(const Common::Array<Block> &blocks, int blockIndex, int &selectedBlock);
+ void renderBlock(int fileIndex);
+
+public:
+ Explorer(Resource *resource, Common::Array<ImVec4> &colors);
+
+ void loadState(const Common::JSONObject &json);
+ Common::JSONObject saveState() const;
+
+ void showSettings();
+
+ void render(const char *icon, ImGuiID dockSpaceId, bool *open);
+};
+
+} // End of namespace Editor
+
+} // End of namespace Scumm
+
+#endif
diff --git a/engines/scumm/module.mk b/engines/scumm/module.mk
index 476871c5ad5..956c09c0638 100644
--- a/engines/scumm/module.mk
+++ b/engines/scumm/module.mk
@@ -100,6 +100,7 @@ ifdef USE_IMGUI
MODULE_OBJS += \
debugger/debugtools.o \
debugger/editor.o \
+ debugger/explorer.o \
debugger/file.o \
debugger/resource.o
endif
More information about the Scummvm-git-logs
mailing list