diff --git a/src/g_game.c b/src/g_game.c
index a927f8ef22747e36f47f6646875d8ecfcab70f07..c9b57004479014f852a911f30b09268514e4d7f9 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -3711,6 +3711,24 @@ static void G_UpdateVisited(void)
 	}
 }
 
+static boolean CanSaveLevel(INT32 mapnum)
+{
+	// You can never save in a special stage.
+	if (G_IsSpecialStage(mapnum))
+		return false;
+
+	// If the game is complete for this save slot, then any level can save!
+	if (gamecomplete)
+		return true;
+
+	// Be kind with Marathon Mode live event backups.
+	if (marathonmode)
+		return true;
+
+	// Any levels that have the savegame flag can save normally.
+	return (mapheaderinfo[mapnum-1] && (mapheaderinfo[mapnum-1]->levelflags & LF_SAVEGAME));
+}
+
 //
 // G_DoCompleted
 //
@@ -3755,64 +3773,64 @@ static void G_DoCompleted(void)
 			nextmap = 1100-1; // No infinite loop for you
 	}
 
-	// Remember last map for when you come out of the special stage.
-	if (!spec)
-		lastmap = nextmap;
-
 	// If nextmap is actually going to get used, make sure it points to
 	// a map of the proper gametype -- skip levels that don't support
 	// the current gametype. (Helps avoid playing boss levels in Race,
 	// for instance).
-	if (!token && !spec
-		&& (nextmap >= 0 && nextmap < NUMMAPS))
+	if (!spec)
 	{
-		register INT16 cm = nextmap;
-		UINT32 tolflag = G_TOLFlag(gametype);
-		UINT8 visitedmap[(NUMMAPS+7)/8];
-
-		memset(visitedmap, 0, sizeof (visitedmap));
-
-		while (!mapheaderinfo[cm] || !(mapheaderinfo[cm]->typeoflevel & tolflag))
+		if (nextmap >= 0 && nextmap < NUMMAPS)
 		{
-			visitedmap[cm/8] |= (1<<(cm&7));
-			if (!mapheaderinfo[cm])
-				cm = -1; // guarantee error execution
-			else if (marathonmode && mapheaderinfo[cm]->marathonnext)
-				cm = (INT16)(mapheaderinfo[cm]->marathonnext-1);
-			else
-				cm = (INT16)(mapheaderinfo[cm]->nextlevel-1);
+			register INT16 cm = nextmap;
+			UINT32 tolflag = G_TOLFlag(gametype);
+			UINT8 visitedmap[(NUMMAPS+7)/8];
 
-			if (cm >= NUMMAPS || cm < 0) // out of range (either 1100ish or error)
+			memset(visitedmap, 0, sizeof (visitedmap));
+
+			while (!mapheaderinfo[cm] || !(mapheaderinfo[cm]->typeoflevel & tolflag))
 			{
-				cm = nextmap; //Start the loop again so that the error checking below is executed.
+				visitedmap[cm/8] |= (1<<(cm&7));
+				if (!mapheaderinfo[cm])
+					cm = -1; // guarantee error execution
+				else if (marathonmode && mapheaderinfo[cm]->marathonnext)
+					cm = (INT16)(mapheaderinfo[cm]->marathonnext-1);
+				else
+					cm = (INT16)(mapheaderinfo[cm]->nextlevel-1);
 
-				//Make sure the map actually exists before you try to go to it!
-				if ((W_CheckNumForName(G_BuildMapName(cm + 1)) == LUMPERROR))
+				if (cm >= NUMMAPS || cm < 0) // out of range (either 1100ish or error)
 				{
-					CONS_Alert(CONS_ERROR, M_GetText("Next map given (MAP %d) doesn't exist! Reverting to MAP01.\n"), cm+1);
-					cm = 0;
-					break;
+					cm = nextmap; //Start the loop again so that the error checking below is executed.
+
+					//Make sure the map actually exists before you try to go to it!
+					if ((W_CheckNumForName(G_BuildMapName(cm + 1)) == LUMPERROR))
+					{
+						CONS_Alert(CONS_ERROR, M_GetText("Next map given (MAP %d) doesn't exist! Reverting to MAP01.\n"), cm+1);
+						cm = 0;
+						break;
+					}
 				}
-			}
 
-			if (visitedmap[cm/8] & (1<<(cm&7))) // smells familiar
-			{
-				// We got stuck in a loop, came back to the map we started on
-				// without finding one supporting the current gametype.
-				// Thus, print a warning, and just use this map anyways.
-				CONS_Alert(CONS_WARNING, M_GetText("Can't find a compatible map after map %d; using map %d anyway\n"), prevmap+1, cm+1);
-				break;
+				if (visitedmap[cm/8] & (1<<(cm&7))) // smells familiar
+				{
+					// We got stuck in a loop, came back to the map we started on
+					// without finding one supporting the current gametype.
+					// Thus, print a warning, and just use this map anyways.
+					CONS_Alert(CONS_WARNING, M_GetText("Can't find a compatible map after map %d; using map %d anyway\n"), prevmap+1, cm+1);
+					break;
+				}
 			}
+			nextmap = cm;
 		}
-		nextmap = cm;
-	}
 
