From cfbbc37f8a7372703d393c19eca3a9800547bbf4 Mon Sep 17 00:00:00 2001 From: modeco80 Date: Sun, 4 Aug 2024 21:23:24 -0400 Subject: [PATCH] more code cleanup, add a stub implementation of the mouse input device --- crates/retro_frontend/src/frontend.rs | 31 ++++++---- .../retro_frontend/src/input_devices/mod.rs | 11 +++- .../retro_frontend/src/input_devices/mouse.rs | 57 +++++++++++++++++++ .../src/input_devices/retropad.rs | 2 +- .../retro_frontend/src/libretro_callbacks.rs | 4 +- crates/retrovnc/src/rfb.rs | 3 + 6 files changed, 91 insertions(+), 17 deletions(-) create mode 100644 crates/retro_frontend/src/input_devices/mouse.rs diff --git a/crates/retro_frontend/src/frontend.rs b/crates/retro_frontend/src/frontend.rs index 6a66f86..50b4861 100644 --- a/crates/retro_frontend/src/frontend.rs +++ b/crates/retro_frontend/src/frontend.rs @@ -35,6 +35,11 @@ pub trait FrontendInterface { /// Called to poll input fn input_poll(&mut self); + + // TODO(lily): Provide APIs for gathering a GL context/fbo. + // This should be abstracted so if a frontend written on top of retro_frontend + // wants to give a FBO from a GLX/WGL/windowed whatever context, it can, + // but a headless frontend can itself provide a headless EGL context just the same. } /// Per-core settings @@ -62,11 +67,14 @@ pub struct Frontend { /// Converted pixel buffer. We store it here so we don't keep allocating over and over. pub(crate) converted_pixel_buffer: Vec, + // Framebuffer attributes. TODO: This really should be another struct or something + // with members to make dealing with it less annoying. + pub(crate) fb_width: u32, pub(crate) fb_height: u32, pub(crate) fb_pitch: u32, - /// The "system" directory. Used for BIOS roms + /// The "system" directory. Used for BIOS roms. pub(crate) system_directory: CString, /// The save directory. Used for saves. (TODO: Should make this per-core!!!) @@ -75,10 +83,11 @@ pub struct Frontend { /// The config directory. Stores configuration for each core. pub(crate) config_directory: String, - /// Hashmap of core variabels. + /// Hashmap of core variables. pub(crate) variables: HashMap, - pub(crate) joypads: HashMap, + /// Hashmap of connected input devices. + pub(crate) input_devices: HashMap, pub(crate) interface: *mut dyn FrontendInterface, } @@ -110,12 +119,12 @@ impl Frontend { variables: HashMap::new(), - joypads: HashMap::new(), + input_devices: HashMap::new(), interface: interface, }); - // Assign to the global fronend pointer + // Assign to the global frontend pointer unsafe { assert!(FRONTEND.is_null(), "Cannot have multiple frontends."); FRONTEND = &mut *boxed as *mut Frontend; @@ -138,10 +147,10 @@ impl Frontend { (core_api.retro_set_controller_port_device)(port, (*device).device_type()); } - if !self.joypads.contains_key(&port) { - self.joypads.insert(port, device); + if !self.input_devices.contains_key(&port) { + self.input_devices.insert(port, device); } else { - (*self.joypads.get_mut(&port).unwrap()) = device; + (*self.input_devices.get_mut(&port).unwrap()) = device; } } } @@ -155,8 +164,8 @@ impl Frontend { (core_api.retro_set_controller_port_device)(port, DEVICE_NONE); } - if !self.joypads.contains_key(&port) { - self.joypads.remove(&port); + if !self.input_devices.contains_key(&port) { + self.input_devices.remove(&port); } } } @@ -349,7 +358,7 @@ impl Frontend { self.fb_pitch = 0; // disconnect all currently connected joypads - self.joypads.clear(); + self.input_devices.clear(); Ok(()) } diff --git a/crates/retro_frontend/src/input_devices/mod.rs b/crates/retro_frontend/src/input_devices/mod.rs index 8381f25..f39b187 100644 --- a/crates/retro_frontend/src/input_devices/mod.rs +++ b/crates/retro_frontend/src/input_devices/mod.rs @@ -2,16 +2,21 @@ pub mod retropad; pub use retropad::*; +pub mod mouse; +pub use mouse::*; + /// Trait for implementing Libretro input devices pub trait InputDevice { - // TODO: is_pressed(id: u32)? - + /// Gets the device type. This should never EVER change, and simply return a constant. fn device_type(&self) -> u32; + /// Gets the state of one button/axis. + /// is_pressed(id) can simply be expressed as `(get_button(id) != 0)`. fn get_button(&self, id: u32) -> i16; + /// Clears the state of all buttons/axes. fn reset(&mut self); + /// Presses a button/axis. fn press_button(&mut self, id: u32, pressure: Option); } - diff --git a/crates/retro_frontend/src/input_devices/mouse.rs b/crates/retro_frontend/src/input_devices/mouse.rs new file mode 100644 index 0000000..e219553 --- /dev/null +++ b/crates/retro_frontend/src/input_devices/mouse.rs @@ -0,0 +1,57 @@ +//! Mouse +use super::InputDevice; +use crate::libretro_sys_new; + +/// Implementation of the [InputDevice] trait for the Libretro mouse. +pub struct Mouse { + buttons: [i16; 8], + + // TODO: hold the last x/y so we can calculate relative position +} + +impl Mouse { + pub fn new() -> Self { + Self { buttons: [0; 8] } + } + + // helpers: + // + // set_pos(x, y) (will do all the stupid scaling, and press the axes with the right value) + // set_buttons(mask) (will press all buttons, including wheel based on standard button mask) +} + +impl InputDevice for Mouse { + fn device_type(&self) -> u32 { + libretro_sys_new::DEVICE_MOUSE + } + + fn get_button(&self, id: u32) -> i16 { + if id > 8 { + return 0; + } + + self.buttons[id as usize] + } + + fn reset(&mut self) { + for button in &mut self.buttons { + *button = 0i16; + } + } + + fn press_button(&mut self, id: u32, pressure: Option) { + if id > 8 { + return; + } + + match pressure { + Some(pressure_value) => { + self.buttons[id as usize] = pressure_value; + } + None => { + // ? or 0x7fff ? Unsure + self.buttons[id as usize] = 0x7fff; + } + } + } +} diff --git a/crates/retro_frontend/src/input_devices/retropad.rs b/crates/retro_frontend/src/input_devices/retropad.rs index e36d354..59ee7cc 100644 --- a/crates/retro_frontend/src/input_devices/retropad.rs +++ b/crates/retro_frontend/src/input_devices/retropad.rs @@ -45,7 +45,7 @@ impl InputDevice for RetroPad { } None => { // ? or 0x7fff ? Unsure - self.buttons[id as usize] = 1; + self.buttons[id as usize] = 0x7fff; } } } diff --git a/crates/retro_frontend/src/libretro_callbacks.rs b/crates/retro_frontend/src/libretro_callbacks.rs index 5b34897..3aab5ff 100644 --- a/crates/retro_frontend/src/libretro_callbacks.rs +++ b/crates/retro_frontend/src/libretro_callbacks.rs @@ -240,9 +240,9 @@ pub(crate) unsafe extern "C" fn input_state_callback( _index: ffi::c_uint, // not used? button_id: ffi::c_uint, ) -> ffi::c_short { - if (*FRONTEND).joypads.contains_key(&port) { + if (*FRONTEND).input_devices.contains_key(&port) { let joypad = *(*FRONTEND) - .joypads + .input_devices .get(&port) .expect("How do we get here when contains_key() returns true but the key doen't exist"); diff --git a/crates/retrovnc/src/rfb.rs b/crates/retrovnc/src/rfb.rs index 4bad069..9b35f17 100644 --- a/crates/retrovnc/src/rfb.rs +++ b/crates/retrovnc/src/rfb.rs @@ -125,6 +125,9 @@ impl RfbServer { } } + // TODO: Pull this out of here, and instead do it in retrovnc app proper. + // This will also make the rfb code more generic which is always a good thing + pub fn get_buttons(&self) -> [bool; 32] { self.buttons }