feat: Introduce Debugging and Testing Guide with enhanced startup options

- Added a new document, E5-debugging-guide.md, providing comprehensive strategies for debugging and testing the `yaze` application, including logging practices and testing frameworks.
- Updated E2-development-guide.md to include a new section on debugging and testing, detailing quick debugging methods using command-line flags for specific editors and UI cards.
- Enhanced the main application to support command-line flags for opening specific editors and cards on startup, improving the developer experience.
- Refactored the Controller class to handle startup editor and card initialization based on command-line inputs.
This commit is contained in:
scawful
2025-10-09 17:19:36 -04:00
parent b3c6fd6e12
commit e769cea1d9
32 changed files with 1044 additions and 413 deletions

View File

@@ -9,6 +9,7 @@
#include "app/zelda3/dungeon/room.h"
#include "app/zelda3/sprite/sprite.h"
#include "imgui/imgui.h"
#include "util/log.h"
namespace yaze::editor {
@@ -337,30 +338,30 @@ void DungeonCanvasViewer::CalculateWallDimensions(const zelda3::RoomObject& obje
// Room graphics management methods
absl::Status DungeonCanvasViewer::LoadAndRenderRoomGraphics(int room_id) {
printf("[LoadAndRender] START room_id=%d\n", room_id);
LOG_DEBUG("[LoadAndRender]", "START room_id=%d", room_id);
if (room_id < 0 || room_id >= 128) {
printf("[LoadAndRender] ERROR: Invalid room ID\n");
LOG_DEBUG("[LoadAndRender]", "ERROR: Invalid room ID");
return absl::InvalidArgumentError("Invalid room ID");
}
if (!rom_ || !rom_->is_loaded()) {
printf("[LoadAndRender] ERROR: ROM not loaded\n");
LOG_DEBUG("[LoadAndRender]", "ERROR: ROM not loaded");
return absl::FailedPreconditionError("ROM not loaded");
}
if (!rooms_) {
printf("[LoadAndRender] ERROR: Room data not available\n");
LOG_DEBUG("[LoadAndRender]", "ERROR: Room data not available");
return absl::FailedPreconditionError("Room data not available");
}
auto& room = (*rooms_)[room_id];
printf("[LoadAndRender] Got room reference\n");
LOG_DEBUG("[LoadAndRender]", "Got room reference");
// Load room graphics with proper blockset
printf("[LoadAndRender] Loading graphics for blockset %d\n", room.blockset);
LOG_DEBUG("[LoadAndRender]", "Loading graphics for blockset %d", room.blockset);
room.LoadRoomGraphics(room.blockset);
printf("[LoadAndRender] Graphics loaded\n");
LOG_DEBUG("[LoadAndRender]", "Graphics loaded");
// Load the room's palette with bounds checking
if (room.palette < rom_->paletteset_ids.size() &&
@@ -373,22 +374,22 @@ absl::Status DungeonCanvasViewer::LoadAndRenderRoomGraphics(int room_id) {
auto full_palette = rom_->palette_group().dungeon_main[current_palette_group_id_];
ASSIGN_OR_RETURN(current_palette_group_,
gfx::CreatePaletteGroupFromLargePalette(full_palette));
printf("[LoadAndRender] Palette loaded: group_id=%zu\n", current_palette_group_id_);
LOG_DEBUG("[LoadAndRender]", "Palette loaded: group_id=%zu", current_palette_group_id_);
}
}
}
// Render the room graphics to the graphics arena
printf("[LoadAndRender] Calling room.RenderRoomGraphics()...\n");
LOG_DEBUG("[LoadAndRender]", "Calling room.RenderRoomGraphics()...");
room.RenderRoomGraphics();
printf("[LoadAndRender] RenderRoomGraphics() complete\n");
LOG_DEBUG("[LoadAndRender]", "RenderRoomGraphics() complete");
// Update the background layers with proper palette
printf("[LoadAndRender] Updating background layers...\n");
LOG_DEBUG("[LoadAndRender]", "Updating background layers...");
RETURN_IF_ERROR(UpdateRoomBackgroundLayers(room_id));
printf("[LoadAndRender] UpdateRoomBackgroundLayers() complete\n");
LOG_DEBUG("[LoadAndRender]", "UpdateRoomBackgroundLayers() complete");
printf("[LoadAndRender] SUCCESS\n");
LOG_DEBUG("[LoadAndRender]", "SUCCESS");
return absl::OkStatus();
}
@@ -475,10 +476,10 @@ void DungeonCanvasViewer::RenderRoomBackgroundLayers(int room_id) {
// Only draw if texture was successfully created
if (bg1_bitmap.texture()) {
printf("[RenderRoomBackgroundLayers] Drawing BG1 bitmap to canvas with texture %p\n", bg1_bitmap.texture());
LOG_DEBUG("DungeonCanvasViewer", "Drawing BG1 bitmap to canvas with texture %p", bg1_bitmap.texture());
canvas_.DrawBitmap(bg1_bitmap, 0, 0, 1.0f, 255);
} else {
printf("[RenderRoomBackgroundLayers] ERROR: BG1 bitmap has no texture!\n");
LOG_DEBUG("DungeonCanvasViewer", "ERROR: BG1 bitmap has no texture!");
}
}
@@ -498,16 +499,16 @@ void DungeonCanvasViewer::RenderRoomBackgroundLayers(int room_id) {
// Use the selected BG2 layer type alpha value
const int bg2_alpha_values[] = {255, 191, 127, 64, 0};
int alpha_value = bg2_alpha_values[std::min(bg2_layer_type_, 4)];
printf("[RenderRoomBackgroundLayers] Drawing BG2 bitmap to canvas with texture %p, alpha=%d\n", bg2_bitmap.texture(), alpha_value);
LOG_DEBUG("DungeonCanvasViewer", "Drawing BG2 bitmap to canvas with texture %p, alpha=%d", bg2_bitmap.texture(), alpha_value);
canvas_.DrawBitmap(bg2_bitmap, 0, 0, 1.0f, alpha_value);
} else {
printf("[RenderRoomBackgroundLayers] ERROR: BG2 bitmap has no texture!\n");
LOG_DEBUG("DungeonCanvasViewer", "ERROR: BG2 bitmap has no texture!");
}
}
// DEBUG: Check if background buffers have content
if (bg1_bitmap.is_active() && bg1_bitmap.width() > 0) {
printf("[RenderRoomBackgroundLayers] BG1 bitmap: %dx%d, active=%d, visible=%d, texture=%p\n",
LOG_DEBUG("DungeonCanvasViewer", "BG1 bitmap: %dx%d, active=%d, visible=%d, texture=%p",
bg1_bitmap.width(), bg1_bitmap.height(), bg1_bitmap.is_active(), bg1_visible_, bg1_bitmap.texture());
// Check bitmap data content
@@ -516,11 +517,11 @@ void DungeonCanvasViewer::RenderRoomBackgroundLayers(int room_id) {
for (size_t i = 0; i < bg1_data.size(); i += 100) { // Sample every 100th pixel
if (bg1_data[i] != 0) non_zero_pixels++;
}
printf("[RenderRoomBackgroundLayers] BG1 bitmap data: %zu pixels, ~%d non-zero samples\n",
LOG_DEBUG("DungeonCanvasViewer", "BG1 bitmap data: %zu pixels, ~%d non-zero samples",
bg1_data.size(), non_zero_pixels);
}
if (bg2_bitmap.is_active() && bg2_bitmap.width() > 0) {
printf("[RenderRoomBackgroundLayers] BG2 bitmap: %dx%d, active=%d, visible=%d, layer_type=%d, texture=%p\n",
LOG_DEBUG("DungeonCanvasViewer", "BG2 bitmap: %dx%d, active=%d, visible=%d, layer_type=%d, texture=%p",
bg2_bitmap.width(), bg2_bitmap.height(), bg2_bitmap.is_active(), bg2_visible_, bg2_layer_type_, bg2_bitmap.texture());
// Check bitmap data content
@@ -529,7 +530,7 @@ void DungeonCanvasViewer::RenderRoomBackgroundLayers(int room_id) {
for (size_t i = 0; i < bg2_data.size(); i += 100) { // Sample every 100th pixel
if (bg2_data[i] != 0) non_zero_pixels++;
}
printf("[RenderRoomBackgroundLayers] BG2 bitmap data: %zu pixels, ~%d non-zero samples\n",
LOG_DEBUG("DungeonCanvasViewer", "BG2 bitmap data: %zu pixels, ~%d non-zero samples",
bg2_data.size(), non_zero_pixels);
}
@@ -542,9 +543,9 @@ void DungeonCanvasViewer::RenderRoomBackgroundLayers(int room_id) {
IM_COL32(255, 0, 0, 255)); // Bright red
// DEBUG: Show canvas and bitmap info
printf("[RenderRoomBackgroundLayers] Canvas pos: (%.1f, %.1f), Canvas size: (%.1f, %.1f)\n",
LOG_DEBUG("DungeonCanvasViewer", "Canvas pos: (%.1f, %.1f), Canvas size: (%.1f, %.1f)",
canvas_pos.x, canvas_pos.y, canvas_.canvas_size().x, canvas_.canvas_size().y);
printf("[RenderRoomBackgroundLayers] BG1 bitmap size: %dx%d, BG2 bitmap size: %dx%d\n",
LOG_DEBUG("DungeonCanvasViewer", "BG1 bitmap size: %dx%d, BG2 bitmap size: %dx%d",
bg1_bitmap.width(), bg1_bitmap.height(), bg2_bitmap.width(), bg2_bitmap.height());
}

View File

@@ -70,9 +70,6 @@ void DungeonEditor::Initialize() {
config.grid_size = 16; // 16x16 tiles
object_editor_->SetConfig(config);
}
// Initialize manual renderer for debugging
printf("[DungeonEditor] Manual renderer initialized\n");
}
absl::Status DungeonEditor::Load() {

View File

@@ -10,6 +10,7 @@
#include "app/gui/icons.h"
#include "app/gui/input.h"
#include "imgui/imgui.h"
#include "util/log.h"
namespace yaze::editor {
@@ -97,8 +98,6 @@ void DungeonEditorV2::Initialize(gfx::IRenderer* renderer, Rom* rom) {
.visibility_flag = &show_palette_editor_,
.priority = 70
});
printf("[DungeonEditorV2] Registered 7 cards with EditorCardManager\n");
}
void DungeonEditorV2::Initialize() {}
@@ -214,7 +213,7 @@ absl::Status DungeonEditorV2::Save() {
auto status = room.SaveObjects();
if (!status.ok()) {
// Log error but continue with other rooms
std::printf("Failed to save room: %s\n", status.message().data());
LOG_ERROR("DungeonEditorV2", "Failed to save room: %s", status.message().data());
}
}

View File

@@ -87,6 +87,15 @@ class DungeonEditorV2 : public Editor {
return absl::StrFormat("ROM loaded: %s", rom_->title());
}
// Card visibility flags - Public for command-line flag access
bool show_room_selector_ = false; // Room selector/list card
bool show_room_matrix_ = false; // Dungeon matrix layout
bool show_entrances_list_ = false; // Entrance list card (renamed from entrances_matrix_)
bool show_room_graphics_ = false; // Room graphics card
bool show_object_editor_ = false; // Object editor card
bool show_palette_editor_ = false; // Palette editor card
bool show_control_panel_ = true; // Control panel (visible by default)
private:
gfx::IRenderer* renderer_ = nullptr;
// Simple UI layout
@@ -119,16 +128,6 @@ class DungeonEditorV2 : public Editor {
std::unordered_map<int, std::shared_ptr<gui::EditorCard>> room_cards_;
int current_room_id_ = 0;
// Card visibility flags - Start with only control panel visible
// Other cards hidden by default to prevent crash on ROM load
// User can open them via View menu or shortcuts
bool show_room_selector_ = false;
bool show_room_matrix_ = false;
bool show_entrances_list_ = false;
bool show_room_graphics_ = false;
bool show_object_editor_ = false;
bool show_palette_editor_ = false;
bool show_control_panel_ = true; // Only control panel visible on start
bool control_panel_minimized_ = false;
// Palette management