Probe world map mappin routes

This commit is contained in:
2026-06-19 23:33:12 -05:00
parent 79b45e40f8
commit d6c80ce0e1
3 changed files with 399 additions and 12 deletions
+13 -4
View File
@@ -1,6 +1,7 @@
# RED4ext logging shim # RED4ext logging shim
`EdgeWeightGPS` is a minimal RED4ext plugin used to verify a native logging foothold without changing gameplay data. `EdgeWeightGPS` is a RED4ext plugin used to probe native GPS/mappin code paths
without changing gameplay data.
It writes `EdgeWeightGPS.log` beside the installed DLL: It writes `EdgeWeightGPS.log` beside the installed DLL:
@@ -12,11 +13,19 @@ Current behavior:
- Logs plugin load/unload. - Logs plugin load/unload.
- Logs the RED4ext plugin handle and SDK pointer value passed to `Main`. - Logs the RED4ext plugin handle and SDK pointer value passed to `Main`.
- Does not call game RTTI or register script functions. - Registers Running game-state callbacks so route tests can be timestamped.
- Hooks selected native wrappers and cores around `GPSSystem`, mappin tracking,
world-map mappin selection, and map path framing.
- Resolves the native mappin system when one of those paths fires, logs relevant
vtable slot addresses, and temporarily hooks the route-adjacent slots.
Planned next step: Current route-probe focus:
- Build a richer RTTI/hooking variant with an MSVC-compatible Windows toolchain or a narrower hand-written SDK surface. The upstream RED4ext SDK headers build under MinGW for loader-only use, but the full SDK/static library currently pulls in generated native/GPU structures with MSVC layout assumptions. - `FrameMappinPath` wrapper/core: `0x27c4314`, `0x27bc1ec`
- `SetSelectedMappin` wrappers/core: `0x27c4a38`, `0x27c4944`,
`0x27c49c4`, `0x27c1684`
- `TrackCustomPositionMappin` wrapper/core: `0x27c4aac`, `0x27c2318`
- mappin-system slots `0x1f0`, `0x280`, and `0x2f0`
Build and install from the Fedora toolbox: Build and install from the Fedora toolbox:
+37 -8
View File
@@ -73,7 +73,7 @@ selection.
## Mappin Tracking Handoff ## Mappin Tracking Handoff
The current native lead is the script/native mappin tracking path: The first native lead was the script/native mappin tracking path:
```text ```text
TrackMappin string rva: 0x2e82c30 TrackMappin string rva: 0x2e82c30
@@ -98,16 +98,45 @@ the supplied mappin handle is null:
- non-null tracked mappin: call resolved system vtable slot `0x220` - non-null tracked mappin: call resolved system vtable slot `0x220`
- null tracked mappin: call resolved system vtable slot `0x228` - null tracked mappin: call resolved system vtable slot `0x228`
That looks exactly like "set tracked mappin" versus "clear tracked mappin". The That looks exactly like "set tracked mappin" versus "clear tracked mappin".
installed RED4ext probe now resolves this system at runtime, logs the concrete However, a clean live test disproved it as the normal world-map route plotting
vtable addresses for slots `0x220`, `0x228`, `0x250`, `0x2e0`, `0x368`, and path: `TrackMappin`, `TrackMappinCore`, and
`0x3a8`, and attaches temporary hooks to slots `0x220` and `0x228`. The next `SetMappinTrackingAlternative` did not fire while plotting three map routes.
in-game route-plotting run should therefore give directly disassemblable RVAs
for the concrete mappin-system methods that receive the tracked destination.
`SetMappinTrackingAlternative` parses two script arguments and calls vtable slot `SetMappinTrackingAlternative` parses two script arguments and calls vtable slot
`0x418` on its receiver. It is probably related to alternate tracking behavior, `0x418` on its receiver. It is probably related to alternate tracking behavior,
but static disassembly has not yet shown it to be the main route planner. but static disassembly and live logging have not shown it to be the main route
planner.
## World-Map Mappin Selection Lead
The next native lead is the world-map mappin controller block around
`0x1427c4314`. These functions are still mappin-facing, but they are closer to
selection, framing, and custom-position route display than the script helper
above:
```text
FrameMappinPath wrapper rva: 0x27c4314
FrameMappinPath core rva: 0x27bc1ec
SetSelectedMappin wrapper rva: 0x27c4a38
SetSelectedMappin by-id wrapper rva: 0x27c4944
SetSelectedMappin by-position wrapper rva: 0x27c49c4
SetSelectedMappin core rva: 0x27c1684
TrackCustomPositionMappin wrapper rva: 0x27c4aac
TrackCustomPositionMappin core rva: 0x27c2318
UntrackCustomPositionMappin wrapper rva: 0x27c4ba0
Mappin system resolver rva: 0x02bb840
```
`FrameMappinPath` calls the resolved mappin-system vtable slot `0x280`.
`TrackCustomPositionMappin` calls slot `0x2f0` to create a custom-position
mappin/route handle and slot `0x1f0` to update an existing one. Those calls are
currently the most route-like native behavior found in static disassembly.
The installed RED4ext probe now logs the wrappers and cores listed above. When
one of them can resolve the mappin system, it also logs concrete vtable RVAs for
slots `0x1f0`, `0x220`, `0x228`, `0x250`, `0x280`, `0x2e0`, `0x2f0`, `0x368`,
and `0x3a8`, then attaches temporary hooks to the route-adjacent slots.
## The High-Level Shape ## The High-Level Shape
+349
View File
@@ -92,12 +92,24 @@ namespace
constexpr uint32_t kGameStateRunning = 2; constexpr uint32_t kGameStateRunning = 2;
constexpr uintptr_t kGpsSystemTickRva = 0x0E6B62C; constexpr uintptr_t kGpsSystemTickRva = 0x0E6B62C;
constexpr uintptr_t kMappinSystemResolverRva = 0x02BB840; constexpr uintptr_t kMappinSystemResolverRva = 0x02BB840;
constexpr uintptr_t kFrameMappinPathWrapperRva = 0x27C4314;
constexpr uintptr_t kFrameMappinPathCoreRva = 0x27BC1EC;
constexpr uintptr_t kSetSelectedMappinWrapperRva = 0x27C4A38;
constexpr uintptr_t kSetSelectedMappinByIdWrapperRva = 0x27C4944;
constexpr uintptr_t kSetSelectedMappinByPositionWrapperRva = 0x27C49C4;
constexpr uintptr_t kSetSelectedMappinCoreRva = 0x27C1684;
constexpr uintptr_t kTrackCustomPositionMappinWrapperRva = 0x27C4AAC;
constexpr uintptr_t kTrackCustomPositionMappinCoreRva = 0x27C2318;
constexpr uintptr_t kUntrackCustomPositionMappinWrapperRva = 0x27C4BA0;
constexpr uintptr_t kTrackMappinWrapperRva = 0x27C4AB4; constexpr uintptr_t kTrackMappinWrapperRva = 0x27C4AB4;
constexpr uintptr_t kTrackMappinCoreRva = 0x27C11D0; constexpr uintptr_t kTrackMappinCoreRva = 0x27C11D0;
constexpr uintptr_t kSetMappinTrackingAlternativeWrapperRva = 0x1246794; constexpr uintptr_t kSetMappinTrackingAlternativeWrapperRva = 0x1246794;
constexpr uintptr_t kMappinUpdateCustomPositionSlotOffset = 0x1F0;
constexpr uintptr_t kMappinSetTrackedSlotOffset = 0x220; constexpr uintptr_t kMappinSetTrackedSlotOffset = 0x220;
constexpr uintptr_t kMappinClearTrackedSlotOffset = 0x228; constexpr uintptr_t kMappinClearTrackedSlotOffset = 0x228;
constexpr uintptr_t kMappinFramePathSlotOffset = 0x280;
constexpr uintptr_t kMappinPositionQuerySlotOffset = 0x2E0; constexpr uintptr_t kMappinPositionQuerySlotOffset = 0x2E0;
constexpr uintptr_t kMappinCreateCustomPositionSlotOffset = 0x2F0;
constexpr uintptr_t kMappinReleaseQuerySlotOffset = 0x368; constexpr uintptr_t kMappinReleaseQuerySlotOffset = 0x368;
constexpr uintptr_t kMappinActiveRouteSlotOffset = 0x3A8; constexpr uintptr_t kMappinActiveRouteSlotOffset = 0x3A8;
@@ -108,20 +120,35 @@ const RED4ext::v1::Sdk* gSdk = nullptr;
uint32_t gUpdateLogCount = 0; uint32_t gUpdateLogCount = 0;
bool gScannedExecutable = false; bool gScannedExecutable = false;
uint32_t gGpsTickLogCount = 0; uint32_t gGpsTickLogCount = 0;
uint32_t gFrameMappinPathWrapperLogCount = 0;
uint32_t gFrameMappinPathCoreLogCount = 0;
uint32_t gSetSelectedMappinWrapperLogCount = 0;
uint32_t gSetSelectedMappinByIdWrapperLogCount = 0;
uint32_t gSetSelectedMappinByPositionWrapperLogCount = 0;
uint32_t gSetSelectedMappinCoreLogCount = 0;
uint32_t gTrackCustomPositionMappinWrapperLogCount = 0;
uint32_t gTrackCustomPositionMappinCoreLogCount = 0;
uint32_t gUntrackCustomPositionMappinWrapperLogCount = 0;
uint32_t gTrackMappinWrapperLogCount = 0; uint32_t gTrackMappinWrapperLogCount = 0;
uint32_t gTrackMappinCoreLogCount = 0; uint32_t gTrackMappinCoreLogCount = 0;
uint32_t gSetMappinTrackingAlternativeLogCount = 0; uint32_t gSetMappinTrackingAlternativeLogCount = 0;
uint32_t gMappinSystemSlotLogCount = 0; uint32_t gMappinSystemSlotLogCount = 0;
uint32_t gMappinUpdateCustomPositionLogCount = 0;
uint32_t gMappinSetTrackedLogCount = 0; uint32_t gMappinSetTrackedLogCount = 0;
uint32_t gMappinClearTrackedLogCount = 0; uint32_t gMappinClearTrackedLogCount = 0;
uint32_t gMappinFramePathLogCount = 0;
uint32_t gMappinPositionQueryLogCount = 0; uint32_t gMappinPositionQueryLogCount = 0;
uint32_t gMappinCreateCustomPositionLogCount = 0;
uint32_t gMappinReleaseQueryLogCount = 0; uint32_t gMappinReleaseQueryLogCount = 0;
uint32_t gMappinActiveRouteLogCount = 0; uint32_t gMappinActiveRouteLogCount = 0;
uint64_t gLogStartTick = 0; uint64_t gLogStartTick = 0;
uint64_t gLogFrequency = 0; uint64_t gLogFrequency = 0;
void* gMappinSetTrackedTarget = nullptr; void* gMappinSetTrackedTarget = nullptr;
void* gMappinClearTrackedTarget = nullptr; void* gMappinClearTrackedTarget = nullptr;
void* gMappinUpdateCustomPositionTarget = nullptr;
void* gMappinFramePathTarget = nullptr;
void* gMappinPositionQueryTarget = nullptr; void* gMappinPositionQueryTarget = nullptr;
void* gMappinCreateCustomPositionTarget = nullptr;
void* gMappinReleaseQueryTarget = nullptr; void* gMappinReleaseQueryTarget = nullptr;
void* gMappinActiveRouteTarget = nullptr; void* gMappinActiveRouteTarget = nullptr;
bool gMappinSlotHookAttachAttempted = false; bool gMappinSlotHookAttachAttempted = false;
@@ -129,19 +156,37 @@ bool gMappinSlotHookAttachAttempted = false;
using ProbeFunc = void (*)(void* aThis, void* a2, void* a3, void* a4); using ProbeFunc = void (*)(void* aThis, void* a2, void* a3, void* a4);
using ScriptNativeVoidFunc = void (*)(void* aThis, void* aStack, void* aResult); using ScriptNativeVoidFunc = void (*)(void* aThis, void* aStack, void* aResult);
using MappinSystemResolverFunc = void* (*)(void* aThis); using MappinSystemResolverFunc = void* (*)(void* aThis);
using FrameMappinPathCoreFunc = void (*)(void* aThis, uint32_t aPathKind, void* a3, void* aPathRect);
using SetSelectedMappinCoreFunc = void (*)(void* aThis, void* aMappinHandle);
using TrackCustomPositionMappinCoreFunc = void (*)(void* aThis);
using TrackMappinCoreFunc = void (*)(void* aThis, void* aMappinHandle); using TrackMappinCoreFunc = void (*)(void* aThis, void* aMappinHandle);
using MappinUpdateCustomPositionFunc = void (*)(void* aSystem, void* aHandle, void* aPositionData);
using MappinSetTrackedFunc = void (*)(void* aSystem, void* aMappinId); using MappinSetTrackedFunc = void (*)(void* aSystem, void* aMappinId);
using MappinClearTrackedFunc = void (*)(void* aSystem); using MappinClearTrackedFunc = void (*)(void* aSystem);
using MappinFramePathFunc = void (*)(void* aSystem, uint32_t aPathKind, void* aResult);
using MappinPositionQueryFunc = void* (*)(void* aSystem, void* a2, void* a3, void* a4, void* a5); using MappinPositionQueryFunc = void* (*)(void* aSystem, void* a2, void* a3, void* a4, void* a5);
using MappinCreateCustomPositionFunc = void* (*)(void* aSystem, void* aName, void* aParams, void* aPositionData);
using MappinReleaseQueryFunc = void (*)(void* aSystem, void* aHandle); using MappinReleaseQueryFunc = void (*)(void* aSystem, void* aHandle);
using MappinActiveRouteFunc = void* (*)(void* aSystem); using MappinActiveRouteFunc = void* (*)(void* aSystem);
ProbeFunc gOriginalGpsSystemTick = nullptr; ProbeFunc gOriginalGpsSystemTick = nullptr;
ScriptNativeVoidFunc gOriginalFrameMappinPathWrapper = nullptr;
FrameMappinPathCoreFunc gOriginalFrameMappinPathCore = nullptr;
ScriptNativeVoidFunc gOriginalSetSelectedMappinWrapper = nullptr;
ScriptNativeVoidFunc gOriginalSetSelectedMappinByIdWrapper = nullptr;
ScriptNativeVoidFunc gOriginalSetSelectedMappinByPositionWrapper = nullptr;
SetSelectedMappinCoreFunc gOriginalSetSelectedMappinCore = nullptr;
ScriptNativeVoidFunc gOriginalTrackCustomPositionMappinWrapper = nullptr;
TrackCustomPositionMappinCoreFunc gOriginalTrackCustomPositionMappinCore = nullptr;
ScriptNativeVoidFunc gOriginalUntrackCustomPositionMappinWrapper = nullptr;
ScriptNativeVoidFunc gOriginalTrackMappinWrapper = nullptr; ScriptNativeVoidFunc gOriginalTrackMappinWrapper = nullptr;
TrackMappinCoreFunc gOriginalTrackMappinCore = nullptr; TrackMappinCoreFunc gOriginalTrackMappinCore = nullptr;
ScriptNativeVoidFunc gOriginalSetMappinTrackingAlternativeWrapper = nullptr; ScriptNativeVoidFunc gOriginalSetMappinTrackingAlternativeWrapper = nullptr;
MappinUpdateCustomPositionFunc gOriginalMappinUpdateCustomPosition = nullptr;
MappinSetTrackedFunc gOriginalMappinSetTracked = nullptr; MappinSetTrackedFunc gOriginalMappinSetTracked = nullptr;
MappinClearTrackedFunc gOriginalMappinClearTracked = nullptr; MappinClearTrackedFunc gOriginalMappinClearTracked = nullptr;
MappinFramePathFunc gOriginalMappinFramePath = nullptr;
MappinPositionQueryFunc gOriginalMappinPositionQuery = nullptr; MappinPositionQueryFunc gOriginalMappinPositionQuery = nullptr;
MappinCreateCustomPositionFunc gOriginalMappinCreateCustomPosition = nullptr;
MappinReleaseQueryFunc gOriginalMappinReleaseQuery = nullptr; MappinReleaseQueryFunc gOriginalMappinReleaseQuery = nullptr;
MappinActiveRouteFunc gOriginalMappinActiveRoute = nullptr; MappinActiveRouteFunc gOriginalMappinActiveRoute = nullptr;
@@ -270,6 +315,32 @@ void LogScriptNativeCall(const char* aName, uint32_t aCount, void* aThis, void*
LogRed4ext(line.str()); LogRed4ext(line.str());
} }
void LogFrameMappinPathCoreCall(uint32_t aCount, void* aThis, uint32_t aPathKind, void* a3, void* aPathRect)
{
std::ostringstream line;
line << "hook FrameMappinPathCore call=" << aCount << " this=" << aThis << " pathKind=" << aPathKind
<< " a3=" << a3 << " pathRect=" << aPathRect;
AppendReturnRva(line, __builtin_return_address(0));
LogRed4ext(line.str());
}
void LogSetSelectedMappinCoreCall(uint32_t aCount, void* aThis, void* aMappinHandle)
{
std::ostringstream line;
line << "hook SetSelectedMappinCore call=" << aCount << " this=" << aThis
<< " mappinHandle=" << aMappinHandle;
AppendReturnRva(line, __builtin_return_address(0));
LogRed4ext(line.str());
}
void LogTrackCustomPositionMappinCoreCall(uint32_t aCount, void* aThis)
{
std::ostringstream line;
line << "hook TrackCustomPositionMappinCore call=" << aCount << " this=" << aThis;
AppendReturnRva(line, __builtin_return_address(0));
LogRed4ext(line.str());
}
void LogTrackMappinCoreCall(uint32_t aCount, void* aThis, void* aMappinHandle) void LogTrackMappinCoreCall(uint32_t aCount, void* aThis, void* aMappinHandle)
{ {
std::ostringstream line; std::ostringstream line;
@@ -293,10 +364,13 @@ void LogMappinSystemSlots(uint32_t aCount, void* aSystem, void* aVtable)
line << "mappin-system slots call=" << aCount; line << "mappin-system slots call=" << aCount;
AppendPointerWithRva(line, "system", aSystem); AppendPointerWithRva(line, "system", aSystem);
AppendPointerWithRva(line, "vtable", aVtable); AppendPointerWithRva(line, "vtable", aVtable);
AppendPointerWithRva(line, "slot1f0", readSlot(kMappinUpdateCustomPositionSlotOffset));
AppendPointerWithRva(line, "slot220", readSlot(kMappinSetTrackedSlotOffset)); AppendPointerWithRva(line, "slot220", readSlot(kMappinSetTrackedSlotOffset));
AppendPointerWithRva(line, "slot228", readSlot(kMappinClearTrackedSlotOffset)); AppendPointerWithRva(line, "slot228", readSlot(kMappinClearTrackedSlotOffset));
AppendPointerWithRva(line, "slot250", readSlot(0x250)); AppendPointerWithRva(line, "slot250", readSlot(0x250));
AppendPointerWithRva(line, "slot280", readSlot(kMappinFramePathSlotOffset));
AppendPointerWithRva(line, "slot2e0", readSlot(kMappinPositionQuerySlotOffset)); AppendPointerWithRva(line, "slot2e0", readSlot(kMappinPositionQuerySlotOffset));
AppendPointerWithRva(line, "slot2f0", readSlot(kMappinCreateCustomPositionSlotOffset));
AppendPointerWithRva(line, "slot368", readSlot(kMappinReleaseQuerySlotOffset)); AppendPointerWithRva(line, "slot368", readSlot(kMappinReleaseQuerySlotOffset));
AppendPointerWithRva(line, "slot3a8", readSlot(kMappinActiveRouteSlotOffset)); AppendPointerWithRva(line, "slot3a8", readSlot(kMappinActiveRouteSlotOffset));
LogRed4ext(line.str()); LogRed4ext(line.str());
@@ -476,6 +550,154 @@ void DetourGpsSystemTick(void* aThis, void* a2, void* a3, void* a4)
} }
} }
void DetourFrameMappinPathWrapper(void* aThis, void* aStack, void* aResult)
{
if (gFrameMappinPathWrapperLogCount < 64)
{
LogScriptNativeCall("FrameMappinPathWrapper", gFrameMappinPathWrapperLogCount, aThis, aStack, aResult);
++gFrameMappinPathWrapperLogCount;
}
InspectAndHookMappinSystem(aThis);
if (gOriginalFrameMappinPathWrapper)
{
gOriginalFrameMappinPathWrapper(aThis, aStack, aResult);
}
}
void DetourFrameMappinPathCore(void* aThis, uint32_t aPathKind, void* a3, void* aPathRect)
{
if (gFrameMappinPathCoreLogCount < 64)
{
LogFrameMappinPathCoreCall(gFrameMappinPathCoreLogCount, aThis, aPathKind, a3, aPathRect);
++gFrameMappinPathCoreLogCount;
}
InspectAndHookMappinSystem(aThis);
if (gOriginalFrameMappinPathCore)
{
gOriginalFrameMappinPathCore(aThis, aPathKind, a3, aPathRect);
}
}
void DetourSetSelectedMappinWrapper(void* aThis, void* aStack, void* aResult)
{
if (gSetSelectedMappinWrapperLogCount < 64)
{
LogScriptNativeCall("SetSelectedMappinWrapper", gSetSelectedMappinWrapperLogCount, aThis, aStack, aResult);
++gSetSelectedMappinWrapperLogCount;
}
InspectAndHookMappinSystem(aThis);
if (gOriginalSetSelectedMappinWrapper)
{
gOriginalSetSelectedMappinWrapper(aThis, aStack, aResult);
}
}
void DetourSetSelectedMappinByIdWrapper(void* aThis, void* aStack, void* aResult)
{
if (gSetSelectedMappinByIdWrapperLogCount < 64)
{
LogScriptNativeCall("SetSelectedMappinByIdWrapper", gSetSelectedMappinByIdWrapperLogCount, aThis, aStack,
aResult);
++gSetSelectedMappinByIdWrapperLogCount;
}
InspectAndHookMappinSystem(aThis);
if (gOriginalSetSelectedMappinByIdWrapper)
{
gOriginalSetSelectedMappinByIdWrapper(aThis, aStack, aResult);
}
}
void DetourSetSelectedMappinByPositionWrapper(void* aThis, void* aStack, void* aResult)
{
if (gSetSelectedMappinByPositionWrapperLogCount < 64)
{
LogScriptNativeCall("SetSelectedMappinByPositionWrapper", gSetSelectedMappinByPositionWrapperLogCount, aThis,
aStack, aResult);
++gSetSelectedMappinByPositionWrapperLogCount;
}
InspectAndHookMappinSystem(aThis);
if (gOriginalSetSelectedMappinByPositionWrapper)
{
gOriginalSetSelectedMappinByPositionWrapper(aThis, aStack, aResult);
}
}
void DetourSetSelectedMappinCore(void* aThis, void* aMappinHandle)
{
if (gSetSelectedMappinCoreLogCount < 64)
{
LogSetSelectedMappinCoreCall(gSetSelectedMappinCoreLogCount, aThis, aMappinHandle);
++gSetSelectedMappinCoreLogCount;
}
InspectAndHookMappinSystem(aThis);
if (gOriginalSetSelectedMappinCore)
{
gOriginalSetSelectedMappinCore(aThis, aMappinHandle);
}
}
void DetourTrackCustomPositionMappinWrapper(void* aThis, void* aStack, void* aResult)
{
if (gTrackCustomPositionMappinWrapperLogCount < 64)
{
LogScriptNativeCall("TrackCustomPositionMappinWrapper", gTrackCustomPositionMappinWrapperLogCount, aThis,
aStack, aResult);
++gTrackCustomPositionMappinWrapperLogCount;
}
InspectAndHookMappinSystem(aThis);
if (gOriginalTrackCustomPositionMappinWrapper)
{
gOriginalTrackCustomPositionMappinWrapper(aThis, aStack, aResult);
}
}
void DetourTrackCustomPositionMappinCore(void* aThis)
{
if (gTrackCustomPositionMappinCoreLogCount < 64)
{
LogTrackCustomPositionMappinCoreCall(gTrackCustomPositionMappinCoreLogCount, aThis);
++gTrackCustomPositionMappinCoreLogCount;
}
InspectAndHookMappinSystem(aThis);
if (gOriginalTrackCustomPositionMappinCore)
{
gOriginalTrackCustomPositionMappinCore(aThis);
}
}
void DetourUntrackCustomPositionMappinWrapper(void* aThis, void* aStack, void* aResult)
{
if (gUntrackCustomPositionMappinWrapperLogCount < 64)
{
LogScriptNativeCall("UntrackCustomPositionMappinWrapper", gUntrackCustomPositionMappinWrapperLogCount, aThis,
aStack, aResult);
++gUntrackCustomPositionMappinWrapperLogCount;
}
InspectAndHookMappinSystem(aThis);
if (gOriginalUntrackCustomPositionMappinWrapper)
{
gOriginalUntrackCustomPositionMappinWrapper(aThis, aStack, aResult);
}
}
void DetourTrackMappinWrapper(void* aThis, void* aStack, void* aResult) void DetourTrackMappinWrapper(void* aThis, void* aStack, void* aResult)
{ {
if (gTrackMappinWrapperLogCount < 64) if (gTrackMappinWrapperLogCount < 64)
@@ -521,6 +743,26 @@ void DetourSetMappinTrackingAlternativeWrapper(void* aThis, void* aStack, void*
} }
} }
void DetourMappinUpdateCustomPosition(void* aSystem, void* aHandle, void* aPositionData)
{
if (gMappinUpdateCustomPositionLogCount < 32)
{
std::ostringstream line;
line << "hook MappinSystem::UpdateCustomPosition slot1f0 call=" << gMappinUpdateCustomPositionLogCount;
AppendPointerWithRva(line, "system", aSystem);
AppendPointerWithRva(line, "handle", aHandle);
AppendPointerWithRva(line, "positionData", aPositionData);
AppendReturnRva(line, __builtin_return_address(0));
LogRed4ext(line.str());
++gMappinUpdateCustomPositionLogCount;
}
if (gOriginalMappinUpdateCustomPosition)
{
gOriginalMappinUpdateCustomPosition(aSystem, aHandle, aPositionData);
}
}
void DetourMappinSetTracked(void* aSystem, void* aMappinId) void DetourMappinSetTracked(void* aSystem, void* aMappinId)
{ {
if (gMappinSetTrackedLogCount < 64) if (gMappinSetTrackedLogCount < 64)
@@ -558,6 +800,26 @@ void DetourMappinClearTracked(void* aSystem)
} }
} }
void DetourMappinFramePath(void* aSystem, uint32_t aPathKind, void* aResult)
{
if (gMappinFramePathLogCount < 32)
{
std::ostringstream line;
line << "hook MappinSystem::FramePath slot280 call=" << gMappinFramePathLogCount
<< " pathKind=" << aPathKind;
AppendPointerWithRva(line, "system", aSystem);
AppendPointerWithRva(line, "result", aResult);
AppendReturnRva(line, __builtin_return_address(0));
LogRed4ext(line.str());
++gMappinFramePathLogCount;
}
if (gOriginalMappinFramePath)
{
gOriginalMappinFramePath(aSystem, aPathKind, aResult);
}
}
void* DetourMappinPositionQuery(void* aSystem, void* a2, void* a3, void* a4, void* a5) void* DetourMappinPositionQuery(void* aSystem, void* a2, void* a3, void* a4, void* a5)
{ {
const auto shouldLog = gMappinPositionQueryLogCount < 32; const auto shouldLog = gMappinPositionQueryLogCount < 32;
@@ -592,6 +854,39 @@ void* DetourMappinPositionQuery(void* aSystem, void* a2, void* a3, void* a4, voi
return result; return result;
} }
void* DetourMappinCreateCustomPosition(void* aSystem, void* aName, void* aParams, void* aPositionData)
{
const auto shouldLog = gMappinCreateCustomPositionLogCount < 32;
if (shouldLog)
{
std::ostringstream line;
line << "hook MappinSystem::CreateCustomPosition slot2f0 call=" << gMappinCreateCustomPositionLogCount;
AppendPointerWithRva(line, "system", aSystem);
AppendPointerWithRva(line, "name", aName);
AppendPointerWithRva(line, "params", aParams);
AppendPointerWithRva(line, "positionData", aPositionData);
AppendReturnRva(line, __builtin_return_address(0));
LogRed4ext(line.str());
++gMappinCreateCustomPositionLogCount;
}
void* result = nullptr;
if (gOriginalMappinCreateCustomPosition)
{
result = gOriginalMappinCreateCustomPosition(aSystem, aName, aParams, aPositionData);
}
if (shouldLog)
{
std::ostringstream line;
line << "hook MappinSystem::CreateCustomPosition slot2f0 result";
AppendPointerWithRva(line, "value", result);
LogRed4ext(line.str());
}
return result;
}
void DetourMappinReleaseQuery(void* aSystem, void* aHandle) void DetourMappinReleaseQuery(void* aSystem, void* aHandle)
{ {
if (gMappinReleaseQueryLogCount < 32) if (gMappinReleaseQueryLogCount < 32)
@@ -733,26 +1028,41 @@ void InspectAndHookMappinSystem(void* aThis)
} }
gMappinSlotHookAttachAttempted = true; gMappinSlotHookAttachAttempted = true;
gMappinUpdateCustomPositionTarget =
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(vtable) + kMappinUpdateCustomPositionSlotOffset);
gMappinSetTrackedTarget = gMappinSetTrackedTarget =
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(vtable) + kMappinSetTrackedSlotOffset); *reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(vtable) + kMappinSetTrackedSlotOffset);
gMappinClearTrackedTarget = gMappinClearTrackedTarget =
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(vtable) + kMappinClearTrackedSlotOffset); *reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(vtable) + kMappinClearTrackedSlotOffset);
gMappinFramePathTarget =
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(vtable) + kMappinFramePathSlotOffset);
gMappinPositionQueryTarget = gMappinPositionQueryTarget =
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(vtable) + kMappinPositionQuerySlotOffset); *reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(vtable) + kMappinPositionQuerySlotOffset);
gMappinCreateCustomPositionTarget =
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(vtable) + kMappinCreateCustomPositionSlotOffset);
gMappinReleaseQueryTarget = gMappinReleaseQueryTarget =
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(vtable) + kMappinReleaseQuerySlotOffset); *reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(vtable) + kMappinReleaseQuerySlotOffset);
gMappinActiveRouteTarget = gMappinActiveRouteTarget =
*reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(vtable) + kMappinActiveRouteSlotOffset); *reinterpret_cast<void**>(reinterpret_cast<uintptr_t>(vtable) + kMappinActiveRouteSlotOffset);
AttachAbsoluteHook("MappinSystem::UpdateCustomPosition slot1f0", gMappinUpdateCustomPositionTarget,
reinterpret_cast<void*>(&DetourMappinUpdateCustomPosition),
reinterpret_cast<void**>(&gOriginalMappinUpdateCustomPosition));
AttachAbsoluteHook("MappinSystem::SetTracked slot220", gMappinSetTrackedTarget, AttachAbsoluteHook("MappinSystem::SetTracked slot220", gMappinSetTrackedTarget,
reinterpret_cast<void*>(&DetourMappinSetTracked), reinterpret_cast<void*>(&DetourMappinSetTracked),
reinterpret_cast<void**>(&gOriginalMappinSetTracked)); reinterpret_cast<void**>(&gOriginalMappinSetTracked));
AttachAbsoluteHook("MappinSystem::ClearTracked slot228", gMappinClearTrackedTarget, AttachAbsoluteHook("MappinSystem::ClearTracked slot228", gMappinClearTrackedTarget,
reinterpret_cast<void*>(&DetourMappinClearTracked), reinterpret_cast<void*>(&DetourMappinClearTracked),
reinterpret_cast<void**>(&gOriginalMappinClearTracked)); reinterpret_cast<void**>(&gOriginalMappinClearTracked));
AttachAbsoluteHook("MappinSystem::FramePath slot280", gMappinFramePathTarget,
reinterpret_cast<void*>(&DetourMappinFramePath),
reinterpret_cast<void**>(&gOriginalMappinFramePath));
AttachAbsoluteHook("MappinSystem::PositionQuery slot2e0", gMappinPositionQueryTarget, AttachAbsoluteHook("MappinSystem::PositionQuery slot2e0", gMappinPositionQueryTarget,
reinterpret_cast<void*>(&DetourMappinPositionQuery), reinterpret_cast<void*>(&DetourMappinPositionQuery),
reinterpret_cast<void**>(&gOriginalMappinPositionQuery)); reinterpret_cast<void**>(&gOriginalMappinPositionQuery));
AttachAbsoluteHook("MappinSystem::CreateCustomPosition slot2f0", gMappinCreateCustomPositionTarget,
reinterpret_cast<void*>(&DetourMappinCreateCustomPosition),
reinterpret_cast<void**>(&gOriginalMappinCreateCustomPosition));
AttachAbsoluteHook("MappinSystem::ReleaseQuery slot368", gMappinReleaseQueryTarget, AttachAbsoluteHook("MappinSystem::ReleaseQuery slot368", gMappinReleaseQueryTarget,
reinterpret_cast<void*>(&DetourMappinReleaseQuery), reinterpret_cast<void*>(&DetourMappinReleaseQuery),
reinterpret_cast<void**>(&gOriginalMappinReleaseQuery)); reinterpret_cast<void**>(&gOriginalMappinReleaseQuery));
@@ -834,6 +1144,33 @@ RED4EXT_C_EXPORT bool RED4EXT_CALL Main(RED4ext::v1::PluginHandle aHandle, RED4e
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("FrameMappinPathWrapper", kFrameMappinPathWrapperRva,
reinterpret_cast<void*>(&DetourFrameMappinPathWrapper),
reinterpret_cast<void**>(&gOriginalFrameMappinPathWrapper));
AttachProbeHook("FrameMappinPathCore", kFrameMappinPathCoreRva,
reinterpret_cast<void*>(&DetourFrameMappinPathCore),
reinterpret_cast<void**>(&gOriginalFrameMappinPathCore));
AttachProbeHook("SetSelectedMappinWrapper", kSetSelectedMappinWrapperRva,
reinterpret_cast<void*>(&DetourSetSelectedMappinWrapper),
reinterpret_cast<void**>(&gOriginalSetSelectedMappinWrapper));
AttachProbeHook("SetSelectedMappinByIdWrapper", kSetSelectedMappinByIdWrapperRva,
reinterpret_cast<void*>(&DetourSetSelectedMappinByIdWrapper),
reinterpret_cast<void**>(&gOriginalSetSelectedMappinByIdWrapper));
AttachProbeHook("SetSelectedMappinByPositionWrapper", kSetSelectedMappinByPositionWrapperRva,
reinterpret_cast<void*>(&DetourSetSelectedMappinByPositionWrapper),
reinterpret_cast<void**>(&gOriginalSetSelectedMappinByPositionWrapper));
AttachProbeHook("SetSelectedMappinCore", kSetSelectedMappinCoreRva,
reinterpret_cast<void*>(&DetourSetSelectedMappinCore),
reinterpret_cast<void**>(&gOriginalSetSelectedMappinCore));
AttachProbeHook("TrackCustomPositionMappinWrapper", kTrackCustomPositionMappinWrapperRva,
reinterpret_cast<void*>(&DetourTrackCustomPositionMappinWrapper),
reinterpret_cast<void**>(&gOriginalTrackCustomPositionMappinWrapper));
AttachProbeHook("TrackCustomPositionMappinCore", kTrackCustomPositionMappinCoreRva,
reinterpret_cast<void*>(&DetourTrackCustomPositionMappinCore),
reinterpret_cast<void**>(&gOriginalTrackCustomPositionMappinCore));
AttachProbeHook("UntrackCustomPositionMappinWrapper", kUntrackCustomPositionMappinWrapperRva,
reinterpret_cast<void*>(&DetourUntrackCustomPositionMappinWrapper),
reinterpret_cast<void**>(&gOriginalUntrackCustomPositionMappinWrapper));
AttachProbeHook("TrackMappinWrapper", kTrackMappinWrapperRva, AttachProbeHook("TrackMappinWrapper", kTrackMappinWrapperRva,
reinterpret_cast<void*>(&DetourTrackMappinWrapper), reinterpret_cast<void*>(&DetourTrackMappinWrapper),
reinterpret_cast<void**>(&gOriginalTrackMappinWrapper)); reinterpret_cast<void**>(&gOriginalTrackMappinWrapper));
@@ -847,12 +1184,24 @@ RED4EXT_C_EXPORT bool RED4EXT_CALL Main(RED4ext::v1::PluginHandle aHandle, RED4e
if (aReason == RED4ext::v1::EMainReason::Unload) if (aReason == RED4ext::v1::EMainReason::Unload)
{ {
DetachProbeHook("GPSSystem/Tick", kGpsSystemTickRva); DetachProbeHook("GPSSystem/Tick", kGpsSystemTickRva);
DetachProbeHook("FrameMappinPathWrapper", kFrameMappinPathWrapperRva);
DetachProbeHook("FrameMappinPathCore", kFrameMappinPathCoreRva);
DetachProbeHook("SetSelectedMappinWrapper", kSetSelectedMappinWrapperRva);
DetachProbeHook("SetSelectedMappinByIdWrapper", kSetSelectedMappinByIdWrapperRva);
DetachProbeHook("SetSelectedMappinByPositionWrapper", kSetSelectedMappinByPositionWrapperRva);
DetachProbeHook("SetSelectedMappinCore", kSetSelectedMappinCoreRva);
DetachProbeHook("TrackCustomPositionMappinWrapper", kTrackCustomPositionMappinWrapperRva);
DetachProbeHook("TrackCustomPositionMappinCore", kTrackCustomPositionMappinCoreRva);
DetachProbeHook("UntrackCustomPositionMappinWrapper", kUntrackCustomPositionMappinWrapperRva);
DetachProbeHook("TrackMappinWrapper", kTrackMappinWrapperRva); DetachProbeHook("TrackMappinWrapper", kTrackMappinWrapperRva);
DetachProbeHook("TrackMappinCore", kTrackMappinCoreRva); DetachProbeHook("TrackMappinCore", kTrackMappinCoreRva);
DetachProbeHook("SetMappinTrackingAlternativeWrapper", kSetMappinTrackingAlternativeWrapperRva); DetachProbeHook("SetMappinTrackingAlternativeWrapper", kSetMappinTrackingAlternativeWrapperRva);
DetachAbsoluteHook("MappinSystem::UpdateCustomPosition slot1f0", gMappinUpdateCustomPositionTarget);
DetachAbsoluteHook("MappinSystem::SetTracked slot220", gMappinSetTrackedTarget); DetachAbsoluteHook("MappinSystem::SetTracked slot220", gMappinSetTrackedTarget);
DetachAbsoluteHook("MappinSystem::ClearTracked slot228", gMappinClearTrackedTarget); DetachAbsoluteHook("MappinSystem::ClearTracked slot228", gMappinClearTrackedTarget);
DetachAbsoluteHook("MappinSystem::FramePath slot280", gMappinFramePathTarget);
DetachAbsoluteHook("MappinSystem::PositionQuery slot2e0", gMappinPositionQueryTarget); DetachAbsoluteHook("MappinSystem::PositionQuery slot2e0", gMappinPositionQueryTarget);
DetachAbsoluteHook("MappinSystem::CreateCustomPosition slot2f0", gMappinCreateCustomPositionTarget);
DetachAbsoluteHook("MappinSystem::ReleaseQuery slot368", gMappinReleaseQueryTarget); DetachAbsoluteHook("MappinSystem::ReleaseQuery slot368", gMappinReleaseQueryTarget);
DetachAbsoluteHook("MappinSystem::ActiveRoute slot3a8", gMappinActiveRouteTarget); DetachAbsoluteHook("MappinSystem::ActiveRoute slot3a8", gMappinActiveRouteTarget);
} }