diff --git a/src/d_main.c b/src/d_main.c
index d75a4d5013d9a92e7abccad7211721b3fa1f00b5..23ccd71f289cca1f5e75c1d3be5cd3817fc365c9 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -132,8 +132,8 @@ INT32 debugload = 0;
 UINT16 numskincolors;
 menucolor_t *menucolorhead, *menucolortail;
 
-char savegamename[256];
-char liveeventbackup[256];
+char savegamename[512];
+char liveeventbackup[512];
 
 char srb2home[256] = ".";
 char srb2path[256] = ".";
@@ -1304,9 +1304,10 @@ void D_SRB2Main(void)
 		CONS_Printf(M_GetText("Development mode ON.\n"));
 
 	// default savegame
-	strcpy(savegamename, SAVEGAMENAME"%u.ssg");
-	strcpy(liveeventbackup, "live"SAVEGAMENAME".bkp"); // intentionally not ending with .ssg
-
+	if(M_CheckParm("-savedir") && M_IsNextParm())
+	{
+		snprintf(savefolder, sizeof(savefolder) - 1, "%s/", M_GetNextParm());
+	}
 	{
 		const char *userhome = D_Home(); //Alam: path to home
 
@@ -1333,7 +1334,6 @@ void D_SRB2Main(void)
 				snprintf(configfile, sizeof configfile, "%s" PATHSEP CONFIGFILENAME, srb2home);
 
 			// can't use sprintf since there is %u in savegamename
-			strcatbf(savegamename, srb2home, PATHSEP);
 			strcatbf(liveeventbackup, srb2home, PATHSEP);
 
 			snprintf(luafiledir, sizeof luafiledir, "%s" PATHSEP "luafiles", srb2home);
@@ -1345,15 +1345,12 @@ void D_SRB2Main(void)
 			else
 				snprintf(configfile, sizeof configfile, "%s" PATHSEP CONFIGFILENAME, userhome);
 
-			// can't use sprintf since there is %u in savegamename
-			strcatbf(savegamename, userhome, PATHSEP);
-			strcatbf(liveeventbackup, userhome, PATHSEP);
-
 			snprintf(luafiledir, sizeof luafiledir, "%s" PATHSEP "luafiles", userhome);
 #endif // DEFAULTDIR
 		}
 
 		configfile[sizeof configfile - 1] = '\0';
+		P_SetSaveGameName("gamedata", SAVEGAMENAME);
 	}
 
 	// Create addons dir
diff --git a/src/deh_soc.c b/src/deh_soc.c
index 343beb3012676b93256af35c0bd57ff6ba7e9076..7fce4aa119f6d5f9d5444183ed83bc42940de025 100644
--- a/src/deh_soc.c
+++ b/src/deh_soc.c
@@ -35,6 +35,7 @@
 #include "fastcmp.h"
 #include "lua_script.h" // Reluctantly included for LUA_EvalMath
 #include "netcode/d_clisrv.h"
+#include "p_saveg.h"
 
 #ifdef HWRENDER
 #include "hardware/hw_light.h"
