From 0a793a6b2e32449d856a5c53d8de2a3571a1c486 Mon Sep 17 00:00:00 2001 From: maybegreat48 <96936658+maybegreat48@users.noreply.github.com> Date: Tue, 25 Mar 2025 20:26:25 -0400 Subject: [PATCH] fix(byte_patches): rewrite byte patches to ensure clang support --- src/core/hooking/Hooking.cpp | 1 + src/core/memory/BytePatch.cpp | 37 --------- src/core/memory/BytePatch.hpp | 72 ------------------ src/core/memory/BytePatches.cpp | 44 +++++++++++ src/core/memory/BytePatches.hpp | 76 +++++++++++++++++++ src/game/gta/Vehicle.cpp | 6 +- src/game/gta/Vehicle.hpp | 3 +- src/game/hooks/Network/HandleNetGameEvent.cpp | 2 + src/game/pointers/Pointers.cpp | 8 +- src/game/pointers/Pointers.hpp | 7 +- 10 files changed, 136 insertions(+), 120 deletions(-) delete mode 100644 src/core/memory/BytePatch.cpp delete mode 100644 src/core/memory/BytePatch.hpp create mode 100644 src/core/memory/BytePatches.cpp create mode 100644 src/core/memory/BytePatches.hpp diff --git a/src/core/hooking/Hooking.cpp b/src/core/hooking/Hooking.cpp index 317901b..b1868b5 100644 --- a/src/core/hooking/Hooking.cpp +++ b/src/core/hooking/Hooking.cpp @@ -45,6 +45,7 @@ namespace YimMenu void Hooking::Destroy() { GetInstance().DestroyImpl(); + BytePatches::RestoreAll(); } bool Hooking::InitImpl() diff --git a/src/core/memory/BytePatch.cpp b/src/core/memory/BytePatch.cpp deleted file mode 100644 index 73489bd..0000000 --- a/src/core/memory/BytePatch.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include "BytePatch.hpp" - -namespace YimMenu -{ - BytePatch::~BytePatch() - { - Restore(); - } - - void BytePatch::Apply() const - { - memcpy(m_Address, m_Value.get(), m_Size); - } - - void BytePatch::Restore() const - { - memcpy(m_Address, m_OriginalBytes.get(), m_Size); - } - - void BytePatch::Remove() const - { - if (const auto it = std::find(m_Patches.begin(), m_Patches.end(), this); it != m_Patches.end()) - { - m_Patches.erase(it); - } - } - - void BytePatch::RestoreAll() - { - m_Patches.clear(); - } - - bool operator==(const std::unique_ptr& a, const BytePatch* b) - { - return a->m_Address == b->m_Address; - } -} \ No newline at end of file diff --git a/src/core/memory/BytePatch.hpp b/src/core/memory/BytePatch.hpp deleted file mode 100644 index 11a6940..0000000 --- a/src/core/memory/BytePatch.hpp +++ /dev/null @@ -1,72 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace YimMenu -{ - class BytePatch - { - public: - virtual ~BytePatch(); - - void Apply() const; - - void Restore() const; - - void Remove() const; - - template - static const std::unique_ptr& Make(TAddr address, std::remove_pointer_t> value) - { - return m_Patches.emplace_back(std::unique_ptr(new BytePatch(address, value))); - } - - template - static const std::unique_ptr& Make(TAddr address, const std::vector& values) - { - return m_Patches.emplace_back(std::unique_ptr(new BytePatch(address, values))); - } - - static void RestoreAll(); - - private: - template - BytePatch(TAddr address, std::remove_pointer_t> value) : - m_Address(address) - { - m_Size = sizeof(std::remove_pointer_t>); - m_OriginalBytes = std::make_unique(m_Size); - m_Value = std::make_unique(m_Size); - - memcpy(m_OriginalBytes.get(), m_Address, m_Size); - memcpy(m_Value.get(), &value, m_Size); - } - - template - BytePatch(TAddr address, const std::vector& values) : - m_Address((void*)address) - { - m_Size = values.size(); - - m_OriginalBytes = std::make_unique(m_Size); - memcpy(m_OriginalBytes.get(), m_Address, m_Size); - - m_Value = std::make_unique(m_Size); - for (size_t i = 0; i < m_Size; i++) - m_Value[i] = values[i]; - } - - protected: - static inline std::vector> m_Patches; - - private: - void* m_Address; - std::unique_ptr m_Value; - std::unique_ptr m_OriginalBytes; - std::size_t m_Size; - - friend bool operator==(const std::unique_ptr& a, const BytePatch* b); - }; -} \ No newline at end of file diff --git a/src/core/memory/BytePatches.cpp b/src/core/memory/BytePatches.cpp new file mode 100644 index 0000000..9af1ec3 --- /dev/null +++ b/src/core/memory/BytePatches.cpp @@ -0,0 +1,44 @@ +#include "BytePatches.hpp" + +namespace YimMenu +{ + BytePatches::Patch::~Patch() + { + Restore(); + } + + void BytePatches::Patch::Apply() + { + if (m_Applied || !g_Running) + return; + memcpy(m_Address, m_Value.get(), m_Size); + m_Applied = true; + } + + void BytePatches::Patch::Restore() + { + if (!m_Applied) + return; + memcpy(m_Address, m_OriginalBytes.get(), m_Size); + m_Applied = false; + } + + bool operator==(const std::shared_ptr& a, const BytePatches::Patch* b) + { + return a->m_Address == b->m_Address; + } + + void BytePatches::Remove(std::shared_ptr& patch) + { + if (const auto it = std::find(m_Patches.begin(), m_Patches.end(), patch.get()); it != m_Patches.end()) + { + m_Patches.erase(it); + } + patch.reset(); + } + + void BytePatches::RestoreAll() + { + m_Patches.clear(); + } +} \ No newline at end of file diff --git a/src/core/memory/BytePatches.hpp b/src/core/memory/BytePatches.hpp new file mode 100644 index 0000000..0556a82 --- /dev/null +++ b/src/core/memory/BytePatches.hpp @@ -0,0 +1,76 @@ +#pragma once + +#include +#include +#include + +namespace YimMenu +{ + class BytePatches + { + public: + class Patch + { + void* m_Address; + std::unique_ptr m_Value; + std::unique_ptr m_OriginalBytes; + std::size_t m_Size; + bool m_Applied; + + public: + template + Patch(TAddr address, std::remove_pointer_t> value) : + m_Address(address), + m_Applied(false) + { + m_Size = sizeof(std::remove_pointer_t>); + m_OriginalBytes = std::make_unique(m_Size); + m_Value = std::make_unique(m_Size); + + memcpy(m_OriginalBytes.get(), m_Address, m_Size); + memcpy(m_Value.get(), &value, m_Size); + } + + Patch(void* address, std::span const values) : + m_Address((void*)address), + m_Applied(false) + { + m_Size = values.size(); + + m_OriginalBytes = std::make_unique(m_Size); + memcpy(m_OriginalBytes.get(), m_Address, m_Size); + + m_Value = std::make_unique(m_Size); + for (size_t i = 0; i < m_Size; i++) + m_Value[i] = values[i]; + } + + ~Patch(); + + void Apply(); + void Restore(); + + friend bool operator==(const std::shared_ptr& a, const Patch* b); + }; + + private: + static inline std::vector> m_Patches; + + public: + template + static std::shared_ptr Add(TAddr address, std::remove_pointer_t> value) + { + return m_Patches.emplace_back(std::make_shared(address, value)); + } + + static std::shared_ptr Add(void* address, std::span const values) + { + return m_Patches.emplace_back(std::make_shared(address, values)); + } + + static void Remove(std::shared_ptr& patch); // do we need this? + static void RestoreAll(); + }; + + using BytePatch = std::shared_ptr; +} \ No newline at end of file diff --git a/src/game/gta/Vehicle.cpp b/src/game/gta/Vehicle.cpp index 1bd6616..fa063da 100644 --- a/src/game/gta/Vehicle.cpp +++ b/src/game/gta/Vehicle.cpp @@ -89,6 +89,7 @@ namespace YimMenu { ENTITY_ASSERT_VALID(); ENTITY_ASSERT_CONTROL(); + ENTITY_ASSERT_SCRIPT_CONTEXT(); auto veh = GetHandle(); @@ -102,7 +103,7 @@ namespace YimMenu VEHICLE::SET_VEHICLE_TYRES_CAN_BURST(veh, false); } - void Vehicle::SetPlateText(const std::string text) + void Vehicle::SetPlateText(std::string_view text) { ENTITY_ASSERT_VALID(); ENTITY_ASSERT_CONTROL(); @@ -112,7 +113,6 @@ namespace YimMenu return; } - const char* cstr = text.c_str(); - VEHICLE::SET_VEHICLE_NUMBER_PLATE_TEXT(GetHandle(), cstr); + VEHICLE::SET_VEHICLE_NUMBER_PLATE_TEXT(GetHandle(), text.data()); } } \ No newline at end of file diff --git a/src/game/gta/Vehicle.hpp b/src/game/gta/Vehicle.hpp index 18d50d9..175f833 100644 --- a/src/game/gta/Vehicle.hpp +++ b/src/game/gta/Vehicle.hpp @@ -20,6 +20,7 @@ namespace YimMenu float GetMaxSpeed(); void Upgrade(); - void SetPlateText(const std::string text); + + void SetPlateText(std::string_view text); }; } \ No newline at end of file diff --git a/src/game/hooks/Network/HandleNetGameEvent.cpp b/src/game/hooks/Network/HandleNetGameEvent.cpp index 1b799d2..04c20d6 100644 --- a/src/game/hooks/Network/HandleNetGameEvent.cpp +++ b/src/game/hooks/Network/HandleNetGameEvent.cpp @@ -52,6 +52,8 @@ namespace YimMenu::Hooks break; } + default: + break; } return true; diff --git a/src/game/pointers/Pointers.cpp b/src/game/pointers/Pointers.cpp index 2f403f0..e532c4f 100644 --- a/src/game/pointers/Pointers.cpp +++ b/src/game/pointers/Pointers.cpp @@ -167,17 +167,17 @@ namespace YimMenu constexpr auto spectatePatchPtrn = Pattern<"74 26 66 83 FF 0D 77 20 0F B7 C7">("SpectatePatch"); scanner.Add(spectatePatchPtrn, [this](PointerCalculator ptr) { - SpectatePatch = BytePatch::Make(ptr.As(), 0xEB).get(); + SpectatePatch = BytePatches::Add(ptr.As(), 0xEB); }); constexpr auto modelSpawnBypassPtrn = Pattern<"E8 ? ? ? ? 48 8B 78 48">("ModelSpawnBypass"); scanner.Add(modelSpawnBypassPtrn, [this](PointerCalculator ptr) { - BytePatch::Make(ptr.Add(1).Rip().Add(0x2B).As(), 0xEB)->Apply(); - });//Maybe it would be better to use this? + ModelSpawnBypass = BytePatches::Add(ptr.Add(1).Rip().Add(0x2B).As(), 0xEB); + }); constexpr auto worldModelSpawnBypassPtrn = Pattern<"4C 8B 2C 01 4D 85 ED 0F 84 ? ? ? ?">("WorldModelSpawnBypass"); scanner.Add(worldModelSpawnBypassPtrn, [this](PointerCalculator ptr) { - WorldModelSpawnBypass = BytePatch::Make(ptr.Add(4).As(), std::vector{0xEB, 0x12, 0x90}).get(); + WorldModelSpawnBypass = BytePatches::Add(ptr.Add(4).As(), std::vector{0xEB, 0x12, 0x90}); }); constexpr auto receiveNetMessagePtrn = Pattern<"48 81 C1 00 03 00 00 4C 89 E2">("ReceiveNetMessage"); diff --git a/src/game/pointers/Pointers.hpp b/src/game/pointers/Pointers.hpp index 450a13e..0e7f25e 100644 --- a/src/game/pointers/Pointers.hpp +++ b/src/game/pointers/Pointers.hpp @@ -3,7 +3,7 @@ #include #include #include "types/script/scrNativeHandler.hpp" -#include "core/memory/BytePatch.hpp" +#include "core/memory/BytePatches.hpp" namespace rage { @@ -74,8 +74,9 @@ namespace YimMenu Functions::QueuePacket QueuePacket; Functions::GetNetObjectById GetNetObjectById; Functions::RequestControl RequestControl; - BytePatch* SpectatePatch; // used to patch the code that prevents you from spawning network objects when spectating - BytePatch* WorldModelSpawnBypass; + BytePatch ModelSpawnBypass; + BytePatch SpectatePatch; // used to patch the code that prevents you from spawning network objects when spectating + BytePatch WorldModelSpawnBypass; PVOID ReceiveNetMessage; rage::netEventMgr** NetEventMgr; Functions::EventAck EventAck;