From eae34aabe69c2c6bb9f6713f9c008f0619fa48a3 Mon Sep 17 00:00:00 2001 From: EmeraldLockdown <86802223+EmeraldLoc@users.noreply.github.com> Date: Tue, 17 Mar 2026 12:06:46 -0500 Subject: [PATCH] Transfer old save names to new format --- autogen/convert_functions.py | 2 +- src/game/save_file.c | 58 ++++++++++++++++++++++++++++-- src/game/save_file.h | 4 +++ src/pc/configfile.c | 35 +++++++++++++++++- src/pc/configfile.h | 3 ++ src/pc/djui/djui_panel_host_save.c | 28 +-------------- src/pc/ultra_reimplementation.c | 1 + 7 files changed, 99 insertions(+), 32 deletions(-) diff --git a/autogen/convert_functions.py b/autogen/convert_functions.py index f9cfedb77..98a3c376e 100644 --- a/autogen/convert_functions.py +++ b/autogen/convert_functions.py @@ -119,7 +119,7 @@ override_disallowed_functions = { "src/pc/djui/djui_console.h": [ " djui_console_create", "djui_console_message_create", "djui_console_message_dequeue" ], "src/pc/djui/djui_chat_message.h": [ "create_from" ], "src/game/interaction.h": [ "process_interaction", "_handle_" ], - "src/game/save_file.h": [ "save_file_get_all_filenames", "save_file_get_dir", "save_file_get_first_available_index", "save_file_get_amount_of_available_indexes", "save_file_get_first_active_index" ], + "src/game/save_file.h": [ "save_file_get_all_filenames", "save_file_get_dir", "save_file_get_first_available_index", "save_file_get_amount_of_available_indexes", "save_file_get_first_active_index", "save_file_rename_file" ], "src/game/sound_init.h": [ "_loop_", "thread4_", "set_sound_mode" ], "src/pc/network/network_utils.h": [ "network_get_player_text_color[^_]" ], "src/pc/network/network_player.h": [ "_init", "_connected[^_]", "_shutdown", "_disconnected", "_update", "construct_player_popup", "network_player_name_valid" ], diff --git a/src/game/save_file.c b/src/game/save_file.c index a705f42fe..22a21efe7 100644 --- a/src/game/save_file.c +++ b/src/game/save_file.c @@ -277,9 +277,10 @@ static void save_file_bswap(struct SaveBuffer *buf) { static void save_file_convert_old_to_new() { struct LegacySaveBuffer saveBuffer = { 0 }; s32 status = osEepromLongRead(&gSIEventMesgQueue, 0, (void*)&saveBuffer, sizeof(saveBuffer), (char*)fs_get_write_path(SAVE_FILENAME), 512); - if (status == 0) { - for (int i = 0; i < 4; i++) - write_eeprom_data(i, saveBuffer.files[i], sizeof(saveBuffer.files[i]), 0); + if (status != 0) return; + for (int i = 0; i < 4; i++) { + write_eeprom_data(i, saveBuffer.files[i], sizeof(saveBuffer.files[i]), 0); + save_file_rename_file(i, configSaveNames[i]); } } @@ -385,6 +386,45 @@ s32 save_file_get_amount_of_available_indexes() { return count; } +/** + * Renames a specific save file. Returns false on failure +*/ +bool save_file_rename_file(s32 fileIndex, char* name) { + if (!fs_sys_dir_exists(fs_get_write_path(SAVE_DIRECTORY))) return false; + if (strstr(name, ".")) return false; + + char filePath[SYS_MAX_PATH]; + save_file_get_dir(fileIndex, filePath, 256, NULL); + char newFilePath[SYS_MAX_PATH]; + save_file_get_dir(fileIndex, newFilePath, 256, name); + + if (strcmp(filePath, newFilePath) == 0) return false; + if (!fs_sys_file_exists(fs_get_write_path(filePath))) return false; + + // write the save data of the file to a variable + u8 content[EEPROM_SIZE] = { 0 }; + fs_file_t* oldFile = fs_open(filePath); + if (oldFile == NULL) return false; + fs_read(oldFile, content, EEPROM_SIZE); + fs_close(oldFile); + + // create a new file with the data + FILE* fp = fopen(fs_get_write_path(newFilePath), "wb"); + if (fp == NULL) return false; + bool success = fwrite(content, 1, EEPROM_SIZE, fp) == EEPROM_SIZE; + fclose(fp); + if (success) { + // nuke old file! + remove(fs_get_write_path(filePath)); + } else { + // uh oh! new file failed to be written to :( nuke new file!! + remove(fs_get_write_path(newFilePath)); + } +} + +/** + * Saves file data to the disk +*/ void save_file_do_save(s32 fileIndex, s8 forceSave) { if (INVALID_FILE_INDEX(fileIndex)) { return; } if (gNetworkType != NT_SERVER) { @@ -411,6 +451,9 @@ void save_file_do_save(s32 fileIndex, s8 forceSave) { } } +/** + * Erases save file ingame and from the disk +*/ void save_file_erase(s32 fileIndex) { if (INVALID_FILE_INDEX(fileIndex)) { return; } @@ -424,6 +467,9 @@ void save_file_erase(s32 fileIndex) { remove(fs_get_write_path(filepath)); } +/** + * Reloads save file from the disk and updates mario's stars +*/ void save_file_reload(u8 loadAll) { gSaveFileModified = TRUE; update_all_mario_stars(); @@ -435,6 +481,9 @@ void save_file_reload(u8 loadAll) { } } +/** + * Erases the current backup save +*/ void save_file_erase_current_backup_save(void) { if (INVALID_FILE_INDEX(gCurrSaveFileNum-1)) { return; } if (gNetworkType != NT_SERVER) { return; } @@ -458,6 +507,9 @@ BAD_RETURN(s32) save_file_copy(s32 srcFileIndex, s32 destFileIndex) { save_file_do_save(destFileIndex, TRUE); } +/** + * Loads save file data from disk +*/ void save_file_load_all(UNUSED u8 reload) { //s32 file; diff --git a/src/game/save_file.h b/src/game/save_file.h index 0e89c5854..8e89f4371 100644 --- a/src/game/save_file.h +++ b/src/game/save_file.h @@ -139,6 +139,8 @@ struct WarpCheckpoint { /*0x04*/ u8 warpNode; }; +struct WarpNode; + extern struct WarpCheckpoint gWarpCheckpoint; extern s8 gMainMenuDataModified; @@ -165,6 +167,8 @@ s32 save_file_get_amount_of_available_indexes(); s32 save_file_get_first_active_index(); +bool save_file_rename_file(s32 fileIndex, char* name); + /* |description| Saves the current state of the game into a specified save file. Includes data verification and backup management. Useful for maintaining game progress during play or when saving manually diff --git a/src/pc/configfile.c b/src/pc/configfile.c index 85c11010b..dada22dae 100644 --- a/src/pc/configfile.c +++ b/src/pc/configfile.c @@ -21,7 +21,6 @@ #include "djui/djui_hud_utils.h" #include "pc/network/network_player.h" #include "pc/pc_main.h" -#include "game/save_file.h" #define ARRAY_LEN(arr) (sizeof(arr) / sizeof(arr[0])) @@ -59,6 +58,14 @@ struct FunctionConfigOption { *Config options and default values */ +// still exists for compatibility reasons +char configSaveNames[4][MAX_SAVE_NAME_STRING] = { + "SM64", + "SM64", + "SM64", + "SM64" +}; + // Video/audio stuff ConfigWindow configWindow = { .x = WAPI_WIN_CENTERPOS, @@ -522,11 +529,37 @@ static void dynos_pack_write(FILE* file) { } } +static void save_name_read(char** tokens, int numTokens) { + if (numTokens < 2) { return; } + char fullSaveName[MAX_SAVE_NAME_STRING] = { 0 }; + int index = 0; + for (int i = 1; i < numTokens; i++) { + if (i == 1) { + index = atoi(tokens[i]); + } else { + if (i > 2) { + strncat(fullSaveName, " ", MAX_SAVE_NAME_STRING - 1); + } + strncat(fullSaveName, tokens[i], MAX_SAVE_NAME_STRING - 1); + } + + } + snprintf(configSaveNames[index], MAX_SAVE_NAME_STRING, "%s", fullSaveName); +} + +static void save_name_write(FILE* file) { + // don't write save name data anymore, this only exists for compat + /*for (int i = 0; i < 4; i++) { + fprintf(file, "%s %d %s\n", "save-name:", i, configSaveNames[i]); + }*/ +} + static const struct FunctionConfigOption functionOptions[] = { { .name = "enable-mod:", .read = enable_mod_read, .write = enable_mod_write }, { .name = "ban:", .read = ban_read, .write = ban_write }, { .name = "moderator:", .read = moderator_read, .write = moderator_write }, { .name = "dynos-pack:", .read = dynos_pack_read, .write = dynos_pack_write }, + { .name = "save-name:", .read = save_name_read, .write = save_name_write } }; // Reads an entire line from a file (excluding the newline character) and returns an allocated string diff --git a/src/pc/configfile.h b/src/pc/configfile.h index c513b0d32..77c26fa13 100644 --- a/src/pc/configfile.h +++ b/src/pc/configfile.h @@ -6,6 +6,7 @@ #include "game/player_palette.h" #include "pc/lua/smlua_autogen.h" #include "game/area.h" +#include "game/save_file.h" #define CONFIGFILE_DEFAULT "sm64config.txt" #define CONFIGFILE_BACKUP "sm64config-backup.txt" @@ -44,6 +45,8 @@ enum RefreshRateMode { RRM_MAX }; +extern char configSaveNames[4][MAX_SAVE_NAME_STRING]; + // display settings extern ConfigWindow configWindow; extern ConfigStick configStick; diff --git a/src/pc/djui/djui_panel_host_save.c b/src/pc/djui/djui_panel_host_save.c index fdf0108db..3de76980e 100644 --- a/src/pc/djui/djui_panel_host_save.c +++ b/src/pc/djui/djui_panel_host_save.c @@ -26,33 +26,7 @@ static void djui_panel_host_reload_saves() { } static void djui_panel_host_save_update_save_name() { - if (!fs_sys_dir_exists(fs_get_write_path(SAVE_DIRECTORY))) return; - if (strstr(sSaveName, ".")) return; - char filePath[256]; - save_file_get_dir(sButtonTag, filePath, 256, NULL); - char newFilePath[256]; - save_file_get_dir(sButtonTag, newFilePath, 256, sSaveName); - if (strcmp(filePath, newFilePath) == 0) return; - if (!fs_sys_file_exists(fs_get_write_path(filePath))) return; - // write the save data of the file to a variable - u8 content[EEPROM_SIZE] = { 0 }; - fs_file_t* oldFile = fs_open(filePath); - if (oldFile == NULL) return; - fs_read(oldFile, content, EEPROM_SIZE); - fs_close(oldFile); - // create a new file with the data - FILE* fp = fopen(fs_get_write_path(newFilePath), "wb"); - if (fp == NULL) return; - bool success = fwrite(content, 1, EEPROM_SIZE, fp) == EEPROM_SIZE; - fclose(fp); - if (success) { - // nuke old file - remove(fs_get_write_path(filePath)); - } else { - // uh oh! New file failed to be written to. Nuke new file - remove(fs_get_write_path(newFilePath)); - } - + save_file_rename_file(sButtonTag, sSaveName); djui_panel_host_reload_saves(); } diff --git a/src/pc/ultra_reimplementation.c b/src/pc/ultra_reimplementation.c index ec2e1963e..c74ae6d2d 100644 --- a/src/pc/ultra_reimplementation.c +++ b/src/pc/ultra_reimplementation.c @@ -4,6 +4,7 @@ #include "macros.h" #include "platform.h" #include "fs/fs.h" +#include "configfile.h" #include "game/save_file.h" u8* gOverrideEeprom[NUM_SAVE_FILES] = { NULL };