split mbcs to files
This commit is contained in:
parent
cf6a14179d
commit
9090aa4621
3 changed files with 190 additions and 186 deletions
|
@ -1,5 +1,10 @@
|
||||||
use crate::processor::memory::Address;
|
use crate::processor::memory::Address;
|
||||||
|
|
||||||
|
mod mbc1;
|
||||||
|
mod none;
|
||||||
|
pub use mbc1::Mbc1;
|
||||||
|
pub use none::None;
|
||||||
|
|
||||||
pub(super) trait Mbc {
|
pub(super) trait Mbc {
|
||||||
fn get(&self, address: Address) -> u8;
|
fn get(&self, address: Address) -> u8;
|
||||||
fn get_ram(&self, address: Address) -> u8;
|
fn get_ram(&self, address: Address) -> u8;
|
||||||
|
@ -8,194 +13,8 @@ pub(super) trait Mbc {
|
||||||
fn mbc_type(&self) -> String;
|
fn mbc_type(&self) -> String;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) struct None {
|
|
||||||
pub(super) data: Vec<u8>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl None {
|
|
||||||
pub(super) fn init(data: Vec<u8>) -> Self {
|
|
||||||
Self { data }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Mbc for None {
|
|
||||||
fn get(&self, address: Address) -> u8 {
|
|
||||||
self.data[address as usize]
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_ram(&self, _address: Address) -> u8 {
|
|
||||||
0xFF
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_ram(&mut self, _address: Address, _data: u8) {}
|
|
||||||
|
|
||||||
fn set(&mut self, _address: Address, _data: u8) {}
|
|
||||||
|
|
||||||
fn mbc_type(&self) -> String {
|
|
||||||
String::from("None")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
enum BankingMode {
|
enum BankingMode {
|
||||||
Simple,
|
Simple,
|
||||||
Advanced,
|
Advanced,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) struct Mbc1 {
|
|
||||||
pub(super) data: Vec<u8>,
|
|
||||||
rom_len: usize,
|
|
||||||
rom_bank: u8,
|
|
||||||
ram_enabled: bool,
|
|
||||||
ram: Option<Vec<u8>>,
|
|
||||||
ram_bank: u8,
|
|
||||||
upper_banks: u8,
|
|
||||||
bank_mode: BankingMode,
|
|
||||||
}
|
|
||||||
|
|
||||||
const KB: usize = 1024;
|
|
||||||
const ROM_BANK_SIZE: usize = 16 * KB;
|
|
||||||
const RAM_BANK_SIZE: usize = 8 * KB;
|
|
||||||
|
|
||||||
impl Mbc1 {
|
|
||||||
pub(super) fn init(
|
|
||||||
data: Vec<u8>,
|
|
||||||
rom_size: u8,
|
|
||||||
ram_size: u8,
|
|
||||||
_save_file: Option<Vec<u8>>,
|
|
||||||
) -> Self {
|
|
||||||
let rom_len = match rom_size {
|
|
||||||
0x00 => 2,
|
|
||||||
0x01 => 4,
|
|
||||||
0x02 => 8,
|
|
||||||
0x03 => 16,
|
|
||||||
0x04 => 32,
|
|
||||||
0x05 => 64,
|
|
||||||
0x06 => 128,
|
|
||||||
0x07 => 256,
|
|
||||||
0x08 => 512,
|
|
||||||
0x52 => 72,
|
|
||||||
0x53 => 80,
|
|
||||||
0x54 => 96,
|
|
||||||
_ => panic!("unacceptable rom size"),
|
|
||||||
} * ROM_BANK_SIZE;
|
|
||||||
// in kb
|
|
||||||
let ram = match ram_size {
|
|
||||||
0x00 => None,
|
|
||||||
0x01 => Some(vec![0; 2 * KB]),
|
|
||||||
0x02 => Some(vec![0; 8 * KB]),
|
|
||||||
0x03 => Some(vec![0; 32 * KB]),
|
|
||||||
0x04 => Some(vec![0; 128 * KB]),
|
|
||||||
0x05 => Some(vec![0; 64 * KB]),
|
|
||||||
_ => panic!("unacceptable ram size"),
|
|
||||||
};
|
|
||||||
Self {
|
|
||||||
data,
|
|
||||||
rom_len,
|
|
||||||
rom_bank: 0x1,
|
|
||||||
ram_enabled: false,
|
|
||||||
ram,
|
|
||||||
ram_bank: 0,
|
|
||||||
upper_banks: 0,
|
|
||||||
bank_mode: BankingMode::Simple,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Mbc for Mbc1 {
|
|
||||||
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 {
|
|
||||||
let addr = self.get_ram_addr(address)%ram.len();
|
|
||||||
return ram[addr];
|
|
||||||
}
|
|
||||||
0xFF
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_ram(&mut self, address: Address, data: u8) {
|
|
||||||
let mut addr = self.get_ram_addr(address);
|
|
||||||
if self.ram_enabled && let Some(ram) = &mut self.ram {
|
|
||||||
addr %= ram.len();
|
|
||||||
ram[addr] = data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set(&mut self, address: Address, data: u8) {
|
|
||||||
match address {
|
|
||||||
0x0..0x2000 => {
|
|
||||||
// enable/disable ram
|
|
||||||
self.ram_enabled = (data & 0x0F) == 0xA;
|
|
||||||
}
|
|
||||||
0x2000..0x4000 => {
|
|
||||||
// rom bank number - lower 5 bits
|
|
||||||
let mut set_data = data & 0b00011111;
|
|
||||||
if set_data == 0 {
|
|
||||||
set_data = 1;
|
|
||||||
}
|
|
||||||
self.rom_bank = set_data;
|
|
||||||
}
|
|
||||||
0x4000..0x6000 => {
|
|
||||||
// ram bank OR upper bits 5 & 6 of rom bank
|
|
||||||
self.upper_banks = data & 0b11;
|
|
||||||
}
|
|
||||||
0x6000..0x8000 => {
|
|
||||||
// mode select
|
|
||||||
self.bank_mode = if (data & 0x1) == 0x1 {
|
|
||||||
BankingMode::Advanced
|
|
||||||
} else {
|
|
||||||
BankingMode::Simple
|
|
||||||
};
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mbc_type(&self) -> String {
|
|
||||||
if let Some(ram) = &self.ram {
|
|
||||||
format!("{}KB MBC1 with {}KB RAM", self.rom_len / KB, ram.len() / KB)
|
|
||||||
} else {
|
|
||||||
format!("{}KB MBC1", self.rom_len / KB)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Mbc1 {
|
|
||||||
fn get_rom_addr(&self, address: Address) -> usize {
|
|
||||||
(match address {
|
|
||||||
0x0..0x4000 => match self.bank_mode {
|
|
||||||
BankingMode::Simple => address as usize,
|
|
||||||
BankingMode::Advanced => {
|
|
||||||
(address as usize) + (self.upper_banks as usize * 512 * KB)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
0x4000..0x8000 => {
|
|
||||||
(address - 0x4000) as usize
|
|
||||||
+ (ROM_BANK_SIZE * self.rom_bank as usize)
|
|
||||||
+ (self.upper_banks as usize * 512 * KB)
|
|
||||||
}
|
|
||||||
|
|
||||||
0xA000..0xC000 => panic!("passed ram address to rom address function"),
|
|
||||||
_ => panic!("address {address} incompatible with MBC1"),
|
|
||||||
} % self.rom_len)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_ram_addr(&self, address: Address) -> usize {
|
|
||||||
match address {
|
|
||||||
0x0..0x8000 => panic!("passed rom address to ram address function"),
|
|
||||||
0xA000..0xC000 => match self.bank_mode {
|
|
||||||
BankingMode::Simple => {
|
|
||||||
(address - 0xA000) as usize + (RAM_BANK_SIZE * self.ram_bank as usize)
|
|
||||||
}
|
|
||||||
BankingMode::Advanced => {
|
|
||||||
(address - 0xA000) as usize
|
|
||||||
+ (RAM_BANK_SIZE * self.ram_bank as usize)
|
|
||||||
+ (self.upper_banks as usize * 16 * KB)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => panic!("address {address} incompatible with MBC1"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
155
src/processor/memory/rom/mbcs/mbc1.rs
Normal file
155
src/processor/memory/rom/mbcs/mbc1.rs
Normal file
|
@ -0,0 +1,155 @@
|
||||||
|
use super::{BankingMode, Mbc};
|
||||||
|
use crate::processor::memory::Address;
|
||||||
|
|
||||||
|
pub struct Mbc1 {
|
||||||
|
pub data: Vec<u8>,
|
||||||
|
rom_len: usize,
|
||||||
|
rom_bank: u8,
|
||||||
|
ram_enabled: bool,
|
||||||
|
ram: Option<Vec<u8>>,
|
||||||
|
ram_bank: u8,
|
||||||
|
upper_banks: u8,
|
||||||
|
bank_mode: BankingMode,
|
||||||
|
}
|
||||||
|
|
||||||
|
const KB: usize = 1024;
|
||||||
|
const ROM_BANK_SIZE: usize = 16 * KB;
|
||||||
|
const RAM_BANK_SIZE: usize = 8 * KB;
|
||||||
|
|
||||||
|
impl Mbc1 {
|
||||||
|
pub fn init(data: Vec<u8>, rom_size: u8, ram_size: u8, _save_file: Option<Vec<u8>>) -> Self {
|
||||||
|
let rom_len = match rom_size {
|
||||||
|
0x00 => 2,
|
||||||
|
0x01 => 4,
|
||||||
|
0x02 => 8,
|
||||||
|
0x03 => 16,
|
||||||
|
0x04 => 32,
|
||||||
|
0x05 => 64,
|
||||||
|
0x06 => 128,
|
||||||
|
0x07 => 256,
|
||||||
|
0x08 => 512,
|
||||||
|
0x52 => 72,
|
||||||
|
0x53 => 80,
|
||||||
|
0x54 => 96,
|
||||||
|
_ => panic!("unacceptable rom size"),
|
||||||
|
} * ROM_BANK_SIZE;
|
||||||
|
// in kb
|
||||||
|
let ram = match ram_size {
|
||||||
|
0x00 => None,
|
||||||
|
0x01 => Some(vec![0; 2 * KB]),
|
||||||
|
0x02 => Some(vec![0; 8 * KB]),
|
||||||
|
0x03 => Some(vec![0; 32 * KB]),
|
||||||
|
0x04 => Some(vec![0; 128 * KB]),
|
||||||
|
0x05 => Some(vec![0; 64 * KB]),
|
||||||
|
_ => panic!("unacceptable ram size"),
|
||||||
|
};
|
||||||
|
Self {
|
||||||
|
data,
|
||||||
|
rom_len,
|
||||||
|
rom_bank: 0x1,
|
||||||
|
ram_enabled: false,
|
||||||
|
ram,
|
||||||
|
ram_bank: 0,
|
||||||
|
upper_banks: 0,
|
||||||
|
bank_mode: BankingMode::Simple,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mbc for Mbc1 {
|
||||||
|
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 {
|
||||||
|
let addr = self.get_ram_addr(address)%ram.len();
|
||||||
|
return ram[addr];
|
||||||
|
}
|
||||||
|
0xFF
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_ram(&mut self, address: Address, data: u8) {
|
||||||
|
let mut addr = self.get_ram_addr(address);
|
||||||
|
if self.ram_enabled && let Some(ram) = &mut self.ram {
|
||||||
|
addr %= ram.len();
|
||||||
|
ram[addr] = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set(&mut self, address: Address, data: u8) {
|
||||||
|
match address {
|
||||||
|
0x0..0x2000 => {
|
||||||
|
// enable/disable ram
|
||||||
|
self.ram_enabled = (data & 0x0F) == 0xA;
|
||||||
|
}
|
||||||
|
0x2000..0x4000 => {
|
||||||
|
// rom bank number - lower 5 bits
|
||||||
|
let mut set_data = data & 0b00011111;
|
||||||
|
if set_data == 0 {
|
||||||
|
set_data = 1;
|
||||||
|
}
|
||||||
|
self.rom_bank = set_data;
|
||||||
|
}
|
||||||
|
0x4000..0x6000 => {
|
||||||
|
// ram bank OR upper bits 5 & 6 of rom bank
|
||||||
|
self.upper_banks = data & 0b11;
|
||||||
|
}
|
||||||
|
0x6000..0x8000 => {
|
||||||
|
// mode select
|
||||||
|
self.bank_mode = if (data & 0x1) == 0x1 {
|
||||||
|
BankingMode::Advanced
|
||||||
|
} else {
|
||||||
|
BankingMode::Simple
|
||||||
|
};
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mbc_type(&self) -> String {
|
||||||
|
if let Some(ram) = &self.ram {
|
||||||
|
format!("{}KB MBC1 with {}KB RAM", self.rom_len / KB, ram.len() / KB)
|
||||||
|
} else {
|
||||||
|
format!("{}KB MBC1", self.rom_len / KB)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mbc1 {
|
||||||
|
fn get_rom_addr(&self, address: Address) -> usize {
|
||||||
|
(match address {
|
||||||
|
0x0..0x4000 => match self.bank_mode {
|
||||||
|
BankingMode::Simple => address as usize,
|
||||||
|
BankingMode::Advanced => {
|
||||||
|
(address as usize) + (self.upper_banks as usize * 512 * KB)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
0x4000..0x8000 => {
|
||||||
|
(address - 0x4000) as usize
|
||||||
|
+ (ROM_BANK_SIZE * self.rom_bank as usize)
|
||||||
|
+ (self.upper_banks as usize * 512 * KB)
|
||||||
|
}
|
||||||
|
|
||||||
|
0xA000..0xC000 => panic!("passed ram address to rom address function"),
|
||||||
|
_ => panic!("address {address} incompatible with MBC1"),
|
||||||
|
} % self.rom_len)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_ram_addr(&self, address: Address) -> usize {
|
||||||
|
match address {
|
||||||
|
0x0..0x8000 => panic!("passed rom address to ram address function"),
|
||||||
|
0xA000..0xC000 => match self.bank_mode {
|
||||||
|
BankingMode::Simple => {
|
||||||
|
(address - 0xA000) as usize + (RAM_BANK_SIZE * self.ram_bank as usize)
|
||||||
|
}
|
||||||
|
BankingMode::Advanced => {
|
||||||
|
(address - 0xA000) as usize
|
||||||
|
+ (RAM_BANK_SIZE * self.ram_bank as usize)
|
||||||
|
+ (self.upper_banks as usize * 16 * KB)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => panic!("address {address} incompatible with MBC1"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
30
src/processor/memory/rom/mbcs/none.rs
Normal file
30
src/processor/memory/rom/mbcs/none.rs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
use super::Mbc;
|
||||||
|
use crate::processor::memory::Address;
|
||||||
|
|
||||||
|
pub struct None {
|
||||||
|
pub(super) data: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl None {
|
||||||
|
pub fn init(data: Vec<u8>) -> Self {
|
||||||
|
Self { data }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mbc for None {
|
||||||
|
fn get(&self, address: Address) -> u8 {
|
||||||
|
self.data[address as usize]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_ram(&self, _address: Address) -> u8 {
|
||||||
|
0xFF
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_ram(&mut self, _address: Address, _data: u8) {}
|
||||||
|
|
||||||
|
fn set(&mut self, _address: Address, _data: u8) {}
|
||||||
|
|
||||||
|
fn mbc_type(&self) -> String {
|
||||||
|
String::from("None")
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue