Probe async GPS traffic results

This commit is contained in:
2026-06-20 22:27:52 -05:00
parent 7a7b18d449
commit 2db6eefebd
+136 -1
View File
@@ -101,9 +101,10 @@ constexpr bool kEnableGpsProviderClassPatch = false;
constexpr bool kEnableGpsProviderClassPatchTrace = false;
constexpr bool kEnableGpsTraceHooks = true;
constexpr bool kEnableGpsQueryLifecycleHooks = true;
constexpr bool kEnableGpsAsyncTrafficProbe = true;
constexpr bool kEnableGpsRouteJobLifecycleHooks = false;
constexpr bool kEnableGpsRouteJobStartTrace = false;
constexpr bool kEnableGpsLocalSearchHooks = true;
constexpr bool kEnableGpsLocalSearchHooks = false;
constexpr bool kEnableRouteUiTraceHooks = false;
constexpr uintptr_t kGpsSystemTickRva = 0x0E6B62C;
constexpr uintptr_t kJournalTrackEntryImplRva = 0x05944FC;
@@ -162,6 +163,8 @@ constexpr uintptr_t kGpsQueryResultFetchRva = 0x07094B8;
constexpr uintptr_t kGpsQueryStatusRva = 0x0AA5704;
constexpr uintptr_t kGpsMapRouteSubmitReturnRva = 0x08D20D4;
constexpr uintptr_t kGpsDispatchAdvanceRva = 0x08D17D8;
constexpr uintptr_t kGpsTrafficResultTakeRva = 0x0709D5C;
constexpr uintptr_t kGpsRoutePostprocessRva = 0x044830C;
constexpr uintptr_t kGpsAsyncWorkerTickRva = 0x0126B28;
constexpr uintptr_t kGpsRouteJobStartRva = 0x0818928;
constexpr uintptr_t kGpsRouteJobPollRva = 0x0883CD8;
@@ -263,6 +266,8 @@ uint32_t gGpsQueryDispatchLogCount = 0;
uint32_t gGpsQueryResultFetchLogCount = 0;
uint32_t gGpsQueryStatusLogCount = 0;
uint32_t gGpsDispatchAdvanceLogCount = 0;
uint32_t gGpsTrafficResultTakeLogCount = 0;
uint32_t gGpsRoutePostprocessLogCount = 0;
uint32_t gGpsAsyncWorkerTickLogCount = 0;
uint32_t gGpsRouteJobStartLogCount = 0;
uint32_t gGpsRouteJobPollLogCount = 0;
@@ -415,6 +420,9 @@ using GpsQueryResultFetchFunc = bool (*)(void* aManager, uint32_t aQueryId, void
using GpsQueryStatusFunc = int32_t (*)(void* aManager, uint32_t aQueryId);
using GpsDispatchAdvanceFunc = void (*)(void* aRouteSystem, void* aRuntimeQuery, void* aOutTicket,
void* aTargetPosition, void* aSourcePosition);
using GpsTrafficResultTakeFunc = void* (*)(void* aTrafficService, void* aOutResult, uint32_t aTicket,
void* aOutMeta);
using GpsRoutePostprocessFunc = void (*)(void* aOutPath, void* aTrafficResult, void* aRouteRecords, float aScale);
using GpsAsyncWorkerTickFunc = void (*)(void* aRouteSystem);
using GpsRouteJobStartFunc = bool (*)(void* aRouteSystem, void* aActiveEntry, float aDelta, void* aOutLocal);
using GpsRouteJobPollFunc = bool (*)(void* aRouteSystem, void* aActiveEntry);
@@ -482,6 +490,8 @@ GpsQueryDispatchFunc gOriginalGpsQueryDispatch = nullptr;
GpsQueryResultFetchFunc gOriginalGpsQueryResultFetch = nullptr;
GpsQueryStatusFunc gOriginalGpsQueryStatus = nullptr;
GpsDispatchAdvanceFunc gOriginalGpsDispatchAdvance = nullptr;
GpsTrafficResultTakeFunc gOriginalGpsTrafficResultTake = nullptr;
GpsRoutePostprocessFunc gOriginalGpsRoutePostprocess = nullptr;
GpsAsyncWorkerTickFunc gOriginalGpsAsyncWorkerTick = nullptr;
GpsRouteJobStartFunc gOriginalGpsRouteJobStart = nullptr;
GpsRouteJobPollFunc gOriginalGpsRouteJobPoll = nullptr;
@@ -2164,6 +2174,44 @@ void AppendRouteOutputPointerSummary(std::ostringstream& aLine, const char* aPre
}
}
void AppendTrafficResultSummary(std::ostringstream& aLine, const char* aPrefix, void* aResult)
{
const auto prefix = std::string(aPrefix);
AppendPointerWithRva(aLine, prefix.c_str(), aResult);
if (!aResult)
{
return;
}
AppendUint32Field(aLine, (prefix + "_count0c").c_str(), aResult, 0x0C);
AppendPointerField(aLine, (prefix + "_records10").c_str(), aResult, 0x10);
AppendUint32Field(aLine, (prefix + "_u2c").c_str(), aResult, 0x2C);
AppendUint32Field(aLine, (prefix + "_u30").c_str(), aResult, 0x30);
AppendUint32Field(aLine, (prefix + "_u34").c_str(), aResult, 0x34);
uint32_t count = 0;
auto* records = ReadPointerField(aResult, 0x10);
if (TryReadUint32FieldValue(aResult, 0x0C, count) && records)
{
const auto sampleCount = std::min<uint32_t>(count, 4);
AppendBytesPointer(aLine, (prefix + "_records10_raw").c_str(), records,
static_cast<size_t>(sampleCount) * 0x10);
}
}
void AppendTrafficResultHolderSummary(std::ostringstream& aLine, const char* aPrefix, void* aOut)
{
const auto prefix = std::string(aPrefix);
AppendPointerWithRva(aLine, prefix.c_str(), aOut);
if (!aOut)
{
return;
}
auto* value = ReadPointerField(aOut, 0x00);
AppendTrafficResultSummary(aLine, (prefix + "_value").c_str(), value);
}
void TrackGpsQuery(uint32_t aQueryId, void* aManager, uintptr_t aSubmitReturnRva, uint32_t aSubmitCall)
{
if (aQueryId == UINT32_MAX)
@@ -3642,6 +3690,75 @@ void DetourGpsDispatchAdvance(void* aRouteSystem, void* aRuntimeQuery, void* aOu
}
}
void* DetourGpsTrafficResultTake(void* aTrafficService, void* aOutResult, uint32_t aTicket, void* aOutMeta)
{
constexpr uint32_t kMaxCalls = 128;
const auto callCount = NextGpsAsyncLogCall(gGpsTrafficResultTakeLogCount);
const auto shouldLog = callCount < kMaxCalls;
if (shouldLog)
{
std::ostringstream line;
line << "hook GPSTrafficResultTake 0x709d5c call=" << callCount << " ticket=" << aTicket;
AppendPointerWithRva(line, "trafficService", aTrafficService);
AppendTrafficResultHolderSummary(line, "outResultBefore", aOutResult);
AppendPointerWithRva(line, "outMeta", aOutMeta);
AppendBytesPointer(line, "outMeta_raw10_before", aOutMeta, 0x10);
AppendReturnRva(line, __builtin_return_address(0));
LogRed4ext(line.str());
}
void* result = nullptr;
if (gOriginalGpsTrafficResultTake)
{
result = gOriginalGpsTrafficResultTake(aTrafficService, aOutResult, aTicket, aOutMeta);
}
if (shouldLog)
{
std::ostringstream line;
line << "hook GPSTrafficResultTake result call=" << callCount;
AppendPointerWithRva(line, "value", result);
AppendTrafficResultHolderSummary(line, "outResultAfter", aOutResult);
AppendPointerWithRva(line, "outMeta", aOutMeta);
AppendBytesPointer(line, "outMeta_raw10_after", aOutMeta, 0x10);
LogRed4ext(line.str());
}
return result;
}
void DetourGpsRoutePostprocess(void* aOutPath, void* aTrafficResult, void* aRouteRecords, float aScale)
{
constexpr uint32_t kMaxCalls = 128;
const auto callCount = NextGpsAsyncLogCall(gGpsRoutePostprocessLogCount);
const auto shouldLog = callCount < kMaxCalls;
if (shouldLog)
{
std::ostringstream line;
line << "hook GPSRoutePostprocess 0x44830c call=" << callCount << " scale=" << aScale;
AppendPointerWithRva(line, "outPath", aOutPath);
AppendTrafficResultSummary(line, "trafficResult", aTrafficResult);
AppendPointerWithRva(line, "routeRecords", aRouteRecords);
AppendReturnRva(line, __builtin_return_address(0));
LogRed4ext(line.str());
}
if (gOriginalGpsRoutePostprocess)
{
gOriginalGpsRoutePostprocess(aOutPath, aTrafficResult, aRouteRecords, aScale);
}
if (shouldLog)
{
std::ostringstream line;
line << "hook GPSRoutePostprocess result call=" << callCount;
AppendGpsResultObjectSummary(line, "outPath", aOutPath);
LogRed4ext(line.str());
}
}
void DetourGpsAsyncWorkerTick(void* aRouteSystem)
{
constexpr uint32_t kMaxCalls = 192;
@@ -4538,6 +4655,18 @@ RED4EXT_C_EXPORT bool RED4EXT_CALL Main(RED4ext::v1::PluginHandle aHandle, RED4e
reinterpret_cast<void*>(&DetourGpsQueryStatus),
reinterpret_cast<void**>(&gOriginalGpsQueryStatus));
}
if (kEnableGpsAsyncTrafficProbe)
{
AttachProbeHook("GPSDispatchAdvance 0x8d17d8", kGpsDispatchAdvanceRva,
reinterpret_cast<void*>(&DetourGpsDispatchAdvance),
reinterpret_cast<void**>(&gOriginalGpsDispatchAdvance));
AttachProbeHook("GPSTrafficResultTake 0x709d5c", kGpsTrafficResultTakeRva,
reinterpret_cast<void*>(&DetourGpsTrafficResultTake),
reinterpret_cast<void**>(&gOriginalGpsTrafficResultTake));
AttachProbeHook("GPSRoutePostprocess 0x44830c", kGpsRoutePostprocessRva,
reinterpret_cast<void*>(&DetourGpsRoutePostprocess),
reinterpret_cast<void**>(&gOriginalGpsRoutePostprocess));
}
if (kEnableGpsRouteJobLifecycleHooks)
{
AttachProbeHook("GPSDispatchAdvance 0x8d17d8", kGpsDispatchAdvanceRva,
@@ -4718,6 +4847,12 @@ RED4EXT_C_EXPORT bool RED4EXT_CALL Main(RED4ext::v1::PluginHandle aHandle, RED4e
DetachProbeHook("GPSQueryResultFetch 0x7094b8", kGpsQueryResultFetchRva);
DetachProbeHook("GPSQueryStatus 0xaa5704", kGpsQueryStatusRva);
}
if (kEnableGpsAsyncTrafficProbe)
{
DetachProbeHook("GPSDispatchAdvance 0x8d17d8", kGpsDispatchAdvanceRva);
DetachProbeHook("GPSTrafficResultTake 0x709d5c", kGpsTrafficResultTakeRva);
DetachProbeHook("GPSRoutePostprocess 0x44830c", kGpsRoutePostprocessRva);
}
if (kEnableGpsRouteJobLifecycleHooks)
{
DetachProbeHook("GPSDispatchAdvance 0x8d17d8", kGpsDispatchAdvanceRva);