diff --git a/crates/retro_frontend/src/frontend.rs b/crates/retro_frontend/src/frontend.rs index b0bbe60..2e526f6 100644 --- a/crates/retro_frontend/src/frontend.rs +++ b/crates/retro_frontend/src/frontend.rs @@ -68,6 +68,7 @@ pub struct Frontend { pub(crate) game_loaded: bool, pub(crate) av_info: Option, + pub(crate) sys_info: Option, /// The core's requested pixel format. /// TODO: HW accel. (or just not care) @@ -114,6 +115,7 @@ impl Frontend { game_loaded: false, av_info: None, + sys_info: None, pixel_format: PixelFormat::RGB565, converted_pixel_buffer: Vec::new(), @@ -374,32 +376,46 @@ impl Frontend { return Err(Error::CoreNotLoaded); } - // For now I'm only implementing the gameinfo garbage that - // makes you read the whole file in. Later on I'll look into VFS - // support; but for now, it seems more cores will probably - // play ball with this.. which sucks :( - // I'm aware this is nasty but bleh let slice = path.as_ref().as_os_str().as_bytes(); let path_string = CString::new(slice).expect("shouldn't fail"); - let contents = fs::read(path)?; - let gameinfo = GameInfo { - path: path_string.as_ptr(), - data: contents.as_ptr() as *const ffi::c_void, - size: contents.len(), - meta: std::ptr::null(), - }; + let system_info = self.get_system_info()?; let core_api = self.core_api.as_ref().unwrap(); - unsafe { - if !(core_api.retro_load_game)(&gameinfo) { - return Err(Error::RomLoadFailed); - } + let mut gameinfo = GameInfo { + path: path_string.as_ptr(), + data: std::ptr::null(), + size: 0, + meta: std::ptr::null(), + }; - self.game_loaded = true; - Ok(()) + // If the core does not need fullpath, then + // read the file data into a buffer we give to the core. + // This is pretty wasteful but works. + if !system_info.need_fullpath { + let contents = fs::read(path)?; + gameinfo.data = contents.as_ptr() as *const ffi::c_void; + gameinfo.size = contents.len(); + + unsafe { + if !(core_api.retro_load_game)(&gameinfo) { + return Err(Error::RomLoadFailed); + } + + self.game_loaded = true; + Ok(()) + } + } else { + unsafe { + if !(core_api.retro_load_game)(&gameinfo) { + return Err(Error::RomLoadFailed); + } + + self.game_loaded = true; + Ok(()) + } } } @@ -443,6 +459,28 @@ impl Frontend { } } + pub fn get_system_info(&mut self) -> Result { + if !self.core_loaded() { + return Err(Error::CoreNotLoaded); + } + + if let Some(sys) = self.sys_info.as_ref() { + Ok(sys.clone()) + } else { + let mut sys_info: MaybeUninit = MaybeUninit::uninit(); + + // Actually get the system info + unsafe { + let core_api = self.core_api.as_ref().unwrap(); + (core_api.retro_get_system_info)(sys_info.as_mut_ptr()); + + self.sys_info = Some(sys_info.assume_init()); + } + + Ok(self.sys_info.as_ref().unwrap().clone()) + } + } + pub fn get_size(&mut self) -> (u32, u32) { (self.fb_width, self.fb_height) }