From 01f0fd53811df30dffada693fa578151687d8efc Mon Sep 17 00:00:00 2001 From: pongo1231 Date: Thu, 16 Jan 2025 23:43:44 +0000 Subject: [PATCH] ChaosMod: (Un-)break a bunch of stuff Simplified the ActiveEffect timer logic Unbroke Debug builds Some other stuff idfk --- ChaosMod/CMakeLists.txt | 3 +- ChaosMod/Components/EffectDispatchTimer.cpp | 15 +- ChaosMod/Components/EffectDispatcher.cpp | 73 ++-- ChaosMod/Components/EffectDispatcher.h | 11 +- .../Components/EffectSound/EffectSound3D.cpp | 1 + ChaosMod/Components/LuaScripts.h | 2 - ChaosMod/Components/SplashTexts.cpp | 2 +- ChaosMod/Components/Voting.cpp | 2 +- ChaosMod/Effects/EffectConfig.h | 2 +- ChaosMod/Effects/EffectThreads.cpp | 6 +- ChaosMod/Effects/EffectThreads.h | 10 +- ChaosMod/Effects/EffectsInfo.h | 2 +- .../Effects/db/Player/PlayerAutopilot.cpp | 2 +- ChaosMod/Memory/Handle.h | 8 +- ChaosMod/Memory/Memory.cpp | 17 +- ChaosMod/Util/Logging.h | 2 +- vendor/Patterns/Patterns.cpp | 1 - vendor/Patterns/Patterns.h | 311 ++++++++---------- 18 files changed, 213 insertions(+), 257 deletions(-) diff --git a/ChaosMod/CMakeLists.txt b/ChaosMod/CMakeLists.txt index e8dd2f848..4333eed35 100644 --- a/ChaosMod/CMakeLists.txt +++ b/ChaosMod/CMakeLists.txt @@ -13,7 +13,8 @@ target_precompile_headers(ChaosMod PUBLIC stdafx.cpp) set_target_properties(ChaosMod PROPERTIES SUFFIX ".asi") set_target_properties(ChaosMod PROPERTIES CXX_STANDARD 20) -target_compile_definitions(ChaosMod PUBLIC $<$:_DEBUG>) +target_compile_definitions(ChaosMod PUBLIC $<$:CHAOSDEBUG>) +target_compile_definitions(ChaosMod PUBLIC NDEBUG) set(include_dirs ${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/../vendor ${PROJECT_SOURCE_DIR}/../vendor/lua/include) set(link_libs shv minhook lua54 winmm d3dcompiler xinput) diff --git a/ChaosMod/Components/EffectDispatchTimer.cpp b/ChaosMod/Components/EffectDispatchTimer.cpp index 5f3b67ecf..2f954a2c7 100644 --- a/ChaosMod/Components/EffectDispatchTimer.cpp +++ b/ChaosMod/Components/EffectDispatchTimer.cpp @@ -23,6 +23,9 @@ EffectDispatchTimer::EffectDispatchTimer(const std::array &timerColor) void EffectDispatchTimer::UpdateTimer(int deltaTime) { + if (!m_EnableTimer || (ComponentExists() && GetComponent()->DisableChaos)) + return; + m_TimerPercentage += deltaTime * (ComponentExists() ? GetComponent()->TimerSpeedModifier : 1.f) / m_EffectSpawnTime / 1000; @@ -44,7 +47,7 @@ void EffectDispatchTimer::UpdateTravelledDistance() auto player = PLAYER_PED_ID(); auto position = GET_ENTITY_COORDS(player, false); - if (ComponentExists() && GetComponent()->DisableChaos) + if (!m_EnableTimer || (ComponentExists() && GetComponent()->DisableChaos)) { m_DistanceChaosState.SavedPosition = position; return; @@ -160,13 +163,9 @@ void EffectDispatchTimer::OnRun() { auto currentUpdateTime = GetTickCount64(); - if (!m_EnableTimer || (ComponentExists() && GetComponent()->DisableChaos)) - { - m_Timer = std::numeric_limits::max(); - return; - } - - if (m_DrawTimerBar && (!ComponentExists() || !GetComponent()->HideChaosUI)) + if (m_EnableTimer && m_DrawTimerBar + && (!ComponentExists() || !GetComponent()->HideChaosUI) + && (!ComponentExists() || !GetComponent()->DisableChaos)) { float percentage = m_FakeTimerPercentage != 0.f ? m_FakeTimerPercentage : m_TimerPercentage; diff --git a/ChaosMod/Components/EffectDispatcher.cpp b/ChaosMod/Components/EffectDispatcher.cpp index 959b9b544..d0f65e4c5 100644 --- a/ChaosMod/Components/EffectDispatcher.cpp +++ b/ChaosMod/Components/EffectDispatcher.cpp @@ -15,6 +15,7 @@ #define EFFECT_TEXT_INNER_SPACING_MAX .075f #define EFFECT_TEXT_TOP_SPACING .2f #define EFFECT_TEXT_TOP_SPACING_EXTRA .35f +#define EFFECT_NONTIMED_TIMER_SPEEDUP_MIN_EFFECTS 3 static void _DispatchEffect(EffectDispatcher *effectDispatcher, const EffectDispatcher::EffectDispatchEntry &entry) { @@ -26,7 +27,11 @@ static void _DispatchEffect(EffectDispatcher *effectDispatcher, const EffectDisp if (!effectDispatcher->OnPreDispatchEffect.Fire(entry.Identifier)) return; - LOG("Dispatching effect \"" << effectData.Name << "\""); + LOG("Dispatching effect \"" << effectData.Name << "\"" +#ifdef CHAOSDEBUG + << " (" << effectData.Id << ")" +#endif + ); // Increase weight for all effects first for (auto &[effectId, effectData] : g_EnabledEffects) @@ -139,12 +144,14 @@ static void _DispatchEffect(EffectDispatcher *effectDispatcher, const EffectDisp effectDuration = effectData.CustomTime; break; default: - effectDuration = -1; + effectDuration = effectData.IsMeta() ? effectDispatcher->SharedState.MetaEffectTimedDur + : effectDispatcher->SharedState.EffectTimedDur; break; } auto &activeEffect = effectDispatcher->SharedState.ActiveEffects.emplace_back( - entry.Identifier, registeredEffect, effectName.str(), effectData, effectDuration); + entry.Identifier, registeredEffect, effectName.str(), effectData, effectDuration, + effectData.TimedType != EffectTimedType::NotTimed); playEffectDispatchSound(activeEffect); @@ -171,11 +178,9 @@ static void _OnRunEffects(LPVOID data) auto effectDispatcher = reinterpret_cast(data); while (true) { - auto currentUpdateTime = GetTickCount64(); - int deltaTime = currentUpdateTime - - (ComponentExists() ? GetComponent()->GetTimer() : 0); - - // the game was paused + int deltaTime = GetTickCount64() + - (!ComponentExists() ? 0 : GetComponent()->GetTimer()); + // The game was paused if (deltaTime > 1000) deltaTime = 0; @@ -272,26 +277,21 @@ void EffectDispatcher::UpdateEffects(int deltaTime) for (auto threadId : m_PermanentEffects) EffectThreads::RunThread(threadId); - float adjustedDeltaTime = (float)deltaTime / 1000; + float adjustedDeltaTime = deltaTime / 1000.f; - int maxEffects = - std::min((int)(floor((1.0f - GetEffectTopSpace()) / EFFECT_TEXT_INNER_SPACING_MIN) - 1), m_MaxRunningEffects); - int activeEffects = 0; - int effectCountToCheckCleaning = 3; + int maxEffects = m_MaxRunningEffects; + int activeEffects = 0; // Reverse order to ensure the effects on top of the list are removed if activeEffects > maxEffects for (auto it = SharedState.ActiveEffects.rbegin(); it != SharedState.ActiveEffects.rend();) { auto &activeEffect = *it; - bool isEffectPaused = EffectThreads::IsThreadPaused(activeEffect.ThreadId); if (!EffectThreads::DoesThreadExist(activeEffect.ThreadId)) { - if (activeEffect.MaxTime > 0.f - || (activeEffect.MaxTime < 0.f - && activeEffect.Timer >= 0.f /* Timer > 0 for non-timed effects = remove */)) + if (activeEffect.IsTimed || activeEffect.Timer <= 0.f) { - // Effect thread doesn't exist anymore so just remove the effect from list + DEBUG_LOG("Discarding ActiveEffect " << activeEffect.Identifier.GetEffectId()); it = static_cast(SharedState.ActiveEffects.erase(std::next(it).base())); continue; } @@ -315,12 +315,9 @@ void EffectDispatcher::UpdateEffects(int deltaTime) effectSharedData->EffectCompletionPercentage = activeEffect.Timer <= 0.f ? 1.f : 1.f - activeEffect.Timer / activeEffect.MaxTime; - if (ComponentExists() && activeEffect.SoundId && !activeEffect.HasSetSoundOptions) - { - activeEffect.HasSetSoundOptions = true; + if (ComponentExists() && activeEffect.SoundId) GetComponent()->SetSoundOptions(activeEffect.SoundId, effectSharedData->EffectSoundPlayOptions); - } if (!effectSharedData->OverrideEffectName.empty()) { @@ -346,34 +343,24 @@ void EffectDispatcher::UpdateEffects(int deltaTime) } } - if (activeEffect.MaxTime > 0.f) - { - if (isEffectPaused) - activeEffect.Timer -= adjustedDeltaTime; - - else - activeEffect.Timer -= - adjustedDeltaTime - / (ComponentExists() ? GetComponent()->EffectDurationModifier : 1.f); - } - else - { - float t = SharedState.EffectTimedDur, m = maxEffects, n = effectCountToCheckCleaning; - // Ensure non-timed effects stay on screen for a certain amount of time - activeEffect.Timer += adjustedDeltaTime / t - * (1.f + (t / 5 - 1) * std::max(0.f, SharedState.ActiveEffects.size() - n) / (m - n)); - } + activeEffect.Timer -= + (adjustedDeltaTime + / (!ComponentExists() ? 1.f : GetComponent()->EffectDurationModifier)) + * (activeEffect.IsTimed + ? 1.f + : std::max(1.f, .5f * (activeEffects - EFFECT_NONTIMED_TIMER_SPEEDUP_MIN_EFFECTS + 3))); - if ((activeEffect.MaxTime > 0.f && activeEffect.Timer <= 0.f) - || (!activeEffect.IsMeta && activeEffects > maxEffects)) + if (activeEffect.Timer <= 0.f || (!activeEffect.IsMeta && activeEffects > maxEffects)) { if (activeEffect.Timer < -60.f) { // Effect took over 60 seconds to stop, forcibly stop it in a blocking manner + DEBUG_LOG("Tiemout reached, forcefully stopping effect " << activeEffect.Identifier.GetEffectId()); EffectThreads::StopThreadImmediately(activeEffect.ThreadId); } else if (!activeEffect.IsStopping) { + DEBUG_LOG("Stopping effect " << activeEffect.Identifier.GetEffectId()); EffectThreads::StopThread(activeEffect.ThreadId); activeEffect.IsStopping = true; } @@ -490,7 +477,7 @@ void EffectDispatcher::DrawEffectTexts() ScreenTextAdjust::Right, { .0f, .915f }); } - if (effect.MaxTime > 0.f) + if (effect.IsTimed) { if (ComponentExists() && GetComponent()->FlipChaosUI) { @@ -639,7 +626,7 @@ void EffectDispatcher::RegisterPermanentEffects() auto *registeredEffect = GetRegisteredEffect(effectIdentifier); if (registeredEffect) { - auto threadId = EffectThreads::CreateThread(registeredEffect, true); + auto threadId = EffectThreads::CreateThread(registeredEffect); m_PermanentEffects.push_back(threadId); } }; diff --git a/ChaosMod/Components/EffectDispatcher.h b/ChaosMod/Components/EffectDispatcher.h index 540134a83..23b66b160 100644 --- a/ChaosMod/Components/EffectDispatcher.h +++ b/ChaosMod/Components/EffectDispatcher.h @@ -35,8 +35,9 @@ class EffectDispatcher : public Component }; std::queue EffectDispatchQueue; - struct ActiveEffect + class ActiveEffect { + public: EffectIdentifier Identifier; std::string Name; @@ -46,6 +47,7 @@ class EffectDispatcher : public Component float Timer = 0.f; float MaxTime = 0.f; + bool IsTimed = false; bool IsMeta = false; @@ -56,18 +58,17 @@ class EffectDispatcher : public Component bool HasSetSoundOptions = false; ActiveEffect(const EffectIdentifier &effectIdentifier, RegisteredEffect *registeredEffect, - const std::string &name, const EffectData &effectData, float effectDuration) + const std::string &name, const EffectData &effectData, float effectDuration, bool isTimed) { Identifier = effectIdentifier; Name = name; FakeName = effectData.FakeName; Timer = effectDuration; MaxTime = effectDuration; + IsTimed = isTimed; HideEffectName = effectData.ShouldHideRealNameOnStart(); IsMeta = effectData.IsMeta(); - - auto timedType = g_EnabledEffects.at(effectIdentifier).TimedType; - ThreadId = EffectThreads::CreateThread(registeredEffect, timedType != EffectTimedType::NotTimed); + ThreadId = EffectThreads::CreateThread(registeredEffect); } }; struct diff --git a/ChaosMod/Components/EffectSound/EffectSound3D.cpp b/ChaosMod/Components/EffectSound/EffectSound3D.cpp index 45a9bf1cd..857eb5d15 100644 --- a/ChaosMod/Components/EffectSound/EffectSound3D.cpp +++ b/ChaosMod/Components/EffectSound/EffectSound3D.cpp @@ -108,6 +108,7 @@ void EffectSound3D::OnRun() DWORD64 EffectSound3D::HandleSound(const std::string &soundFile) { auto &sound = m_Sounds[m_SoundIdCounter]; + DEBUG_LOG("Playing sound for \"" << soundFile << "\" with ID " << m_SoundIdCounter); if (ma_sound_init_from_file(&m_maEngine, soundFile.c_str(), MA_SOUND_FLAG_ASYNC, nullptr, nullptr, &sound.Handle) != MA_SUCCESS) { diff --git a/ChaosMod/Components/LuaScripts.h b/ChaosMod/Components/LuaScripts.h index 215915502..967cb75fd 100644 --- a/ChaosMod/Components/LuaScripts.h +++ b/ChaosMod/Components/LuaScripts.h @@ -2,8 +2,6 @@ #include "Components/Component.h" -#include - #define SOL_ALL_SAFETIES_ON 1 #define SOL_SAFE_NUMERICS 1 #include diff --git a/ChaosMod/Components/SplashTexts.cpp b/ChaosMod/Components/SplashTexts.cpp index b17d10a38..cac6cb5de 100644 --- a/ChaosMod/Components/SplashTexts.cpp +++ b/ChaosMod/Components/SplashTexts.cpp @@ -18,7 +18,7 @@ SplashTexts::SplashTexts() ShowSplash("Chaos Mod v" MOD_VERSION "\n\nSee credits.txt for a list of contributors", { .2f, .3f }, .65f, { 60, 245, 190 }); -#ifdef _DEBUG +#ifdef CHAOSDEBUG ShowSplash("DEBUG BUILD!", { .2f, .5f }, .7f, { 255, 0, 0 }); #endif diff --git a/ChaosMod/Components/Voting.cpp b/ChaosMod/Components/Voting.cpp index b49130ab9..0050ed6f0 100644 --- a/ChaosMod/Components/Voting.cpp +++ b/ChaosMod/Components/Voting.cpp @@ -62,7 +62,7 @@ bool Voting::Init() PROCESS_INFORMATION procInfo = {}; auto str = _wcsdup(VOTING_PROXY_START_ARGS); -#ifdef _DEBUG +#ifdef CHAOSDEBUG DWORD attributes = NULL; if (DoesFeatureFlagExist("forcenovotingconsole")) attributes = CREATE_NO_WINDOW; diff --git a/ChaosMod/Effects/EffectConfig.h b/ChaosMod/Effects/EffectConfig.h index 2554c5f49..21b9e5efb 100644 --- a/ChaosMod/Effects/EffectConfig.h +++ b/ChaosMod/Effects/EffectConfig.h @@ -125,7 +125,7 @@ namespace EffectConfig effectData.SetAttribute(EffectAttributes::IsMeta, effectInfo.ExecutionType == EffectExecutionType::Meta); effectData.Name = effectInfo.Name; effectData.SetAttribute(EffectAttributes::HideRealNameOnStart, effectInfo.HideRealNameOnStart); -#ifdef _DEBUG +#ifdef CHAOSDEBUG effectData.ShortcutKeycode = effectInfo.DebugShortcutKeycode ? effectInfo.DebugShortcutKeycode : configValues.Values.ShortcutKeycode; #else diff --git a/ChaosMod/Effects/EffectThreads.cpp b/ChaosMod/Effects/EffectThreads.cpp index a279377df..ebe151b1e 100644 --- a/ChaosMod/Effects/EffectThreads.cpp +++ b/ChaosMod/Effects/EffectThreads.cpp @@ -25,12 +25,12 @@ static auto _StopThreadImmediately(auto it) namespace EffectThreads { - LPVOID CreateThread(RegisteredEffect *effect, bool isTimed) + LPVOID CreateThread(RegisteredEffect *effect) { - auto thread = std::make_unique(effect, isTimed); + auto thread = std::make_unique(effect); auto threadId = thread->Thread; m_Threads[threadId] = std::move(thread); - LOG(threadId); + DEBUG_LOG("Created Effect Thread " << threadId); return threadId; } diff --git a/ChaosMod/Effects/EffectThreads.h b/ChaosMod/Effects/EffectThreads.h index afdc54a36..9d6e1270e 100644 --- a/ChaosMod/Effects/EffectThreads.h +++ b/ChaosMod/Effects/EffectThreads.h @@ -25,21 +25,21 @@ struct EffectThreadData { RegisteredEffect *Effect = nullptr; bool HasOnStartExecuted = false; - bool IsRunning = false; + bool IsRunning = true; bool HasStopped = false; void *CallerFiber = nullptr; EffectThreadSharedData SharedData; - EffectThreadData(RegisteredEffect *effect, bool isRunning) : Effect(effect), IsRunning(isRunning) + EffectThreadData(RegisteredEffect *effect) : Effect(effect) { } }; namespace EffectThreads { - LPVOID CreateThread(RegisteredEffect *effect, bool isTimed); + LPVOID CreateThread(RegisteredEffect *effect); void StopThread(LPVOID threadId); void StopThreadImmediately(LPVOID threadId); @@ -75,7 +75,6 @@ inline void EffectThreadFunc(LPVOID data) threadData.Effect->Tick(); } - SwitchToFiber(threadData.CallerFiber); threadData.Effect->Stop(); threadData.HasStopped = true; @@ -91,8 +90,7 @@ class EffectThread LPVOID Thread = nullptr; EffectThreadData ThreadData; - EffectThread(RegisteredEffect *effect, bool isTimed) - : ThreadData(effect, isTimed), Thread(CreateFiber(0, EffectThreadFunc, &ThreadData)) + EffectThread(RegisteredEffect *effect) : ThreadData(effect), Thread(CreateFiber(0, EffectThreadFunc, &ThreadData)) { } diff --git a/ChaosMod/Effects/EffectsInfo.h b/ChaosMod/Effects/EffectsInfo.h index 3f607648e..fc1ef2744 100644 --- a/ChaosMod/Effects/EffectsInfo.h +++ b/ChaosMod/Effects/EffectsInfo.h @@ -15,7 +15,7 @@ struct EffectInfo bool IsTimed = false; bool IsShortDuration = false; bool HideRealNameOnStart = false; -#ifdef _DEBUG +#ifdef CHAOSDEBUG int DebugShortcutKeycode = 0; #endif std::vector IncompatibleWith; diff --git a/ChaosMod/Effects/db/Player/PlayerAutopilot.cpp b/ChaosMod/Effects/db/Player/PlayerAutopilot.cpp index d4a845b1d..5efa975d3 100644 --- a/ChaosMod/Effects/db/Player/PlayerAutopilot.cpp +++ b/ChaosMod/Effects/db/Player/PlayerAutopilot.cpp @@ -62,7 +62,7 @@ static void OnTick() return; } -#ifdef _DEBUG +#ifdef CHAOSDEBUG // Draw debug go to line if (ms_State == STATE_TO_COORDS) { diff --git a/ChaosMod/Memory/Handle.h b/ChaosMod/Memory/Handle.h index d49de43eb..86706662d 100644 --- a/ChaosMod/Memory/Handle.h +++ b/ChaosMod/Memory/Handle.h @@ -6,13 +6,11 @@ using DWORD = unsigned long; class Handle { private: - DWORD64 m_Addr; + uintptr_t m_Addr = 0; public: - Handle() : m_Addr(0) - { - } - Handle(DWORD64 addr) : m_Addr(addr) + Handle() = default; + Handle(uintptr_t addr) : m_Addr(addr) { } diff --git a/ChaosMod/Memory/Memory.cpp b/ChaosMod/Memory/Memory.cpp index 3b4e35f1b..9a5afbba0 100644 --- a/ChaosMod/Memory/Memory.cpp +++ b/ChaosMod/Memory/Memory.cpp @@ -168,7 +168,14 @@ namespace Memory Handle FindPattern(const std::string &pattern, const PatternScanRange &&scanRange) { - DEBUG_LOG("Searching for pattern: " << pattern); + DEBUG_LOG("Searching for pattern \"" + << pattern + << (scanRange.StartAddr == 0 && scanRange.EndAddr == 0 + ? "\"" + : (std::stringstream() + << "\" within address range 0x" << std::uppercase << std::hex << std::setfill(' ') + << scanRange.StartAddr << " to 0x" << std::uppercase << std::hex << scanRange.EndAddr) + .str())); if ((scanRange.StartAddr != 0 || scanRange.EndAddr != 0) && scanRange.StartAddr >= scanRange.EndAddr) { @@ -176,7 +183,7 @@ namespace Memory return Handle(); } - auto scanPattern = [&]() + auto scanPattern = [&]() -> Handle { auto copy = pattern; for (size_t pos = copy.find("??"); pos != std::string::npos; pos = copy.find("??", pos + 1)) @@ -186,9 +193,11 @@ namespace Memory ? hook::pattern(copy) : hook::pattern(scanRange.StartAddr, scanRange.EndAddr, copy); if (!thePattern.size()) - return Handle(); + return {}; - return Handle(uintptr_t(thePattern.get_first())); + auto resultAddr = reinterpret_cast(thePattern.get_first()); + DEBUG_LOG("Found pattern \"" << pattern << "\" at address 0x" << std::uppercase << std::hex << resultAddr); + return resultAddr; }; if (EffectThreads::IsThreadAnEffectThread()) diff --git a/ChaosMod/Util/Logging.h b/ChaosMod/Util/Logging.h index f7c180ebe..1ab9dde75 100644 --- a/ChaosMod/Util/Logging.h +++ b/ChaosMod/Util/Logging.h @@ -57,7 +57,7 @@ inline const auto g_ModStartTime = std::time(nullptr); COLOR_PREFIX_LOG("(" << fileName << ")", _text); \ } while (0) -#ifdef _DEBUG +#ifdef CHAOSDEBUG #define DEBUG_LOG(_text) LOG(_text) #else #define DEBUG_LOG(_text) diff --git a/vendor/Patterns/Patterns.cpp b/vendor/Patterns/Patterns.cpp index 4f49684a1..4bf45d3cb 100644 --- a/vendor/Patterns/Patterns.cpp +++ b/vendor/Patterns/Patterns.cpp @@ -6,7 +6,6 @@ */ #include "Patterns.h" -#include #define WIN32_LEAN_AND_MEAN #include diff --git a/vendor/Patterns/Patterns.h b/vendor/Patterns/Patterns.h index 531936eea..0e5e09f9e 100644 --- a/vendor/Patterns/Patterns.h +++ b/vendor/Patterns/Patterns.h @@ -8,196 +8,161 @@ #pragma once #include -#include #include #include +#include -namespace hook -{ - extern ptrdiff_t baseAddressDifference; +namespace hook { +extern ptrdiff_t baseAddressDifference; - // sets the base address difference based on an obtained pointer - inline void set_base(uintptr_t address) - { +// sets the base address difference based on an obtained pointer +inline void set_base(uintptr_t address) { #ifdef _M_IX86 - uintptr_t addressDiff = (address - 0x400000); + uintptr_t addressDiff = (address - 0x400000); #elif defined(_M_AMD64) - uintptr_t addressDiff = (address - 0x140000000); + uintptr_t addressDiff = (address - 0x140000000); #endif - // pointer-style cast to ensure unsigned overflow ends up copied directly into a signed value - baseAddressDifference = *(ptrdiff_t*)&addressDiff; - } + // pointer-style cast to ensure unsigned overflow ends up copied directly into + // a signed value + baseAddressDifference = *(ptrdiff_t *)&addressDiff; +} - // sets the base to the process main base - void set_base(); +// sets the base to the process main base +void set_base(); - inline uintptr_t getRVA(uintptr_t rva) - { - set_base(); +inline uintptr_t getRVA(uintptr_t rva) { + set_base(); #ifdef _M_IX86 - return static_cast(baseAddressDifference + 0x400000 + rva); + return static_cast(baseAddressDifference + 0x400000 + rva); #elif defined(_M_AMD64) - return static_cast(baseAddressDifference + 0x140000000 + rva); + return static_cast(baseAddressDifference + 0x140000000 + rva); #endif - } - - class pattern_match - { - private: - void* m_pointer; - - public: - inline pattern_match(void* pointer) - : m_pointer(pointer) - { - } - - template - T* get(ptrdiff_t offset = 0) const - { - char* ptr = reinterpret_cast(m_pointer); - return reinterpret_cast(ptr + offset); - } - }; - - class pattern - { - private: - std::basic_string m_bytes; - std::basic_string m_mask; +} + +class pattern_match { +private: + void *m_pointer; + +public: + inline pattern_match(void *pointer) : m_pointer(pointer) {} + + template T *get(ptrdiff_t offset = 0) const { + char *ptr = reinterpret_cast(m_pointer); + return reinterpret_cast(ptr + offset); + } +}; + +class pattern { +private: + std::basic_string m_bytes; + std::basic_string m_mask; #if PATTERNS_USE_HINTS - uint64_t m_hash; + uint64_t m_hash; #endif - std::vector m_matches; - - bool m_matched = false; - - uintptr_t m_rangeStart; - uintptr_t m_rangeEnd; - - private: - void Initialize(std::string_view pattern); - - bool ConsiderHint(uintptr_t offset); - - void EnsureMatches(uint32_t maxCount); - - inline pattern_match _get_internal(size_t index) const - { - return m_matches[index]; - } - - inline pattern(uintptr_t module) - : pattern( module, 0 ) - { - } - - inline pattern(uintptr_t begin, uintptr_t end) - : m_rangeStart(begin), m_rangeEnd(end) - { - } - - public: - pattern(std::string_view pattern) - : hook::pattern(getRVA(0)) - { - Initialize(std::move(pattern)); - } - - inline pattern(void* module, std::string_view pattern) - : hook::pattern(reinterpret_cast(module)) - { - Initialize(std::move(pattern)); - } - - inline pattern(uintptr_t begin, uintptr_t end, std::string_view pattern) - : m_rangeStart(begin), m_rangeEnd(end) - { - Initialize(std::move(pattern)); - } - - inline pattern&& count(uint32_t expected) - { - EnsureMatches(expected); - assert(m_matches.size() == expected); - return std::forward(*this); - } - - inline pattern&& count_hint(uint32_t expected) - { - EnsureMatches(expected); - return std::forward(*this); - } - - inline pattern&& clear() - { - m_matches.clear(); - m_matched = false; - return std::forward(*this); - } - - inline size_t size() - { - EnsureMatches(UINT32_MAX); - return m_matches.size(); - } - - inline bool empty() - { - return size() == 0; - } - - inline pattern_match get(size_t index) - { - EnsureMatches(UINT32_MAX); - return _get_internal(index); - } - - inline pattern_match get_one() - { - return std::forward(*this).count(1)._get_internal(0); - } - - template - inline auto get_first(ptrdiff_t offset = 0) - { - return get_one().get(offset); - } - - template - inline Pred for_each_result(Pred&& pred) - { - EnsureMatches(UINT32_MAX); - for ( auto it : m_matches ) - { - std::forward(pred)(it); - } - return std::forward(pred); - } - - public: + std::vector m_matches; + + bool m_matched = false; + + uintptr_t m_rangeStart; + uintptr_t m_rangeEnd; + +private: + void Initialize(std::string_view pattern); + + bool ConsiderHint(uintptr_t offset); + + void EnsureMatches(uint32_t maxCount); + + inline pattern_match _get_internal(size_t index) const { + return m_matches[index]; + } + + inline pattern(uintptr_t module) : pattern(module, 0) {} + + inline pattern(uintptr_t begin, uintptr_t end) + : m_rangeStart(begin), m_rangeEnd(end) {} + +public: + pattern(std::string_view pattern) : hook::pattern(getRVA(0)) { + Initialize(std::move(pattern)); + } + + inline pattern(void *module, std::string_view pattern) + : hook::pattern(reinterpret_cast(module)) { + Initialize(std::move(pattern)); + } + + inline pattern(uintptr_t begin, uintptr_t end, std::string_view pattern) + : m_rangeStart(begin), m_rangeEnd(end) { + Initialize(std::move(pattern)); + } + + inline pattern &&count(uint32_t expected) { + EnsureMatches(expected); + assert(m_matches.size() == expected); + return std::forward(*this); + } + + inline pattern &&count_hint(uint32_t expected) { + EnsureMatches(expected); + return std::forward(*this); + } + + inline pattern &&clear() { + m_matches.clear(); + m_matched = false; + return std::forward(*this); + } + + inline size_t size() { + EnsureMatches(UINT32_MAX); + return m_matches.size(); + } + + inline bool empty() { return size() == 0; } + + inline pattern_match get(size_t index) { + EnsureMatches(UINT32_MAX); + return _get_internal(index); + } + + inline pattern_match get_one() { + return std::forward(*this).count(1)._get_internal(0); + } + + template inline auto get_first(ptrdiff_t offset = 0) { + return get_one().get(offset); + } + + template inline Pred for_each_result(Pred &&pred) { + EnsureMatches(UINT32_MAX); + for (auto it : m_matches) { + std::forward(pred)(it); + } + return std::forward(pred); + } + +public: #if PATTERNS_USE_HINTS && PATTERNS_CAN_SERIALIZE_HINTS - // define a hint - static void hint(uint64_t hash, uintptr_t address); + // define a hint + static void hint(uint64_t hash, uintptr_t address); #endif - }; - - inline pattern make_module_pattern(void* module, std::string_view bytes) - { - return pattern(module, std::move(bytes)); - } - - inline pattern make_range_pattern(uintptr_t begin, uintptr_t end, std::string_view bytes) - { - return pattern(begin, end, std::move(bytes)); - } - - template - inline auto get_pattern(std::string_view pattern_string, ptrdiff_t offset = 0) - { - return pattern(std::move(pattern_string)).get_first(offset); - } +}; + +inline pattern make_module_pattern(void *module, std::string_view bytes) { + return pattern(module, std::move(bytes)); +} + +inline pattern make_range_pattern(uintptr_t begin, uintptr_t end, + std::string_view bytes) { + return pattern(begin, end, std::move(bytes)); +} + +template +inline auto get_pattern(std::string_view pattern_string, ptrdiff_t offset = 0) { + return pattern(std::move(pattern_string)).get_first(offset); } +} // namespace hook