From e055b856375eb1d41dab4c255e6ea3ae627bc1bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Magalh=C3=A3es?= <joamag@gmail.com> Date: Sun, 6 Aug 2023 22:59:30 +0100 Subject: [PATCH] chore: initial loading support --- frontends/sdl/src/main.rs | 2 +- src/cpu.rs | 10 +++ src/state.rs | 128 ++++++++++++++++++++++++++++++++++---- 3 files changed, 128 insertions(+), 12 deletions(-) diff --git a/frontends/sdl/src/main.rs b/frontends/sdl/src/main.rs index 68b5ad1b..c5e786fa 100644 --- a/frontends/sdl/src/main.rs +++ b/frontends/sdl/src/main.rs @@ -411,7 +411,7 @@ impl Emulator { //load_state_file("tobias1.sav", &self.system); load_state_file( "C:\\Users\\joamag\\Dropbox\\Roms\\gb\\kirby_2.s0", - &self.system, + &mut self.system, ); } _ => {} diff --git a/src/cpu.rs b/src/cpu.rs index 74bc9302..7d86859e 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -397,11 +397,21 @@ impl Cpu { self.pc } + #[inline(always)] + pub fn set_pc(&mut self, value: u16) { + self.pc = value; + } + #[inline(always)] pub fn sp(&self) -> u16 { self.sp } + #[inline(always)] + pub fn set_sp(&mut self, value: u16) { + self.sp = value; + } + #[inline(always)] pub fn af(&self) -> u16 { (self.a as u16) << 8 | self.f() as u16 diff --git a/src/state.rs b/src/state.rs index cf7da9b4..c67b136a 100644 --- a/src/state.rs +++ b/src/state.rs @@ -18,6 +18,7 @@ pub trait Serialize { pub trait State { fn from_gb(gb: &GameBoy) -> Self; + fn to_gb(&self, gb: &mut GameBoy); } pub struct BeesState { @@ -31,12 +32,19 @@ impl BeesState { pub fn description(&self, column_length: usize) -> String { let emulator_l = format!("{:width$}", "Emulator", width = column_length); let title_l: String = format!("{:width$}", "Title", width = column_length); + let version_l: String = format!("{:width$}", "Version", width = column_length); + let model_l: String = format!("{:width$}", "Model", width = column_length); format!( - "{} {}\n{} {}\n", + "{} {}\n{} {}\n{} {}.{}\n{} {}\n", emulator_l, self.name.name, title_l, self.info.title(), + version_l, + self.core.major, + self.core.minor, + model_l, + self.core.model, ) } } @@ -74,6 +82,12 @@ impl State for BeesState { core: BeesCore::from_gb(gb), } } + + fn to_gb(&self, gb: &mut GameBoy) { + self.name.to_gb(gb); + self.info.to_gb(gb); + self.core.to_gb(gb); + } } impl Default for BeesState { @@ -125,6 +139,22 @@ pub struct BeesBuffer { offset: u32, } +impl Serialize for BeesBuffer { + fn save(&self, buffer: &mut Vec<u8>) { + buffer.write_all(&self.size.to_le_bytes()).unwrap(); + buffer.write_all(&self.offset.to_le_bytes()).unwrap(); + } + + fn load(&mut self, data: &mut Cursor<Vec<u8>>) { + let mut buffer = [0x00; 4]; + data.read_exact(&mut buffer).unwrap(); + self.size = u32::from_le_bytes(buffer.try_into().unwrap()); + let mut buffer = [0x00; 4]; + data.read_exact(&mut buffer).unwrap(); + self.offset = u32::from_le_bytes(buffer.try_into().unwrap()); + } +} + pub struct BeesFooter { start_offset: u32, magic: u32, @@ -190,9 +220,11 @@ impl Serialize for BeesName { } impl State for BeesName { - fn from_gb(_: &GameBoy) -> Self { + fn from_gb(_gb: &GameBoy) -> Self { Self::new(format!("{} v{}", name(), version())) } + + fn to_gb(&self, _gb: &mut GameBoy) {} } impl Default for BeesName { @@ -245,6 +277,8 @@ impl State for BeesInfo { &gb.cartridge_i().rom_data()[0x14e..=0x14f], ) } + + fn to_gb(&self, _gb: &mut GameBoy) {} } impl Default for BeesInfo { @@ -259,7 +293,7 @@ pub struct BeesCore { major: u16, minor: u16, - model: u32, + model: String, pc: u16, af: u16, @@ -286,7 +320,7 @@ pub struct BeesCore { } impl BeesCore { - pub fn new(model: u32, pc: u16, af: u16, bc: u16, de: u16, hl: u16, sp: u16) -> Self { + pub fn new(model: String, pc: u16, af: u16, bc: u16, de: u16, hl: u16, sp: u16) -> Self { Self { header: BeesBlockHeader::new( String::from("CORE"), @@ -323,15 +357,72 @@ impl BeesCore { } impl Serialize for BeesCore { - fn save(&self, buffer: &mut Vec<u8>) {} + fn save(&self, buffer: &mut Vec<u8>) { + self.header.save(buffer); + } + + fn load(&mut self, data: &mut Cursor<Vec<u8>>) { + self.header.load(data); - fn load(&mut self, data: &mut Cursor<Vec<u8>>) {} + let mut buffer = [0x00; 2]; + data.read_exact(&mut buffer).unwrap(); + self.major = u16::from_le_bytes(buffer.try_into().unwrap()); + let mut buffer = [0x00; 2]; + data.read_exact(&mut buffer).unwrap(); + self.minor = u16::from_le_bytes(buffer.try_into().unwrap()); + + let mut buffer = [0x00; 4]; + data.read_exact(&mut buffer).unwrap(); + self.model = String::from_utf8(Vec::from(buffer)).unwrap(); + + let mut buffer = [0x00; 2]; + data.read_exact(&mut buffer).unwrap(); + self.pc = u16::from_le_bytes(buffer.try_into().unwrap()); + let mut buffer = [0x00; 2]; + data.read_exact(&mut buffer).unwrap(); + self.af = u16::from_le_bytes(buffer.try_into().unwrap()); + let mut buffer = [0x00; 2]; + data.read_exact(&mut buffer).unwrap(); + self.bc = u16::from_le_bytes(buffer.try_into().unwrap()); + let mut buffer = [0x00; 2]; + data.read_exact(&mut buffer).unwrap(); + self.de = u16::from_le_bytes(buffer.try_into().unwrap()); + let mut buffer = [0x00; 2]; + data.read_exact(&mut buffer).unwrap(); + self.hl = u16::from_le_bytes(buffer.try_into().unwrap()); + let mut buffer = [0x00; 2]; + data.read_exact(&mut buffer).unwrap(); + self.sp = u16::from_le_bytes(buffer.try_into().unwrap()); + + let mut buffer = [0x00; 1]; + data.read_exact(&mut buffer).unwrap(); + self.ime = u8::from_le_bytes(buffer.try_into().unwrap()); + let mut buffer = [0x00; 1]; + data.read_exact(&mut buffer).unwrap(); + self.ie = u8::from_le_bytes(buffer.try_into().unwrap()); + let mut buffer = [0x00; 1]; + data.read_exact(&mut buffer).unwrap(); + self.execution_mode = u8::from_le_bytes(buffer.try_into().unwrap()); + let mut buffer = [0x00; 1]; + data.read_exact(&mut buffer).unwrap(); + self._padding = u8::from_le_bytes(buffer.try_into().unwrap()); + + data.read_exact(&mut self.io_registers).unwrap(); + + self.ram.load(data); + self.vram.load(data); + self.mbc_ram.load(data); + self.oam.load(data); + self.hram.load(data); + self.background_palettes.load(data); + self.object_palettes.load(data); + } } impl State for BeesCore { fn from_gb(gb: &GameBoy) -> Self { Self::new( - 0x0002_u32, //GB_MODEL_DMG_B + String::from("GD "), gb.cpu_i().pc(), gb.cpu_i().af(), gb.cpu_i().bc(), @@ -340,13 +431,27 @@ impl State for BeesCore { gb.cpu_i().sp(), ) } + + fn to_gb(&self, gb: &mut GameBoy) { + gb.cpu().set_pc(self.pc); + gb.cpu().set_af(self.af); + gb.cpu().set_bc(self.bc); + gb.cpu().set_de(self.de); + gb.cpu().set_hl(self.hl); + gb.cpu().set_sp(self.sp); + } } impl Default for BeesCore { fn default() -> Self { Self::new( - 0x0002_u32, //GB_MODEL_DMG_B - 0x0000_u16, 0x0000_u16, 0x0000_u16, 0x0000_u16, 0x0000_u16, 0x0000_u16, + String::from("GD "), + 0x0000_u16, + 0x0000_u16, + 0x0000_u16, + 0x0000_u16, + 0x0000_u16, + 0x0000_u16, ) } } @@ -363,15 +468,16 @@ pub fn save_state(gb: &GameBoy) -> Vec<u8> { data } -pub fn load_state_file(file_path: &str, gb: &GameBoy) { +pub fn load_state_file(file_path: &str, gb: &mut GameBoy) { let mut file = File::open(file_path).unwrap(); let mut data = vec![]; file.read_to_end(&mut data).unwrap(); load_state(&data, gb); } -pub fn load_state(data: &Vec<u8>, gb: &GameBoy) { +pub fn load_state(data: &Vec<u8>, gb: &mut GameBoy) { let mut state = BeesState::default(); state.load(&mut Cursor::new(data.to_vec())); print!("{}", state); + state.to_gb(gb); } -- GitLab