Add savegame files

This commit is contained in:
Kevin Hamacher 2016-06-02 13:21:45 +02:00
parent dc0656475f
commit be4f9da380
7 changed files with 90 additions and 23 deletions

View File

@ -19,10 +19,11 @@ enum RamSize {
pub struct Cartridge {
mbc: Box<super::mbc::mbc::MBC>,
savefile: Option<String>,
}
impl Cartridge {
pub fn new(rom: Box<[u8]>) -> Cartridge {
pub fn new(rom: Box<[u8]>, save_file: Option<String>) -> Cartridge {
let mbc_type: MemoryBankControllerType = match rom[0x0147] {
0x00 | 0x08 ... 0x09 => MemoryBankControllerType::None,
0x01 ... 0x03 => MemoryBankControllerType::MBC1,
@ -54,12 +55,7 @@ impl Cartridge {
println!("Rom size: {} banks", rom_banks);
println!("Ram size: {:?}", ram_size);
let ram = match ram_size {
RamSize::None => vec![0u8; 0].into_boxed_slice(),
RamSize::Ram2KB => vec![0u8; 2048].into_boxed_slice(),
RamSize::Ram8KB => vec![0u8; 4 * 2048].into_boxed_slice(),
RamSize::Ram32KB => vec![0u8; 16 * 2048].into_boxed_slice(),
};
let ram = Cartridge::load_savefile(&save_file, ram_size);
let mbc: Box<super::mbc::mbc::MBC> = match mbc_type {
MemoryBankControllerType::None => Box::new(super::mbc::mbc::NoMBC::new(rom, ram)),
@ -71,6 +67,39 @@ impl Cartridge {
Cartridge {
mbc: mbc,
savefile: save_file,
}
}
fn load_savefile(save_file: &Option<String>, ram_size: RamSize) -> Box<[u8]> {
let old_data;
let size = match ram_size {
RamSize::None => 0,
RamSize::Ram2KB => 2048,
RamSize::Ram8KB => 4 * 2048,
RamSize::Ram32KB => 16 * 2048,
};
if let &Some(ref filename) = save_file {
let data = super::read_file(&filename);
if let Ok(success) = data {
old_data = success
} else {
old_data = vec![0u8; size].into_boxed_slice();
}
} else {
old_data = vec![0u8; size].into_boxed_slice();
}
old_data
}
pub fn save(&self) {
if let &Some(ref fil) = &self.savefile {
self.mbc.dump_ram(fil);
println!("Ram dump updated.")
} else {
println!("Did not update ram dump");
}
}

View File

@ -59,13 +59,16 @@ pub struct Interconnect {
joy_regular_keys: u8,
joy_special_keys: u8,
joy_switch: u8,
// Used for polling SDL events
cycles: u16,
}
impl Interconnect {
pub fn new(bios: Box<[u8]>, rom: Box<[u8]>) -> Interconnect {
pub fn new(bios: Box<[u8]>, rom: Box<[u8]>, save_file: Option<String>) -> Interconnect {
Interconnect {
bios: bios,
cartridge: cartridge::Cartridge::new(rom),
cartridge: cartridge::Cartridge::new(rom, save_file),
ram: vec![0; WRAM_SIZE].into_boxed_slice(),
hiram: vec![0; HIRAM_SIZE].into_boxed_slice(),
wram_bank: 1,

View File

@ -2,7 +2,9 @@
// gameboy (color?)
use std::path::Path;
use std::io;
use std::io::Read;
use std::io::Write;
use std::fs;
use std::env;
@ -17,23 +19,39 @@ mod mbc;
fn main() {
let bios_path = env::args().nth(1).unwrap();
let rom_path = env::args().nth(2).unwrap();
let bios = read_rom(&bios_path);
let rom = read_rom(&rom_path);
let args: Vec<String> = env::args().collect();
if args.len() < 3 || args.len() > 4 {
println!("Usage: {} bios game [savefile]", args[0]);
} else {
let bios_path = &args[1];
let rom_path = &args[2];
let mut save_file: Option<String> = None;
if args.len() == 4 {
save_file = Some(args[3].clone());
}
// Now we need to execute commands
let interconnect = interconnect::Interconnect::new(bios, rom);
let mut cpu = cpu::CPU::new(interconnect);
let bios = read_file(&bios_path).unwrap();
let rom = read_file(&rom_path).unwrap();
loop {
cpu.run_instruction();
// Now we need to execute commands
let interconnect = interconnect::Interconnect::new(bios, rom, save_file);
let mut cpu = cpu::CPU::new(interconnect);
loop {
cpu.run();
}
}
}
fn read_rom<P: AsRef<Path>>(rom_path: P) -> Box<[u8]> {
let mut file = fs::File::open(rom_path).unwrap();
pub fn read_file<P: AsRef<Path>>(rom_path: P) -> Result<Box<[u8]>, io::Error> {
let mut file = try!(fs::File::open(rom_path));
let mut buf = Vec::new();
file.read_to_end(&mut buf).expect("Reading file failed");
buf.into_boxed_slice()
try!(file.read_to_end(&mut buf));
Ok(buf.into_boxed_slice())
}
pub fn write_file<P: AsRef<Path>>(path: P, data: &Box<[u8]>) -> Result<(), io::Error> {
let mut file = try!(fs::File::create(path));
try!(file.write(&data));
Ok(())
}

View File

@ -1,6 +1,8 @@
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 {
@ -10,7 +12,6 @@ pub struct NoMBC {
impl NoMBC {
pub fn new(rom: Box<[u8]>, ram: Box<[u8]>) -> NoMBC {
NoMBC {
rom: rom,
ram: ram,
@ -19,6 +20,10 @@ impl NoMBC {
}
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);
}

View File

@ -43,6 +43,10 @@ impl MBC1 {
}
impl MBC for MBC1 {
fn dump_ram(&self, file: &String){
super::super::write_file(&file, &self.ram).expect("Saving failed");
}
fn read_byte(&self, addr: u16) -> u8 {
match addr {
0x0000 ... 0x3FFF => self.rom[addr as usize],

View File

@ -23,6 +23,10 @@ impl MBC2 {
}
impl MBC for MBC2 {
fn dump_ram(&self, file: &String){
super::super::write_file(&file, &self.ram).expect("Saving failed");
}
fn read_byte(&self, addr: u16) -> u8 {
match addr {
0x0000 ... 0x3FFF => self.rom[addr as usize],

View File

@ -29,6 +29,10 @@ impl MBC3 {
}
impl MBC for MBC3 {
fn dump_ram(&self, file: &String){
super::super::write_file(&file, &self.ram).expect("Saving failed");
}
fn read_byte(&self, addr: u16) -> u8 {
match addr {
0x0000 ... 0x3FFF => self.rom[addr as usize],