more registersf
This commit is contained in:
parent
2bc9d0f665
commit
3e1b68fc1e
|
@ -12,11 +12,17 @@ const fn reg(a: Address) -> usize {
|
||||||
|
|
||||||
struct Channel {
|
struct Channel {
|
||||||
enabled: bool,
|
enabled: bool,
|
||||||
|
pan_left: bool,
|
||||||
|
pan_right: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Channel {
|
impl Channel {
|
||||||
fn new(enabled: bool) -> Self {
|
fn new(enabled: bool, pan_left: bool, pan_right: bool) -> Self {
|
||||||
Self { enabled }
|
Self {
|
||||||
|
enabled,
|
||||||
|
pan_left,
|
||||||
|
pan_right,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,18 +36,27 @@ struct Channels {
|
||||||
impl Default for Channels {
|
impl Default for Channels {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
one: Channel::new(true),
|
one: Channel::new(true, true, true),
|
||||||
two: Channel::new(false),
|
two: Channel::new(false, true, true),
|
||||||
three: Channel::new(false),
|
three: Channel::new(false, true, false),
|
||||||
four: Channel::new(false),
|
four: Channel::new(false, true, false),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct VinEnable {
|
||||||
|
left: bool,
|
||||||
|
right: bool,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Apu {
|
pub struct Apu {
|
||||||
mem: [u8; MEM_SIZE],
|
mem: [u8; MEM_SIZE],
|
||||||
apu_enable: bool,
|
apu_enable: bool,
|
||||||
channels: Channels,
|
channels: Channels,
|
||||||
|
vin: VinEnable,
|
||||||
|
vol_left: u8,
|
||||||
|
vol_right: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Apu {
|
impl Default for Apu {
|
||||||
|
@ -50,6 +65,9 @@ impl Default for Apu {
|
||||||
mem: [0x0; MEM_SIZE],
|
mem: [0x0; MEM_SIZE],
|
||||||
apu_enable: true,
|
apu_enable: true,
|
||||||
channels: Channels::default(),
|
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 {
|
fn make_register(&self, addr: Address) -> u8 {
|
||||||
match addr {
|
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 => {
|
0xFF26 => {
|
||||||
// NR52 - Sound on/off
|
// NR52 - Sound on/off
|
||||||
let mut v = if self.apu_enable { 1 << 7 } else { 0 };
|
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 = set_or_clear_bit(v, 3, self.channels.four.enabled);
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
|
// write-only registers
|
||||||
|
0xFF13 | 0xFF18 | 0xFF1B | 0xFF1D | 0xFF20 => 0xFF,
|
||||||
|
// not registers
|
||||||
0xFF15 | 0xFF1F | 0xFF27..0xFF30 => 0xFF,
|
0xFF15 | 0xFF1F | 0xFF27..0xFF30 => 0xFF,
|
||||||
0x0..0xFF10 | 0xFF40..0xFFFF | 0xFFFF => panic!("non-apu addr in apu"),
|
0x0..0xFF10 | 0xFF40..0xFFFF | 0xFFFF => panic!("non-apu addr in apu"),
|
||||||
_ => self.mem[reg(addr)],
|
_ => self.mem[reg(addr)],
|
||||||
|
@ -95,6 +136,16 @@ impl Apu {
|
||||||
0xFF23 => {
|
0xFF23 => {
|
||||||
self.mem[reg(addr)] = (self.mem[reg(addr)] & 0b10111111) | (data & 0b01000000)
|
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),
|
0xFF26 => self.apu_enable = (1 << 7) == (data & 0b10000000),
|
||||||
0xFF11..0xFF1A | 0xFF1B | 0xFF1D..0xFF23 | 0xFF24..0xFF40 => self.mem[reg(addr)] = data,
|
0xFF11..0xFF1A | 0xFF1B | 0xFF1D..0xFF23 | 0xFF24..0xFF40 => self.mem[reg(addr)] = data,
|
||||||
0x0..0xFF10 | 0xFF40..0xFFFF | 0xFFFF => panic!("non-apu addr in apu"),
|
0x0..0xFF10 | 0xFF40..0xFFFF | 0xFFFF => panic!("non-apu addr in apu"),
|
||||||
|
|
Loading…
Reference in a new issue