sdl: use gamecontroller api for initial btn/axis binding

This commit is contained in:
Flyinghead 2020-12-07 22:18:23 +01:00
parent a39199d379
commit d1fbbac0ae
2 changed files with 84 additions and 35 deletions

View File

@ -41,7 +41,7 @@ static void sdl_open_joystick(int index)
INFO_LOG(INPUT, "SDL: Cannot open joystick %d", index + 1);
return;
}
std::shared_ptr<SDLGamepadDevice> gamepad = std::make_shared<SDLGamepadDevice>(index < MAPLE_PORTS ? index : -1, pJoystick);
std::shared_ptr<SDLGamepadDevice> gamepad = std::make_shared<SDLGamepadDevice>(index < MAPLE_PORTS ? index : -1, index, pJoystick);
SDLGamepadDevice::AddSDLGamepad(gamepad);
}
@ -59,9 +59,17 @@ void input_sdl_init()
// We want joystick events even if we loose focus
SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1");
if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0)
{
die("SDL: error initializing Joystick subsystem");
std::string db = get_readonly_data_path("gamecontrollerdb.txt");
int rv = SDL_GameControllerAddMappingsFromFile(db.c_str());
if (rv < 0)
{
db = get_readonly_config_path("gamecontrollerdb.txt");
rv = SDL_GameControllerAddMappingsFromFile(db.c_str());
}
if (rv > 0)
DEBUG_LOG(INPUT ,"%d mappings loaded from %s", rv, db.c_str());
}
if (SDL_WasInit(SDL_INIT_HAPTIC) == 0)
SDL_InitSubSystem(SDL_INIT_HAPTIC);

View File

