diff --git a/libultraship/libultraship/GlobalCtx2.cpp b/libultraship/libultraship/GlobalCtx2.cpp index dd8125bcc..4c3d27aaa 100644 --- a/libultraship/libultraship/GlobalCtx2.cpp +++ b/libultraship/libultraship/GlobalCtx2.cpp @@ -1,4 +1,5 @@ #include "GlobalCtx2.h" +#include #include #include #include "ResourceMgr.h" @@ -82,4 +83,56 @@ namespace Ship { std::cout << "Log initialization failed: " << ex.what() << std::endl; } } + + std::fstream GetSaveFile(std::shared_ptr config, std::ios_base::openmode additionalFlags = 0) { + std::string directory = (*config)["SAVE"]["Save File Directory"]; + std::string fileName = (*config)["SAVE"]["Save Filename"]; + + if (fileName.empty()) { + fileName = "oot_save.sav"; + (*config)["SAVE"]["Save Filename"] = fileName; + (*config).Save(); + } + std::filesystem::path saveFile = std::filesystem::path(directory) / std::filesystem::path(fileName); + + if (directory.length() && !std::filesystem::exists(directory)) { + std::filesystem::create_directories(directory); + } + + std::fstream retval = std::fstream(saveFile, std::fstream::binary | additionalFlags); + + return retval; + } + + void GlobalCtx2::CheckSaveFile(size_t sramSize) { + std::fstream saveFile = GetSaveFile(Config); + if (saveFile.fail()) { + saveFile = GetSaveFile(Config, std::fstream::app); + for (int i = 0; i < sramSize; ++i) { + saveFile.write("\0", 1); + } + } + saveFile.close(); + } + + void GlobalCtx2::WriteSaveFile(uintptr_t addr, void* dramAddr, size_t size) { + std::fstream saveFile = GetSaveFile(Config); + saveFile.seekp(addr); + saveFile.write((char*)dramAddr, size); + saveFile.close(); + } + + void GlobalCtx2::ReadSaveFile(uintptr_t addr, void* dramAddr, size_t size) { + std::fstream saveFile = GetSaveFile(Config); + + // If the file doesn't exist, initialize DRAM + if (saveFile.good()) { + saveFile.seekg(addr); + saveFile.read((char*)dramAddr, size); + } else { + memset(dramAddr, 0, size); + } + + saveFile.close(); + } } \ No newline at end of file diff --git a/libultraship/libultraship/GlobalCtx2.h b/libultraship/libultraship/GlobalCtx2.h index a10421ec0..9b93629f0 100644 --- a/libultraship/libultraship/GlobalCtx2.h +++ b/libultraship/libultraship/GlobalCtx2.h @@ -20,6 +20,10 @@ namespace Ship { std::shared_ptr GetLogger() { return Logger; } std::shared_ptr GetConfig() { return Config; } + void CheckSaveFile(size_t sramSize); + void WriteSaveFile(uintptr_t addr, void* dramAddr, size_t size); + void ReadSaveFile(uintptr_t addr, void* dramAddr, size_t size); + GlobalCtx2(const std::string& Name); ~GlobalCtx2(); diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 69121d7a0..92c24e72e 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -29,6 +29,7 @@ OTRGlobals* OTRGlobals::Instance; OTRGlobals::OTRGlobals() { context = Ship::GlobalCtx2::CreateInstance("Ship of Harkinian"); context->GetWindow()->Init(); + context->CheckSaveFile(SRAM_SIZE); } OTRGlobals::~OTRGlobals() { @@ -619,11 +620,18 @@ extern "C" s32* ResourceMgr_LoadCSByName(char* path) return (s32*)res->commands.data(); } +extern "C" void Ctx_ReadSaveFile(uintptr_t addr, void* dramAddr, size_t size) { + OTRGlobals::Instance->context->ReadSaveFile(addr, dramAddr, size); +} + +extern "C" void Ctx_WriteSaveFile(uintptr_t addr, void* dramAddr, size_t size) { + OTRGlobals::Instance->context->WriteSaveFile(addr, dramAddr, size); +} + /* Remember to free after use of value */ -extern "C" char* Config_getValue(char* category, char* key) -{ - std::shared_ptr pConf = OTRGlobals::Instance->context->GetConfig(); - Ship::ConfigFile& Conf = *pConf.get(); +extern "C" char* Config_getValue(char* category, char* key) { + std::shared_ptr pConf = OTRGlobals::Instance->context->GetConfig(); + Ship::ConfigFile& Conf = *pConf.get(); std::string data = Conf.get(std::string(category)).get(std::string(key)); char* retval = (char*)malloc(data.length()+1); @@ -632,10 +640,9 @@ extern "C" char* Config_getValue(char* category, char* key) return retval; } -extern "C" bool Config_setValue(char* category, char* key, char* value) -{ - std::shared_ptr pConf = OTRGlobals::Instance->context->GetConfig(); - Ship::ConfigFile& Conf = *pConf.get(); +extern "C" bool Config_setValue(char* category, char* key, char* value) { + std::shared_ptr pConf = OTRGlobals::Instance->context->GetConfig(); + Ship::ConfigFile& Conf = *pConf.get(); Conf[std::string(category)][std::string(key)] = std::string(value); return Conf.Save(); } diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index 8a51a7d78..ee8f128c6 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -40,6 +40,8 @@ Gfx* ResourceMgr_LoadGfxByName(char* path); Vtx* ResourceMgr_LoadVtxByCRC(uint64_t crc); Vtx* ResourceMgr_LoadVtxByName(char* path); CollisionHeader* ResourceMgr_LoadColByName(char* path); +void Ctx_ReadSaveFile(uintptr_t addr, void* dramAddr, size_t size); +void Ctx_WriteSaveFile(uintptr_t addr, void* dramAddr, size_t size); char* Config_getValue(char* category, char* key); bool Config_setValue(char* category, char* key, char* value); uint64_t GetPerfCounter(); diff --git a/soh/src/code/z_ss_sram.c b/soh/src/code/z_ss_sram.c index 6865f9ec6..8be84e07b 100644 --- a/soh/src/code/z_ss_sram.c +++ b/soh/src/code/z_ss_sram.c @@ -2,15 +2,7 @@ #include "global.h" #include -#include #include -#include - -#if defined(WIN32) -#define DIR_SEPARATOR '\\' -#else -#define DIR_SEPARATOR '/' -#endif #if 0 typedef struct { @@ -64,102 +56,17 @@ void SsSram_Dma(void* dramAddr, size_t size, s32 direction) { } #endif -//https://stackoverflow.com/a/15019112 -void combineDirectoryAndFileName(char* destination, char* directory, char* fileName) -{ - if(directory && *directory) { - int len = strlen(directory); - strcpy(destination, directory); - - if (destination[len - 1] == DIR_SEPARATOR) - { - if (fileName && *fileName) - { - strcpy(destination + len, (*fileName == DIR_SEPARATOR) ? (fileName + 1) : fileName); - } - } - else - { - if(fileName && *fileName) - { - if (*fileName == DIR_SEPARATOR) - { - strcpy(destination + len, fileName); - } - else - { - destination[len] = DIR_SEPARATOR; - strcpy(destination + len + 1, fileName); - } - } - } - } - else if(fileName && *fileName) - { - strcpy(destination, fileName); - } - else - { - destination[0] = '\0'; - } -} - void SsSram_ReadWrite(uintptr_t addr, void* dramAddr, size_t size, s32 direction) { osSyncPrintf("ssSRAMReadWrite:%08x %08x %08x %d\n", addr, (uintptr_t)dramAddr, size, direction); - char* directory = Config_getValue("SAVE", "Save File Directory"); - char* fileName = Config_getValue("SAVE", "Save Filename"); - - // This only happens if a user deletes the default filename and doesn't replace it - if(fileName[0] == '\0') - { - Config_setValue("SAVE", "Save Filename", "oot_save.sav"); - free(fileName); - fileName = malloc(sizeof("oot_save.sav")+1); - strcpy(fileName, "oot_save.sav"); - } - - char* file = malloc(strlen(directory) + strlen(fileName) + 2); - combineDirectoryAndFileName(file, directory, fileName); - - //Check to see if the file exists - FILE* saveFile; - saveFile = fopen(file, "rb"); - - if (saveFile == NULL) { - - saveFile = fopen(file, "wb"); - fseek(saveFile, 0, SEEK_SET); - assert(saveFile != NULL); // OTRTODO LOG - uint8_t zero = 0; - - for (uint32_t i = 0; i < SRAM_SIZE; i++) { - fwrite(&zero, 1, 1, saveFile); - } - fclose(saveFile); - } else { - fclose(saveFile); - } switch (direction) { case OS_WRITE: { - saveFile = fopen(file, "r+b"); - rewind(saveFile); - fseek(saveFile, addr, SEEK_SET); - fwrite(dramAddr, size, 1, saveFile); - fclose(saveFile); + Ctx_WriteSaveFile(addr, dramAddr, size); } break; case OS_READ: { - saveFile = fopen(file, "rb+"); - rewind(saveFile); - fseek(saveFile, addr, SEEK_SET); - fread(dramAddr, size, 1, saveFile); - fclose(saveFile); + Ctx_ReadSaveFile(addr, dramAddr, size); } break; } //SsSram_Init(addr, DEVICE_TYPE_SRAM, PI_DOMAIN2, 5, 0xD, 2, 0xC, 0); //SsSram_Dma(dramAddr, size, direction); - - free(file); - free(directory); - free(fileName); }