3#define REL_MAKE_MEMBER_FUNCTION_POD_TYPE_HELPER_IMPL(a_nopropQual, a_propQual, ...) \
8 struct member_function_pod_type<R (Cls::*)(Args...) __VA_ARGS__ a_nopropQual a_propQual> \
10 using type = R(__VA_ARGS__ Cls*, Args...) a_propQual; \
17 struct member_function_pod_type<R (Cls::*)(Args..., ...) __VA_ARGS__ a_nopropQual a_propQual> \
19 using type = R(__VA_ARGS__ Cls*, Args..., ...) a_propQual; \
22#define REL_MAKE_MEMBER_FUNCTION_POD_TYPE_HELPER(a_qualifer, ...) \
23 REL_MAKE_MEMBER_FUNCTION_POD_TYPE_HELPER_IMPL(a_qualifer, , ##__VA_ARGS__) \
24 REL_MAKE_MEMBER_FUNCTION_POD_TYPE_HELPER_IMPL(a_qualifer, noexcept, ##__VA_ARGS__)
26#define REL_MAKE_MEMBER_FUNCTION_POD_TYPE(...) \
27 REL_MAKE_MEMBER_FUNCTION_POD_TYPE_HELPER(, __VA_ARGS__) \
28 REL_MAKE_MEMBER_FUNCTION_POD_TYPE_HELPER(&, ##__VA_ARGS__) \
29 REL_MAKE_MEMBER_FUNCTION_POD_TYPE_HELPER(&&, ##__VA_ARGS__)
31#define REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE_HELPER_IMPL(a_nopropQual, a_propQual, ...) \
36 struct member_function_non_pod_type<R (Cls::*)(Args...) __VA_ARGS__ a_nopropQual a_propQual> \
38 using type = R&(__VA_ARGS__ Cls*, void*, Args...)a_propQual; \
45 struct member_function_non_pod_type<R (Cls::*)(Args..., ...) __VA_ARGS__ a_nopropQual a_propQual> \
47 using type = R&(__VA_ARGS__ Cls*, void*, Args..., ...)a_propQual; \
50#define REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE_HELPER(a_qualifer, ...) \
51 REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE_HELPER_IMPL(a_qualifer, , ##__VA_ARGS__) \
52 REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE_HELPER_IMPL(a_qualifer, noexcept, ##__VA_ARGS__)
54#define REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE(...) \
55 REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE_HELPER(, __VA_ARGS__) \
56 REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE_HELPER(&, ##__VA_ARGS__) \
57 REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE_HELPER(&&, ##__VA_ARGS__)
70 _mapping(a_rhs._mapping),
73 a_rhs._mapping =
nullptr;
74 a_rhs._view =
nullptr;
83 if (
this != std::addressof(a_rhs)) {
84 _mapping = a_rhs._mapping;
85 a_rhs._mapping =
nullptr;
88 a_rhs._view =
nullptr;
93 [[nodiscard]]
void*
data() noexcept {
return _view; }
100 void* _mapping{
nullptr };
101 void* _view{
nullptr };
131 std::bool_constant<sizeof(T) == 1>,
132 std::bool_constant<sizeof(T) == 2>,
133 std::bool_constant<sizeof(T) == 4>,
134 std::bool_constant<sizeof(T) == 8>>
140 std::is_trivially_constructible<T>,
141 std::is_trivially_destructible<T>,
142 std::is_trivially_copy_assignable<T>,
144 std::is_polymorphic<T>>>
149 std::is_standard_layout<T>
152 template <
class T,
class =
void>
161 std::is_union_v<T>>> :
169 std::is_class_v<T>>> :
172 meets_function_req<T>,
184 noexcept(std::is_nothrow_invocable_v<F, First, Rest...>)
186 using result_t = std::invoke_result_t<F, First, Rest...>;
187 std::aligned_storage_t<
sizeof(result_t),
alignof(result_t)> result;
190 auto func = stl::unrestricted_cast<func_t*>(std::forward<F>(a_func));
192 return func(std::forward<First>(a_first), std::addressof(result), std::forward<Rest>(a_rest)...);
196 inline constexpr std::uint8_t
NOP = 0x90;
197 inline constexpr std::uint8_t
RET = 0xC3;
198 inline constexpr std::uint8_t
INT3 = 0xCC;
200 template <
class F,
class... Args>
201 std::invoke_result_t<F, Args...>
invoke(F&& a_func, Args&&... a_args)
202 noexcept(std::is_nothrow_invocable_v<F, Args...>)
203 requires(std::invocable<F, Args...>)
205 if constexpr (std::is_member_function_pointer_v<std::decay_t<F>>) {
208 auto func = stl::unrestricted_cast<func_t*>(std::forward<F>(a_func));
209 return func(std::forward<Args>(a_args)...);
214 return std::forward<F>(a_func)(std::forward<Args>(a_args)...);
218 inline void safe_write(std::uintptr_t a_dst,
const void* a_src, std::size_t a_count)
220 std::uint32_t old{ 0 };
223 reinterpret_cast<void*
>(a_dst),
226 std::addressof(old));
228 std::memcpy(
reinterpret_cast<void*
>(a_dst), a_src, a_count);
231 reinterpret_cast<void*
>(a_dst),
234 std::addressof(old));
237 assert(success != 0);
240 template <std::
integral T>
243 safe_write(a_dst, std::addressof(a_data),
sizeof(T));
249 safe_write(a_dst, a_data.data(), a_data.size_bytes());
252 inline void safe_fill(std::uintptr_t a_dst, std::uint8_t a_value, std::size_t a_count)
254 std::uint32_t old{ 0 };
257 reinterpret_cast<void*
>(a_dst),
260 std::addressof(old));
262 std::fill_n(
reinterpret_cast<std::uint8_t*
>(a_dst), a_count, a_value);
265 reinterpret_cast<void*
>(a_dst),
268 std::addressof(old));
271 assert(success != 0);
288 _impl{ a_v1, a_v2, a_v3, a_v4 }
294 [[nodiscard]]
constexpr decltype(
auto)
begin()
const noexcept {
return _impl.begin(); }
295 [[nodiscard]]
constexpr decltype(
auto)
cbegin()
const noexcept {
return _impl.cbegin(); }
296 [[nodiscard]]
constexpr decltype(
auto)
end()
const noexcept {
return _impl.end(); }
297 [[nodiscard]]
constexpr decltype(
auto)
cend()
const noexcept {
return _impl.cend(); }
299 [[nodiscard]] std::strong_ordering
constexpr compare(
const Version& a_rhs)
const noexcept
301 for (std::size_t i = 0; i < _impl.size(); ++i) {
302 if ((*
this)[i] != a_rhs[i]) {
303 return (*
this)[i] < a_rhs[i] ? std::strong_ordering::less : std::strong_ordering::greater;
306 return std::strong_ordering::equal;
309 [[nodiscard]]
constexpr std::uint32_t
pack() const noexcept
311 return static_cast<std::uint32_t
>(
312 (_impl[0] & 0x0FF) << 24u |
313 (_impl[1] & 0x0FF) << 16u |
314 (_impl[2] & 0xFFF) << 4u |
315 (_impl[3] & 0x00F) << 0u);
321 for (
auto&& ver : _impl) {
322 result += std::to_string(ver);
332 for (
auto&& ver : _impl) {
333 result += std::to_wstring(ver);
341 std::array<value_type, 4> _impl{ 0, 0, 0, 0 };
345 [[nodiscard]]
constexpr std::strong_ordering
operator<=>(
const Version& a_lhs,
const Version& a_rhs)
noexcept {
return a_lhs.compare(a_rhs); }
359 void* verBuf{
nullptr };
360 std::uint32_t verLen{ 0 };
361 if (!
WinAPI::VerQueryValue(buf.data(), L
"\\StringFileInfo\\040904B0\\ProductVersion", std::addressof(verBuf), std::addressof(verLen))) {
366 std::wistringstream ss(
367 std::wstring(
static_cast<const wchar_t*
>(verBuf), verLen));
369 for (std::size_t i = 0; i < 4 &&
std::getline(ss, token, L
'.'); ++i) {
370 version[i] =
static_cast<std::uint16_t
>(std::stoi(token));
394 Segment(
std::uintptr_t a_proxyBase,
std::uintptr_t a_address,
std::uintptr_t a_size) noexcept :
395 _proxyBase(a_proxyBase),
400 [[nodiscard]] std::uintptr_t
address() const noexcept {
return _address; }
401 [[nodiscard]] std::size_t
offset() const noexcept {
return address() - _proxyBase; }
402 [[nodiscard]] std::size_t
size() const noexcept {
return _size; }
404 [[nodiscard]]
void*
pointer() const noexcept {
return reinterpret_cast<void*
>(
address()); }
409 return static_cast<T*
>(
pointer());
413 std::uintptr_t _proxyBase{ 0 };
414 std::uintptr_t _address{ 0 };
415 std::size_t _size{ 0 };
427 [[nodiscard]] std::uintptr_t
base() const noexcept {
return _base; }
433 [[nodiscard]]
void*
pointer() const noexcept {
return reinterpret_cast<void*
>(
base()); }
438 return static_cast<T*
>(
pointer());
447 Module(
const Module&) =
delete;
448 Module(Module&&) =
delete;
450 ~Module() noexcept = default;
452 Module& operator=(const Module&) = delete;
453 Module& operator=(Module&&) = delete;
458 if (handle ==
nullptr) {
460 "Failed to obtain module handle for game executable."sv);
462 _base =
reinterpret_cast<std::uintptr_t
>(handle);
471 static_cast<std::uint32_t
>(path.size())));
473 _filename = std::filesystem::path(path).filename().c_str();
479 void load_segments();
489 "Failed to obtain file version info for: {}\n"
490 "Please contact the author of this script extender plugin for further assistance."sv,
495 static constexpr std::array SEGMENTS{
497 std::make_pair(
".idata"sv,
static_cast<std::uint32_t
>(0)),
498 std::make_pair(
".rdata"sv,
static_cast<std::uint32_t
>(0)),
499 std::make_pair(
".data"sv,
static_cast<std::uint32_t
>(0)),
500 std::make_pair(
".pdata"sv,
static_cast<std::uint32_t
>(0)),
501 std::make_pair(
".tls"sv,
static_cast<std::uint32_t
>(0)),
503 std::make_pair(
".gfids"sv,
static_cast<std::uint32_t
>(0))
506 std::wstring _filename;
507 std::array<Segment, Segment::total> _segments;
509 std::uintptr_t _base{ 0 };
518 std::uint64_t offset;
531 template <
class ExecutionPolicy>
533 requires(std::is_execution_policy_v<std::decay_t<ExecutionPolicy>>)
542 [](
auto&& a_lhs,
auto&& a_rhs) {
543 return a_lhs.offset < a_rhs.offset;
551 [[nodiscard]] std::uint64_t
operator()(std::size_t a_offset)
const
553 const mapping_t elem{ 0, a_offset };
554 const auto it = std::lower_bound(
558 [](
auto&& a_lhs,
auto&& a_rhs) {
559 return a_lhs.offset < a_rhs.offset;
561 if (it == _offset2id.end()) {
564 "Failed to find the offset within the database: 0x{:08X}"sv,
595 [[nodiscard]]
inline std::size_t
id2offset(std::uint64_t a_id)
const
597 mapping_t elem{ a_id, 0 };
598 const auto it = std::lower_bound(
602 [](
auto&& a_lhs,
auto&& a_rhs) {
603 return a_lhs.id < a_rhs.id;
605 if (it == _id2offset.end()) {
608 "Failed to find the id within the address library: {}\n"
609 "This means this script extender plugin is incompatible with the address "
610 "library for this version of the game, and thus does not support it."sv,
614 return static_cast<std::size_t
>(it->offset);
623 void read(binary_io::file_istream& a_in)
625 const auto [format] = a_in.read<std::int32_t>();
629 "Unsupported address library format: {}\n"
630 "This means this script extender plugin is incompatible with the address "
631 "library available for this version of the game, and thus does not "
636 const auto [major, minor, patch, revision] =
637 a_in.read<std::int32_t, std::int32_t, std::int32_t, std::int32_t>();
638 _version[0] =
static_cast<std::uint16_t
>(major);
639 _version[1] =
static_cast<std::uint16_t
>(minor);
640 _version[2] =
static_cast<std::uint16_t
>(patch);
641 _version[3] =
static_cast<std::uint16_t
>(revision);
643 const auto [nameLen] = a_in.read<std::int32_t>();
644 a_in.seek_relative(nameLen);
646 a_in.read(_pointerSize, _addressCount);
649 [[nodiscard]] std::size_t address_count() const noexcept {
return static_cast<std::size_t
>(_addressCount); }
650 [[nodiscard]] std::uint64_t pointer_size() const noexcept {
return static_cast<std::uint64_t
>(_pointerSize); }
651 [[nodiscard]] Version version() const noexcept {
return _version; }
655 std::int32_t _pointerSize{ 0 };
656 std::int32_t _addressCount{ 0 };
659 IDDatabase() { load(); }
661 IDDatabase(
const IDDatabase&) =
delete;
662 IDDatabase(IDDatabase&&) =
delete;
664 ~IDDatabase() =
default;
666 IDDatabase& operator=(
const IDDatabase&) =
delete;
667 IDDatabase& operator=(IDDatabase&&) =
delete;
672 const auto filename =
675 "Data/SKSE/Plugins/versionlib-{}.bin"sv,
677 .value_or(L
"<unknown filename>"s);
678 load_file(filename, version);
684 binary_io::file_istream in(a_filename);
687 if (header.version() != a_version) {
691 auto mapname = L
"CommonLibSSEOffsets-v2-"s;
692 mapname += a_version.wstring();
693 const auto byteSize =
static_cast<std::size_t
>(header.address_count()) *
sizeof(mapping_t);
694 if (_mmap.
open(mapname, byteSize)) {
695 _id2offset = {
static_cast<mapping_t*
>(_mmap.
data()), header.address_count() };
696 }
else if (_mmap.
create(mapname, byteSize)) {
697 _id2offset = {
static_cast<mapping_t*
>(_mmap.
data()), header.address_count() };
698 unpack_file(in, header);
702 [](
auto&& a_lhs,
auto&& a_rhs) {
703 return a_lhs.id < a_rhs.id;
708 }
catch (
const std::system_error&) {
711 "Failed to locate an appropriate address library with the path: {}\n"
712 "This means you are missing the address library for this specific version of "
713 "the game. Please continue to the mod page for address library to download "
714 "an appropriate version. If one is not available, then it is likely that "
715 "address library has not yet added support for this version of the game."sv,
720 void unpack_file(binary_io::file_istream& a_in, header_t a_header)
722 std::uint8_t type = 0;
723 std::uint64_t
id = 0;
724 std::uint64_t offset = 0;
725 std::uint64_t prevID = 0;
726 std::uint64_t prevOffset = 0;
727 for (
auto& mapping : _id2offset) {
729 const auto lo =
static_cast<std::uint8_t
>(type & 0xF);
730 const auto hi =
static_cast<std::uint8_t
>(type >> 4);
740 id = prevID + std::get<0>(a_in.read<std::uint8_t>());
743 id = prevID - std::get<0>(a_in.read<std::uint8_t>());
746 id = prevID + std::get<0>(a_in.read<std::uint16_t>());
749 id = prevID - std::get<0>(a_in.read<std::uint16_t>());
752 std::tie(
id) = a_in.read<std::uint16_t>();
755 std::tie(
id) = a_in.read<std::uint32_t>();
761 const std::uint64_t tmp = (hi & 8) != 0 ? (prevOffset / a_header.pointer_size()) : prevOffset;
771 offset = tmp + std::get<0>(a_in.read<std::uint8_t>());
774 offset = tmp - std::get<0>(a_in.read<std::uint8_t>());
777 offset = tmp + std::get<0>(a_in.read<std::uint16_t>());
780 offset = tmp - std::get<0>(a_in.read<std::uint16_t>());
783 std::tie(offset) = a_in.read<std::uint16_t>();
786 std::tie(offset) = a_in.read<std::uint32_t>();
793 offset *= a_header.pointer_size();
796 mapping = { id, offset };
803 detail::memory_map _mmap;
804 std::span<mapping_t> _id2offset;
812 explicit constexpr
Offset(
std::
size_t a_offset) noexcept :
823 [[nodiscard]]
constexpr std::size_t
offset() const noexcept {
return _offset; }
826 [[nodiscard]]
static std::uintptr_t base() {
return Module::get().
base(); }
828 std::size_t _offset{ 0 };
834 constexpr ID() noexcept = default;
836 explicit constexpr
ID(
std::uint64_t a_id) noexcept :
847 [[nodiscard]]
constexpr std::uint64_t
id() const noexcept {
return _id; }
851 [[nodiscard]]
static std::uintptr_t base() {
return Module::get().
base(); }
853 std::uint64_t _id{ 0 };
862 std::is_member_pointer_v<T> || std::is_function_v<std::remove_pointer_t<T>>,
881 _impl{ a_id.
address() + a_offset }
902 template <
class U = value_type>
903 [[nodiscard]]
decltype(
auto)
operator*()
const noexcept
904 requires(std::is_pointer_v<U>)
909 template <
class U = value_type>
911 requires(
std::is_pointer_v<U>)
916 template <
class... Args>
918 noexcept(std::is_nothrow_invocable_v<
const value_type&, Args...>)
919 requires(std::invocable<const value_type&, Args...>)
924 [[nodiscard]]
constexpr std::uintptr_t
address() const noexcept {
return _impl; }
925 [[nodiscard]] std::size_t
offset()
const {
return _impl - base(); }
931 return stl::unrestricted_cast<value_type>(_impl);
934 template <
class U = value_type>
935 std::uintptr_t
write_vfunc(std::size_t a_idx, std::uintptr_t a_newFunc)
936 requires(std::same_as<U, std::uintptr_t>)
938 const auto addr =
address() + (
sizeof(
void*) * a_idx);
939 const auto result = *
reinterpret_cast<std::uintptr_t*
>(addr);
946 requires(std::same_as<value_type, std::uintptr_t>)
948 return write_vfunc(a_idx, stl::unrestricted_cast<std::uintptr_t>(a_newFunc));
953 [[nodiscard]]
static std::uintptr_t base() {
return Module::get().
base(); }
956 std::uintptr_t _impl{ 0 };
965 return (
'0' <= a_ch && a_ch <=
'9') ||
966 (
'A' <= a_ch && a_ch <=
'F') ||
967 (
'a' <= a_ch && a_ch <=
'f');
970 [[nodiscard]]
constexpr bool space(
char a_ch)
noexcept
975 [[nodiscard]]
constexpr bool wildcard(
char a_ch)
noexcept
987 constexpr auto lut = []()
noexcept {
988 std::array<std::uint8_t, std::numeric_limits<unsigned char>::max() + 1> a = {};
990 const auto iterate = [&](std::uint8_t a_iFirst,
unsigned char a_cFirst,
unsigned char a_cLast)
noexcept {
991 for (; a_cFirst <= a_cLast; ++a_cFirst, ++a_iFirst) {
992 a[a_cFirst] = a_iFirst;
996 iterate(0,
'0',
'9');
997 iterate(0xA,
'A',
'F');
998 iterate(0xa,
'a',
'f');
1003 return static_cast<std::byte
>(
1004 lut[
static_cast<unsigned char>(a_hi)] * 0x10u +
1005 lut[
static_cast<unsigned char>(a_lo)]);
1009 template <
char HI,
char LO>
1013 [[nodiscard]]
static constexpr bool match(std::byte a_byte)
noexcept
1016 return a_byte == expected;
1035 [[nodiscard]]
static constexpr bool match(std::byte)
noexcept
1046 template <
char,
char>
1049 template <
char C1,
char C2>
1051 requires(characters::hexadecimal(C1) && characters::hexadecimal(C2));
1053 template <
char C1,
char C2>
1055 requires(characters::wildcard(C1) && characters::wildcard(C2));
1058 template <class... Rules>
1062 static_assert(
sizeof...(Rules) >= 1,
"must provide at least 1 rule for the pattern matcher");
1064 [[nodiscard]]
constexpr bool match(std::span<
const std::byte,
sizeof...(Rules)> a_bytes)
const noexcept
1067 return (Rules::match(a_bytes[i++]) && ...);
1070 [[nodiscard]]
bool match(std::uintptr_t a_address)
const noexcept
1072 return this->match(*
reinterpret_cast<const std::byte(*)[sizeof...(Rules)]
>(a_address));
1075 void match_or_fail(std::uintptr_t a_address, std::source_location a_loc = std::source_location::current()) const noexcept
1077 if (!this->match(a_address)) {
1081 "A pattern has failed to match.\n"
1082 "This means the plugin is incompatible with the current version of the game ({}.{}.{}). "
1083 "Head to the mod page of this plugin to see if an update is available."sv,
1094 template <stl::nttp::string S,
class... Rules>
1097 if constexpr (S.length() == 0) {
1099 }
else if constexpr (S.length() == 1) {
1100 constexpr char c = S[0];
1102 consteval_error(
"the given pattern has an unpaired rule (rules are required to be written in pairs of 2)");
1104 consteval_error(
"the given pattern has trailing characters at the end (which is not allowed)");
1107 using rule_t =
decltype(rules::rule_for<S[0], S[1]>());
1108 if constexpr (std::same_as<rule_t, void>) {
1111 if constexpr (S.length() <= 3) {
1116 consteval_error(
"a space character is required to split byte patterns");
1122 template <
class... Bytes>
1124 -> std::array<std::byte,
sizeof...(Bytes)>
1126 static_assert((std::integral<Bytes> && ...),
"all bytes must be an integral type");
1127 return {
static_cast<std::byte
>(a_bytes)... };
1131 template <stl::nttp::
string S>
1134 return detail::do_make_pattern<S>();
1139 static_assert(
make_pattern<
"B8 D0 ?? ?? D4 6E">().match(
1143#undef REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE
1144#undef REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE_HELPER
1145#undef REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE_HELPER_IMPL
1147#undef REL_MAKE_MEMBER_FUNCTION_POD_TYPE
1148#undef REL_MAKE_MEMBER_FUNCTION_POD_TYPE_HELPER
1149#undef REL_MAKE_MEMBER_FUNCTION_POD_TYPE_HELPER_IMPL
Definition: Relocation.h:523
Offset2ID()
Definition: Relocation.h:547
typename container_type::const_iterator const_iterator
Definition: Relocation.h:528
typename container_type::const_reverse_iterator const_reverse_iterator
Definition: Relocation.h:529
const_reverse_iterator crbegin() const noexcept
Definition: Relocation.h:578
const_iterator begin() const noexcept
Definition: Relocation.h:571
std::vector< value_type > container_type
Definition: Relocation.h:526
size_type size() const noexcept
Definition: Relocation.h:583
Offset2ID(ExecutionPolicy &&a_policy)
Definition: Relocation.h:532
const_reverse_iterator rbegin() const noexcept
Definition: Relocation.h:577
const_reverse_iterator crend() const noexcept
Definition: Relocation.h:581
const_iterator cbegin() const noexcept
Definition: Relocation.h:572
typename container_type::size_type size_type
Definition: Relocation.h:527
const_iterator cend() const noexcept
Definition: Relocation.h:575
std::uint64_t operator()(std::size_t a_offset) const
Definition: Relocation.h:551
mapping_t value_type
Definition: Relocation.h:525
const_reverse_iterator rend() const noexcept
Definition: Relocation.h:580
const_iterator end() const noexcept
Definition: Relocation.h:574
Definition: Relocation.h:513
static IDDatabase & get()
Definition: Relocation.h:589
std::size_t id2offset(std::uint64_t a_id) const
Definition: Relocation.h:595
Definition: Relocation.h:832
std::size_t offset() const
Definition: Relocation.h:848
constexpr ID & operator=(std::uint64_t a_id) noexcept
Definition: Relocation.h:840
constexpr std::uint64_t id() const noexcept
Definition: Relocation.h:847
constexpr ID() noexcept=default
std::uintptr_t address() const
Definition: Relocation.h:846
Definition: Relocation.h:419
Version version() const noexcept
Definition: Relocation.h:429
T * pointer() const noexcept
Definition: Relocation.h:436
std::uintptr_t base() const noexcept
Definition: Relocation.h:427
stl::zwstring filename() const noexcept
Definition: Relocation.h:428
static Module & get()
Definition: Relocation.h:421
void * pointer() const noexcept
Definition: Relocation.h:433
Segment segment(Segment::Name a_segment) const noexcept
Definition: Relocation.h:431
Definition: Relocation.h:808
constexpr Offset() noexcept=default
std::uintptr_t address() const
Definition: Relocation.h:822
constexpr Offset & operator=(std::size_t a_offset) noexcept
Definition: Relocation.h:816
constexpr std::size_t offset() const noexcept
Definition: Relocation.h:823
Definition: Relocation.h:858
std::uintptr_t write_vfunc(std::size_t a_idx, std::uintptr_t a_newFunc)
Definition: Relocation.h:935
constexpr std::uintptr_t address() const noexcept
Definition: Relocation.h:924
std::conditional_t< std::is_member_pointer_v< T >||std::is_function_v< std::remove_pointer_t< T > >, std::decay_t< T >, T > value_type
Definition: Relocation.h:864
Relocation & operator=(ID a_id)
Definition: Relocation.h:896
value_type get() const noexcept(std::is_nothrow_copy_constructible_v< value_type >)
Definition: Relocation.h:927
Relocation(Offset a_offset)
Definition: Relocation.h:872
auto operator->() const noexcept
Definition: Relocation.h:910
Relocation(ID a_id, std::ptrdiff_t a_offset)
Definition: Relocation.h:880
constexpr Relocation & operator=(std::uintptr_t a_address) noexcept
Definition: Relocation.h:884
constexpr Relocation() noexcept=default
Relocation(ID a_id)
Definition: Relocation.h:876
std::invoke_result_t< const value_type &, Args... > operator()(Args &&... a_args) const noexcept(std::is_nothrow_invocable_v< const value_type &, Args... >)
Definition: Relocation.h:917
std::size_t offset() const
Definition: Relocation.h:925
Relocation & operator=(Offset a_offset)
Definition: Relocation.h:890
std::uintptr_t write_vfunc(std::size_t a_idx, F a_newFunc)
Definition: Relocation.h:945
Definition: Relocation.h:377
std::size_t size() const noexcept
Definition: Relocation.h:402
Name
Definition: Relocation.h:380
@ data
Definition: Relocation.h:384
@ tls
Definition: Relocation.h:386
@ textw
Definition: Relocation.h:387
@ gfids
Definition: Relocation.h:388
@ total
Definition: Relocation.h:389
@ idata
Definition: Relocation.h:382
@ textx
Definition: Relocation.h:381
@ pdata
Definition: Relocation.h:385
@ rdata
Definition: Relocation.h:383
void * pointer() const noexcept
Definition: Relocation.h:404
std::uintptr_t address() const noexcept
Definition: Relocation.h:400
Segment() noexcept=default
std::size_t offset() const noexcept
Definition: Relocation.h:401
T * pointer() const noexcept
Definition: Relocation.h:407
Definition: Relocation.h:275
constexpr decltype(auto) end() const noexcept
Definition: Relocation.h:296
constexpr Version(value_type a_v1, value_type a_v2=0, value_type a_v3=0, value_type a_v4=0) noexcept
Definition: Relocation.h:287
constexpr reference operator[](std::size_t a_idx) noexcept
Definition: Relocation.h:291
std::strong_ordering constexpr compare(const Version &a_rhs) const noexcept
Definition: Relocation.h:299
constexpr decltype(auto) cbegin() const noexcept
Definition: Relocation.h:295
std::string string() const
Definition: Relocation.h:318
constexpr std::uint32_t pack() const noexcept
Definition: Relocation.h:309
constexpr const_reference operator[](std::size_t a_idx) const noexcept
Definition: Relocation.h:292
std::uint16_t value_type
Definition: Relocation.h:277
constexpr decltype(auto) cend() const noexcept
Definition: Relocation.h:297
value_type & reference
Definition: Relocation.h:278
const value_type & const_reference
Definition: Relocation.h:279
constexpr Version() noexcept=default
constexpr decltype(auto) begin() const noexcept
Definition: Relocation.h:294
std::wstring wstring() const
Definition: Relocation.h:329
Definition: Relocation.h:1060
constexpr bool match(std::span< const std::byte, sizeof...(Rules)> a_bytes) const noexcept
Definition: Relocation.h:1064
void match_or_fail(std::uintptr_t a_address, std::source_location a_loc=std::source_location::current()) const noexcept
Definition: Relocation.h:1075
bool match(std::uintptr_t a_address) const noexcept
Definition: Relocation.h:1070
Definition: Relocation.h:64
~memory_map()
Definition: Relocation.h:77
memory_map & operator=(memory_map &&a_rhs) noexcept
Definition: Relocation.h:81
memory_map & operator=(const memory_map &)=delete
memory_map() noexcept=default
void * data() noexcept
Definition: Relocation.h:93
bool create(stl::zwstring a_name, std::size_t a_size)
bool open(stl::zwstring a_name, std::size_t a_size)
Definition: Relocation.h:1011
static constexpr bool match(std::byte a_byte) noexcept
Definition: Relocation.h:1013
Definition: Relocation.h:1033
static constexpr bool match(std::byte) noexcept
Definition: Relocation.h:1035
constexpr bool space(char a_ch) noexcept
Definition: Relocation.h:970
constexpr bool hexadecimal(char a_ch) noexcept
Definition: Relocation.h:963
constexpr bool wildcard(char a_ch) noexcept
Definition: Relocation.h:975
consteval std::byte hexacharacters_to_hexadecimal(char a_hi, char a_lo) noexcept
Definition: Relocation.h:985
typename member_function_non_pod_type< F >::type member_function_non_pod_type_t
Definition: Relocation.h:124
decltype(auto) invoke_member_function_non_pod(F &&a_func, First &&a_first, Rest &&... a_rest) noexcept(std::is_nothrow_invocable_v< F, First, Rest... >)
Definition: Relocation.h:183
consteval auto make_byte_array(Bytes... a_bytes) noexcept -> std::array< std::byte, sizeof...(Bytes)>
Definition: Relocation.h:1123
typename member_function_pod_type< F >::type member_function_pod_type_t
Definition: Relocation.h:113
constexpr bool is_x64_pod_v
Definition: Relocation.h:177
void consteval_error(const char *a_error)
constexpr auto do_make_pattern() noexcept
Definition: Relocation.h:1095
REL_MAKE_MEMBER_FUNCTION_POD_TYPE()
REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE()
Definition: Relocation.h:60
std::invoke_result_t< F, Args... > invoke(F &&a_func, Args &&... a_args) noexcept(std::is_nothrow_invocable_v< F, Args... >)
Definition: Relocation.h:201
std::optional< Version > get_file_version(stl::zwstring a_filename)
Definition: Relocation.h:347
constexpr std::uint8_t NOP
Definition: Relocation.h:196
constexpr std::strong_ordering operator<=>(const Version &a_lhs, const Version &a_rhs) noexcept
Definition: Relocation.h:345
constexpr std::uint8_t INT3
Definition: Relocation.h:198
constexpr bool operator==(const Version &a_lhs, const Version &a_rhs) noexcept
Definition: Relocation.h:344
void safe_fill(std::uintptr_t a_dst, std::uint8_t a_value, std::size_t a_count)
Definition: Relocation.h:252
void safe_write(std::uintptr_t a_dst, const void *a_src, std::size_t a_count)
Definition: Relocation.h:218
constexpr auto make_pattern() noexcept
Definition: Relocation.h:1132
constexpr std::uint8_t RET
Definition: Relocation.h:197
std::uint32_t GetFileVersionInfoSize(const char *a_filename, std::uint32_t *a_handle) noexcept
bool VirtualProtect(void *a_address, std::size_t a_size, std::uint32_t a_newProtect, std::uint32_t *a_oldProtect) noexcept
constexpr auto IMAGE_SCN_MEM_WRITE
Definition: WinAPI.h:7
std::uint32_t GetModuleFileName(void *a_module, char *a_filename, std::uint32_t a_size) noexcept
constexpr auto PAGE_EXECUTE_READWRITE
Definition: WinAPI.h:11
void * GetModuleHandle(const char *a_moduleName) noexcept
bool GetFileVersionInfo(const char *a_filename, std::uint32_t a_handle, std::uint32_t a_len, void *a_data) noexcept
constexpr auto IMAGE_SCN_MEM_EXECUTE
Definition: WinAPI.h:6
bool VerQueryValue(const void *a_block, const char *a_subBlock, void **a_buffer, unsigned int *a_len) noexcept
void report_and_fail(std::string_view a_msg, std::source_location a_loc=std::source_location::current())
Definition: PCH.h:580
auto utf16_to_utf8(std::wstring_view a_in) noexcept -> std::optional< std::string >
Definition: PCH.h:552
auto utf8_to_utf16(std::string_view a_in) noexcept -> std::optional< std::wstring >
Definition: PCH.h:526
basic_zstring< wchar_t > zwstring
Definition: PCH.h:78
Definition: NiBinaryStream.h:94
bool getline(RE::NiBinaryStream &a_input, std::basic_string< CharT, Traits, Allocator > &a_str)
Definition: NiBinaryStream.h:96
Definition: Relocation.h:155
Definition: Relocation.h:145
Definition: Relocation.h:135
Definition: Relocation.h:150
Definition: Relocation.h:116
Definition: Relocation.h:105