many apu improvements

This commit is contained in:
Alex Janka 2023-02-28 09:58:01 +11:00
parent 0c0c42e8ba
commit 80d58ba497
2 changed files with 60 additions and 14 deletions

View file

@ -251,10 +251,10 @@ impl Apu {
} else { } else {
0b01111111 0b01111111
}; };
v = set_or_clear_bit(v, 0, self.channels.one.enabled); v = set_or_clear_bit(v, 0, self.channels.one.is_dac_enabled());
v = set_or_clear_bit(v, 1, self.channels.two.enabled); v = set_or_clear_bit(v, 1, self.channels.two.is_dac_enabled());
v = set_or_clear_bit(v, 2, self.channels.three.enabled); v = set_or_clear_bit(v, 2, self.channels.three.is_dac_enabled());
v = set_or_clear_bit(v, 3, self.channels.four.enabled); v = set_or_clear_bit(v, 3, self.channels.four.is_dac_enabled());
v v
} }
// write-only registers // write-only registers
@ -303,7 +303,17 @@ impl Apu {
self.mixer.ch3.left = Volume::from_bool(get_bit(data, 6)); self.mixer.ch3.left = Volume::from_bool(get_bit(data, 6));
self.mixer.ch4.left = Volume::from_bool(get_bit(data, 7)); 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), 0xFF30..0xFF40 => self.channels.three.update_wave_ram(addr, data),
0xFF15 | 0xFF1F | 0xFF27..0xFF30 => {} 0xFF15 | 0xFF1F | 0xFF27..0xFF30 => {}
0x0..0xFF10 | 0xFF40..=0xFFFF => panic!("non-apu addr in apu"), 0x0..0xFF10 | 0xFF40..=0xFFFF => panic!("non-apu addr in apu"),

View file

@ -146,8 +146,15 @@ impl PwmChannel {
} }
fn trigger(&mut self) { fn trigger(&mut self) {
self.enabled = true; if self.get_volume_and_envelope() & 0xF8 != 0 {
self.enabled = true;
}
self.envelope = self.queued_envelope; 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<f32> { pub fn tick(&mut self, steps: usize) -> Vec<f32> {
@ -199,7 +206,7 @@ impl PwmChannel {
} }
pub(super) fn length_tick(&mut self) { pub(super) fn length_tick(&mut self) {
if self.length_enable && self.enabled { if self.length_enable {
self.length_timer += 1; self.length_timer += 1;
if self.length_timer >= 64 { if self.length_timer >= 64 {
self.enabled = false; self.enabled = false;
@ -244,6 +251,9 @@ impl PwmChannel {
}, },
data & 0b111, data & 0b111,
); );
if data & 0b11111000 == 0 {
self.enabled = false;
}
} }
pub(super) fn get_volume_and_envelope(&self) -> u8 { pub(super) fn get_volume_and_envelope(&self) -> u8 {
@ -276,6 +286,10 @@ impl PwmChannel {
fn set_wave_timer(&mut self) { fn set_wave_timer(&mut self) {
self.wave_timer = (2048 - self.wavelength) * 4; self.wave_timer = (2048 - self.wavelength) * 4;
} }
pub(super) fn is_dac_enabled(&self) -> bool {
self.enabled
}
} }
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
@ -329,7 +343,7 @@ impl WaveChannel {
enabled, enabled,
dac_enabled: false, dac_enabled: false,
length_enable: false, length_enable: false,
length_timer: 0xFF, length_timer: 0,
volume: ShiftVolumePercent::Zero, volume: ShiftVolumePercent::Zero,
wavelength, wavelength,
wave_timer: (2048 - wavelength) * 2, wave_timer: (2048 - wavelength) * 2,
@ -339,7 +353,14 @@ impl WaveChannel {
} }
fn trigger(&mut self) { 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<f32> { pub fn tick(&mut self, steps: usize) -> Vec<f32> {
@ -369,9 +390,10 @@ impl WaveChannel {
} }
pub(super) fn length_tick(&mut self) { pub(super) fn length_tick(&mut self) {
if self.length_enable && self.enabled { if self.length_enable {
self.length_timer = self.length_timer.saturating_add(1); let (new, overflow) = self.length_timer.overflowing_add(1);
if self.length_timer == 0xFF { self.length_timer = new;
if overflow {
self.enabled = false; self.enabled = false;
} }
} }
@ -437,6 +459,10 @@ impl WaveChannel {
fn set_wave_timer(&mut self) { fn set_wave_timer(&mut self) {
self.wave_timer = (2048 - self.wavelength) * 2; self.wave_timer = (2048 - self.wavelength) * 2;
} }
pub(super) fn is_dac_enabled(&self) -> bool {
self.dac_enabled && self.enabled
}
} }
#[derive(PartialEq)] #[derive(PartialEq)]
@ -524,9 +550,12 @@ impl NoiseChannel {
} }
fn trigger(&mut self) { fn trigger(&mut self) {
self.enabled = true; // self.enabled = true;
self.envelope = self.queued_envelope; self.envelope = self.queued_envelope;
self.lfsr.register = 0; self.lfsr.register = 0;
if self.length_timer >= 64 {
self.length_timer = 0;
}
} }
pub fn tick(&mut self, steps: usize) -> Vec<f32> { pub fn tick(&mut self, steps: usize) -> Vec<f32> {
@ -553,7 +582,7 @@ impl NoiseChannel {
} }
pub(super) fn length_tick(&mut self) { pub(super) fn length_tick(&mut self) {
if self.length_enable && self.enabled { if self.length_enable {
self.length_timer += 1; self.length_timer += 1;
if self.length_timer >= 64 { if self.length_timer >= 64 {
self.enabled = false; self.enabled = false;
@ -575,6 +604,9 @@ impl NoiseChannel {
}, },
data & 0b111, data & 0b111,
); );
if data & 0b11111000 == 0 {
self.enabled = false;
}
} }
pub(super) fn get_volume_and_envelope(&self) -> u8 { pub(super) fn get_volume_and_envelope(&self) -> u8 {
@ -615,4 +647,8 @@ impl NoiseChannel {
pub(super) fn get_control(&self) -> u8 { pub(super) fn get_control(&self) -> u8 {
set_or_clear_bit(0xFF, 6, self.length_enable) 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
}
} }