2022-10-21 13:25:37 +02:00
|
|
|
#pragma once
|
2022-11-21 16:37:12 +01:00
|
|
|
#include <span>
|
2022-10-21 13:25:37 +02:00
|
|
|
|
|
|
|
namespace memory
|
|
|
|
{
|
2022-11-21 16:37:12 +01:00
|
|
|
template<typename T>
|
|
|
|
concept SpanCompatibleType = requires(T a)
|
|
|
|
{
|
|
|
|
std::span{ a };
|
|
|
|
};
|
|
|
|
|
2022-10-21 13:25:37 +02:00
|
|
|
class byte_patch
|
|
|
|
{
|
|
|
|
public:
|
2022-10-30 19:14:19 +01:00
|
|
|
virtual ~byte_patch();
|
2022-10-26 21:20:26 +02:00
|
|
|
|
2022-10-30 19:14:19 +01:00
|
|
|
void apply() const;
|
2022-10-21 13:25:37 +02:00
|
|
|
|
2022-10-30 19:14:19 +01:00
|
|
|
void restore() const;
|
2022-10-26 21:20:26 +02:00
|
|
|
|
2022-10-30 19:14:19 +01:00
|
|
|
void remove() const;
|
2022-10-21 13:25:37 +02:00
|
|
|
|
|
|
|
template <typename TAddr>
|
2022-10-21 14:09:20 +02:00
|
|
|
static const std::unique_ptr<byte_patch>& make(TAddr address, std::remove_pointer_t<std::remove_reference_t<TAddr>> value)
|
2022-10-21 13:25:37 +02:00
|
|
|
{
|
2022-10-21 14:09:20 +02:00
|
|
|
return m_patches.emplace_back(
|
|
|
|
std::unique_ptr<byte_patch>(new byte_patch(address, value)));
|
2022-10-21 13:25:37 +02:00
|
|
|
}
|
|
|
|
|
2022-11-21 16:37:12 +01:00
|
|
|
template <typename TAddr, typename T> requires SpanCompatibleType<T>
|
|
|
|
static const std::unique_ptr<byte_patch>& make(TAddr address, T span_compatible)
|
|
|
|
{
|
|
|
|
return m_patches.emplace_back(
|
|
|
|
std::unique_ptr<byte_patch>(new byte_patch(address, std::span{ span_compatible })));
|
|
|
|
}
|
|
|
|
|
2022-10-30 19:14:19 +01:00
|
|
|
static void restore_all();
|
2022-10-21 13:25:37 +02:00
|
|
|
|
|
|
|
private:
|
|
|
|
template <typename TAddr>
|
|
|
|
byte_patch(TAddr address, std::remove_pointer_t<std::remove_reference_t<TAddr>> value)
|
|
|
|
: m_address(address)
|
|
|
|
{
|
2022-10-26 21:20:26 +02:00
|
|
|
m_size = sizeof(std::remove_pointer_t<std::remove_reference_t<TAddr>>);
|
2022-10-21 13:25:37 +02:00
|
|
|
|
2022-11-21 16:37:12 +01:00
|
|
|
m_original_bytes = std::make_unique<byte[]>(m_size);
|
2022-10-26 21:20:26 +02:00
|
|
|
memcpy(m_original_bytes.get(), m_address, m_size);
|
2022-11-21 16:37:12 +01:00
|
|
|
|
|
|
|
m_value = std::make_unique<byte[]>(m_size);
|
2022-10-26 21:20:26 +02:00
|
|
|
memcpy(m_value.get(), &value, m_size);
|
2022-10-21 13:25:37 +02:00
|
|
|
}
|
|
|
|
|
2022-11-21 16:37:12 +01:00
|
|
|
template <typename TAddr, typename T, std::size_t N>
|
|
|
|
byte_patch(TAddr address, std::span<T, N> span)
|
|
|
|
: m_address((void*)address)
|
|
|
|
{
|
|
|
|
m_size = span.size_bytes();
|
|
|
|
|
|
|
|
m_original_bytes = std::make_unique<byte[]>(m_size);
|
|
|
|
memcpy(m_original_bytes.get(), m_address, m_size);
|
|
|
|
|
|
|
|
m_value = std::make_unique<byte[]>(m_size);
|
|
|
|
memcpy(m_value.get(), span.data(), m_size);
|
|
|
|
}
|
|
|
|
|
2022-10-21 13:25:37 +02:00
|
|
|
protected:
|
2022-10-21 14:09:20 +02:00
|
|
|
static inline std::vector<std::unique_ptr<byte_patch>> m_patches;
|
2022-10-21 13:25:37 +02:00
|
|
|
|
|
|
|
private:
|
|
|
|
void* m_address;
|
2022-11-21 16:37:12 +01:00
|
|
|
std::unique_ptr<byte[]> m_value;
|
|
|
|
std::unique_ptr<byte[]> m_original_bytes;
|
2022-10-26 21:20:26 +02:00
|
|
|
std::size_t m_size;
|
2022-10-21 13:25:37 +02:00
|
|
|
|
2022-10-21 14:09:20 +02:00
|
|
|
friend bool operator== (const std::unique_ptr<byte_patch>& a, const byte_patch* b);
|
2022-10-21 13:25:37 +02:00
|
|
|
};
|
|
|
|
}
|