Add Debugger interface, RoomObject class
- Log instructions to debugger using experiment flag - Use BitmapManager for more functionality - Draw framebuffer and integrated debugger
This commit is contained in:
@@ -13,7 +13,7 @@ namespace emu {
|
||||
|
||||
void Emulator::Run() {
|
||||
// Initialize the emulator if a ROM is loaded
|
||||
if (!snes_.running()) {
|
||||
if (!snes_.running() && loading_) {
|
||||
if (rom()->isLoaded()) {
|
||||
snes_.Init(*rom());
|
||||
running_ = true;
|
||||
@@ -23,13 +23,17 @@ void Emulator::Run() {
|
||||
// Render the emulator output
|
||||
RenderNavBar();
|
||||
|
||||
RenderEmulator();
|
||||
|
||||
if (running_) {
|
||||
// Handle user input events
|
||||
HandleEvents();
|
||||
// Update the emulator state
|
||||
UpdateEmulator();
|
||||
|
||||
RenderEmulator();
|
||||
}
|
||||
|
||||
if (debugger_) {
|
||||
RenderDebugger();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,14 +42,32 @@ void Emulator::RenderEmulator() {
|
||||
// You can use the ImGui::Image function to display the emulator output as a
|
||||
// texture
|
||||
// ...
|
||||
ImVec2 size = ImVec2(320, 240);
|
||||
if (snes_.running()) {
|
||||
ImGui::Image((void*)snes_.Ppu().GetScreen()->texture(), size, ImVec2(0, 0),
|
||||
ImVec2(1, 1));
|
||||
ImGui::Separator();
|
||||
} else {
|
||||
ImGui::Dummy(size);
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Emulator output not available.");
|
||||
}
|
||||
}
|
||||
|
||||
void Emulator::RenderNavBar() {
|
||||
MENU_BAR()
|
||||
|
||||
if (ImGui::BeginMenu("Game")) {
|
||||
MENU_ITEM("Power Off") {}
|
||||
MENU_ITEM("Pause") {}
|
||||
MENU_ITEM("Load ROM") { loading_ = true; }
|
||||
MENU_ITEM("Power Off") {
|
||||
running_ = false;
|
||||
loading_ = false;
|
||||
debugger_ = false;
|
||||
}
|
||||
MENU_ITEM("Pause") {
|
||||
running_ = false;
|
||||
debugger_ = false;
|
||||
}
|
||||
MENU_ITEM("Reset") {}
|
||||
|
||||
MENU_ITEM("Save State") {}
|
||||
@@ -56,7 +78,15 @@ void Emulator::RenderNavBar() {
|
||||
|
||||
if (ImGui::BeginMenu("Debug")) {
|
||||
ImGui::MenuItem("PPU Register Viewer", nullptr, &show_ppu_reg_viewer_);
|
||||
MENU_ITEM("Debugger") {}
|
||||
MENU_ITEM("Debugger") { debugger_ = !debugger_; }
|
||||
if (ImGui::MenuItem("Integrated Debugger", nullptr,
|
||||
&integrated_debugger_mode_)) {
|
||||
separate_debugger_mode_ = !integrated_debugger_mode_;
|
||||
}
|
||||
if (ImGui::MenuItem("Separate Debugger Windows", nullptr,
|
||||
&separate_debugger_mode_)) {
|
||||
integrated_debugger_mode_ = !separate_debugger_mode_;
|
||||
}
|
||||
MENU_ITEM("Memory Viewer") {}
|
||||
MENU_ITEM("Tile Viewer") {}
|
||||
ImGui::EndMenu();
|
||||
@@ -82,6 +112,102 @@ void Emulator::UpdateEmulator() {
|
||||
snes_.Run();
|
||||
}
|
||||
|
||||
void Emulator::RenderDebugger() {
|
||||
// Define a lambda with the actual debugger
|
||||
auto debugger = [&]() {
|
||||
if (ImGui::BeginTable(
|
||||
"DebugTable", 2,
|
||||
ImGuiTableFlags_Resizable | ImGuiTableFlags_ScrollY)) {
|
||||
ImGui::TableNextColumn();
|
||||
RenderCpuState(snes_.Cpu());
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
RenderCPUInstructionLog(snes_.Cpu().instruction_log_);
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
};
|
||||
|
||||
if (integrated_debugger_mode_) {
|
||||
debugger();
|
||||
} else if (separate_debugger_mode_) {
|
||||
ImGui::Begin("Debugger");
|
||||
debugger();
|
||||
ImGui::End();
|
||||
}
|
||||
}
|
||||
|
||||
void Emulator::RenderCpuState(CPU& cpu) {
|
||||
ImGui::Columns(2, "RegistersColumns");
|
||||
ImGui::Separator();
|
||||
ImGui::Text("A: 0x%04X", cpu.A);
|
||||
ImGui::NextColumn();
|
||||
ImGui::Text("D: 0x%04X", cpu.D);
|
||||
ImGui::NextColumn();
|
||||
ImGui::Text("X: 0x%04X", cpu.X);
|
||||
ImGui::NextColumn();
|
||||
ImGui::Text("DB: 0x%02X", cpu.DB);
|
||||
ImGui::NextColumn();
|
||||
ImGui::Text("Y: 0x%04X", cpu.Y);
|
||||
ImGui::NextColumn();
|
||||
ImGui::Text("PB: 0x%02X", cpu.PB);
|
||||
ImGui::NextColumn();
|
||||
ImGui::Text("PC: 0x%04X", cpu.PC);
|
||||
ImGui::NextColumn();
|
||||
ImGui::Text("E: %d", cpu.E);
|
||||
ImGui::NextColumn();
|
||||
ImGui::Columns(1);
|
||||
ImGui::Separator();
|
||||
// Call Stack
|
||||
if (ImGui::CollapsingHeader("Call Stack")) {
|
||||
// For each return address in the call stack:
|
||||
ImGui::Text("Return Address: 0x%08X", 0xFFFFFF); // Placeholder
|
||||
}
|
||||
}
|
||||
|
||||
void Emulator::RenderMemoryViewer() {
|
||||
// Render memory viewer
|
||||
}
|
||||
|
||||
namespace {
|
||||
bool ShouldDisplay(const InstructionEntry& entry, const char* filter,
|
||||
bool showAll) {
|
||||
// Implement logic to determine if the entry should be displayed based on the
|
||||
// filter and showAll flag
|
||||
return true;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void Emulator::RenderCPUInstructionLog(
|
||||
const std::vector<InstructionEntry>& instructionLog) {
|
||||
if (ImGui::CollapsingHeader("CPU Instruction Log")) {
|
||||
// Filtering options
|
||||
static char filterBuf[256];
|
||||
ImGui::InputText("Filter", filterBuf, IM_ARRAYSIZE(filterBuf));
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Clear")) { /* Clear filter logic */
|
||||
}
|
||||
|
||||
// Toggle for showing all opcodes
|
||||
static bool showAllOpcodes = false;
|
||||
ImGui::Checkbox("Show All Opcodes", &showAllOpcodes);
|
||||
|
||||
// Instruction list
|
||||
ImGui::BeginChild("InstructionList");
|
||||
for (const auto& entry : instructionLog) {
|
||||
if (ShouldDisplay(entry, filterBuf, showAllOpcodes)) {
|
||||
if (ImGui::Selectable(absl::StrFormat("%04X: %02X %s %s", entry.address,
|
||||
entry.opcode, entry.operands,
|
||||
entry.instruction)
|
||||
.c_str())) {
|
||||
// Logic to handle click (e.g., jump to address, set breakpoint)
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::EndChild();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace emu
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
Reference in New Issue
Block a user