154 lines
4.5 KiB
C
154 lines
4.5 KiB
C
#include <windows.h>
|
|
#include <xinput.h>
|
|
#include <stdint.h>
|
|
|
|
#ifdef __GNUC__
|
|
#include <ntdef.h>
|
|
#else
|
|
#include <winnt.h>
|
|
#endif
|
|
|
|
#include "hook/table.h"
|
|
|
|
#include "ferrumhook/xinput.h"
|
|
#include "ferrumhook/ferrum-dll.h"
|
|
|
|
#include "util/dprintf.h"
|
|
#include "util/str.h"
|
|
|
|
static DWORD WINAPI my_XInputGetCapabilities(DWORD dwUserIndex, DWORD dwFlags, XINPUT_CAPABILITIES *pCapabilities);
|
|
static DWORD WINAPI my_XInputGetState(DWORD dwUserIndex, XINPUT_STATE *pState);
|
|
static DWORD WINAPI my_XInputSetState(DWORD dwUserIndex, XINPUT_VIBRATION *pVibration);
|
|
static DWORD my_driverUtilGetControllerUsbIdPairs(uint64_t qwUnknown, unsigned int *numControllers);
|
|
|
|
static DWORD (WINAPI *next_XInputGetCapabilities)(DWORD dwUserIndex, DWORD dwFlags, XINPUT_CAPABILITIES *pCapabilities);
|
|
static DWORD (WINAPI *next_XInputGetState)(DWORD dwUserIndex, DWORD dwFlags, XINPUT_CAPABILITIES *pCapabilities);
|
|
static DWORD (WINAPI *next_XInputSetState)(DWORD dwUserIndex, DWORD dwFlags, XINPUT_CAPABILITIES *pCapabilities);
|
|
static DWORD (*next_driverUtilGetControllerUsbIdPairs)(uint64_t qwUnknown, unsigned int *numControllers);
|
|
|
|
uint8_t lastBtnState = 0;
|
|
DWORD packetNum = 0;
|
|
|
|
static const struct hook_symbol xinput_hook_syms[] = {
|
|
{
|
|
.ordinal = 4,
|
|
.patch = my_XInputGetCapabilities,
|
|
.link = (void **) &next_XInputGetCapabilities,
|
|
}, {
|
|
.ordinal = 2,
|
|
.patch = my_XInputGetState,
|
|
.link = (void **) &next_XInputGetState,
|
|
}, {
|
|
.ordinal = 3,
|
|
.patch = my_XInputSetState,
|
|
.link = (void **) &next_XInputSetState,
|
|
},
|
|
};
|
|
|
|
static const struct hook_symbol driverutil_hook_syms[] = {
|
|
{
|
|
.name = "driverUtilGetControllerUsbIdPairs",
|
|
.ordinal = 1,
|
|
.patch = my_driverUtilGetControllerUsbIdPairs,
|
|
.link = (void **) &next_driverUtilGetControllerUsbIdPairs,
|
|
}
|
|
};
|
|
|
|
HRESULT ferrum_xinput_init(struct ferrum_xinput_config *cfg)
|
|
{
|
|
if (!cfg->enable) {
|
|
dprintf("Xinput: Emulation disabled\n");
|
|
return S_OK;
|
|
}
|
|
|
|
dprintf("Xinput: init\n");
|
|
|
|
hook_table_apply(
|
|
NULL,
|
|
"XINPUT1_3.dll",
|
|
xinput_hook_syms,
|
|
_countof(xinput_hook_syms));
|
|
|
|
hook_table_apply(
|
|
NULL,
|
|
"driverUtil.dll",
|
|
driverutil_hook_syms,
|
|
_countof(driverutil_hook_syms));
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static DWORD WINAPI my_XInputGetCapabilities(DWORD dwUserIndex, DWORD dwFlags, XINPUT_CAPABILITIES *pCapabilities)
|
|
{
|
|
//dprintf("Xinput: %s dwUserIndex %li dwFlags %li \n", __func__, dwUserIndex, dwFlags);
|
|
|
|
if (!dwUserIndex) {
|
|
HRESULT hr = ferrum_dll.gamepad_init();
|
|
|
|
if (FAILED(hr)) {
|
|
return ERROR_DEVICE_NOT_CONNECTED;
|
|
}
|
|
|
|
pCapabilities->Flags = XINPUT_CAPS_VOICE_SUPPORTED;
|
|
pCapabilities->Type = XINPUT_DEVTYPE_GAMEPAD;
|
|
pCapabilities->SubType = XINPUT_DEVSUBTYPE_GAMEPAD;
|
|
|
|
pCapabilities->Gamepad.wButtons = 0xF3FF;
|
|
|
|
pCapabilities->Gamepad.bLeftTrigger = 0xFF;
|
|
pCapabilities->Gamepad.bRightTrigger = 0xFF;
|
|
|
|
pCapabilities->Gamepad.sThumbLX = (SHORT)0xFFC0;
|
|
pCapabilities->Gamepad.sThumbLY = (SHORT)0xFFC0;
|
|
pCapabilities->Gamepad.sThumbRX = (SHORT)0xFFC0;
|
|
pCapabilities->Gamepad.sThumbRY = (SHORT)0xFFC0;
|
|
|
|
pCapabilities->Vibration.wLeftMotorSpeed = 0xFF;
|
|
pCapabilities->Vibration.wRightMotorSpeed = 0xFF;
|
|
|
|
return ERROR_SUCCESS;
|
|
} else {
|
|
return ERROR_DEVICE_NOT_CONNECTED;
|
|
}
|
|
|
|
}
|
|
|
|
static DWORD WINAPI my_XInputGetState(DWORD dwUserIndex, XINPUT_STATE *pState)
|
|
{
|
|
//dprintf("Xinput: %s dwUserIndex %li\n", __func__, dwUserIndex);
|
|
assert(ferrum_dll.gamepad_poll != NULL);
|
|
|
|
if (!dwUserIndex) {
|
|
uint16_t gamebtn = 0;
|
|
ferrum_dll.gamepad_poll(&gamebtn);
|
|
|
|
pState->Gamepad.wButtons = gamebtn;
|
|
|
|
if (gamebtn == lastBtnState) {
|
|
pState->dwPacketNumber = packetNum;
|
|
} else {
|
|
pState->dwPacketNumber = packetNum++;
|
|
}
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
else {
|
|
return ERROR_DEVICE_NOT_CONNECTED;
|
|
}
|
|
|
|
}
|
|
|
|
static DWORD WINAPI my_XInputSetState(DWORD dwUserIndex, XINPUT_VIBRATION *pVibration)
|
|
{
|
|
//dprintf("Xinput: %s dwUserIndex %li left %i right %i\n", __func__, dwUserIndex, pVibration->wLeftMotorSpeed, pVibration->wRightMotorSpeed);
|
|
if (!dwUserIndex)
|
|
return ERROR_SUCCESS;
|
|
else
|
|
return ERROR_DEVICE_NOT_CONNECTED;
|
|
}
|
|
|
|
static DWORD my_driverUtilGetControllerUsbIdPairs(uint64_t qwUnknown, unsigned int *numControllers)
|
|
{
|
|
dprintf("Xinput: %s hit!\n", __func__);
|
|
return 1;
|
|
} |