From f9f3e40e3a60c18aa311d270a2cda2d99898a443 Mon Sep 17 00:00:00 2001 From: Nico Giansanti Date: Fri, 5 Apr 2019 04:45:22 +0300 Subject: [PATCH] Open source GRID and GTI Club 3 Open source GRID and GTI Club 3 --- .../src/Functions/Games/Europa-R/GRID.cpp | 147 ++++++++++++++++++ .../src/Functions/Games/TypeX2/GTIClub3.cpp | 120 ++++++++++++++ OpenParrot/src/Functions/Types.h | 2 +- OpenParrot/src/Utility/GameDetect.cpp | 6 + OpenParrot/src/Utility/GameID.h | 4 +- 5 files changed, 277 insertions(+), 2 deletions(-) create mode 100644 OpenParrot/src/Functions/Games/Europa-R/GRID.cpp create mode 100644 OpenParrot/src/Functions/Games/TypeX2/GTIClub3.cpp diff --git a/OpenParrot/src/Functions/Games/Europa-R/GRID.cpp b/OpenParrot/src/Functions/Games/Europa-R/GRID.cpp new file mode 100644 index 0000000..9548f79 --- /dev/null +++ b/OpenParrot/src/Functions/Games/Europa-R/GRID.cpp @@ -0,0 +1,147 @@ +#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; + +DWORD jOffset = 0x0081D64E; +DWORD myPointer = 0; + +typedef struct +{ + DWORD *SomeAddress; + float ControlValue; +} ControlStruct, *PControlStruct; + +void __declspec(naked) FixMissingData() +{ + __asm + { + mov ebx, [edx] + cmp ebx, 0xFFFFFFFF + jne skip + mov ebx, 0 + skip: + mov[ecx], ebx + sub eax, 1 + jmp jOffset + } +} + +void __declspec(naked) GetControlOffset() +{ + __asm + { + CMP myPointer, 0 + JNE skip + CMP[ECX - 0x1C], 0x580 + JNE skip + mov myPointer, ecx + sub myPointer, 0x18 + skip: + RET 4 + } +} + +bool inputInitialized = false; + +float toFloatGRID(uint8_t x) +{ + return x / 255.0; +} + +void SetButton(DWORD address, bool pressed) +{ + if (pressed) + *(DWORD*)address = 0x3F800000; + else + *(DWORD*)address = 0; +} + +DWORD WINAPI XInputGetStateGRID +( + __in DWORD dwUserIndex, // Index of the gamer associated with the device + __out DWORD* pState // Receives the current state +) +{ + if (myPointer != 0) + { + // Write control injector here + if (!inputInitialized) + { + //info(true, "The Page is at: %08X", myPointer); + inputInitialized = true; + } + + DWORD buttons2 = *wheelSection; + DWORD buttons = *ffbOffset; + BYTE wheel = *ffbOffset2; + BYTE gas = *ffbOffset3; + BYTE brake = *ffbOffset4; + + float wheelFloat = toFloatGRID(wheel); + float gasFloat = toFloatGRID(gas); + float brakeFloat = toFloatGRID(brake); + + // Wheel Float + memcpy((void *)(myPointer + 0x484), &wheelFloat, 4); + + // Gas Float + memcpy((void *)(myPointer + 0x49C), &gasFloat, 4); + + // Brake Float + memcpy((void *)(myPointer + 0x494), &brakeFloat, 4); + + SetButton(myPointer + 0x4, buttons & 0x1); + SetButton(myPointer + 0x1C, buttons & 0x2); + SetButton(myPointer + 0x24, buttons & 0x4); + + SetButton(myPointer + 0xC, buttons2 & 0x1); + SetButton(myPointer + 0x14, buttons2 & 0x2); + SetButton(myPointer + 0x4C, buttons2 & 0x4); + SetButton(myPointer + 0x414, buttons2 & 0x8); + SetButton(myPointer + 0x404, buttons2 & 0x10); + SetButton(myPointer + 0x3C, buttons2 & 0x20); + SetButton(myPointer + 0x34, buttons2 & 0x40); + SetButton(myPointer + 0x40c, buttons2 & 0x80); + } + + return ERROR_DEVICE_NOT_CONNECTED; +} + +static InitFunction GRIDFunc([]() +{ + // Crash fix + injector::MakeNOP(0x005AB9E5, 2); + + // Fix stupid "let's put 0xFFFFFFFF in stuff we miss to cause crashes" + injector::MakeJMP(0x0081D647, FixMissingData, true); + injector::WriteMemory(0x00AEA6DD, 0x00000000, true); + + // Get Control Offset + injector::MakeJMP(0x00A878E0, GetControlOffset, true); + + // Button mashing on + injector::WriteMemory(0xEAF304, 0x01, true); + + // Prevent overwriting of button mashing by xml + injector::MakeNOP(0x005F44B8, 6); + injector::MakeNOP(0x00AEC695, 5); + + // Force button mashing on + injector::MakeNOP(0x00B76560, 6); + + // Hook XInput to send our controls + MH_Initialize(); + MH_CreateHookApi(L"xinput1_3.dll", "XInputGetState", &XInputGetStateGRID, NULL); + MH_EnableHook(MH_ALL_HOOKS); + +}, GameID::GRID); +#endif \ No newline at end of file diff --git a/OpenParrot/src/Functions/Games/TypeX2/GTIClub3.cpp b/OpenParrot/src/Functions/Games/TypeX2/GTIClub3.cpp new file mode 100644 index 0000000..0b81f47 --- /dev/null +++ b/OpenParrot/src/Functions/Games/TypeX2/GTIClub3.cpp @@ -0,0 +1,120 @@ +#include +#include "Utility/InitFunction.h" +#include "Functions/Global.h" +#if _M_IX86 +DWORD mainModuleBase; +int __cdecl IgnoreFunc(int a1, int a2) +{ + int result; // eax + + result = a2; + *(BYTE *)(a2 + 8) = 1; + + // Enable Input + *(BYTE *)(mainModuleBase + 0x67E75B) = 1; + return result; +} + +extern int* ffbOffset; +extern int* ffbOffset2; +extern int* ffbOffset3; +extern int* ffbOffset4; + + +float toFloat(uint8_t x) +{ + return x / 255.0; +} + +float toFloatWheel(uint8_t x) +{ + return x / 255.0 * 2.0 - 1.0; +} + +static int InjectKeys() +{ + int notButtons = ~*(WORD *)(mainModuleBase + 0x67E784); + int buttons = *ffbOffset; + DWORD wheel = *ffbOffset2; + DWORD gas = *ffbOffset3; + DWORD brake = *ffbOffset4; + + BYTE wheelVal = (wheel - 0xFF) / 0x100; + BYTE gasVal = (gas - 0xFF) / 0x100; + BYTE brakeVal = (brake - 0xFF) / 0x100; + + float wheelFloat = toFloatWheel(wheelVal); + float gasFloat = toFloat(gasVal); + float brakeFloat = toFloat(brakeVal); + + if (wheelVal < 0x60) + buttons |= 0x200; + + if (wheelVal > 0xA0) + buttons |= 0x400; + + if (gasVal > 0xA0) + buttons |= 0x20; + + if (brakeVal > 0xA0) + buttons |= 0x40; + + // Digital Inputs + *(WORD *)(mainModuleBase + 0x67E784) = buttons; + + // Wheel Test Menu + *(WORD *)(mainModuleBase + 0x518C8C) = *ffbOffset2; + + // Gas Test Menu + *(WORD *)(mainModuleBase + 0x518C90) = *ffbOffset3; + + // Brake Test Menu + *(WORD *)(mainModuleBase + 0x518C94) = *ffbOffset4; + + // Wheel Float + memcpy((void *)(mainModuleBase + 0x518C80), &wheelFloat, 4); + + // Gas Float + memcpy((void *)(mainModuleBase + 0x518C84), &gasFloat, 4); + + // Brake Float + memcpy((void *)(mainModuleBase + 0x518C88), &brakeFloat, 4); + + *(DWORD*)0xA7E788 = buttons & notButtons; + + return 1; +} + +static int(*g_origac_io_hbhi_COMUNICATE)(); + +signed int __cdecl ac_io_hbhi_COMUNICATE() +{ + InjectKeys(); + + return g_origac_io_hbhi_COMUNICATE(); +} + +static InitFunction GtiClub3Func([]() +{ + + mainModuleBase = (DWORD)GetModuleHandle(0); + + DWORD funcPtr = (DWORD)(void *)IgnoreFunc; + + CreateDirectoryA("EUP", nullptr); + CreateDirectoryA("FUP", nullptr); + + injector::WriteMemory(mainModuleBase + 0x4C0E0C, funcPtr, true); + injector::WriteMemory(mainModuleBase + 0x4C0E14, funcPtr, true); + injector::WriteMemory(mainModuleBase + 0x4C0E1C, funcPtr, true); + injector::WriteMemory(mainModuleBase + 0x4C0E3C, funcPtr, true); + + injector::WriteMemory(mainModuleBase + 0x357CB4, 0x55465C2E, true); + injector::WriteMemory(mainModuleBase + 0x357C80, 0x55455C2E, true); + + MH_Initialize(); + MH_CreateHook((void*)(mainModuleBase + 0x409C0), ac_io_hbhi_COMUNICATE, (void**)&g_origac_io_hbhi_COMUNICATE); // ? + MH_EnableHook(MH_ALL_HOOKS); + +}, GameID::GTIClub3); +#endif \ No newline at end of file diff --git a/OpenParrot/src/Functions/Types.h b/OpenParrot/src/Functions/Types.h index 971a004..34d2367 100644 --- a/OpenParrot/src/Functions/Types.h +++ b/OpenParrot/src/Functions/Types.h @@ -10,5 +10,5 @@ enum class X2Type { Generic, GaiaAttack4, BattleFantasia, - MB4 + MB4, }; \ No newline at end of file diff --git a/OpenParrot/src/Utility/GameDetect.cpp b/OpenParrot/src/Utility/GameDetect.cpp index 5c23219..466e15f 100644 --- a/OpenParrot/src/Utility/GameDetect.cpp +++ b/OpenParrot/src/Utility/GameDetect.cpp @@ -360,6 +360,12 @@ void GameDetect::DetectCurrentGame() case 0xbb359a1a: // Suggoi! Arcana Heart 2 currentGame = GameID::ExBoardGeneric; break; + case 0x4966e11b: + currentGame = GameID::GRID; + break; + case 0x326ebcd6: + currentGame = GameID::GTIClub3; + break; //case 0xea1984ff: // currentGame = GameID::ExBoardGeneric; // break; diff --git a/OpenParrot/src/Utility/GameID.h b/OpenParrot/src/Utility/GameID.h index d1f5d61..a9b1c23 100644 --- a/OpenParrot/src/Utility/GameID.h +++ b/OpenParrot/src/Utility/GameID.h @@ -46,5 +46,7 @@ enum class GameID MagicalBeat, CrimzonClover, Daytona3, - MB4 + MB4, + GTIClub3, + GRID }; \ No newline at end of file