From 67d95c93594fd5637d0543ae734d9a454af3b6e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Magalh=C3=A3es?= <joamag@gmail.com> Date: Sun, 23 Jul 2023 22:58:41 +0100 Subject: [PATCH] chore: initial support for loading sav files --- frontends/sdl/src/main.rs | 14 ++++++++--- src/util.rs | 52 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 61 insertions(+), 5 deletions(-) diff --git a/frontends/sdl/src/main.rs b/frontends/sdl/src/main.rs index d0b54912..2fcab56b 100644 --- a/frontends/sdl/src/main.rs +++ b/frontends/sdl/src/main.rs @@ -13,6 +13,7 @@ use boytacean::{ ppu::{PaletteInfo, PpuMode}, rom::Cartridge, serial::{NullDevice, SerialDevice}, + util::replace_ext, }; use chrono::Utc; use clap::Parser; @@ -202,10 +203,15 @@ impl Emulator { } pub fn load_rom(&mut self, path: Option<&str>) { - let path_res = path.unwrap_or(&self.rom_path); + let rom_path: &str = path.unwrap_or(&self.rom_path); + let ram_path = replace_ext(rom_path, "sav").unwrap_or("".to_string()); let rom = self.system.load_rom_file( - path_res, - Some("C:/repo.other/boytacean/res/roms.prop/super_mario_2.sav"), + rom_path, + if Path::new(&ram_path).exists() { + Some(&ram_path) + } else { + None + }, ); println!( "========= Cartridge =========\n{}\n=============================", @@ -216,7 +222,7 @@ impl Emulator { .set_title(format!("{} [{}]", self.title, rom.title()).as_str()) .unwrap(); } - self.rom_path = String::from(path_res); + self.rom_path = String::from(rom_path); } pub fn reset(&mut self) { diff --git a/src/util.rs b/src/util.rs index 96776eec..37393a92 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,4 +1,4 @@ -use std::{cell::RefCell, fs::File, io::Read, rc::Rc}; +use std::{cell::RefCell, fs::File, io::Read, path::Path, rc::Rc}; pub type SharedMut<T> = Rc<RefCell<T>>; @@ -11,3 +11,53 @@ pub fn read_file(path: &str) -> Vec<u8> { file.read_to_end(&mut data).unwrap(); data } + +/// Replaces the extension in the given path with the provided extension. +/// This function allows for simple associated file discovery. +pub fn replace_ext(path: &str, new_extension: &str) -> Option<String> { + let file_path = Path::new(path); + let parent_dir = file_path.parent()?; + let file_stem = file_path.file_stem()?; + let file_extension = file_path.extension()?; + if file_stem == file_extension { + return None; + } + let new_file_name = format!("{}.{}", file_stem.to_str()?, new_extension); + let new_file_path = parent_dir.join(new_file_name); + Some(String::from(new_file_path.to_str()?)) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_change_extension() { + let new_path = replace_ext("/path/to/file.txt", "dat").unwrap(); + assert_eq!( + new_path, + Path::new("/path/to").join("file.dat").to_str().unwrap() + ); + + let new_path = replace_ext("/path/to/file.with.multiple.dots.txt", "dat").unwrap(); + assert_eq!( + new_path, + Path::new("/path/to") + .join("file.with.multiple.dots.dat") + .to_str() + .unwrap() + ); + + let new_path = replace_ext("/path/to/file.without.extension", "dat").unwrap(); + assert_eq!( + new_path, + Path::new("/path/to") + .join("file.without.dat") + .to_str() + .unwrap() + ); + + let new_path = replace_ext("/path/to/directory/", "dat"); + assert_eq!(new_path, None); + } +} -- GitLab