Add savegame files
This commit is contained in:
parent
dc0656475f
commit
be4f9da380
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
44
src/main.rs
44
src/main.rs
@ -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(())
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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],
|
||||
|
||||
@ -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],
|
||||
|
||||
@ -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],
|
||||
|
||||
Loading…
Reference in New Issue
Block a user