Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions include/RE/B/BGSPackIn.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -28,11 +28,12 @@ namespace RE
~BGSPackIn() override; // 00

// members
TESObjectCELL* cell; // 190
std::uint32_t flags; // 198
BSStringT<char> filter; // 19C
BSTArray<BGSLayeredMaterialSwap*> materialSwaps; // 1B0
std::uint32_t unk1C0; // 1C0
TESObjectCELL* cell; // 198
std::uint32_t flags; // 1A0
BSString filter; // 1A4
BSTArray<BGSLayeredMaterialSwap*> materialSwaps; // 1B8
std::uint32_t unk1C0; // 1C8
};
static_assert(offsetof(BGSPackIn, filter) == 0x1A4);
static_assert(sizeof(BGSPackIn) == 0x1D0);
}
100 changes: 49 additions & 51 deletions include/RE/B/BSStringT.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#include "RE/M/MemoryManager.h"

namespace RE
{
template <class CharT, std::uint16_t>
Expand Down Expand Up @@ -33,89 +35,85 @@ namespace RE
using traits_type = std::char_traits<value_type>;

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;
}

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<value_type, traits_type>() 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_t> 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<pointer>(std::as_const(*this).data()); }
[[nodiscard]] const_pointer c_str() const noexcept { return data(); }
[[nodiscard]] operator std::basic_string_view<value_type, traits_type>() 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<size_type>(traits_type::length(c_str())) : _size; }

[[nodiscard]] size_type length() const noexcept { return _size == std::numeric_limits<size_type>::max() ? static_cast<size_type>(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<char>;
static_assert(sizeof(BSString) == 0x10);
static_assert(alignof(BSString) == 0x2);
}
6 changes: 5 additions & 1 deletion include/RE/IDs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 };
Expand Down
7 changes: 4 additions & 3 deletions include/RE/S/Script.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,11 @@ namespace RE
struct ScriptVariable
{
// members
SCRIPT_LOCAL data; // 00
BSStringT<char> 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
{
Expand Down
23 changes: 4 additions & 19 deletions include/RE/T/TESFile.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#include "RE/B/BSStringT.h"

namespace RE
{
class TESFile
Expand Down Expand Up @@ -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<const char**>(result);
}
};
static_assert(sizeof(TextData) == 0x10);

std::uint8_t pad0[0x38]; // 000
char fileName[260]; // 038
std::uint8_t pad13C[0x7B]; // 13C
Expand All @@ -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);
Expand Down
38 changes: 5 additions & 33 deletions src/RE/C/ControlMap.cpp
Original file line number Diff line number Diff line change
@@ -1,46 +1,18 @@
#include "RE/C/ControlMap.h"

#include <cstring>
#include "RE/B/BSStringT.h"

namespace RE
{
namespace
{
struct alignas(8) MappingRowString
{
~MappingRowString()
{
static REL::Relocation<void (*)(MappingRowString*)> 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_t> 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();
Expand All @@ -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_t> 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();
Expand Down
Loading