-	if (nextmap < 0 || (nextmap >= NUMMAPS && nextmap < 1100-1) || nextmap > 1103-1)
-		I_Error("Followed map %d to invalid map %d\n", prevmap + 1, nextmap + 1);
+		// wrap around in race
+		if (nextmap >= 1100-1 && nextmap <= 1102-1 && !(gametyperules & GTR_CAMPAIGN))
+			nextmap = (INT16)(spstage_start-1);
+
+		if (nextmap < 0 || (nextmap >= NUMMAPS && nextmap < 1100-1) || nextmap > 1103-1)
+			I_Error("Followed map %d to invalid map %d\n", prevmap + 1, nextmap + 1);
 
-	// wrap around in race
-	if (nextmap >= 1100-1 && nextmap <= 1102-1 && !(gametyperules & GTR_CAMPAIGN))
-		nextmap = (INT16)(spstage_start-1);
+		lastmap = nextmap; // Remember last map for when you come out of the special stage.
+	}
 
 	if ((gottoken = ((gametyperules & GTR_SPECIALSTAGES) && token)))
 	{
@@ -3851,7 +3869,22 @@ static void G_DoCompleted(void)
 	if (nextmap < NUMMAPS && !mapheaderinfo[nextmap])
 		P_AllocMapHeader(nextmap);
 
-	// do this before going to the intermission or starting a custom cutscene, mostly for the sake of marathon mode but it also massively reduces redundant file save events in f_finale.c
+	// If the current gametype has no intermission screen set, then don't start it.
+	Y_DetermineIntermissionType();
+
+	if ((skipstats && !modeattacking) || (spec && modeattacking && stagefailed) || (intertype == int_none))
+	{
+		G_UpdateVisited();
+		G_AfterIntermission();
+	}
+	else
+	{
+		G_SetGamestate(GS_INTERMISSION);
+		Y_StartIntermission();
+		G_UpdateVisited();
+	}
+
+	// do this before running the intermission or custom cutscene, mostly for the sake of marathon mode but it also massively reduces redundant file save events in f_finale.c
 	if (nextmap >= 1100-1)
 	{
 		if (!gamecomplete)
@@ -3865,25 +3898,14 @@ static void G_DoCompleted(void)
 					remove(liveeventbackup);
 				cursaveslot = 0;
 			}
-			else if ((!modifiedgame || savemoddata) && !(netgame || multiplayer))
-				G_SaveGame((UINT32)cursaveslot);
+			else if ((!modifiedgame || savemoddata) && !(netgame || multiplayer || ultimatemode || demorecording || metalrecording || modeattacking))
+				G_SaveGame((UINT32)cursaveslot, spstage_start);
 		}
 	}
