diff --git a/src/g_game.c b/src/g_game.c
index a76d4770ec6135e85da6aefdd01f3d197c11c505..1e97f08cbb63bc878d44792427cb49fa628af725 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -391,7 +391,7 @@ static CV_PossibleValue_t joyaxis_cons_t[] = {{0, "None"},
 {7, "LAnalog"}, {8, "RAnalog"}, {-7, "LAnalog-"}, {-8, "RAnalog-"},
 #endif
 #else
-{1, "X-Axis"}, {2, "Y-Axis"}, {-1, "X-Axis-"}, {-2, "Y-Axis-"},
+{1, "Left X"}, {2, "Left Y"}, {-1, "Left X-"}, {-2, "Left Y-"},
 #ifdef _arch_dreamcast
 {3, "R-Trig"}, {4, "L-Trig"}, {-3, "R-Trig-"}, {-4, "L-Trig-"},
 {5, "Alt X-Axis"}, {6, "Alt Y-Axis"}, {-5, "Alt X-Axis-"}, {-6, "Alt Y-Axis-"},
@@ -400,10 +400,10 @@ static CV_PossibleValue_t joyaxis_cons_t[] = {{0, "None"},
 {3, "Alt X-Axis"}, {4, "Alt Y-Axis"}, {-3, "Alt X-Axis-"}, {-4, "Alt Y-Axis-"},
 #else
 #if JOYAXISSET > 1
-{3, "Z-Axis"}, {4, "X-Rudder"}, {-3, "Z-Axis-"}, {-4, "X-Rudder-"},
+{3, "Right X"}, {4, "Right Y"}, {-3, "Right X-"}, {-4, "Right Y-"},
 #endif
 #if JOYAXISSET > 2
-{5, "Y-Rudder"}, {6, "Z-Rudder"}, {-5, "Y-Rudder-"}, {-6, "Z-Rudder-"},
+{5, "L Trigger"}, {6, "R Trigger"}, {-5, "L Trigger-"}, {-6, "R Trigger-"},
 #endif
 #if JOYAXISSET > 3
 {7, "U-Axis"}, {8, "V-Axis"}, {-7, "U-Axis-"}, {-8, "V-Axis-"},
@@ -486,40 +486,40 @@ consvar_t cv_useranalog3 = {"useranalog3", "Off", CV_SAVE|CV_CALL, CV_OnOff, Use
 consvar_t cv_useranalog4 = {"useranalog4", "Off", CV_SAVE|CV_CALL, CV_OnOff, UserAnalog4_OnChange, 0, NULL, NULL, 0, 0, NULL};
 #endif
 
-consvar_t cv_turnaxis = {"joyaxis_turn", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_turnaxis = {"joyaxis_turn", "Left X", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_moveaxis = {"joyaxis_move", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_brakeaxis = {"joyaxis_brake", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
-consvar_t cv_aimaxis = {"joyaxis_aim", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_aimaxis = {"joyaxis_aim", "Left Y", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_lookaxis = {"joyaxis_look", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_fireaxis = {"joyaxis_fire", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_driftaxis = {"joyaxis_drift", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_xdeadzone = {"joy_xdeadzone", "0.3", CV_FLOAT|CV_SAVE, deadzone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_ydeadzone = {"joy_ydeadzone", "0.5", CV_FLOAT|CV_SAVE, deadzone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 
-consvar_t cv_turnaxis2 = {"joyaxis2_turn", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_turnaxis2 = {"joyaxis2_turn", "Left X", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_moveaxis2 = {"joyaxis2_move", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_brakeaxis2 = {"joyaxis2_brake", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
-consvar_t cv_aimaxis2 = {"joyaxis2_aim", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_aimaxis2 = {"joyaxis2_aim", "Left Y", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_lookaxis2 = {"joyaxis2_look", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_fireaxis2 = {"joyaxis2_fire", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_driftaxis2 = {"joyaxis2_drift", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_xdeadzone2 = {"joy2_xdeadzone", "0.3", CV_FLOAT|CV_SAVE, deadzone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_ydeadzone2 = {"joy2_ydeadzone", "0.5", CV_FLOAT|CV_SAVE, deadzone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 
-consvar_t cv_turnaxis3 = {"joyaxis3_turn", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_turnaxis3 = {"joyaxis3_turn", "Left X", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_moveaxis3 = {"joyaxis3_move", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_brakeaxis3 = {"joyaxis3_brake", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
-consvar_t cv_aimaxis3 = {"joyaxis3_aim", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_aimaxis3 = {"joyaxis3_aim", "Left Y", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_lookaxis3 = {"joyaxis3_look", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_fireaxis3 = {"joyaxis3_fire", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_driftaxis3 = {"joyaxis3_drift", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_xdeadzone3 = {"joy3_xdeadzone", "0.3", CV_FLOAT|CV_SAVE, deadzone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_ydeadzone3 = {"joy3_ydeadzone", "0.5", CV_FLOAT|CV_SAVE, deadzone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 
-consvar_t cv_turnaxis4 = {"joyaxis4_turn", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_turnaxis4 = {"joyaxis4_turn", "Left X", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_moveaxis4 = {"joyaxis4_move", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_brakeaxis4 = {"joyaxis4_brake", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
-consvar_t cv_aimaxis4 = {"joyaxis4_aim", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_aimaxis4 = {"joyaxis4_aim", "Left Y", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_lookaxis4 = {"joyaxis4_look", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_fireaxis4 = {"joyaxis4_fire", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_driftaxis4 = {"joyaxis4_drift", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c
index 8cb479b864841d74d83cb84a784bd9f798ce628d..2372950339617ca6a5e283e13624b972328c2995 100644
--- a/src/sdl/i_system.c
+++ b/src/sdl/i_system.c
@@ -201,7 +201,7 @@ static void JoyReset(SDLJoyInfo_t *JoySet)
 {
 	if (JoySet->dev)
 	{
-		SDL_JoystickClose(JoySet->dev);
+		SDL_GameControllerClose(JoySet->dev);
 	}
 	JoySet->dev = NULL;
 	JoySet->oldjoy = -1;
@@ -884,17 +884,15 @@ void I_JoyScale4(void)
 }
 
 // Cheat to get the device index for a joystick handle
-INT32 I_GetJoystickDeviceIndex(SDL_Joystick *dev)
+INT32 I_GetJoystickDeviceIndex(SDL_GameController *dev)
 {
-	INT32 i, count = SDL_NumJoysticks();
+	SDL_Joystick *joystick = NULL;
 
-	for (i = 0; dev && i < count; i++)
+	joystick = SDL_GameControllerGetJoystick(dev);
+	
+	if (joystick)
 	{
-		SDL_Joystick *test = SDL_JoystickOpen(i);
-		if (test && test == dev)
-			return i;
-		else if (JoyInfo.dev != test && JoyInfo2.dev != test && JoyInfo3.dev != test && JoyInfo4.dev != test)
-			SDL_JoystickClose(test);
+		return SDL_JoystickInstanceID(joystick);
 	}
 
 	return -1;
@@ -1196,15 +1194,10 @@ void I_GetJoystickEvents(void)
 	}
 #endif
 
-	for (i = JoyInfo.hats - 1; i >= 0; i--)
-	{
-		Uint8 hat = SDL_JoystickGetHat(JoyInfo.dev, i);
-
-		if (hat & SDL_HAT_UP   ) joyhats|=(UINT64)0x1<<(0 + 4*i);
-		if (hat & SDL_HAT_DOWN ) joyhats|=(UINT64)0x1<<(1 + 4*i);
-		if (hat & SDL_HAT_LEFT ) joyhats|=(UINT64)0x1<<(2 + 4*i);
-		if (hat & SDL_HAT_RIGHT) joyhats|=(UINT64)0x1<<(3 + 4*i);
-	}
+	joyhats |= SDL_GameControllerGetButton(JoyInfo.dev, SDL_CONTROLLER_BUTTON_DPAD_UP);
+	joyhats |= SDL_GameControllerGetButton(JoyInfo.dev, SDL_CONTROLLER_BUTTON_DPAD_DOWN) << 1;
+	joyhats |= SDL_GameControllerGetButton(JoyInfo.dev, SDL_CONTROLLER_BUTTON_DPAD_LEFT) << 2;
+	joyhats |= SDL_GameControllerGetButton(JoyInfo.dev, SDL_CONTROLLER_BUTTON_DPAD_RIGHT) << 3;
 
 	if (joyhats != lastjoyhats)
 	{
@@ -1290,7 +1283,7 @@ void I_GetJoystickEvents(void)
 */
 static int joy_open(int joyindex)
 {
-	SDL_Joystick *newdev = NULL;
+	SDL_GameController *newdev = NULL;
 	int num_joy = 0;
 
 	if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0)
@@ -1298,6 +1291,11 @@ static int joy_open(int joyindex)
 		CONS_Printf(M_GetText("Joystick subsystem not started\n"));
 		return -1;
 	}
+	if (SDL_WasInit(SDL_INIT_GAMECONTROLLER) == 0)
+	{
+		CONS_Printf(M_GetText("Game Controller subsystem not started\n"));
+		return -1;
+	}
 
 	if (joyindex <= 0)
 		return -1;
@@ -1310,7 +1308,7 @@ static int joy_open(int joyindex)
 		return -1;
 	}
 
-	newdev = SDL_JoystickOpen(joyindex-1);
+	newdev = SDL_GameControllerOpen(joyindex-1);
 
 	// Handle the edge case where the device <-> joystick index assignment can change due to hotplugging
 	// This indexing is SDL's responsibility and there's not much we can do about it.
@@ -1325,8 +1323,8 @@ static int joy_open(int joyindex)
 	if (JoyInfo.dev)
 	{
 		if (JoyInfo.dev == newdev // same device, nothing to do
-			|| (newdev == NULL && SDL_JoystickGetAttached(JoyInfo.dev))) // we failed, but already have a working device
-			return JoyInfo.axises;
+			|| (newdev == NULL && SDL_GameControllerGetAttached(JoyInfo.dev))) // we failed, but already have a working device
+			return SDL_CONTROLLER_AXIS_MAX;
 		// Else, we're changing devices, so send neutral joy events
 		CONS_Debug(DBG_GAMELOGIC, "Joystick1 device is changing; resetting events...\n");
 		I_ShutdownJoystick();
@@ -1341,8 +1339,8 @@ static int joy_open(int joyindex)
 	}
 	else
 	{
-		CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick1: %s\n"), SDL_JoystickName(JoyInfo.dev));
-		JoyInfo.axises = SDL_JoystickNumAxes(JoyInfo.dev);
+		CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick1: %s\n"), SDL_GameControllerName(JoyInfo.dev));
+		JoyInfo.axises = SDL_CONTROLLER_AXIS_MAX;
 		if (JoyInfo.axises > JOYAXISSET*2)
 			JoyInfo.axises = JOYAXISSET*2;
 	/*		if (joyaxes<2)
@@ -1351,15 +1349,15 @@ static int joy_open(int joyindex)
 			return 0;
 		}*/
 
-		JoyInfo.buttons = SDL_JoystickNumButtons(JoyInfo.dev);
+		JoyInfo.buttons = SDL_CONTROLLER_BUTTON_MAX ; // dpad is 4 buttons
 		if (JoyInfo.buttons > JOYBUTTONS)
 			JoyInfo.buttons = JOYBUTTONS;
 
-		JoyInfo.hats = SDL_JoystickNumHats(JoyInfo.dev);
+		JoyInfo.hats = 4;
 		if (JoyInfo.hats > JOYHATS)
 			JoyInfo.hats = JOYHATS;
 
-		JoyInfo.balls = SDL_JoystickNumBalls(JoyInfo.dev);
+		JoyInfo.balls = 0;
 
 		//Joystick.bGamepadStyle = !stricmp(SDL_JoystickName(JoyInfo.dev), "pad");
 
@@ -1468,15 +1466,10 @@ void I_GetJoystick2Events(void)
 	}
 #endif
 
-	for (i = JoyInfo2.hats - 1; i >= 0; i--)
-	{
-		Uint8 hat = SDL_JoystickGetHat(JoyInfo2.dev, i);
-
-		if (hat & SDL_HAT_UP   ) joyhats|=(UINT64)0x1<<(0 + 4*i);
-		if (hat & SDL_HAT_DOWN ) joyhats|=(UINT64)0x1<<(1 + 4*i);
-		if (hat & SDL_HAT_LEFT ) joyhats|=(UINT64)0x1<<(2 + 4*i);
-		if (hat & SDL_HAT_RIGHT) joyhats|=(UINT64)0x1<<(3 + 4*i);
-	}
+	joyhats |= SDL_GameControllerGetButton(JoyInfo2.dev, SDL_CONTROLLER_BUTTON_DPAD_UP);
+	joyhats |= SDL_GameControllerGetButton(JoyInfo2.dev, SDL_CONTROLLER_BUTTON_DPAD_DOWN) << 1;
+	joyhats |= SDL_GameControllerGetButton(JoyInfo2.dev, SDL_CONTROLLER_BUTTON_DPAD_LEFT) << 2;
+	joyhats |= SDL_GameControllerGetButton(JoyInfo2.dev, SDL_CONTROLLER_BUTTON_DPAD_RIGHT) << 3;
 
 	if (joyhats != lastjoy2hats)
 	{
@@ -1562,7 +1555,7 @@ void I_GetJoystick2Events(void)
 */
 static int joy_open2(int joyindex)
 {
-	SDL_Joystick *newdev = NULL;
+	SDL_GameController *newdev = NULL;
 	int num_joy = 0;
 
 	if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0)
@@ -1570,6 +1563,11 @@ static int joy_open2(int joyindex)
 		CONS_Printf(M_GetText("Joystick subsystem not started\n"));
 		return -1;
 	}
+	if (SDL_WasInit(SDL_INIT_GAMECONTROLLER) == 0)
+	{
+		CONS_Printf(M_GetText("Game Controller subsystem not started\n"));
+		return -1;
+	}
 
 	if (joyindex <= 0)
 		return -1;
@@ -1582,7 +1580,7 @@ static int joy_open2(int joyindex)
 		return -1;
 	}
 
-	newdev = SDL_JoystickOpen(joyindex-1);
+	newdev = SDL_GameControllerOpen(joyindex-1);
 
 	// Handle the edge case where the device <-> joystick index assignment can change due to hotplugging
 	// This indexing is SDL's responsibility and there's not much we can do about it.
@@ -1597,8 +1595,8 @@ static int joy_open2(int joyindex)
 	if (JoyInfo2.dev)
 	{
 		if (JoyInfo2.dev == newdev // same device, nothing to do
-			|| (newdev == NULL && SDL_JoystickGetAttached(JoyInfo2.dev))) // we failed, but already have a working device
-			return JoyInfo.axises;
+			|| (newdev == NULL && SDL_GameControllerGetAttached(JoyInfo2.dev))) // we failed, but already have a working device
+			return SDL_CONTROLLER_AXIS_MAX;
 		// Else, we're changing devices, so send neutral joy events
 		CONS_Debug(DBG_GAMELOGIC, "Joystick2 device is changing; resetting events...\n");
 		I_ShutdownJoystick2();
@@ -1613,8 +1611,8 @@ static int joy_open2(int joyindex)
 	}
 	else
 	{
-		CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick2: %s\n"), SDL_JoystickName(JoyInfo2.dev));
-		JoyInfo2.axises = SDL_JoystickNumAxes(JoyInfo2.dev);
+		CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick2: %s\n"), SDL_GameControllerName(JoyInfo2.dev));
+		JoyInfo2.axises = SDL_CONTROLLER_AXIS_MAX;
 		if (JoyInfo2.axises > JOYAXISSET*2)
 			JoyInfo2.axises = JOYAXISSET*2;
 /*		if (joyaxes<2)
@@ -1623,15 +1621,15 @@ static int joy_open2(int joyindex)
 			return 0;
 		}*/
 
-		JoyInfo2.buttons = SDL_JoystickNumButtons(JoyInfo2.dev);
+		JoyInfo2.buttons = SDL_CONTROLLER_BUTTON_MAX ; // dpad is 4 buttons
 		if (JoyInfo2.buttons > JOYBUTTONS)
 			JoyInfo2.buttons = JOYBUTTONS;
 
-		JoyInfo2.hats = SDL_JoystickNumHats(JoyInfo2.dev);
+		JoyInfo2.hats = 4;
 		if (JoyInfo2.hats > JOYHATS)
 			JoyInfo2.hats = JOYHATS;
 
-		JoyInfo2.balls = SDL_JoystickNumBalls(JoyInfo2.dev);
+		JoyInfo2.balls = 0;
 
 		//Joystick.bGamepadStyle = !stricmp(SDL_JoystickName(JoyInfo2.dev), "pad");
 
@@ -1740,15 +1738,10 @@ void I_GetJoystick3Events(void)
 	}
 #endif
 
-	for (i = JoyInfo3.hats - 1; i >= 0; i--)
-	{
-		Uint8 hat = SDL_JoystickGetHat(JoyInfo3.dev, i);
-
-		if (hat & SDL_HAT_UP   ) joyhats|=(UINT64)0x1<<(0 + 4*i);
-		if (hat & SDL_HAT_DOWN ) joyhats|=(UINT64)0x1<<(1 + 4*i);
-		if (hat & SDL_HAT_LEFT ) joyhats|=(UINT64)0x1<<(2 + 4*i);
-		if (hat & SDL_HAT_RIGHT) joyhats|=(UINT64)0x1<<(3 + 4*i);
-	}
+	joyhats |= SDL_GameControllerGetButton(JoyInfo3.dev, SDL_CONTROLLER_BUTTON_DPAD_UP);
+	joyhats |= SDL_GameControllerGetButton(JoyInfo3.dev, SDL_CONTROLLER_BUTTON_DPAD_DOWN) << 1;
+	joyhats |= SDL_GameControllerGetButton(JoyInfo3.dev, SDL_CONTROLLER_BUTTON_DPAD_LEFT) << 2;
+	joyhats |= SDL_GameControllerGetButton(JoyInfo3.dev, SDL_CONTROLLER_BUTTON_DPAD_RIGHT) << 3;
 
 	if (joyhats != lastjoy3hats)
 	{
@@ -1770,6 +1763,7 @@ void I_GetJoystick3Events(void)
 		}
 	}
 
+#if 0
 	// send joystick axis positions
 	event.type = ev_joystick3;
 
@@ -1820,7 +1814,7 @@ void I_GetJoystick3Events(void)
 		}
 		D_PostEvent(&event);
 	}
-
+#endif
 }
 
 /**	\brief	Open joystick handle
@@ -1833,7 +1827,7 @@ void I_GetJoystick3Events(void)
 */
 static int joy_open3(int joyindex)
 {
-	SDL_Joystick *newdev = NULL;
+	SDL_GameController *newdev = NULL;
 	int num_joy = 0;
 
 	if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0)
@@ -1841,6 +1835,11 @@ static int joy_open3(int joyindex)
 		CONS_Printf(M_GetText("Joystick subsystem not started\n"));
 		return -1;
 	}
+	if (SDL_WasInit(SDL_INIT_GAMECONTROLLER) == 0)
+	{
+		CONS_Printf(M_GetText("Game Controller subsystem not started\n"));
+		return -1;
+	}
 
 	if (joyindex <= 0)
 		return -1;
@@ -1853,7 +1852,7 @@ static int joy_open3(int joyindex)
 		return -1;
 	}
 
-	newdev = SDL_JoystickOpen(joyindex - 1);
+	newdev = SDL_GameControllerOpen(joyindex - 1);
 
 	// Handle the edge case where the device <-> joystick index assignment can change due to hotplugging
 	// This indexing is SDL's responsibility and there's not much we can do about it.
@@ -1868,8 +1867,8 @@ static int joy_open3(int joyindex)
 	if (JoyInfo3.dev)
 	{
 		if (JoyInfo3.dev == newdev // same device, nothing to do
-			|| (newdev == NULL && SDL_JoystickGetAttached(JoyInfo3.dev))) // we failed, but already have a working device
-			return JoyInfo.axises;
+			|| (newdev == NULL && SDL_GameControllerGetAttached(JoyInfo3.dev))) // we failed, but already have a working device
+			return SDL_CONTROLLER_AXIS_MAX;
 		// Else, we're changing devices, so send neutral joy events
 		CONS_Debug(DBG_GAMELOGIC, "Joystick3 device is changing; resetting events...\n");
 		I_ShutdownJoystick3();
@@ -1884,8 +1883,8 @@ static int joy_open3(int joyindex)
 	}
 	else
 	{
-		CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick3: %s\n"), SDL_JoystickName(JoyInfo3.dev));
-		JoyInfo3.axises = SDL_JoystickNumAxes(JoyInfo3.dev);
+		CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick3: %s\n"), SDL_GameControllerName(JoyInfo3.dev));
+		JoyInfo3.axises = SDL_CONTROLLER_AXIS_MAX;
 		if (JoyInfo3.axises > JOYAXISSET * 2)
 			JoyInfo3.axises = JOYAXISSET * 2;
 		/*		if (joyaxes<2)
@@ -1894,15 +1893,15 @@ static int joy_open3(int joyindex)
 		return 0;
 		}*/
 
-		JoyInfo3.buttons = SDL_JoystickNumButtons(JoyInfo3.dev);
+		JoyInfo3.buttons = SDL_CONTROLLER_BUTTON_MAX ; // dpad is 4 buttons
 		if (JoyInfo3.buttons > JOYBUTTONS)
 			JoyInfo3.buttons = JOYBUTTONS;
 
-		JoyInfo3.hats = SDL_JoystickNumHats(JoyInfo3.dev);
+		JoyInfo3.hats = 4;
 		if (JoyInfo3.hats > JOYHATS)
 			JoyInfo3.hats = JOYHATS;
 
-		JoyInfo3.balls = SDL_JoystickNumBalls(JoyInfo3.dev);
+		JoyInfo3.balls = 0;
 
 		//Joystick.bGamepadStyle = !stricmp(SDL_JoystickName(JoyInfo3.dev), "pad");
 
@@ -2011,15 +2010,10 @@ void I_GetJoystick4Events(void)
 	}
 #endif
 
-	for (i = JoyInfo4.hats - 1; i >= 0; i--)
-	{
-		Uint8 hat = SDL_JoystickGetHat(JoyInfo4.dev, i);
-
-		if (hat & SDL_HAT_UP   ) joyhats|=(UINT64)0x1<<(0 + 4*i);
-		if (hat & SDL_HAT_DOWN ) joyhats|=(UINT64)0x1<<(1 + 4*i);
-		if (hat & SDL_HAT_LEFT ) joyhats|=(UINT64)0x1<<(2 + 4*i);
-		if (hat & SDL_HAT_RIGHT) joyhats|=(UINT64)0x1<<(3 + 4*i);
-	}
+	joyhats |= SDL_GameControllerGetButton(JoyInfo4.dev, SDL_CONTROLLER_BUTTON_DPAD_UP);
+	joyhats |= SDL_GameControllerGetButton(JoyInfo4.dev, SDL_CONTROLLER_BUTTON_DPAD_DOWN) << 1;
+	joyhats |= SDL_GameControllerGetButton(JoyInfo4.dev, SDL_CONTROLLER_BUTTON_DPAD_LEFT) << 2;
+	joyhats |= SDL_GameControllerGetButton(JoyInfo4.dev, SDL_CONTROLLER_BUTTON_DPAD_RIGHT) << 3;
 
 	if (joyhats != lastjoy4hats)
 	{
@@ -2041,6 +2035,7 @@ void I_GetJoystick4Events(void)
 		}
 	}
 
+#if 0
 	// send joystick axis positions
 	event.type = ev_joystick4;
 
@@ -2091,7 +2086,7 @@ void I_GetJoystick4Events(void)
 		}
 		D_PostEvent(&event);
 	}
-
+#endif
 }
 
 /**	\brief	Open joystick handle
@@ -2104,7 +2099,7 @@ void I_GetJoystick4Events(void)
 */
 static int joy_open4(int joyindex)
 {
-	SDL_Joystick *newdev = NULL;
+	SDL_GameController *newdev = NULL;
 	int num_joy = 0;
 
 	if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0)
@@ -2112,6 +2107,11 @@ static int joy_open4(int joyindex)
 		CONS_Printf(M_GetText("Joystick subsystem not started\n"));
 		return -1;
 	}
+	if (SDL_WasInit(SDL_INIT_GAMECONTROLLER) == 0)
+	{
+		CONS_Printf(M_GetText("Game Controller subsystem not started\n"));
+		return -1;
+	}
 
 	if (joyindex <= 0)
 		return -1;
@@ -2124,7 +2124,7 @@ static int joy_open4(int joyindex)
 		return -1;
 	}
 
-	newdev = SDL_JoystickOpen(joyindex - 1);
+	newdev = SDL_GameControllerOpen(joyindex - 1);
 
 	// Handle the edge case where the device <-> joystick index assignment can change due to hotplugging
 	// This indexing is SDL's responsibility and there's not much we can do about it.
@@ -2139,8 +2139,8 @@ static int joy_open4(int joyindex)
 	if (JoyInfo4.dev)
 	{
 		if (JoyInfo4.dev == newdev // same device, nothing to do
-			|| (newdev == NULL && SDL_JoystickGetAttached(JoyInfo4.dev))) // we failed, but already have a working device
-			return JoyInfo.axises;
+			|| (newdev == NULL && SDL_GameControllerGetAttached(JoyInfo4.dev))) // we failed, but already have a working device
+			return SDL_CONTROLLER_AXIS_MAX;
 		// Else, we're changing devices, so send neutral joy events
 		CONS_Debug(DBG_GAMELOGIC, "Joystick4 device is changing; resetting events...\n");
 		I_ShutdownJoystick4();
@@ -2155,8 +2155,8 @@ static int joy_open4(int joyindex)
 	}
 	else
 	{
-		CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick4: %s\n"), SDL_JoystickName(JoyInfo4.dev));
-		JoyInfo4.axises = SDL_JoystickNumAxes(JoyInfo4.dev);
+		CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick4: %s\n"), SDL_GameControllerName(JoyInfo4.dev));
+		JoyInfo4.axises = SDL_CONTROLLER_AXIS_MAX;
 		if (JoyInfo4.axises > JOYAXISSET * 2)
 			JoyInfo4.axises = JOYAXISSET * 2;
 		/*		if (joyaxes<2)
@@ -2165,15 +2165,15 @@ static int joy_open4(int joyindex)
 		return 0;
 		}*/
 
-		JoyInfo4.buttons = SDL_JoystickNumButtons(JoyInfo4.dev);
+		JoyInfo4.buttons = SDL_CONTROLLER_BUTTON_MAX ; // dpad is 4 buttons
 		if (JoyInfo4.buttons > JOYBUTTONS)
 			JoyInfo4.buttons = JOYBUTTONS;
 
-		JoyInfo4.hats = SDL_JoystickNumHats(JoyInfo4.dev);
+		JoyInfo4.hats = 4;
 		if (JoyInfo4.hats > JOYHATS)
 			JoyInfo4.hats = JOYHATS;
 
-		JoyInfo4.balls = SDL_JoystickNumBalls(JoyInfo4.dev);
+		JoyInfo4.balls = 0;
 
 		//Joystick.bGamepadStyle = !stricmp(SDL_JoystickName(JoyInfo4.dev), "pad");
 
@@ -2186,7 +2186,7 @@ static int joy_open4(int joyindex)
 //
 void I_InitJoystick(void)
 {
-	SDL_Joystick *newjoy = NULL;
+	SDL_GameController *newcontroller = NULL;
 
 	//I_ShutdownJoystick();
 	//SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE);
@@ -2209,13 +2209,21 @@ void I_InitJoystick(void)
 			return;
 		}
 	}
+	if (SDL_WasInit(SDL_INIT_GAMECONTROLLER) == 0)
+	{
+		if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) == -1)
+		{
+			CONS_Printf(M_GetText("Couldn't initialize gamepads: %s\n"), SDL_GetError());
+			return;
+		}
+	}
 
 	if (cv_usejoystick.value)
-		newjoy = SDL_JoystickOpen(cv_usejoystick.value-1);
+		newcontroller = SDL_GameControllerOpen(cv_usejoystick.value-1);
 
-	if (newjoy && (JoyInfo2.dev == newjoy || JoyInfo3.dev == newjoy || JoyInfo4.dev == newjoy)) // don't override an active device
+	if (newcontroller && (JoyInfo2.dev == newcontroller || JoyInfo3.dev == newcontroller || JoyInfo4.dev == newcontroller)) // don't override an active device
 		cv_usejoystick.value = I_GetJoystickDeviceIndex(JoyInfo.dev) + 1;
-	else if (newjoy && joy_open(cv_usejoystick.value) != -1)
+	else if (newcontroller && joy_open(cv_usejoystick.value) != -1)
 	{
 		// SDL's device indexes are unstable, so cv_usejoystick may not match
 		// the actual device index. So let's cheat a bit and find the device's current index.
@@ -2230,13 +2238,13 @@ void I_InitJoystick(void)
 		joystick_started = 0;
 	}
 
-	if (JoyInfo.dev != newjoy && JoyInfo2.dev != newjoy && JoyInfo3.dev != newjoy && JoyInfo4.dev != newjoy)
-		SDL_JoystickClose(newjoy);
+	if (JoyInfo.dev != newcontroller && JoyInfo2.dev != newcontroller && JoyInfo3.dev != newcontroller && JoyInfo4.dev != newcontroller)
+		SDL_GameControllerClose(newcontroller);
 }
 
 void I_InitJoystick2(void)
 {
-	SDL_Joystick *newjoy = NULL;
+	SDL_GameController *newcontroller = NULL;
 
 	//I_ShutdownJoystick2();
 	//SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE);
@@ -2252,13 +2260,21 @@ void I_InitJoystick2(void)
 			return;
 		}
 	}
+	if (SDL_WasInit(SDL_INIT_GAMECONTROLLER) == 0)
+	{
+		if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) == -1)
+		{
+			CONS_Printf(M_GetText("Couldn't initialize gamepads: %s\n"), SDL_GetError());
+			return;
+		}
+	}
 
 	if (cv_usejoystick2.value)
-		newjoy = SDL_JoystickOpen(cv_usejoystick2.value-1);
+		newcontroller = SDL_GameControllerOpen(cv_usejoystick2.value-1);
 
-	if (newjoy && (JoyInfo.dev == newjoy || JoyInfo3.dev == newjoy || JoyInfo4.dev == newjoy)) // don't override an active device
+	if (newcontroller && (JoyInfo.dev == newcontroller || JoyInfo3.dev == newcontroller || JoyInfo4.dev == newcontroller)) // don't override an active device
 		cv_usejoystick2.value = I_GetJoystickDeviceIndex(JoyInfo2.dev) + 1;
-	else if (newjoy && joy_open2(cv_usejoystick2.value) != -1)
+	else if (newcontroller && joy_open2(cv_usejoystick2.value) != -1)
 	{
 		// SDL's device indexes are unstable, so cv_usejoystick may not match
 		// the actual device index. So let's cheat a bit and find the device's current index.
@@ -2273,13 +2289,13 @@ void I_InitJoystick2(void)
 		joystick2_started = 0;
 	}
 
-	if (JoyInfo.dev != newjoy && JoyInfo2.dev != newjoy && JoyInfo3.dev != newjoy && JoyInfo4.dev != newjoy)
-		SDL_JoystickClose(newjoy);
+	if (JoyInfo.dev != newcontroller && JoyInfo2.dev != newcontroller && JoyInfo3.dev != newcontroller && JoyInfo4.dev != newcontroller)
+		SDL_GameControllerClose(newcontroller);
 }
 
 void I_InitJoystick3(void)
 {
-	SDL_Joystick *newjoy = NULL;
+	SDL_GameController *newcontroller = NULL;
 
 	//I_ShutdownJoystick3();
 	//SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE);
@@ -2295,13 +2311,21 @@ void I_InitJoystick3(void)
 			return;
 		}
 	}
+	if (SDL_WasInit(SDL_INIT_GAMECONTROLLER) == 0)
+	{
+		if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) == -1)
+		{
+			CONS_Printf(M_GetText("Couldn't initialize gamepads: %s\n"), SDL_GetError());
+			return;
+		}
+	}
 
 	if (cv_usejoystick3.value)
-		newjoy = SDL_JoystickOpen(cv_usejoystick3.value - 1);
+		newcontroller = SDL_GameControllerOpen(cv_usejoystick3.value - 1);
 
-	if (newjoy && (JoyInfo.dev == newjoy || JoyInfo2.dev == newjoy || JoyInfo4.dev == newjoy)) // don't override an active device
+	if (newcontroller && (JoyInfo.dev == newcontroller || JoyInfo2.dev == newcontroller || JoyInfo4.dev == newcontroller)) // don't override an active device
 		cv_usejoystick3.value = I_GetJoystickDeviceIndex(JoyInfo3.dev) + 1;
-	else if (newjoy && joy_open3(cv_usejoystick3.value) != -1)
+	else if (newcontroller && joy_open3(cv_usejoystick3.value) != -1)
 	{
 		// SDL's device indexes are unstable, so cv_usejoystick may not match
 		// the actual device index. So let's cheat a bit and find the device's current index.
@@ -2316,13 +2340,13 @@ void I_InitJoystick3(void)
 		joystick3_started = 0;
 	}
 
-	if (JoyInfo.dev != newjoy && JoyInfo2.dev != newjoy && JoyInfo3.dev != newjoy && JoyInfo4.dev != newjoy)
-		SDL_JoystickClose(newjoy);
+	if (JoyInfo.dev != newcontroller && JoyInfo2.dev != newcontroller && JoyInfo3.dev != newcontroller && JoyInfo4.dev != newcontroller)
+		SDL_GameControllerClose(newcontroller);
 }
 
 void I_InitJoystick4(void)
 {
-	SDL_Joystick *newjoy = NULL;
+	SDL_GameController *newcontroller = NULL;
 
 	//I_ShutdownJoystick4();
 	//SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE);
@@ -2338,13 +2362,21 @@ void I_InitJoystick4(void)
 			return;
 		}
 	}
+	if (SDL_WasInit(SDL_INIT_GAMECONTROLLER) == 0)
+	{
+		if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) == -1)
+		{
+			CONS_Printf(M_GetText("Couldn't initialize gamepads: %s\n"), SDL_GetError());
+			return;
+		}
+	}
 
 	if (cv_usejoystick4.value)
-		newjoy = SDL_JoystickOpen(cv_usejoystick4.value - 1);
+		newcontroller = SDL_GameControllerOpen(cv_usejoystick4.value - 1);
 
-	if (newjoy && (JoyInfo.dev == newjoy || JoyInfo2.dev == newjoy || JoyInfo4.dev == newjoy)) // don't override an active device
+	if (newcontroller && (JoyInfo.dev == newcontroller || JoyInfo2.dev == newcontroller || JoyInfo4.dev == newcontroller)) // don't override an active device
 		cv_usejoystick4.value = I_GetJoystickDeviceIndex(JoyInfo4.dev) + 1;
-	else if (newjoy && joy_open4(cv_usejoystick4.value) != -1)
+	else if (newcontroller && joy_open4(cv_usejoystick4.value) != -1)
 	{
 		// SDL's device indexes are unstable, so cv_usejoystick may not match
 		// the actual device index. So let's cheat a bit and find the device's current index.
@@ -2359,8 +2391,8 @@ void I_InitJoystick4(void)
 		joystick4_started = 0;
 	}
 
-	if (JoyInfo.dev != newjoy && JoyInfo2.dev != newjoy && JoyInfo3.dev != newjoy && JoyInfo4.dev != newjoy)
-		SDL_JoystickClose(newjoy);
+	if (JoyInfo.dev != newcontroller && JoyInfo2.dev != newcontroller && JoyInfo3.dev != newcontroller && JoyInfo4.dev != newcontroller)
+		SDL_GameControllerClose(newcontroller);
 }
 
 static void I_ShutdownInput(void)
@@ -2373,6 +2405,13 @@ static void I_ShutdownInput(void)
 	I_ShutdownJoystick3();
 	I_ShutdownJoystick4();
 
+	if (SDL_WasInit(SDL_INIT_GAMECONTROLLER) == SDL_INIT_GAMECONTROLLER)
+	{
+		CONS_Printf("Shutting down gamecontroller system\n");
+		SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER);
+		I_OutputMsg("I_Joystick: SDL's Game Controller system has been shutdown\n");
+	}
+
 	if (SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK)
 	{
 		CONS_Printf("Shutting down joy system\n");
diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c
index 02bea08d562e20a48ee27af59a11cb4d5df6a891..b3771ebaf17ba12295429fc98f6382751fca6b76 100644
--- a/src/sdl/i_video.c
+++ b/src/sdl/i_video.c
@@ -788,18 +788,18 @@ static void Impl_HandleMouseWheelEvent(SDL_MouseWheelEvent evt)
 	}
 }
 
-static void Impl_HandleJoystickAxisEvent(SDL_JoyAxisEvent evt)
+static void Impl_HandleControllerAxisEvent(SDL_ControllerAxisEvent evt)
 {
 	event_t event;
 	SDL_JoystickID joyid[4];
+	int32_t value;
 
 	// Determine the Joystick IDs for each current open joystick
-	joyid[0] = SDL_JoystickInstanceID(JoyInfo.dev);
-	joyid[1] = SDL_JoystickInstanceID(JoyInfo2.dev);
-	joyid[2] = SDL_JoystickInstanceID(JoyInfo3.dev);
-	joyid[3] = SDL_JoystickInstanceID(JoyInfo4.dev);
+	joyid[0] = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(JoyInfo.dev));
+	joyid[1] = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(JoyInfo2.dev));
+	joyid[2] = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(JoyInfo3.dev));
+	joyid[3] = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(JoyInfo4.dev));
 
-	evt.axis++;
 	event.data1 = event.data2 = event.data3 = INT32_MAX;
 
 	if (evt.which == joyid[0])
@@ -823,16 +823,35 @@ static void Impl_HandleJoystickAxisEvent(SDL_JoyAxisEvent evt)
 	if (evt.axis > JOYAXISSET*2)
 		return;
 	//vaule
-	if (evt.axis%2)
-	{
-		event.data1 = evt.axis / 2;
-		event.data2 = SDLJoyAxis(evt.value, event.type);
-	}
-	else
+	value = SDLJoyAxis(evt.value, event.type);
+	switch (evt.axis)
 	{
-		evt.axis--;
-		event.data1 = evt.axis / 2;
-		event.data3 = SDLJoyAxis(evt.value, event.type);
+		case SDL_CONTROLLER_AXIS_LEFTX:
+			event.data1 = 0;
+			event.data2 = SDLJoyAxis(evt.value, event.type);
+			break;
+		case SDL_CONTROLLER_AXIS_LEFTY:
+			event.data1 = 0;
+			event.data3 = SDLJoyAxis(evt.value, event.type);
+			break;
+		case SDL_CONTROLLER_AXIS_RIGHTX:
+			event.data1 = 1;
+			event.data2 = SDLJoyAxis(evt.value, event.type);
+			break;
+		case SDL_CONTROLLER_AXIS_RIGHTY:
+			event.data1 = 1;
+			event.data3 = SDLJoyAxis(evt.value, event.type);
+			break;
+		case SDL_CONTROLLER_AXIS_TRIGGERLEFT:
+			event.data1 = 2;
+			event.data2 = SDLJoyAxis(evt.value, event.type);
+			break;
+		case SDL_CONTROLLER_AXIS_TRIGGERRIGHT:
+			event.data1 = 2;
+			event.data3 = SDLJoyAxis(evt.value, event.type);
+			break;
+		default:
+			return;
 	}
 	D_PostEvent(&event);
 }
@@ -864,16 +883,25 @@ static void Impl_HandleJoystickHatEvent(SDL_JoyHatEvent evt)
 }
 #endif
 
-static void Impl_HandleJoystickButtonEvent(SDL_JoyButtonEvent evt, Uint32 type)
+static void Impl_HandleControllerButtonEvent(SDL_ControllerButtonEvent evt, Uint32 type)
 {
 	event_t event;
 	SDL_JoystickID joyid[4];
 
 	// Determine the Joystick IDs for each current open joystick
-	joyid[0] = SDL_JoystickInstanceID(JoyInfo.dev);
-	joyid[1] = SDL_JoystickInstanceID(JoyInfo2.dev);
-	joyid[2] = SDL_JoystickInstanceID(JoyInfo3.dev);
-	joyid[3] = SDL_JoystickInstanceID(JoyInfo4.dev);
+	joyid[0] = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(JoyInfo.dev));
+	joyid[1] = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(JoyInfo2.dev));
+	joyid[2] = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(JoyInfo3.dev));
+	joyid[3] = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(JoyInfo4.dev));
+
+	if (evt.button == SDL_CONTROLLER_BUTTON_DPAD_UP
+		|| evt.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN
+		|| evt.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT
+		|| evt.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT)
+	{
+		// dpad buttons are mapped as the hat instead
+		return;
+	}
 
 	if (evt.which == joyid[0])
 	{
@@ -892,11 +920,11 @@ static void Impl_HandleJoystickButtonEvent(SDL_JoyButtonEvent evt, Uint32 type)
 		event.data1 = KEY_4JOY1;
 	}
 	else return;
-	if (type == SDL_JOYBUTTONUP)
+	if (type == SDL_CONTROLLERBUTTONUP)
 	{
 		event.type = ev_keyup;
 	}
-	else if (type == SDL_JOYBUTTONDOWN)
+	else if (type == SDL_CONTROLLERBUTTONDOWN)
 	{
 		event.type = ev_keydown;
 	}
@@ -950,26 +978,26 @@ void I_GetEvent(void)
 			case SDL_MOUSEWHEEL:
 				Impl_HandleMouseWheelEvent(evt.wheel);
 				break;
-			case SDL_JOYAXISMOTION:
-				Impl_HandleJoystickAxisEvent(evt.jaxis);
+			case SDL_CONTROLLERAXISMOTION:
+				Impl_HandleControllerAxisEvent(evt.caxis);
 				break;
 #if 0
 			case SDL_JOYHATMOTION:
 				Impl_HandleJoystickHatEvent(evt.jhat)
 				break;
 #endif
-			case SDL_JOYBUTTONUP:
-			case SDL_JOYBUTTONDOWN:
-				Impl_HandleJoystickButtonEvent(evt.jbutton, evt.type);
+			case SDL_CONTROLLERBUTTONUP:
+			case SDL_CONTROLLERBUTTONDOWN:
+				Impl_HandleControllerButtonEvent(evt.cbutton, evt.type);
 				break;
 
 			////////////////////////////////////////////////////////////
 
-			case SDL_JOYDEVICEADDED:
+			case SDL_CONTROLLERDEVICEADDED:
 				{
 					// OH BOY are you in for a good time! #abominationstation
 
-					SDL_Joystick *newjoy = SDL_JoystickOpen(evt.jdevice.which);
+					SDL_GameController *newcontroller = SDL_GameControllerOpen(evt.cdevice.which);
 
 					CONS_Debug(DBG_GAMELOGIC, "Joystick device index %d added\n", evt.jdevice.which + 1);
 
@@ -988,10 +1016,10 @@ void I_GetEvent(void)
 					// PLAYER 1
 					//////////////////////////////
 
-					if (newjoy && (!JoyInfo.dev || !SDL_JoystickGetAttached(JoyInfo.dev))
-						&& JoyInfo2.dev != newjoy && JoyInfo3.dev != newjoy && JoyInfo4.dev != newjoy) // don't override a currently active device
+					if (newcontroller && (!JoyInfo.dev || !SDL_GameControllerGetAttached(JoyInfo.dev))
+						&& JoyInfo2.dev != newcontroller && JoyInfo3.dev != newcontroller && JoyInfo4.dev != newcontroller) // don't override a currently active device
 					{
-						cv_usejoystick.value = evt.jdevice.which + 1;
+						cv_usejoystick.value = evt.cdevice.which + 1;
 						I_UpdateJoystickDeviceIndices(1);
 					}
 
@@ -999,10 +1027,10 @@ void I_GetEvent(void)
 					// PLAYER 2
 					//////////////////////////////
 
-					else if (newjoy && (!JoyInfo2.dev || !SDL_JoystickGetAttached(JoyInfo2.dev))
-						&& JoyInfo.dev != newjoy && JoyInfo3.dev != newjoy && JoyInfo4.dev != newjoy) // don't override a currently active device
+					else if (newcontroller && (!JoyInfo2.dev || !SDL_GameControllerGetAttached(JoyInfo2.dev))
+						&& JoyInfo.dev != newcontroller && JoyInfo3.dev != newcontroller && JoyInfo4.dev != newcontroller) // don't override a currently active device
 					{
-						cv_usejoystick2.value = evt.jdevice.which + 1;
+						cv_usejoystick2.value = evt.cdevice.which + 1;
 						I_UpdateJoystickDeviceIndices(2);
 					}
 
@@ -1010,10 +1038,10 @@ void I_GetEvent(void)
 					// PLAYER 3
 					//////////////////////////////
 
-					else if (newjoy && (!JoyInfo3.dev || !SDL_JoystickGetAttached(JoyInfo3.dev))
-						&& JoyInfo.dev != newjoy && JoyInfo2.dev != newjoy && JoyInfo4.dev != newjoy) // don't override a currently active device
+					else if (newcontroller && (!JoyInfo3.dev || !SDL_GameControllerGetAttached(JoyInfo3.dev))
+						&& JoyInfo.dev != newcontroller && JoyInfo2.dev != newcontroller && JoyInfo4.dev != newcontroller) // don't override a currently active device
 					{
-						cv_usejoystick3.value = evt.jdevice.which + 1;
+						cv_usejoystick3.value = evt.cdevice.which + 1;
 						I_UpdateJoystickDeviceIndices(3);
 					}
 
@@ -1021,10 +1049,10 @@ void I_GetEvent(void)
 					// PLAYER 4
 					//////////////////////////////
 
-					else if (newjoy && (!JoyInfo4.dev || !SDL_JoystickGetAttached(JoyInfo4.dev))
-						&& JoyInfo.dev != newjoy && JoyInfo2.dev != newjoy && JoyInfo3.dev != newjoy) // don't override a currently active device
+					else if (newcontroller && (!JoyInfo4.dev || !SDL_GameControllerGetAttached(JoyInfo4.dev))
+						&& JoyInfo.dev != newcontroller && JoyInfo2.dev != newcontroller && JoyInfo3.dev != newcontroller) // don't override a currently active device
 					{
-						cv_usejoystick4.value = evt.jdevice.which + 1;
+						cv_usejoystick4.value = evt.cdevice.which + 1;
 						I_UpdateJoystickDeviceIndices(4);
 					}
 
@@ -1079,33 +1107,33 @@ void I_GetEvent(void)
 					if (currentMenu == &OP_JoystickSetDef)
 						M_SetupJoystickMenu(0);
 
-					if (JoyInfo.dev != newjoy && JoyInfo2.dev != newjoy && JoyInfo3.dev != newjoy && JoyInfo4.dev != newjoy)
-						SDL_JoystickClose(newjoy);
+					if (JoyInfo.dev != newcontroller && JoyInfo2.dev != newcontroller && JoyInfo3.dev != newcontroller && JoyInfo4.dev != newcontroller)
+						SDL_GameControllerClose(newcontroller);
 				}
 				break;
 
 			////////////////////////////////////////////////////////////
 
-			case SDL_JOYDEVICEREMOVED:
-				if (JoyInfo.dev && !SDL_JoystickGetAttached(JoyInfo.dev))
+			case SDL_CONTROLLERDEVICEREMOVED:
+				if (JoyInfo.dev && !SDL_GameControllerGetAttached(JoyInfo.dev))
 				{
 					CONS_Debug(DBG_GAMELOGIC, "Joystick1 removed, device index: %d\n", JoyInfo.oldjoy);
 					I_ShutdownJoystick();
 				}
 
-				if (JoyInfo2.dev && !SDL_JoystickGetAttached(JoyInfo2.dev))
+				if (JoyInfo2.dev && !SDL_GameControllerGetAttached(JoyInfo2.dev))
 				{
 					CONS_Debug(DBG_GAMELOGIC, "Joystick2 removed, device index: %d\n", JoyInfo2.oldjoy);
 					I_ShutdownJoystick2();
 				}
 
-				if (JoyInfo3.dev && !SDL_JoystickGetAttached(JoyInfo3.dev))
+				if (JoyInfo3.dev && !SDL_GameControllerGetAttached(JoyInfo3.dev))
 				{
 					CONS_Debug(DBG_GAMELOGIC, "Joystick3 removed, device index: %d\n", JoyInfo3.oldjoy);
 					I_ShutdownJoystick3();
 				}
 
-				if (JoyInfo4.dev && !SDL_JoystickGetAttached(JoyInfo4.dev))
+				if (JoyInfo4.dev && !SDL_GameControllerGetAttached(JoyInfo4.dev))
 				{
 					CONS_Debug(DBG_GAMELOGIC, "Joystick4 removed, device index: %d\n", JoyInfo4.oldjoy);
 					I_ShutdownJoystick4();
@@ -1294,9 +1322,9 @@ void I_OsPolling(void)
 
 	if (consolevent)
 		I_GetConsoleEvents();
-	if (SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK)
+	if (SDL_WasInit(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER) == SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER)
 	{
-		SDL_JoystickUpdate();
+		SDL_GameControllerUpdate();
 		I_GetJoystickEvents();
 		I_GetJoystick2Events();
 		I_GetJoystick3Events();
diff --git a/src/sdl/sdlmain.h b/src/sdl/sdlmain.h
index 0bc771a713248bf9076963da7c610b1b3d8201ba..01edd866a323a5c83dba1cd1fe77a476a65c41af 100644
--- a/src/sdl/sdlmain.h
+++ b/src/sdl/sdlmain.h
@@ -40,8 +40,8 @@ extern SDL_bool framebuffer;
 */
 typedef struct SDLJoyInfo_s
 {
-	/// Joystick handle
-	SDL_Joystick *dev;
+	/// Controller handle
+	SDL_GameController *dev;
 	/// number of old joystick
 	int oldjoy;
 	/// number of axies
@@ -57,7 +57,7 @@ typedef struct SDLJoyInfo_s
 
 } SDLJoyInfo_t;
 
-/**	\brief SDL info about joystick 1
+/**	\brief SDL info about controller 1
 */
 extern SDLJoyInfo_t JoyInfo;
 
@@ -66,15 +66,15 @@ extern SDLJoyInfo_t JoyInfo;
 #define SDL_JDEADZONE 153
 #undef SDL_JDEADZONE
 
-/**	\brief SDL inof about joystick 2
+/**	\brief SDL inof about controller 2
 */
 extern SDLJoyInfo_t JoyInfo2;
 
-/**	\brief SDL inof about joystick 3
+/**	\brief SDL inof about controller 3
 */
 extern SDLJoyInfo_t JoyInfo3;
 
-/**	\brief SDL inof about joystick 4
+/**	\brief SDL inof about controller 4
 */
 extern SDLJoyInfo_t JoyInfo4;
 
@@ -86,8 +86,8 @@ void I_ShutdownJoystick2(void);
 void I_ShutdownJoystick3(void);
 void I_ShutdownJoystick4(void);
 
-// Cheat to get the device index for a joystick handle
-INT32 I_GetJoystickDeviceIndex(SDL_Joystick *dev);
+// Cheat to get the device index for a game controller handle
+INT32 I_GetJoystickDeviceIndex(SDL_GameController *dev);
 
 // Quick thing to make SDL_JOYDEVICEADDED events less of an abomination
 void I_UpdateJoystickDeviceIndices(INT32 player);