apu handles memory
This commit is contained in:
parent
49a37b933a
commit
f0a8a978b2
|
@ -1,4 +1,4 @@
|
||||||
use self::mmio::Joypad;
|
use self::mmio::{Apu, Joypad};
|
||||||
pub use self::rom::Rom;
|
pub use self::rom::Rom;
|
||||||
use crate::{processor::SplitRegister, verbose_println};
|
use crate::{processor::SplitRegister, verbose_println};
|
||||||
use gilrs::ConnectedGamepadsIterator;
|
use gilrs::ConnectedGamepadsIterator;
|
||||||
|
@ -26,7 +26,7 @@ pub struct Memory {
|
||||||
io: [u8; 76],
|
io: [u8; 76],
|
||||||
pub(super) user_mode: bool,
|
pub(super) user_mode: bool,
|
||||||
joypad: Joypad,
|
joypad: Joypad,
|
||||||
pub(super) apu_enabled: bool,
|
apu: Apu,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Memory {
|
impl Memory {
|
||||||
|
@ -46,7 +46,7 @@ impl Memory {
|
||||||
io: [0xFF; 76],
|
io: [0xFF; 76],
|
||||||
user_mode: false,
|
user_mode: false,
|
||||||
joypad: Joypad::default(),
|
joypad: Joypad::default(),
|
||||||
apu_enabled: true,
|
apu: Apu::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,10 +119,11 @@ impl Memory {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_io(&self, address: Address) -> u8 {
|
fn get_io(&self, address: Address) -> u8 {
|
||||||
if address == 0xFF00 {
|
match address {
|
||||||
return self.joypad.as_register();
|
0xFF00 => self.joypad.as_register(),
|
||||||
|
0xFF10..0xFF40 => self.apu.get_register(address),
|
||||||
|
_ => self.io[(address - 0xFF00) as usize],
|
||||||
}
|
}
|
||||||
self.io[(address - 0xFF00) as usize]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_io(&mut self, address: Address, data: u8) {
|
fn set_io(&mut self, address: Address, data: u8) {
|
||||||
|
@ -144,19 +145,7 @@ impl Memory {
|
||||||
0xFF04 => self.io[addr_l] = 0,
|
0xFF04 => self.io[addr_l] = 0,
|
||||||
0xFF07 => self.masked_io(addr_l, data, 0b111),
|
0xFF07 => self.masked_io(addr_l, data, 0b111),
|
||||||
0xFF0F => self.masked_io(addr_l, data, 0b11111),
|
0xFF0F => self.masked_io(addr_l, data, 0b11111),
|
||||||
0xFF10 => self.masked_io(addr_l, data, 0b01111111),
|
0xFF10..0xFF40 => self.apu.mmio_write(address, data),
|
||||||
0xFF1A => self.masked_io(addr_l, data, 0b10000000),
|
|
||||||
0xFF1C => self.masked_io(addr_l, data, 0b1100000),
|
|
||||||
0xFF20 => self.masked_io(addr_l, data, 0b111111),
|
|
||||||
0xFF23 => self.io[addr_l] = (self.io[addr_l] & 0b10111111) | (data & 0b01000000),
|
|
||||||
0xFF26 => {
|
|
||||||
self.io[addr_l] = (self.io[addr_l] & 0b1111111) | (data & 0b10000000);
|
|
||||||
self.apu_enabled = self.io[addr_l] & 0b10000000 == 0b10000000
|
|
||||||
}
|
|
||||||
0xFF11 | 0xFF14 | 0xFF16 | 0xFF19 | 0xFF1E => {
|
|
||||||
// sound
|
|
||||||
self.io[addr_l] = data;
|
|
||||||
}
|
|
||||||
0xFF41 => {
|
0xFF41 => {
|
||||||
// mixed read/write
|
// mixed read/write
|
||||||
self.masked_io(addr_l, data, 0b01111000);
|
self.masked_io(addr_l, data, 0b01111000);
|
||||||
|
@ -165,16 +154,7 @@ impl Memory {
|
||||||
// cgb only
|
// cgb only
|
||||||
self.io[addr_l] = data;
|
self.io[addr_l] = data;
|
||||||
}
|
}
|
||||||
0xFF03
|
0xFF03 | 0xFF08..0xFF0F | 0xFF44 | 0xFF76 | 0xFF77 => {
|
||||||
| 0xFF08..0xFF0F
|
|
||||||
| 0xFF15
|
|
||||||
| 0xFF1F
|
|
||||||
| 0xFF27
|
|
||||||
| 0xFF28
|
|
||||||
| 0xFF29
|
|
||||||
| 0xFF44
|
|
||||||
| 0xFF76
|
|
||||||
| 0xFF77 => {
|
|
||||||
// read-only addresses
|
// read-only addresses
|
||||||
println!("BANNED write: {data:#X} to {address:#X}");
|
println!("BANNED write: {data:#X} to {address:#X}");
|
||||||
}
|
}
|
||||||
|
@ -198,7 +178,7 @@ impl Memory {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn masked_io(&mut self, addr_l: usize, data: u8, mask: u8) {
|
fn masked_io(&mut self, addr_l: usize, data: u8, mask: u8) {
|
||||||
self.io[addr_l] = (self.io[addr_l] & (!mask)) | (data & mask);
|
self.io[addr_l] = masked_update(self.io[addr_l], data, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_pressed_keys(
|
pub fn update_pressed_keys(
|
||||||
|
@ -235,3 +215,7 @@ impl Memory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn masked_update(current: u8, data: u8, mask: u8) -> u8 {
|
||||||
|
(current & (!mask)) | (data & mask)
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,61 @@
|
||||||
pub struct Apu {}
|
use crate::{
|
||||||
|
processor::memory::{masked_update, Address},
|
||||||
|
util::get_bit,
|
||||||
|
};
|
||||||
|
|
||||||
impl Apu {
|
const MEM_START: usize = 0xFF10;
|
||||||
fn init() -> Self {
|
const MEM_SIZE: usize = 0xFF40 - MEM_START;
|
||||||
Self {}
|
|
||||||
|
const fn reg(a: Address) -> usize {
|
||||||
|
(a as usize) - MEM_START
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Apu {
|
||||||
|
mem: [u8; MEM_SIZE],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Apu {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
mem: [0x0; MEM_SIZE],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Apu {
|
||||||
|
pub fn get_register(&self, addr: Address) -> u8 {
|
||||||
|
if addr == 0xFF26
|
||||||
|
|| addr == 0xFF11
|
||||||
|
|| addr == 0xFF16
|
||||||
|
|| addr == 0xFF1B
|
||||||
|
|| addr == 0xFF20
|
||||||
|
|| get_bit(self.mem[reg(0xFF26)], 7)
|
||||||
|
{
|
||||||
|
self.mem[reg(addr)]
|
||||||
|
} else {
|
||||||
|
0xFF
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mmio_write(&mut self, addr: Address, data: u8) {
|
||||||
|
match addr {
|
||||||
|
0xFF10 => self.masked_io(reg(addr), data, 0b01111111),
|
||||||
|
0xFF1A => self.masked_io(reg(addr), data, 0b10000000),
|
||||||
|
0xFF1C => self.masked_io(reg(addr), data, 0b1100000),
|
||||||
|
0xFF20 => self.masked_io(reg(addr), data, 0b111111),
|
||||||
|
0xFF23 => {
|
||||||
|
self.mem[reg(addr)] = (self.mem[reg(addr)] & 0b10111111) | (data & 0b01000000)
|
||||||
|
}
|
||||||
|
0xFF26 => self.mem[reg(addr)] = (self.mem[reg(addr)] & 0b1111111) | (data & 0b10000000),
|
||||||
|
0xFF11 | 0xFF14 | 0xFF16 | 0xFF19 | 0xFF1E => self.mem[reg(addr)] = data,
|
||||||
|
0xFF15 | 0xFF1F | 0xFF27 | 0xFF28 | 0xFF29 => {
|
||||||
|
println!("BANNED write in APU: {data:#X} to {addr:#X}")
|
||||||
|
}
|
||||||
|
_ => 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue