47 template <
typename Ret,
typename... Args>
static Ret
GenericCall(REL::ID a_id, uint32_t a_offset, Args... args)
49 using func_t = Ret(*)(Args...);
50 static REL::Relocation<func_t> target{ a_id, a_offset };
51 return target(std::forward<Args>(args)...);
58 struct Patch : Xbyak::CodeGenerator
60 Patch(std::uintptr_t a_originalFuncAddr, std::size_t a_originalByteLength)
63 for (
size_t i = 0; i < a_originalByteLength; ++i) {
64 db(*
reinterpret_cast<std::uint8_t*
>(a_originalFuncAddr + i));
67 dq(a_originalFuncAddr + a_originalByteLength);
71 Patch p(a_src, BYTES);
74 auto& trampoline = SKSE::GetTrampoline();
75 trampoline.write_branch<5>(a_src, T::thunk);
77 auto alloc = trampoline.allocate(p.getSize());
78 std::memcpy(alloc, p.getCode(), p.getSize());
80 T::func =
reinterpret_cast<std::uintptr_t
>(alloc);