feat: Enhance emulator functionality with card registration and UI improvements
- Registered multiple emulator cards (CPU Debugger, Memory Viewer, PPU Viewer, Audio Mixer) with the EditorCardManager for improved access and organization. - Updated EditorManager to support the new Emulator editor type in context-sensitive card controls. - Improved GraphicsEditor loading process with enhanced logging and palette management for graphics sheets. - Refactored MessageEditor to streamline font bitmap creation and texture queuing, ensuring better performance and clarity in the rendering loop.
This commit is contained in:
@@ -952,6 +952,12 @@ void EditorManager::DrawContextSensitiveCardControl() {
|
||||
case EditorType::kAssembly:
|
||||
// Assembly editor uses dynamic file tabs
|
||||
return;
|
||||
case EditorType::kEmulator:
|
||||
category = "Emulator";
|
||||
break;
|
||||
case EditorType::kMusic:
|
||||
// Music editor doesn't use cards yet
|
||||
return;
|
||||
default:
|
||||
return; // No cards for this editor type
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "imgui/imgui.h"
|
||||
#include "imgui/misc/cpp/imgui_stdlib.h"
|
||||
#include "imgui_memory_editor.h"
|
||||
#include "util/log.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace editor {
|
||||
@@ -92,6 +93,7 @@ absl::Status GraphicsEditor::Load() {
|
||||
gfx::ScopedTimer timer("GraphicsEditor::Load");
|
||||
|
||||
// Initialize all graphics sheets with appropriate palettes from ROM
|
||||
// This ensures textures are created for editing
|
||||
if (rom()->is_loaded()) {
|
||||
auto& sheets = gfx::Arena::Get().gfx_sheets();
|
||||
|
||||
@@ -100,34 +102,56 @@ absl::Status GraphicsEditor::Load() {
|
||||
// Sheets 113-127: Use sprite palettes
|
||||
// Sheets 128-222: Use auxiliary/menu palettes
|
||||
|
||||
LOG_INFO("GraphicsEditor", "Initializing textures for %d graphics sheets", kNumGfxSheets);
|
||||
|
||||
int sheets_initialized = 0;
|
||||
for (int i = 0; i < kNumGfxSheets; i++) {
|
||||
if (sheets[i].is_active() && sheets[i].surface()) {
|
||||
// Determine which palette group to use based on sheet index
|
||||
gfx::SnesPalette sheet_palette;
|
||||
|
||||
if (i < 113) {
|
||||
// Overworld/Dungeon graphics - use main palette
|
||||
auto palette_group = rom()->palette_group().dungeon_main;
|
||||
sheet_palette = palette_group[0]; // Use first palette as default
|
||||
} else if (i < 128) {
|
||||
// Sprite graphics - use sprite palettes
|
||||
auto palette_group = rom()->palette_group().sprites_aux1;
|
||||
if (!sheets[i].is_active() || !sheets[i].surface()) {
|
||||
continue; // Skip inactive or surface-less sheets
|
||||
}
|
||||
|
||||
// Determine which palette group to use based on sheet index
|
||||
gfx::SnesPalette sheet_palette;
|
||||
|
||||
if (i < 113) {
|
||||
// Overworld/Dungeon graphics - use dungeon main palette
|
||||
auto palette_group = rom()->palette_group().dungeon_main;
|
||||
if (palette_group.size() > 0) {
|
||||
sheet_palette = palette_group[0];
|
||||
} else {
|
||||
// Auxiliary graphics - use HUD/menu palettes
|
||||
sheet_palette = rom()->palette_group().hud.palette(0);
|
||||
}
|
||||
|
||||
// Apply palette and queue texture creation
|
||||
sheets[i].SetPalette(sheet_palette);
|
||||
|
||||
// Queue texture creation if not already created
|
||||
if (!sheets[i].texture()) {
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::CREATE, &sheets[i]);
|
||||
} else if (i < 128) {
|
||||
// Sprite graphics - use sprite palettes
|
||||
auto palette_group = rom()->palette_group().sprites_aux1;
|
||||
if (palette_group.size() > 0) {
|
||||
sheet_palette = palette_group[0];
|
||||
}
|
||||
} else {
|
||||
// Auxiliary graphics - use HUD/menu palettes
|
||||
auto palette_group = rom()->palette_group().hud;
|
||||
if (palette_group.size() > 0) {
|
||||
sheet_palette = palette_group.palette(0);
|
||||
}
|
||||
}
|
||||
|
||||
// CRITICAL: Apply palette BEFORE queueing texture creation
|
||||
// The palette must be set on the surface before creating the texture
|
||||
if (!sheet_palette.empty()) {
|
||||
sheets[i].SetPalette(sheet_palette);
|
||||
sheets_initialized++;
|
||||
} else {
|
||||
LOG_WARN("GraphicsEditor", "Sheet %d: Empty palette, skipping", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Queue texture creation if not already created
|
||||
if (!sheets[i].texture()) {
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::CREATE, &sheets[i]);
|
||||
}
|
||||
}
|
||||
|
||||
LOG_INFO("GraphicsEditor", "Initialized %d sheets with palettes, queued for texture creation",
|
||||
sheets_initialized);
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
|
||||
@@ -114,12 +114,17 @@ void MessageEditor::Initialize() {
|
||||
}
|
||||
message_preview_.font_gfx16_data_ =
|
||||
gfx::SnesTo8bppSheet(raw_font_gfx_data_, /*bpp=*/2, /*num_sheets=*/2);
|
||||
// Create bitmap and queue texture creation
|
||||
|
||||
// Create bitmap for font graphics
|
||||
font_gfx_bitmap_.Create(kFontGfxMessageSize, kFontGfxMessageSize,
|
||||
kFontGfxMessageDepth, message_preview_.font_gfx16_data_);
|
||||
font_gfx_bitmap_.SetPalette(font_preview_colors_);
|
||||
|
||||
// Queue texture creation - will be processed in render loop
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::CREATE, &font_gfx_bitmap_);
|
||||
|
||||
printf("[MessageEditor] Font bitmap created and texture queued\n");
|
||||
*current_font_gfx16_bitmap_.mutable_palette() = font_preview_colors_;
|
||||
|
||||
auto load_font = LoadFontGraphics(*rom());
|
||||
|
||||
@@ -49,6 +49,47 @@ void Emulator::Initialize(gfx::IRenderer* renderer, const std::vector<uint8_t>&
|
||||
renderer_ = renderer;
|
||||
rom_data_ = rom_data;
|
||||
|
||||
// Register emulator cards with EditorCardManager
|
||||
auto& card_manager = gui::EditorCardManager::Get();
|
||||
|
||||
card_manager.RegisterCard({
|
||||
.card_id = "emulator.cpu_debugger",
|
||||
.display_name = "CPU Debugger",
|
||||
.icon = ICON_MD_BUG_REPORT,
|
||||
.category = "Emulator",
|
||||
.visibility_flag = &show_cpu_debugger_,
|
||||
.priority = 10
|
||||
});
|
||||
|
||||
card_manager.RegisterCard({
|
||||
.card_id = "emulator.memory_viewer",
|
||||
.display_name = "Memory Viewer",
|
||||
.icon = ICON_MD_MEMORY,
|
||||
.category = "Emulator",
|
||||
.visibility_flag = &show_memory_viewer_,
|
||||
.priority = 20
|
||||
});
|
||||
|
||||
card_manager.RegisterCard({
|
||||
.card_id = "emulator.ppu_viewer",
|
||||
.display_name = "PPU Viewer",
|
||||
.icon = ICON_MD_GRID_VIEW,
|
||||
.category = "Emulator",
|
||||
.visibility_flag = &show_ppu_viewer_,
|
||||
.priority = 30
|
||||
});
|
||||
|
||||
card_manager.RegisterCard({
|
||||
.card_id = "emulator.audio_mixer",
|
||||
.display_name = "Audio Mixer",
|
||||
.icon = ICON_MD_AUDIO_FILE,
|
||||
.category = "Emulator",
|
||||
.visibility_flag = &show_audio_mixer_,
|
||||
.priority = 40
|
||||
});
|
||||
|
||||
printf("[Emulator] Registered 4 cards with EditorCardManager\n");
|
||||
|
||||
// Reset state for new ROM
|
||||
running_ = false;
|
||||
snes_initialized_ = false;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "app/emu/snes.h"
|
||||
#include "app/emu/audio/audio_backend.h"
|
||||
#include "app/emu/debug/breakpoint_manager.h"
|
||||
#include "app/gui/editor_card_manager.h"
|
||||
#include "app/emu/debug/disassembly_viewer.h"
|
||||
#include "app/emu/input/input_manager.h"
|
||||
#include "app/rom.h"
|
||||
@@ -36,6 +37,12 @@ class Emulator {
|
||||
void Initialize(gfx::IRenderer* renderer, const std::vector<uint8_t>& rom_data);
|
||||
void Run(Rom* rom);
|
||||
void Cleanup();
|
||||
|
||||
// Card visibility for emulator UI panels
|
||||
bool& show_cpu_debugger() { return show_cpu_debugger_; }
|
||||
bool& show_memory_viewer() { return show_memory_viewer_; }
|
||||
bool& show_ppu_viewer() { return show_ppu_viewer_; }
|
||||
bool& show_audio_mixer() { return show_audio_mixer_; }
|
||||
|
||||
auto snes() -> Snes& { return snes_; }
|
||||
auto running() const -> bool { return running_; }
|
||||
@@ -156,6 +163,12 @@ class Emulator {
|
||||
gfx::IRenderer* renderer_ = nullptr;
|
||||
void* ppu_texture_ = nullptr;
|
||||
|
||||
// Card visibility states
|
||||
bool show_cpu_debugger_ = false;
|
||||
bool show_memory_viewer_ = false;
|
||||
bool show_ppu_viewer_ = false;
|
||||
bool show_audio_mixer_ = false;
|
||||
|
||||
// Debugger infrastructure
|
||||
BreakpointManager breakpoint_manager_;
|
||||
debug::DisassemblyViewer disassembly_viewer_;
|
||||
|
||||
@@ -268,15 +268,16 @@ void EditorCardManager::DrawCompactCardControl(const std::string& category) {
|
||||
return; // Nothing to show
|
||||
}
|
||||
|
||||
// Draw as a small button with popup menu
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.3f, 0.3f, 0.4f, 0.8f));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.4f, 0.4f, 0.5f, 1.0f));
|
||||
// Use theme colors for button
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyleColorVec4(ImGuiCol_Button));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImGui::GetStyleColorVec4(ImGuiCol_ButtonActive));
|
||||
|
||||
if (ImGui::SmallButton(ICON_MD_VIEW_MODULE)) {
|
||||
ImGui::OpenPopup("CardControlPopup");
|
||||
}
|
||||
|
||||
ImGui::PopStyleColor(2);
|
||||
ImGui::PopStyleColor(3);
|
||||
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("%s Card Controls", category.c_str());
|
||||
|
||||
Reference in New Issue
Block a user