Skip to content

Commit 4f6bb95

Browse files
committed
feat: BGSSaveLoad
1 parent cb089ff commit 4f6bb95

File tree

4 files changed

+234
-28
lines changed

4 files changed

+234
-28
lines changed

include/RE/B/BGSSaveLoad.h

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
#pragma once
2+
3+
#include "RE/B/BSPauseRequester.h"
4+
#include "RE/B/BSFixedString.h"
5+
#include "RE/B/BSTArray.h"
6+
#include "RE/B/BSTEvent.h"
7+
#include "RE/B/BSTScatterTable.h"
8+
9+
namespace RE
10+
{
11+
namespace PlayerNameEvent
12+
{
13+
struct NameChangedEvent;
14+
}
15+
16+
class BGSSaveLoadFile
17+
{
18+
public:
19+
20+
};
21+
22+
class BGSSaveLoadFileEntry
23+
{
24+
public:
25+
[[nodiscard]] char* GetFileName() const
26+
{
27+
return fileName;
28+
}
29+
30+
[[nodiscard]] char* GetPlayerName()
31+
{
32+
if (playerName)
33+
return playerName;
34+
35+
LoadData();
36+
return playerName;
37+
}
38+
39+
[[nodiscard]] bool IsAutoSave() const
40+
{
41+
return fileName && !_strnicmp(fileName, "AutoSave", 8);
42+
}
43+
44+
[[nodiscard]] bool IsExitSave() const
45+
{
46+
return fileName && !_strnicmp(fileName, "ExitSave", 8);
47+
}
48+
49+
[[nodiscard]] bool IsGenerated() const
50+
{
51+
return fileName && !_strnicmp(fileName, "Save", 4);
52+
}
53+
54+
[[nodiscard]] bool IsQuickSave() const
55+
{
56+
return fileName && !_strnicmp(fileName, "QuickSave", 9);
57+
}
58+
59+
void LoadData()
60+
{
61+
using func_t = decltype(&BGSSaveLoadFileEntry::LoadData);
62+
static REL::Relocation<func_t> func{ ID::BGSSaveLoadFileEntry::LoadData };
63+
func(this);
64+
}
65+
66+
// members
67+
char* fileName; // 00
68+
char* playerName; // 08
69+
};
70+
71+
class BGSSaveLoadThread
72+
{
73+
public:
74+
SF_RTTI_VTABLE(BGSSaveLoadThread);
75+
76+
struct AsyncRequest
77+
{
78+
using TaskFinishedCallback_t = std::add_pointer_t<void(bool a_result)>;
79+
};
80+
};
81+
82+
class BGSSaveLoadManager :
83+
public BSTEventSink<PlayerNameEvent::NameChangedEvent>,
84+
public BSPauseRequester
85+
{
86+
public:
87+
SF_RTTI_VTABLE(BGSSaveLoadManager);
88+
89+
enum class SaveFileCategory : std::uint32_t
90+
{
91+
kUser = 0,
92+
kAuto = 1,
93+
kQuick = 2,
94+
kExit = 3
95+
};
96+
97+
enum class QueuedTask : std::uint32_t
98+
{
99+
kAutoSave = 0x1,
100+
kForceSave = 0x2,
101+
kQuickSave = 0x8,
102+
kQuickLoad = 0x10,
103+
kLoadGame = 0x40,
104+
kAutoSaveCommit = 0x200,
105+
kQuickSaveCommit = 0x400,
106+
kBuildSaveGameList = 0x1000,
107+
kSaveAndQuit = 0x4000,
108+
};
109+
110+
virtual ~BGSSaveLoadManager(); // 00
111+
112+
// override (BSTEventSink)
113+
BSEventNotifyControl ProcessEvent(const PlayerNameEvent::NameChangedEvent& a_event, BSTEventSource<PlayerNameEvent::NameChangedEvent>* a_source) override; // 01
114+
115+
[[nodiscard]] static auto GetSingleton()
116+
{
117+
static REL::Relocation<BGSSaveLoadManager**> singleton{ ID::BGSSaveLoadManager::Singleton };
118+
return *singleton;
119+
}
120+
121+
[[nodiscard]] static bool IsSaveFileNameAutoSave(const char* a_name)
122+
{
123+
return a_name && !_strnicmp(a_name, "AutoSave", 8);
124+
}
125+
126+
[[nodiscard]] static bool IsSaveFileNameExitSave(const char* a_name)
127+
{
128+
return a_name && !_strnicmp(a_name, "ExitSave", 8);
129+
}
130+
131+
[[nodiscard]] static bool IsSaveFileNameGenerated(const char* a_name)
132+
{
133+
return a_name && !_strnicmp(a_name, "Save", 4);
134+
}
135+
136+
[[nodiscard]] static bool IsSaveFileNameQuickSave(const char* a_name)
137+
{
138+
return a_name && !_strnicmp(a_name, "QuickSave", 9);
139+
}
140+
141+
bool DeleteSaveFile(const char* a_filename, void* a_unk1, bool a_skipRemainingSavesCheck)
142+
{
143+
using func_t = decltype(&BGSSaveLoadManager::DeleteSaveFile);
144+
static REL::Relocation<func_t> func{ ID::BGSSaveLoadManager::DeleteSaveFile };
145+
return func(this, a_filename, a_unk1, a_skipRemainingSavesCheck);
146+
}
147+
148+
void QueueBuildSaveGameList(BGSSaveLoadThread::AsyncRequest::TaskFinishedCallback_t a_taskFinished = nullptr)
149+
{
150+
using func_t = decltype(&BGSSaveLoadManager::QueueBuildSaveGameList);
151+
static REL::Relocation<func_t> func{ ID::BGSSaveLoadManager::QueueBuildSaveGameList };
152+
func(this, a_taskFinished);
153+
}
154+
155+
void QueueLoadGame(BGSSaveLoadFileEntry* a_entry)
156+
{
157+
queuedEntryToLoad = a_entry;
158+
queuedTasks.set(QueuedTask::kLoadGame);
159+
}
160+
161+
void QueueLoadMostRecentSaveGame()
162+
{
163+
if (!saveGameListBuilt) {
164+
return QueueBuildSaveGameList([](bool a_result) {
165+
if (a_result)
166+
GetSingleton()->QueueLoadMostRecentSaveGame();
167+
});
168+
}
169+
170+
if (saveGameCount > 0)
171+
QueueLoadGame(saveGameList.back());
172+
}
173+
174+
void QueueSaveLoadTask(QueuedTask a_task)
175+
{
176+
using func_t = decltype(&BGSSaveLoadManager::QueueSaveLoadTask);
177+
static REL::Relocation<func_t> func{ ID::BGSSaveLoadManager::QueueSaveLoadTask };
178+
func(this, a_task);
179+
}
180+
181+
[[nodiscard]] bool IsSaveGameListBuilt() const
182+
{
183+
return saveGameListBuilt;
184+
}
185+
186+
// members
187+
std::byte pad010[0x008]; // 010
188+
BSTArray<BGSSaveLoadFileEntry*> saveGameList; // 018
189+
std::byte pad028[0x008]; // 028
190+
bool saveGameListBuilt; // 030
191+
std::uint32_t saveGameCount; // 034
192+
std::uint32_t currentSaveGameNumber; // 038
193+
std::byte pad03C[0x004]; // 03C
194+
std::uint64_t saveGameListBuildID; // 040
195+
std::uint32_t currentAutoSaveNumber; // 048
196+
std::byte pad04C[0x004]; // 04C
197+
REX::EnumSet<QueuedTask> queuedTasks; // 050
198+
std::byte pad054[0x004]; // 054
199+
BGSSaveLoadFileEntry* queuedEntryToLoad; // 058
200+
std::byte pad060[0x010]; // 060
201+
char* mostRecentSaveGame; // 070
202+
std::int32_t mostRecentSaveGameDeviceID; // 078
203+
std::byte pad07C[0x08C]; // 07C
204+
std::uint64_t currentPlayerID; // 108
205+
std::uint64_t displayPlayerID; // 110
206+
BSFixedString saveFileNameToDelete; // 118
207+
BSTHashMap<std::uint32_t, BSFixedString> autoSaveFileNames; // 120
208+
BSFixedString quickSaveFileName; // 158
209+
BSFixedString exitSaveFileName; // 160
210+
std::byte pad168[0x010]; // 168
211+
BGSSaveLoadFile* saveLoadFile; // 178
212+
bool returnedFromSysUtil; // 180
213+
bool sysUtilLoadDataComplete; // 181
214+
};
215+
static_assert(offsetof(BGSSaveLoadManager, saveGameList) == 0x018);
216+
static_assert(offsetof(BGSSaveLoadManager, saveGameListBuilt) == 0x030);
217+
static_assert(offsetof(BGSSaveLoadManager, saveGameCount) == 0x034);
218+
static_assert(offsetof(BGSSaveLoadManager, saveGameListBuildID) == 0x040);
219+
static_assert(offsetof(BGSSaveLoadManager, queuedTasks) == 0x050);
220+
static_assert(offsetof(BGSSaveLoadManager, mostRecentSaveGame) == 0x070);
221+
static_assert(offsetof(BGSSaveLoadManager, currentPlayerID) == 0x108);
222+
static_assert(offsetof(BGSSaveLoadManager, quickSaveFileName) == 0x158);
223+
static_assert(offsetof(BGSSaveLoadManager, saveLoadFile) == 0x178);
224+
static_assert(offsetof(BGSSaveLoadManager, sysUtilLoadDataComplete) == 0x181);
225+
}