@ -21,34 +21,88 @@ public:
set_axis(DC_AXIS_Y2, 3, false);
dirty = false;
}
};
class Xbox360InputMapping : public InputMapping
{
public:
Xbox360InputMapping()
DefaultInputMapping(int joystick_idx) : DefaultInputMapping()
{
name = "Xbox 360";
set_button(DC_BTN_A, 0);
set_button(DC_BTN_B, 1);
set_button(DC_BTN_X, 2);
set_button(DC_BTN_Y, 3);
set_button(DC_BTN_START, 7);
if (SDL_IsGameController(joystick_idx))
{
SDL_GameController *sdl_controller = SDL_GameControllerOpen(joystick_idx);
name = SDL_GameControllerName(sdl_controller);
INFO_LOG(INPUT, "SDL: using SDL game controller mappings for '%s'", name.c_str());
set_axis(DC_AXIS_X, 0, false);
set_axis(DC_AXIS_Y, 1, false);
set_axis(DC_AXIS_LT, 2, false);
set_axis(DC_AXIS_RT, 5, false);
set_axis(DC_DPAD_LEFT, 6, false);
set_axis(DC_DPAD_UP, 7, false);
dirty = false;
auto map_button = [&](SDL_GameControllerButton sdl_btn, DreamcastKey dc_btn) {
SDL_GameControllerButtonBind bind = SDL_GameControllerGetBindForButton(sdl_controller, sdl_btn);
if (bind.bindType == SDL_CONTROLLER_BINDTYPE_BUTTON)
set_button(dc_btn, bind.value.button);
else if (bind.bindType == SDL_CONTROLLER_BINDTYPE_HAT)
{
int dir;
switch (bind.value.hat.hat_mask)
{
case SDL_HAT_UP:
dir = 0;
break;
case SDL_HAT_DOWN:
dir = 1;
break;
case SDL_HAT_LEFT:
dir = 2;
break;
case SDL_HAT_RIGHT:
dir = 3;
break;
default:
return;
}
set_button(dc_btn, ((bind.value.hat.hat + 1) << 8) | dir);
}
};
map_button(SDL_CONTROLLER_BUTTON_A, DC_BTN_A);
map_button(SDL_CONTROLLER_BUTTON_B, DC_BTN_B);
map_button(SDL_CONTROLLER_BUTTON_X, DC_BTN_X);
map_button(SDL_CONTROLLER_BUTTON_Y, DC_BTN_Y);
map_button(SDL_CONTROLLER_BUTTON_START, DC_BTN_START);
map_button(SDL_CONTROLLER_BUTTON_DPAD_UP, DC_DPAD_UP);
map_button(SDL_CONTROLLER_BUTTON_DPAD_DOWN, DC_DPAD_DOWN);
map_button(SDL_CONTROLLER_BUTTON_DPAD_LEFT, DC_DPAD_LEFT);
map_button(SDL_CONTROLLER_BUTTON_DPAD_RIGHT, DC_DPAD_RIGHT);
map_button(SDL_CONTROLLER_BUTTON_BACK, EMU_BTN_MENU);
map_button(SDL_CONTROLLER_BUTTON_LEFTSHOULDER, DC_BTN_C); // service
map_button(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, DC_BTN_Z); // test
auto map_axis = [&](SDL_GameControllerAxis sdl_axis, DreamcastKey dc_axis) {
SDL_GameControllerButtonBind bind = SDL_GameControllerGetBindForAxis(sdl_controller, sdl_axis);
if (bind.bindType != SDL_CONTROLLER_BINDTYPE_AXIS)
return false;
bool invert_axis = false;
const char *s = SDL_GameControllerGetStringForAxis(sdl_axis);
if (s != nullptr && s[strlen(s) - 1] == '~')
invert_axis = true;
set_axis(dc_axis, bind.value.axis, invert_axis);
return true;
};
map_axis(SDL_CONTROLLER_AXIS_LEFTX, DC_AXIS_X);
map_axis(SDL_CONTROLLER_AXIS_LEFTY, DC_AXIS_Y);
map_axis(SDL_CONTROLLER_AXIS_RIGHTX, DC_AXIS_X2);
map_axis(SDL_CONTROLLER_AXIS_RIGHTY, DC_AXIS_Y2);
if (!map_axis(SDL_CONTROLLER_AXIS_TRIGGERLEFT, DC_AXIS_LT))
map_button(SDL_CONTROLLER_BUTTON_LEFTSHOULDER, EMU_BTN_TRIGGER_LEFT);
if (!map_axis(SDL_CONTROLLER_AXIS_TRIGGERRIGHT, DC_AXIS_RT))
map_button(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, EMU_BTN_TRIGGER_RIGHT);
SDL_GameControllerClose(sdl_controller);
dirty = false;
}
else
INFO_LOG(INPUT, "using default mapping");
}
};
class SDLGamepadDevice : public GamepadDevice
{
public:
SDLGamepadDevice(int maple_port, SDL_Joystick* sdl_joystick) : GamepadDevice(maple_port, "SDL"), sdl_joystick(sdl_joystick)
SDLGamepadDevice(int maple_port, int joystick_idx, SDL_Joystick* sdl_joystick) : GamepadDevice(maple_port, "SDL"), sdl_joystick(sdl_joystick)
{
_name = SDL_JoystickName(sdl_joystick);
sdl_joystick_instance = SDL_JoystickInstanceID(sdl_joystick);
@ -56,19 +110,7 @@ public:
INFO_LOG(INPUT, "SDL: Opened joystick %d on port %d: '%s' unique_id=%s", sdl_joystick_instance, maple_port, _name.c_str(), _unique_id.c_str());
if (!find_mapping())
{
if (_name == "Microsoft X-Box 360 pad")
{
input_mapper = std::make_shared<Xbox360InputMapping>();
INFO_LOG(INPUT, "using Xbox 360 mapping");
}
else
{
input_mapper = std::make_shared<DefaultInputMapping>();
INFO_LOG(INPUT, "using default mapping");
}
save_mapping();
}
input_mapper = std::make_shared<DefaultInputMapping>(joystick_idx);
else
INFO_LOG(INPUT, "using custom mapping '%s'", input_mapper->name.c_str());
sdl_haptic = SDL_HapticOpenFromJoystick(sdl_joystick);
@ -77,7 +119,6 @@ public:
SDL_HapticClose(sdl_haptic);
sdl_haptic = NULL;
}
}
virtual void rumble(float power, float inclination, u32 duration_ms) override