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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions include/RE/IDs.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ namespace RE::ID
{
namespace Activation::Event
{
inline constexpr REL::ID GetEventSource{ 0 }; // 106834
inline constexpr REL::ID GetEventSource{ 63133 }; // 106834
}

namespace ActivityEvents::ActivityCompletedEvent
{
inline constexpr REL::ID GetEventSource{ 0 }; // 86737
inline constexpr REL::ID GetEventSource{ 47920 }; // 86737
}

namespace Actor
Expand Down Expand Up @@ -64,37 +64,37 @@ namespace RE::ID

namespace BarterMenu_BuyItem
{
inline constexpr REL::ID GetEventSource{ 0 }; // 138993
inline constexpr REL::ID GetEventSource{ 91373 }; // 138993
}

namespace BarterMenu_CloseMenu
{
inline constexpr REL::ID GetEventSource{ 0 }; // 138994
inline constexpr REL::ID GetEventSource{ 91378 }; // 138994
}

namespace BarterMenu_HideModel
{
inline constexpr REL::ID GetEventSource{ 0 }; // 138995
inline constexpr REL::ID GetEventSource{ 91376 }; // 138995
}

namespace BarterMenu_LoadModel
{
inline constexpr REL::ID GetEventSource{ 0 }; // 138996
inline constexpr REL::ID GetEventSource{ 91377 }; // 138996
}

namespace BarterMenu_SellItem
{
inline constexpr REL::ID GetEventSource{ 0 }; // 138997
inline constexpr REL::ID GetEventSource{ 91372 }; // 138997
}

namespace BarterMenu_SetMouseOverModel
{
inline constexpr REL::ID GetEventSource{ 0 }; // 138998
inline constexpr REL::ID GetEventSource{ 91371 }; // 138998
}

namespace BarterMenu_ViewedItem
{
inline constexpr REL::ID GetEventSource{ 0 }; // 139000
inline constexpr REL::ID GetEventSource{ 91374 }; // 139000
}

namespace BaseExtraList
Expand Down Expand Up @@ -274,9 +274,9 @@ namespace RE::ID

namespace Object
{
inline constexpr REL::ID ctor{ 0 }; // 196025
inline constexpr REL::ID dtor{ 0 }; // 196032
inline constexpr REL::ID GetHandle{ 0 }; // 196069
inline constexpr REL::ID ctor{ 137778 }; // 196025
inline constexpr REL::ID dtor{ 0 }; // 196032 - inlined
inline constexpr REL::ID GetHandle{ 0 }; // 196069 - inlined
inline constexpr REL::ID SetHandle{ 0 }; // 196079
inline constexpr REL::ID IncRef{ 0 }; // 37879
inline constexpr REL::ID DecRef{ 0 }; // 196057
Expand Down
27 changes: 6 additions & 21 deletions include/RE/O/Object.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ namespace RE::BSScript

~Object()
{
// TODO: The destructor was inlined in version Starfield 1.15 and still needs to be
// pieced together or reimplemented
dtor();
}

Expand All @@ -44,26 +46,9 @@ namespace RE::BSScript
[[nodiscard]] constexpr bool IsInitialized() const noexcept { return static_cast<bool>(initialized); }
[[nodiscard]] constexpr bool IsValid() const noexcept { return static_cast<bool>(valid); }

[[nodiscard]] std::uint32_t DecRef() const
{
using func_t = decltype(&Object::DecRef);
static REL::Relocation<func_t> func{ ID::BSScript::Object::DecRef };
return func(this);
}

[[nodiscard]] std::size_t GetHandle() const
{
using func_t = decltype(&Object::GetHandle);
static REL::Relocation<func_t> func{ ID::BSScript::Object::GetHandle };
return func(this);
}

void IncRef() const
{
using func_t = decltype(&Object::IncRef);
static REL::Relocation<func_t> func{ ID::BSScript::Object::IncRef };
return func(this);
}
[[nodiscard]] std::uint32_t DecRef();
[[nodiscard]] std::size_t GetHandle();
void IncRef();

SF_HEAP_REDEFINE_NEW();

Expand All @@ -84,7 +69,7 @@ namespace RE::BSScript
void* lockStructure; // 30
IObjectHandlePolicy* handlePolicy; // 38
std::size_t handle; // 40
std::uint32_t refCountAndHandleLock; // 48
volatile std::uint32_t refCountAndHandleLock; // 48
};
static_assert(sizeof(Object) == 0x50);
}
130 changes: 130 additions & 0 deletions src/RE/O/Object.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
#include "RE/O/Object.h"