include/RE/B/BGSSaveLoadManager.h

Lines changed: 0 additions & 26 deletions
This file was deleted.

include/RE/IDs.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ namespace RE::ID
6565
inline constexpr REL::ID ctor{ 101725 };
6666
}
6767

68+
namespace BGSSaveLoadFileEntry
69+
{
70+
inline constexpr REL::ID LoadData{ 147331 };
71+
}
72+
6873
namespace BGSSaveLoadGame
6974
{
7075
inline constexpr REL::ID SaveGame{ 147515 };
@@ -73,8 +78,10 @@ namespace RE::ID
7378

7479
namespace BGSSaveLoadManager
7580
{
76-
inline constexpr REL::ID Singleton{ 880997 };
7781
inline constexpr REL::ID DeleteSaveFile{ 147844 };
82+
inline constexpr REL::ID QueueBuildSaveGameList{ 147900 };
83+
inline constexpr REL::ID QueueSaveLoadTask{ 1536882 };
84+
inline constexpr REL::ID Singleton{ 880997 };
7885
}
7986

8087
namespace BGSStoryTeller

include/RE/Starfield.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@
144144
#include "RE/B/BGSResourceGenerationData.h"
145145
#include "RE/B/BGSReverbParameters.h"
146146
#include "RE/B/BGSSaveLoadGame.h"
147-
#include "RE/B/BGSSaveLoadManager.h"
147+
#include "RE/B/BGSSaveLoad.h"
148148
#include "RE/B/BGSScene.h"
149149
#include "RE/B/BGSSecondaryDamageList.h"
150150
#include "RE/B/BGSShaderParticleGeometryData.h"

0 commit comments

Comments
 (0)