diff options
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | src/g_game.c | 30 | ||||
-rw-r--r-- | src/p_saveg.c | 27 | ||||
-rw-r--r-- | src/p_saveg.h | 4 |
4 files changed, 54 insertions, 10 deletions
@@ -32,6 +32,9 @@ * The default startup delay has been set to one second, to allow time for the screen to settle before starting the game (some monitors have a delay before they come back on after changing modes). + * If a savegame buffer overrun occurs, the savegame does not get saved + and existing savegames are not overwritten (same behaviour as + Vanilla). Bugs fixed: * Desync with STRAIN demos and dehacked Misc values not being set diff --git a/src/g_game.c b/src/g_game.c index c9e3879f..4f7a3d43 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1485,21 +1485,25 @@ G_SaveGame void G_DoSaveGame (void) { - char name[100]; - char* description; - - strcpy(name, P_SaveGameFile(savegameslot)); + char *savegame_file; + char *temp_savegame_file; - description = savedescription; - - save_stream = fopen(name, "wb"); + temp_savegame_file = P_TempSaveGameFile(); + savegame_file = P_SaveGameFile(savegameslot); + + // Open the savegame file for writing. We write to a temporary file + // and then rename it at the end if it was successfully written. + // This prevents an existing savegame from being overwritten by + // a corrupted one, or if a savegame buffer overrun occurs. + + save_stream = fopen(temp_savegame_file, "wb"); if (save_stream == NULL) { return; } - P_WriteSaveGameHeader(description); + P_WriteSaveGameHeader(savedescription); P_ArchivePlayers (); P_ArchiveWorld (); @@ -1516,11 +1520,19 @@ void G_DoSaveGame (void) I_Error ("Savegame buffer overrun"); } + // Finish up, close the savegame file. + fclose(save_stream); + // Now rename the temporary savegame file to the actual savegame + // file, overwriting the old savegame if there was one there. + + remove(savegame_file); + rename(temp_savegame_file, savegame_file); + gameaction = ga_nothing; strcpy(savedescription, ""); - + players[consoleplayer].message = DEH_String(GGSAVED); // draw the pattern into the back screen diff --git a/src/p_saveg.c b/src/p_saveg.c index afd3852d..40b5f988 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -44,11 +44,36 @@ FILE *save_stream; int savegamelength; +// Get the filename of a temporary file to write the savegame to. After +// the file has been successfully saved, it will be renamed to the +// real file. + +char *P_TempSaveGameFile(void) +{ + static char *filename = NULL; + + if (filename == NULL) + { + filename = malloc(strlen(savegamedir) + 32); + } + + sprintf(filename, "%stemp.dsg", savegamedir); + + return filename; +} + +// Get the filename of the save game file to use for the specified slot. + char *P_SaveGameFile(int slot) { - static char filename[256]; + static char *filename = NULL; char basename[32]; + if (filename == NULL) + { + filename = malloc(strlen(savegamedir) + 32); + } + sprintf(basename, DEH_String(SAVEGAMENAME "%d.dsg"), slot); sprintf(filename, "%s%s", savegamedir, basename); diff --git a/src/p_saveg.h b/src/p_saveg.h index 6f95585e..3a96cc3e 100644 --- a/src/p_saveg.h +++ b/src/p_saveg.h @@ -34,6 +34,10 @@ #define SAVESTRINGSIZE 24 +// temporary filename to use while saving. + +char *P_TempSaveGameFile(void); + // filename to use for a savegame slot char *P_SaveGameFile(int slot); |