50 static bool loaded =
false;
51 if (!
snes_.running() &&
rom()->is_loaded()) {
53 SDL_PIXELFORMAT_ARGB8888,
54 SDL_TEXTUREACCESS_STREAMING, 512, 480);
56 printf(
"Failed to create texture: %s\n", SDL_GetError());
75 uint64_t current_count = SDL_GetPerformanceCounter();
97 if (SDL_LockTexture(
ppu_texture_, NULL, &ppu_pixels_, &ppu_pitch_) !=
99 printf(
"Failed to lock texture: %s\n", SDL_GetError());
102 snes_.SetPixels(
static_cast<uint8_t*
>(ppu_pixels_));
112 ImVec2 size = ImVec2(512, 480);
113 if (
snes_.running()) {
114 ImGui::BeginChild(
"EmulatorOutput", ImVec2(0, 480),
true,
115 ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar);
116 ImGui::SetCursorPosX((ImGui::GetWindowSize().x - size.x) * 0.5f);
117 ImGui::SetCursorPosY((ImGui::GetWindowSize().y - size.y) * 0.5f);
118 ImGui::Image((ImTextureID)(intptr_t)
ppu_texture_, size, ImVec2(0, 0),
123 ImGui::Text(
"Emulator output not available.");
124 ImGui::BeginChild(
"EmulatorOutput", ImVec2(0, 480),
true,
125 ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar);
126 ImGui::SetCursorPosX(((ImGui::GetWindowSize().x * 0.5f) - size.x) * 0.5f);
127 ImGui::SetCursorPosY(((ImGui::GetWindowSize().y * 0.5f) - size.y) * 0.5f);
135 std::string navbar_layout = R
"(
137 BeginMenu title="Options" {
138 MenuItem title="Input" {}
139 MenuItem title="Audio" {}
140 MenuItem title="Video" {}
151 if (ImGui::IsItemHovered()) {
152 ImGui::SetTooltip(
"Start Emulation");
159 if (ImGui::IsItemHovered()) {
160 ImGui::SetTooltip(
"Pause Emulation");
166 snes_.cpu().RunOpcode();
168 if (ImGui::IsItemHovered()) {
169 ImGui::SetTooltip(
"Step Through Code");
177 if (ImGui::IsItemHovered()) {
178 ImGui::SetTooltip(
"Reset Emulator");
186 if (ImGui::IsItemHovered()) {
187 ImGui::SetTooltip(
"Stop Emulation");
194 if (ImGui::IsItemHovered()) {
195 ImGui::SetTooltip(
"Save State");
201 if (ImGui::IsItemHovered()) {
202 ImGui::SetTooltip(
"Load State");
210 if (ImGui::IsItemHovered()) {
211 ImGui::SetTooltip(
"Settings");
214 static bool open_file =
false;
221 if (ImGui::IsItemHovered()) {
222 ImGui::SetTooltip(
"About Debugger");
225 ImGui::Checkbox(
"Logging",
snes_.cpu().mutable_log_instructions());
230 static bool show_memory_viewer =
false;
234 show_memory_viewer = !show_memory_viewer;
236 if (ImGui::IsItemHovered()) {
237 ImGui::SetTooltip(
"Memory Viewer");
240 if (show_memory_viewer) {
241 ImGui::Begin(
"Memory Viewer", &show_memory_viewer);
248 if (!file_name.empty()) {
249 std::ifstream file(file_name, std::ios::binary);
251 rom_data_.assign(std::istreambuf_iterator<char>(file),
252 std::istreambuf_iterator<char>());
359 if (ImGui::Button(
"Set SPC PC")) {
360 snes_.apu().spc700().PC = 0xFFEF;
365 static char breakpoint_input[10] =
"";
366 static int current_memory_mode = 0;
368 static bool read_mode =
false;
369 static bool write_mode =
false;
370 static bool execute_mode =
false;
372 if (ImGui::Combo(
"##TypeOfMemory", ¤t_memory_mode,
"PRG\0RAM\0")) {
375 ImGui::Checkbox(
"Read", &read_mode);
377 ImGui::Checkbox(
"Write", &write_mode);
379 ImGui::Checkbox(
"Execute", &execute_mode);
382 if (ImGui::InputText(
"##BreakpointInput", breakpoint_input, 10,
383 ImGuiInputTextFlags_EnterReturnsTrue)) {
384 int breakpoint = std::stoi(breakpoint_input,
nullptr, 16);
385 snes_.cpu().SetBreakpoint(breakpoint);
386 memset(breakpoint_input, 0,
sizeof(breakpoint_input));
389 if (ImGui::Button(
"Add")) {
390 int breakpoint = std::stoi(breakpoint_input,
nullptr, 16);
391 snes_.cpu().SetBreakpoint(breakpoint);
392 memset(breakpoint_input, 0,
sizeof(breakpoint_input));
395 if (ImGui::Button(
"Clear")) {
396 snes_.cpu().ClearBreakpoints();
399 auto breakpoints =
snes_.cpu().GetBreakpoints();
400 if (!breakpoints.empty()) {
401 Text(
"Breakpoints:");
402 ImGui::BeginChild(
"BreakpointsList", ImVec2(0, 100),
true);
403 for (
auto breakpoint : breakpoints) {
404 if (ImGui::Selectable(absl::StrFormat(
"0x%04X", breakpoint).c_str())) {
414 if (ImGui::Button(
"Set Current Address")) {
421 static MemoryEditor ram_edit;
422 static MemoryEditor aram_edit;
423 static MemoryEditor mem_edit;
425 if (ImGui::BeginTable(
"MemoryViewerTable", 4,
426 ImGuiTableFlags_Resizable | ImGuiTableFlags_ScrollY)) {
427 ImGui::TableSetupColumn(
"Bookmarks");
428 ImGui::TableSetupColumn(
"RAM");
429 ImGui::TableSetupColumn(
"ARAM");
430 ImGui::TableSetupColumn(
"ROM");
431 ImGui::TableHeadersRow();
434 if (ImGui::CollapsingHeader(
"Bookmarks", ImGuiTreeNodeFlags_DefaultOpen)) {
436 static char nameBuf[256];
437 static uint64_t uint64StringBuf;
438 ImGui::InputText(
"Name", nameBuf, IM_ARRAYSIZE(nameBuf));
440 if (ImGui::Button(
"Add Bookmark")) {
441 bookmarks.push_back({nameBuf, uint64StringBuf});
442 memset(nameBuf, 0,
sizeof(nameBuf));
448 if (ImGui::TreeNode(bookmark.name.c_str(),
ICON_MD_STAR)) {
449 auto bookmark_string = absl::StrFormat(
450 "%s: 0x%08X", bookmark.name.c_str(), bookmark.value);
451 if (ImGui::Selectable(bookmark_string.c_str())) {
452 mem_edit.GotoAddrAndHighlight(
static_cast<ImU64
>(bookmark.value),
456 if (ImGui::Button(
"Delete")) {
460 return b.name == bookmark.name &&
461 b.value == bookmark.value;
471 if (ImGui::BeginChild(
"RAM", ImVec2(0, 0),
true,
472 ImGuiWindowFlags_NoMove |
473 ImGuiWindowFlags_NoScrollbar |
474 ImGuiWindowFlags_NoScrollWithMouse)) {
475 ram_edit.DrawContents((
void*)
snes_.get_ram(), 0x20000);
480 if (ImGui::BeginChild(
"ARAM", ImVec2(0, 0),
true,
481 ImGuiWindowFlags_NoMove |
482 ImGuiWindowFlags_NoScrollbar |
483 ImGuiWindowFlags_NoScrollWithMouse)) {
484 aram_edit.DrawContents((
void*)
snes_.apu().ram.data(),
485 snes_.apu().ram.size());
490 if (ImGui::BeginChild(
"ROM", ImVec2(0, 0),
true,
491 ImGuiWindowFlags_NoMove |
492 ImGuiWindowFlags_NoScrollbar |
493 ImGuiWindowFlags_NoScrollWithMouse)) {
494 mem_edit.DrawContents((
void*)
snes_.Memory().rom_.data(),
495 snes_.Memory().rom_.size());
504 const std::vector<InstructionEntry>& instruction_log) {
505 if (ImGui::CollapsingHeader(
"Instruction Log",
506 ImGuiTreeNodeFlags_DefaultOpen)) {
508 static char filter[256];
509 ImGui::InputText(
"Filter", filter, IM_ARRAYSIZE(filter));
512 ImGui::BeginChild(
"InstructionList", ImVec2(0, 0), ImGuiChildFlags_None);
513 for (
const auto& entry : instruction_log) {
514 if (ShouldDisplay(entry, filter)) {
515 if (ImGui::Selectable(
516 absl::StrFormat(
"%06X:", entry.address).c_str())) {
522 ImVec4 color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
523 ImGui::TextColored(color,
"%s",
525 ImVec4 operand_color = ImVec4(0.7f, 0.5f, 0.3f, 1.0f);
527 ImGui::TextColored(operand_color,
"%s", entry.operands.c_str());
531 if (ImGui::GetScrollY() >= ImGui::GetScrollMaxY()) {
532 ImGui::SetScrollHereY(1.0f);