namespace RE::BSScript
{
[[nodiscard]] std::uint32_t Object::DecRef()
{
std::int32_t iVar1;
std::uint32_t uVar2;
bool bVar3;

uVar2 = 0;
do {
while (true) {
while (iVar1 = this->refCountAndHandleLock, iVar1 < 0) {
if (uVar2 == 0) {
_mm_pause();
uVar2 = 1;
} else {
bVar3 = 9999 < uVar2;
if (!bVar3) {
uVar2 = uVar2 + 1;
}
REX::W32::Sleep(static_cast<unsigned int>(bVar3));
}
}

if (iVar1 != 2)
break;

bVar3 = _InterlockedCompareExchange(reinterpret_cast<volatile long*>(&(this->refCountAndHandleLock)),
-0x7ffffffe, 2) == 2;
if (bVar3) {
_mm_mfence();
this->handlePolicy->ReleaseHandle(this->handle);
_mm_mfence();
this->refCountAndHandleLock = 1;
return 1;
}
}
bVar3 = _InterlockedCompareExchange(reinterpret_cast<volatile long*>(&(this->refCountAndHandleLock)),
iVar1 - 1, iVar1) == iVar1;

} while (!bVar3);
return iVar1 - 1;
}

[[nodiscard]] std::size_t Object::GetHandle()
{
std::uint32_t uVar1;
std::uint32_t uVar2;
bool bVar3;
//The hexadecimal numbers next to the member functions in
// IObjectHandlePolicy are vtable indices, NOT byte offsets
this->handlePolicy->EmptyHandle();
uVar2 = 0;
do {
while (uVar1 = this->refCountAndHandleLock, (int)uVar1 < 0) {
if (uVar2 == 0) {
_mm_pause();
uVar2 = 1;
} else {
bVar3 = 9999 < uVar2;
if (!bVar3) {
uVar2 = uVar2 + 1;
}
REX::W32::Sleep(static_cast<std::uint32_t>(bVar3));
}
}

bVar3 = _InterlockedCompareExchange(reinterpret_cast<volatile long*>(&(this->refCountAndHandleLock)),
uVar1 | 0x80000000, uVar1) == uVar1;

} while (!bVar3);
_mm_mfence();
this->refCountAndHandleLock = uVar1;
_mm_mfence();
return this->handle;
}

void Object::IncRef()
{
std::uint32_t uVar1;
std::uint32_t uVar2;
std::uint64_t uVar3;
std::uint32_t uVar4;
bool bVar5;

uVar4 = 0;
do {
while (true) {
_mm_mfence();
while (uVar2 = this->refCountAndHandleLock, (int)uVar2 < 0) {
if (uVar4 == 0) {
_mm_pause();
uVar4 = 1;
} else {
bVar5 = 9999 < uVar4;
if (!bVar5) {
uVar4 = uVar4 + 1;
}
REX::W32::Sleep(static_cast<std::uint32_t>(bVar5));
}
}
if (uVar2 != 1)
break;

bVar5 = _InterlockedCompareExchange(reinterpret_cast<volatile long*>(&(this->refCountAndHandleLock)),
-0x7fffffff, 1) == 1;
if (bVar5) {
_mm_mfence();
this->handlePolicy->PersistHandle(this->handle);
_mm_mfence();
this->refCountAndHandleLock = 2;
return;
}
}

bVar5 = _InterlockedCompareExchange(reinterpret_cast<volatile long*>(&(this->refCountAndHandleLock)),
uVar2 + 1, uVar2) == uVar2;
if (bVar5) {
uVar1 = uVar2;
return;
}

} while (!bVar5);

this->refCountAndHandleLock = uVar1;
return;
}
}