initial commit
This commit is contained in:
commit
6448c0a040
|
@ -0,0 +1,4 @@
|
||||||
|
/target
|
||||||
|
**/*.rs.bk
|
||||||
|
/.idea
|
||||||
|
/Cargo.lock
|
|
@ -0,0 +1,12 @@
|
||||||
|
[package]
|
||||||
|
name = "rustro"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["lifning <lifning+git@pm.me>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
failure = "^0.1"
|
||||||
|
libloading = "^0.5"
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
bindgen = "^0.51" # keep an eye on https://github.com/rust-lang/rust-bindgen/issues/1541
|
|
@ -0,0 +1,29 @@
|
||||||
|
extern crate bindgen;
|
||||||
|
|
||||||
|
use std::env;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// Tell cargo to invalidate the built crate whenever the wrapper changes
|
||||||
|
println!("cargo:rerun-if-changed=libretro.h");
|
||||||
|
|
||||||
|
// The bindgen::Builder is the main entry point
|
||||||
|
// to bindgen, and lets you build up options for
|
||||||
|
// the resulting bindings.
|
||||||
|
let bindings = bindgen::Builder::default()
|
||||||
|
// The input header we would like to generate
|
||||||
|
// bindings for.
|
||||||
|
.header("libretro.h")
|
||||||
|
// We use libloading to dlopen() and dlsym() the cores at runtime.
|
||||||
|
.ignore_functions()
|
||||||
|
// Finish the builder and generate the bindings.
|
||||||
|
.generate()
|
||||||
|
// Unwrap the Result and panic on failure.
|
||||||
|
.expect("Unable to generate bindings");
|
||||||
|
|
||||||
|
// Write the bindings to the $OUT_DIR/bindings.rs file.
|
||||||
|
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
|
||||||
|
bindings
|
||||||
|
.write_to_file(out_path.join("libretro_types.rs"))
|
||||||
|
.expect("Couldn't write bindings!");
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,103 @@
|
||||||
|
use std::os::raw::{c_char, c_uint, c_void};
|
||||||
|
|
||||||
|
use failure::Fallible;
|
||||||
|
use libloading;
|
||||||
|
|
||||||
|
use crate::libretro_types::*;
|
||||||
|
|
||||||
|
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_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_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_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_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_size: libloading::Symbol<'a, unsafe extern "C" fn(id: c_uint) -> usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> LibretroApi<'a> {
|
||||||
|
pub fn from_library(lib: &'a libloading::Library) -> Fallible<Self> {
|
||||||
|
unsafe {
|
||||||
|
Ok(LibretroApi {
|
||||||
|
retro_set_environment: lib.get(b"retro_set_environment")?,
|
||||||
|
retro_set_video_refresh: lib.get(b"retro_set_video_refresh")?,
|
||||||
|
retro_set_audio_sample: lib.get(b"retro_set_audio_sample")?,
|
||||||
|
retro_set_audio_sample_batch: lib.get(b"retro_set_audio_sample_batch")?,
|
||||||
|
retro_set_input_poll: lib.get(b"retro_set_input_poll")?,
|
||||||
|
retro_set_input_state: lib.get(b"retro_set_input_state")?,
|
||||||
|
retro_init: lib.get(b"retro_init")?,
|
||||||
|
retro_deinit: lib.get(b"retro_deinit")?,
|
||||||
|
retro_api_version: lib.get(b"retro_api_version")?,
|
||||||
|
retro_get_system_info: lib.get(b"retro_get_system_info")?,
|
||||||
|
retro_get_system_av_info: lib.get(b"retro_get_system_av_info")?,
|
||||||
|
retro_set_controller_port_device: lib.get(b"retro_set_controller_port_device")?,
|
||||||
|
retro_reset: lib.get(b"retro_reset")?,
|
||||||
|
retro_run: lib.get(b"retro_run")?,
|
||||||
|
retro_serialize_size: lib.get(b"retro_serialize_size")?,
|
||||||
|
retro_serialize: lib.get(b"retro_serialize")?,
|
||||||
|
retro_unserialize: lib.get(b"retro_unserialize")?,
|
||||||
|
retro_cheat_reset: lib.get(b"retro_cheat_reset")?,
|
||||||
|
retro_cheat_set: lib.get(b"retro_cheat_set")?,
|
||||||
|
retro_load_game: lib.get(b"retro_load_game")?,
|
||||||
|
retro_load_game_special: lib.get(b"retro_load_game_special")?,
|
||||||
|
retro_unload_game: lib.get(b"retro_unload_game")?,
|
||||||
|
retro_get_region: lib.get(b"retro_get_region")?,
|
||||||
|
retro_get_memory_data: lib.get(b"retro_get_memory_data")?,
|
||||||
|
retro_get_memory_size: lib.get(b"retro_get_memory_size")?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// retro_set_environment() must be called before retro_init().
|
||||||
|
pub fn init(&self) {
|
||||||
|
unsafe {
|
||||||
|
// TODO assert!(called retro_set_environment);
|
||||||
|
(&self.retro_init)();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/** 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>();
|
||||||
|
(&self.retro_get_system_info)(&mut info);
|
||||||
|
info
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/** Gets information about system audio/video timings and geometry.
|
||||||
|
* Can be called only after retro_load_game() has successfully completed.
|
||||||
|
* NOTE: The implementation of this function might not initialize every
|
||||||
|
* variable if needed.
|
||||||
|
* E.g. geom.aspect_ratio might not be initialized if core doesn't
|
||||||
|
* desire a particular aspect ratio. */
|
||||||
|
pub fn get_system_av_info(&self) -> retro_system_av_info {
|
||||||
|
unsafe {
|
||||||
|
let mut av_info = ::std::mem::zeroed::<retro_system_av_info>();
|
||||||
|
(&self.retro_get_system_av_info)(&mut av_info);
|
||||||
|
av_info
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,18 @@
|
||||||
|
extern crate failure;
|
||||||
|
extern crate libloading;
|
||||||
|
|
||||||
|
use std::ffi::CStr;
|
||||||
|
|
||||||
|
#[allow(non_camel_case_types, non_upper_case_globals, non_snake_case, dead_code)]
|
||||||
|
mod libretro_types;
|
||||||
|
mod libretro_loading;
|
||||||
|
|
||||||
|
fn main() -> failure::Fallible<()> {
|
||||||
|
let lib = libloading::Library::new("/home/lifning/.config/retroarch/cores/gambatte_libretro.so")?;
|
||||||
|
let retro = libretro_loading::LibretroApi::from_library(&lib)?;
|
||||||
|
unsafe {
|
||||||
|
println!("api version: {}", (&retro.retro_api_version)());
|
||||||
|
println!("name: {}", CStr::from_ptr(retro.get_system_info().library_name).to_string_lossy());
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
Loading…
Reference in New Issue