diff --git a/CommonLibF4/cmake/sourcelist.cmake b/CommonLibF4/cmake/sourcelist.cmake index 77c1ccfc..a8a558f9 100644 --- a/CommonLibF4/cmake/sourcelist.cmake +++ b/CommonLibF4/cmake/sourcelist.cmake @@ -216,6 +216,7 @@ set(SOURCES include/RE/Bethesda/Settings.h include/RE/Bethesda/Sky.h include/RE/Bethesda/SplineUtils.h + include/RE/Bethesda/TaskQueueInterface.h include/RE/Bethesda/TESBoundAnimObjects.h include/RE/Bethesda/TESBoundObjects.h include/RE/Bethesda/TESCamera.h @@ -230,7 +231,7 @@ set(SOURCES include/RE/Bethesda/TESRace.h include/RE/Bethesda/TESWaterForm.h include/RE/Bethesda/TESWorldSpace.h - include/RE/Bethesda/TaskQueueInterface.h + include/RE/Bethesda/TLS.h include/RE/Bethesda/UI.h include/RE/Bethesda/UIMessage.h include/RE/Bethesda/UIMessageQueue.h @@ -390,6 +391,7 @@ set(SOURCES include/REX/W32/DXGI_5.h include/REX/W32/DXGI_6.h include/REX/W32/KERNEL32.h + include/REX/W32/NT.h include/REX/W32/OLE32.h include/REX/W32/SHELL32.h include/REX/W32/USER32.h diff --git a/CommonLibF4/include/RE/Bethesda/TESCondition.h b/CommonLibF4/include/RE/Bethesda/TESCondition.h index 013ea95b..5cbe8b6a 100644 --- a/CommonLibF4/include/RE/Bethesda/TESCondition.h +++ b/CommonLibF4/include/RE/Bethesda/TESCondition.h @@ -80,11 +80,18 @@ namespace RE [[nodiscard]] bool IsTrue(TESObjectREFR* a_actionRef, TESObjectREFR* a_targetRef) { - using func_t = decltype(&TESConditionItem::IsTrue); + using func_t = bool(*)(TESConditionItem*, TESObjectREFR*, TESObjectREFR*); static REL::Relocation func{ REL::ID(2212008) }; return func(this, a_actionRef, a_targetRef); } + [[nodiscard]] bool IsTrue(ConditionCheckParams& a_params) + { + using func_t = bool(*)(TESConditionItem*, ConditionCheckParams&); + static REL::Relocation func{ REL::ID(2212009) }; + return func(this, a_params); + } + // members TESConditionItem* next; // 00 CONDITION_ITEM_DATA data; // 08 diff --git a/CommonLibF4/include/RE/Bethesda/TLS.h b/CommonLibF4/include/RE/Bethesda/TLS.h new file mode 100644 index 00000000..fc90e1ab --- /dev/null +++ b/CommonLibF4/include/RE/Bethesda/TLS.h @@ -0,0 +1,18 @@ +#pragma once + +#include "REX/W32/NT.h" + +namespace RE +{ + struct TLS + { + [[nodiscard]] static TLS* GetSingleton() + { + return *static_cast(REX::W32::NtCurrentTeb()->threadLocalStoragePointer); + } + + // members + std::byte pad000[0x830]; // 000 + bool consoleMode; // 830 + }; +} diff --git a/CommonLibF4/include/RE/Fallout.h b/CommonLibF4/include/RE/Fallout.h index 2cbac517..f156fb4a 100644 --- a/CommonLibF4/include/RE/Fallout.h +++ b/CommonLibF4/include/RE/Fallout.h @@ -211,6 +211,7 @@ #include "RE/Bethesda/Settings.h" #include "RE/Bethesda/Sky.h" #include "RE/Bethesda/SplineUtils.h" +#include "RE/Bethesda/TaskQueueInterface.h" #include "RE/Bethesda/TESBoundAnimObjects.h" #include "RE/Bethesda/TESBoundObjects.h" #include "RE/Bethesda/TESCamera.h" @@ -225,7 +226,7 @@ #include "RE/Bethesda/TESRace.h" #include "RE/Bethesda/TESWaterForm.h" #include "RE/Bethesda/TESWorldSpace.h" -#include "RE/Bethesda/TaskQueueInterface.h" +#include "RE/Bethesda/TLS.h" #include "RE/Bethesda/UI.h" #include "RE/Bethesda/UIMessage.h" #include "RE/Bethesda/UIMessageQueue.h" diff --git a/CommonLibF4/include/REL/Relocation.h b/CommonLibF4/include/REL/Relocation.h index 2a3bf789..65aa44ce 100644 --- a/CommonLibF4/include/REL/Relocation.h +++ b/CommonLibF4/include/REL/Relocation.h @@ -300,28 +300,32 @@ namespace REL safe_write(address(), a_data.data(), a_data.size_bytes()); } - template - std::uintptr_t write_branch(const std::uintptr_t a_dst) requires(std::same_as) + template + std::uintptr_t write_branch(const std::uintptr_t a_dst) + requires(std::same_as) { - return F4SE::GetTrampoline().write_branch(address(), a_dst); + return F4SE::GetTrampoline().write_branch(address() + O, a_dst); } - template - std::uintptr_t write_branch(const F a_dst) requires(std::same_as) + template + std::uintptr_t write_branch(const F a_dst) + requires(std::same_as) { - return F4SE::GetTrampoline().write_branch(address(), stl::unrestricted_cast(a_dst)); + return F4SE::GetTrampoline().write_branch(address() + O, stl::unrestricted_cast(a_dst)); } - template - std::uintptr_t write_call(const std::uintptr_t a_dst) requires(std::same_as) + template + std::uintptr_t write_call(const std::uintptr_t a_dst) + requires(std::same_as) { - return F4SE::GetTrampoline().write_call(address(), a_dst); + return F4SE::GetTrampoline().write_call(address() + O , a_dst); } - template - std::uintptr_t write_call(const F a_dst) requires(std::same_as) + template + std::uintptr_t write_call(const F a_dst) + requires(std::same_as) { - return F4SE::GetTrampoline().write_call(address(), stl::unrestricted_cast(a_dst)); + return F4SE::GetTrampoline().write_call(address() + O, stl::unrestricted_cast(a_dst)); } void write_fill(const std::uint8_t a_value, const std::size_t a_count) requires(std::same_as) diff --git a/CommonLibF4/include/REX/REX.h b/CommonLibF4/include/REX/REX.h index b7b8aa04..e16baae6 100644 --- a/CommonLibF4/include/REX/REX.h +++ b/CommonLibF4/include/REX/REX.h @@ -1,5 +1,70 @@ #pragma once +namespace REX +{ + template < + class E, + class U = std::underlying_type_t> + class Enum + { + public: + using enum_type = E; + using underlying_type = U; + + static_assert(std::is_enum_v, "Enum must be an enum"); + static_assert(std::is_integral_v, "Enum<..., U> must be an integral"); + + constexpr Enum() noexcept = default; + constexpr Enum(const Enum&) noexcept = default; + constexpr Enum(Enum&&) noexcept = default; + + template // NOLINTNEXTLINE(google-explicit-constructor) + constexpr Enum(Enum a_rhs) noexcept : + _impl(static_cast(a_rhs.get())) + {} + + constexpr Enum(E a_value) noexcept : + _impl(static_cast(a_value)) + {} + + ~Enum() noexcept = default; + + constexpr Enum& operator=(const Enum&) noexcept = default; + constexpr Enum& operator=(Enum&&) noexcept = default; + + template + constexpr Enum& operator=(Enum a_rhs) noexcept + { + _impl = static_cast(a_rhs.get()); + } + + constexpr Enum& operator=(E a_value) noexcept + { + _impl = static_cast(a_value); + return *this; + } + + public: + [[nodiscard]] explicit constexpr operator bool() const noexcept { return _impl != static_cast(0); } + [[nodiscard]] constexpr E operator*() const noexcept { return get(); } + [[nodiscard]] constexpr E get() const noexcept { return static_cast(_impl); } + [[nodiscard]] constexpr U underlying() const noexcept { return _impl; } + + public: + friend constexpr bool operator==(Enum a_lhs, Enum a_rhs) noexcept { return a_lhs.underlying() == a_rhs.underlying(); } + friend constexpr bool operator==(Enum a_lhs, E a_rhs) noexcept { return a_lhs.underlying() == static_cast(a_rhs); } + friend constexpr bool operator==(E a_lhs, Enum a_rhs) noexcept { return static_cast(a_lhs) == a_rhs.underlying(); } + + private: + U _impl{ 0 }; + }; + template + Enum(Args...) -> Enum< + std::common_type_t, + std::underlying_type_t< + std::common_type_t>>; +} + namespace REX { template < diff --git a/CommonLibF4/include/REX/W32.h b/CommonLibF4/include/REX/W32.h index 6deadaa1..b11a7f6e 100644 --- a/CommonLibF4/include/REX/W32.h +++ b/CommonLibF4/include/REX/W32.h @@ -21,6 +21,7 @@ #include "REX/W32/DXGI_5.h" #include "REX/W32/DXGI_6.h" #include "REX/W32/KERNEL32.h" +#include "REX/W32/NT.h" #include "REX/W32/OLE32.h" #include "REX/W32/USER32.h" #include "REX/W32/VERSION.h" diff --git a/CommonLibF4/include/REX/W32/BASE.h b/CommonLibF4/include/REX/W32/BASE.h index 13cce382..1196560a 100644 --- a/CommonLibF4/include/REX/W32/BASE.h +++ b/CommonLibF4/include/REX/W32/BASE.h @@ -162,6 +162,7 @@ namespace REX::W32 }; std::int64_t value; }; + static_assert(sizeof(LARGE_INTEGER) == 0x8); union ULARGE_INTEGER { @@ -172,6 +173,15 @@ namespace REX::W32 }; std::uint64_t value; }; + static_assert(sizeof(ULARGE_INTEGER) == 0x8); + + struct UNICODE_STRING + { + std::uint16_t length; + std::uint16_t maxLength; + wchar_t* buffer; + }; + static_assert(sizeof(UNICODE_STRING) == 0x10); } namespace REX::W32 diff --git a/CommonLibF4/include/REX/W32/NT.h b/CommonLibF4/include/REX/W32/NT.h new file mode 100644 index 00000000..9a410f64 --- /dev/null +++ b/CommonLibF4/include/REX/W32/NT.h @@ -0,0 +1,92 @@ +#pragma once + +#include "REX/W32/BASE.h" + +namespace REX::W32 +{ + struct EXCEPTION_REGISTRATION_RECORD; + struct PEB_LDR_DATA; + struct RTL_USER_PROCESS_PARAMETERS; + struct UNICODE_STRING; + + using PS_POST_PROCESS_INIT_ROUTINE = void (*)(); + + struct LIST_ENTRY + { + struct LIST_ENTRY* fLink; + struct LIST_ENTRY* bLink; + }; + + struct NT_TIB + { + EXCEPTION_REGISTRATION_RECORD* exceptionList; + void* stackBase; + void* stackLimit; + void* subSystemTib; + union + { + void* fiberData; + std::uint32_t version; + }; + void* arbitraryUserPointer; + struct NT_TIB* self; + }; + + struct PEB + { + std::byte reserved1[2]; + std::byte beingDebugged; + std::byte reserved2[1]; + void* reserved3[2]; + PEB_LDR_DATA* ldr; + RTL_USER_PROCESS_PARAMETERS* processParameters; + void* reserved4[3]; + void* atlThunkSListPtr; + void* reserved5; + std::uint32_t reserved6; + void* reserved7; + std::uint32_t reserved8; + std::uint32_t atlThunkSListPtr32; + void* reserved9[45]; + std::byte reserved10[96]; + PS_POST_PROCESS_INIT_ROUTINE postProcessInitRoutine; + std::byte reserved11[128]; + void* reserved12[1]; + std::uint32_t sessionID; + }; + + struct PEB_LDR_DATA + { + std::byte reserved1[8]; + void* reserved2[3]; + LIST_ENTRY inMemoryOrderModuleList; + }; + + struct RTL_USER_PROCESS_PARAMETERS + { + std::byte reserved1[16]; + void* reserved2[10]; + UNICODE_STRING imagePathName; + UNICODE_STRING commandLine; + }; + + struct TEB + { + void* reserved1[11]; + void* threadLocalStoragePointer; + PEB* processEnvironmentBlock; + void* reserved2[399]; + std::byte reserved3[1952]; + void* tlsSlots[64]; + std::byte reserved4[8]; + void* reserved5[26]; + void* reservedForOle; + void* reserved6[4]; + void* tlsExpansionSlots; + }; +} + +namespace REX::W32 +{ + TEB* NtCurrentTeb() noexcept; +} diff --git a/CommonLibF4/src/REX/W32.cpp b/CommonLibF4/src/REX/W32.cpp index 27d40a73..7249caba 100644 --- a/CommonLibF4/src/REX/W32.cpp +++ b/CommonLibF4/src/REX/W32.cpp @@ -5,6 +5,7 @@ #include "REX/W32/DBGHELP.h" #include "REX/W32/DXGI.h" #include "REX/W32/KERNEL32.h" +#include "REX/W32/NT.h" #include "REX/W32/OLE32.h" #include "REX/W32/SHELL32.h" #include "REX/W32/USER32.h" @@ -796,6 +797,16 @@ namespace REX::W32 } } +// NT + +namespace REX::W32 +{ + TEB* NtCurrentTeb() noexcept + { + return reinterpret_cast(__readgsqword(offsetof(NT_TIB, self))); + } +} + // OLE32 REX_W32_IMPORT(void, CoTaskMemFree, void*);