From c7e3cb5b35ddbea4f66ad3f29e95484cd3ff391c Mon Sep 17 00:00:00 2001 From: Rekai Musuka Date: Sun, 25 Jul 2021 18:19:27 -0500 Subject: [PATCH] fix(apu): abstract Apu read/write using BusIO trait --- src/apu.rs | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++---- src/bus.rs | 45 +++-------------------------------- 2 files changed, 68 insertions(+), 47 deletions(-) diff --git a/src/apu.rs b/src/apu.rs index 7347bce..f8b6ee7 100644 --- a/src/apu.rs +++ b/src/apu.rs @@ -19,15 +19,15 @@ const SAMPLE_INCREMENT: u64 = SAMPLE_RATE as u64; #[derive(Default, Debug, Clone)] pub struct Apu { - pub(crate) ctrl: SoundControl, + ctrl: SoundControl, /// Tone & Sweep - pub(crate) ch1: Channel1, + ch1: Channel1, /// Tone - pub(crate) ch2: Channel2, + ch2: Channel2, /// Wave - pub(crate) ch3: Channel3, + ch3: Channel3, /// Noise - pub(crate) ch4: Channel4, + ch4: Channel4, // Frame Sequencer frame_seq_state: FrameSequencerState, @@ -39,6 +39,66 @@ pub struct Apu { buffer: AudioBuffer<(f32, f32)>, } +impl BusIo for Apu { + fn read_byte(&self, addr: u16) -> u8 { + match addr & 0x00FF { + 0x11 => self.ch1.duty(), + 0x12 => self.ch1.envelope(), + 0x14 => self.ch1.freq_hi(), + 0x16 => self.ch2.duty(), + 0x17 => self.ch2.envelope(), + 0x19 => self.ch2.freq_hi(), + 0x1A => self.ch3.enabled(), + 0x1B => self.ch3.len(), + 0x1C => self.ch3.volume(), + 0x1E => self.ch3.freq_hi(), + 0x20 => self.ch4.len(), + 0x21 => self.ch4.envelope(), + 0x22 => self.ch4.poly(), + 0x23 => self.ch4.frequency(), + 0x24 => self.ctrl.channel(), + 0x25 => self.ctrl.output(), + 0x26 => self.ctrl.status(self), + 0x30..=0x3F => self.ch3.read_byte(addr), + _ => { + eprintln!("Read 0xFF from unused IO register {:#06X} [APU]", addr); + 0xFF + } + } + } + + fn write_byte(&mut self, addr: u16, byte: u8) { + match addr & 0x00FF { + 0x10 => self.ch1.set_sweep(byte), + 0x11 => self.ch1.set_duty(byte), + 0x12 => self.ch1.set_envelope(byte), + 0x13 => self.ch1.set_freq_lo(byte), + 0x14 => self.ch1.set_freq_hi(byte), + 0x16 => self.ch2.set_duty(byte), + 0x17 => self.ch2.set_envelope(byte), + 0x18 => self.ch2.set_freq_lo(byte), + 0x19 => self.ch2.set_freq_hi(byte), + 0x1A => self.ch3.set_enabled(byte), + 0x1B => self.ch3.set_len(byte), + 0x1C => self.ch3.set_volume(byte), + 0x1D => self.ch3.set_freq_lo(byte), + 0x1E => self.ch3.set_freq_hi(byte), + 0x20 => self.ch4.set_len(byte), + 0x21 => self.ch4.set_envelope(byte), + 0x22 => self.ch4.set_poly(byte), + 0x23 => self.ch4.set_freq_data(byte), + 0x24 => self.ctrl.set_channel(byte), + 0x25 => self.ctrl.set_output(byte), + 0x26 => self.set_status(byte), + 0x30..=0x3F => self.ch3.write_byte(addr, byte), + _ => eprintln!( + "Wrote {:#04X} to unused IO register {:#06X} [APU]", + byte, addr + ), + } + } +} + impl Apu { pub(crate) fn clock(&mut self, div: u16) { use FrameSequencerState::*; diff --git a/src/bus.rs b/src/bus.rs index 55715f3..ece6cd5 100644 --- a/src/bus.rs +++ b/src/bus.rs @@ -224,25 +224,7 @@ impl BusIo for Bus { 0x06 => self.timer.modulo, 0x07 => self.timer.ctrl.into(), 0x0F => self.interrupt_flag().into(), - 0x10 => self.apu.ch1.sweep(), - 0x11 => self.apu.ch1.duty(), - 0x12 => self.apu.ch1.envelope(), - 0x14 => self.apu.ch1.freq_hi(), - 0x16 => self.apu.ch2.duty(), - 0x17 => self.apu.ch2.envelope(), - 0x19 => self.apu.ch2.freq_hi(), - 0x1A => self.apu.ch3.enabled(), - 0x1B => self.apu.ch3.len(), - 0x1C => self.apu.ch3.volume(), - 0x1E => self.apu.ch3.freq_hi(), - 0x20 => self.apu.ch4.len(), - 0x21 => self.apu.ch4.envelope(), - 0x22 => self.apu.ch4.poly(), - 0x23 => self.apu.ch4.frequency(), - 0x24 => self.apu.ctrl.channel(), - 0x25 => self.apu.ctrl.output(), - 0x26 => self.apu.ctrl.status(&self.apu), - 0x30..=0x3F => self.apu.ch3.read_byte(addr), + 0x10..=0x3F => self.apu.read_byte(addr), 0x40 => self.ppu.ctrl.into(), 0x41 => self.ppu.stat.into(), 0x42 => self.ppu.pos.scroll_y, @@ -255,7 +237,7 @@ impl BusIo for Bus { 0x49 => self.ppu.monochrome.obj_palette_1.into(), 0x4A => self.ppu.pos.window_y, 0x4B => self.ppu.pos.window_x, - 0x4D => 0xFF, // CGB Specific Register + 0x4D => 0xFF, // TODO: CGB Specific Register _ => { eprintln!("Read 0xFF from unused IO register {:#06X}.", addr); 0xFF @@ -342,28 +324,7 @@ impl BusIo for Bus { 0x06 => self.timer.modulo = byte, 0x07 => self.timer.ctrl = byte.into(), 0x0F => self.set_interrupt_flag(byte), - 0x10 => self.apu.ch1.set_sweep(byte), - 0x11 => self.apu.ch1.set_duty(byte), - 0x12 => self.apu.ch1.set_envelope(byte), - 0x13 => self.apu.ch1.set_freq_lo(byte), - 0x14 => self.apu.ch1.set_freq_hi(byte), - 0x16 => self.apu.ch2.set_duty(byte), - 0x17 => self.apu.ch2.set_envelope(byte), - 0x18 => self.apu.ch2.set_freq_lo(byte), - 0x19 => self.apu.ch2.set_freq_hi(byte), - 0x1A => self.apu.ch3.set_enabled(byte), - 0x1B => self.apu.ch3.set_len(byte), - 0x1C => self.apu.ch3.set_volume(byte), - 0x1D => self.apu.ch3.set_freq_lo(byte), - 0x1E => self.apu.ch3.set_freq_hi(byte), - 0x20 => self.apu.ch4.set_len(byte), - 0x21 => self.apu.ch4.set_envelope(byte), - 0x22 => self.apu.ch4.set_poly(byte), - 0x23 => self.apu.ch4.set_freq_data(byte), - 0x24 => self.apu.ctrl.set_channel(byte), - 0x25 => self.apu.ctrl.set_output(byte), - 0x26 => self.apu.set_status(byte), - 0x30..=0x3F => self.apu.ch3.write_byte(addr, byte), + 0x10..=0x3F => self.apu.write_byte(addr, byte), 0x40 => self.ppu.ctrl = byte.into(), 0x41 => self.ppu.stat.update(byte), 0x42 => self.ppu.pos.scroll_y = byte,