[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