diff --git a/OpenParrot/src/Functions/Games/Other/Daytona3.cpp b/OpenParrot/src/Functions/Games/Other/Daytona3.cpp index 748611f..a76dd66 100644 --- a/OpenParrot/src/Functions/Games/Other/Daytona3.cpp +++ b/OpenParrot/src/Functions/Games/Other/Daytona3.cpp @@ -1,244 +1,273 @@ -#include -#include "Utility/InitFunction.h" -#include "Functions/Global.h" -#include "Utility\Hooking.Patterns.h" - -#pragma comment(lib, "Ws2_32.lib") - -#ifndef _M_AMD64 -extern int* wheelSection; -extern int* ffbOffset; -extern int* ffbOffset2; -extern int* ffbOffset3; -extern int* ffbOffset4; -uintptr_t imageBase; -bool shiftup = false; -bool shiftdown = false; - -void ShiftUp(BYTE shift) -{ - *(BYTE *)(imageBase + 0x15B468C) = shift + 1; -} - -void ShiftDown(BYTE shift) -{ - *(BYTE *)(imageBase + 0x15B468C) = shift - 1; -} - -static void InjectKeys() -{ - DWORD buttons2 = *wheelSection; - DWORD buttons = *ffbOffset; - BYTE wheel = *ffbOffset2; - BYTE gas = *ffbOffset3; - BYTE brake = *ffbOffset4; - BYTE gamestate = *(BYTE *)(imageBase + 0x15B5744); - BYTE gear = *(BYTE *)(imageBase + 0x15B468C); - - *(BYTE *)(imageBase + 0x15B4679) = gas; - *(BYTE *)(imageBase + 0x15B467A) = brake; - DWORD track = *(DWORD *)(imageBase + 0x1228C78); - if (track != 0) - { - BYTE track1 = *(BYTE *)(track + 0x4); -#ifdef _DEBUG - info(true, "%02X %02X", track1, gamestate); -#endif - if ((track1 == 2 || track1 == 4) && (gamestate == 0x16)) - { - BYTE reverse = wheel * 0xFF; - if (reverse == 0x00) - *(BYTE *)(imageBase + 0x15B4678) = 0xFF; - else - *(BYTE *)(imageBase + 0x15B4678) = reverse; -#ifdef _DEBUG - info(true, "Reverse wheel"); -#endif - } - else - { - *(BYTE *)(imageBase + 0x15B4678) = wheel; -#ifdef _DEBUG - info(true, "Normal wheel1"); -#endif - } - } - else - { - *(BYTE *)(imageBase + 0x15B4678) = wheel; -#ifdef _DEBUG - info(true, "Normal wheel2"); -#endif - } - - - - if(wheel <= 0x40) - { - //Menu Left - DWORD p = *(DWORD *)(imageBase + 0x1AAFFF0); - DWORD p1 = *(DWORD *)(p + 0x00); - if (p != 0) - { - *(BYTE *)(p1 + 0x25) = 0xFF; - } - - } - else if(wheel >= 0xC0) - { - //Menu Right - DWORD p = *(DWORD *)(imageBase + 0x1AAFFF0); - DWORD p1 = *(DWORD *)(p + 0x00); - if (p1 != 0) - { - *(BYTE *)(p1 + 0x27) = 0xFF; - } - } - else - { - DWORD p = *(DWORD *)(imageBase + 0x1AAFFF0); - DWORD p1 = *(DWORD *)(p + 0x00); - if (p1 != 0) - { - *(BYTE *)(p1 + 0x25) = 0x00; - *(BYTE *)(p1 + 0x27) = 0x00; - } - } - - if (buttons == 0x01) - { - //Inject Start - DWORD p = *(DWORD *)(imageBase + 0x1AB0010); - DWORD p1 = *(DWORD *)(p + 0x00); - if (p1 != 0) - { - *(DWORD *)(p1 + 0x08) = 0x01; - } - } - else - { - DWORD p = *(DWORD *)(imageBase + 0x1AB0010); - DWORD p1 = *(DWORD *)(p + 0x00); - if (p1 != 0) - { - *(DWORD *)(p1 + 0x08) = 0x00; - } - } - - if ((buttons == 0x02) && (gear < 0x03)) - { - if (!shiftup) - { - shiftup = true; - ShiftUp(*(BYTE *)(imageBase + 0x15B468C)); - } - } - else - { - shiftup = false; - } - - if ((buttons == 0x04) && (gear > 0x00)) //crashes right now - { - if (!shiftdown) - { - shiftdown = true; - ShiftDown(*(BYTE *)(imageBase + 0x15B468C)); - } - } - else - { - shiftdown = false; - } - - if (buttons2 == 0x01) - { - //Gear Change 1 - *(BYTE *)(imageBase + 0x15B468C) = 0x00; - } - - if (buttons2 == 0x02) - { - //Gear Change 2 - *(BYTE *)(imageBase + 0x15B468C) = 0x01; - } - - if (buttons2 == 0x04) - { - //Gear Change 3 - *(BYTE *)(imageBase + 0x15B468C) = 0x02; - } - - if (buttons2 == 0x08) - { - //Gear Change 4 - *(BYTE *)(imageBase + 0x15B468C) = 0x03; - } - - if (buttons2 == 0x10) - { - //View Change 1 - { - *(DWORD *)(imageBase + 0x15B5DB0) = 0x00; - } - } - - if (buttons2 == 0x20) - { - //View Change 2 - { - *(DWORD *)(imageBase + 0x15B5DB0) = 0x01; - } - } - - if (buttons2 == 0x40) - { - //View Change 3 - { - *(DWORD *)(imageBase + 0x15B5DB0) = 0x02; - } - } - - if (buttons2 == 0x80) - { - //View Change 4 - { - *(DWORD *)(imageBase + 0x15B5DB0) = 0x03; - } - } - - if (buttons2 == 0xF0) - { - //View Change 5 - { - *(DWORD *)(imageBase + 0x15B5DB0) = 0x04; - } - } -} - -int(__stdcall *g_origControlsFunction)(); - -int __stdcall ControlsFunction() -{ - int result = g_origControlsFunction(); - InjectKeys(); - return result; -} - -static InitFunction Daytona3Func([]() -{ - - imageBase = (uintptr_t)GetModuleHandleA(0); - injector::WriteMemoryRaw(imageBase + 0xDD697, "\x90\x90\x90\x90\x90\x90\x38\x05\xC8\xF9\x5A\x01\x90\x90\x90\x90\x90\x90", 18, true); - injector::MakeNOP(imageBase + 0x1DDDFA, 5); - injector::MakeNOP(imageBase + 0x1DDE1E, 6); - injector::MakeNOP(imageBase + 0x1DDE45, 6); - injector::MakeNOP(imageBase + 0x1DE10D, 6); - injector::MakeNOP(imageBase + 0x29B481, 3); - injector::MakeNOP(imageBase + 0x29B513, 4); - MH_Initialize(); - MH_CreateHook((void*)(imageBase + 0x1E9280), ControlsFunction, (void**)&g_origControlsFunction); - MH_EnableHook(MH_ALL_HOOKS); - -}, GameID::Daytona3); +#include +#include "Utility/InitFunction.h" +#include "Functions/Global.h" +#include "Utility\Hooking.Patterns.h" + +#pragma comment(lib, "Ws2_32.lib") + +#ifndef _M_AMD64 +extern int* wheelSection; +extern int* ffbOffset; +extern int* ffbOffset2; +extern int* ffbOffset3; +extern int* ffbOffset4; +bool daytonaPressStart = false; +uintptr_t imageBase; +bool shiftup = false; +bool shiftdown = false; + +void ShiftUp(BYTE shift) +{ + *(BYTE *)(imageBase + 0x15B468C) = shift + 1; +} + +void ShiftDown(BYTE shift) +{ + *(BYTE *)(imageBase + 0x15B468C) = shift - 1; +} + +static void InjectKeys() +{ + + DWORD buttons2 = *wheelSection; + DWORD buttons = *ffbOffset; + BYTE wheel = *ffbOffset2; + BYTE gas = *ffbOffset3; + BYTE brake = *ffbOffset4; + + BYTE gamestate = *(BYTE *)(imageBase + 0x15B5744); + BYTE gear = *(BYTE *)(imageBase + 0x15B468C); + + *(BYTE *)(imageBase + 0x15B4679) = gas; + *(BYTE *)(imageBase + 0x15B467A) = brake; + + DWORD track = *(DWORD *)(imageBase + 0x011B0148); + if (track != 0) + { + BYTE track1 = *(BYTE *)(track + 0x4); +#ifdef _DEBUG + info(true, "%02X %02X", track1, gamestate); +#endif + if ((track1 == 2 || track1 == 4) && (gamestate == 0x16)) + { + BYTE reverse = wheel * 0xFF; + if (reverse == 0x00) + *(BYTE *)(imageBase + 0x15B4678) = 0xFF; + else + *(BYTE *)(imageBase + 0x15B4678) = reverse; +#ifdef _DEBUG + info(true, "Reverse wheel"); +#endif + } + else + { + *(BYTE *)(imageBase + 0x15B4678) = wheel; +#ifdef _DEBUG + info(true, "Normal wheel1"); +#endif + } + } + else + { + *(BYTE *)(imageBase + 0x15B4678) = wheel; +#ifdef _DEBUG + info(true, "Normal wheel2"); +#endif + } + + if (gas >= 0x40) + { + daytonaPressStart = true; + } + else + { + daytonaPressStart = false; + } + + if (wheel <= 0x40) + { + //Menu Left + DWORD p = *(DWORD *)(imageBase + 0x1AAFFF0); + if (p != 0) + { + DWORD p1 = *(DWORD *)(p + 0x00); + if (p1 != 0) + { + *(BYTE *)(p1 + 0x25) = 0xFF; + } + } + } + else if (wheel >= 0xC0) + { + //Menu Right + DWORD p = *(DWORD *)(imageBase + 0x1AAFFF0); + if (p != 0) + { + DWORD p1 = *(DWORD *)(p + 0x00); + if (p1 != 0) + { + *(BYTE *)(p1 + 0x27) = 0xFF; + } + } + } + else + { + DWORD p = *(DWORD *)(imageBase + 0x1AAFFF0); + if (p != 0) + { + DWORD p1 = *(DWORD *)(p + 0x00); + if (p1 != 0) + { + *(BYTE *)(p1 + 0x25) = 0x00; + *(BYTE *)(p1 + 0x27) = 0x00; + } + } + } + + if (buttons == 0x01) + { + //Inject Start + DWORD p = *(DWORD *)(imageBase + 0x1AB0010); + if (p != 0) + { + DWORD p1 = *(DWORD *)(p + 0x00); + if (p1 != 0) + { + *(DWORD *)(p1 + 0x08) = 0x01; + } + } + } + else + { + DWORD p = *(DWORD *)(imageBase + 0x1AB0010); + if (p != 0) + { + DWORD p1 = *(DWORD *)(p + 0x00); + if (p1 != 0) + { + *(DWORD *)(p1 + 0x08) = 0x00; + } + } + } + + if ((buttons == 0x02) && (gear < 0x03)) + { + if (!shiftup) + { + shiftup = true; + ShiftUp(*(BYTE *)(imageBase + 0x15B468C)); + } + } + else + { + shiftup = false; + } + + if ((buttons == 0x04) && (gear > 0x00)) + { + if (!shiftdown) + { + shiftdown = true; + ShiftDown(*(BYTE *)(imageBase + 0x15B468C)); + } + } + else + { + shiftdown = false; + } + + if (buttons2 == 0x01) + { + //Gear Change 1 + *(BYTE *)(imageBase + 0x15B468C) = 0x00; + } + + if (buttons2 == 0x02) + { + //Gear Change 2 + *(BYTE *)(imageBase + 0x15B468C) = 0x01; + } + + if (buttons2 == 0x04) + { + //Gear Change 3 + *(BYTE *)(imageBase + 0x15B468C) = 0x02; + } + + if (buttons2 == 0x08) + { + //Gear Change 4 + *(BYTE *)(imageBase + 0x15B468C) = 0x03; + } + + if (buttons2 == 0x10) + { + //View Change 1 + { + *(DWORD *)(imageBase + 0x15B5DB0) = 0x00; + } + } + + if (buttons2 == 0x20) + { + //View Change 2 + { + *(DWORD *)(imageBase + 0x15B5DB0) = 0x01; + } + } + + if (buttons2 == 0x40) + { + //View Change 3 + { + *(DWORD *)(imageBase + 0x15B5DB0) = 0x02; + } + } + + if (buttons2 == 0x80) + { + //View Change 4 + { + *(DWORD *)(imageBase + 0x15B5DB0) = 0x03; + } + } + + if (buttons2 == 0xF0) + { + //View Change 5 + { + *(DWORD *)(imageBase + 0x15B5DB0) = 0x04; + } + } +} + +int(__stdcall *g_origControlsFunction)(); + +int __stdcall ControlsFunction() +{ + int result = g_origControlsFunction(); + InjectKeys(); + return result; +} + +static InitFunction Daytona3Func([]() +{ + imageBase = (uintptr_t)GetModuleHandleA(0); + injector::WriteMemoryRaw(imageBase + 0xDD697, "\x90\x90\x90\x90\x90\x90\x38\x05\xC8\xF9\x5A\x01\x90\x90\x90\x90\x90\x90", 18, true); + injector::WriteMemoryRaw(imageBase + 0x12958F, "\x33\xC0\x8A\x45\x08\x90\x90\x90\x90\x72\x08\x66\xA3\x46\xFC\x5A\x01\xEB\x06\x66\xA3\x44\xFC\x5A\x01\x31\xFF\x31\xF6\x47\xBE\x0F\x00\x00\x00\xEB\x4C\x90\x90\x90\x90", 41, true); + injector::MakeNOP(imageBase + 0x1DDDFA, 5); + injector::MakeNOP(imageBase + 0x1DDE1E, 6); + injector::MakeNOP(imageBase + 0x1DDE45, 6); + injector::MakeNOP(imageBase + 0x1DE10D, 6); + injector::MakeNOP(imageBase + 0x29B481, 3); + injector::MakeNOP(imageBase + 0x29B513, 4); + if (ToBool(config["General"]["MSAA4X Disable"])) + { + injector::WriteMemoryRaw(imageBase + 0x17CD3D, "\x00", 1, true); + } + MH_Initialize(); + MH_CreateHook((void*)(imageBase + 0x1E9280), ControlsFunction, (void**)&g_origControlsFunction); + MH_EnableHook(MH_ALL_HOOKS); + +}, GameID::Daytona3); #endif \ No newline at end of file diff --git a/OpenParrot/src/Functions/PokkenXInputEmu.cpp b/OpenParrot/src/Functions/PokkenXInputEmu.cpp index b6e6513..4268566 100644 --- a/OpenParrot/src/Functions/PokkenXInputEmu.cpp +++ b/OpenParrot/src/Functions/PokkenXInputEmu.cpp @@ -1,359 +1,357 @@ -#pragma optimize("", off) -#include "StdInc.h" -#include "Utility/GameDetect.h" -#include "Utility/InitFunction.h" -#include "PokkenXInputEmu.h" - -struct XboxOneControllerHandler -{ - struct usb_dev_handle *handle; - bool isConnected; - XBOXONE_STATE controllerState; - - uint8_t lastState[64]; - unsigned int tickCount; - - XINPUT_GAMEPAD lastGamepadState; -}; - -XboxOneControllerHandler *controllerHandler[4] = { NULL, NULL, NULL, NULL }; -HANDLE XboxOneControllerThread[4] = { 0 }; -HANDLE XboxOneControllerMutex[4] = { 0 }; - -static unsigned short idVendor = 0x045E; -static unsigned short idProduct = 0x02D1; - -static bool daytonaPressStart = false; - -int configuration = 1; -int interface = 0; -int endpointIn = 0x81; -int endpointOut = 0x01; -int timeout = 2000; // milliseconds -bool controllerInit = false; -bool runThread = true; - -// Structure we receive from the controller -struct XboxOneControllerState -{ - char eventCount; - char unknown; - char buttons1; - char buttons2; - short leftTrigger; // Triggers are 0 - 1023 - short rightTrigger; - short thumbLX; // Axes are -32767 - 32767 - short thumbLY; - short thumbRX; - short thumbRY; -}; - -bool connectController(bool enable) -{ - controllerInit = enable; - return true; -} - -int iround(double num) { - return (num > 0.0) ? (int)floor(num + 0.5) : (int)ceil(num - 0.5); -} - -extern int* ffbOffset; - -DWORD WINAPI XInputGetState -( - __in DWORD dwUserIndex, // Index of the gamer associated with the device - __out XINPUT_STATE* pState // Receives the current state -) -{ - if (!controllerInit) - { - connectController(true); - } - if (controllerInit && dwUserIndex == 0) - { - XINPUT_GAMEPAD gamepadState = { 0 }; - - if (GameDetect::currentGame == GameID::Daytona3) - gamepadState.wButtons |= *ffbOffset; - else - gamepadState.wButtons |= 0; - - if (GameDetect::currentGame == GameID::Daytona3) - { - gamepadState.bRightTrigger = daytonaPressStart ? 0xFF : 0x00; - } - - if (pState->dwPacketNumber == UINT_MAX) - pState->dwPacketNumber = 0; - else - pState->dwPacketNumber++; - - pState->Gamepad = gamepadState; - return ERROR_SUCCESS; - } - else - { - return ERROR_DEVICE_NOT_CONNECTED; - } -} - -DWORD WINAPI XInputSetState -( - __in DWORD dwUserIndex, // Index of the gamer associated with the device - __in XINPUT_VIBRATION* pVibration // The vibration information to send to the controller -) -{ - if (!controllerInit) - { - connectController(true); - } - - if (controllerInit && dwUserIndex == 0) - { - // We're receiving as XInput [0 ~ 65535], need to be [0 ~ 255] !! - int leftVal = iround(((float)pVibration->wLeftMotorSpeed / 65535) * 255); - int rightVal = iround(((float)pVibration->wRightMotorSpeed / 65535) * 255); - return ERROR_SUCCESS; - } - else - { - return ERROR_DEVICE_NOT_CONNECTED; - } -} - -DWORD WINAPI XInputGetCapabilities -( - __in DWORD dwUserIndex, // Index of the gamer associated with the device - __in DWORD dwFlags, // Input flags that identify the device type - __out XINPUT_CAPABILITIES* pCapabilities // Receives the capabilities -) -{ - if (!controllerInit) - { - connectController(true); - } - - if (dwFlags > XINPUT_FLAG_GAMEPAD) - { - return ERROR_BAD_ARGUMENTS; - } - - if (controllerInit && dwUserIndex == 0) - { - 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; - } -} - -void WINAPI XInputEnable -( - __in bool enable // [in] Indicates whether xinput is enabled or disabled. -) -{ - if (!controllerInit) - { - connectController(true); - } - - if (controllerInit && !enable) - { - XINPUT_VIBRATION Vibration = { 0, 0 }; - int xboxControllerCounter = 0; - - while (xboxControllerCounter < 4) - { - if (controllerHandler[xboxControllerCounter]) - { - XInputSetState(xboxControllerCounter, &Vibration); - } - xboxControllerCounter++; - } - } -} - -DWORD WINAPI XInputGetDSoundAudioDeviceGuids -( - __in DWORD dwUserIndex, // Index of the gamer associated with the device - __out GUID* pDSoundRenderGuid, // DSound device ID for render - __out GUID* pDSoundCaptureGuid // DSound device ID for capture -) -{ - if (!controllerInit) - { - connectController(true); - } - - if (controllerInit && dwUserIndex == 0) - { - pDSoundRenderGuid = NULL; - pDSoundCaptureGuid = NULL; - - return ERROR_SUCCESS; - } - else - { - return ERROR_DEVICE_NOT_CONNECTED; - } -} - -DWORD XInputGetBatteryInformation -( - __in DWORD dwUserIndex, // Index of the gamer associated with the device - __in BYTE devType, // Which device on this user index - __out XINPUT_BATTERY_INFORMATION* pBatteryInformation // Contains the level and types of batteries -) -{ - if (!controllerInit) - { - connectController(true); - } - - if (controllerInit && dwUserIndex == 0) - { - pBatteryInformation->BatteryType = BATTERY_TYPE_WIRED; - pBatteryInformation->BatteryLevel = BATTERY_LEVEL_FULL; - return ERROR_SUCCESS; - } - else - { - return ERROR_DEVICE_NOT_CONNECTED; - } -} - -DWORD WINAPI XInputGetKeystroke -( - __in DWORD dwUserIndex, // Index of the gamer associated with the device - __reserved DWORD dwReserved, // Reserved for future use - __out PXINPUT_KEYSTROKE pKeystroke // Pointer to an XINPUT_KEYSTROKE structure that receives an input event. -) -{ - if (!controllerInit) - { - connectController(true); - } - - if (controllerInit && dwUserIndex == 0) - { - return ERROR_EMPTY; // or ERROR_SUCCESS - } - else - { - return ERROR_DEVICE_NOT_CONNECTED; - } -} - -DWORD WINAPI XInputGetStateEx -( - __in DWORD dwUserIndex, // Index of the gamer associated with the device - __out XINPUT_STATE* pState // Receives the current state -) -{ - if (!controllerInit) - { - connectController(true); - } - if (controllerInit && dwUserIndex == 0) - { - XINPUT_GAMEPAD gamepadState = { 0 }; - - if (GameDetect::currentGame == GameID::Daytona3) - gamepadState.wButtons = *ffbOffset; - else - gamepadState.wButtons = 0; - - if (GameDetect::currentGame == GameID::Daytona3) - { - gamepadState.bRightTrigger = daytonaPressStart ? 0xFF : 0x00; - } - - if (pState->dwPacketNumber == UINT_MAX) - pState->dwPacketNumber = 0; - else - pState->dwPacketNumber++; - pState->Gamepad = gamepadState; - return ERROR_SUCCESS; - } - else - { - return ERROR_DEVICE_NOT_CONNECTED; - } -} - -DWORD WINAPI XInputSetStateEx -( -__in DWORD dwUserIndex, // Index of the gamer associated with the device -__in XINPUT_VIBRATION_EX* pVibration // The vibration information to send to the controller -) -{ - if (!controllerInit) - { - connectController(true); - } - - if (controllerInit && dwUserIndex == 0) - { - int leftTriggerVal = iround(((float)pVibration->wLeftTriggerMotorSpeed / 65535) * 255); - int rightTriggerVal = iround(((float)pVibration->wRightTriggerMotorSpeed / 65535) * 255); - int leftVal = iround(((float)pVibration->wLeftMotorSpeed / 65535) * 255); - int rightVal = iround(((float)pVibration->wRightMotorSpeed / 65535) * 255); - - return ERROR_SUCCESS; - } - else - { - return ERROR_DEVICE_NOT_CONNECTED; - } -} - -LPCWSTR libName = L"xinput1_3.dll"; -LPCWSTR daytonalibName = L"xinput9_1_0.dll"; -LPCWSTR ptrToUse; - -static InitFunction XInputHook([]() -{ - if (GameDetect::currentGame == GameID::PokkenTournament || GameDetect::currentGame == GameID::SchoolOfRagnarok || GameDetect::currentGame == GameID::Daytona3) - { - controllerInit = true; - - MH_Initialize(); - - if (GameDetect::currentGame == GameID::Daytona3) - ptrToUse = daytonalibName; - else - ptrToUse = libName; - - MH_CreateHookApi(ptrToUse, "XInputGetState", &XInputGetState, NULL); - MH_CreateHookApi(ptrToUse, "XInputSetState", &XInputSetState, NULL); - MH_CreateHookApi(ptrToUse, "XInputGetCapabilities", &XInputGetCapabilities, NULL); - MH_CreateHookApi(ptrToUse, "XInputEnable", &XInputEnable, NULL); - MH_CreateHookApi(ptrToUse, "XInputGetDSoundAudioDeviceGuids", &XInputGetDSoundAudioDeviceGuids, NULL); - MH_CreateHookApi(ptrToUse, "XInputGetBatteryInformation", &XInputGetBatteryInformation, NULL); - MH_CreateHookApi(ptrToUse, "XInputGetKeystroke", &XInputGetKeystroke, NULL); - MH_CreateHookApi(ptrToUse, "XInputGetStateEx", &XInputGetStateEx, NULL); - MH_CreateHookApi(ptrToUse, "XInputSetStateEx", &XInputSetStateEx, NULL); - - MH_EnableHook(MH_ALL_HOOKS); - } -}); -#pragma optimize("", on) \ No newline at end of file +#pragma optimize("", off) +#include "StdInc.h" +#include "Utility/GameDetect.h" +#include "Utility/InitFunction.h" +#include "PokkenXInputEmu.h" + +struct XboxOneControllerHandler +{ + struct usb_dev_handle *handle; + bool isConnected; + XBOXONE_STATE controllerState; + + uint8_t lastState[64]; + unsigned int tickCount; + + XINPUT_GAMEPAD lastGamepadState; +}; + +XboxOneControllerHandler *controllerHandler[4] = { NULL, NULL, NULL, NULL }; +HANDLE XboxOneControllerThread[4] = { 0 }; +HANDLE XboxOneControllerMutex[4] = { 0 }; + +static unsigned short idVendor = 0x045E; +static unsigned short idProduct = 0x02D1; + +int configuration = 1; +int interface = 0; +int endpointIn = 0x81; +int endpointOut = 0x01; +int timeout = 2000; // milliseconds +bool controllerInit = false; +bool runThread = true; + +// Structure we receive from the controller +struct XboxOneControllerState +{ + char eventCount; + char unknown; + char buttons1; + char buttons2; + short leftTrigger; // Triggers are 0 - 1023 + short rightTrigger; + short thumbLX; // Axes are -32767 - 32767 + short thumbLY; + short thumbRX; + short thumbRY; +}; + +bool connectController(bool enable) +{ + controllerInit = enable; + return true; +} + +int iround(double num) { + return (num > 0.0) ? (int)floor(num + 0.5) : (int)ceil(num - 0.5); +} + +extern int* ffbOffset; + +DWORD WINAPI XInputGetState +( + __in DWORD dwUserIndex, // Index of the gamer associated with the device + __out XINPUT_STATE* pState // Receives the current state +) +{ + if (!controllerInit) + { + connectController(true); + } + if (controllerInit && dwUserIndex == 0) + { + XINPUT_GAMEPAD gamepadState = { 0 }; + + if (GameDetect::currentGame == GameID::Daytona3) + gamepadState.wButtons |= *ffbOffset; + else + gamepadState.wButtons |= 0; + + if (GameDetect::currentGame == GameID::Daytona3) + { + gamepadState.bRightTrigger = daytonaPressStart ? 0xFF : 0x00; + } + + if (pState->dwPacketNumber == UINT_MAX) + pState->dwPacketNumber = 0; + else + pState->dwPacketNumber++; + + pState->Gamepad = gamepadState; + return ERROR_SUCCESS; + } + else + { + return ERROR_DEVICE_NOT_CONNECTED; + } +} + +DWORD WINAPI XInputSetState +( + __in DWORD dwUserIndex, // Index of the gamer associated with the device + __in XINPUT_VIBRATION* pVibration // The vibration information to send to the controller +) +{ + if (!controllerInit) + { + connectController(true); + } + + if (controllerInit && dwUserIndex == 0) + { + // We're receiving as XInput [0 ~ 65535], need to be [0 ~ 255] !! + int leftVal = iround(((float)pVibration->wLeftMotorSpeed / 65535) * 255); + int rightVal = iround(((float)pVibration->wRightMotorSpeed / 65535) * 255); + return ERROR_SUCCESS; + } + else + { + return ERROR_DEVICE_NOT_CONNECTED; + } +} + +DWORD WINAPI XInputGetCapabilities +( + __in DWORD dwUserIndex, // Index of the gamer associated with the device + __in DWORD dwFlags, // Input flags that identify the device type + __out XINPUT_CAPABILITIES* pCapabilities // Receives the capabilities +) +{ + if (!controllerInit) + { + connectController(true); + } + + if (dwFlags > XINPUT_FLAG_GAMEPAD) + { + return ERROR_BAD_ARGUMENTS; + } + + if (controllerInit && dwUserIndex == 0) + { + 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; + } +} + +void WINAPI XInputEnable +( + __in bool enable // [in] Indicates whether xinput is enabled or disabled. +) +{ + if (!controllerInit) + { + connectController(true); + } + + if (controllerInit && !enable) + { + XINPUT_VIBRATION Vibration = { 0, 0 }; + int xboxControllerCounter = 0; + + while (xboxControllerCounter < 4) + { + if (controllerHandler[xboxControllerCounter]) + { + XInputSetState(xboxControllerCounter, &Vibration); + } + xboxControllerCounter++; + } + } +} + +DWORD WINAPI XInputGetDSoundAudioDeviceGuids +( + __in DWORD dwUserIndex, // Index of the gamer associated with the device + __out GUID* pDSoundRenderGuid, // DSound device ID for render + __out GUID* pDSoundCaptureGuid // DSound device ID for capture +) +{ + if (!controllerInit) + { + connectController(true); + } + + if (controllerInit && dwUserIndex == 0) + { + pDSoundRenderGuid = NULL; + pDSoundCaptureGuid = NULL; + + return ERROR_SUCCESS; + } + else + { + return ERROR_DEVICE_NOT_CONNECTED; + } +} + +DWORD XInputGetBatteryInformation +( + __in DWORD dwUserIndex, // Index of the gamer associated with the device + __in BYTE devType, // Which device on this user index + __out XINPUT_BATTERY_INFORMATION* pBatteryInformation // Contains the level and types of batteries +) +{ + if (!controllerInit) + { + connectController(true); + } + + if (controllerInit && dwUserIndex == 0) + { + pBatteryInformation->BatteryType = BATTERY_TYPE_WIRED; + pBatteryInformation->BatteryLevel = BATTERY_LEVEL_FULL; + return ERROR_SUCCESS; + } + else + { + return ERROR_DEVICE_NOT_CONNECTED; + } +} + +DWORD WINAPI XInputGetKeystroke +( + __in DWORD dwUserIndex, // Index of the gamer associated with the device + __reserved DWORD dwReserved, // Reserved for future use + __out PXINPUT_KEYSTROKE pKeystroke // Pointer to an XINPUT_KEYSTROKE structure that receives an input event. +) +{ + if (!controllerInit) + { + connectController(true); + } + + if (controllerInit && dwUserIndex == 0) + { + return ERROR_EMPTY; // or ERROR_SUCCESS + } + else + { + return ERROR_DEVICE_NOT_CONNECTED; + } +} + +DWORD WINAPI XInputGetStateEx +( + __in DWORD dwUserIndex, // Index of the gamer associated with the device + __out XINPUT_STATE* pState // Receives the current state +) +{ + if (!controllerInit) + { + connectController(true); + } + if (controllerInit && dwUserIndex == 0) + { + XINPUT_GAMEPAD gamepadState = { 0 }; + + if (GameDetect::currentGame == GameID::Daytona3) + gamepadState.wButtons = *ffbOffset; + else + gamepadState.wButtons = 0; + + if (GameDetect::currentGame == GameID::Daytona3) + { + gamepadState.bRightTrigger = daytonaPressStart ? 0xFF : 0x00; + } + + if (pState->dwPacketNumber == UINT_MAX) + pState->dwPacketNumber = 0; + else + pState->dwPacketNumber++; + pState->Gamepad = gamepadState; + return ERROR_SUCCESS; + } + else + { + return ERROR_DEVICE_NOT_CONNECTED; + } +} + +DWORD WINAPI XInputSetStateEx +( +__in DWORD dwUserIndex, // Index of the gamer associated with the device +__in XINPUT_VIBRATION_EX* pVibration // The vibration information to send to the controller +) +{ + if (!controllerInit) + { + connectController(true); + } + + if (controllerInit && dwUserIndex == 0) + { + int leftTriggerVal = iround(((float)pVibration->wLeftTriggerMotorSpeed / 65535) * 255); + int rightTriggerVal = iround(((float)pVibration->wRightTriggerMotorSpeed / 65535) * 255); + int leftVal = iround(((float)pVibration->wLeftMotorSpeed / 65535) * 255); + int rightVal = iround(((float)pVibration->wRightMotorSpeed / 65535) * 255); + + return ERROR_SUCCESS; + } + else + { + return ERROR_DEVICE_NOT_CONNECTED; + } +} + +LPCWSTR libName = L"xinput1_3.dll"; +LPCWSTR daytonalibName = L"xinput9_1_0.dll"; +LPCWSTR ptrToUse; + +static InitFunction XInputHook([]() +{ + if (GameDetect::currentGame == GameID::PokkenTournament || GameDetect::currentGame == GameID::SchoolOfRagnarok || GameDetect::currentGame == GameID::Daytona3) + { + controllerInit = true; + + MH_Initialize(); + + if (GameDetect::currentGame == GameID::Daytona3) + ptrToUse = daytonalibName; + else + ptrToUse = libName; + + MH_CreateHookApi(ptrToUse, "XInputGetState", &XInputGetState, NULL); + MH_CreateHookApi(ptrToUse, "XInputSetState", &XInputSetState, NULL); + MH_CreateHookApi(ptrToUse, "XInputGetCapabilities", &XInputGetCapabilities, NULL); + MH_CreateHookApi(ptrToUse, "XInputEnable", &XInputEnable, NULL); + MH_CreateHookApi(ptrToUse, "XInputGetDSoundAudioDeviceGuids", &XInputGetDSoundAudioDeviceGuids, NULL); + MH_CreateHookApi(ptrToUse, "XInputGetBatteryInformation", &XInputGetBatteryInformation, NULL); + MH_CreateHookApi(ptrToUse, "XInputGetKeystroke", &XInputGetKeystroke, NULL); + MH_CreateHookApi(ptrToUse, "XInputGetStateEx", &XInputGetStateEx, NULL); + MH_CreateHookApi(ptrToUse, "XInputSetStateEx", &XInputSetStateEx, NULL); + + MH_EnableHook(MH_ALL_HOOKS); + } +}); +#pragma optimize("", on)´ diff --git a/OpenParrot/src/Functions/PokkenXInputEmu.h b/OpenParrot/src/Functions/PokkenXInputEmu.h index e5c3137..b70b944 100644 --- a/OpenParrot/src/Functions/PokkenXInputEmu.h +++ b/OpenParrot/src/Functions/PokkenXInputEmu.h @@ -149,4 +149,6 @@ typedef struct _XINPUT_KEYSTROKE WORD Flags; BYTE UserIndex; BYTE HidCode; -} XINPUT_KEYSTROKE, *PXINPUT_KEYSTROKE; \ No newline at end of file +} XINPUT_KEYSTROKE, *PXINPUT_KEYSTROKE; + +extern bool daytonaPressStart; \ No newline at end of file