diff --git a/src/d_netcmd.c b/src/d_netcmd.c
index e80d07b76..f622966c5 100644
--- a/src/d_netcmd.c
+++ b/src/d_netcmd.c
@@ -823,6 +823,10 @@ void D_RegisterClientCommands(void)
 	CV_RegisterVar(&cv_autobrake);
 	CV_RegisterVar(&cv_autobrake2);
 
+	// Ported from kart
+	CV_RegisterVar(&cv_deadzone);
+	CV_RegisterVar(&cv_deadzone2);
+
 	// s_sound.c
 	CV_RegisterVar(&cv_soundvolume);
 	CV_RegisterVar(&cv_closedcaptioning);
diff --git a/src/g_game.c b/src/g_game.c
index 0105b88c6..d2d27528c 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -400,6 +400,11 @@ consvar_t cv_directionchar2 = {"directionchar2", "Movement", CV_SAVE|CV_CALL, di
 consvar_t cv_autobrake = {"autobrake", "On", CV_SAVE|CV_CALL, CV_OnOff, AutoBrake_OnChange, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_autobrake2 = {"autobrake2", "On", CV_SAVE|CV_CALL, CV_OnOff, AutoBrake2_OnChange, 0, NULL, NULL, 0, 0, NULL};
 
+static CV_PossibleValue_t deadzone_cons_t[] = {{0, "MIN"}, {FRACUNIT, "MAX"}, {0, NULL}};
+consvar_t cv_deadzone = {"deadzone", "0.25", CV_FLOAT|CV_SAVE, deadzone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_deadzone2 = {"deadzone2", "0.25", CV_FLOAT|CV_SAVE, deadzone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
+
+
 typedef enum
 {
 	AXISNONE = 0,
@@ -407,7 +412,6 @@ typedef enum
 	AXISMOVE,
 	AXISLOOK,
 	AXISSTRAFE,
-	AXISDEAD, //Axises that don't want deadzones
 	AXISJUMP,
 	AXISSPIN,
 	AXISFIRE,
@@ -961,10 +965,9 @@ static INT32 Joy2Axis(axis_input_e axissel)
 
 // Take a magnitude of two axes, and adjust it to take out the deadzone
 // Will return a value between 0 and JOYAXISRANGE
-static INT32 G_BasicDeadZoneCalculation(INT32 magnitude)
+static INT32 G_BasicDeadZoneCalculation(INT32 magnitude, fixed_t deadZone)
 {
-	// TODO: console variable for deadzone setting
-	const INT32 jdeadzone = JOYAXISRANGE/4;
+	const INT32 jdeadzone = (JOYAXISRANGE * deadZone) / FRACUNIT;
 	INT32 deadzoneAppliedValue = 0;
 
 	if (jdeadzone > 0)
@@ -987,10 +990,12 @@ static INT32 G_BasicDeadZoneCalculation(INT32 magnitude)
 static void G_HandleAxisDeadZone(UINT8 splitnum, joystickvector2_t *joystickvector)
 {
 	INT32 gamepadStyle = Joystick.bGamepadStyle;
+	fixed_t deadZone = cv_deadzone.value;
 
 	if (splitnum == 1)
 	{
 		gamepadStyle = Joystick2.bGamepadStyle;
+		deadZone = cv_deadzone2.value;
 	}
 
 	// When gamepadstyle is "true" the values are just -1, 0, or 1. This is done in the interface code.
@@ -998,22 +1003,22 @@ static void G_HandleAxisDeadZone(UINT8 splitnum, joystickvector2_t *joystickvect
 	{
 		// Get the total magnitude of the 2 axes
 		INT32 magnitude = (joystickvector->xaxis * joystickvector->xaxis) + (joystickvector->yaxis * joystickvector->yaxis);
-		INT32 normalisedxaxis;
-		INT32 normalisedyaxis;
+		INT32 normalisedXAxis;
+		INT32 normalisedYAxis;
 		INT32 normalisedMagnitude;
 		double dMagnitude = sqrt((double)magnitude);
 		magnitude = (INT32)dMagnitude;
 
 		// Get the normalised xy values from the magnitude
-		normalisedxaxis = (joystickvector->xaxis * magnitude) / JOYAXISRANGE;
-		normalisedyaxis = (joystickvector->yaxis * magnitude) / JOYAXISRANGE;
+		normalisedXAxis = (joystickvector->xaxis * magnitude) / JOYAXISRANGE;
+		normalisedYAxis = (joystickvector->yaxis * magnitude) / JOYAXISRANGE;
 
 		// Apply the deadzone to the magnitude to give a correct value between 0 and JOYAXISRANGE
-		normalisedMagnitude = G_BasicDeadZoneCalculation(magnitude);
+		normalisedMagnitude = G_BasicDeadZoneCalculation(magnitude, deadZone);
 
 		// Apply the deadzone to the xy axes
-		joystickvector->xaxis = (normalisedxaxis * normalisedMagnitude) / JOYAXISRANGE;
-		joystickvector->yaxis = (normalisedyaxis * normalisedMagnitude) / JOYAXISRANGE;
+		joystickvector->xaxis = (normalisedXAxis * normalisedMagnitude) / JOYAXISRANGE;
+		joystickvector->yaxis = (normalisedYAxis * normalisedMagnitude) / JOYAXISRANGE;
 
 		// Cap the values so they don't go above the correct maximum
 		joystickvector->xaxis = min(joystickvector->xaxis, JOYAXISRANGE);
diff --git a/src/g_game.h b/src/g_game.h
index e7f4a4677..c19faebe4 100644
--- a/src/g_game.h
+++ b/src/g_game.h
@@ -72,6 +72,7 @@ extern consvar_t cv_useranalog, cv_useranalog2;
 extern consvar_t cv_analog, cv_analog2;
 extern consvar_t cv_directionchar, cv_directionchar2;
 extern consvar_t cv_autobrake, cv_autobrake2;
+extern consvar_t cv_deadzone, cv_deadzone2;
 extern consvar_t cv_sideaxis,cv_turnaxis,cv_moveaxis,cv_lookaxis,cv_jumpaxis,cv_spinaxis,cv_fireaxis,cv_firenaxis;
 extern consvar_t cv_sideaxis2,cv_turnaxis2,cv_moveaxis2,cv_lookaxis2,cv_jumpaxis2,cv_spinaxis2,cv_fireaxis2,cv_firenaxis2;
 extern consvar_t cv_ghost_bestscore, cv_ghost_besttime, cv_ghost_bestrings, cv_ghost_last, cv_ghost_guest;
diff --git a/src/m_menu.c b/src/m_menu.c
index e367041e0..cbcc3bdb6 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -1119,6 +1119,8 @@ static menuitem_t OP_Joystick1Menu[] =
 
 	{IT_STRING | IT_CVAR, NULL, "First-Person Vert-Look", &cv_alwaysfreelook, 120},
 	{IT_STRING | IT_CVAR, NULL, "Third-Person Vert-Look", &cv_chasefreelook,  130},
+	{IT_STRING | IT_CVAR | IT_CV_FLOATSLIDER,
+	                      NULL, "Deadzone",               &cv_deadzone,       140 },
 };
 
 static menuitem_t OP_Joystick2Menu[] =
@@ -1135,6 +1137,8 @@ static menuitem_t OP_Joystick2Menu[] =
 
 	{IT_STRING | IT_CVAR, NULL, "First-Person Vert-Look", &cv_alwaysfreelook2,120},
 	{IT_STRING | IT_CVAR, NULL, "Third-Person Vert-Look", &cv_chasefreelook2, 130},
+	{IT_STRING | IT_CVAR | IT_CV_FLOATSLIDER,
+	                      NULL, "Deadzone",               &cv_deadzone2,      140 },
 };
 
 static menuitem_t OP_JoystickSetMenu[1+MAX_JOYSTICKS];
@@ -3025,7 +3029,7 @@ boolean M_Responder(event_t *ev)
 		}
 		else if (ev->type == ev_joystick  && ev->data1 == 0 && joywait < I_GetTime())
 		{
-			const INT32 jdeadzone = JOYAXISRANGE/4;
+			const INT32 jdeadzone = (JOYAXISRANGE * cv_deadzone.value) / FRACUNIT;
 			if (ev->data3 != INT32_MAX)
 			{
 				if (Joystick.bGamepadStyle || abs(ev->data3) > jdeadzone)