mirror of
https://github.com/gopher64/gopher64.git
synced 2026-07-11 01:25:20 +02:00
handle controller reconnection (#815)
This commit is contained in:
@@ -211,6 +211,7 @@ fn main() {
|
||||
.allowlist_function("rdp_save_state")
|
||||
.allowlist_function("rdp_load_state")
|
||||
.allowlist_function("rdp_set_fps")
|
||||
.allowlist_function("get_joystick_event")
|
||||
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
|
||||
.generate()
|
||||
.expect("Unable to generate bindings");
|
||||
|
||||
@@ -98,8 +98,8 @@ static GFX_INFO gfx_info;
|
||||
static const uint32_t *fragment_spirv;
|
||||
static size_t fragment_size;
|
||||
|
||||
std::vector<bool> rdram_dirty;
|
||||
uint64_t sync_signal;
|
||||
static std::vector<bool> rdram_dirty;
|
||||
static uint64_t sync_signal;
|
||||
|
||||
static TTF_Font *message_font;
|
||||
static std::queue<Message> messages;
|
||||
@@ -114,6 +114,8 @@ static bool display_challenge_indicator;
|
||||
static bool display_fps;
|
||||
static Vulkan::ImageHandle fps_image;
|
||||
|
||||
static std::queue<JoystickEvent> joystick_events;
|
||||
|
||||
typedef struct {
|
||||
float SourceSize[4];
|
||||
float OutputSize[4];
|
||||
@@ -125,6 +127,12 @@ static const unsigned cmd_len_lut[64] = {
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
};
|
||||
|
||||
static void add_joystick_event(void *userdata) {
|
||||
JoystickEvent *joystick_event = (JoystickEvent *)userdata;
|
||||
joystick_events.push(*joystick_event);
|
||||
delete joystick_event;
|
||||
}
|
||||
|
||||
bool sdl_event_filter(void *userdata, SDL_Event *event) {
|
||||
if (event->type == SDL_EVENT_WINDOW_CLOSE_REQUESTED) {
|
||||
callback.paused = false;
|
||||
@@ -209,11 +217,29 @@ bool sdl_event_filter(void *userdata, SDL_Event *event) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (event->type == SDL_EVENT_JOYSTICK_ADDED) {
|
||||
JoystickEvent *joystick_event = new JoystickEvent;
|
||||
joystick_event->joystick_id = event->jdevice.which;
|
||||
joystick_event->connected = true;
|
||||
SDL_RunOnMainThread(add_joystick_event, joystick_event, false);
|
||||
} else if (event->type == SDL_EVENT_JOYSTICK_REMOVED) {
|
||||
JoystickEvent *joystick_event = new JoystickEvent;
|
||||
joystick_event->joystick_id = event->jdevice.which;
|
||||
joystick_event->connected = false;
|
||||
SDL_RunOnMainThread(add_joystick_event, joystick_event, false);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
JoystickEvent get_joystick_event() {
|
||||
if (joystick_events.empty())
|
||||
return JoystickEvent{0, false};
|
||||
JoystickEvent joystick_event = joystick_events.front();
|
||||
joystick_events.pop();
|
||||
return joystick_event;
|
||||
}
|
||||
|
||||
void rdp_new_processor(GFX_INFO _gfx_info) {
|
||||
gfx_info = _gfx_info;
|
||||
|
||||
|
||||
@@ -37,6 +37,11 @@ typedef struct {
|
||||
uint32_t save_state_slot;
|
||||
} CALL_BACK;
|
||||
|
||||
typedef struct {
|
||||
uint32_t joystick_id;
|
||||
bool connected;
|
||||
} JoystickEvent;
|
||||
|
||||
typedef enum {
|
||||
MESSAGE_VERY_SHORT = 500,
|
||||
MESSAGE_SHORT = 3000,
|
||||
@@ -59,6 +64,8 @@ void rdp_save_state(uint8_t *state);
|
||||
void rdp_load_state(const uint8_t *state);
|
||||
void rdp_set_fps(uint32_t fps, uint32_t vis);
|
||||
|
||||
JoystickEvent get_joystick_event();
|
||||
|
||||
void achievement_challenge_indicator_add(const char *achievement_title);
|
||||
void achievement_challenge_indicator_remove(const char *achievement_title);
|
||||
void achievement_progress_add(const char *achievement_title,
|
||||
|
||||
@@ -58,12 +58,12 @@ pub fn process(device: &mut device::Device, channel: usize) {
|
||||
let offset = device.pif.channels[channel].rx_buf.unwrap();
|
||||
let input = if let Some(netplay) = &mut device.netplay {
|
||||
if netplay.player_number as usize == channel {
|
||||
let local_input = ui::input::get(&device.ui, 0);
|
||||
let local_input = ui::input::get(&mut device.ui, 0);
|
||||
netplay::send_input(netplay, local_input);
|
||||
}
|
||||
netplay::get_input(device, channel)
|
||||
} else {
|
||||
ui::input::get(&device.ui, channel)
|
||||
ui::input::get(&mut device.ui, channel)
|
||||
};
|
||||
|
||||
device.pif.ram[offset..offset + 4].copy_from_slice(&input.data.to_ne_bytes());
|
||||
|
||||
@@ -151,21 +151,25 @@ impl Ui {
|
||||
game_controller: std::ptr::null_mut(),
|
||||
joystick: std::ptr::null_mut(),
|
||||
rumble: false,
|
||||
guid: sdl3_sys::guid::SDL_GUID::default(),
|
||||
},
|
||||
input::Controllers {
|
||||
game_controller: std::ptr::null_mut(),
|
||||
joystick: std::ptr::null_mut(),
|
||||
rumble: false,
|
||||
guid: sdl3_sys::guid::SDL_GUID::default(),
|
||||
},
|
||||
input::Controllers {
|
||||
game_controller: std::ptr::null_mut(),
|
||||
joystick: std::ptr::null_mut(),
|
||||
rumble: false,
|
||||
guid: sdl3_sys::guid::SDL_GUID::default(),
|
||||
},
|
||||
input::Controllers {
|
||||
game_controller: std::ptr::null_mut(),
|
||||
joystick: std::ptr::null_mut(),
|
||||
rumble: false,
|
||||
guid: sdl3_sys::guid::SDL_GUID::default(),
|
||||
},
|
||||
],
|
||||
keyboard_state: std::ptr::null_mut(),
|
||||
|
||||
+64
-5
@@ -34,6 +34,7 @@ pub struct Controllers {
|
||||
pub rumble: bool,
|
||||
pub game_controller: *mut sdl3_sys::gamepad::SDL_Gamepad,
|
||||
pub joystick: *mut sdl3_sys::joystick::SDL_Joystick,
|
||||
pub guid: sdl3_sys::guid::SDL_GUID,
|
||||
}
|
||||
|
||||
pub struct InputData {
|
||||
@@ -400,9 +401,59 @@ pub fn get_controller_paths(game_ui: &ui::Ui) -> Vec<Option<String>> {
|
||||
controller_paths
|
||||
}
|
||||
|
||||
pub fn get(ui: &ui::Ui, channel: usize) -> InputData {
|
||||
let profile_name = ui.config.input.input_profile_binding[channel].clone();
|
||||
let profile = ui.config.input.input_profiles.get(&profile_name).unwrap();
|
||||
fn handle_joystick_events(ui: &mut ui::Ui) {
|
||||
let joystick_event = unsafe { ui::video::get_joystick_event() };
|
||||
if joystick_event.joystick_id != 0 {
|
||||
let joystick_id = sdl3_sys::joystick::SDL_JoystickID(joystick_event.joystick_id);
|
||||
for (i, controller) in ui.input.controllers.iter_mut().enumerate() {
|
||||
if joystick_event.connected {
|
||||
let profile = ui
|
||||
.config
|
||||
.input
|
||||
.input_profiles
|
||||
.get(&ui.config.input.input_profile_binding[i])
|
||||
.unwrap();
|
||||
if profile.dinput {
|
||||
if controller.joystick.is_null()
|
||||
&& controller.guid
|
||||
== unsafe { sdl3_sys::joystick::SDL_GetJoystickGUIDForID(joystick_id) }
|
||||
{
|
||||
controller.joystick =
|
||||
unsafe { sdl3_sys::joystick::SDL_OpenJoystick(joystick_id) };
|
||||
}
|
||||
} else {
|
||||
if controller.game_controller.is_null()
|
||||
&& controller.guid
|
||||
== unsafe { sdl3_sys::gamepad::SDL_GetGamepadGUIDForID(joystick_id) }
|
||||
{
|
||||
controller.game_controller =
|
||||
unsafe { sdl3_sys::gamepad::SDL_OpenGamepad(joystick_id) };
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if !controller.joystick.is_null()
|
||||
&& controller.joystick
|
||||
== unsafe { sdl3_sys::joystick::SDL_GetJoystickFromID(joystick_id) }
|
||||
{
|
||||
unsafe { sdl3_sys::joystick::SDL_CloseJoystick(controller.joystick) };
|
||||
controller.joystick = std::ptr::null_mut();
|
||||
} else if !controller.game_controller.is_null()
|
||||
&& controller.game_controller
|
||||
== unsafe { sdl3_sys::gamepad::SDL_GetGamepadFromID(joystick_id) }
|
||||
{
|
||||
unsafe { sdl3_sys::gamepad::SDL_CloseGamepad(controller.game_controller) };
|
||||
controller.game_controller = std::ptr::null_mut();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(ui: &mut ui::Ui, channel: usize) -> InputData {
|
||||
handle_joystick_events(ui);
|
||||
|
||||
let profile_name = &ui.config.input.input_profile_binding[channel];
|
||||
let profile = ui.config.input.input_profiles.get(profile_name).unwrap();
|
||||
let mut keys = 0;
|
||||
let controller = ui.input.controllers[channel].game_controller;
|
||||
let joystick = ui.input.controllers[channel].joystick;
|
||||
@@ -990,8 +1041,12 @@ pub fn init(ui: &mut ui::Ui) {
|
||||
}
|
||||
|
||||
if joystick_id != 0 {
|
||||
let profile_name = ui.config.input.input_profile_binding[i].clone();
|
||||
let profile = ui.config.input.input_profiles.get(&profile_name).unwrap();
|
||||
let profile = ui
|
||||
.config
|
||||
.input
|
||||
.input_profiles
|
||||
.get(&ui.config.input.input_profile_binding[i])
|
||||
.unwrap();
|
||||
|
||||
if !profile.dinput {
|
||||
let gamepad = unsafe { sdl3_sys::gamepad::SDL_OpenGamepad(joystick_id) };
|
||||
@@ -999,6 +1054,8 @@ pub fn init(ui: &mut ui::Ui) {
|
||||
println!("could not connect gamepad: {}", u32::from(joystick_id))
|
||||
} else {
|
||||
ui.input.controllers[i].game_controller = gamepad;
|
||||
ui.input.controllers[i].guid =
|
||||
unsafe { sdl3_sys::gamepad::SDL_GetGamepadGUIDForID(joystick_id) };
|
||||
let properties =
|
||||
unsafe { sdl3_sys::gamepad::SDL_GetGamepadProperties(gamepad) };
|
||||
if properties == 0 {
|
||||
@@ -1018,6 +1075,8 @@ pub fn init(ui: &mut ui::Ui) {
|
||||
println!("could not connect joystick: {}", u32::from(joystick_id))
|
||||
} else {
|
||||
ui.input.controllers[i].joystick = joystick;
|
||||
ui.input.controllers[i].guid =
|
||||
unsafe { sdl3_sys::joystick::SDL_GetJoystickGUIDForID(joystick_id) };
|
||||
let properties =
|
||||
unsafe { sdl3_sys::joystick::SDL_GetJoystickProperties(joystick) };
|
||||
if properties == 0 {
|
||||
|
||||
Reference in New Issue
Block a user