From 14369a8b90c478e00c44fa5866c4ba457c73edbe Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 10:57:48 -0700 Subject: [PATCH 01/39] fix: rename IFunction::TranslateIPToLineNumber --- CommonLibSF/include/RE/I/IFunction.h | 2 +- CommonLibSF/include/RE/N/NativeFunctionBase.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CommonLibSF/include/RE/I/IFunction.h b/CommonLibSF/include/RE/I/IFunction.h index 86cfcf04..b8c00153 100644 --- a/CommonLibSF/include/RE/I/IFunction.h +++ b/CommonLibSF/include/RE/I/IFunction.h @@ -43,7 +43,7 @@ namespace RE::BSScript virtual void Unk_0E(std::uint32_t a_unk) = 0; virtual std::uint32_t Invoke(std::uint64_t a_unk0, std::uint64_t a_unk1, VMClassRegistry* a_registry, VMState* a_unk3) = 0; virtual BSFixedString* Unk_10(void) = 0; // file/line number? - virtual bool Unk_11(std::uint32_t a_unk0, std::uint32_t* a_unk1) = 0; + virtual bool TranslateIPToLineNumber(std::uint32_t a_instructionPointer, std::uint32_t* r_lineNumber) = 0; virtual std::uint64_t* Unk_12(std::uint64_t* a_out) = 0; // new, might be type reflection virtual Unk13 Unk_13(Unk13* a_out) = 0; // new, might be type reflection virtual bool GetParamInfo(std::uint32_t a_idx, void* a_out) = 0; // param list stuff diff --git a/CommonLibSF/include/RE/N/NativeFunctionBase.h b/CommonLibSF/include/RE/N/NativeFunctionBase.h index 9ddd8b44..e4528dc1 100644 --- a/CommonLibSF/include/RE/N/NativeFunctionBase.h +++ b/CommonLibSF/include/RE/N/NativeFunctionBase.h @@ -80,10 +80,10 @@ namespace RE::BSScript REL::Relocation func{ ID::BSScript::Internal::NF_util::NativeFunctionBase::Unk_10 }; return func(this); } - virtual bool Unk_11(std::uint32_t a_unk0, std::uint32_t* a_unk1) override + virtual bool TranslateIPToLineNumber(std::uint32_t a_IP, std::uint32_t* r_lineNumber) override { - (void)a_unk0; - *a_unk1 = 0; + (void)a_IP; + *r_lineNumber = 0; return false; } virtual std::uint64_t* Unk_12(std::uint64_t* a_out) override From 032c39053b3640b57e2562b448679ec541fcd6eb Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 10:57:48 -0700 Subject: [PATCH 02/39] feat: add IRemoteDebugger, RemoteDebugger --- CommonLibSF/include/RE/D/DebuggerMessages.h | 1 + CommonLibSF/include/RE/I/IRemoteDebugger.h | 19 ++++ CommonLibSF/include/RE/I/idTCP.h | 1 + CommonLibSF/include/RE/IDs.h | 16 ++++ CommonLibSF/include/RE/R/RemoteDebugger.h | 100 ++++++++++++++++++++ CommonLibSF/include/RE/Starfield.h | 2 + CommonLibSF/src/RE/R/RemoteDebugger.cpp | 53 +++++++++++ 7 files changed, 192 insertions(+) create mode 100644 CommonLibSF/include/RE/I/IRemoteDebugger.h create mode 100644 CommonLibSF/include/RE/R/RemoteDebugger.h create mode 100644 CommonLibSF/src/RE/R/RemoteDebugger.cpp diff --git a/CommonLibSF/include/RE/D/DebuggerMessages.h b/CommonLibSF/include/RE/D/DebuggerMessages.h index 56cd5869..756e0121 100644 --- a/CommonLibSF/include/RE/D/DebuggerMessages.h +++ b/CommonLibSF/include/RE/D/DebuggerMessages.h @@ -2,6 +2,7 @@ #include "RE/B/BSFixedString.h" #include "RE/B/BSLog.h" +#include "RE/F/FormTypes.h" static_assert(sizeof(std::string) == 0x20); // If this fails, _ITERATOR_DEBUG_LEVEL is greater than 0 static_assert(sizeof(std::vector) == 0x18); diff --git a/CommonLibSF/include/RE/I/IRemoteDebugger.h b/CommonLibSF/include/RE/I/IRemoteDebugger.h new file mode 100644 index 00000000..c2ba33c4 --- /dev/null +++ b/CommonLibSF/include/RE/I/IRemoteDebugger.h @@ -0,0 +1,19 @@ +#pragma once + +#include "RE/E/ErrorLogger.h" +namespace RE::BSScript +{ + class IVMRemoteDebuggerInterface; + class StackFrame; + class __declspec(novtable) IRemoteDebugger + { + ~IRemoteDebugger() = delete; + + virtual void SetVMRemoteDebuggerInterface(IVMRemoteDebuggerInterface* a_interface) = 0; // 00 + virtual bool IsPaused() = 0; // 01 + virtual bool CheckForBreakpoint(StackFrame& a_frame) = 0; // 02 + virtual void EmitThreadEvent(std::uint32_t a_threadId, bool a_exited) = 0; // 03 + virtual void EmitOutputEvent(const ICachedErrorMessage& a_message, ErrorLogger::Severity a_severity) = 0; // 04 + virtual void SendQueuedMessage(bool isPaused) = 0; // 05 + }; +} \ No newline at end of file diff --git a/CommonLibSF/include/RE/I/idTCP.h b/CommonLibSF/include/RE/I/idTCP.h index 13632d0c..b3db24b0 100644 --- a/CommonLibSF/include/RE/I/idTCP.h +++ b/CommonLibSF/include/RE/I/idTCP.h @@ -25,6 +25,7 @@ namespace RE class idTCP { + public: SF_RTTI_VTABLE(idTCP); virtual ~idTCP(); // 00 diff --git a/CommonLibSF/include/RE/IDs.h b/CommonLibSF/include/RE/IDs.h index 47a8109d..be37e0ef 100644 --- a/CommonLibSF/include/RE/IDs.h +++ b/CommonLibSF/include/RE/IDs.h @@ -180,6 +180,22 @@ namespace RE::ID inline constexpr REL::ID HasType{ 83208 }; } + namespace GameScript + { + namespace RemoteDebugger + { + inline constexpr REL::ID HandleContinueRequest{ 167579 }; + inline constexpr REL::ID HandleDisconnectRequest{ 167580 }; + inline constexpr REL::ID HandlePauseRequest{ 167581 }; + inline constexpr REL::ID HandleSetBreakpointsRequest{ 167582 }; + inline constexpr REL::ID HandleStackTraceRequest{ 167583 }; + inline constexpr REL::ID HandleThreadsRequest{ 167584 }; + inline constexpr REL::ID HandleValueRequest{ 167585 }; + inline constexpr REL::ID HandleVariablesRequest{ 167586 }; + inline constexpr REL::ID HandleStepRequest{ 167587 }; + } + } + namespace idLogging { inline constexpr REL::ID singleton{ 895197 }; diff --git a/CommonLibSF/include/RE/R/RemoteDebugger.h b/CommonLibSF/include/RE/R/RemoteDebugger.h new file mode 100644 index 00000000..be15e0b1 --- /dev/null +++ b/CommonLibSF/include/RE/R/RemoteDebugger.h @@ -0,0 +1,100 @@ +#pragma once + +#include "RE/B/BSFixedString.h" +#include "RE/D/DebuggerMessages.h" +#include "RE/I/IRemoteDebugger.h" +#include "RE/I/idTCP.h" +namespace RE::GameScript +{ + + class RemoteDebugger : BSScript::IRemoteDebugger + { + public: + struct Breakpoint + { + BSFixedString className; + BSFixedString stateName; + BSFixedString functionName; + std::uint32_t instructionPointer; + }; + + enum class StepKind : std::uint8_t + { + kNext, + kStepIn, + kStepOut + }; + + struct StackFramePointer + { + std::uint32_t threadId; + int stackFrameIndex; + std::uint32_t lineNumber; + int instructionPointer; + StepKind stepKind; + }; + + struct TCPServer + { + idTCP listenTCP; // 00 + idTCP readWriteTCP; // 20 + BSNonReentrantSpinLock lock; // 40 + }; + static_assert(sizeof(TCPServer) == 0x48); + + struct VMRemoteInterfaceStruct + { + void* listenThread; // 00 + BSScript::IVMRemoteDebuggerInterface* VMRemoteDebuggerIface; // 08 + BSReadWriteLock lock; // 10 + }; + static_assert(sizeof(VMRemoteInterfaceStruct) == 0x18); + + struct State + { + msvc::unique_ptr PauseResponse; // 00 + msvc::unique_ptr ContinueResponse; // 08 + msvc::unique_ptr StoppedEvent; // 10 + std::vector breakpoints; // 18 -- TODO: use BSTHeapSTLAllocator + std::vector stackFramePointers; // 30 -- TODO: use BSTHeapSTLAllocator + bool paused; // 48 + BSReadWriteLock lock; // 50 + }; + static_assert(sizeof(State) == 0x58); + + ~RemoteDebugger() = delete; + + // override IRemoteDebugger + virtual void SetVMRemoteDebuggerInterface(BSScript::IVMRemoteDebuggerInterface* a_interface) override; // 00 + virtual bool IsPaused() override; // 01 + virtual bool CheckForBreakpoint(BSScript::StackFrame& a_frame) override; // 02 + virtual void EmitThreadEvent(std::uint32_t a_threadId, bool a_exited) override; // 03 + virtual void EmitOutputEvent(const BSScript::ICachedErrorMessage& a_message, BSScript::ErrorLogger::Severity a_severity) override; // 04 + virtual void SendQueuedMessage(bool a_isPaused) override; // 05 + + BSLog* GetLogger(); + + void HandleContinueRequest(const DebuggerMessages::ContinueRequest& a_request); + void HandleDisconnectRequest(const DebuggerMessages::DisconnectRequest& a_request); + void HandlePauseRequest(const DebuggerMessages::PauseRequest& a_request); + void HandleSetBreakpointsRequest(const DebuggerMessages::SetBreakpointsRequest& a_request); + void HandleStackTraceRequest(const DebuggerMessages::StackTraceRequest& a_request); + void HandleStepRequest(const DebuggerMessages::Request& a_request, uint32_t a_threadid, StepKind a_stepKind); + void HandleThreadsRequest(const DebuggerMessages::ThreadsRequest& a_request); + void HandleValueRequest(const DebuggerMessages::ValueRequest& a_request); + void HandleVariablesRequest(const DebuggerMessages::VariablesRequest& a_request); + + private: + void ListenLoop(std::uint16_t port); + + public: + // members + bool active; // 08 + TCPServer tcpServer; // 10 + State statestruct; // 58 + VMRemoteInterfaceStruct VMremoteIfaceStruct; // B0 + BSLog* logger; // C8 + BSNonReentrantSpinLock logLock; // D0 + }; + static_assert(sizeof(RemoteDebugger) == 0xD8); +} \ No newline at end of file diff --git a/CommonLibSF/include/RE/Starfield.h b/CommonLibSF/include/RE/Starfield.h index 7a7929ac..050776e3 100644 --- a/CommonLibSF/include/RE/Starfield.h +++ b/CommonLibSF/include/RE/Starfield.h @@ -245,6 +245,7 @@ #include "RE/I/INISettingCollection.h" #include "RE/I/IObjectHandlePolicy.h" #include "RE/I/IPostAnimationChannelUpdateFunctor.h" +#include "RE/I/IRemoteDebugger.h" #include "RE/I/ISavePatcherInterface.h" #include "RE/I/IStoreAnimationActions.h" #include "RE/I/IVMDebugInterface.h" @@ -293,6 +294,7 @@ #include "RE/P/PropertyTypeInfo.h" #include "RE/R/RawFuncCallQuery.h" #include "RE/R/RegSettingCollection.h" +#include "RE/R/RemoteDebugger.h" #include "RE/RTTI.h" #include "RE/S/SWFToCodeFunctionHandler.h" #include "RE/S/SavePatcher.h" diff --git a/CommonLibSF/src/RE/R/RemoteDebugger.cpp b/CommonLibSF/src/RE/R/RemoteDebugger.cpp new file mode 100644 index 00000000..4f90eb40 --- /dev/null +++ b/CommonLibSF/src/RE/R/RemoteDebugger.cpp @@ -0,0 +1,53 @@ +#include "RE/R/RemoteDebugger.h" +namespace RE::GameScript +{ + void RemoteDebugger::HandleContinueRequest(const DebuggerMessages::ContinueRequest& a_request) + { + using func_t = decltype(&RemoteDebugger::HandleContinueRequest); + REL::Relocation func{ ID::GameScript::RemoteDebugger::HandleContinueRequest }; + return func(this, a_request); + } + void RemoteDebugger::HandleDisconnectRequest(const DebuggerMessages::DisconnectRequest& a_request) + { + using func_t = decltype(&RemoteDebugger::HandleDisconnectRequest); + REL::Relocation func{ ID::GameScript::RemoteDebugger::HandleDisconnectRequest }; + return func(this, a_request); + } + void RemoteDebugger::HandlePauseRequest(const DebuggerMessages::PauseRequest& a_request) + { + using func_t = decltype(&RemoteDebugger::HandlePauseRequest); + REL::Relocation func{ ID::GameScript::RemoteDebugger::HandlePauseRequest }; + return func(this, a_request); + } + void RemoteDebugger::HandleSetBreakpointsRequest(const DebuggerMessages::SetBreakpointsRequest& a_request) + { + using func_t = decltype(&RemoteDebugger::HandleSetBreakpointsRequest); + REL::Relocation func{ ID::GameScript::RemoteDebugger::HandleSetBreakpointsRequest }; + return func(this, a_request); + } + void RemoteDebugger::HandleStackTraceRequest(const DebuggerMessages::StackTraceRequest& a_request) + { + using func_t = decltype(&RemoteDebugger::HandleStackTraceRequest); + REL::Relocation func{ ID::GameScript::RemoteDebugger::HandleStackTraceRequest }; + return func(this, a_request); + } + void RemoteDebugger::HandleStepRequest(const DebuggerMessages::Request& a_request, uint32_t a_threadid, StepKind a_stepKind) + { + using func_t = decltype(&RemoteDebugger::HandleStepRequest); + REL::Relocation func{ ID::GameScript::RemoteDebugger::HandleStepRequest }; + return func(this, a_request, a_threadid, a_stepKind); + } + void RemoteDebugger::HandleVariablesRequest(const DebuggerMessages::VariablesRequest& a_request) + { + using func_t = decltype(&RemoteDebugger::HandleVariablesRequest); + REL::Relocation func{ ID::GameScript::RemoteDebugger::HandleVariablesRequest }; + return func(this, a_request); + } + void RemoteDebugger::HandleValueRequest(const DebuggerMessages::ValueRequest& a_request) + { + using func_t = decltype(&RemoteDebugger::HandleValueRequest); + REL::Relocation func{ ID::GameScript::RemoteDebugger::HandleValueRequest }; + return func(this, a_request); + } + +} From 642f67effdd07becf664ea6a442485101db3179d Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 10:57:48 -0700 Subject: [PATCH 03/39] feat: add MemoryManager::GetThreadScrapHeap() --- CommonLibSF/include/RE/IDs.h | 1 + CommonLibSF/include/RE/M/MemoryManager.h | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/CommonLibSF/include/RE/IDs.h b/CommonLibSF/include/RE/IDs.h index be37e0ef..ed759e4f 100644 --- a/CommonLibSF/include/RE/IDs.h +++ b/CommonLibSF/include/RE/IDs.h @@ -231,6 +231,7 @@ namespace RE::ID inline constexpr REL::ID GetSingleton{ 33961 }; inline constexpr REL::ID Allocate{ 33962 }; inline constexpr REL::ID Free{ 34032 }; + inline constexpr REL::ID GetThreadScrapHeap{ 36848 }; } namespace Misc diff --git a/CommonLibSF/include/RE/M/MemoryManager.h b/CommonLibSF/include/RE/M/MemoryManager.h index f9a9be42..0b3a53ab 100644 --- a/CommonLibSF/include/RE/M/MemoryManager.h +++ b/CommonLibSF/include/RE/M/MemoryManager.h @@ -2,6 +2,9 @@ namespace RE { + + class ScrapHeap; + class MemoryManager { public: @@ -25,6 +28,13 @@ namespace RE const REL::Relocation func{ ID::MemoryManager::Free }; return func(this, a_ptr, a_alignmentRequired); } + + ScrapHeap* GetThreadScrapHeap() + { + using func_t = decltype(&MemoryManager::GetThreadScrapHeap); + const REL::Relocation func{ ID::MemoryManager::GetThreadScrapHeap }; + return func(this); + } }; [[nodiscard]] inline void* malloc(std::size_t a_size, std::size_t a_alignment = 0) From 390ff22d21cc8b672f17db00d7cbb383266600c8 Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 10:57:48 -0700 Subject: [PATCH 04/39] feat: Add ScrapHeap and associated interfaces --- CommonLibSF/include/RE/M/MemoryManager.h | 265 +++++++++++++++++++++++ 1 file changed, 265 insertions(+) diff --git a/CommonLibSF/include/RE/M/MemoryManager.h b/CommonLibSF/include/RE/M/MemoryManager.h index 0b3a53ab..6a553f31 100644 --- a/CommonLibSF/include/RE/M/MemoryManager.h +++ b/CommonLibSF/include/RE/M/MemoryManager.h @@ -4,6 +4,10 @@ namespace RE { class ScrapHeap; + struct HeapStats; + struct MemoryStats; + + enum class MEM_CONTEXT : std::int32_t; class MemoryManager { @@ -72,6 +76,267 @@ namespace RE auto mem = MemoryManager::GetSingleton(); mem->Free(a_ptr, a_alignmentRequired); } + + class __declspec(novtable) IMemoryStoreBase + { + public: + static constexpr auto RTTI{ RTTI::IMemoryStoreBase }; + static constexpr auto VTABLE{ VTABLE::IMemoryStoreBase }; + + virtual ~IMemoryStoreBase() = default; // 00 + + // add + virtual std::size_t Size(void const* a_mem) const = 0; // 01 + virtual void GetMemoryStats(MemoryStats* a_stats) = 0; // 02 + virtual bool ContainsBlockImpl(const void* a_block) const = 0; // 03 + }; + static_assert(sizeof(IMemoryStoreBase) == 0x8); + + class __declspec(novtable) IMemoryStore : + public IMemoryStoreBase // 0 + { + public: + static constexpr auto RTTI{ RTTI::IMemoryStore }; + static constexpr auto VTABLE{ VTABLE::IMemoryStore }; + + // NOLINTNEXTLINE(modernize-use-override) + virtual ~IMemoryStore() = default; // 00 + + // add + virtual void* AllocateAlignImpl(std::size_t a_size, std::uint32_t a_alignment) = 0; // 04 + virtual void DeallocateAlignImpl(void*& a_block) = 0; // 05 + virtual void* TryAllocateImpl([[maybe_unused]] std::size_t a_size, [[maybe_unused]] std::uint32_t a_alignment) { return nullptr; } // 06 + }; + static_assert(sizeof(IMemoryStore) == 0x8); + + class __declspec(novtable) IMemoryHeap : + public IMemoryStore // 00 + { + public: + static constexpr auto RTTI{ RTTI::IMemoryHeap }; + //static constexpr auto VTABLE{ VTABLE::IMemoryHeap }; -- optimized out? + + // NOLINTNEXTLINE(modernize-use-override) + virtual ~IMemoryHeap() = default; + + // override (IMemoryStore) + bool ContainsBlockImpl(const void* a_block) const override { return PointerInHeap(a_block); } // 03 + void* AllocateAlignImpl(std::size_t a_size, std::uint32_t a_alignment) override { return Allocate(a_size, a_alignment); } // 04 + void DeallocateAlignImpl(void*& a_block) override { Deallocate(a_block, 0); } // 05 + + // add + virtual const char* GetName() const = 0; // 07 + virtual void Unk08() = 0; // 08 -- Sets value of ptr[rax] to 0 in all implementations? + virtual void Unk09() = 0; // 09 -- Same here + virtual void* Allocate(std::size_t a_size, std::uint32_t a_alignment) = 0; // 0A + virtual void Deallocate(void* a_mem, std::uint32_t) = 0; // 0B + virtual bool PointerInHeap(const void* a_pointer) const = 0; // 0C + virtual std::size_t TotalSize(const void* a_pointer) const = 0; // 0D + virtual void GetHeapStats(HeapStats* a_stats, bool a_fullBlockInfo) = 0; // 0E + virtual bool ShouldTrySmallBlockPools(std::size_t a_size, MEM_CONTEXT a_context) = 0; // 0F + virtual std::uint32_t GetPageSize() const = 0; // 10 + }; + static_assert(sizeof(IMemoryHeap) == 0x8); + + template + class __declspec(novtable) TAllocatorAddressSpace : + public store_type // 00 + { + // This is a templated class that overrides Unk08, Unk09, Allocate, and Deallocate. + // The only classes that seem to be used with it are IMemoryHeap and BSFixedSizeBlockAllocator::BuddyAllocTag + // Also seems to have member variables that are not used in the functions that are overridden. + + // TODO: implement an allocator traits class to test if store_type interface has these functions + + // override (store_type) + virtual void Unk08() override; // ?? + virtual void Unk09() override; // ?? + virtual void* Allocate(std::size_t a_size, std::uint32_t a_alignment) override; // ?? + virtual void Deallocate(void* a_mem, std::uint32_t) override; // ?? + }; + + class HeapAllocator : + public TAllocatorAddressSpace // 00 + { + public: + SF_RTTI_VTABLE(HeapAllocator); + + // NOLINTNEXTLINE(modernize-use-override) + virtual ~HeapAllocator(); // 00 + // override (IMemoryStoreBase) + std::size_t Size(void const* a_mem) const override; // 01 + void GetMemoryStats(MemoryStats* a_stats) override; // 02 + bool ContainsBlockImpl(const void* a_block) const override; // 03 + + // override (IMemoryStore) + void* AllocateAlignImpl(std::size_t a_size, std::uint32_t a_alignment) override; // 04 + void DeallocateAlignImpl(void*& a_block) override; // 05 + virtual void* TryAllocateImpl([[maybe_unused]] std::size_t a_size, [[maybe_unused]] std::uint32_t a_alignment) override; // 06 + + // override (IMemoryHeap) + const char* GetName() const override; // 07 + bool PointerInHeap(const void* a_pointer) const override; // 0C + std::size_t TotalSize(const void* a_pointer) const override; // 0D + void GetHeapStats(HeapStats* a_stats, bool a_fullBlockInfo) override; // 0E + bool ShouldTrySmallBlockPools(std::size_t a_size, MEM_CONTEXT a_context) override; // 0F + std::uint32_t GetPageSize() const override; // 10 + + // members + char name[128]; // 08 + void* unk_88; // 088 + std::uint64_t unk_90; // 090 + std::uint64_t unk_98; // 098 + std::uint64_t unk_a0; // 0a0 + std::uint64_t unk_a8; // 0a8 + std::uint64_t unk_b0; // 0b0 + std::uint64_t unk_b8; // 0b8 + std::uint64_t unk_c0; // 0c0 + std::int32_t unk_c8; // 0c8 + std::int16_t unk_cc; // 0cc + std::uint16_t gap_CE; // 0CE + std::uint64_t unk_d0; // 0d0 + std::uint64_t unk_d8; // 0d8 + std::uint64_t unk_e0; // 0e0 + std::uint64_t unk_e8; // 0e8 + std::uint64_t unk_f0; // 0f0 + std::uint64_t unk_f8; // 0f8 + std::uint64_t unk_100; // 100 + std::uint64_t unk_108; // 108 + std::uint64_t unk_110; // 110 + std::uint64_t unk_118; // 118 + std::uint64_t unk_120; // 120 + std::uint64_t unk_128; // 128 + std::uint64_t unk_130; // 130 + std::uint64_t unk_138; // 138 + std::uint64_t unk_140; // 140 + std::uint64_t unk_148; // 148 + std::uint64_t unk_150; // 150 + std::uint64_t unk_158; // 158 + std::uint64_t unk_160; // 160 + std::uint64_t unk_168; // 168 + std::uint64_t unk_170; // 170 + std::uint64_t unk_178; // 178 + std::uint64_t unk_180; // 180 + std::uint64_t unk_188; // 188 + std::uint64_t unk_190; // 190 + std::uint64_t unk_198; // 198 + std::uint64_t unk_1a0; // 1a0 + std::uint64_t unk_1a8; // 1a8 + std::uint64_t unk_1b0; // 1b0 + std::uint64_t unk_1b8; // 1b8 + std::uint64_t unk_1c0; // 1c0 + std::uint64_t unk_1c8; // 1c8 + std::uint64_t unk_1d0; // 1d0 + std::uint64_t unk_1d8; // 1d8 + std::uint64_t unk_1e0; // 1e0 + std::uint64_t unk_1e8; // 1e8 + std::uint64_t unk_1f0; // 1f0 + std::uint64_t unk_1f8; // 1f8 + std::uint64_t unk_200; // 200 + std::uint64_t unk_208; // 208 + std::uint64_t unk_210; // 210 + std::uint64_t unk_218; // 218 + std::uint64_t unk_220; // 220 + std::uint64_t unk_228; // 228 + std::uint64_t unk_230; // 230 + std::uint64_t unk_238; // 238 + std::uint64_t unk_240; // 240 + std::uint64_t unk_248; // 248 + std::uint64_t unk_250; // 250 + std::uint64_t unk_258; // 258 + std::uint64_t unk_260; // 260 + std::uint64_t unk_268; // 268 + std::uint64_t unk_270; // 270 + std::uint64_t unk_278; // 278 + std::uint64_t unk_280; // 280 + std::uint64_t unk_288; // 288 + std::uint64_t unk_290; // 290 + std::uint64_t unk_298; // 298 + std::uint64_t unk_2a0; // 2a0 + std::uint64_t unk_2a8; // 2a8 + std::uint64_t unk_2b0; // 2b0 + std::uint64_t unk_2b8; // 2b8 + std::uint64_t unk_2c0; // 2c0 + std::uint64_t unk_2c8; // 2c8 + std::uint64_t unk_2d0; // 2d0 + std::uint64_t unk_2d8; // 2d8 + std::uint64_t unk_2e0; // 2e0 + std::uint64_t unk_2e8; // 2e8 + std::uint64_t unk_2f0; // 2f0 + std::uint64_t unk_2f8; // 2f8 + std::uint64_t unk_300; // 300 + std::uint64_t unk_308; // 308 + std::uint64_t unk_310; // 310 + std::uint64_t unk_318; // 318 + std::uint64_t unk_320; // 320 + std::uint64_t unk_328; // 328 + std::uint64_t unk_330; // 330 + std::uint64_t unk_338; // 338 + std::uint64_t unk_340; // 340 + std::uint64_t unk_348; // 348 + std::uint64_t unk_350; // 350 + std::uint64_t unk_358; // 358 + std::uint64_t unk_360; // 360 + std::uint64_t unk_368; // 368 + std::uint64_t unk_370; // 370 + std::uint64_t unk_378; // 378 + std::uint64_t unk_380; // 380 + std::uint64_t unk_388; // 388 + std::uint64_t unk_390; // 390 + std::uint64_t unk_398; // 398 + std::uint64_t unk_3a0; // 3a0 + std::uint64_t unk_3a8; // 3a8 + std::uint64_t unk_3b0; // 3b0 + std::uint64_t unk_3b8; // 3b8 + std::uint64_t unk_3c0; // 3c0 + std::uint64_t unk_3c8; // 3c8 + std::uint64_t unk_3d0; // 3d0 + std::uint64_t unk_3d8; // 3d8 + std::uint64_t unk_3e0; // 3e0 + std::uint64_t unk_3e8; // 3e8 + std::uint64_t unk_3f0; // 3f0 + std::uint64_t unk_3f8; // 3f8 + std::uint64_t unk_400; // 400 + bool unk_408; // 408 + bool unk_409; // 409 + bool unk_40a; // 40a + }; + static_assert(sizeof(HeapAllocator) == 0x410); + + class ScrapHeap : + public HeapAllocator // 00 + { + public: + SF_RTTI_VTABLE(ScrapHeap); + + ~ScrapHeap(); // 00 + + void* Allocate(std::size_t a_size, std::uint32_t a_alignment) override; // 0A + void Deallocate(void* a_mem, std::uint32_t) override; // 0B + + // members + + std::uint64_t unk_410; // 410 + std::byte unk_418; // 418 + std::byte gap_419[31]; // 419 + std::uint64_t unk_438; // 438 + std::byte gap_440[32]; // 440 + std::uint64_t unk_460; // 460 + std::uint64_t unk_468; // 468 + std::uint64_t unk_470; // 470 + std::uint64_t unk_478; // 478 + std::uint64_t unk_480; // 480 + std::uint64_t* unk_488; // 488 + char unk_490; // 490 + std::byte gap_491[7]; // 491 + std::uint64_t* unk_498; // 498 + std::uint32_t unk_4a0; // 4a0 + std::byte gap_4A4[4]; // 4A4 + char unk_4a8; // 4a8 + std::byte gap_4A9[7]; // 4A9 + std::uint64_t unk_4b0; // 4b0 + std::uint32_t unk_4b8; // 4b8 + }; } #define SF_HEAP_REDEFINE_NEW_HELPER(...) \ From 4883c68c1d62410b2267a235ae65c126a25466b3 Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 10:57:48 -0700 Subject: [PATCH 05/39] feat: add funcs to BSScrapArrayAllocator --- CommonLibSF/include/RE/B/BSTArray.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CommonLibSF/include/RE/B/BSTArray.h b/CommonLibSF/include/RE/B/BSTArray.h index 6264d459..0349cfe5 100644 --- a/CommonLibSF/include/RE/B/BSTArray.h +++ b/CommonLibSF/include/RE/B/BSTArray.h @@ -82,6 +82,18 @@ namespace RE class BSScrapArrayAllocator { + public: + void* allocate(std::size_t a_size) + { + const auto mem = _allocator->Allocate(a_size, 0); + if (!mem) { + stl::report_and_fail("out of memory"sv); + } + std::memset(mem, 0, a_size); + return mem; + } + void deallocate(void* a_ptr) { _allocator->Deallocate(a_ptr, 0); } + protected: // members ScrapHeap* _allocator{ nullptr }; // 00 @@ -301,4 +313,5 @@ namespace RE template using BSScrapArray = BSTArray; + static_assert(sizeof(BSScrapArray) == 0x18); } From ee2878ba7c612639dc2f351702564c0f9954693e Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 10:58:13 -0700 Subject: [PATCH 06/39] feat: add BSTObjectArena --- CommonLibSF/include/RE/B/BSTObjectArena.h | 272 ++++++++++++++++++++++ CommonLibSF/include/RE/Starfield.h | 1 + 2 files changed, 273 insertions(+) create mode 100644 CommonLibSF/include/RE/B/BSTObjectArena.h diff --git a/CommonLibSF/include/RE/B/BSTObjectArena.h b/CommonLibSF/include/RE/B/BSTObjectArena.h new file mode 100644 index 00000000..1c407fef --- /dev/null +++ b/CommonLibSF/include/RE/B/BSTObjectArena.h @@ -0,0 +1,272 @@ +#pragma once + +#include "RE/M/MemoryManager.h" +#include + +namespace RE +{ + struct BSTObjectArenaScrapAllocBase + { + public: + // members + ScrapHeap* scrapHeap{ MemoryManager::GetSingleton()->GetThreadScrapHeap() }; // 0 + }; + static_assert(sizeof(BSTObjectArenaScrapAllocBase) == 0x8); + + struct BSTObjectArenaScrapAlloc : + private BSTObjectArenaScrapAllocBase // 0 + { + public: + [[nodiscard]] void* allocate_bytes(std::size_t a_bytes) { return scrapHeap->Allocate(a_bytes, 0x8); } + void deallocate_bytes(void* a_ptr) { scrapHeap->Deallocate(a_ptr, 0); } + }; + static_assert(sizeof(BSTObjectArenaScrapAlloc) == 0x8); + + template < + class T, + class Allocator = BSTObjectArenaScrapAlloc, + std::uint32_t N = 32> + class BSTObjectArena : + private Allocator // 00 + { + private: + using super = Allocator; + + public: + using value_type = T; + using allocator_type = Allocator; + using size_type = std::uint32_t; + using pointer = value_type*; + + struct Page + { + public: + SF_HEAP_REDEFINE_NEW(Page); + + [[nodiscard]] std::byte* begin() noexcept { return std::begin(buffer); } + [[nodiscard]] const std::byte* begin() const noexcept { return std::begin(buffer); } + [[nodiscard]] const std::byte* cbegin() const noexcept { return begin(); } + + [[nodiscard]] std::byte* end() noexcept { return std::end(buffer); } + [[nodiscard]] const std::byte* end() const noexcept { return std::end(buffer); } + [[nodiscard]] const std::byte* cend() const noexcept { return end(); } + + // members + std::byte buffer[sizeof(value_type) * N]{ static_cast(0) }; // 00 + Page* next{ nullptr }; // ?? + }; + + private: + template + class iterator_base : + public boost::stl_interfaces::iterator_interface< + iterator_base, + std::forward_iterator_tag, + U> + { + private: + using super = + boost::stl_interfaces::iterator_interface< + iterator_base, + std::forward_iterator_tag, + U>; + + public: + using difference_type = typename super::difference_type; + using value_type = typename super::value_type; + using pointer = typename super::pointer; + using reference = typename super::reference; + using iterator_category = typename super::iterator_category; + + iterator_base() noexcept = default; + + template + iterator_base(const iterator_base& a_rhs) noexcept // + requires(std::convertible_to::reference, reference>) + : + _proxy(a_rhs._proxy), + _first(a_rhs._first), + _last(a_rhs._last) + {} + + ~iterator_base() noexcept = default; + + template + iterator_base& operator=(const iterator_base& a_rhs) noexcept // + requires(std::convertible_to::reference, reference>) + { + _proxy = a_rhs._proxy; + _first = a_rhs._first; + _last = a_rhs._last; + return *this; + } + + [[nodiscard]] reference operator*() const noexcept + { + assert(good()); + return *std::launder(reinterpret_cast(_first)); + } + + template + [[nodiscard]] bool operator==(const iterator_base& a_rhs) const noexcept + { + assert(_last == a_rhs._last); + if (_first == a_rhs._first) { + assert(_proxy == a_rhs._proxy); + return true; + } else { + return false; + } + } + + using super::operator++; + + void operator++() noexcept + { + assert(good()); + _first += sizeof(value_type); + if (_first == _proxy->cend() && _first != _last) { + _proxy = _proxy->next; + _first = _proxy->begin(); + } + } + + protected: + template + friend class BSTObjectArena; + + explicit iterator_base(Page* a_proxy, std::byte* a_first, std::byte* a_last) noexcept : + _proxy(a_proxy), + _first(a_first), + _last(a_last) + {} + + private: + template + friend class iterator_base; + + [[nodiscard]] bool good() const noexcept + { + return _proxy != nullptr && + _first != nullptr && + _last != nullptr && + _first != _last && + _first != _proxy->cend(); + } + + Page* _proxy{ nullptr }; + std::byte* _first{ nullptr }; + std::byte* _last{ nullptr }; + }; + + public: + using iterator = iterator_base; + using const_iterator = iterator_base; + + ~BSTObjectArena() + { + const auto del = [](Page*& a_page) { + while (a_page != nullptr) { + delete std::exchange(a_page, a_page->next); + } + }; + + clear(); + del(_head); + del(_free); + _tail = nullptr; + _end = nullptr; + _begin = nullptr; + } + + SF_HEAP_REDEFINE_NEW(BSTObjectArena); + + [[nodiscard]] iterator begin() noexcept { return iterator{ _head, _begin, _end }; } + [[nodiscard]] const_iterator begin() const noexcept { return iterator{ _head, _begin, _end }; } + [[nodiscard]] const_iterator cbegin() const noexcept { return begin(); } + + [[nodiscard]] iterator end() noexcept { return iterator{ _tail, _end, _end }; } + [[nodiscard]] const_iterator end() const noexcept { return iterator{ _tail, _end, _end }; } + [[nodiscard]] const_iterator cend() const noexcept { return end(); } + + [[nodiscard]] bool empty() const noexcept { return size() == 0; } + [[nodiscard]] size_type size() const noexcept { return _size; } + [[nodiscard]] size_type capacity() const noexcept { return N; } + + void clear() + { + for (; _size > 0; --_size) { + std::destroy_at(reinterpret_cast(_begin)); + _begin += sizeof(value_type); + if (_begin == _head->cend()) { + if (_head == _tail) { // reached the end + _next = std::addressof(_head); + _tail = nullptr; + _end = nullptr; + _begin = nullptr; + } else { // update pos to next page + _begin = _head->next->begin(); + } + + // move head into free list, grab next page + _head = + std::exchange(_head->next, + std::exchange(_free, _head)); + } + } + + assert(empty()); + } + + iterator push_back(const value_type& a_value) { return emplace(a_value); } + iterator push_back(value_type&& a_value) { return emplace(std::move(a_value)); } + + template + iterator emplace_back(Args&&... a_args) + { + const auto buf = allocate_buffer(); + std::construct_at( + reinterpret_cast(buf.data()), + std::forward(a_args)...); + return iterator{ _tail, buf.data(), _end }; + } + + private: + [[nodiscard]] auto allocate_buffer() + -> std::span + { + if (!_tail || _end == _tail->cend()) { + const auto page = + _free ? + std::exchange(_free, _free->next) : // pull from free list + std::construct_at( + allocator_type::allocate_bytes(sizeof(Page))); // go to heap + if (page) { + page->next = nullptr; + *_next = page; + _next = std::addressof(page->next); + } + + _tail = page; + _end = page->buffer; + if (_begin == nullptr) { + _begin = page->buffer; + } + } + + ++_size; + const auto buf = _end; + _end += sizeof(value_type); + return std::span{ buf, sizeof(value_type) }; + } + + // members + Page* _head{ nullptr }; // 08 - head of active pages + Page** _next{ std::addressof(_head) }; // 10 - used to update next ptr when appending pages + Page* _tail{ nullptr }; // 18 - tail of active pages + Page* _free{ nullptr }; // 20 - local free list + std::byte* _end{ nullptr }; // 28 - ptr to end of active lifetime elements + std::byte* _begin{ nullptr }; // 30 - ptr to beginning of active lifetime elements + size_type _size{ 0 }; // 38 + }; +} diff --git a/CommonLibSF/include/RE/Starfield.h b/CommonLibSF/include/RE/Starfield.h index 050776e3..774a94c8 100644 --- a/CommonLibSF/include/RE/Starfield.h +++ b/CommonLibSF/include/RE/Starfield.h @@ -195,6 +195,7 @@ #include "RE/B/BSTEvent.h" #include "RE/B/BSTList.h" #include "RE/B/BSTOptional.h" +#include "RE/B/BSTObjectArena.h" #include "RE/B/BSTSingleton.h" #include "RE/B/BSTSmartPointer.h" #include "RE/B/BSTTuple.h" From 28fb956631d0d78830831628e33b02898032450e Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 10:58:43 -0700 Subject: [PATCH 07/39] feat: add IObjectProcessor, LinkerProcessor --- CommonLibSF/include/RE/I/IObjectProcessor.h | 26 ++++++++++++ CommonLibSF/include/RE/L/LinkerProcessor.h | 47 +++++++++++++++++++++ CommonLibSF/include/RE/Starfield.h | 2 + 3 files changed, 75 insertions(+) create mode 100644 CommonLibSF/include/RE/I/IObjectProcessor.h create mode 100644 CommonLibSF/include/RE/L/LinkerProcessor.h diff --git a/CommonLibSF/include/RE/I/IObjectProcessor.h b/CommonLibSF/include/RE/I/IObjectProcessor.h new file mode 100644 index 00000000..73c2776c --- /dev/null +++ b/CommonLibSF/include/RE/I/IObjectProcessor.h @@ -0,0 +1,26 @@ +#pragma once +#include "RE/B/BSFixedString.h" +#include "RE/I/ILoader.h" + +namespace RE +{ + namespace BSScript + { + struct ILoader; + + class __declspec(novtable) IObjectProcessor + { + public: + static constexpr auto RTTI{ RTTI::BSScript__IObjectProcessor }; + static constexpr auto VTABLE{ VTABLE::BSScript__IObjectProcessor }; + + virtual ~IObjectProcessor(); // 00 + + // add + virtual IObjectProcessor* Clone() = 0; // 01 + virtual void SetLoader(ILoader* a_loader) = 0; // 02 + virtual bool Process(const BSFixedString& a_className) = 0; // 03 + }; + static_assert(sizeof(IObjectProcessor) == 0x8); + } +} diff --git a/CommonLibSF/include/RE/L/LinkerProcessor.h b/CommonLibSF/include/RE/L/LinkerProcessor.h new file mode 100644 index 00000000..fae047e8 --- /dev/null +++ b/CommonLibSF/include/RE/L/LinkerProcessor.h @@ -0,0 +1,47 @@ +#pragma once + +#include "RE/B/BSFixedString.h" +#include "RE/B/BSTArray.h" +#include "RE/B/BSTSmartPointer.h" +#include "RE/I/IObjectProcessor.h" + +namespace RE +{ + namespace BSScript + { + class ErrorLogger; + + namespace Internal + { + class VirtualMachine; + } + + class __declspec(novtable) LinkerProcessor : + public IObjectProcessor + { + public: + static constexpr auto RTTI{ RTTI::BSScript__LinkerProcessor }; + static constexpr auto VTABLE{ VTABLE::BSScript__LinkerProcessor }; + + virtual ~LinkerProcessor(); // 00 + + // override (IObjectProcessor) + virtual IObjectProcessor* Clone() override; // 01 + virtual void SetLoader(ILoader* a_loader) override; // 02 - { loader = a_loader; } + virtual bool Process(const BSFixedString& a_className) override; // 03 + + // members + Internal::VirtualMachine* virtualMachine; // 08 + ErrorLogger* errorLogger; // 10 + ILoader* loader; // 18 + std::uint64_t unk20; // 20 + char* unk28; // 28 + BSScrapArray loadedParents; // 30 + BSScrapArray objectsToTypecheck; // 48 + BSScrapArray processQueue; // 60 + /*BSTHashMap>**/ void* objectTypeInfoMap; // 78 + /*BSTHashMap>**/ void* structTypeInfoMap; // 80 + }; + static_assert(sizeof(LinkerProcessor) == 0x88); + } +} diff --git a/CommonLibSF/include/RE/Starfield.h b/CommonLibSF/include/RE/Starfield.h index 774a94c8..8879a826 100644 --- a/CommonLibSF/include/RE/Starfield.h +++ b/CommonLibSF/include/RE/Starfield.h @@ -245,6 +245,7 @@ #include "RE/I/INIPrefSettingCollection.h" #include "RE/I/INISettingCollection.h" #include "RE/I/IObjectHandlePolicy.h" +#include "RE/I/IObjectProcessor.h" #include "RE/I/IPostAnimationChannelUpdateFunctor.h" #include "RE/I/IRemoteDebugger.h" #include "RE/I/ISavePatcherInterface.h" @@ -264,6 +265,7 @@ #include "RE/IDs_RTTI.h" #include "RE/IDs_VTABLE.h" #include "RE/L/Location.h" +#include "RE/L/LinkerProcessor.h" #include "RE/L/LockPickedEvent.h" #include "RE/L/Logger.h" #include "RE/M/MagicItem.h" From c1f70922a47973aea4b1b865eaf75fafaf1d7f10 Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 10:58:45 -0700 Subject: [PATCH 08/39] feat: add ReadableStringTable --- .../include/RE/R/ReadableStringTable.h | 49 +++++++++++++++++++ CommonLibSF/include/RE/Starfield.h | 1 + 2 files changed, 50 insertions(+) create mode 100644 CommonLibSF/include/RE/R/ReadableStringTable.h diff --git a/CommonLibSF/include/RE/R/ReadableStringTable.h b/CommonLibSF/include/RE/R/ReadableStringTable.h new file mode 100644 index 00000000..18a766f5 --- /dev/null +++ b/CommonLibSF/include/RE/R/ReadableStringTable.h @@ -0,0 +1,49 @@ +#pragma once + +#include "RE/B/BSFixedString.h" +#include "RE/B/BSTArray.h" +#include "RE/B/BSTObjectArena.h" + +namespace RE +{ + namespace BSScript + { + namespace Internal + { + enum class StringIndexSize + { + kSmall, + kLarge + }; + + class ReadableStringTable + { + public: + class StringEntry + { + public: + // members + const char* originalData; // 00 + BSFixedString convertedString; // 08 + }; + static_assert(sizeof(StringEntry) == 0x10); + + class StringTableScrapPage + { + public: + // members + char buffer[0x1000]; // 0000 + char* curr; // 1000 + const char* const end; // 1008 + }; + static_assert(sizeof(StringTableScrapPage) == 0x1010); + + // members + msvc::unique_ptr> scrapPages; // 00 + msvc::unique_ptr> entries; // 08 + stl::enumeration indexSize; // 10 + }; + static_assert(sizeof(ReadableStringTable) == 0x18); + } + } +} diff --git a/CommonLibSF/include/RE/Starfield.h b/CommonLibSF/include/RE/Starfield.h index 8879a826..85ce3cee 100644 --- a/CommonLibSF/include/RE/Starfield.h +++ b/CommonLibSF/include/RE/Starfield.h @@ -296,6 +296,7 @@ #include "RE/P/PropertyGroupInfo.h" #include "RE/P/PropertyTypeInfo.h" #include "RE/R/RawFuncCallQuery.h" +#include "RE/R/ReadableStringTable.h" #include "RE/R/RegSettingCollection.h" #include "RE/R/RemoteDebugger.h" #include "RE/RTTI.h" From bdad88fc61d41cc9dfa5ef0fe1eb010e846f8bc5 Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 10:59:09 -0700 Subject: [PATCH 09/39] feat: Add CompiledScriptLoader, ILoader --- .../include/RE/C/CompiledScriptLoader.h | 49 +++++++++++++++++++ CommonLibSF/include/RE/I/ILoader.h | 32 ++++++++++++ CommonLibSF/include/RE/Starfield.h | 2 + 3 files changed, 83 insertions(+) create mode 100644 CommonLibSF/include/RE/C/CompiledScriptLoader.h create mode 100644 CommonLibSF/include/RE/I/ILoader.h diff --git a/CommonLibSF/include/RE/C/CompiledScriptLoader.h b/CommonLibSF/include/RE/C/CompiledScriptLoader.h new file mode 100644 index 00000000..d32cd2c4 --- /dev/null +++ b/CommonLibSF/include/RE/C/CompiledScriptLoader.h @@ -0,0 +1,49 @@ +#pragma once + +#include "RE/B/BSTSmartPointer.h" +#include "RE/I/ILoader.h" +#include "RE/R/ReadableStringTable.h" + +namespace RE +{ + namespace BSScript + { + class ErrorLogger; + class IStore; // stub + class Object; + + struct ILoader; + + namespace Internal + { + class ReadableStringTable; + + } + namespace UnlinkedTypes + { + struct Object; // stub + } + + class __declspec(novtable) CompiledScriptLoader : + public ILoader // 00 + { + public: + static constexpr auto RTTI{ RTTI::BSScript__CompiledScriptLoader }; + static constexpr auto VTABLE{ VTABLE::BSScript__CompiledScriptLoader }; + + // override (ILoader) + ILoader* Clone() const override; // 01 + void SetScriptStore(const BSTSmartPointer& a_newStore) override; // 02 + bool GetClass(const char* a_name, UnlinkedTypes::Object& a_unlinkedClass) override; // 03 + + // members + ErrorLogger* errorHandler; // 08 + BSTSmartPointer scriptStore; // 10 + Internal::ReadableStringTable stringTable; // 18 + std::int8_t fileMajorVersion; // 30 + std::int8_t fileMinorVersion; // 31 + std::int8_t loadFlags; // 32 + }; + static_assert(sizeof(CompiledScriptLoader) == 0x38); + } +} diff --git a/CommonLibSF/include/RE/I/ILoader.h b/CommonLibSF/include/RE/I/ILoader.h new file mode 100644 index 00000000..d298ffb6 --- /dev/null +++ b/CommonLibSF/include/RE/I/ILoader.h @@ -0,0 +1,32 @@ +#pragma once + +#include "RE/B/BSTSmartPointer.h" + +namespace RE +{ + namespace BSScript + { + class IStore; // stub + class Object; + + namespace UnlinkedTypes + { + struct Object; // stub + } + + struct __declspec(novtable) ILoader + { + public: + static constexpr auto RTTI{ RTTI::BSScript__ILoader }; + static constexpr auto VTABLE{ VTABLE::BSScript__ILoader }; + + virtual ~ILoader() = default; // 00 + + // add + virtual ILoader* Clone() const = 0; // 01 + virtual void SetScriptStore(const BSTSmartPointer& a_newStore) = 0; // 02 + virtual bool GetClass(const char* a_name, UnlinkedTypes::Object& a_unlinkedClass) = 0; // 03 + }; + static_assert(sizeof(ILoader) == 0x8); + } +} diff --git a/CommonLibSF/include/RE/Starfield.h b/CommonLibSF/include/RE/Starfield.h index 85ce3cee..8b453fd8 100644 --- a/CommonLibSF/include/RE/Starfield.h +++ b/CommonLibSF/include/RE/Starfield.h @@ -208,6 +208,7 @@ #include "RE/C/Color.h" #include "RE/C/CombatGroup.h" #include "RE/C/ConeProjectile.h" +#include "RE/C/CompiledScriptLoader.h" #include "RE/C/Console.h" #include "RE/C/ConsoleLog.h" #include "RE/D/DebuggerMessages.h" @@ -237,6 +238,7 @@ #include "RE/I/IFuncCallQuery.h" #include "RE/I/IFunction.h" #include "RE/I/IKeywordFormBase.h" +#include "RE/I/ILoader.h" #include "RE/I/IMenu.h" #include "RE/I/IMovementInterface.h" #include "RE/I/IMovementPlayerControlsFilter.h" From a0829b3bec03063ccd417dabe0a494fc0c336d88 Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 10:59:12 -0700 Subject: [PATCH 10/39] feat: add AutoScrapBuffer --- CommonLibSF/include/RE/IDs.h | 6 +++++ CommonLibSF/include/RE/M/MemoryManager.h | 29 ++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/CommonLibSF/include/RE/IDs.h b/CommonLibSF/include/RE/IDs.h index ed759e4f..1c95ab5e 100644 --- a/CommonLibSF/include/RE/IDs.h +++ b/CommonLibSF/include/RE/IDs.h @@ -228,6 +228,12 @@ namespace RE::ID namespace MemoryManager { + + namespace AutoScrapBuffer + { + inline constexpr REL::ID ctor{ 178513 }; + inline constexpr REL::ID dtor{ 178516 }; + } inline constexpr REL::ID GetSingleton{ 33961 }; inline constexpr REL::ID Allocate{ 33962 }; inline constexpr REL::ID Free{ 34032 }; diff --git a/CommonLibSF/include/RE/M/MemoryManager.h b/CommonLibSF/include/RE/M/MemoryManager.h index 6a553f31..ad42ec22 100644 --- a/CommonLibSF/include/RE/M/MemoryManager.h +++ b/CommonLibSF/include/RE/M/MemoryManager.h @@ -12,6 +12,35 @@ namespace RE class MemoryManager { public: + struct AutoScrapBuffer + { + public: + AutoScrapBuffer() { ctor(0, 0); } + AutoScrapBuffer(std::size_t a_size, std::size_t a_alignment) { ctor(a_size, a_alignment); } + ~AutoScrapBuffer() { dtor(); } + + [[nodiscard]] void* GetPtr() const noexcept { return ptr; } + + // members + void* ptr{ nullptr }; // 0 + + private: + AutoScrapBuffer* ctor(std::size_t a_size, std::size_t a_alignment) + { + using func_t = decltype(&AutoScrapBuffer::ctor); + REL::Relocation func{ ID::MemoryManager::AutoScrapBuffer::ctor }; + return func(this, a_size, a_alignment); + } + + void dtor() + { + using func_t = decltype(&AutoScrapBuffer::dtor); + REL::Relocation func{ ID::MemoryManager::AutoScrapBuffer::dtor }; + return func(this); + } + }; + static_assert(sizeof(AutoScrapBuffer) == 0x8); + [[nodiscard]] static MemoryManager* GetSingleton() { using func_t = decltype(&MemoryManager::GetSingleton); From 7eb02a5c0b68c2c63df3a0ef81a060fcf1e49456 Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 10:59:12 -0700 Subject: [PATCH 11/39] feat: add BSStorage --- CommonLibSF/include/RE/B/BSStorage.h | 107 +++++++++++++++++++++++++++ CommonLibSF/include/RE/IDs.h | 7 ++ CommonLibSF/include/RE/Starfield.h | 1 + 3 files changed, 115 insertions(+) create mode 100644 CommonLibSF/include/RE/B/BSStorage.h diff --git a/CommonLibSF/include/RE/B/BSStorage.h b/CommonLibSF/include/RE/B/BSStorage.h new file mode 100644 index 00000000..1190477a --- /dev/null +++ b/CommonLibSF/include/RE/B/BSStorage.h @@ -0,0 +1,107 @@ +#pragma once + +#include "RE/B/BSIntrusiveRefCounted.h" +#include "RE/B/BSTSmartPointer.h" + +namespace RE +{ + namespace BSStorageDefs + { + enum class ErrorCode + { + kOK = 0, + kError = 1, + kNotImplemented = 2, + }; + enum class SeekMode; + struct StreamBuffer + { + void Reset() + { + ptrCur = buffer.GetPtr(); + } + + StreamBuffer() = delete; + StreamBuffer(std::size_t a_size) : + size(a_size), + buffer(a_size, 8), + ptrCur(buffer.GetPtr()) + { + } + + std::size_t size; + MemoryManager::AutoScrapBuffer buffer; + void* ptrCur; + }; + } + + class __declspec(novtable) BSStorage : + public BSIntrusiveRefCounted + { + public: + inline static constexpr auto RTTI = { RTTI::BSStorage }; + inline static constexpr auto VTABLE = { VTABLE::BSStorage }; + + virtual ~BSStorage(); // 00 + + virtual std::size_t GetSize() const = 0; // 01 + virtual std::size_t GetPosition() const = 0; // 02 + virtual BSStorageDefs::ErrorCode Seek(std::size_t a_offset, BSStorageDefs::SeekMode a_seekMode) const = 0; // 03 + virtual BSStorageDefs::ErrorCode Read(std::size_t a_numBytes, std::byte* a_bytes) const = 0; // 04 + virtual BSStorageDefs::ErrorCode Write(std::size_t a_numBytes, const std::byte* a_bytes) = 0; // 05 + + template + BSStorageDefs::ErrorCode Write(T a_value) + requires(std::is_arithmetic_v) + { + if (usingStreambuffer && buf && PrepareStreamBuffer(sizeof(T)) == BSStorageDefs::ErrorCode::kOK) { + *reinterpret_cast(buf->ptrCur) = a_value; + buf->ptrCur = reinterpret_cast(buf->ptrCur) + sizeof(T); + return BSStorageDefs::ErrorCode::kOK; + } + return Write(sizeof(T), reinterpret_cast(&a_value)); + } + + template + BSStorageDefs::ErrorCode Write(const T& a_value) + requires(!std::is_arithmetic_v) + { + return Write(sizeof(T), reinterpret_cast(&a_value)); + } + + template + BSStorageDefs::ErrorCode Read(T& a_value) + { + return Read(sizeof(T), reinterpret_cast(&a_value)); + } + + BSStorageDefs::ErrorCode WriteString(const char* a_string, bool use32bitLength) + { + using func_t = decltype(&BSStorage::WriteString); + REL::Relocation func{ ID::BSStorage::WriteString }; + return func(this, a_string, use32bitLength); + } + + BSStorageDefs::ErrorCode PrepareStreamBuffer(std::size_t a_size) + { + using func_t = decltype(&BSStorage::PrepareStreamBuffer); + REL::Relocation func{ ID::BSStorage::PrepareStreamBuffer }; + return func(this, a_size); + } + + BSStorageDefs::ErrorCode FlushStreamBuffer() + { + using func_t = decltype(&BSStorage::FlushStreamBuffer); + REL::Relocation func{ ID::BSStorage::FlushStreamBuffer }; + return func(this); + } + + // members + bool unk0C; // 0C + bool unk0D; // 0D + uint16_t unk0E; // 0E + BSStorageDefs::StreamBuffer* buf; // 10 + bool usingStreambuffer; // 18 + }; + static_assert(sizeof(BSStorage) == 0x20); +} diff --git a/CommonLibSF/include/RE/IDs.h b/CommonLibSF/include/RE/IDs.h index 1c95ab5e..e32d42e2 100644 --- a/CommonLibSF/include/RE/IDs.h +++ b/CommonLibSF/include/RE/IDs.h @@ -138,6 +138,13 @@ namespace RE::ID inline constexpr REL::ID GetEntry_wchar_t_{ 198220 }; } + + namespace BSStorage + { + inline constexpr REL::ID FlushStreamBuffer{ 72433 }; + inline constexpr REL::ID PrepareStreamBuffer{ 72461 }; + inline constexpr REL::ID WriteString{ 87863 }; + } namespace BSSystemFile { inline constexpr REL::ID ctor{ 198445 }; diff --git a/CommonLibSF/include/RE/Starfield.h b/CommonLibSF/include/RE/Starfield.h index 8b453fd8..fae87040 100644 --- a/CommonLibSF/include/RE/Starfield.h +++ b/CommonLibSF/include/RE/Starfield.h @@ -188,6 +188,7 @@ #include "RE/B/BSLock.h" #include "RE/B/BSLog.h" #include "RE/B/BSReflection.h" +#include "RE/B/BSStorage.h" #include "RE/B/BSStringPool.h" #include "RE/B/BSStringT.h" #include "RE/B/BSSystemFile.h" From ed496a3ef9154ab276d1851fe192011b37a356d3 Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 10:59:12 -0700 Subject: [PATCH 12/39] fix: add scrapheap ids --- CommonLibSF/include/RE/IDs.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CommonLibSF/include/RE/IDs.h b/CommonLibSF/include/RE/IDs.h index e32d42e2..ebd8c14e 100644 --- a/CommonLibSF/include/RE/IDs.h +++ b/CommonLibSF/include/RE/IDs.h @@ -316,6 +316,12 @@ namespace RE::ID } } + namespace ScrapHeap + { + inline constexpr REL::ID Allocate{ 34432 }; + inline constexpr REL::ID Deallocate{ 37624 }; + } + namespace Script { inline constexpr REL::ID GetConsoleCommands{ 841465 }; From 979d1d1050143fc02cc8ffe5950a74993ff40b31 Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 10:59:12 -0700 Subject: [PATCH 13/39] fix: Fix BSStorage --- CommonLibSF/include/RE/B/BSStorage.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/CommonLibSF/include/RE/B/BSStorage.h b/CommonLibSF/include/RE/B/BSStorage.h index 1190477a..9caf420f 100644 --- a/CommonLibSF/include/RE/B/BSStorage.h +++ b/CommonLibSF/include/RE/B/BSStorage.h @@ -97,11 +97,8 @@ namespace RE } // members - bool unk0C; // 0C - bool unk0D; // 0D - uint16_t unk0E; // 0E - BSStorageDefs::StreamBuffer* buf; // 10 - bool usingStreambuffer; // 18 + msvc::unique_ptr buf{ nullptr }; // 10 + bool usingStreambuffer{ 0 }; // 18 }; static_assert(sizeof(BSStorage) == 0x20); } From 0362849176ed08284dc1ad98e925772533500e01 Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 10:59:12 -0700 Subject: [PATCH 14/39] feat: add Stream, StreamBase --- CommonLibSF/include/RE/S/Stream.h | 67 ++++++++++ CommonLibSF/include/RE/S/StreamBase.h | 48 +++++++ CommonLibSF/include/RE/Starfield.h | 2 + CommonLibSF/src/RE/S/Stream.cpp | 186 ++++++++++++++++++++++++++ CommonLibSF/src/RE/S/StreamBase.cpp | 62 +++++++++ 5 files changed, 365 insertions(+) create mode 100644 CommonLibSF/include/RE/S/Stream.h create mode 100644 CommonLibSF/include/RE/S/StreamBase.h create mode 100644 CommonLibSF/src/RE/S/Stream.cpp create mode 100644 CommonLibSF/src/RE/S/StreamBase.cpp diff --git a/CommonLibSF/include/RE/S/Stream.h b/CommonLibSF/include/RE/S/Stream.h new file mode 100644 index 00000000..51258990 --- /dev/null +++ b/CommonLibSF/include/RE/S/Stream.h @@ -0,0 +1,67 @@ +#pragma once + +#include "RE/B/BSFixedString.h" +#include "RE/B/BSIntrusiveRefCounted.h" +#include "RE/B/BSResourceEnums.h" +#include "RE/B/BSTSmartPointer.h" +#include "RE/S/StreamBase.h" + +namespace RE +{ + struct BSEventFlag; // stub + + namespace BSResource + { + class AsyncStream; + class CacheDrive; + + class __declspec(novtable) Stream : + public StreamBase + { + public: + SF_RTTI_VTABLE(BSResource__Stream); + + Stream(); + Stream(const Stream& a_rhs); + Stream(Stream&& a_rhs); + Stream(std::uint32_t a_totalSize, bool writable); + ~Stream() override = default; // 00 + + // add + virtual void DoClone(BSTSmartPointer& a_result) const = 0; // 05 + virtual ErrorCode DoRead(void* a_buffer, std::uint64_t a_bytes, std::uint64_t& a_read) const = 0; // 06 + virtual ErrorCode DoReadAt(void* a_buffer, std::uint64_t a_bytes, std::uint64_t a_pos, std::uint64_t& a_read) const; // 07 + virtual ErrorCode DoWrite(const void* a_buffer, std::uint64_t a_bytes, std::uint64_t& a_write) const = 0; // 08 + virtual ErrorCode DoSeek(std::int64_t a_offset, SeekMode a_seekMode, std::uint64_t& a_pos) const = 0; // 09 + virtual ErrorCode DoSetEndOfStream(); // 0A + virtual ErrorCode DoPrefetchAt(std::uint64_t a_bytes, std::uint64_t a_offset, std::uint32_t a_priority) const; // 0B + virtual ErrorCode DoStartTaggedPrioritizedRead(void* a_buffer, std::uint64_t a_bytes, std::uint64_t a_offset, std::uint32_t a_priority, volatile std::uint32_t* a_completionTag, std::uint32_t& a_completionTagWaitValue, BSEventFlag* a_eventFlag) const; // 0C + virtual ErrorCode DoWaitTags(volatile std::uint32_t* a_completionTag, BSEventFlag* a_eventFlag, std::uint32_t a_completionTagWaitValue) const; // 0D + virtual ErrorCode DoPrefetchAll(std::uint32_t a_priority) const; // 0E + virtual bool DoGetName(BSFixedString& a_result) const; // 0F + virtual ErrorCode DoCreateAsync(BSTSmartPointer& a_result) const; // 10 + virtual bool DoQTaggedPrioritizedReadSupported() const; // 11 + virtual bool Unk_12() const; // 12 - { return false; } + virtual ErrorCode Unk_13() const; // 13 - { return ErrorCode::kUnsupported; } + virtual ErrorCode Unk_14() const; // 14 - { return ErrorCode::kUnsupported; } + + // non virtuals + bool GetName(BSFixedString& a_dst) const; + ErrorCode Open(bool buffered, bool fullReadHint); + ErrorCode Read(void* a_buffer, std::uint64_t a_toRead, std::uint64_t& a_read) const; + ErrorCode Seek(std::uint64_t a_toSeek, SeekMode a_mode, std::uint64_t& a_sought) const; + ErrorCode Write(const void* a_buffer, std::uint64_t a_toWrite, std::uint64_t& a_written) const; + ErrorCode ReadAt(void* a_buffer, std::uint64_t a_offset, std::uint64_t a_toRead, std::uint64_t& a_read) const; + ErrorCode CreateAsync(BSTSmartPointer& a_streamOut) const; + ErrorCode PrefetchAll(std::uint32_t a_v) const; + ErrorCode PrefetchAt(std::uint64_t a_v, std::uint64_t b_v, std::uint32_t c_v) const; + std::uint32_t QFullReadHint() const; + bool QTaggedPrioritizedReadSupported() const; + ErrorCode StartTaggedPrioritizedRead(void* buf, std::uint64_t a_v, std::uint64_t b_v, std::uint32_t c_V, std::uint32_t volatile* d_v, std::uint32_t& e_v, BSEventFlag* event_flag) const; + ErrorCode WaitTags(volatile std::uint32_t* a_completionTag, BSEventFlag* a_eventFlag, std::uint32_t a_completionTagWaitValue) const; + std::uint32_t QBuffered() const; + ErrorCode SetEndOfStream(); + }; + static_assert(sizeof(Stream) == 0x10); + } +} \ No newline at end of file diff --git a/CommonLibSF/include/RE/S/StreamBase.h b/CommonLibSF/include/RE/S/StreamBase.h new file mode 100644 index 00000000..de656a4c --- /dev/null +++ b/CommonLibSF/include/RE/S/StreamBase.h @@ -0,0 +1,48 @@ +#pragma once + +#include "RE/B/BSResourceEnums.h" +#include "RE/M/MemoryManager.h" + +namespace RE::BSResource +{ + class __declspec(novtable) StreamBase + { + public: + inline static constexpr auto RTTI = { RTTI::BSResource__StreamBase }; + inline static constexpr auto VTABLE = { VTABLE::BSResource__StreamBase }; + + enum : std::uint32_t + { + kWritable = 1 << 0, + kBuffered = 1 << 1, + kFullReadHint = 1 << 2, + kUnk3 = 1 << 3, + kUnk4 = 1 << 4, + kRefCountBeg = 0x1000, + kRefCountMask = (std::uint32_t)0xFFFFF000 + }; + + StreamBase(); + StreamBase(const StreamBase& a_rhs); + StreamBase(StreamBase&& a_rhs); + StreamBase(std::uint32_t a_totalSize, bool writable); + virtual ~StreamBase() = default; // 00 + + // add + virtual ErrorCode DoOpen() = 0; // 01 + virtual void DoClose() = 0; // 02 + [[nodiscard]] virtual std::uint64_t DoGetKey() const; // 03 - { return 0xFFFFFFFF00000000; } + virtual ErrorCode DoGetInfo(Info& a_info); // 04 - { return ErrorCode::kUnsupported; } + + SF_HEAP_REDEFINE_NEW(StreamBase); + + std::uint32_t DecRef(); + std::uint32_t IncRef(); + [[nodiscard]] bool IsWritable() const; + + // members + std::uint32_t totalSize; // 08 + std::uint32_t flags; // 0C + }; + static_assert(sizeof(StreamBase) == 0x10); +} diff --git a/CommonLibSF/include/RE/Starfield.h b/CommonLibSF/include/RE/Starfield.h index fae87040..f47a54ef 100644 --- a/CommonLibSF/include/RE/Starfield.h +++ b/CommonLibSF/include/RE/Starfield.h @@ -323,6 +323,8 @@ #include "RE/S/SpellItem.h" #include "RE/S/Stack.h" #include "RE/S/StackFrame.h" +#include "RE/S/Stream.h" +#include "RE/S/StreamBase.h" #include "RE/S/Struct.h" #include "RE/S/StructTypeInfo.h" #include "RE/T/TBO_InstanceData.h" diff --git a/CommonLibSF/src/RE/S/Stream.cpp b/CommonLibSF/src/RE/S/Stream.cpp new file mode 100644 index 00000000..b9b388b0 --- /dev/null +++ b/CommonLibSF/src/RE/S/Stream.cpp @@ -0,0 +1,186 @@ +#include "RE/S/Stream.h" + +namespace RE +{ + namespace BSResource + { + Stream::Stream() : + Stream(0, false) + {} + + Stream::Stream(std::uint32_t a_totalSize, bool writable) : + StreamBase(a_totalSize, writable) + {} + + Stream::Stream(const Stream& a_rhs) : + StreamBase(a_rhs) + {} + + Stream::Stream(Stream&& a_rhs) : + StreamBase(std::move(a_rhs)) + {} + + ErrorCode Stream::DoSetEndOfStream() + { + return ErrorCode::kUnsupported; + } + + ErrorCode Stream::DoPrefetchAt([[maybe_unused]] std::uint64_t a_v, [[maybe_unused]] std::uint64_t b_v, [[maybe_unused]] std::uint32_t c_v) const + { + return ErrorCode::kUnsupported; + } + + ErrorCode Stream::DoPrefetchAll([[maybe_unused]] std::uint32_t a_v) const + { + return ErrorCode::kUnsupported; + } + + ErrorCode Stream::DoStartTaggedPrioritizedRead([[maybe_unused]] void* a_buf, + [[maybe_unused]] std::uint64_t a_v, + [[maybe_unused]] std::uint64_t b_v, + [[maybe_unused]] std::uint32_t c_v, + [[maybe_unused]] std::uint32_t volatile* d_v, + [[maybe_unused]] std::uint32_t& e_v, + [[maybe_unused]] BSEventFlag* event_flag) const + { + return ErrorCode::kUnsupported; + } + + bool Stream::DoGetName(BSFixedString& a_dst) const + { + a_dst = ""; + return false; + } + + ErrorCode Stream::DoCreateAsync(BSTSmartPointer&) const + { + return ErrorCode::kUnsupported; + } + + ErrorCode Stream::DoWaitTags([[maybe_unused]] volatile std::uint32_t* a_completionTag, + [[maybe_unused]] BSEventFlag* a_eventFlag, + [[maybe_unused]] std::uint32_t a_completionTagWaitValue) const + { + return ErrorCode::kUnsupported; + } + + bool Stream::DoQTaggedPrioritizedReadSupported() const + { + return false; + } + + ErrorCode Stream::DoReadAt([[maybe_unused]] void* a_buffer, + [[maybe_unused]] std::uint64_t a_offset, + [[maybe_unused]] std::uint64_t a_toRead, + [[maybe_unused]] std::uint64_t& a_read) const + { + return ErrorCode::kUnsupported; + } + + // interface functions + ErrorCode Stream::Read(void* a_buffer, std::uint64_t a_toRead, std::uint64_t& a_read) const + { + if ((flags & kWritable) != 0) { + return ErrorCode::kUnsupported; + } + return DoRead(a_buffer, a_toRead, a_read); + } + + ErrorCode Stream::ReadAt(void* a_buffer, std::uint64_t a_offset, std::uint64_t a_toRead, std::uint64_t& a_read) const + { + if ((flags & kWritable) != 0) { + return ErrorCode::kUnsupported; + } + return DoReadAt(a_buffer, a_offset, a_toRead, a_read); + } + + bool Stream::GetName(BSFixedString& a_dst) const + { + return DoGetName(a_dst); + } + + ErrorCode Stream::Open(bool buffered, bool readFullHint) + { + uint32_t _flags = kUnk3; + if (buffered) { + _flags |= kBuffered; + } + if (readFullHint) { + _flags |= kBuffered | kFullReadHint; + } + static std::atomic_ref myflags{ flags }; + uint32_t old_flags = flags; + while (!myflags.compare_exchange_strong(old_flags, (old_flags | _flags))) { + old_flags = flags; + } + return DoOpen(); + } + + ErrorCode Stream::Seek(std::uint64_t a_toSeek, SeekMode a_mode, std::uint64_t& a_sought) const + { + return DoSeek(a_toSeek, a_mode, a_sought); + } + + ErrorCode Stream::Write(const void* a_buffer, std::uint64_t a_toWrite, std::uint64_t& a_written) const + { + if ((flags & kWritable) != 0) { + return DoWrite(a_buffer, a_toWrite, a_written); + } + return ErrorCode::kUnsupported; + } + + ErrorCode Stream::CreateAsync(BSTSmartPointer& a_streamOut) const + { + return DoCreateAsync(a_streamOut); + } + + ErrorCode Stream::PrefetchAll(std::uint32_t a_v) const + { + if ((flags & kWritable) != 0) { + return ErrorCode::kUnsupported; + } + return DoPrefetchAll(a_v); + } + + ErrorCode Stream::PrefetchAt(std::uint64_t a_v, std::uint64_t b_v, std::uint32_t c_v) const + { + if ((flags & kWritable) != 0) { + return ErrorCode::kUnsupported; + } + return DoPrefetchAt(a_v, b_v, c_v); + } + + std::uint32_t Stream::QFullReadHint() const + { + return flags & kFullReadHint; + } + + bool Stream::QTaggedPrioritizedReadSupported() const + { + return DoQTaggedPrioritizedReadSupported(); + } + + ErrorCode Stream::StartTaggedPrioritizedRead(void* buf, std::uint64_t a_v, std::uint64_t b_v, std::uint32_t c_V, std::uint32_t volatile* d_v, std::uint32_t& e_v, BSEventFlag* event_flag) const + { + if ((flags & kWritable) != 0) { + return ErrorCode::kUnsupported; + } + return DoStartTaggedPrioritizedRead(buf, a_v, b_v, c_V, d_v, e_v, event_flag); + } + + ErrorCode Stream::WaitTags(volatile std::uint32_t* a_completionTag, BSEventFlag* a_eventFlag, std::uint32_t a_completionTagWaitValue) const + { + return DoWaitTags(a_completionTag, a_eventFlag, a_completionTagWaitValue); + } + + std::uint32_t Stream::QBuffered() const + { + return flags & kBuffered; + } + + ErrorCode Stream::SetEndOfStream() + { + return DoSetEndOfStream(); + } + } +} diff --git a/CommonLibSF/src/RE/S/StreamBase.cpp b/CommonLibSF/src/RE/S/StreamBase.cpp new file mode 100644 index 00000000..98297c33 --- /dev/null +++ b/CommonLibSF/src/RE/S/StreamBase.cpp @@ -0,0 +1,62 @@ +#include "RE/S/StreamBase.h" + +namespace RE +{ + namespace BSResource + { + StreamBase::StreamBase() : + totalSize(0), + flags(0) + {} + + StreamBase::StreamBase(const StreamBase& a_rhs) : + totalSize(a_rhs.totalSize), + flags(a_rhs.flags & ~kRefCountMask) + {} + + StreamBase::StreamBase(StreamBase&& a_rhs) : + totalSize(a_rhs.totalSize), + flags(a_rhs.flags & ~kRefCountMask) + {} + + StreamBase::StreamBase(std::uint32_t a_totalSize, bool writable) : + totalSize(a_totalSize), + flags(writable ? 1 : 0) + {} + + std::uint64_t StreamBase::DoGetKey() const + { + return 0xFFFFFFFF00000000; + } + + ErrorCode StreamBase::DoGetInfo(Info&) + { + return ErrorCode::kUnsupported; + } + + std::uint32_t StreamBase::DecRef() + { + stl::atomic_ref myFlags{ flags }; + std::uint32_t expected; + do { + expected = myFlags; + } while (!myFlags.compare_exchange_weak(expected, expected - kRefCountBeg)); + return (expected - kRefCountBeg) & kRefCountMask; + } + + std::uint32_t StreamBase::IncRef() + { + stl::atomic_ref myFlags{ flags }; + std::uint32_t expected; + do { + expected = myFlags; + } while (!myFlags.compare_exchange_weak(expected, expected + kRefCountBeg)); + return (expected - kRefCountBeg) & kRefCountMask; + } + + bool StreamBase::IsWritable() const + { + return static_cast(flags & kWritable); + } + } +} From 52eae7101f04cfef667cbd9aa85d59d8bf808aeb Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 10:59:12 -0700 Subject: [PATCH 15/39] feat: add IStore, Store --- CommonLibSF/include/RE/I/IStore.h | 32 +++++++++++++++++++++++++++ CommonLibSF/include/RE/S/Store.h | 35 ++++++++++++++++++++++++++++++ CommonLibSF/include/RE/Starfield.h | 2 ++ 3 files changed, 69 insertions(+) create mode 100644 CommonLibSF/include/RE/I/IStore.h create mode 100644 CommonLibSF/include/RE/S/Store.h diff --git a/CommonLibSF/include/RE/I/IStore.h b/CommonLibSF/include/RE/I/IStore.h new file mode 100644 index 00000000..90547414 --- /dev/null +++ b/CommonLibSF/include/RE/I/IStore.h @@ -0,0 +1,32 @@ +#pragma once +#include "RE/B/BSFixedString.h" +#include "RE/B/BSStorage.h" +#include "RE/B/BSTSmartPointer.h" +namespace RE +{ + namespace BSScript + { + class __declspec(novtable) IStore : public BSStorage + { + public: + SF_RTTI_VTABLE(BSScript__IStore); + + virtual ~IStore() = default; // 00 + + // override (BSStorage) + BSStorageDefs::ErrorCode Write([[maybe_unused]] std::size_t a_numBytes, [[maybe_unused]] const std::byte* a_bytes) override // 05 + { + return BSStorageDefs::ErrorCode::kNotImplemented; + }; + + // add + virtual bool Open(const char* a_fileName) = 0; // 06 + virtual bool Close() = 0; // 07 + virtual const BSFixedString& StoreName() const = 0; // 08 + virtual bool GetIsOpen() const = 0; // 09 + virtual bool GetIsGood() const = 0; // 0A + virtual bool GetIsEOS() const = 0; // 0B + }; + static_assert(sizeof(IStore) == 0x20); + } +} diff --git a/CommonLibSF/include/RE/S/Store.h b/CommonLibSF/include/RE/S/Store.h new file mode 100644 index 00000000..1a03cace --- /dev/null +++ b/CommonLibSF/include/RE/S/Store.h @@ -0,0 +1,35 @@ +#pragma once + +#include "RE/B/BSTSmartPointer.h" +#include "RE/I/IStore.h" +#include "RE/S/Stream.h" +namespace RE +{ + namespace GameScript + { + + class Store : public BSScript::IStore + { + public: + SF_RTTI_VTABLE(GameScript__Store); + + virtual ~Store() override; // 00 + + // override (BSScript::IStore) + virtual bool Open(const char* a_fileName) override; // 06 + virtual bool Close() override; // 07 + virtual const BSFixedString& StoreName() const override; // 08 + virtual bool GetIsOpen() const override; // 09 + virtual bool GetIsGood() const override; // 0A + virtual bool GetIsEOS() const override; // 0B + + // members + size_t streamPos; // 20 + BSTSmartPointer stream; // 28 + BSFixedString relPath; // 30 + bool hasOpenFile; // 38 + bool fileIsGood; // 39 + }; + static_assert(sizeof(Store) == 0x40); + } +} diff --git a/CommonLibSF/include/RE/Starfield.h b/CommonLibSF/include/RE/Starfield.h index f47a54ef..634ff320 100644 --- a/CommonLibSF/include/RE/Starfield.h +++ b/CommonLibSF/include/RE/Starfield.h @@ -252,6 +252,7 @@ #include "RE/I/IPostAnimationChannelUpdateFunctor.h" #include "RE/I/IRemoteDebugger.h" #include "RE/I/ISavePatcherInterface.h" +#include "RE/I/IStore.h" #include "RE/I/IStoreAnimationActions.h" #include "RE/I/IVMDebugInterface.h" #include "RE/I/IVMFunctionMessageDispatch.h" @@ -323,6 +324,7 @@ #include "RE/S/SpellItem.h" #include "RE/S/Stack.h" #include "RE/S/StackFrame.h" +#include "RE/S/Store.h" #include "RE/S/Stream.h" #include "RE/S/StreamBase.h" #include "RE/S/Struct.h" From cc740dd653617469f7dac7a1df9e58f822a616c0 Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 10:59:12 -0700 Subject: [PATCH 16/39] fix: Fix BSStorage --- CommonLibSF/include/RE/B/BSStorage.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CommonLibSF/include/RE/B/BSStorage.h b/CommonLibSF/include/RE/B/BSStorage.h index 9caf420f..ac0259d0 100644 --- a/CommonLibSF/include/RE/B/BSStorage.h +++ b/CommonLibSF/include/RE/B/BSStorage.h @@ -42,7 +42,7 @@ namespace RE inline static constexpr auto RTTI = { RTTI::BSStorage }; inline static constexpr auto VTABLE = { VTABLE::BSStorage }; - virtual ~BSStorage(); // 00 + virtual ~BSStorage() = default; // 00 virtual std::size_t GetSize() const = 0; // 01 virtual std::size_t GetPosition() const = 0; // 02 From 21e99bb31850620a64a109c9e79a1c0c8f579c80 Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 10:59:12 -0700 Subject: [PATCH 17/39] feat: add BSResourceEnums --- CommonLibSF/include/RE/B/BSResourceEnums.h | 56 ++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 CommonLibSF/include/RE/B/BSResourceEnums.h diff --git a/CommonLibSF/include/RE/B/BSResourceEnums.h b/CommonLibSF/include/RE/B/BSResourceEnums.h new file mode 100644 index 00000000..27eea02f --- /dev/null +++ b/CommonLibSF/include/RE/B/BSResourceEnums.h @@ -0,0 +1,56 @@ +#pragma once + +namespace RE::BSResource +{ + enum class ErrorCode : std::uint32_t + { + kNone = 0, + kNotExist = 1, + kInvalidPath = 2, + kFileError = 3, + kInvalidType = 4, + kMemoryError = 5, + kBusy = 6, + kInvalidParam = 7, + kUnsupported = 8 + }; + + enum class SeekMode + { + kSet = 0, + kCurrent = 1, + kEnd = 2 + }; + + struct FileID + { + public: + [[nodiscard]] bool operator==(const FileID&) const noexcept = default; + + // members + std::uint32_t file = 0; // 0 + std::uint32_t ext = 0; // 4 + }; + static_assert(sizeof(FileID) == 0x8); + + struct ID : + public FileID // 0 + { + public: + [[nodiscard]] bool operator==(const ID&) const noexcept = default; + + // members + std::uint32_t dir = 0; // 8 + }; + static_assert(sizeof(BSResource::ID) == 0xC); + + struct Info + { + public: + // members + WinAPI::FILETIME modifyTime; // 00 + WinAPI::FILETIME createTime; // 08 + std::uint64_t fileSize; // 10 + }; + static_assert(sizeof(Info) == 0x18); +} \ No newline at end of file From ea9b33ed9bf41b5c13adaaacaa5c26597f55cb4b Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 10:59:12 -0700 Subject: [PATCH 18/39] fix: Fix CompiledScriptLoader --- CommonLibSF/include/RE/C/CompiledScriptLoader.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/CommonLibSF/include/RE/C/CompiledScriptLoader.h b/CommonLibSF/include/RE/C/CompiledScriptLoader.h index d32cd2c4..afd2a582 100644 --- a/CommonLibSF/include/RE/C/CompiledScriptLoader.h +++ b/CommonLibSF/include/RE/C/CompiledScriptLoader.h @@ -12,8 +12,6 @@ namespace RE class IStore; // stub class Object; - struct ILoader; - namespace Internal { class ReadableStringTable; From 456a9996834684eb798660c858a08e143e72ae1b Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 10:59:12 -0700 Subject: [PATCH 19/39] fix: add BSResourceEnums to starfield.h --- CommonLibSF/include/RE/Starfield.h | 1 + 1 file changed, 1 insertion(+) diff --git a/CommonLibSF/include/RE/Starfield.h b/CommonLibSF/include/RE/Starfield.h index 634ff320..b62ae753 100644 --- a/CommonLibSF/include/RE/Starfield.h +++ b/CommonLibSF/include/RE/Starfield.h @@ -188,6 +188,7 @@ #include "RE/B/BSLock.h" #include "RE/B/BSLog.h" #include "RE/B/BSReflection.h" +#include "RE/B/BSResourceEnums.h" #include "RE/B/BSStorage.h" #include "RE/B/BSStringPool.h" #include "RE/B/BSStringT.h" From 2776bc32fdd5ce71a5395877a1345be46b4e3c94 Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 10:59:31 -0700 Subject: [PATCH 20/39] feat: add HandleReaderWriters --- CommonLibSF/include/RE/H/HandleReaderWriter.h | 66 +++++++++++++++++++ .../include/RE/I/IHandleReaderWriter.h | 25 +++++++ CommonLibSF/include/RE/Starfield.h | 2 + 3 files changed, 93 insertions(+) create mode 100644 CommonLibSF/include/RE/H/HandleReaderWriter.h create mode 100644 CommonLibSF/include/RE/I/IHandleReaderWriter.h diff --git a/CommonLibSF/include/RE/H/HandleReaderWriter.h b/CommonLibSF/include/RE/H/HandleReaderWriter.h new file mode 100644 index 00000000..25849acb --- /dev/null +++ b/CommonLibSF/include/RE/H/HandleReaderWriter.h @@ -0,0 +1,66 @@ +#include "RE/I/IHandleReaderWriter.h" +#include "RE/I/IObjectHandlePolicy.h" +#include "RE/T/TESFile.h" + +namespace RE::GameScript +{ + class __declspec(novtable) BaseHandleReaderWriter : + public RE::BSScript::IHandleReaderWriter + { + public: + inline static constexpr auto RTTI = { RTTI::GameScript__BaseHandleReaderWriter }; + // inline static constexpr auto VTABLE = { VTABLE::GameScript__BaseHandleReaderWriter }; -- optimized out? + + ~BaseHandleReaderWriter() override; // 0 + + // override (BSScript::IHandleReaderWriter) + virtual std::uint16_t GetHandleVersion() const override; // 1 + virtual bool WriteHandle(BSStorage& storage, std::uint64_t) const override; // 2 + virtual bool ReadHandle(BSStorage const& storage, std::uint64_t&) const override; // 3 + virtual bool ReadHandleNoRemap(BSStorage const& storage, std::uint64_t&) const override; // 4 + + // add + virtual bool WriteFormID(BSStorage& storage, std::uint32_t) const = 0; // 5 + virtual bool ReadFormID(const BSStorage& storage, std::uint32_t&) const = 0; // 6 + + // members + BSScript::IObjectHandlePolicy* objectHandlePolicy; //08 + }; + static_assert(sizeof(BaseHandleReaderWriter) == 0x10); + + class SaveFileHandleReaderWriter : + public BaseHandleReaderWriter + { + public: + inline static constexpr auto RTTI = { RTTI::GameScript__DataFileHandleReaderWriter }; + inline static constexpr auto VTABLE = { VTABLE::GameScript__DataFileHandleReaderWriter }; + + ~SaveFileHandleReaderWriter() override; // 0 + //SaveFileHandleReaderWriter(BSScript::IObjectHandlePolicy * objectHandlePolicy); + + // override (GameScript::BaseHandleReaderWriter) + virtual bool WriteFormID(BSStorage& storage, std::uint32_t) const override; // 5 + virtual bool ReadFormID(const BSStorage& storage, std::uint32_t&) const override; // 6 + }; + static_assert(sizeof(SaveFileHandleReaderWriter) == 0x10); + + class DataFileHandleReaderWriter : + public BaseHandleReaderWriter + { + public: + inline static constexpr auto RTTI = { RTTI::GameScript__DataFileHandleReaderWriter }; + inline static constexpr auto VTABLE = { VTABLE::GameScript__DataFileHandleReaderWriter }; + + ~DataFileHandleReaderWriter() override; // 0 + //DataFileHandleReaderWriter(TESFile *f, BSScript::IObjectHandlePolicy * objectHandlePolicy); + + // override (GameScript::BaseHandleReaderWriter) + virtual bool WriteFormID(BSStorage& storage, std::uint32_t) const override; // 5 + virtual bool ReadFormID(const BSStorage& storage, std::uint32_t&) const override; // 6 + + // members + TESFile* file; //10 + }; + static_assert(sizeof(DataFileHandleReaderWriter) == 0x18); + +} \ No newline at end of file diff --git a/CommonLibSF/include/RE/I/IHandleReaderWriter.h b/CommonLibSF/include/RE/I/IHandleReaderWriter.h new file mode 100644 index 00000000..61436ba4 --- /dev/null +++ b/CommonLibSF/include/RE/I/IHandleReaderWriter.h @@ -0,0 +1,25 @@ +#pragma once + +namespace RE +{ + class BSStorage; + + namespace BSScript + { + struct __declspec(novtable) IHandleReaderWriter + { + public: + inline static constexpr auto RTTI = { RTTI::BSScript__IHandleReaderWriter }; + inline static constexpr auto VTABLE = { VTABLE::BSScript__IHandleReaderWriter }; + + virtual ~IHandleReaderWriter(); // 0 + + // add + virtual std::uint16_t GetHandleVersion() const = 0; // 142D8E390 + virtual bool WriteHandle(BSStorage& storage, std::uint64_t) const = 0; // 142D8E398 + virtual bool ReadHandle(BSStorage const& storage, std::uint64_t&) const = 0; // 142D8E3A0 + virtual bool ReadHandleNoRemap(BSStorage const& storage, std::uint64_t&) const = 0; // 142D8E3A8 + }; + static_assert(sizeof(IHandleReaderWriter) == 0x8); + } +} diff --git a/CommonLibSF/include/RE/Starfield.h b/CommonLibSF/include/RE/Starfield.h index b62ae753..35a0f189 100644 --- a/CommonLibSF/include/RE/Starfield.h +++ b/CommonLibSF/include/RE/Starfield.h @@ -233,12 +233,14 @@ #include "RE/H/HandlePolicy.h" #include "RE/H/Hazard.h" #include "RE/I/IAddressControllerStore.h" +#include "RE/H/HandleReaderWriter.h" #include "RE/I/IAnimationGraphManagerHolder.h" #include "RE/I/IBGSBaseFormData.h" #include "RE/I/ICachedErrorMessage.h" #include "RE/I/IComplexType.h" #include "RE/I/IFuncCallQuery.h" #include "RE/I/IFunction.h" +#include "RE/I/IHandleReaderWriter.h" #include "RE/I/IKeywordFormBase.h" #include "RE/I/ILoader.h" #include "RE/I/IMenu.h" From 12ae96ff23d46b3ea9ac04b29d73eae16cf22279 Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 10:59:49 -0700 Subject: [PATCH 21/39] feat: add ReadbleTypeTable, WritableStringTable, WritableTypeTable --- CommonLibSF/include/RE/R/ReadableTypeTable.h | 31 +++++++++++++++++++ CommonLibSF/include/RE/Starfield.h | 3 ++ .../include/RE/W/WritableStringTable.h | 25 +++++++++++++++ CommonLibSF/include/RE/W/WritableTypeTable.h | 25 +++++++++++++++ 4 files changed, 84 insertions(+) create mode 100644 CommonLibSF/include/RE/R/ReadableTypeTable.h create mode 100644 CommonLibSF/include/RE/W/WritableStringTable.h create mode 100644 CommonLibSF/include/RE/W/WritableTypeTable.h diff --git a/CommonLibSF/include/RE/R/ReadableTypeTable.h b/CommonLibSF/include/RE/R/ReadableTypeTable.h new file mode 100644 index 00000000..78f2fcb8 --- /dev/null +++ b/CommonLibSF/include/RE/R/ReadableTypeTable.h @@ -0,0 +1,31 @@ +#pragma once + +#include "RE/B/BSFixedString.h" +#include "RE/B/BSTSmartPointer.h" + +namespace RE +{ + namespace BSScript + { + namespace Internal + { + class ReadableTypeTable + { + public: + struct SaveTypeInfo : + public BSIntrusiveRefCounted // 00 + { + public: + // members + BSFixedString parentType; // 08 + BSScrapArray variableIndicies; // 10 + }; + static_assert(sizeof(SaveTypeInfo) == 0x28); + + // members + /*BSTScrapHashMap>* */ void* saveTypeInfo; // 00 + }; + static_assert(sizeof(ReadableTypeTable) == 0x08); + } + } +} diff --git a/CommonLibSF/include/RE/Starfield.h b/CommonLibSF/include/RE/Starfield.h index 35a0f189..f9d21a2a 100644 --- a/CommonLibSF/include/RE/Starfield.h +++ b/CommonLibSF/include/RE/Starfield.h @@ -304,6 +304,7 @@ #include "RE/P/PropertyTypeInfo.h" #include "RE/R/RawFuncCallQuery.h" #include "RE/R/ReadableStringTable.h" +#include "RE/R/ReadableTypeTable.h" #include "RE/R/RegSettingCollection.h" #include "RE/R/RemoteDebugger.h" #include "RE/RTTI.h" @@ -414,3 +415,5 @@ #include "RE/V/Variable.h" #include "RE/W/WwiseGUID.h" #include "RE/W/WwiseSoundHook.h" +#include "RE/W/WritableStringTable.h" +#include "RE/W/WritableTypeTable.h" diff --git a/CommonLibSF/include/RE/W/WritableStringTable.h b/CommonLibSF/include/RE/W/WritableStringTable.h new file mode 100644 index 00000000..38fe64b5 --- /dev/null +++ b/CommonLibSF/include/RE/W/WritableStringTable.h @@ -0,0 +1,25 @@ +#pragma once + +#include "RE/B/BSFixedString.h" +#include "RE/B/BSTObjectArena.h" + +namespace RE +{ + namespace BSScript + { + namespace Internal + { + enum class StringIndexSize; + + class WritableStringTable + { + public: + // members + msvc::unique_ptr> stringTable; // 00 + /*msvc::unique_ptr>*/ void* stringReferenceMap; // 08 + stl::enumeration indexSize; // 10 + }; + static_assert(sizeof(WritableStringTable) == 0x18); + } + } +} diff --git a/CommonLibSF/include/RE/W/WritableTypeTable.h b/CommonLibSF/include/RE/W/WritableTypeTable.h new file mode 100644 index 00000000..c00228f2 --- /dev/null +++ b/CommonLibSF/include/RE/W/WritableTypeTable.h @@ -0,0 +1,25 @@ +#pragma once + +#include "RE/B/BSFixedString.h" +#include "RE/B/BSTSmartPointer.h" + +namespace RE +{ + namespace BSScript + { + class ObjectTypeInfo; + class StructTypeInfo; + + namespace Internal + { + class WritableTypeTable + { + public: + // members + /*BSTScrapHashMap>* */ void* objectTypeMap; // 00 + /*BSTScrapHashMap>* */ void* structTypeMap; // 08 + }; + static_assert(sizeof(WritableTypeTable) == 0x10); + } + } +} From 3af60fc86c849a58b0628f7fbc639723aac643ab Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 10:59:50 -0700 Subject: [PATCH 22/39] feat: add SuspendedStack --- CommonLibSF/include/RE/S/SuspendedStack.h | 24 +++++++++++++++++++++++ CommonLibSF/include/RE/Starfield.h | 1 + 2 files changed, 25 insertions(+) create mode 100644 CommonLibSF/include/RE/S/SuspendedStack.h diff --git a/CommonLibSF/include/RE/S/SuspendedStack.h b/CommonLibSF/include/RE/S/SuspendedStack.h new file mode 100644 index 00000000..22bc8df5 --- /dev/null +++ b/CommonLibSF/include/RE/S/SuspendedStack.h @@ -0,0 +1,24 @@ +#pragma once + +#include "RE/I/IFuncCallQuery.h" +#include "RE/S/Stack.h" + +namespace RE +{ + namespace BSScript + { + class Stack; + + namespace Internal + { + struct SuspendedStack + { + public: + // members + BSTSmartPointer stack; // 00 + BSTSmartPointer funcCallQuery; // 08 + }; + static_assert(sizeof(SuspendedStack) == 0x10); + } + } +} diff --git a/CommonLibSF/include/RE/Starfield.h b/CommonLibSF/include/RE/Starfield.h index f9d21a2a..5b44b856 100644 --- a/CommonLibSF/include/RE/Starfield.h +++ b/CommonLibSF/include/RE/Starfield.h @@ -333,6 +333,7 @@ #include "RE/S/StreamBase.h" #include "RE/S/Struct.h" #include "RE/S/StructTypeInfo.h" +#include "RE/S/SuspendedStack.h" #include "RE/T/TBO_InstanceData.h" #include "RE/T/TESAIForm.h" #include "RE/T/TESActorBase.h" From be663965420e5b2ba06158bcf9d669c4b58c33c2 Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 11:00:01 -0700 Subject: [PATCH 23/39] feat: Add VirtualMachine --- .../include/RE/I/IVMFunctionMessageDispatch.h | 4 +- .../include/RE/I/IVMRemoteDebuggerInterface.h | 6 +- .../include/RE/I/IVMSaveLoadInterface.h | 2 +- CommonLibSF/include/RE/I/IVirtualMachine.h | 19 +- CommonLibSF/include/RE/Starfield.h | 1 + CommonLibSF/include/RE/V/VirtualMachine.h | 327 ++++++++++++++++++ 6 files changed, 350 insertions(+), 9 deletions(-) create mode 100644 CommonLibSF/include/RE/V/VirtualMachine.h diff --git a/CommonLibSF/include/RE/I/IVMFunctionMessageDispatch.h b/CommonLibSF/include/RE/I/IVMFunctionMessageDispatch.h index 7fdb9b9a..600f239e 100644 --- a/CommonLibSF/include/RE/I/IVMFunctionMessageDispatch.h +++ b/CommonLibSF/include/RE/I/IVMFunctionMessageDispatch.h @@ -2,13 +2,13 @@ namespace RE::BSScript::Internal { - class __declspec(novtable) IVMFunctionMessageDispatch + struct __declspec(novtable) IVMFunctionMessageDispatch { public: SF_RTTI(BSScript__Internal__IVMFunctionMessageDispatch); // VTable got optimized out? - virtual void Unk00(); // 00 + virtual void Unk00() = 0; // 00 virtual ~IVMFunctionMessageDispatch(); // 01 -- destructor is BELOW the first function. }; static_assert(sizeof(IVMFunctionMessageDispatch) == 0x8); diff --git a/CommonLibSF/include/RE/I/IVMRemoteDebuggerInterface.h b/CommonLibSF/include/RE/I/IVMRemoteDebuggerInterface.h index 2ff821a3..c991af0c 100644 --- a/CommonLibSF/include/RE/I/IVMRemoteDebuggerInterface.h +++ b/CommonLibSF/include/RE/I/IVMRemoteDebuggerInterface.h @@ -11,9 +11,9 @@ namespace RE::BSScript ~IVMRemoteDebuggerInterface() = delete; - virtual void Unk00(); // 00 -- calls Unk05 in IVirtualMachine - virtual void Unk01(); // 01 - virtual void Unk02(); // 02 + virtual bool IsCompletelyFrozen() = 0; // 00 -- just calls IsCompletelyFrozen on the VM + virtual void Unk01() = 0; // 01 + virtual void Unk02() = 0; // 02 }; static_assert(sizeof(IVMRemoteDebuggerInterface) == 0x8); } diff --git a/CommonLibSF/include/RE/I/IVMSaveLoadInterface.h b/CommonLibSF/include/RE/I/IVMSaveLoadInterface.h index 06e8a4e9..107995bc 100644 --- a/CommonLibSF/include/RE/I/IVMSaveLoadInterface.h +++ b/CommonLibSF/include/RE/I/IVMSaveLoadInterface.h @@ -54,7 +54,7 @@ namespace RE virtual void SetSaveHandleForArray(const Array* a_Array, std::uint64_t) = 0; // 14 virtual bool GetArrayBySaveHandle(std::uint64_t handle, BSTSmartPointer& a_array_pointer) const = 0; // 15 virtual bool GetStackByID(unsigned int, BSTSmartPointer& a_stack_pointer) const = 0; // 16 - virtual void unk_17(void) = 0; // 17 + virtual bool IsStackRunning(std::uint32_t a_stackid) = 0; // 17 virtual const Internal::WritableStringTable& GetWritableStringTable() const = 0; // 18 virtual const Internal::WritableStringTable& GetWritableStringTable() = 0; // 19 virtual Internal::ReadableStringTable& GetReadableStringTable() const = 0; // 1A diff --git a/CommonLibSF/include/RE/I/IVirtualMachine.h b/CommonLibSF/include/RE/I/IVirtualMachine.h index c219e6eb..5b2c0065 100644 --- a/CommonLibSF/include/RE/I/IVirtualMachine.h +++ b/CommonLibSF/include/RE/I/IVirtualMachine.h @@ -43,6 +43,19 @@ namespace RE public: SF_RTTI_VTABLE(BSScript__IVirtualMachine); + struct GlobalGuardData + { + std::byte unk00[0x108]; // 00 + BSNonReentrantSpinLock guardlock; // 108 + }; + + struct GuardDataIFace + { + IVirtualMachine* thisVMInterface; // 000 + GlobalGuardData globalGuardData; // 008 + }; + static_assert(sizeof(GuardDataIFace) == 0x118); + virtual ~IVirtualMachine() = default; // 00 // add @@ -97,15 +110,15 @@ namespace RE virtual bool DispatchMethodCall(const BSTSmartPointer& a_self, const BSFixedString& a_funcName, const BSTThreadScrapFunction&)>& a_arguments, const BSTSmartPointer& a_callback, int a_unk0) = 0; // 31 virtual bool DispatchUnboundMethodCall(std::uint64_t a_objHandle, const BSTSmartPointer& a_script, const BSFixedString& a_funcName, const BSTThreadScrapFunction&)>& a_arguments, const BSTSmartPointer& a_callback, int a_unk0) = 0; // 32 virtual void ReturnFromLatent(std::uint32_t a_stackID, const Variable& a_retValue) = 0; // 33 -- IsWaitingOnLatent was removed - virtual void UnkGuardFunction(void) = 0; // 34 + virtual void ReattemptGuardLock(std::uint32_t a_stackID) = 0; // 34 [[nodiscard]] virtual ErrorLogger& GetErrorLogger() const = 0; // 35 [[nodiscard]] virtual const IObjectHandlePolicy& GetObjectHandlePolicy() const = 0; // 36 [[nodiscard]] virtual IObjectHandlePolicy& GetObjectHandlePolicy() = 0; // 37 [[nodiscard]] virtual const ObjectBindPolicy& GetObjectBindPolicy() const = 0; // 38 [[nodiscard]] virtual ObjectBindPolicy& GetObjectBindPolicy() = 0; // 39 [[nodiscard]] virtual ISavePatcherInterface& GetSavePatcherInterface() = 0; // 3A - [[nodiscard]] virtual const IVirtualMachine& GetVMInterface() const = 0; // 3B - [[nodiscard]] virtual IVirtualMachine& GetVMInterface() = 0; // 3C + [[nodiscard]] virtual const GuardDataIFace GetGlobalGuardDataInterface() const = 0; // 3B + [[nodiscard]] virtual GuardDataIFace GetGlobalGuardDataInterface() = 0; // 3C virtual void RegisterForLogEvent(BSTEventSink* a_sink) = 0; // 3D virtual void UnregisterForLogEvent(BSTEventSink* a_sink) = 0; // 3E virtual void RegisterForStatsEvent(BSTEventSink* a_sink) = 0; // 3F diff --git a/CommonLibSF/include/RE/Starfield.h b/CommonLibSF/include/RE/Starfield.h index 5b44b856..965da9cc 100644 --- a/CommonLibSF/include/RE/Starfield.h +++ b/CommonLibSF/include/RE/Starfield.h @@ -416,5 +416,6 @@ #include "RE/V/Variable.h" #include "RE/W/WwiseGUID.h" #include "RE/W/WwiseSoundHook.h" +#include "RE/V/VirtualMachine.h" #include "RE/W/WritableStringTable.h" #include "RE/W/WritableTypeTable.h" diff --git a/CommonLibSF/include/RE/V/VirtualMachine.h b/CommonLibSF/include/RE/V/VirtualMachine.h new file mode 100644 index 00000000..d35f9863 --- /dev/null +++ b/CommonLibSF/include/RE/V/VirtualMachine.h @@ -0,0 +1,327 @@ +#pragma once + +#include "RE/B/BSFixedString.h" +#include "RE/B/BSLock.h" +// #include "RE/I/IClientVM.h" +#include "RE/B/BSContainer.h" +#include "RE/B/BSTEvent.h" +#include "RE/E/ErrorLogger.h" +#include "RE/I/IVMDebugInterface.h" +#include "RE/I/IVMFunctionMessageDispatch.h" +#include "RE/I/IVMObjectBindInterface.h" +#include "RE/I/IVMRemoteDebuggerInterface.h" +#include "RE/I/IVMSaveLoadInterface.h" +#include "RE/I/IVirtualMachine.h" +#include "RE/L/LinkerProcessor.h" +#include "RE/R/ReadableStringTable.h" +#include "RE/R/ReadableTypeTable.h" +#include "RE/S/SuspendedStack.h" +#include "RE/W/WritableStringTable.h" +#include "RE/W/WritableTypeTable.h" + +namespace RE +{ + namespace BSScript + { + class Array; + class ErrorLogger; + class IFreezeQuery; + class IProfilePolicy; + class ISavePatcherInterface; + class IStackCallbackFunctor; + class IStackCallbackSaveInterface; + class ObjectBindPolicy; + class Stack; + class IRemoteDebugger; + class IClientVM; + + struct IMemoryPagePolicy; + struct IObjectHandlePolicy; + struct StatsEvent; + + namespace Internal + { + class CodeTasklet; + + class VirtualMachine : + public IVirtualMachine, // 0000 + /* IVM -> public BSIntrusiveRefCounted */ // 0008 + public IVMObjectBindInterface, // 0010 + public IVMSaveLoadInterface, // 0018 + public IVMDebugInterface, // 0020 + public IVMRemoteDebuggerInterface, // 0028 + public IVMFunctionMessageDispatch, // 0030 + public BSTEventSource // 0038 + { + public: + static constexpr auto RTTI{ RTTI::BSScript__Internal__VirtualMachine }; + static constexpr auto VTABLE{ VTABLE::BSScript__Internal__VirtualMachine }; + + enum class FreezeState + { + kNotFrozen = 0, + kFreezing, + kFrozen + }; + + struct LoadedArrayEntry + { + public: + // members + BSTSmartPointer array; // 00 + std::uint32_t arraySize; // 08 + }; + static_assert(sizeof(LoadedArrayEntry) == 0x10); + + struct PendingLatentReturn + { + public: + // members + std::uint32_t stackID; // 00 + Variable returnValue; // 08 + }; + static_assert(sizeof(PendingLatentReturn) == 0x18); + + struct QueuedUnbindRefs + { + public: + // members + BSTSmartPointer obj; // 00 + std::uint32_t refCount; // 08 + std::uint32_t pad0C; // 0C + }; + static_assert(sizeof(QueuedUnbindRefs) == 0x10); + + ~VirtualMachine() override; // 00 + + using RE::BSScript::IVirtualMachine::SendEvent; + //using RE::BSTEventSource::SendEvent; + + public: + // override (IVirtualMachine) + // add + virtual void SetLoader(ILoader* a_newLoader) override; // 01 + virtual void SetLinkedCallback(ITypeLinkedCallback* a_typeLinkedCallback) override; // 02 + virtual void Update(float a_updateBudget) override; // 03 + virtual void UpdateTasklets(float a_updateBudget) override; // 04 + virtual void Unk_05(void) override; // 05 + virtual void SetOverstressed(bool a_overstressed) override; // 06 + virtual void Unk_07(void) override; // 07 + virtual bool IsCompletelyFrozen() const override; // 08 + virtual void Unk_09(void) override; // 09 + virtual bool RegisterObjectType(std::uint32_t a_typeID, const char* a_objectTypeName) override; // 0A + virtual bool GetScriptObjectType(std::uint32_t a_typeID, BSTSmartPointer& a_objType) override; // 0B + virtual bool GetScriptObjectType(const BSFixedString& a_name, BSTSmartPointer& a_objType) override; // 0C + virtual bool GetScriptObjectTypeNoLoad(std::uint32_t a_typeID, BSTSmartPointer& a_objType) const override; // 0D + virtual bool GetScriptObjectTypeNoLoad(const BSFixedString& a_objectTypeName, BSTSmartPointer& a_objType) const override; // 0E + virtual bool GetTypeIDForScriptObject(const BSFixedString& a_objectTypeName, std::uint32_t& a_typeID) const override; // 0F + virtual void GetScriptObjectsWithATypeID(BSScrapArray& a_objectTypeList) const override; // 10 + virtual bool GetParentNativeType(const BSFixedString& a_childTypeName, BSTSmartPointer& a_parentType) override; // 11 + virtual bool TypeIsValid(const BSFixedString& a_objectTypeName) override; // 12 + virtual bool ReloadType(const char* a_objectTypeName) override; // 13 + virtual void TasksToJobs(JobList& a_jobList) override; // 14 + virtual void CalculateFullReloadList(const /*BSTSet&*/ void* a_scriptSet, /*BSTObjectArena&*/ void* a_scriptList) const override; // 15 + virtual bool GetScriptStructType(const BSFixedString& a_structTypeName, BSTSmartPointer& a_structType) override; // 16 + virtual bool GetScriptStructTypeNoLoad(const BSFixedString& a_structTypeName, BSTSmartPointer& a_structType) const override; // 17 + virtual bool GetChildStructTypes(const BSFixedString& a_parentObjectName, /*BSTObjectArena&*/ void* a_structTypes) const override; // 18 + virtual bool CreateObject(const BSFixedString& a_objectTypeName, const /*BSTScrapHashMap&*/ void* a_properties, BSTSmartPointer& a_newObj) override; // 19 + virtual bool CreateObject(const BSFixedString& a_objectTypeName, BSTSmartPointer& a_newObj) override; // 1A + virtual bool CreateStruct(const BSFixedString& a_structTypeName, BSTSmartPointer& a_newStruct) override; // 1B + virtual bool CreateArray(TypeInfo::RawType a_elementType, const BSFixedString& a_elementObjectTypeName, std::uint32_t a_elementCount, BSTSmartPointer& a_newArray) override; // 1C + virtual bool CreateArray(const TypeInfo& a_type, std::uint32_t a_elementCount, BSTSmartPointer& a_newArray) override; // 1D + virtual bool BindNativeMethod(IFunction* a_function) override; // 1E + virtual void SetCallableFromTasklets(const char* a_objectName, const char* a_functionName, bool a_taskletCallable) override; // 1F + virtual void SetCallableFromTasklets(const char* a_objectName, const char* a_stateName, const char* a_functionName, bool a_taskletCallable) override; // 20 + virtual void ForEachBoundObject(std::uint64_t a_objHandle, const BSTThreadScrapFunction& a_functor) override; // 21 + virtual bool FindBoundObject(std::uint64_t a_objHandle, const char* a_objectTypeName, bool a_allowConst, BSTSmartPointer& a_attachedObj, bool a_exactMatch) const override; // 22 + virtual void MoveBoundObjects(std::uint64_t a_sourceHandle, std::uint64_t a_destHandle) override; // 23 + virtual void ResetAllBoundObjects(std::uint64_t a_objHandle) override; // 24 + virtual bool CastObject(const BSTSmartPointer& a_sourceObj, const BSTSmartPointer& a_targetType, BSTSmartPointer& a_castedObj) override; // 25 + virtual bool SetPropertyValue(const BSTSmartPointer& a_self, ...) override; // 26 -- unknown VA args + virtual bool GetPropertyValue(const BSTSmartPointer& a_self, const char* a_propName, const BSTSmartPointer& a_callback, int a_unk0) override; // 27 + virtual bool GetVariableValue(std::uint64_t a_objHandle, const BSFixedString& a_scriptName, std::uint32_t a_varIndex, Variable& a_var) const override; // 28 + virtual bool GetVariableValue(const BSTSmartPointer& a_obj, std::uint32_t a_varIndex, Variable& a_var) const override; // 29 + virtual bool HandleImplementsEvent(std::uint64_t a_object, const BSFixedString& a_eventName) const override; // 2A + virtual bool AddEventRelay(std::uint64_t a_sourceObject, const BSFixedString& a_eventName, const BSTSmartPointer& a_destObj) override; // 2B + virtual void RemoveEventRelay(std::uint64_t a_sourceObject, const BSFixedString& a_eventName, const BSTSmartPointer& a_destObj) override; // 2C + virtual void RemoveAllEventRelays(const BSTSmartPointer& a_destObj) override; // 2D + virtual void SendEvent(std::uint64_t a_objHandle, const BSFixedString& a_eventName, const BSTThreadScrapFunction&)>& a_arguments, const BSTThreadScrapFunction&)>& a_filter, const BSTSmartPointer& a_callback, int a_unk0) override; // 2E + virtual bool DispatchStaticCall(const BSFixedString& a_objName, const BSFixedString& a_funcName, const BSTThreadScrapFunction&)>& a_arguments, const BSTSmartPointer& a_callback, int a_unk0) override; // 2F + virtual bool DispatchMethodCall(std::uint64_t a_objHandle, const BSFixedString& a_objName, const BSFixedString& a_funcName, const BSTThreadScrapFunction&)>& a_arguments, const BSTSmartPointer& a_callback, int a_unk0) override; // 30 + virtual bool DispatchMethodCall(const BSTSmartPointer& a_self, const BSFixedString& a_funcName, const BSTThreadScrapFunction&)>& a_arguments, const BSTSmartPointer& a_callback, int a_unk0) override; // 31 + virtual bool DispatchUnboundMethodCall(std::uint64_t a_objHandle, const BSTSmartPointer& a_script, const BSFixedString& a_funcName, const BSTThreadScrapFunction&)>& a_arguments, const BSTSmartPointer& a_callback, int a_unk0) override; // 32 + virtual void ReturnFromLatent(std::uint32_t a_stackID, const Variable& a_retValue) override; // 33 -- IsWaitingOnLatent was removed + virtual void ReattemptGuardLock(std::uint32_t a_stackID) override; // 34 + [[nodiscard]] virtual ErrorLogger& GetErrorLogger() const override; // 35 + [[nodiscard]] virtual const IObjectHandlePolicy& GetObjectHandlePolicy() const override; // 36 + [[nodiscard]] virtual IObjectHandlePolicy& GetObjectHandlePolicy() override; // 37 + [[nodiscard]] virtual const ObjectBindPolicy& GetObjectBindPolicy() const override; // 38 + [[nodiscard]] virtual ObjectBindPolicy& GetObjectBindPolicy() override; // 39 + [[nodiscard]] virtual ISavePatcherInterface& GetSavePatcherInterface() override; // 3A + [[nodiscard]] virtual const GuardDataIFace GetGlobalGuardDataInterface() const override; // 3B + [[nodiscard]] virtual GuardDataIFace GetGlobalGuardDataInterface() override; // 3C + virtual void RegisterForLogEvent(BSTEventSink* a_sink) override; // 3D + virtual void UnregisterForLogEvent(BSTEventSink* a_sink) override; // 3E + virtual void RegisterForStatsEvent(BSTEventSink* a_sink) override; // 3F + virtual void UnregisterForStatsEvent(BSTEventSink* a_sink) override; // 40 + virtual void PostCachedErrorToLogger(const ICachedErrorMessage& a_errorFunctor, ErrorLogger::Severity a_severity) const override; // 41 + virtual void PostCachedErrorToLogger(const ICachedErrorMessage& a_errorFunctor, std::uint32_t a_stackID, ErrorLogger::Severity a_severity) const override; // 42 + + // override (IVMObjectBindInterface) + [[nodiscard]] virtual std::uint64_t GetBoundHandle(const BSTSmartPointer& a_objPtr) const override; // 01 + virtual void TypeCanBeBound(const BSFixedString& a_className, std::uint64_t a_handle) override; // 02 + virtual void BindObject(BSTSmartPointer& a_objPtr, std::uint64_t a_handle, bool a_conditional) override; // 03 + virtual void HandleLoadedBinding(BSTSmartPointer& a_objPtr, std::uint64_t a_handle, bool a_conditional) override; // 04 + virtual void RemoveAllBoundObjects(std::uint64_t a_handle) override; // 05 + virtual void RemoveAllDiskLoadedBoundObjects(std::uint64_t a_handle) override; // 06 + virtual void HandleCObjectDeletion(std::uint64_t a_handle) override; // 07 + virtual void UnbindObject(const BSTSmartPointer& a_objPtr) override; // 08 + virtual bool CreateObjectWithProperties(const BSFixedString& a_className, std::uint32_t a_numProperties, BSTSmartPointer& a_objPtr) override; // 09 + virtual bool InitObjectProperties(BSTSmartPointer& a_objPtr, void* a_property, bool a_arg3) override; // 0A + + // override (IVMSaveLoadInterface) + virtual bool SaveGame(BSStorage& a_storage, IHandleReaderWriter const& a_HandleReaderWriter, bool a_flag) override; // 01 + virtual bool LoadGame(BSStorage const& a_storage, IHandleReaderWriter const& a_HandleReaderWriter, bool& a_flag, bool& b_flag) override; // 02 + virtual void MarkSaveInvalid(BSStorage& a_storage) override; // 03 + virtual unsigned short GetSaveGameVersion() const override; // 04 + virtual void CleanupSave() override; // 05 + virtual void CleanupLoad() override; // 06 + virtual void DropAllRunningData() override; // 07 + virtual std::uint64_t GetSaveHandleForObject(const Object* a_Object) const override; // 08 + virtual void SetSaveHandleForObject(const Object* a_Object, std::uint64_t) override; // 09 + virtual bool GetObjectBySaveHandle(std::uint64_t, const TypeInfo& a_TypeInfo, BSTSmartPointer& a_object_pointer) const override; // 0A + virtual bool GetObjectBySaveHandle(std::uint64_t, BSTSmartPointer& a_object_pointer) const override; // 0B + virtual void unk_0C(void) override; // 0C + virtual void unk_0D(void) override; // 0D + virtual std::uint64_t GetSaveHandleForStruct(const Struct* a_Struct) const override; // 0E + virtual void SetSaveHandleForStruct(const Struct* a_Struct, std::uint64_t) override; // 0F + virtual bool GetStructBySaveHandle(std::uint64_t, BSTSmartPointer& a_object_pointer) const override; // 10 + virtual void unk_11(void) override; // 11 + virtual void unk_12(void) override; // 12 + virtual std::uint64_t GetSaveHandleForArray(const Array* a_Array) const override; // 13 + virtual void SetSaveHandleForArray(const Array* a_Array, std::uint64_t) override; // 14 + virtual bool GetArrayBySaveHandle(std::uint64_t handle, BSTSmartPointer& a_array_pointer) const override; // 15 + virtual bool GetStackByID(unsigned int, BSTSmartPointer& a_stack_pointer) const override; // 16 + virtual bool IsStackRunning(std::uint32_t a_stackid) override; // 17 + virtual const Internal::WritableStringTable& GetWritableStringTable() const override; // 18 + virtual const Internal::WritableStringTable& GetWritableStringTable() override; // 19 + virtual Internal::ReadableStringTable& GetReadableStringTable() const override; // 1A + virtual const Internal::WritableTypeTable& GetWritableTypeTable() const override; // 1B + virtual Internal::WritableTypeTable& GetWritableTypeTable() override; // 1C + virtual const Internal::ReadableTypeTable& GetReadableTypeTable() const override; // 1D + virtual void unk_1E(void) override; // 1E + virtual bool CreateEmptyTasklet(Stack* a_Stack, BSTSmartPointer& a_tasklet_pointer) override; // 1F + + // override (IVMDebugInterface) + virtual void DumpRunningStacksToLog() override; // 01 + virtual void DumpStackFrameToLog(unsigned int a_v, unsigned int b_v, bool a_flag) override; // 02 + virtual void GetStackFrame(unsigned int a_v, unsigned int b_v, bool a_flag, BSFixedString& a_identifier) override; // 03 + virtual void DumpPersistenceInformationToLog(char const* logfile, uint64_t a_v) const override; // 04 + virtual void DumpEventRelayInformationToLog(char const* logfile, uint64_t a_v, BSFixedString const& a_string) const override; // 05 + + // override (IVMRemoteDebuggerInterface) + virtual bool IsCompletelyFrozen() override; // 00 + virtual void Unk01() override; // 01 + virtual void Unk02() override; // 02 + + // override (IVMFunctionMessageDispatch) + virtual void Unk00() override; // 00 + + static VirtualMachine* GetSingleton(); + + //bool StackExists(std::uint32_t stack_id); + + // members + ErrorLogger* errorLogger; // 0060 + IMemoryPagePolicy* memoryPagePolicy; // 0068 + IObjectHandlePolicy* handlePolicy; // 0070 + ObjectBindPolicy* objectBindPolicy; // 0078 + IClientVM* clientVM; // 0080 + IStackCallbackSaveInterface* stackCallbackSaveInterface; // 0088 + IProfilePolicy* profilePolicy; // 0090 + IRemoteDebugger* remoteDebugger; // 0098 + ISavePatcherInterface* savePatcherInterface; // 00A0 + GuardDataIFace globalGuardDataInterface; // 00A8 + std::uint64_t unk01C0; // 01C0 -- 2nd param passed into constructor + 0x10 + mutable BSSpinLock typeInfoLock; // 01C8 + LinkerProcessor linker; // 01D0 + /*BSTHashMap>*/ std::byte objectTypeMap[0x38]; // 0258 + /*BSTHashMap>*/ std::byte structTypeMap[0x38]; // 0290 + /*BSTHashMap*/ std::byte typeIDToObjectType[0x38]; // 02C8 + /*BSTHashMap*/ std::byte objectTypeToTypeID[0x38]; // 0300 + BSTArray> typesToUnload; // 0338 + std::byte gap_0348[0x380 - 0x348]; // 0348 + /*BSScript::Internal::FunctionMessageProcessor*/ std::byte funcMsgProcessor[0x3C0]; // 0380 + BSTArray vmTasks; // 0740 + BSNonReentrantSpinLock vmTasksLock; // 0750 + std::uint32_t gap_754; // 0754 + bool overstressed; // 0758 + std::byte gap0759[0x780 - 0x759]; // 0759 + /*BSTCommonStaticMessageQueue*/ std::byte suspendQueue1[0x1A80]; // 0780 + /*BSTCommonStaticMessageQueue*/ std::byte suspendQueue2[0x1A80]; // 2200 + BSTArray overflowSuspendArray1; // 3C80 + BSTArray overflowSuspendArray2; // 3C90 + mutable BSSpinLock suspendQueueLock; // 3CA0 + /*BSTCommonStaticMessageQueue* */ void* stacksToResume; // 3CA8 - ref to suspendQueue1 + BSTArray* stacksToResumeOverflow; // 3CB0 - ref to overflowSuspendArray1 + /*BSTCommonStaticMessageQueue* */ void* stacksToSuspend; // 3CB8 - ref to suspendQueue2 + BSTArray* stacksToSuspendOverflow; // 3CC0 - ref to overflowSuspendArray2 + mutable BSReadWriteLock runningStacksLock; // 3CC8 + /*BSTHashMap>*/ std::byte allRunningStacks[0x38]; // 3CD0 + BSTArray waitingLatentReturns; // 3D08 + std::uint32_t nextStackID; // 3D18 + mutable BSSpinLock frozenStacksLock; // 3D1C + std::uint32_t gap3D24; // 3D24 + BSTArray> pendingLatentReturns; // 3D28 + BSTArray stacksWaitingOnGuard; // 3D38 + BSTSmartPointer frozenStacksHead; // 3D48 + std::uint32_t frozenStacksCount; // 3D50 + stl::enumeration freezeState; // 3D54 + mutable BSSpinLock attachedScriptsLock; // 3D58 + /*BSTHashMap>*/ std::byte attachedScripts[0x38]; // 3D60 + std::uint64_t unk3D98; // 3D98 + std::uint32_t nextObjectToClean; // 3DA0 + std::uint32_t gap3DA4; // 3DA4 + std::uint64_t nextAttachedObjectToClean; // 3DA8 + BSTArray> detachedScripts; // 3DB0 + mutable BSSpinLock structsLock; // 3DC0 + std::uint32_t nextStructToClean; // 3DC8 + BSTArray> allStructs; // 3DD0 + mutable BSSpinLock arraysLock; // 3DE0 + std::uint32_t nextArrayToClean; // 3DE8 + BSTArray> arrays; // 3DF0 + mutable BSSpinLock objectResetLock; // 3E00 + BSTArray> objectsAwaitingReset; // 3E08 + mutable BSSpinLock loadTableLock; // 3E18 + /*BSTHashMap>*/ std::byte loadTable[0x38]; // 3E20 + /*BSTHashMap */ std::byte loadHandlesTable[0x38]; // 3E58 + /*BSTHashMap>*/ std::byte structLoadTable[0x38]; // 3E90 + /*BSTHashMap */ std::byte arrayLoadTable[0x38]; // 3EC8 + std::uint64_t unk3F00; // 3F00 + mutable BSSpinLock queuedUnbindLock; // 3F08 + BSTArray queuedUnbinds; // 3F10 + mutable BSSpinLock eventRelayLock; // 3F20 + /* BSTHashMap>*/ std::byte eventRelays[0x38]; // 3F28 + std::uint64_t unk3F60; // 3F60 + std::uint64_t unk3F68; // 3F68 + std::uint64_t unk3F70; // 3F70 + std::uint64_t unk3F78; // 3F78 + std::uint16_t currentSaveGameVersion; // 3F80 + std::uint16_t gap3F82; // 3F82 + std::uint32_t saveObjectCount; // 3F84 + std::uint32_t saveObjectDataCount; // 3F88 + std::uint32_t saveStructCount; // 3F8C + std::uint32_t saveArrayCount; // 3F90 + std::uint32_t gap3F94; // 3F94 + WritableStringTable writableStringTable; // 3F98 + ReadableStringTable readableStringTable; // 3FB0 + WritableTypeTable writableTypeTable; // 3FC8 + ReadableTypeTable readableTypeTable; // 3FD8 + std::byte pad3FE0[0x4040 - 0x3FE0]; // 3FE0 + }; + static_assert(sizeof(VirtualMachine) == 0x4040); + static_assert(offsetof(VirtualMachine, writableStringTable) == 0x3F98); + static_assert(offsetof(VirtualMachine, frozenStacksLock) == 0x3D1C); + } + } +} From f7cb46fe310e2d94e832d2980213c89795eb21cf Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 11:00:04 -0700 Subject: [PATCH 24/39] feat: add IClientVM --- CommonLibSF/include/RE/I/IClientVM.h | 22 ++++++++++++++++++++++ CommonLibSF/include/RE/Starfield.h | 1 + 2 files changed, 23 insertions(+) create mode 100644 CommonLibSF/include/RE/I/IClientVM.h diff --git a/CommonLibSF/include/RE/I/IClientVM.h b/CommonLibSF/include/RE/I/IClientVM.h new file mode 100644 index 00000000..0ce9b127 --- /dev/null +++ b/CommonLibSF/include/RE/I/IClientVM.h @@ -0,0 +1,22 @@ +#pragma once + +namespace RE +{ + namespace BSScript + { + class __declspec(novtable) IClientVM + { + public: + static constexpr auto RTTI{ RTTI::BSScript__IClientVM }; + static constexpr auto VTABLE{ VTABLE::BSScript__IClientVM }; + + virtual ~IClientVM() = default; // 00 + + // add + virtual bool IsVMFrozen() const = 0; // 01 + virtual void PreSave() = 0; // 02 + virtual void Unk_03(void) = 0; // 03 + }; + static_assert(sizeof(IClientVM) == 0x8); + } +} diff --git a/CommonLibSF/include/RE/Starfield.h b/CommonLibSF/include/RE/Starfield.h index 965da9cc..c6895a50 100644 --- a/CommonLibSF/include/RE/Starfield.h +++ b/CommonLibSF/include/RE/Starfield.h @@ -237,6 +237,7 @@ #include "RE/I/IAnimationGraphManagerHolder.h" #include "RE/I/IBGSBaseFormData.h" #include "RE/I/ICachedErrorMessage.h" +#include "RE/I/IClientVM.h" #include "RE/I/IComplexType.h" #include "RE/I/IFuncCallQuery.h" #include "RE/I/IFunction.h" From a9a224c892b87a95efbcbbbda1724b31c5aca94e Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 11:00:04 -0700 Subject: [PATCH 25/39] fix: fix VirtualMachine IClient --- CommonLibSF/include/RE/V/VirtualMachine.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/CommonLibSF/include/RE/V/VirtualMachine.h b/CommonLibSF/include/RE/V/VirtualMachine.h index d35f9863..fbb136e4 100644 --- a/CommonLibSF/include/RE/V/VirtualMachine.h +++ b/CommonLibSF/include/RE/V/VirtualMachine.h @@ -1,11 +1,11 @@ #pragma once +#include "RE/B/BSContainer.h" #include "RE/B/BSFixedString.h" #include "RE/B/BSLock.h" -// #include "RE/I/IClientVM.h" -#include "RE/B/BSContainer.h" #include "RE/B/BSTEvent.h" #include "RE/E/ErrorLogger.h" +#include "RE/I/IClientVM.h" #include "RE/I/IVMDebugInterface.h" #include "RE/I/IVMFunctionMessageDispatch.h" #include "RE/I/IVMObjectBindInterface.h" @@ -33,7 +33,6 @@ namespace RE class ObjectBindPolicy; class Stack; class IRemoteDebugger; - class IClientVM; struct IMemoryPagePolicy; struct IObjectHandlePolicy; From 6f5bb91cb2759d06de5e53b28bc44aa013a12065 Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 11:00:04 -0700 Subject: [PATCH 26/39] feat: add IStackCallbackSaveInterface --- .../RE/I/IStackCallbackSaveInterface.h | 27 +++++++++++++++++++ CommonLibSF/include/RE/Starfield.h | 1 + 2 files changed, 28 insertions(+) create mode 100644 CommonLibSF/include/RE/I/IStackCallbackSaveInterface.h diff --git a/CommonLibSF/include/RE/I/IStackCallbackSaveInterface.h b/CommonLibSF/include/RE/I/IStackCallbackSaveInterface.h new file mode 100644 index 00000000..c47cdb73 --- /dev/null +++ b/CommonLibSF/include/RE/I/IStackCallbackSaveInterface.h @@ -0,0 +1,27 @@ +#pragma once + +#include "RE/B/BSTSmartPointer.h" + +namespace RE +{ + class BSStorage; + + namespace BSScript + { + class IStackCallbackFunctor; + + class __declspec(novtable) IStackCallbackSaveInterface + { + public: + static constexpr auto RTTI{ RTTI::BSScript__IStackCallbackSaveInterface }; + static constexpr auto VTABLE{ VTABLE::BSScript__IStackCallbackSaveInterface }; + + virtual ~IStackCallbackSaveInterface() = default; // 00 + + // add + virtual bool SaveStackCallback(BSStorage& a_buffer, const BSTSmartPointer& a_callback) const = 0; // 01 + virtual bool LoadStackCallback(const BSStorage& a_buffer, bool&, BSTSmartPointer& a_callback) const = 0; // 02 + }; + static_assert(sizeof(IStackCallbackSaveInterface) == 0x8); + } +} diff --git a/CommonLibSF/include/RE/Starfield.h b/CommonLibSF/include/RE/Starfield.h index c6895a50..9650d962 100644 --- a/CommonLibSF/include/RE/Starfield.h +++ b/CommonLibSF/include/RE/Starfield.h @@ -256,6 +256,7 @@ #include "RE/I/IPostAnimationChannelUpdateFunctor.h" #include "RE/I/IRemoteDebugger.h" #include "RE/I/ISavePatcherInterface.h" +#include "RE/I/IStackCallbackSaveInterface.h" #include "RE/I/IStore.h" #include "RE/I/IStoreAnimationActions.h" #include "RE/I/IVMDebugInterface.h" From 0e729b3782b20df30c655f006199c9a3753360b3 Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 11:00:04 -0700 Subject: [PATCH 27/39] fix: Fix IFuncCallQuery namespace --- CommonLibSF/include/RE/I/IFuncCallQuery.h | 45 ++++++++++++----------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/CommonLibSF/include/RE/I/IFuncCallQuery.h b/CommonLibSF/include/RE/I/IFuncCallQuery.h index 3ecc2935..db5b23b5 100644 --- a/CommonLibSF/include/RE/I/IFuncCallQuery.h +++ b/CommonLibSF/include/RE/I/IFuncCallQuery.h @@ -11,28 +11,31 @@ namespace RE::BSScript class ObjectTypeInfo; class Object; - class IFuncCallQuery : public BSIntrusiveRefCounted + namespace Internal { - public: - SF_RTTI_VTABLE(BSScript__Internal__IFuncCallQuery); - - enum class CallType + class IFuncCallQuery : public BSIntrusiveRefCounted { - kMember, - kStatic, - kGetter, - kSetter - }; - virtual ~IFuncCallQuery(); // 00 + public: + SF_RTTI_VTABLE(BSScript__Internal__IFuncCallQuery); - // add - virtual bool GetFunctionCallInfo( - CallType& a_callType, - BSTSmartPointer& a_objectTypeInfo, - BSFixedString& a_name, - Variable& a_self, - void* /* BSScrapArray& */ a_args) const = 0; // 01 - virtual BSTSmartPointer GetSelfAsObject() const = 0; // 02 - }; - static_assert(sizeof(IFuncCallQuery) == 0x10); + enum class CallType + { + kMember, + kStatic, + kGetter, + kSetter + }; + virtual ~IFuncCallQuery(); // 00 + + // add + virtual bool GetFunctionCallInfo( + CallType& a_callType, + BSTSmartPointer& a_objectTypeInfo, + BSFixedString& a_name, + Variable& a_self, + void* /* BSScrapArray& */ a_args) const = 0; // 01 + virtual BSTSmartPointer GetSelfAsObject() const = 0; // 02 + }; + static_assert(sizeof(IFuncCallQuery) == 0x10); + } } From eeccc110f2bbe6e96a7bc7a90cf43ab6b7fcc4a8 Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 11:00:04 -0700 Subject: [PATCH 28/39] fix: fix pragma once in handlepolicy.h --- CommonLibSF/include/RE/H/HandlePolicy.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CommonLibSF/include/RE/H/HandlePolicy.h b/CommonLibSF/include/RE/H/HandlePolicy.h index 686f99b6..0d85bf8f 100644 --- a/CommonLibSF/include/RE/H/HandlePolicy.h +++ b/CommonLibSF/include/RE/H/HandlePolicy.h @@ -1,5 +1,8 @@ +#pragma once + #include "RE/B/BSFixedString.h" #include "RE/B/BSIntrusiveRefCounted.h" +#include "RE/B/BSLock.h" #include "RE/I/IObjectHandlePolicy.h" namespace RE::GameScript From 185ce40c2813d9f6fcc8289b328672cb6869c2af Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 11:00:15 -0700 Subject: [PATCH 29/39] feat: add BSTimer --- CommonLibSF/include/RE/B/BSTimer.h | 29 +++++++++++++++++++++++++++++ CommonLibSF/include/RE/Starfield.h | 1 + 2 files changed, 30 insertions(+) create mode 100644 CommonLibSF/include/RE/B/BSTimer.h diff --git a/CommonLibSF/include/RE/B/BSTimer.h b/CommonLibSF/include/RE/B/BSTimer.h new file mode 100644 index 00000000..bac78082 --- /dev/null +++ b/CommonLibSF/include/RE/B/BSTimer.h @@ -0,0 +1,29 @@ + +#pragma once + +namespace RE +{ + class BSTimer + { + public: + // members + std::uint64_t unk00; // 00 + std::int64_t highPrecisionInitTime; // 08 + float clamp; // 10 + float clampRemainder; // 14 + float delta; // 18 + float realTimeDelta; // 1C + std::uint64_t diffLastUpdate; // 20 + std::uint64_t lastTime; // 28 + std::uint64_t lastUpdate; // 30 + std::uint64_t firstTime; // 38 + std::uint64_t disabledLastTime; // 40 + std::uint64_t disabledFirstTime; // 48 + std::uint32_t disableCounter; // 50 + float cumulutiveDelta; // 54 + bool useGlobalTimeMultiplierTarget; // 58 + std::uint8_t unk59; // 59 + std::uint8_t unk5A; // 5A + }; + static_assert(sizeof(BSTimer) == 0x60); +} diff --git a/CommonLibSF/include/RE/Starfield.h b/CommonLibSF/include/RE/Starfield.h index 9650d962..1b98092c 100644 --- a/CommonLibSF/include/RE/Starfield.h +++ b/CommonLibSF/include/RE/Starfield.h @@ -203,6 +203,7 @@ #include "RE/B/BSTTuple.h" #include "RE/B/BSTTuple3.h" #include "RE/B/BarrierProjectile.h" +#include "RE/B/BSTimer.h" #include "RE/B/BaseFormComponent.h" #include "RE/B/BeamProjectile.h" #include "RE/C/CodeTasklet.h" From 9f50a6ad630c52936a91cdbe11a5f374653cef79 Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 11:00:18 -0700 Subject: [PATCH 30/39] feat: add BSTFreeList --- CommonLibSF/include/RE/B/BSTFreeList.h | 34 ++++++++++++++++++++++++++ CommonLibSF/include/RE/Starfield.h | 1 + 2 files changed, 35 insertions(+) create mode 100644 CommonLibSF/include/RE/B/BSTFreeList.h diff --git a/CommonLibSF/include/RE/B/BSTFreeList.h b/CommonLibSF/include/RE/B/BSTFreeList.h new file mode 100644 index 00000000..dabcd7c3 --- /dev/null +++ b/CommonLibSF/include/RE/B/BSTFreeList.h @@ -0,0 +1,34 @@ +#pragma once + +namespace RE +{ + template + struct BSTFreeListElem + { + public: + // members + std::byte rawElem[sizeof(T)]; // 00 + BSTFreeListElem* next; // ?? + }; + + template + class __declspec(novtable) BSTFreeList + { + public: + virtual ~BSTFreeList(); // 00 + + // members + std::uint32_t lock; // 08 + BSTFreeListElem* free; // 10 + }; + //static_assert(sizeof(BSTFreeList) == 0x18); + + template + class __declspec(novtable) BSTStaticFreeList : + public BSTFreeList // 00 + { + public: + // members + BSTFreeListElem elems[N]; // ?? + }; +} diff --git a/CommonLibSF/include/RE/Starfield.h b/CommonLibSF/include/RE/Starfield.h index 1b98092c..01e0e8e3 100644 --- a/CommonLibSF/include/RE/Starfield.h +++ b/CommonLibSF/include/RE/Starfield.h @@ -195,6 +195,7 @@ #include "RE/B/BSSystemFile.h" #include "RE/B/BSTArray.h" #include "RE/B/BSTEvent.h" +#include "RE/B/BSTFreeList.h" #include "RE/B/BSTList.h" #include "RE/B/BSTOptional.h" #include "RE/B/BSTObjectArena.h" From 170feb55e0ac626679c2c4cfea11d019d172cb2f Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 11:00:18 -0700 Subject: [PATCH 31/39] feat: add MemoryPagePolicies --- CommonLibSF/include/RE/I/IMemoryPagePolicy.h | 38 +++++++++++++++ .../RE/S/SimpleAllocMemoryPagePolicy.h | 46 +++++++++++++++++++ CommonLibSF/include/RE/Starfield.h | 2 + 3 files changed, 86 insertions(+) create mode 100644 CommonLibSF/include/RE/I/IMemoryPagePolicy.h create mode 100644 CommonLibSF/include/RE/S/SimpleAllocMemoryPagePolicy.h diff --git a/CommonLibSF/include/RE/I/IMemoryPagePolicy.h b/CommonLibSF/include/RE/I/IMemoryPagePolicy.h new file mode 100644 index 00000000..dd0d0530 --- /dev/null +++ b/CommonLibSF/include/RE/I/IMemoryPagePolicy.h @@ -0,0 +1,38 @@ +#pragma once + +#include "RE/B/BSContainer.h" +#include "RE/B/BSFixedString.h" +#include "RE/B/BSLock.h" +#include "RE/B/BSTArray.h" +#include "RE/B/BSTEvent.h" +#include "RE/B/BSTObjectArena.h" +#include "RE/B/BSTSmartPointer.h" +#include "RE/B/BSTTuple.h" + +namespace RE +{ + namespace BSScript + { + class MemoryPage; // stub + + struct __declspec(novtable) IMemoryPagePolicy + { + public: + static constexpr auto RTTI{ RTTI::BSScript__IMemoryPagePolicy }; + static constexpr auto VTABLE{ VTABLE::BSScript__IMemoryPagePolicy }; + + enum class AllocationStatus; + enum class NewPageStrategy; + + virtual ~IMemoryPagePolicy() = default; // 00 + + // add + virtual std::uint32_t MaximumPageSize() const = 0; // 01 + virtual std::uint32_t MaximumStackDepth() const = 0; // 02 + virtual AllocationStatus AllocatePage(std::uint32_t a_sizeInBytes, NewPageStrategy a_strategy, BSTAutoPointer& a_newPage) = 0; // 03 + virtual AllocationStatus GetLargestAvailablePage(BSTAutoPointer& a_newPage) = 0; // 04 + virtual void DisposePage(BSTAutoPointer& a_oldPage) = 0; // 05 + }; + static_assert(sizeof(IMemoryPagePolicy) == 0x8); + } +} diff --git a/CommonLibSF/include/RE/S/SimpleAllocMemoryPagePolicy.h b/CommonLibSF/include/RE/S/SimpleAllocMemoryPagePolicy.h new file mode 100644 index 00000000..0dce0981 --- /dev/null +++ b/CommonLibSF/include/RE/S/SimpleAllocMemoryPagePolicy.h @@ -0,0 +1,46 @@ +#pragma once + +#include "RE/B/BSContainer.h" +#include "RE/B/BSFixedString.h" +#include "RE/B/BSLock.h" +#include "RE/B/BSTArray.h" +#include "RE/B/BSTEvent.h" +#include "RE/B/BSTHashMap.h" +#include "RE/B/BSTObjectArena.h" +#include "RE/B/BSTSmartPointer.h" +#include "RE/B/BSTTuple.h" +#include "RE/I/IMemoryPagePolicy.h" + +namespace RE +{ + namespace BSScript + { + class MemoryPage; // stub + + class SimpleAllocMemoryPagePolicy : + public IMemoryPagePolicy + { + public: + SF_RTTI_VTABLE(BSScript__SimpleAllocMemoryPagePolicy); + + // override (IMemoryPagePolicy) + std::uint32_t MaximumPageSize() const override { return maxPageSize; } // 01 + std::uint32_t MaximumStackDepth() const override { return maxStackDepth; } // 02 + AllocationStatus AllocatePage(std::uint32_t a_sizeInBytes, NewPageStrategy a_strategy, BSTAutoPointer& a_newPage) override; // 03 + AllocationStatus GetLargestAvailablePage(BSTAutoPointer& a_newPage) override; // 04 + void DisposePage(BSTAutoPointer& a_oldPage) override; // 05 + + // members + const std::uint32_t minPageSize{ 0x40 }; // 08 + const std::uint32_t maxPageSize{ 0x2000 }; // 0C + const std::uint32_t maxAllocatedMemory{ 0x100000 }; // 10 + const std::uint32_t maxStackDepth{ 500 }; // 14 + bool ignoreMemoryLimit{ false }; // 18 + bool outOfMemory{ false }; // 19 + BSSpinLock dataLock; // 1C + std::uint32_t currentMemorySize{ 0 }; // 24 + std::uint32_t maxAdditionalAllocations{ 0 }; // 28 + }; + static_assert(sizeof(SimpleAllocMemoryPagePolicy) == 0x30); + } +} diff --git a/CommonLibSF/include/RE/Starfield.h b/CommonLibSF/include/RE/Starfield.h index 01e0e8e3..22523012 100644 --- a/CommonLibSF/include/RE/Starfield.h +++ b/CommonLibSF/include/RE/Starfield.h @@ -246,6 +246,7 @@ #include "RE/I/IHandleReaderWriter.h" #include "RE/I/IKeywordFormBase.h" #include "RE/I/ILoader.h" +#include "RE/I/IMemoryPagePolicy.h" #include "RE/I/IMenu.h" #include "RE/I/IMovementInterface.h" #include "RE/I/IMovementPlayerControlsFilter.h" @@ -329,6 +330,7 @@ #include "RE/S/SettingCollectionList.h" #include "RE/S/SettingCollectionMap.h" #include "RE/S/Sexes.h" +#include "RE/S/SimpleAllocMemoryPagePolicy.h" #include "RE/S/SpellItem.h" #include "RE/S/Stack.h" #include "RE/S/StackFrame.h" From 9022aabf45ee97523cf997418aeba7c40ae4b0fd Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 11:00:40 -0700 Subject: [PATCH 32/39] feat: add Profiler, IProfilePolicy --- CommonLibSF/include/RE/I/IProfilePolicy.h | 37 ++++++++++++++++++++ CommonLibSF/include/RE/P/Profiler.h | 42 +++++++++++++++++++++++ CommonLibSF/include/RE/Starfield.h | 2 ++ 3 files changed, 81 insertions(+) create mode 100644 CommonLibSF/include/RE/I/IProfilePolicy.h create mode 100644 CommonLibSF/include/RE/P/Profiler.h diff --git a/CommonLibSF/include/RE/I/IProfilePolicy.h b/CommonLibSF/include/RE/I/IProfilePolicy.h new file mode 100644 index 00000000..32065119 --- /dev/null +++ b/CommonLibSF/include/RE/I/IProfilePolicy.h @@ -0,0 +1,37 @@ +#pragma once + +#include "RE/B/BSFixedString.h" +#include "RE/B/BSLock.h" +#include "RE/B/BSTSmartPointer.h" + +namespace RE +{ + namespace BSScript + { + class Variable; + + namespace Internal + { + class IFuncCallQuery; + } + + class __declspec(novtable) IProfilePolicy + { + public: + static constexpr auto RTTI{ RTTI::BSScript__IProfilePolicy }; + static constexpr auto VTABLE{ VTABLE::BSScript__IProfilePolicy }; + + virtual ~IProfilePolicy() = default; // 00 + + // add + virtual void StackFramePushQueued(std::uint32_t a_stackID, std::uint32_t a_frameNumber, const BSTSmartPointer& a_funcCallQuery) = 0; // 01 + virtual void StackFramePushed(std::uint32_t a_stackID, std::uint32_t a_frameNumber, const Variable& a_self, const BSFixedString& a_scriptName, const BSFixedString& a_stateName, const BSFixedString& a_functionName) = 0; // 02 + virtual void StackFramePopQueued(std::uint32_t a_stackID, std::uint32_t a_frameNumber, const Variable& a_self, const BSFixedString& a_scriptName, const BSFixedString& a_stateName, const BSFixedString& a_functionName) = 0; // 03 + virtual void StackFramePopped(std::uint32_t a_stackID, std::uint32_t a_frameNumber, const Variable& a_self, const BSFixedString& a_scriptName, const BSFixedString& a_stateName, const BSFixedString& a_functionName) = 0; // 04 + virtual void GuardPending(std::uint32_t a_stackID, std::uint32_t a_frameNumber, const BSScript::Variable& a_self, const BSFixedString& a_scriptName, const BSFixedString& a_guardName) = 0; // 05 + virtual void GuardTaken(std::uint32_t a_stackID, std::uint32_t a_frameNumber, const BSScript::Variable& a_self, const BSFixedString& a_scriptName, const BSFixedString& a_guardName) = 0; // 05 + virtual void GuardReleased(std::uint32_t a_stackID, std::uint32_t a_frameNumber, const BSScript::Variable& a_self, const BSFixedString& a_scriptName, const BSFixedString& a_guardName) = 0; // 05 + }; + static_assert(sizeof(IProfilePolicy) == 0x8); + } +} diff --git a/CommonLibSF/include/RE/P/Profiler.h b/CommonLibSF/include/RE/P/Profiler.h new file mode 100644 index 00000000..610180ef --- /dev/null +++ b/CommonLibSF/include/RE/P/Profiler.h @@ -0,0 +1,42 @@ +#pragma once + +#include "RE/B/BSTArray.h" +#include "RE/B/BSTTuple.h" +#include "RE/B/BSTimer.h" +#include "RE/I/IFuncCallQuery.h" +#include "RE/I/IProfilePolicy.h" + +namespace RE +{ + class BSLog; + + namespace GameScript + { + class __declspec(novtable) Profiler : + public BSScript::IProfilePolicy // 000 + { + public: + static constexpr auto RTTI{ RTTI::GameScript__Profiler }; + static constexpr auto VTABLE{ VTABLE::GameScript__Profiler }; + + // override (BSScript::IProfilePolicy) + void StackFramePushQueued(std::uint32_t a_stackID, std::uint32_t a_frameNumber, const BSTSmartPointer& a_funcCallQuery) override; // 01 + void StackFramePushed(std::uint32_t a_stackID, std::uint32_t a_frameNumber, const BSScript::Variable& a_self, const BSFixedString& a_scriptName, const BSFixedString& a_stateName, const BSFixedString& a_functionName) override; // 02 + void StackFramePopQueued(std::uint32_t a_stackID, std::uint32_t a_frameNumber, const BSScript::Variable& a_self, const BSFixedString& a_scriptName, const BSFixedString& a_stateName, const BSFixedString& a_functionName) override; // 03 + void StackFramePopped(std::uint32_t a_stackID, std::uint32_t a_frameNumber, const BSScript::Variable& a_self, const BSFixedString& a_scriptName, const BSFixedString& a_stateName, const BSFixedString& a_functionName) override; // 04 + void GuardPending(std::uint32_t a_stackID, std::uint32_t a_frameNumber, const BSScript::Variable& a_self, const BSFixedString& a_scriptName, const BSFixedString& a_guardName) override; // 05 + void GuardTaken(std::uint32_t a_stackID, std::uint32_t a_frameNumber, const BSScript::Variable& a_self, const BSFixedString& a_scriptName, const BSFixedString& a_guardName) override; // 05 + void GuardReleased(std::uint32_t a_stackID, std::uint32_t a_frameNumber, const BSScript::Variable& a_self, const BSFixedString& a_scriptName, const BSFixedString& a_guardName) override; // 05 + + // members + BSSpinLock dataLock; // 008 + BSLog* globalProfilingLog; // 010 + /*BSTHashMap*/ std::byte watchedStacks[0x38]; // 018 + /*BSTHashMap*/ std::byte watchedScripts[0x38]; // 050 + /*BSTHashMap */ std::byte watchedObjects[0x38]; // 088 + BSTArray> watchedStackRoots; // 0C0 + BSTimer timer; // 0D0 + }; + static_assert(sizeof(Profiler) == 0x130); + } +} \ No newline at end of file diff --git a/CommonLibSF/include/RE/Starfield.h b/CommonLibSF/include/RE/Starfield.h index 22523012..89b6e1c5 100644 --- a/CommonLibSF/include/RE/Starfield.h +++ b/CommonLibSF/include/RE/Starfield.h @@ -257,6 +257,7 @@ #include "RE/I/IObjectHandlePolicy.h" #include "RE/I/IObjectProcessor.h" #include "RE/I/IPostAnimationChannelUpdateFunctor.h" +#include "RE/I/IProfilePolicy.h" #include "RE/I/IRemoteDebugger.h" #include "RE/I/ISavePatcherInterface.h" #include "RE/I/IStackCallbackSaveInterface.h" @@ -305,6 +306,7 @@ #include "RE/P/PlayerCamera.h" #include "RE/P/PlayerCharacter.h" #include "RE/P/Projectile.h" +#include "RE/P/Profiler.h" #include "RE/P/PropertyGroupInfo.h" #include "RE/P/PropertyTypeInfo.h" #include "RE/R/RawFuncCallQuery.h" From 4bf4d6ecd4fef1edf1fc75ff80f96cd30efb34e8 Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 11:00:51 -0700 Subject: [PATCH 33/39] feat: add GameVM --- CommonLibSF/include/RE/G/GameVM.h | 219 +++++++++++++++++++++++++++++ CommonLibSF/include/RE/IDs.h | 4 + CommonLibSF/include/RE/Starfield.h | 1 + 3 files changed, 224 insertions(+) create mode 100644 CommonLibSF/include/RE/G/GameVM.h diff --git a/CommonLibSF/include/RE/G/GameVM.h b/CommonLibSF/include/RE/G/GameVM.h new file mode 100644 index 00000000..b0f38d86 --- /dev/null +++ b/CommonLibSF/include/RE/G/GameVM.h @@ -0,0 +1,219 @@ +#pragma once + +#include "RE/B/BSTEvent.h" +#include "RE/B/BSTFreeList.h" +#include "RE/B/BSTSingleton.h" +#include "RE/B/BSTSmartPointer.h" +#include "RE/C/CompiledScriptLoader.h" +#include "RE/H/HandlePolicy.h" +#include "RE/I/IClientVM.h" +#include "RE/I/IStackCallbackSaveInterface.h" +#include "RE/I/IVirtualMachine.h" +#include "RE/L/Logger.h" +#include "RE/O/ObjectBindPolicy.h" +#include "RE/P/Profiler.h" +#include "RE/R/RemoteDebugger.h" +#include "RE/S/SavePatcher.h" +#include "RE/S/SimpleAllocMemoryPagePolicy.h" + +namespace RE +{ + + struct InputEnableLayerDestroyedEvent; + struct PositionPlayerEvent; + struct TESFormDeleteEvent; + struct TESFormIDRemapEvent; + struct TESInitScriptEvent; + struct TESResolveNPCTemplatesEvent; + struct TESUniqueIDChangeEvent; + namespace ModelReferenceEffectEvents + { + struct ReferenceEffectFinished; + } + namespace BSScript + { + struct StatsEvent; + class IVMSaveLoadInterface; + class IVMDebugInterface; + } + namespace GameScript + { + struct StatsEvent; + struct UserLogEvent; + + class __declspec(novtable) DelayFunctor : + public BSIntrusiveRefCounted // 08 + { + public: + static constexpr auto RTTI{ RTTI::GameScript__DelayFunctor }; + static constexpr auto VTABLE{ VTABLE::GameScript__DelayFunctor }; + + enum class FunctorType + { + kMoveTo = 0, + kMoveToOwnEditorLoc = 1, + kDamageObject = 2, + kEnable = 3, + kDisable = 4, + kDelete = 5, + kSetPosition = 6, + kSetAngle = 7, + kSetMotionType = 8, + kNonLatentDelete = 9, + kMoveToPackLoc = 10, + kSetScale = 11, + kDropObject = 12, + kAttachAshPile = 13, + kForceAddRemoveRagdoll = 15, + kApplyHavokImpulse = 16, + kReset = 17, + kSendPlayerToJail = 18, + kAddItem = 19, + kResurrect = 20, + kCast = 21, + kScrollCast = 22, + kRemoveItem = 23, + kWaitFor3D = 24, + kPlayBink = 25, + kMoveToNearestNavmeshLoc = 26, + kClearDestruction = 27, + //kWaitForResourceRecalc -- appears to have been removed + kRemoveComponent = 29, + kDropRef = 30, + kPopPlayerTo = 31, + }; + + virtual ~DelayFunctor(); // 00 + + // add + [[nodiscard]] virtual BSScript::Variable operator()() = 0; // 01 + [[nodiscard]] virtual bool IsLatent() const = 0; // 02 + [[nodiscard]] virtual bool WantsRequeue() const { return false; } // 03 + [[nodiscard]] virtual FunctorType GetType() const = 0; // 04 + virtual bool SaveImpl(BSStorage& a_storage) const = 0; // 05 + virtual bool LoadImpl(const BSStorage& a_storage, std::uint32_t a_scriptSaveVersion, bool& a_dataValid) = 0; // 06 + + SF_HEAP_REDEFINE_NEW(DelayFunctor); + + // members + std::uint32_t stackID; // 0C + }; + static_assert(sizeof(DelayFunctor) == 0x10); + } + + class GameVM : + public BSScript::IClientVM, // 0000 + public BSScript::IStackCallbackSaveInterface, // 0008 + public BSTEventSink, // 0010 + public BSTEventSink, // 0018 + public BSTEventSink, // 0020 + public BSTEventSink, // 0028 + public BSTEventSink, // 0030 + public BSTEventSink, // 0038 + public BSTEventSink, // 0040 + public BSTEventSink, // 0048 + public BSTEventSource, // 0050 + public BSTEventSource, // 0078 + public BSTEventSink, // 00A0 + public BSTSingletonSDM // 00A8 + { + public: + SF_RTTI_VTABLE(GameVM); + + ~GameVM() override; // 00 + + // override (BSScript::IClientVM) + bool IsVMFrozen() const override; // 01 + void PreSave() override; // 02 + void Unk_03() override { return; }; // 03 + + // override (BSScript::IStackCallbackSaveInterface) + bool SaveStackCallback(BSStorage& a_buffer, const BSTSmartPointer& a_callback) const override; // 01 + bool LoadStackCallback(const BSStorage& a_buffer, bool& a_arg2, BSTSmartPointer& a_callback) const override; // 02 + + // override (BSTEventSink) + BSEventNotifyControl ProcessEvent(const BSScript::StatsEvent& a_event, BSTEventSource* a_dispatcher) override; // 01 + + // override (BSTEventSink) + BSEventNotifyControl ProcessEvent(const InputEnableLayerDestroyedEvent& a_event, BSTEventSource* a_dispatcher) override; // 01 + + // override (BSTEventSink) + BSEventNotifyControl ProcessEvent(const PositionPlayerEvent& a_event, BSTEventSource* a_dispatcher) override; // 01 + + // override (BSTEventSink) + BSEventNotifyControl ProcessEvent(const TESFormDeleteEvent& a_event, BSTEventSource* a_dispatcher) override; // 01 + + // override (BSTEventSink) + BSEventNotifyControl ProcessEvent(const TESFormIDRemapEvent& a_event, BSTEventSource* a_dispatcher) override; // 01 + + // override (BSTEventSink) + BSEventNotifyControl ProcessEvent(const TESInitScriptEvent& a_event, BSTEventSource* a_dispatcher) override; // 01 + + // override (BSTEventSink) + BSEventNotifyControl ProcessEvent(const TESResolveNPCTemplatesEvent& a_event, BSTEventSource* a_dispatcher) override; // 01 + + // override (BSTEventSink) + BSEventNotifyControl ProcessEvent(const TESUniqueIDChangeEvent& a_event, BSTEventSource* a_dispatcher) override; // 01 + + // override (BSTEventSink) + BSEventNotifyControl ProcessEvent(const ModelReferenceEffectEvents::ReferenceEffectFinished& a_event, BSTEventSource* a_dispatcher) override; // 01 + + [[nodiscard]] static GameVM* GetSingleton() + { + REL::Relocation singleton{ ID::GameVM::singleton }; + return *singleton; + } + + // members + std::uint64_t unkB0; // 00B0 + std::uint64_t unkB8; // 00B8 + std::uint64_t unkC0; // 00C0 + std::uint64_t unkC8; // 00C8 + std::uint64_t unkD0; // 00D0 + BSTSmartPointer impl; // 00D8 + BSScript::IVMSaveLoadInterface* saveLoadInterface; // 00E0 + BSScript::IVMDebugInterface* debugInterface; // 00E8 + BSScript::SimpleAllocMemoryPagePolicy memoryPagePolicy; // 00F0 + BSScript::CompiledScriptLoader scriptLoader; // 0120 + GameScript::Logger logger; // 0158 + GameScript::HandlePolicy handlePolicy; // 01E0 + GameScript::ObjectBindPolicy objectBindPolicy; // 02A0 + BSTSmartPointer scriptStore; // 03A0 + /*GameScript::FragmentSystem*/ std::byte fragmentSystem[0x200]; // 03A8 + GameScript::Profiler profiler; // 05A8 + GameScript::RemoteDebugger remoteDebugger; // 06D8 + GameScript::SavePatcher savePatcher; // 07B0 + BSSpinLock freezeLock; // 07B8 + bool frozen; // 07C0 + BSSpinLock vmTimeLock; // 07C4 + std::uint32_t currentTime; // 07CC + std::uint32_t currentMenuModeTime; // 07D0 + std::uint32_t currentGameTime; // 07D4 + bool updateHasBeenRun; // 07D8 + bool saveLoad; // 07D9 + BSTStaticFreeList, 512> renderSafeFunctorPool1; // 07E0 + /*BSTCommonLLMessageQueue>*/ std::byte renderSafeFunctorQueue1[0x28]; // 27F8 + BSTStaticFreeList, 512> renderSafeFunctorPool2; // 2820 + /*BSTCommonLLMessageQueue>*/ std::byte renderSafeFunctorQueue2[0x28]; // 4838 + BSTStaticFreeList, 512> postRenderFunctorPool1; // 4860 + /*BSTCommonLLMessageQueue>*/ std::byte postRenderFunctorQueue1[0x28]; // 6878 + BSTStaticFreeList, 512> postRenderFunctorPool2; // 68A0 + /*BSTCommonLLMessageQueue>*/ std::byte postRenderFunctorQueue2[0x28]; // 88B8 + BSSpinLock renderSafeQueueLock; // 88E0 + /*BSTCommonLLMessageQueue>* */ void* renderSafeQueueToReadFrom; // 88E8 + /*BSTCommonLLMessageQueue>* */ void* renderSafeQueueToWriteTo; // 88F0 + BSSpinLock postRenderQueueLock; // 88F8 + /*BSTCommonLLMessageQueue>* */ void* postRenderQueueToReadFrom; // 8900 + /*BSTCommonLLMessageQueue>* */ void* postRenderQueueToWriteTo; // 8908 + BSSpinLock userLogLock; // 8910 + /*BSTHashMap*/ std::byte userLogs[0x38]; // 8918 + BSSpinLock statsWarningLock; // 8950 + std::uint32_t initialSuspendOverageTime; // 8958 + std::uint32_t initialRunningOverageTime; // 895C + std::uint32_t initialStackMemoryOverageTime; // 8960 + std::uint32_t lastWarningTime; // 8964 + std::uint32_t overflowFlags; // 8968 + }; + static_assert(sizeof(GameVM) == 0x8970); + +} diff --git a/CommonLibSF/include/RE/IDs.h b/CommonLibSF/include/RE/IDs.h index ebd8c14e..da35dad8 100644 --- a/CommonLibSF/include/RE/IDs.h +++ b/CommonLibSF/include/RE/IDs.h @@ -202,6 +202,10 @@ namespace RE::ID inline constexpr REL::ID HandleStepRequest{ 167587 }; } } + namespace GameVM + { + inline constexpr REL::ID singleton{ 878371 }; + } namespace idLogging { diff --git a/CommonLibSF/include/RE/Starfield.h b/CommonLibSF/include/RE/Starfield.h index 89b6e1c5..231c0a02 100644 --- a/CommonLibSF/include/RE/Starfield.h +++ b/CommonLibSF/include/RE/Starfield.h @@ -232,6 +232,7 @@ #include "RE/F/FormTypes.h" #include "RE/G/GameMenuBase.h" #include "RE/G/GrenadeProjectile.h" +#include "RE/G/GameVM.h" #include "RE/H/HandlePolicy.h" #include "RE/H/Hazard.h" #include "RE/I/IAddressControllerStore.h" From 9b2bc010d9cf1212edac19a83efd04d46574deb3 Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 11:00:54 -0700 Subject: [PATCH 34/39] feat: fix Logger members --- CommonLibSF/include/RE/L/Logger.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CommonLibSF/include/RE/L/Logger.h b/CommonLibSF/include/RE/L/Logger.h index c8f4e0a1..1e284f5d 100644 --- a/CommonLibSF/include/RE/L/Logger.h +++ b/CommonLibSF/include/RE/L/Logger.h @@ -1,6 +1,7 @@ #pragma once #include "RE/E/ErrorLogger.h" +#include "RE/I/IRemoteDebugger.h" namespace RE::GameScript { @@ -16,9 +17,9 @@ namespace RE::GameScript void PostErrorImpl(const BSScript::ICachedErrorMessage* a_errMsg, Severity a_severity) override; // 01 // members - BSFixedString logFolder; // 70 - BSLog* log; // 78 - std::uint64_t unk80; // 80 + BSFixedString logFolder; // 70 + BSLog* log; // 78 + BSScript::IRemoteDebugger* remoteDebugger; // 80 }; static_assert(sizeof(Logger) == 0x88); } From 813d5a0e08c3890fa1321ce1ba7d86d528745058 Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 11:00:54 -0700 Subject: [PATCH 35/39] fix: change TESFormDeleteEvent to struct --- CommonLibSF/include/RE/P/PlayerCharacter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CommonLibSF/include/RE/P/PlayerCharacter.h b/CommonLibSF/include/RE/P/PlayerCharacter.h index 70653c60..f619ebe0 100644 --- a/CommonLibSF/include/RE/P/PlayerCharacter.h +++ b/CommonLibSF/include/RE/P/PlayerCharacter.h @@ -8,7 +8,7 @@ namespace RE class MenuModeChangeEvent; class MenuOpenCloseEvent; class OtherEventEnabledEvent; - class TESFormDeleteEvent; + struct TESFormDeleteEvent; class TESHitEvent; class UserEventEnabledEvent; From 638c4b2f29ff84221034e554f2d6f8e3bfcf0d4c Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 11:00:54 -0700 Subject: [PATCH 36/39] fix: fix missing includes in IVirtualMachine --- CommonLibSF/include/RE/I/IVirtualMachine.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CommonLibSF/include/RE/I/IVirtualMachine.h b/CommonLibSF/include/RE/I/IVirtualMachine.h index 5b2c0065..9f7ec6af 100644 --- a/CommonLibSF/include/RE/I/IVirtualMachine.h +++ b/CommonLibSF/include/RE/I/IVirtualMachine.h @@ -1,7 +1,10 @@ #pragma once +#include "RE/B/BSFixedString.h" #include "RE/B/BSIntrusiveRefCounted.h" +#include "RE/B/BSLock.h" #include "RE/B/BSTSmartPointer.h" +#include "RE/T/TypeInfo.h" namespace RE { From 2726c3827333f5d5ca04bd1b5848180d9b787282 Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 11:00:54 -0700 Subject: [PATCH 37/39] feat: Implement VirtualMachine::GetSingleton() --- CommonLibSF/src/RE/V/VirtualMachine.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 CommonLibSF/src/RE/V/VirtualMachine.cpp diff --git a/CommonLibSF/src/RE/V/VirtualMachine.cpp b/CommonLibSF/src/RE/V/VirtualMachine.cpp new file mode 100644 index 00000000..ee0706c9 --- /dev/null +++ b/CommonLibSF/src/RE/V/VirtualMachine.cpp @@ -0,0 +1,11 @@ +#include "RE/V/VirtualMachine.h" +#include "RE/G/GameVM.h" + +namespace RE::BSScript::Internal +{ + VirtualMachine* VirtualMachine::GetSingleton() + { + auto vm = GameVM::GetSingleton(); + return vm ? static_cast(vm->impl.get()) : nullptr; + } +} \ No newline at end of file From 3d1f4c3b848213f38bf00882cf45376af867e97d Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 11:00:54 -0700 Subject: [PATCH 38/39] fix: fix access in RemoteDebugger --- CommonLibSF/include/RE/I/IRemoteDebugger.h | 1 + 1 file changed, 1 insertion(+) diff --git a/CommonLibSF/include/RE/I/IRemoteDebugger.h b/CommonLibSF/include/RE/I/IRemoteDebugger.h index c2ba33c4..f2c749b8 100644 --- a/CommonLibSF/include/RE/I/IRemoteDebugger.h +++ b/CommonLibSF/include/RE/I/IRemoteDebugger.h @@ -7,6 +7,7 @@ namespace RE::BSScript class StackFrame; class __declspec(novtable) IRemoteDebugger { + public: ~IRemoteDebugger() = delete; virtual void SetVMRemoteDebuggerInterface(IVMRemoteDebuggerInterface* a_interface) = 0; // 00 From 356ba9cc41ff162a5e9a9036f5cc0046226f668f Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Tue, 9 Apr 2024 11:00:54 -0700 Subject: [PATCH 39/39] fix: add boost-stl-interfaces for BSTObjectArena --- CommonLibSF/vcpkg.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CommonLibSF/vcpkg.json b/CommonLibSF/vcpkg.json index 73e4df00..b08f7acb 100644 --- a/CommonLibSF/vcpkg.json +++ b/CommonLibSF/vcpkg.json @@ -17,6 +17,7 @@ "host": true }, "spdlog", - "xbyak" + "xbyak", + "boost-stl-interfaces" ] } \ No newline at end of file