more registersf

This commit is contained in:
Alex Janka 2023-02-13 14:37:43 +11:00
parent 2bc9d0f665
commit 3e1b68fc1e

View file

@ -12,11 +12,17 @@ const fn reg(a: Address) -> usize {
struct Channel {
enabled: bool,
pan_left: bool,
pan_right: bool,
}
impl Channel {
fn new(enabled: bool) -> Self {
Self { enabled }
fn new(enabled: bool, pan_left: bool, pan_right: bool) -> Self {
Self {
enabled,
pan_left,
pan_right,
}
}
}
@ -30,18 +36,27 @@ struct Channels {
impl Default for Channels {
fn default() -> Self {
Self {
one: Channel::new(true),
two: Channel::new(false),
three: Channel::new(false),
four: Channel::new(false),
one: Channel::new(true, true, true),
two: Channel::new(false, true, true),
three: Channel::new(false, true, false),
four: Channel::new(false, true, false),
}
}
}
#[derive(Default)]
struct VinEnable {
left: bool,
right: bool,
}
pub struct Apu {
mem: [u8; MEM_SIZE],
apu_enable: bool,
channels: Channels,
vin: VinEnable,
vol_left: u8,
vol_right: u8,
}
impl Default for Apu {
@ -50,6 +65,9 @@ impl Default for Apu {
mem: [0x0; MEM_SIZE],
apu_enable: true,
channels: Channels::default(),
vin: VinEnable::default(),
vol_left: 7,
vol_right: 7,
}
}
}
@ -71,6 +89,26 @@ impl Apu {
fn make_register(&self, addr: Address) -> u8 {
match addr {
0xFF24 => {
// NR50 - Master volume + VIN panning
let mut v = ((self.vol_left << 4) & 0b1110000) | (self.vol_right & 0b111);
v = set_or_clear_bit(v, 7, self.vin.left);
v = set_or_clear_bit(v, 3, self.vin.right);
v
}
0xFF25 => {
// NR51 - Panning
let mut v = 0;
v = set_or_clear_bit(v, 0, self.channels.one.pan_right);
v = set_or_clear_bit(v, 1, self.channels.two.pan_right);
v = set_or_clear_bit(v, 2, self.channels.three.pan_right);
v = set_or_clear_bit(v, 3, self.channels.four.pan_right);
v = set_or_clear_bit(v, 4, self.channels.one.pan_left);
v = set_or_clear_bit(v, 5, self.channels.two.pan_left);
v = set_or_clear_bit(v, 6, self.channels.three.pan_left);
v = set_or_clear_bit(v, 7, self.channels.four.pan_left);
v
}
0xFF26 => {
// NR52 - Sound on/off
let mut v = if self.apu_enable { 1 << 7 } else { 0 };
@ -80,6 +118,9 @@ impl Apu {
v = set_or_clear_bit(v, 3, self.channels.four.enabled);
v
}
// write-only registers
0xFF13 | 0xFF18 | 0xFF1B | 0xFF1D | 0xFF20 => 0xFF,
// not registers
0xFF15 | 0xFF1F | 0xFF27..0xFF30 => 0xFF,
0x0..0xFF10 | 0xFF40..0xFFFF | 0xFFFF => panic!("non-apu addr in apu"),
_ => self.mem[reg(addr)],
@ -95,6 +136,16 @@ impl Apu {
0xFF23 => {
self.mem[reg(addr)] = (self.mem[reg(addr)] & 0b10111111) | (data & 0b01000000)
}
0xFF25 => {
self.channels.one.pan_right = get_bit(data, 0);
self.channels.two.pan_right = get_bit(data, 1);
self.channels.three.pan_right = get_bit(data, 2);
self.channels.four.pan_right = get_bit(data, 3);
self.channels.one.pan_left = get_bit(data, 4);
self.channels.two.pan_left = get_bit(data, 5);
self.channels.three.pan_left = get_bit(data, 6);
self.channels.four.pan_left = get_bit(data, 7);
}
0xFF26 => self.apu_enable = (1 << 7) == (data & 0b10000000),
0xFF11..0xFF1A | 0xFF1B | 0xFF1D..0xFF23 | 0xFF24..0xFF40 => self.mem[reg(addr)] = data,
0x0..0xFF10 | 0xFF40..0xFFFF | 0xFFFF => panic!("non-apu addr in apu"),