This guide summarizes the architecture and implementation standards used across the editor codebase.
| Editor | State | Notes |
|---|---|---|
| Overworld | Stable | Full feature set; continue regression testing after palette fixes. |
| Message | Stable | Re-test rendering after recent palette work. |
| Emulator | Stable | UI and core subsystems aligned with production builds. |
| Palette | Stable | Serves as the source of truth for palette helpers. |
| Assembly | Stable | No outstanding refactors. |
| Dungeon | Experimental | Requires thorough manual coverage before release. |
| Graphics | Experimental | Large rendering changes in flight; validate texture pipeline. |
| Sprite | Experimental | UI patterns still migrating to the new card system. |
These patterns, established during the Overworld Editor refactoring, should be applied to all new and existing editor components.
Principle: Decompose large, monolithic editor classes into smaller, single-responsibility modules.
*Renderer classes (e.g., OverworldEntityRenderer). The main editor class should delegate drawing calls, not implement them.MapPropertiesSystem), which then communicate with the parent editor via callbacks.Benefit: Smaller, focused modules are easier to test, debug, and maintain. The main editor class becomes a coordinator, which is a much cleaner architecture.
Principle: Use std::function callbacks for child-to-parent communication to avoid circular dependencies.
SetCallbacks method) during initialization. The child component invokes these callbacks to notify the parent of events or to request actions (like a refresh).MapPropertiesSystem receives a RefreshCallback from OverworldEditor. When a property is changed in the UI, it calls the function, allowing the OverworldEditor to execute the refresh logic without the MapPropertiesSystem needing to know anything about the editor itself.Principle: All expensive asset loading operations must be performed asynchronously to prevent UI freezes. The gfx::Arena singleton provides a centralized, priority-based system for this.
gfx::Arena::Get().QueueDeferredTexture(bitmap, priority);Update() loop of an editor, process a small batch of textures each frame: auto batch = gfx::Arena::Get().GetNextDeferredTextureBatch(4, 2); (e.g., 4 high-priority, 2 low-priority).To ensure a consistent and polished look and feel, all new UI components must adhere to the established theme and helper function system.
ImVec4)**. All UI colors must be derived from the central theme.AgentUITheme system (src/app/editor/agent/agent_ui_theme.h) provides a struct of semantic color names (e.g., panel_bg_color, status_success, provider_ollama). These colors are automatically derived from the application's current ThemeManager.**Usage: Fetch the theme at the beginning of a draw call and use the semantic colors:
cpp const auto& theme = AgentUI::GetTheme(); ImGui::PushStyleColor(ImGuiCol_ChildBg, theme.panel_bg_color);
AgentUI and gui namespaces):AgentUI::PushPanelStyle() / PopPanelStyle()AgentUI::RenderSectionHeader(icon, label, color)AgentUI::RenderStatusIndicator() (status dot), AgentUI::StatusBadge() (colored text badge).AgentUI::StyledButton(), AgentUI::IconButton().AgentUI::VerticalSpacing(), AgentUI::HorizontalSpacing().ImGui::BeginGroup(). Instead, manage layout with ImGui::SameLine() and end the toolbar with ImGui::NewLine().ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical) for vertical separators that do not affect item layout.toolbar.AddProperty() method for consistent spacing and sizing of input fields within the toolbar.Renderer::Get().RenderBitmap() for an immediate, blocking update. UpdateBitmap() is deferred and should not be used for changes the user expects to see instantly.Load*() method (e.g., map.LoadAreaGraphics()) to load the new data from the ROM into memory.Small to Large), you must use the zelda3::Overworld::ConfigureMultiAreaMap() method. Do not set the area_size property directly.asm_version byte before rendering a UI component. If the feature is not supported, display a helpful message (e.g., "This feature requires ZSCustomOverworld v3+") instead of the UI.0.85f to ensure they are clearly visible against any background.The repository ships curated .clangd and .clang-tidy files that mirror our Google-style C++23 guidelines while accommodating ROM hacking patterns.
.clangd consumes build/compile_commands.json, enumerates src/, incl/, third_party/, generated directories, and sets feature flags such as YAZE_WITH_GRPC, YAZE_WITH_JSON, and Z3ED_AI so IntelliSense matches the active preset..clang-tidy enables the clang-analyzer, performance, bugprone, readability, modernize, google, and abseil suites, but relaxes common ROM hacking pain points (magic numbers, explicit integer sizing, C arrays, carefully scoped narrowing conversions).gfx::SnesColor utilities intentionally return ImVec4 values in 0‑255 space; rely on the helper converters instead of manual scaling to avoid precision loss.cmake --preset mac-dbg (or the platform equivalent) and ensure the file lives at build/compile_commands.json.clang-tidy path/to/file.cc -p build --quiet or a batch run via presets before sending larger patches.To accelerate your debugging workflow, use command-line flags to jump directly to specific editors and open relevant UI cards:
Available Editors: Assembly, Dungeon, Graphics, Music, Overworld, Palette, Screen, Sprite, Message, Hex, Agent, Settings
Dungeon Editor Cards: Rooms List, Room Matrix, Entrances List, Room Graphics, Object Editor, Palette Editor, Room N (where N is room ID 0-319)
See debugging-startup-flags.md for complete documentation.
For a comprehensive overview of debugging tools and testing strategies, including how to use the logging framework, command-line test runners, and the GUI automation harness for AI agents, please refer to the Debugging and Testing Guide.
Decision: All binaries in the yaze project (yaze, z3ed, yaze_test, etc.) will standardize on the Abseil Flags library for command-line argument parsing.
--help generation, type safety, validation, and --flagfile support.The project will migrate away from the legacy yaze::util::Flag system and manual parsing in phases. All new flags should be implemented using ABSL_FLAG.
z3ed and yaze_emu_test already use Abseil flags.yaze application will be migrated from the custom util::Flag system to Abseil flags.yaze_test runner's manual argument parsing will be replaced with Abseil flags.util::flag source files will be removed from the project.Developers should refer to the Abseil Flags Guide for documentation on defining, declaring, and accessing flags.
When working with bitmaps and textures, understand that two memory locations must stay synchronized:
data_ vector**: C++ std::vector<uint8_t> holding pixel datasurface_->pixels**: SDL surface's raw pixel buffer (used for texture creation)Critical Rules:
set_data() for bulk data replacement (syncs both vector and surface)WriteToPixel() for single-pixel modificationsmutable_data() for replacements (only updates vector, not surface)ProcessTextureQueue() every frame to process pending texture operationsExample:
Graphics sheets (223 total) are managed centrally by gfx::Arena. When modifying a sheet:
auto& sheet = Arena::Get().mutable_gfx_sheet(index);Arena::Get().NotifySheetModified(index);Default palettes are applied during ROM loading based on sheet index: