Implement controller support for the SDL2 frontend
Former-commit-id: 60c49c399631cda7ff069e47718544ffdc93f9b8 Former-commit-id: abe52243473054ba8042a5874cefcdcfa504974a
This commit is contained in:
parent
b745e07fa3
commit
59111ee062
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -1,3 +1,6 @@
|
||||||
[submodule "external/gba-suite"]
|
[submodule "external/gba-suite"]
|
||||||
path = external/gba-suite
|
path = external/gba-suite
|
||||||
url = https://github.com/jsmolka/gba-suite.git
|
url = https://github.com/jsmolka/gba-suite.git
|
||||||
|
[submodule "external/SDL_GameControllerDB"]
|
||||||
|
path = external/SDL_GameControllerDB
|
||||||
|
url = https://github.com/gabomdq/SDL_GameControllerDB
|
||||||
|
|
1
external/SDL_GameControllerDB
vendored
Submodule
1
external/SDL_GameControllerDB
vendored
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 14cb29eb4e33425195629edb44f922e310b75614
|
|
@ -1,4 +1,5 @@
|
||||||
use sdl2::keyboard::Scancode;
|
use sdl2::keyboard::Scancode;
|
||||||
|
use sdl2::controller::Button;
|
||||||
|
|
||||||
use rustboyadvance_core::keypad as gba_keypad;
|
use rustboyadvance_core::keypad as gba_keypad;
|
||||||
use rustboyadvance_core::InputInterface;
|
use rustboyadvance_core::InputInterface;
|
||||||
|
@ -22,11 +23,24 @@ impl Sdl2Input {
|
||||||
self.keyinput.set_bit(key as usize, false);
|
self.keyinput.set_bit(key as usize, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_keyboard_key_up(&mut self, scancode: Scancode) {
|
pub fn on_keyboard_key_up(&mut self, scancode: Scancode) {
|
||||||
if let Some(key) = scancode_to_keypad(scancode) {
|
if let Some(key) = scancode_to_keypad(scancode) {
|
||||||
self.keyinput.set_bit(key as usize, true);
|
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<gba_keypad::Keys> {
|
fn scancode_to_keypad(scancode: Scancode) -> Option<gba_keypad::Keys> {
|
||||||
|
@ -45,6 +59,22 @@ fn scancode_to_keypad(scancode: Scancode) -> Option<gba_keypad::Keys> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn controller_button_to_keypad(button: Button) -> Option<gba_keypad::Keys> {
|
||||||
|
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 {
|
pub fn create_input() -> Sdl2Input {
|
||||||
Sdl2Input {
|
Sdl2Input {
|
||||||
keyinput: gba_keypad::KEYINPUT_ALL_RELEASED,
|
keyinput: gba_keypad::KEYINPUT_ALL_RELEASED,
|
||||||
|
|
|
@ -16,7 +16,7 @@ use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io::Read;
|
use std::io::{Cursor, Read};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::process;
|
use std::process;
|
||||||
use std::time;
|
use std::time;
|
||||||
|
@ -192,6 +192,26 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
|
||||||
canvas.set_logical_size(CANVAS_WIDTH, CANVAS_HEIGHT)?;
|
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::<Vec<u32>>();
|
||||||
|
|
||||||
|
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") {
|
let mut rom_path = match matches.value_of("game_rom") {
|
||||||
Some(path) => path.to_string(),
|
Some(path) => path.to_string(),
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -298,6 +318,12 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
Scancode::Space => frame_limiter = true,
|
Scancode::Space => frame_limiter = true,
|
||||||
k => input.borrow_mut().on_keyboard_key_up(k),
|
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::Quit { .. } => break 'running,
|
||||||
Event::DropFile { filename, .. } => {
|
Event::DropFile { filename, .. } => {
|
||||||
// load the new rom
|
// load the new rom
|
||||||
|
|
Reference in a new issue