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 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
|
||||
// ******************************************************************
|
||||
void XTL::EmuXInputPCPoll( XTL::PXINPUT_STATE Controller )
|
||||
void XTL::EmuXInputPCPoll( DWORD dwPort,XTL::PXINPUT_STATE Controller )
|
||||
{
|
||||
//
|
||||
// Get the PC's XInput values
|
||||
//
|
||||
|
||||
if( XInputGetState( 0, &g_Controller ) != ERROR_SUCCESS )
|
||||
if( XInputGetState( dwPort, &g_Controller ) != ERROR_SUCCESS )
|
||||
return;
|
||||
|
||||
//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
|
||||
// ******************************************************************
|
||||
void XTL::EmuXInputSetState(XTL::PXINPUT_FEEDBACK Feedback)
|
||||
void XTL::EmuXInputSetState(DWORD dwPort, XTL::PXINPUT_FEEDBACK Feedback)
|
||||
{
|
||||
XINPUT_VIBRATION FrameVibration =
|
||||
{
|
||||
|
@ -151,5 +172,5 @@ void XTL::EmuXInputSetState(XTL::PXINPUT_FEEDBACK Feedback)
|
|||
//
|
||||
// Set the PC XInput state
|
||||
|
||||
XInputSetState(0, &FrameVibration);
|
||||
XInputSetState(dwPort, &FrameVibration);
|
||||
}
|
||||
|
|
|
@ -34,14 +34,17 @@
|
|||
#ifndef EMUXINPUT_H
|
||||
#define EMUXINPUT_H
|
||||
|
||||
//query the total connected xinput gamepad
|
||||
DWORD XInputGamepad_Connected(void);
|
||||
|
||||
// ******************************************************************
|
||||
// * patch: XInputPCPoll
|
||||
// ******************************************************************
|
||||
void EmuXInputPCPoll( XTL::PXINPUT_STATE Controller );
|
||||
void EmuXInputPCPoll( DWORD dwPort, XTL::PXINPUT_STATE Controller );
|
||||
|
||||
// ******************************************************************
|
||||
// * Native implementation of XInputSetState
|
||||
// ******************************************************************
|
||||
void EmuXInputSetState(XTL::PXINPUT_FEEDBACK Feedback);
|
||||
void EmuXInputSetState(DWORD dwPort, XTL::PXINPUT_FEEDBACK Feedback);
|
||||
|
||||
#endif
|
|
@ -68,9 +68,9 @@ XTL::PXPP_DEVICE_TYPE gDeviceType_Gamepad = nullptr;
|
|||
#include "EmuXTL.h"
|
||||
|
||||
|
||||
XTL::POLLING_PARAMETERS_HANDLE g_pph;
|
||||
XTL::XINPUT_POLLING_PARAMETERS g_pp;
|
||||
|
||||
XTL::POLLING_PARAMETERS_HANDLE g_pph[4];
|
||||
XTL::XINPUT_POLLING_PARAMETERS g_pp[4];
|
||||
DWORD total_xinput_gamepad = 0;
|
||||
|
||||
void SetupXboxDeviceTypes()
|
||||
{
|
||||
|
@ -165,6 +165,18 @@ VOID WINAPI XTL::EMUPATCH(XInitDevices)
|
|||
{
|
||||
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()
|
||||
|
@ -239,10 +251,14 @@ DWORD WINAPI XTL::EMUPATCH(XGetDevices)
|
|||
DeviceType->ChangeConnected = 0;
|
||||
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) {
|
||||
ret = DeviceType->CurrentConnected = 1;
|
||||
DeviceType->ChangeConnected = 1;
|
||||
for (int i = 0; i < total_xinput_gamepad; i++)
|
||||
{
|
||||
DeviceType->CurrentConnected |= 1<<i;
|
||||
}
|
||||
DeviceType->ChangeConnected = DeviceType->CurrentConnected ;
|
||||
ret = DeviceType->CurrentConnected;
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
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
|
||||
if(dwPort >= 0 && (dwPort <= 0))
|
||||
//rever back to return handle for port 0~3, this is for multi controller support.
|
||||
if(dwPort >= 0 && (dwPort <= total_xinput_gamepad))
|
||||
{
|
||||
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)
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
@ -367,7 +383,7 @@ HANDLE WINAPI XTL::EMUPATCH(XInputOpen)
|
|||
{
|
||||
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));
|
||||
|
@ -404,8 +420,10 @@ VOID WINAPI XTL::EMUPATCH(XInputClose)
|
|||
LOG_FUNC_ONE_ARG(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)
|
||||
{
|
||||
int v;
|
||||
|
@ -420,15 +438,16 @@ VOID WINAPI XTL::EMUPATCH(XInputClose)
|
|||
g_pXInputSetStateStatus[v].dwLatency = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if(pph->pPollingParameters != NULL)
|
||||
{
|
||||
delete pph->pPollingParameters;
|
||||
}
|
||||
|
||||
delete pph;
|
||||
*/
|
||||
}
|
||||
//*/
|
||||
|
||||
}
|
||||
|
||||
// ******************************************************************
|
||||
|
@ -506,8 +525,8 @@ DWORD WINAPI XTL::EMUPATCH(XInputGetCapabilities)
|
|||
if(pph != NULL)
|
||||
{
|
||||
DWORD dwPort = pph->dwPort;
|
||||
|
||||
if(dwPort == 0)
|
||||
//return gamepad capabilities for port 0~3.
|
||||
if(dwPort >= 0 && dwPort<=total_xinput_gamepad)
|
||||
{
|
||||
pCapabilities->SubType = XINPUT_DEVSUBTYPE_GC_GAMEPAD;
|
||||
pCapabilities->In.Gamepad = {};
|
||||
|
@ -556,20 +575,18 @@ DWORD WINAPI XTL::EMUPATCH(XInputGetState)
|
|||
|
||||
DWORD dwPort = pph->dwPort;
|
||||
|
||||
if((dwPort >= 0) && (dwPort <= 3))
|
||||
if((dwPort >= 0) && (dwPort <= total_xinput_gamepad))
|
||||
{
|
||||
DbgPrintf("XAPI: EmuXInputGetState(): dwPort = %d\n", dwPort );
|
||||
|
||||
if(dwPort == 0)
|
||||
{
|
||||
//for xinput, we query the state corresponds to port.
|
||||
if (g_XInputEnabled) {
|
||||
EmuXInputPCPoll(pState);
|
||||
EmuXInputPCPoll(dwPort,pState);
|
||||
} else {
|
||||
EmuDInputPoll(pState);
|
||||
}
|
||||
|
||||
ret = ERROR_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -652,12 +669,9 @@ DWORD WINAPI XTL::EMUPATCH(XInputSetState)
|
|||
}
|
||||
}
|
||||
|
||||
if (pph->dwPort == 0)
|
||||
if (g_XInputEnabled)
|
||||
{
|
||||
if (g_XInputEnabled)
|
||||
{
|
||||
XTL::EmuXInputSetState(pFeedback);
|
||||
}
|
||||
XTL::EmuXInputSetState(pph->dwPort, pFeedback);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue