diff --git a/src/d_netcmd.c b/src/d_netcmd.c
index d05c5cc4576dab807fbf1dade177bd3d52213f8f..3574f2e90c7b32f1df8641b5265bf94f428f7918 100644
--- a/src/d_netcmd.c
+++ b/src/d_netcmd.c
@@ -838,6 +838,8 @@ void D_RegisterClientCommands(void)
 	CV_RegisterVar(&cv_cam_turnfacingspindash[1]);
 	CV_RegisterVar(&cv_cam_turnfacinginput[0]);
 	CV_RegisterVar(&cv_cam_turnfacinginput[1]);
+	CV_RegisterVar(&cv_cam_centertoggle[0]);
+	CV_RegisterVar(&cv_cam_centertoggle[1]);
 	CV_RegisterVar(&cv_cam_lockedinput[0]);
 	CV_RegisterVar(&cv_cam_lockedinput[1]);
 	CV_RegisterVar(&cv_cam_lockonboss[0]);
diff --git a/src/g_game.c b/src/g_game.c
index b91e0a7976e7c1d4a66e1c2d5d25130eb18630f7..6fed500b30abba675b021226011bf4839693096e 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -421,8 +421,13 @@ consvar_t cv_cam_turnfacinginput[2] = {
 	{"cam2_turnfacinginput", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
 };
 
-static CV_PossibleValue_t lockedinput_cons_t[] = {{0, "Strafe"}, {1, "Turn"}, {0, NULL}};
+static CV_PossibleValue_t centertoggle_cons_t[] = {{0, "Hold"}, {1, "Toggle"}, {0, NULL}};
+consvar_t cv_cam_centertoggle[2] = {
+	{"cam_centertoggle", "Hold", CV_SAVE, centertoggle_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
+	{"cam2_centertoggle", "Hold", CV_SAVE, centertoggle_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
+};
 
+static CV_PossibleValue_t lockedinput_cons_t[] = {{0, "Strafe"}, {1, "Turn"}, {0, NULL}};
 consvar_t cv_cam_lockedinput[2] = {
 	{"cam_lockedinput", "Strafe", CV_SAVE, lockedinput_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
 	{"cam2_lockedinput", "Strafe", CV_SAVE, lockedinput_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
@@ -436,7 +441,6 @@ static CV_PossibleValue_t lockedassist_cons_t[] = {
 	{LOCK_BOSS|LOCK_ENEMY|LOCK_INTERESTS, "Full"},
 	{0, NULL}
 };
-
 consvar_t cv_cam_lockonboss[2] = {
 	{"cam_lockaimassist", "Bosses", CV_SAVE, lockedassist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
 	{"cam2_lockaimassist", "Bosses", CV_SAVE, lockedassist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL},
@@ -1057,8 +1061,12 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
 	static boolean keyboard_look[2]; // true if lookup/down using keyboard
 	static boolean resetdown[2]; // don't cam reset every frame
 	static boolean joyaiming[2]; // check the last frame's value if we need to reset the camera
+
+	// simple mode vars
 	static boolean zchange[2]; // only switch z targets once per press
 	static fixed_t tta_factor[2] = {FRACUNIT, FRACUNIT}; // disables turn-to-angle when manually turning camera until movement happens
+	boolean centerviewdown = false;
+
 	UINT8 forplayer = ssplayer-1;
 
 	if (ssplayer == 1)
@@ -1291,7 +1299,23 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
 	if (PLAYERINPUTDOWN(ssplayer, gc_use) || (usejoystick && axis > 0))
 		cmd->buttons |= BT_USE;
 
-	if (PLAYERINPUTDOWN(ssplayer, gc_centerview))
+	// Centerview can be a toggle in simple mode!
+	{
+		static boolean last_centerviewdown[2], centerviewhold[2]; // detect taps for toggle behavior
+		boolean down = PLAYERINPUTDOWN(ssplayer, gc_centerview);
+
+		if (!(abilitydirection && cv_cam_centertoggle[forplayer].value))
+			centerviewdown = down;
+		else
+		{
+			if (down && !last_centerviewdown[forplayer])
+				centerviewhold[forplayer] = !centerviewhold[forplayer];
+			last_centerviewdown[forplayer] = down;
+			centerviewdown = centerviewhold[forplayer];
+		}
+	}
+
+	if (centerviewdown)
 	{
 		if (abilitydirection && !ticcmd_centerviewdown[forplayer])
 		{
diff --git a/src/g_game.h b/src/g_game.h
index 0a018e253880a1e8600073bd8457f6aa1a3e8456..8ba3bc373e65b81e4e3c2c8e104a38e6d4d9ea25 100644
--- a/src/g_game.h
+++ b/src/g_game.h
@@ -79,7 +79,7 @@ extern consvar_t cv_ghost_bestscore, cv_ghost_besttime, cv_ghost_bestrings, cv_g
 // hi here's some new controls
 extern consvar_t cv_abilitydirection[2], cv_cam_shiftfacing[2], cv_cam_turnfacing[2],
 	cv_cam_turnfacingability[2], cv_cam_turnfacingspindash[2], cv_cam_turnfacinginput[2],
-	cv_cam_lockedinput[2], cv_cam_lockonboss[2];
+	cv_cam_centertoggle[2], cv_cam_lockedinput[2], cv_cam_lockonboss[2];
 
 typedef enum
 {
diff --git a/src/m_menu.c b/src/m_menu.c
index bfe118af1f2f0e1ad76688d411c71303e6b4ba3b..fb1737f103243189f9dcc9edbf3cff7fbddfde5d 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -1238,11 +1238,12 @@ static menuitem_t OP_CameraExtendedOptionsMenu[] =
 	{IT_STRING  | IT_CVAR | IT_CV_SLIDER, NULL, "Turn to input", &cv_cam_turnfacinginput[0],  85},
 
 	{IT_HEADER,            NULL, "Locked Camera Options", NULL, 95},
-	{IT_STRING  | IT_CVAR, NULL, "Sideways movement", &cv_cam_lockedinput[0],  100},
-	{IT_STRING  | IT_CVAR, NULL, "Targeting assist", &cv_cam_lockonboss[0],  105},
+	{IT_STRING  | IT_CVAR, NULL, "Lock button behavior", &cv_cam_centertoggle[0],  100},
+	{IT_STRING  | IT_CVAR, NULL, "Sideways movement", &cv_cam_lockedinput[0],  105},
+	{IT_STRING  | IT_CVAR, NULL, "Targeting assist", &cv_cam_lockonboss[0],  110},
 
-	{IT_HEADER,            NULL, "Display Options", NULL, 115},
-	{IT_STRING  | IT_CVAR, NULL, "Crosshair", &cv_crosshair, 120},
+	{IT_HEADER,            NULL, "Display Options", NULL, 120},
+	{IT_STRING  | IT_CVAR, NULL, "Crosshair", &cv_crosshair, 125},
 };
 
 static menuitem_t OP_Camera2ExtendedOptionsMenu[] =
@@ -1267,11 +1268,12 @@ static menuitem_t OP_Camera2ExtendedOptionsMenu[] =
 	{IT_STRING  | IT_CVAR | IT_CV_SLIDER, NULL, "Turn to input", &cv_cam_turnfacinginput[1],  85},
 
 	{IT_HEADER,            NULL, "Locked Camera Options", NULL, 95},
-	{IT_STRING  | IT_CVAR, NULL, "Sideways movement", &cv_cam_lockedinput[1],  100},
-	{IT_STRING  | IT_CVAR, NULL, "Targeting assist", &cv_cam_lockonboss[1],  105},
+	{IT_STRING  | IT_CVAR, NULL, "Lock button behavior", &cv_cam_centertoggle[1],  100},
+	{IT_STRING  | IT_CVAR, NULL, "Sideways movement", &cv_cam_lockedinput[1],  105},
+	{IT_STRING  | IT_CVAR, NULL, "Targeting assist", &cv_cam_lockonboss[1],  110},
 
-	{IT_HEADER,            NULL, "Display Options", NULL, 115},
-	{IT_STRING  | IT_CVAR, NULL, "Crosshair", &cv_crosshair2, 120},
+	{IT_HEADER,            NULL, "Display Options", NULL, 120},
+	{IT_STRING  | IT_CVAR, NULL, "Crosshair", &cv_crosshair2, 125},
 };
 
 static menuitem_t OP_VideoOptionsMenu[] =