start making giant match statement in environment cb wrapper
This commit is contained in:
		
							parent
							
								
									eaab387216
								
							
						
					
					
						commit
						498c874bc7
					
				
					 3 changed files with 208 additions and 263 deletions
				
			
		| 
						 | 
				
			
			@ -1,19 +1,19 @@
 | 
			
		|||
use std::convert::{TryFrom, TryInto};
 | 
			
		||||
use std::os::raw::{c_uint, c_void};
 | 
			
		||||
use std::os::raw::c_uint;
 | 
			
		||||
use std::path::PathBuf;
 | 
			
		||||
 | 
			
		||||
use num_enum::TryFromPrimitive;
 | 
			
		||||
use num_enum::{TryFromPrimitive, IntoPrimitive};
 | 
			
		||||
 | 
			
		||||
use crate::libretro_ffi::*;
 | 
			
		||||
 | 
			
		||||
#[derive(TryFromPrimitive)]
 | 
			
		||||
#[derive(TryFromPrimitive, IntoPrimitive)]
 | 
			
		||||
#[repr(u32)]
 | 
			
		||||
pub enum Region {
 | 
			
		||||
    NTSC = RETRO_REGION_NTSC,
 | 
			
		||||
    PAL = RETRO_REGION_PAL,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(TryFromPrimitive)]
 | 
			
		||||
#[derive(TryFromPrimitive, IntoPrimitive)]
 | 
			
		||||
#[repr(u32)]
 | 
			
		||||
pub enum DeviceType {
 | 
			
		||||
    None = RETRO_DEVICE_NONE,
 | 
			
		||||
| 
						 | 
				
			
			@ -25,7 +25,7 @@ pub enum DeviceType {
 | 
			
		|||
    Pointer = RETRO_DEVICE_POINTER,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(TryFromPrimitive)]
 | 
			
		||||
#[derive(TryFromPrimitive, IntoPrimitive)]
 | 
			
		||||
#[repr(u32)]
 | 
			
		||||
pub enum DeviceIndex {
 | 
			
		||||
    Left = RETRO_DEVICE_INDEX_ANALOG_LEFT,
 | 
			
		||||
| 
						 | 
				
			
			@ -33,7 +33,7 @@ pub enum DeviceIndex {
 | 
			
		|||
    Button = RETRO_DEVICE_INDEX_ANALOG_BUTTON,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(TryFromPrimitive)]
 | 
			
		||||
#[derive(TryFromPrimitive, IntoPrimitive)]
 | 
			
		||||
#[repr(u32)]
 | 
			
		||||
pub enum JoypadButton {
 | 
			
		||||
    B = RETRO_DEVICE_ID_JOYPAD_B,
 | 
			
		||||
| 
						 | 
				
			
			@ -54,14 +54,14 @@ pub enum JoypadButton {
 | 
			
		|||
    R3 = RETRO_DEVICE_ID_JOYPAD_R3,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(TryFromPrimitive)]
 | 
			
		||||
#[derive(TryFromPrimitive, IntoPrimitive)]
 | 
			
		||||
#[repr(u32)]
 | 
			
		||||
pub enum AnalogAxis {
 | 
			
		||||
    X = RETRO_DEVICE_ID_ANALOG_X,
 | 
			
		||||
    Y = RETRO_DEVICE_ID_ANALOG_Y,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(TryFromPrimitive)]
 | 
			
		||||
#[derive(TryFromPrimitive, IntoPrimitive)]
 | 
			
		||||
#[repr(u32)]
 | 
			
		||||
pub enum MouseButton {
 | 
			
		||||
    X = RETRO_DEVICE_ID_MOUSE_X,
 | 
			
		||||
| 
						 | 
				
			
			@ -77,7 +77,7 @@ pub enum MouseButton {
 | 
			
		|||
    Button5 = RETRO_DEVICE_ID_MOUSE_BUTTON_5,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(TryFromPrimitive)]
 | 
			
		||||
#[derive(TryFromPrimitive, IntoPrimitive)]
 | 
			
		||||
#[repr(u32)]
 | 
			
		||||
pub enum LightGunButton {
 | 
			
		||||
    ScreenX = RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X,
 | 
			
		||||
| 
						 | 
				
			
			@ -99,7 +99,7 @@ pub enum LightGunButton {
 | 
			
		|||
    Pause = RETRO_DEVICE_ID_LIGHTGUN_PAUSE,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(TryFromPrimitive)]
 | 
			
		||||
#[derive(TryFromPrimitive, IntoPrimitive)]
 | 
			
		||||
#[repr(u32)]
 | 
			
		||||
pub enum PointerStat {
 | 
			
		||||
    X = RETRO_DEVICE_ID_POINTER_X,
 | 
			
		||||
| 
						 | 
				
			
			@ -137,7 +137,7 @@ impl<D> TryFrom<(D, c_uint)> for Input
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(TryFromPrimitive)]
 | 
			
		||||
#[derive(TryFromPrimitive, IntoPrimitive)]
 | 
			
		||||
#[repr(u32)]
 | 
			
		||||
pub enum EnvRotation {
 | 
			
