refactor: Remove unused room diagnostic files and update CMake configuration
- Deleted the room_diagnostic.cc and room_visual_diagnostic.cc files, along with their corresponding header files, to clean up the codebase. - Updated zelda3_library.cmake to remove references to the deleted diagnostic files, streamlining the build process. - Removed the inclusion of room_diagnostic.h in room.cc as it is no longer needed.
This commit is contained in:
@@ -11,7 +11,6 @@
|
||||
#include "app/rom.h"
|
||||
#include "app/snes.h"
|
||||
#include "app/zelda3/dungeon/object_drawer.h"
|
||||
#include "app/zelda3/dungeon/room_diagnostic.h"
|
||||
#include "app/zelda3/dungeon/room_object.h"
|
||||
#include "app/zelda3/sprite/sprite.h"
|
||||
#include "util/log.h"
|
||||
|
||||
@@ -1,193 +0,0 @@
|
||||
#include "room.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <vector>
|
||||
|
||||
#include "app/gfx/arena.h"
|
||||
#include "app/gfx/bitmap.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace zelda3 {
|
||||
|
||||
void DiagnoseRoomRendering(Room& room, int room_id) {
|
||||
std::printf("\n========== ROOM RENDERING DIAGNOSTIC ==========\n");
|
||||
std::printf("Room ID: %d\n\n", room_id);
|
||||
|
||||
// Step 1: Check ROM and graphics buffer
|
||||
std::printf("=== Step 1: ROM and Graphics Buffer ===\n");
|
||||
auto* rom = room.rom();
|
||||
if (!rom) {
|
||||
std::printf("❌ ROM pointer is NULL\n");
|
||||
return;
|
||||
}
|
||||
std::printf("✓ ROM pointer valid\n");
|
||||
std::printf(" ROM loaded: %s\n", rom->is_loaded() ? "YES" : "NO");
|
||||
std::printf(" ROM size: %zu bytes\n", rom->size());
|
||||
|
||||
auto* gfx_buffer = rom->mutable_graphics_buffer();
|
||||
if (!gfx_buffer || gfx_buffer->empty()) {
|
||||
std::printf("❌ Graphics buffer empty\n");
|
||||
return;
|
||||
}
|
||||
std::printf("✓ Graphics buffer loaded: %zu bytes\n", gfx_buffer->size());
|
||||
|
||||
// Step 2: Check room blocks
|
||||
std::printf("\n=== Step 2: Room Graphics Blocks ===\n");
|
||||
auto blocks = room.blocks();
|
||||
std::printf(" Blocks loaded: %s\n", blocks.empty() ? "NO" : "YES");
|
||||
if (!blocks.empty()) {
|
||||
std::printf(" Block indices: ");
|
||||
for (int i = 0; i < 16; i++) {
|
||||
std::printf("%d ", blocks[i]);
|
||||
if (i == 7) std::printf("\n ");
|
||||
}
|
||||
std::printf("\n");
|
||||
}
|
||||
|
||||
// Step 3: Check current_gfx16_ buffer
|
||||
std::printf("\n=== Step 3: current_gfx16_ Buffer ===\n");
|
||||
// Sample first 100 bytes to check if populated
|
||||
bool has_data = false;
|
||||
int non_zero_count = 0;
|
||||
for (int i = 0; i < 100 && i < 32768; i++) {
|
||||
// Access through room's internal buffer would require making it accessible
|
||||
// For now, just note this step
|
||||
}
|
||||
std::printf(" Note: current_gfx16_ is internal, assuming populated after CopyRoomGraphicsToBuffer()\n");
|
||||
|
||||
// Step 4: Check THIS ROOM's background buffers (not arena!)
|
||||
std::printf("\n=== Step 4: Room Background Buffers ===\n");
|
||||
auto& bg1 = room.bg1_buffer();
|
||||
auto& bg2 = room.bg2_buffer();
|
||||
auto bg1_buffer = bg1.buffer();
|
||||
auto bg2_buffer = bg2.buffer();
|
||||
|
||||
std::printf("BG1 Buffer:\n");
|
||||
std::printf(" Size: %zu\n", bg1_buffer.size());
|
||||
int bg1_non_ff = 0;
|
||||
int bg1_non_zero = 0;
|
||||
for (const auto& word : bg1_buffer) {
|
||||
if (word != 0xFFFF) bg1_non_ff++;
|
||||
if (word != 0) bg1_non_zero++;
|
||||
}
|
||||
std::printf(" Non-0xFFFF tiles: %d / %zu\n", bg1_non_ff, bg1_buffer.size());
|
||||
std::printf(" Non-zero tiles: %d / %zu\n", bg1_non_zero, bg1_buffer.size());
|
||||
|
||||
// Sample first 10 non-0xFFFF tiles
|
||||
std::printf(" Sample tiles (first 10 non-0xFFFF): ");
|
||||
int sample_count = 0;
|
||||
for (size_t i = 0; i < bg1_buffer.size() && sample_count < 10; i++) {
|
||||
if (bg1_buffer[i] != 0xFFFF) {
|
||||
std::printf("0x%04X ", bg1_buffer[i]);
|
||||
sample_count++;
|
||||
}
|
||||
}
|
||||
std::printf("\n");
|
||||
|
||||
std::printf("\nBG2 Buffer:\n");
|
||||
std::printf(" Size: %zu\n", bg2_buffer.size());
|
||||
int bg2_non_ff = 0;
|
||||
int bg2_non_zero = 0;
|
||||
for (const auto& word : bg2_buffer) {
|
||||
if (word != 0xFFFF) bg2_non_ff++;
|
||||
if (word != 0) bg2_non_zero++;
|
||||
}
|
||||
std::printf(" Non-0xFFFF tiles: %d / %zu\n", bg2_non_ff, bg2_buffer.size());
|
||||
std::printf(" Non-zero tiles: %d / %zu\n", bg2_non_zero, bg2_buffer.size());
|
||||
|
||||
// Step 5: Check bitmaps
|
||||
std::printf("\n=== Step 5: Bitmaps ===\n");
|
||||
auto& bg1_bitmap = bg1.bitmap();
|
||||
auto& bg2_bitmap = bg2.bitmap();
|
||||
|
||||
std::printf("BG1 Bitmap:\n");
|
||||
std::printf(" Active: %s\n", bg1_bitmap.is_active() ? "YES" : "NO");
|
||||
std::printf(" Dimensions: %dx%d\n", bg1_bitmap.width(), bg1_bitmap.height());
|
||||
std::printf(" Data size: %zu bytes\n", bg1_bitmap.vector().size());
|
||||
std::printf(" Modified: %s\n", bg1_bitmap.modified() ? "YES" : "NO");
|
||||
|
||||
if (!bg1_bitmap.vector().empty()) {
|
||||
// Sample first 100 pixels
|
||||
int non_zero_pixels = 0;
|
||||
std::vector<uint8_t> unique_colors;
|
||||
for (size_t i = 0; i < 100 && i < bg1_bitmap.vector().size(); i++) {
|
||||
uint8_t pixel = bg1_bitmap.vector()[i];
|
||||
if (pixel != 0) non_zero_pixels++;
|
||||
if (std::find(unique_colors.begin(), unique_colors.end(), pixel) == unique_colors.end()) {
|
||||
unique_colors.push_back(pixel);
|
||||
}
|
||||
}
|
||||
std::printf(" First 100 pixels: %d non-zero, %zu unique colors\n",
|
||||
non_zero_pixels, unique_colors.size());
|
||||
std::printf(" Unique colors: ");
|
||||
for (size_t i = 0; i < std::min<size_t>(10, unique_colors.size()); i++) {
|
||||
std::printf("%d ", unique_colors[i]);
|
||||
}
|
||||
std::printf("\n");
|
||||
}
|
||||
|
||||
std::printf("\nBG2 Bitmap:\n");
|
||||
std::printf(" Active: %s\n", bg2_bitmap.is_active() ? "YES" : "NO");
|
||||
std::printf(" Dimensions: %dx%d\n", bg2_bitmap.width(), bg2_bitmap.height());
|
||||
std::printf(" Data size: %zu bytes\n", bg2_bitmap.vector().size());
|
||||
|
||||
// Step 6: Check textures
|
||||
std::printf("\n=== Step 6: SDL Textures ===\n");
|
||||
std::printf("BG1 Texture:\n");
|
||||
std::printf(" Texture pointer: %p\n", (void*)bg1_bitmap.texture());
|
||||
std::printf(" Texture valid: %s\n", bg1_bitmap.texture() != nullptr ? "YES" : "NO");
|
||||
|
||||
std::printf("\nBG2 Texture:\n");
|
||||
std::printf(" Texture pointer: %p\n", (void*)bg2_bitmap.texture());
|
||||
std::printf(" Texture valid: %s\n", bg2_bitmap.texture() != nullptr ? "YES" : "NO");
|
||||
|
||||
// Step 7: Check palette
|
||||
std::printf("\n=== Step 7: Palette ===\n");
|
||||
auto& palette = bg1_bitmap.palette();
|
||||
std::printf(" Palette size: %zu colors\n", palette.size());
|
||||
if (!palette.empty()) {
|
||||
std::printf(" First 8 colors (SNES format): ");
|
||||
for (size_t i = 0; i < 8 && i < palette.size(); i++) {
|
||||
std::printf("0x%04X ", palette[i].snes());
|
||||
}
|
||||
std::printf("\n");
|
||||
|
||||
// Check the actual colors being used by the bitmap pixels
|
||||
std::printf(" Colors at pixel indices being used:\n");
|
||||
std::vector<uint8_t> sample_indices;
|
||||
for (size_t i = 0; i < 100 && i < bg1_bitmap.vector().size(); i++) {
|
||||
uint8_t idx = bg1_bitmap.vector()[i];
|
||||
if (std::find(sample_indices.begin(), sample_indices.end(), idx) == sample_indices.end()) {
|
||||
sample_indices.push_back(idx);
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i < std::min<size_t>(10, sample_indices.size()); i++) {
|
||||
uint8_t idx = sample_indices[i];
|
||||
if (idx < palette.size()) {
|
||||
auto color = palette[idx];
|
||||
auto rgb_vec = color.rgb();
|
||||
std::printf(" [%d] = SNES:0x%04X RGB:(%.0f,%.0f,%.0f)\n",
|
||||
idx, color.snes(), rgb_vec.x * 255, rgb_vec.y * 255, rgb_vec.z * 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 8: Check room objects
|
||||
std::printf("\n=== Step 8: Room Objects ===\n");
|
||||
const auto& objects = room.GetTileObjects();
|
||||
std::printf(" Object count: %zu\n", objects.size());
|
||||
if (!objects.empty()) {
|
||||
std::printf(" First 5 objects:\n");
|
||||
for (size_t i = 0; i < 5 && i < objects.size(); i++) {
|
||||
const auto& obj = objects[i];
|
||||
std::printf(" [%zu] ID=0x%03X, Pos=(%d,%d), Size=%d, Layer=%d\n",
|
||||
i, obj.id_, obj.x_, obj.y_, obj.size_, obj.GetLayerValue());
|
||||
}
|
||||
}
|
||||
|
||||
std::printf("\n========== DIAGNOSTIC COMPLETE ==========\n\n");
|
||||
}
|
||||
|
||||
} // namespace zelda3
|
||||
} // namespace yaze
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
#ifndef YAZE_APP_ZELDA3_DUNGEON_ROOM_DIAGNOSTIC_H
|
||||
#define YAZE_APP_ZELDA3_DUNGEON_ROOM_DIAGNOSTIC_H
|
||||
|
||||
namespace yaze {
|
||||
namespace zelda3 {
|
||||
|
||||
class Room;
|
||||
|
||||
// Comprehensive diagnostic function to trace room rendering pipeline
|
||||
void DiagnoseRoomRendering(Room& room, int room_id);
|
||||
|
||||
} // namespace zelda3
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_ZELDA3_DUNGEON_ROOM_DIAGNOSTIC_H
|
||||
|
||||
@@ -1,330 +0,0 @@
|
||||
#include "app/zelda3/dungeon/room_visual_diagnostic.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "app/gfx/snes_tile.h"
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace zelda3 {
|
||||
namespace dungeon {
|
||||
|
||||
void RoomVisualDiagnostic::DrawDiagnosticWindow(
|
||||
bool* p_open,
|
||||
gfx::BackgroundBuffer& bg1_buffer,
|
||||
gfx::BackgroundBuffer& bg2_buffer,
|
||||
const gfx::SnesPalette& palette,
|
||||
const std::vector<uint8_t>& gfx16_data) {
|
||||
|
||||
if (!ImGui::Begin("Room Rendering Diagnostic", p_open, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
if (ImGui::CollapsingHeader("Texture Previews", ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||
DrawTexturePreview(bg1_buffer.bitmap(), "BG1 Texture");
|
||||
ImGui::Separator();
|
||||
DrawTexturePreview(bg2_buffer.bitmap(), "BG2 Texture");
|
||||
}
|
||||
|
||||
if (ImGui::CollapsingHeader("Palette Inspector")) {
|
||||
DrawPaletteInspector(palette);
|
||||
}
|
||||
|
||||
if (ImGui::CollapsingHeader("Tile Buffer Inspector")) {
|
||||
if (ImGui::BeginTabBar("BufferTabs")) {
|
||||
if (ImGui::BeginTabItem("BG1 Buffer")) {
|
||||
DrawTileBufferInspector(bg1_buffer, palette);
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (ImGui::BeginTabItem("BG2 Buffer")) {
|
||||
DrawTileBufferInspector(bg2_buffer, palette);
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::CollapsingHeader("Pixel Inspector")) {
|
||||
if (ImGui::BeginTabBar("PixelTabs")) {
|
||||
if (ImGui::BeginTabItem("BG1 Pixels")) {
|
||||
DrawPixelInspector(bg1_buffer.bitmap(), palette);
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (ImGui::BeginTabItem("BG2 Pixels")) {
|
||||
DrawPixelInspector(bg2_buffer.bitmap(), palette);
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::CollapsingHeader("Tile Decoder")) {
|
||||
static int test_tile_id = 0xEE;
|
||||
ImGui::InputInt("Tile ID (hex)", &test_tile_id, 1, 16, ImGuiInputTextFlags_CharsHexadecimal);
|
||||
test_tile_id = std::clamp(test_tile_id, 0, 0x1FF);
|
||||
DrawTileDecoder(gfx16_data, test_tile_id);
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void RoomVisualDiagnostic::DrawTexturePreview(const gfx::Bitmap& bitmap, const char* label) {
|
||||
ImGui::Text("%s", label);
|
||||
|
||||
if (!bitmap.is_active()) {
|
||||
ImGui::TextColored(ImVec4(1, 0, 0, 1), "Bitmap not active");
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui::Text("Size: %dx%d, Data: %zu bytes",
|
||||
bitmap.width(), bitmap.height(), bitmap.vector().size());
|
||||
|
||||
// Show texture if available
|
||||
if (bitmap.texture()) {
|
||||
ImVec2 preview_size(256, 256); // Quarter size preview
|
||||
ImGui::Image(bitmap.texture(), preview_size);
|
||||
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::BeginTooltip();
|
||||
// Zoomed preview on hover
|
||||
ImVec2 zoom_size(512, 512);
|
||||
ImGui::Image(bitmap.texture(), zoom_size);
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
} else {
|
||||
ImGui::TextColored(ImVec4(1, 1, 0, 1), "No texture available");
|
||||
}
|
||||
}
|
||||
|
||||
void RoomVisualDiagnostic::DrawPaletteInspector(const gfx::SnesPalette& palette) {
|
||||
ImGui::Text("Palette size: %zu colors", palette.size());
|
||||
|
||||
int cols = 16;
|
||||
for (size_t i = 0; i < palette.size(); i++) {
|
||||
if (i % cols != 0) ImGui::SameLine();
|
||||
|
||||
auto color = palette[i];
|
||||
auto rgb = color.rgb();
|
||||
ImVec4 imcolor(rgb.x, rgb.y, rgb.z, 1.0f);
|
||||
|
||||
ImGui::PushID(static_cast<int>(i));
|
||||
if (ImGui::ColorButton("##color", imcolor,
|
||||
ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoPicker,
|
||||
ImVec2(20, 20))) {
|
||||
// Clicked - could add inspection
|
||||
}
|
||||
ImGui::PopID();
|
||||
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("[%zu] SNES:0x%04X RGB:(%.0f,%.0f,%.0f)",
|
||||
i, color.snes(),
|
||||
rgb.x * 255, rgb.y * 255, rgb.z * 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RoomVisualDiagnostic::DrawTileBufferInspector(gfx::BackgroundBuffer& buffer,
|
||||
const gfx::SnesPalette& palette) {
|
||||
const auto& tile_buffer = buffer.buffer();
|
||||
const auto& bitmap = buffer.bitmap();
|
||||
int tiles_w = bitmap.width() / 8;
|
||||
int tiles_h = bitmap.height() / 8;
|
||||
|
||||
ImGui::Text("Buffer size: %zu tiles (%d x %d)", tile_buffer.size(), tiles_w, tiles_h);
|
||||
|
||||
// Count non-empty tiles
|
||||
int non_empty = 0;
|
||||
std::set<uint16_t> unique_tiles;
|
||||
for (auto word : tile_buffer) {
|
||||
if (word != 0xFFFF && word != 0) {
|
||||
non_empty++;
|
||||
unique_tiles.insert(word);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Text("Non-empty tiles: %d / %zu", non_empty, tile_buffer.size());
|
||||
ImGui::Text("Unique tile words: %zu", unique_tiles.size());
|
||||
|
||||
// Sample tiles
|
||||
ImGui::Separator();
|
||||
ImGui::Text("First 20 tiles:");
|
||||
|
||||
static int selected_tile = -1;
|
||||
for (int i = 0; i < std::min<int>(20, tile_buffer.size()); i++) {
|
||||
uint16_t word = tile_buffer[i];
|
||||
auto tile = gfx::WordToTileInfo(word);
|
||||
|
||||
bool is_selected = (selected_tile == i);
|
||||
if (ImGui::Selectable(absl::StrFormat("[%d] Word:0x%04X ID:%d Pal:%d H:%d V:%d P:%d",
|
||||
i, word, tile.id_, tile.palette_,
|
||||
tile.horizontal_mirror_, tile.vertical_mirror_,
|
||||
tile.over_).c_str(),
|
||||
is_selected)) {
|
||||
selected_tile = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (selected_tile >= 0 && selected_tile < tile_buffer.size()) {
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Selected Tile %d:", selected_tile);
|
||||
uint16_t word = tile_buffer[selected_tile];
|
||||
auto tile = gfx::WordToTileInfo(word);
|
||||
|
||||
ImGui::BulletText("Word: 0x%04X", word);
|
||||
ImGui::BulletText("Tile ID: 0x%03X (%d)", tile.id_, tile.id_);
|
||||
ImGui::BulletText("Palette: %d", tile.palette_);
|
||||
ImGui::BulletText("H-Mirror: %d, V-Mirror: %d",
|
||||
tile.horizontal_mirror_, tile.vertical_mirror_);
|
||||
ImGui::BulletText("Priority: %d", tile.over_);
|
||||
|
||||
// Calculate palette color range for this tile
|
||||
int pal_start = tile.palette_ * 16;
|
||||
int pal_end = pal_start + 15;
|
||||
ImGui::BulletText("Palette range: colors %d-%d", pal_start, pal_end);
|
||||
|
||||
if (pal_end >= palette.size()) {
|
||||
ImGui::TextColored(ImVec4(1, 0, 0, 1),
|
||||
"WARNING: Palette range exceeds palette size (%zu)!",
|
||||
palette.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RoomVisualDiagnostic::DrawPixelInspector(const gfx::Bitmap& bitmap,
|
||||
const gfx::SnesPalette& palette) {
|
||||
if (!bitmap.is_active() || bitmap.vector().empty()) {
|
||||
ImGui::TextColored(ImVec4(1, 0, 0, 1), "Bitmap not active or empty");
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& pixels = bitmap.vector();
|
||||
|
||||
// Analyze pixels
|
||||
std::map<uint8_t, int> color_histogram;
|
||||
for (size_t i = 0; i < std::min<size_t>(1000, pixels.size()); i++) {
|
||||
color_histogram[pixels[i]]++;
|
||||
}
|
||||
|
||||
ImGui::Text("Pixel analysis (first 1000 pixels):");
|
||||
ImGui::Text("Unique colors: %zu", color_histogram.size());
|
||||
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Color distribution:");
|
||||
|
||||
// Show top 10 most common colors
|
||||
std::vector<std::pair<uint8_t, int>> sorted_colors(color_histogram.begin(), color_histogram.end());
|
||||
std::sort(sorted_colors.begin(), sorted_colors.end(),
|
||||
[](const auto& a, const auto& b) { return a.second > b.second; });
|
||||
|
||||
for (size_t i = 0; i < std::min<size_t>(10, sorted_colors.size()); i++) {
|
||||
uint8_t idx = sorted_colors[i].first;
|
||||
int count = sorted_colors[i].second;
|
||||
|
||||
ImGui::Text("[%3d] Count: %4d (%.1f%%)", idx, count, (count * 100.0f) / 1000.0f);
|
||||
|
||||
if (idx < palette.size()) {
|
||||
ImGui::SameLine();
|
||||
auto color = palette[idx];
|
||||
auto rgb = color.rgb();
|
||||
ImVec4 imcolor(rgb.x, rgb.y, rgb.z, 1.0f);
|
||||
ImGui::ColorButton("##pal", imcolor, ImGuiColorEditFlags_NoAlpha, ImVec2(16, 16));
|
||||
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("SNES:0x%04X RGB:(%.0f,%.0f,%.0f)",
|
||||
color.snes(), rgb.x * 255, rgb.y * 255, rgb.z * 255);
|
||||
}
|
||||
} else {
|
||||
ImGui::SameLine();
|
||||
ImGui::TextColored(ImVec4(1, 0, 0, 1), "OUT OF RANGE!");
|
||||
}
|
||||
}
|
||||
|
||||
// Interactive pixel inspector
|
||||
ImGui::Separator();
|
||||
static int inspect_x = 0;
|
||||
static int inspect_y = 0;
|
||||
|
||||
ImGui::Text("Pixel Inspector:");
|
||||
ImGui::SliderInt("X", &inspect_x, 0, bitmap.width() - 1);
|
||||
ImGui::SliderInt("Y", &inspect_y, 0, bitmap.height() - 1);
|
||||
|
||||
int pixel_idx = inspect_y * bitmap.width() + inspect_x;
|
||||
if (pixel_idx >= 0 && pixel_idx < pixels.size()) {
|
||||
uint8_t pal_idx = pixels[pixel_idx];
|
||||
ImGui::Text("Pixel (%d, %d) = Palette Index %d", inspect_x, inspect_y, pal_idx);
|
||||
|
||||
if (pal_idx < palette.size()) {
|
||||
auto color = palette[pal_idx];
|
||||
auto rgb = color.rgb();
|
||||
ImVec4 imcolor(rgb.x, rgb.y, rgb.z, 1.0f);
|
||||
ImGui::ColorButton("##pixel_color", imcolor, ImGuiColorEditFlags_NoAlpha, ImVec2(40, 40));
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("SNES:0x%04X RGB:(%.0f,%.0f,%.0f)",
|
||||
color.snes(), rgb.x * 255, rgb.y * 255, rgb.z * 255);
|
||||
} else {
|
||||
ImGui::TextColored(ImVec4(1, 0, 0, 1), "Palette index %d out of range (max: %zu)!",
|
||||
pal_idx, palette.size() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RoomVisualDiagnostic::DrawTileDecoder(const std::vector<uint8_t>& gfx16_data, int tile_id) {
|
||||
if (gfx16_data.empty()) {
|
||||
ImGui::TextColored(ImVec4(1, 0, 0, 1), "No graphics data");
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate tile offset in graphics data
|
||||
int tx = (tile_id / 16 * 512) + ((tile_id & 0xF) * 4);
|
||||
|
||||
ImGui::Text("Decoding tile 0x%03X", tile_id);
|
||||
ImGui::Text("Offset in gfx16_data: 0x%X (%d)", tx, tx);
|
||||
|
||||
if (tx < 0 || tx + 32 > gfx16_data.size()) {
|
||||
ImGui::TextColored(ImVec4(1, 0, 0, 1), "Tile offset out of range!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Show raw tile data
|
||||
ImGui::Text("Raw 4bpp data (32 bytes):");
|
||||
for (int i = 0; i < 32; i += 8) {
|
||||
ImGui::Text("%02X %02X %02X %02X %02X %02X %02X %02X",
|
||||
gfx16_data[tx + i], gfx16_data[tx + i + 1],
|
||||
gfx16_data[tx + i + 2], gfx16_data[tx + i + 3],
|
||||
gfx16_data[tx + i + 4], gfx16_data[tx + i + 5],
|
||||
gfx16_data[tx + i + 6], gfx16_data[tx + i + 7]);
|
||||
}
|
||||
|
||||
// Decode and visualize 8x8 tile
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Decoded 8x8 pixel values (palette 0):");
|
||||
|
||||
// Decode the tile manually to show what pixels are produced
|
||||
for (int y = 0; y < 8; y++) {
|
||||
std::string line;
|
||||
for (int x = 0; x < 8; x++) {
|
||||
int yl = (y / 8) * 64 + (y % 8) * 8;
|
||||
int xl = x / 2;
|
||||
|
||||
if (tx + yl + xl < gfx16_data.size()) {
|
||||
uint8_t pixel_byte = gfx16_data[tx + yl + xl];
|
||||
uint8_t pixel_val = (x % 2 == 0) ? (pixel_byte >> 4) : (pixel_byte & 0x0F);
|
||||
line += absl::StrFormat("%X", pixel_val);
|
||||
} else {
|
||||
line += "?";
|
||||
}
|
||||
}
|
||||
ImGui::Text("%s", line.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace dungeon
|
||||
} // namespace zelda3
|
||||
} // namespace yaze
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
#ifndef YAZE_APP_ZELDA3_DUNGEON_ROOM_VISUAL_DIAGNOSTIC_H
|
||||
#define YAZE_APP_ZELDA3_DUNGEON_ROOM_VISUAL_DIAGNOSTIC_H
|
||||
|
||||
#include "imgui/imgui.h"
|
||||
#include "app/gfx/bitmap.h"
|
||||
#include "app/gfx/snes_palette.h"
|
||||
#include "app/gfx/background_buffer.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace zelda3 {
|
||||
namespace dungeon {
|
||||
|
||||
/**
|
||||
* @brief Visual diagnostic tool for dungeon rendering using ImGui
|
||||
*
|
||||
* Provides interactive visualization of:
|
||||
* - Texture previews (BG1, BG2)
|
||||
* - Bitmap data with zoom
|
||||
* - Tile buffer contents
|
||||
* - Palette colors
|
||||
* - Pixel value inspection
|
||||
*/
|
||||
class RoomVisualDiagnostic {
|
||||
public:
|
||||
/**
|
||||
* @brief Draw the diagnostic window
|
||||
* @param bg1_buffer Background 1 buffer reference
|
||||
* @param bg2_buffer Background 2 buffer reference
|
||||
* @param palette Current palette being used
|
||||
* @param gfx16_data Graphics data buffer
|
||||
*/
|
||||
static void DrawDiagnosticWindow(
|
||||
bool* p_open,
|
||||
gfx::BackgroundBuffer& bg1_buffer,
|
||||
gfx::BackgroundBuffer& bg2_buffer,
|
||||
const gfx::SnesPalette& palette,
|
||||
const std::vector<uint8_t>& gfx16_data);
|
||||
|
||||
private:
|
||||
static void DrawTexturePreview(const gfx::Bitmap& bitmap, const char* label);
|
||||
static void DrawPaletteInspector(const gfx::SnesPalette& palette);
|
||||
static void DrawTileBufferInspector(gfx::BackgroundBuffer& buffer, const gfx::SnesPalette& palette);
|
||||
static void DrawPixelInspector(const gfx::Bitmap& bitmap, const gfx::SnesPalette& palette);
|
||||
static void DrawTileDecoder(const std::vector<uint8_t>& gfx16_data, int tile_id);
|
||||
};
|
||||
|
||||
} // namespace dungeon
|
||||
} // namespace zelda3
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_ZELDA3_DUNGEON_ROOM_VISUAL_DIAGNOSTIC_H
|
||||
|
||||
@@ -16,8 +16,6 @@ set(
|
||||
app/zelda3/dungeon/object_renderer.cc
|
||||
app/zelda3/dungeon/object_drawer.cc
|
||||
app/zelda3/dungeon/room_layout.cc
|
||||
app/zelda3/dungeon/room_diagnostic.cc
|
||||
app/zelda3/dungeon/room_visual_diagnostic.cc
|
||||
app/zelda3/dungeon/dungeon_editor_system.cc
|
||||
app/zelda3/dungeon/dungeon_object_editor.cc
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user