diff --git a/include/RE/B/BGSPackIn.h b/include/RE/B/BGSPackIn.h index 96be27f..fab6632 100644 --- a/include/RE/B/BGSPackIn.h +++ b/include/RE/B/BGSPackIn.h @@ -15,11 +15,11 @@ namespace RE class BGSPackIn : public TESBoundObject, // 000 - public BGSKeywordForm, // 0E0 - public BGSPropertySheet, // 110 - public BGSPreviewTransform, // 120 - public BGSForcedLocRefType, // 168 - public BGSNativeTerminalForm // 180 + public BGSKeywordForm, // 0E8 + public BGSPropertySheet, // 118 + public BGSPreviewTransform, // 128 + public BGSForcedLocRefType, // 170 + public BGSNativeTerminalForm // 188 { public: SF_RTTI_VTABLE(BGSPackIn); @@ -28,11 +28,12 @@ namespace RE ~BGSPackIn() override; // 00 // members - TESObjectCELL* cell; // 190 - std::uint32_t flags; // 198 - BSStringT filter; // 19C - BSTArray materialSwaps; // 1B0 - std::uint32_t unk1C0; // 1C0 + TESObjectCELL* cell; // 198 + std::uint32_t flags; // 1A0 + BSString filter; // 1A4 + BSTArray materialSwaps; // 1B8 + std::uint32_t unk1C0; // 1C8 }; + static_assert(offsetof(BGSPackIn, filter) == 0x1A4); static_assert(sizeof(BGSPackIn) == 0x1D0); } diff --git a/include/RE/B/BSStringT.h b/include/RE/B/BSStringT.h index a98a998..95ef0a9 100644 --- a/include/RE/B/BSStringT.h +++ b/include/RE/B/BSStringT.h @@ -1,5 +1,7 @@ #pragma once +#include "RE/M/MemoryManager.h" + namespace RE { template @@ -33,24 +35,15 @@ namespace RE using traits_type = std::char_traits; constexpr BSStringT() noexcept = default; - - BSStringT(const BSStringT& a_rhs) { copy_from(a_rhs); } - - BSStringT(BSStringT&& a_rhs) noexcept - { - if constexpr (allocator_type::propagate_on_container_move_assignment::value) { - move_from(std::move(a_rhs)); - } else { - copy_from(a_rhs); - } - } - + BSStringT(const_pointer a_string) { Assign(a_string); } + BSStringT(const BSStringT& a_rhs) { Assign(a_rhs.c_str()); } + BSStringT(BSStringT&& a_rhs) noexcept { move_from(std::move(a_rhs)); } ~BSStringT() { release(); } BSStringT& operator=(const BSStringT& a_rhs) { if (this != std::addressof(a_rhs)) { - copy_from(a_rhs); + Assign(a_rhs.c_str()); } return *this; } @@ -58,64 +51,69 @@ namespace RE BSStringT& operator=(BSStringT&& a_rhs) noexcept { if (this != std::addressof(a_rhs)) { - if constexpr (allocator_type::propagate_on_container_move_assignment::value) { - move_from(std::move(a_rhs)); - } else { - copy_from(a_rhs); - } + release(); + move_from(std::move(a_rhs)); } return *this; } - [[nodiscard]] const_pointer data() const noexcept { return _data; } - [[nodiscard]] pointer data() noexcept { return _data; } - - [[nodiscard]] const_pointer c_str() const noexcept { return data(); } + BSStringT& operator=(const_pointer a_string) + { + Assign(a_string); + return *this; + } - [[nodiscard]] operator std::basic_string_view() const noexcept { return { data(), size() }; } + bool Assign(const_pointer a_string, std::size_t a_reserveLength = 0) + { + using func_t = bool (*)(BSStringT*, const_pointer, std::size_t); + static REL::Relocation func{ ID::BSStringT::Assign }; + return func(this, a_string, a_reserveLength); + } - [[nodiscard]] bool empty() const noexcept { return size() == 0; } + [[nodiscard]] const_pointer data() const noexcept + { + if (_capacity <= kInlineCapacity) { + return _storage; + } + pointer result; + std::memcpy(&result, _storage, sizeof(result)); + return result; + } + [[nodiscard]] pointer data() noexcept { return const_cast(std::as_const(*this).data()); } + [[nodiscard]] const_pointer c_str() const noexcept { return data(); } + [[nodiscard]] operator std::basic_string_view() const noexcept { return { data(), size() }; } + [[nodiscard]] bool empty() const noexcept { return size() == 0; } [[nodiscard]] size_type size() const noexcept { return length(); } - [[nodiscard]] size_type length() const noexcept { return _size == N ? static_cast(traits_type::length(c_str())) : _size; } - + [[nodiscard]] size_type length() const noexcept { return _size == std::numeric_limits::max() ? static_cast(traits_type::length(c_str())) : _size; } [[nodiscard]] size_type capacity() const noexcept { return _capacity; } private: - void release() - { - allocator_type::deallocate(_data, _capacity); - _data = nullptr; - _size = 0; - _capacity = 0; - } + static constexpr size_type kInlineCapacity = 0xC; - void copy_from(const BSStringT& a_rhs) + void release() { - release(); - - _size = a_rhs._size; - _capacity = a_rhs._capacity; - _data = allocator_type::allocate(_capacity); - - std::uninitialized_copy_n(a_rhs._data, _size, _data); + if (_capacity > kInlineCapacity) { + allocator_type::deallocate(data(), _capacity); + } } - void move_from(BSStringT&& a_rhs) + void move_from(BSStringT&& a_rhs) noexcept { - release(); - - _data = a_rhs._data; + std::memcpy(_storage, a_rhs._storage, sizeof(_storage)); _size = a_rhs._size; _capacity = a_rhs._capacity; - - a_rhs._data = nullptr; + a_rhs._storage[0] = '\0'; a_rhs._size = 0; - a_rhs._capacity = 0; + a_rhs._capacity = 1; } - pointer _data{}; // ?? - size_type _size{}; // ?? - size_type _capacity{}; // ?? + value_type _storage[kInlineCapacity]{}; // 00 + size_type _capacity{ 1 }; // 0C (includes the terminator) + size_type _size{}; // 0E }; + + using BSString = BSStringT; + static_assert(sizeof(BSString) == 0x10); + static_assert(alignof(BSString) == 0x2); } diff --git a/include/RE/IDs.h b/include/RE/IDs.h index 63041c5..1f46fe7 100644 --- a/include/RE/IDs.h +++ b/include/RE/IDs.h @@ -430,6 +430,11 @@ namespace RE::ID inline constexpr REL::ID Unlock{ 35630 }; } + namespace BSStringT + { + inline constexpr REL::ID Assign{ 36345 }; + } + namespace BSStringPool { namespace Entry @@ -812,7 +817,6 @@ namespace RE::ID { inline constexpr REL::ID FormatMappingRow{ 124100 }; inline constexpr REL::ID FormatMappingRowWithKeyCodes{ 124101 }; - inline constexpr REL::ID MappingRowStringDtor{ 35706 }; inline constexpr REL::ID Singleton{ 938003 }; inline constexpr REL::ID InputContextNameTable{ 360965 }; inline constexpr REL::ID LoadMappings{ 124116 }; diff --git a/include/RE/S/Script.h b/include/RE/S/Script.h index d081aa9..817646f 100644 --- a/include/RE/S/Script.h +++ b/include/RE/S/Script.h @@ -173,10 +173,11 @@ namespace RE struct ScriptVariable { // members - SCRIPT_LOCAL data; // 00 - BSStringT name; // 10 + SCRIPT_LOCAL data; // 00 + BSString name; // 0C }; - static_assert(sizeof(ScriptVariable) == 0x20); + static_assert(offsetof(ScriptVariable, name) == 0x0C); + static_assert(sizeof(ScriptVariable) == 0x1C); class Script { diff --git a/include/RE/T/TESFile.h b/include/RE/T/TESFile.h index 4c8dd5b..a8287fe 100644 --- a/include/RE/T/TESFile.h +++ b/include/RE/T/TESFile.h @@ -1,5 +1,7 @@ #pragma once +#include "RE/B/BSStringT.h" + namespace RE { class TESFile @@ -27,23 +29,6 @@ namespace RE }; static_assert(sizeof(TypedIndex) == 0x4); - struct TextData - { - private: - static constexpr inline std::uint16_t kRawCapacity = 12; - // members - const char _data[kRawCapacity]; // 00 - std::uint16_t _bufferSize; // 0C - std::uint16_t _size; // 0E - public: - const char* GetText() const - { - const char* result = _data; - return _size < kRawCapacity ? result : *std::bit_cast(result); - } - }; - static_assert(sizeof(TextData) == 0x10); - std::uint8_t pad0[0x38]; // 000 char fileName[260]; // 038 std::uint8_t pad13C[0x7B]; // 13C @@ -52,8 +37,8 @@ namespace RE std::uint8_t pad1BC[0x4]; // 1BC std::uint8_t pad1C0[0x58]; // 1C0 TypedIndex fileIndex; // 218 - TextData fileAuthor; // 21C - TextData fileDescription; // 22C + BSString fileAuthor; // 21C + BSString fileDescription; // 22C }; static_assert(offsetof(TESFile, fileFlags) == 0x1B8); static_assert(offsetof(TESFile, fileIndex) == 0x218); diff --git a/src/RE/C/ControlMap.cpp b/src/RE/C/ControlMap.cpp index 62edd2b..ae8cffc 100644 --- a/src/RE/C/ControlMap.cpp +++ b/src/RE/C/ControlMap.cpp @@ -1,46 +1,18 @@ #include "RE/C/ControlMap.h" -#include +#include "RE/B/BSStringT.h" namespace RE { - namespace - { - struct alignas(8) MappingRowString - { - ~MappingRowString() - { - static REL::Relocation destroy{ ID::ControlMap::MappingRowStringDtor }; - destroy(this); - } - - [[nodiscard]] const char* c_str() const - { - if (capacity <= sizeof(storage)) { - return storage; - } - const char* data; - std::memcpy(&data, storage, sizeof(data)); - return data; - } - - char storage[0xC]{}; - std::uint16_t capacity{ 1 }; - std::uint16_t unk0E{}; - }; - static_assert(sizeof(MappingRowString) == 0x10); - static_assert(offsetof(MappingRowString, capacity) == 0xC); - } - std::string ControlMap::FormatMappingRow( const char* a_event, const char* a_keyboard, const char* a_mouse, const char* a_gamepad, bool a_keyboardVisible, bool a_mouseVisible, bool a_gamepadVisible, std::uint32_t a_controlMask, std::uint32_t a_groupMask, bool a_required) { - using func_t = MappingRowString* (*)(MappingRowString*, const char*, const char*, const char*, const char*, + using func_t = BSString* (*)(BSString*, const char*, const char*, const char*, const char*, bool, bool, bool, std::uint32_t, std::uint32_t, bool); static REL::Relocation func{ ID::ControlMap::FormatMappingRow }; - MappingRowString text; + BSString text; func(&text, a_event, a_keyboard, a_mouse, a_gamepad, a_keyboardVisible, a_mouseVisible, a_gamepadVisible, a_controlMask, a_groupMask, a_required); return text.c_str(); @@ -51,10 +23,10 @@ namespace RE bool a_keyboardVisible, bool a_mouseVisible, bool a_gamepadVisible, std::uint32_t a_controlMask, std::uint32_t a_groupMask, bool a_required) { - using func_t = MappingRowString* (*)(MappingRowString*, const char*, std::uint32_t, std::uint32_t, std::uint32_t, + using func_t = BSString* (*)(BSString*, const char*, std::uint32_t, std::uint32_t, std::uint32_t, bool, bool, bool, std::uint32_t, std::uint32_t, bool); static REL::Relocation func{ ID::ControlMap::FormatMappingRowWithKeyCodes }; - MappingRowString text; + BSString text; func(&text, a_event, a_keyboard, a_mouse, a_gamepad, a_keyboardVisible, a_mouseVisible, a_gamepadVisible, a_controlMask, a_groupMask, a_required); return text.c_str();