From 6f6c308d84bfd88bc8925e6300972e835e18dc54 Mon Sep 17 00:00:00 2001 From: Rekai Musuka Date: Sun, 18 Jul 2021 22:10:32 -0500 Subject: [PATCH] fix(apu): implement write guards for Ch1 & Ch1 when disabled --- src/apu.rs | 126 ++++++++++++++++++++++++++++++++++++----------------- src/bus.rs | 12 ++--- 2 files changed, 93 insertions(+), 45 deletions(-) diff --git a/src/apu.rs b/src/apu.rs index 093f204..5c2bb53 100644 --- a/src/apu.rs +++ b/src/apu.rs @@ -275,11 +275,11 @@ impl SoundControl { #[derive(Debug, Clone, Copy, Default)] pub(crate) struct Channel1 { /// 0xFF10 | NR10 - Channel 1 Sweep Register - pub(crate) sweep: Sweep, + sweep: Sweep, /// 0xFF11 | NR11 - Channel 1 Sound length / Wave pattern duty duty: SoundDuty, /// 0xFF12 | NR12 - Channel 1 Volume Envelope - pub(crate) envelope: VolumeEnvelope, + envelope: VolumeEnvelope, /// 0xFF13 | NR13 - Channel 1 Frequency low (lower 8 bits only) freq_lo: u8, /// 0xFF14 | NR14 - Channel 1 Frequency high @@ -322,6 +322,18 @@ impl Channel1 { } } + /// 0xFF10 | NR10 - Channel 1 Sweep Register + pub(crate) fn sweep(&self) -> u8 { + self.sweep.into() + } + + /// 0xFF10 | NR10 - Channel 1 Sweep Register + pub(crate) fn set_sweep(&mut self, byte: u8) { + if self.enabled { + self.sweep = byte.into() + } + } + /// 0xFF11 | NR11 - Channel 1 Sound length / Wave pattern duty pub(crate) fn duty(&self) -> u8 { u8::from(self.duty) & 0xC0 // Only bits 7 and 6 can be read @@ -329,13 +341,29 @@ impl Channel1 { /// 0xFF11 | NR11 - Channel 1 Sound length / Wave pattern duty pub(crate) fn set_duty(&mut self, byte: u8) { - self.duty = byte.into(); - self.length_timer = 64 - self.duty.sound_length() as u16; + if self.enabled { + self.duty = byte.into(); + self.length_timer = 64 - self.duty.sound_length() as u16; + } + } + + /// 0xFF12 | NR12 - Channel 1 Volume Envelope + pub fn envelope(&self) -> u8 { + self.envelope.into() + } + + /// 0xFF12 | NR12 - Channel 1 Volume Envelope + pub(crate) fn set_envelope(&mut self, byte: u8) { + if self.enabled { + self.envelope = byte.into() + } } /// 0xFF13 | NR13 - Channel 1 Frequency low (lower 8 bits only) pub(crate) fn set_freq_lo(&mut self, byte: u8) { - self.freq_lo = byte; + if self.enabled { + self.freq_lo = byte; + } } /// 0xFF14 | NR14 - Channel 1 Frequency high @@ -345,33 +373,35 @@ impl Channel1 { /// 0xFF14 | NR14 - Channel 1 Frequency high pub(crate) fn set_freq_hi(&mut self, byte: u8) { - self.freq_hi = byte.into(); + if self.enabled { + self.freq_hi = byte.into(); - // If this bit is set, a trigger event occurs - if self.freq_hi.initial() { - // Envelope Behaviour during trigger event - self.period_timer = self.envelope.period(); - self.current_volume = self.envelope.init_vol(); + // If this bit is set, a trigger event occurs + if self.freq_hi.initial() { + // Envelope Behaviour during trigger event + self.period_timer = self.envelope.period(); + self.current_volume = self.envelope.init_vol(); - // Sweep behaviour during trigger event - self.shadow_freq = self.frequency() & 0x07FF; // Mask should be redundant - self.sweep_timer = if self.sweep.period() != 0 { - self.sweep.period() - } else { - 8 - }; + // Sweep behaviour during trigger event + self.shadow_freq = self.frequency() & 0x07FF; // Mask should be redundant + self.sweep_timer = if self.sweep.period() != 0 { + self.sweep.period() + } else { + 8 + }; - if self.sweep.period() != 0 || self.sweep.shift_count() != 0 { - self.sweep_enabled = true; - } + if self.sweep.period() != 0 || self.sweep.shift_count() != 0 { + self.sweep_enabled = true; + } - if self.sweep.shift_count() != 0 { - let _ = self.calc_sweep_freq(); - } + if self.sweep.shift_count() != 0 { + let _ = self.calc_sweep_freq(); + } - // Length behaviour during trigger event - if self.length_timer == 0 { - self.length_timer = 64; + // Length behaviour during trigger event + if self.length_timer == 0 { + self.length_timer = 64; + } } } } @@ -410,7 +440,7 @@ pub(crate) struct Channel2 { /// 0xFF16 | NR21 - Channel 2 Sound length / Wave Pattern Duty duty: SoundDuty, /// 0xFF17 | NR22 - Channel 2 Volume ENvelope - pub(crate) envelope: VolumeEnvelope, + envelope: VolumeEnvelope, /// 0xFF18 | NR23 - Channel 2 Frequency low (lower 8 bits only) freq_lo: u8, /// 0xFF19 | NR24 - Channel 2 Frequency high @@ -455,13 +485,29 @@ impl Channel2 { /// 0xFF16 | NR21 - Channel 2 Sound length / Wave Pattern Duty pub(crate) fn set_duty(&mut self, byte: u8) { - self.duty = byte.into(); - self.length_timer = 64 - self.duty.sound_length() as u16; + if self.enabled { + self.duty = byte.into(); + self.length_timer = 64 - self.duty.sound_length() as u16; + } + } + + /// 0xFF17 | NR22 - Channel 2 Volume ENvelope + pub(crate) fn envelope(&self) -> u8 { + self.envelope.into() + } + + /// 0xFF17 | NR22 - Channel 2 Volume ENvelope + pub(crate) fn set_envelope(&mut self, byte: u8) { + if self.enabled { + self.envelope = byte.into() + } } /// 0xFF18 | NR23 - Channel 2 Frequency low (lower 8 bits only) pub(crate) fn set_freq_lo(&mut self, byte: u8) { - self.freq_lo = byte; + if self.enabled { + self.freq_lo = byte; + } } /// 0xFF19 | NR24 - Channel 2 Frequency high @@ -471,16 +517,18 @@ impl Channel2 { /// 0xFF19 | NR24 - Channel 2 Frequency high pub(crate) fn set_freq_hi(&mut self, byte: u8) { - self.freq_hi = byte.into(); + if self.enabled { + self.freq_hi = byte.into(); - if self.freq_hi.initial() { - // Envelope behaviour during trigger event - self.period_timer = self.envelope.period(); - self.current_volume = self.envelope.init_vol(); + if self.freq_hi.initial() { + // Envelope behaviour during trigger event + self.period_timer = self.envelope.period(); + self.current_volume = self.envelope.init_vol(); - // Length behaviour during trigger event - if self.length_timer == 0 { - self.length_timer = 64; + // Length behaviour during trigger event + if self.length_timer == 0 { + self.length_timer = 64; + } } } } diff --git a/src/bus.rs b/src/bus.rs index b8d8837..80c3f4a 100644 --- a/src/bus.rs +++ b/src/bus.rs @@ -224,12 +224,12 @@ impl BusIo for Bus { 0x06 => self.timer.modulo, 0x07 => self.timer.ctrl.into(), 0x0F => self.interrupt_flag().into(), - 0x10 => self.apu.ch1.sweep.into(), + 0x10 => self.apu.ch1.sweep(), 0x11 => self.apu.ch1.duty(), - 0x12 => self.apu.ch1.envelope.into(), + 0x12 => self.apu.ch1.envelope(), 0x14 => self.apu.ch1.freq_hi(), 0x16 => self.apu.ch2.duty(), - 0x17 => self.apu.ch2.envelope.into(), + 0x17 => self.apu.ch2.envelope(), 0x19 => self.apu.ch2.freq_hi(), 0x1A => self.apu.ch3.enabled(), 0x1B => self.apu.ch3.len(), @@ -342,13 +342,13 @@ 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.sweep = byte.into(), + 0x10 => self.apu.ch1.set_sweep(byte), 0x11 => self.apu.ch1.set_duty(byte), - 0x12 => self.apu.ch1.envelope = byte.into(), + 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.envelope = byte.into(), + 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),