Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 19 additions & 4 deletions rpcs3/Input/sdl_instance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@ void sdl_instance::pump_events()
SDL_PumpEvents();
}

void sdl_instance::set_hint(const char* name, const char* value)
{
if (!SDL_SetHint(name, value))
{
sdl_log.error("Could not set hint '%s' to '%s': %s", name, value, SDL_GetError());
}
}

bool sdl_instance::initialize()
{
const std::lock_guard<std::mutex> lock(m_instance_mutex);
Expand All @@ -52,10 +60,14 @@ bool sdl_instance::initialize()
sdl_log.notice("Initializing SDL ...");

// Set non-dynamic hints before SDL_Init
if (!SDL_SetHint(SDL_HINT_JOYSTICK_THREAD, "1"))
{
sdl_log.error("Could not set SDL_HINT_JOYSTICK_THREAD: %s", SDL_GetError());
}
set_hint(SDL_HINT_JOYSTICK_THREAD, "1");

// DS3 pressure sensitive buttons
#ifdef _WIN32
set_hint(SDL_HINT_JOYSTICK_HIDAPI_PS3_SIXAXIS_DRIVER, "1");
#else
set_hint(SDL_HINT_JOYSTICK_HIDAPI_PS3, "1");
#endif

if (!SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD))
{
Expand Down Expand Up @@ -96,6 +108,9 @@ bool sdl_instance::initialize()
case SDL_LOG_CATEGORY_TEST:
category_name = "test";
break;
case SDL_LOG_CATEGORY_GPU:
category_name = "gpu";
break;
default:
category_name = fmt::format("unknown(%d)", category);
break;
Expand Down
6 changes: 6 additions & 0 deletions rpcs3/Input/sdl_instance.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#ifdef HAVE_SDL3

#include <mutex>

struct sdl_instance
Expand All @@ -14,6 +16,10 @@ struct sdl_instance
void pump_events();

private:
void set_hint(const char* name, const char* value);

bool m_initialized = false;
std::mutex m_instance_mutex;
};

#endif
127 changes: 121 additions & 6 deletions rpcs3/Input/sdl_pad_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ sdl_pad_handler::sdl_pad_handler() : PadHandlerBase(pad_handler::sdl)
{ SDLKeyCodes::RS, "RS" },
{ SDLKeyCodes::Guide, "Guide" },
{ SDLKeyCodes::Misc1, "Misc 1" },
{ SDLKeyCodes::Misc2, "Misc 2" },
{ SDLKeyCodes::Misc3, "Misc 3" },
{ SDLKeyCodes::Misc4, "Misc 4" },
{ SDLKeyCodes::Misc5, "Misc 5" },
{ SDLKeyCodes::Misc6, "Misc 6" },
{ SDLKeyCodes::RPaddle1, "R Paddle 1" },
{ SDLKeyCodes::LPaddle1, "L Paddle 1" },
{ SDLKeyCodes::RPaddle2, "R Paddle 2" },
Expand All @@ -51,6 +56,16 @@ sdl_pad_handler::sdl_pad_handler() : PadHandlerBase(pad_handler::sdl)
{ SDLKeyCodes::RSXPos, "RS X+" },
{ SDLKeyCodes::RSYPos, "RS Y+" },
{ SDLKeyCodes::RSYNeg, "RS Y-" },
{ SDLKeyCodes::PressureCross, "South" }, // Same name as non-pressure button
{ SDLKeyCodes::PressureCircle, "East" }, // Same name as non-pressure button
{ SDLKeyCodes::PressureSquare, "West" }, // Same name as non-pressure button
{ SDLKeyCodes::PressureTriangle, "North" }, // Same name as non-pressure button
{ SDLKeyCodes::PressureL1, "LB" }, // Same name as non-pressure button
{ SDLKeyCodes::PressureR1, "RB" }, // Same name as non-pressure button
{ SDLKeyCodes::PressureUp, "Up" }, // Same name as non-pressure button
{ SDLKeyCodes::PressureDown, "Down" }, // Same name as non-pressure button
{ SDLKeyCodes::PressureLeft, "Left" }, // Same name as non-pressure button
{ SDLKeyCodes::PressureRight, "Right" }, // Same name as non-pressure button
};

