diff --git a/src/app/emu/emulator.cc b/src/app/emu/emulator.cc index 75604abc..8f2de9ff 100644 --- a/src/app/emu/emulator.cc +++ b/src/app/emu/emulator.cc @@ -59,8 +59,8 @@ void Emulator::Run() { return; } snes_.Init(*rom()); - wanted_frames_ = 1.0 / (snes_.Memory()->pal_timing() ? 50.0 : 60.0); - wanted_samples_ = 48000 / (snes_.Memory()->pal_timing() ? 50 : 60); + wanted_frames_ = 1.0 / (snes_.Memory().pal_timing() ? 50.0 : 60.0); + wanted_samples_ = 48000 / (snes_.Memory().pal_timing() ? 50 : 60); loaded = true; countFreq = SDL_GetPerformanceFrequency(); @@ -84,6 +84,12 @@ void Emulator::Run() { if (loaded) { snes_.RunFrame(); + + snes_.SetSamples(audio_buffer_, wanted_samples_); + if (SDL_GetQueuedAudioSize(audio_device_) <= wanted_samples_ * 4 * 6) { + SDL_QueueAudio(audio_device_, audio_buffer_, wanted_samples_ * 4); + } + void* ppu_pixels_; int ppu_pitch_; if (SDL_LockTexture(ppu_texture_, NULL, &ppu_pixels_, &ppu_pitch_) != @@ -153,7 +159,7 @@ void Emulator::RenderNavBar() { if (ImGui::Button(ICON_MD_SKIP_NEXT)) { // Step through Code logic - snes_.cpu()->RunOpcode(); + snes_.cpu().RunOpcode(); } if (ImGui::IsItemHovered()) { ImGui::SetTooltip("Step Through Code"); @@ -210,7 +216,7 @@ void Emulator::RenderNavBar() { } SameLine(); - ImGui::Checkbox("Logging", snes_.cpu()->mutable_log_instructions()); + ImGui::Checkbox("Logging", snes_.cpu().mutable_log_instructions()); static bool show_memory_viewer = false; @@ -257,28 +263,28 @@ void Emulator::RenderBreakpointList() { if (ImGui::InputText("##BreakpointInput", breakpoint_input, 10, ImGuiInputTextFlags_EnterReturnsTrue)) { int breakpoint = std::stoi(breakpoint_input, nullptr, 16); - snes_.cpu()->SetBreakpoint(breakpoint); + snes_.cpu().SetBreakpoint(breakpoint); memset(breakpoint_input, 0, sizeof(breakpoint_input)); } SameLine(); if (ImGui::Button("Add")) { int breakpoint = std::stoi(breakpoint_input, nullptr, 16); - snes_.cpu()->SetBreakpoint(breakpoint); + snes_.cpu().SetBreakpoint(breakpoint); memset(breakpoint_input, 0, sizeof(breakpoint_input)); } SameLine(); if (ImGui::Button("Clear")) { - snes_.cpu()->ClearBreakpoints(); + snes_.cpu().ClearBreakpoints(); } Separator(); - auto breakpoints = snes_.cpu()->GetBreakpoints(); + auto breakpoints = snes_.cpu().GetBreakpoints(); if (!breakpoints.empty()) { Text("Breakpoints:"); ImGui::BeginChild("BreakpointsList", ImVec2(0, 100), true); for (auto breakpoint : breakpoints) { if (ImGui::Selectable(absl::StrFormat("0x%04X", breakpoint).c_str())) { // Jump to breakpoint - // snes_.cpu()->JumpToBreakpoint(breakpoint); + // snes_.cpu().JumpToBreakpoint(breakpoint); } } ImGui::EndChild(); @@ -287,8 +293,8 @@ void Emulator::RenderBreakpointList() { gui::InputHexByte("PB", &manual_pb_, 50.f); gui::InputHexWord("PC", &manual_pc_, 75.f); if (ImGui::Button("Set Current Address")) { - snes_.cpu()->PC = manual_pc_; - snes_.cpu()->PB = manual_pb_; + snes_.cpu().PC = manual_pc_; + snes_.cpu().PB = manual_pb_; } } @@ -342,8 +348,8 @@ void Emulator::RenderMemoryViewer() { } TableNextColumn(); - mem_edit.DrawContents((void*)snes_.Memory()->rom_.data(), - snes_.Memory()->rom_.size()); + mem_edit.DrawContents((void*)snes_.Memory().rom_.data(), + snes_.Memory().rom_.size()); ImGui::EndTable(); } diff --git a/src/app/emu/emulator.h b/src/app/emu/emulator.h index a157c497..aac8b563 100644 --- a/src/app/emu/emulator.h +++ b/src/app/emu/emulator.h @@ -56,13 +56,13 @@ class Emulator : public SharedRom { } )"; const std::map data_bindings = { - {"cpu.A", &snes_.cpu()->A}, {"cpu.D", &snes_.cpu()->D}, - {"cpu.X", &snes_.cpu()->X}, {"cpu.DB", &snes_.cpu()->DB}, - {"cpu.Y", &snes_.cpu()->Y}, {"cpu.PB", &snes_.cpu()->PB}, - {"cpu.PC", &snes_.cpu()->PC}, {"cpu.E", &snes_.cpu()->E}}; + {"cpu.A", &snes_.cpu().A}, {"cpu.D", &snes_.cpu().D}, + {"cpu.X", &snes_.cpu().X}, {"cpu.DB", &snes_.cpu().DB}, + {"cpu.Y", &snes_.cpu().Y}, {"cpu.PB", &snes_.cpu().PB}, + {"cpu.PC", &snes_.cpu().PC}, {"cpu.E", &snes_.cpu().E}}; emulator_node_ = gui::zeml::Parse(emulator_layout, data_bindings); Bind(emulator_node_.GetNode("CpuInstructionLog"), - [&]() { RenderCpuInstructionLog(snes_.cpu()->instruction_log_); }); + [&]() { RenderCpuInstructionLog(snes_.cpu().instruction_log_); }); Bind(emulator_node_.GetNode("SnesPpu"), [&]() { RenderSnesPpu(); }); Bind(emulator_node_.GetNode("BreakpointList"), [&]() { RenderBreakpointList(); }); @@ -72,6 +72,9 @@ class Emulator : public SharedRom { auto snes() -> SNES& { return snes_; } auto running() const -> bool { return running_; } void set_audio_buffer(int16_t* audio_buffer) { audio_buffer_ = audio_buffer; } + auto set_audio_device_id(SDL_AudioDeviceID audio_device) { + audio_device_ = audio_device; + } auto wanted_samples() const -> int { return wanted_samples_; } private: @@ -108,6 +111,7 @@ class Emulator : public SharedRom { float timeAdder = 0.0; int16_t* audio_buffer_; + SDL_AudioDeviceID audio_device_; SNES snes_; SDL_Texture* ppu_texture_; diff --git a/src/app/emu/snes.cc b/src/app/emu/snes.cc index 0a65d11f..507447d8 100644 --- a/src/app/emu/snes.cc +++ b/src/app/emu/snes.cc @@ -37,45 +37,6 @@ void SNES::Init(Rom& rom) { // rom_info_ = memory_.ReadRomHeader(); Reset(true); - // Disable the emulation flag (switch to 65816 native mode) - // cpu_.E = 0; - // cpu_.PB = 0x00; - // cpu_.PC = 0x8000; - - // Disable interrupts and rendering - memory_.WriteByte(0x4200, 0x00); // NMITIMEN - memory_.WriteByte(0x420C, 0x00); // HDMAEN - - // Disable screen - memory_.WriteByte(0x2100, 0x8F); // INIDISP - - // Reset PPU registers to a known good state - memory_.WriteByte(0x4201, 0xFF); // WRIO - - // Scroll Registers - memory_.WriteByte(0x210D, 0x00); // BG1HOFS - memory_.WriteByte(0x210E, 0xFF); // BG1VOFS - - memory_.WriteByte(0x210F, 0x00); // BG2HOFS - memory_.WriteByte(0x2110, 0xFF); // BG2VOFS - - memory_.WriteByte(0x2111, 0x00); // BG3HOFS - memory_.WriteByte(0x2112, 0xFF); // BG3VOFS - - memory_.WriteByte(0x2113, 0x00); // BG4HOFS - memory_.WriteByte(0x2114, 0xFF); // BG4VOFS - - // VRAM Registers - memory_.WriteByte(0x2115, 0x80); // VMAIN - - // Color Math - memory_.WriteByte(0x2130, 0x30); // CGWSEL - memory_.WriteByte(0x2131, 0x00); // CGADSUB - memory_.WriteByte(0x2132, 0xE0); // COLDATA - - // Misc - memory_.WriteByte(0x2133, 0x00); // SETINI - running_ = true; } @@ -291,7 +252,7 @@ uint8_t SNES::ReadBBus(uint8_t adr) { } if (adr < 0x80) { CatchUpApu(); // catch up the apu before reading - return apu_.outPorts[adr & 0x3]; + return apu_.out_ports_[adr & 0x3]; } if (adr == 0x80) { uint8_t ret = ram[ram_adr_++]; @@ -397,7 +358,7 @@ void SNES::WriteBBus(uint8_t adr, uint8_t val) { } if (adr < 0x80) { CatchUpApu(); // catch up the apu before writing - apu_.inPorts[adr & 0x3] = val; + apu_.in_ports_[adr & 0x3] = val; return; } switch (adr) { diff --git a/src/app/emu/snes.h b/src/app/emu/snes.h index 605d2f8c..dd84b318 100644 --- a/src/app/emu/snes.h +++ b/src/app/emu/snes.h @@ -67,9 +67,9 @@ class SNES { void SetPixels(uint8_t* pixel_data); bool running() const { return running_; } - auto cpu() -> Cpu* { return &cpu_; } - auto ppu() -> video::Ppu* { return &ppu_; } - auto Memory() -> memory::MemoryImpl* { return &memory_; } + auto cpu() -> Cpu& { return cpu_; } + auto ppu() -> video::Ppu& { return ppu_; } + auto Memory() -> memory::MemoryImpl& { return memory_; } private: // Components of the SNES @@ -77,7 +77,6 @@ class SNES { Debugger debugger; memory::RomInfo rom_info_; memory::MemoryImpl memory_; - audio::AudioRamImpl audio_ram_; memory::CpuCallbacks cpu_callbacks_ = { [&](uint32_t adr) { return CpuRead(adr); }, @@ -86,7 +85,7 @@ class SNES { }; Cpu cpu_{memory_, clock_, cpu_callbacks_}; video::Ppu ppu_{memory_, clock_}; - audio::Apu apu_{memory_, audio_ram_, clock_}; + audio::Apu apu_{memory_, clock_}; // Currently loaded ROM std::vector rom_data;