1111#include " input/input_state.h"
1212#include " input/keycodes.h"
1313#include " XinputDevice.h"
14+ #include " Core/Core.h"
15+ #include " Core/HLE/sceCtrl.h"
1416
1517// Utilities to dynamically load XInput. Adapted from SDL.
1618
1719#if !PPSSPP_PLATFORM(UWP)
1820
1921typedef DWORD (WINAPI *XInputGetState_t) (DWORD dwUserIndex, XINPUT_STATE* pState);
22+ typedef DWORD (WINAPI *XInputSetState_t) (DWORD dwUserIndex, XINPUT_VIBRATION* pVibration);
2023
2124static XInputGetState_t PPSSPP_XInputGetState = NULL ;
25+ static XInputSetState_t PPSSPP_XInputSetState = NULL ;
2226static DWORD PPSSPP_XInputVersion = 0 ;
2327static HMODULE s_pXInputDLL = 0 ;
2428static int s_XInputDLLRefCount = 0 ;
@@ -65,6 +69,17 @@ static int LoadXInputDLL() {
6569 return -1 ;
6670 }
6771
72+ /* Let's try the name first, then fall back to a non-Ex version (xinput9_1_0.dll doesn't have Ex) */
73+ PPSSPP_XInputSetState = (XInputSetState_t)GetProcAddress ((HMODULE)s_pXInputDLL, " XInputSetStateEx" );
74+ if (!PPSSPP_XInputSetState) {
75+ PPSSPP_XInputSetState = (XInputSetState_t)GetProcAddress ((HMODULE)s_pXInputDLL, " XInputSetState" );
76+ }
77+
78+ if (!PPSSPP_XInputSetState) {
79+ UnloadXInputDLL ();
80+ return -1 ;
81+ }
82+
6883 return 0 ;
6984}
7085
@@ -81,6 +96,7 @@ static void UnloadXInputDLL() {
8196static int LoadXInputDLL () { return 0 ; }
8297static void UnloadXInputDLL () {}
8398#define PPSSPP_XInputGetState XInputGetState
99+ #define PPSSPP_XInputSetState XInputSetState
84100#endif
85101
86102#ifndef XUSER_MAX_COUNT
@@ -231,11 +247,13 @@ int XinputDevice::UpdateState() {
231247 for (int i = 0 ; i < XUSER_MAX_COUNT; i++) {
232248 XINPUT_STATE state;
233249 ZeroMemory (&state, sizeof (XINPUT_STATE));
250+ XINPUT_VIBRATION vibration;
251+ ZeroMemory (&vibration, sizeof (XINPUT_VIBRATION));
234252 if (check_delay[i]-- > 0 )
235253 continue ;
236254 DWORD dwResult = PPSSPP_XInputGetState (i, &state);
237255 if (dwResult == ERROR_SUCCESS) {
238- UpdatePad (i, state);
256+ UpdatePad (i, state, vibration );
239257 anySuccess = true ;
240258 } else {
241259 check_delay[i] = 30 ;
@@ -247,13 +265,14 @@ int XinputDevice::UpdateState() {
247265 return anySuccess ? UPDATESTATE_SKIP_PAD : 0 ;
248266}
249267
250- void XinputDevice::UpdatePad (int pad, const XINPUT_STATE &state) {
268+ void XinputDevice::UpdatePad (int pad, const XINPUT_STATE &state, XINPUT_VIBRATION &vibration ) {
251269 static bool notified = false ;
252270 if (!notified) {
253271 notified = true ;
254272 KeyMap::NotifyPadConnected (" Xbox 360 Pad" );
255273 }
256274 ApplyButtons (pad, state);
275+ ApplyVibration (pad, vibration);
257276
258277 const float STICK_DEADZONE = g_Config.fXInputAnalogDeadzone ;
259278 const int STICK_INV_MODE = g_Config.iXInputAnalogInverseMode ;
@@ -338,3 +357,21 @@ void XinputDevice::ApplyButtons(int pad, const XINPUT_STATE &state) {
338357 }
339358 }
340359}
360+
361+
362+ void XinputDevice::ApplyVibration (int pad, XINPUT_VIBRATION &vibration) {
363+ if (PSP_IsInited ()) {
364+ vibration.wLeftMotorSpeed = GetLeftVibration (); // use any value between 0-65535 here
365+ vibration.wRightMotorSpeed = GetRightVibration (); // use any value between 0-65535 here
366+ if (prevVibration[pad].wLeftMotorSpeed != vibration.wLeftMotorSpeed || prevVibration[pad].wRightMotorSpeed != vibration.wRightMotorSpeed ) {
367+ PPSSPP_XInputSetState (pad, &vibration);
368+ prevVibration[pad] = vibration;
369+ }
370+ } else {
371+ DWORD dwResult = PPSSPP_XInputSetState (pad, &vibration);
372+ if (dwResult != ERROR_SUCCESS) {
373+ check_delay[pad] = 30 ;
374+ }
375+ }
376+ }
377+
0 commit comments