implement RETRO_ENVIRONMENT_SET_VARIABLES

This commit is contained in:
lif 2019-11-17 22:03:37 -08:00
parent 0e3ba53eec
commit 871e0f799f
2 changed files with 32 additions and 9 deletions

View File

@ -5,7 +5,7 @@ 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;
use rustro::retro::wrapper::{LibretroWrapper, VariableDescriptor};
use std::ffi::CStr;
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> {
Some(self.core_path.clone())
}

View File

@ -53,7 +53,7 @@ pub trait Handler: Unpin + 'static {
fn set_input_descriptors(&mut self, input_descriptors: &[InputDescriptor]) -> 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: &[Variable]) -> bool { false }
fn set_variables(&mut self, variables: &[VariableDescriptor]) -> 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,6 +80,13 @@ pub trait Handler: Unpin + 'static {
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)]
struct StaticCallbacks {
handler: Option<Pin<&'static mut dyn Handler>>,
@ -122,7 +129,7 @@ impl StaticCallbacks {
}
let handler = maybe_handler?;
let parsed_cmd = cmd.try_into().ok();
if parsed_cmd.is_none() {
if cfg!(debug) && parsed_cmd.is_none() {
eprintln!(
"Unknown{} env cmd: {}",
if cmd >= ENVIRONMENT_EXPERIMENTAL { ", experimental" } else { "" },
@ -160,16 +167,25 @@ impl StaticCallbacks {
EnvCmd::GetVariable => {
let mut var = Self::from_void::<Variable>(data)?;
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)?;
// leaks memory.
var.value = CString::new(value).ok()?.into_raw();
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::SetSupportNoGame => handler.set_support_no_game(*Self::from_void(data)?),
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> {
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) })
}
pub fn disk_get_image_index(&self) -> Option<c_uint> {