@@ -3907,6 +3908,7 @@ void readmaincfg(MYFILE *f)
 			else if (fastcmp(word, "GAMEDATA"))
 			{
 				size_t filenamelen;
+				char tmpfilename[sizeof(timeattackfolder)];
 
 				// Check the data filename so that mods
 				// can't write arbitrary files.
@@ -3914,26 +3916,20 @@ void readmaincfg(MYFILE *f)
 					I_Error("Maincfg: bad data file name '%s'\n", word2);
 
 				G_SaveGameData(clientGamedata);
-				strlcpy(gamedatafilename, word2, sizeof (gamedatafilename));
-				strlwr(gamedatafilename);
 				savemoddata = true;
 
 				// Also save a time attack folder
-				filenamelen = strlen(gamedatafilename);  // Strip off the extension
+				filenamelen = strlen(word2);  // Strip off the extension
 				if (filenamelen >= 4)
 					filenamelen -= 4;
 				if (filenamelen >= sizeof(timeattackfolder))
 					filenamelen = sizeof(timeattackfolder)-1;
-				strncpy(timeattackfolder, gamedatafilename, filenamelen);
-				timeattackfolder[min(filenamelen, sizeof (timeattackfolder) - 1)] = '\0';
+				strncpy(tmpfilename, word2, filenamelen);
+				tmpfilename[min(filenamelen, sizeof (timeattackfolder) - 1)] = '\0';
+				strlwr(tmpfilename);
+				strncpy(timeattackfolder, tmpfilename, sizeof(timeattackfolder));
 
-				strcpy(savegamename, timeattackfolder);
-				strlcat(savegamename, "%u.ssg", sizeof(savegamename));
-				// can't use sprintf since there is %u in savegamename
-				strcatbf(savegamename, srb2home, PATHSEP);
-
-				strcpy(liveeventbackup, va("live%s.bkp", timeattackfolder));
-				strcatbf(liveeventbackup, srb2home, PATHSEP);
+				P_SetSaveGameName(tmpfilename, tmpfilename);
 
 				gamedataadded = true;
 				titlechanged = true;
diff --git a/src/doomdef.h b/src/doomdef.h
index 81ab7bbfb5505507f3df07b6b5709b6d4f995e81..c53acc0cff6c334e483e14a90d37a906e69dede0 100644
--- a/src/doomdef.h
+++ b/src/doomdef.h
@@ -537,8 +537,8 @@ void CONS_Debug(INT32 debugflags, const char *fmt, ...) FUNCDEBUG;
 
 // Things that used to be in dstrings.h
 #define SAVEGAMENAME "srb2sav"
-extern char savegamename[256];
-extern char liveeventbackup[256];
+extern char savegamename[512];
+extern char liveeventbackup[512];
 
 // m_misc.h
 #ifdef GETTEXT
diff --git a/src/g_game.c b/src/g_game.c
index 1c186ae03149780b254c72f5243ed3d551350e52..34f2678799fa990de5903b7b302146094e4ca72a 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -69,8 +69,9 @@ JoyType_t Joystick2;
 // 1024 bytes is plenty for a savegame
 #define SAVEGAMESIZE (1024)
 
-char gamedatafilename[64] = "gamedata.dat";
+char gamedatafilename[512] = "gamedata.dat";
 char timeattackfolder[64] = "main";
+char savefolder[64] = "save";
 char customversionstring[32] = "\0";
 
 static void G_DoCompleted(void);
@@ -4745,7 +4746,7 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
 {
 	save_t savebuffer;
 	char vcheck[VERSIONSIZE];
-	char savename[255];
+	char savename[260];
 
 	// memset savedata to all 0, fixes calling perfectly valid saves corrupt because of bots
 	memset(&savedata, 0, sizeof(savedata));
@@ -4835,7 +4836,7 @@ void G_SaveGame(UINT32 slot, INT16 mapnum)
 {
 	save_t savebuffer;
 	boolean saved;
-	char savename[256] = "";
+	char savename[260] = "";
 	const char *backup;
 
 	if (marathonmode)
diff --git a/src/g_game.h b/src/g_game.h
index f72ea6b41b1b29b4b263b9039c0ad588bc78de17..c5c1b3863e1f27593bf70d4797c39215bb101c2f 100644
--- a/src/g_game.h
+++ b/src/g_game.h
@@ -21,8 +21,9 @@
 #include "m_cheat.h" // objectplacing
 #include "m_cond.h"
 
-extern char gamedatafilename[64];
+extern char gamedatafilename[512];
 extern char timeattackfolder[64];
+extern char savefolder[64];
 extern char customversionstring[32];
 #define GAMEDATASIZE (4*8192)
 
diff --git a/src/p_saveg.c b/src/p_saveg.c
index 650622f59f8130a896257748eb56a4116e963f7e..035492894ae468b7ec5b9b4c5ed48f32ecd67a1d 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -36,6 +36,8 @@
 #include "lua_script.h"
 #include "p_slopes.h"
 #include "hu_stuff.h"
+#include "m_menu.h"
+#include "i_system.h"
 
 savedata_t savedata;
 
@@ -5355,6 +5357,51 @@ static inline boolean P_UnArchiveLuabanksAndConsistency(save_t *save_p)
 	return true;
 }
 
+void P_SetSaveGameName(const char* gamedataPrefix, const char* savedataPrefix)
+{
+	char buffer[512];
+	snprintf(buffer, sizeof(buffer) -1, "%s/%s", srb2home, savefolder);
+	I_mkdir(buffer, 0755);
+	snprintf(gamedatafilename, sizeof(gamedatafilename) - 1, "%s/%s/%s.dat", srb2home, savefolder, gamedataPrefix);
+	snprintf(savegamename, sizeof(savegamename) - 1, "%s/%s/%s%%u.ssg", srb2home, savefolder, savedataPrefix);
+	snprintf(liveeventbackup, sizeof(liveeventbackup) - 1, "%s/%s/live%s.bkp", srb2home, savefolder, savedataPrefix);
+
+	CONS_Printf("%s\n%s\n%s\n", gamedatafilename, timeattackfolder, savegamename);
+
+	// Attempt to copy files from root if we don't have a gamedata
+	FILE* f = fopen(gamedatafilename, "rb");
+	if(!f)
+	{
+		char buffer2[512];
+		snprintf(buffer, sizeof(buffer) - 1, "%s/%s.dat", srb2home, gamedataPrefix);
+
+		f = fopen(buffer, "rb");
+		if(f)
+		{
+			fclose(f);
+			rename(buffer, gamedatafilename);
+		}
+
+
+		// Now repeat for saves
+		for(int slot = 0; slot < (MAXSAVEGAMES - 1); slot++)
+		{
+			snprintf(buffer, sizeof(buffer) - 1, "%s/%s%u.ssg", srb2home, savedataPrefix, slot);
+			f = fopen(buffer, "rb");
+			if(f)
+			{
+				snprintf(buffer2, sizeof(buffer2) - 1, "%s/%s/%s%u.ssg", srb2home, savefolder, savedataPrefix, slot);
+				fclose(f);
+				rename(buffer, buffer2);
+			}
+		}
+	}
+	else
+	{
+		fclose(f);
+	}
+}
+
 void P_SaveGame(save_t *save_p, INT16 mapnum)
 {
 	P_ArchiveMisc(save_p, mapnum);
diff --git a/src/p_saveg.h b/src/p_saveg.h
index 05e82190aeb27bb8aa62f5bf4a2b2c8b889759fb..d1b976fb934883c880493dd285fc32e2164e1e94 100644
--- a/src/p_saveg.h
+++ b/src/p_saveg.h
@@ -32,6 +32,7 @@ typedef struct
 	size_t pos;
 } save_t;
 
+void P_SetSaveGameName(const char* gamedataPrefix, const char* savedataPrefix);
 void P_SaveGame(save_t *save_p, INT16 mapnum);
 void P_SaveNetGame(save_t *save_p, boolean resending);
 boolean P_LoadGame(save_t *save_p, INT16 mapoverride);