From 9f9cd006c080deca6d855034f531d68e162a8edb Mon Sep 17 00:00:00 2001 From: Alex Janka Date: Mon, 20 Feb 2023 14:30:35 +1100 Subject: [PATCH] channel 4 mem interface + ditch apu ram array --- src/processor/memory/mmio/apu.rs | 35 +++------ src/processor/memory/mmio/apu/channels.rs | 95 ++++++++++++++++++++++- 2 files changed, 104 insertions(+), 26 deletions(-) diff --git a/src/processor/memory/mmio/apu.rs b/src/processor/memory/mmio/apu.rs index ba5b54f..aa4f892 100644 --- a/src/processor/memory/mmio/apu.rs +++ b/src/processor/memory/mmio/apu.rs @@ -1,10 +1,6 @@ use self::types::{Channels, DacSample, Mixer, VinEnable, Volume}; use crate::{ - processor::{ - memory::{masked_update, Address}, - timer::CLOCK_SPEED, - Cpu, - }, + processor::{memory::Address, timer::CLOCK_SPEED, Cpu}, util::{get_bit, set_or_clear_bit}, }; use async_ringbuf::{AsyncHeapProducer, AsyncHeapRb}; @@ -19,13 +15,6 @@ use samplerate::{ConverterType, Samplerate}; mod channels; mod types; -const MEM_START: usize = 0xFF10; -const MEM_SIZE: usize = 0xFF40 - MEM_START; - -const fn reg(a: Address) -> usize { - (a as usize) - MEM_START -} - impl DacSample { fn mixed(&self, mixer: &Mixer) -> Vec { let left = (self.one * mixer.ch1.left.scale()) @@ -46,7 +35,6 @@ impl DacSample { } pub struct Apu { - mem: [u8; MEM_SIZE], apu_enable: bool, channels: Channels, vin: VinEnable, @@ -87,7 +75,6 @@ impl Default for Apu { let config = config.config(); Self { - mem: [0x0; MEM_SIZE], apu_enable: true, channels: Channels::default(), vin: VinEnable::default(), @@ -196,7 +183,7 @@ impl Apu { || addr == 0xFF16 || addr == 0xFF1B || addr == 0xFF20 - || get_bit(self.mem[reg(0xFF26)], 7) + || self.apu_enable { self.make_register(addr) } else { @@ -216,6 +203,9 @@ impl Apu { 0xFF1A => self.channels.three.get_dac(), 0xFF1C => self.channels.three.get_volume(), 0xFF1E => self.channels.three.get_control(), + 0xFF21 => self.channels.four.get_volume_and_envelope(), + 0xFF22 => self.channels.four.get_frequency_and_randomness(), + 0xFF23 => self.channels.four.get_control(), 0xFF24 => { // NR50 - Master volume + VIN panning let mut v = @@ -253,7 +243,6 @@ impl Apu { // wave ram 0xFF30..0xFF40 => 0xFF, 0x0..0xFF10 | 0xFF40..=0xFFFF => panic!("non-apu addr in apu"), - _ => self.mem[reg(addr)], } } @@ -273,10 +262,10 @@ impl Apu { 0xFF1C => self.channels.three.update_volume(data), 0xFF1D => self.channels.three.update_wavelength_low(data), 0xFF1E => self.channels.three.update_wavelength_high_and_control(data), - 0xFF20 => self.masked_io(reg(addr), data, 0b111111), - 0xFF23 => { - self.mem[reg(addr)] = (self.mem[reg(addr)] & 0b10111111) | (data & 0b01000000) - } + 0xFF20 => self.channels.four.update_length_timer(data), + 0xFF21 => self.channels.four.update_volume_and_envelope(data), + 0xFF22 => self.channels.four.update_frequency_and_randomness(data), + 0xFF23 => self.channels.four.update_control(data), 0xFF24 => { self.vin.left = get_bit(data, 7); self.vin.right = get_bit(data, 3); @@ -295,14 +284,10 @@ impl Apu { } 0xFF26 => self.apu_enable = (1 << 7) == (data & 0b10000000), 0xFF30..0xFF40 => self.channels.three.update_wave_ram(addr, data), - 0xFF11..0xFF1A | 0xFF1D..0xFF23 | 0xFF24..0xFF30 => self.mem[reg(addr)] = data, + 0xFF15 | 0xFF1F | 0xFF27..0xFF30 => {} 0x0..0xFF10 | 0xFF40..=0xFFFF => panic!("non-apu addr in apu"), } } - - fn masked_io(&mut self, addr_el: usize, data: u8, mask: u8) { - self.mem[addr_el] = masked_update(self.mem[addr_el], data, mask); - } } impl Cpu { diff --git a/src/processor/memory/mmio/apu/channels.rs b/src/processor/memory/mmio/apu/channels.rs index 0e7ca7d..56efdc7 100644 --- a/src/processor/memory/mmio/apu/channels.rs +++ b/src/processor/memory/mmio/apu/channels.rs @@ -441,12 +441,105 @@ impl WaveChannel { } } +#[derive(PartialEq)] +enum LfsrWidth { + FifteenBit, + SevenBit, +} + +struct Lfsr { + clock_shift: u8, + width: LfsrWidth, + clock_divider: u8, +} + +impl Default for Lfsr { + fn default() -> Self { + Self { + clock_shift: Default::default(), + width: LfsrWidth::FifteenBit, + clock_divider: Default::default(), + } + } +} + pub(super) struct NoiseChannel { pub(super) enabled: bool, + length_enable: bool, + length_timer: u8, + envelope: Envelope, + queued_envelope: Envelope, + lfsr: Lfsr, } impl NoiseChannel { pub(super) fn new(enabled: bool) -> Self { - Self { enabled } + Self { + enabled, + length_enable: false, + length_timer: 0, + envelope: Envelope::default(), + queued_envelope: Envelope::default(), + lfsr: Lfsr::default(), + } + } + + fn trigger(&mut self) { + self.enabled = true; + self.envelope = self.queued_envelope; + } + + pub(super) fn update_length_timer(&mut self, data: u8) { + self.length_timer = data & 0b111111; + } + + pub(super) fn update_volume_and_envelope(&mut self, data: u8) { + self.queued_envelope = Envelope::new( + (data & 0b11110000) >> 4, + if (data & 0b1000) == 0b1000 { + EnvelopeMode::Increase + } else { + EnvelopeMode::Decrease + }, + data & 0b111, + ); + } + + pub(super) fn get_volume_and_envelope(&self) -> u8 { + set_or_clear_bit( + (self.queued_envelope.rate & 0b111) + | ((self.queued_envelope.initial_volume & 0b1111) << 4), + 3, + self.queued_envelope.mode == EnvelopeMode::Decrease, + ) + } + + pub(super) fn update_frequency_and_randomness(&mut self, data: u8) { + self.lfsr.clock_shift = (data & 0b11110000) >> 4; + self.lfsr.width = if get_bit(data, 3) { + LfsrWidth::SevenBit + } else { + LfsrWidth::FifteenBit + }; + self.lfsr.clock_divider = data & 0b111; + } + + pub(super) fn get_frequency_and_randomness(&self) -> u8 { + set_or_clear_bit( + self.lfsr.clock_shift << 4 | self.lfsr.clock_divider, + 3, + self.lfsr.width == LfsrWidth::SevenBit, + ) + } + + pub(super) fn update_control(&mut self, data: u8) { + if get_bit(data, 7) { + self.trigger(); + } + self.length_enable = get_bit(data, 6); + } + + pub(super) fn get_control(&self) -> u8 { + set_or_clear_bit(0xFF, 6, self.length_enable) } }