init_configs();
Expand Down Expand Up @@ -242,6 +257,7 @@ SDLDevice::sdl_info sdl_pad_handler::get_sdl_info(SDL_JoystickID id)
}

info.type = SDL_GetGamepadType(info.gamepad);
info.real_type = SDL_GetRealGamepadType(info.gamepad);
info.vid = SDL_GetGamepadVendor(info.gamepad);
info.pid = SDL_GetGamepadProduct(info.gamepad);
info.product_version = SDL_GetGamepadProductVersion(info.gamepad);
Expand Down Expand Up @@ -275,8 +291,8 @@ SDLDevice::sdl_info sdl_pad_handler::get_sdl_info(SDL_JoystickID id)
}
}

sdl_log.notice("Found game pad %d: type=%d, name='%s', path='%s', serial='%s', vid=0x%x, pid=0x%x, product_version=0x%x, firmware_version=0x%x, has_led=%d, has_player_led=%d, has_mono_led=%d, has_rumble=%d, has_rumble_triggers=%d, has_accel=%d, has_gyro=%d",
id, static_cast<int>(info.type), info.name, info.path, info.serial, info.vid, info.pid, info.product_version, info.firmware_version, info.has_led, info.has_player_led, info.has_mono_led, info.has_rumble, info.has_rumble_triggers, info.has_accel, info.has_gyro);
sdl_log.notice("Found game pad %d: type=%d, real_type=%d, name='%s', path='%s', serial='%s', vid=0x%x, pid=0x%x, product_version=0x%x, firmware_version=0x%x, has_led=%d, has_player_led=%d, has_mono_led=%d, has_rumble=%d, has_rumble_triggers=%d, has_accel=%d, has_gyro=%d",
id, static_cast<int>(info.type), static_cast<int>(info.real_type), info.name, info.path, info.serial, info.vid, info.pid, info.product_version, info.firmware_version, info.has_led, info.has_player_led, info.has_mono_led, info.has_rumble, info.has_rumble_triggers, info.has_accel, info.has_gyro);

if (info.has_accel)
{
Expand Down Expand Up @@ -326,6 +342,33 @@ SDLDevice::sdl_info sdl_pad_handler::get_sdl_info(SDL_JoystickID id)
}
}

// The DS3 may have extra pressure sensitive buttons as axis
if (info.real_type == SDL_GamepadType::SDL_GAMEPAD_TYPE_PS3)
{
if (SDL_Joystick* joystick = SDL_GetGamepadJoystick(info.gamepad))
{
const int num_axes = SDL_GetNumJoystickAxes(joystick);
const int num_buttons = SDL_GetNumJoystickButtons(joystick);

info.is_ds3_with_pressure_buttons = num_axes == 16 && num_buttons == 11;

sdl_log.notice("DS3 device %d has %d axis and %d buttons (has_pressure_buttons=%d)", id, num_axes, num_buttons, info.is_ds3_with_pressure_buttons);

if (info.is_ds3_with_pressure_buttons)
{
// Add pressure buttons
for (int i = SDL_GAMEPAD_AXIS_COUNT; i < num_axes; i++)
{
const SDL_GamepadAxis axis_id = static_cast<SDL_GamepadAxis>(i);
//if (SDL_GamepadHasAxis(info.gamepad, axis_id)) // Always returns false for axis >= SDL_GAMEPAD_AXIS_COUNT
{
info.axis_ids.insert(axis_id);
}
}
}
}
}

return info;
}

