implement RETRO_ENVIRONMENT_SET_VARIABLES
This commit is contained in:
parent
0e3ba53eec
commit
871e0f799f
2 changed files with 32 additions and 9 deletions
|
@ -5,7 +5,7 @@ extern crate sdl2;
|
||||||
use rustro::retro;
|
use rustro::retro;
|
||||||
use rustro::retro::ffi::{GameGeometry, SystemInfo, SystemAvInfo};
|
use rustro::retro::ffi::{GameGeometry, SystemInfo, SystemAvInfo};
|
||||||
use rustro::retro::constants::{Input, DeviceIndex, JoypadButton, AnalogAxis, DeviceType};
|
use rustro::retro::constants::{Input, DeviceIndex, JoypadButton, AnalogAxis, DeviceType};
|
||||||
use rustro::retro::wrapper::LibretroWrapper;
|
use rustro::retro::wrapper::{LibretroWrapper, VariableDescriptor};
|
||||||
|
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
@ -280,6 +280,13 @@ impl retro::wrapper::Handler for MyEmulator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_variables(&mut self, variables: &[VariableDescriptor]) -> bool {
|
||||||
|
for v in variables {
|
||||||
|
eprintln!("{:?}", v);
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
fn get_libretro_path(&mut self) -> Option<PathBuf> {
|
fn get_libretro_path(&mut self) -> Option<PathBuf> {
|
||||||
Some(self.core_path.clone())
|
Some(self.core_path.clone())
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ pub trait Handler: Unpin + 'static {
|
||||||
fn set_input_descriptors(&mut self, input_descriptors: &[InputDescriptor]) -> bool { false }
|
fn set_input_descriptors(&mut self, input_descriptors: &[InputDescriptor]) -> bool { false }
|
||||||
fn set_hw_render(&mut self, hw_render_callback: HwRenderCallback) -> 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 get_variable(&mut self, key: &str) -> Option<String> { None }
|
||||||
fn set_variables(&mut self, variables: &[Variable]) -> bool { false }
|
fn set_variables(&mut self, variables: &[VariableDescriptor]) -> bool { false }
|
||||||
fn get_variable_update(&mut self) -> Option<bool> { None }
|
fn get_variable_update(&mut self) -> Option<bool> { None }
|
||||||
fn set_support_no_game(&mut self, supports_no_game: bool) -> bool { false }
|
fn set_support_no_game(&mut self, supports_no_game: bool) -> bool { false }
|
||||||
fn get_libretro_path(&mut self) -> Option<PathBuf> { None }
|
fn get_libretro_path(&mut self) -> Option<PathBuf> { None }
|
||||||
|
@ -80,6 +80,13 @@ pub trait Handler: Unpin + 'static {
|
||||||
fn set_rumble_state(&mut self, port: c_uint, effect: RumbleEffect, strength: u16) -> bool { false }
|
fn set_rumble_state(&mut self, port: c_uint, effect: RumbleEffect, strength: u16) -> bool { false }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct VariableDescriptor {
|
||||||
|
pub key: String,
|
||||||
|
pub description: String,
|
||||||
|
pub options: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct StaticCallbacks {
|
struct StaticCallbacks {
|
||||||
handler: Option<Pin<&'static mut dyn Handler>>,
|
handler: Option<Pin<&'static mut dyn Handler>>,
|
||||||
|
@ -122,7 +129,7 @@ impl StaticCallbacks {
|
||||||
}
|
}
|
||||||
let handler = maybe_handler?;
|
let handler = maybe_handler?;
|
||||||
let parsed_cmd = cmd.try_into().ok();
|
let parsed_cmd = cmd.try_into().ok();
|
||||||
if parsed_cmd.is_none() {
|
if cfg!(debug) && parsed_cmd.is_none() {
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"Unknown{} env cmd: {}",
|
"Unknown{} env cmd: {}",
|
||||||
if cmd >= ENVIRONMENT_EXPERIMENTAL { ", experimental" } else { "" },
|
if cmd >= ENVIRONMENT_EXPERIMENTAL { ", experimental" } else { "" },
|
||||||
|
@ -160,16 +167,25 @@ impl StaticCallbacks {
|
||||||
EnvCmd::GetVariable => {
|
EnvCmd::GetVariable => {
|
||||||
let mut var = Self::from_void::<Variable>(data)?;
|
let mut var = Self::from_void::<Variable>(data)?;
|
||||||
let key = unsafe { CStr::from_ptr(var.key) }.to_str().ok()?;
|
let key = unsafe { CStr::from_ptr(var.key) }.to_str().ok()?;
|
||||||
if !var.value.is_null() {
|
|
||||||
let placeholder = unsafe { CStr::from_ptr(var.value) }.to_string_lossy();
|
|
||||||
eprintln!("querying {}: {}", key, placeholder);
|
|
||||||
}
|
|
||||||
let value = handler.get_variable(key)?;
|
let value = handler.get_variable(key)?;
|
||||||
// leaks memory.
|
// leaks memory.
|
||||||
var.value = CString::new(value).ok()?.into_raw();
|
var.value = CString::new(value).ok()?.into_raw();
|
||||||
true
|
true
|
||||||
},
|
},
|
||||||
// TODO EnvCmd::SetVariables => {},
|
EnvCmd::SetVariables => {
|
||||||
|
let mut var = data as *const Variable;
|
||||||
|
let mut descriptors = Vec::new();
|
||||||
|
while !unsafe { var.as_ref() }?.key.is_null() {
|
||||||
|
let key = unsafe { CStr::from_ptr({ var.as_ref() }?.key) }.to_str().ok()?.to_string();
|
||||||
|
let value = unsafe { CStr::from_ptr({ var.as_ref() }?.value) }.to_str().ok()?;
|
||||||
|
let split: Vec<&str> = value.splitn(2, "; ").collect();
|
||||||
|
let description = split.get(0)?.to_string();
|
||||||
|
let options = split.get(1)?.split('|').map(String::from).collect();
|
||||||
|
descriptors.push(VariableDescriptor { key, description, options });
|
||||||
|
var = var.wrapping_add(1);
|
||||||
|
}
|
||||||
|
handler.set_variables(descriptors.as_ref())
|
||||||
|
},
|
||||||
EnvCmd::GetVariableUpdate => Self::clone_into_void(data, &handler.get_variable_update()?)?,
|
EnvCmd::GetVariableUpdate => Self::clone_into_void(data, &handler.get_variable_update()?)?,
|
||||||
EnvCmd::SetSupportNoGame => handler.set_support_no_game(*Self::from_void(data)?),
|
EnvCmd::SetSupportNoGame => handler.set_support_no_game(*Self::from_void(data)?),
|
||||||
EnvCmd::GetLibretroPath => Self::path_into_void(data, handler.get_libretro_path()?)?,
|
EnvCmd::GetLibretroPath => Self::path_into_void(data, handler.get_libretro_path()?)?,
|
||||||
|
@ -344,7 +360,7 @@ impl LibretroWrapper {
|
||||||
pub fn disk_get_eject_state(&self) -> Option<bool> {
|
pub fn disk_get_eject_state(&self) -> Option<bool> {
|
||||||
self.disk_get_eject_state_cb.map(|f| unsafe { f() })
|
self.disk_get_eject_state_cb.map(|f| unsafe { f() })
|
||||||
}
|
}
|
||||||
pub fn disk_set_eject_state(&self) -> Option<bool> {
|
pub fn disk_set_eject_state(&self, ejected: bool) -> Option<bool> {
|
||||||
self.disk_set_eject_state_cb.map(|f| unsafe { f(ejected) })
|
self.disk_set_eject_state_cb.map(|f| unsafe { f(ejected) })
|
||||||
}
|
}
|
||||||
pub fn disk_get_image_index(&self) -> Option<c_uint> {
|
pub fn disk_get_image_index(&self) -> Option<c_uint> {
|
||||||
|
|
Loading…
Add table
Reference in a new issue