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;
39 [[nodiscard]]
void*
data() noexcept {
return _view; }
46 void* _mapping{
nullptr };
47 void* _view{
nullptr };
66 using size_type =
typename container_type::size_type;
70 template <
class ExecutionPolicy>
72 requires(std::is_execution_policy_v<std::decay_t<ExecutionPolicy>>)
77 std::sort(a_policy, _offset2id.begin(), _offset2id.end(), [](
auto&& a_lhs,
auto&& a_rhs) {
78 return a_lhs.offset < a_rhs.offset;
86 [[nodiscard]] std::uint64_t
operator()(std::size_t a_offset)
const
88 const mapping_t elem{ 0, a_offset };
89 const auto it = std::lower_bound(
93 [](
auto&& a_lhs,
auto&& a_rhs) {
94 return a_lhs.offset < a_rhs.offset;
96 if (it == _offset2id.end()) {
99 "Failed to find the offset within the database: 0x{:08X}"sv,
130 [[nodiscard]]
inline std::size_t
id2offset(std::uint64_t a_id)
const
132 mapping_t elem{ a_id, 0 };
133 const auto it = std::lower_bound(
137 [](
auto&& a_lhs,
auto&& a_rhs) {
138 return a_lhs.id < a_rhs.id;
140 if (it == _id2offset.end()) {
143 "Failed to find the id within the address library: {}\n"
144 "This means this script extender plugin is incompatible with the address "
145 "library for this version of the game, and thus does not support it."sv,
149 return static_cast<std::size_t
>(it->offset);
158 void read(binary_io::file_istream& a_in)
160 const auto [format] = a_in.read<std::int32_t>();
161 #ifdef SKYRIM_SUPPORT_AE
168 "Unsupported address library format: {}\n"
169 "This means this script extender plugin is incompatible with the address "
170 "library available for this version of the game, and thus does not "
175 const auto [major, minor, patch, revision] =
176 a_in.read<std::int32_t, std::int32_t, std::int32_t, std::int32_t>();
177 _version[0] =
static_cast<std::uint16_t
>(major);
178 _version[1] =
static_cast<std::uint16_t
>(minor);
179 _version[2] =
static_cast<std::uint16_t
>(patch);
180 _version[3] =
static_cast<std::uint16_t
>(revision);
182 const auto [nameLen] = a_in.read<std::int32_t>();
183 a_in.seek_relative(nameLen);
185 a_in.read(_pointerSize, _addressCount);
188 [[nodiscard]] std::size_t address_count() const noexcept {
return static_cast<std::size_t
>(_addressCount); }
189 [[nodiscard]] std::uint64_t pointer_size() const noexcept {
return static_cast<std::uint64_t
>(_pointerSize); }
190 [[nodiscard]] Version version() const noexcept {
return _version; }
194 std::int32_t _pointerSize{ 0 };
195 std::int32_t _addressCount{ 0 };
198 IDDatabase() { load(); }
200 IDDatabase(
const IDDatabase&) =
delete;
201 IDDatabase(IDDatabase&&) =
delete;
203 ~IDDatabase() =
default;
205 IDDatabase& operator=(
const IDDatabase&) =
delete;
206 IDDatabase& operator=(IDDatabase&&) =
delete;
211 const auto filename =
214 #ifdef SKYRIM_SUPPORT_AE
215 "Data/SKSE/Plugins/versionlib-{}.bin"sv,
217 "Data/SKSE/Plugins/version-{}.bin"sv,
220 .value_or(L
"<unknown filename>"s);
221 load_file(filename, version);
227 binary_io::file_istream in(a_filename);
230 if (header.version() != a_version) {
234 auto mapname = L
"CommonLibSSEOffsets-v2-"s;
235 mapname += a_version.wstring();
236 const auto byteSize =
static_cast<std::size_t
>(header.address_count()) *
sizeof(mapping_t);
237 if (_mmap.open(mapname, byteSize)) {
238 _id2offset = {
static_cast<mapping_t*
>(_mmap.data()), header.address_count() };
239 }
else if (_mmap.create(mapname, byteSize)) {
240 _id2offset = {
static_cast<mapping_t*
>(_mmap.data()), header.address_count() };
241 unpack_file(in, header);
245 [](
auto&& a_lhs,
auto&& a_rhs) {
246 return a_lhs.id < a_rhs.id;
251 }
catch (
const std::system_error&) {
254 "Failed to locate an appropriate address library with the path: {}\n"
255 "This means you are missing the address library for this specific version of "
256 "the game. Please continue to the mod page for address library to download "
257 "an appropriate version. If one is not available, then it is likely that "
258 "address library has not yet added support for this version of the game."sv,
263 void unpack_file(binary_io::file_istream& a_in, header_t a_header)
265 std::uint8_t type = 0;
266 std::uint64_t
id = 0;
267 std::uint64_t offset = 0;
268 std::uint64_t prevID = 0;
269 std::uint64_t prevOffset = 0;
270 for (
auto& mapping : _id2offset) {
272 const auto lo =
static_cast<std::uint8_t
>(type & 0xF);
273 const auto hi =
static_cast<std::uint8_t
>(type >> 4);
283 id = prevID + std::get<0>(a_in.read<std::uint8_t>());
286 id = prevID - std::get<0>(a_in.read<std::uint8_t>());
289 id = prevID + std::get<0>(a_in.read<std::uint16_t>());
292 id = prevID - std::get<0>(a_in.read<std::uint16_t>());
295 std::tie(
id) = a_in.read<std::uint16_t>();
298 std::tie(
id) = a_in.read<std::uint32_t>();
304 const std::uint64_t tmp = (hi & 8) != 0 ? (prevOffset / a_header.pointer_size()) : prevOffset;
314 offset = tmp + std::get<0>(a_in.read<std::uint8_t>());
317 offset = tmp - std::get<0>(a_in.read<std::uint8_t>());
320 offset = tmp + std::get<0>(a_in.read<std::uint16_t>());
323 offset = tmp - std::get<0>(a_in.read<std::uint16_t>());
326 std::tie(offset) = a_in.read<std::uint16_t>();
329 std::tie(offset) = a_in.read<std::uint32_t>();
336 offset *= a_header.pointer_size();
339 mapping = { id, offset };
346 detail::memory_map _mmap;
347 std::span<mapping_t> _id2offset;
353 constexpr
ID() noexcept = default;
355 explicit constexpr
ID(
std::uint64_t a_id) noexcept :
365 [[nodiscard]] std::uintptr_t
address()
const {
return base() + offset(); }
366 [[nodiscard]] constexpr std::uint64_t
id() const noexcept {
return _id; }
370 [[nodiscard]]
static std::uintptr_t base() {
return Module::get().
base(); }
372 std::uint64_t _id{ 0 };
Offset2ID()
Definition: ID.h:82
typename container_type::const_iterator const_iterator
Definition: ID.h:67
typename container_type::const_reverse_iterator const_reverse_iterator
Definition: ID.h:68
const_reverse_iterator crbegin() const noexcept
Definition: ID.h:113
Offset2ID(ExecutionPolicy &&a_policy) requires(std
Definition: ID.h:71
const_iterator begin() const noexcept
Definition: ID.h:106
std::vector< value_type > container_type
Definition: ID.h:65
size_type size() const noexcept
Definition: ID.h:118
const_reverse_iterator rbegin() const noexcept
Definition: ID.h:112
const_reverse_iterator crend() const noexcept
Definition: ID.h:116
const_iterator cbegin() const noexcept
Definition: ID.h:107
typename container_type::size_type size_type
Definition: ID.h:66
const_iterator cend() const noexcept
Definition: ID.h:110
std::uint64_t operator()(std::size_t a_offset) const
Definition: ID.h:86
mapping_t value_type
Definition: ID.h:64
const_reverse_iterator rend() const noexcept
Definition: ID.h:115
const_iterator end() const noexcept
Definition: ID.h:109
std::size_t id2offset(std::uint64_t a_id) const
Definition: ID.h:130
static IDDatabase & get()
Definition: ID.h:124
std::size_t offset() const
Definition: ID.h:367
constexpr ID & operator=(std::uint64_t a_id) noexcept
Definition: ID.h:359
constexpr std::uint64_t id() const noexcept
Definition: ID.h:366
constexpr ID() noexcept=default
std::uintptr_t address() const
Definition: ID.h:365
static Module & get()
Definition: Module.h:54
Version version() const noexcept
Definition: Module.h:62
std::uintptr_t base() const noexcept
Definition: Module.h:60
~memory_map()
Definition: ID.h:23
void * data() noexcept
Definition: ID.h:39
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)
void report_and_fail(std::string_view a_msg, std::source_location a_loc=std::source_location::current())
Definition: PCH.h:396
auto utf16_to_utf8(std::wstring_view a_in) noexcept -> std::optional< std::string >
Definition: PCH.h:368
auto utf8_to_utf16(std::string_view a_in) noexcept -> std::optional< std::wstring >
Definition: PCH.h:342
requires(std::invocable< std::remove_reference_t< EF >>) class scope_exit
Definition: PCH.h:153
basic_zstring< wchar_t > zwstring
Definition: PCH.h:82
Definition: EffectArchetypes.h:65