Track GPS query status lifecycle

This commit is contained in:
2026-06-20 13:00:35 -05:00
parent 50c81b780a
commit 751e2175f7
2 changed files with 283 additions and 79 deletions
+26 -3
View File
@@ -53,9 +53,14 @@ Current behavior:
native registration cluster: native registration cluster:
`0x29bd128` (`RunGPSQuery` body), `0x29bd254` (`UpdateGPSQuery` body), `0x29bd128` (`RunGPSQuery` body), `0x29bd254` (`UpdateGPSQuery` body),
`0x70a42c` (shared query submitter), `0x70a570` (low-level query dispatch), `0x70a42c` (shared query submitter), `0x70a570` (low-level query dispatch),
and `0x7094b8` (query result/path fetch). `0x7094b8` (query result/path fetch), and `0xaa5704` (query status check).
- Logs query endpoints, returned query IDs, shared submitter return RVAs, query - Logs query endpoints, returned query IDs, shared submitter return RVAs, query
state fields, result-fetch success, and summarized path buffers/point counts. state fields, status values, result-fetch success, and summarized path
buffers/point counts.
- The active probe now records query IDs returned from `0x70a42c` and always
logs result/status polling for those tracked IDs. Startup polling of query
IDs `0`/`1` is sampled only briefly so it cannot exhaust the route-click log
budget.
- Resolves the native mappin system when one of those paths fires, logs relevant - Resolves the native mappin system when one of those paths fires, logs relevant
vtable slot addresses, and temporarily hooks the route-adjacent slots. vtable slot addresses, and temporarily hooks the route-adjacent slots.
@@ -79,7 +84,7 @@ Current route-probe focus:
classified as journal metadata) classified as journal metadata)
- route-build candidate called by the bridge: `0x5625a4` - route-build candidate called by the bridge: `0x5625a4`
- GPS query lifecycle: `0x29bd128`, `0x29bd254`, `0x70a42c`, `0x70a570`, - GPS query lifecycle: `0x29bd128`, `0x29bd254`, `0x70a42c`, `0x70a570`,
`0x7094b8` `0x7094b8`, `0xaa5704`
Quest/objective pins did not fire the mappin tracking hooks in live tests. The Quest/objective pins did not fire the mappin tracking hooks in live tests. The
REDscript decompile shows that those pins call `JournalManager.TrackEntry` REDscript decompile shows that those pins call `JournalManager.TrackEntry`
@@ -134,6 +139,24 @@ Current static lead:
so return RVAs and query IDs are important for separating map GPS from traffic so return RVAs and query IDs are important for separating map GPS from traffic
or AI path requests. or AI path requests.
Latest GPS-query finding:
- During a controlled route test, the normal world-map GPS path did not call
the script-native `RunGPSQuery`/`UpdateGPSQuery` bodies.
- Each deliberate quest/custom route click called the shared submitter
`0x70a42c` from return RVA `0x8d20d4`, then returned query IDs `3`, `4`, `5`,
and `6` for the three quest routes plus the custom pin.
- Each submitted route produced three `0x70a570` dispatches: current/player
position, a nearby snapped/lane position, then the destination position.
- The dense log stream immediately after Space-to-Continue was repeated
`0x7094b8` result polling for startup query IDs `0`/`1`, matching the HUD /
minimap route initialization delay. The next probe tracks submitted IDs so
route-click completion can be captured without being drowned by startup
polling.
- Static disassembly confirms `0xaa5704` takes `(manager, queryId)` and returns
a small status code; one caller checks for value `1` as the completed-query
state.
Build and install from the Fedora toolbox: Build and install from the Fedora toolbox:
```bash ```bash
+257 -76
View File
@@ -92,6 +92,9 @@ struct Sdk
namespace namespace
{ {
constexpr uint32_t kGameStateRunning = 2; constexpr uint32_t kGameStateRunning = 2;
constexpr bool kEnableVerboseJournalListenerHooks = false;
constexpr bool kEnableVerboseRouteObserverHooks = false;
constexpr bool kEnableVerboseMappinRouteState = false;
constexpr uintptr_t kGpsSystemTickRva = 0x0E6B62C; constexpr uintptr_t kGpsSystemTickRva = 0x0E6B62C;
constexpr uintptr_t kJournalTrackEntryImplRva = 0x05944FC; constexpr uintptr_t kJournalTrackEntryImplRva = 0x05944FC;
constexpr uintptr_t kJournalListenerArrayOffset = 0x210; constexpr uintptr_t kJournalListenerArrayOffset = 0x210;
@@ -146,6 +149,7 @@ constexpr uintptr_t kUpdateGpsQueryBodyRva = 0x29BD254;
constexpr uintptr_t kGpsQuerySubmitRva = 0x070A42C; constexpr uintptr_t kGpsQuerySubmitRva = 0x070A42C;
constexpr uintptr_t kGpsQueryDispatchRva = 0x070A570; constexpr uintptr_t kGpsQueryDispatchRva = 0x070A570;
constexpr uintptr_t kGpsQueryResultFetchRva = 0x07094B8; constexpr uintptr_t kGpsQueryResultFetchRva = 0x07094B8;
constexpr uintptr_t kGpsQueryStatusRva = 0x0AA5704;
HMODULE gModule = nullptr; HMODULE gModule = nullptr;
std::mutex gLogMutex; std::mutex gLogMutex;
@@ -205,6 +209,7 @@ uint32_t gUpdateGpsQueryBodyLogCount = 0;
uint32_t gGpsQuerySubmitLogCount = 0; uint32_t gGpsQuerySubmitLogCount = 0;
uint32_t gGpsQueryDispatchLogCount = 0; uint32_t gGpsQueryDispatchLogCount = 0;
uint32_t gGpsQueryResultFetchLogCount = 0; uint32_t gGpsQueryResultFetchLogCount = 0;
uint32_t gGpsQueryStatusLogCount = 0;
uint64_t gLogStartTick = 0; uint64_t gLogStartTick = 0;
uint64_t gLogFrequency = 0; uint64_t gLogFrequency = 0;
void* gMappinSetTrackedTarget = nullptr; void* gMappinSetTrackedTarget = nullptr;
@@ -219,6 +224,21 @@ void* gObserver1ServiceRouteLookupTarget = nullptr;
bool gMappinSlotHookAttachAttempted = false; bool gMappinSlotHookAttachAttempted = false;
bool gObserver1ServiceRouteLookupHookAttachAttempted = false; bool gObserver1ServiceRouteLookupHookAttachAttempted = false;
struct TrackedGpsQuery
{
bool active = false;
uint32_t id = 0;
void* manager = nullptr;
uintptr_t submitReturnRva = 0;
uint32_t submitCall = 0;
uint32_t resultFetchCalls = 0;
uint32_t statusCalls = 0;
};
std::mutex gTrackedGpsQueryMutex;
std::array<TrackedGpsQuery, 32> gTrackedGpsQueries{};
uint32_t gTrackedGpsQueryNext = 0;
using ProbeFunc = void (*)(void* aThis, void* a2, void* a3, void* a4); using ProbeFunc = void (*)(void* aThis, void* a2, void* a3, void* a4);
using JournalTrackEntryFunc = void (*)(void* aThis, void* aEntryHandle); using JournalTrackEntryFunc = void (*)(void* aThis, void* aEntryHandle);
using ScriptNativeVoidFunc = void (*)(void* aThis, void* aStack, void* aResult); using ScriptNativeVoidFunc = void (*)(void* aThis, void* aStack, void* aResult);
@@ -253,6 +273,7 @@ using UpdateGpsQueryBodyFunc = bool (*)(void* aThis, uint32_t aQueryId, void* aO
using GpsQuerySubmitFunc = int32_t (*)(void* aManager, void* aQuery); using GpsQuerySubmitFunc = int32_t (*)(void* aManager, void* aQuery);
using GpsQueryDispatchFunc = void (*)(void* aRuntimeQuery, void* aTargetPosition, void* aArg3, void* aArg4); using GpsQueryDispatchFunc = void (*)(void* aRuntimeQuery, void* aTargetPosition, void* aArg3, void* aArg4);
using GpsQueryResultFetchFunc = bool (*)(void* aManager, uint32_t aQueryId, void* aOutPath); using GpsQueryResultFetchFunc = bool (*)(void* aManager, uint32_t aQueryId, void* aOutPath);
using GpsQueryStatusFunc = int32_t (*)(void* aManager, uint32_t aQueryId);
ProbeFunc gOriginalGpsSystemTick = nullptr; ProbeFunc gOriginalGpsSystemTick = nullptr;
JournalTrackEntryFunc gOriginalJournalTrackEntry = nullptr; JournalTrackEntryFunc gOriginalJournalTrackEntry = nullptr;
ScriptNativeVoidFunc gOriginalFrameMappinPathWrapper = nullptr; ScriptNativeVoidFunc gOriginalFrameMappinPathWrapper = nullptr;
@@ -303,6 +324,7 @@ UpdateGpsQueryBodyFunc gOriginalUpdateGpsQueryBody = nullptr;
GpsQuerySubmitFunc gOriginalGpsQuerySubmit = nullptr; GpsQuerySubmitFunc gOriginalGpsQuerySubmit = nullptr;
GpsQueryDispatchFunc gOriginalGpsQueryDispatch = nullptr; GpsQueryDispatchFunc gOriginalGpsQueryDispatch = nullptr;
GpsQueryResultFetchFunc gOriginalGpsQueryResultFetch = nullptr; GpsQueryResultFetchFunc gOriginalGpsQueryResultFetch = nullptr;
GpsQueryStatusFunc gOriginalGpsQueryStatus = nullptr;
std::filesystem::path GetLogPath() std::filesystem::path GetLogPath()
{ {
@@ -390,6 +412,17 @@ bool IsInImage(const void* aPointer)
return imageBase && imageEnd && address >= imageBase && address < imageEnd; return imageBase && imageEnd && address >= imageBase && address < imageEnd;
} }
bool TryGetImageRva(const void* aPointer, uintptr_t& aRva)
{
if (!IsInImage(aPointer))
{
return false;
}
aRva = reinterpret_cast<uintptr_t>(aPointer) - GetImageBase();
return true;
}
void AppendPointerWithRva(std::ostringstream& aLine, const char* aLabel, const void* aPointer) void AppendPointerWithRva(std::ostringstream& aLine, const char* aLabel, const void* aPointer)
{ {
aLine << " " << aLabel << "=" << aPointer; aLine << " " << aLabel << "=" << aPointer;
@@ -710,6 +743,81 @@ void AppendPathBufferSummary(std::ostringstream& aLine, const char* aPrefix, voi
} }
} }
void TrackGpsQuery(uint32_t aQueryId, void* aManager, uintptr_t aSubmitReturnRva, uint32_t aSubmitCall)
{
if (aQueryId == UINT32_MAX)
{
return;
}
std::lock_guard lock(gTrackedGpsQueryMutex);
for (auto& query : gTrackedGpsQueries)
{
if (query.active && query.id == aQueryId && query.manager == aManager)
{
query.submitReturnRva = aSubmitReturnRva;
query.submitCall = aSubmitCall;
return;
}
}
auto& query = gTrackedGpsQueries[gTrackedGpsQueryNext++ % gTrackedGpsQueries.size()];
query.active = true;
query.id = aQueryId;
query.manager = aManager;
query.submitReturnRva = aSubmitReturnRva;
query.submitCall = aSubmitCall;
query.resultFetchCalls = 0;
query.statusCalls = 0;
}
bool NoteTrackedGpsQueryResultFetch(uint32_t aQueryId, void* aManager, TrackedGpsQuery& aSnapshot,
uint32_t& aPerQueryCall)
{
std::lock_guard lock(gTrackedGpsQueryMutex);
for (auto& query : gTrackedGpsQueries)
{
if (!query.active || query.id != aQueryId || query.manager != aManager)
{
continue;
}
aPerQueryCall = query.resultFetchCalls++;
aSnapshot = query;
return true;
}
return false;
}
bool NoteTrackedGpsQueryStatus(uint32_t aQueryId, void* aManager, TrackedGpsQuery& aSnapshot,
uint32_t& aPerQueryCall)
{
std::lock_guard lock(gTrackedGpsQueryMutex);
for (auto& query : gTrackedGpsQueries)
{
if (!query.active || query.id != aQueryId || query.manager != aManager)
{
continue;
}
aPerQueryCall = query.statusCalls++;
aSnapshot = query;
return true;
}
return false;
}
void AppendTrackedGpsQuery(std::ostringstream& aLine, const TrackedGpsQuery& aQuery)
{
aLine << " submitCall=" << aQuery.submitCall << " submitRetRva=0x" << std::hex << aQuery.submitReturnRva
<< std::dec;
}
void AppendRouteRefFields(std::ostringstream& aLine, const char* aPrefix, void* aRouteRef) void AppendRouteRefFields(std::ostringstream& aLine, const char* aPrefix, void* aRouteRef)
{ {
AppendPointerWithRva(aLine, aPrefix, aRouteRef); AppendPointerWithRva(aLine, aPrefix, aRouteRef);
@@ -730,6 +838,11 @@ void AppendRouteRefFields(std::ostringstream& aLine, const char* aPrefix, void*
void LogMappinRouteCollections(const char* aName, uint32_t aCount, void* aSystem) void LogMappinRouteCollections(const char* aName, uint32_t aCount, void* aSystem)
{ {
if (!kEnableVerboseMappinRouteState)
{
return;
}
if (!aSystem) if (!aSystem)
{ {
return; return;
@@ -1133,7 +1246,6 @@ void DetourJournalTrackEntry(void* aThis, void* aEntryHandle)
AppendReturnRva(line, __builtin_return_address(0)); AppendReturnRva(line, __builtin_return_address(0));
LogRed4ext(line.str()); LogRed4ext(line.str());
LogJournalListeners(callCount, aThis);
++gJournalTrackEntryLogCount; ++gJournalTrackEntryLogCount;
} }
@@ -1906,6 +2018,10 @@ int32_t DetourGpsQuerySubmit(void* aManager, void* aQuery)
{ {
constexpr uint32_t kMaxCalls = 128; constexpr uint32_t kMaxCalls = 128;
const auto returnAddress = __builtin_return_address(0);
uintptr_t returnRva = 0;
TryGetImageRva(returnAddress, returnRva);
const auto callCount = gGpsQuerySubmitLogCount; const auto callCount = gGpsQuerySubmitLogCount;
const auto shouldLog = callCount < kMaxCalls; const auto shouldLog = callCount < kMaxCalls;
if (shouldLog) if (shouldLog)
@@ -1920,7 +2036,7 @@ int32_t DetourGpsQuerySubmit(void* aManager, void* aQuery)
AppendUint32Field(line, "query_f0c", aQuery, 0x0C); AppendUint32Field(line, "query_f0c", aQuery, 0x0C);
AppendUint32Field(line, "query_fcc", aQuery, 0xCC); AppendUint32Field(line, "query_fcc", aQuery, 0xCC);
AppendVector4Field(line, "query_pos58", aQuery, 0x58); AppendVector4Field(line, "query_pos58", aQuery, 0x58);
AppendReturnRva(line, __builtin_return_address(0)); AppendReturnRva(line, returnAddress);
LogRed4ext(line.str()); LogRed4ext(line.str());
++gGpsQuerySubmitLogCount; ++gGpsQuerySubmitLogCount;
} }
@@ -1931,6 +2047,11 @@ int32_t DetourGpsQuerySubmit(void* aManager, void* aQuery)
result = gOriginalGpsQuerySubmit(aManager, aQuery); result = gOriginalGpsQuerySubmit(aManager, aQuery);
} }
if (result >= 0)
{
TrackGpsQuery(static_cast<uint32_t>(result), aManager, returnRva, callCount);
}
if (shouldLog) if (shouldLog)
{ {
std::ostringstream line; std::ostringstream line;
@@ -1969,20 +2090,11 @@ void DetourGpsQueryDispatch(void* aRuntimeQuery, void* aTargetPosition, void* aA
bool DetourGpsQueryResultFetch(void* aManager, uint32_t aQueryId, void* aOutPath) bool DetourGpsQueryResultFetch(void* aManager, uint32_t aQueryId, void* aOutPath)
{ {
constexpr uint32_t kMaxCalls = 128; constexpr uint32_t kMaxUntrackedSamples = 32;
constexpr uint32_t kMaxTrackedSamplesPerQuery = 24;
const auto callCount = gGpsQueryResultFetchLogCount; const auto callCount = gGpsQueryResultFetchLogCount++;
const auto shouldLog = callCount < kMaxCalls; const auto returnAddress = __builtin_return_address(0);
if (shouldLog)
{
std::ostringstream line;
line << "hook GPSQueryResultFetch 0x7094b8 call=" << callCount << " queryId=" << aQueryId;
AppendPointerWithRva(line, "manager", aManager);
AppendPointerWithRva(line, "outPath", aOutPath);
AppendReturnRva(line, __builtin_return_address(0));
LogRed4ext(line.str());
++gGpsQueryResultFetchLogCount;
}
bool result = false; bool result = false;
if (gOriginalGpsQueryResultFetch) if (gOriginalGpsQueryResultFetch)
@@ -1990,10 +2102,25 @@ bool DetourGpsQueryResultFetch(void* aManager, uint32_t aQueryId, void* aOutPath
result = gOriginalGpsQueryResultFetch(aManager, aQueryId, aOutPath); result = gOriginalGpsQueryResultFetch(aManager, aQueryId, aOutPath);
} }
TrackedGpsQuery trackedQuery{};
uint32_t perQueryCall = 0;
const auto isTracked = NoteTrackedGpsQueryResultFetch(aQueryId, aManager, trackedQuery, perQueryCall);
const auto shouldLog = (isTracked && (perQueryCall < kMaxTrackedSamplesPerQuery || result)) ||
(!isTracked && callCount < kMaxUntrackedSamples && aQueryId < 2);
if (shouldLog) if (shouldLog)
{ {
std::ostringstream line; std::ostringstream line;
line << "hook GPSQueryResultFetch result call=" << callCount << " value=" << static_cast<uint32_t>(result); line << "hook GPSQueryResultFetch 0x7094b8 call=" << callCount << " queryId=" << aQueryId
<< " tracked=" << static_cast<uint32_t>(isTracked) << " perQueryCall=" << perQueryCall
<< " value=" << static_cast<uint32_t>(result);
if (isTracked)
{
AppendTrackedGpsQuery(line, trackedQuery);
}
AppendPointerWithRva(line, "manager", aManager);
AppendPointerWithRva(line, "outPath", aOutPath);
AppendReturnRva(line, returnAddress);
AppendPathBufferSummary(line, "outPath", aOutPath); AppendPathBufferSummary(line, "outPath", aOutPath);
LogRed4ext(line.str()); LogRed4ext(line.str());
} }
@@ -2001,6 +2128,44 @@ bool DetourGpsQueryResultFetch(void* aManager, uint32_t aQueryId, void* aOutPath
return result; return result;
} }
int32_t DetourGpsQueryStatus(void* aManager, uint32_t aQueryId)
{
constexpr uint32_t kMaxUntrackedSamples = 32;
constexpr uint32_t kMaxTrackedSamplesPerQuery = 24;
const auto callCount = gGpsQueryStatusLogCount++;
const auto returnAddress = __builtin_return_address(0);
int32_t result = 0;
if (gOriginalGpsQueryStatus)
{
result = gOriginalGpsQueryStatus(aManager, aQueryId);
}
TrackedGpsQuery trackedQuery{};
uint32_t perQueryCall = 0;
const auto isTracked = NoteTrackedGpsQueryStatus(aQueryId, aManager, trackedQuery, perQueryCall);
const auto shouldLog = (isTracked && (perQueryCall < kMaxTrackedSamplesPerQuery || result != 0)) ||
(!isTracked && callCount < kMaxUntrackedSamples && aQueryId < 2);
if (shouldLog)
{
std::ostringstream line;
line << "hook GPSQueryStatus 0xaa5704 call=" << callCount << " queryId=" << aQueryId
<< " tracked=" << static_cast<uint32_t>(isTracked) << " perQueryCall=" << perQueryCall
<< " value=" << result;
if (isTracked)
{
AppendTrackedGpsQuery(line, trackedQuery);
}
AppendPointerWithRva(line, "manager", aManager);
AppendReturnRva(line, returnAddress);
LogRed4ext(line.str());
}
return result;
}
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)
@@ -2324,38 +2489,44 @@ RED4EXT_C_EXPORT bool RED4EXT_CALL Main(RED4ext::v1::PluginHandle aHandle, RED4e
AttachProbeHook("GPSQueryResultFetch 0x7094b8", kGpsQueryResultFetchRva, AttachProbeHook("GPSQueryResultFetch 0x7094b8", kGpsQueryResultFetchRva,
reinterpret_cast<void*>(&DetourGpsQueryResultFetch), reinterpret_cast<void*>(&DetourGpsQueryResultFetch),
reinterpret_cast<void**>(&gOriginalGpsQueryResultFetch)); reinterpret_cast<void**>(&gOriginalGpsQueryResultFetch));
AttachProbeHook("GPSQueryStatus 0xaa5704", kGpsQueryStatusRva,
reinterpret_cast<void*>(&DetourGpsQueryStatus),
reinterpret_cast<void**>(&gOriginalGpsQueryStatus));
AttachProbeHook("GPSSystem/Tick", kGpsSystemTickRva, reinterpret_cast<void*>(&DetourGpsSystemTick), AttachProbeHook("GPSSystem/Tick", kGpsSystemTickRva, reinterpret_cast<void*>(&DetourGpsSystemTick),
reinterpret_cast<void**>(&gOriginalGpsSystemTick)); reinterpret_cast<void**>(&gOriginalGpsSystemTick));
AttachProbeHook("JournalManager::TrackEntry impl", kJournalTrackEntryImplRva, AttachProbeHook("JournalManager::TrackEntry impl", kJournalTrackEntryImplRva,
reinterpret_cast<void*>(&DetourJournalTrackEntry), reinterpret_cast<void*>(&DetourJournalTrackEntry),
reinterpret_cast<void**>(&gOriginalJournalTrackEntry)); reinterpret_cast<void**>(&gOriginalJournalTrackEntry));
AttachProbeHook("JournalListener::Objective vt28", kJournalListenerObjectiveVt28Rva, if (kEnableVerboseJournalListenerHooks)
reinterpret_cast<void*>(&DetourJournalListenerObjectiveVt28), {
reinterpret_cast<void**>(&gOriginalJournalListenerObjectiveVt28)); AttachProbeHook("JournalListener::Objective vt28", kJournalListenerObjectiveVt28Rva,
AttachProbeHook("JournalListener::Objective vt30", kJournalListenerObjectiveVt30Rva, reinterpret_cast<void*>(&DetourJournalListenerObjectiveVt28),
reinterpret_cast<void*>(&DetourJournalListenerObjectiveVt30), reinterpret_cast<void**>(&gOriginalJournalListenerObjectiveVt28));
reinterpret_cast<void**>(&gOriginalJournalListenerObjectiveVt30)); AttachProbeHook("JournalListener::Objective vt30", kJournalListenerObjectiveVt30Rva,
AttachProbeHook("JournalListener::Route vt28", kJournalListenerRouteVt28Rva, reinterpret_cast<void*>(&DetourJournalListenerObjectiveVt30),
reinterpret_cast<void*>(&DetourJournalListenerRouteVt28), reinterpret_cast<void**>(&gOriginalJournalListenerObjectiveVt30));
reinterpret_cast<void**>(&gOriginalJournalListenerRouteVt28)); AttachProbeHook("JournalListener::Route vt28", kJournalListenerRouteVt28Rva,
AttachProbeHook("JournalListener::Route vt30", kJournalListenerRouteVt30Rva, reinterpret_cast<void*>(&DetourJournalListenerRouteVt28),
reinterpret_cast<void*>(&DetourJournalListenerRouteVt30), reinterpret_cast<void**>(&gOriginalJournalListenerRouteVt28));
reinterpret_cast<void**>(&gOriginalJournalListenerRouteVt30)); AttachProbeHook("JournalListener::Route vt30", kJournalListenerRouteVt30Rva,
AttachProbeHook("JournalListener::RouteAlt vt28", kJournalListenerRouteAltVt28Rva, reinterpret_cast<void*>(&DetourJournalListenerRouteVt30),
reinterpret_cast<void*>(&DetourJournalListenerRouteAltVt28), reinterpret_cast<void**>(&gOriginalJournalListenerRouteVt30));
reinterpret_cast<void**>(&gOriginalJournalListenerRouteAltVt28)); AttachProbeHook("JournalListener::RouteAlt vt28", kJournalListenerRouteAltVt28Rva,
AttachProbeHook("JournalListener::RouteAlt vt30", kJournalListenerRouteAltVt30Rva, reinterpret_cast<void*>(&DetourJournalListenerRouteAltVt28),
reinterpret_cast<void*>(&DetourJournalListenerRouteAltVt30), reinterpret_cast<void**>(&gOriginalJournalListenerRouteAltVt28));
reinterpret_cast<void**>(&gOriginalJournalListenerRouteAltVt30)); AttachProbeHook("JournalListener::RouteAlt vt30", kJournalListenerRouteAltVt30Rva,
AttachProbeHook("JournalListener::UI vt28", kJournalListenerUiVt28Rva, reinterpret_cast<void*>(&DetourJournalListenerRouteAltVt30),
reinterpret_cast<void*>(&DetourJournalListenerUiVt28), reinterpret_cast<void**>(&gOriginalJournalListenerRouteAltVt30));
reinterpret_cast<void**>(&gOriginalJournalListenerUiVt28)); AttachProbeHook("JournalListener::UI vt28", kJournalListenerUiVt28Rva,
AttachProbeHook("JournalListener::UI vt30", kJournalListenerUiVt30Rva, reinterpret_cast<void*>(&DetourJournalListenerUiVt28),
reinterpret_cast<void*>(&DetourJournalListenerUiVt30), reinterpret_cast<void**>(&gOriginalJournalListenerUiVt28));
reinterpret_cast<void**>(&gOriginalJournalListenerUiVt30)); AttachProbeHook("JournalListener::UI vt30", kJournalListenerUiVt30Rva,
AttachProbeHook("JournalListener::Tracker vt28", kJournalListenerTrackerVt28Rva, reinterpret_cast<void*>(&DetourJournalListenerUiVt30),
reinterpret_cast<void*>(&DetourJournalListenerTrackerVt28), reinterpret_cast<void**>(&gOriginalJournalListenerUiVt30));
reinterpret_cast<void**>(&gOriginalJournalListenerTrackerVt28)); AttachProbeHook("JournalListener::Tracker vt28", kJournalListenerTrackerVt28Rva,
reinterpret_cast<void*>(&DetourJournalListenerTrackerVt28),
reinterpret_cast<void**>(&gOriginalJournalListenerTrackerVt28));
}
AttachProbeHook("JournalRouteBridge::Update candidate", kJournalRouteBridgeRva, AttachProbeHook("JournalRouteBridge::Update candidate", kJournalRouteBridgeRva,
reinterpret_cast<void*>(&DetourJournalRouteBridge), reinterpret_cast<void*>(&DetourJournalRouteBridge),
reinterpret_cast<void**>(&gOriginalJournalRouteBridge)); reinterpret_cast<void**>(&gOriginalJournalRouteBridge));
@@ -2374,24 +2545,27 @@ RED4EXT_C_EXPORT bool RED4EXT_CALL Main(RED4ext::v1::PluginHandle aHandle, RED4e
AttachProbeHook("RouteBuildCandidate 0x5625a4", kRouteBuildCandidateRva, AttachProbeHook("RouteBuildCandidate 0x5625a4", kRouteBuildCandidateRva,
reinterpret_cast<void*>(&DetourRouteBuildCandidate), reinterpret_cast<void*>(&DetourRouteBuildCandidate),
reinterpret_cast<void**>(&gOriginalRouteBuildCandidate)); reinterpret_cast<void**>(&gOriginalRouteBuildCandidate));
AttachProbeHook("RouteObserver0::Activate slot48", kRouteObserver0ActivateRva, if (kEnableVerboseRouteObserverHooks)
reinterpret_cast<void*>(&DetourRouteObserver0Activate), {
reinterpret_cast<void**>(&gOriginalRouteObserver0Activate)); AttachProbeHook("RouteObserver0::Activate slot48", kRouteObserver0ActivateRva,
AttachProbeHook("RouteObserver1::Activate slot48", kRouteObserver1ActivateRva, reinterpret_cast<void*>(&DetourRouteObserver0Activate),
reinterpret_cast<void*>(&DetourRouteObserver1Activate), reinterpret_cast<void**>(&gOriginalRouteObserver0Activate));
reinterpret_cast<void**>(&gOriginalRouteObserver1Activate)); AttachProbeHook("RouteObserver1::Activate slot48", kRouteObserver1ActivateRva,
AttachProbeHook("RouteObserver23::Activate slot48", kRouteObserver23ActivateRva, reinterpret_cast<void*>(&DetourRouteObserver1Activate),
reinterpret_cast<void*>(&DetourRouteObserver23Activate), reinterpret_cast<void**>(&gOriginalRouteObserver1Activate));
reinterpret_cast<void**>(&gOriginalRouteObserver23Activate)); AttachProbeHook("RouteObserver23::Activate slot48", kRouteObserver23ActivateRva,
AttachProbeHook("RouteObserver0::Deactivate slot50", kRouteObserver0DeactivateRva, reinterpret_cast<void*>(&DetourRouteObserver23Activate),
reinterpret_cast<void*>(&DetourRouteObserver0Deactivate), reinterpret_cast<void**>(&gOriginalRouteObserver23Activate));
reinterpret_cast<void**>(&gOriginalRouteObserver0Deactivate)); AttachProbeHook("RouteObserver0::Deactivate slot50", kRouteObserver0DeactivateRva,
AttachProbeHook("RouteObserver1::Deactivate slot50", kRouteObserver1DeactivateRva, reinterpret_cast<void*>(&DetourRouteObserver0Deactivate),
reinterpret_cast<void*>(&DetourRouteObserver1Deactivate), reinterpret_cast<void**>(&gOriginalRouteObserver0Deactivate));
reinterpret_cast<void**>(&gOriginalRouteObserver1Deactivate)); AttachProbeHook("RouteObserver1::Deactivate slot50", kRouteObserver1DeactivateRva,
AttachProbeHook("RouteObserver23::Deactivate slot50", kRouteObserver23DeactivateRva, reinterpret_cast<void*>(&DetourRouteObserver1Deactivate),
reinterpret_cast<void*>(&DetourRouteObserver23Deactivate), reinterpret_cast<void**>(&gOriginalRouteObserver1Deactivate));
reinterpret_cast<void**>(&gOriginalRouteObserver23Deactivate)); AttachProbeHook("RouteObserver23::Deactivate slot50", kRouteObserver23DeactivateRva,
reinterpret_cast<void*>(&DetourRouteObserver23Deactivate),
reinterpret_cast<void**>(&gOriginalRouteObserver23Deactivate));
}
AttachProbeHook("FrameMappinPathWrapper", kFrameMappinPathWrapperRva, AttachProbeHook("FrameMappinPathWrapper", kFrameMappinPathWrapperRva,
reinterpret_cast<void*>(&DetourFrameMappinPathWrapper), reinterpret_cast<void*>(&DetourFrameMappinPathWrapper),
reinterpret_cast<void**>(&gOriginalFrameMappinPathWrapper)); reinterpret_cast<void**>(&gOriginalFrameMappinPathWrapper));
@@ -2436,29 +2610,36 @@ RED4EXT_C_EXPORT bool RED4EXT_CALL Main(RED4ext::v1::PluginHandle aHandle, RED4e
DetachProbeHook("GPSQuerySubmit 0x70a42c", kGpsQuerySubmitRva); DetachProbeHook("GPSQuerySubmit 0x70a42c", kGpsQuerySubmitRva);
DetachProbeHook("GPSQueryDispatch 0x70a570", kGpsQueryDispatchRva); DetachProbeHook("GPSQueryDispatch 0x70a570", kGpsQueryDispatchRva);
DetachProbeHook("GPSQueryResultFetch 0x7094b8", kGpsQueryResultFetchRva); DetachProbeHook("GPSQueryResultFetch 0x7094b8", kGpsQueryResultFetchRva);
DetachProbeHook("GPSQueryStatus 0xaa5704", kGpsQueryStatusRva);
DetachProbeHook("GPSSystem/Tick", kGpsSystemTickRva); DetachProbeHook("GPSSystem/Tick", kGpsSystemTickRva);
DetachProbeHook("JournalManager::TrackEntry impl", kJournalTrackEntryImplRva); DetachProbeHook("JournalManager::TrackEntry impl", kJournalTrackEntryImplRva);
DetachProbeHook("JournalListener::Objective vt28", kJournalListenerObjectiveVt28Rva); if (kEnableVerboseJournalListenerHooks)
DetachProbeHook("JournalListener::Objective vt30", kJournalListenerObjectiveVt30Rva); {
DetachProbeHook("JournalListener::Route vt28", kJournalListenerRouteVt28Rva); DetachProbeHook("JournalListener::Objective vt28", kJournalListenerObjectiveVt28Rva);
DetachProbeHook("JournalListener::Route vt30", kJournalListenerRouteVt30Rva); DetachProbeHook("JournalListener::Objective vt30", kJournalListenerObjectiveVt30Rva);
DetachProbeHook("JournalListener::RouteAlt vt28", kJournalListenerRouteAltVt28Rva); DetachProbeHook("JournalListener::Route vt28", kJournalListenerRouteVt28Rva);
DetachProbeHook("JournalListener::RouteAlt vt30", kJournalListenerRouteAltVt30Rva); DetachProbeHook("JournalListener::Route vt30", kJournalListenerRouteVt30Rva);
DetachProbeHook("JournalListener::UI vt28", kJournalListenerUiVt28Rva); DetachProbeHook("JournalListener::RouteAlt vt28", kJournalListenerRouteAltVt28Rva);
DetachProbeHook("JournalListener::UI vt30", kJournalListenerUiVt30Rva); DetachProbeHook("JournalListener::RouteAlt vt30", kJournalListenerRouteAltVt30Rva);
DetachProbeHook("JournalListener::Tracker vt28", kJournalListenerTrackerVt28Rva); DetachProbeHook("JournalListener::UI vt28", kJournalListenerUiVt28Rva);
DetachProbeHook("JournalListener::UI vt30", kJournalListenerUiVt30Rva);
DetachProbeHook("JournalListener::Tracker vt28", kJournalListenerTrackerVt28Rva);
}
DetachProbeHook("JournalRouteBridge::Update candidate", kJournalRouteBridgeRva); DetachProbeHook("JournalRouteBridge::Update candidate", kJournalRouteBridgeRva);
DetachProbeHook("MappinSystem::RouteEventEnqueue slot240", kMappinRouteEventEnqueueRva); DetachProbeHook("MappinSystem::RouteEventEnqueue slot240", kMappinRouteEventEnqueueRva);
DetachProbeHook("MappinRouteEvent::Handle", kMappinRouteEventHandlerRva); DetachProbeHook("MappinRouteEvent::Handle", kMappinRouteEventHandlerRva);
DetachProbeHook("MappinSystem::RouteActivate", kMappinRouteActivateRva); DetachProbeHook("MappinSystem::RouteActivate", kMappinRouteActivateRva);
DetachProbeHook("MappinSystem::RouteDeactivate", kMappinRouteDeactivateRva); DetachProbeHook("MappinSystem::RouteDeactivate", kMappinRouteDeactivateRva);
DetachProbeHook("RouteBuildCandidate 0x5625a4", kRouteBuildCandidateRva); DetachProbeHook("RouteBuildCandidate 0x5625a4", kRouteBuildCandidateRva);
DetachProbeHook("RouteObserver0::Activate slot48", kRouteObserver0ActivateRva); if (kEnableVerboseRouteObserverHooks)
DetachProbeHook("RouteObserver1::Activate slot48", kRouteObserver1ActivateRva); {
DetachProbeHook("RouteObserver23::Activate slot48", kRouteObserver23ActivateRva); DetachProbeHook("RouteObserver0::Activate slot48", kRouteObserver0ActivateRva);
DetachProbeHook("RouteObserver0::Deactivate slot50", kRouteObserver0DeactivateRva); DetachProbeHook("RouteObserver1::Activate slot48", kRouteObserver1ActivateRva);
DetachProbeHook("RouteObserver1::Deactivate slot50", kRouteObserver1DeactivateRva); DetachProbeHook("RouteObserver23::Activate slot48", kRouteObserver23ActivateRva);
DetachProbeHook("RouteObserver23::Deactivate slot50", kRouteObserver23DeactivateRva); DetachProbeHook("RouteObserver0::Deactivate slot50", kRouteObserver0DeactivateRva);
DetachProbeHook("RouteObserver1::Deactivate slot50", kRouteObserver1DeactivateRva);
DetachProbeHook("RouteObserver23::Deactivate slot50", kRouteObserver23DeactivateRva);
}
DetachProbeHook("FrameMappinPathWrapper", kFrameMappinPathWrapperRva); DetachProbeHook("FrameMappinPathWrapper", kFrameMappinPathWrapperRva);
DetachProbeHook("FrameMappinPathCore", kFrameMappinPathCoreRva); DetachProbeHook("FrameMappinPathCore", kFrameMappinPathCoreRva);
DetachProbeHook("SetSelectedMappinWrapper", kSetSelectedMappinWrapperRva); DetachProbeHook("SetSelectedMappinWrapper", kSetSelectedMappinWrapperRva);