From 53efd04ae6a2ee920d253ef328acc0179f00faf1 Mon Sep 17 00:00:00 2001 From: _Sakura <97910292+0x-FADED@users.noreply.github.com> Date: Sun, 17 Mar 2024 23:08:58 +0900 Subject: [PATCH] dynamically fetch game version instead of using a pattern for it - use win api for getting game version & remove memory scanning dependency for it - could be useful for maintaining compatibility across different game versions --- EGameTools/EGameTools.vcxproj | 4 +- EGameTools/source/core.cpp | 17 +++++-- EGameTools/source/core.h | 8 ++-- EGameTools/source/game/GamePH/Other.cpp | 60 +++++++++++++++++++------ EGameTools/source/game/GamePH/Other.h | 4 +- EGameTools/source/offsets.h | 1 - 6 files changed, 67 insertions(+), 27 deletions(-) diff --git a/EGameTools/EGameTools.vcxproj b/EGameTools/EGameTools.vcxproj index 4a212d4..7b8b89c 100644 --- a/EGameTools/EGameTools.vcxproj +++ b/EGameTools/EGameTools.vcxproj @@ -262,7 +262,7 @@ Windows true false - DbgHelp.lib;spdlog-mtd.lib;freetype-mtd.lib;libMinHook-x64-v141-mtd.lib;%(AdditionalDependencies) + DbgHelp.lib;Version.lib;spdlog-mtd.lib;freetype-mtd.lib;libMinHook-x64-v141-mtd.lib;%(AdditionalDependencies) @@ -298,7 +298,7 @@ false false source\spdlog\lib;source\ImGui\freetype\lib;source\MinHook\lib;%(AdditionalLibraryDirectories) - DbgHelp.lib;spdlog-mt.lib;freetype-mt.lib;libMinHook-x64-v141-mtd.lib;$(CoreLibraryDependencies);%(AdditionalDependencies) + DbgHelp.lib;Version.lib;spdlog-mt.lib;freetype-mt.lib;libMinHook-x64-v141-mtd.lib;$(CoreLibraryDependencies);%(AdditionalDependencies) /NOIMPLIB /NOEXP %(AdditionalOptions) diff --git a/EGameTools/source/core.cpp b/EGameTools/source/core.cpp index 5f0779c..2712637 100644 --- a/EGameTools/source/core.cpp +++ b/EGameTools/source/core.cpp @@ -159,14 +159,23 @@ namespace Core { } } - DWORD64 gameVer = 0; + uint16_t gameVer = 0; static void LoopGetGameVer() { + + auto str = GamePH::GetCurrentGameVersionStr(); + auto end = str.c_str() + std::char_traits::length(str.c_str()); + while (true) { if (exiting) return; - gameVer = GamePH::GetCurrentGameVersion(); - if (!gameVer) + uint16_t value; + std::from_chars(str.c_str(), end, value); + + if(value!=0) + gameVer = value; + + if (gameVer == 0) continue; break; @@ -236,7 +245,7 @@ namespace Core { if (Core::gameVer != GAME_VER_COMPAT) { spdlog::error("Please note that your game version has not been officially tested with this mod, therefore expect bugs, glitches or the mod to completely stop working. If so, please {}", Core::gameVer > GAME_VER_COMPAT ? "wait for a new patch." : "upgrade your game version to one that the mod supports."); } - }).detach(); + }).detach(); spdlog::warn("Hooking DX11/DX12 renderer"); std::thread([]() { diff --git a/EGameTools/source/core.h b/EGameTools/source/core.h index 861a94c..e48f94c 100644 --- a/EGameTools/source/core.h +++ b/EGameTools/source/core.h @@ -16,9 +16,9 @@ #define VK_MWHEELUP 0x101 #endif -constexpr auto MOD_VERSION_STR = "v1.1.3"; -constexpr auto MOD_VERSION = 10103; -constexpr auto GAME_VER_COMPAT = 11504; +constexpr auto MOD_VERSION_STR = "v1.1.2"; +constexpr auto MOD_VERSION = 10102; +constexpr uint16_t GAME_VER_COMPAT = 11530; struct Key { constexpr Key(std::string_view name, int code, ImGuiKey imGuiCode) : name(name), code(code), imGuiCode(imGuiCode) {} @@ -227,6 +227,6 @@ namespace Core { extern bool exiting; extern int rendererAPI; - extern DWORD64 gameVer; + extern uint16_t gameVer; extern void OnPostUpdate(); } \ No newline at end of file diff --git a/EGameTools/source/game/GamePH/Other.cpp b/EGameTools/source/game/GamePH/Other.cpp index 4c4e2a5..d137d1e 100644 --- a/EGameTools/source/game/GamePH/Other.cpp +++ b/EGameTools/source/game/GamePH/Other.cpp @@ -4,27 +4,59 @@ #include "gen_TPPModel.h" namespace GamePH { - const DWORD64 GetCurrentGameVersion() { - DWORD64(*pGetCurrentGameVersion)() = (decltype(pGetCurrentGameVersion))Offsets::Get_GetCurrentGameVersion(); - if (!pGetCurrentGameVersion) - return 0; + const std::tuple GetCurrentGameVersion() { + WCHAR inBuf[MAX_PATH] = { 0 }; + GetModuleFileNameW(GetModuleHandleW(nullptr), inBuf, static_cast(std::size(inBuf))); + std::wstring fileStr = inBuf; - return pGetCurrentGameVersion(); - } - const std::string GameVerToStr(DWORD64 version) { - DWORD64 major = version / 10000; - DWORD64 minor = (version / 100) % 100; - DWORD64 patch = version % 100; + DWORD verHandle; + DWORD verSz = GetFileVersionInfoSizeW(fileStr.data(), &verHandle); - return std::string(std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(patch)); + if (verSz != 0 && verHandle == 0) { + + std::vector verData(verSz); + + if (GetFileVersionInfoW(fileStr.data(), verHandle, verSz, verData.data())) { + + LPVOID buffer; + UINT bufferLength; + + if (VerQueryValueW(verData.data(), L"\\", &buffer, &bufferLength) && bufferLength != 0) { + + VS_FIXEDFILEINFO* verInfo = reinterpret_cast(buffer); + + if (verInfo->dwSignature == 0xFEEF04BD) { + const auto major = (verInfo->dwFileVersionMS >> 16) & 0xFFFF; + const auto minor = verInfo->dwFileVersionMS & 0xFFFF; + const auto build = (verInfo->dwFileVersionLS >> 16) & 0xFFFF; + const auto revision = verInfo->dwFileVersionLS & 0xFFFF; + return { major, minor, build, revision }; + } + } + } + } + + return { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF }; } + const std::string GetCurrentGameVersionStr() { - if (!GetCurrentGameVersion()) + auto [major, minor, build, revision] = GetCurrentGameVersion(); + + if (major == 0xFFFF || minor == 0xFFFF || build == 0xFFFF || revision == 0xFFFF) return "UNKNOWN"; - return GameVerToStr(GetCurrentGameVersion()); + return std::string(std::to_string(major) + std::to_string(minor) + std::to_string(build) + std::to_string(revision)); } - + + const std::string GameVerToStr(uint16_t version) { + uint16_t major = version / 10000; + uint16_t minor = (version / 100) % 100; + uint16_t build = (version / 10) % 10; + uint16_t revision = version % 10; + + return std::string(std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(build) + "." + std::to_string(revision)); + } + static DWORD64 ShowTPPModelFunc2(GameDI_PH* pGameDI_PH) { DWORD64(*pShowTPPModelFunc2)(LPVOID pGameDI_PH) = (decltype(pShowTPPModelFunc2))Offsets::Get_ShowTPPModelFunc2(); if (!pShowTPPModelFunc2) diff --git a/EGameTools/source/game/GamePH/Other.h b/EGameTools/source/game/GamePH/Other.h index bc2afc0..f4fd336 100644 --- a/EGameTools/source/game/GamePH/Other.h +++ b/EGameTools/source/game/GamePH/Other.h @@ -3,9 +3,9 @@ #include namespace GamePH { - extern const DWORD64 GetCurrentGameVersion(); - extern const std::string GameVerToStr(DWORD64 version); + extern const std::tuple GetCurrentGameVersion(); extern const std::string GetCurrentGameVersionStr(); + extern const std::string GameVerToStr(uint16_t version); extern void ShowTPPModel(bool showTPPModel); extern bool ReloadJumps(); } \ No newline at end of file diff --git a/EGameTools/source/offsets.h b/EGameTools/source/offsets.h index ade8203..6c367f7 100644 --- a/EGameTools/source/offsets.h +++ b/EGameTools/source/offsets.h @@ -50,7 +50,6 @@ struct Offsets { // Functions AddOffset(ReadVideoSettings, "engine_x64_rwdi.dll", "48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 48 83 EC ?? 48 8B FA 48 8B D9 45 84 C0", Utils::SigScan::PatternType::Address, LPVOID) AddOffset(MoveCameraFromForwardUpPos, "engine_x64_rwdi.dll", "48 89 5C 24 ?? 57 48 83 EC ?? 49 8B C1 48 8B F9", Utils::SigScan::PatternType::Address, LPVOID) - AddOffset(GetCurrentGameVersion, "gamedll_ph_x64_rwdi.dll", "B8 ?? ?? ?? ?? C3 CC CC CC CC CC CC CC CC CC CC 48 83 79", Utils::SigScan::PatternType::Address, LPVOID) AddOffset(CalculateFreeCamCollision, "gamedll_ph_x64_rwdi.dll", "48 8B C4 55 53 56 57 48 8D A8 ?? ?? ?? ?? 48 81 EC ?? ?? ?? ?? 83 B9", Utils::SigScan::PatternType::Address, LPVOID) AddOffset(AllowCameraMovement, "gamedll_ph_x64_rwdi.dll", "89 91 ?? ?? ?? ?? C3 CC CC CC CC CC CC CC CC CC 48 8B C4 55 56", Utils::SigScan::PatternType::Address, LPVOID) //AddOffset(GetViewCamera, "engine_x64_rwdi.dll", "E8 [?? ?? ?? ?? 48 85 C0 74 28 48 8B C8", PatternType::RelativePointer, LPVOID)