mbc3 first pass - no rtc
This commit is contained in:
parent
0536d19242
commit
0417f94518
|
@ -1,7 +1,7 @@
|
|||
use crate::processor::memory::Address;
|
||||
use std::str::from_utf8_unchecked;
|
||||
|
||||
use self::mbcs::{Mbc, Mbc1, Mbc5, None};
|
||||
use self::mbcs::{Mbc, Mbc1, Mbc3, Mbc5, None};
|
||||
|
||||
mod mbcs;
|
||||
|
||||
|
@ -32,6 +32,14 @@ impl Rom {
|
|||
println!("MBC1 w/battery - battery not implemented!");
|
||||
Box::new(Mbc1::init(data, rom_size, ram_size, None))
|
||||
}
|
||||
0x0F => panic!("MBC3 + RTC"),
|
||||
0x1F => panic!("MBC3 + RTC + RAM"),
|
||||
0x11 => Box::new(Mbc3::init(data, rom_size, 0)),
|
||||
0x12 => Box::new(Mbc3::init(data, rom_size, ram_size)),
|
||||
0x13 => {
|
||||
println!("MBC3 w/battery - battery not implemented!");
|
||||
Box::new(Mbc3::init(data, rom_size, 0))
|
||||
}
|
||||
0x19 => Box::new(Mbc5::init(data, rom_size, 0)),
|
||||
0x1A => Box::new(Mbc5::init(data, rom_size, ram_size)),
|
||||
0x1B => {
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
use crate::processor::memory::Address;
|
||||
|
||||
mod mbc1;
|
||||
mod mbc3;
|
||||
mod mbc5;
|
||||
mod none;
|
||||
pub use mbc1::Mbc1;
|
||||
pub use mbc3::Mbc3;
|
||||
pub use mbc5::Mbc5;
|
||||
pub use none::None;
|
||||
|
||||
|
|
102
src/processor/memory/rom/mbcs/mbc3.rs
Normal file
102
src/processor/memory/rom/mbcs/mbc3.rs
Normal file
|
@ -0,0 +1,102 @@
|
|||
use crate::processor::memory::Address;
|
||||
|
||||
use super::{ram_size_kb, rom_banks, Mbc, KB, RAM_BANK_SIZE, ROM_BANK_SIZE};
|
||||
|
||||
pub struct Mbc3 {
|
||||
data: Vec<u8>,
|
||||
rom_bank: u8,
|
||||
rom_size: usize,
|
||||
ram: Option<Vec<u8>>,
|
||||
ram_bank: u8,
|
||||
ram_size: usize,
|
||||
ram_enabled: bool,
|
||||
}
|
||||
|
||||
impl Mbc3 {
|
||||
pub fn init(data: Vec<u8>, rom_size: u8, ram_size: u8) -> Self {
|
||||
let ram = ram_size_kb(ram_size).map(|s| vec![0; s * KB]);
|
||||
Self {
|
||||
data,
|
||||
rom_bank: 1,
|
||||
rom_size: rom_banks(rom_size) * ROM_BANK_SIZE,
|
||||
ram,
|
||||
ram_bank: 0,
|
||||
ram_size: ram_size_kb(ram_size).map_or(1, |s| s * KB),
|
||||
ram_enabled: false,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_rom_addr(&self, address: Address) -> usize {
|
||||
(match address {
|
||||
0x0..0x4000 => address as usize,
|
||||
0x4000..0x8000 => {
|
||||
let internal_addr = address as usize - 0x4000;
|
||||
internal_addr + (ROM_BANK_SIZE * self.rom_bank as usize)
|
||||
}
|
||||
_ => panic!("address {address} incompatible with MBC5"),
|
||||
} % self.rom_size)
|
||||
}
|
||||
|
||||
fn get_ram_addr(&self, address: Address) -> usize {
|
||||
((address as usize - 0xA000) + (RAM_BANK_SIZE * self.ram_bank as usize)) % self.ram_size
|
||||
}
|
||||
}
|
||||
|
||||
impl Mbc for Mbc3 {
|
||||
fn get(&self, address: Address) -> u8 {
|
||||
self.data[self.get_rom_addr(address)]
|
||||
}
|
||||
|
||||
fn get_ram(&self, address: Address) -> u8 {
|
||||
if self.ram_enabled && let Some(ram) = &self.ram {
|
||||
ram[self.get_ram_addr(address)]
|
||||
} else {
|
||||
0xFF
|
||||
}
|
||||
}
|
||||
|
||||
fn set(&mut self, address: Address, data: u8) {
|
||||
match address {
|
||||
0x0..0x2000 => {
|
||||
if data & 0xF == 0xA {
|
||||
self.ram_enabled = true;
|
||||
}
|
||||
}
|
||||
0x2000..0x4000 => {
|
||||
self.rom_bank = data & 0b01111111;
|
||||
if self.rom_bank == 0 {
|
||||
self.rom_bank = 1;
|
||||
}
|
||||
}
|
||||
0x4000..0x6000 => match data {
|
||||
0x0..=0x03 => self.ram_bank = data,
|
||||
0x08..=0x0C => panic!("rtc bank map: {data:#X}"),
|
||||
_ => panic!("ram/rtc bank error: tried to map {data:#X}"),
|
||||
},
|
||||
0x6000..0x8000 => {
|
||||
// RTC
|
||||
}
|
||||
|
||||
_ => panic!("unsupported addr"),
|
||||
}
|
||||
}
|
||||
|
||||
fn set_ram(&mut self, address: Address, data: u8) {
|
||||
let real_addr = self.get_ram_addr(address);
|
||||
if self.ram_enabled && let Some(ram) = &mut self.ram {
|
||||
ram[real_addr] = data;
|
||||
}
|
||||
}
|
||||
|
||||
fn mbc_type(&self) -> String {
|
||||
if let Some(ram) = &self.ram {
|
||||
format!(
|
||||
"{}KB MBC3 with {}KB RAM",
|
||||
self.rom_size / KB,
|
||||
ram.len() / KB,
|
||||
)
|
||||
} else {
|
||||
format!("{}KB MBC3", self.rom_size / KB)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue