53 static bool loaded =
false;
56 SDL_PIXELFORMAT_ARGB8888,
57 SDL_TEXTUREACCESS_STREAMING, 512, 480);
59 printf(
"Failed to create texture: %s\n", SDL_GetError());
78 uint64_t current_count = SDL_GetPerformanceCounter();
100 if (SDL_LockTexture(
ppu_texture_, NULL, &ppu_pixels_, &ppu_pitch_) !=
102 printf(
"Failed to lock texture: %s\n", SDL_GetError());
115 ImVec2 size = ImVec2(512, 480);
117 ImGui::BeginChild(
"EmulatorOutput", ImVec2(0, 480),
true,
118 ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar);
119 ImGui::SetCursorPosX((ImGui::GetWindowSize().x - size.x) * 0.5f);
120 ImGui::SetCursorPosY((ImGui::GetWindowSize().y - size.y) * 0.5f);
121 ImGui::Image((
void*)
ppu_texture_, size, ImVec2(0, 0), ImVec2(1, 1));
125 ImGui::Text(
"Emulator output not available.");
126 ImGui::BeginChild(
"EmulatorOutput", ImVec2(0, 480),
true,
127 ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar);
128 ImGui::SetCursorPosX(((ImGui::GetWindowSize().x * 0.5f) - size.x) * 0.5f);
129 ImGui::SetCursorPosY(((ImGui::GetWindowSize().y * 0.5f) - size.y) * 0.5f);
137 std::string navbar_layout = R
"(
139 BeginMenu title="Options" {
140 MenuItem title="Input" {}
141 MenuItem title="Audio" {}
142 MenuItem title="Video" {}
153 if (ImGui::IsItemHovered()) {
154 ImGui::SetTooltip(
"Start Emulation");
161 if (ImGui::IsItemHovered()) {
162 ImGui::SetTooltip(
"Pause Emulation");
170 if (ImGui::IsItemHovered()) {
171 ImGui::SetTooltip(
"Step Through Code");
179 if (ImGui::IsItemHovered()) {
180 ImGui::SetTooltip(
"Reset Emulator");
188 if (ImGui::IsItemHovered()) {
189 ImGui::SetTooltip(
"Stop Emulation");
196 if (ImGui::IsItemHovered()) {
197 ImGui::SetTooltip(
"Save State");
203 if (ImGui::IsItemHovered()) {
204 ImGui::SetTooltip(
"Load State");
212 if (ImGui::IsItemHovered()) {
213 ImGui::SetTooltip(
"Settings");
216 static bool open_file =
false;
223 if (ImGui::IsItemHovered()) {
224 ImGui::SetTooltip(
"About Debugger");
227 ImGui::Checkbox(
"Logging",
snes_.
cpu().mutable_log_instructions());
232 static bool show_memory_viewer =
false;
236 show_memory_viewer = !show_memory_viewer;
238 if (ImGui::IsItemHovered()) {
239 ImGui::SetTooltip(
"Memory Viewer");
242 if (show_memory_viewer) {
243 ImGui::Begin(
"Memory Viewer", &show_memory_viewer);
250 if (!file_name.empty()) {
251 std::ifstream file(file_name, std::ios::binary);
253 rom_data_.assign(std::istreambuf_iterator<char>(file),
254 std::istreambuf_iterator<char>());
267 if (ImGui::Button(
"Set SPC PC")) {
273 static char breakpoint_input[10] =
"";
274 static int current_memory_mode = 0;
276 static bool read_mode =
false;
277 static bool write_mode =
false;
278 static bool execute_mode =
false;
280 if (ImGui::Combo(
"##TypeOfMemory", ¤t_memory_mode,
"PRG\0RAM\0")) {
283 ImGui::Checkbox(
"Read", &read_mode);
285 ImGui::Checkbox(
"Write", &write_mode);
287 ImGui::Checkbox(
"Execute", &execute_mode);
290 if (ImGui::InputText(
"##BreakpointInput", breakpoint_input, 10,
291 ImGuiInputTextFlags_EnterReturnsTrue)) {
292 int breakpoint = std::stoi(breakpoint_input,
nullptr, 16);
293 snes_.
cpu().SetBreakpoint(breakpoint);
294 memset(breakpoint_input, 0,
sizeof(breakpoint_input));
297 if (ImGui::Button(
"Add")) {
298 int breakpoint = std::stoi(breakpoint_input,
nullptr, 16);
299 snes_.
cpu().SetBreakpoint(breakpoint);
300 memset(breakpoint_input, 0,
sizeof(breakpoint_input));
303 if (ImGui::Button(
"Clear")) {
307 auto breakpoints =
snes_.
cpu().GetBreakpoints();
308 if (!breakpoints.empty()) {
309 Text(
"Breakpoints:");
310 ImGui::BeginChild(
"BreakpointsList", ImVec2(0, 100),
true);
311 for (
auto breakpoint : breakpoints) {
312 if (ImGui::Selectable(absl::StrFormat(
"0x%04X", breakpoint).c_str())) {
322 if (ImGui::Button(
"Set Current Address")) {
329 static MemoryEditor ram_edit;
330 static MemoryEditor aram_edit;
331 static MemoryEditor mem_edit;
333 if (ImGui::BeginTable(
"MemoryViewerTable", 4,
334 ImGuiTableFlags_Resizable | ImGuiTableFlags_ScrollY)) {
335 ImGui::TableSetupColumn(
"Bookmarks");
336 ImGui::TableSetupColumn(
"RAM");
337 ImGui::TableSetupColumn(
"ARAM");
338 ImGui::TableSetupColumn(
"ROM");
339 ImGui::TableHeadersRow();
342 if (ImGui::CollapsingHeader(
"Bookmarks", ImGuiTreeNodeFlags_DefaultOpen)) {
344 static char nameBuf[256];
345 static uint64_t uint64StringBuf;
346 ImGui::InputText(
"Name", nameBuf, IM_ARRAYSIZE(nameBuf));
348 if (ImGui::Button(
"Add Bookmark")) {
349 bookmarks.push_back({nameBuf, uint64StringBuf});
350 memset(nameBuf, 0,
sizeof(nameBuf));
356 if (ImGui::TreeNode(bookmark.name.c_str(),
ICON_MD_STAR)) {
357 auto bookmark_string = absl::StrFormat(
358 "%s: 0x%08X", bookmark.name.c_str(), bookmark.value);
359 if (ImGui::Selectable(bookmark_string.c_str())) {
360 mem_edit.GotoAddrAndHighlight(
static_cast<ImU64
>(bookmark.value),
364 if (ImGui::Button(
"Delete")) {
368 return b.name == bookmark.name &&
369 b.value == bookmark.value;
379 if (ImGui::BeginChild(
"RAM", ImVec2(0, 0),
true,
380 ImGuiWindowFlags_NoMove |
381 ImGuiWindowFlags_NoScrollbar |
382 ImGuiWindowFlags_NoScrollWithMouse)) {
388 if (ImGui::BeginChild(
"ARAM", ImVec2(0, 0),
true,
389 ImGuiWindowFlags_NoMove |
390 ImGuiWindowFlags_NoScrollbar |
391 ImGuiWindowFlags_NoScrollWithMouse)) {
392 aram_edit.DrawContents((
void*)
snes_.
apu().ram.data(),
398 if (ImGui::BeginChild(
"ROM", ImVec2(0, 0),
true,
399 ImGuiWindowFlags_NoMove |
400 ImGuiWindowFlags_NoScrollbar |
401 ImGuiWindowFlags_NoScrollWithMouse)) {
402 mem_edit.DrawContents((
void*)
snes_.
Memory().rom_.data(),
412 const std::vector<InstructionEntry>& instruction_log) {
413 if (ImGui::CollapsingHeader(
"Instruction Log",
414 ImGuiTreeNodeFlags_DefaultOpen)) {
416 static char filter[256];
417 ImGui::InputText(
"Filter", filter, IM_ARRAYSIZE(filter));
420 ImGui::BeginChild(
"InstructionList", ImVec2(0, 0), ImGuiChildFlags_None);
421 for (
const auto& entry : instruction_log) {
422 if (ShouldDisplay(entry, filter)) {
423 if (ImGui::Selectable(
424 absl::StrFormat(
"%06X:", entry.address).c_str())) {
430 ImVec4 color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
431 ImGui::TextColored(color,
"%s",
433 ImVec4 operand_color = ImVec4(0.7f, 0.5f, 0.3f, 1.0f);
435 ImGui::TextColored(operand_color,
"%s", entry.operands.c_str());
439 if (ImGui::GetScrollY() >= ImGui::GetScrollMaxY()) {
440 ImGui::SetScrollHereY(1.0f);