Path: blob/master/RSDKv5/RSDK/Core/Reader.hpp
1163 views
#ifndef READER_H1#define READER_H23#if RETRO_RENDERDEVICE_SDL2 || RETRO_AUDIODEVICE_SDL2 || RETRO_INPUTDEVICE_SDL24#define FileIO SDL_RWops5#define fOpen(path, mode) SDL_RWFromFile(path, mode)6#define fRead(buffer, elementSize, elementCount, file) SDL_RWread(file, buffer, elementSize, elementCount)7#define fSeek(file, offset, whence) SDL_RWseek(file, offset, whence)8#define fTell(file) SDL_RWtell(file)9#define fClose(file) SDL_RWclose(file)10#define fWrite(buffer, elementSize, elementCount, file) SDL_RWwrite(file, buffer, elementSize, elementCount)11#else12#define FileIO FILE13#define fOpen(path, mode) fopen(path, mode)14#define fRead(buffer, elementSize, elementCount, file) fread(buffer, elementSize, elementCount, file)15#define fSeek(file, offset, whence) fseek(file, offset, whence)16#define fTell(file) ftell(file)17#define fClose(file) fclose(file)18#define fWrite(buffer, elementSize, elementCount, file) fwrite(buffer, elementSize, elementCount, file)19#endif2021#if RETRO_PLATFORM == RETRO_ANDROID22#undef fOpen23FileIO *fOpen(const char *path, const char *mode);24#endif2526#include <miniz/miniz.h>2728namespace RSDK29{3031#define RSDK_SIGNATURE_RSDK (0x4B445352) // "RSDK"32#if RETRO_REV0U33#define RSDK_SIGNATURE_DATA (0x61746144) // "Data"34#endif3536#define DATAFILE_COUNT (0x1000)37#define DATAPACK_COUNT (4)3839enum Scopes {40SCOPE_NONE,41SCOPE_GLOBAL,42SCOPE_STAGE,43};4445struct FileInfo {46int32 fileSize;47int32 externalFile;48FileIO *file;49uint8 *fileBuffer;50int32 readPos;51int32 fileOffset;52uint8 usingFileBuffer;53uint8 encrypted;54uint8 eNybbleSwap;55uint8 encryptionKeyA[0x10];56uint8 encryptionKeyB[0x10];57uint8 eKeyPosA;58uint8 eKeyPosB;59uint8 eKeyNo;60};6162struct RSDKFileInfo {63RETRO_HASH_MD5(hash);64int32 size;65int32 offset;66uint8 encrypted;67uint8 useFileBuffer;68int32 packID;69};7071struct RSDKContainer {72char name[0x100];73uint8 *fileBuffer;74int32 fileCount;75};7677extern RSDKFileInfo dataFileList[DATAFILE_COUNT];78extern RSDKContainer dataPacks[DATAPACK_COUNT];7980extern uint8 dataPackCount;81extern uint16 dataFileListCount;8283extern char gameLogicName[0x200];8485extern bool32 useDataPack;8687#if RETRO_REV0U88void DetectEngineVersion();89#endif90bool32 LoadDataPack(const char *filename, size_t fileOffset, bool32 useBuffer);91bool32 OpenDataFile(FileInfo *info, const char *filename);9293enum FileModes { FMODE_NONE, FMODE_RB, FMODE_WB, FMODE_RB_PLUS };9495static const char *openModes[3] = { "rb", "wb", "rb+" };9697inline bool32 CheckBigEndian()98{99uint32 x = 1;100uint8 *c = (uint8 *)&x;101return ((int32)*c) == 0;102}103104inline void InitFileInfo(FileInfo *info)105{106info->file = NULL;107info->fileSize = 0;108info->externalFile = false;109info->usingFileBuffer = false;110info->encrypted = false;111info->readPos = 0;112info->fileOffset = 0;113}114115bool32 LoadFile(FileInfo *info, const char *filename, uint8 fileMode);116117inline void CloseFile(FileInfo *info)118{119if (!info->usingFileBuffer && info->file)120fClose(info->file);121122info->file = NULL;123}124125void GenerateELoadKeys(FileInfo *info, const char *key1, int32 key2);126void DecryptBytes(FileInfo *info, void *buffer, size_t size);127void SkipBytes(FileInfo *info, int32 size);128129inline void Seek_Set(FileInfo *info, int32 count)130{131if (info->readPos != count) {132if (info->encrypted) {133info->eKeyNo = (info->fileSize / 4) & 0x7F;134info->eKeyPosA = 0;135info->eKeyPosB = 8;136info->eNybbleSwap = false;137SkipBytes(info, count);138}139140info->readPos = count;141if (info->usingFileBuffer) {142uint8 *fileBuffer = (uint8 *)info->file;143info->fileBuffer = &fileBuffer[info->readPos];144}145else {146fSeek(info->file, info->fileOffset + info->readPos, SEEK_SET);147}148}149}150151inline void Seek_Cur(FileInfo *info, int32 count)152{153info->readPos += count;154155if (info->encrypted)156SkipBytes(info, count);157158if (info->usingFileBuffer) {159info->fileBuffer += count;160}161else {162fSeek(info->file, count, SEEK_CUR);163}164}165166inline size_t ReadBytes(FileInfo *info, void *data, int32 count)167{168size_t bytesRead = 0;169170if (info->usingFileBuffer) {171bytesRead = MIN(count, info->fileSize - info->readPos);172memcpy(data, info->fileBuffer, bytesRead);173info->fileBuffer += bytesRead;174}175else {176bytesRead = fRead(data, 1, count, info->file);177}178179if (info->encrypted)180DecryptBytes(info, data, bytesRead);181182info->readPos += (int32)bytesRead;183return bytesRead;184}185186inline uint8 ReadInt8(FileInfo *info)187{188int8 result = 0;189size_t bytesRead = 0;190191if (info->usingFileBuffer) {192bytesRead = MIN(sizeof(int8), info->fileSize - info->readPos);193if (bytesRead) {194result = info->fileBuffer[0];195info->fileBuffer += sizeof(int8);196}197}198else {199bytesRead = fRead(&result, 1, sizeof(int8), info->file);200}201202if (info->encrypted)203DecryptBytes(info, &result, bytesRead);204205info->readPos += (int32)bytesRead;206return result;207}208209inline int16 ReadInt16(FileInfo *info)210{211union {212uint16 result;213uint8 b[sizeof(result)];214} buffer;215memset(&buffer, 0, sizeof(buffer));216217size_t bytesRead = 0;218219if (info->usingFileBuffer) {220bytesRead = MIN(sizeof(buffer), info->fileSize - info->readPos);221if (bytesRead >= sizeof(buffer)) {222memcpy(buffer.b, info->fileBuffer, sizeof(buffer));223224info->fileBuffer += sizeof(buffer);225}226}227else {228bytesRead = fRead(buffer.b, 1, sizeof(int16), info->file);229}230231if (info->encrypted)232DecryptBytes(info, buffer.b, bytesRead);233234// if we're on a big endian machine, swap the byte order235// this is done AFTER reading & decrypting since they expect little endian order on all systems236if (CheckBigEndian()) {237uint8 bytes[sizeof(buffer)];238memcpy(bytes, &buffer, sizeof(buffer));239240int32 max = sizeof(buffer) - 1;241for (int32 i = 0; i < sizeof(buffer) / 2; ++i) {242uint8 store = bytes[i];243bytes[i] = bytes[max - i];244bytes[max - i] = store;245}246memcpy(&buffer, bytes, sizeof(buffer));247}248249info->readPos += (int32)bytesRead;250return buffer.result;251}252253inline int32 ReadInt32(FileInfo *info, bool32 swapEndian)254{255union {256uint32 result;257uint8 b[sizeof(result)];258} buffer;259memset(&buffer, 0, sizeof(buffer));260261size_t bytesRead = 0;262263if (info->usingFileBuffer) {264bytesRead = MIN(sizeof(buffer), info->fileSize - info->readPos);265if (bytesRead >= sizeof(buffer)) {266memcpy(buffer.b, info->fileBuffer, sizeof(buffer));267268info->fileBuffer += sizeof(buffer);269}270}271else {272bytesRead = fRead(buffer.b, 1, sizeof(int32), info->file);273}274275if (info->encrypted)276DecryptBytes(info, buffer.b, bytesRead);277278if (swapEndian) {279uint8 bytes[sizeof(buffer)];280memcpy(bytes, &buffer, sizeof(buffer));281282int32 max = sizeof(buffer) - 1;283for (int32 i = 0; i < sizeof(buffer) / 2; ++i) {284uint8 store = bytes[i];285bytes[i] = bytes[max - i];286bytes[max - i] = store;287}288memcpy(&buffer, bytes, sizeof(buffer));289}290291// if we're on a big endian machine, swap the byte order292// this is done AFTER reading & decrypting since they expect little endian order on all systems293if (CheckBigEndian()) {294uint8 bytes[sizeof(buffer)];295memcpy(bytes, &buffer, sizeof(buffer));296297int32 max = sizeof(buffer) - 1;298for (int32 i = 0; i < sizeof(buffer) / 2; ++i) {299uint8 store = bytes[i];300bytes[i] = bytes[max - i];301bytes[max - i] = store;302}303memcpy(&buffer, bytes, sizeof(buffer));304}305306info->readPos += (int32)bytesRead;307return buffer.result;308}309inline int64 ReadInt64(FileInfo *info)310{311union {312uint64 result;313uint8 b[sizeof(result)];314} buffer;315memset(&buffer, 0, sizeof(buffer));316317size_t bytesRead = 0;318319if (info->usingFileBuffer) {320bytesRead = MIN(sizeof(buffer), info->fileSize - info->readPos);321if (bytesRead >= sizeof(buffer)) {322memcpy(buffer.b, info->fileBuffer, sizeof(buffer));323324info->fileBuffer += sizeof(buffer);325}326}327else {328bytesRead = fRead(buffer.b, 1, sizeof(int64), info->file);329}330331if (info->encrypted)332DecryptBytes(info, buffer.b, bytesRead);333334// if we're on a big endian machine, swap the byte order335// this is done AFTER reading & decrypting since they expect little endian order on all systems336if (CheckBigEndian()) {337uint8 bytes[sizeof(buffer)];338memcpy(bytes, &buffer, sizeof(buffer));339340int32 max = sizeof(buffer) - 1;341for (int32 i = 0; i < sizeof(buffer) / 2; ++i) {342uint8 store = bytes[i];343bytes[i] = bytes[max - i];344bytes[max - i] = store;345}346memcpy(&buffer, bytes, sizeof(buffer));347}348349info->readPos += (int32)bytesRead;350return buffer.result;351}352353inline float ReadSingle(FileInfo *info)354{355union {356float result;357uint8 b[sizeof(result)];358} buffer;359memset(&buffer, 0, sizeof(buffer));360361size_t bytesRead = 0;362363if (info->usingFileBuffer) {364bytesRead = MIN(sizeof(buffer), info->fileSize - info->readPos);365if (bytesRead >= sizeof(buffer)) {366memcpy(buffer.b, info->fileBuffer, sizeof(buffer));367368info->fileBuffer += sizeof(buffer);369}370}371else {372bytesRead = fRead(buffer.b, 1, sizeof(float), info->file);373}374375if (info->encrypted)376DecryptBytes(info, buffer.b, bytesRead);377378// if we're on a big endian machine, swap the byte order379// this is done AFTER reading & decrypting since they expect little endian order on all systems380if (CheckBigEndian()) {381uint8 bytes[sizeof(buffer)];382memcpy(bytes, &buffer, sizeof(buffer));383384int32 max = sizeof(buffer) - 1;385for (int32 i = 0; i < sizeof(buffer) / 2; ++i) {386uint8 store = bytes[i];387bytes[i] = bytes[max - i];388bytes[max - i] = store;389}390memcpy(&buffer, bytes, sizeof(buffer));391}392393info->readPos += (int32)bytesRead;394return buffer.result;395}396397inline void ReadString(FileInfo *info, char *buffer)398{399uint8 size = ReadInt8(info);400ReadBytes(info, buffer, size);401buffer[size] = 0;402}403404inline int32 Uncompress(uint8 **cBuffer, int32 cSize, uint8 **buffer, int32 size)405{406if (!buffer || !cBuffer)407return 0;408409uLongf cLen = cSize;410uLongf destLen = size;411412int32 result = uncompress(*buffer, &destLen, *cBuffer, cLen);413(void)result;414415return (int32)destLen;416}417418// The buffer passed in parameter is allocated here, so it's up to the caller to free it once it goes unused419inline int32 ReadCompressed(FileInfo *info, uint8 **buffer)420{421if (!buffer)422return 0;423424uint32 cSize = ReadInt32(info, false) - 4;425uint32 sizeBE = ReadInt32(info, false);426427uint32 sizeLE = (uint32)((sizeBE << 24) | ((sizeBE << 8) & 0x00FF0000) | ((sizeBE >> 8) & 0x0000FF00) | (sizeBE >> 24));428AllocateStorage((void **)buffer, sizeLE, DATASET_TMP, false);429430uint8 *cBuffer = NULL;431AllocateStorage((void **)&cBuffer, cSize, DATASET_TMP, false);432ReadBytes(info, cBuffer, cSize);433434uint32 newSize = Uncompress(&cBuffer, cSize, buffer, sizeLE);435RemoveStorageEntry((void **)&cBuffer);436437return newSize;438}439440inline void ClearDataFiles()441{442// Unload file list443for (int32 f = 0; f < DATAFILE_COUNT; ++f) {444HASH_CLEAR_MD5(dataFileList[f].hash);445}446}447448} // namespace RSDK449450#endif451452453