diff --git a/src/g_input.c b/src/g_input.c
index cb27fb345a4d8c1217ef8f0c2be2eff4a9f55d2b..b1511fcd93fc4492d3a2e16ce1265da29048ca50 100644
--- a/src/g_input.c
+++ b/src/g_input.c
@@ -45,6 +45,7 @@ UINT8 gamekeydown[NUMINPUTS];
 // two key codes (or virtual key) per game control
 INT32 gamecontrol[num_gamecontrols][2];
 INT32 gamecontrolbis[num_gamecontrols][2]; // secondary splitscreen player
+INT32 gamecontroldefault[num_gamecontrolschemes][num_gamecontrols][2]; // default control storage, use 0 (gcs_custom) for memory retention
 
 typedef struct
 {
@@ -611,79 +612,119 @@ INT32 G_KeyStringtoNum(const char *keystr)
 	return 0;
 }
 
-void G_Controldefault(INT32 scheme, boolean setcommon)
+void G_DefineDefaultControls(void)
 {
-	if (scheme == CONTROL_DEFAULT_PLATFORM)
+	INT32 i;
+
+	// FPS game controls (WASD)
+	gamecontroldefault[gcs_fps][gc_forward    ][0] = 'w';
+	gamecontroldefault[gcs_fps][gc_backward   ][0] = 's';
+	gamecontroldefault[gcs_fps][gc_strafeleft ][0] = 'a';
+	gamecontroldefault[gcs_fps][gc_straferight][0] = 'd';
+	gamecontroldefault[gcs_fps][gc_lookup     ][0] = KEY_UPARROW;
+	gamecontroldefault[gcs_fps][gc_lookdown   ][0] = KEY_DOWNARROW;
+	gamecontroldefault[gcs_fps][gc_turnleft   ][0] = KEY_LEFTARROW;
+	gamecontroldefault[gcs_fps][gc_turnright  ][0] = KEY_RIGHTARROW;
+	gamecontroldefault[gcs_fps][gc_centerview ][0] = KEY_END;
+	gamecontroldefault[gcs_fps][gc_jump       ][0] = KEY_SPACE;
+	gamecontroldefault[gcs_fps][gc_use        ][0] = KEY_LSHIFT;
+	gamecontroldefault[gcs_fps][gc_fire       ][0] = KEY_RCTRL;
+	gamecontroldefault[gcs_fps][gc_fire       ][1] = KEY_MOUSE1+0;
+	gamecontroldefault[gcs_fps][gc_firenormal ][0] = 'c';
+
+	// Platform game controls (arrow keys)
+	// gamecontroldefault[gcs_platform][gc_forward    ][0] = KEY_UPARROW;
+	// gamecontroldefault[gcs_platform][gc_backward   ][0] = KEY_DOWNARROW;
+	// gamecontroldefault[gcs_platform][gc_strafeleft ][0] = 'a';
+	// gamecontroldefault[gcs_platform][gc_straferight][0] = 'd';
+	// gamecontroldefault[gcs_platform][gc_lookup     ][0] = KEY_PGUP;
+	// gamecontroldefault[gcs_platform][gc_lookdown   ][0] = KEY_PGDN;
+	// gamecontroldefault[gcs_platform][gc_turnleft   ][0] = KEY_LEFTARROW;
+	// gamecontroldefault[gcs_platform][gc_turnright  ][0] = KEY_RIGHTARROW;
+	// gamecontroldefault[gcs_platform][gc_centerview ][0] = KEY_END;
+	// gamecontroldefault[gcs_platform][gc_jump       ][0] = KEY_SPACE;
+	// gamecontroldefault[gcs_platform][gc_use        ][0] = KEY_LSHIFT;
+	// gamecontroldefault[gcs_platform][gc_fire       ][0] = 's';
+	// gamecontroldefault[gcs_platform][gc_fire       ][1] = KEY_MOUSE1+0;
+	// gamecontroldefault[gcs_platform][gc_firenormal ][0] = 'w';
+
+	for (i = 1; i < num_gamecontrolschemes; i++) // skip gcs_custom (0)
 	{
-		gamecontrol[gc_forward    ][0] = KEY_UPARROW;
-		gamecontrol[gc_backward   ][0] = KEY_DOWNARROW;
-		gamecontrol[gc_strafeleft ][0] = 'a';
-		gamecontrol[gc_straferight][0] = 'd';
-		gamecontrol[gc_lookup     ][0] = KEY_PGUP;
-		gamecontrol[gc_lookdown   ][0] = KEY_PGDN;
-		gamecontrol[gc_turnleft   ][0] = KEY_LEFTARROW;
-		gamecontrol[gc_turnright  ][0] = KEY_RIGHTARROW;
-		gamecontrol[gc_centerview ][0] = KEY_END;
-		gamecontrol[gc_jump       ][0] = KEY_SPACE;
-		gamecontrol[gc_use        ][0] = KEY_LSHIFT;
-		gamecontrol[gc_fire       ][0] = 's';
-		gamecontrol[gc_fire       ][1] = KEY_MOUSE1+0;
-		gamecontrol[gc_firenormal ][0] = 'w';
+		gamecontroldefault[i][gc_weaponnext ][0] = 'e';
+		gamecontroldefault[i][gc_weaponprev ][0] = 'q';
+		gamecontroldefault[i][gc_wepslot1   ][0] = '1';
+		gamecontroldefault[i][gc_wepslot2   ][0] = '2';
+		gamecontroldefault[i][gc_wepslot3   ][0] = '3';
+		gamecontroldefault[i][gc_wepslot4   ][0] = '4';
+		gamecontroldefault[i][gc_wepslot5   ][0] = '5';
+		gamecontroldefault[i][gc_wepslot6   ][0] = '6';
+		gamecontroldefault[i][gc_wepslot7   ][0] = '7';
+		gamecontroldefault[i][gc_wepslot8   ][0] = '8';
+		gamecontroldefault[i][gc_wepslot9   ][0] = '9';
+		gamecontroldefault[i][gc_wepslot10  ][0] = '0';
+		gamecontroldefault[i][gc_tossflag   ][0] = '\'';
+		gamecontroldefault[i][gc_camtoggle  ][0] = 'v';
+		gamecontroldefault[i][gc_camreset   ][0] = 'r';
+		gamecontroldefault[i][gc_talkkey    ][0] = 't';
+		gamecontroldefault[i][gc_teamkey    ][0] = 'y';
+		gamecontroldefault[i][gc_scores     ][0] = KEY_TAB;
+		gamecontroldefault[i][gc_console    ][0] = KEY_CONSOLE;
+		gamecontroldefault[i][gc_pause      ][0] = KEY_PAUSE;
 	}
-	else // if (scheme == CONTROL_DEFAULT_FPS)
+}
+
+INT32 G_GetControlScheme(INT32 (*fromcontrols)[2], boolean movementonly)
+{
+	INT32 i, j, gc;
+	boolean skipscheme;
+
+	gamecontrols_e movement[] = {
+		gc_forward, gc_backward, gc_strafeleft, gc_straferight,
+		gc_lookup, gc_lookdown, gc_turnleft, gc_turnright, gc_centerview,
+		gc_jump, gc_use
+		// , gc_fire, gc_firenormal
+	};
+
+	for (i = 1; i < num_gamecontrolschemes; i++) // skip gcs_custom (0)
 	{
-		gamecontrol[gc_forward    ][0] = 'w';
-		gamecontrol[gc_backward   ][0] = 's';
-		gamecontrol[gc_strafeleft ][0] = 'a';
-		gamecontrol[gc_straferight][0] = 'd';
-		gamecontrol[gc_lookup     ][0] = KEY_UPARROW;
-		gamecontrol[gc_lookdown   ][0] = KEY_DOWNARROW;
-		gamecontrol[gc_turnleft   ][0] = KEY_LEFTARROW;
-		gamecontrol[gc_turnright  ][0] = KEY_RIGHTARROW;
-		gamecontrol[gc_centerview ][0] = KEY_END;
-		gamecontrol[gc_jump       ][0] = KEY_SPACE;
-		gamecontrol[gc_use        ][0] = KEY_LSHIFT;
-		gamecontrol[gc_fire       ][0] = KEY_RCTRL;
-		gamecontrol[gc_fire       ][1] = KEY_MOUSE1+0;
-		gamecontrol[gc_firenormal ][0] = 'c';
+		skipscheme = false;
+		for (j = 0; j < (movementonly ? sizeof(movement) : num_gamecontrols); j++)
+		{
+			gc = (movementonly) ? movement[j] : j;
+			if (fromcontrols[gc][0] != gamecontroldefault[i][gc][0] && fromcontrols[gc][1] != gamecontroldefault[i][gc][1])
+			{
+				skipscheme = true;
+				break;
+			}
+		}
+		if (!skipscheme)
+			return i;
 	}
 
-	if (setcommon)
+	return gcs_custom;
+}
+
+void G_CopyControls(INT32 (*setupcontrols)[2], INT32 (*fromcontrols)[2])
+{
+	INT32 i;
+	for (i = 0; i < num_gamecontrols; i++)
 	{
-		gamecontrol[gc_weaponnext ][0] = 'e';
-		gamecontrol[gc_weaponprev ][0] = 'q';
-		gamecontrol[gc_wepslot1   ][0] = '1';
-		gamecontrol[gc_wepslot2   ][0] = '2';
-		gamecontrol[gc_wepslot3   ][0] = '3';
-		gamecontrol[gc_wepslot4   ][0] = '4';
-		gamecontrol[gc_wepslot5   ][0] = '5';
-		gamecontrol[gc_wepslot6   ][0] = '6';
-		gamecontrol[gc_wepslot7   ][0] = '7';
-		gamecontrol[gc_wepslot8   ][0] = '8';
-		gamecontrol[gc_wepslot9   ][0] = '9';
-		gamecontrol[gc_wepslot10  ][0] = '0';
-		gamecontrol[gc_tossflag   ][0] = '\'';
-		gamecontrol[gc_camtoggle  ][0] = 'v';
-		gamecontrol[gc_camreset   ][0] = 'r';
-		gamecontrol[gc_talkkey    ][0] = 't';
-		gamecontrol[gc_teamkey    ][0] = 'y';
-		gamecontrol[gc_scores     ][0] = KEY_TAB;
-		gamecontrol[gc_console    ][0] = KEY_CONSOLE;
-		gamecontrol[gc_pause      ][0] = KEY_PAUSE;
+		setupcontrols[i][0] = fromcontrols[i][0];
+		setupcontrols[i][1] = fromcontrols[i][1];
 	}
 }
 
