Skip to content

Commit 0305c5b

Browse files
authored
feat: merge pull request #10 from RunnerScrab/RunnerScrab_FixBSScriptObject
Fix BSScript::Object in v1.15.222 by reimplementing previously inlined member functions
2 parents c0bad6a + 9f2e6d1 commit 0305c5b

File tree

3 files changed

+148
-33
lines changed

3 files changed

+148
-33
lines changed

include/RE/IDs.h

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ namespace RE::ID
44
{
55
namespace Activation::Event
66
{
7-
inline constexpr REL::ID GetEventSource{ 0 }; // 106834
7+
inline constexpr REL::ID GetEventSource{ 63133 }; // 106834
88
}
99

1010
namespace ActivityEvents::ActivityCompletedEvent
1111
{
12-
inline constexpr REL::ID GetEventSource{ 0 }; // 86737
12+
inline constexpr REL::ID GetEventSource{ 47920 }; // 86737
1313
}
1414

1515
namespace Actor
@@ -64,37 +64,37 @@ namespace RE::ID
6464

6565
namespace BarterMenu_BuyItem
6666
{
67-
inline constexpr REL::ID GetEventSource{ 0 }; // 138993
67+
inline constexpr REL::ID GetEventSource{ 91373 }; // 138993
6868
}
6969

7070
namespace BarterMenu_CloseMenu
7171
{
72-
inline constexpr REL::ID GetEventSource{ 0 }; // 138994
72+
inline constexpr REL::ID GetEventSource{ 91378 }; // 138994
7373
}
7474

7575
namespace BarterMenu_HideModel
7676
{
77-
inline constexpr REL::ID GetEventSource{ 0 }; // 138995
77+
inline constexpr REL::ID GetEventSource{ 91376 }; // 138995
7878
}
7979

8080
namespace BarterMenu_LoadModel
8181
{
82-
inline constexpr REL::ID GetEventSource{ 0 }; // 138996
82+
inline constexpr REL::ID GetEventSource{ 91377 }; // 138996
8383
}
8484

8585
namespace BarterMenu_SellItem
8686
{
87-
inline constexpr REL::ID GetEventSource{ 0 }; // 138997
87+
inline constexpr REL::ID GetEventSource{ 91372 }; // 138997
8888
}
8989

9090
namespace BarterMenu_SetMouseOverModel
9191
{
92-
inline constexpr REL::ID GetEventSource{ 0 }; // 138998
92+
inline constexpr REL::ID GetEventSource{ 91371 }; // 138998
9393
}
9494

9595
namespace BarterMenu_ViewedItem
9696
{
97-
inline constexpr REL::ID GetEventSource{ 0 }; // 139000
97+
inline constexpr REL::ID GetEventSource{ 91374 }; // 139000
9898
}
9999

100100
namespace BaseExtraList
@@ -274,9 +274,9 @@ namespace RE::ID
274274

275275
namespace Object
276276
{
277-
inline constexpr REL::ID ctor{ 0 }; // 196025
278-
inline constexpr REL::ID dtor{ 0 }; // 196032
279-
inline constexpr REL::ID GetHandle{ 0 }; // 196069
277+
inline constexpr REL::ID ctor{ 137778 }; // 196025
278+
inline constexpr REL::ID dtor{ 0 }; // 196032 - inlined
279+
inline constexpr REL::ID GetHandle{ 0 }; // 196069 - inlined
280280
inline constexpr REL::ID SetHandle{ 0 }; // 196079
281281
inline constexpr REL::ID IncRef{ 0 }; // 37879
282282
inline constexpr REL::ID DecRef{ 0 }; // 196057

include/RE/O/Object.h

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ namespace RE::BSScript
2323

2424
~Object()
2525
{
26+
// TODO: The destructor was inlined in version Starfield 1.15 and still needs to be
27+
// pieced together or reimplemented
2628
dtor();
2729
}
2830

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

47-
[[nodiscard]] std::uint32_t DecRef() const
48-
{
49-
using func_t = decltype(&Object::DecRef);
50-
static REL::Relocation<func_t> func{ ID::BSScript::Object::DecRef };
51-
return func(this);
52-
}
53-
54-
[[nodiscard]] std::size_t GetHandle() const
55-
{
56-
using func_t = decltype(&Object::GetHandle);
57-
static REL::Relocation<func_t> func{ ID::BSScript::Object::GetHandle };
58-
return func(this);
59-
}
60-
61-
void IncRef() const
62-
{
63-
using func_t = decltype(&Object::IncRef);
64-
static REL::Relocation<func_t> func{ ID::BSScript::Object::IncRef };
65-
return func(this);
66-
}
49+
[[nodiscard]] std::uint32_t DecRef();
50+
[[nodiscard]] std::size_t GetHandle();
51+
void IncRef();
6752

6853
SF_HEAP_REDEFINE_NEW();
6954

@@ -84,7 +69,7 @@ namespace RE::BSScript
8469
void* lockStructure; // 30
8570
IObjectHandlePolicy* handlePolicy; // 38
8671
std::size_t handle; // 40
87-
std::uint32_t refCountAndHandleLock; // 48
72+
volatile std::uint32_t refCountAndHandleLock; // 48
8873
};
8974
static_assert(sizeof(Object) == 0x50);
9075
}

