diff --git a/OpenParrot/src/Functions/Games/Other/FNFDrift.cpp b/OpenParrot/src/Functions/Games/Other/FNFDrift.cpp new file mode 100644 index 0000000..260b533 --- /dev/null +++ b/OpenParrot/src/Functions/Games/Other/FNFDrift.cpp @@ -0,0 +1,274 @@ +#include +#include "Utility/InitFunction.h" +#include "Functions/Global.h" +#include "Utility\Hooking.Patterns.h" +#include +#include +#include + +#pragma comment(lib, "Ws2_32.lib") + +#define clamp( x, xmin, xmax ) min( xmax, max( x, xmin ) ) + +DWORD BaseAddress = 0x00400000; +int horizontal = 0; +int vertical = 0; +HWND hWndRT = 0; +HCURSOR cursorhndle; +// controls +extern int* ffbOffset; +extern int* ffbOffset2; +extern int* ffbOffset3; +extern int* ffbOffset4; +// hooks ori +BOOL(__stdcall *original_SetWindowPos)(HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags); +BOOL(__stdcall *original_CreateWindowExA)(DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam); + +DWORD WINAPI InputRT(LPVOID lpParam) +{ + int deltaTimer = 16; + INT_PTR keyboardBuffer = (0x41B5920 + BaseAddress); + bool previousLeft = false; + bool previousRight = false; + bool previousUp = false; + bool previousDown = false; + + while (true) + { + // ESCAPE QUITS GAME + if (GetAsyncKeyState(VK_ESCAPE) & 0x8000) + { + exit(0); + } + // buttons see bitwise values in TPui//RawThrills.cs + // START + if (*ffbOffset & 0x08) + { + injector::WriteMemory((keyboardBuffer + DIK_SPACE), 2, true); + } + // TEST (shift+numlock TO FIX) + if (*ffbOffset & 0x01) + { + // injector::WriteMemory((keyboardBuffer + DIK_NUMLOCK), 2, true); + // injector::WriteMemory((keyboardBuffer + DIK_LSHIFT), 2, true); + } + // NITRO ( = START too) + if (*ffbOffset & 0x100) + { + injector::WriteMemory((keyboardBuffer + DIK_N), 2, true); + injector::WriteMemory((keyboardBuffer + DIK_SPACE), 2, true); + } + // SHIFT DOWN + if (*ffbOffset & 0x2000) + { + if (!previousDown) + { + injector::WriteMemory((keyboardBuffer + DIK_DOWN), 2, true); + previousDown = true; + } + + else + { + previousDown = false; + } + } + // SHIFT UP + if (*ffbOffset & 0x1000) + { + if (!previousUp) + { + injector::WriteMemory((keyboardBuffer + DIK_UP), 2, true); + previousUp = true; + } + + else + { + previousUp = false; + } + } + // BUTTON 1/ VIEW 1 + if (*ffbOffset & 0x200) + { + injector::WriteMemory((keyboardBuffer + DIK_A), 2, true); + injector::WriteMemory((keyboardBuffer + DIK_F1), 2, true); + } + // BUTTON 2/ VIEW 2 + if (*ffbOffset & 0x400) + { + injector::WriteMemory((keyboardBuffer + DIK_B), 2, true); + injector::WriteMemory((keyboardBuffer + DIK_F2), 2, true); + } + // BUTTON 3/ VIEW 3 + if (*ffbOffset & 0x800) + { + injector::WriteMemory((keyboardBuffer + DIK_E), 2, true); + injector::WriteMemory((keyboardBuffer + DIK_F3), 2, true); + } + // MENU LEFT + if (*ffbOffset & 0x4000) + { + if (!previousLeft) + { + injector::WriteMemory((keyboardBuffer + DIK_LEFT), 2, true); + previousLeft = true; + } + + else + { + previousLeft = false; + } + } + // MENU RIGHT + if (*ffbOffset & 0x8000) + { + if (!previousRight) + { + injector::WriteMemory((keyboardBuffer + DIK_RIGHT), 2, true); + previousRight = true; + } + + else + { + previousRight = false; + } + } + // WHEEL + int iWheel = (((float)*ffbOffset2) - 128); + float wheel = (iWheel * 0.0078125f); + injector::WriteMemory((0x19A300 + BaseAddress), wheel, true); + injector::WriteMemory((0x41B85B0 + BaseAddress), iWheel, true); + // GAS + BYTE gas = ((float)*ffbOffset3) / 255.0f; + int iGas = (int)(gas * 255); + injector::WriteMemory((0x41B85B1 + BaseAddress), iGas, true); + // BRAKE + BYTE brake = ((float)*ffbOffset4) / 255.0f; + int iBrake = (int)(brake * 255); + injector::WriteMemory((0x41B85B2 + BaseAddress), iBrake, true); + injector::WriteMemory((0x19A310 + BaseAddress), gas - brake, true); + + //DEBUG////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // info(true, "test value %f ", test); + //DEBUG////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + Sleep(deltaTimer); + } + + return 0; +} + +DWORD WINAPI WindowRT(LPVOID lpParam) +{ + while (true) + { + // LEFT-CLICK MOVES WINDOW FROM TOP-LEFT CORNER + if (GetAsyncKeyState(VK_LBUTTON) & 0x8000) + { + HWND hWndTMP = GetForegroundWindow(); + if (hWndRT == 0) + { + hWndRT = FindWindowA(NULL, "FNF Drift"); + } + if (hWndTMP == hWndRT) + { + POINT point; + GetCursorPos(&point); + RECT rect; + GetWindowRect(hWndRT, &rect); + int width = rect.right - rect.left; + int height = rect.bottom - rect.top; + LPARAM blah = MAKELPARAM(point.x, point.y); + int xClick = LOWORD(blah) + 10; + int yClick = HIWORD(blah); + if ((xClick + width) > horizontal) + { + xClick = ((horizontal - width) + 10); + } + if ((yClick + height) > vertical) + { + yClick = (vertical - height); + } + original_SetWindowPos(hWndRT, HWND_TOP, xClick, yClick, width, height, SWP_NOSIZE); + SetForegroundWindow(hWndRT); + + } + } + // RIGHT-CLICK MINIMIZES WINDOW + if (GetAsyncKeyState(VK_RBUTTON) & 0x8000) + { + HWND hWndTMP = GetForegroundWindow(); + if (hWndRT == 0) + { + hWndRT = FindWindowA(NULL, "FNF Drift"); + } + if (hWndTMP == hWndRT) + { + original_SetWindowPos(hWndRT, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE); + ShowWindow(hWndRT, SW_MINIMIZE); + } + } + } +} + +DWORD WINAPI CreateWindowExART(DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam) +{ + return original_CreateWindowExA(dwExStyle, lpClassName, "FNF Drift", 0x96C60000, X, Y, (nWidth+16), (nHeight+39), hWndParent, hMenu, hInstance, lpParam); +} + +HCURSOR WINAPI SetCursorRT(int X, int Y) +{ + return cursorhndle; +} + +DWORD WINAPI SetCursorPosRT(int X, int Y) +{ + return 1; +} + +DWORD WINAPI SetWindowPosRT(HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags) +{ + return 1; +} + +static InitFunction FNFDriftFunc([]() +{ + GetDesktopResolution(horizontal, vertical); + cursorhndle = GetCursor(); + + // DISABLE MOUSE AND JOYSTICK + injector::WriteMemory((0x553FD + BaseAddress), 0x13, true); + + // PATCH CODE FOR GAS AND BRAKE + injector::WriteMemoryRaw((0x67E44 + BaseAddress), "\xA1\x10\xA3\x59\x00\x89\x86\xD4\x00\x00\x00\xEB\x17", 13, true); + injector::MakeNOP((0x67E85 + BaseAddress), 10); + injector::MakeNOP((0x67EB8 + BaseAddress), 6); + + // FIX FOCUS CRASH + injector::MakeNOP((0x63E17 + BaseAddress), 6); + + // REPLACE SPACE KEY WITH ESC TO PREVENT EXITING LEVEL PREMATURELY + injector::WriteMemory((0x58E8A + BaseAddress), DIK_ESCAPE, true); + + // REMOVE ERROR MESSAGEBOX ON CLOSE + injector::WriteMemory((0x6431D + BaseAddress), 0xEB, true); + + CreateThread(NULL, 0, InputRT, NULL, 0, NULL); + + if (ToBool(config["General"]["Windowed"])) + { + // CURSOR NOT HIDDEN + injector::WriteMemory((0x63F6F + BaseAddress), 0x01, true); + // SETWINDOWPOS DISABLE + injector::WriteMemory((0xCB596 + BaseAddress), 0x74, true); + + CreateThread(NULL, 0, WindowRT, NULL, 0, NULL); + + MH_Initialize(); + MH_CreateHookApi(L"user32.dll", "CreateWindowExA", &CreateWindowExART, (void**)&original_CreateWindowExA); + MH_CreateHookApi(L"user32.dll", "SetCursorPos", &SetCursorPosRT, NULL); + MH_CreateHookApi(L"user32.dll", "SetCursor", &SetCursorRT, NULL); + MH_CreateHookApi(L"user32.dll", "SetWindowPos", &SetWindowPosRT, (void**)&original_SetWindowPos); + MH_EnableHook(MH_ALL_HOOKS); + } + +}, GameID::FNFDrift); diff --git a/OpenParrot/src/Functions/Games/TypeX2/DirectInputWrapper.cpp b/OpenParrot/src/Functions/Games/TypeX2/DirectInputWrapper.cpp index ca28c77..4b0d1d5 100644 --- a/OpenParrot/src/Functions/Games/TypeX2/DirectInputWrapper.cpp +++ b/OpenParrot/src/Functions/Games/TypeX2/DirectInputWrapper.cpp @@ -378,7 +378,8 @@ static InitFunction initFunc([]() { if (GameDetect::currentGame == GameID::PokkenTournament) return; - + if (GameDetect::currentGame == GameID::FNFDrift) + return; MH_Initialize(); MH_CreateHookApi(L"DINPUT8.dll", "DirectInput8Create", &Hook_DirectInput8Create, (void**)&__DirectInput8Create); diff --git a/OpenParrot/src/Utility/GameDetect.cpp b/OpenParrot/src/Utility/GameDetect.cpp index 06f59c9..a925954 100644 --- a/OpenParrot/src/Utility/GameDetect.cpp +++ b/OpenParrot/src/Utility/GameDetect.cpp @@ -374,6 +374,9 @@ void GameDetect::DetectCurrentGame() currentGame = GameID::TypeXGeneric; X2Type = X2Type::Wontertainment; break; + case 0x47922b80: // FNF Drift + currentGame = GameID::FNFDrift; + break; //case 0xea1984ff: // currentGame = GameID::ExBoardGeneric; // break; diff --git a/OpenParrot/src/Utility/GameID.h b/OpenParrot/src/Utility/GameID.h index 2a48ff3..58bdbaf 100644 --- a/OpenParrot/src/Utility/GameID.h +++ b/OpenParrot/src/Utility/GameID.h @@ -51,5 +51,6 @@ enum class GameID GTIClub3, GRID, UltraStreetFighterIV, - UltraStreetFighterIVDevExe + UltraStreetFighterIVDevExe, + FNFDrift }; \ No newline at end of file