-void G_SaveKeySetting(FILE *f)
+void G_SaveKeySetting(FILE *f, INT32 (*fromcontrols)[2], INT32 (*fromcontrolsbis)[2])
 {
 	INT32 i;
 
 	for (i = 1; i < num_gamecontrols; i++)
 	{
 		fprintf(f, "setcontrol \"%s\" \"%s\"", gamecontrolname[i],
-			G_KeynumToString(gamecontrol[i][0]));
+			G_KeynumToString(fromcontrols[i][0]));
 
-		if (gamecontrol[i][1])
-			fprintf(f, " \"%s\"\n", G_KeynumToString(gamecontrol[i][1]));
+		if (fromcontrols[i][1])
+			fprintf(f, " \"%s\"\n", G_KeynumToString(fromcontrols[i][1]));
 		else
 			fprintf(f, "\n");
 	}
@@ -691,10 +732,10 @@ void G_SaveKeySetting(FILE *f)
 	for (i = 1; i < num_gamecontrols; i++)
 	{
 		fprintf(f, "setcontrol2 \"%s\" \"%s\"", gamecontrolname[i],
-			G_KeynumToString(gamecontrolbis[i][0]));
+			G_KeynumToString(fromcontrolsbis[i][0]));
 
-		if (gamecontrolbis[i][1])
-			fprintf(f, " \"%s\"\n", G_KeynumToString(gamecontrolbis[i][1]));
+		if (fromcontrolsbis[i][1])
+			fprintf(f, " \"%s\"\n", G_KeynumToString(fromcontrolsbis[i][1]));
 		else
 			fprintf(f, "\n");
 	}
