Add multi controller support for Xinput gamepads
This commit is contained in:
parent
7e21e8bb80
commit
3838ae7318
|
@ -51,17 +51,38 @@
|
||||||
static XINPUT_STATE g_Controller;
|
static XINPUT_STATE g_Controller;
|
||||||
static BOOL g_bXInputInitialized = FALSE;
|
static BOOL g_bXInputInitialized = FALSE;
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
DWORD XTL::XInputGamepad_Connected(void)
|
||||||
|
{
|
||||||
|
DWORD dwResult;
|
||||||
|
DWORD gamepad_connected = 0;
|
||||||
|
for (DWORD i = 0; i< 4; i++)
|
||||||
|
{
|
||||||
|
ZeroMemory(&g_Controller, sizeof(XINPUT_STATE));
|
||||||
|
|
||||||
|
// query each port for gamepad state
|
||||||
|
dwResult = XInputGetState(i, &g_Controller);
|
||||||
|
|
||||||
|
//success means gamepad is connected
|
||||||
|
if (dwResult == ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
gamepad_connected++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return gamepad_connected;
|
||||||
|
}
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
// * patch: XInputPCPoll
|
// * patch: XInputPCPoll
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
void XTL::EmuXInputPCPoll( XTL::PXINPUT_STATE Controller )
|
void XTL::EmuXInputPCPoll( DWORD dwPort,XTL::PXINPUT_STATE Controller )
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// Get the PC's XInput values
|
// Get the PC's XInput values
|
||||||
//
|
//
|
||||||
|
|
||||||
if( XInputGetState( 0, &g_Controller ) != ERROR_SUCCESS )
|
if( XInputGetState( dwPort, &g_Controller ) != ERROR_SUCCESS )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//Packet# must be updated to trigger the xbe processing the input state.
|
//Packet# must be updated to trigger the xbe processing the input state.
|
||||||
|
@ -140,7 +161,7 @@ void XTL::EmuXInputPCPoll( XTL::PXINPUT_STATE Controller )
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
// * Native implementation of XInputSetState
|
// * Native implementation of XInputSetState
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
void XTL::EmuXInputSetState(XTL::PXINPUT_FEEDBACK Feedback)
|
void XTL::EmuXInputSetState(DWORD dwPort, XTL::PXINPUT_FEEDBACK Feedback)
|
||||||
{
|
{
|
||||||
XINPUT_VIBRATION FrameVibration =
|
XINPUT_VIBRATION FrameVibration =
|
||||||
{
|
{
|
||||||
|
@ -151,5 +172,5 @@ void XTL::EmuXInputSetState(XTL::PXINPUT_FEEDBACK Feedback)
|
||||||
//
|
//
|
||||||
// Set the PC XInput state
|
// Set the PC XInput state
|
||||||
|
|
||||||
XInputSetState(0, &FrameVibration);
|
XInputSetState(dwPort, &FrameVibration);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,14 +34,17 @@
|
||||||
#ifndef EMUXINPUT_H
|
#ifndef EMUXINPUT_H
|
||||||
#define EMUXINPUT_H
|
#define EMUXINPUT_H
|
||||||
|
|
||||||
|
//query the total connected xinput gamepad
|
||||||
|
DWORD XInputGamepad_Connected(void);
|
||||||
|
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
// * patch: XInputPCPoll
|
// * patch: XInputPCPoll
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
void EmuXInputPCPoll( XTL::PXINPUT_STATE Controller );
|
void EmuXInputPCPoll( DWORD dwPort, XTL::PXINPUT_STATE Controller );
|
||||||
|
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
// * Native implementation of XInputSetState
|
// * Native implementation of XInputSetState
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
void EmuXInputSetState(XTL::PXINPUT_FEEDBACK Feedback);
|
void EmuXInputSetState(DWORD dwPort, XTL::PXINPUT_FEEDBACK Feedback);
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -68,9 +68,9 @@ XTL::PXPP_DEVICE_TYPE gDeviceType_Gamepad = nullptr;
|
||||||
#include "EmuXTL.h"
|
#include "EmuXTL.h"
|
||||||
|
|
||||||
|
|
||||||
XTL::POLLING_PARAMETERS_HANDLE g_pph;
|
XTL::POLLING_PARAMETERS_HANDLE g_pph[4];
|
||||||
XTL::XINPUT_POLLING_PARAMETERS g_pp;
|
XTL::XINPUT_POLLING_PARAMETERS g_pp[4];
|
||||||
|
DWORD total_xinput_gamepad = 0;
|
||||||
|
|
||||||
void SetupXboxDeviceTypes()
|
void SetupXboxDeviceTypes()
|
||||||
{
|
{
|
||||||
|
@ -165,6 +165,18 @@ VOID WINAPI XTL::EMUPATCH(XInitDevices)
|
||||||
{
|
{
|
||||||
g_hInputHandle[v] = 0;
|
g_hInputHandle[v] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (g_XInputEnabled)
|
||||||
|
{
|
||||||
|
//query the total connected xinput gamepad.
|
||||||
|
total_xinput_gamepad = XInputGamepad_Connected();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//using keyboard, we set the gamd pad count to 1
|
||||||
|
total_xinput_gamepad = 1;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TitleIsJSRF()
|
bool TitleIsJSRF()
|
||||||
|
@ -239,10 +251,14 @@ DWORD WINAPI XTL::EMUPATCH(XGetDevices)
|
||||||
DeviceType->ChangeConnected = 0;
|
DeviceType->ChangeConnected = 0;
|
||||||
DeviceType->PreviousConnected = DeviceType->CurrentConnected;
|
DeviceType->PreviousConnected = DeviceType->CurrentConnected;
|
||||||
|
|
||||||
// If this is a gamepad, and no gamepad was previously detected, connect one
|
// If this is for getting gamepad devices, and no gamepad was previously detected, connect one
|
||||||
if (DeviceType == gDeviceType_Gamepad && DeviceType->CurrentConnected == 0) {
|
if (DeviceType == gDeviceType_Gamepad && DeviceType->CurrentConnected == 0) {
|
||||||
ret = DeviceType->CurrentConnected = 1;
|
for (int i = 0; i < total_xinput_gamepad; i++)
|
||||||
DeviceType->ChangeConnected = 1;
|
{
|
||||||
|
DeviceType->CurrentConnected |= 1<<i;
|
||||||
|
}
|
||||||
|
DeviceType->ChangeConnected = DeviceType->CurrentConnected ;
|
||||||
|
ret = DeviceType->CurrentConnected;
|
||||||
}
|
}
|
||||||
|
|
||||||
// JSRF Hack: Don't set the ChangeConnected flag. Without this, JSRF hard crashes
|
// JSRF Hack: Don't set the ChangeConnected flag. Without this, JSRF hard crashes
|
||||||
|
@ -339,16 +355,16 @@ HANDLE WINAPI XTL::EMUPATCH(XInputOpen)
|
||||||
LOG_FUNC_END;
|
LOG_FUNC_END;
|
||||||
|
|
||||||
POLLING_PARAMETERS_HANDLE *pph = 0;
|
POLLING_PARAMETERS_HANDLE *pph = 0;
|
||||||
//return pph handle only for port 0, this prevents some title from polling input state with port other than 0 thus fix the no input issue such as RalliSport
|
//rever back to return handle for port 0~3, this is for multi controller support.
|
||||||
if(dwPort >= 0 && (dwPort <= 0))
|
if(dwPort >= 0 && (dwPort <= total_xinput_gamepad))
|
||||||
{
|
{
|
||||||
if(g_hInputHandle[dwPort] == 0)
|
if(g_hInputHandle[dwPort] == 0)
|
||||||
{
|
{
|
||||||
pph = (POLLING_PARAMETERS_HANDLE*) &g_pph; // new POLLING_PARAMETERS_HANDLE();
|
pph = (POLLING_PARAMETERS_HANDLE*) &g_pph[dwPort]; // new POLLING_PARAMETERS_HANDLE();
|
||||||
|
|
||||||
if(pPollingParameters != NULL)
|
if(pPollingParameters != NULL)
|
||||||
{
|
{
|
||||||
pph->pPollingParameters = (XINPUT_POLLING_PARAMETERS*) &g_pp; // new XINPUT_POLLING_PARAMETERS();
|
pph->pPollingParameters = (XINPUT_POLLING_PARAMETERS*) &g_pp[dwPort]; // new XINPUT_POLLING_PARAMETERS();
|
||||||
|
|
||||||
memcpy(pph->pPollingParameters, pPollingParameters, sizeof(XINPUT_POLLING_PARAMETERS));
|
memcpy(pph->pPollingParameters, pPollingParameters, sizeof(XINPUT_POLLING_PARAMETERS));
|
||||||
}
|
}
|
||||||
|
@ -367,7 +383,7 @@ HANDLE WINAPI XTL::EMUPATCH(XInputOpen)
|
||||||
{
|
{
|
||||||
if(pph->pPollingParameters == 0)
|
if(pph->pPollingParameters == 0)
|
||||||
{
|
{
|
||||||
pph->pPollingParameters = (XINPUT_POLLING_PARAMETERS*) &g_pp; // new XINPUT_POLLING_PARAMETERS();
|
pph->pPollingParameters = (XINPUT_POLLING_PARAMETERS*) &g_pp[dwPort]; // new XINPUT_POLLING_PARAMETERS();
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(pph->pPollingParameters, pPollingParameters, sizeof(XINPUT_POLLING_PARAMETERS));
|
memcpy(pph->pPollingParameters, pPollingParameters, sizeof(XINPUT_POLLING_PARAMETERS));
|
||||||
|
@ -404,8 +420,10 @@ VOID WINAPI XTL::EMUPATCH(XInputClose)
|
||||||
LOG_FUNC_ONE_ARG(hDevice);
|
LOG_FUNC_ONE_ARG(hDevice);
|
||||||
|
|
||||||
POLLING_PARAMETERS_HANDLE *pph = (POLLING_PARAMETERS_HANDLE*)hDevice;
|
POLLING_PARAMETERS_HANDLE *pph = (POLLING_PARAMETERS_HANDLE*)hDevice;
|
||||||
|
DWORD dwPort = pph->dwPort;
|
||||||
|
//NULL out the input handle corresponds to port.
|
||||||
|
g_hInputHandle[dwPort] = 0;
|
||||||
|
|
||||||
/* no longer necessary
|
|
||||||
if(pph != NULL)
|
if(pph != NULL)
|
||||||
{
|
{
|
||||||
int v;
|
int v;
|
||||||
|
@ -420,15 +438,16 @@ VOID WINAPI XTL::EMUPATCH(XInputClose)
|
||||||
g_pXInputSetStateStatus[v].dwLatency = 0;
|
g_pXInputSetStateStatus[v].dwLatency = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
if(pph->pPollingParameters != NULL)
|
if(pph->pPollingParameters != NULL)
|
||||||
{
|
{
|
||||||
delete pph->pPollingParameters;
|
delete pph->pPollingParameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete pph;
|
delete pph;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
//*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
|
@ -506,8 +525,8 @@ DWORD WINAPI XTL::EMUPATCH(XInputGetCapabilities)
|
||||||
if(pph != NULL)
|
if(pph != NULL)
|
||||||
{
|
{
|
||||||
DWORD dwPort = pph->dwPort;
|
DWORD dwPort = pph->dwPort;
|
||||||
|
//return gamepad capabilities for port 0~3.
|
||||||
if(dwPort == 0)
|
if(dwPort >= 0 && dwPort<=total_xinput_gamepad)
|
||||||
{
|
{
|
||||||
pCapabilities->SubType = XINPUT_DEVSUBTYPE_GC_GAMEPAD;
|
pCapabilities->SubType = XINPUT_DEVSUBTYPE_GC_GAMEPAD;
|
||||||
pCapabilities->In.Gamepad = {};
|
pCapabilities->In.Gamepad = {};
|
||||||
|
@ -556,20 +575,18 @@ DWORD WINAPI XTL::EMUPATCH(XInputGetState)
|
||||||
|
|
||||||
DWORD dwPort = pph->dwPort;
|
DWORD dwPort = pph->dwPort;
|
||||||
|
|
||||||
if((dwPort >= 0) && (dwPort <= 3))
|
if((dwPort >= 0) && (dwPort <= total_xinput_gamepad))
|
||||||
{
|
{
|
||||||
DbgPrintf("XAPI: EmuXInputGetState(): dwPort = %d\n", dwPort );
|
DbgPrintf("XAPI: EmuXInputGetState(): dwPort = %d\n", dwPort );
|
||||||
|
|
||||||
if(dwPort == 0)
|
//for xinput, we query the state corresponds to port.
|
||||||
{
|
|
||||||
if (g_XInputEnabled) {
|
if (g_XInputEnabled) {
|
||||||
EmuXInputPCPoll(pState);
|
EmuXInputPCPoll(dwPort,pState);
|
||||||
} else {
|
} else {
|
||||||
EmuDInputPoll(pState);
|
EmuDInputPoll(pState);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = ERROR_SUCCESS;
|
ret = ERROR_SUCCESS;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -607,7 +624,7 @@ DWORD WINAPI XTL::EMUPATCH(XInputSetState)
|
||||||
//
|
//
|
||||||
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
for(v=0;v<XINPUT_SETSTATE_SLOTS;v++)
|
for(v=0;v<XINPUT_SETSTATE_SLOTS;v++)
|
||||||
{
|
{
|
||||||
if(g_pXInputSetStateStatus[v].hDevice == hDevice)
|
if(g_pXInputSetStateStatus[v].hDevice == hDevice)
|
||||||
|
@ -652,12 +669,9 @@ DWORD WINAPI XTL::EMUPATCH(XInputSetState)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pph->dwPort == 0)
|
if (g_XInputEnabled)
|
||||||
{
|
{
|
||||||
if (g_XInputEnabled)
|
XTL::EmuXInputSetState(pph->dwPort, pFeedback);
|
||||||
{
|
|
||||||
XTL::EmuXInputSetState(pFeedback);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue