summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS3
-rw-r--r--src/g_game.c30
-rw-r--r--src/p_saveg.c27
-rw-r--r--src/p_saveg.h4
4 files changed, 54 insertions, 10 deletions
diff --git a/NEWS b/NEWS
index 805fee13..a9a9a5c7 100644
--- a/NEWS
+++ b/NEWS
@@ -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);