wave channel memory implemented
This commit is contained in:
parent
e80fd6a73a
commit
5cfe28a309
|
@ -208,6 +208,9 @@ impl Apu {
|
|||
0xFF16 => self.channels.two.get_length_timer_and_duty_cycle(),
|
||||
0xFF17 => self.channels.two.get_volume_and_envelope(),
|
||||
0xFF19 => self.channels.two.get_control(),
|
||||
0xFF1A => self.channels.three.get_dac(),
|
||||
0xFF1C => self.channels.three.get_volume(),
|
||||
0xFF1E => self.channels.three.get_control(),
|
||||
0xFF24 => {
|
||||
// NR50 - Master volume + VIN panning
|
||||
let mut v =
|
||||
|
@ -242,6 +245,8 @@ impl Apu {
|
|||
0xFF13 | 0xFF18 | 0xFF1B | 0xFF1D | 0xFF20 => 0xFF,
|
||||
// not registers
|
||||
0xFF15 | 0xFF1F | 0xFF27..0xFF30 => 0xFF,
|
||||
// wave ram
|
||||
0xFF30..0xFF40 => 0xFF,
|
||||
0x0..0xFF10 | 0xFF40..=0xFFFF => panic!("non-apu addr in apu"),
|
||||
_ => self.mem[reg(addr)],
|
||||
}
|
||||
|
@ -258,8 +263,11 @@ impl Apu {
|
|||
0xFF17 => self.channels.two.update_volume_and_envelope(data),
|
||||
0xFF18 => self.channels.two.update_wavelength_low(data),
|
||||
0xFF19 => self.channels.two.update_wavelength_high_and_control(data),
|
||||
0xFF1A => self.masked_io(reg(addr), data, 0b10000000),
|
||||
0xFF1C => self.masked_io(reg(addr), data, 0b1100000),
|
||||
0xFF1A => self.channels.three.update_dac(data),
|
||||
0xFF1B => self.channels.three.update_length(data),
|
||||
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)
|
||||
|
@ -281,7 +289,8 @@ impl Apu {
|
|||
self.mixer.ch4.left = Volume::from_bool(get_bit(data, 7));
|
||||
}
|
||||
0xFF26 => self.apu_enable = (1 << 7) == (data & 0b10000000),
|
||||
0xFF11..0xFF1A | 0xFF1B | 0xFF1D..0xFF23 | 0xFF24..0xFF40 => self.mem[reg(addr)] = data,
|
||||
0xFF30..0xFF40 => self.channels.three.update_wave_ram(addr, data),
|
||||
0xFF11..0xFF1A | 0xFF1D..0xFF23 | 0xFF24..0xFF30 => self.mem[reg(addr)] = data,
|
||||
0x0..0xFF10 | 0xFF40..0xFFFF | 0xFFFF => panic!("non-apu addr in apu"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
use crate::util::{get_bit, set_or_clear_bit};
|
||||
use crate::{
|
||||
processor::memory::Address,
|
||||
util::{get_bit, set_or_clear_bit},
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
pub(super) enum EnvelopeMode {
|
||||
|
@ -276,13 +279,105 @@ impl PwmChannel {
|
|||
}
|
||||
}
|
||||
|
||||
enum ShiftVolumePercent {
|
||||
Zero,
|
||||
TwentyFive,
|
||||
Fifty,
|
||||
OneHundred,
|
||||
}
|
||||
|
||||
pub(super) struct WaveChannel {
|
||||
pub(super) enabled: bool,
|
||||
dac_enabled: bool,
|
||||
length_enable: bool,
|
||||
length_timer: u8,
|
||||
volume: ShiftVolumePercent,
|
||||
wavelength: u16,
|
||||
wave_timer: u16,
|
||||
wave_position: usize,
|
||||
wave_ram: [u8; 16],
|
||||
}
|
||||
|
||||
impl WaveChannel {
|
||||
pub(super) fn new(enabled: bool) -> Self {
|
||||
Self { enabled }
|
||||
let wavelength = 0x7FF;
|
||||
Self {
|
||||
enabled,
|
||||
dac_enabled: false,
|
||||
length_enable: false,
|
||||
length_timer: 0xFF,
|
||||
volume: ShiftVolumePercent::Zero,
|
||||
wavelength,
|
||||
wave_timer: (2048 - wavelength) * 4,
|
||||
wave_position: 1,
|
||||
wave_ram: [0; 16],
|
||||
}
|
||||
}
|
||||
|
||||
fn trigger(&mut self) {
|
||||
self.enabled = true;
|
||||
}
|
||||
|
||||
pub(super) fn update_dac(&mut self, data: u8) {
|
||||
self.dac_enabled = get_bit(data, 7);
|
||||
}
|
||||
|
||||
pub(super) fn get_dac(&self) -> u8 {
|
||||
set_or_clear_bit(0xFF, 7, self.dac_enabled)
|
||||
}
|
||||
|
||||
pub(super) fn update_length(&mut self, data: u8) {
|
||||
self.length_timer = data;
|
||||
}
|
||||
|
||||
pub(super) fn update_volume(&mut self, data: u8) {
|
||||
self.volume = match (data & 0b1100000) >> 5 {
|
||||
0b00 => ShiftVolumePercent::Zero,
|
||||
0b01 => ShiftVolumePercent::OneHundred,
|
||||
0b10 => ShiftVolumePercent::Fifty,
|
||||
0b11 => ShiftVolumePercent::TwentyFive,
|
||||
_ => panic!("should be unreachable"),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn get_volume(&self) -> u8 {
|
||||
0b10011111
|
||||
& (match self.volume {
|
||||
ShiftVolumePercent::Zero => 0b00,
|
||||
ShiftVolumePercent::TwentyFive => 0b11,
|
||||
ShiftVolumePercent::Fifty => 0b10,
|
||||
ShiftVolumePercent::OneHundred => 0b01,
|
||||
} << 5)
|
||||
}
|
||||
|
||||
pub(super) fn update_wavelength_low(&mut self, data: u8) {
|
||||
self.wavelength = (self.wavelength & 0xFF00) | (data as u16);
|
||||
self.set_wave_timer();
|
||||
}
|
||||
|
||||
pub(super) fn update_wavelength_high_and_control(&mut self, data: u8) {
|
||||
self.length_enable = get_bit(data, 6);
|
||||
self.wavelength = (self.wavelength & 0xFF) | (((data & 0b111) as u16) << 8);
|
||||
self.set_wave_timer();
|
||||
if get_bit(data, 7) {
|
||||
self.trigger();
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn get_control(&self) -> u8 {
|
||||
set_or_clear_bit(0xFF, 6, self.length_enable)
|
||||
}
|
||||
|
||||
pub(super) fn update_wave_ram(&mut self, addr: Address, data: u8) {
|
||||
let real_addr = (addr - 0xFF30) as usize;
|
||||
if real_addr >= self.wave_ram.len() {
|
||||
panic!("sent the wrong address to update_wave_ram");
|
||||
}
|
||||
self.wave_ram[real_addr] = data;
|
||||
}
|
||||
|
||||
fn set_wave_timer(&mut self) {
|
||||
self.wave_timer = (2048 - self.wavelength) * 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue