static-linked libretro core support
This commit is contained in:
parent
464e670be4
commit
f5b86f9f8e
|
@ -12,3 +12,6 @@ libretro-sys = "0.1"
|
|||
libloading = "0.5"
|
||||
num_enum = "0.4"
|
||||
once_cell = "1"
|
||||
|
||||
[features]
|
||||
static = []
|
||||
|
|
|
@ -3,4 +3,9 @@ fn main() {
|
|||
cc::Build::new()
|
||||
.file("src/retro/c_ext/log_wrapper.c")
|
||||
.compile("log_wrapper");
|
||||
if cfg!(feature = "static") {
|
||||
println!("cargo:rustc-link-search=./lib");
|
||||
println!("cargo:rustc-link-lib=retro");
|
||||
println!("cargo:rustc-link-lib=m");
|
||||
}
|
||||
}
|
|
@ -10,7 +10,7 @@ use super::ffi::*;
|
|||
pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;
|
||||
|
||||
pub struct LibretroApi {
|
||||
_lib: libloading::Library, // for tying our lifetime to its own
|
||||
_lib: Option<libloading::Library>, // for tying our lifetime to its own
|
||||
pub core_api: CoreAPI,
|
||||
loaded_game: bool,
|
||||
environment_set: bool,
|
||||
|
@ -46,9 +46,68 @@ impl LibretroApi {
|
|||
retro_get_memory_data: *lib.get(b"retro_get_memory_data")?,
|
||||
retro_get_memory_size: *lib.get(b"retro_get_memory_size")?,
|
||||
};
|
||||
Ok(LibretroApi { _lib: lib, core_api, loaded_game: false, environment_set: false })
|
||||
Ok(LibretroApi { _lib: Some(lib), core_api, loaded_game: false, environment_set: false })
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "static")]
|
||||
pub fn from_static() -> Self {
|
||||
use std::os::raw::c_uint;
|
||||
extern "C" {
|
||||
fn retro_set_environment(callback: EnvironmentFn);
|
||||
fn retro_set_video_refresh(callback: VideoRefreshFn);
|
||||
fn retro_set_audio_sample(callback: AudioSampleFn);
|
||||
fn retro_set_audio_sample_batch(callback: AudioSampleBatchFn);
|
||||
fn retro_set_input_poll(callback: InputPollFn);
|
||||
fn retro_set_input_state(callback: InputStateFn);
|
||||
fn retro_init();
|
||||
fn retro_deinit();
|
||||
fn retro_api_version() -> c_uint;
|
||||
fn retro_get_system_info(info: *mut SystemInfo);
|
||||
fn retro_get_system_av_info(info: *mut SystemAvInfo);
|
||||
fn retro_set_controller_port_device(port: c_uint, device: c_uint);
|
||||
fn retro_reset();
|
||||
fn retro_run();
|
||||
fn retro_serialize_size() -> usize;
|
||||
fn retro_serialize(data: *mut c_void, size: usize);
|
||||
fn retro_unserialize(data: *const c_void, size: usize) -> bool;
|
||||
fn retro_cheat_reset();
|
||||
fn retro_cheat_set(index: c_uint, enabled: bool, code: *const c_char);
|
||||
fn retro_load_game(game: *const GameInfo) -> bool;
|
||||
fn retro_load_game_special(game_type: c_uint, info: *const GameInfo, num_info: usize) -> bool;
|
||||
fn retro_unload_game();
|
||||
fn retro_get_region() -> c_uint;
|
||||
fn retro_get_memory_data(id: c_uint) -> *mut c_void;
|
||||
fn retro_get_memory_size(id: c_uint) -> usize;
|
||||
}
|
||||
let core_api = CoreAPI {
|
||||
retro_set_environment,
|
||||
retro_set_video_refresh,
|
||||
retro_set_audio_sample,
|
||||
retro_set_audio_sample_batch,
|
||||
retro_set_input_poll,
|
||||
retro_set_input_state,
|
||||
retro_init,
|
||||
retro_deinit,
|
||||
retro_api_version,
|
||||
retro_get_system_info,
|
||||
retro_get_system_av_info,
|
||||
retro_set_controller_port_device,
|
||||
retro_reset,
|
||||
retro_run,
|
||||
retro_serialize_size,
|
||||
retro_serialize,
|
||||
retro_unserialize,
|
||||
retro_cheat_reset,
|
||||
retro_cheat_set,
|
||||
retro_load_game,
|
||||
retro_load_game_special,
|
||||
retro_unload_game,
|
||||
retro_get_region,
|
||||
retro_get_memory_data,
|
||||
retro_get_memory_size,
|
||||
};
|
||||
LibretroApi { _lib: None, core_api, loaded_game: false, environment_set: false }
|
||||
}
|
||||
/// set_environment() must be called before init().
|
||||
pub fn set_environment(&mut self, cb: EnvironmentFn) {
|
||||
self.environment_set = true;
|
||||
|
|
|
@ -22,6 +22,7 @@ crossbeam-channel = "0.4"
|
|||
structopt = "0.3"
|
||||
|
||||
[features]
|
||||
static = ["ferretro_base/static"]
|
||||
ffmpeg_comp = ["ffmpeg-next"]
|
||||
sdl2_comp = ["sdl2", "gl", "crossbeam-channel"]
|
||||
|
||||
|
|
|
@ -4,16 +4,18 @@
|
|||
|
||||
use crate::prelude::*;
|
||||
use ferretro_base::retro::ffi::*;
|
||||
use ferretro_base::retro::loading::LibretroApi;
|
||||
use ferretro_base::prelude::{LibretroWrapperAccess, RetroHandlerId};
|
||||
|
||||
use core::any::{Any, TypeId};
|
||||
use core::pin::Pin;
|
||||
|
||||
use std::os::raw::c_uint;
|
||||
use std::path::{PathBuf, Path};
|
||||
use std::io::Read;
|
||||
use std::collections::HashMap;
|
||||
use std::ffi::c_void;
|
||||
use std::io::Read;
|
||||
use std::os::raw::c_uint;
|
||||
use std::path::{PathBuf, Path};
|
||||
use tempfile::TempDir;
|
||||
|
||||
pub struct RetroComponentBase {
|
||||
retro: LibretroWrapper,
|
||||
|
@ -37,7 +39,7 @@ pub struct RetroComponentBase {
|
|||
cached_geometry: Option<GameGeometry>,
|
||||
|
||||
handler_id: Option<RetroHandlerId>,
|
||||
_temp_dir: tempfile::TempDir,
|
||||
_temp_dir: Option<tempfile::TempDir>,
|
||||
}
|
||||
|
||||
unsafe impl Send for RetroComponentBase {}
|
||||
|
@ -62,7 +64,6 @@ pub trait RetroComponent: RetroCallbacks + Any {
|
|||
}
|
||||
|
||||
impl RetroComponentBase {
|
||||
// TODO: constructor & wrapper that uses a statically linked libretro?
|
||||
pub fn new(core_path: impl AsRef<Path>) -> Pin<Box<Self>> {
|
||||
// allow multiple copies of same lib, possibly?
|
||||
let temp_dir = tempfile::tempdir().unwrap();
|
||||
|
@ -70,7 +71,16 @@ impl RetroComponentBase {
|
|||
std::fs::copy(core_path.as_ref(), &libretro_path).unwrap();
|
||||
|
||||
let lib = libloading::Library::new(&libretro_path).unwrap();
|
||||
let raw_retro = ferretro_base::retro::loading::LibretroApi::from_library(lib).unwrap();
|
||||
let raw_retro = LibretroApi::from_library(lib).unwrap();
|
||||
Self::new_inner(raw_retro, libretro_path, Some(temp_dir))
|
||||
}
|
||||
|
||||
#[cfg(feature = "static")]
|
||||
pub fn new_static() -> Pin<Box<Self>> {
|
||||
Self::new_inner(LibretroApi::from_static(), PathBuf::new(), None)
|
||||
}
|
||||
|
||||
fn new_inner(raw_retro: LibretroApi, libretro_path: PathBuf, _temp_dir: Option<TempDir>) -> Pin<Box<Self>> {
|
||||
let retro = LibretroWrapper::from(raw_retro);
|
||||
|
||||
let emu = RetroComponentBase {
|
||||
|
@ -90,7 +100,7 @@ impl RetroComponentBase {
|
|||
cached_memory_map: None,
|
||||
cached_geometry: None,
|
||||
handler_id: None,
|
||||
_temp_dir: temp_dir,
|
||||
_temp_dir,
|
||||
};
|
||||
|
||||
let mut pin_emu = Box::pin(emu);
|
||||
|
|
Loading…
Reference in New Issue