Cleanup MBC related code
This commit is contained in:
parent
fc935ab214
commit
847d12c3a8
@ -1,4 +1,4 @@
|
||||
use crate::mbc::{mbc, mbc1, mbc2, mbc3, mbc5};
|
||||
use crate::mbc;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
enum MemoryBankControllerType {
|
||||
@ -24,7 +24,7 @@ pub struct Cartridge {
|
||||
}
|
||||
|
||||
impl Cartridge {
|
||||
pub fn new(rom: Box<[u8]>, save_file: Option<String>) -> Cartridge {
|
||||
pub fn new(rom: Box<[u8]>, savefile: Option<String>) -> Cartridge {
|
||||
let mbc_type: MemoryBankControllerType = match rom[0x0147] {
|
||||
0x00 | 0x08..=0x09 => MemoryBankControllerType::None,
|
||||
0x01..=0x03 => MemoryBankControllerType::MBC1,
|
||||
@ -57,23 +57,20 @@ impl Cartridge {
|
||||
println!("Rom size: {} banks", rom_banks);
|
||||
println!("Ram size: {:?}", ram_size);
|
||||
|
||||
let ram = Cartridge::load_savefile(&save_file, ram_size);
|
||||
let ram = Cartridge::load_savefile(&savefile, ram_size);
|
||||
|
||||
let mbc: Box<dyn mbc::MBC> = match mbc_type {
|
||||
MemoryBankControllerType::None => Box::new(mbc::NoMBC::new(rom, ram)),
|
||||
MemoryBankControllerType::MBC1 => Box::new(mbc1::MBC1::new(rom, ram)),
|
||||
MemoryBankControllerType::MBC2 => Box::new(mbc2::MBC2::new(rom, ram)),
|
||||
MemoryBankControllerType::MBC3 => Box::new(mbc3::MBC3::new(rom, ram)),
|
||||
MemoryBankControllerType::MBC5 => Box::new(mbc5::MBC5::new(rom, ram)),
|
||||
MemoryBankControllerType::MBC1 => Box::new(mbc::MBC1::new(rom, ram)),
|
||||
MemoryBankControllerType::MBC2 => Box::new(mbc::MBC2::new(rom, ram)),
|
||||
MemoryBankControllerType::MBC3 => Box::new(mbc::MBC3::new(rom, ram)),
|
||||
MemoryBankControllerType::MBC5 => Box::new(mbc::MBC5::new(rom, ram)),
|
||||
};
|
||||
|
||||
Cartridge {
|
||||
mbc: mbc,
|
||||
savefile: save_file,
|
||||
}
|
||||
Cartridge { mbc, savefile }
|
||||
}
|
||||
|
||||
fn load_savefile(save_file: &Option<String>, ram_size: RamSize) -> Box<[u8]> {
|
||||
fn load_savefile(savefile: &Option<String>, ram_size: RamSize) -> Box<[u8]> {
|
||||
let size = match ram_size {
|
||||
RamSize::None => 0,
|
||||
RamSize::Ram2KB => 2048,
|
||||
@ -81,7 +78,7 @@ impl Cartridge {
|
||||
RamSize::Ram32KB => 16 * 2048,
|
||||
};
|
||||
|
||||
if let &Some(ref filename) = save_file {
|
||||
if let &Some(ref filename) = savefile {
|
||||
let data = super::read_file(&filename);
|
||||
if let Ok(data) = data {
|
||||
if data.len() != size {
|
||||
|
||||
@ -165,87 +165,83 @@ impl Interconnect {
|
||||
|
||||
// Make sure the window is responsive:
|
||||
if self.cycles > 500 {
|
||||
loop {
|
||||
if let Some(event) = self.display.event_pump.poll_event() {
|
||||
match event {
|
||||
Event::Quit { .. }
|
||||
| Event::KeyDown {
|
||||
keycode: Some(Keycode::Escape),
|
||||
..
|
||||
} => {
|
||||
self.cartridge.save();
|
||||
self.display.dump_vram();
|
||||
return TickResult::Shutdown;
|
||||
}
|
||||
Event::KeyDown {
|
||||
keycode: Some(Keycode::Left),
|
||||
..
|
||||
} => self.press_key(Key::LEFT),
|
||||
Event::KeyDown {
|
||||
keycode: Some(Keycode::Down),
|
||||
..
|
||||
} => self.press_key(Key::DOWN),
|
||||
Event::KeyDown {
|
||||
keycode: Some(Keycode::Up),
|
||||
..
|
||||
} => self.press_key(Key::UP),
|
||||
Event::KeyDown {
|
||||
keycode: Some(Keycode::Right),
|
||||
..
|
||||
} => self.press_key(Key::RIGHT),
|
||||
Event::KeyDown {
|
||||
keycode: Some(Keycode::A),
|
||||
..
|
||||
} => self.press_key(Key::START),
|
||||
Event::KeyDown {
|
||||
keycode: Some(Keycode::S),
|
||||
..
|
||||
} => self.press_key(Key::SELECT),
|
||||
Event::KeyDown {
|
||||
keycode: Some(Keycode::Z),
|
||||
..
|
||||
} => self.press_key(Key::A),
|
||||
Event::KeyDown {
|
||||
keycode: Some(Keycode::X),
|
||||
..
|
||||
} => self.press_key(Key::B),
|
||||
|
||||
Event::KeyUp {
|
||||
keycode: Some(Keycode::Left),
|
||||
..
|
||||
} => self.release_key(Key::LEFT),
|
||||
Event::KeyUp {
|
||||
keycode: Some(Keycode::Down),
|
||||
..
|
||||
} => self.release_key(Key::DOWN),
|
||||
Event::KeyUp {
|
||||
keycode: Some(Keycode::Up),
|
||||
..
|
||||
} => self.release_key(Key::UP),
|
||||
Event::KeyUp {
|
||||
keycode: Some(Keycode::Right),
|
||||
..
|
||||
} => self.release_key(Key::RIGHT),
|
||||
Event::KeyUp {
|
||||
keycode: Some(Keycode::A),
|
||||
..
|
||||
} => self.release_key(Key::START),
|
||||
Event::KeyUp {
|
||||
keycode: Some(Keycode::S),
|
||||
..
|
||||
} => self.release_key(Key::SELECT),
|
||||
Event::KeyUp {
|
||||
keycode: Some(Keycode::Z),
|
||||
..
|
||||
} => self.release_key(Key::A),
|
||||
Event::KeyUp {
|
||||
keycode: Some(Keycode::X),
|
||||
..
|
||||
} => self.release_key(Key::B),
|
||||
_ => {}
|
||||
while let Some(event) = self.display.event_pump.poll_event() {
|
||||
match event {
|
||||
Event::Quit { .. }
|
||||
| Event::KeyDown {
|
||||
keycode: Some(Keycode::Escape),
|
||||
..
|
||||
} => {
|
||||
self.cartridge.save();
|
||||
self.display.dump_vram();
|
||||
return TickResult::Shutdown;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
Event::KeyDown {
|
||||
keycode: Some(Keycode::Left),
|
||||
..
|
||||
} => self.press_key(Key::LEFT),
|
||||
Event::KeyDown {
|
||||
keycode: Some(Keycode::Down),
|
||||
..
|
||||
} => self.press_key(Key::DOWN),
|
||||
Event::KeyDown {
|
||||
keycode: Some(Keycode::Up),
|
||||
..
|
||||
} => self.press_key(Key::UP),
|
||||
Event::KeyDown {
|
||||
keycode: Some(Keycode::Right),
|
||||
..
|
||||
} => self.press_key(Key::RIGHT),
|
||||
Event::KeyDown {
|
||||
keycode: Some(Keycode::A),
|
||||
..
|
||||
} => self.press_key(Key::START),
|
||||
Event::KeyDown {
|
||||
keycode: Some(Keycode::S),
|
||||
..
|
||||
} => self.press_key(Key::SELECT),
|
||||
Event::KeyDown {
|
||||
keycode: Some(Keycode::Z),
|
||||
..
|
||||
} => self.press_key(Key::A),
|
||||
Event::KeyDown {
|
||||
keycode: Some(Keycode::X),
|
||||
..
|
||||
} => self.press_key(Key::B),
|
||||
|
||||
Event::KeyUp {
|
||||
keycode: Some(Keycode::Left),
|
||||
..
|
||||
} => self.release_key(Key::LEFT),
|
||||
Event::KeyUp {
|
||||
keycode: Some(Keycode::Down),
|
||||
..
|
||||
} => self.release_key(Key::DOWN),
|
||||
Event::KeyUp {
|
||||
keycode: Some(Keycode::Up),
|
||||
..
|
||||
} => self.release_key(Key::UP),
|
||||
Event::KeyUp {
|
||||
keycode: Some(Keycode::Right),
|
||||
..
|
||||
} => self.release_key(Key::RIGHT),
|
||||
Event::KeyUp {
|
||||
keycode: Some(Keycode::A),
|
||||
..
|
||||
} => self.release_key(Key::START),
|
||||
Event::KeyUp {
|
||||
keycode: Some(Keycode::S),
|
||||
..
|
||||
} => self.release_key(Key::SELECT),
|
||||
Event::KeyUp {
|
||||
keycode: Some(Keycode::Z),
|
||||
..
|
||||
} => self.release_key(Key::A),
|
||||
Event::KeyUp {
|
||||
keycode: Some(Keycode::X),
|
||||
..
|
||||
} => self.release_key(Key::B),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
self.cycles = 0;
|
||||
|
||||
@ -1,53 +0,0 @@
|
||||
pub trait MBC {
|
||||
fn read_byte(&self, addr: u16) -> u8;
|
||||
fn write_byte(&mut self, addr: u16, val: u8);
|
||||
|
||||
fn dump_ram(&self, file: &String);
|
||||
}
|
||||
|
||||
pub struct NoMBC {
|
||||
rom: Box<[u8]>,
|
||||
ram: Box<[u8]>,
|
||||
}
|
||||
|
||||
impl NoMBC {
|
||||
pub fn new(rom: Box<[u8]>, ram: Box<[u8]>) -> NoMBC {
|
||||
NoMBC { rom: rom, ram: ram }
|
||||
}
|
||||
}
|
||||
|
||||
impl MBC for NoMBC {
|
||||
fn dump_ram(&self, file: &String) {
|
||||
super::super::write_file(&file, &self.ram).expect("Saving failed");
|
||||
}
|
||||
|
||||
fn write_byte(&mut self, addr: u16, val: u8) {
|
||||
println!(
|
||||
"Writing not supported for cartridges without MBC. (Tried to set {:04X} to {:02X})",
|
||||
addr, val
|
||||
);
|
||||
}
|
||||
|
||||
fn read_byte(&self, addr: u16) -> u8 {
|
||||
match addr {
|
||||
0x0000..=0x7FFF => self.rom[addr as usize],
|
||||
0xA000..=0xBFFF => {
|
||||
// TODO: Check for ram
|
||||
let addr = (addr as usize) - 0xA000;
|
||||
|
||||
if addr >= self.ram.len() {
|
||||
println!(
|
||||
"Tried to access {:04X}, however the memory is not present.",
|
||||
addr + 0xA000
|
||||
);
|
||||
0
|
||||
} else {
|
||||
self.ram[addr]
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
panic!("Cartride: Unable to read from {:04X}", addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
use super::mbc::MBC;
|
||||
use super::MBC;
|
||||
|
||||
enum BankMode {
|
||||
RomBankMode,
|
||||
@ -17,8 +17,8 @@ pub struct MBC1 {
|
||||
impl MBC1 {
|
||||
pub fn new(rom: Box<[u8]>, ram: Box<[u8]>) -> MBC1 {
|
||||
MBC1 {
|
||||
rom: rom,
|
||||
ram: ram,
|
||||
rom,
|
||||
ram,
|
||||
rom_bank_no: 1,
|
||||
bank_mode: BankMode::RomBankMode,
|
||||
bank_no_high: 0,
|
||||
@ -43,7 +43,7 @@ impl MBC1 {
|
||||
}
|
||||
|
||||
impl MBC for MBC1 {
|
||||
fn dump_ram(&self, file: &String) {
|
||||
fn dump_ram(&self, file: &str) {
|
||||
super::super::write_file(&file, &self.ram).expect("Saving failed");
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use super::mbc::MBC;
|
||||
use super::MBC;
|
||||
|
||||
pub struct MBC2 {
|
||||
rom: Box<[u8]>,
|
||||
@ -10,8 +10,8 @@ pub struct MBC2 {
|
||||
impl MBC2 {
|
||||
pub fn new(rom: Box<[u8]>, ram: Box<[u8]>) -> MBC2 {
|
||||
MBC2 {
|
||||
rom: rom,
|
||||
ram: ram,
|
||||
rom,
|
||||
ram,
|
||||
rom_bank_no: 1,
|
||||
ram_enable: false,
|
||||
}
|
||||
@ -23,7 +23,7 @@ impl MBC2 {
|
||||
}
|
||||
|
||||
impl MBC for MBC2 {
|
||||
fn dump_ram(&self, file: &String) {
|
||||
fn dump_ram(&self, file: &str) {
|
||||
super::super::write_file(&file, &self.ram).expect("Saving failed");
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use super::mbc::MBC;
|
||||
use super::MBC;
|
||||
|
||||
pub struct MBC3 {
|
||||
rom: Box<[u8]>,
|
||||
@ -11,8 +11,8 @@ pub struct MBC3 {
|
||||
impl MBC3 {
|
||||
pub fn new(rom: Box<[u8]>, ram: Box<[u8]>) -> MBC3 {
|
||||
MBC3 {
|
||||
rom: rom,
|
||||
ram: ram,
|
||||
rom,
|
||||
ram,
|
||||
rom_bank_no: 1,
|
||||
ram_bank_no: 0,
|
||||
ram_rtc_enabled: false,
|
||||
@ -28,7 +28,7 @@ impl MBC3 {
|
||||
}
|
||||
|
||||
impl MBC for MBC3 {
|
||||
fn dump_ram(&self, file: &String) {
|
||||
fn dump_ram(&self, file: &str) {
|
||||
super::super::write_file(&file, &self.ram).expect("Saving failed");
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use super::mbc::MBC;
|
||||
use super::MBC;
|
||||
|
||||
pub struct MBC5 {
|
||||
rom: Box<[u8]>,
|
||||
@ -11,8 +11,8 @@ pub struct MBC5 {
|
||||
impl MBC5 {
|
||||
pub fn new(rom: Box<[u8]>, ram: Box<[u8]>) -> Self {
|
||||
MBC5 {
|
||||
rom: rom,
|
||||
ram: ram,
|
||||
rom,
|
||||
ram,
|
||||
rom_bank_no: 1,
|
||||
ram_bank_no: 0,
|
||||
ram_rtc_enabled: false,
|
||||
@ -28,7 +28,7 @@ impl MBC5 {
|
||||
}
|
||||
|
||||
impl MBC for MBC5 {
|
||||
fn dump_ram(&self, file: &String) {
|
||||
fn dump_ram(&self, file: &str) {
|
||||
use crate::write_file;
|
||||
write_file(&file, &self.ram).expect("Saving failed");
|
||||
}
|
||||
|
||||
@ -1,5 +1,63 @@
|
||||
pub mod mbc;
|
||||
pub mod mbc1;
|
||||
pub mod mbc2;
|
||||
pub mod mbc3;
|
||||
pub mod mbc5;
|
||||
mod mbc1;
|
||||
mod mbc2;
|
||||
mod mbc3;
|
||||
mod mbc5;
|
||||
|
||||
pub use mbc1::MBC1;
|
||||
pub use mbc2::MBC2;
|
||||
pub use mbc3::MBC3;
|
||||
pub use mbc5::MBC5;
|
||||
|
||||
pub trait MBC {
|
||||
fn read_byte(&self, addr: u16) -> u8;
|
||||
fn write_byte(&mut self, addr: u16, val: u8);
|
||||
|
||||
fn dump_ram(&self, file: &str);
|
||||
}
|
||||
|
||||
pub struct NoMBC {
|
||||
rom: Box<[u8]>,
|
||||
ram: Box<[u8]>,
|
||||
}
|
||||
|
||||
impl NoMBC {
|
||||
pub fn new(rom: Box<[u8]>, ram: Box<[u8]>) -> NoMBC {
|
||||
NoMBC { rom: rom, ram: ram }
|
||||
}
|
||||
}
|
||||
|
||||
impl MBC for NoMBC {
|
||||
fn dump_ram(&self, file: &str) {
|
||||
super::write_file(&file, &self.ram).expect("Saving failed");
|
||||
}
|
||||
|
||||
fn write_byte(&mut self, addr: u16, val: u8) {
|
||||
println!(
|
||||
"Writing not supported for cartridges without MBC. (Tried to set {:04X} to {:02X})",
|
||||
addr, val
|
||||
);
|
||||
}
|
||||
|
||||
fn read_byte(&self, addr: u16) -> u8 {
|
||||
match addr {
|
||||
0x0000..=0x7FFF => self.rom[addr as usize],
|
||||
0xA000..=0xBFFF => {
|
||||
// TODO: Check for ram
|
||||
let addr = (addr as usize) - 0xA000;
|
||||
|
||||
if addr >= self.ram.len() {
|
||||
println!(
|
||||
"Tried to access {:04X}, however the memory is not present.",
|
||||
addr + 0xA000
|
||||
);
|
||||
0
|
||||
} else {
|
||||
self.ram[addr]
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
panic!("Cartride: Unable to read from {:04X}", addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,7 +5,10 @@ mod square;
|
||||
mod wave;
|
||||
|
||||
use self::pulse_simple::Playback;
|
||||
use std::sync::{Arc, Mutex, atomic::{AtomicBool, Ordering}};
|
||||
use std::sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
Arc, Mutex,
|
||||
};
|
||||
use std::thread;
|
||||
|
||||
const OUTPUT_SAMPLE_RATE: usize = 48100;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user