#[non_exhaustive]
pub struct MemoryMap {
pub external_ram: BankManager,
}
impl MemoryMap {
pub unsafe fn new() -> Self {
Self {
external_ram: BankManager::new(),
}
}
}
#[non_exhaustive]
pub struct BankManager;
impl BankManager {
const BANK_SELECTION_ADDR: u16 = 0x0000;
const RAM_BANK_START: u16 = 0xB000;
unsafe fn new() -> Self {
Self
}
unsafe fn select_bank(&mut self, bank: u8) {
*(Self::BANK_SELECTION_ADDR as *mut u8).as_mut().unwrap() = bank;
}
unsafe fn read_bank(&self) -> u8 {
*(Self::BANK_SELECTION_ADDR as *const u8).as_ref().unwrap()
}
pub fn fetch_bank(&mut self, bank: u8) -> &mut RamBank {
unsafe {
self.select_bank(bank);
(Self::RAM_BANK_START as *mut RamBank).as_mut().unwrap()
}
}
fn fetch<T>(&mut self, ptr: &mut BankPtr<T>) -> &mut T {
let bank = self.fetch_bank(ptr.bank_number);
bank.fetch_mut(ptr)
}
}
struct RamBank {
bank_number: u8,
}
impl RamBank {
fn fetch<T>(&self, ptr: &BankPtr<T>) -> &T {
assert_eq!(ptr.bank_number, self.bank_number);
unsafe { ptr.ptr.as_ref().unwrap() }
}
fn fetch_mut<T>(&mut self, ptr: &mut BankPtr<T>) -> &mut T {
assert_eq!(ptr.bank_number, self.bank_number);
unsafe { ptr.ptr.as_mut().unwrap() }
}
}
struct BankPtr<T> {
bank_number: u8,
ptr: *mut T,
}