146 lines
3.5 KiB
C
146 lines
3.5 KiB
C
/**
|
|
* 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();
|
|
}
|