From 59111ee06253b966029853adf06837fdc7ef2496 Mon Sep 17 00:00:00 2001 From: Tibor Nagy Date: Sat, 9 May 2020 23:51:40 +0200 Subject: [PATCH] Implement controller support for the SDL2 frontend Former-commit-id: 60c49c399631cda7ff069e47718544ffdc93f9b8 Former-commit-id: abe52243473054ba8042a5874cefcdcfa504974a --- .gitmodules | 3 +++ external/SDL_GameControllerDB | 1 + platform/rustboyadvance-sdl2/src/input.rs | 30 +++++++++++++++++++++++ platform/rustboyadvance-sdl2/src/main.rs | 28 ++++++++++++++++++++- 4 files changed, 61 insertions(+), 1 deletion(-) create mode 160000 external/SDL_GameControllerDB diff --git a/.gitmodules b/.gitmodules index 67fe5ea..a114108 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "external/gba-suite"] path = external/gba-suite url = https://github.com/jsmolka/gba-suite.git +[submodule "external/SDL_GameControllerDB"] + path = external/SDL_GameControllerDB + url = https://github.com/gabomdq/SDL_GameControllerDB diff --git a/external/SDL_GameControllerDB b/external/SDL_GameControllerDB new file mode 160000 index 0000000..14cb29e --- /dev/null +++ b/external/SDL_GameControllerDB @@ -0,0 +1 @@ +Subproject commit 14cb29eb4e33425195629edb44f922e310b75614 diff --git a/platform/rustboyadvance-sdl2/src/input.rs b/platform/rustboyadvance-sdl2/src/input.rs index df2207c..407ddf6 100644 --- a/platform/rustboyadvance-sdl2/src/input.rs +++ b/platform/rustboyadvance-sdl2/src/input.rs @@ -1,4 +1,5 @@ use sdl2::keyboard::Scancode; +use sdl2::controller::Button; use rustboyadvance_core::keypad as gba_keypad; use rustboyadvance_core::InputInterface; @@ -22,11 +23,24 @@ impl Sdl2Input { self.keyinput.set_bit(key as usize, false); } } + pub fn on_keyboard_key_up(&mut self, scancode: Scancode) { if let Some(key) = scancode_to_keypad(scancode) { self.keyinput.set_bit(key as usize, true); } } + + pub fn on_controller_button_down(&mut self, button: Button) { + if let Some(key) = controller_button_to_keypad(button) { + self.keyinput.set_bit(key as usize, false); + } + } + + pub fn on_controller_button_up(&mut self, button: Button) { + if let Some(key) = controller_button_to_keypad(button) { + self.keyinput.set_bit(key as usize, true); + } + } } fn scancode_to_keypad(scancode: Scancode) -> Option { @@ -45,6 +59,22 @@ fn scancode_to_keypad(scancode: Scancode) -> Option { } } +fn controller_button_to_keypad(button: Button) -> Option { + match button { + Button::DPadUp => Some(gba_keypad::Keys::Up), + Button::DPadDown => Some(gba_keypad::Keys::Down), + Button::DPadLeft => Some(gba_keypad::Keys::Left), + Button::DPadRight => Some(gba_keypad::Keys::Right), + Button::A => Some(gba_keypad::Keys::ButtonB), // A and B are swapped compared to the SDL layout + Button::B => Some(gba_keypad::Keys::ButtonA), + Button::Start => Some(gba_keypad::Keys::Start), + Button::Back => Some(gba_keypad::Keys::Select), + Button::LeftShoulder => Some(gba_keypad::Keys::ButtonL), + Button::RightShoulder => Some(gba_keypad::Keys::ButtonR), + _ => None, + } +} + pub fn create_input() -> Sdl2Input { Sdl2Input { keyinput: gba_keypad::KEYINPUT_ALL_RELEASED, diff --git a/platform/rustboyadvance-sdl2/src/main.rs b/platform/rustboyadvance-sdl2/src/main.rs index f38fc5a..17011db 100644 --- a/platform/rustboyadvance-sdl2/src/main.rs +++ b/platform/rustboyadvance-sdl2/src/main.rs @@ -16,7 +16,7 @@ use std::cell::RefCell; use std::rc::Rc; use std::fs; -use std::io::Read; +use std::io::{Cursor, Read}; use std::path::{Path, PathBuf}; use std::process; use std::time; @@ -192,6 +192,26 @@ fn main() -> Result<(), Box> { canvas.set_logical_size(CANVAS_WIDTH, CANVAS_HEIGHT)?; + let controller_subsystem = sdl_context.game_controller()?; + let controller_mappings = include_str!("../../../external/SDL_GameControllerDB/gamecontrollerdb.txt"); + controller_subsystem.load_mappings_from_read(&mut Cursor::new(controller_mappings))?; + + let available_controllers = (0..controller_subsystem.num_joysticks()?) + .filter(|&id| controller_subsystem.is_game_controller(id)) + .collect::>(); + + let _active_controller = match available_controllers.first() { + Some(&id) => { + let controller = controller_subsystem.open(id)?; + info!("Found game controller: {}", controller.name()); + Some(controller) + }, + _ => { + info!("No game controllers were found"); + None + }, + }; + let mut rom_path = match matches.value_of("game_rom") { Some(path) => path.to_string(), _ => { @@ -298,6 +318,12 @@ fn main() -> Result<(), Box> { Scancode::Space => frame_limiter = true, k => input.borrow_mut().on_keyboard_key_up(k), }, + Event::ControllerButtonDown { button, .. } => { + input.borrow_mut().on_controller_button_down(button); + }, + Event::ControllerButtonUp { button, .. } => { + input.borrow_mut().on_controller_button_up(button); + }, Event::Quit { .. } => break 'running, Event::DropFile { filename, .. } => { // load the new rom