From 7ae685d390ca755c5b6af3e7bfa6d590b18c871a Mon Sep 17 00:00:00 2001 From: good <2020679950@qq.com> Date: Sat, 12 Jun 2021 16:41:48 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BA=86=E5=A3=B0=E9=9F=B3?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NES/Simple_Apu.cpp | 44 +++++++++++++++----------------------------- NES/Simple_Apu.h | 19 +++++++++++-------- NES/bus.cpp | 6 ++---- NES/mainwindow.cpp | 15 ++++++++++----- 4 files changed, 38 insertions(+), 46 deletions(-) diff --git a/NES/Simple_Apu.cpp b/NES/Simple_Apu.cpp index ded9046..d04c89c 100644 --- a/NES/Simple_Apu.cpp +++ b/NES/Simple_Apu.cpp @@ -21,27 +21,15 @@ static int null_dmc_reader(void*, cpu_addr_t) Simple_Apu::Simple_Apu() { - memset(out_buf, 0, sizeof(blip_sample_t) * 2048); - out_count = 0; - apu.dmc_reader(null_dmc_reader, NULL); - if (sample_rate(44100)) - abort(); + time = 0; + frame_length = 29780; + apu.dmc_reader( null_dmc_reader, NULL ); } Simple_Apu::~Simple_Apu() { } -void Simple_Apu::reset() -{ - memset(out_buf, 0, sizeof(blip_sample_t) * 2048); - out_count = 0; - apu.reset(); - buf.clear(); - if (sample_rate(44100)) - abort(); -} - void Simple_Apu::dmc_reader(int (*f)(void* user_data, cpu_addr_t), void* p) { assert(f); @@ -55,24 +43,14 @@ blargg_err_t Simple_Apu::sample_rate(long rate) return buf.sample_rate(rate); } -void Simple_Apu::write_register(int frame_length, cpu_addr_t addr, int data) -{ - apu.write_register(frame_length, addr, data); -} - -int Simple_Apu::read_status(int frame_length) +void Simple_Apu::write_register(cpu_addr_t addr, int data) { - return apu.read_status(frame_length); + apu.write_register(clock(), addr, data); } -void Simple_Apu::clock(int frame_length) +int Simple_Apu::read_status() { - apu.end_frame(frame_length); - buf.end_frame(frame_length); - - if (buf.samples_avail() >= 2048) { - out_count = buf.read_samples(out_buf, 2048); - } + return apu.read_status(clock()); } long Simple_Apu::samples_avail() const @@ -94,3 +72,11 @@ void Simple_Apu::load_snapshot(apu_snapshot_t const& in) { apu.load_snapshot(in); } + +void Simple_Apu::end_frame() +{ + time = 0; + frame_length ^= 1; + apu.end_frame( frame_length ); + buf.end_frame( frame_length ); +} diff --git a/NES/Simple_Apu.h b/NES/Simple_Apu.h index ca55577..7407d01 100644 --- a/NES/Simple_Apu.h +++ b/NES/Simple_Apu.h @@ -8,13 +8,13 @@ #include "nes_apu/Nes_Apu.h" #include "nes_apu/Blip_Buffer.h" +#define SAMPLE_RATE 8000 + class Simple_Apu { public: Simple_Apu(); ~Simple_Apu(); - void reset(); - // This simpler interface works well for most games. Some benefit from // the higher precision of the full Nes_Apu interface, which provides // clock-cycle accurate register read/write and IRQ timing functions. @@ -26,13 +26,10 @@ public: blargg_err_t sample_rate(long rate); // Write to register (0x4000-0x4017, except 0x4014 and 0x4016) - void write_register(int frame_length, cpu_addr_t, int data); + void write_register(cpu_addr_t, int data); // Read from status register at 0x4015 - int read_status(int frame_length); - - // End a 1/60 sound frame - void clock(int frame_length); + int read_status(); // Number of samples in buffer long samples_avail() const; @@ -45,13 +42,19 @@ public: void save_snapshot(apu_snapshot_t* out) const; void load_snapshot(apu_snapshot_t const&); + // End a 1/60 sound frame + void end_frame(); + public: - blip_sample_t out_buf[2048]; + blip_sample_t out_buf[SAMPLE_RATE]; size_t out_count; private: Nes_Apu apu; Blip_Buffer buf; + blip_time_t time; + blip_time_t frame_length; + blip_time_t clock() { return time += 4; } }; #endif diff --git a/NES/bus.cpp b/NES/bus.cpp index 3fb60c0..bae4d3b 100644 --- a/NES/bus.cpp +++ b/NES/bus.cpp @@ -17,13 +17,11 @@ void Bus::reset() clock_count = 0; Cpu.reset(); Ppu.reset(); - Apu.reset(); } void Bus::clock() { Ppu.clock(); - Apu.clock(Cpu.cycles_wait); if (clock_count % 3 == 0) { if (dma_transfer) { @@ -100,7 +98,7 @@ void Bus::save(uint16_t addr, uint8_t data) } } else if ((addr >= 0x4000 && addr <= 0x4013) || addr == 0x4015 || addr == 0x4017) { // APU write - Apu.write_register(Cpu.cycles_wait, addr, data); + Apu.write_register(addr, data); } else if (addr == 0x4014) { // OAM DMA dma_page = data; @@ -150,7 +148,7 @@ uint8_t Bus::load(uint16_t addr) } } else if (addr == 0x4015) { // APU Status - return Apu.read_status(Cpu.cycles_wait); + return Apu.read_status(); } else if (addr == 0x4016) { // controller 1 key state return controller_left.output_key_states(); diff --git a/NES/mainwindow.cpp b/NES/mainwindow.cpp index 7ff9f24..5c2f813 100644 --- a/NES/mainwindow.cpp +++ b/NES/mainwindow.cpp @@ -60,7 +60,7 @@ void MainWindow::InitAudio() delete m_audioOutput; QAudioFormat format; - format.setSampleRate(44100); + format.setSampleRate(SAMPLE_RATE); format.setChannelCount(1); format.setSampleSize(16); format.setCodec("audio/pcm"); @@ -78,6 +78,8 @@ void MainWindow::InitAudio() QAudio::LinearVolumeScale); m_audioOutput->setVolume(linearVolume); qAudioDevice = m_audioOutput->start(); + + Nes.Apu.sample_rate(SAMPLE_RATE); } void MainWindow::FCInit() @@ -150,13 +152,16 @@ void MainWindow::OnNewFrame() { do { Nes.clock(); - if (OpenSound && Nes.Apu.out_count > 0) { - char *buf_ptr = (char *) Nes.Apu.out_buf; - qAudioDevice->write(buf_ptr, Nes.Apu.out_count * 2); - } } while (!Nes.Ppu.frame_complete); Nes.Ppu.frame_complete = false; + Nes.Apu.end_frame(); + if(OpenSound) { + Nes.Apu.out_count = Nes.Apu.read_samples(Nes.Apu.out_buf, SAMPLE_RATE); + char *buf_ptr = (char *) Nes.Apu.out_buf; + qAudioDevice->write(buf_ptr, Nes.Apu.out_count * 2); + } + scene_game->clear(); for (int x = 0; x < 256; x++) { -- Gitee