Skip to content
Snippets Groups Projects
Verified Commit 0d47c46e authored by João Magalhães's avatar João Magalhães :rocket:
Browse files

chore: better state saving

parent 5e593120
No related branches found
No related tags found
1 merge request!31System state save
Pipeline #3207 failed
......@@ -5,6 +5,7 @@ pub mod consts;
use boytacean::{
debugln,
gb::{AudioProvider, GameBoy},
gen::VERSION,
pad::PadKey,
ppu::{DISPLAY_HEIGHT, DISPLAY_WIDTH, FRAME_BUFFER_SIZE, XRGB8888_SIZE},
rom::Cartridge,
......@@ -173,7 +174,7 @@ pub extern "C" fn retro_reset() {
pub unsafe extern "C" fn retro_get_system_info(info: *mut RetroSystemInfo) {
debugln!("retro_get_system_info()");
(*info).library_name = "Boytacean\0".as_ptr() as *const c_char;
(*info).library_version = "v0.9.13\0".as_ptr() as *const c_char;
(*info).library_version = format!("v{}\0", VERSION).as_ptr() as *const c_char;
(*info).valid_extensions = "gb|gbc\0".as_ptr() as *const c_char;
(*info).need_fullpath = false;
(*info).block_extract = false;
......
......@@ -13,6 +13,7 @@ use boytacean::{
ppu::PaletteInfo,
rom::Cartridge,
serial::{NullDevice, SerialDevice},
state::save_state_file,
util::{replace_ext, write_file},
};
use chrono::Utc;
......@@ -816,6 +817,8 @@ fn main() {
game_boy.attach_serial(device);
game_boy.load(!args.no_boot);
save_state_file("tobias.sav", &game_boy);
// prints the current version of the emulator (informational message)
println!("========= Boytacean =========\n{}", game_boy);
......
use std::{convert::TryInto, io::Write};
use std::{
convert::TryInto,
fs::File,
io::{Cursor, Read, Write},
};
use crate::{gb::GameBoy, gen::VERSION};
pub trait Serialize {
fn save(&self, buffer: &mut Vec<u8>);
fn load(&mut self, data: &mut Cursor<Vec<u8>>);
}
#[repr(packed)]
pub struct BeesState {
pub name: BeesName,
pub info: BeesInfo,
pub core: BeesCore,
}
#[repr(packed)]
impl Serialize for BeesState {
fn save(&self, buffer: &mut Vec<u8>) {
self.name.save(buffer);
self.info.save(buffer);
self.core.save(buffer);
}
fn load(&mut self, data: &mut Cursor<Vec<u8>>) {
todo!()
}
}
pub struct BeesBlockHeader {
pub magic: u32,
pub magic: String,
pub size: u32,
}
#[repr(packed)]
impl BeesBlockHeader {
pub fn new(magic: String, size: u32) -> Self {
Self { magic, size }
}
}
impl Serialize for BeesBlockHeader {
fn save(&self, buffer: &mut Vec<u8>) {
buffer.write_all(&self.magic.as_bytes()).unwrap();
buffer.write_all(&self.size.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.magic = String::from_utf8(Vec::from(buffer)).unwrap();
data.read_exact(&mut buffer).unwrap();
self.size = u32::from_le_bytes(buffer.try_into().unwrap());
}
}
pub struct BeesBuffer {
pub size: u32,
pub offset: u32,
}
#[repr(packed)]
pub struct BeesFooter {
pub start_offset: u32,
pub magic: u32,
}
#[repr(packed)]
pub struct BeesName {
pub header: BeesBlockHeader,
pub name: String,
}
#[repr(packed)]
impl BeesName {
pub fn new(name: String) -> Self {
Self {
header: BeesBlockHeader::new(String::from("NAME"), name.len() as u32),
name,
}
}
}
impl Serialize for BeesName {
fn save(&self, buffer: &mut Vec<u8>) {
self.header.save(buffer);
buffer.write_all(self.name.as_bytes()).unwrap();
}
fn load(&mut self, data: &mut Cursor<Vec<u8>>) {
let mut buffer = Vec::with_capacity(self.header.size as usize);
buffer.resize(self.header.size as usize, 0);
data.read_exact(&mut buffer).unwrap();
self.name = String::from_utf8(Vec::from(buffer)).unwrap();
}
}
pub struct BeesInfo {
pub header: BeesBlockHeader,
pub title: [u8; 16],
pub checksum: [u8; 2],
}
#[repr(packed)]
impl Serialize for BeesInfo {
fn save(&self, buffer: &mut Vec<u8>) {}
fn load(&mut self, data: &mut Cursor<Vec<u8>>) {}
}
pub struct BeesCore {
pub header: BeesBlockHeader,
......@@ -71,46 +137,24 @@ pub struct BeesCore {
pub object_palettes: BeesBuffer,
}
trait Serialize {
fn store(&self, buffer: &mut Vec<u8>);
fn load(&mut self, data: &[u8]) -> u32;
}
impl Serialize for BeesState {
fn store(&self, buffer: &mut Vec<u8>) {
self.info.store(buffer);
}
impl Serialize for BeesCore {
fn save(&self, buffer: &mut Vec<u8>) {}
fn load(&mut self, data: &[u8]) -> u32 {
todo!()
}
fn load(&mut self, data: &mut Cursor<Vec<u8>>) {}
}
impl Serialize for BeesBlockHeader {
fn store(&self, buffer: &mut Vec<u8>) {
buffer.write(&self.magic.to_le_bytes()).unwrap();
buffer.write(&self.size.to_le_bytes()).unwrap();
}
fn load(&mut self, data: &[u8]) -> u32 {
self.magic = u32::from_le_bytes(data[0..4].try_into().unwrap());
self.size = u32::from_le_bytes(data[4..8].try_into().unwrap());
8
}
pub fn save_state_file(file_path: &str, gb: &GameBoy) {
let mut file = File::create(file_path).unwrap();
let data = save_state(gb);
file.write_all(&data).unwrap();
}
impl Serialize for BeesName {
fn store(&self, buffer: &mut Vec<u8>) {}
fn load(&mut self, data: &[u8]) -> u32 {
0
}
}
pub fn save_state(gb: &GameBoy) -> Vec<u8> {
let mut data: Vec<u8> = vec![];
impl Serialize for BeesInfo {
fn store(&self, buffer: &mut Vec<u8>) {}
BeesName::new(format!("Boytacean v{}", VERSION)).save(&mut data);
fn load(&mut self, data: &[u8]) -> u32 {
0
}
data
}
pub fn load_state(state: Vec<u8>, gb: &GameBoy) {}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment