Probe GPS and traffic pathfinding hooks
This commit is contained in:
@@ -62,6 +62,12 @@ struct GameStates
|
||||
bool (*Add)(PluginHandle aHandle, uint32_t aType, GameState* aState);
|
||||
};
|
||||
|
||||
struct Hooking
|
||||
{
|
||||
bool (*Attach)(PluginHandle aHandle, void* aTarget, void* aDetour, void** aOriginal);
|
||||
bool (*Detach)(PluginHandle aHandle, void* aTarget);
|
||||
};
|
||||
|
||||
struct Scripts
|
||||
{
|
||||
bool (*Add)(PluginHandle aHandle, const wchar_t* aPath);
|
||||
@@ -75,7 +81,7 @@ struct Sdk
|
||||
{
|
||||
SemVer* runtime;
|
||||
Logger* logger;
|
||||
void* hooking;
|
||||
Hooking* hooking;
|
||||
GameStates* gameStates;
|
||||
Scripts* scripts;
|
||||
};
|
||||
@@ -84,6 +90,8 @@ struct Sdk
|
||||
namespace
|
||||
{
|
||||
constexpr uint32_t kGameStateRunning = 2;
|
||||
constexpr uintptr_t kGpsSystemTickRva = 0x0E6B62C;
|
||||
constexpr uintptr_t kTrafficSystemPathfindingRva = 0x0AD1234;
|
||||
|
||||
HMODULE gModule = nullptr;
|
||||
std::mutex gLogMutex;
|
||||
@@ -91,6 +99,12 @@ RED4ext::v1::PluginHandle gHandle = nullptr;
|
||||
const RED4ext::v1::Sdk* gSdk = nullptr;
|
||||
uint32_t gUpdateLogCount = 0;
|
||||
bool gScannedExecutable = false;
|
||||
uint32_t gGpsTickLogCount = 0;
|
||||
uint32_t gTrafficPathfindingLogCount = 0;
|
||||
|
||||
using ProbeFunc = void (*)(void* aThis, void* a2, void* a3, void* a4);
|
||||
ProbeFunc gOriginalGpsSystemTick = nullptr;
|
||||
ProbeFunc gOriginalTrafficSystemPathfinding = nullptr;
|
||||
|
||||
std::filesystem::path GetLogPath()
|
||||
{
|
||||
@@ -133,6 +147,14 @@ void LogRed4ext(std::string_view aMessage)
|
||||
}
|
||||
}
|
||||
|
||||
void LogHookCall(const char* aName, uint32_t aCount, void* aThis, void* a2, void* a3, void* a4)
|
||||
{
|
||||
std::ostringstream line;
|
||||
line << "hook " << aName << " call=" << aCount << " this=" << aThis << " a2=" << a2 << " a3=" << a3
|
||||
<< " a4=" << a4;
|
||||
LogRed4ext(line.str());
|
||||
}
|
||||
|
||||
const char* ReasonToString(RED4ext::v1::EMainReason aReason)
|
||||
{
|
||||
switch (aReason)
|
||||
@@ -290,6 +312,66 @@ void ScanExecutableStrings()
|
||||
LogRed4ext("exe-string scan end");
|
||||
}
|
||||
|
||||
void DetourGpsSystemTick(void* aThis, void* a2, void* a3, void* a4)
|
||||
{
|
||||
if (gGpsTickLogCount < 16)
|
||||
{
|
||||
LogHookCall("GPSSystem/Tick", gGpsTickLogCount, aThis, a2, a3, a4);
|
||||
++gGpsTickLogCount;
|
||||
}
|
||||
|
||||
if (gOriginalGpsSystemTick)
|
||||
{
|
||||
gOriginalGpsSystemTick(aThis, a2, a3, a4);
|
||||
}
|
||||
}
|
||||
|
||||
void DetourTrafficSystemPathfinding(void* aThis, void* a2, void* a3, void* a4)
|
||||
{
|
||||
if (gTrafficPathfindingLogCount < 16)
|
||||
{
|
||||
LogHookCall("TrafficSystem_Pathfinding", gTrafficPathfindingLogCount, aThis, a2, a3, a4);
|
||||
++gTrafficPathfindingLogCount;
|
||||
}
|
||||
|
||||
if (gOriginalTrafficSystemPathfinding)
|
||||
{
|
||||
gOriginalTrafficSystemPathfinding(aThis, a2, a3, a4);
|
||||
}
|
||||
}
|
||||
|
||||
void AttachProbeHook(const char* aName, uintptr_t aRva, void* aDetour, void** aOriginal)
|
||||
{
|
||||
if (!gSdk || !gSdk->hooking || !gSdk->hooking->Attach)
|
||||
{
|
||||
LogRed4ext("hook attach skipped: RED4ext hooking API unavailable");
|
||||
return;
|
||||
}
|
||||
|
||||
auto* target = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(GetModuleHandleW(nullptr)) + aRva);
|
||||
const auto attached = gSdk->hooking->Attach(gHandle, target, aDetour, aOriginal);
|
||||
|
||||
std::ostringstream line;
|
||||
line << "hook attach " << aName << " target=" << target << " rva=0x" << std::hex << aRva << std::dec
|
||||
<< " result=" << (attached ? "ok" : "failed") << " original=" << (aOriginal ? *aOriginal : nullptr);
|
||||
LogRed4ext(line.str());
|
||||
}
|
||||
|
||||
void DetachProbeHook(const char* aName, uintptr_t aRva)
|
||||
{
|
||||
if (!gSdk || !gSdk->hooking || !gSdk->hooking->Detach)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto* target = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(GetModuleHandleW(nullptr)) + aRva);
|
||||
const auto detached = gSdk->hooking->Detach(gHandle, target);
|
||||
|
||||
std::ostringstream line;
|
||||
line << "hook detach " << aName << " target=" << target << " result=" << (detached ? "ok" : "failed");
|
||||
LogRed4ext(line.str());
|
||||
}
|
||||
|
||||
bool OnRunningEnter(void* aApp)
|
||||
{
|
||||
std::ostringstream line;
|
||||
@@ -355,6 +437,18 @@ RED4EXT_C_EXPORT bool RED4EXT_CALL Main(RED4ext::v1::PluginHandle aHandle, RED4e
|
||||
{
|
||||
const auto added = aSdk->gameStates->Add(aHandle, kGameStateRunning, &gRunningState);
|
||||
LogRed4ext(added ? "registered Running game-state callbacks" : "failed to register Running game-state callbacks");
|
||||
|
||||
AttachProbeHook("GPSSystem/Tick", kGpsSystemTickRva, reinterpret_cast<void*>(&DetourGpsSystemTick),
|
||||
reinterpret_cast<void**>(&gOriginalGpsSystemTick));
|
||||
AttachProbeHook("TrafficSystem_Pathfinding", kTrafficSystemPathfindingRva,
|
||||
reinterpret_cast<void*>(&DetourTrafficSystemPathfinding),
|
||||
reinterpret_cast<void**>(&gOriginalTrafficSystemPathfinding));
|
||||
}
|
||||
|
||||
if (aReason == RED4ext::v1::EMainReason::Unload)
|
||||
{
|
||||
DetachProbeHook("GPSSystem/Tick", kGpsSystemTickRva);
|
||||
DetachProbeHook("TrafficSystem_Pathfinding", kTrafficSystemPathfindingRva);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user