		||||
    None = 0,
 | 
			
		||||
| 
						 | 
				
			
			@ -146,7 +146,7 @@ pub enum EnvRotation {
 | 
			
		|||
    CounterClockwise270 = 3,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(TryFromPrimitive)]
 | 
			
		||||
#[derive(TryFromPrimitive, IntoPrimitive)]
 | 
			
		||||
#[repr(u32)]
 | 
			
		||||
pub enum EnvPixelFormat {
 | 
			
		||||
    XRGB555 = retro_pixel_format_RETRO_PIXEL_FORMAT_0RGB1555,
 | 
			
		||||
| 
						 | 
				
			
			@ -162,7 +162,7 @@ pub struct EnvVariable {
 | 
			
		|||
    value: Option<String>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(TryFromPrimitive)]
 | 
			
		||||
#[derive(TryFromPrimitive, IntoPrimitive)]
 | 
			
		||||
#[repr(u32)]
 | 
			
		||||
pub enum EnvLanguage {
 | 
			
		||||
    English = retro_language_RETRO_LANGUAGE_ENGLISH,
 | 
			
		||||
| 
						 | 
				
			
			@ -186,90 +186,89 @@ pub enum EnvLanguage {
 | 
			
		|||
    Last = retro_language_RETRO_LANGUAGE_LAST,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO: lifetime
 | 
			
		||||
// TODO: experimental calls
 | 
			
		||||
#[derive(TryFromPrimitive, IntoPrimitive)]
 | 
			
		||||
#[repr(u32)]
 | 
			
		||||
pub enum EnvironmentCmdData {
 | 
			
		||||
    SetRotation(EnvRotation),
 | 
			
		||||
    GetOverscan(&'static mut bool),
 | 
			
		||||
    GetCanDupe(&'static mut bool),
 | 
			
		||||
    SetMessage(retro_message), // TODO
 | 
			
		||||
    Shutdown,
 | 
			
		||||
    SetPerformanceLevel(c_uint),
 | 
			
		||||
    GetSystemDirectory(&'static mut PathBuf),
 | 
			
		||||
    SetPixelFormat(EnvPixelFormat),
 | 
			
		||||
    SetInputDescriptors(&'static [retro_input_descriptor]), // TODO
 | 
			
		||||
    SetKeyboardCallback(retro_keyboard_callback), // TODO
 | 
			
		||||
    SetDiskControlInterface(retro_disk_control_callback), // TODO
 | 
			
		||||
    SetHwRender(retro_hw_render_callback), // TODO
 | 
			
		||||
    GetVariable(&'static mut EnvVariable),
 | 
			
		||||
    SetVariables(&'static [EnvVariable]),
 | 
			
		||||
    GetVariableUpdate(&'static mut bool),
 | 
			
		||||
    SetSupportNoGame(bool),
 | 
			
		||||
    GetLibretroPath(&'static mut PathBuf),
 | 
			
		||||
    SetFrameTimeCallback(retro_frame_time_callback), // TODO
 | 
			
		||||
    SetAudioCallback(retro_audio_callback), // TODO
 | 
			
		||||
    GetRumbleInterface(&'static mut retro_rumble_interface), // TODO
 | 
			
		||||
    GetInputDeviceCapabilities(&'static mut u64), // TODO
 | 
			
		||||
    GetSensorInterface(&'static mut retro_sensor_interface), // TODO
 | 
			
		||||
    GetCameraInterface(&'static mut retro_camera_callback), // TODO
 | 
			
		||||
    GetLogInterface(&'static mut retro_log_callback), // TODO
 | 
			
		||||
    GetPerfInterface(&'static mut retro_perf_callback), // TODO
 | 
			
		||||
    GetLocationInterface(&'static mut retro_location_callback), // TODO
 | 
			
		||||
    GetCoreAssetsDirectory(&'static mut PathBuf),
 | 
			
		||||
    GetSaveDirectory(&'static mut PathBuf),
 | 
			
		||||
    SetSystemAvInfo(retro_system_av_info),
 | 
			
		||||
    SetProcAddressCallback(retro_get_proc_address_interface), // TODO
 | 
			
		||||
    SetSubsystemInfo(retro_subsystem_info), // TODO
 | 
			
		||||
    SetControllerInfo(retro_controller_info), // TODO
 | 
			
		||||
    SetMemoryMaps(retro_memory_map), // TODO
 | 
			
		||||
    SetGeometry(retro_game_geometry), // TODO
 | 
			
		||||
    GetUsername(&'static mut String),
 | 
			
		||||
    GetLanguage(&'static mut EnvLanguage),
 | 
			
		||||
    SetSerializationQuirks(&'static mut u64), // TODO
 | 
			
		||||
    SetRotation = RETRO_ENVIRONMENT_SET_ROTATION,
 | 
			
		||||
    GetOverscan = RETRO_ENVIRONMENT_GET_OVERSCAN,
 | 
			
		||||
    GetCanDupe = RETRO_ENVIRONMENT_GET_CAN_DUPE,
 | 
			
		||||
    SetMessage = RETRO_ENVIRONMENT_SET_MESSAGE,
 | 
			
		||||
    Shutdown = RETRO_ENVIRONMENT_SHUTDOWN,
 | 
			
		||||
    SetPerformanceLevel = RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL,
 | 
			
		||||
    GetSystemDirectory = RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY,
 | 
			
		||||
    SetPixelFormat = RETRO_ENVIRONMENT_SET_PIXEL_FORMAT,
 | 
			
		||||
    SetInputDescriptors = RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS,
 | 
			
		||||
    SetKeyboardCallback = RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK,
 | 
			
		||||
    SetDiskControlInterface = RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE,
 | 
			
		||||
    SetHwRender = RETRO_ENVIRONMENT_SET_HW_RENDER,
 | 
			
		||||
    GetVariable = RETRO_ENVIRONMENT_GET_VARIABLE,
 | 
			
		||||
    SetVariables = RETRO_ENVIRONMENT_SET_VARIABLES,
 | 
			
		||||
    GetVariableUpdate = RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE,
 | 
			
		||||
    SetSupportNoGame = RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME,
 | 
			
		||||
    GetLibretroPath = RETRO_ENVIRONMENT_GET_LIBRETRO_PATH,
 | 
			
		||||
    SetFrameTimeCallback = RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK,
 | 
			
		||||
    SetAudioCallback = RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK,
 | 
			
		||||
    GetRumbleInterface = RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE,
 | 
			
		||||
    GetInputDeviceCapabilities = RETRO_ENVIRONMENT_GET_INPUT_DEVICE_CAPABILITIES,
 | 
			
		||||
    GetSensorInterface = RETRO_ENVIRONMENT_GET_SENSOR_INTERFACE,
 | 
			
		||||
    GetCameraInterface = RETRO_ENVIRONMENT_GET_CAMERA_INTERFACE,
 | 
			
		||||
    GetLogInterface = RETRO_ENVIRONMENT_GET_LOG_INTERFACE,
 | 
			
		||||
    GetPerfInterface = RETRO_ENVIRONMENT_GET_PERF_INTERFACE,
 | 
			
		||||
    GetLocationInterface = RETRO_ENVIRONMENT_GET_LOCATION_INTERFACE,
 | 
			
		||||
    GetCoreAssetsDirectory = RETRO_ENVIRONMENT_GET_CORE_ASSETS_DIRECTORY,
 | 
			
		||||
    GetSaveDirectory = RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY,
 | 
			
		||||
    SetSystemAvInfo = RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO,
 | 
			
		||||
    SetProcAddressCallback = RETRO_ENVIRONMENT_SET_PROC_ADDRESS_CALLBACK,
 | 
			
		||||
    SetSubsystemInfo = RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO,
 | 
			
		||||
    SetControllerInfo = RETRO_ENVIRONMENT_SET_CONTROLLER_INFO,
 | 
			
		||||
    SetMemoryMaps = RETRO_ENVIRONMENT_SET_MEMORY_MAPS,
 | 
			
		||||
    SetGeometry = RETRO_ENVIRONMENT_SET_GEOMETRY,
 | 
			
		||||
    GetUsername = RETRO_ENVIRONMENT_GET_USERNAME,
 | 
			
		||||
    GetLanguage = RETRO_ENVIRONMENT_GET_LANGUAGE,
 | 
			
		||||
    SetSerializationQuirks = RETRO_ENVIRONMENT_SET_SERIALIZATION_QUIRKS,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub trait HandlesEnvironment: Send + Sync + 'static {
 | 
			
		||||
    // TODO: wrap cmd+data in enum
 | 
			
		||||
    fn environment(&mut self, cmd: u32, data: *mut c_void) -> bool;
 | 
			
		||||
 | 
			
		||||
    fn SetRotation(&mut self, rotation: EnvRotation) -> bool;
 | 
			
		||||
    fn GetOverscan(&mut self, overscan: &mut bool) -> bool;
 | 
			
		||||
    fn GetCanDupe(&mut self, frame_duping: &mut bool) -> bool;
 | 
			
		||||
    fn SetMessage(&mut self, message: retro_message) -> bool;
 | 
			
		||||
    fn Shutdown(&mut self) -> bool;
 | 
			
		||||
    fn SetPerformanceLevel(&mut self, level: c_uint) -> bool;
 | 
			
		||||
    fn GetSystemDirectory(&mut self, path: &mut PathBuf) -> bool;
 | 
			
		||||
    fn SetPixelFormat(&mut self, format: EnvPixelFormat) -> bool;
 | 
			
		||||
    fn SetInputDescriptors(&mut self, input_descriptors: &[retro_input_descriptor]) -> bool;
 | 
			
		||||
    fn SetKeyboardCallback(&mut self, keyboard_callback: retro_keyboard_callback) -> bool;
 | 
			
		||||
    fn SetDiskControlInterface(&mut self, disk_control_callback: retro_disk_control_callback) -> bool;
 | 
			
		||||
    fn SetHwRender(&mut self, hw_render_callback: retro_hw_render_callback) -> bool;
 | 
			
		||||
    fn GetVariable(&mut self, variable: &mut EnvVariable) -> bool;
 | 
			
		||||
    fn SetVariables(&mut self, variables: &[EnvVariable]) -> bool;
 | 
			
		||||
    fn GetVariableUpdate(&mut self, variables_updated: &mut bool) -> bool;
 | 
			
		||||
    fn SetSupportNoGame(&mut self, supports_no_game: bool) -> bool;
 | 
			
		||||
    fn GetLibretroPath(&mut self, path: &mut PathBuf) -> bool;
 | 
			
		||||
    fn SetFrameTimeCallback(&mut self, frame_time_callback: retro_frame_time_callback) -> bool;
 | 
			
		||||
    fn SetAudioCallback(&mut self, audio_callback: retro_audio_callback) -> bool;
 | 
			
		||||
    fn GetRumbleInterface(&mut self, rumble_interface: &mut retro_rumble_interface) -> bool;
 | 
			
		||||
    fn GetInputDeviceCapabilities(&mut self, input_device_capabilities: &mut u64) -> bool;
 | 
			
		||||
    fn GetSensorInterface(&mut self, sensor_interface: &mut retro_sensor_interface) -> bool;
 | 
			
		||||
    fn GetCameraInterface(&mut self, camera_callback: &mut retro_camera_callback) -> bool;
 | 
			
		||||
    fn GetLogInterface(&mut self, log_callback: &mut retro_log_callback) -> bool;
 | 
			
		||||
    fn GetPerfInterface(&mut self, perf_callback: &mut retro_perf_callback) -> bool;
 | 
			
		||||
    fn GetLocationInterface(&mut self, location_callback: &mut retro_location_callback) -> bool;
 | 
			
		||||
    fn GetCoreAssetsDirectory(&mut self, path: &mut PathBuf) -> bool;
 | 
			
		||||
    fn GetSaveDirectory(&mut self, path: &mut PathBuf) -> bool;
 | 
			
		||||
    fn SetSystemAvInfo(&mut self, system_av_info: retro_system_av_info) -> bool;
 | 
			
		||||
    fn SetProcAddressCallback(&mut self, get_proc_address_interface: retro_get_proc_address_interface) -> bool;
 | 
			
		||||
    fn SetSubsystemInfo(&mut self, subsystem_info: retro_subsystem_info) -> bool;
 | 
			
		||||
    fn SetControllerInfo(&mut self, controller_info: retro_controller_info) -> bool;
 | 
			
		||||
    fn SetMemoryMaps(&mut self, memory_map: retro_memory_map) -> bool;
 | 
			
		||||
    fn SetGeometry(&mut self, game_geometry: retro_game_geometry) -> bool;
 | 
			
		||||
    fn GetUsername(&mut self, username: &mut String) -> bool;
 | 
			
		||||
    fn GetLanguage(&mut self, language: &mut EnvLanguage) -> bool;
 | 
			
		||||
    fn SetSerializationQuirks(&mut self, quirks: &mut u64) -> bool;
 | 
			
		||||
    fn set_rotation(&mut self, rotation: EnvRotation) -> bool { false }
 | 
			
		||||
    fn get_overscan(&mut self) -> Option<bool> { None }
 | 
			
		||||
    fn get_can_dupe(&mut self) -> Option<bool> { None }
 | 
			
		||||
    fn set_message(&mut self, message: retro_message) -> bool { false }
 | 
			
		||||
    fn shutdown(&mut self) -> bool { false }
 | 
			
		||||
    fn set_performance_level(&mut self, level: c_uint) -> bool { false }
 | 
			
		||||
    fn get_system_directory(&mut self) -> Option<PathBuf> { None }
 | 
			
		||||
    fn set_pixel_format(&mut self, format: EnvPixelFormat) -> bool { false }
 | 
			
		||||
    fn set_input_descriptors(&mut self, input_descriptors: &[retro_input_descriptor]) -> bool { false }
 | 
			
		||||
    fn set_keyboard_callback(&mut self, cb: retro_keyboard_callback) -> bool { false }
 | 
			
		||||
    fn set_disk_control_interface(&mut self, cb: retro_disk_control_callback) -> bool { false }
 | 
			
		||||
    fn set_hw_render(&mut self, hw_render_callback: retro_hw_render_callback) -> bool { false }
 | 
			
		||||
    fn get_variable(&mut self) -> Option<EnvVariable> { None }
 | 
			
		||||
    fn set_variables(&mut self, variables: &[EnvVariable]) -> bool { false }
 | 
			
		||||
    fn get_variable_update(&mut self) -> Option<bool> { None }
 | 
			
		||||
    fn set_support_no_game(&mut self, supports_no_game: bool) -> bool { false }
 | 
			
		||||
    fn get_libretro_path(&mut self) -> Option<PathBuf> { None }
 | 
			
		||||
    fn set_frame_time_callback(&mut self, cb: retro_frame_time_callback) -> bool { false }
 | 
			
		||||
    fn set_audio_callback(&mut self, audio_callback: retro_audio_callback) -> bool { false }
 | 
			
		||||
    fn get_rumble_interface(&mut self) -> Option<retro_rumble_interface> { None }
 | 
			
		||||
    fn get_input_device_capabilities(&mut self) -> Option<u64> { None }
 | 
			
		||||
    fn get_sensor_interface(&mut self) -> Option<retro_sensor_interface> { None }
 | 
			
		||||
    fn get_camera_interface(&mut self) -> Option<retro_camera_callback> { None }
 | 
			
		||||
    fn get_log_interface(&mut self) -> Option<retro_log_callback> { None }
 | 
			
		||||
    fn get_perf_interface(&mut self) -> Option<retro_perf_callback> { None }
 | 
			
		||||
    fn get_location_interface(&mut self) -> Option<retro_location_callback> { None }
 | 
			
		||||
    fn get_core_assets_directory(&mut self) -> Option<PathBuf> { None }
 | 
			
		||||
    fn get_save_directory(&mut self) -> Option<PathBuf> { None }
 | 
			
		||||
    fn set_system_av_info(&mut self, system_av_info: retro_system_av_info) -> bool { false }
 | 
			
		||||
    fn set_proc_address_callback(&mut self, cb: retro_get_proc_address_interface) -> bool { false }
 | 
			
		||||
    fn set_subsystem_info(&mut self, subsystem_info: retro_subsystem_info) -> bool { false }
 | 
			
		||||
    fn set_controller_info(&mut self, controller_info: retro_controller_info) -> bool { false }
 | 
			
		||||
    fn set_memory_maps(&mut self, memory_map: retro_memory_map) -> bool { false }
 | 
			
		||||
    fn set_geometry(&mut self, game_geometry: retro_game_geometry) -> bool { false }
 | 
			
		||||
    fn get_username(&mut self) -> Option<String> { None }
 | 
			
		||||
    fn get_language(&mut self) -> Option<EnvLanguage> { None }
 | 
			
		||||
    fn set_serialization_quirks(&mut self, quirks: &mut u64) -> bool { false }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub trait HandlesVideoRefresh: Send + Sync + 'static {
 | 
			
		||||
    fn video_refresh(&mut self, data: &[u8], width: c_uint, height: c_uint, pitch: c_uint);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,10 +2,13 @@ use core::convert::TryInto;
 | 
			
		|||
use core::ffi::c_void;
 | 
			
		||||
use core::slice::from_raw_parts;
 | 
			
		||||
 | 
			
		||||
use std::os::raw::c_uint;
 | 
			
		||||
use std::ffi::CString;
 | 
			
		||||
use std::os::raw::{c_uint, c_char};
 | 
			
		||||
 | 
			
		||||
use crate::libretro_convert::*;
 | 
			
		||||
use crate::libretro_loading::*;
 | 
			
		||||
use std::path::Path;
 | 
			
		||||
use num_enum::{IntoPrimitive, TryFromPrimitive};
 | 
			
		||||
 | 
			
		||||
static mut CB_SINGLETON: StaticCallbacks = StaticCallbacks {
 | 
			
		||||
    environment: None,
 | 
			
		||||
| 
						 | 
				
			
			@ -29,13 +32,80 @@ struct StaticCallbacks {
 | 
			
		|||
unsafe impl Sync for StaticCallbacks {}
 | 
			
		||||
 | 
			
		||||
impl StaticCallbacks {
 | 
			
		||||
    extern "C" fn environment_cb(cmd: u32, data: *mut c_void) -> bool {
 | 
			
		||||
        match unsafe { CB_SINGLETON.environment.as_mut() } {
 | 
			
		||||
            Some(cb) => cb.environment(cmd, data),
 | 
			
		||||
            None => false,
 | 
			
		||||
        }
 | 
			
		||||
    // helpers for environ cb
 | 
			
		||||
    fn clone_into_void<T: Clone>(data: *mut c_void, source: &T) -> Option<bool> {
 | 
			
		||||
        unsafe { (data as *mut T).as_mut() }?.clone_from(source);
 | 
			
		||||
        Some(true)
 | 
			
		||||
    }
 | 
			
		||||
    extern "C" fn video_refresh_cb(data: *const c_void, width: c_uint, height: c_uint, pitch: usize) {
 | 
			
		||||
    fn string_into_void(data: *mut c_void, source: impl AsRef<str>) -> Option<bool> {
 | 
			
		||||
        *unsafe { (data as *mut *const c_char).as_mut()? } = CString::new(source.as_ref()).ok()?.into_raw();
 | 
			
		||||
        Some(true)
 | 
			
		||||
    }
 | 
			
		||||
    fn path_into_void(data: *mut c_void, source: impl AsRef<Path>) -> Option<bool> {
 | 
			
		||||
        Self::string_into_void(data, source.as_ref().to_string_lossy())
 | 
			
		||||
    }
 | 
			
		||||
    fn from_void<T>(data: *mut c_void) -> Option<&'static mut T> {
 | 
			
		||||
        unsafe { (data as *mut T).as_mut() }
 | 
			
		||||
    }
 | 
			
		||||
    fn enum_from_void<T>(data: *mut c_void) -> Option<T>
 | 
			
		||||
        where T: TryFromPrimitive, <T as TryFromPrimitive>::Primitive: 'static
 | 
			
		||||
    {
 | 
			
		||||
        let number = Self::from_void(data).cloned()?;
 | 
			
		||||
        T::try_from_primitive(number).ok()
 | 
			
		||||
    }
 | 
			
		||||
    fn environment_cb_inner(cmd: u32, data: *mut c_void) -> Option<bool> {
 | 
			
		||||
        let mut handler = unsafe { CB_SINGLETON.environment.as_mut() }?;
 | 
			
		||||
        match cmd.try_into().ok()? {
 | 
			
		||||
            EnvironmentCmdData::SetRotation => handler.set_rotation(Self::enum_from_void(data)?),
 | 
			
		||||
            EnvironmentCmdData::GetOverscan => Self::clone_into_void(data, &handler.get_overscan()?)?,
 | 
			
		||||
            EnvironmentCmdData::GetCanDupe => Self::clone_into_void(data, &handler.get_can_dupe()?)?,
 | 
			
		||||
            EnvironmentCmdData::SetMessage => handler.set_message(*Self::from_void(data)?),
 | 
			
		||||
            EnvironmentCmdData::Shutdown => handler.shutdown(),
 | 
			
		||||
            EnvironmentCmdData::SetPerformanceLevel => handler.set_performance_level(*Self::from_void(data)?),
 | 
			
		||||
            EnvironmentCmdData::GetSystemDirectory => Self::path_into_void(data, handler.get_system_directory()?)?,
 | 
			
		||||
            EnvironmentCmdData::SetPixelFormat => handler.set_pixel_format(Self::enum_from_void(data)?),
 | 
			
		||||
            // TODO EnvironmentCmdData::SetInputDescriptors => {},
 | 
			
		||||
            // TODO EnvironmentCmdData::SetKeyboardCallback => {},
 | 
			
		||||
            // TODO EnvironmentCmdData::SetDiskControlInterface => {},
 | 
			
		||||
            // TODO EnvironmentCmdData::SetHwRender => {},
 | 
			
		||||
            // TODO EnvironmentCmdData::GetVariable => {}, -- also change to mut parameter?
 | 
			
		||||
            // TODO EnvironmentCmdData::SetVariables => {},
 | 
			
		||||
            EnvironmentCmdData::GetVariableUpdate => Self::clone_into_void(data, &handler.get_variable_update()?)?,
 | 
			
		||||
            EnvironmentCmdData::SetSupportNoGame => handler.set_support_no_game(*Self::from_void(data)?),
 | 
			
		||||
            EnvironmentCmdData::GetLibretroPath => Self::path_into_void(data, handler.get_libretro_path()?)?,
 | 
			
		||||
            // TODO EnvironmentCmdData::SetFrameTimeCallback => {},
 | 
			
		||||
            // TODO EnvironmentCmdData::SetAudioCallback => {},
 | 
			
		||||
            // TODO EnvironmentCmdData::GetRumbleInterface => {},
 | 
			
		||||
            EnvironmentCmdData::GetInputDeviceCapabilities => Self::clone_into_void(data, &handler.get_input_device_capabilities()?)?,
 | 
			
		||||
            // TODO EnvironmentCmdData::GetSensorInterface => {},
 | 
			
		||||
            // TODO EnvironmentCmdData::GetCameraInterface => {},
 | 
			
		||||
            // TODO EnvironmentCmdData::GetLogInterface => {},
 | 
			
		||||
            // TODO EnvironmentCmdData::GetPerfInterface => {},
 | 
			
		||||
            // TODO EnvironmentCmdData::GetLocationInterface => {},
 | 
			
		||||
            EnvironmentCmdData::GetCoreAssetsDirectory => Self::path_into_void(data, handler.get_core_assets_directory()?)?,
 | 
			
		||||
            EnvironmentCmdData::GetSaveDirectory => Self::path_into_void(data, handler.get_save_directory()?)?,
 | 
			
		||||
            EnvironmentCmdData::SetSystemAvInfo => handler.set_system_av_info(*Self::from_void(data)?),
 | 
			
		||||
            // TODO EnvironmentCmdData::SetProcAddressCallback => {},
 | 
			
		||||
            // TODO EnvironmentCmdData::SetSubsystemInfo => {},
 | 
			
		||||
            // TODO EnvironmentCmdData::SetControllerInfo => {},
 | 
			
		||||
            // TODO EnvironmentCmdData::SetMemoryMaps => {},
 | 
			
		||||
            EnvironmentCmdData::SetGeometry => handler.set_geometry(*Self::from_void(data)?),
 | 
			
		||||
            EnvironmentCmdData::GetUsername => Self::string_into_void(data, handler.get_username()?)?,
 | 
			
		||||
            EnvironmentCmdData::GetLanguage => Self::clone_into_void(data, &c_uint::from(handler.get_language()?))?,
 | 
			
		||||
            EnvironmentCmdData::SetSerializationQuirks => handler.set_serialization_quirks(Self::from_void(data)?),
 | 
			
		||||
            _ => false,
 | 
			
		||||
        }.into()
 | 
			
		||||
    }
 | 
			
		||||
    extern "C" fn environment_cb(cmd: u32, data: *mut c_void) -> bool {
 | 
			
		||||
        Self::environment_cb_inner(cmd, data).unwrap_or(false)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    extern "C" fn video_refresh_cb(
 | 
			
		||||
        data: *const c_void,
 | 
			
		||||
        width: c_uint,
 | 
			
		||||
        height: c_uint,
 | 
			
		||||
        pitch: usize,
 | 
			
		||||
    ) {
 | 
			
		||||
        if !data.is_null() {
 | 
			
		||||
            if let Some(cb) = unsafe { CB_SINGLETON.video_refresh.as_mut() } {
 | 
			
		||||
                let data = data as *const u8;
 | 
			
		||||
| 
						 | 
				
			
			@ -56,7 +126,7 @@ impl StaticCallbacks {
 | 
			
		|||
                Some(cb) => match data.is_null() {
 | 
			
		||||
                    true => 0,
 | 
			
		||||
                    false => cb.audio_sample_batch(from_raw_parts(data, frames)),
 | 
			
		||||
                }
 | 
			
		||||
                },
 | 
			
		||||
                None => 0,
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -74,22 +144,34 @@ impl StaticCallbacks {
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
    pub(crate) fn set_environment(cb: &'static mut dyn HandlesEnvironment) {
 | 
			
		||||
        unsafe { CB_SINGLETON.environment.replace(cb); }
 | 
			
		||||
        unsafe {
 | 
			
		||||
            CB_SINGLETON.environment.replace(cb);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    pub(crate) fn set_video_refresh(cb: &'static mut dyn HandlesVideoRefresh) {
 | 
			
		||||
        unsafe { CB_SINGLETON.video_refresh.replace(cb); }
 | 
			
		||||
        unsafe {
 | 
			
		||||
            CB_SINGLETON.video_refresh.replace(cb);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    pub(crate) fn set_audio_sample(cb: &'static mut dyn HandlesAudioSample) {
 | 
			
		||||
        unsafe { CB_SINGLETON.audio_sample.replace(cb); }
 | 
			
		||||
        unsafe {
 | 
			
		||||
            CB_SINGLETON.audio_sample.replace(cb);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    pub(crate) fn set_audio_sample_batch(cb: &'static mut dyn HandlesAudioSampleBatch) {
 | 
			
		||||
        unsafe { CB_SINGLETON.audio_sample_batch.replace(cb); }
 | 
			
		||||
        unsafe {
 | 
			
		||||
            CB_SINGLETON.audio_sample_batch.replace(cb);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    pub(crate) fn set_input_poll(cb: &'static mut dyn HandlesInputPoll) {
 | 
			
		||||
        unsafe { CB_SINGLETON.input_poll.replace(cb); }
 | 
			
		||||
        unsafe {
 | 
			
		||||
            CB_SINGLETON.input_poll.replace(cb);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    pub(crate) fn set_input_state(cb: &'static mut dyn HandlesInputState) {
 | 
			
		||||
        unsafe { CB_SINGLETON.input_state.replace(cb); }
 | 
			
		||||
        unsafe {
 | 
			
		||||
            CB_SINGLETON.input_state.replace(cb);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    pub(crate) fn reset() {
 | 
			
		||||
        unsafe {
 | 
			
		||||
| 
						 | 
				
			
			@ -115,9 +197,7 @@ impl<'a> From<LibretroApi<'a>> for LibretroWrapper<'a> {
 | 
			
		|||
        api.set_audio_sample_batch(Some(StaticCallbacks::audio_sample_batch_cb));
 | 
			
		||||
        api.set_input_poll(Some(StaticCallbacks::input_poll_cb));
 | 
			
		||||
        api.set_input_state(Some(StaticCallbacks::input_state_cb));
 | 
			
		||||
        LibretroWrapper {
 | 
			
		||||
            api,
 | 
			
		||||
        }
 | 
			
		||||
        LibretroWrapper { api }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -148,7 +228,10 @@ impl<'a> LibretroWrapper<'a> {
 | 
			
		|||
        let ptr: *mut dyn HandlesAudioSample = handler;
 | 
			
		||||
        StaticCallbacks::set_audio_sample(unsafe { ptr.as_mut() }.unwrap());
 | 
			
		||||
    }
 | 
			
		||||
    pub fn register_audio_sample_batch_handler(&self, handler: &'a mut dyn HandlesAudioSampleBatch) {
 | 
			
		||||
    pub fn register_audio_sample_batch_handler(
 | 
			
		||||
        &self,
 | 
			
		||||
        handler: &'a mut dyn HandlesAudioSampleBatch,
 | 
			
		||||
    ) {
 | 
			
		||||
        let ptr: *mut dyn HandlesAudioSampleBatch = handler;
 | 
			
		||||
        StaticCallbacks::set_audio_sample_batch(unsafe { ptr.as_mut() }.unwrap());
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -160,4 +243,20 @@ impl<'a> LibretroWrapper<'a> {
 | 
			
		|||
        let ptr: *mut dyn HandlesInputState = handler;
 | 
			
		||||
        StaticCallbacks::set_input_state(unsafe { ptr.as_mut() }.unwrap());
 | 
			
		||||
    }
 | 
			
		||||
    pub fn register_for_all<T>(&self, handler: &'a mut T)
 | 
			
		||||
    where
 | 
			
		||||
        T: HandlesEnvironment
 | 
			
		||||
            + HandlesVideoRefresh
 | 
			
		||||
            + HandlesAudioSample
 | 
			
		||||
            + HandlesAudioSampleBatch
 | 
			
		||||
            + HandlesInputPoll
 | 
			
		||||
            + HandlesInputState,
 | 
			
		||||
    {
 | 
			
		||||
        self.register_environment_handler(handler);
 | 
			
		||||
        self.register_video_refresh_handler(handler);
 | 
			
		||||
        self.register_audio_sample_handler(handler);
 | 
			
		||||
        self.register_audio_sample_batch_handler(handler);
 | 
			
		||||
        self.register_input_poll_handler(handler);
 | 
			
		||||
        self.register_input_state_handler(handler);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										155
									
								
								src/main.rs
									
										
									
									
									
								
							
							
						
						
									
										155
									
								
								src/main.rs
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -7,7 +7,7 @@ mod libretro_loading;
 | 
			
		|||
mod libretro_convert;
 | 
			
		||||
mod libretro_wrapper;
 | 
			
		||||
 | 
			
		||||
use std::ffi::{CStr, c_void};
 | 
			
		||||
use std::ffi::CStr;
 | 
			
		||||
use std::path::PathBuf;
 | 
			
		||||
 | 
			
		||||
use structopt::StructOpt;
 | 
			
		||||
| 
						 | 
				
			
			@ -16,159 +16,6 @@ use crate::libretro_convert::{HandlesEnvironment, HandlesVideoRefresh};
 | 
			
		|||
 | 
			
		||||
struct Foo;
 | 
			
		||||
impl HandlesEnvironment for Foo {
 | 
			
		||||
    fn environment(&mut self, cmd: u32, data: *mut c_void) -> bool {
 | 
			
		||||
        println!("environment cmd: {}", cmd);
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn SetRotation(&mut self, rotation: EnvRotation) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn GetOverscan(&mut self, overscan: &mut bool) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn GetCanDupe(&mut self, frame_duping: &mut bool) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn SetMessage(&mut self, message: retro_message) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn Shutdown(&mut self) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn SetPerformanceLevel(&mut self, level: c_uint) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn GetSystemDirectory(&mut self, path: &mut PathBuf) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn SetPixelFormat(&mut self, format: EnvPixelFormat) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn SetInputDescriptors(&mut self, input_descriptors: &[retro_input_descriptor]) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn SetKeyboardCallback(&mut self, keyboard_callback: retro_keyboard_callback) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn SetDiskControlInterface(&mut self, disk_control_callback: retro_disk_control_callback) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn SetHwRender(&mut self, hw_render_callback: retro_hw_render_callback) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn GetVariable(&mut self, variable: &mut EnvVariable) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn SetVariables(&mut self, variables: &[EnvVariable]) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn GetVariableUpdate(&mut self, variables_updated: &mut bool) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn SetSupportNoGame(&mut self, supports_no_game: bool) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn GetLibretroPath(&mut self, path: &mut PathBuf) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn SetFrameTimeCallback(&mut self, frame_time_callback: retro_frame_time_callback) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn SetAudioCallback(&mut self, audio_callback: retro_audio_callback) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn GetRumbleInterface(&mut self, rumble_interface: &mut retro_rumble_interface) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn GetInputDeviceCapabilities(&mut self, input_device_capabilities: &mut u64) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn GetSensorInterface(&mut self, sensor_interface: &mut retro_sensor_interface) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn GetCameraInterface(&mut self, camera_callback: &mut retro_camera_callback) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn GetLogInterface(&mut self, log_callback: &mut retro_log_callback) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn GetPerfInterface(&mut self, perf_callback: &mut retro_perf_callback) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn GetLocationInterface(&mut self, location_callback: &mut retro_location_callback) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn GetCoreAssetsDirectory(&mut self, path: &mut PathBuf) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn GetSaveDirectory(&mut self, path: &mut PathBuf) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn SetSystemAvInfo(&mut self, system_av_info: retro_system_av_info) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn SetProcAddressCallback(&mut self, get_proc_address_interface: retro_get_proc_address_interface) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn SetSubsystemInfo(&mut self, subsystem_info: retro_subsystem_info) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn SetControllerInfo(&mut self, controller_info: retro_controller_info) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn SetMemoryMaps(&mut self, memory_map: retro_memory_map) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn SetGeometry(&mut self, game_geometry: retro_game_geometry) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn GetUsername(&mut self, username: &mut String) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn GetLanguage(&mut self, language: &mut EnvLanguage) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn SetSerializationQuirks(&mut self, quirks: &mut u64) -> bool {
 | 
			
		||||
        false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl HandlesVideoRefresh for Foo {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue