From 2f45ee419ac521a4e9d04dd262aa5032aca98005 Mon Sep 17 00:00:00 2001 From: Josh Pearson Date: Tue, 25 Feb 2025 13:36:26 -0700 Subject: [PATCH] Game Save + Load From VMU --- miami/save/GenericGameStorage.cpp | 39 ++++++------- miami/save/PCSave.cpp | 95 +++++++++++++++++++++++++++---- miami/save/PCSave.h | 1 + 3 files changed, 106 insertions(+), 29 deletions(-) diff --git a/miami/save/GenericGameStorage.cpp b/miami/save/GenericGameStorage.cpp index b68b805a..75dd7a40 100644 --- a/miami/save/GenericGameStorage.cpp +++ b/miami/save/GenericGameStorage.cpp @@ -41,6 +41,8 @@ #include "Timecycle.h" #include "Fluff.h" +#include "../vmu/vmu.h" + #define BLOCK_COUNT 22 #define SIZE_OF_SIMPLEVARS 0xE4 @@ -94,11 +96,10 @@ PopulateRadioStationPositionList() #define LoadSaveDataBlock()\ do {\ - if (!ReadDataFromFile(file, (uint8 *) &size, 4))\ - return false;\ - size = align4bytes(size);\ - if (!ReadDataFromFile(file, work_buff, size))\ - return false;\ + size = C_PcSave::PcClassLoadRoutine(file, work_buff); \ + if (!size) {\ + return false; \ + } \ buf = work_buff;\ } while (0) @@ -285,6 +286,7 @@ GenericSave(int file) bool GenericLoad() { + printf("GenericLoad\n"); uint8 *buf; int32 file; uint32 size; @@ -299,12 +301,14 @@ GenericLoad() CheckSum = 0; CDate dummy; // unused CPad::ResetCheats(); - if (!ReadInSizeofSaveFileBuffer(file, size)) - return false; - size = align4bytes(size); - ReadDataFromFile(file, work_buff, size); + + file = CFileMgr::OpenFile(LoadFileName, "rb"); + assert(file != 0); + size = C_PcSave::PcClassLoadRoutine(file, work_buff); + assert(size != 0); buf = (work_buff + 0x40); ReadDataFromBufferPointer(buf, saveSize); + #ifdef MISSION_REPLAY // a hack to keep compatibility but get new data from save qs = saveSize >> 24; #endif @@ -562,13 +566,8 @@ CheckDataNotCorrupt(int32 slot, char *name) strcpy(name, filename); while (SIZE_OF_ONE_GAME_IN_BYTES - sizeof(uint32) > bytes_processed && blocknum < 40) { int32 blocksize; - if (!ReadDataFromFile(file, (uint8*)&blocksize, sizeof(blocksize))) { - CloseFile(file); - return false; - } - if (blocksize > align4bytes(sizeof(work_buff))) - blocksize = sizeof(work_buff) - sizeof(uint32); - if (!ReadDataFromFile(file, work_buff, align4bytes(blocksize))) { + blocksize = C_PcSave::PcClassLoadRoutine(file, work_buff); + if (blocksize == 0) { CloseFile(file); return false; } @@ -606,14 +605,16 @@ CheckDataNotCorrupt(int32 slot, char *name) bool RestoreForStartLoad() { - uint8 buf[999]; - int file = CFileMgr::OpenFile(LoadFileName, "rb"); if (file == 0) { PcSaveHelper.nErrorCode = SAVESTATUS_ERR_LOAD_OPEN; return false; } - ReadDataFromFile(file, buf, sizeof(buf)); + + uint32_t size = C_PcSave::PcClassLoadRoutine(file, work_buff); + assert(size != 0); + uint8 *buf = work_buff; + if (CFileMgr::GetErrorReadWrite(file)) { PcSaveHelper.nErrorCode = SAVESTATUS_ERR_LOAD_READ; if (!CloseFile(file)) diff --git a/miami/save/PCSave.cpp b/miami/save/PCSave.cpp index a33e9d90..b2f66bcb 100644 --- a/miami/save/PCSave.cpp +++ b/miami/save/PCSave.cpp @@ -12,6 +12,11 @@ #include "PCSave.h" #include "Text.h" +#include "minilzo.h" +#include "main.h" + +#include "../vmu/vmu.h" + const char* _psGetUserFilesFolder(); C_PcSave PcSaveHelper; @@ -19,7 +24,11 @@ C_PcSave PcSaveHelper; void C_PcSave::SetSaveDirectory(const char *path) { + #if defined(RW_DC) + sprintf(DefaultPCSaveFileName, "%s/%s", path, "GTAVCsf"); + #else sprintf(DefaultPCSaveFileName, "%s\\%s", path, "GTAVCsf"); + #endif } bool @@ -65,14 +74,39 @@ C_PcSave::SaveSlot(int32 slot) bool C_PcSave::PcClassSaveRoutine(int32 file, uint8 *data, uint32 size) { - CFileMgr::Write(file, (const char*)&size, sizeof(size)); - if (CFileMgr::GetErrorReadWrite(file)) { - nErrorCode = SAVESTATUS_ERR_SAVE_WRITE; - strncpy(SaveFileNameJustSaved, ValidSaveName, sizeof(ValidSaveName) - 1); + void* wrkmem = malloc(LZO1X_1_MEM_COMPRESS); + uint8* compressed = (uint8*)malloc(size*2); + lzo_uint compressed_size; + int crv = lzo1x_1_compress(data, size, compressed, &compressed_size, wrkmem); + free(wrkmem); + + if (crv == LZO_E_OK) { + uint32_t compressed_size32 = compressed_size | 0x80000000; + CFileMgr::Write(file, (const char*)&compressed_size32, sizeof(compressed_size32)); + if (CFileMgr::GetErrorReadWrite(file)) { + free(compressed); + nErrorCode = SAVESTATUS_ERR_SAVE_WRITE; + strncpy(SaveFileNameJustSaved, ValidSaveName, sizeof(ValidSaveName) - 1); + return false; + } + + CFileMgr::Write(file, (const char*)compressed, compressed_size); + free(compressed); + } else if (crv == LZO_E_NOT_COMPRESSIBLE) { + free(compressed); + uint32_t compressed_size32 = size; + CFileMgr::Write(file, (const char*)&compressed_size32, sizeof(compressed_size32)); + if (CFileMgr::GetErrorReadWrite(file)) { + nErrorCode = SAVESTATUS_ERR_SAVE_WRITE; + strncpy(SaveFileNameJustSaved, ValidSaveName, sizeof(ValidSaveName) - 1); + return false; + } + CFileMgr::Write(file, (const char*)data, align4bytes(size)); + } else { + free(compressed); return false; } - CFileMgr::Write(file, (const char*)data, align4bytes(size)); CheckSum += (uint8) size; CheckSum += (uint8) (size >> 8); CheckSum += (uint8) (size >> 16); @@ -89,6 +123,44 @@ C_PcSave::PcClassSaveRoutine(int32 file, uint8 *data, uint32 size) return true; } +uint32_t C_PcSave::PcClassLoadRoutine(int32 file, uint8 *data) { + uint32 size; + CFileMgr::Read(file, (char*)&size, sizeof(size)); + + + assert(data == work_buff); + + if (!(size & 0x80000000)) { + assert(align4bytes(size) == size); + CFileMgr::Read(file, (char*)data, align4bytes(size)); + if (CFileMgr::GetErrorReadWrite(file)) { + return 0; + } + return size; + } else { + size &= ~0x80000000; + uint8* compressed = (uint8*)malloc(size); + CFileMgr::Read(file, (const char*)compressed, size); + if (CFileMgr::GetErrorReadWrite(file)) { + free(compressed); + return 0; + } + + lzo_uint decompressed_size = 0; + auto crv = lzo1x_decompress(compressed, size, data, &decompressed_size, NULL); + free(compressed); + if (crv != LZO_E_OK) { + return 0; + } + + if (align4bytes(decompressed_size) != decompressed_size) { + return 0; + } + + return decompressed_size; + } +} + void C_PcSave::PopulateSlotInfo() { @@ -103,16 +175,16 @@ C_PcSave::PopulateSlotInfo() #else char savename[52]; #endif - struct { - int size; + struct header_t { wchar FileName[24]; SYSTEMTIME SaveDateTime; } header; sprintf(savename, "%s%i%s", DefaultPCSaveFileName, i + 1, ".b"); int file = CFileMgr::OpenFile(savename, "rb"); if (file != 0) { - CFileMgr::Read(file, (char*)&header, sizeof(header)); - if (strncmp((char*)&header, TopLineEmptyFile, sizeof(TopLineEmptyFile)-1) != 0) { + if (C_PcSave::PcClassLoadRoutine(file, (uint8*)work_buff)) { + header = *(header_t*)work_buff; + Slots[i] = SLOT_OK; memcpy(SlotFileName[i], &header.FileName, sizeof(header.FileName)); @@ -120,6 +192,9 @@ C_PcSave::PopulateSlotInfo() } CFileMgr::CloseFile(file); } +#if defined(RW_DC) + return; +#endif if (Slots[i] == SLOT_OK) { if (CheckDataNotCorrupt(i, savename)) { #ifdef FIX_INCOMPATIBLE_SAVES @@ -163,4 +238,4 @@ C_PcSave::PopulateSlotInfo() } } } -} +} \ No newline at end of file diff --git a/miami/save/PCSave.h b/miami/save/PCSave.h index 2a29fa95..2205105b 100644 --- a/miami/save/PCSave.h +++ b/miami/save/PCSave.h @@ -34,6 +34,7 @@ public: bool DeleteSlot(int32 slot); int8 SaveSlot(int32 slot); bool PcClassSaveRoutine(int32 file, uint8 *data, uint32 size); + static uint32_t PcClassLoadRoutine(int32 file, uint8 *data); static void SetSaveDirectory(const char *path); };