1
0
mirror of synced 2025-02-01 12:17:55 +01:00

Open source GRID and GTI Club 3

Open source GRID and GTI Club 3
This commit is contained in:
Nico Giansanti 2019-04-05 04:45:22 +03:00
parent 251ee88cdb
commit f9f3e40e3a
5 changed files with 277 additions and 2 deletions

View File

@ -0,0 +1,147 @@
#include <StdInc.h>
#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<DWORD>(0x00AEA6DD, 0x00000000, true);
// Get Control Offset
injector::MakeJMP(0x00A878E0, GetControlOffset, true);
// Button mashing on
injector::WriteMemory<BYTE>(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

View File

@ -0,0 +1,120 @@
#include <StdInc.h>
#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<DWORD>(mainModuleBase + 0x4C0E0C, funcPtr, true);
injector::WriteMemory<DWORD>(mainModuleBase + 0x4C0E14, funcPtr, true);
injector::WriteMemory<DWORD>(mainModuleBase + 0x4C0E1C, funcPtr, true);
injector::WriteMemory<DWORD>(mainModuleBase + 0x4C0E3C, funcPtr, true);
injector::WriteMemory<DWORD>(mainModuleBase + 0x357CB4, 0x55465C2E, true);
injector::WriteMemory<DWORD>(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

View File

@ -10,5 +10,5 @@ enum class X2Type {
Generic,
GaiaAttack4,
BattleFantasia,
MB4
MB4,
};

View File

@ -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;

View File

@ -46,5 +46,7 @@ enum class GameID
MagicalBeat,
CrimzonClover,
Daytona3,
MB4
MB4,
GTIClub3,
GRID
};