Play audio in emulator class, update class references from the SNES

This commit is contained in:
scawful
2024-04-24 10:08:05 -04:00
parent f3cf9ac555
commit bd6fc2e8f1
4 changed files with 34 additions and 64 deletions

View File

@@ -59,8 +59,8 @@ void Emulator::Run() {
return; return;
} }
snes_.Init(*rom()); snes_.Init(*rom());
wanted_frames_ = 1.0 / (snes_.Memory()->pal_timing() ? 50.0 : 60.0); wanted_frames_ = 1.0 / (snes_.Memory().pal_timing() ? 50.0 : 60.0);
wanted_samples_ = 48000 / (snes_.Memory()->pal_timing() ? 50 : 60); wanted_samples_ = 48000 / (snes_.Memory().pal_timing() ? 50 : 60);
loaded = true; loaded = true;
countFreq = SDL_GetPerformanceFrequency(); countFreq = SDL_GetPerformanceFrequency();
@@ -84,6 +84,12 @@ void Emulator::Run() {
if (loaded) { if (loaded) {
snes_.RunFrame(); 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_; void* ppu_pixels_;
int ppu_pitch_; int ppu_pitch_;
if (SDL_LockTexture(ppu_texture_, NULL, &ppu_pixels_, &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)) { if (ImGui::Button(ICON_MD_SKIP_NEXT)) {
// Step through Code logic // Step through Code logic
snes_.cpu()->RunOpcode(); snes_.cpu().RunOpcode();
} }
if (ImGui::IsItemHovered()) { if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Step Through Code"); ImGui::SetTooltip("Step Through Code");
@@ -210,7 +216,7 @@ void Emulator::RenderNavBar() {
} }
SameLine(); SameLine();
ImGui::Checkbox("Logging", snes_.cpu()->mutable_log_instructions()); ImGui::Checkbox("Logging", snes_.cpu().mutable_log_instructions());
static bool show_memory_viewer = false; static bool show_memory_viewer = false;
@@ -257,28 +263,28 @@ void Emulator::RenderBreakpointList() {
if (ImGui::InputText("##BreakpointInput", breakpoint_input, 10, if (ImGui::InputText("##BreakpointInput", breakpoint_input, 10,
ImGuiInputTextFlags_EnterReturnsTrue)) { ImGuiInputTextFlags_EnterReturnsTrue)) {
int breakpoint = std::stoi(breakpoint_input, nullptr, 16); int breakpoint = std::stoi(breakpoint_input, nullptr, 16);
snes_.cpu()->SetBreakpoint(breakpoint); snes_.cpu().SetBreakpoint(breakpoint);
memset(breakpoint_input, 0, sizeof(breakpoint_input)); memset(breakpoint_input, 0, sizeof(breakpoint_input));
} }
SameLine(); SameLine();
if (ImGui::Button("Add")) { if (ImGui::Button("Add")) {
int breakpoint = std::stoi(breakpoint_input, nullptr, 16); int breakpoint = std::stoi(breakpoint_input, nullptr, 16);
snes_.cpu()->SetBreakpoint(breakpoint); snes_.cpu().SetBreakpoint(breakpoint);
memset(breakpoint_input, 0, sizeof(breakpoint_input)); memset(breakpoint_input, 0, sizeof(breakpoint_input));
} }
SameLine(); SameLine();
if (ImGui::Button("Clear")) { if (ImGui::Button("Clear")) {
snes_.cpu()->ClearBreakpoints(); snes_.cpu().ClearBreakpoints();
} }
Separator(); Separator();
auto breakpoints = snes_.cpu()->GetBreakpoints(); auto breakpoints = snes_.cpu().GetBreakpoints();
if (!breakpoints.empty()) { if (!breakpoints.empty()) {
Text("Breakpoints:"); Text("Breakpoints:");
ImGui::BeginChild("BreakpointsList", ImVec2(0, 100), true); ImGui::BeginChild("BreakpointsList", ImVec2(0, 100), true);
for (auto breakpoint : breakpoints) { for (auto breakpoint : breakpoints) {
if (ImGui::Selectable(absl::StrFormat("0x%04X", breakpoint).c_str())) { if (ImGui::Selectable(absl::StrFormat("0x%04X", breakpoint).c_str())) {
// Jump to breakpoint // Jump to breakpoint
// snes_.cpu()->JumpToBreakpoint(breakpoint); // snes_.cpu().JumpToBreakpoint(breakpoint);
} }
} }
ImGui::EndChild(); ImGui::EndChild();
@@ -287,8 +293,8 @@ void Emulator::RenderBreakpointList() {
gui::InputHexByte("PB", &manual_pb_, 50.f); gui::InputHexByte("PB", &manual_pb_, 50.f);
gui::InputHexWord("PC", &manual_pc_, 75.f); gui::InputHexWord("PC", &manual_pc_, 75.f);
if (ImGui::Button("Set Current Address")) { if (ImGui::Button("Set Current Address")) {
snes_.cpu()->PC = manual_pc_; snes_.cpu().PC = manual_pc_;
snes_.cpu()->PB = manual_pb_; snes_.cpu().PB = manual_pb_;
} }
} }
@@ -342,8 +348,8 @@ void Emulator::RenderMemoryViewer() {
} }
TableNextColumn(); TableNextColumn();
mem_edit.DrawContents((void*)snes_.Memory()->rom_.data(), mem_edit.DrawContents((void*)snes_.Memory().rom_.data(),
snes_.Memory()->rom_.size()); snes_.Memory().rom_.size());
ImGui::EndTable(); ImGui::EndTable();
} }

View File

@@ -56,13 +56,13 @@ class Emulator : public SharedRom {
} }
)"; )";
const std::map<std::string, void*> data_bindings = { const std::map<std::string, void*> data_bindings = {
{"cpu.A", &snes_.cpu()->A}, {"cpu.D", &snes_.cpu()->D}, {"cpu.A", &snes_.cpu().A}, {"cpu.D", &snes_.cpu().D},
{"cpu.X", &snes_.cpu()->X}, {"cpu.DB", &snes_.cpu()->DB}, {"cpu.X", &snes_.cpu().X}, {"cpu.DB", &snes_.cpu().DB},
{"cpu.Y", &snes_.cpu()->Y}, {"cpu.PB", &snes_.cpu()->PB}, {"cpu.Y", &snes_.cpu().Y}, {"cpu.PB", &snes_.cpu().PB},
{"cpu.PC", &snes_.cpu()->PC}, {"cpu.E", &snes_.cpu()->E}}; {"cpu.PC", &snes_.cpu().PC}, {"cpu.E", &snes_.cpu().E}};
emulator_node_ = gui::zeml::Parse(emulator_layout, data_bindings); emulator_node_ = gui::zeml::Parse(emulator_layout, data_bindings);
Bind(emulator_node_.GetNode("CpuInstructionLog"), 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("SnesPpu"), [&]() { RenderSnesPpu(); });
Bind(emulator_node_.GetNode("BreakpointList"), Bind(emulator_node_.GetNode("BreakpointList"),
[&]() { RenderBreakpointList(); }); [&]() { RenderBreakpointList(); });
@@ -72,6 +72,9 @@ class Emulator : public SharedRom {
auto snes() -> SNES& { return snes_; } auto snes() -> SNES& { return snes_; }
auto running() const -> bool { return running_; } auto running() const -> bool { return running_; }
void set_audio_buffer(int16_t* audio_buffer) { audio_buffer_ = audio_buffer; } 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_; } auto wanted_samples() const -> int { return wanted_samples_; }
private: private:
@@ -108,6 +111,7 @@ class Emulator : public SharedRom {
float timeAdder = 0.0; float timeAdder = 0.0;
int16_t* audio_buffer_; int16_t* audio_buffer_;
SDL_AudioDeviceID audio_device_;
SNES snes_; SNES snes_;
SDL_Texture* ppu_texture_; SDL_Texture* ppu_texture_;

View File

@@ -37,45 +37,6 @@ void SNES::Init(Rom& rom) {
// rom_info_ = memory_.ReadRomHeader(); // rom_info_ = memory_.ReadRomHeader();
Reset(true); 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; running_ = true;
} }
@@ -291,7 +252,7 @@ uint8_t SNES::ReadBBus(uint8_t adr) {
} }
if (adr < 0x80) { if (adr < 0x80) {
CatchUpApu(); // catch up the apu before reading CatchUpApu(); // catch up the apu before reading
return apu_.outPorts[adr & 0x3]; return apu_.out_ports_[adr & 0x3];
} }
if (adr == 0x80) { if (adr == 0x80) {
uint8_t ret = ram[ram_adr_++]; uint8_t ret = ram[ram_adr_++];
@@ -397,7 +358,7 @@ void SNES::WriteBBus(uint8_t adr, uint8_t val) {
} }
if (adr < 0x80) { if (adr < 0x80) {
CatchUpApu(); // catch up the apu before writing CatchUpApu(); // catch up the apu before writing
apu_.inPorts[adr & 0x3] = val; apu_.in_ports_[adr & 0x3] = val;
return; return;
} }
switch (adr) { switch (adr) {

View File

@@ -67,9 +67,9 @@ class SNES {
void SetPixels(uint8_t* pixel_data); void SetPixels(uint8_t* pixel_data);
bool running() const { return running_; } bool running() const { return running_; }
auto cpu() -> Cpu* { return &cpu_; } auto cpu() -> Cpu& { return cpu_; }
auto ppu() -> video::Ppu* { return &ppu_; } auto ppu() -> video::Ppu& { return ppu_; }
auto Memory() -> memory::MemoryImpl* { return &memory_; } auto Memory() -> memory::MemoryImpl& { return memory_; }
private: private:
// Components of the SNES // Components of the SNES
@@ -77,7 +77,6 @@ class SNES {
Debugger debugger; Debugger debugger;
memory::RomInfo rom_info_; memory::RomInfo rom_info_;
memory::MemoryImpl memory_; memory::MemoryImpl memory_;
audio::AudioRamImpl audio_ram_;
memory::CpuCallbacks cpu_callbacks_ = { memory::CpuCallbacks cpu_callbacks_ = {
[&](uint32_t adr) { return CpuRead(adr); }, [&](uint32_t adr) { return CpuRead(adr); },
@@ -86,7 +85,7 @@ class SNES {
}; };
Cpu cpu_{memory_, clock_, cpu_callbacks_}; Cpu cpu_{memory_, clock_, cpu_callbacks_};
video::Ppu ppu_{memory_, clock_}; video::Ppu ppu_{memory_, clock_};
audio::Apu apu_{memory_, audio_ram_, clock_}; audio::Apu apu_{memory_, clock_};
// Currently loaded ROM // Currently loaded ROM
std::vector<uint8_t> rom_data; std::vector<uint8_t> rom_data;