From 56729dac1504603ac6358eacfd7e53dac8121f87 Mon Sep 17 00:00:00 2001 From: lif Date: Tue, 7 Dec 2021 18:10:49 -0800 Subject: [PATCH] WIP local save file component --- .../examples/multifunction_emulator.rs | 2 + ferretro_components/src/base/mod.rs | 4 ++ .../src/provided/stdlib/mod.rs | 2 + .../src/provided/stdlib/saves.rs | 42 +++++++++++++++++++ 4 files changed, 50 insertions(+) create mode 100644 ferretro_components/src/provided/stdlib/saves.rs diff --git a/ferretro_components/examples/multifunction_emulator.rs b/ferretro_components/examples/multifunction_emulator.rs index df28c77..e3b18eb 100644 --- a/ferretro_components/examples/multifunction_emulator.rs +++ b/ferretro_components/examples/multifunction_emulator.rs @@ -92,6 +92,8 @@ pub fn main() -> Result<(), Box> { save_path: Some(std::env::temp_dir()), })?; + emu.register_component(LocalFileSaveComponent::default())?; + emu.init()?; emu.load_game(&opt.rom)?; if let Some(state) = opt.state { diff --git a/ferretro_components/src/base/mod.rs b/ferretro_components/src/base/mod.rs index 4ca1320..40117fc 100644 --- a/ferretro_components/src/base/mod.rs +++ b/ferretro_components/src/base/mod.rs @@ -61,6 +61,7 @@ pub trait RetroComponent: RetroCallbacks + Any { fn post_load_game(&mut self, retro: &mut LibretroWrapper, rom: &Path) -> Result<()> { Ok(()) } fn pre_run(&mut self, retro: &mut LibretroWrapper) -> ControlFlow { ControlFlow::Continue } fn post_run(&mut self, retro: &mut LibretroWrapper) -> ControlFlow { ControlFlow::Continue } + fn pre_drop(&mut self, retro: &mut LibretroWrapper) {} } impl RetroComponentBase { @@ -608,6 +609,9 @@ impl RetroCallbacks for RetroComponentBase { impl Drop for RetroComponentBase { fn drop(&mut self) { + for comp in &mut self.components { + comp.pre_drop(&mut self.retro); + } ferretro_base::retro::unset_handler(self.handler_id.unwrap()).unwrap(); } } diff --git a/ferretro_components/src/provided/stdlib/mod.rs b/ferretro_components/src/provided/stdlib/mod.rs index 31a64d3..364b8b8 100644 --- a/ferretro_components/src/provided/stdlib/mod.rs +++ b/ferretro_components/src/provided/stdlib/mod.rs @@ -7,6 +7,7 @@ mod input; mod logs; mod memory; mod paths; +mod saves; mod variables; pub use camera::CameraInfoComponent; @@ -16,4 +17,5 @@ pub use logs::StderrCallTraceComponent; pub use logs::StderrLogComponent; pub use logs::StderrSysInfoLogComponent; pub use paths::PathBufComponent; +pub use saves::LocalFileSaveComponent; pub use variables::VariableStoreComponent; diff --git a/ferretro_components/src/provided/stdlib/saves.rs b/ferretro_components/src/provided/stdlib/saves.rs new file mode 100644 index 0000000..dc23cb5 --- /dev/null +++ b/ferretro_components/src/provided/stdlib/saves.rs @@ -0,0 +1,42 @@ +use std::error::Error; +use std::fs::File; +use std::io::{Read, Write}; +use std::path::{Path, PathBuf}; +use crate::prelude::{LibretroWrapper, RetroCallbacks, RetroComponent}; +use ferretro_base::retro::ffi::MEMORY_SAVE_RAM; + +#[derive(Default)] +pub struct LocalFileSaveComponent { + rom_path: PathBuf, + initial_sram: Vec, +} + +impl LocalFileSaveComponent { + fn save_path(&self) -> PathBuf { + self.rom_path.with_extension(".sav") + } +} + +impl RetroComponent for LocalFileSaveComponent { + fn post_load_game(&mut self, retro: &mut LibretroWrapper, rom: &Path) -> Result<(), Box> { + self.rom_path = rom.to_path_buf(); + let save = self.save_path(); + if save.is_file() { + File::open(save)?.read(retro.mut_memory(MEMORY_SAVE_RAM))?; + } + self.initial_sram = retro.get_memory(MEMORY_SAVE_RAM).to_vec(); + Ok(()) + } + + fn pre_drop(&mut self, retro: &mut LibretroWrapper) { + let final_sram = retro.get_memory(MEMORY_SAVE_RAM); + if &self.initial_sram != final_sram { + let save = self.save_path(); + if let Ok(mut f) = File::create(save) { + let _ = f.write(final_sram); + } + } + } +} + +impl RetroCallbacks for LocalFileSaveComponent {}