/** * Copyright (c) 2026 Dominic Masters * * This software is released under the MIT License. * https://opensource.org/licenses/MIT */ #include "save/save.h" #include "util/memory.h" #include "util/string.h" static void _saveGetFileName( const uint8_t slot, char_t *out, const size_t max ) { snprintf(out, max, "%s_%u", SAVE_DOLPHIN_GAME_CODE, (uint32_t)slot); } errorret_t saveInitDolphin(void) { SAVE.platform.mounted = false; int32_t result = CARD_Mount( SAVE_DOLPHIN_CHANNEL, SAVE.platform.cardBuffer, NULL ); if(result < 0) { errorThrow("Failed to mount memory card (error %d)", result); } SAVE.platform.mounted = true; errorOk(); } errorret_t saveDisposeDolphin(void) { if(SAVE.platform.mounted) { CARD_Unmount(SAVE_DOLPHIN_CHANNEL); SAVE.platform.mounted = false; } errorOk(); } errorret_t saveLoadDolphin(const uint8_t slot, savefile_t *file) { char_t fileName[SAVE_DOLPHIN_FILE_NAME_MAX]; _saveGetFileName(slot, fileName, SAVE_DOLPHIN_FILE_NAME_MAX); int32_t result = CARD_Open( SAVE_DOLPHIN_CHANNEL, fileName, &SAVE.platform.cardFile ); if(result == CARD_ERROR_NOFILE) { file->exists = false; errorOk(); } if(result < 0) { file->exists = false; errorThrow("Failed to open memory card file for slot %u (error %d)", (uint32_t)slot, result ); } void *buffer = memoryAlign(32, SAVE_DOLPHIN_SECTOR_SIZE); if(!buffer) { CARD_Close(&SAVE.platform.cardFile); errorThrow("Failed to allocate memory card read buffer"); } result = CARD_Read( &SAVE.platform.cardFile, buffer, SAVE_DOLPHIN_SECTOR_SIZE, 0 ); CARD_Close(&SAVE.platform.cardFile); if(result < 0) { memoryFree(buffer); file->exists = false; errorThrow("Failed to read memory card data for slot %u (error %d)", (uint32_t)slot, result ); } memoryCopy(file, buffer, sizeof(savefile_t)); memoryFree(buffer); file->exists = true; errorOk(); } errorret_t saveWriteDolphin(const uint8_t slot, const savefile_t *file) { char_t fileName[SAVE_DOLPHIN_FILE_NAME_MAX]; _saveGetFileName(slot, fileName, SAVE_DOLPHIN_FILE_NAME_MAX); void *buffer = memoryAlign(32, SAVE_DOLPHIN_SECTOR_SIZE); if(!buffer) { errorThrow("Failed to allocate memory card write buffer"); } memoryZero(buffer, SAVE_DOLPHIN_SECTOR_SIZE); memoryCopy(buffer, file, sizeof(savefile_t)); // Try open existing file first; create if absent. int32_t result = CARD_Open( SAVE_DOLPHIN_CHANNEL, fileName, &SAVE.platform.cardFile ); if(result == CARD_ERROR_NOFILE) { result = CARD_Create( SAVE_DOLPHIN_CHANNEL, fileName, SAVE_DOLPHIN_SECTOR_SIZE, &SAVE.platform.cardFile ); } if(result < 0) { memoryFree(buffer); errorThrow("Failed to open/create memory card file for slot %u (error %d)", (uint32_t)slot, result ); } result = CARD_Write( &SAVE.platform.cardFile, buffer, SAVE_DOLPHIN_SECTOR_SIZE, 0 ); CARD_Close(&SAVE.platform.cardFile); memoryFree(buffer); if(result < 0) { errorThrow("Failed to write memory card data for slot %u (error %d)", (uint32_t)slot, result ); } errorOk(); } errorret_t saveDeleteDolphin(const uint8_t slot) { char_t fileName[SAVE_DOLPHIN_FILE_NAME_MAX]; _saveGetFileName(slot, fileName, SAVE_DOLPHIN_FILE_NAME_MAX); int32_t result = CARD_Delete(SAVE_DOLPHIN_CHANNEL, fileName); if(result < 0 && result != CARD_ERROR_NOFILE) { errorThrow("Failed to delete memory card file for slot %u (error %d)", (uint32_t)slot, result ); } errorOk(); }