code cleanup
- make joypad a directory module, split retropad implementation into new module (but re-export it). also rename joypad to InputDevice - remove spurious retro_reset (it's not needed and in fact crashes some cores) - rename frontend input device APIs, add one for removing (unplugging) a device
This commit is contained in:
parent
ad634bf1fa
commit
a7544cb64d
6 changed files with 71 additions and 54 deletions
|
@ -1,4 +1,4 @@
|
||||||
use crate::joypad::Joypad;
|
use crate::input_devices::InputDevice;
|
||||||
use crate::libretro_callbacks;
|
use crate::libretro_callbacks;
|
||||||
use crate::libretro_core_variable::CoreVariable;
|
use crate::libretro_core_variable::CoreVariable;
|
||||||
use crate::result::{Error, Result};
|
use crate::result::{Error, Result};
|
||||||
|
@ -66,13 +66,19 @@ pub struct Frontend {
|
||||||
pub(crate) fb_height: u32,
|
pub(crate) fb_height: u32,
|
||||||
pub(crate) fb_pitch: u32,
|
pub(crate) fb_pitch: u32,
|
||||||
|
|
||||||
|
/// The "system" directory. Used for BIOS roms
|
||||||
pub(crate) system_directory: CString,
|
pub(crate) system_directory: CString,
|
||||||
|
|
||||||
|
/// The save directory. Used for saves. (TODO: Should make this per-core!!!)
|
||||||
pub(crate) save_directory: CString,
|
pub(crate) save_directory: CString,
|
||||||
|
|
||||||
|
/// The config directory. Stores configuration for each core.
|
||||||
pub(crate) config_directory: String,
|
pub(crate) config_directory: String,
|
||||||
|
|
||||||
|
/// Hashmap of core variabels.
|
||||||
pub(crate) variables: HashMap<String, CoreVariable>,
|
pub(crate) variables: HashMap<String, CoreVariable>,
|
||||||
|
|
||||||
pub(crate) joypads: HashMap<u32 /* port */, *mut dyn Joypad>,
|
pub(crate) joypads: HashMap<u32 /* port */, *mut dyn InputDevice>,
|
||||||
|
|
||||||
pub(crate) interface: *mut dyn FrontendInterface,
|
pub(crate) interface: *mut dyn FrontendInterface,
|
||||||
}
|
}
|
||||||
|
@ -111,7 +117,7 @@ impl Frontend {
|
||||||
|
|
||||||
// Assign to the global fronend pointer
|
// Assign to the global fronend pointer
|
||||||
unsafe {
|
unsafe {
|
||||||
assert!(FRONTEND.is_null(), "Cannot have multiple sir.");
|
assert!(FRONTEND.is_null(), "Cannot have multiple frontends.");
|
||||||
FRONTEND = &mut *boxed as *mut Frontend;
|
FRONTEND = &mut *boxed as *mut Frontend;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,7 +129,8 @@ impl Frontend {
|
||||||
self.core_library.is_some() && self.core_api.is_some()
|
self.core_library.is_some() && self.core_api.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_input_port_device(&mut self, port: u32, device: *mut dyn Joypad) {
|
/// Plugs in an input device to the specified port.
|
||||||
|
pub fn plug_input_device(&mut self, port: u32, device: *mut dyn InputDevice) {
|
||||||
if self.core_loaded() {
|
if self.core_loaded() {
|
||||||
let core_api = self.core_api.as_mut().unwrap();
|
let core_api = self.core_api.as_mut().unwrap();
|
||||||
|
|
||||||
|
@ -131,11 +138,28 @@ impl Frontend {
|
||||||
(core_api.retro_set_controller_port_device)(port, (*device).device_type());
|
(core_api.retro_set_controller_port_device)(port, (*device).device_type());
|
||||||
}
|
}
|
||||||
|
|
||||||
self.joypads.insert(port, device);
|
if !self.joypads.contains_key(&port) {
|
||||||
|
self.joypads.insert(port, device);
|
||||||
|
} else {
|
||||||
|
(*self.joypads.get_mut(&port).unwrap()) = device;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear_input_port_device?
|
/// Unplugs a input device from the given port.
|
||||||
|
pub fn unplug_input_device(&mut self, port: u32) {
|
||||||
|
if self.core_loaded() {
|
||||||
|
let core_api = self.core_api.as_mut().unwrap();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
(core_api.retro_set_controller_port_device)(port, DEVICE_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.joypads.contains_key(&port) {
|
||||||
|
self.joypads.remove(&port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn get_config_file_path(&self) -> String {
|
fn get_config_file_path(&self) -> String {
|
||||||
let path = unsafe {
|
let path = unsafe {
|
||||||
|
@ -280,8 +304,6 @@ impl Frontend {
|
||||||
libretro_callbacks::audio_sample_batch_callback,
|
libretro_callbacks::audio_sample_batch_callback,
|
||||||
);
|
);
|
||||||
|
|
||||||
(core_api_ref.retro_reset)();
|
|
||||||
|
|
||||||
info!("Core {} loaded", path.as_ref().display());
|
info!("Core {} loaded", path.as_ref().display());
|
||||||
|
|
||||||
// Get AV info
|
// Get AV info
|
||||||
|
|
17
crates/retro_frontend/src/input_devices/mod.rs
Normal file
17
crates/retro_frontend/src/input_devices/mod.rs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
//! Input devices
|
||||||
|
pub mod retropad;
|
||||||
|
pub use retropad::*;
|
||||||
|
|
||||||
|
/// Trait for implementing Libretro input devices
|
||||||
|
pub trait InputDevice {
|
||||||
|
// TODO: is_pressed(id: u32)?
|
||||||
|
|
||||||
|
fn device_type(&self) -> u32;
|
||||||
|
|
||||||
|
fn get_button(&self, id: u32) -> i16;
|
||||||
|
|
||||||
|
fn reset(&mut self);
|
||||||
|
|
||||||
|
fn press_button(&mut self, id: u32, pressure: Option<i16>);
|
||||||
|
}
|
||||||
|
|
|
@ -1,23 +1,8 @@
|
||||||
//! libretro pad abstraction
|
//! RetroPad
|
||||||
|
use super::InputDevice;
|
||||||
use crate::libretro_sys_new;
|
use crate::libretro_sys_new;
|
||||||
|
|
||||||
pub trait Joypad {
|
/// Implementation of the [InputDevice] trait for the Libretro
|
||||||
// TODO: is_pressed(id: u32)?
|
|
||||||
|
|
||||||
fn device_type(&self) -> u32;
|
|
||||||
|
|
||||||
fn get_button(&self, id: u32) -> i16;
|
|
||||||
|
|
||||||
fn reset(&mut self);
|
|
||||||
|
|
||||||
fn press_button(&mut self, id: u32, pressure: Option<i16>);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Split this into a new module, and make this a dir based one
|
|
||||||
// (mod.rs/retropad.rs/analogpad.rs) once we have AnalogPad support.
|
|
||||||
|
|
||||||
/// Implementation of the [Joypad] trait for the Libretro
|
|
||||||
/// RetroPad; which is essentially a standard PS1 controller,
|
/// RetroPad; which is essentially a standard PS1 controller,
|
||||||
/// with a couple more buttons inherited from the Dual Analog/DualShock.
|
/// with a couple more buttons inherited from the Dual Analog/DualShock.
|
||||||
pub struct RetroPad {
|
pub struct RetroPad {
|
||||||
|
@ -30,7 +15,7 @@ impl RetroPad {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Joypad for RetroPad {
|
impl InputDevice for RetroPad {
|
||||||
fn device_type(&self) -> u32 {
|
fn device_type(&self) -> u32 {
|
||||||
libretro_sys_new::DEVICE_JOYPAD
|
libretro_sys_new::DEVICE_JOYPAD
|
||||||
}
|
}
|
|
@ -6,7 +6,7 @@ mod libretro_log;
|
||||||
|
|
||||||
pub mod libretro_sys_new;
|
pub mod libretro_sys_new;
|
||||||
|
|
||||||
pub mod joypad;
|
pub mod input_devices;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
|
||||||
pub mod frontend;
|
pub mod frontend;
|
||||||
|
|
|
@ -6,13 +6,24 @@ use tracing::*;
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
/// This recieves log messages from our C++ helper code, and pulls them out into Tracing messages.
|
/// This recieves log messages from our C++ helper code, and pulls them out into Tracing messages.
|
||||||
pub extern "C" fn libretro_log_recieve(level: LogLevel, buf: *const ffi::c_char) {
|
pub extern "C" fn libretro_log_recieve(level: LogLevel, buf: *const ffi::c_char) {
|
||||||
let mut msg: Option<&str> = None;
|
|
||||||
|
|
||||||
// Safety: This pointer is never null, and always comes from the stack;
|
// Safety: This pointer is never null, and always comes from the stack;
|
||||||
// we really only should get UTF-8 errors here in the case a core spits out something invalid.
|
// we really only should get UTF-8 errors here in the case a core spits out something invalid.
|
||||||
unsafe {
|
unsafe {
|
||||||
match ffi::CStr::from_ptr(buf).to_str() {
|
match ffi::CStr::from_ptr(buf).to_str() {
|
||||||
Ok(message) => msg = Some(message),
|
Ok(message) => match level {
|
||||||
|
LogLevel::Debug => {
|
||||||
|
debug!("{}", message)
|
||||||
|
}
|
||||||
|
LogLevel::Info => {
|
||||||
|
info!("{}", message)
|
||||||
|
}
|
||||||
|
LogLevel::Warn => {
|
||||||
|
warn!("{}", message)
|
||||||
|
}
|
||||||
|
LogLevel::Error => {
|
||||||
|
error!("{}", message)
|
||||||
|
}
|
||||||
|
},
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!(
|
error!(
|
||||||
"Core for some reason gave a broken string to log interface: {:?}",
|
"Core for some reason gave a broken string to log interface: {:?}",
|
||||||
|
@ -21,23 +32,6 @@ pub extern "C" fn libretro_log_recieve(level: LogLevel, buf: *const ffi::c_char)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(message) = &msg {
|
|
||||||
match level {
|
|
||||||
LogLevel::Debug => {
|
|
||||||
debug!("Core log: {}", message)
|
|
||||||
}
|
|
||||||
LogLevel::Info => {
|
|
||||||
info!("Core log: {}", message)
|
|
||||||
}
|
|
||||||
LogLevel::Warn => {
|
|
||||||
warn!("Core log: {}", message)
|
|
||||||
}
|
|
||||||
LogLevel::Error => {
|
|
||||||
error!("Core log: {}", message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
|
@ -4,7 +4,7 @@ use anyhow::Result;
|
||||||
|
|
||||||
use retro_frontend::{
|
use retro_frontend::{
|
||||||
frontend::{Frontend, FrontendInterface},
|
frontend::{Frontend, FrontendInterface},
|
||||||
joypad::{Joypad, RetroPad},
|
input_devices::{InputDevice, RetroPad},
|
||||||
};
|
};
|
||||||
use tracing::Level;
|
use tracing::Level;
|
||||||
use tracing_subscriber::FmtSubscriber;
|
use tracing_subscriber::FmtSubscriber;
|
||||||
|
@ -25,7 +25,6 @@ impl App {
|
||||||
let mut boxed = Box::new(Self {
|
let mut boxed = Box::new(Self {
|
||||||
frontend: None,
|
frontend: None,
|
||||||
rfb_server: RfbServer::new(rfb_config)?,
|
rfb_server: RfbServer::new(rfb_config)?,
|
||||||
// nasty, but idk a better way
|
|
||||||
pad: RetroPad::new(),
|
pad: RetroPad::new(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -43,9 +42,9 @@ impl App {
|
||||||
|
|
||||||
fn init(&mut self) {
|
fn init(&mut self) {
|
||||||
// Currently retrovnc just hardcodes the assumption of a single RetroPad.
|
// Currently retrovnc just hardcodes the assumption of a single RetroPad.
|
||||||
let pad = &mut self.pad as *mut dyn Joypad;
|
let pad = &mut self.pad as *mut dyn InputDevice;
|
||||||
|
|
||||||
self.get_frontend().set_input_port_device(0, pad);
|
self.get_frontend().plug_input_device(0, pad);
|
||||||
|
|
||||||
// Initalize the display
|
// Initalize the display
|
||||||
self.init_display();
|
self.init_display();
|
||||||
|
@ -66,7 +65,7 @@ impl App {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_core<P: AsRef<Path>>(&mut self, path: P) -> Result<(), retro_frontend::result::Error> {
|
fn load_core<P: AsRef<Path>>(&mut self, path: P) -> Result<()> {
|
||||||
if self.get_frontend().core_loaded() {
|
if self.get_frontend().core_loaded() {
|
||||||
println!("???");
|
println!("???");
|
||||||
let _ = self.get_frontend().unload_core();
|
let _ = self.get_frontend().unload_core();
|
||||||
|
@ -76,7 +75,7 @@ impl App {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_game<P: AsRef<Path>>(&mut self, path: P) -> Result<(), retro_frontend::result::Error> {
|
fn load_game<P: AsRef<Path>>(&mut self, path: P) -> Result<()> {
|
||||||
self.get_frontend().load_game(path)?;
|
self.get_frontend().load_game(path)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue