Skip to content

Commit 6161138

Browse files
committed
More declarations
Added declarations for locks, various NiObjects, and BSExtraData
1 parent cae9016 commit 6161138

16 files changed

+1081
-8
lines changed

sfse/CMakeLists.txt

+10
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,13 @@ source_group(
5757
GameConsole.cpp
5858
GameConsole.h
5959
GameEvents.h
60+
GameExtraData.cpp
61+
GameExtraData.h
6062
GameFormComponents.h
6163
GameForms.cpp
6264
GameForms.h
65+
GameLock.cpp
66+
GameLock.h
6367
GameMemory.cpp
6468
GameMemory.h
6569
GameMenu.h
@@ -79,6 +83,12 @@ source_group(
7983
GameTypes.h
8084
GameUI.cpp
8185
GameUI.h
86+
NiExtraData.cpp
87+
NiExtraData.h
88+
NiObject.cpp
89+
NiObject.h
90+
NiRTTI.cpp
91+
NiRTTI.h
8292
)
8393

8494
source_group(

sfse/GameData.h

+65-3
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,20 @@ class TESFile
7979
u64 unk240;
8080
u32 unk248;
8181
u32 unk24C;
82-
char* unk250;
82+
char* unk250;
8383
u32 unk258;
8484
u32 unk25C;
85+
86+
static const u8 LightIndex = 0xFE;
87+
static const u8 MediumIndex = 0xFD;
88+
89+
static bool IsActive(u8 index) { return index != 0xFF; }
90+
static bool IsLight(u8 index) { return index == LightIndex; }
91+
static bool IsMedium(u8 index) { return index == MediumIndex; }
92+
93+
bool IsActive() const { return IsActive(cCompileIndex); }
94+
bool IsLight() const { return IsLight(cCompileIndex); }
95+
bool IsMedium() const { return IsMedium(cCompileIndex); }
8596
};
8697
static_assert(sizeof(TESFile) == 0x260);
8798
static_assert(offsetof(TESFile, cCompileIndex) == 0x218);
@@ -96,7 +107,7 @@ class TESPackedFile : public TESFile
96107
};
97108
static_assert(sizeof(TESPackedFile) == 0x3C8);
98109

99-
class TESDataHandler :
110+
class TESDataHandler :
100111
public BSTEventSource<BGSHotloadCompletedEvent>
101112
{
102113
public:
@@ -108,7 +119,7 @@ class TESDataHandler :
108119
BSTArray<TESForm*> pFormsA;
109120
};
110121

111-
122+
112123

113124
void* unk28; // BSService::Detail::TService<BSService::Detail::TServiceTraits<TESDataHandler,BSService::Detail::ReferenceGetterDefaultPointer<TESDataHandler *>>>
114125
u64 unk30;
@@ -138,6 +149,57 @@ class TESDataHandler :
138149
RelocPtr<TESDataHandler*> singleton(0x0642EB08);
139150
return *singleton;
140151
}
152+
153+
uint32_t GetSubIndex(const TESFile* file) const
154+
{
155+
if (!file->IsActive())
156+
return -1;
157+
158+
if (file->IsLight())
159+
{
160+
return file->sSmallFileCompileIndex;
161+
}
162+
else if (file->IsMedium())
163+
{
164+
int32_t foundIndex = -1;
165+
for(uint32_t i = 0; i < CompiledFileCollection.MediumFileA.size(); ++i)
166+
{
167+
if (file == CompiledFileCollection.MediumFileA[i])
168+
{
169+
foundIndex = i;
170+
break;
171+
}
172+
}
173+
return foundIndex;
174+
}
175+
176+
return file->cCompileIndex;
177+
}
178+
179+
const TESFile* GetModByFormId(const uint32_t formId)
180+
{
181+
uint8_t modIndex = formId >> 24;
182+
uint16_t middleIndex = (formId >> 12) & 0xFFF;
183+
if (TESFile::IsLight(modIndex))
184+
{
185+
if (middleIndex < CompiledFileCollection.SmallFileA.size())
186+
{
187+
return CompiledFileCollection.SmallFileA[middleIndex];
188+
}
189+
}
190+
else if (TESFile::IsMedium(modIndex))
191+
{
192+
if (middleIndex < CompiledFileCollection.MediumFileA.size())
193+
{
194+
return CompiledFileCollection.MediumFileA[middleIndex];
195+
}
196+
}
197+
else if (modIndex < CompiledFileCollection.FileA.size())
198+
{
199+
return CompiledFileCollection.FileA[modIndex];
200+
}
201+
return nullptr;
202+
}
141203
};
142204
static_assert(offsetof(TESDataHandler, pFormArray) == 0x70);
143205
static_assert(offsetof(TESDataHandler, listFiles) == 0x1538);

sfse/GameExtraData.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#include "sfse/GameExtraData.h"

