diff --git a/src/processor/memory/mmio/apu.rs b/src/processor/memory/mmio/apu.rs index 15bb435..0001038 100644 --- a/src/processor/memory/mmio/apu.rs +++ b/src/processor/memory/mmio/apu.rs @@ -251,10 +251,10 @@ impl Apu { } else { 0b01111111 }; - v = set_or_clear_bit(v, 0, self.channels.one.enabled); - v = set_or_clear_bit(v, 1, self.channels.two.enabled); - v = set_or_clear_bit(v, 2, self.channels.three.enabled); - v = set_or_clear_bit(v, 3, self.channels.four.enabled); + v = set_or_clear_bit(v, 0, self.channels.one.is_dac_enabled()); + v = set_or_clear_bit(v, 1, self.channels.two.is_dac_enabled()); + v = set_or_clear_bit(v, 2, self.channels.three.is_dac_enabled()); + v = set_or_clear_bit(v, 3, self.channels.four.is_dac_enabled()); v } // write-only registers @@ -303,7 +303,17 @@ impl Apu { self.mixer.ch3.left = Volume::from_bool(get_bit(data, 6)); self.mixer.ch4.left = Volume::from_bool(get_bit(data, 7)); } - 0xFF26 => self.apu_enable = (1 << 7) == (data & 0b10000000), + 0xFF26 => { + if !self.apu_enable { + for i in 0xFF10..0xFF20 { + self.mmio_write(i, 0x0); + } + for i in 0xFF21..0xFF25 { + self.mmio_write(i, 0x0); + } + } + self.apu_enable = (1 << 7) == (data & 0b10000000); + } 0xFF30..0xFF40 => self.channels.three.update_wave_ram(addr, data), 0xFF15 | 0xFF1F | 0xFF27..0xFF30 => {} 0x0..0xFF10 | 0xFF40..=0xFFFF => panic!("non-apu addr in apu"), diff --git a/src/processor/memory/mmio/apu/channels.rs b/src/processor/memory/mmio/apu/channels.rs index 27c279c..301ce0d 100644 --- a/src/processor/memory/mmio/apu/channels.rs +++ b/src/processor/memory/mmio/apu/channels.rs @@ -146,8 +146,15 @@ impl PwmChannel { } fn trigger(&mut self) { - self.enabled = true; + if self.get_volume_and_envelope() & 0xF8 != 0 { + self.enabled = true; + } self.envelope = self.queued_envelope; + self.set_wave_timer(); + self.wave_position = 0; + if self.length_timer >= 64 { + self.length_timer = 0; + } } pub fn tick(&mut self, steps: usize) -> Vec { @@ -199,7 +206,7 @@ impl PwmChannel { } pub(super) fn length_tick(&mut self) { - if self.length_enable && self.enabled { + if self.length_enable { self.length_timer += 1; if self.length_timer >= 64 { self.enabled = false; @@ -244,6 +251,9 @@ impl PwmChannel { }, data & 0b111, ); + if data & 0b11111000 == 0 { + self.enabled = false; + } } pub(super) fn get_volume_and_envelope(&self) -> u8 { @@ -276,6 +286,10 @@ impl PwmChannel { fn set_wave_timer(&mut self) { self.wave_timer = (2048 - self.wavelength) * 4; } + + pub(super) fn is_dac_enabled(&self) -> bool { + self.enabled + } } #[derive(Debug, PartialEq)] @@ -329,7 +343,7 @@ impl WaveChannel { enabled, dac_enabled: false, length_enable: false, - length_timer: 0xFF, + length_timer: 0, volume: ShiftVolumePercent::Zero, wavelength, wave_timer: (2048 - wavelength) * 2, @@ -339,7 +353,14 @@ impl WaveChannel { } fn trigger(&mut self) { - self.enabled = true; + if self.dac_enabled { + self.enabled = true; + }; + self.set_wave_timer(); + self.wave_position = 0; + if self.length_timer == 0xFF { + self.length_timer = 0; + } } pub fn tick(&mut self, steps: usize) -> Vec { @@ -369,9 +390,10 @@ impl WaveChannel { } pub(super) fn length_tick(&mut self) { - if self.length_enable && self.enabled { - self.length_timer = self.length_timer.saturating_add(1); - if self.length_timer == 0xFF { + if self.length_enable { + let (new, overflow) = self.length_timer.overflowing_add(1); + self.length_timer = new; + if overflow { self.enabled = false; } } @@ -437,6 +459,10 @@ impl WaveChannel { fn set_wave_timer(&mut self) { self.wave_timer = (2048 - self.wavelength) * 2; } + + pub(super) fn is_dac_enabled(&self) -> bool { + self.dac_enabled && self.enabled + } } #[derive(PartialEq)] @@ -524,9 +550,12 @@ impl NoiseChannel { } fn trigger(&mut self) { - self.enabled = true; + // self.enabled = true; self.envelope = self.queued_envelope; self.lfsr.register = 0; + if self.length_timer >= 64 { + self.length_timer = 0; + } } pub fn tick(&mut self, steps: usize) -> Vec { @@ -553,7 +582,7 @@ impl NoiseChannel { } pub(super) fn length_tick(&mut self) { - if self.length_enable && self.enabled { + if self.length_enable { self.length_timer += 1; if self.length_timer >= 64 { self.enabled = false; @@ -575,6 +604,9 @@ impl NoiseChannel { }, data & 0b111, ); + if data & 0b11111000 == 0 { + self.enabled = false; + } } pub(super) fn get_volume_and_envelope(&self) -> u8 { @@ -615,4 +647,8 @@ impl NoiseChannel { pub(super) fn get_control(&self) -> u8 { set_or_clear_bit(0xFF, 6, self.length_enable) } + + pub(super) fn is_dac_enabled(&self) -> bool { + self.get_volume_and_envelope() & 0xF8 == 0 && self.enabled + } }