WinRT: Fixed game controller axis mappings
SDL/WinRT currently uses a separate XInput backend from SDL/Win32, as WinRT has no support for DirectInput. This change makes SDL/WinRT's XInput code snag some recently-changed bits from the Win32-specific, DirectInput + XInput backend, in order to get the SDL_GameController API working again on WinRT, insofar that axes map to the correct parts. TODO: - test all buttons, making sure WinRT maps buttons the same way that Win32 does - consider making the Win32 and WinRT codebases share more stuff, minus the sort of duplication happening via this change. Maybe simulate, or stub-out, DirectInput calls when on WinRT?main
parent
a838a56d45
commit
65023e0767
|
@ -43,6 +43,10 @@
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <Xinput.h>
|
#include <Xinput.h>
|
||||||
|
|
||||||
|
#ifndef XINPUT_GAMEPAD_GUIDE
|
||||||
|
#define XINPUT_GAMEPAD_GUIDE 0x0400
|
||||||
|
#endif
|
||||||
|
|
||||||
struct joystick_hwdata {
|
struct joystick_hwdata {
|
||||||
//Uint8 bXInputHaptic; // Supports force feedback via XInput.
|
//Uint8 bXInputHaptic; // Supports force feedback via XInput.
|
||||||
DWORD userIndex; // The XInput device index, in the range [0, XUSER_MAX_COUNT-1] (probably [0,3]).
|
DWORD userIndex; // The XInput device index, in the range [0, XUSER_MAX_COUNT-1] (probably [0,3]).
|
||||||
|
@ -377,6 +381,51 @@ static int ButtonChanged( int ButtonsNow, int ButtonsPrev, int ButtonMask )
|
||||||
return ( ButtonsNow & ButtonMask ) != ( ButtonsPrev & ButtonMask );
|
return ( ButtonsNow & ButtonMask ) != ( ButtonsPrev & ButtonMask );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This is an almost-identical copy of UpdateXInputJoystickState from the
|
||||||
|
DirectInput + XInput backend.
|
||||||
|
|
||||||
|
TODO, WinRT: look into making the DirectInput+Xinput and WinRT/XInput joystick backends share more code, without duplication
|
||||||
|
TODO, WinRT: consider adding support for the "old" XInput controller mapping (via SDL_HINT_XINPUT_USE_OLD_JOYSTICK_MAPPING)
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
UpdateXInputJoystickState(SDL_Joystick * joystick, XINPUT_STATE *pXInputState)
|
||||||
|
{
|
||||||
|
static WORD s_XInputButtons[] = {
|
||||||
|
XINPUT_GAMEPAD_A, XINPUT_GAMEPAD_B, XINPUT_GAMEPAD_X, XINPUT_GAMEPAD_Y,
|
||||||
|
XINPUT_GAMEPAD_LEFT_SHOULDER, XINPUT_GAMEPAD_RIGHT_SHOULDER, XINPUT_GAMEPAD_BACK, XINPUT_GAMEPAD_START,
|
||||||
|
XINPUT_GAMEPAD_LEFT_THUMB, XINPUT_GAMEPAD_RIGHT_THUMB,
|
||||||
|
XINPUT_GAMEPAD_GUIDE
|
||||||
|
};
|
||||||
|
WORD wButtons = pXInputState->Gamepad.wButtons;
|
||||||
|
Uint8 button;
|
||||||
|
Uint8 hat = SDL_HAT_CENTERED;
|
||||||
|
|
||||||
|
SDL_PrivateJoystickAxis(joystick, 0, (Sint16)pXInputState->Gamepad.sThumbLX);
|
||||||
|
SDL_PrivateJoystickAxis(joystick, 1, (Sint16)(-SDL_max(-32767, pXInputState->Gamepad.sThumbLY)));
|
||||||
|
SDL_PrivateJoystickAxis(joystick, 2, (Sint16)(((int)pXInputState->Gamepad.bLeftTrigger * 65535 / 255) - 32768));
|
||||||
|
SDL_PrivateJoystickAxis(joystick, 3, (Sint16)pXInputState->Gamepad.sThumbRX);
|
||||||
|
SDL_PrivateJoystickAxis(joystick, 4, (Sint16)(-SDL_max(-32767, pXInputState->Gamepad.sThumbRY)));
|
||||||
|
SDL_PrivateJoystickAxis(joystick, 5, (Sint16)(((int)pXInputState->Gamepad.bRightTrigger * 65535 / 255) - 32768));
|
||||||
|
|
||||||
|
for (button = 0; button < SDL_arraysize(s_XInputButtons); ++button) {
|
||||||
|
SDL_PrivateJoystickButton(joystick, button, (wButtons & s_XInputButtons[button]) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wButtons & XINPUT_GAMEPAD_DPAD_UP) {
|
||||||
|
hat |= SDL_HAT_UP;
|
||||||
|
}
|
||||||
|
if (wButtons & XINPUT_GAMEPAD_DPAD_DOWN) {
|
||||||
|
hat |= SDL_HAT_DOWN;
|
||||||
|
}
|
||||||
|
if (wButtons & XINPUT_GAMEPAD_DPAD_LEFT) {
|
||||||
|
hat |= SDL_HAT_LEFT;
|
||||||
|
}
|
||||||
|
if (wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) {
|
||||||
|
hat |= SDL_HAT_RIGHT;
|
||||||
|
}
|
||||||
|
SDL_PrivateJoystickHat(joystick, 0, hat);
|
||||||
|
}
|
||||||
|
|
||||||
/* Function to update the state of a joystick - called as a device poll.
|
/* Function to update the state of a joystick - called as a device poll.
|
||||||
* This function shouldn't update the joystick structure directly,
|
* This function shouldn't update the joystick structure directly,
|
||||||
* but instead should call SDL_PrivateJoystick*() to deliver events
|
* but instead should call SDL_PrivateJoystick*() to deliver events
|
||||||
|
@ -413,45 +462,7 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
|
||||||
&& joystick->hwdata->XInputState.dwPacketNumber != prevXInputState.dwPacketNumber )
|
&& joystick->hwdata->XInputState.dwPacketNumber != prevXInputState.dwPacketNumber )
|
||||||
{
|
{
|
||||||
XINPUT_STATE *pXInputState = &joystick->hwdata->XInputState;
|
XINPUT_STATE *pXInputState = &joystick->hwdata->XInputState;
|
||||||
XINPUT_STATE *pXInputStatePrev = &prevXInputState;
|
UpdateXInputJoystickState(joystick, pXInputState);
|
||||||
|
|
||||||
SDL_PrivateJoystickAxis(joystick, 0, (Sint16)pXInputState->Gamepad.sThumbLX );
|
|
||||||
SDL_PrivateJoystickAxis(joystick, 1, (Sint16)(-1*pXInputState->Gamepad.sThumbLY-1) );
|
|
||||||
SDL_PrivateJoystickAxis(joystick, 2, (Sint16)pXInputState->Gamepad.sThumbRX );
|
|
||||||
SDL_PrivateJoystickAxis(joystick, 3, (Sint16)(-1*pXInputState->Gamepad.sThumbRY-1) );
|
|
||||||
SDL_PrivateJoystickAxis(joystick, 4, (Sint16)((int)pXInputState->Gamepad.bLeftTrigger*32767/255) );
|
|
||||||
SDL_PrivateJoystickAxis(joystick, 5, (Sint16)((int)pXInputState->Gamepad.bRightTrigger*32767/255) );
|
|
||||||
|
|
||||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_DPAD_UP ) )
|
|
||||||
SDL_PrivateJoystickButton(joystick, 0, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP ? SDL_PRESSED : SDL_RELEASED );
|
|
||||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_DPAD_DOWN ) )
|
|
||||||
SDL_PrivateJoystickButton(joystick, 1, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN ? SDL_PRESSED : SDL_RELEASED );
|
|
||||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_DPAD_LEFT ) )
|
|
||||||
SDL_PrivateJoystickButton(joystick, 2, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT ? SDL_PRESSED : SDL_RELEASED );
|
|
||||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_DPAD_RIGHT ) )
|
|
||||||
SDL_PrivateJoystickButton(joystick, 3, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT ? SDL_PRESSED : SDL_RELEASED );
|
|
||||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_START ) )
|
|
||||||
SDL_PrivateJoystickButton(joystick, 4, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_START ? SDL_PRESSED : SDL_RELEASED );
|
|
||||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_BACK ) )
|
|
||||||
SDL_PrivateJoystickButton(joystick, 5, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_BACK ? SDL_PRESSED : SDL_RELEASED );
|
|
||||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_LEFT_THUMB ) )
|
|
||||||
SDL_PrivateJoystickButton(joystick, 6, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB ? SDL_PRESSED : SDL_RELEASED );
|
|
||||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_RIGHT_THUMB ) )
|
|
||||||
SDL_PrivateJoystickButton(joystick, 7, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB ? SDL_PRESSED : SDL_RELEASED );
|
|
||||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_LEFT_SHOULDER ) )
|
|
||||||
SDL_PrivateJoystickButton(joystick, 8, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER ? SDL_PRESSED : SDL_RELEASED );
|
|
||||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_RIGHT_SHOULDER ) )
|
|
||||||
SDL_PrivateJoystickButton(joystick, 9, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER ? SDL_PRESSED : SDL_RELEASED );
|
|
||||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_A ) )
|
|
||||||
SDL_PrivateJoystickButton(joystick, 10, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_A ? SDL_PRESSED : SDL_RELEASED );
|
|
||||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_B ) )
|
|
||||||
SDL_PrivateJoystickButton(joystick, 11, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_B ? SDL_PRESSED : SDL_RELEASED );
|
|
||||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_X ) )
|
|
||||||
SDL_PrivateJoystickButton(joystick, 12, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_X ? SDL_PRESSED : SDL_RELEASED );
|
|
||||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_Y ) )
|
|
||||||
SDL_PrivateJoystickButton(joystick, 13, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_Y ? SDL_PRESSED : SDL_RELEASED );
|
|
||||||
if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, 0x400 ) )
|
|
||||||
SDL_PrivateJoystickButton(joystick, 14, pXInputState->Gamepad.wButtons & 0x400 ? SDL_PRESSED : SDL_RELEASED ); // 0x400 is the undocumented code for the guide button
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_UnlockMutex(g_DeviceInfoLock);
|
SDL_UnlockMutex(g_DeviceInfoLock);
|
||||||
|
|
Loading…
Reference in New Issue