The rest of the functions - but not a good answer for callbacks yet
This commit is contained in:
parent
6448c0a040
commit
e34b9daa38
|
@ -1,35 +1,60 @@
|
|||
use std::os::raw::{c_char, c_uint, c_void};
|
||||
use std::path::Path;
|
||||
|
||||
use failure::Fallible;
|
||||
use libloading;
|
||||
|
||||
use crate::libretro_types::*;
|
||||
use libloading;
|
||||
use std::ffi::OsStr;
|
||||
|
||||
pub struct LibretroApi<'a> {
|
||||
pub retro_set_environment: libloading::Symbol<'a, unsafe extern "C" fn(arg1: retro_environment_t)>,
|
||||
pub retro_set_video_refresh: libloading::Symbol<'a, unsafe extern "C" fn(arg1: retro_video_refresh_t)>,
|
||||
pub retro_set_audio_sample: libloading::Symbol<'a, unsafe extern "C" fn(arg1: retro_audio_sample_t)>,
|
||||
pub retro_set_audio_sample_batch: libloading::Symbol<'a, unsafe extern "C" fn(arg1: retro_audio_sample_batch_t)>,
|
||||
pub retro_set_input_poll: libloading::Symbol<'a, unsafe extern "C" fn(arg1: retro_input_poll_t)>,
|
||||
pub retro_set_input_state: libloading::Symbol<'a, unsafe extern "C" fn(arg1: retro_input_state_t)>,
|
||||
pub retro_set_environment:
|
||||
libloading::Symbol<'a, unsafe extern "C" fn(arg1: retro_environment_t)>,
|
||||
pub retro_set_video_refresh:
|
||||
libloading::Symbol<'a, unsafe extern "C" fn(arg1: retro_video_refresh_t)>,
|
||||
pub retro_set_audio_sample:
|
||||
libloading::Symbol<'a, unsafe extern "C" fn(arg1: retro_audio_sample_t)>,
|
||||
pub retro_set_audio_sample_batch:
|
||||
libloading::Symbol<'a, unsafe extern "C" fn(arg1: retro_audio_sample_batch_t)>,
|
||||
pub retro_set_input_poll:
|
||||
libloading::Symbol<'a, unsafe extern "C" fn(arg1: retro_input_poll_t)>,
|
||||
pub retro_set_input_state:
|
||||
libloading::Symbol<'a, unsafe extern "C" fn(arg1: retro_input_state_t)>,
|
||||
pub retro_init: libloading::Symbol<'a, unsafe extern "C" fn()>,
|
||||
pub retro_deinit: libloading::Symbol<'a, unsafe extern "C" fn()>,
|
||||
pub retro_api_version: libloading::Symbol<'a, unsafe extern "C" fn() -> c_uint>,
|
||||
pub retro_get_system_info: libloading::Symbol<'a, unsafe extern "C" fn(info: *mut retro_system_info)>,
|
||||
pub retro_get_system_av_info: libloading::Symbol<'a, unsafe extern "C" fn(info: *mut retro_system_av_info)>,
|
||||
pub retro_set_controller_port_device: libloading::Symbol<'a, unsafe extern "C" fn(port: c_uint, device: c_uint)>,
|
||||
pub retro_get_system_info:
|
||||
libloading::Symbol<'a, unsafe extern "C" fn(info: *mut retro_system_info)>,
|
||||
pub retro_get_system_av_info:
|
||||
libloading::Symbol<'a, unsafe extern "C" fn(info: *mut retro_system_av_info)>,
|
||||
pub retro_set_controller_port_device:
|
||||
libloading::Symbol<'a, unsafe extern "C" fn(port: c_uint, device: c_uint)>,
|
||||
pub retro_reset: libloading::Symbol<'a, unsafe extern "C" fn()>,
|
||||
pub retro_run: libloading::Symbol<'a, unsafe extern "C" fn()>,
|
||||
pub retro_serialize_size: libloading::Symbol<'a, unsafe extern "C" fn() -> usize>,
|
||||
pub retro_serialize: libloading::Symbol<'a, unsafe extern "C" fn(data: *mut c_void, size: usize) -> bool>,
|
||||
pub retro_unserialize: libloading::Symbol<'a, unsafe extern "C" fn(data: *const c_void, size: usize) -> bool>,
|
||||
pub retro_serialize:
|
||||
libloading::Symbol<'a, unsafe extern "C" fn(data: *mut c_void, size: usize) -> bool>,
|
||||
pub retro_unserialize:
|
||||
libloading::Symbol<'a, unsafe extern "C" fn(data: *const c_void, size: usize) -> bool>,
|
||||
pub retro_cheat_reset: libloading::Symbol<'a, unsafe extern "C" fn()>,
|
||||
pub retro_cheat_set: libloading::Symbol<'a, unsafe extern "C" fn(index: c_uint, enabled: bool, code: *const c_char)>,
|
||||
pub retro_load_game: libloading::Symbol<'a, unsafe extern "C" fn(game: *const retro_game_info) -> bool>,
|
||||
pub retro_load_game_special: libloading::Symbol<'a, unsafe extern "C" fn(game_type: c_uint, info: *const retro_game_info, num_info: usize) -> bool>,
|
||||
pub retro_cheat_set: libloading::Symbol<
|
||||
'a,
|
||||
unsafe extern "C" fn(index: c_uint, enabled: bool, code: *const c_char),
|
||||
>,
|
||||
pub retro_load_game:
|
||||
libloading::Symbol<'a, unsafe extern "C" fn(game: *const retro_game_info) -> bool>,
|
||||
pub retro_load_game_special: libloading::Symbol<
|
||||
'a,
|
||||
unsafe extern "C" fn(
|
||||
game_type: c_uint,
|
||||
info: *const retro_game_info,
|
||||
num_info: usize,
|
||||
) -> bool,
|
||||
>,
|
||||
pub retro_unload_game: libloading::Symbol<'a, unsafe extern "C" fn()>,
|
||||
pub retro_get_region: libloading::Symbol<'a, unsafe extern "C" fn() -> c_uint>,
|
||||
pub retro_get_memory_data: libloading::Symbol<'a, unsafe extern "C" fn(id: c_uint) -> *mut c_void>,
|
||||
pub retro_get_memory_data:
|
||||
libloading::Symbol<'a, unsafe extern "C" fn(id: c_uint) -> *mut c_void>,
|
||||
pub retro_get_memory_size: libloading::Symbol<'a, unsafe extern "C" fn(id: c_uint) -> usize>,
|
||||
}
|
||||
|
||||
|
@ -66,20 +91,37 @@ impl<'a> LibretroApi<'a> {
|
|||
}
|
||||
}
|
||||
/// retro_set_environment() must be called before retro_init().
|
||||
pub fn init(&self) {
|
||||
unsafe {
|
||||
// TODO assert!(called retro_set_environment);
|
||||
(&self.retro_init)();
|
||||
}
|
||||
pub fn set_environment(&self, cb: retro_environment_t) {
|
||||
unsafe { (&self.retro_set_environment)(cb) }
|
||||
}
|
||||
pub fn set_video_refresh(&self, cb: retro_video_refresh_t) {
|
||||
unsafe { (&self.retro_set_video_refresh)(env) }
|
||||
}
|
||||
pub fn set_audio_sample(&self, cb: retro_audio_sample_t) {
|
||||
unsafe { (&self.retro_set_audio_sample)(env) }
|
||||
}
|
||||
pub fn set_audio_sample_batch(&self, cb: retro_audio_sample_batch_t) {
|
||||
unsafe { (&self.retro_set_audio_sample_batch)(env) }
|
||||
}
|
||||
pub fn set_input_poll(&self, cb: retro_input_poll_t) {
|
||||
unsafe { (&self.retro_set_input_poll)(env) }
|
||||
}
|
||||
pub fn set_input_state(&self, cb: retro_input_state_t) {
|
||||
unsafe { (&self.retro_set_input_state)(env) }
|
||||
}
|
||||
/// retro_set_environment() must be called before retro_init().
|
||||
pub fn retro_set_environment(&self, env: retro_environment_t) {
|
||||
unsafe {
|
||||
(&self.retro_set_environment)(env);
|
||||
}
|
||||
pub fn init(&self) {
|
||||
// TODO assert!(called retro_set_environment);
|
||||
unsafe { (&self.retro_init)() }
|
||||
}
|
||||
/** Gets statically known system info.
|
||||
* Can be called at any time, even before retro_init(). */
|
||||
pub fn deinit(&self) {
|
||||
unsafe { (&self.retro_deinit)() }
|
||||
}
|
||||
/// Must return RETRO_API_VERSION. Used to validate ABI compatibility when the API is revised.
|
||||
pub fn api_version(&self) -> u32 {
|
||||
unsafe { (&self.retro_api_version)() as u32 }
|
||||
}
|
||||
/// Gets statically known system info. Can be called at any time, even before retro_init().
|
||||
pub fn get_system_info(&self) -> retro_system_info {
|
||||
unsafe {
|
||||
let mut info = ::std::mem::zeroed::<retro_system_info>();
|
||||
|
@ -100,4 +142,105 @@ impl<'a> LibretroApi<'a> {
|
|||
av_info
|
||||
}
|
||||
}
|
||||
/** Sets device to be used for player 'port'.
|
||||
* By default, RETRO_DEVICE_JOYPAD is assumed to be plugged into all
|
||||
* available ports.
|
||||
* Setting a particular device type is not a guarantee that libretro cores
|
||||
* will only poll input based on that particular device type. It is only a
|
||||
* hint to the libretro core when a core cannot automatically detect the
|
||||
* appropriate input device type on its own. It is also relevant when a
|
||||
* core can change its behavior depending on device type.
|
||||
*
|
||||
* As part of the core's implementation of retro_set_controller_port_device,
|
||||
* the core should call RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS to notify the
|
||||
* frontend if the descriptions for any controls have changed as a
|
||||
* result of changing the device type.
|
||||
*/
|
||||
pub fn set_controller_port_device(&self, port: u32, device: u32) {
|
||||
unsafe { (&self.retro_set_controller_port_device)(port, device) }
|
||||
}
|
||||
/// Resets the current game.
|
||||
pub fn reset(&self) {
|
||||
unsafe { (&self.retro_reset)() }
|
||||
}
|
||||
/** Runs the game for one video frame.
|
||||
* During retro_run(), input_poll callback must be called at least once.
|
||||
*
|
||||
* If a frame is not rendered for reasons where a game "dropped" a frame,
|
||||
* this still counts as a frame, and retro_run() should explicitly dupe
|
||||
* a frame if GET_CAN_DUPE returns true.
|
||||
* In this case, the video callback can take a NULL argument for data.
|
||||
*/
|
||||
pub fn run(&self) {
|
||||
unsafe { (&self.retro_run)() }
|
||||
}
|
||||
/// Serializes internal state.
|
||||
pub fn serialize(&self) -> Fallible<Vec<u8>> {
|
||||
let size = unsafe { (&self.retro_serialize_size)() };
|
||||
let mut vec = Vec::with_capacity(size);
|
||||
vec.resize(size, 0);
|
||||
if unsafe { (&self.retro_serialize)(vec.as_mut_ptr() as *mut c_void, size) } {
|
||||
Ok(vec)
|
||||
} else {
|
||||
Err(failure::err_msg("Serialize failed"))
|
||||
}
|
||||
}
|
||||
pub fn unserialize(&self, data: &[u8]) -> Fallible<()> {
|
||||
if unsafe { (&self.retro_unserialize)(data.as_ptr() as *const c_void, data.len()) } {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(failure::err_msg("Unserialize failed"))
|
||||
}
|
||||
}
|
||||
pub fn cheat_reset(&self) {
|
||||
unsafe { (&self.retro_cheat_reset)() }
|
||||
}
|
||||
pub fn cheat_set(&self, index: u32, enabled: bool, code: &str) {
|
||||
unsafe { (&self.retro_cheat_set)(index, enabled, code.as_bytes().as_ptr() as *const c_char) }
|
||||
}
|
||||
/// Loads a game.
|
||||
pub fn load_game(
|
||||
&self,
|
||||
path: Option<&Path>,
|
||||
data: Option<&[u8]>,
|
||||
meta: Option<&str>,
|
||||
) -> Fallible<()> {
|
||||
let mut game = retro_game_info {
|
||||
path: std::ptr::null(),
|
||||
data: std::ptr::null(),
|
||||
size: 0,
|
||||
meta: std::ptr::null(),
|
||||
};
|
||||
if let Some(p) = path.and_then(Path::to_str) {
|
||||
game.path = p.as_bytes().as_ptr() as *const c_char;
|
||||
}
|
||||
if let Some(d) = data {
|
||||
game.data = d.as_ptr() as *const c_void;
|
||||
game.size = d.len();
|
||||
}
|
||||
if let Some(m) = meta {
|
||||
game.meta = m.as_bytes().as_ptr() as *const c_char;
|
||||
}
|
||||
|
||||
if unsafe { (&self.retro_load_game)(&game) } {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(failure::err_msg("Failed to load game"))
|
||||
}
|
||||
}
|
||||
/// Unloads the currently loaded game. Called before deinit().
|
||||
pub fn unload_game(&self) {
|
||||
unsafe { (&self.retro_unload_game)() }
|
||||
}
|
||||
pub fn get_region(&self) -> u32 {
|
||||
unsafe { (&self.retro_get_region)() as u32 }
|
||||
}
|
||||
/// Gets region of memory
|
||||
pub fn get_memory(&self, id: u32) -> &mut [u8] {
|
||||
unsafe {
|
||||
let data = (&self.retro_get_memory_data)(id);
|
||||
let size = (&self.retro_get_memory_size)(id);
|
||||
std::slice::from_raw_parts_mut(data as *mut u8, size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue