Add savegame files
This commit is contained in:
parent
dc0656475f
commit
be4f9da380
@ -19,10 +19,11 @@ enum RamSize {
|
|||||||
|
|
||||||
pub struct Cartridge {
|
pub struct Cartridge {
|
||||||
mbc: Box<super::mbc::mbc::MBC>,
|
mbc: Box<super::mbc::mbc::MBC>,
|
||||||
|
savefile: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Cartridge {
|
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] {
|
let mbc_type: MemoryBankControllerType = match rom[0x0147] {
|
||||||
0x00 | 0x08 ... 0x09 => MemoryBankControllerType::None,
|
0x00 | 0x08 ... 0x09 => MemoryBankControllerType::None,
|
||||||
0x01 ... 0x03 => MemoryBankControllerType::MBC1,
|
0x01 ... 0x03 => MemoryBankControllerType::MBC1,
|
||||||
@ -54,12 +55,7 @@ impl Cartridge {
|
|||||||
println!("Rom size: {} banks", rom_banks);
|
println!("Rom size: {} banks", rom_banks);
|
||||||
println!("Ram size: {:?}", ram_size);
|
println!("Ram size: {:?}", ram_size);
|
||||||
|
|
||||||
let ram = match ram_size {
|
let ram = Cartridge::load_savefile(&save_file, 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 mbc: Box<super::mbc::mbc::MBC> = match mbc_type {
|
let mbc: Box<super::mbc::mbc::MBC> = match mbc_type {
|
||||||
MemoryBankControllerType::None => Box::new(super::mbc::mbc::NoMBC::new(rom, ram)),
|
MemoryBankControllerType::None => Box::new(super::mbc::mbc::NoMBC::new(rom, ram)),
|
||||||
@ -71,6 +67,39 @@ impl Cartridge {
|
|||||||
|
|
||||||
Cartridge {
|
Cartridge {
|
||||||
mbc: mbc,
|
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_regular_keys: u8,
|
||||||
joy_special_keys: u8,
|
joy_special_keys: u8,
|
||||||
joy_switch: u8,
|
joy_switch: u8,
|
||||||
|
|
||||||
|
// Used for polling SDL events
|
||||||
|
cycles: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Interconnect {
|
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 {
|
Interconnect {
|
||||||
bios: bios,
|
bios: bios,
|
||||||
cartridge: cartridge::Cartridge::new(rom),
|
cartridge: cartridge::Cartridge::new(rom, save_file),
|
||||||
ram: vec![0; WRAM_SIZE].into_boxed_slice(),
|
ram: vec![0; WRAM_SIZE].into_boxed_slice(),
|
||||||
hiram: vec![0; HIRAM_SIZE].into_boxed_slice(),
|
hiram: vec![0; HIRAM_SIZE].into_boxed_slice(),
|
||||||
wram_bank: 1,
|
wram_bank: 1,
|
||||||
|
|||||||
44
src/main.rs
44
src/main.rs
@ -2,7 +2,9 @@
|
|||||||
// gameboy (color?)
|
// gameboy (color?)
|
||||||
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use std::io;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
use std::io::Write;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
@ -17,23 +19,39 @@ mod mbc;
|
|||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let bios_path = env::args().nth(1).unwrap();
|
let args: Vec<String> = env::args().collect();
|
||||||
let rom_path = env::args().nth(2).unwrap();
|
if args.len() < 3 || args.len() > 4 {
|
||||||
let bios = read_rom(&bios_path);
|
println!("Usage: {} bios game [savefile]", args[0]);
|
||||||
let rom = read_rom(&rom_path);
|
} 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 bios = read_file(&bios_path).unwrap();
|
||||||
let interconnect = interconnect::Interconnect::new(bios, rom);
|
let rom = read_file(&rom_path).unwrap();
|
||||||
let mut cpu = cpu::CPU::new(interconnect);
|
|
||||||
|
|
||||||
loop {
|
// Now we need to execute commands
|
||||||
cpu.run_instruction();
|
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]> {
|
pub fn read_file<P: AsRef<Path>>(rom_path: P) -> Result<Box<[u8]>, io::Error> {
|
||||||
let mut file = fs::File::open(rom_path).unwrap();
|
let mut file = try!(fs::File::open(rom_path));
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
file.read_to_end(&mut buf).expect("Reading file failed");
|
try!(file.read_to_end(&mut buf));
|
||||||
buf.into_boxed_slice()
|
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 {
|
pub trait MBC {
|
||||||
fn read_byte(&self, addr: u16) -> u8;
|
fn read_byte(&self, addr: u16) -> u8;
|
||||||
fn write_byte(&mut self, addr: u16, val: u8);
|
fn write_byte(&mut self, addr: u16, val: u8);
|
||||||
|
|
||||||
|
fn dump_ram(&self, file: &String);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct NoMBC {
|
pub struct NoMBC {
|
||||||
@ -10,7 +12,6 @@ pub struct NoMBC {
|
|||||||
|
|
||||||
impl NoMBC {
|
impl NoMBC {
|
||||||
pub fn new(rom: Box<[u8]>, ram: Box<[u8]>) -> NoMBC {
|
pub fn new(rom: Box<[u8]>, ram: Box<[u8]>) -> NoMBC {
|
||||||
|
|
||||||
NoMBC {
|
NoMBC {
|
||||||
rom: rom,
|
rom: rom,
|
||||||
ram: ram,
|
ram: ram,
|
||||||
@ -19,6 +20,10 @@ impl NoMBC {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl MBC for 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) {
|
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);
|
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 {
|
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 {
|
fn read_byte(&self, addr: u16) -> u8 {
|
||||||
match addr {
|
match addr {
|
||||||
0x0000 ... 0x3FFF => self.rom[addr as usize],
|
0x0000 ... 0x3FFF => self.rom[addr as usize],
|
||||||
|
|||||||
@ -23,6 +23,10 @@ impl MBC2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl MBC for 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 {
|
fn read_byte(&self, addr: u16) -> u8 {
|
||||||
match addr {
|
match addr {
|
||||||
0x0000 ... 0x3FFF => self.rom[addr as usize],
|
0x0000 ... 0x3FFF => self.rom[addr as usize],
|
||||||
|
|||||||
@ -29,6 +29,10 @@ impl MBC3 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl MBC for 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 {
|
fn read_byte(&self, addr: u16) -> u8 {
|
||||||
match addr {
|
match addr {
|
||||||
0x0000 ... 0x3FFF => self.rom[addr as usize],
|
0x0000 ... 0x3FFF => self.rom[addr as usize],
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user