sfse/GameExtraData.h

+320
Large diffs are not rendered by default.

sfse/GameForms.h

+16
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ class TESFile;
99
class TESObjectREFR;
1010
class BGSMorphableObject;
1111
class TESNPC;
12+
class NiAVObject;
13+
class TESWaterForm;
1214

1315
enum class FormType : u32
1416
{
@@ -375,6 +377,20 @@ struct OBJ_REFR
375377
};
376378
static_assert(sizeof(OBJ_REFR) == 0x20);
377379

380+
struct LOADED_REF_DATA
381+
{
382+
public:
383+
// members
384+
void* handleList; // 00 - TODO
385+
NiPointer<NiAVObject> data3D; // 08
386+
TESWaterForm* currentWaterType; // 10
387+
float relevantWaterHeight; // 18
388+
float cachedRadius; // 1C
389+
u32 flags; // 20
390+
u16 underwaterCount; // 24
391+
};
392+
static_assert(sizeof(LOADED_REF_DATA) == 0x28);
393+
378394
class BGSListForm :
379395
public TESForm
380396
{

sfse/GameLock.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#include "sfse/GameLock.h"

sfse/GameLock.h

+158
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
#pragma once
2+
3+
#include "sfse_common/Types.h"
4+
#include "sfse_common/Utilities.h"
5+
6+
class BSNonReentrantSpinLock
7+
{
8+
public:
9+
DEFINE_MEMBER_FN_0(lock, void, 0x0123AA2C);
10+
DEFINE_MEMBER_FN_0(try_lock, bool, 0x01252E8C);
11+
DEFINE_MEMBER_FN_0(unlock, void, 0x0123BD64);
12+
13+
private:
14+
// members
15+
volatile u32 _lock{}; // 0
16+
};
17+
static_assert(sizeof(BSNonReentrantSpinLock) == 0x4);
18+
19+
class BSReadWriteLock
20+
{
21+
public:
22+
DEFINE_MEMBER_FN_0(lock_read, void, 0x02E1CF10);
23+
DEFINE_MEMBER_FN_0(lock_write, void, 0x0058ADE8);
24+
DEFINE_MEMBER_FN_0(unlock_read, void, 0x02E1D0D8);
25+
DEFINE_MEMBER_FN_0(unlock_write, void, 0x0059B8B4);
26+
27+
private:
28+
// members
29+
u32 _writerThread{}; // 0
30+
volatile u32 _lock{}; // 4
31+
};
32+
static_assert(sizeof(BSReadWriteLock) == 0x8);
33+
34+
class BSSpinLock
35+
{
36+
public:
37+
DEFINE_MEMBER_FN_0(lock, void, 0x02E1AD20);
38+
DEFINE_MEMBER_FN_0(try_lock, bool, 0x02E1AE30);
39+
DEFINE_MEMBER_FN_0(unlock, void, 0x02E1ADF0);
40+
41+
private:
42+
// members
43+
u32 _owningThread{}; // 0
44+
volatile u32 _lock{}; // 4
45+
};
46+
static_assert(sizeof(BSSpinLock) == 0x8);
47+
48+
template <class Mutex>
49+
struct BSAutoLockDefaultPolicy
50+
{
51+
public:
52+
static void lock(Mutex& a_mutex) { a_mutex.lock(); }
53+
static void unlock(Mutex& a_mutex) { a_mutex.unlock(); }
54+
};
55+
static_assert(std::is_empty_v<BSAutoLockDefaultPolicy<BSSpinLock>>);
56+
57+
template <class Mutex>
58+
struct BSAutoLockReadLockPolicy
59+
{
60+
public:
61+
static void lock(Mutex& a_mutex) { a_mutex.lock_read(); }
62+
static void unlock(Mutex& a_mutex) { a_mutex.unlock_read(); }
63+
};
64+
static_assert(std::is_empty_v<BSAutoLockReadLockPolicy<BSReadWriteLock>>);
65+
66+
template <class Mutex>
67+
struct BSAutoLockWriteLockPolicy
68+
{
69+
public:
70+
static void lock(Mutex& a_mutex) { a_mutex.lock_write(); }
71+
static void unlock(Mutex& a_mutex) { a_mutex.unlock_write(); }
72+
};
73+
static_assert(std::is_empty_v<BSAutoLockWriteLockPolicy<BSReadWriteLock>>);
74+
75+
template <class Mutex, template <class> class Policy = BSAutoLockDefaultPolicy>
76+
class BSAutoLock
77+
{
78+
public:
79+
using mutex_type = Mutex;
80+
using policy_type = Policy<mutex_type>;
81+
82+
explicit BSAutoLock(mutex_type& a_mutex) :
83+
_lock(std::addressof(a_mutex))
84+
{
85+
policy_type::lock(*_lock);
86+
}
87+
88+
explicit BSAutoLock(mutex_type* a_mutex) :
89+
_lock(a_mutex)
90+
{
91+
if (_lock) {
92+
policy_type::lock(*_lock);
93+
}
94+
}
95+
96+
~BSAutoLock()
97+
{
98+
if (_lock) {
99+
policy_type::unlock(*_lock);
100+
}
101+
}
102+
103+
private:
104+
// members
105+
mutex_type* _lock{}; // 00
106+
};
107+
static_assert(sizeof(BSAutoLock<void*>) == 0x8);
108+
109+
using BSAutoReadLock = BSAutoLock<BSReadWriteLock, BSAutoLockReadLockPolicy>;
110+
static_assert(sizeof(BSAutoReadLock) == 0x8);
111+
112+
using BSAutoWriteLock = BSAutoLock<BSReadWriteLock, BSAutoLockWriteLockPolicy>;
113+
static_assert(sizeof(BSAutoWriteLock) == 0x8);
114+
115+
template <class T, class Mutex>
116+
class BSGuarded
117+
{
118+
public:
119+
template <class U, template <class> class Policy = BSAutoLockDefaultPolicy>
120+
class Guard
121+
{
122+
public:
123+
explicit Guard(U& a_data, Mutex& a_mutex) :
124+
_guard(a_mutex),
125+
_data(a_data)
126+
{}
127+
128+
U& operator*() { return _data; }
129+
U& operator->() { return _data; }
130+
const U& operator*() const { return _data; }
131+
const U& operator->() const { return _data; }
132+
133+
private:
134+
// members
135+
BSAutoLock<Mutex, Policy> _guard{}; // 0 - Lock guard is first here?
136+
U& _data; // 8
137+
};
138+
139+
auto lock()
140+
{
141+
return Guard<T>(_data, _lock);
142+
}
143+
144+
auto lock_read() const
145+
{
146+
return Guard<const T, BSAutoLockReadLockPolicy>(_data, _lock);
147+
}
148+
149+
auto lock_write()
150+
{
151+
return Guard<T, BSAutoLockWriteLockPolicy>(_data, _lock);
152+
}
153+
154+
private:
155+
// members
156+
T _data{}; // ??
157+
mutable Mutex _lock{}; // ??
158+
};

sfse/GameReferences.h

+4-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22

33
#include "sfse/GameForms.h"
4+
#include "sfse/GameExtraData.h"
45
#include "sfse/NiTypes.h"
56

67
class BGSLocation;
@@ -236,12 +237,10 @@ class TESObjectREFR : public TESForm
236237

237238
// members
238239
OBJ_REFR data; // 78
239-
u64 inventoryLock; // 98
240-
void* inventoryList; // A0
240+
BSGuarded<void*, BSReadWriteLock> inventoryList; // A0
241241
TESObjectCELL* parentCell; // A8
242-
void* loadedData; // B0
243-
u64 unkF0; // B8
244-
u64 extraDataList; // C0
242+
BSGuarded<LOADED_REF_DATA*, BSReadWriteLock> loadedData; // B0
243+
BSTSmartPointer<ExtraDataList> extraDataList; // C0
245244
u16 scale; // C8
246245
u8 unkE2; // CB
247246
u8 flags; // CC

sfse/GameTypes.h

+20
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,26 @@ class BSSimpleList
2424
Node node;
2525
};
2626

