Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-Mania-Decompilation
Path: blob/master/SonicMania/Objects/Helpers/ReplayDB.c
338 views
1
// ---------------------------------------------------------------------
2
// RSDK Project: Sonic Mania
3
// Object Description: ReplayDB Object
4
// Object Author: Christian Whitehead/Simon Thomley/Hunter Bridges
5
// Decompiled by: Rubberduckycooly & RMGRich
6
// ---------------------------------------------------------------------
7
8
#include "Game.h"
9
10
#if MANIA_USE_PLUS
11
ObjectReplayDB *ReplayDB;
12
13
void ReplayDB_Update(void) {}
14
15
void ReplayDB_LateUpdate(void) {}
16
17
void ReplayDB_StaticUpdate(void) {}
18
19
void ReplayDB_Draw(void) {}
20
21
void ReplayDB_Create(void *data) {}
22
23
void ReplayDB_StageLoad(void) {}
24
25
void ReplayDB_CreateDB(void)
26
{
27
globals->replayTableID = API.InitUserDB("ReplayDB.bin", DBVAR_UINT32, "score", DBVAR_UINT8, "zoneID", DBVAR_UINT8, "act", DBVAR_UINT8,
28
"characterID", DBVAR_UINT8, "encore", DBVAR_UINT32, "zoneSortVal", NULL);
29
30
if (globals->replayTableID == -1)
31
globals->replayTableLoaded = STATUS_ERROR;
32
else
33
globals->replayTableLoaded = STATUS_OK;
34
}
35
36
void ReplayDB_LoadDB(void (*callback)(bool32 success))
37
{
38
if ((globals->replayTableID != -1 && globals->replayTableLoaded == STATUS_OK) || globals->replayTableLoaded == STATUS_CONTINUE) {
39
if (callback)
40
callback(false);
41
}
42
else {
43
LogHelpers_Print("Loading Replay DB");
44
globals->replayTableLoaded = STATUS_CONTINUE;
45
46
ReplayDB->loadEntity = SceneInfo->entity;
47
ReplayDB->loadCallback = callback;
48
globals->replayTableID = API.LoadUserDB("ReplayDB.bin", ReplayDB_LoadDBCallback);
49
50
if (globals->replayTableID == -1) {
51
LogHelpers_Print("Couldn't claim a slot for loading %s", "ReplayDB.bin");
52
globals->replayTableLoaded = STATUS_ERROR;
53
}
54
}
55
}
56
57
void ReplayDB_SaveDB(void (*callback)(bool32 success))
58
{
59
if (API_GetNoSave() || globals->replayTableID == (uint16)-1 || globals->replayTableLoaded != STATUS_OK) {
60
if (callback)
61
callback(false);
62
}
63
else {
64
LogHelpers_Print("Saving Replay DB");
65
ReplayDB->saveEntity = SceneInfo->entity;
66
ReplayDB->saveCallback = callback;
67
API.SaveUserDB(globals->replayTableID, ReplayDB_SaveDBCallback);
68
}
69
}
70
71
uint32 ReplayDB_AddReplay(uint8 zoneID, uint8 act, uint8 characterID, int32 score, uint8 encore)
72
{
73
if (globals->replayTableLoaded == STATUS_OK) {
74
uint32 rowID = API.AddUserDBRow(globals->replayTableID);
75
int32 zoneStortVal = (score & 0x3FFFFFF) | (((zoneID << 2) | (act & 1) | ((encore & 1) << 1)) << 26);
76
77
API.SetUserDBValue(globals->replayTableID, rowID, DBVAR_UINT32, "score", &score);
78
API.SetUserDBValue(globals->replayTableID, rowID, DBVAR_UINT8, "zoneID", &zoneID);
79
API.SetUserDBValue(globals->replayTableID, rowID, DBVAR_UINT8, "act", &act);
80
API.SetUserDBValue(globals->replayTableID, rowID, DBVAR_UINT8, "characterID", &characterID);
81
API.SetUserDBValue(globals->replayTableID, rowID, DBVAR_UINT8, "encore", &encore);
82
API.SetUserDBValue(globals->replayTableID, rowID, DBVAR_UINT32, "zoneSortVal", &zoneStortVal);
83
84
uint32 UUID = API.GetUserDBRowUUID(globals->replayTableID, rowID);
85
char createTime[24];
86
sprintf_s(createTime, (int32)sizeof(createTime), "");
87
API.GetUserDBRowCreationTime(globals->replayTableID, rowID, createTime, sizeof(createTime) - 1, "%Y/%m/%d %H:%M:%S");
88
89
LogHelpers_Print("Replay DB Added Entry");
90
LogHelpers_Print("Created at %s", createTime);
91
LogHelpers_Print("Row ID: %d", rowID);
92
LogHelpers_Print("UUID: %08X", UUID);
93
94
return rowID;
95
}
96
97
return -1;
98
}
99
100
void ReplayDB_DeleteReplay(int32 row, void (*callback)(bool32 success), bool32 useAltCB)
101
{
102
int32 id = API.GetUserDBRowUUID(globals->replayTableID, row);
103
int32 replayID = 0;
104
105
ReplayDB->deleteEntity = SceneInfo->entity;
106
ReplayDB->deleteCallback = callback;
107
API.RemoveDBRow(globals->replayTableID, row);
108
TimeAttackData->loaded = false;
109
110
API.SetupUserDBRowSorting(globals->taTableID);
111
API.AddRowSortFilter(globals->taTableID, DBVAR_UINT32, "replayID", &id);
112
113
int32 count = API.GetSortedUserDBRowCount(globals->taTableID);
114
for (int32 i = 0; i < count; ++i) {
115
uint32 uuid = API.GetSortedUserDBRowID(globals->taTableID, i);
116
LogHelpers_Print("Deleting Time Attack replay from row #%d", uuid);
117
API.SetUserDBValue(globals->taTableID, uuid, DBVAR_UINT32, "replayID", &replayID);
118
}
119
120
char filename[0x20];
121
sprintf_s(filename, (int32)sizeof(filename), "Replay_%08X.bin", id);
122
if (!useAltCB)
123
API.DeleteUserFile(filename, ReplayDB_DeleteReplay_CB);
124
else
125
API.DeleteUserFile(filename, ReplayDB_DeleteReplaySave2_CB);
126
}
127
128
void ReplayDB_DeleteReplay_CB(int32 status)
129
{
130
LogHelpers_Print("DeleteReplay_CB(%d)", status);
131
132
API.SaveUserDB(globals->replayTableID, ReplayDB_DeleteReplaySave_CB);
133
}
134
135
void ReplayDB_DeleteReplaySave_CB(int32 status)
136
{
137
LogHelpers_Print("DeleteReplaySave_CB(%d)", status);
138
139
API.SaveUserDB(globals->taTableID, ReplayDB_DeleteReplaySave2_CB);
140
}
141
142
void ReplayDB_DeleteReplaySave2_CB(int32 status)
143
{
144
LogHelpers_Print("DeleteReplaySave2_CB(%d)", status);
145
146
if (ReplayDB->deleteCallback) {
147
Entity *store = SceneInfo->entity;
148
if (ReplayDB->deleteEntity)
149
SceneInfo->entity = ReplayDB->deleteEntity;
150
ReplayDB->deleteCallback(status == STATUS_OK);
151
SceneInfo->entity = store;
152
153
ReplayDB->deleteCallback = NULL;
154
ReplayDB->deleteEntity = NULL;
155
}
156
}
157
158
void ReplayDB_LoadDBCallback(int32 status)
159
{
160
if (status == STATUS_OK) {
161
globals->replayTableLoaded = STATUS_OK;
162
API.SetupUserDBRowSorting(globals->replayTableID);
163
LogHelpers_Print("Load Succeeded! Replay count: %d", API.GetSortedUserDBRowCount(globals->replayTableID));
164
}
165
else {
166
LogHelpers_Print("Load Failed! Creating new Replay DB");
167
ReplayDB_CreateDB();
168
}
169
170
LogHelpers_Print("Replay DB Slot => %d, Load Status => %d", globals->replayTableID, globals->replayTableLoaded);
171
172
if (ReplayDB->loadCallback) {
173
Entity *store = SceneInfo->entity;
174
if (ReplayDB->loadEntity)
175
SceneInfo->entity = ReplayDB->loadEntity;
176
ReplayDB->loadCallback(status == STATUS_OK);
177
SceneInfo->entity = store;
178
179
ReplayDB->loadCallback = NULL;
180
ReplayDB->loadEntity = NULL;
181
}
182
}
183
184
void ReplayDB_SaveDBCallback(int32 status)
185
{
186
if (ReplayDB->saveCallback) {
187
Entity *store = SceneInfo->entity;
188
if (ReplayDB->saveEntity)
189
SceneInfo->entity = ReplayDB->saveEntity;
190
ReplayDB->saveCallback(status == STATUS_OK);
191
SceneInfo->entity = store;
192
193
ReplayDB->saveCallback = NULL;
194
ReplayDB->saveEntity = NULL;
195
}
196
}
197
198
void ReplayDB_LoadCallback(bool32 success) {}
199
200
int32 ReplayDB_Buffer_PackEntry(uint8 *compressed, void *uncompressed)
201
{
202
ReplayFrame *framePtr = (ReplayFrame *)uncompressed;
203
204
compressed[0] = framePtr->info;
205
compressed[1] = framePtr->changedValues;
206
bool32 forcePack = framePtr->info == REPLAY_INFO_STATECHANGE || framePtr->info == REPLAY_INFO_PASSEDGATE;
207
uint8 changes = framePtr->changedValues;
208
209
uint8 *compressedBuffer = &compressed[2];
210
211
// input
212
if (forcePack || (changes & REPLAY_CHANGED_INPUT)) {
213
*compressedBuffer = framePtr->inputs;
214
++compressedBuffer;
215
}
216
217
// position
218
if (forcePack || (changes & REPLAY_CHANGED_POS)) {
219
*((int32 *)compressedBuffer) = framePtr->position.x;
220
compressedBuffer += sizeof(int32);
221
222
*((int32 *)compressedBuffer) = framePtr->position.y;
223
compressedBuffer += sizeof(int32);
224
}
225
226
// velocity
227
if (forcePack || (changes & REPLAY_CHANGED_VEL)) {
228
*((int32 *)compressedBuffer) = framePtr->velocity.x;
229
compressedBuffer += sizeof(int32);
230
231
*((int32 *)compressedBuffer) = framePtr->velocity.y;
232
compressedBuffer += sizeof(int32);
233
}
234
235
// rotation
236
if (forcePack || (changes & REPLAY_CHANGED_ROT)) {
237
*compressedBuffer = framePtr->rotation >> 1;
238
compressedBuffer += sizeof(uint8);
239
}
240
241
// direction
242
if (forcePack || (changes & REPLAY_CHANGED_DIR)) {
243
*compressedBuffer = framePtr->direction;
244
++compressedBuffer;
245
}
246
247
// anim
248
if (forcePack || (changes & REPLAY_CHANGED_ANIM)) {
249
*compressedBuffer = framePtr->anim;
250
++compressedBuffer;
251
}
252
253
// frame
254
if (forcePack || (changes & REPLAY_CHANGED_FRAME)) {
255
*compressedBuffer = framePtr->frame;
256
++compressedBuffer;
257
}
258
259
return (int32)(compressedBuffer - compressed);
260
}
261
262
int32 ReplayDB_Buffer_UnpackEntry(void *uncompressed, uint8 *compressed)
263
{
264
ReplayFrame *framePtr = (ReplayFrame *)uncompressed;
265
266
// compress state
267
framePtr->info = compressed[0];
268
269
bool32 forceUnpack = *compressed == REPLAY_INFO_STATECHANGE || *compressed == REPLAY_INFO_PASSEDGATE;
270
uint8 changes = compressed[1];
271
framePtr->changedValues = changes;
272
273
uint8 *compressedBuffer = &compressed[2];
274
275
// input
276
if (forceUnpack || (changes & REPLAY_CHANGED_INPUT)) {
277
framePtr->inputs = *compressedBuffer++;
278
}
279
280
// position
281
if (forceUnpack || (changes & REPLAY_CHANGED_POS)) {
282
int32 x = *(int32 *)compressedBuffer;
283
compressedBuffer += sizeof(int32);
284
285
int32 y = *(int32 *)compressedBuffer;
286
compressedBuffer += sizeof(int32);
287
288
framePtr->position.x = x;
289
framePtr->position.y = y;
290
}
291
292
// velocity
293
if (forceUnpack || (changes & REPLAY_CHANGED_VEL)) {
294
int32 x = *(int32 *)compressedBuffer;
295
compressedBuffer += sizeof(int32);
296
297
int32 y = *(int32 *)compressedBuffer;
298
compressedBuffer += sizeof(int32);
299
300
framePtr->velocity.x = x;
301
framePtr->velocity.y = y;
302
}
303
304
// rotation
305
if (forceUnpack || (changes & REPLAY_CHANGED_ROT)) {
306
int32 rotation = *compressedBuffer++;
307
framePtr->rotation = rotation << 1;
308
}
309
310
// direction
311
if (forceUnpack || (changes & REPLAY_CHANGED_DIR)) {
312
framePtr->direction = *compressedBuffer++;
313
}
314
315
// anim
316
if (forceUnpack || (changes & REPLAY_CHANGED_ANIM)) {
317
framePtr->anim = *compressedBuffer++;
318
}
319
320
// frame
321
if (forceUnpack || (changes & REPLAY_CHANGED_FRAME)) {
322
framePtr->frame = *compressedBuffer++;
323
}
324
325
return (int32)(compressedBuffer - compressed);
326
}
327
328
#if GAME_INCLUDE_EDITOR
329
void ReplayDB_EditorDraw(void) {}
330
331
void ReplayDB_EditorLoad(void) {}
332
#endif
333
334
void ReplayDB_Serialize(void) {}
335
#endif
336
337