src/RE/O/Object.cpp

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
#include "RE/O/Object.h"
2+
3+
namespace RE::BSScript
4+
{
5+
[[nodiscard]] std::uint32_t Object::DecRef()
6+
{
7+
std::int32_t iVar1;
8+
std::uint32_t uVar2;
9+
bool bVar3;
10+
11+
uVar2 = 0;
12+
do {
13+
while (true) {
14+
while (iVar1 = this->refCountAndHandleLock, iVar1 < 0) {
15+
if (uVar2 == 0) {
16+
_mm_pause();
17+
uVar2 = 1;
18+
} else {
19+
bVar3 = 9999 < uVar2;
20+
if (!bVar3) {
21+
uVar2 = uVar2 + 1;
22+
}
23+
REX::W32::Sleep(static_cast<unsigned int>(bVar3));
24+
}
25+
}
26+
27+
if (iVar1 != 2)
28+
break;
29+
30+
bVar3 = _InterlockedCompareExchange(reinterpret_cast<volatile long*>(&(this->refCountAndHandleLock)),
31+
-0x7ffffffe, 2) == 2;
32+
if (bVar3) {
33+
_mm_mfence();
34+
this->handlePolicy->ReleaseHandle(this->handle);
35+
_mm_mfence();
36+
this->refCountAndHandleLock = 1;
37+
return 1;
38+
}
39+
}
40+
bVar3 = _InterlockedCompareExchange(reinterpret_cast<volatile long*>(&(this->refCountAndHandleLock)),
41+
iVar1 - 1, iVar1) == iVar1;
42+
43+
} while (!bVar3);
44+
return iVar1 - 1;
45+
}
46+
47+
[[nodiscard]] std::size_t Object::GetHandle()
48+
{
49+
std::uint32_t uVar1;
50+
std::uint32_t uVar2;
51+
bool bVar3;
52+
//The hexadecimal numbers next to the member functions in
53+
// IObjectHandlePolicy are vtable indices, NOT byte offsets
54+
this->handlePolicy->EmptyHandle();
55+
uVar2 = 0;
56+
do {
57+
while (uVar1 = this->refCountAndHandleLock, (int)uVar1 < 0) {
58+
if (uVar2 == 0) {
59+
_mm_pause();
60+
uVar2 = 1;
61+
} else {
62+
bVar3 = 9999 < uVar2;
63+
if (!bVar3) {
64+
uVar2 = uVar2 + 1;
65+
}
66+
REX::W32::Sleep(static_cast<std::uint32_t>(bVar3));
67+
}
68+
}
69+
70+
bVar3 = _InterlockedCompareExchange(reinterpret_cast<volatile long*>(&(this->refCountAndHandleLock)),
71+
uVar1 | 0x80000000, uVar1) == uVar1;
72+
73+
} while (!bVar3);
74+
_mm_mfence();
75+
this->refCountAndHandleLock = uVar1;
76+
_mm_mfence();
77+
return this->handle;
78+
}
79+
80+
void Object::IncRef()
81+
{
82+
std::uint32_t uVar1;
83+
std::uint32_t uVar2;
84+
std::uint64_t uVar3;
85+
std::uint32_t uVar4;
86+
bool bVar5;
87+
88+
uVar4 = 0;
89+
do {
90+
while (true) {
91+
_mm_mfence();
92+
while (uVar2 = this->refCountAndHandleLock, (int)uVar2 < 0) {
93+
if (uVar4 == 0) {
94+
_mm_pause();
95+
uVar4 = 1;
96+
} else {
97+
bVar5 = 9999 < uVar4;
98+
if (!bVar5) {
99+
uVar4 = uVar4 + 1;
100+
}
101+
REX::W32::Sleep(static_cast<std::uint32_t>(bVar5));
102+
}
103+
}
104+
if (uVar2 != 1)
105+
break;
106+
107+
bVar5 = _InterlockedCompareExchange(reinterpret_cast<volatile long*>(&(this->refCountAndHandleLock)),
108+
-0x7fffffff, 1) == 1;
109+
if (bVar5) {
110+
_mm_mfence();
111+
this->handlePolicy->PersistHandle(this->handle);
112+
_mm_mfence();
113+
this->refCountAndHandleLock = 2;
114+
return;
115+
}
116+
}
117+
118+
bVar5 = _InterlockedCompareExchange(reinterpret_cast<volatile long*>(&(this->refCountAndHandleLock)),
119+
uVar2 + 1, uVar2) == uVar2;
120+
if (bVar5) {
121+
uVar1 = uVar2;
122+
return;
123+
}
124+
125+
} while (!bVar5);
126+
127+
this->refCountAndHandleLock = uVar1;
128+
return;
129+
}
130+
}

0 commit comments

Comments
 (0)