diff --git a/src/g_input.h b/src/g_input.h
index ea952a8eaccdde6a040bf4f21e0fcb8b3f02afc8..af52bbd6535efc66a9d739f619c2364c9d0441fe 100644
--- a/src/g_input.h
+++ b/src/g_input.h
@@ -27,10 +27,6 @@
 #define JOYHATS      4  // 4 hats
 #define JOYAXISSET   4  // 4 Sets of 2 axises
 
-#define CONTROL_DEFAULT_FPS 0
-#define CONTROL_DEFAULT_PLATFORM 1
-#define CONTROL_DEFAULT_CUSTOM 2
-
 //
 // mouse and joystick buttons are handled as 'virtual' keys
 //
@@ -103,6 +99,14 @@ typedef enum
 	num_gamecontrols
 } gamecontrols_e;
 
+typedef enum
+{
+	gcs_custom,
+	gcs_fps,
+	//gcs_platform,
+	num_gamecontrolschemes
+} gamecontrolschemes_e;
+
 // mouse values are used once
 extern consvar_t cv_mousesens, cv_mouseysens;
 extern consvar_t cv_mousesens2, cv_mouseysens2;
@@ -120,6 +124,7 @@ extern UINT8 gamekeydown[NUMINPUTS];
 // two key codes (or virtual key) per game control
 extern INT32 gamecontrol[num_gamecontrols][2];
 extern INT32 gamecontrolbis[num_gamecontrols][2]; // secondary splitscreen player