27+
// Does not actually do refcounting atm, just a wrapper
28+
template<typename element_type>
29+
class BSTSmartPointer
30+
{
31+
public:
32+
constexpr element_type* get() const noexcept { return _ptr; }
33+
explicit constexpr operator bool() const noexcept { return _ptr != nullptr; }
34+
constexpr element_type& operator*() const noexcept
35+
{
36+
return *_ptr;
37+
}
38+
constexpr element_type* operator->() const noexcept
39+
{
40+
return _ptr;
41+
}
42+
43+
private:
44+
element_type* _ptr;
45+
};
46+
2747

2848
class BSTArrayBase
2949
{

sfse/NiExtraData.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#include "sfse/NiExtraData.h"

sfse/NiExtraData.h

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#pragma once
2+
3+
#include "sfse/NiObject.h"
4+
#include "sfse/GameTypes.h"
5+
6+
class NiExtraData : public NiObject
7+
{
8+
public:
9+
BSFixedString m_kName; // 10
10+
};
11+
12+
class BSTransformExtra : public NiExtraData
13+
{
14+
public:
15+
u64 unk18; // 18 - Probably just padding, doesnt get initialized
16+
NiTransform m_transform; // 20
17+
};
18+
static_assert(offsetof(BSTransformExtra, m_transform) == 0x20);
19+
static_assert(sizeof(BSTransformExtra) == 0x60);

sfse/NiObject.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#include "sfse/NiObject.h"

0 commit comments

Comments
 (0)