diff --git a/src/command.c b/src/command.c
index 47c6d2e5f7e8922cd321f5cda2e0805b23e35175..3045c1769e53eec6c916c68b6c398e008685f36b 100644
--- a/src/command.c
+++ b/src/command.c
@@ -63,7 +63,7 @@ CV_PossibleValue_t CV_YesNo[] = {{0, "No"}, {1, "Yes"}, {0, NULL}};
 CV_PossibleValue_t CV_Unsigned[] = {{0, "MIN"}, {999999999, "MAX"}, {0, NULL}};
 CV_PossibleValue_t CV_Natural[] = {{1, "MIN"}, {999999999, "MAX"}, {0, NULL}};
 
-// Filter consvars by MODVERSION
+// Filter consvars by EXECVERSION
 // First implementation is 26 (2.1.21), so earlier configs default at 25 (2.1.20)
 // Also set CV_HIDEN during runtime, after config is loaded
 consvar_t cv_execversion = {"execversion","25",0,CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL};
@@ -1589,7 +1589,7 @@ void CV_InitFilterVar(void)
 static boolean CV_FilterJoyAxisVars(consvar_t *v, const char *valstr)
 {
 	// If ALL axis settings are previous defaults, set them to the new defaults
-	// MODVERSION < 26 (2.1.21)
+	// EXECVERSION < 26 (2.1.21)
 
 	if (joyaxis_default)
 	{
@@ -1730,6 +1730,11 @@ static boolean CV_FilterJoyAxisVars(consvar_t *v, const char *valstr)
 
 static boolean CV_FilterVarByVersion(consvar_t *v, const char *valstr)
 {
+	INT32 majorexecversion = abs(cv_execversion.value) & 0xFFFF;
+#if 0 // unused for now
+	INT32 minorexecversion = abs(cv_execversion.value) >> 16;
+#endif
+
 	// True means allow the CV change, False means block it
 
 	// We only care about CV_SAVE because this filters the user's config files
@@ -1737,8 +1742,7 @@ static boolean CV_FilterVarByVersion(consvar_t *v, const char *valstr)
 	if (!(v->flags & CV_SAVE))
 		return true;
 
-	// We go by MODVERSION here
-	if (cv_execversion.value < 26) // 26 = 2.1.21
+	if (majorexecversion < 26) // 26 = 2.1.21
 	{
 		// MOUSE SETTINGS
 		// alwaysfreelook split between first and third person (chasefreelook)
diff --git a/src/doomdef.h b/src/doomdef.h
index 796221c91802d4051e1c04a61f50374abc1a0c04..0485698d1b0e8ab260fb344aa1ecacde7d2949e0 100644
--- a/src/doomdef.h
+++ b/src/doomdef.h
@@ -216,6 +216,12 @@ extern FILE *logstream;
 // Note that we use this to help keep internal testing in check; this is why v2.1.0 is not version "1".
 #define MODVERSION 26
 
+// To version config.cfg, EXECVERSION was originally equal to MODVERSION
+// So keep it equal to MODVERSION, and increment MINOREXECVERSION whenever a config change
+// is needed that does not correspond to an increment in MODVERSION
+#define EXECVERSION 26
+#define MINOREXECVERSION 1
+
 // =========================================================================
 
 // The maximum number of players, multiplayer/networking.
diff --git a/src/m_misc.c b/src/m_misc.c
index 1ab5f1fe369258db0aee2ebc642f6c222f9bcf4c..bb25c5405e651da528ebacbcaf31b24f0cbf05cd 100644
--- a/src/m_misc.c
+++ b/src/m_misc.c
@@ -451,7 +451,7 @@ void Command_LoadConfig_f(void)
 	COM_BufInsertText(va("exec \"%s\"\n", configfile));
 
 	// don't filter anymore vars and don't let this convsvar be changed
-	COM_BufInsertText(va("%s \"%d\"\n", cv_execversion.name, MODVERSION));
+	COM_BufInsertText(va("%s \"%d\"\n", cv_execversion.name, EXECVERSION));
 	cv_execversion.flags |= CV_HIDEN;
 }
 
@@ -503,7 +503,7 @@ void M_FirstLoadConfig(void)
 	// no COM_BufExecute() needed; that does it right away
 
 	// don't filter anymore vars and don't let this convsvar be changed
-	COM_BufInsertText(va("%s \"%d\"\n", cv_execversion.name, MODVERSION));
+	COM_BufInsertText(va("%s \"%d\"\n", cv_execversion.name, EXECVERSION));
 	cv_execversion.flags |= CV_HIDEN;
 
 	// make sure I_Quit() will write back the correct config
@@ -562,8 +562,8 @@ void M_SaveConfig(const char *filename)
 	fprintf(f, "// SRB2 configuration file.\n");
 
 	// print execversion FIRST, because subsequent consvars need to be filtered
-	// always print current MODVERSION
-	fprintf(f, "%s \"%d\"\n", cv_execversion.name, MODVERSION);
+	// always print current EXECVERSION
+	fprintf(f, "%s \"%d\"\n", cv_execversion.name, (EXECVERSION + (MINOREXECVERSION << 16)));
 
 	// FIXME: save key aliases if ever implemented..