120 const char* env_value = std::getenv(
"YAZE_USE_SDL_AUDIO_STREAM");
121 if (env_value && std::atoi(env_value) != 0) {
129 ImGui::TextColored(ImVec4(1.0f, 0.3f, 0.3f, 1.0f),
130 "Emulator renderer not initialized");
148 LOG_ERROR(
"Emulator",
"Failed to initialize audio backend");
150 LOG_INFO(
"Emulator",
"Audio backend initialized (lazy): %s",
159 LOG_ERROR(
"Emulator",
"Failed to initialize input manager");
161 LOG_INFO(
"Emulator",
"Input manager initialized: %s",
173 512, 480, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING);
175 printf(
"Failed to create PPU texture: %s\n", SDL_GetError());
210 static bool was_running_before_resize =
false;
214 was_running_before_resize =
true;
219 was_running_before_resize =
false;
230 uint64_t current_count = SDL_GetPerformanceCounter();
242 int frames_to_process = 0;
249 if (frames_to_process > 4) {
250 frames_to_process = 4;
255 for (
int i = 0; i < frames_to_process; i++) {
256 bool should_render = (i == frames_to_process - 1);
282 audio_backend_->SetAudioStreamResampling(
true, kNativeSampleRate, 2);
285 audio_backend_->SetAudioStreamResampling(
false, kNativeSampleRate, 2);
291 const bool use_native_stream =
296 uint32_t queued_frames = audio_status.queued_frames;
304 if (queued_frames < max_buffer) {
305 bool queue_ok =
true;
307 if (use_native_stream) {
308 const int frames_native =
snes_.
apu().dsp().CopyNativeFrame(
318 if (!queue_ok && use_native_stream) {
325 static int error_count = 0;
326 if (++error_count % 300 == 0) {
328 "Failed to queue audio (count: %d, stream=%s)",
329 error_count, use_native_stream ?
"SDL" :
"manual");
334 static int overflow_count = 0;
335 if (++overflow_count % 60 == 0) {
337 "Audio buffer overflow (count: %d, queued: %u)",
338 overflow_count, queued_frames);
505 const auto& theme = theme_manager.GetCurrentTheme();
521 static char bp_addr[16] =
"00FFD9";
523 ImGui::PushItemWidth(100);
524 ImGui::InputText(
"##BPAddr", bp_addr, IM_ARRAYSIZE(bp_addr),
525 ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase);
526 ImGui::PopItemWidth();
529 uint32_t addr = std::strtoul(bp_addr,
nullptr, 16);
532 "", absl::StrFormat(
"BP at $%06X", addr));
536 ImGui::BeginChild(
"##BPList", ImVec2(0, 100),
true);
539 bool enabled = bp.enabled;
540 if (ImGui::Checkbox(absl::StrFormat(
"##en%d", bp.id).c_str(), &enabled)) {
544 ImGui::Text(
"$%06X", bp.address);
546 ImGui::TextDisabled(
"(hits: %d)", bp.hit_count);
548 if (ImGui::SmallButton(absl::StrFormat(
ICON_MD_DELETE "##%d", bp.id).c_str())) {
557 ImGui::TextColored(ConvertColorToImVec4(theme.accent),
"CPU Status");
558 ImGui::PushStyleColor(ImGuiCol_ChildBg,
559 ConvertColorToImVec4(theme.child_bg));
560 ImGui::BeginChild(
"##CpuStatus", ImVec2(0, 180),
true);
563 if (ImGui::BeginTable(
565 ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit)) {
566 ImGui::TableSetupColumn(
"Register", ImGuiTableColumnFlags_WidthFixed, 60);
567 ImGui::TableSetupColumn(
"Value", ImGuiTableColumnFlags_WidthFixed, 80);
568 ImGui::TableSetupColumn(
"Register", ImGuiTableColumnFlags_WidthFixed, 60);
569 ImGui::TableSetupColumn(
"Value", ImGuiTableColumnFlags_WidthFixed, 80);
570 ImGui::TableHeadersRow();
572 ImGui::TableNextRow();
573 ImGui::TableNextColumn();
575 ImGui::TableNextColumn();
576 ImGui::TextColored(ConvertColorToImVec4(theme.accent),
"0x%04X",
578 ImGui::TableNextColumn();
580 ImGui::TableNextColumn();
581 ImGui::TextColored(ConvertColorToImVec4(theme.accent),
"0x%04X",
584 ImGui::TableNextRow();
585 ImGui::TableNextColumn();
587 ImGui::TableNextColumn();
588 ImGui::TextColored(ConvertColorToImVec4(theme.accent),
"0x%04X",
590 ImGui::TableNextColumn();
592 ImGui::TableNextColumn();
593 ImGui::TextColored(ConvertColorToImVec4(theme.accent),
"0x%02X",
596 ImGui::TableNextRow();
597 ImGui::TableNextColumn();
599 ImGui::TableNextColumn();
600 ImGui::TextColored(ConvertColorToImVec4(theme.accent),
"0x%04X",
602 ImGui::TableNextColumn();
604 ImGui::TableNextColumn();
605 ImGui::TextColored(ConvertColorToImVec4(theme.accent),
"0x%02X",
608 ImGui::TableNextRow();
609 ImGui::TableNextColumn();
611 ImGui::TableNextColumn();
612 ImGui::TextColored(ConvertColorToImVec4(theme.success),
"0x%04X",
614 ImGui::TableNextColumn();
616 ImGui::TableNextColumn();
617 ImGui::TextColored(ConvertColorToImVec4(theme.accent),
"0x%02X",
620 ImGui::TableNextRow();
621 ImGui::TableNextColumn();
623 ImGui::TableNextColumn();
624 ImGui::TextColored(ConvertColorToImVec4(theme.warning),
"0x%02X",
626 ImGui::TableNextColumn();
627 ImGui::Text(
"Cycle");
628 ImGui::TableNextColumn();
629 ImGui::TextColored(ConvertColorToImVec4(theme.info),
"%llu",
636 ImGui::PopStyleColor();
639 ImGui::TextColored(ConvertColorToImVec4(theme.accent),
"SPC700 Status");
640 ImGui::PushStyleColor(ImGuiCol_ChildBg,
641 ConvertColorToImVec4(theme.child_bg));
642 ImGui::BeginChild(
"##SpcStatus", ImVec2(0, 150),
true);
644 if (ImGui::BeginTable(
646 ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit)) {
647 ImGui::TableSetupColumn(
"Register", ImGuiTableColumnFlags_WidthFixed, 50);
648 ImGui::TableSetupColumn(
"Value", ImGuiTableColumnFlags_WidthFixed, 60);
649 ImGui::TableSetupColumn(
"Register", ImGuiTableColumnFlags_WidthFixed, 50);
650 ImGui::TableSetupColumn(
"Value", ImGuiTableColumnFlags_WidthFixed, 60);
651 ImGui::TableHeadersRow();
653 ImGui::TableNextRow();
654 ImGui::TableNextColumn();
656 ImGui::TableNextColumn();
657 ImGui::TextColored(ConvertColorToImVec4(theme.accent),
"0x%02X",
659 ImGui::TableNextColumn();
661 ImGui::TableNextColumn();
662 ImGui::TextColored(ConvertColorToImVec4(theme.success),
"0x%04X",
665 ImGui::TableNextRow();
666 ImGui::TableNextColumn();
668 ImGui::TableNextColumn();
669 ImGui::TextColored(ConvertColorToImVec4(theme.accent),
"0x%02X",
671 ImGui::TableNextColumn();
673 ImGui::TableNextColumn();
674 ImGui::TextColored(ConvertColorToImVec4(theme.accent),
"0x%02X",
677 ImGui::TableNextRow();
678 ImGui::TableNextColumn();
680 ImGui::TableNextColumn();
681 ImGui::TextColored(ConvertColorToImVec4(theme.accent),
"0x%02X",
683 ImGui::TableNextColumn();
685 ImGui::TableNextColumn();
687 ConvertColorToImVec4(theme.warning),
"0x%02X",
694 ImGui::PopStyleColor();
697 if (ImGui::CollapsingHeader(
"Disassembly Viewer",
698 ImGuiTreeNodeFlags_DefaultOpen)) {
699 uint32_t current_pc = (
static_cast<uint32_t
>(
snes_.
cpu().PB) << 16) |
snes_.
cpu().PC;
700 auto& disasm =
snes_.
cpu().disassembly_viewer();
701 if (disasm.IsAvailable()) {
702 disasm.Render(current_pc,
snes_.
cpu().breakpoints_);
704 ImGui::TextColored(ConvertColorToImVec4(theme.error),
"Disassembly viewer unavailable.");
707 }
catch (
const std::exception& e) {
710 ImGui::PopStyleColor();
714 ImGui::Text(
"CPU Debugger Error: %s", e.what());