Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Rubberduckycooly
GitHub Repository: Rubberduckycooly/RSDKv5-Decompilation
Path: blob/master/RSDKv5/RSDK/Core/Reader.hpp
1163 views
1
#ifndef READER_H
2
#define READER_H
3
4
#if RETRO_RENDERDEVICE_SDL2 || RETRO_AUDIODEVICE_SDL2 || RETRO_INPUTDEVICE_SDL2
5
#define FileIO SDL_RWops
6
#define fOpen(path, mode) SDL_RWFromFile(path, mode)
7
#define fRead(buffer, elementSize, elementCount, file) SDL_RWread(file, buffer, elementSize, elementCount)
8
#define fSeek(file, offset, whence) SDL_RWseek(file, offset, whence)
9
#define fTell(file) SDL_RWtell(file)
10
#define fClose(file) SDL_RWclose(file)
11
#define fWrite(buffer, elementSize, elementCount, file) SDL_RWwrite(file, buffer, elementSize, elementCount)
12
#else
13
#define FileIO FILE
14
#define fOpen(path, mode) fopen(path, mode)
15
#define fRead(buffer, elementSize, elementCount, file) fread(buffer, elementSize, elementCount, file)
16
#define fSeek(file, offset, whence) fseek(file, offset, whence)
17
#define fTell(file) ftell(file)
18
#define fClose(file) fclose(file)
19
#define fWrite(buffer, elementSize, elementCount, file) fwrite(buffer, elementSize, elementCount, file)
20
#endif
21
22
#if RETRO_PLATFORM == RETRO_ANDROID
23
#undef fOpen
24
FileIO *fOpen(const char *path, const char *mode);
25
#endif
26
27
#include <miniz/miniz.h>
28
29
namespace RSDK
30
{
31
32
#define RSDK_SIGNATURE_RSDK (0x4B445352) // "RSDK"
33
#if RETRO_REV0U
34
#define RSDK_SIGNATURE_DATA (0x61746144) // "Data"
35
#endif
36
37
#define DATAFILE_COUNT (0x1000)
38
#define DATAPACK_COUNT (4)
39
40
enum Scopes {
41
SCOPE_NONE,
42
SCOPE_GLOBAL,
43
SCOPE_STAGE,
44
};
45
46
struct FileInfo {
47
int32 fileSize;
48
int32 externalFile;
49
FileIO *file;
50
uint8 *fileBuffer;
51
int32 readPos;
52
int32 fileOffset;
53
uint8 usingFileBuffer;
54
uint8 encrypted;
55
uint8 eNybbleSwap;
56
uint8 encryptionKeyA[0x10];
57
uint8 encryptionKeyB[0x10];
58
uint8 eKeyPosA;
59
uint8 eKeyPosB;
60
uint8 eKeyNo;
61
};
62
63
struct RSDKFileInfo {
64
RETRO_HASH_MD5(hash);
65
int32 size;
66
int32 offset;
67
uint8 encrypted;
68
uint8 useFileBuffer;
69
int32 packID;
70
};
71
72
struct RSDKContainer {
73
char name[0x100];
74
uint8 *fileBuffer;
75
int32 fileCount;
76
};
77
78
extern RSDKFileInfo dataFileList[DATAFILE_COUNT];
79
extern RSDKContainer dataPacks[DATAPACK_COUNT];
80
81
extern uint8 dataPackCount;
82
extern uint16 dataFileListCount;
83
84
extern char gameLogicName[0x200];
85
86
extern bool32 useDataPack;
87
88
#if RETRO_REV0U
89
void DetectEngineVersion();
90
#endif
91
bool32 LoadDataPack(const char *filename, size_t fileOffset, bool32 useBuffer);
92
bool32 OpenDataFile(FileInfo *info, const char *filename);
93
94
enum FileModes { FMODE_NONE, FMODE_RB, FMODE_WB, FMODE_RB_PLUS };
95
96
static const char *openModes[3] = { "rb", "wb", "rb+" };
97
98
inline bool32 CheckBigEndian()
99
{
100
uint32 x = 1;
101
uint8 *c = (uint8 *)&x;
102
return ((int32)*c) == 0;
103
}
104
105
inline void InitFileInfo(FileInfo *info)
106
{
107
info->file = NULL;
108
info->fileSize = 0;
109
info->externalFile = false;
110
info->usingFileBuffer = false;
111
info->encrypted = false;
112
info->readPos = 0;
113
info->fileOffset = 0;
114
}
115
116
bool32 LoadFile(FileInfo *info, const char *filename, uint8 fileMode);
117
118
inline void CloseFile(FileInfo *info)
119
{
120
if (!info->usingFileBuffer && info->file)
121
fClose(info->file);
122
123
info->file = NULL;
124
}
125
126
void GenerateELoadKeys(FileInfo *info, const char *key1, int32 key2);
127
void DecryptBytes(FileInfo *info, void *buffer, size_t size);
128
void SkipBytes(FileInfo *info, int32 size);
129
130
inline void Seek_Set(FileInfo *info, int32 count)
131
{
132
if (info->readPos != count) {
133
if (info->encrypted) {
134
info->eKeyNo = (info->fileSize / 4) & 0x7F;
135
info->eKeyPosA = 0;
136
info->eKeyPosB = 8;
137
info->eNybbleSwap = false;
138
SkipBytes(info, count);
139
}
140
141
info->readPos = count;
142
if (info->usingFileBuffer) {
143
uint8 *fileBuffer = (uint8 *)info->file;
144
info->fileBuffer = &fileBuffer[info->readPos];
145
}
146
else {
147
fSeek(info->file, info->fileOffset + info->readPos, SEEK_SET);
148
}
149
}
150
}
151
152
inline void Seek_Cur(FileInfo *info, int32 count)
153
{
154
info->readPos += count;
155
156
if (info->encrypted)
157
SkipBytes(info, count);
158
159
if (info->usingFileBuffer) {
160
info->fileBuffer += count;
161
}
162
else {
163
fSeek(info->file, count, SEEK_CUR);
164
}
165
}
166
167
inline size_t ReadBytes(FileInfo *info, void *data, int32 count)
168
{
169
size_t bytesRead = 0;
170
171
if (info->usingFileBuffer) {
172
bytesRead = MIN(count, info->fileSize - info->readPos);
173
memcpy(data, info->fileBuffer, bytesRead);
174
info->fileBuffer += bytesRead;
175
}
176
else {
177
bytesRead = fRead(data, 1, count, info->file);
178
}
179
180
if (info->encrypted)
181
DecryptBytes(info, data, bytesRead);
182
183
info->readPos += (int32)bytesRead;
184
return bytesRead;
185
}
186
187
inline uint8 ReadInt8(FileInfo *info)
188
{
189
int8 result = 0;
190
size_t bytesRead = 0;
191
192
if (info->usingFileBuffer) {
193
bytesRead = MIN(sizeof(int8), info->fileSize - info->readPos);
194
if (bytesRead) {
195
result = info->fileBuffer[0];
196
info->fileBuffer += sizeof(int8);
197
}
198
}
199
else {
200
bytesRead = fRead(&result, 1, sizeof(int8), info->file);
201
}
202
203
if (info->encrypted)
204
DecryptBytes(info, &result, bytesRead);
205
206
info->readPos += (int32)bytesRead;
207
return result;
208
}
209
210
inline int16 ReadInt16(FileInfo *info)
211
{
212
union {
213
uint16 result;
214
uint8 b[sizeof(result)];
215
} buffer;
216
memset(&buffer, 0, sizeof(buffer));
217
218
size_t bytesRead = 0;
219
220
if (info->usingFileBuffer) {
221
bytesRead = MIN(sizeof(buffer), info->fileSize - info->readPos);
222
if (bytesRead >= sizeof(buffer)) {
223
memcpy(buffer.b, info->fileBuffer, sizeof(buffer));
224
225
info->fileBuffer += sizeof(buffer);
226
}
227
}
228
else {
229
bytesRead = fRead(buffer.b, 1, sizeof(int16), info->file);
230
}
231
232
if (info->encrypted)
233
DecryptBytes(info, buffer.b, bytesRead);
234
235
// if we're on a big endian machine, swap the byte order
236
// this is done AFTER reading & decrypting since they expect little endian order on all systems
237
if (CheckBigEndian()) {
238
uint8 bytes[sizeof(buffer)];
239
memcpy(bytes, &buffer, sizeof(buffer));
240
241
int32 max = sizeof(buffer) - 1;
242
for (int32 i = 0; i < sizeof(buffer) / 2; ++i) {
243
uint8 store = bytes[i];
244
bytes[i] = bytes[max - i];
245
bytes[max - i] = store;
246
}
247
memcpy(&buffer, bytes, sizeof(buffer));
248
}
249
250
info->readPos += (int32)bytesRead;
251
return buffer.result;
252
}
253
254
inline int32 ReadInt32(FileInfo *info, bool32 swapEndian)
255
{
256
union {
257
uint32 result;
258
uint8 b[sizeof(result)];
259
} buffer;
260
memset(&buffer, 0, sizeof(buffer));
261
262
size_t bytesRead = 0;
263
264
if (info->usingFileBuffer) {
265
bytesRead = MIN(sizeof(buffer), info->fileSize - info->readPos);
266
if (bytesRead >= sizeof(buffer)) {
267
memcpy(buffer.b, info->fileBuffer, sizeof(buffer));
268
269
info->fileBuffer += sizeof(buffer);
270
}
271
}
272
else {
273
bytesRead = fRead(buffer.b, 1, sizeof(int32), info->file);
274
}
275
276
if (info->encrypted)
277
DecryptBytes(info, buffer.b, bytesRead);
278
279
if (swapEndian) {
280
uint8 bytes[sizeof(buffer)];
281
memcpy(bytes, &buffer, sizeof(buffer));
282
283
int32 max = sizeof(buffer) - 1;
284
for (int32 i = 0; i < sizeof(buffer) / 2; ++i) {
285
uint8 store = bytes[i];
286
bytes[i] = bytes[max - i];
287
bytes[max - i] = store;
288
}
289
memcpy(&buffer, bytes, sizeof(buffer));
290
}
291
292
// if we're on a big endian machine, swap the byte order
293
// this is done AFTER reading & decrypting since they expect little endian order on all systems
294
if (CheckBigEndian()) {
295
uint8 bytes[sizeof(buffer)];
296
memcpy(bytes, &buffer, sizeof(buffer));
297
298
int32 max = sizeof(buffer) - 1;
299
for (int32 i = 0; i < sizeof(buffer) / 2; ++i) {
300
uint8 store = bytes[i];
301
bytes[i] = bytes[max - i];
302
bytes[max - i] = store;
303
}
304
memcpy(&buffer, bytes, sizeof(buffer));
305
}
306
307
info->readPos += (int32)bytesRead;
308
return buffer.result;
309
}
310
inline int64 ReadInt64(FileInfo *info)
311
{
312
union {
313
uint64 result;
314
uint8 b[sizeof(result)];
315
} buffer;
316
memset(&buffer, 0, sizeof(buffer));
317
318
size_t bytesRead = 0;
319
320
if (info->usingFileBuffer) {
321
bytesRead = MIN(sizeof(buffer), info->fileSize - info->readPos);
322
if (bytesRead >= sizeof(buffer)) {
323
memcpy(buffer.b, info->fileBuffer, sizeof(buffer));
324
325
info->fileBuffer += sizeof(buffer);
326
}
327
}
328
else {
329
bytesRead = fRead(buffer.b, 1, sizeof(int64), info->file);
330
}
331
332
if (info->encrypted)
333
DecryptBytes(info, buffer.b, bytesRead);
334
335
// if we're on a big endian machine, swap the byte order
336
// this is done AFTER reading & decrypting since they expect little endian order on all systems
337
if (CheckBigEndian()) {
338
uint8 bytes[sizeof(buffer)];
339
memcpy(bytes, &buffer, sizeof(buffer));
340
341
int32 max = sizeof(buffer) - 1;
342
for (int32 i = 0; i < sizeof(buffer) / 2; ++i) {
343
uint8 store = bytes[i];
344
bytes[i] = bytes[max - i];
345
bytes[max - i] = store;
346
}
347
memcpy(&buffer, bytes, sizeof(buffer));
348
}
349
350
info->readPos += (int32)bytesRead;
351
return buffer.result;
352
}
353
354
inline float ReadSingle(FileInfo *info)
355
{
356
union {
357
float result;
358
uint8 b[sizeof(result)];
359
} buffer;
360
memset(&buffer, 0, sizeof(buffer));
361
362
size_t bytesRead = 0;
363
364
if (info->usingFileBuffer) {
365
bytesRead = MIN(sizeof(buffer), info->fileSize - info->readPos);
366
if (bytesRead >= sizeof(buffer)) {
367
memcpy(buffer.b, info->fileBuffer, sizeof(buffer));
368
369
info->fileBuffer += sizeof(buffer);
370
}
371
}
372
else {
373
bytesRead = fRead(buffer.b, 1, sizeof(float), info->file);
374
}
375
376
if (info->encrypted)
377
DecryptBytes(info, buffer.b, bytesRead);
378
379
// if we're on a big endian machine, swap the byte order
380
// this is done AFTER reading & decrypting since they expect little endian order on all systems
381
if (CheckBigEndian()) {
382
uint8 bytes[sizeof(buffer)];
383
memcpy(bytes, &buffer, sizeof(buffer));
384
385
int32 max = sizeof(buffer) - 1;
386
for (int32 i = 0; i < sizeof(buffer) / 2; ++i) {
387
uint8 store = bytes[i];
388
bytes[i] = bytes[max - i];
389
bytes[max - i] = store;
390
}
391
memcpy(&buffer, bytes, sizeof(buffer));
392
}
393
394
info->readPos += (int32)bytesRead;
395
return buffer.result;
396
}
397
398
inline void ReadString(FileInfo *info, char *buffer)
399
{
400
uint8 size = ReadInt8(info);
401
ReadBytes(info, buffer, size);
402
buffer[size] = 0;
403
}
404
405
inline int32 Uncompress(uint8 **cBuffer, int32 cSize, uint8 **buffer, int32 size)
406
{
407
if (!buffer || !cBuffer)
408
return 0;
409
410
uLongf cLen = cSize;
411
uLongf destLen = size;
412
413
int32 result = uncompress(*buffer, &destLen, *cBuffer, cLen);
414
(void)result;
415
416
return (int32)destLen;
417
}
418
419
// The buffer passed in parameter is allocated here, so it's up to the caller to free it once it goes unused
420
inline int32 ReadCompressed(FileInfo *info, uint8 **buffer)
421
{
422
if (!buffer)
423
return 0;
424
425
uint32 cSize = ReadInt32(info, false) - 4;
426
uint32 sizeBE = ReadInt32(info, false);
427
428
uint32 sizeLE = (uint32)((sizeBE << 24) | ((sizeBE << 8) & 0x00FF0000) | ((sizeBE >> 8) & 0x0000FF00) | (sizeBE >> 24));
429
AllocateStorage((void **)buffer, sizeLE, DATASET_TMP, false);
430
431
uint8 *cBuffer = NULL;
432
AllocateStorage((void **)&cBuffer, cSize, DATASET_TMP, false);
433
ReadBytes(info, cBuffer, cSize);
434
435
uint32 newSize = Uncompress(&cBuffer, cSize, buffer, sizeLE);
436
RemoveStorageEntry((void **)&cBuffer);
437
438
return newSize;
439
}
440
441
inline void ClearDataFiles()
442
{
443
// Unload file list
444
for (int32 f = 0; f < DATAFILE_COUNT; ++f) {
445
HASH_CLEAR_MD5(dataFileList[f].hash);
446
}
447
}
448
449
} // namespace RSDK
450
451
#endif
452
453