From f9ea57c066a1e6fb1f47987fabde93e532880c5a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=A3o=20Magalh=C3=A3es?= <joamag@gmail.com>
Date: Sat, 23 Mar 2024 17:58:30 +0000
Subject: [PATCH] chore: support for ext game info

---
 frontends/libretro/src/consts.rs |  1 +
 frontends/libretro/src/lib.rs    | 60 +++++++++++++++++++++++++++-----
 src/macros.rs                    | 10 ++++++
 3 files changed, 63 insertions(+), 8 deletions(-)

diff --git a/frontends/libretro/src/consts.rs b/frontends/libretro/src/consts.rs
index 51082f85..7cd882bd 100644
--- a/frontends/libretro/src/consts.rs
+++ b/frontends/libretro/src/consts.rs
@@ -5,6 +5,7 @@ pub const RETRO_ENVIRONMENT_SET_PIXEL_FORMAT: u32 = 10;
 pub const RETRO_ENVIRONMENT_GET_VARIABLE: u32 = 15;
 pub const RETRO_ENVIRONMENT_SET_VARIABLES: u32 = 16;
 pub const RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE: u32 = 17;
+pub const RETRO_ENVIRONMENT_GET_GAME_INFO_EXT: u32 = 66;
 
 pub const RETRO_PIXEL_FORMAT_0RGB1555: usize = 0;
 pub const RETRO_PIXEL_FORMAT_XRGB8888: usize = 1;
diff --git a/frontends/libretro/src/lib.rs b/frontends/libretro/src/lib.rs
index 6a50023a..3c99ed4a 100644
--- a/frontends/libretro/src/lib.rs
+++ b/frontends/libretro/src/lib.rs
@@ -7,6 +7,7 @@ use boytacean::{
     debugln,
     gb::{AudioProvider, GameBoy},
     info::Info,
+    infoln,
     pad::PadKey,
     ppu::{DISPLAY_HEIGHT, DISPLAY_WIDTH, FRAME_BUFFER_SIZE, XRGB8888_SIZE},
     rom::Cartridge,
@@ -20,14 +21,14 @@ use consts::{
     RETRO_DEVICE_ID_JOYPAD_R2, RETRO_DEVICE_ID_JOYPAD_R3, RETRO_DEVICE_ID_JOYPAD_RIGHT,
     RETRO_DEVICE_ID_JOYPAD_SELECT, RETRO_DEVICE_ID_JOYPAD_START, RETRO_DEVICE_ID_JOYPAD_UP,
     RETRO_DEVICE_ID_JOYPAD_X, RETRO_DEVICE_ID_JOYPAD_Y, RETRO_DEVICE_JOYPAD,
-    RETRO_ENVIRONMENT_GET_VARIABLE, RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE,
-    RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, RETRO_ENVIRONMENT_SET_VARIABLES,
-    RETRO_PIXEL_FORMAT_XRGB8888,
+    RETRO_ENVIRONMENT_GET_GAME_INFO_EXT, RETRO_ENVIRONMENT_GET_VARIABLE,
+    RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, RETRO_ENVIRONMENT_SET_PIXEL_FORMAT,
+    RETRO_ENVIRONMENT_SET_VARIABLES, RETRO_PIXEL_FORMAT_XRGB8888,
 };
 use palettes::get_palette;
 use std::{
     collections::HashMap,
-    ffi::CStr,
+    ffi::{c_uchar, CStr},
     fmt::{self, Display, Formatter},
     os::raw::{c_char, c_float, c_uint, c_void},
     ptr::{self, addr_of},
@@ -54,6 +55,20 @@ static mut INFO: LibRetroInfo = LibRetroInfo {
     version_s: String::new(),
 };
 
+static mut GAME_INFO_EXT: RetroGameInfoExt = RetroGameInfoExt {
+    full_path: std::ptr::null(),
+    archive_path: std::ptr::null(),
+    archive_file: std::ptr::null(),
+    dir: std::ptr::null(),
+    name: std::ptr::null(),
+    ext: std::ptr::null(),
+    meta: std::ptr::null(),
+    data: std::ptr::null(),
+    size: 0,
+    file_in_archive: 0,
+    persistent_data: 0,
+};
+
 static mut PENDING_CYCLES: u32 = 0_u32;
 
 static mut ENVIRONMENT_CALLBACK: Option<extern "C" fn(u32, *const c_void) -> bool> = None;
@@ -149,13 +164,28 @@ pub struct RetroGameInfo {
     pub meta: *const c_char,
 }
 
+#[repr(C)]
+pub struct RetroGameInfoExt {
+    pub full_path: *const c_char,
+    pub archive_path: *const c_char,
+    pub archive_file: *const c_char,
+    pub dir: *const c_char,
+    pub name: *const c_char,
+    pub ext: *const c_char,
+    pub meta: *const c_char,
+    pub data: *const c_void,
+    pub size: usize,
+    pub file_in_archive: c_uchar,
+    pub persistent_data: c_uchar,
+}
+
 #[repr(C)]
 pub struct RetroSystemInfo {
     pub library_name: *const c_char,
     pub library_version: *const c_char,
     pub valid_extensions: *const c_char,
-    pub need_fullpath: bool,
-    pub block_extract: bool,
+    pub need_fullpath: c_uchar,
+    pub block_extract: c_uchar,
 }
 
 #[repr(C)]
@@ -225,8 +255,8 @@ pub unsafe extern "C" fn retro_get_system_info(info: *mut RetroSystemInfo) {
     (*info).library_name = INFO.name.as_ptr() as *const c_char;
     (*info).library_version = INFO.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;
+    (*info).need_fullpath = u8::from(false);
+    (*info).block_extract = u8::from(false);
 }
 
 /// # Safety
@@ -378,6 +408,20 @@ pub extern "C" fn retro_get_region() -> u32 {
 #[no_mangle]
 pub unsafe extern "C" fn retro_load_game(game: *const RetroGameInfo) -> bool {
     debugln!("retro_load_game()");
+    let environment_cb = ENVIRONMENT_CALLBACK.as_ref().unwrap();
+    let ext_result = environment_cb(
+        RETRO_ENVIRONMENT_GET_GAME_INFO_EXT,
+        addr_of!(GAME_INFO_EXT) as *const _ as *const c_void,
+    );
+    infoln!(
+        "Loading ROM file in Boytacean from '{}' ({} bytes)...",
+        String::from(CStr::from_ptr((*game).path).to_str().unwrap()),
+        if ext_result {
+            GAME_INFO_EXT.size
+        } else {
+            (*game).size
+        },
+    );
     let instance = EMULATOR.as_mut().unwrap();
     let data_buffer = from_raw_parts((*game).data as *const u8, (*game).size);
     let rom = Cartridge::from_data(data_buffer).unwrap();
diff --git a/src/macros.rs b/src/macros.rs
index 0291d604..4fb08076 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -17,6 +17,16 @@ macro_rules! debugln {
     };
 }
 
+#[macro_export]
+macro_rules! infoln {
+    ($($rest:tt)*) => {
+        {
+            std::print!("[INFO] ");
+            std::println!($($rest)*);
+        }
+    }
+}
+
 #[cfg(feature = "pedantic")]
 #[macro_export]
 macro_rules! warnln {
-- 
GitLab