+extern INT32 gamecontroldefault[num_gamecontrolschemes][num_gamecontrols][2]; // default control storage, use 0 (gcs_custom) for memory retention
 #define PLAYER1INPUTDOWN(gc) (gamekeydown[gamecontrol[gc][0]] || gamekeydown[gamecontrol[gc][1]])
 #define PLAYER2INPUTDOWN(gc) (gamekeydown[gamecontrolbis[gc][0]] || gamekeydown[gamecontrolbis[gc][1]])
 
@@ -137,8 +142,10 @@ INT32 G_KeyStringtoNum(const char *keystr);
 void G_ClearControlKeys(INT32 (*setupcontrols)[2], INT32 control);
 void Command_Setcontrol_f(void);
 void Command_Setcontrol2_f(void);
-void G_Controldefault(INT32 scheme);
-void G_SaveKeySetting(FILE *f);
+void G_DefineDefaultControls(void);
+INT32 G_GetControlScheme(INT32 (*fromcontrols)[2], boolean movementonly);
+void G_CopyControls(INT32 (*setupcontrols)[2], INT32 (*fromcontrols)[2]);
+void G_SaveKeySetting(FILE *f, INT32 (*fromcontrols)[2], INT32 (*fromcontrolsbis)[2]);
 void G_CheckDoubleUsage(INT32 keynum);
 
 #endif
diff --git a/src/m_misc.c b/src/m_misc.c
index cfd788d87fc20fb04cab240458278fce2e71af9f..8211239ef2fd0f5db959bedf06b3f04138aad532 100644
--- a/src/m_misc.c
+++ b/src/m_misc.c
@@ -475,7 +475,8 @@ void M_FirstLoadConfig(void)
 	}
 
 	// load default control
-	G_Controldefault(CONTROL_DEFAULT_FPS, true);
+	G_DefineDefaultControls();
+	G_CopyControls(gamecontrol, gamecontroldefault[gcs_fps]);
 
 	// load config, make sure those commands doesnt require the screen...
 	COM_BufInsertText(va("exec \"%s\"\n", configfile));
@@ -539,7 +540,7 @@ void M_SaveConfig(const char *filename)
 	// FIXME: save key aliases if ever implemented..
 
 	CV_SaveVariables(f);
-	if (!dedicated) G_SaveKeySetting(f);
+	if (!dedicated) G_SaveKeySetting(f, gamecontrol, gamecontrolbis);
 
 	fclose(f);
 }