mirror of
https://github.com/libretro/ppsspp.git
synced 2025-03-04 22:49:46 +00:00
Let multiple XInput devices be mapped separately. Fixes #8250
This commit is contained in:
parent
b14e10632d
commit
947f8c5bdd
@ -99,7 +99,6 @@ XinputDevice::XinputDevice() {
|
||||
if (LoadXInputDLL() != 0) {
|
||||
WARN_LOG(SCECTRL, "Failed to load XInput! DLL missing");
|
||||
}
|
||||
this->gamepad_idx = -1;
|
||||
}
|
||||
|
||||
XinputDevice::~XinputDevice() {
|
||||
@ -205,121 +204,108 @@ int XinputDevice::UpdateState(InputState &input_state) {
|
||||
if (!s_pXInputDLL)
|
||||
return 0;
|
||||
|
||||
if (this->check_delay-- > 0)
|
||||
return -1;
|
||||
|
||||
XINPUT_STATE state;
|
||||
ZeroMemory( &state, sizeof(XINPUT_STATE) );
|
||||
|
||||
DWORD dwResult;
|
||||
if (this->gamepad_idx >= 0) {
|
||||
dwResult = PPSSPP_XInputGetState( this->gamepad_idx, &state );
|
||||
} else {
|
||||
// use the first gamepad that responds
|
||||
for (int i = 0; i < XUSER_MAX_COUNT; i++) {
|
||||
dwResult = PPSSPP_XInputGetState( i, &state );
|
||||
if (dwResult == ERROR_SUCCESS) {
|
||||
this->gamepad_idx = i;
|
||||
break;
|
||||
}
|
||||
bool anySuccess = false;
|
||||
for (int i = 0; i < XUSER_MAX_COUNT; i++) {
|
||||
XINPUT_STATE state;
|
||||
ZeroMemory(&state, sizeof(XINPUT_STATE));
|
||||
if (check_delay[i]-- > 0)
|
||||
continue;
|
||||
DWORD dwResult = PPSSPP_XInputGetState(i, &state);
|
||||
if (dwResult == ERROR_SUCCESS) {
|
||||
UpdatePad(i, state, input_state);
|
||||
anySuccess = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( dwResult == ERROR_SUCCESS ) {
|
||||
static bool notified = false;
|
||||
if (!notified) {
|
||||
notified = true;
|
||||
KeyMap::NotifyPadConnected("Xbox 360 Pad");
|
||||
}
|
||||
ApplyButtons(state, input_state);
|
||||
|
||||
const float STICK_DEADZONE = g_Config.fXInputAnalogDeadzone;
|
||||
const int STICK_INV_MODE = g_Config.iXInputAnalogInverseMode;
|
||||
const float STICK_INV_DEADZONE = g_Config.fXInputAnalogInverseDeadzone;
|
||||
const float STICK_SENSITIVITY = g_Config.fXInputAnalogSensitivity;
|
||||
|
||||
if (NormalizedDeadzoneDiffers(prevState.Gamepad.sThumbLX, prevState.Gamepad.sThumbLY, state.Gamepad.sThumbLX, state.Gamepad.sThumbLY, STICK_DEADZONE)) {
|
||||
Stick left = NormalizedDeadzoneFilter(state.Gamepad.sThumbLX, state.Gamepad.sThumbLY, STICK_DEADZONE, STICK_INV_MODE, STICK_INV_DEADZONE, STICK_SENSITIVITY);
|
||||
|
||||
AxisInput axis;
|
||||
axis.deviceId = DEVICE_ID_X360_0;
|
||||
axis.axisId = JOYSTICK_AXIS_X;
|
||||
axis.value = left.x;
|
||||
if (prevState.Gamepad.sThumbLX != state.Gamepad.sThumbLX) {
|
||||
NativeAxis(axis);
|
||||
}
|
||||
axis.axisId = JOYSTICK_AXIS_Y;
|
||||
axis.value = left.y;
|
||||
if (prevState.Gamepad.sThumbLY != state.Gamepad.sThumbLY) {
|
||||
NativeAxis(axis);
|
||||
}
|
||||
}
|
||||
|
||||
if (NormalizedDeadzoneDiffers(prevState.Gamepad.sThumbRX, prevState.Gamepad.sThumbRY, state.Gamepad.sThumbRX, state.Gamepad.sThumbRY, STICK_DEADZONE)) {
|
||||
Stick right = NormalizedDeadzoneFilter(state.Gamepad.sThumbRX, state.Gamepad.sThumbRY, STICK_DEADZONE, STICK_INV_MODE, STICK_INV_DEADZONE, STICK_SENSITIVITY);
|
||||
|
||||
AxisInput axis;
|
||||
axis.deviceId = DEVICE_ID_X360_0;
|
||||
axis.axisId = JOYSTICK_AXIS_Z;
|
||||
axis.value = right.x;
|
||||
if (prevState.Gamepad.sThumbRX != state.Gamepad.sThumbRX) {
|
||||
NativeAxis(axis);
|
||||
}
|
||||
axis.axisId = JOYSTICK_AXIS_RZ;
|
||||
axis.value = right.y;
|
||||
if (prevState.Gamepad.sThumbRY != state.Gamepad.sThumbRY) {
|
||||
NativeAxis(axis);
|
||||
}
|
||||
}
|
||||
|
||||
if (NormalizedDeadzoneDiffers(prevState.Gamepad.bLeftTrigger, state.Gamepad.bLeftTrigger, XINPUT_GAMEPAD_TRIGGER_THRESHOLD)) {
|
||||
AxisInput axis;
|
||||
axis.deviceId = DEVICE_ID_X360_0;
|
||||
axis.axisId = JOYSTICK_AXIS_LTRIGGER;
|
||||
axis.value = (float)state.Gamepad.bLeftTrigger / 255.0f;
|
||||
NativeAxis(axis);
|
||||
}
|
||||
|
||||
if (NormalizedDeadzoneDiffers(prevState.Gamepad.bRightTrigger, state.Gamepad.bRightTrigger, XINPUT_GAMEPAD_TRIGGER_THRESHOLD)) {
|
||||
AxisInput axis;
|
||||
axis.deviceId = DEVICE_ID_X360_0;
|
||||
axis.axisId = JOYSTICK_AXIS_RTRIGGER;
|
||||
axis.value = (float)state.Gamepad.bRightTrigger / 255.0f;
|
||||
NativeAxis(axis);
|
||||
}
|
||||
|
||||
this->prevState = state;
|
||||
this->check_delay = 0;
|
||||
|
||||
// If there's an XInput pad, skip following pads. This prevents DInput and XInput
|
||||
// from colliding.
|
||||
return UPDATESTATE_SKIP_PAD;
|
||||
} else {
|
||||
// wait check_delay frames before polling the controller again
|
||||
this->gamepad_idx = -1;
|
||||
this->check_delay = 100;
|
||||
return -1;
|
||||
}
|
||||
// If we get XInput, skip the others. This might not actually be a good idea.
|
||||
return anySuccess ? UPDATESTATE_SKIP_PAD : 0;
|
||||
}
|
||||
|
||||
void XinputDevice::ApplyButtons(XINPUT_STATE &state, InputState &input_state) {
|
||||
void XinputDevice::UpdatePad(int pad, const XINPUT_STATE &state, InputState &input_state) {
|
||||
static bool notified = false;
|
||||
if (!notified) {
|
||||
notified = true;
|
||||
KeyMap::NotifyPadConnected("Xbox 360 Pad");
|
||||
}
|
||||
ApplyButtons(pad, state, input_state);
|
||||
|
||||
const float STICK_DEADZONE = g_Config.fXInputAnalogDeadzone;
|
||||
const int STICK_INV_MODE = g_Config.iXInputAnalogInverseMode;
|
||||
const float STICK_INV_DEADZONE = g_Config.fXInputAnalogInverseDeadzone;
|
||||
const float STICK_SENSITIVITY = g_Config.fXInputAnalogSensitivity;
|
||||
|
||||
if (NormalizedDeadzoneDiffers(prevState[pad].Gamepad.sThumbLX, prevState[pad].Gamepad.sThumbLY, state.Gamepad.sThumbLX, state.Gamepad.sThumbLY, STICK_DEADZONE)) {
|
||||
Stick left = NormalizedDeadzoneFilter(state.Gamepad.sThumbLX, state.Gamepad.sThumbLY, STICK_DEADZONE, STICK_INV_MODE, STICK_INV_DEADZONE, STICK_SENSITIVITY);
|
||||
|
||||
AxisInput axis;
|
||||
axis.deviceId = DEVICE_ID_X360_0 + pad;
|
||||
axis.axisId = JOYSTICK_AXIS_X;
|
||||
axis.value = left.x;
|
||||
if (prevState[pad].Gamepad.sThumbLX != state.Gamepad.sThumbLX) {
|
||||
NativeAxis(axis);
|
||||
}
|
||||
axis.axisId = JOYSTICK_AXIS_Y;
|
||||
axis.value = left.y;
|
||||
if (prevState[pad].Gamepad.sThumbLY != state.Gamepad.sThumbLY) {
|
||||
NativeAxis(axis);
|
||||
}
|
||||
}
|
||||
|
||||
if (NormalizedDeadzoneDiffers(prevState[pad].Gamepad.sThumbRX, prevState[pad].Gamepad.sThumbRY, state.Gamepad.sThumbRX, state.Gamepad.sThumbRY, STICK_DEADZONE)) {
|
||||
Stick right = NormalizedDeadzoneFilter(state.Gamepad.sThumbRX, state.Gamepad.sThumbRY, STICK_DEADZONE, STICK_INV_MODE, STICK_INV_DEADZONE, STICK_SENSITIVITY);
|
||||
|
||||
AxisInput axis;
|
||||
axis.deviceId = DEVICE_ID_X360_0 + pad;
|
||||
axis.axisId = JOYSTICK_AXIS_Z;
|
||||
axis.value = right.x;
|
||||
if (prevState[pad].Gamepad.sThumbRX != state.Gamepad.sThumbRX) {
|
||||
NativeAxis(axis);
|
||||
}
|
||||
axis.axisId = JOYSTICK_AXIS_RZ;
|
||||
axis.value = right.y;
|
||||
if (prevState[pad].Gamepad.sThumbRY != state.Gamepad.sThumbRY) {
|
||||
NativeAxis(axis);
|
||||
}
|
||||
}
|
||||
|
||||
if (NormalizedDeadzoneDiffers(prevState[pad].Gamepad.bLeftTrigger, state.Gamepad.bLeftTrigger, XINPUT_GAMEPAD_TRIGGER_THRESHOLD)) {
|
||||
AxisInput axis;
|
||||
axis.deviceId = DEVICE_ID_X360_0 + pad;
|
||||
axis.axisId = JOYSTICK_AXIS_LTRIGGER;
|
||||
axis.value = (float)state.Gamepad.bLeftTrigger / 255.0f;
|
||||
NativeAxis(axis);
|
||||
}
|
||||
|
||||
if (NormalizedDeadzoneDiffers(prevState[pad].Gamepad.bRightTrigger, state.Gamepad.bRightTrigger, XINPUT_GAMEPAD_TRIGGER_THRESHOLD)) {
|
||||
AxisInput axis;
|
||||
axis.deviceId = DEVICE_ID_X360_0 + pad;
|
||||
axis.axisId = JOYSTICK_AXIS_RTRIGGER;
|
||||
axis.value = (float)state.Gamepad.bRightTrigger / 255.0f;
|
||||
NativeAxis(axis);
|
||||
}
|
||||
|
||||
this->prevState[pad] = state;
|
||||
this->check_delay[pad] = 0;
|
||||
}
|
||||
|
||||
void XinputDevice::ApplyButtons(int pad, const XINPUT_STATE &state, InputState &input_state) {
|
||||
u32 buttons = state.Gamepad.wButtons;
|
||||
|
||||
u32 downMask = buttons & (~prevButtons);
|
||||
u32 upMask = (~buttons) & prevButtons;
|
||||
prevButtons = buttons;
|
||||
u32 downMask = buttons & (~prevButtons[pad]);
|
||||
u32 upMask = (~buttons) & prevButtons[pad];
|
||||
prevButtons[pad] = buttons;
|
||||
|
||||
for (int i = 0; i < xinput_ctrl_map_size; i++) {
|
||||
if (downMask & xinput_ctrl_map[i].from) {
|
||||
KeyInput key;
|
||||
key.deviceId = DEVICE_ID_X360_0;
|
||||
key.deviceId = DEVICE_ID_X360_0 + pad;
|
||||
key.flags = KEY_DOWN;
|
||||
key.keyCode = xinput_ctrl_map[i].to;
|
||||
NativeKey(key);
|
||||
}
|
||||
if (upMask & xinput_ctrl_map[i].from) {
|
||||
KeyInput key;
|
||||
key.deviceId = DEVICE_ID_X360_0;
|
||||
key.deviceId = DEVICE_ID_X360_0 + pad;
|
||||
key.flags = KEY_UP;
|
||||
key.keyCode = xinput_ctrl_map[i].to;
|
||||
NativeKey(key);
|
||||
|
@ -10,10 +10,11 @@ public:
|
||||
~XinputDevice();
|
||||
virtual int UpdateState(InputState &input_state);
|
||||
virtual bool IsPad() { return true; }
|
||||
|
||||
private:
|
||||
void ApplyButtons(XINPUT_STATE &state, InputState &input_state);
|
||||
int gamepad_idx;
|
||||
int check_delay = 0;
|
||||
XINPUT_STATE prevState{};
|
||||
u32 prevButtons = 0;
|
||||
void UpdatePad(int pad, const XINPUT_STATE &state, InputState &input_state);
|
||||
void ApplyButtons(int pad, const XINPUT_STATE &state, InputState &input_state);
|
||||
int check_delay[4]{};
|
||||
XINPUT_STATE prevState[4]{};
|
||||
u32 prevButtons[4]{};
|
||||
};
|
@ -18,6 +18,9 @@ const char *GetDeviceName(int deviceId) {
|
||||
case DEVICE_ID_PAD_8: return "pad9";
|
||||
case DEVICE_ID_PAD_9: return "pad10";
|
||||
case DEVICE_ID_X360_0: return "x360";
|
||||
case DEVICE_ID_X360_1: return "x360_2";
|
||||
case DEVICE_ID_X360_2: return "x360_3";
|
||||
case DEVICE_ID_X360_3: return "x360_4";
|
||||
case DEVICE_ID_ACCELEROMETER: return "accelerometer";
|
||||
case DEVICE_ID_MOUSE: return "mouse";
|
||||
default:
|
||||
|
@ -34,6 +34,9 @@ enum {
|
||||
DEVICE_ID_PAD_8 = 18,
|
||||
DEVICE_ID_PAD_9 = 19,
|
||||
DEVICE_ID_X360_0 = 20, // XInput joypads
|
||||
DEVICE_ID_X360_1 = 21,
|
||||
DEVICE_ID_X360_2 = 22,
|
||||
DEVICE_ID_X360_3 = 23,
|
||||
DEVICE_ID_ACCELEROMETER = 30,
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user