28 Segment(
std::uintptr_t a_proxyBase,
std::uintptr_t a_address,
std::uintptr_t a_size) noexcept:
29 _proxyBase(a_proxyBase),
34 [[nodiscard]] std::uintptr_t
address() const noexcept {
return _address; }
36 [[nodiscard]] std::size_t
offset() const noexcept {
return address() - _proxyBase; }
38 [[nodiscard]] std::size_t
size() const noexcept {
return _size; }
40 [[nodiscard]]
void*
pointer() const noexcept {
return reinterpret_cast<void *
>(
address()); }
45 return static_cast<T*
>(
pointer());
51 std::uintptr_t _proxyBase{0};
52 std::uintptr_t _address{0};
84 if (_initialized.load(std::memory_order_relaxed)) {
87 [[maybe_unused]] std::unique_lock lock(_initLock);
93 #ifdef ENABLE_COMMONLIBSSE_TESTING
105 static bool inject(std::wstring_view a_filePath)
109 return _instance.init(a_filePath);
135 constexpr std::size_t bufferSize = 4096;
136 const wchar_t* subKey =
138 LR
"(SOFTWARE\Bethesda Softworks\Skyrim VR)" :
139 LR"(SOFTWARE\Bethesda Softworks\Skyrim Special Edition)";
140 std::uint32_t length = bufferSize * sizeof(wchar_t);
141 std::uint8_t value[bufferSize];
145 std::filesystem::path installPath(
reinterpret_cast<wchar_t *
>(value));
146 installPath /= a_runtime ==
Runtime::VR ? L
"SkyrimVR.exe" : L
"SkyrimSE.exe";
147 return inject(installPath.c_str());
153 std::wstring_view a_filename = L
"SkyrimSE.exe"sv,
154 std::uintptr_t a_base = 0,
155 std::array<std::uintptr_t, Segment::total> a_segmentSizes = {0x1603000, 0, 0x8ee000, 0x1887000, 0x15c000, 0x3000, 0x2000, 0x1000})
160 if (a_filename.empty() || !a_segmentSizes[0]) {
164 _instance._filename = _instance._filePath = a_filename.data();
165 _instance._version = a_version;
167 switch (a_version[1]) {
178 _instance._runtime = a_runtime;
180 _instance._base = a_base;
182 auto currentAddress = a_base + 0x1000;
183 for (std::size_t i = 0; i < a_segmentSizes.size(); ++i) {
184 auto &
segment = _instance._segments[i];
185 segment._size = a_segmentSizes[i];
195 static void reset() {
196 _initialized =
false;
201 [[nodiscard]] std::uintptr_t
base() const noexcept {
return _base; }
216 return static_cast<T*
>(
pointer());
224 #if (!defined(ENABLE_SKYRIM_AE) && !defined(ENABLE_SKYRIM_VR))
226 #elif (!defined(ENABLE_SKYRIM_SE) && !defined(ENABLE_SKYRIM_VR))
228 #elif (!defined(ENABLE_SKYRIM_AE) && !defined(ENABLE_SKYRIM_SE))
231 return get()._runtime;
256 #ifndef ENABLE_SKYRIM_VR
258 #elif !defined(ENABLE_SKYRIM_AE) && !defined(ENABLE_SKYRIM_SE)
270 ~
Module() noexcept = default;
277 const auto getFilename = [&]() {
281 static_cast<std::uint32_t
>(_filename.size()));
284 void *moduleHandle =
nullptr;
285 _filename.resize(getFilename());
286 if (
const auto result = getFilename();
287 result != _filename.size() - 1 ||
289 for (
auto runtime : RUNTIMES) {
297 _filePath = _filename;
301 "Failed to obtain module handle for: \"{0}\".\n"
302 "You have likely renamed the executable to something unexpected. "
303 "Renaming the executable back to \"{0}\" may resolve the issue."sv,
306 return load(moduleHandle,
true);
309 bool init(std::wstring_view a_filePath)
311 std::filesystem::path exePath(a_filePath);
312 _filename = exePath.filename().wstring();
313 _filePath = exePath.wstring();
315 if (_injectedModule) {
316 return load(_injectedModule,
false);
321 [[nodiscard]]
bool load(
void *a_handle,
bool a_failOnError)
323 _base =
reinterpret_cast<std::uintptr_t
>(a_handle);
324 if (!load_version(a_failOnError)) {
331 void load_segments();
333 bool load_version(
bool a_failOnError)
338 switch (_version[1]) {
352 "Failed to obtain file version info for: {}\n"
353 "Please contact the author of this script extender plugin for further assistance."sv,
354 stl::utf16_to_utf8(_filename).value_or(
"<unicode conversion error>"s)), a_failOnError);
359 static constexpr std::array SEGMENTS{
370 static constexpr
auto ENVIRONMENT = L
"SKSE_RUNTIME"sv;
371 static constexpr std::array<std::wstring_view, 2> RUNTIMES{
372 {L
"SkyrimVR.exe", L
"SkyrimSE.exe"}
375 static Module _instance;
376 static inline std::atomic_bool _initialized{
false};
377 static inline std::mutex _initLock;
379 std::wstring _filename;
380 std::wstring _filePath;
381 std::array<Segment, Segment::total> _segments;
383 std::uintptr_t _base{0};
#define SKYRIM_REL_VR
Definition: Common.h:76
#define SKYRIM_REL
Definition: Common.h:38
static SKYRIM_REL_VR bool IsVR() noexcept
Definition: Module.h:254
static SKYRIM_REL bool IsSE() noexcept
Definition: Module.h:246
static Module & get()
Definition: Module.h:82
Runtime
Definition: Module.h:63
Version version() const noexcept
Definition: Module.h:207
std::uintptr_t base() const noexcept
Definition: Module.h:201
stl::zwstring filename() const noexcept
Definition: Module.h:203
REX::W32::HMODULE pointer() const noexcept
Definition: Module.h:211
T * pointer() const noexcept
Definition: Module.h:214
stl::zwstring filePath() const noexcept
Definition: Module.h:205
Segment segment(Segment::Name a_segment) const noexcept
Definition: Module.h:209
static SKYRIM_REL Runtime GetRuntime() noexcept
Definition: Module.h:222
static SKYRIM_REL bool IsAE() noexcept
Definition: Module.h:238
std::size_t size() const noexcept
Definition: Module.h:38
void * pointer() const noexcept
Definition: Module.h:40
Name
Definition: Module.h:14
@ data
Definition: Module.h:18
@ tls
Definition: Module.h:20
@ textw
Definition: Module.h:21
@ gfids
Definition: Module.h:22
@ total
Definition: Module.h:23
@ idata
Definition: Module.h:16
@ textx
Definition: Module.h:15
@ pdata
Definition: Module.h:19
@ rdata
Definition: Module.h:17
T * pointer() const noexcept
Definition: Module.h:43
std::uintptr_t address() const noexcept
Definition: Module.h:34
Segment() noexcept=default
std::size_t offset() const noexcept
Definition: Module.h:36
std::optional< Version > GetFileVersion(stl::zwstring a_filename)
std::int32_t RegGetValueW(HKEY a_key, const wchar_t *a_subKey, const wchar_t *a_value, std::uint32_t a_flags, std::uint32_t *a_type, void *a_data, std::uint32_t *a_dataLen)
auto HKEY_LOCAL_MACHINE
Definition: ADVAPI32.h:9
HMODULE LoadLibraryW(const wchar_t *a_name) noexcept
constexpr auto IMAGE_SCN_MEM_EXECUTE
Definition: KERNEL32.h:96
constexpr auto IMAGE_SCN_MEM_WRITE
Definition: KERNEL32.h:98
HINSTANCE HMODULE
Definition: BASE.h:24
HMODULE GetModuleHandleW(const wchar_t *a_name) noexcept
std::uint32_t GetEnvironmentVariableW(const wchar_t *a_name, wchar_t *a_buf, std::uint32_t a_bufLen) noexcept
auto make_pair(T1 &&a_first, T2 &&a_second)
Definition: BSTTuple.h:177
void report_and_fail(std::string_view a_msg, std::source_location a_loc=std::source_location::current())
Definition: PCH.h:660
auto utf16_to_utf8(std::wstring_view a_in) noexcept -> std::optional< std::string >
Definition: PCH.h:570
bool report_and_error(std::string_view a_msg, bool a_fail=true, std::source_location a_loc=std::source_location::current())
Definition: PCH.h:598
basic_zstring< wchar_t > zwstring
Definition: PCH.h:78
Definition: ActorValueList.h:28