This repository has been archived on 2024-10-22. You can view files and clone it, but cannot push or open issues or pull requests.
YimMenu/src/memory/batch.hpp

119 lines
2.7 KiB
C++
Raw Normal View History

2019-03-21 20:18:31 +01:00
#pragma once
#include "pattern.hpp"
2023-04-14 18:54:07 +02:00
#include "range.hpp"
#include "signature.hpp"
2023-04-14 18:54:07 +02:00
#include <future>
2019-03-21 20:18:31 +01:00
namespace memory
{
2023-04-14 18:54:07 +02:00
template<size_t N>
struct batch
2019-03-21 20:18:31 +01:00
{
2023-04-14 18:54:07 +02:00
std::array<signature, N> m_entries;
2019-03-21 20:18:31 +01:00
2023-04-14 18:54:07 +02:00
constexpr batch(std::array<signature, N> entries)
{
m_entries = entries;
}
};
template<size_t N>
struct batch_and_hash
{
batch<N> m_batch;
uint32_t m_hash;
};
struct signature_hasher
{
static inline constexpr uint32_t FNV_PRIME_32 = 16777619u;
static inline constexpr uint32_t FNV_OFFSET_32 = 2166136261u;
static inline constexpr uint32_t fnv1a_32(const char* str, uint32_t hash = FNV_OFFSET_32) noexcept
{
return (str[0] == '\0') ? hash : fnv1a_32(&str[1], (hash ^ static_cast<uint32_t>(str[0])) * FNV_PRIME_32);
}
template<signature sig>
static inline constexpr uint32_t compute_hash(uint32_t hash)
{
hash = fnv1a_32(sig.m_ida, hash);
return hash;
}
template<signature sig, signature... rest_sigs>
static inline constexpr uint32_t add(uint32_t hash = FNV_OFFSET_32)
{
hash = compute_hash<sig>(hash);
if constexpr (sizeof...(rest_sigs) > 0)
{
hash = add<rest_sigs...>(hash);
}
return hash;
}
};
2023-04-14 18:54:07 +02:00
template<signature... args>
static inline constexpr auto make_batch(uint32_t hash = signature_hasher::FNV_OFFSET_32)
{
constexpr std::array<signature, sizeof...(args)> a1 = {args...};
constexpr memory::batch<a1.size()> h(a1);
return batch_and_hash<a1.size()>{h, signature_hasher::add<args...>()};
}
struct batch_runner
{
inline static std::mutex s_entry_mutex;
inline static std::vector<std::future<bool>> g_futures;
template<size_t N>
inline static bool run(const memory::batch<N> batch, range region)
2019-03-21 20:18:31 +01:00
{
2023-04-14 18:54:07 +02:00
for (auto& entry : batch.m_entries)
{
2023-04-14 18:54:07 +02:00
g_futures.emplace_back(std::async(&scan_pattern_and_execute_callback, region, entry));
}
bool found_all_patterns = true;
for (auto& future : g_futures)
{
future.wait();
if (!future.get())
found_all_patterns = false;
}
2023-04-14 18:54:07 +02:00
g_futures.clear();
return found_all_patterns;
}
inline static bool scan_pattern_and_execute_callback(range region, signature entry)
{
if (auto result = region.scan(entry.m_ida); result.has_value())
2023-04-14 18:54:07 +02:00
{
if (entry.m_on_signature_found)
{
std::lock_guard<std::mutex> lock(s_entry_mutex); // Acquire a lock on the mutex to synchronize access.
std::invoke(std::move(entry.m_on_signature_found), result.value());
2023-04-14 18:54:07 +02:00
LOG(INFO) << "Found '" << entry.m_name << "' GTA5.exe+"
<< HEX_TO_UPPER(result.value().as<DWORD64>() - region.begin().as<DWORD64>());
2023-04-14 18:54:07 +02:00
return true;
}
}
LOG(WARNING) << "Failed to find '" << entry.m_name << "'.";
return false;
}
2019-03-21 20:18:31 +01:00
};
}