Patch GPS search provider class costs
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user