8 #define REL_MAKE_MEMBER_FUNCTION_POD_TYPE_HELPER_IMPL(a_nopropQual, a_propQual, ...) \
13 struct member_function_pod_type<R (Cls::*)(Args...) __VA_ARGS__ a_nopropQual a_propQual> \
15 using type = R(__VA_ARGS__ Cls*, Args...) a_propQual; \
22 struct member_function_pod_type<R (Cls::*)(Args..., ...) __VA_ARGS__ a_nopropQual a_propQual> \
24 using type = R(__VA_ARGS__ Cls*, Args..., ...) a_propQual; \
27 #define REL_MAKE_MEMBER_FUNCTION_POD_TYPE_HELPER(a_qualifer, ...) \
28 REL_MAKE_MEMBER_FUNCTION_POD_TYPE_HELPER_IMPL(a_qualifer, , ##__VA_ARGS__) \
29 REL_MAKE_MEMBER_FUNCTION_POD_TYPE_HELPER_IMPL(a_qualifer, noexcept, ##__VA_ARGS__)
31 #define REL_MAKE_MEMBER_FUNCTION_POD_TYPE(...) \
32 REL_MAKE_MEMBER_FUNCTION_POD_TYPE_HELPER(, __VA_ARGS__) \
33 REL_MAKE_MEMBER_FUNCTION_POD_TYPE_HELPER(&, ##__VA_ARGS__) \
34 REL_MAKE_MEMBER_FUNCTION_POD_TYPE_HELPER(&&, ##__VA_ARGS__)
36 #define REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE_HELPER_IMPL(a_nopropQual, a_propQual, ...) \
41 struct member_function_non_pod_type<R (Cls::*)(Args...) __VA_ARGS__ a_nopropQual a_propQual> \
43 using type = R&(__VA_ARGS__ Cls*, void*, Args...)a_propQual; \
50 struct member_function_non_pod_type<R (Cls::*)(Args..., ...) __VA_ARGS__ a_nopropQual a_propQual> \
52 using type = R&(__VA_ARGS__ Cls*, void*, Args..., ...)a_propQual; \
55 #define REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE_HELPER(a_qualifer, ...) \
56 REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE_HELPER_IMPL(a_qualifer, , ##__VA_ARGS__) \
57 REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE_HELPER_IMPL(a_qualifer, noexcept, ##__VA_ARGS__)
59 #define REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE(...) \
60 REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE_HELPER(, __VA_ARGS__) \
61 REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE_HELPER(&, ##__VA_ARGS__) \
62 REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE_HELPER(&&, ##__VA_ARGS__)
95 std::bool_constant<sizeof(T) == 1>,
96 std::bool_constant<sizeof(T) == 2>,
97 std::bool_constant<sizeof(T) == 4>,
98 std::bool_constant<sizeof(T) == 8>>
104 std::is_trivially_constructible<T>,
105 std::is_trivially_destructible<T>,
106 std::is_trivially_copy_assignable<T>,
108 std::is_polymorphic<T>>>
114 template<
class T,
class =
void>
121 std::is_union_v<T>>> :
128 std::is_class_v<T>>> :
131 meets_function_req<T>,
132 meets_member_req<T>> {};
142 noexcept(
std::is_nothrow_invocable_v<F, First, Rest...>) {
143 using result_t = std::invoke_result_t<F, First, Rest...>;
144 std::aligned_storage_t<
sizeof(result_t),
alignof(result_t)> result;
147 auto func = stl::unrestricted_cast<func_t*>(std::forward<F>(a_func));
149 return func(std::forward<First>(a_first), std::addressof(result), std::forward<Rest>(a_rest)...);
153 inline constexpr std::uint8_t
NOP = 0x90;
154 inline constexpr std::uint8_t
NOP2[] = { 0x66, 0x90 };
155 inline constexpr std::uint8_t
NOP3[] = { 0x0F, 0x1F, 0x00 };
156 inline constexpr std::uint8_t
NOP4[] = { 0x0F, 0x1F, 0x40, 0x00 };
157 inline constexpr std::uint8_t
NOP5[] = { 0x0F, 0x1F, 0x44, 0x00, 0x00 };
158 inline constexpr std::uint8_t
NOP6[] = { 0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00 };
159 inline constexpr std::uint8_t
NOP7[] = { 0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00 };
160 inline constexpr std::uint8_t
NOP8[] = { 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 };
161 inline constexpr std::uint8_t
NOP9[] = { 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 };
163 inline constexpr std::uint8_t
JMP8 = 0xEB;
164 inline constexpr std::uint8_t
JMP32 = 0xE9;
165 inline constexpr std::uint8_t
RET = 0xC3;
166 inline constexpr std::uint8_t
INT3 = 0xCC;
168 template<
class F,
class... Args>
169 std::invoke_result_t<F, Args...>
invoke(F&& a_func, Args&&... a_args)
170 noexcept(std::is_nothrow_invocable_v<F, Args...>)
171 requires(std::invocable<F, Args...>)
173 if constexpr (std::is_member_function_pointer_v<std::decay_t<F>>) {
176 auto func = stl::unrestricted_cast<func_t *>(std::forward<F>(a_func));
177 return func(std::forward<Args>(a_args)...);
182 return std::forward<F>(a_func)(std::forward<Args>(a_args)...);
186 void safe_write(std::uintptr_t a_dst,
const void* a_src, std::size_t a_count);
188 template<std::
integral T>
191 safe_write(a_dst, std::addressof(a_data),
sizeof(T));
197 safe_write(a_dst, a_data.data(), a_data.size_bytes());
200 void safe_fill(std::uintptr_t a_dst, std::uint8_t a_value, std::size_t a_count);
202 template <
class T = std::u
intptr_t>
208 std::is_member_pointer_v<T> || std::is_function_v<std::remove_pointer_t<T>>,
231 _impl{a_id.
address() + a_offset}
247 _impl{a_id.
address() + a_offset}
263 _impl{a_id.
address() + a_offset}
310 template<
class U = value_type>
311 [[nodiscard]] decltype(
auto) operator*() const noexcept
317 template<
class U = value_type>
324 template<
class... Args>
326 noexcept(std::is_nothrow_invocable_v<const value_type &, Args...>)
327 requires(std::invocable<const value_type &, Args...>)
332 [[nodiscard]] constexpr std::uintptr_t
address() const noexcept {
return _impl; }
334 [[nodiscard]] std::size_t
offset()
const {
return _impl - base(); }
340 return stl::unrestricted_cast<value_type>(_impl);
343 template <std::
integral U>
345 requires(std::same_as<value_type, std::uintptr_t>)
351 void write(
const std::span<U> a_data)
352 requires(std::same_as<value_type, std::uintptr_t>)
357 template <std::
size_t N>
359 requires(std::same_as<value_type, std::uintptr_t>)
364 template <std::
size_t N,
class F>
366 requires(std::same_as<value_type, std::uintptr_t>)
371 template <std::
size_t N>
373 requires(std::same_as<value_type, std::uintptr_t>)
378 template <std::
size_t N,
class F>
380 requires(std::same_as<value_type, std::uintptr_t>)
385 void write_fill(
const std::uint8_t a_value,
const std::size_t a_count)
386 requires(std::same_as<value_type, std::uintptr_t>)
391 template <
class U = value_type>
392 std::uintptr_t
write_vfunc(
const std::size_t a_idx,
const std::uintptr_t a_newFunc)
393 requires(std::same_as<U, std::uintptr_t>)
395 const auto addr =
address() + (
sizeof(
void *) * a_idx);
396 const auto result = *
reinterpret_cast<std::uintptr_t *
>(addr);
403 requires(std::same_as<value_type, std::uintptr_t>)
405 return write_vfunc(a_idx, stl::unrestricted_cast<std::uintptr_t>(a_newFunc));
410 [[nodiscard]]
static std::uintptr_t base() {
return Module::get().
base(); }
413 std::uintptr_t _impl{0};
433 [[maybe_unused]] T&& a_seAndVR,
434 [[maybe_unused]] T&& a_ae) noexcept
436 #ifndef ENABLE_SKYRIM_AE
438 #elif !defined(ENABLE_SKYRIM_SE) && !defined(ENABLE_SKYRIM_VR)
464 [[maybe_unused]] T a_se,
465 [[maybe_unused]] T a_ae,
466 [[maybe_unused]] T a_vr) noexcept
468 #if !defined(ENABLE_SKYRIM_AE) && !defined(ENABLE_SKYRIM_VR)
470 #elif !defined(ENABLE_SKYRIM_SE) && !defined(ENABLE_SKYRIM_VR)
472 #elif !defined(ENABLE_SKYRIM_AE) && !defined(ENABLE_SKYRIM_SE)
491 template<
class Ret,
class This>
499 template<
class Ret,
class This,
class... Args>
507 template<
class Ret,
class This>
515 template<
class Ret,
class This,
class... Args>
523 template<
class Ret,
class This>
531 template<
class Ret,
class This,
class... Args>
560 template<
class Fn,
class... Args>
562 [[maybe_unused]] std::ptrdiff_t a_seAndAEVtableOffset,
563 [[maybe_unused]] std::ptrdiff_t a_vrVtableOffset,
564 [[maybe_unused]] std::ptrdiff_t a_seAndAEVtableIndex,
565 [[maybe_unused]] std::ptrdiff_t a_vrVtableIndex,
569 *
reinterpret_cast<const uintptr_t *
>(
reinterpret_cast<uintptr_t
>(a_self) +
570 #ifndef ENABLE_SKYRIM_VR
571 a_seAndAEVtableOffset) +
573 #elif !defined(ENABLE_SKYRIM_AE) && !defined(ENABLE_SKYRIM_SE)
577 (
Module::IsVR() ? a_vrVtableOffset : a_seAndAEVtableOffset)) +
578 (
Module::IsVR() ? a_vrVtableIndex : a_seAndAEVtableIndex)
580 *
sizeof(uintptr_t)))(a_self, std::forward<Args>(a_args)...);
606 template<
class Fn,
class... Args>
608 std::ptrdiff_t a_seAndAEVtableIndex,
609 std::ptrdiff_t a_vrVtableIndex,
612 return RelocateVirtual<Fn, Args...>(0, 0, a_seAndAEVtableIndex, a_vrVtableIndex, a_self, std::forward<Args>(a_args)...);
632 template<
class T,
class This>
633 [[nodiscard]]
inline T&
RelocateMember(This* a_self, std::ptrdiff_t a_seAndAE, std::ptrdiff_t a_vr)
635 return *
reinterpret_cast<T*
>(
reinterpret_cast<uintptr_t
>(a_self) +
Relocate(a_seAndAE, a_seAndAE, a_vr));
638 template<
class T,
class This>
641 return *
reinterpret_cast<T*
>(
reinterpret_cast<uintptr_t
>(a_self) + offset);
644 template<
class T,
class This>
645 [[nodiscard]]
inline T&
RelocateMemberIf(
bool condition, This* a_self, std::ptrdiff_t a, std::ptrdiff_t b)
647 return *
reinterpret_cast<T*
>(
reinterpret_cast<uintptr_t
>(a_self) + (condition ? a : b));
650 template<
class T,
class This>
653 return *
reinterpret_cast<T*
>(
reinterpret_cast<uintptr_t
>(a_self) +
658 #undef REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE
659 #undef REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE_HELPER
660 #undef REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE_HELPER_IMPL
662 #undef REL_MAKE_MEMBER_FUNCTION_POD_TYPE
663 #undef REL_MAKE_MEMBER_FUNCTION_POD_TYPE_HELPER
664 #undef REL_MAKE_MEMBER_FUNCTION_POD_TYPE_HELPER_IMPL
#define SKYRIM_ADDR
Definition: Common.h:18
#define SKYRIM_REL
Definition: Common.h:38
std::uintptr_t address() const
Definition: ID.h:444
static SKYRIM_REL_VR bool IsVR() noexcept
Definition: Module.h:254
static Module & get()
Definition: Module.h:82
Version version() const noexcept
Definition: Module.h:207
std::uintptr_t base() const noexcept
Definition: Module.h:201
static SKYRIM_REL bool IsAE() noexcept
Definition: Module.h:238
std::uintptr_t address() const
Definition: Offset.h:22
std::uintptr_t address() const
Definition: ID.h:492
Definition: Relocation.h:204
void write(const std::span< U > a_data) requires(std
Definition: Relocation.h:351
constexpr std::uintptr_t address() const noexcept
Definition: Relocation.h:332
std::uintptr_t write_branch(const F a_dst) requires(std
Definition: Relocation.h:365
auto operator->() const noexcept requires(std
Definition: Relocation.h:318
std::uintptr_t write_call(const F a_dst) requires(std
Definition: Relocation.h:379
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:210
Relocation(ID a_id, Offset a_offset)
Definition: Relocation.h:234
constexpr Relocation & operator=(std::uintptr_t a_address) noexcept
Definition: Relocation.h:274
Relocation(VariantID a_id, VariantOffset a_offset)
Definition: Relocation.h:270
std::uintptr_t write_vfunc(const std::size_t a_idx, const std::uintptr_t a_newFunc) requires(std
Definition: Relocation.h:392
Relocation & operator=(RelocationID a_id)
Definition: Relocation.h:298
std::uintptr_t write_branch(const std::uintptr_t a_dst) requires(std
Definition: Relocation.h:358
std::uintptr_t write_call(const std::uintptr_t a_dst) requires(std
Definition: Relocation.h:372
value_type get() const noexcept(std::is_nothrow_copy_constructible_v< value_type >)
Definition: Relocation.h:336
Relocation(Offset a_offset)
Definition: Relocation.h:218
Relocation(RelocationID a_id, Offset a_offset)
Definition: Relocation.h:250
Relocation(ID a_id, std::ptrdiff_t a_offset)
Definition: Relocation.h:230
Relocation(VariantID a_id, Offset a_offset)
Definition: Relocation.h:266
Relocation(VariantID a_id)
Definition: Relocation.h:258
Relocation(RelocationID a_id, std::ptrdiff_t a_offset)
Definition: Relocation.h:246
std::uintptr_t write_vfunc(std::size_t a_idx, F a_newFunc) requires(std
Definition: Relocation.h:402
Relocation(VariantID a_id, std::ptrdiff_t a_offset)
Definition: Relocation.h:262
Relocation & operator=(Offset a_offset)
Definition: Relocation.h:280
void write_fill(const std::uint8_t a_value, const std::size_t a_count) requires(std
Definition: Relocation.h:385
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:325
constexpr Relocation() noexcept=default
void write(const U &a_data) requires(std
Definition: Relocation.h:344
Relocation(ID a_id, VariantOffset a_offset)
Definition: Relocation.h:238
Relocation & operator=(VariantOffset a_offset)
Definition: Relocation.h:286
Relocation(VariantOffset a_offset)
Definition: Relocation.h:222
Relocation(ID a_id)
Definition: Relocation.h:226
Relocation & operator=(VariantID a_id)
Definition: Relocation.h:304
Relocation(RelocationID a_id)
Definition: Relocation.h:242
Relocation(RelocationID a_id, VariantOffset a_offset)
Definition: Relocation.h:254
Relocation & operator=(ID a_id)
Definition: Relocation.h:292
std::size_t offset() const
Definition: Relocation.h:334
std::uintptr_t address() const
Definition: ID.h:563
std::uintptr_t address() const
Definition: Offset.h:53
constexpr std::strong_ordering compare(const Version &a_rhs) const noexcept
Definition: Version.h:59
std::uintptr_t write_call(std::uintptr_t a_src, std::uintptr_t a_dst)
Definition: Trampoline.h:107
std::uintptr_t write_branch(std::uintptr_t a_src, std::uintptr_t a_dst)
Definition: Trampoline.h:82
typename member_function_non_pod_type< F >::type member_function_non_pod_type_t
Definition: Relocation.h:88
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:141
typename member_function_pod_type< F >::type member_function_pod_type_t
Definition: Relocation.h:77
constexpr bool is_x64_pod_v
Definition: Relocation.h:135
REL_MAKE_MEMBER_FUNCTION_POD_TYPE()
REL_MAKE_MEMBER_FUNCTION_NON_POD_TYPE()
constexpr std::uint8_t NOP6[]
Definition: Relocation.h:158
constexpr std::uint8_t JMP8
Definition: Relocation.h:163
constexpr std::uint8_t NOP
Definition: Relocation.h:153
constexpr std::uint8_t NOP4[]
Definition: Relocation.h:156
T & RelocateMember(This *a_self, std::ptrdiff_t a_seAndAE, std::ptrdiff_t a_vr)
Definition: Relocation.h:633
constexpr std::uint8_t INT3
Definition: Relocation.h:166
detail::RelocateVirtualHelper< Fn >::return_type RelocateVirtual([[maybe_unused]] std::ptrdiff_t a_seAndAEVtableOffset, [[maybe_unused]] std::ptrdiff_t a_vrVtableOffset, [[maybe_unused]] std::ptrdiff_t a_seAndAEVtableIndex, [[maybe_unused]] std::ptrdiff_t a_vrVtableIndex, typename detail::RelocateVirtualHelper< Fn >::this_type *a_self, Args &&... a_args)
Definition: Relocation.h:561
constexpr std::uint8_t NOP8[]
Definition: Relocation.h:160
constexpr std::uint8_t NOP2[]
Definition: Relocation.h:154
T & RelocateMemberIfNewer(Version v, This *a_self, std::ptrdiff_t older, std::ptrdiff_t newer)
Definition: Relocation.h:651
SKYRIM_ADDR T Relocate([[maybe_unused]] T &&a_seAndVR, [[maybe_unused]] T &&a_ae) noexcept
Definition: Relocation.h:432
void safe_fill(std::uintptr_t a_dst, std::uint8_t a_value, std::size_t a_count)
T & RelocateMemberIf(bool condition, This *a_self, std::ptrdiff_t a, std::ptrdiff_t b)
Definition: Relocation.h:645
void safe_write(std::uintptr_t a_dst, const void *a_src, std::size_t a_count)
constexpr std::uint8_t NOP5[]
Definition: Relocation.h:157
constexpr std::uint8_t NOP3[]
Definition: Relocation.h:155
constexpr std::uint8_t NOP9[]
Definition: Relocation.h:161
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:169
constexpr std::uint8_t RET
Definition: Relocation.h:165
constexpr std::uint8_t JMP32
Definition: Relocation.h:164
constexpr std::uint8_t NOP7[]
Definition: Relocation.h:159
requires(is_builtin_convertible_v< T >) struct GetRawType< T >
Definition: PackUnpack.h:30
Trampoline & GetTrampoline()
Definition: ActorValueList.h:28
This this_type
Definition: Relocation.h:502
Ret(This *, Args...) function_type
Definition: Relocation.h:504
Ret return_type
Definition: Relocation.h:503
Ret return_type
Definition: Relocation.h:495
This this_type
Definition: Relocation.h:494
Ret(This *) function_type
Definition: Relocation.h:496
Ret return_type
Definition: Relocation.h:535
Ret(const This *, Args...) function_type
Definition: Relocation.h:536
const This this_type
Definition: Relocation.h:534
Ret return_type
Definition: Relocation.h:519
Ret(This *, Args...) function_type
Definition: Relocation.h:520
This this_type
Definition: Relocation.h:518
const This this_type
Definition: Relocation.h:526
Ret(const This *) function_type
Definition: Relocation.h:528
Ret return_type
Definition: Relocation.h:527
Ret return_type
Definition: Relocation.h:511
Ret(This *) function_type
Definition: Relocation.h:512
This this_type
Definition: Relocation.h:510
Definition: Relocation.h:489
Definition: Relocation.h:115
Definition: Relocation.h:109
Definition: Relocation.h:99
Definition: Relocation.h:112
Definition: Relocation.h:80
Definition: Relocation.h:69