Patch GPS search provider class costs

This commit is contained in:
2026-06-20 16:05:03 -05:00
parent 6ae557d200
commit d6d0ed9766
+123 -5
View File
@@ -96,7 +96,9 @@ constexpr bool kEnableVerboseJournalListenerHooks = false;
constexpr bool kEnableVerboseRouteObserverHooks = false;
constexpr bool kEnableVerboseMappinRouteState = false;
constexpr bool kEnableGpsMultiplierHooks = false;
constexpr bool kEnableGpsCostTablePatch = true;
constexpr bool kEnableGpsCostTablePatch = false;
constexpr bool kEnableGpsProviderClassPatch = true;
constexpr bool kEnableGpsProviderClassPatchTrace = true;
constexpr bool kEnableGpsTraceHooks = false;
constexpr bool kEnableGpsRouteJobStartTrace = false;
constexpr bool kEnableGpsLocalSearchHooks = false;
@@ -165,12 +167,26 @@ constexpr uintptr_t kGpsRouteJobBuildRva = 0x0818BA8;
constexpr uintptr_t kGpsRouteProducerRva = 0x044CC7C;
constexpr uintptr_t kGpsSearchRva = 0x044F054;
constexpr uintptr_t kGpsEdgeCostRva = 0x044F838;
constexpr uintptr_t kGpsBaseCostProviderVtableRva = 0x2AE6120;
constexpr uintptr_t kGpsFilteredCostProviderVtableRva = 0x2AE60F8;
constexpr uintptr_t kGpsAuxMultiplierRva = 0x040BB00;
constexpr uintptr_t kGpsNodeMultiplierRva = 0x040BB40;
constexpr uintptr_t kGpsCostMultiplierTableRva = 0x3154D28;
constexpr std::array<float, 7> kGpsPatchedCostMultipliers = {
12.0f, 7.0f, 2.5f, 0.0f, 3.0f, 2.0f, 1.25f,
};
constexpr std::array<float, 64> kGpsPatchedProviderClassMultipliers = [] {
std::array<float, 64> values{};
values.fill(1.0f);
values[1] = 0.70f;
values[3] = 1.45f;
values[4] = 1.25f;
values[5] = 1.75f;
values[15] = 0.80f;
return values;
}();
HMODULE gModule = nullptr;
std::mutex gLogMutex;
@@ -243,6 +259,7 @@ uint32_t gGpsEdgeCostLogCount = 0;
uint32_t gGpsAuxMultiplierLogCount = 0;
uint32_t gGpsNodeMultiplierLogCount = 0;
uint32_t gGpsCostTablePatchLogCount = 0;
uint32_t gGpsProviderClassPatchLogCount = 0;
std::array<uint32_t, 64> gGpsEdgeCostClassLogCounts{};
std::mutex gGpsCostLogMutex;
std::mutex gGpsAsyncLogMutex;
@@ -1708,6 +1725,100 @@ private:
std::array<float, kGpsPatchedCostMultipliers.size()> m_original{};
};
bool IsKnownGpsCostProvider(void* aProvider, uintptr_t& aVtableRva)
{
aVtableRva = 0;
auto* vtable = ReadPointerField(aProvider, 0x00);
if (!TryGetImageRva(vtable, aVtableRva))
{
return false;
}
return aVtableRva == kGpsBaseCostProviderVtableRva || aVtableRva == kGpsFilteredCostProviderVtableRva;
}
class ScopedGpsProviderClassPatch
{
public:
ScopedGpsProviderClassPatch(void* aProvider, uint32_t aSearchCall)
: m_provider(aProvider)
, m_searchCall(aSearchCall)
{
if (!kEnableGpsProviderClassPatch || !m_provider)
{
return;
}
if (!IsKnownGpsCostProvider(m_provider, m_vtableRva))
{
LogPatch("gps-provider-class-patch skipped", "reason=unknown-provider");
return;
}
m_table = reinterpret_cast<float*>(reinterpret_cast<uintptr_t>(m_provider) + 0x08);
if (!IsReadableMemory(m_table, sizeof(m_original)))
{
LogPatch("gps-provider-class-patch skipped", "reason=unreadable-table");
return;
}
std::memcpy(m_original.data(), m_table, sizeof(m_original));
std::memcpy(m_table, kGpsPatchedProviderClassMultipliers.data(), sizeof(m_original));
m_active = true;
LogPatch("gps-provider-class-patch applied", nullptr);
}
~ScopedGpsProviderClassPatch()
{
if (!m_active || !m_table)
{
return;
}
std::memcpy(m_table, m_original.data(), sizeof(m_original));
LogPatch("gps-provider-class-patch restored", nullptr);
}
private:
void LogPatch(const char* aMessage, const char* aReason)
{
if (!kEnableGpsProviderClassPatchTrace)
{
return;
}
const auto patchLogCall = NextGpsAsyncLogCall(gGpsProviderClassPatchLogCount);
if (patchLogCall >= 48)
{
return;
}
std::ostringstream line;
line << aMessage << " patchCall=" << patchLogCall << " searchCall=" << m_searchCall;
AppendPointerWithRva(line, "provider", m_provider);
line << " provider_vtable_rva=0x" << std::hex << m_vtableRva << std::dec;
if (aReason)
{
line << " " << aReason;
}
if (m_table && IsReadableMemory(m_table, sizeof(m_original)))
{
AppendFloatArray(line, "current", m_table, m_original.size());
}
AppendFloatArray(line, "original", m_original.data(), m_original.size());
AppendFloatArray(line, "patched", kGpsPatchedProviderClassMultipliers.data(),
kGpsPatchedProviderClassMultipliers.size());
LogRed4ext(line.str());
}
void* m_provider = nullptr;
float* m_table = nullptr;
uint32_t m_searchCall = 0;
uintptr_t m_vtableRva = 0;
bool m_active = false;
std::array<float, kGpsPatchedProviderClassMultipliers.size()> m_original{};
};
void AppendRouteJobSummary(std::ostringstream& aLine, const char* aPrefix, void* aJob)
{
const auto prefix = std::string(aPrefix);
@@ -3544,7 +3655,7 @@ int32_t DetourGpsSearch(void* aGraph, uint64_t aStartHandle, uint64_t aTargetHan
{
std::lock_guard lock(gGpsCostLogMutex);
callCount = gGpsSearchLogCount++;
shouldLog = callCount < kMaxCalls;
shouldLog = kEnableGpsTraceHooks && callCount < kMaxCalls;
}
if (shouldLog)
@@ -3569,6 +3680,7 @@ int32_t DetourGpsSearch(void* aGraph, uint64_t aStartHandle, uint64_t aTargetHan
int32_t result = 0x80000008;
if (gOriginalGpsSearch)
{
ScopedGpsProviderClassPatch providerPatch(aCostProvider, callCount);
result = gOriginalGpsSearch(aGraph, aStartHandle, aTargetHandle, aStartPoint, aTargetPoint, aCostProvider,
aOutPath, aOutCount);
}
@@ -4072,13 +4184,16 @@ RED4EXT_C_EXPORT bool RED4EXT_CALL Main(RED4ext::v1::PluginHandle aHandle, RED4e
reinterpret_cast<void*>(&DetourGpsRouteJobStart),
reinterpret_cast<void**>(&gOriginalGpsRouteJobStart));
}
if (kEnableGpsProviderClassPatch || (kEnableGpsTraceHooks && kEnableGpsLocalSearchHooks))
{
AttachProbeHook("GPSSearch 0x44f054", kGpsSearchRva, reinterpret_cast<void*>(&DetourGpsSearch),
reinterpret_cast<void**>(&gOriginalGpsSearch));
}
if (kEnableGpsTraceHooks && kEnableGpsLocalSearchHooks)
{
AttachProbeHook("GPSRouteProducer 0x44cc7c", kGpsRouteProducerRva,
reinterpret_cast<void*>(&DetourGpsRouteProducer),
reinterpret_cast<void**>(&gOriginalGpsRouteProducer));
AttachProbeHook("GPSSearch 0x44f054", kGpsSearchRva, reinterpret_cast<void*>(&DetourGpsSearch),
reinterpret_cast<void**>(&gOriginalGpsSearch));
AttachProbeHook("GPSEdgeCost 0x44f838", kGpsEdgeCostRva, reinterpret_cast<void*>(&DetourGpsEdgeCost),
reinterpret_cast<void**>(&gOriginalGpsEdgeCost));
}
@@ -4225,10 +4340,13 @@ RED4EXT_C_EXPORT bool RED4EXT_CALL Main(RED4ext::v1::PluginHandle aHandle, RED4e
{
DetachProbeHook("GPSRouteJobStart 0x818928", kGpsRouteJobStartRva);
}
if (kEnableGpsProviderClassPatch || (kEnableGpsTraceHooks && kEnableGpsLocalSearchHooks))
{
DetachProbeHook("GPSSearch 0x44f054", kGpsSearchRva);
}
if (kEnableGpsTraceHooks && kEnableGpsLocalSearchHooks)
{
DetachProbeHook("GPSRouteProducer 0x44cc7c", kGpsRouteProducerRva);
DetachProbeHook("GPSSearch 0x44f054", kGpsSearchRva);
DetachProbeHook("GPSEdgeCost 0x44f838", kGpsEdgeCostRva);
}
if (kEnableGpsMultiplierHooks)