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());
444 const auto getFilename = [&]() {
448 static_cast<std::uint32_t
>(_filename.size()));
451 _filename.resize(getFilename());
452 if (
const auto result = getFilename();
453 result != _filename.size() - 1 ||
455 _filename = L
"SkyrimSE.exe"sv;
461 Module(
const Module&) =
delete;
462 Module(Module&&) =
delete;
464 ~Module() noexcept = default;
466 Module& operator=(const Module&) = delete;
467 Module& operator=(Module&&) = delete;
472 if (handle ==
nullptr) {
475 "Failed to obtain module handle for: \"{0}\".\n"
476 "You have likely renamed the executable to something unexpected. "
477 "Renaming the executable back to \"{0}\" may resolve the issue."sv,
480 _base =
reinterpret_cast<std::uintptr_t
>(handle);
486 void load_segments();
496 "Failed to obtain file version info for: {}\n"
497 "Please contact the author of this script extender plugin for further assistance."sv,
502 static constexpr std::array SEGMENTS{
513 static constexpr
auto ENVIRONMENT = L
"SKSE_RUNTIME"sv;
515 std::wstring _filename;
516 std::array<Segment, Segment::total> _segments;
518 std::uintptr_t _base{ 0 };
527 std::uint64_t offset;
540 template <
class ExecutionPolicy>
542 requires(std::is_execution_policy_v<std::decay_t<ExecutionPolicy>>)
551 [](
auto&& a_lhs,
auto&& a_rhs) {
552 return a_lhs.offset < a_rhs.offset;
560 [[nodiscard]] std::uint64_t
operator()(std::size_t a_offset)
const
562 const mapping_t elem{ 0, a_offset };
563 const auto it = std::lower_bound(
567 [](
auto&& a_lhs,
auto&& a_rhs) {
568 return a_lhs.offset < a_rhs.offset;
570 if (it == _offset2id.end()) {
573 "Failed to find the offset within the database: 0x{:08X}"sv,
604 [[nodiscard]]
inline std::size_t
id2offset(std::uint64_t a_id)
const
606 mapping_t elem{ a_id, 0 };
607 const auto it = std::lower_bound(
611 [](
auto&& a_lhs,
auto&& a_rhs) {
612 return a_lhs.id < a_rhs.id;
614 if (it == _id2offset.end()) {
617 "Failed to find the id within the address library: {}\n"
618 "This means this script extender plugin is incompatible with the address "
619 "library for this version of the game, and thus does not support it."sv,
623 return static_cast<std::size_t
>(it->offset);
632 void read(binary_io::file_istream& a_in)
634 const auto [format] = a_in.read<std::int32_t>();
638 "Unsupported address library format: {}\n"
639 "This means this script extender plugin is incompatible with the address "
640 "library available for this version of the game, and thus does not "
645 const auto [major, minor, patch, revision] =
646 a_in.read<std::int32_t, std::int32_t, std::int32_t, std::int32_t>();
647 _version[0] =
static_cast<std::uint16_t
>(major);
648 _version[1] =
static_cast<std::uint16_t
>(minor);
649 _version[2] =
static_cast<std::uint16_t
>(patch);
650 _version[3] =
static_cast<std::uint16_t
>(revision);
652 const auto [nameLen] = a_in.read<std::int32_t>();
653 a_in.seek_relative(nameLen);
655 a_in.read(_pointerSize, _addressCount);
658 [[nodiscard]] std::size_t address_count() const noexcept {
return static_cast<std::size_t
>(_addressCount); }
659 [[nodiscard]] std::uint64_t pointer_size() const noexcept {
return static_cast<std::uint64_t
>(_pointerSize); }
660 [[nodiscard]] Version version() const noexcept {
return _version; }
664 std::int32_t _pointerSize{ 0 };
665 std::int32_t _addressCount{ 0 };
668 IDDatabase() { load(); }
670 IDDatabase(
const IDDatabase&) =
delete;
671 IDDatabase(IDDatabase&&) =
delete;
673 ~IDDatabase() =
default;
675 IDDatabase& operator=(
const IDDatabase&) =
delete;
676 IDDatabase& operator=(IDDatabase&&) =
delete;
681 const auto filename =
684 "Data/SKSE/Plugins/versionlib-{}.bin"sv,
686 .value_or(L
"<unknown filename>"s);
687 load_file(filename, version);
693 binary_io::file_istream in(a_filename);
696 if (header.version() != a_version) {
700 auto mapname = L
"CommonLibSSEOffsets-v2-"s;
701 mapname += a_version.wstring();
702 const auto byteSize =
static_cast<std::size_t
>(header.address_count()) *
sizeof(mapping_t);
703 if (_mmap.
open(mapname, byteSize)) {
704 _id2offset = {
static_cast<mapping_t*
>(_mmap.
data()), header.address_count() };
705 }
else if (_mmap.
create(mapname, byteSize)) {
706 _id2offset = {
static_cast<mapping_t*
>(_mmap.
data()), header.address_count() };
707 unpack_file(in, header);
711 [](
auto&& a_lhs,
auto&& a_rhs) {
712 return a_lhs.id < a_rhs.id;
717 }
catch (
const std::system_error&) {
720 "Failed to locate an appropriate address library with the path: {}\n"
721 "This means you are missing the address library for this specific version of "
722 "the game. Please continue to the mod page for address library to download "
723 "an appropriate version. If one is not available, then it is likely that "
724 "address library has not yet added support for this version of the game."sv,
729 void unpack_file(binary_io::file_istream& a_in, header_t a_header)
731 std::uint8_t type = 0;
732 std::uint64_t
id = 0;
733 std::uint64_t offset = 0;
734 std::uint64_t prevID = 0;
735 std::uint64_t prevOffset = 0;
736 for (
auto& mapping : _id2offset) {
738 const auto lo =
static_cast<std::uint8_t
>(type & 0xF);
739 const auto hi =
static_cast<std::uint8_t
>(type >> 4);
749 id = prevID + std::get<0>(a_in.read<std::uint8_t>());
752 id = prevID - std::get<0>(a_in.read<std::uint8_t>());
755 id = prevID + std::get<0>(a_in.read<std::uint16_t>());
758 id = prevID - std::get<0>(a_in.read<std::uint16_t>());
761 std::tie(
id) = a_in.read<std::uint16_t>();
764 std::tie(
id) = a_in.read<std::uint32_t>();
770 const std::uint64_t tmp = (hi & 8) != 0 ? (prevOffset / a_header.pointer_size()) : prevOffset;
780 offset = tmp + std::get<0>(a_in.read<std::uint8_t>());
783 offset = tmp - std::get<0>(a_in.read<std::uint8_t>());
786 offset = tmp + std::get<0>(a_in.read<std::uint16_t>());
789 offset = tmp - std::get<0>(a_in.read<std::uint16_t>());
792 std::tie(offset) = a_in.read<std::uint16_t>();
795 std::tie(offset) = a_in.read<std::uint32_t>();
802 offset *= a_header.pointer_size();
805 mapping = { id, offset };
812 detail::memory_map _mmap;
813 std::span<mapping_t> _id2offset;
821 explicit constexpr
Offset(
std::
size_t a_offset) noexcept :
832 [[nodiscard]] constexpr std::size_t
offset() const noexcept {
return _offset; }
835 [[nodiscard]]
static std::uintptr_t base() {
return Module::get().
base(); }
837 std::size_t _offset{ 0 };
843 constexpr
ID() noexcept = default;
845 explicit constexpr
ID(
std::uint64_t a_id) noexcept :
856 [[nodiscard]] constexpr std::uint64_t
id() const noexcept {
return _id; }
860 [[nodiscard]]
static std::uintptr_t base() {
return Module::get().
base(); }
862 std::uint64_t _id{ 0 };
871 std::is_member_pointer_v<T> || std::is_function_v<std::remove_pointer_t<T>>,
890 _impl{ a_id.
address() + a_offset }
911 template <
class U = value_type>
912 [[nodiscard]] decltype(
auto) operator*() const noexcept
918 template <
class U = value_type>
925 template <
class... Args>
927 noexcept(std::is_nothrow_invocable_v<const value_type&, Args...>)
928 requires(std::invocable<const value_type&, Args...>)
933 [[nodiscard]] constexpr std::uintptr_t
address() const noexcept {
return _impl; }
934 [[nodiscard]] std::size_t
offset()
const {
return _impl - base(); }
940 return stl::unrestricted_cast<value_type>(_impl);
943 template <
class U = value_type>
944 std::uintptr_t
write_vfunc(std::size_t a_idx, std::uintptr_t a_newFunc)
945 requires(std::same_as<U, std::uintptr_t>)
947 const auto addr =
address() + (
sizeof(
void*) * a_idx);
948 const auto result = *
reinterpret_cast<std::uintptr_t*
>(addr);
955 requires(std::same_as<value_type, std::uintptr_t>)
957 return write_vfunc(a_idx, stl::unrestricted_cast<std::uintptr_t>(a_newFunc));
962 [[nodiscard]]
static std::uintptr_t base() {
return Module::get().
base(); }
965 std::uintptr_t _impl{ 0 };
974 return (
'0' <= a_ch && a_ch <=
'9') ||
975 (
'A' <= a_ch && a_ch <=
'F') ||
976 (
'a' <= a_ch && a_ch <=
'f');
979 [[nodiscard]] constexpr
bool space(
char a_ch) noexcept
984 [[nodiscard]] constexpr
bool wildcard(
char a_ch) noexcept
996 constexpr
auto lut = []() noexcept {
997 std::array<std::uint8_t, std::numeric_limits<unsigned char>::max() + 1> a = {};
999 const auto iterate = [&](std::uint8_t a_iFirst,
unsigned char a_cFirst,
unsigned char a_cLast) noexcept {
1000 for (; a_cFirst <= a_cLast; ++a_cFirst, ++a_iFirst) {
1001 a[a_cFirst] = a_iFirst;
1005 iterate(0,
'0',
'9');
1006 iterate(0xA,
'A',
'F');
1007 iterate(0xa,
'a',
'f');
1012 return static_cast<std::byte
>(
1013 lut[
static_cast<unsigned char>(a_hi)] * 0x10u +
1014 lut[
static_cast<unsigned char>(a_lo)]);
1018 template <
char HI,
char LO>
1022 [[nodiscard]]
static constexpr
bool match(std::byte a_byte) noexcept
1025 return a_byte == expected;
1044 [[nodiscard]]
static constexpr
bool match(std::byte) noexcept
1055 template <
char,
char>
1058 template <
char C1,
char C2>
1062 template <
char C1,
char C2>
1067 template <class... Rules>
1071 static_assert(
sizeof...(Rules) >= 1,
"must provide at least 1 rule for the pattern matcher");
1073 [[nodiscard]] constexpr
bool match(std::span<
const std::byte,
sizeof...(Rules)> a_bytes)
const noexcept
1076 return (Rules::match(a_bytes[i++]) && ...);
1079 [[nodiscard]]
bool match(std::uintptr_t a_address)
const noexcept
1081 return this->match(*
reinterpret_cast<const std::byte(*)[sizeof...(Rules)]
>(a_address));
1084 void match_or_fail(std::uintptr_t a_address, std::source_location a_loc = std::source_location::current()) const noexcept
1086 if (!this->match(a_address)) {
1090 "A pattern has failed to match.\n"
1091 "This means the plugin is incompatible with the current version of the game ({}.{}.{}). "
1092 "Head to the mod page of this plugin to see if an update is available."sv,
1106 if constexpr (S.length() == 0) {
1108 }
else if constexpr (S.length() == 1) {
1109 constexpr
char c = S[0];
1111 consteval_error(
"the given pattern has an unpaired rule (rules are required to be written in pairs of 2)");
1113 consteval_error(
"the given pattern has trailing characters at the end (which is not allowed)");
1117 if constexpr (std::same_as<rule_t, void>) {
1120 if constexpr (S.length() <= 3) {
1125 consteval_error(
"a space character is required to split byte patterns");
1131 template <
class... Bytes>
1133 -> std::array<std::byte,
sizeof...(Bytes)>
1135 static_assert((std::integral<Bytes> && ...),
"all bytes must be an integral type");
1136 return {
static_cast<std::byte
>(a_bytes)... };
1140 template <stl::nttp::
string S>
1143 return detail::do_make_pattern<S>();
1146 static_assert(make_pattern<"40 10 F2 ??">().match(
1148 static_assert(make_pattern<"B8 D0 ?? ?? D4 6E">().match(
1152 #undef REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE
1153 #undef REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE_HELPER
1154 #undef REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE_HELPER_IMPL
1156 #undef REL_MAKE_MEMBER_FUNCTION_POD_TYPE
1157 #undef REL_MAKE_MEMBER_FUNCTION_POD_TYPE_HELPER
1158 #undef REL_MAKE_MEMBER_FUNCTION_POD_TYPE_HELPER_IMPL
Definition: Relocation.h:532
Offset2ID()
Definition: Relocation.h:556
typename container_type::const_iterator const_iterator
Definition: Relocation.h:537
typename container_type::const_reverse_iterator const_reverse_iterator
Definition: Relocation.h:538
const_reverse_iterator crbegin() const noexcept
Definition: Relocation.h:587
Offset2ID(ExecutionPolicy &&a_policy) requires(std
Definition: Relocation.h:541
const_iterator begin() const noexcept
Definition: Relocation.h:580
std::vector< value_type > container_type
Definition: Relocation.h:535
size_type size() const noexcept
Definition: Relocation.h:592
const_reverse_iterator rbegin() const noexcept
Definition: Relocation.h:586
const_reverse_iterator crend() const noexcept
Definition: Relocation.h:590
const_iterator cbegin() const noexcept
Definition: Relocation.h:581
typename container_type::size_type size_type
Definition: Relocation.h:536
const_iterator cend() const noexcept
Definition: Relocation.h:584
std::uint64_t operator()(std::size_t a_offset) const
Definition: Relocation.h:560
mapping_t value_type
Definition: Relocation.h:534
const_reverse_iterator rend() const noexcept
Definition: Relocation.h:589
const_iterator end() const noexcept
Definition: Relocation.h:583
Definition: Relocation.h:522
std::size_t id2offset(std::uint64_t a_id) const
Definition: Relocation.h:604
static IDDatabase & get()
Definition: Relocation.h:598
Definition: Relocation.h:841
std::size_t offset() const
Definition: Relocation.h:857
constexpr ID & operator=(std::uint64_t a_id) noexcept
Definition: Relocation.h:849
constexpr std::uint64_t id() const noexcept
Definition: Relocation.h:856
constexpr ID() noexcept=default
std::uintptr_t address() const
Definition: Relocation.h:855
Definition: Relocation.h:419
static Module & get()
Definition: Relocation.h:421
Version version() const noexcept
Definition: Relocation.h:429
std::uintptr_t base() const noexcept
Definition: Relocation.h:427
stl::zwstring filename() const noexcept
Definition: Relocation.h:428
T * pointer() const noexcept
Definition: Relocation.h:436
void * pointer() const noexcept
Definition: Relocation.h:433
Segment segment(Segment::Name a_segment) const noexcept
Definition: Relocation.h:431
Definition: Relocation.h:817
constexpr Offset() noexcept=default
std::uintptr_t address() const
Definition: Relocation.h:831
constexpr Offset & operator=(std::size_t a_offset) noexcept
Definition: Relocation.h:825
constexpr std::size_t offset() const noexcept
Definition: Relocation.h:832
Definition: Relocation.h:867
constexpr std::uintptr_t address() const noexcept
Definition: Relocation.h:933
auto operator->() const noexcept requires(std
Definition: Relocation.h:919
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:873
constexpr Relocation & operator=(std::uintptr_t a_address) noexcept
Definition: Relocation.h:893
std::invoke_result_t< const value_type &, Args... > operator()(Args &&... a_args) const noexcept(std::is_nothrow_invocable_v< const value_type &, Args... >) requires(std
Definition: Relocation.h:926
value_type get() const noexcept(std::is_nothrow_copy_constructible_v< value_type >)
Definition: Relocation.h:936
Relocation(Offset a_offset)
Definition: Relocation.h:881
Relocation(ID a_id, std::ptrdiff_t a_offset)
Definition: Relocation.h:889
std::uintptr_t write_vfunc(std::size_t a_idx, std::uintptr_t a_newFunc) requires(std
Definition: Relocation.h:944
std::uintptr_t write_vfunc(std::size_t a_idx, F a_newFunc) requires(std
Definition: Relocation.h:954
Relocation & operator=(Offset a_offset)
Definition: Relocation.h:899
constexpr Relocation() noexcept=default
Relocation(ID a_id)
Definition: Relocation.h:885
Relocation & operator=(ID a_id)
Definition: Relocation.h:905
std::size_t offset() const
Definition: Relocation.h:934
Definition: Relocation.h:377
std::size_t size() const noexcept
Definition: Relocation.h:402
void * pointer() const noexcept
Definition: Relocation.h:404
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
T * pointer() const noexcept
Definition: Relocation.h:407
std::uintptr_t address() const noexcept
Definition: Relocation.h:400
Segment() noexcept=default
std::size_t offset() const noexcept
Definition: Relocation.h:401
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
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 std::strong_ordering compare(const Version &a_rhs) const noexcept
Definition: Relocation.h:299
constexpr decltype(auto) begin() const noexcept
Definition: Relocation.h:294
std::wstring wstring() const
Definition: Relocation.h:329
Definition: Relocation.h:1069
constexpr bool match(std::span< const std::byte, sizeof...(Rules)> a_bytes) const noexcept
Definition: Relocation.h:1073
void match_or_fail(std::uintptr_t a_address, std::source_location a_loc=std::source_location::current()) const noexcept
Definition: Relocation.h:1084
bool match(std::uintptr_t a_address) const noexcept
Definition: Relocation.h:1079
Definition: Relocation.h:64
~memory_map()
Definition: Relocation.h:77
void * data() noexcept
Definition: Relocation.h:93
memory_map & operator=(memory_map &&a_rhs) noexcept
Definition: Relocation.h:81
memory_map() noexcept=default
bool create(stl::zwstring a_name, std::size_t a_size)
memory_map & operator=(const memory_map &)=delete
bool open(stl::zwstring a_name, std::size_t a_size)
Definition: Relocation.h:1020
static constexpr bool match(std::byte a_byte) noexcept
Definition: Relocation.h:1022
Definition: Relocation.h:1042
static constexpr bool match(std::byte) noexcept
Definition: Relocation.h:1044
constexpr bool space(char a_ch) noexcept
Definition: Relocation.h:979
constexpr bool hexadecimal(char a_ch) noexcept
Definition: Relocation.h:972
constexpr bool wildcard(char a_ch) noexcept
Definition: Relocation.h:984
consteval std::byte hexacharacters_to_hexadecimal(char a_hi, char a_lo) noexcept
Definition: Relocation.h:994
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:1132
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:1104
REL_MAKE_MEMBER_FUNCTION_POD_TYPE()
REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE()
Definition: Relocation.h:60
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:1141
std::optional< Version > get_file_version(stl::zwstring a_filename)
Definition: Relocation.h:347
std::invoke_result_t< F, Args... > invoke(F &&a_func, Args &&... a_args) noexcept(std::is_nothrow_invocable_v< F, Args... >) requires(std
Definition: Relocation.h:201
constexpr std::uint8_t RET
Definition: Relocation.h:197
auto make_pair(T1 &&a_first, T2 &&a_second)
Definition: BSTTuple.h:177
std::uint32_t GetFileVersionInfoSize(const char *a_filename, std::uint32_t *a_handle) noexcept
std::uint32_t GetEnvironmentVariable(const char *a_name, char *a_buffer, std::uint32_t a_size) 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
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
string(const CharT(&)[N]) -> string< CharT, N - 1 >
void report_and_fail(std::string_view a_msg, std::source_location a_loc=std::source_location::current())
Definition: PCH.h:579
auto utf16_to_utf8(std::wstring_view a_in) noexcept -> std::optional< std::string >
Definition: PCH.h:551
auto utf8_to_utf16(std::string_view a_in) noexcept -> std::optional< std::wstring >
Definition: PCH.h:525
requires(std::invocable< std::remove_reference_t< EF >>) class scope_exit
Definition: PCH.h:148
basic_zstring< wchar_t > zwstring
Definition: PCH.h:77
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