start making giant match statement in environment cb wrapper

This commit is contained in:
lif 2019-11-10 23:21:38 -08:00
parent eaab387216
commit 498c874bc7
3 changed files with 208 additions and 263 deletions

View File

@ -1,19 +1,19 @@
use std::convert::{TryFrom, TryInto}; use std::convert::{TryFrom, TryInto};
use std::os::raw::{c_uint, c_void}; use std::os::raw::c_uint;
use std::path::PathBuf; use std::path::PathBuf;
use num_enum::TryFromPrimitive; use num_enum::{TryFromPrimitive, IntoPrimitive};
use crate::libretro_ffi::*; use crate::libretro_ffi::*;
#[derive(TryFromPrimitive)] #[derive(TryFromPrimitive, IntoPrimitive)]
#[repr(u32)] #[repr(u32)]
pub enum Region { pub enum Region {
NTSC = RETRO_REGION_NTSC, NTSC = RETRO_REGION_NTSC,
PAL = RETRO_REGION_PAL, PAL = RETRO_REGION_PAL,
} }
#[derive(TryFromPrimitive)] #[derive(TryFromPrimitive, IntoPrimitive)]
#[repr(u32)] #[repr(u32)]
pub enum DeviceType { pub enum DeviceType {
None = RETRO_DEVICE_NONE, None = RETRO_DEVICE_NONE,
@ -25,7 +25,7 @@ pub enum DeviceType {
Pointer = RETRO_DEVICE_POINTER, Pointer = RETRO_DEVICE_POINTER,
} }
#[derive(TryFromPrimitive)] #[derive(TryFromPrimitive, IntoPrimitive)]
#[repr(u32)] #[repr(u32)]
pub enum DeviceIndex { pub enum DeviceIndex {
Left = RETRO_DEVICE_INDEX_ANALOG_LEFT, Left = RETRO_DEVICE_INDEX_ANALOG_LEFT,
@ -33,7 +33,7 @@ pub enum DeviceIndex {
Button = RETRO_DEVICE_INDEX_ANALOG_BUTTON, Button = RETRO_DEVICE_INDEX_ANALOG_BUTTON,
} }
#[derive(TryFromPrimitive)] #[derive(TryFromPrimitive, IntoPrimitive)]
#[repr(u32)] #[repr(u32)]
pub enum JoypadButton { pub enum JoypadButton {
B = RETRO_DEVICE_ID_JOYPAD_B, B = RETRO_DEVICE_ID_JOYPAD_B,
@ -54,14 +54,14 @@ pub enum JoypadButton {
R3 = RETRO_DEVICE_ID_JOYPAD_R3, R3 = RETRO_DEVICE_ID_JOYPAD_R3,
} }
#[derive(TryFromPrimitive)] #[derive(TryFromPrimitive, IntoPrimitive)]
#[repr(u32)] #[repr(u32)]
pub enum AnalogAxis { pub enum AnalogAxis {
X = RETRO_DEVICE_ID_ANALOG_X, X = RETRO_DEVICE_ID_ANALOG_X,
Y = RETRO_DEVICE_ID_ANALOG_Y, Y = RETRO_DEVICE_ID_ANALOG_Y,
} }
#[derive(TryFromPrimitive)] #[derive(TryFromPrimitive, IntoPrimitive)]
#[repr(u32)] #[repr(u32)]
pub enum MouseButton { pub enum MouseButton {
X = RETRO_DEVICE_ID_MOUSE_X, X = RETRO_DEVICE_ID_MOUSE_X,
@ -77,7 +77,7 @@ pub enum MouseButton {
Button5 = RETRO_DEVICE_ID_MOUSE_BUTTON_5, Button5 = RETRO_DEVICE_ID_MOUSE_BUTTON_5,
} }
#[derive(TryFromPrimitive)] #[derive(TryFromPrimitive, IntoPrimitive)]
#[repr(u32)] #[repr(u32)]
pub enum LightGunButton { pub enum LightGunButton {
ScreenX = RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X, ScreenX = RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X,
@ -99,7 +99,7 @@ pub enum LightGunButton {
Pause = RETRO_DEVICE_ID_LIGHTGUN_PAUSE, Pause = RETRO_DEVICE_ID_LIGHTGUN_PAUSE,
} }
#[derive(TryFromPrimitive)] #[derive(TryFromPrimitive, IntoPrimitive)]
#[repr(u32)] #[repr(u32)]
pub enum PointerStat { pub enum PointerStat {
X = RETRO_DEVICE_ID_POINTER_X, 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)] #[repr(u32)]
pub enum EnvRotation { pub enum EnvRotation {
None = 0, None = 0,
@ -146,7 +146,7 @@ pub enum EnvRotation {
CounterClockwise270 = 3, CounterClockwise270 = 3,
} }
#[derive(TryFromPrimitive)] #[derive(TryFromPrimitive, IntoPrimitive)]
#[repr(u32)] #[repr(u32)]
pub enum EnvPixelFormat { pub enum EnvPixelFormat {
XRGB555 = retro_pixel_format_RETRO_PIXEL_FORMAT_0RGB1555, XRGB555 = retro_pixel_format_RETRO_PIXEL_FORMAT_0RGB1555,
@ -162,7 +162,7 @@ pub struct EnvVariable {
value: Option<String>, value: Option<String>,
} }
#[derive(TryFromPrimitive)] #[derive(TryFromPrimitive, IntoPrimitive)]
#[repr(u32)] #[repr(u32)]
pub enum EnvLanguage { pub enum EnvLanguage {
English = retro_language_RETRO_LANGUAGE_ENGLISH, English = retro_language_RETRO_LANGUAGE_ENGLISH,
@ -186,90 +186,89 @@ pub enum EnvLanguage {
Last = retro_language_RETRO_LANGUAGE_LAST, Last = retro_language_RETRO_LANGUAGE_LAST,
} }
// TODO: lifetime
// TODO: experimental calls // TODO: experimental calls
#[derive(TryFromPrimitive, IntoPrimitive)]
#[repr(u32)]
pub enum EnvironmentCmdData { pub enum EnvironmentCmdData {
SetRotation(EnvRotation), SetRotation = RETRO_ENVIRONMENT_SET_ROTATION,
GetOverscan(&'static mut bool), GetOverscan = RETRO_ENVIRONMENT_GET_OVERSCAN,
GetCanDupe(&'static mut bool), GetCanDupe = RETRO_ENVIRONMENT_GET_CAN_DUPE,
SetMessage(retro_message), // TODO SetMessage = RETRO_ENVIRONMENT_SET_MESSAGE,
Shutdown, Shutdown = RETRO_ENVIRONMENT_SHUTDOWN,
SetPerformanceLevel(c_uint), SetPerformanceLevel = RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL,
GetSystemDirectory(&'static mut PathBuf), GetSystemDirectory = RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY,
SetPixelFormat(EnvPixelFormat), SetPixelFormat = RETRO_ENVIRONMENT_SET_PIXEL_FORMAT,
SetInputDescriptors(&'static [retro_input_descriptor]), // TODO SetInputDescriptors = RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS,
SetKeyboardCallback(retro_keyboard_callback), // TODO SetKeyboardCallback = RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK,
SetDiskControlInterface(retro_disk_control_callback), // TODO SetDiskControlInterface = RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE,
SetHwRender(retro_hw_render_callback), // TODO SetHwRender = RETRO_ENVIRONMENT_SET_HW_RENDER,
GetVariable(&'static mut EnvVariable), GetVariable = RETRO_ENVIRONMENT_GET_VARIABLE,
SetVariables(&'static [EnvVariable]), SetVariables = RETRO_ENVIRONMENT_SET_VARIABLES,
GetVariableUpdate(&'static mut bool), GetVariableUpdate = RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE,
SetSupportNoGame(bool), SetSupportNoGame = RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME,
GetLibretroPath(&'static mut PathBuf), GetLibretroPath = RETRO_ENVIRONMENT_GET_LIBRETRO_PATH,
SetFrameTimeCallback(retro_frame_time_callback), // TODO SetFrameTimeCallback = RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK,
SetAudioCallback(retro_audio_callback), // TODO SetAudioCallback = RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK,
GetRumbleInterface(&'static mut retro_rumble_interface), // TODO GetRumbleInterface = RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE,
GetInputDeviceCapabilities(&'static mut u64), // TODO GetInputDeviceCapabilities = RETRO_ENVIRONMENT_GET_INPUT_DEVICE_CAPABILITIES,
GetSensorInterface(&'static mut retro_sensor_interface), // TODO GetSensorInterface = RETRO_ENVIRONMENT_GET_SENSOR_INTERFACE,
GetCameraInterface(&'static mut retro_camera_callback), // TODO GetCameraInterface = RETRO_ENVIRONMENT_GET_CAMERA_INTERFACE,
GetLogInterface(&'static mut retro_log_callback), // TODO GetLogInterface = RETRO_ENVIRONMENT_GET_LOG_INTERFACE,
GetPerfInterface(&'static mut retro_perf_callback), // TODO GetPerfInterface = RETRO_ENVIRONMENT_GET_PERF_INTERFACE,
GetLocationInterface(&'static mut retro_location_callback), // TODO GetLocationInterface = RETRO_ENVIRONMENT_GET_LOCATION_INTERFACE,
GetCoreAssetsDirectory(&'static mut PathBuf), GetCoreAssetsDirectory = RETRO_ENVIRONMENT_GET_CORE_ASSETS_DIRECTORY,
GetSaveDirectory(&'static mut PathBuf), GetSaveDirectory = RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY,
SetSystemAvInfo(retro_system_av_info), SetSystemAvInfo = RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO,
SetProcAddressCallback(retro_get_proc_address_interface), // TODO SetProcAddressCallback = RETRO_ENVIRONMENT_SET_PROC_ADDRESS_CALLBACK,
SetSubsystemInfo(retro_subsystem_info), // TODO SetSubsystemInfo = RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO,
SetControllerInfo(retro_controller_info), // TODO SetControllerInfo = RETRO_ENVIRONMENT_SET_CONTROLLER_INFO,
SetMemoryMaps(retro_memory_map), // TODO SetMemoryMaps = RETRO_ENVIRONMENT_SET_MEMORY_MAPS,
SetGeometry(retro_game_geometry), // TODO SetGeometry = RETRO_ENVIRONMENT_SET_GEOMETRY,
GetUsername(&'static mut String), GetUsername = RETRO_ENVIRONMENT_GET_USERNAME,
GetLanguage(&'static mut EnvLanguage), GetLanguage = RETRO_ENVIRONMENT_GET_LANGUAGE,
SetSerializationQuirks(&'static mut u64), // TODO SetSerializationQuirks = RETRO_ENVIRONMENT_SET_SERIALIZATION_QUIRKS,
} }
pub trait HandlesEnvironment: Send + Sync + 'static { pub trait HandlesEnvironment: Send + Sync + 'static {
// TODO: wrap cmd+data in enum fn set_rotation(&mut self, rotation: EnvRotation) -> bool { false }
fn environment(&mut self, cmd: u32, data: *mut c_void) -> bool; fn get_overscan(&mut self) -> Option<bool> { None }
fn get_can_dupe(&mut self) -> Option<bool> { None }
fn SetRotation(&mut self, rotation: EnvRotation) -> bool; fn set_message(&mut self, message: retro_message) -> bool { false }
fn GetOverscan(&mut self, overscan: &mut bool) -> bool; fn shutdown(&mut self) -> bool { false }
fn GetCanDupe(&mut self, frame_duping: &mut bool) -> bool; fn set_performance_level(&mut self, level: c_uint) -> bool { false }
fn SetMessage(&mut self, message: retro_message) -> bool; fn get_system_directory(&mut self) -> Option<PathBuf> { None }
fn Shutdown(&mut self) -> bool; fn set_pixel_format(&mut self, format: EnvPixelFormat) -> bool { false }
fn SetPerformanceLevel(&mut self, level: c_uint) -> bool; fn set_input_descriptors(&mut self, input_descriptors: &[retro_input_descriptor]) -> bool { false }
fn GetSystemDirectory(&mut self, path: &mut PathBuf) -> bool; fn set_keyboard_callback(&mut self, cb: retro_keyboard_callback) -> bool { false }
fn SetPixelFormat(&mut self, format: EnvPixelFormat) -> bool; fn set_disk_control_interface(&mut self, cb: retro_disk_control_callback) -> bool { false }
fn SetInputDescriptors(&mut self, input_descriptors: &[retro_input_descriptor]) -> bool; fn set_hw_render(&mut self, hw_render_callback: retro_hw_render_callback) -> bool { false }
fn SetKeyboardCallback(&mut self, keyboard_callback: retro_keyboard_callback) -> bool; fn get_variable(&mut self) -> Option<EnvVariable> { None }
fn SetDiskControlInterface(&mut self, disk_control_callback: retro_disk_control_callback) -> bool; fn set_variables(&mut self, variables: &[EnvVariable]) -> bool { false }
fn SetHwRender(&mut self, hw_render_callback: retro_hw_render_callback) -> bool; fn get_variable_update(&mut self) -> Option<bool> { None }
fn GetVariable(&mut self, variable: &mut EnvVariable) -> bool; fn set_support_no_game(&mut self, supports_no_game: bool) -> bool { false }
fn SetVariables(&mut self, variables: &[EnvVariable]) -> bool; fn get_libretro_path(&mut self) -> Option<PathBuf> { None }
fn GetVariableUpdate(&mut self, variables_updated: &mut bool) -> bool; fn set_frame_time_callback(&mut self, cb: retro_frame_time_callback) -> bool { false }
fn SetSupportNoGame(&mut self, supports_no_game: bool) -> bool; fn set_audio_callback(&mut self, audio_callback: retro_audio_callback) -> bool { false }
fn GetLibretroPath(&mut self, path: &mut PathBuf) -> bool; fn get_rumble_interface(&mut self) -> Option<retro_rumble_interface> { None }
fn SetFrameTimeCallback(&mut self, frame_time_callback: retro_frame_time_callback) -> bool; fn get_input_device_capabilities(&mut self) -> Option<u64> { None }
fn SetAudioCallback(&mut self, audio_callback: retro_audio_callback) -> bool; fn get_sensor_interface(&mut self) -> Option<retro_sensor_interface> { None }
fn GetRumbleInterface(&mut self, rumble_interface: &mut retro_rumble_interface) -> bool; fn get_camera_interface(&mut self) -> Option<retro_camera_callback> { None }
fn GetInputDeviceCapabilities(&mut self, input_device_capabilities: &mut u64) -> bool; fn get_log_interface(&mut self) -> Option<retro_log_callback> { None }
fn GetSensorInterface(&mut self, sensor_interface: &mut retro_sensor_interface) -> bool; fn get_perf_interface(&mut self) -> Option<retro_perf_callback> { None }
fn GetCameraInterface(&mut self, camera_callback: &mut retro_camera_callback) -> bool; fn get_location_interface(&mut self) -> Option<retro_location_callback> { None }
fn GetLogInterface(&mut self, log_callback: &mut retro_log_callback) -> bool; fn get_core_assets_directory(&mut self) -> Option<PathBuf> { None }
fn GetPerfInterface(&mut self, perf_callback: &mut retro_perf_callback) -> bool; fn get_save_directory(&mut self) -> Option<PathBuf> { None }
fn GetLocationInterface(&mut self, location_callback: &mut retro_location_callback) -> bool; fn set_system_av_info(&mut self, system_av_info: retro_system_av_info) -> bool { false }
fn GetCoreAssetsDirectory(&mut self, path: &mut PathBuf) -> bool; fn set_proc_address_callback(&mut self, cb: retro_get_proc_address_interface) -> bool { false }
fn GetSaveDirectory(&mut self, path: &mut PathBuf) -> bool; fn set_subsystem_info(&mut self, subsystem_info: retro_subsystem_info) -> bool { false }
fn SetSystemAvInfo(&mut self, system_av_info: retro_system_av_info) -> bool; fn set_controller_info(&mut self, controller_info: retro_controller_info) -> bool { false }
fn SetProcAddressCallback(&mut self, get_proc_address_interface: retro_get_proc_address_interface) -> bool; fn set_memory_maps(&mut self, memory_map: retro_memory_map) -> bool { false }
fn SetSubsystemInfo(&mut self, subsystem_info: retro_subsystem_info) -> bool; fn set_geometry(&mut self, game_geometry: retro_game_geometry) -> bool { false }
fn SetControllerInfo(&mut self, controller_info: retro_controller_info) -> bool; fn get_username(&mut self) -> Option<String> { None }
fn SetMemoryMaps(&mut self, memory_map: retro_memory_map) -> bool; fn get_language(&mut self) -> Option<EnvLanguage> { None }
fn SetGeometry(&mut self, game_geometry: retro_game_geometry) -> bool; fn set_serialization_quirks(&mut self, quirks: &mut u64) -> bool { false }
fn GetUsername(&mut self, username: &mut String) -> bool;
fn GetLanguage(&mut self, language: &mut EnvLanguage) -> bool;
fn SetSerializationQuirks(&mut self, quirks: &mut u64) -> bool;
} }
pub trait HandlesVideoRefresh: Send + Sync + 'static { pub trait HandlesVideoRefresh: Send + Sync + 'static {
fn video_refresh(&mut self, data: &[u8], width: c_uint, height: c_uint, pitch: c_uint); fn video_refresh(&mut self, data: &[u8], width: c_uint, height: c_uint, pitch: c_uint);
} }

View File

@ -2,10 +2,13 @@ use core::convert::TryInto;
use core::ffi::c_void; use core::ffi::c_void;
use core::slice::from_raw_parts; 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_convert::*;
use crate::libretro_loading::*; use crate::libretro_loading::*;
use std::path::Path;
use num_enum::{IntoPrimitive, TryFromPrimitive};
static mut CB_SINGLETON: StaticCallbacks = StaticCallbacks { static mut CB_SINGLETON: StaticCallbacks = StaticCallbacks {
environment: None, environment: None,
@ -29,13 +32,80 @@ struct StaticCallbacks {
unsafe impl Sync for StaticCallbacks {} unsafe impl Sync for StaticCallbacks {}
impl StaticCallbacks { impl StaticCallbacks {
extern "C" fn environment_cb(cmd: u32, data: *mut c_void) -> bool { // helpers for environ cb
match unsafe { CB_SINGLETON.environment.as_mut() } { fn clone_into_void<T: Clone>(data: *mut c_void, source: &T) -> Option<bool> {
Some(cb) => cb.environment(cmd, data), unsafe { (data as *mut T).as_mut() }?.clone_from(source);
None => false, 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 !data.is_null() {
if let Some(cb) = unsafe { CB_SINGLETON.video_refresh.as_mut() } { if let Some(cb) = unsafe { CB_SINGLETON.video_refresh.as_mut() } {
let data = data as *const u8; let data = data as *const u8;
@ -56,7 +126,7 @@ impl StaticCallbacks {
Some(cb) => match data.is_null() { Some(cb) => match data.is_null() {
true => 0, true => 0,
false => cb.audio_sample_batch(from_raw_parts(data, frames)), false => cb.audio_sample_batch(from_raw_parts(data, frames)),
} },
None => 0, None => 0,
} }
} }
@ -74,22 +144,34 @@ impl StaticCallbacks {
} }
} }
pub(crate) fn set_environment(cb: &'static mut dyn HandlesEnvironment) { 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) { 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) { 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) { 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) { 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) { 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() { pub(crate) fn reset() {
unsafe { 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_audio_sample_batch(Some(StaticCallbacks::audio_sample_batch_cb));
api.set_input_poll(Some(StaticCallbacks::input_poll_cb)); api.set_input_poll(Some(StaticCallbacks::input_poll_cb));
api.set_input_state(Some(StaticCallbacks::input_state_cb)); api.set_input_state(Some(StaticCallbacks::input_state_cb));
LibretroWrapper { LibretroWrapper { api }
api,
}
} }
} }
@ -148,7 +228,10 @@ impl<'a> LibretroWrapper<'a> {
let ptr: *mut dyn HandlesAudioSample = handler; let ptr: *mut dyn HandlesAudioSample = handler;
StaticCallbacks::set_audio_sample(unsafe { ptr.as_mut() }.unwrap()); 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; let ptr: *mut dyn HandlesAudioSampleBatch = handler;
StaticCallbacks::set_audio_sample_batch(unsafe { ptr.as_mut() }.unwrap()); StaticCallbacks::set_audio_sample_batch(unsafe { ptr.as_mut() }.unwrap());
} }
@ -160,4 +243,20 @@ impl<'a> LibretroWrapper<'a> {
let ptr: *mut dyn HandlesInputState = handler; let ptr: *mut dyn HandlesInputState = handler;
StaticCallbacks::set_input_state(unsafe { ptr.as_mut() }.unwrap()); 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);
}
} }

View File

@ -7,7 +7,7 @@ mod libretro_loading;
mod libretro_convert; mod libretro_convert;
mod libretro_wrapper; mod libretro_wrapper;
use std::ffi::{CStr, c_void}; use std::ffi::CStr;
use std::path::PathBuf; use std::path::PathBuf;
use structopt::StructOpt; use structopt::StructOpt;
@ -16,159 +16,6 @@ use crate::libretro_convert::{HandlesEnvironment, HandlesVideoRefresh};
struct Foo; struct Foo;
impl HandlesEnvironment for 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 { impl HandlesVideoRefresh for Foo {