16 _mapping(a_rhs._mapping),
19 a_rhs._mapping =
nullptr;
20 a_rhs._view =
nullptr;
29 if (
this != std::addressof(a_rhs)) {
30 _mapping = a_rhs._mapping;
31 a_rhs._mapping =
nullptr;
34 a_rhs._view =
nullptr;
40 [[nodiscard]]
void*
data() noexcept {
return _view; }
49 void* _mapping{
nullptr};
76 using size_type =
typename container_type::size_type;
80 template<
class ExecutionPolicy>
82 requires(std::is_execution_policy_v<std::decay_t<ExecutionPolicy>>)
87 std::sort(a_policy, _offset2id.begin(), _offset2id.end(), [](
auto &&a_lhs,
auto &&a_rhs) {
88 return a_lhs.offset < a_rhs.offset;
96 [[nodiscard]] std::uint64_t
operator()(std::size_t a_offset)
const
98 const mapping_t elem{0, a_offset};
99 const auto it = std::lower_bound(
103 [](
auto &&a_lhs,
auto &&a_rhs) {
104 return a_lhs.offset < a_rhs.offset;
106 if (it == _offset2id.end()) {
109 "Failed to find the offset within the database: 0x{:08X}"sv,
132 if (_initialized.load(std::memory_order_relaxed)) {
135 [[maybe_unused]] std::unique_lock lock(_initLock);
137 _initialized.store(
true, std::memory_order_relaxed);
141 #ifdef ENABLE_COMMONLIBSSE_TESTING
142 [[nodiscard]]
static bool inject(std::wstring_view a_filePath,
Format a_format)
144 return inject(a_filePath, a_format,
Module::get().version());
147 [[nodiscard]]
static bool inject(std::wstring_view a_filePath,
Format a_format, Version a_version)
153 return _instance.load_file(a_filePath.data(), a_version, 1,
false);
155 return _instance.load_file(a_filePath.data(), a_version, 2,
false);
156 #ifdef ENABLE_SKYRIM_VR
158 return _instance.load_csv(a_filePath.data(), a_version,
false);
168 _initialized =
false;
172 [[nodiscard]]
inline std::size_t
id2offset(std::uint64_t a_id)
const
174 mapping_t elem{a_id, 0};
175 const auto it = std::lower_bound(
179 [](
auto &&a_lhs,
auto &&a_rhs) {
180 return a_lhs.id < a_rhs.id;
184 if (it == _id2offset.end()) {
187 if (it->id != a_id) {
194 "Failed to find the id within the address library: {}\n"
195 "This means this script extender plugin is incompatible with the address "
196 "library for this version of the game, and thus does not support it."sv,
200 return static_cast<std::size_t
>(it->offset);
209 using stream_type = std::ifstream;
210 using pointer = stream_type *;
211 using const_pointer =
const stream_type *;
212 using reference = stream_type &;
213 using const_reference =
const stream_type &;
215 inline istream_t(
stl::zwstring a_filename, std::ios_base::openmode a_mode) :
216 _stream(a_filename.data(), a_mode)
218 if (!_stream.is_open()) {
222 _stream.exceptions(std::ios::badbit | std::ios::failbit | std::ios::eofbit);
225 inline void ignore(std::streamsize a_count) { _stream.ignore(a_count); }
228 inline void readin(T &a_val)
230 _stream.read(
reinterpret_cast<char *
>(std::addressof(a_val)),
sizeof(T));
236 std::is_arithmetic_v<T>,
252 void read(istream_t &a_in, std::uint8_t a_formatVersion)
254 std::int32_t format{};
256 if (format != a_formatVersion) {
259 "Unsupported address library format: {}\n"
260 "This means this script extender plugin is incompatible with the address "
261 "library available for this version of the game, and thus does not "
266 std::int32_t version[4]{};
267 std::int32_t nameLen{};
268 a_in.readin(version);
269 a_in.readin(nameLen);
270 a_in.ignore(nameLen);
272 a_in.readin(_pointerSize);
273 a_in.readin(_addressCount);
275 for (std::size_t i = 0; i < std::extent_v<decltype(version)>; ++i) {
276 _version[i] =
static_cast<std::uint16_t
>(version[i]);
280 [[nodiscard]] std::size_t address_count() const noexcept {
return static_cast<std::size_t
>(_addressCount); }
282 [[nodiscard]] std::uint64_t pointer_size() const noexcept {
return static_cast<std::uint64_t
>(_pointerSize); }
284 [[nodiscard]] Version version() const noexcept {
return _version; }
288 std::int32_t _pointerSize{0};
289 std::int32_t _addressCount{0};
292 IDDatabase() =
default;
293 IDDatabase(
const IDDatabase&) =
delete;
294 IDDatabase(IDDatabase&&) =
delete;
296 ~IDDatabase() =
default;
298 IDDatabase& operator=(
const IDDatabase&) =
delete;
299 IDDatabase& operator=(IDDatabase&&) =
delete;
304 #ifdef ENABLE_SKYRIM_VR
306 const auto filename =
308 std::format(
"Data/SKSE/Plugins/version-{}.csv"sv, version.string()))
309 .value_or(L
"<unknown filename>"s);
310 load_csv(filename, version,
true);
313 const auto filename =
316 std::format(
"Data/SKSE/Plugins/versionlib-{}.bin"sv, version.string()) :
317 std::format(
"Data/SKSE/Plugins/version-{}.bin"sv, version.string()))
318 .value_or(L
"<unknown filename>"s);
319 load_file(filename, version,
Module::IsAE() ? 2 : 1,
true);
320 #ifdef ENABLE_SKYRIM_VR
325 bool load_file(
stl::zwstring a_filename, Version a_version, std::uint8_t a_formatVersion,
bool a_failOnError);
327 #ifdef ENABLE_SKYRIM_VR
328 bool load_csv(
stl::zwstring a_filename, Version a_version,
bool a_failOnError);
331 bool unpack_file(istream_t &a_in, header_t a_header,
bool a_failOnError)
333 std::uint8_t type = 0;
334 std::uint64_t
id = 0;
335 std::uint64_t offset = 0;
336 std::uint64_t prevID = 0;
337 std::uint64_t prevOffset = 0;
338 for (
auto& mapping: _id2offset) {
340 const auto lo =
static_cast<std::uint8_t
>(type & 0xF);
341 const auto hi =
static_cast<std::uint8_t
>(type >> 4);
351 id = prevID + a_in.readout<std::uint8_t>();
354 id = prevID - a_in.readout<std::uint8_t>();
357 id = prevID + a_in.readout<std::uint16_t>();
360 id = prevID - a_in.readout<std::uint16_t>();
363 id = a_in.readout<std::uint16_t>();
366 id = a_in.readout<std::uint32_t>();
372 const std::uint64_t tmp = (hi & 8) != 0 ? (prevOffset / a_header.pointer_size()) : prevOffset;
382 offset = tmp + a_in.readout<std::uint8_t>();
385 offset = tmp - a_in.readout<std::uint8_t>();
388 offset = tmp + a_in.readout<std::uint16_t>();
391 offset = tmp - a_in.readout<std::uint16_t>();
394 offset = a_in.readout<std::uint16_t>();
397 offset = a_in.readout<std::uint32_t>();
404 offset *= a_header.pointer_size();
407 mapping = {id, offset};
422 static IDDatabase _instance;
423 static inline std::atomic_bool _initialized{
false};
424 static inline std::mutex _initLock;
425 detail::memory_map _mmap;
426 std::span<mapping_t> _id2offset;
432 constexpr
ID() noexcept = default;
434 explicit constexpr
ID(
std::uint64_t a_id) noexcept:
446 [[nodiscard]] constexpr std::uint64_t
id() const noexcept {
return _id; }
451 [[nodiscard]]
static std::uintptr_t base() {
return Module::get().
base(); }
453 std::uint64_t _id{0};
462 [[maybe_unused]]
std::uint64_t a_seID,
463 [[maybe_unused]]
std::uint64_t a_aeID) noexcept
465 #ifdef ENABLE_SKYRIM_SE
468 #ifdef ENABLE_SKYRIM_AE
471 #ifdef ENABLE_SKYRIM_VR
477 [[maybe_unused]] std::uint64_t a_seID,
478 [[maybe_unused]] std::uint64_t a_aeID,
479 [[maybe_unused]] std::uint64_t a_vrID) noexcept
481 #ifdef ENABLE_SKYRIM_SE
484 #ifdef ENABLE_SKYRIM_AE
487 #ifdef ENABLE_SKYRIM_VR
494 auto thisOffset =
offset();
495 return thisOffset ? base() +
offset() : 0;
507 #ifdef ENABLE_SKYRIM_AE
511 #ifdef ENABLE_SKYRIM_SE
515 #ifdef ENABLE_SKYRIM_VR
529 [[nodiscard]]
static std::uintptr_t base() {
return Module::get().
base(); }
531 #ifdef ENABLE_SKYRIM_SE
532 std::uint64_t _seID{0};
534 #ifdef ENABLE_SKYRIM_AE
535 std::uint64_t _aeID{0};
537 #ifdef ENABLE_SKYRIM_VR
538 std::uint64_t _vrID{0};
548 [[maybe_unused]]
std::uint64_t a_seID,
549 [[maybe_unused]]
std::uint64_t a_aeID,
550 [[maybe_unused]]
std::uint64_t a_vrOffset) noexcept
552 #ifdef ENABLE_SKYRIM_SE
555 #ifdef ENABLE_SKYRIM_AE
558 #ifdef ENABLE_SKYRIM_VR
559 _vrOffset = a_vrOffset;
565 auto thisOffset =
offset();
566 return thisOffset ? base() +
offset() : 0;
572 #ifdef ENABLE_SKYRIM_AE
576 #ifdef ENABLE_SKYRIM_SE
580 #ifdef ENABLE_SKYRIM_VR
590 [[nodiscard]]
static std::uintptr_t base() {
return Module::get().
base(); }
592 #ifdef ENABLE_SKYRIM_SE
593 std::uint64_t _seID{0};
595 #ifdef ENABLE_SKYRIM_AE
596 std::uint64_t _aeID{0};
598 #ifdef ENABLE_SKYRIM_VR
599 std::uint64_t _vrOffset{0};
#define SKYRIM_REL_VR_CONSTEXPR
Definition: Common.h:85
#define SKYRIM_REL_CONSTEXPR
Definition: Common.h:47
#define SKYRIM_REL
Definition: Common.h:38
Offset2ID()
Definition: ID.h:92
typename container_type::const_iterator const_iterator
Definition: ID.h:77
typename container_type::const_reverse_iterator const_reverse_iterator
Definition: ID.h:78
const_reverse_iterator crbegin() const noexcept
Definition: ID.h:121
Offset2ID(ExecutionPolicy &&a_policy) requires(std
Definition: ID.h:81
const_iterator begin() const noexcept
Definition: ID.h:116
std::vector< value_type > container_type
Definition: ID.h:75
size_type size() const noexcept
Definition: ID.h:124
const_reverse_iterator rbegin() const noexcept
Definition: ID.h:120
const_reverse_iterator crend() const noexcept
Definition: ID.h:123
const_iterator cbegin() const noexcept
Definition: ID.h:117
typename container_type::size_type size_type
Definition: ID.h:76
const_iterator cend() const noexcept
Definition: ID.h:119
std::uint64_t operator()(std::size_t a_offset) const
Definition: ID.h:96
mapping_t value_type
Definition: ID.h:74
const_reverse_iterator rend() const noexcept
Definition: ID.h:122
const_iterator end() const noexcept
Definition: ID.h:118
std::size_t id2offset(std::uint64_t a_id) const
Definition: ID.h:172
Format
Definition: ID.h:65
static IDDatabase & get()
Definition: ID.h:130
std::size_t offset() const
Definition: ID.h:448
constexpr ID & operator=(std::uint64_t a_id) noexcept
Definition: ID.h:438
constexpr std::uint64_t id() const noexcept
Definition: ID.h:446
constexpr ID() noexcept=default
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 Runtime GetRuntime() noexcept
Definition: Module.h:222
static SKYRIM_REL bool IsAE() noexcept
Definition: Module.h:238
std::size_t offset() const
Definition: ID.h:498
constexpr RelocationID([[maybe_unused]] std::uint64_t a_seID, [[maybe_unused]] std::uint64_t a_aeID, [[maybe_unused]] std::uint64_t a_vrID) noexcept
Definition: ID.h:476
SKYRIM_REL std::uint64_t id() const noexcept
Definition: ID.h:504
std::uintptr_t address() const
Definition: ID.h:492
constexpr RelocationID() noexcept=default
std::uintptr_t address() const
Definition: ID.h:563
constexpr VariantID() noexcept=default
std::size_t offset() const
Definition: ID.h:569
~memory_map()
Definition: ID.h:23
void * data() noexcept
Definition: ID.h:40
memory_map & operator=(memory_map &&a_rhs) noexcept
Definition: ID.h:27
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)
requires(is_builtin_convertible_v< T >) struct GetRawType< T >
Definition: PackUnpack.h:30
void report_and_fail(std::string_view a_msg, std::source_location a_loc=std::source_location::current())
Definition: PCH.h:660
auto utf8_to_utf16(std::string_view a_in) noexcept -> std::optional< std::wstring >
Definition: PCH.h:544
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