implement ENVIRONMENT_SET_INPUT_DESCRIPTORS

This commit is contained in:
lif 2019-11-23 19:37:18 -08:00
parent 49aa491904
commit 3f31cf6625
3 changed files with 75 additions and 33 deletions

View File

@ -4,8 +4,8 @@ extern crate sdl2;
use rustro::retro;
use rustro::retro::ffi::{GameGeometry, SystemInfo, SystemAvInfo};
use rustro::retro::constants::{Input, DeviceIndex, JoypadButton, AnalogAxis, DeviceType};
use rustro::retro::wrapper::{LibretroWrapper, VariableDescriptor, ControllerDescription2, SubsystemInfo2};
use rustro::retro::constants::{InputDeviceId, InputIndex, JoypadButton, AnalogAxis, DeviceType};
use rustro::retro::wrapper::{LibretroWrapper, Variable2, ControllerDescription2, SubsystemInfo2, InputDescriptor2};
use std::ffi::CStr;
use std::io::Read;
@ -239,11 +239,11 @@ impl retro::wrapper::Handler for MyEmulator {
self.gamepad_subsys.update();
}
fn input_state(&mut self, port: u32, device: Input, index: DeviceIndex) -> i16 {
fn input_state(&mut self, port: u32, device: InputDeviceId, index: InputIndex) -> i16 {
match self.gamepads.get(port as usize) {
Some(gamepad) => {
match device {
Input::Joypad(button) => {
InputDeviceId::Joypad(button) => {
match button_map(&button) {
Some(x) => gamepad.button(x) as i16,
None => match button {
@ -253,7 +253,7 @@ impl retro::wrapper::Handler for MyEmulator {
}
}
}
Input::Analog(axis) => gamepad.axis(axis_map(index, axis)),
InputDeviceId::Analog(axis) => gamepad.axis(axis_map(index, axis)),
_ => 0,
}
}
@ -275,11 +275,6 @@ impl retro::wrapper::Handler for MyEmulator {
};
true
}
fn set_subsystem_info(&mut self, subsystem_info: Vec<SubsystemInfo2>) -> bool {
println!("subsystem info: {:?}", subsystem_info);
true
}
fn get_variable(&mut self, key: &str) -> Option<String> {
match key {
"beetle_saturn_analog_stick_deadzone" => Some("15%".to_string()),
@ -289,7 +284,7 @@ impl retro::wrapper::Handler for MyEmulator {
}
}
fn set_variables(&mut self, variables: Vec<VariableDescriptor>) -> bool {
fn set_variables(&mut self, variables: Vec<Variable2>) -> bool {
for v in variables {
eprintln!("{:?}", v);
}
@ -315,6 +310,11 @@ impl retro::wrapper::Handler for MyEmulator {
true
}
fn set_subsystem_info(&mut self, subsystem_info: Vec<SubsystemInfo2>) -> bool {
println!("subsystem info: {:?}", subsystem_info);
true
}
fn set_controller_info(&mut self, controller_info: Vec<ControllerDescription2>) -> bool {
for ci in controller_info {
// so we can have analog support in beetle/mednafen saturn
@ -326,6 +326,13 @@ impl retro::wrapper::Handler for MyEmulator {
true
}
fn set_input_descriptors(&mut self, descriptors: Vec<InputDescriptor2>) -> bool {
for id in descriptors {
println!("{:?}", id);
}
true
}
fn set_geometry(&mut self, geom: GameGeometry) -> bool {
let _ = self.canvas.window_mut().set_size(geom.base_width, geom.base_height);
let _ = self.canvas.set_logical_size(geom.base_width, geom.base_height);
@ -399,11 +406,11 @@ fn button_map(retro_button: &JoypadButton) -> Option<Button> {
}
}
fn axis_map(index: DeviceIndex, axis: AnalogAxis) -> Axis {
fn axis_map(index: InputIndex, axis: AnalogAxis) -> Axis {
match (index, axis) {
(DeviceIndex::Left, AnalogAxis::X) => Axis::LeftX,
(DeviceIndex::Left, AnalogAxis::Y) => Axis::LeftY,
(DeviceIndex::Right, AnalogAxis::X) => Axis::RightX,
(DeviceIndex::Right, AnalogAxis::Y) => Axis::RightY,
(InputIndex::Left, AnalogAxis::X) => Axis::LeftX,
(InputIndex::Left, AnalogAxis::Y) => Axis::LeftY,
(InputIndex::Right, AnalogAxis::X) => Axis::RightX,
(InputIndex::Right, AnalogAxis::Y) => Axis::RightY,
}
}

View File

@ -27,7 +27,7 @@ impl DeviceType {
#[derive(TryFromPrimitive, IntoPrimitive, Debug)]
#[repr(u32)]
pub enum DeviceIndex {
pub enum InputIndex {
Left = DEVICE_INDEX_ANALOG_LEFT,
Right = DEVICE_INDEX_ANALOG_RIGHT,
// Button = DEVICE_INDEX_ANALOG_BUTTON,
@ -106,7 +106,7 @@ pub enum PointerStat {
}
#[derive(Debug)]
pub enum Input {
pub enum InputDeviceId {
None(c_uint),
Joypad(JoypadButton),
Mouse(MouseButton),
@ -116,7 +116,7 @@ pub enum Input {
Pointer(PointerStat),
}
impl<D> TryFrom<(D, c_uint)> for Input
impl<D> TryFrom<(D, c_uint)> for InputDeviceId
where D: TryInto<DeviceType>,
<D as std::convert::TryInto<DeviceType>>::Error: std::error::Error + Send + Sync + 'static,
{
@ -125,13 +125,13 @@ impl<D> TryFrom<(D, c_uint)> for Input
fn try_from(pair: (D, c_uint)) -> failure::Fallible<Self> {
let (device, id) = pair;
Ok(match device.try_into()? {
DeviceType::None => Input::None(id),
DeviceType::Joypad => Input::Joypad(JoypadButton::try_from(id)?),
DeviceType::Mouse => Input::Mouse(MouseButton::try_from(id)?),
DeviceType::Keyboard => Input::Keyboard(id),
DeviceType::LightGun => Input::LightGun(LightGunButton::try_from(id)?),
DeviceType::Analog => Input::Analog(AnalogAxis::try_from(id)?),
DeviceType::Pointer => Input::Pointer(PointerStat::try_from(id)?),
DeviceType::None => InputDeviceId::None(id),
DeviceType::Joypad => InputDeviceId::Joypad(JoypadButton::try_from(id)?),
DeviceType::Mouse => InputDeviceId::Mouse(MouseButton::try_from(id)?),
DeviceType::Keyboard => InputDeviceId::Keyboard(id),
DeviceType::LightGun => InputDeviceId::LightGun(LightGunButton::try_from(id)?),
DeviceType::Analog => InputDeviceId::Analog(AnalogAxis::try_from(id)?),
DeviceType::Pointer => InputDeviceId::Pointer(PointerStat::try_from(id)?),
})
}
}

View File

@ -38,7 +38,7 @@ pub trait Handler: Unpin + 'static {
fn audio_sample(&mut self, left: i16, right: i16) {}
fn audio_sample_batch(&mut self, stereo_pcm: &[i16]) -> usize { stereo_pcm.len() }
fn input_poll(&mut self) {}
fn input_state(&mut self, port: u32, device: Input, index: DeviceIndex) -> i16 { 0 }
fn input_state(&mut self, port: u32, device: InputDeviceId, index: InputIndex) -> i16 { 0 }
// -- environment callbacks --
fn set_rotation(&mut self, rotation: EnvRotation) -> bool { false }
@ -49,10 +49,10 @@ pub trait Handler: Unpin + 'static {
fn set_performance_level(&mut self, level: c_uint) -> bool { false }
fn get_system_directory(&mut self) -> Option<PathBuf> { None }
fn set_pixel_format(&mut self, format: PixelFormat) -> bool { false }
fn set_input_descriptors(&mut self, input_descriptors: &[InputDescriptor]) -> bool { false }
fn set_input_descriptors(&mut self, input_descriptors: Vec<InputDescriptor2>) -> bool { false }
fn set_hw_render(&mut self, hw_render_callback: HwRenderCallback) -> bool { false }
fn get_variable(&mut self, key: &str) -> Option<String> { None }
fn set_variables(&mut self, variables: Vec<VariableDescriptor>) -> bool { false }
fn set_variables(&mut self, variables: Vec<Variable2>) -> bool { false }
fn get_variable_update(&mut self) -> Option<bool> { None }
fn set_support_no_game(&mut self, supports_no_game: bool) -> bool { false }
fn get_libretro_path(&mut self) -> Option<PathBuf> { None }
@ -80,13 +80,13 @@ pub trait Handler: Unpin + 'static {
}
#[derive(Debug)]
pub struct VariableDescriptor {
pub struct Variable2 {
pub key: String,
pub description: String,
pub options: Vec<String>,
}
impl From<&Variable> for VariableDescriptor {
impl From<&Variable> for Variable2 {
fn from(var: &Variable) -> Self {
let key = unsafe { CStr::from_ptr(var.key) }
.to_string_lossy()
@ -102,7 +102,7 @@ impl From<&Variable> for VariableDescriptor {
.split('|')
.map(String::from)
.collect();
VariableDescriptor {
Variable2 {
key,
description,
options,
@ -146,6 +146,33 @@ impl TryFrom<&ControllerDescription> for ControllerDescription2 {
}
}
#[derive(Debug)]
pub struct InputDescriptor2 {
pub port: c_uint,
pub device_id: InputDeviceId,
pub index: InputIndex,
pub description: String,
}
impl TryFrom<&InputDescriptor> for InputDescriptor2 {
type Error = ();
fn try_from(t: &InputDescriptor) -> Result<Self, Self::Error> {
if t.id >> DEVICE_TYPE_SHIFT != 0 {
eprintln!("Device subclass encountered in retro_input_descriptor, ignoring");
}
let description = unsafe { CStr::from_ptr(t.description) }
.to_str()
.map_err(|_| ())?
.to_string();
Ok(InputDescriptor2 {
port: t.port,
device_id: InputDeviceId::try_from((t.device & DEVICE_MASK, t.id)).map_err(|_| ())?,
index: InputIndex::try_from(t.index).map_err(|_| ())?,
description,
})
}
}
#[derive(Debug)]
pub struct SubsystemInfo2 {
pub description: String,
@ -286,7 +313,15 @@ impl StaticCallbacks {
EnvCmd::SetPixelFormat => {
handler.set_pixel_format(PixelFormat::from_uint(*Self::from_void(data)?)?)
}
// TODO EnvCmd::SetInputDescriptors => {},
EnvCmd::SetInputDescriptors => {
let mut input_desc = data as *const InputDescriptor;
let mut descriptors = Vec::new();
while !unsafe { input_desc.as_ref() }?.description.is_null() {
descriptors.push(unsafe { input_desc.as_ref() }?.try_into().ok()?);
input_desc = input_desc.wrapping_add(1);
}
handler.set_input_descriptors(descriptors)
},
EnvCmd::SetKeyboardCallback => {
let kc: &mut KeyboardCallback = Self::from_void(data)?;
handler