-
-	// If the current gametype has no intermission screen set, then don't start it.
-	Y_DetermineIntermissionType();
-
-	if ((skipstats && !modeattacking) || (spec && modeattacking && stagefailed) || (intertype == int_none))
-	{
-		G_UpdateVisited();
-		G_AfterIntermission();
-	}
-	else
-	{
-		G_SetGamestate(GS_INTERMISSION);
-		Y_StartIntermission();
-		G_UpdateVisited();
-	}
+	// and doing THIS here means you don't lose your progress if you close the game mid-intermission
+	else if (!(ultimatemode || netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking)
+		&& (!modifiedgame || savemoddata) && cursaveslot > 0 && CanSaveLevel(lastmap+1))
+		G_SaveGame((UINT32)cursaveslot, lastmap+1); // not nextmap+1 to route around special stages
 }
 
 // See also F_EndCutscene, the only other place which handles intra-map/ending transitions
@@ -3902,7 +3924,7 @@ void G_AfterIntermission(void)
 
 	HU_ClearCEcho();
 
-	if ((gametyperules & GTR_CUTSCENES) && mapheaderinfo[gamemap-1]->cutscenenum && !modeattacking && skipstats <= 1 && !(marathonmode & MA_NOCUTSCENES)) // Start a custom cutscene.
+	if ((gametyperules & GTR_CUTSCENES) && mapheaderinfo[gamemap-1]->cutscenenum && !modeattacking && skipstats <= 1 && (gamecomplete || !(marathonmode & MA_NOCUTSCENES))) // Start a custom cutscene.
 		F_StartCustomCutscene(mapheaderinfo[gamemap-1]->cutscenenum-1, false, false);
 	else
 	{
@@ -4445,7 +4467,7 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
 // G_SaveGame
 // Saves your game.
 //
-void G_SaveGame(UINT32 slot)
+void G_SaveGame(UINT32 slot, INT16 mapnum)
 {
 	boolean saved;
 	char savename[256] = "";
@@ -4473,7 +4495,7 @@ void G_SaveGame(UINT32 slot)
 		sprintf(name, (marathonmode ? "back-up %d" : "version %d"), VERSION);
 		WRITEMEM(save_p, name, VERSIONSIZE);
 
-		P_SaveGame();
+		P_SaveGame(mapnum);
 		if (marathonmode)
 		{
 			WRITEUINT32(save_p, marathontime);
diff --git a/src/g_game.h b/src/g_game.h
index fecfa4096fd37d331000ba734c70e8e47ddf5195..c8abe560c629a607f6e3d1f24895abfc3a281a64 100644
--- a/src/g_game.h
+++ b/src/g_game.h
@@ -166,7 +166,7 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride);
 
 void G_SaveGameData(void);
 
-void G_SaveGame(UINT32 slot);
+void G_SaveGame(UINT32 slot, INT16 mapnum);
 
 void G_SaveGameOver(UINT32 slot, boolean modifylives);
 
diff --git a/src/p_saveg.c b/src/p_saveg.c
index b4d7ef83872291f4bccf077a94c6acbb55ee2363..6f54467950d961df3a00f8ecef3454bf66234091 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -3785,16 +3785,15 @@ static void P_NetUnArchiveSpecials(void)
 // =======================================================================
 //          Misc
 // =======================================================================
-static inline void P_ArchiveMisc(void)
+static inline void P_ArchiveMisc(INT16 mapnum)
 {
-	if (gamecomplete)
-		WRITEINT16(save_p, gamemap | 8192);
-	else
-		WRITEINT16(save_p, gamemap);
+	//lastmapsaved = mapnum;
+	lastmaploaded = mapnum;
 
-	//lastmapsaved = gamemap;
-	lastmaploaded = gamemap;
+	if (gamecomplete)
+		mapnum |= 8192;
 
+	WRITEINT16(save_p, mapnum);
 	WRITEUINT16(save_p, emeralds+357);
 	WRITESTRINGN(save_p, timeattackfolder, sizeof(timeattackfolder));
 }
@@ -4035,9 +4034,9 @@ static inline boolean P_UnArchiveLuabanksAndConsistency(void)
 	return true;
 }
 
-void P_SaveGame(void)
+void P_SaveGame(INT16 mapnum)
 {
-	P_ArchiveMisc();
+	P_ArchiveMisc(mapnum);
 	P_ArchivePlayer();
 	P_ArchiveLuabanksAndConsistency();
 }
diff --git a/src/p_saveg.h b/src/p_saveg.h
index 012e7023b8021dd4d65d9fc359e826055a7bce59..d8756a7a9b955e4520e46849c3d76313329b1623 100644
--- a/src/p_saveg.h
+++ b/src/p_saveg.h
@@ -21,7 +21,7 @@
 // Persistent storage/archiving.
 // These are the load / save game routines.
 
-void P_SaveGame(void);
+void P_SaveGame(INT16 mapnum);
 void P_SaveNetGame(void);
 boolean P_LoadGame(INT16 mapoverride);
 boolean P_LoadNetGame(void);
diff --git a/src/p_setup.c b/src/p_setup.c
index 5027bab0c6cdb93bdd5d4381fec15d150e6bdc5f..f86de5ad4954ddbb9c76133596569b8d54cb4187 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -3297,21 +3297,6 @@ static void P_InitCamera(void)
 	}
 }
 
