ferretro/ferretro_base/src/retro/mod.rs

70 lines
2.5 KiB
Rust

use std::pin::Pin;
use std::sync::Mutex;
use callbacks::RootRetroCallbacks;
use once_cell::sync::Lazy;
pub mod callbacks;
pub mod constants;
#[allow(non_camel_case_types, non_upper_case_globals, non_snake_case, dead_code)]
pub mod ffi;
pub mod loading;
pub mod wrapped_types;
pub mod wrapper;
// TODO: macro this
pub const MAX_HANDLERS: usize = 8;
mod statics_00 { include!("statics.rs"); }
mod statics_01 { include!("statics.rs"); }
mod statics_02 { include!("statics.rs"); }
mod statics_03 { include!("statics.rs"); }
mod statics_04 { include!("statics.rs"); }
mod statics_05 { include!("statics.rs"); }
mod statics_06 { include!("statics.rs"); }
mod statics_07 { include!("statics.rs"); }
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub struct RetroHandlerId(usize);
static mut CALLBACK_REGISTRY: Lazy<Mutex<[bool; MAX_HANDLERS]>> = Lazy::new(|| Mutex::new([false; MAX_HANDLERS]));
pub fn set_handler(handler: Pin<&'_ mut (dyn RootRetroCallbacks + '_)>) -> Result<RetroHandlerId, Box<dyn std::error::Error>> {
let mut lock = unsafe { &mut CALLBACK_REGISTRY }.lock()?;
for (id, taken) in lock.iter_mut().enumerate() {
if !*taken {
match id {
0 => statics_00::set_handler(handler),
1 => statics_01::set_handler(handler),
2 => statics_02::set_handler(handler),
3 => statics_03::set_handler(handler),
4 => statics_04::set_handler(handler),
5 => statics_05::set_handler(handler),
6 => statics_06::set_handler(handler),
7 => statics_07::set_handler(handler),
_ => unreachable!(),
}
*taken = true;
return Ok(RetroHandlerId(id))
}
}
Err(format!("only compiled with support for up to {} callback handlers", MAX_HANDLERS).into())
}
pub fn unset_handler(id: RetroHandlerId) -> Result<(), Box<dyn std::error::Error>> {
let mut lock = unsafe { &mut CALLBACK_REGISTRY }.lock()?;
if let Some(taken) = lock.get_mut(id.0) {
*taken = false;
}
match id.0 {
0 => Ok(statics_00::unset_handler()),
1 => Ok(statics_01::unset_handler()),
2 => Ok(statics_02::unset_handler()),
3 => Ok(statics_03::unset_handler()),
4 => Ok(statics_04::unset_handler()),
5 => Ok(statics_05::unset_handler()),
6 => Ok(statics_06::unset_handler()),
7 => Ok(statics_07::unset_handler()),
x => Err(format!("invalid RetroHandlerId provided: {}", x).into())
}
}