Probe pathfinding start stop wrappers

This commit is contained in:
2026-06-19 22:16:02 -05:00
parent bd4e2b574e
commit bb9fe301bc
+104 -1
View File
@@ -92,6 +92,10 @@ namespace
constexpr uint32_t kGameStateRunning = 2; constexpr uint32_t kGameStateRunning = 2;
constexpr uintptr_t kGpsSystemTickRva = 0x0E6B62C; constexpr uintptr_t kGpsSystemTickRva = 0x0E6B62C;
constexpr uintptr_t kTrafficSystemPathfindingRva = 0x0AD1234; constexpr uintptr_t kTrafficSystemPathfindingRva = 0x0AD1234;
constexpr uintptr_t kStopPathfindingA = 0x11C20A8;
constexpr uintptr_t kStopPathfindingB = 0x11C2148;
constexpr uintptr_t kStartPathfindingA = 0x11C21FC;
constexpr uintptr_t kStartPathfindingB = 0x11C22B0;
HMODULE gModule = nullptr; HMODULE gModule = nullptr;
std::mutex gLogMutex; std::mutex gLogMutex;
@@ -101,10 +105,20 @@ uint32_t gUpdateLogCount = 0;
bool gScannedExecutable = false; bool gScannedExecutable = false;
uint32_t gGpsTickLogCount = 0; uint32_t gGpsTickLogCount = 0;
uint32_t gTrafficPathfindingLogCount = 0; uint32_t gTrafficPathfindingLogCount = 0;
uint32_t gStopPathfindingALogCount = 0;
uint32_t gStopPathfindingBLogCount = 0;
uint32_t gStartPathfindingALogCount = 0;
uint32_t gStartPathfindingBLogCount = 0;
uint64_t gLogStartTick = 0;
uint64_t gLogFrequency = 0;
using ProbeFunc = void (*)(void* aThis, void* a2, void* a3, void* a4); using ProbeFunc = void (*)(void* aThis, void* a2, void* a3, void* a4);
ProbeFunc gOriginalGpsSystemTick = nullptr; ProbeFunc gOriginalGpsSystemTick = nullptr;
ProbeFunc gOriginalTrafficSystemPathfinding = nullptr; ProbeFunc gOriginalTrafficSystemPathfinding = nullptr;
ProbeFunc gOriginalStopPathfindingA = nullptr;
ProbeFunc gOriginalStopPathfindingB = nullptr;
ProbeFunc gOriginalStartPathfindingA = nullptr;
ProbeFunc gOriginalStartPathfindingB = nullptr;
std::filesystem::path GetLogPath() std::filesystem::path GetLogPath()
{ {
@@ -133,7 +147,16 @@ void Log(std::string_view aMessage)
return; return;
} }
out << std::put_time(&localTime, "%Y-%m-%d %H:%M:%S") << " " << aMessage << "\n"; uint64_t elapsedMs = 0;
if (gLogStartTick && gLogFrequency)
{
LARGE_INTEGER counter{};
QueryPerformanceCounter(&counter);
elapsedMs = static_cast<uint64_t>((counter.QuadPart - gLogStartTick) * 1000 / gLogFrequency);
}
out << std::put_time(&localTime, "%Y-%m-%d %H:%M:%S") << "." << std::setw(3) << std::setfill('0')
<< elapsedMs % 1000 << std::setfill(' ') << " +" << elapsedMs << "ms " << aMessage << "\n";
} }
void LogRed4ext(std::string_view aMessage) void LogRed4ext(std::string_view aMessage)
@@ -149,9 +172,15 @@ void LogRed4ext(std::string_view aMessage)
void LogHookCall(const char* aName, uint32_t aCount, void* aThis, void* a2, void* a3, void* a4) void LogHookCall(const char* aName, uint32_t aCount, void* aThis, void* a2, void* a3, void* a4)
{ {
const auto imageBase = reinterpret_cast<uintptr_t>(GetModuleHandleW(nullptr));
const auto ret = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
std::ostringstream line; std::ostringstream line;
line << "hook " << aName << " call=" << aCount << " this=" << aThis << " a2=" << a2 << " a3=" << a3 line << "hook " << aName << " call=" << aCount << " this=" << aThis << " a2=" << a2 << " a3=" << a3
<< " a4=" << a4; << " a4=" << a4;
if (ret && imageBase && ret >= imageBase)
{
line << " ret_rva=0x" << std::hex << (ret - imageBase) << std::dec;
}
LogRed4ext(line.str()); LogRed4ext(line.str());
} }
@@ -340,6 +369,62 @@ void DetourTrafficSystemPathfinding(void* aThis, void* a2, void* a3, void* a4)
} }
} }
void DetourStopPathfindingA(void* aThis, void* a2, void* a3, void* a4)
{
if (gStopPathfindingALogCount < 32)
{
LogHookCall("StopPathfindingA", gStopPathfindingALogCount, aThis, a2, a3, a4);
++gStopPathfindingALogCount;
}
if (gOriginalStopPathfindingA)
{
gOriginalStopPathfindingA(aThis, a2, a3, a4);
}
}
void DetourStopPathfindingB(void* aThis, void* a2, void* a3, void* a4)
{
if (gStopPathfindingBLogCount < 32)
{
LogHookCall("StopPathfindingB", gStopPathfindingBLogCount, aThis, a2, a3, a4);
++gStopPathfindingBLogCount;
}
if (gOriginalStopPathfindingB)
{
gOriginalStopPathfindingB(aThis, a2, a3, a4);
}
}
void DetourStartPathfindingA(void* aThis, void* a2, void* a3, void* a4)
{
if (gStartPathfindingALogCount < 32)
{
LogHookCall("StartPathfindingA", gStartPathfindingALogCount, aThis, a2, a3, a4);
++gStartPathfindingALogCount;
}
if (gOriginalStartPathfindingA)
{
gOriginalStartPathfindingA(aThis, a2, a3, a4);
}
}
void DetourStartPathfindingB(void* aThis, void* a2, void* a3, void* a4)
{
if (gStartPathfindingBLogCount < 32)
{
LogHookCall("StartPathfindingB", gStartPathfindingBLogCount, aThis, a2, a3, a4);
++gStartPathfindingBLogCount;
}
if (gOriginalStartPathfindingB)
{
gOriginalStartPathfindingB(aThis, a2, a3, a4);
}
}
void AttachProbeHook(const char* aName, uintptr_t aRva, void* aDetour, void** aOriginal) void AttachProbeHook(const char* aName, uintptr_t aRva, void* aDetour, void** aOriginal)
{ {
if (!gSdk || !gSdk->hooking || !gSdk->hooking->Attach) if (!gSdk || !gSdk->hooking || !gSdk->hooking->Attach)
@@ -414,6 +499,12 @@ BOOL APIENTRY DllMain(HMODULE aModule, DWORD aReason, LPVOID)
if (aReason == DLL_PROCESS_ATTACH) if (aReason == DLL_PROCESS_ATTACH)
{ {
gModule = aModule; gModule = aModule;
LARGE_INTEGER frequency{};
LARGE_INTEGER counter{};
QueryPerformanceFrequency(&frequency);
QueryPerformanceCounter(&counter);
gLogFrequency = static_cast<uint64_t>(frequency.QuadPart);
gLogStartTick = static_cast<uint64_t>(counter.QuadPart);
} }
return TRUE; return TRUE;
} }
@@ -443,12 +534,24 @@ RED4EXT_C_EXPORT bool RED4EXT_CALL Main(RED4ext::v1::PluginHandle aHandle, RED4e
AttachProbeHook("TrafficSystem_Pathfinding", kTrafficSystemPathfindingRva, AttachProbeHook("TrafficSystem_Pathfinding", kTrafficSystemPathfindingRva,
reinterpret_cast<void*>(&DetourTrafficSystemPathfinding), reinterpret_cast<void*>(&DetourTrafficSystemPathfinding),
reinterpret_cast<void**>(&gOriginalTrafficSystemPathfinding)); reinterpret_cast<void**>(&gOriginalTrafficSystemPathfinding));
AttachProbeHook("StopPathfindingA", kStopPathfindingA, reinterpret_cast<void*>(&DetourStopPathfindingA),
reinterpret_cast<void**>(&gOriginalStopPathfindingA));
AttachProbeHook("StopPathfindingB", kStopPathfindingB, reinterpret_cast<void*>(&DetourStopPathfindingB),
reinterpret_cast<void**>(&gOriginalStopPathfindingB));
AttachProbeHook("StartPathfindingA", kStartPathfindingA, reinterpret_cast<void*>(&DetourStartPathfindingA),
reinterpret_cast<void**>(&gOriginalStartPathfindingA));
AttachProbeHook("StartPathfindingB", kStartPathfindingB, reinterpret_cast<void*>(&DetourStartPathfindingB),
reinterpret_cast<void**>(&gOriginalStartPathfindingB));
} }
if (aReason == RED4ext::v1::EMainReason::Unload) if (aReason == RED4ext::v1::EMainReason::Unload)
{ {
DetachProbeHook("GPSSystem/Tick", kGpsSystemTickRva); DetachProbeHook("GPSSystem/Tick", kGpsSystemTickRva);
DetachProbeHook("TrafficSystem_Pathfinding", kTrafficSystemPathfindingRva); DetachProbeHook("TrafficSystem_Pathfinding", kTrafficSystemPathfindingRva);
DetachProbeHook("StopPathfindingA", kStopPathfindingA);
DetachProbeHook("StopPathfindingB", kStopPathfindingB);
DetachProbeHook("StartPathfindingA", kStartPathfindingA);
DetachProbeHook("StartPathfindingB", kStartPathfindingB);
} }
return true; return true;