fix(apu): implement write guards for Ch1 & Ch1 when disabled

This commit is contained in:
Rekai Nyangadzayi Musuka 2021-07-18 22:10:32 -05:00
parent f429d72882
commit 6f6c308d84
2 changed files with 93 additions and 45 deletions

View File

@ -275,11 +275,11 @@ impl SoundControl {
#[derive(Debug, Clone, Copy, Default)] #[derive(Debug, Clone, Copy, Default)]
pub(crate) struct Channel1 { pub(crate) struct Channel1 {
/// 0xFF10 | NR10 - Channel 1 Sweep Register /// 0xFF10 | NR10 - Channel 1 Sweep Register
pub(crate) sweep: Sweep, sweep: Sweep,
/// 0xFF11 | NR11 - Channel 1 Sound length / Wave pattern duty /// 0xFF11 | NR11 - Channel 1 Sound length / Wave pattern duty
duty: SoundDuty, duty: SoundDuty,
/// 0xFF12 | NR12 - Channel 1 Volume Envelope /// 0xFF12 | NR12 - Channel 1 Volume Envelope
pub(crate) envelope: VolumeEnvelope, envelope: VolumeEnvelope,
/// 0xFF13 | NR13 - Channel 1 Frequency low (lower 8 bits only) /// 0xFF13 | NR13 - Channel 1 Frequency low (lower 8 bits only)
freq_lo: u8, freq_lo: u8,
/// 0xFF14 | NR14 - Channel 1 Frequency high /// 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 /// 0xFF11 | NR11 - Channel 1 Sound length / Wave pattern duty
pub(crate) fn duty(&self) -> u8 { pub(crate) fn duty(&self) -> u8 {
u8::from(self.duty) & 0xC0 // Only bits 7 and 6 can be read u8::from(self.duty) & 0xC0 // Only bits 7 and 6 can be read
@ -329,14 +341,30 @@ impl Channel1 {
/// 0xFF11 | NR11 - Channel 1 Sound length / Wave pattern duty /// 0xFF11 | NR11 - Channel 1 Sound length / Wave pattern duty
pub(crate) fn set_duty(&mut self, byte: u8) { pub(crate) fn set_duty(&mut self, byte: u8) {
if self.enabled {
self.duty = byte.into(); self.duty = byte.into();
self.length_timer = 64 - self.duty.sound_length() as u16; 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) /// 0xFF13 | NR13 - Channel 1 Frequency low (lower 8 bits only)
pub(crate) fn set_freq_lo(&mut self, byte: u8) { pub(crate) fn set_freq_lo(&mut self, byte: u8) {
if self.enabled {
self.freq_lo = byte; self.freq_lo = byte;
} }
}
/// 0xFF14 | NR14 - Channel 1 Frequency high /// 0xFF14 | NR14 - Channel 1 Frequency high
pub(crate) fn freq_hi(&self) -> u8 { pub(crate) fn freq_hi(&self) -> u8 {
@ -345,6 +373,7 @@ impl Channel1 {
/// 0xFF14 | NR14 - Channel 1 Frequency high /// 0xFF14 | NR14 - Channel 1 Frequency high
pub(crate) fn set_freq_hi(&mut self, byte: u8) { pub(crate) fn set_freq_hi(&mut self, byte: u8) {
if self.enabled {
self.freq_hi = byte.into(); self.freq_hi = byte.into();
// If this bit is set, a trigger event occurs // If this bit is set, a trigger event occurs
@ -375,6 +404,7 @@ impl Channel1 {
} }
} }
} }
}
fn calc_sweep_freq(&mut self) -> u16 { fn calc_sweep_freq(&mut self) -> u16 {
use SweepDirection::*; use SweepDirection::*;
@ -410,7 +440,7 @@ pub(crate) struct Channel2 {
/// 0xFF16 | NR21 - Channel 2 Sound length / Wave Pattern Duty /// 0xFF16 | NR21 - Channel 2 Sound length / Wave Pattern Duty
duty: SoundDuty, duty: SoundDuty,
/// 0xFF17 | NR22 - Channel 2 Volume ENvelope /// 0xFF17 | NR22 - Channel 2 Volume ENvelope
pub(crate) envelope: VolumeEnvelope, envelope: VolumeEnvelope,
/// 0xFF18 | NR23 - Channel 2 Frequency low (lower 8 bits only) /// 0xFF18 | NR23 - Channel 2 Frequency low (lower 8 bits only)
freq_lo: u8, freq_lo: u8,
/// 0xFF19 | NR24 - Channel 2 Frequency high /// 0xFF19 | NR24 - Channel 2 Frequency high
@ -455,14 +485,30 @@ impl Channel2 {
/// 0xFF16 | NR21 - Channel 2 Sound length / Wave Pattern Duty /// 0xFF16 | NR21 - Channel 2 Sound length / Wave Pattern Duty
pub(crate) fn set_duty(&mut self, byte: u8) { pub(crate) fn set_duty(&mut self, byte: u8) {
if self.enabled {
self.duty = byte.into(); self.duty = byte.into();
self.length_timer = 64 - self.duty.sound_length() as u16; 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) /// 0xFF18 | NR23 - Channel 2 Frequency low (lower 8 bits only)
pub(crate) fn set_freq_lo(&mut self, byte: u8) { pub(crate) fn set_freq_lo(&mut self, byte: u8) {
if self.enabled {
self.freq_lo = byte; self.freq_lo = byte;
} }
}
/// 0xFF19 | NR24 - Channel 2 Frequency high /// 0xFF19 | NR24 - Channel 2 Frequency high
pub(crate) fn freq_hi(&self) -> u8 { pub(crate) fn freq_hi(&self) -> u8 {
@ -471,6 +517,7 @@ impl Channel2 {
/// 0xFF19 | NR24 - Channel 2 Frequency high /// 0xFF19 | NR24 - Channel 2 Frequency high
pub(crate) fn set_freq_hi(&mut self, byte: u8) { pub(crate) fn set_freq_hi(&mut self, byte: u8) {
if self.enabled {
self.freq_hi = byte.into(); self.freq_hi = byte.into();
if self.freq_hi.initial() { if self.freq_hi.initial() {
@ -484,6 +531,7 @@ impl Channel2 {
} }
} }
} }
}
fn frequency(&self) -> u16 { fn frequency(&self) -> u16 {
(self.freq_hi.freq_bits() as u16) << 8 | self.freq_lo as u16 (self.freq_hi.freq_bits() as u16) << 8 | self.freq_lo as u16

View File

@ -224,12 +224,12 @@ impl BusIo for Bus {
0x06 => self.timer.modulo, 0x06 => self.timer.modulo,
0x07 => self.timer.ctrl.into(), 0x07 => self.timer.ctrl.into(),
0x0F => self.interrupt_flag().into(), 0x0F => self.interrupt_flag().into(),
0x10 => self.apu.ch1.sweep.into(), 0x10 => self.apu.ch1.sweep(),
0x11 => self.apu.ch1.duty(), 0x11 => self.apu.ch1.duty(),
0x12 => self.apu.ch1.envelope.into(), 0x12 => self.apu.ch1.envelope(),
0x14 => self.apu.ch1.freq_hi(), 0x14 => self.apu.ch1.freq_hi(),
0x16 => self.apu.ch2.duty(), 0x16 => self.apu.ch2.duty(),
0x17 => self.apu.ch2.envelope.into(), 0x17 => self.apu.ch2.envelope(),
0x19 => self.apu.ch2.freq_hi(), 0x19 => self.apu.ch2.freq_hi(),
0x1A => self.apu.ch3.enabled(), 0x1A => self.apu.ch3.enabled(),
0x1B => self.apu.ch3.len(), 0x1B => self.apu.ch3.len(),
@ -342,13 +342,13 @@ impl BusIo for Bus {
0x06 => self.timer.modulo = byte, 0x06 => self.timer.modulo = byte,
0x07 => self.timer.ctrl = byte.into(), 0x07 => self.timer.ctrl = byte.into(),
0x0F => self.set_interrupt_flag(byte), 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), 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), 0x13 => self.apu.ch1.set_freq_lo(byte),
0x14 => self.apu.ch1.set_freq_hi(byte), 0x14 => self.apu.ch1.set_freq_hi(byte),
0x16 => self.apu.ch2.set_duty(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), 0x18 => self.apu.ch2.set_freq_lo(byte),
0x19 => self.apu.ch2.set_freq_hi(byte), 0x19 => self.apu.ch2.set_freq_hi(byte),
0x1A => self.apu.ch3.set_enabled(byte), 0x1A => self.apu.ch3.set_enabled(byte),