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 {
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"),

View file

@ -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<f32> {
@ -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<f32> {
@ -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<f32> {
@ -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
}
}