Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Rubberduckycooly
GitHub Repository: Rubberduckycooly/RSDKv5-Decompilation
Path: blob/master/RSDKv5/RSDK/User/Core/UserStorage.cpp
1162 views
1
#include "RSDK/Core/RetroEngine.hpp"
2
3
#if RETRO_REV02
4
5
// ====================
6
// API Cores
7
// ====================
8
9
namespace RSDK
10
{
11
namespace SKU
12
{
13
14
// Dummy API
15
#if RETRO_USERCORE_DUMMY
16
#include "RSDK/User/Dummy/DummyStorage.cpp"
17
#endif
18
19
// Steam API
20
#if RETRO_USERCORE_STEAM
21
#include "RSDK/User/Steam/SteamStorage.cpp"
22
#endif
23
24
// Epic Games API
25
#if RETRO_USERCORE_EOS
26
#include "RSDK/User/EOS/EOSStorage.cpp"
27
#endif
28
29
// Switch API
30
#if RETRO_USERCORE_NX
31
#include "RSDK/User/NX/NXStorage.cpp"
32
#endif
33
34
} // namespace SKU
35
} // namespace RSDK
36
37
using namespace RSDK;
38
39
RSDK::SKU::UserStorage *RSDK::SKU::userStorage = NULL;
40
RSDK::SKU::UserDBStorage *RSDK::SKU::userDBStorage = NULL;
41
42
// =======================
43
// USER DB VALUE
44
// =======================
45
bool32 RSDK::SKU::UserDBValue::CheckMatch(int32 row, int32 column)
46
{
47
UserDB *userDB = (UserDB *)parent;
48
UserDBValue *other = &userDB->rows[row].values[column];
49
50
switch (userDB->columnTypes[column]) {
51
case DBVAR_BOOL:
52
case DBVAR_UINT8:
53
case DBVAR_INT8: return memcmp(data, other->data, sizeof(int8)) == 0;
54
55
case DBVAR_UINT16:
56
case DBVAR_INT16: return memcmp(data, other->data, sizeof(int16)) == 0;
57
58
case DBVAR_UINT32:
59
case DBVAR_INT32:
60
case DBVAR_FLOAT:
61
case DBVAR_COLOR: return memcmp(data, other->data, sizeof(int32)) == 0;
62
63
case DBVAR_STRING: {
64
char *thisString = (char *)data;
65
char *otherString = (char *)other->data;
66
67
return strcmp(thisString, otherString) == 0;
68
}
69
default: break;
70
}
71
72
return false;
73
}
74
void RSDK::SKU::UserDBValue::Set(int32 type, void *data)
75
{
76
size = 0;
77
memset(this->data, 0, sizeof(this->data));
78
if (data) {
79
switch (type) {
80
case DBVAR_BOOL:
81
case DBVAR_UINT8:
82
case DBVAR_INT8:
83
size = sizeof(int8);
84
memcpy(this->data, data, sizeof(int8));
85
break;
86
87
case DBVAR_UINT16:
88
case DBVAR_INT16:
89
size = sizeof(int16);
90
memcpy(this->data, data, sizeof(int16));
91
break;
92
93
case DBVAR_UINT32:
94
case DBVAR_INT32:
95
case DBVAR_FLOAT:
96
case DBVAR_COLOR:
97
size = sizeof(int32);
98
memcpy(this->data, data, sizeof(int32));
99
break;
100
101
case DBVAR_STRING: {
102
char *string = (char *)data;
103
104
int32 len = (int32)strlen(string);
105
for (int32 c = 0; c < len && c < 15; ++c) {
106
this->data[c] = string[c];
107
}
108
break;
109
}
110
111
default: break;
112
}
113
}
114
}
115
void RSDK::SKU::UserDBValue::Get(int32 type, void *data)
116
{
117
int8 *outData = (int8 *)data;
118
switch (type) {
119
case DBVAR_BOOL:
120
case DBVAR_UINT8:
121
case DBVAR_INT8: memcpy(outData, this->data, sizeof(int8)); break;
122
123
case DBVAR_UINT16:
124
case DBVAR_INT16: memcpy(outData, this->data, sizeof(int16)); break;
125
126
case DBVAR_UINT32:
127
case DBVAR_INT32:
128
case DBVAR_FLOAT:
129
case DBVAR_COLOR: memcpy(outData, this->data, sizeof(int32)); break;
130
131
case DBVAR_STRING: {
132
memset(outData, 0, size + 1);
133
char *string = (char *)this->data;
134
for (int32 c = 0; c < size; ++c) {
135
outData[c] = string[c];
136
}
137
break;
138
}
139
140
default: break;
141
}
142
}
143
144
// =======================
145
// USER DB ROW
146
// =======================
147
bool32 RSDK::SKU::UserDBRow::AddValue(int32 type, char *name, void *value)
148
{
149
UserDB *userDB = parent;
150
uint32 uuid = 0;
151
GenerateHashCRC(&uuid, name);
152
153
for (int32 c = 0; c < userDB->columnCount; ++c) {
154
if (userDB->columnUUIDs[c] == uuid) {
155
if (c < 0 || type != userDB->columnTypes[c])
156
return false;
157
158
values[c].Set(type, value);
159
160
time_t t;
161
time(&t);
162
changeTime = *localtime(&t);
163
return true;
164
}
165
}
166
167
return false;
168
}
169
bool32 RSDK::SKU::UserDBRow::GetValue(int32 type, char *name, void *value)
170
{
171
UserDB *userDB = parent;
172
uint32 uuid = 0;
173
GenerateHashCRC(&uuid, name);
174
175
for (int32 c = 0; c < userDB->columnCount; ++c) {
176
if (userDB->columnUUIDs[c] == uuid) {
177
if (c < 0 || type != userDB->columnTypes[c])
178
return false;
179
180
values[c].Get(type, value);
181
return true;
182
}
183
}
184
185
return false;
186
}
187
188
bool32 RSDK::SKU::UserDBRow::Compare(UserDBRow *other, int32 type, char *name, bool32 sortAscending)
189
{
190
uint8 thisData[0x10];
191
uint8 otherData[0x10];
192
memset(thisData, 0, sizeof(thisData));
193
memset(otherData, 0, sizeof(otherData));
194
195
this->GetValue(type, name, thisData);
196
other->GetValue(type, name, otherData);
197
switch (type) {
198
case DBVAR_BOOL:
199
case DBVAR_UINT8: {
200
uint8 thisValue = 0, otherValue = 0;
201
memcpy(&thisValue, thisData, sizeof(uint8));
202
memcpy(&otherValue, otherData, sizeof(uint8));
203
204
if (!sortAscending)
205
return thisValue > otherValue;
206
else
207
return thisValue < otherValue;
208
break;
209
}
210
211
case DBVAR_INT8: {
212
int8 thisValue = 0, otherValue = 0;
213
memcpy(&thisValue, thisData, sizeof(int8));
214
memcpy(&otherValue, otherData, sizeof(int8));
215
216
if (!sortAscending)
217
return thisValue > otherValue;
218
else
219
return thisValue < otherValue;
220
break;
221
}
222
223
case DBVAR_UINT16: {
224
uint16 thisValue = 0, otherValue = 0;
225
memcpy(&thisValue, thisData, sizeof(uint16));
226
memcpy(&otherValue, otherData, sizeof(uint16));
227
228
if (!sortAscending)
229
return thisValue > otherValue;
230
else
231
return thisValue < otherValue;
232
break;
233
}
234
235
case DBVAR_INT16: {
236
int16 thisValue = 0, otherValue = 0;
237
memcpy(&thisValue, thisData, sizeof(int16));
238
memcpy(&otherValue, otherData, sizeof(int16));
239
240
if (!sortAscending)
241
return thisValue > otherValue;
242
else
243
return thisValue < otherValue;
244
break;
245
}
246
247
case DBVAR_UINT32:
248
case DBVAR_COLOR: {
249
uint32 thisValue = 0, otherValue = 0;
250
memcpy(&thisValue, thisData, sizeof(uint32));
251
memcpy(&otherValue, otherData, sizeof(uint32));
252
253
if (!sortAscending)
254
return thisValue > otherValue;
255
else
256
return thisValue < otherValue;
257
break;
258
}
259
260
case DBVAR_INT32: {
261
int32 thisValue = 0, otherValue = 0;
262
memcpy(&thisValue, thisData, sizeof(int32));
263
memcpy(&otherValue, otherData, sizeof(int32));
264
265
if (!sortAscending)
266
return thisValue > otherValue;
267
else
268
return thisValue < otherValue;
269
break;
270
}
271
272
case DBVAR_FLOAT: {
273
float thisValue = 0, otherValue = 0;
274
memcpy(&thisValue, thisData, sizeof(float));
275
memcpy(&otherValue, otherData, sizeof(float));
276
277
if (!sortAscending)
278
return thisValue > otherValue;
279
else
280
return thisValue < otherValue;
281
break;
282
}
283
284
case DBVAR_STRING: {
285
char *thisString = (char *)thisData;
286
char *otherString = (char *)otherData;
287
288
int32 result = strcmp(thisString, otherString);
289
if (sortAscending)
290
return result > 0 ? true : false;
291
else
292
return result < 0 ? true : false;
293
break;
294
}
295
default: break;
296
}
297
return false;
298
}
299
300
// =======================
301
// USER DB
302
// =======================
303
void RSDK::SKU::UserDB::Init(va_list list)
304
{
305
int32 cnt = 0;
306
while (true) {
307
int32 type = va_arg(list, int32);
308
if (!type)
309
break;
310
311
columnTypes[cnt] = type;
312
memset(columnNames[cnt], 0, 0x10);
313
sprintf_s(columnNames[cnt], sizeof(columnNames[cnt]), "%s", va_arg(list, const char *));
314
GenerateHashCRC(&columnUUIDs[cnt], columnNames[cnt]);
315
++cnt;
316
}
317
318
columnCount = cnt;
319
rowCount = 0;
320
memset(rows, 0, sizeof(rows));
321
Refresh();
322
active = true;
323
valid = true;
324
}
325
bool32 RSDK::SKU::UserDB::Load(uint8 *buffer)
326
{
327
uint32 signature = *(uint32 *)buffer;
328
if (signature != RETRO_USERDB_SIGNATURE)
329
return false;
330
331
buffer += sizeof(int32);
332
buffer += sizeof(int32); // used size
333
334
rowCount = *(uint16 *)buffer;
335
buffer += sizeof(uint16);
336
337
columnCount = *buffer;
338
buffer++;
339
340
for (int32 c = 0; c < columnCount; ++c) {
341
columnTypes[c] = *buffer;
342
buffer++;
343
344
sprintf_s(columnNames[c], sizeof(columnNames[c]), "%s", (char *)buffer);
345
buffer += 0x10;
346
347
GenerateHashCRC(&columnUUIDs[c], columnNames[c]);
348
}
349
350
for (int32 r = 0; r < rowCount; ++r) {
351
rows[r].uuid = *(uint32 *)buffer;
352
buffer += sizeof(uint32);
353
354
memcpy(&rows[r].createTime, buffer, sizeof(tm));
355
buffer += sizeof(tm);
356
memcpy(&rows[r].changeTime, buffer, sizeof(tm));
357
buffer += sizeof(tm);
358
359
for (int32 c = 0; c < columnCount; ++c) {
360
rows[r].values[c].size = *buffer;
361
buffer++;
362
363
memcpy(&rows[r].values[c].data, buffer, rows[r].values[c].size);
364
buffer += rows[r].values[c].size;
365
}
366
}
367
368
active = true;
369
Refresh();
370
return true;
371
}
372
void RSDK::SKU::UserDB::Save(int32 totalSize, uint8 *buffer)
373
{
374
int32 size = 0;
375
if (sizeof(uint32) < totalSize) {
376
size = sizeof(uint32);
377
*(uint32 *)buffer = RETRO_USERDB_SIGNATURE;
378
buffer += sizeof(uint32);
379
}
380
381
if (size + sizeof(uint32) < totalSize) {
382
size += sizeof(uint32);
383
*(uint32 *)buffer = (int32)GetSize(); // used size
384
buffer += sizeof(uint32);
385
}
386
387
if (size + sizeof(uint16) < totalSize) {
388
size += sizeof(uint16);
389
*(uint16 *)buffer = rowCount;
390
buffer += sizeof(uint16);
391
}
392
393
if (size + sizeof(uint8) < totalSize) {
394
++size;
395
*buffer++ = columnCount;
396
}
397
398
for (int32 c = 0; c < columnCount; ++c) {
399
if (size + sizeof(uint8) < totalSize) {
400
++size;
401
*buffer++ = (uint8)columnTypes[c];
402
}
403
if (size + 0x10 * sizeof(uint8) < totalSize) {
404
memset(buffer, 0, 0x10 * sizeof(uint8));
405
sprintf_s((char *)buffer, sizeof(columnNames[c]), "%s", columnNames[c]);
406
size += 0x10;
407
buffer += 0x10;
408
}
409
}
410
411
for (int32 r = 0; r < rowCount; ++r) {
412
if (size + sizeof(uint32) < totalSize) {
413
size += sizeof(uint32);
414
*(uint32 *)buffer = rows[r].uuid;
415
buffer += sizeof(uint32);
416
}
417
if (size + sizeof(tm) < totalSize) {
418
memcpy(buffer, &rows[r].createTime, sizeof(tm));
419
size += sizeof(tm);
420
buffer += sizeof(tm);
421
}
422
if (size + sizeof(tm) < totalSize) {
423
memcpy(buffer, &rows[r].changeTime, sizeof(tm));
424
size += sizeof(tm);
425
buffer += sizeof(tm);
426
}
427
428
for (int32 c = 0; c < columnCount; ++c) {
429
if (size + sizeof(uint8) < totalSize) {
430
++size;
431
*buffer++ = (uint8)rows[r].values[c].size;
432
}
433
if (rows[r].values[c].size + size < totalSize) {
434
memcpy(buffer, rows[r].values[c].data, rows[r].values[c].size);
435
size += rows[r].values[c].size;
436
buffer += rows[r].values[c].size;
437
}
438
}
439
}
440
441
if (size < totalSize)
442
memset(buffer, 0, totalSize - size);
443
}
444
void RSDK::SKU::UserDB::Clear()
445
{
446
sortedRowList.Clear();
447
loaded = false;
448
active = false;
449
valid = false;
450
uuid = 0;
451
rowCount = 0;
452
columnCount = 0;
453
memset(columnTypes, 0, sizeof(columnTypes));
454
memset(columnNames, 0, sizeof(columnNames));
455
memset(columnUUIDs, 0, sizeof(columnUUIDs));
456
memset(rows, 0, sizeof(rows));
457
rowsChanged = true;
458
}
459
460
int32 RSDK::SKU::UserDB::GetColumnID(const char *name)
461
{
462
uint32 uuid = 0;
463
GenerateHashCRC(&uuid, (char *)name);
464
465
int32 id = -1;
466
for (int32 i = 0; i < columnCount; ++i) {
467
if (uuid == columnUUIDs[i]) {
468
id = i;
469
break;
470
}
471
}
472
return id;
473
}
474
475
int32 RSDK::SKU::UserDB::AddRow()
476
{
477
if (rowCount >= RETRO_USERDB_ROW_MAX)
478
return -1;
479
480
UserDBRow *row = &rows[rowCount];
481
row->uuid = CreateRowUUID();
482
483
time_t timeInfo;
484
time(&timeInfo);
485
tm *tmA = localtime(&timeInfo);
486
tm *tmB = localtime(&timeInfo);
487
488
memcpy(&row->createTime, tmA, sizeof(tm));
489
memcpy(&row->changeTime, tmB, sizeof(tm));
490
491
memset(row->values, 0, sizeof(UserDBValue) * RETRO_USERDB_COL_MAX);
492
++rowCount;
493
valid = true;
494
495
Refresh();
496
rowsChanged = true;
497
return rowCount - 1;
498
}
499
bool32 RSDK::SKU::UserDB::RemoveRow(uint32 row)
500
{
501
if (row < rowCount) {
502
UserDBRow *entry = &rows[row];
503
memset(entry, 0, sizeof(UserDBRow));
504
505
int32 id = (int32)(rowCount - row - 1);
506
memcpy(entry, &entry[1], id * sizeof(UserDBRow));
507
memset(&entry[id + 1], 0, sizeof(UserDBRow));
508
509
--rowCount;
510
valid = true;
511
512
Refresh();
513
rowsChanged = true;
514
}
515
return true;
516
}
517
bool32 RSDK::SKU::UserDB::RemoveAllRows()
518
{
519
rowCount = 0;
520
memset(rows, 0, sizeof(UserDBRow) * RETRO_USERDB_ROW_MAX);
521
Refresh();
522
return true;
523
}
524
uint16 RSDK::SKU::UserDB::GetRowByID(uint32 uuid)
525
{
526
if (!rowCount)
527
return -1;
528
529
for (int32 i = 0; i < rowCount; ++i) {
530
if (uuid == rows[i].uuid) {
531
return i;
532
}
533
}
534
return -1;
535
}
536
537
void RSDK::SKU::UserDB::FilterValues(UserDBValue *value, int32 column)
538
{
539
for (int32 i = sortedRowList.Count() - 1; i >= 0; --i) {
540
if (!value->CheckMatch(sortedRowIDs[i], column)) {
541
sortedRowList.Remove(i);
542
}
543
}
544
}
545
void RSDK::SKU::UserDB::AddSortFilter(const char *name, void *value)
546
{
547
int32 id = GetColumnID(name);
548
549
if (id >= 0) {
550
if (sortedRowCount) {
551
UserDBValue dbValue;
552
// this is very hacky
553
dbValue.parent = (UserDBRow *)this;
554
dbValue.Set(columnTypes[id], value);
555
FilterValues(&dbValue, id);
556
SetupRowSortIDs();
557
}
558
}
559
}
560
561
void RSDK::SKU::UserDB::SetupRowSortIDs()
562
{
563
sortedRowCount = 0;
564
memset(sortedRowIDs, 0, sizeof(sortedRowIDs));
565
566
for (int32 i = 0; i < sortedRowList.Count(); ++i) {
567
sortedRowIDs[i] = *sortedRowList.At(i);
568
++sortedRowCount;
569
}
570
}
571
void RSDK::SKU::UserDB::RefreshSortList()
572
{
573
sortedRowList.Clear();
574
575
for (int32 i = 0; i < rowCount; ++i) {
576
int32 *row = sortedRowList.Append();
577
if (row)
578
*row = i;
579
}
580
581
rowsChanged = false;
582
583
SetupRowSortIDs();
584
}
585
void RSDK::SKU::UserDB::SortRows(int32 type, char *name, bool32 sortAscending)
586
{
587
if (!rowsChanged && sortedRowCount) {
588
if (type || name) { // sort by value
589
int32 col = GetColumnID(name);
590
if (col >= 0) {
591
for (int32 i = 0; i < sortedRowList.Count(); i++) {
592
for (int32 j = i + 1; j < sortedRowList.Count(); j++) {
593
int32 *id1 = sortedRowList.At(i);
594
int32 *id2 = sortedRowList.At(j);
595
596
if (rows[*id1].Compare(&rows[*id2], type, name, sortAscending)) {
597
int32 temp = *id1;
598
*id1 = *id2;
599
*id2 = temp;
600
}
601
}
602
}
603
604
SetupRowSortIDs();
605
}
606
}
607
else { // sort by date
608
for (int32 i = 0; i < sortedRowList.Count(); i++) {
609
for (int32 j = i + 1; j < sortedRowList.Count(); j++) {
610
int32 *id1 = sortedRowList.At(i);
611
int32 *id2 = sortedRowList.At(j);
612
613
double d = difftime(mktime(&rows[*id1].createTime), mktime(&rows[*id2].createTime));
614
615
bool32 swap = false;
616
if (sortAscending)
617
swap = (d < 0) - (d > 0);
618
else
619
swap = (d > 0) - (d < 0);
620
621
if (swap) {
622
int32 temp = *id1;
623
*id1 = *id2;
624
*id2 = temp;
625
}
626
}
627
}
628
629
SetupRowSortIDs();
630
}
631
}
632
}
633
634
uint32 RSDK::SKU::UserDB::CreateRowUUID()
635
{
636
bool32 flag = true;
637
uint32 uuid = 0;
638
639
while (flag) {
640
uint8 bytes[4];
641
bytes[0] = rand();
642
bytes[1] = rand();
643
bytes[2] = rand();
644
bytes[3] = rand();
645
uuid = (bytes[0]) | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24);
646
647
if (uuid < 0x10000000)
648
uuid |= 0x10000000;
649
650
flag = false;
651
for (int32 e = 0; e < rowCount; ++e) {
652
if (uuid == rows[e].uuid) {
653
flag = true;
654
}
655
}
656
}
657
return uuid;
658
}
659
void RSDK::SKU::UserDB::Refresh()
660
{
661
parent = this;
662
for (int32 r = 0; r < RETRO_USERDB_ROW_MAX; ++r) {
663
rows[r].parent = this;
664
for (int32 c = 0; c < columnCount; ++c) {
665
rows[r].values[c].parent = &rows[r];
666
}
667
}
668
}
669
size_t RSDK::SKU::UserDB::GetSize()
670
{
671
int32 colSize = 1;
672
if (columnCount)
673
colSize = (0x10 * columnCount) + columnCount + 1;
674
675
size_t size = colSize + 10;
676
677
for (int32 r = 0; r < RETRO_USERDB_ROW_MAX; ++r) {
678
rows[r].parent = this;
679
int32 rowSize = (sizeof(tm) * 2) + sizeof(uint32);
680
for (int32 c = 0; c < columnCount; ++c) {
681
rowSize += sizeof(uint8) + rows[r].values[c].size;
682
}
683
size += rowSize;
684
}
685
686
return size;
687
}
688
689
// =======================
690
// USER DB STORAGE
691
// =======================
692
693
RSDK::SKU::UserDBStorage::UserDBStorage()
694
{
695
unknown = 0;
696
697
this->loadCallback[0] = UserDBStorage_LoadCB1;
698
this->loadCallback[1] = UserDBStorage_LoadCB2;
699
this->loadCallback[2] = UserDBStorage_LoadCB3;
700
this->loadCallback[3] = UserDBStorage_LoadCB4;
701
this->loadCallback[4] = UserDBStorage_LoadCB5;
702
this->loadCallback[5] = UserDBStorage_LoadCB6;
703
this->loadCallback[6] = UserDBStorage_LoadCB7;
704
this->loadCallback[7] = UserDBStorage_LoadCB8;
705
706
this->saveCallback[0] = UserDBStorage_SaveCB1;
707
this->saveCallback[1] = UserDBStorage_SaveCB2;
708
this->saveCallback[2] = UserDBStorage_SaveCB3;
709
this->saveCallback[3] = UserDBStorage_SaveCB4;
710
this->saveCallback[4] = UserDBStorage_SaveCB5;
711
this->saveCallback[5] = UserDBStorage_SaveCB6;
712
this->saveCallback[6] = UserDBStorage_SaveCB7;
713
this->saveCallback[7] = UserDBStorage_SaveCB8;
714
}
715
716
// UserDB Management
717
uint16 RSDK::SKU::UserDBStorage::InitUserDB(const char *name, va_list list)
718
{
719
int32 tableID = -1;
720
uint32 uuid = 0;
721
GenerateHashCRC(&uuid, (char *)name);
722
723
for (int32 i = 0; i < RETRO_USERDB_MAX; ++i) {
724
if (!userDBStorage->userDB[i].loaded) {
725
tableID = i;
726
break;
727
}
728
}
729
730
if (tableID == -1)
731
return -1;
732
733
UserDB *userDB = &userDBStorage->userDB[tableID];
734
735
userDB->loaded = true;
736
userDB->name = name;
737
GenerateHashCRC(&userDB->uuid, (char *)name);
738
userDB->Init(list);
739
userDB->parent->RefreshSortList();
740
741
return tableID;
742
}
743
uint16 RSDK::SKU::UserDBStorage::LoadUserDB(const char *filename, void (*callback)(int32 status))
744
{
745
int32 tableID = -1;
746
uint32 uuid = 0;
747
GenerateHashCRC(&uuid, (char *)filename);
748
for (int32 i = 0; i < RETRO_USERDB_MAX; ++i) {
749
if (uuid == userDBStorage->userDB[i].uuid && userDBStorage->userDB[i].loaded)
750
return i;
751
}
752
753
for (int32 i = 0; i < RETRO_USERDB_MAX; ++i) {
754
if (!userDBStorage->userDB[i].loaded) {
755
tableID = i;
756
break;
757
}
758
}
759
760
if (tableID == -1) {
761
if (callback)
762
callback(STATUS_ERROR);
763
return -1;
764
}
765
766
AllocateStorage((void **)&userDBStorage->readBuffer[tableID], sizeof(UserDB), DATASET_TMP, true);
767
userDBStorage->dbLoadCB[tableID] = UserDBStorage::LoadCB;
768
userDBStorage->callbacks[tableID] = callback;
769
TryLoadUserFile(filename, userDBStorage->readBuffer[tableID], sizeof(UserDB), userDBStorage->loadCallback[tableID]);
770
771
UserDB *userDB = &userDBStorage->userDB[tableID];
772
userDB->loaded = true;
773
userDB->name = filename;
774
userDB->uuid = uuid;
775
776
return tableID;
777
}
778
bool32 RSDK::SKU::UserDBStorage::SaveUserDB(uint16 tableID, void (*callback)(int32 status))
779
{
780
UserDB *userDB = &userDBStorage->userDB[tableID];
781
782
bool32 success = false;
783
if (userDB->active) {
784
int32 totalSize = (int32)userDB->GetSize();
785
AllocateStorage((void **)&userDBStorage->writeBuffer[tableID], totalSize, DATASET_TMP, true);
786
userDB->Save(totalSize, (uint8 *)userDBStorage->writeBuffer[tableID]);
787
userDBStorage->dbSaveCB[tableID] = UserDBStorage::SaveCB;
788
userDBStorage->callbacks[tableID] = callback;
789
success = TrySaveUserFile(userDB->name, userDBStorage->writeBuffer[tableID], totalSize, userDBStorage->saveCallback[tableID], true);
790
}
791
else {
792
if (callback)
793
callback(STATUS_ERROR);
794
}
795
796
return success;
797
}
798
void RSDK::SKU::UserDBStorage::ClearUserDB(uint16 tableID)
799
{
800
if (tableID == (uint16)-1)
801
return;
802
803
UserDB *userDB = &userDBStorage->userDB[tableID];
804
if (userDB->loaded) {
805
userDB->Clear();
806
}
807
}
808
void RSDK::SKU::UserDBStorage::ClearAllUserDBs()
809
{
810
for (int32 i = 0; i < RETRO_USERDB_MAX; ++i) ClearUserDB(i);
811
}
812
813
bool32 RSDK::SKU::UserDBStorage::LoadCB(uint16 tableID, int32 status)
814
{
815
bool32 succeeded = false;
816
if (status == STATUS_OK) {
817
UserDB *userDB = &userDBStorage->userDB[tableID];
818
819
succeeded = userDB->Load((uint8 *)userDBStorage->readBuffer[tableID]);
820
if (succeeded) {
821
userDB->parent->RefreshSortList();
822
}
823
}
824
else {
825
RSDK::SKU::ClearUserDB(tableID);
826
}
827
RemoveStorageEntry((void **)&userDBStorage->readBuffer[tableID]);
828
829
if (userDBStorage->callbacks[tableID]) {
830
userDBStorage->callbacks[tableID](succeeded ? status : STATUS_ERROR);
831
userDBStorage->callbacks[tableID] = NULL;
832
}
833
834
return succeeded;
835
}
836
bool32 RSDK::SKU::UserDBStorage::SaveCB(uint16 tableID, int32 status)
837
{
838
RemoveStorageEntry((void **)&userDBStorage->writeBuffer[tableID]);
839
if (status != STATUS_OK)
840
userDBStorage->userDB[tableID].valid = false;
841
842
if (userDBStorage->callbacks[tableID]) {
843
userDBStorage->callbacks[tableID](status);
844
userDBStorage->callbacks[tableID] = NULL;
845
return true;
846
}
847
return false;
848
}
849
850
// =======================
851
// USER DB API
852
// =======================
853
854
// UserDB Row Sorting
855
uint16 RSDK::SKU::SetupUserDBRowSorting(uint16 tableID)
856
{
857
if (tableID == (uint16)-1)
858
return 0;
859
userDBStorage->userDB[tableID].parent->RefreshSortList();
860
861
return userDBStorage->userDB[tableID].sortedRowCount;
862
}
863
int32 RSDK::SKU::AddUserDBRowSortFilter(uint16 tableID, int32 type, const char *name, void *value)
864
{
865
if (tableID == (uint16)-1)
866
return 0;
867
UserDB *userDB = &userDBStorage->userDB[tableID];
868
if (!userDB->active)
869
return 0;
870
871
userDB->parent->AddSortFilter(name, value);
872
return userDB->sortedRowCount;
873
}
874
int32 RSDK::SKU::SortUserDBRows(uint16 tableID, int32 type, const char *name, bool32 sortAscending)
875
{
876
if (tableID == (uint16)-1)
877
return 0;
878
879
UserDB *userDB = &userDBStorage->userDB[tableID];
880
if (!userDB->active)
881
return 0;
882
883
userDB->parent->SortRows(type, (char *)name, sortAscending);
884
return userDB->sortedRowCount;
885
}
886
int32 RSDK::SKU::GetSortedUserDBRowCount(uint16 tableID)
887
{
888
if (tableID == (uint16)-1)
889
return 0;
890
891
UserDB *userDB = &userDBStorage->userDB[tableID];
892
if (!userDB->active)
893
return 0;
894
895
return userDB->sortedRowCount;
896
}
897
int32 RSDK::SKU::GetSortedUserDBRowID(uint16 tableID, uint16 sortedRowID)
898
{
899
if (tableID == (uint16)-1)
900
return -1;
901
902
UserDB *userDB = &userDBStorage->userDB[tableID];
903
if (!userDB->active || userDB->rowsChanged || sortedRowID >= userDB->sortedRowCount)
904
return -1;
905
906
return userDB->sortedRowIDs[sortedRowID];
907
}
908
909
// UserDB Values
910
bool32 RSDK::SKU::GetUserDBValue(uint16 tableID, uint32 rowID, int32 type, char *name, void *value)
911
{
912
if (tableID == (uint16)-1 || rowID == (uint16)-1 || !userDBStorage->userDB[tableID].active)
913
return false;
914
return userDBStorage->userDB[tableID].rows[rowID].GetValue(type, name, value);
915
}
916
bool32 RSDK::SKU::SetUserDBValue(uint16 tableID, uint32 rowID, int32 type, char *name, void *value)
917
{
918
if (tableID == (uint16)-1 || rowID == (uint16)-1 || !userDBStorage->userDB[tableID].active)
919
return false;
920
921
return userDBStorage->userDB[tableID].rows[rowID].AddValue(type, name, value);
922
}
923
924
// UserDB Misc
925
bool32 RSDK::SKU::GetUserDBRowsChanged(uint16 tableID) { return userDBStorage->userDB[tableID].rowsChanged; }
926
void RSDK::SKU::GetUserDBRowCreationTime(uint16 tableID, uint16 rowID, char *buf, size_t size, char *format)
927
{
928
if (tableID != (uint16)-1 && rowID != (uint16)-1) {
929
UserDB *userDB = &userDBStorage->userDB[tableID];
930
if (userDB->active)
931
strftime(buf, size, format, &userDB->rows[rowID].createTime);
932
}
933
}
934
935
// =======================
936
// USER DB CALLBACKS
937
// =======================
938
939
void RSDK::SKU::UserDBStorage_LoadCB1(int32 status)
940
{
941
if (userDBStorage->dbLoadCB[0])
942
userDBStorage->dbLoadCB[0](0, status);
943
}
944
void RSDK::SKU::UserDBStorage_LoadCB2(int32 status)
945
{
946
if (userDBStorage->dbLoadCB[1])
947
userDBStorage->dbLoadCB[1](1, status);
948
}
949
void RSDK::SKU::UserDBStorage_LoadCB3(int32 status)
950
{
951
if (userDBStorage->dbLoadCB[2])
952
userDBStorage->dbLoadCB[2](2, status);
953
}
954
void RSDK::SKU::UserDBStorage_LoadCB4(int32 status)
955
{
956
if (userDBStorage->dbLoadCB[3])
957
userDBStorage->dbLoadCB[3](3, status);
958
}
959
void RSDK::SKU::UserDBStorage_LoadCB5(int32 status)
960
{
961
if (userDBStorage->dbLoadCB[4])
962
userDBStorage->dbLoadCB[4](4, status);
963
}
964
void RSDK::SKU::UserDBStorage_LoadCB6(int32 status)
965
{
966
if (userDBStorage->dbLoadCB[5])
967
userDBStorage->dbLoadCB[5](5, status);
968
}
969
void RSDK::SKU::UserDBStorage_LoadCB7(int32 status)
970
{
971
if (userDBStorage->dbLoadCB[6])
972
userDBStorage->dbLoadCB[6](6, status);
973
}
974
void RSDK::SKU::UserDBStorage_LoadCB8(int32 status)
975
{
976
if (userDBStorage->dbLoadCB[7])
977
userDBStorage->dbLoadCB[7](7, status);
978
}
979
980
void RSDK::SKU::UserDBStorage_SaveCB1(int32 status)
981
{
982
if (userDBStorage->dbSaveCB[0])
983
userDBStorage->dbSaveCB[0](0, status);
984
}
985
void RSDK::SKU::UserDBStorage_SaveCB2(int32 status)
986
{
987
if (userDBStorage->dbSaveCB[1])
988
userDBStorage->dbSaveCB[1](1, status);
989
}
990
void RSDK::SKU::UserDBStorage_SaveCB3(int32 status)
991
{
992
if (userDBStorage->dbSaveCB[2])
993
userDBStorage->dbSaveCB[2](2, status);
994
}
995
void RSDK::SKU::UserDBStorage_SaveCB4(int32 status)
996
{
997
if (userDBStorage->dbSaveCB[3])
998
userDBStorage->dbSaveCB[3](3, status);
999
}
1000
void RSDK::SKU::UserDBStorage_SaveCB5(int32 status)
1001
{
1002
if (userDBStorage->dbSaveCB[4])
1003
userDBStorage->dbSaveCB[4](4, status);
1004
}
1005
void RSDK::SKU::UserDBStorage_SaveCB6(int32 status)
1006
{
1007
if (userDBStorage->dbSaveCB[5])
1008
userDBStorage->dbSaveCB[5](5, status);
1009
}
1010
void RSDK::SKU::UserDBStorage_SaveCB7(int32 status)
1011
{
1012
if (userDBStorage->dbSaveCB[6])
1013
userDBStorage->dbSaveCB[6](6, status);
1014
}
1015
void RSDK::SKU::UserDBStorage_SaveCB8(int32 status)
1016
{
1017
if (userDBStorage->dbSaveCB[7])
1018
userDBStorage->dbSaveCB[7](7, status);
1019
}
1020
1021
#endif
1022
1023
void (*RSDK::SKU::preLoadSaveFileCB)();
1024
void (*RSDK::SKU::postLoadSaveFileCB)();
1025
char RSDK::SKU::userFileDir[0x100];
1026
1027
bool32 RSDK::SKU::LoadUserFile(const char *filename, void *buffer, uint32 bufSize)
1028
{
1029
if (preLoadSaveFileCB)
1030
preLoadSaveFileCB();
1031
1032
char fullFilePath[0x400];
1033
#if RETRO_USE_MOD_LOADER
1034
if (strlen(customUserFileDir))
1035
sprintf_s(fullFilePath, sizeof(fullFilePath), "%s%s", customUserFileDir, filename);
1036
else
1037
sprintf_s(fullFilePath, sizeof(fullFilePath), "%s%s", userFileDir, filename);
1038
#else
1039
sprintf_s(fullFilePath, sizeof(fullFilePath), "%s%s", userFileDir, filename);
1040
#endif
1041
PrintLog(PRINT_NORMAL, "Attempting to load user file: %s", fullFilePath);
1042
1043
FileIO *file = fOpen(fullFilePath, "rb");
1044
if (file) {
1045
fSeek(file, 0, SEEK_END);
1046
uint32 fSize = (uint32)fTell(file);
1047
fSeek(file, 0, SEEK_SET);
1048
uint32 size = bufSize;
1049
if (bufSize > fSize)
1050
size = fSize;
1051
fRead(buffer, 1, size, file);
1052
fClose(file);
1053
1054
if (postLoadSaveFileCB)
1055
postLoadSaveFileCB();
1056
1057
return true;
1058
}
1059
else {
1060
if (postLoadSaveFileCB)
1061
postLoadSaveFileCB();
1062
1063
PrintLog(PRINT_NORMAL, "Nope!");
1064
}
1065
1066
return false;
1067
}
1068
bool32 RSDK::SKU::SaveUserFile(const char *filename, void *buffer, uint32 bufSize)
1069
{
1070
if (preLoadSaveFileCB)
1071
preLoadSaveFileCB();
1072
1073
char fullFilePath[0x400];
1074
#if RETRO_USE_MOD_LOADER
1075
if (strlen(customUserFileDir))
1076
sprintf_s(fullFilePath, sizeof(fullFilePath), "%s%s", customUserFileDir, filename);
1077
else
1078
sprintf_s(fullFilePath, sizeof(fullFilePath), "%s%s", userFileDir, filename);
1079
#else
1080
sprintf_s(fullFilePath, sizeof(fullFilePath), "%s%s", userFileDir, filename);
1081
#endif
1082
PrintLog(PRINT_NORMAL, "Attempting to save user file: %s", fullFilePath);
1083
1084
FileIO *file = fOpen(fullFilePath, "wb");
1085
if (file) {
1086
fWrite(buffer, 1, bufSize, file);
1087
fClose(file);
1088
1089
if (postLoadSaveFileCB)
1090
postLoadSaveFileCB();
1091
1092
return true;
1093
}
1094
else {
1095
if (postLoadSaveFileCB)
1096
postLoadSaveFileCB();
1097
1098
PrintLog(PRINT_NORMAL, "Nope!");
1099
}
1100
return false;
1101
}
1102
bool32 RSDK::SKU::DeleteUserFile(const char *filename)
1103
{
1104
if (preLoadSaveFileCB)
1105
preLoadSaveFileCB();
1106
1107
char fullFilePath[0x400];
1108
#if RETRO_USE_MOD_LOADER
1109
if (strlen(customUserFileDir))
1110
sprintf_s(fullFilePath, sizeof(fullFilePath), "%s%s", customUserFileDir, filename);
1111
else
1112
sprintf_s(fullFilePath, sizeof(fullFilePath), "%s%s", userFileDir, filename);
1113
#else
1114
sprintf_s(fullFilePath, sizeof(fullFilePath), "%s%s", userFileDir, filename);
1115
#endif
1116
PrintLog(PRINT_NORMAL, "Attempting to delete user file: %s", fullFilePath);
1117
int32 status = remove(fullFilePath);
1118
1119
if (postLoadSaveFileCB)
1120
postLoadSaveFileCB();
1121
1122
return status == 0;
1123
}
1124
1125
#if !RETRO_REV02
1126
bool32 RSDK::SKU::TryLoadUserFile(const char *filename, void *buffer, uint32 size, void (*callback)(int32 status))
1127
{
1128
bool32 success = false;
1129
1130
success = LoadUserFile(filename, buffer, size);
1131
1132
if (callback)
1133
callback(success ? STATUS_OK : STATUS_ERROR);
1134
1135
return success;
1136
}
1137
bool32 RSDK::SKU::TrySaveUserFile(const char *filename, void *buffer, uint32 size, void (*callback)(int32 status))
1138
{
1139
bool32 success = false;
1140
1141
success = SaveUserFile(filename, buffer, size);
1142
1143
if (callback)
1144
callback(success ? STATUS_OK : STATUS_ERROR);
1145
1146
return success;
1147
}
1148
#endif
1149
1150
void RSDK::SKU::InitUserDirectory()
1151
{
1152
#if RETRO_PLATFORM == RETRO_OSX
1153
1154
char buffer[0x100];
1155
sprintf_s(buffer, sizeof(buffer), "%s/RSDKv5/", getResourcesPath());
1156
SKU::SetUserFileCallbacks(buffer, NULL, NULL);
1157
1158
#elif RETRO_PLATFORM == RETRO_ANDROID
1159
1160
// done by javaside
1161
1162
#elif RETRO_PLATFORM == RETRO_LINUX
1163
1164
SKU::SetUserFileCallbacks("./", NULL, NULL);
1165
1166
#else
1167
1168
SKU::SetUserFileCallbacks("", NULL, NULL);
1169
1170
#endif
1171
}
1172