/** * Copyright (c) 2026 Dominic Masters * * This software is released under the MIT License. * https://opensource.org/licenses/MIT */ #include "save/save.h" #include "save/savejsonlinux.h" #include "util/string.h" #include "util/memory.h" #include #include errorret_t saveInitLinux(void) { stringCopy(SAVE.platform.savePath, SAVE_LINUX_PATH, SAVE_LINUX_PATH_MAX); if(mkdir(SAVE.platform.savePath, 0755) != 0 && errno != EEXIST) { errorThrow("Failed to create save directory: %s", SAVE.platform.savePath); } errorOk(); } errorret_t saveDisposeLinux(void) { errorOk(); } static void _saveSlotPathLinux( char_t *out, const size_t max, const uint8_t slot ) { snprintf( out, max, SAVE_LINUX_SLOT_FILE_FORMAT, SAVE.platform.savePath, (uint32_t)slot ); } static void _saveMetaPathLinux(char_t *out, const size_t max) { snprintf(out, max, SAVE_LINUX_META_FILE_FORMAT, SAVE.platform.savePath); } errorret_t saveSlotLoadLinux(const uint8_t slot, saveslot_t *out) { char_t path[SAVE_LINUX_PATH_MAX]; _saveSlotPathLinux(path, SAVE_LINUX_PATH_MAX, slot); yyjson_doc *doc; yyjson_val *root; bool_t found; errorret_t ret = saveJsonReaderOpenLinux(path, &doc, &root, &found); if(errorIsNotOk(ret)) { yyjson_doc_free(doc); errorChain(ret); } if(!found) errorOk(); memoryZero(out, sizeof(saveslot_t)); out->version = saveJsonReadUInt32Linux(root, "version", SAVE_SLOT_VERSION); saveJsonReadStringLinux( root, "playerName", out->playerName, SAVE_PLAYER_NAME_MAX, "" ); saveJsonReadBoolArrayLinux( root, "globalItemCollected", out->globalItemCollected, SAVE_GLOBAL_ITEM_COUNT_MAX ); saveJsonReadUInt8ArrayLinux( root, "storyFlags", out->storyFlags, SAVE_STORY_FLAG_COUNT_MAX ); out->exists = true; yyjson_doc_free(doc); errorOk(); } errorret_t saveSlotWriteLinux(const uint8_t slot, saveslot_t *slotData) { char_t path[SAVE_LINUX_PATH_MAX]; _saveSlotPathLinux(path, SAVE_LINUX_PATH_MAX, slot); slotData->version = SAVE_SLOT_VERSION; savejsonwriterlinux_t writer; errorChain(saveJsonWriterInitLinux(&writer)); saveJsonWriterAddUInt32Linux(&writer, "version", slotData->version); saveJsonWriterAddStringLinux(&writer, "playerName", slotData->playerName); saveJsonWriterAddBoolArrayLinux( &writer, "globalItemCollected", slotData->globalItemCollected, SAVE_GLOBAL_ITEM_COUNT_MAX ); saveJsonWriterAddUInt8ArrayLinux( &writer, "storyFlags", slotData->storyFlags, SAVE_STORY_FLAG_COUNT_MAX ); errorret_t ret = saveJsonWriterSaveLinux(&writer, path); saveJsonWriterDisposeLinux(&writer); errorChain(ret); slotData->exists = true; errorOk(); } errorret_t saveDeleteSlotLinux(const uint8_t slot) { char_t path[SAVE_LINUX_PATH_MAX]; _saveSlotPathLinux(path, SAVE_LINUX_PATH_MAX, slot); if(remove(path) != 0 && errno != ENOENT) { errorThrow("Failed to delete save slot %u: %s", (uint32_t)slot, path); } errorOk(); } errorret_t saveMetaLoadLinux(savemeta_t *out) { char_t path[SAVE_LINUX_PATH_MAX]; _saveMetaPathLinux(path, SAVE_LINUX_PATH_MAX); yyjson_doc *doc; yyjson_val *root; bool_t found; errorret_t ret = saveJsonReaderOpenLinux(path, &doc, &root, &found); if(errorIsNotOk(ret)) { yyjson_doc_free(doc); errorChain(ret); } if(!found) errorOk(); out->version = saveJsonReadUInt32Linux(root, "version", SAVE_META_VERSION); out->deadzone = saveJsonReadFloatLinux( root, "deadzone", SAVE_META_DEADZONE_DEFAULT ); out->exists = true; yyjson_doc_free(doc); errorOk(); } errorret_t saveMetaWriteLinux(savemeta_t *meta) { char_t path[SAVE_LINUX_PATH_MAX]; _saveMetaPathLinux(path, SAVE_LINUX_PATH_MAX); meta->version = SAVE_META_VERSION; savejsonwriterlinux_t writer; errorChain(saveJsonWriterInitLinux(&writer)); saveJsonWriterAddUInt32Linux(&writer, "version", meta->version); saveJsonWriterAddFloatLinux(&writer, "deadzone", meta->deadzone); errorret_t ret = saveJsonWriterSaveLinux(&writer, path); saveJsonWriterDisposeLinux(&writer); errorChain(ret); meta->exists = true; errorOk(); }