7357b4a5df
Replaces the last hardcoded English strings (initial-scene modals, game menu save status messages) with locale-loaded text, adds a shared LOCALE_LIST so the settings dropdown and locale manager stay in sync, and persists the chosen language into savemeta_t across all platforms. Also fixes two message buffers that were too small for their longest translations. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
151 lines
4.2 KiB
C
151 lines
4.2 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 "save/savejsonlinux.h"
|
|
#include "util/string.h"
|
|
#include "util/memory.h"
|
|
#include <sys/stat.h>
|
|
#include <errno.h>
|
|
|
|
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->language = saveJsonReadUInt8Linux(
|
|
root, "language", SAVE_META_LANGUAGE_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);
|
|
saveJsonWriterAddUInt8Linux(&writer, "language", meta->language);
|
|
|
|
errorret_t ret = saveJsonWriterSaveLinux(&writer, path);
|
|
saveJsonWriterDisposeLinux(&writer);
|
|
errorChain(ret);
|
|
|
|
meta->exists = true;
|
|
errorOk();
|
|
}
|