-static boolean CanSaveLevel(INT32 mapnum)
-{
-	if (ultimatemode) // never save in ultimate (probably redundant with cursaveslot also being checked)
-		return false;
-
-	if (G_IsSpecialStage(mapnum) // don't save in special stages
-		|| mapnum == lastmaploaded) // don't save if the last map loaded was this one
-		return false;
-
-	// Any levels that have the savegame flag can save normally.
-	// If the game is complete for this save slot, then any level can save!
-	// On the other side of the spectrum, if lastmaploaded is 0, then the save file has only just been created and needs to save ASAP!
-	return (mapheaderinfo[mapnum-1]->levelflags & LF_SAVEGAME || (gamecomplete != 0) || marathonmode || !lastmaploaded);
-}
-
 static void P_RunSpecialStageWipe(void)
 {
 	tic_t starttime = I_GetTime();
@@ -3748,11 +3733,19 @@ boolean P_LoadLevel(boolean fromnetsave)
 
 	P_RunCachedActions();
 
-	if (!(netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking || players[consoleplayer].lives <= 0)
-		&& (!modifiedgame || savemoddata) && cursaveslot > 0 && CanSaveLevel(gamemap))
-		G_SaveGame((UINT32)cursaveslot);
-
-	lastmaploaded = gamemap; // HAS to be set after saving!!
+	// Took me 3 hours to figure out why my progression kept on getting overwritten with the titlemap...
+	if (!titlemapinaction)
+	{
+		if (!lastmaploaded) // Start a new game?
+		{
+			// I'd love to do this in the menu code instead of here, but everything's a mess and I can't guarantee saving proper player struct info before the first act's started. You could probably refactor it, but it'd be a lot of effort. Easier to just work off known good code. ~toast 22/06/2020
+			if (!(ultimatemode || netgame || multiplayer || demoplayback || demorecording || metalrecording || modeattacking)
+			&& (!modifiedgame || savemoddata) && cursaveslot > 0)
+				G_SaveGame((UINT32)cursaveslot, gamemap);
+			// If you're looking for saving sp file progression (distinct from G_SaveGameOver), check G_DoCompleted.
+		}
+		lastmaploaded = gamemap; // HAS to be set after saving!!
+	}
 
 	if (!fromnetsave) // uglier hack
 	{ // to make a newly loaded level start on the second frame.