Expand Down Expand Up @@ -623,7 +666,7 @@ void sdl_pad_handler::get_extended_info(const pad_ensemble& binding)
{
const f32 accel_x = dev->values_accel[0]; // Angular speed around the x axis (pitch)
const f32 accel_y = dev->values_accel[1]; // Angular speed around the y axis (yaw)
const f32 accel_z = dev->values_accel[2]; // Angular speed around the z axis (roll
const f32 accel_z = dev->values_accel[2]; // Angular speed around the z axis (roll)

// Convert to ds3. The ds3 resolution is 113/G.
pad->m_sensors[0].m_value = Clamp0To1023((accel_x / SDL_STANDARD_GRAVITY) * -1 * MOTION_ONE_G + 512);
Expand Down Expand Up @@ -873,18 +916,61 @@ std::unordered_map<u64, u16> sdl_pad_handler::get_button_values(const std::share
if (!dev || !dev->sdl.gamepad)
return values;

std::set<SDLKeyCodes> pressed_pressure_buttons;

for (SDL_GamepadButton button_id : dev->sdl.button_ids)
{
const u8 value = SDL_GetGamepadButton(dev->sdl.gamepad, button_id);
const bool value = SDL_GetGamepadButton(dev->sdl.gamepad, button_id);
const SDLKeyCodes key_code = get_button_code(button_id);

// TODO: SDL does not support DS3 button intensity in the current version
// NOTE: SDL does not simply support DS3 button intensity in the current version
// So we have to skip the normal buttons if a DS3 with pressure buttons was detected
if (dev->sdl.is_ds3_with_pressure_buttons)
{
switch (key_code)
{
case SDLKeyCodes::North:
case SDLKeyCodes::South:
case SDLKeyCodes::West:
case SDLKeyCodes::East:
case SDLKeyCodes::Left:
case SDLKeyCodes::Right:
case SDLKeyCodes::Up:
case SDLKeyCodes::Down:
case SDLKeyCodes::LB:
case SDLKeyCodes::RB:
{
static const std::map<SDLKeyCodes, SDLKeyCodes> button_to_pressure =
{
{ SDLKeyCodes::South, SDLKeyCodes::PressureCross },
{ SDLKeyCodes::East, SDLKeyCodes::PressureCircle },
{ SDLKeyCodes::West, SDLKeyCodes::PressureSquare },
{ SDLKeyCodes::North, SDLKeyCodes::PressureTriangle },
{ SDLKeyCodes::LB, SDLKeyCodes::PressureL1 },
{ SDLKeyCodes::RB, SDLKeyCodes::PressureR1 },
{ SDLKeyCodes::Up, SDLKeyCodes::PressureUp },
{ SDLKeyCodes::Down, SDLKeyCodes::PressureDown },
{ SDLKeyCodes::Left, SDLKeyCodes::PressureLeft },
{ SDLKeyCodes::Right, SDLKeyCodes::PressureRight }
};

if (value)
{
pressed_pressure_buttons.insert(::at32(button_to_pressure, key_code));
}
continue;
}
default:
break;
}
}

values[key_code] = value ? 255 : 0;
}

for (SDL_GamepadAxis axis_id : dev->sdl.axis_ids)
{
const s16 value = SDL_GetGamepadAxis(dev->sdl.gamepad, axis_id);
s16 value = SDL_GetGamepadAxis(dev->sdl.gamepad, axis_id);

switch (axis_id)
{
Expand All @@ -911,8 +997,32 @@ std::unordered_map<u64, u16> sdl_pad_handler::get_button_values(const std::share
values[SDLKeyCodes::RSYPos] = value < 0 ? std::abs(value) - 1 : 0;
break;
default:
{
if (dev->sdl.is_ds3_with_pressure_buttons)
{
// Get pressure button value from axis
if (const int key_code = SDLKeyCodes::PressureBegin + 1 + axis_id - SDL_GAMEPAD_AXIS_COUNT;
key_code > SDLKeyCodes::PressureBegin && key_code < SDLKeyCodes::PressureEnd)
{
// We need to get the joystick value directly for axis >= SDL_GAMEPAD_AXIS_COUNT
if (SDL_Joystick* joystick = SDL_GetGamepadJoystick(dev->sdl.gamepad))
{
value = SDL_GetJoystickAxis(joystick, axis_id);
}

value = static_cast<s16>(ScaledInput(value, SDL_JOYSTICK_AXIS_MIN, SDL_JOYSTICK_AXIS_MAX, 0.0f, 255.0f));

if (value <= 0 && pressed_pressure_buttons.contains(static_cast<SDLKeyCodes>(key_code)))
{
value = 1;
}

values[key_code] = Clamp0To255(value);
}
}
break;
}
}
}

for (const SDLDevice::touchpad& touchpad : dev->sdl.touchpads)
Expand Down Expand Up @@ -1006,6 +1116,11 @@ sdl_pad_handler::SDLKeyCodes sdl_pad_handler::get_button_code(SDL_GamepadButton
case SDL_GamepadButton::SDL_GAMEPAD_BUTTON_RIGHT_STICK: return SDLKeyCodes::RS;
case SDL_GamepadButton::SDL_GAMEPAD_BUTTON_GUIDE: return SDLKeyCodes::Guide;
case SDL_GamepadButton::SDL_GAMEPAD_BUTTON_MISC1: return SDLKeyCodes::Misc1;
case SDL_GamepadButton::SDL_GAMEPAD_BUTTON_MISC2: return SDLKeyCodes::Misc2;
case SDL_GamepadButton::SDL_GAMEPAD_BUTTON_MISC3: return SDLKeyCodes::Misc3;
case SDL_GamepadButton::SDL_GAMEPAD_BUTTON_MISC4: return SDLKeyCodes::Misc4;
case SDL_GamepadButton::SDL_GAMEPAD_BUTTON_MISC5: return SDLKeyCodes::Misc5;
case SDL_GamepadButton::SDL_GAMEPAD_BUTTON_MISC6: return SDLKeyCodes::Misc6;
case SDL_GamepadButton::SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1: return SDLKeyCodes::RPaddle1;
case SDL_GamepadButton::SDL_GAMEPAD_BUTTON_LEFT_PADDLE1: return SDLKeyCodes::LPaddle1;
case SDL_GamepadButton::SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2: return SDLKeyCodes::RPaddle2;
Expand Down
23 changes: 22 additions & 1 deletion rpcs3/Input/sdl_pad_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class SDLDevice : public PadDevice
{
SDL_Gamepad* gamepad = nullptr;
SDL_GamepadType type = SDL_GamepadType::SDL_GAMEPAD_TYPE_UNKNOWN;
SDL_GamepadType real_type = SDL_GamepadType::SDL_GAMEPAD_TYPE_UNKNOWN;
int power_level = 0;
int last_power_level = 0;

Expand All @@ -47,6 +48,7 @@ class SDLDevice : public PadDevice
u16 firmware_version = 0;

bool is_virtual_device = false;
bool is_ds3_with_pressure_buttons = false;

bool has_led = false;
bool has_mono_led = false;
Expand Down Expand Up @@ -98,6 +100,11 @@ class sdl_pad_handler : public PadHandlerBase
Back,
Guide,
Misc1,
Misc2,
Misc3,
Misc4,
Misc5,
Misc6,
RPaddle1,
LPaddle1,
RPaddle2,
Expand All @@ -119,7 +126,21 @@ class sdl_pad_handler : public PadHandlerBase
RSXNeg,
RSXPos,
RSYNeg,
RSYPos
RSYPos,

// DS3 Pressure sensitive buttons (reported as axis)
PressureBegin,
PressureCross, // Cross axis 6
PressureCircle, // Circle axis 7
PressureSquare, // Square axis 8
PressureTriangle, // Triangle axis 9
PressureL1, // L1 axis 10
PressureR1, // R1 axis 11
PressureUp, // D-Pad Up axis 12
PressureDown, // D-Pad Down axis 13
PressureLeft, // D-Pad Left axis 14
PressureRight, // D-Pad Right axis 15
PressureEnd,
};

public:
Expand Down