Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Rubberduckycooly
GitHub Repository: Rubberduckycooly/RSDKv5-Decompilation
Path: blob/master/RSDKv5/RSDK/Core/Reader.cpp
1163 views
1
#include "RSDK/Core/RetroEngine.hpp"
2
3
using namespace RSDK;
4
5
RSDKFileInfo RSDK::dataFileList[DATAFILE_COUNT];
6
RSDKContainer RSDK::dataPacks[DATAPACK_COUNT];
7
8
uint8 RSDK::dataPackCount = 0;
9
uint16 RSDK::dataFileListCount = 0;
10
11
char RSDK::gameLogicName[0x200];
12
13
bool32 RSDK::useDataPack = false;
14
15
#if RETRO_REV0U
16
void RSDK::DetectEngineVersion()
17
{
18
bool32 readDataPack = useDataPack;
19
#if RETRO_USE_MOD_LOADER
20
// mods can manually set their target engine versions if needed
21
if (modSettings.versionOverride) {
22
engine.version = modSettings.versionOverride;
23
return;
24
}
25
26
// check if we have any mods with gameconfigs
27
int32 m = 0;
28
for (m = 0; m < modList.size(); ++m) {
29
if (!modList[m].active)
30
break;
31
SetActiveMod(m);
32
33
FileInfo checkInfo;
34
InitFileInfo(&checkInfo);
35
if (LoadFile(&checkInfo, "Data/Game/GameConfig.bin", FMODE_RB)) {
36
readDataPack = false;
37
CloseFile(&checkInfo);
38
m = 0; // found one, just sets this to 0 again
39
break;
40
}
41
}
42
43
if (m) // didn't find a gameconfig
44
SetActiveMod(-1);
45
#endif
46
47
FileInfo info;
48
InitFileInfo(&info);
49
if (!readDataPack) {
50
if (LoadFile(&info, "Data/Game/GameConfig.bin", FMODE_RB)) {
51
#if RETRO_USE_MOD_LOADER
52
SetActiveMod(-1);
53
#endif
54
uint32 sig = ReadInt32(&info, false);
55
56
// GameConfig has "CFG" signature, its RSDKv5 formatted
57
if (sig == RSDK_SIGNATURE_CFG) {
58
engine.version = 5;
59
}
60
else {
61
// else, assume its RSDKv4 for now
62
engine.version = 4;
63
64
// Go back to the start of the file to check v3's "Data" string, that way we can tell if its v3 or v4
65
Seek_Set(&info, 0);
66
67
uint8 length = ReadInt8(&info);
68
char buffer[0x40];
69
ReadBytes(&info, buffer, length);
70
71
// the "Data" thing is actually a string, but lets treat it as a "signature" for simplicity's sake shall we?
72
length = ReadInt8(&info);
73
uint32 sig = ReadInt32(&info, false);
74
if (sig == RSDK_SIGNATURE_DATA && length == 4)
75
engine.version = 3;
76
}
77
78
CloseFile(&info);
79
}
80
}
81
else {
82
info.externalFile = true;
83
if (LoadFile(&info, dataPacks[dataPackCount - 1].name, FMODE_RB)) {
84
uint32 sig = ReadInt32(&info, false);
85
if (sig == RSDK_SIGNATURE_RSDK) {
86
ReadInt8(&info); // 'v'
87
uint8 version = ReadInt8(&info);
88
89
switch (version) {
90
default: break;
91
case '3': engine.version = 3; break;
92
case '4': engine.version = 4; break;
93
case '5': engine.version = 5; break;
94
}
95
}
96
else {
97
// v3 has no 'RSDK' signature
98
engine.version = 3;
99
}
100
101
CloseFile(&info);
102
}
103
}
104
}
105
#endif
106
107
bool32 RSDK::LoadDataPack(const char *filePath, size_t fileOffset, bool32 useBuffer)
108
{
109
MEM_ZERO(dataPacks[dataPackCount]);
110
useDataPack = false;
111
FileInfo info;
112
113
char dataPackPath[0x100];
114
sprintf_s(dataPackPath, sizeof(dataPackPath), "%s%s", SKU::userFileDir, filePath);
115
116
InitFileInfo(&info);
117
info.externalFile = true;
118
if (LoadFile(&info, dataPackPath, FMODE_RB)) {
119
uint32 sig = ReadInt32(&info, false);
120
if (sig != RSDK_SIGNATURE_RSDK)
121
return false;
122
123
useDataPack = true;
124
125
ReadInt8(&info); // 'v'
126
ReadInt8(&info); // version
127
128
strcpy(dataPacks[dataPackCount].name, dataPackPath);
129
130
dataPacks[dataPackCount].fileCount = ReadInt16(&info);
131
for (int32 f = 0; f < dataPacks[dataPackCount].fileCount; ++f) {
132
uint8 b[4];
133
for (int32 y = 0; y < 4; y++) {
134
ReadBytes(&info, b, 4);
135
dataFileList[f].hash[y] = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3] << 0);
136
}
137
138
dataFileList[f].offset = ReadInt32(&info, false);
139
dataFileList[f].size = ReadInt32(&info, false);
140
141
dataFileList[f].encrypted = (dataFileList[f].size & 0x80000000) != 0;
142
dataFileList[f].size &= 0x7FFFFFFF;
143
dataFileList[f].useFileBuffer = useBuffer;
144
dataFileList[f].packID = dataPackCount;
145
}
146
147
dataPacks[dataPackCount].fileBuffer = NULL;
148
if (useBuffer) {
149
dataPacks[dataPackCount].fileBuffer = (uint8 *)malloc(info.fileSize);
150
Seek_Set(&info, 0);
151
ReadBytes(&info, dataPacks[dataPackCount].fileBuffer, info.fileSize);
152
}
153
154
dataFileListCount += dataPacks[dataPackCount].fileCount;
155
dataPackCount++;
156
157
CloseFile(&info);
158
159
return true;
160
}
161
else {
162
useDataPack = false;
163
return false;
164
}
165
}
166
167
#if !RETRO_USE_ORIGINAL_CODE && RETRO_REV0U
168
inline bool ends_with(std::string const &value, std::string const &ending)
169
{
170
if (ending.size() > value.size())
171
return false;
172
return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
173
}
174
#endif
175
176
bool32 RSDK::OpenDataFile(FileInfo *info, const char *filename)
177
{
178
char hashBuffer[0x400];
179
StringLowerCase(hashBuffer, filename);
180
RETRO_HASH_MD5(hash);
181
GEN_HASH_MD5_BUFFER(hashBuffer, hash);
182
183
for (int32 f = 0; f < dataFileListCount; ++f) {
184
RSDKFileInfo *file = &dataFileList[f];
185
186
if (!HASH_MATCH_MD5(hash, file->hash))
187
continue;
188
189
info->usingFileBuffer = file->useFileBuffer;
190
if (!file->useFileBuffer) {
191
info->file = fOpen(dataPacks[file->packID].name, "rb");
192
if (!info->file) {
193
PrintLog(PRINT_NORMAL, "File not found (Unable to open datapack): %s", filename);
194
return false;
195
}
196
197
fSeek(info->file, file->offset, SEEK_SET);
198
}
199
else {
200
// a bit of a hack, but it is how it is in the original
201
info->file = (FileIO *)&dataPacks[file->packID].fileBuffer[file->offset];
202
203
uint8 *fileBuffer = (uint8 *)info->file;
204
info->fileBuffer = fileBuffer;
205
}
206
207
info->fileSize = file->size;
208
info->readPos = 0;
209
info->fileOffset = file->offset;
210
info->encrypted = file->encrypted;
211
memset(info->encryptionKeyA, 0, 0x10 * sizeof(uint8));
212
memset(info->encryptionKeyB, 0, 0x10 * sizeof(uint8));
213
if (info->encrypted) {
214
GenerateELoadKeys(info, filename, info->fileSize);
215
info->eKeyNo = (info->fileSize / 4) & 0x7F;
216
info->eKeyPosA = 0;
217
info->eKeyPosB = 8;
218
info->eNybbleSwap = false;
219
}
220
221
#if !RETRO_USE_ORIGINAL_CODE
222
PrintLog(PRINT_NORMAL, "Loaded data file %s", filename);
223
#endif
224
return true;
225
}
226
227
#if !RETRO_USE_ORIGINAL_CODE
228
PrintLog(PRINT_NORMAL, "Data file not found: %s", filename);
229
#else
230
PrintLog(PRINT_NORMAL, "File not found: %s", filename);
231
#endif
232
return false;
233
}
234
235
bool32 RSDK::LoadFile(FileInfo *info, const char *filename, uint8 fileMode)
236
{
237
if (info->file)
238
return false;
239
240
char fullFilePath[0x100];
241
strcpy(fullFilePath, filename);
242
243
#if RETRO_USE_MOD_LOADER
244
char pathLower[0x100];
245
memset(pathLower, 0, sizeof(pathLower));
246
for (int32 c = 0; c < strlen(filename); ++c) pathLower[c] = tolower(filename[c]);
247
248
bool32 addPath = false;
249
int32 m = modSettings.activeMod != -1 ? modSettings.activeMod : 0;
250
for (; m < modList.size(); ++m) {
251
if (modList[m].active) {
252
std::map<std::string, std::string>::const_iterator iter = modList[m].fileMap.find(pathLower);
253
if (iter != modList[m].fileMap.cend()) {
254
if (std::find(modList[m].excludedFiles.begin(), modList[m].excludedFiles.end(), pathLower) == modList[m].excludedFiles.end()) {
255
strcpy(fullFilePath, iter->second.c_str());
256
info->externalFile = true;
257
break;
258
}
259
else {
260
PrintLog(PRINT_NORMAL, "[MOD] Excluded File: %s", filename);
261
}
262
}
263
}
264
if (modSettings.activeMod != -1) {
265
PrintLog(PRINT_NORMAL, "[MOD] Failed to find file %s in active mod %s", filename, modList[m].id.c_str());
266
// TODO return false? check original impl later
267
}
268
}
269
270
#if RETRO_REV0U
271
if (modSettings.forceScripts && !info->externalFile) {
272
if (std::string(fullFilePath).rfind("Data/Scripts/", 0) == 0 && ends_with(std::string(fullFilePath), "txt")) {
273
// is a script, since those dont exist normally, load them from "scripts/"
274
info->externalFile = true;
275
addPath = true;
276
std::string fStr = std::string(fullFilePath);
277
fStr.erase(fStr.begin(), fStr.begin() + 5); // remove "Data/"
278
StrCopy(fullFilePath, fStr.c_str());
279
}
280
}
281
#endif
282
283
#if RETRO_PLATFORM == RETRO_OSX || RETRO_PLATFORM == RETRO_ANDROID
284
if (addPath) {
285
char pathBuf[0x100];
286
sprintf_s(pathBuf, sizeof(pathBuf), "%s%s", SKU::userFileDir, fullFilePath);
287
sprintf_s(fullFilePath, sizeof(fullFilePath), "%s", pathBuf);
288
}
289
#else
290
(void)addPath;
291
#endif // ! RETRO_PLATFORM
292
#endif // ! RETRO_MOD_LOADER
293
294
#if !RETRO_USE_ORIGNAL_CODE
295
// somewhat hacky that also pleases the mod gods
296
if (!info->externalFile) {
297
char pathBuf[0x100];
298
sprintf_s(pathBuf, sizeof(pathBuf), "%s%s", SKU::userFileDir, fullFilePath);
299
sprintf_s(fullFilePath, sizeof(fullFilePath), "%s", pathBuf);
300
}
301
#endif
302
303
if (!info->externalFile && fileMode == FMODE_RB && useDataPack) {
304
return OpenDataFile(info, filename);
305
}
306
307
if (fileMode == FMODE_RB || fileMode == FMODE_WB || fileMode == FMODE_RB_PLUS) {
308
info->file = fOpen(fullFilePath, openModes[fileMode - 1]);
309
}
310
311
if (!info->file) {
312
#if !RETRO_USE_ORIGINAL_CODE
313
PrintLog(PRINT_NORMAL, "File not found: %s", fullFilePath);
314
#endif
315
return false;
316
}
317
318
info->readPos = 0;
319
info->fileSize = 0;
320
321
if (fileMode != FMODE_WB) {
322
fSeek(info->file, 0, SEEK_END);
323
info->fileSize = (int32)fTell(info->file);
324
fSeek(info->file, 0, SEEK_SET);
325
}
326
#if !RETRO_USE_ORIGINAL_CODE
327
PrintLog(PRINT_NORMAL, "Loaded file %s", fullFilePath);
328
#endif
329
return true;
330
}
331
332
void RSDK::GenerateELoadKeys(FileInfo *info, const char *key1, int32 key2)
333
{
334
// This function splits hashes into bytes by casting their integers to byte arrays,
335
// which only works as intended on little-endian CPUs.
336
#if !RETRO_USE_ORIGINAL_CODE
337
RETRO_HASH_MD5(hash);
338
#else
339
uint8 hash[0x10];
340
#endif
341
char hashBuffer[0x400];
342
343
// KeyA
344
StringUpperCase(hashBuffer, key1);
345
#if !RETRO_USE_ORIGINAL_CODE
346
GEN_HASH_MD5_BUFFER(hashBuffer, hash);
347
348
for (int32 i = 0; i < 4; ++i)
349
for (int32 j = 0; j < 4; ++j) info->encryptionKeyA[i * 4 + j] = (hash[i] >> (8 * (j ^ 3))) & 0xFF;
350
#else
351
GEN_HASH_MD5_BUFFER(hashBuffer, (uint32 *)hash);
352
353
for (int32 y = 0; y < 0x10; y += 4) {
354
info->encryptionKeyA[y + 3] = hash[y + 0];
355
info->encryptionKeyA[y + 2] = hash[y + 1];
356
info->encryptionKeyA[y + 1] = hash[y + 2];
357
info->encryptionKeyA[y + 0] = hash[y + 3];
358
}
359
#endif
360
361
// KeyB
362
sprintf_s(hashBuffer, sizeof(hashBuffer), "%d", key2);
363
#if !RETRO_USE_ORIGINAL_CODE
364
GEN_HASH_MD5_BUFFER(hashBuffer, hash);
365
366
for (int32 i = 0; i < 4; ++i)
367
for (int32 j = 0; j < 4; ++j) info->encryptionKeyB[i * 4 + j] = (hash[i] >> (8 * (j ^ 3))) & 0xFF;
368
#else
369
GEN_HASH_MD5_BUFFER(hashBuffer, (uint32 *)hash);
370
371
for (int32 y = 0; y < 0x10; y += 4) {
372
info->encryptionKeyB[y + 3] = hash[y + 0];
373
info->encryptionKeyB[y + 2] = hash[y + 1];
374
info->encryptionKeyB[y + 1] = hash[y + 2];
375
info->encryptionKeyB[y + 0] = hash[y + 3];
376
}
377
#endif
378
}
379
380
void RSDK::DecryptBytes(FileInfo *info, void *buffer, size_t size)
381
{
382
if (size) {
383
uint8 *data = (uint8 *)buffer;
384
while (size > 0) {
385
*data ^= info->eKeyNo ^ info->encryptionKeyB[info->eKeyPosB];
386
if (info->eNybbleSwap)
387
*data = ((*data << 4) + (*data >> 4)) & 0xFF;
388
*data ^= info->encryptionKeyA[info->eKeyPosA];
389
390
info->eKeyPosA++;
391
info->eKeyPosB++;
392
393
if (info->eKeyPosA <= 15) {
394
if (info->eKeyPosB > 12) {
395
info->eKeyPosB = 0;
396
info->eNybbleSwap ^= 1;
397
}
398
}
399
else if (info->eKeyPosB <= 8) {
400
info->eKeyPosA = 0;
401
info->eNybbleSwap ^= 1;
402
}
403
else {
404
info->eKeyNo += 2;
405
info->eKeyNo &= 0x7F;
406
407
if (info->eNybbleSwap) {
408
info->eNybbleSwap = false;
409
410
info->eKeyPosA = info->eKeyNo % 7;
411
info->eKeyPosB = (info->eKeyNo % 12) + 2;
412
}
413
else {
414
info->eNybbleSwap = true;
415
416
info->eKeyPosA = (info->eKeyNo % 12) + 3;
417
info->eKeyPosB = info->eKeyNo % 7;
418
}
419
}
420
421
++data;
422
--size;
423
}
424
}
425
}
426
void RSDK::SkipBytes(FileInfo *info, int32 size)
427
{
428
if (size) {
429
while (size > 0) {
430
info->eKeyPosA++;
431
info->eKeyPosB++;
432
433
if (info->eKeyPosA <= 15) {
434
if (info->eKeyPosB > 12) {
435
info->eKeyPosB = 0;
436
info->eNybbleSwap ^= 1;
437
}
438
}
439
else if (info->eKeyPosB <= 8) {
440
info->eKeyPosA = 0;
441
info->eNybbleSwap ^= 1;
442
}
443
else {
444
info->eKeyNo += 2;
445
info->eKeyNo &= 0x7F;
446
447
if (info->eNybbleSwap) {
448
info->eNybbleSwap = false;
449
450
info->eKeyPosA = info->eKeyNo % 7;
451
info->eKeyPosB = (info->eKeyNo % 12) + 2;
452
}
453
else {
454
info->eNybbleSwap = true;
455
456
info->eKeyPosA = (info->eKeyNo % 12) + 3;
457
info->eKeyPosB = info->eKeyNo % 7;
458
}
459
}
460
461
--size;
462
}
463
}
464
}
465
466