@@ -44,25 +44,150 @@ namespace RE::BSScript
4444 [[nodiscard]] constexpr bool IsInitialized () const noexcept { return static_cast <bool >(initialized); }
4545 [[nodiscard]] constexpr bool IsValid () const noexcept { return static_cast <bool >(valid); }
4646
47- [[nodiscard]] std::uint32_t DecRef () const
47+ [[nodiscard]] std::uint32_t DecRef ()
4848 {
49- using func_t = decltype (&Object::DecRef);
50- static REL ::Relocation<func_t > func{ ID ::BSScript::Object::DecRef };
51- return func (this );
49+ std::int32_t iVar1;
50+ std::uint32_t uVar2;
51+ bool bVar3;
52+
53+ uVar2 = 0 ;
54+ do
55+ {
56+ while (true )
57+ {
58+ while (iVar1 = this ->refCountAndHandleLock , iVar1 < 0 )
59+ {
60+ if (uVar2 == 0 )
61+ {
62+ _mm_pause ();
63+ uVar2 = 1 ;
64+ }
65+ else
66+ {
67+ bVar3 = 9999 < uVar2;
68+ if (!bVar3)
69+ {
70+ uVar2 = uVar2 + 1 ;
71+ }
72+ REX::W32::Sleep (static_cast <unsigned int >(bVar3));
73+ }
74+ }
75+
76+ if (iVar1 != 2 )
77+ break ;
78+
79+ bVar3 = _InterlockedCompareExchange (reinterpret_cast <volatile long *>(&(this ->refCountAndHandleLock )),
80+ -0x7ffffffe , 2 ) == 2 ;
81+ if (bVar3)
82+ {
83+ _mm_mfence ();
84+ this ->handlePolicy ->ReleaseHandle (this ->handle );
85+ _mm_mfence ();
86+ this ->refCountAndHandleLock = 1 ;
87+ return 1 ;
88+ }
89+ }
90+ bVar3 = _InterlockedCompareExchange (reinterpret_cast <volatile long *>(&(this ->refCountAndHandleLock )),
91+ iVar1 - 1 , iVar1) == iVar1;
92+
93+ } while (!bVar3);
94+ return iVar1 - 1 ;
5295 }
5396
54- [[nodiscard]] std::size_t GetHandle () const
97+ [[nodiscard]] std::size_t GetHandle ()
5598 {
56- using func_t = decltype (&Object::GetHandle);
57- static REL ::Relocation<func_t > func{ ID ::BSScript::Object::GetHandle };
58- return func (this );
99+ std::uint32_t uVar1;
100+ std::uint32_t uVar2;
101+ bool bVar3;
102+ // The hexadecimal numbers next to the member functions in
103+ // IObjectHandlePolicy are vtable indices, NOT byte offsets
104+ this ->handlePolicy ->EmptyHandle ();
105+ uVar2 = 0 ;
106+ do {
107+ while (uVar1 = this ->refCountAndHandleLock , (int ) uVar1 < 0 ) {
108+ if (uVar2 == 0 )
109+ {
110+ _mm_pause ();
111+ uVar2 = 1 ;
112+ }
113+ else
114+ {
115+ bVar3 = 9999 < uVar2;
116+ if (!bVar3) {
117+ uVar2 = uVar2 + 1 ;
118+ }
119+ REX::W32::Sleep (static_cast <std::uint32_t >(bVar3));
120+ }
121+ }
122+
123+ bVar3 = _InterlockedCompareExchange (reinterpret_cast <volatile long *>(&(this ->refCountAndHandleLock )),
124+ uVar1 | 0x80000000 , uVar1) == uVar1;
125+
126+ } while (!bVar3);
127+ _mm_mfence ();
128+ this ->refCountAndHandleLock = uVar1;
129+ _mm_mfence ();
130+ return this ->handle ;
59131 }
60132
61- void IncRef () const
133+ void IncRef ()
62134 {
63- using func_t = decltype (&Object::IncRef);
64- static REL ::Relocation<func_t > func{ ID ::BSScript::Object::IncRef };
65- return func (this );
135+ std::uint32_t uVar1;
136+ std::uint32_t uVar2;
137+ std::uint64_t uVar3;
138+ std::uint32_t uVar4;
139+ bool bVar5;
140+
141+ uVar4 = 0 ;
142+ do
143+ {
144+ while (true )
145+ {
146+ _mm_mfence ();
147+ while (uVar2 = this ->refCountAndHandleLock , (int )uVar2 < 0 )
148+ {
149+ if (uVar4 == 0 )
150+ {
151+ _mm_pause ();
152+ uVar4 = 1 ;
153+ }
154+ else
155+ {
156+ bVar5 = 9999 < uVar4;
157+ if (!bVar5)
158+ {
159+ uVar4 = uVar4 + 1 ;
160+ }
161+ REX::W32::Sleep (static_cast <std::uint32_t >(bVar5));
162+ }
163+ }
164+ if (uVar2 != 1 )
165+ break ;
166+
167+ bVar5 = _InterlockedCompareExchange (reinterpret_cast <volatile long *>(&(this ->refCountAndHandleLock )),
168+ -0x7fffffff , 1 ) == 1 ;
169+ if (bVar5)
170+ {
171+ _mm_mfence ();
172+ this ->handlePolicy ->PersistHandle (this ->handle );
173+ _mm_mfence ();
174+ this ->refCountAndHandleLock = 2 ;
175+ return ;
176+ }
177+ }
178+
179+ bVar5 = _InterlockedCompareExchange (reinterpret_cast <volatile long *>(&(this ->refCountAndHandleLock )),
180+ uVar2 + 1 , uVar2) == uVar2;
181+ if (bVar5)
182+ {
183+ uVar1 = uVar2;
184+ return ;
185+ }
186+
187+ } while (!bVar5);
188+
189+ this ->refCountAndHandleLock = uVar1;
190+ return ;
66191 }
67192
68193 SF_HEAP_REDEFINE_NEW ();
@@ -84,7 +209,7 @@ namespace RE::BSScript
84209 void * lockStructure; // 30
85210 IObjectHandlePolicy* handlePolicy; // 38
86211 std::size_t handle; // 40
87- std::uint32_t refCountAndHandleLock; // 48
212+ volatile std::uint32_t refCountAndHandleLock; // 48
88213 };
89214 static_assert (sizeof (Object) == 0x50 );
90215}
0 commit comments