mirror of
				https://github.com/KartKrewDev/RingRacers.git
				synced 2025-10-30 08:01:28 +00:00 
			
		
		
		
	Handle gamepads from interface dynamically
Fixes numerous issues with hotswapping, gamepad assignment, and menu responsiveness.
This commit is contained in:
		
							parent
							
								
									feb70916c1
								
							
						
					
					
						commit
						86a9579e16
					
				
					 18 changed files with 558 additions and 597 deletions
				
			
		| 
						 | 
				
			
			@ -449,7 +449,7 @@ boolean AM_Responder(event_t *ev)
 | 
			
		|||
			{
 | 
			
		||||
				//faB: prevent alt-tab in win32 version to activate automap just before
 | 
			
		||||
				//     minimizing the app; doesn't do any harm to the DOS version
 | 
			
		||||
				if (!gamekeydown[0][KEY_LALT] && !gamekeydown[0][KEY_RALT])
 | 
			
		||||
				if (!G_GetDeviceGameKeyDownArray(0)[KEY_LALT] && !G_GetDeviceGameKeyDownArray(0)[KEY_RALT])
 | 
			
		||||
				{
 | 
			
		||||
					bigstate = 0; //added : 24-01-98 : toggle off large view
 | 
			
		||||
					AM_Start();
 | 
			
		||||
| 
						 | 
				
			
			@ -1069,7 +1069,7 @@ static void AM_drawWalls(UINT8 pass)
 | 
			
		|||
			else if (backc1 != frontc1 || backc2 != frontc2)
 | 
			
		||||
			{
 | 
			
		||||
				if (!(pass & PASS_INTANGIBLE))
 | 
			
		||||
					;	
 | 
			
		||||
					;
 | 
			
		||||
				else if (abs(backc1 - frontc1) < maxstep
 | 
			
		||||
					|| abs(backc2 - frontc2) < maxstep)
 | 
			
		||||
				{
 | 
			
		||||
| 
						 | 
				
			
			@ -1115,7 +1115,7 @@ static void AM_drawWalls(UINT8 pass)
 | 
			
		|||
				else
 | 
			
		||||
				{
 | 
			
		||||
					ffloor_t *rover = NULL;
 | 
			
		||||
					
 | 
			
		||||
 | 
			
		||||
					if (lines[i].frontsector->ffloors || lines[i].backsector->ffloors)
 | 
			
		||||
					{
 | 
			
		||||
						if (lines[i].backsector->ffloors == NULL)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1485,7 +1485,7 @@ void CL_UpdateServerList (void)
 | 
			
		|||
 | 
			
		||||
static void M_ConfirmConnect(void)
 | 
			
		||||
{
 | 
			
		||||
	if (G_PlayerInputDown(0, gc_a, 1) || gamekeydown[0][KEY_ENTER])
 | 
			
		||||
	if (G_PlayerInputDown(0, gc_a, 1) || G_GetDeviceGameKeyDownArray(0)[KEY_ENTER])
 | 
			
		||||
	{
 | 
			
		||||
		if (totalfilesrequestednum > 0)
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			@ -1512,7 +1512,7 @@ static void M_ConfirmConnect(void)
 | 
			
		|||
 | 
			
		||||
		M_StopMessage(0);
 | 
			
		||||
	}
 | 
			
		||||
	else if (G_PlayerInputDown(0, gc_b, 1) || G_PlayerInputDown(0, gc_x, 1) || gamekeydown[0][KEY_ESCAPE])
 | 
			
		||||
	else if (G_PlayerInputDown(0, gc_b, 1) || G_PlayerInputDown(0, gc_x, 1) || G_GetDeviceGameKeyDownArray(0)[KEY_ESCAPE])
 | 
			
		||||
	{
 | 
			
		||||
		cl_mode = CL_ABORTED;
 | 
			
		||||
		M_StopMessage(0);
 | 
			
		||||
| 
						 | 
				
			
			@ -1962,7 +1962,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
 | 
			
		|||
		renderdeltatics = FRACUNIT;
 | 
			
		||||
		rendertimefrac = FRACUNIT;
 | 
			
		||||
 | 
			
		||||
		memset(deviceResponding, false, sizeof (deviceResponding));
 | 
			
		||||
		G_ResetAllDeviceResponding();
 | 
			
		||||
 | 
			
		||||
		if (netgame)
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			@ -1979,7 +1979,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
 | 
			
		|||
			{
 | 
			
		||||
				if (G_PlayerInputDown(0, gc_b, 1)
 | 
			
		||||
					|| G_PlayerInputDown(0, gc_x, 1)
 | 
			
		||||
					|| gamekeydown[0][KEY_ESCAPE])
 | 
			
		||||
					|| G_GetDeviceGameKeyDownArray(0)[KEY_ESCAPE])
 | 
			
		||||
					cl_mode = CL_ABORTED;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,7 +28,9 @@ typedef enum
 | 
			
		|||
	ev_keyup,
 | 
			
		||||
	ev_console,
 | 
			
		||||
	ev_mouse,
 | 
			
		||||
	ev_joystick,
 | 
			
		||||
	ev_gamepad_axis,
 | 
			
		||||
	ev_gamepad_device_added,
 | 
			
		||||
	ev_gamepad_device_removed,
 | 
			
		||||
} evtype_t;
 | 
			
		||||
 | 
			
		||||
// Event structure.
 | 
			
		||||
| 
						 | 
				
			
			@ -38,7 +40,7 @@ struct event_t
 | 
			
		|||
	INT32 data1; // keys / mouse/joystick buttons
 | 
			
		||||
	INT32 data2; // mouse/joystick x move
 | 
			
		||||
	INT32 data3; // mouse/joystick y move
 | 
			
		||||
	INT32 device; // which player's device it belongs to
 | 
			
		||||
	INT32 device; // which device ID it belongs to (controller ID)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										56
									
								
								src/d_main.c
									
										
									
									
									
								
							
							
						
						
									
										56
									
								
								src/d_main.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -171,6 +171,54 @@ UINT8 ctrldown = 0; // 0x1 left, 0x2 right
 | 
			
		|||
UINT8 altdown = 0; // 0x1 left, 0x2 right
 | 
			
		||||
boolean capslock = 0;	// gee i wonder what this does.
 | 
			
		||||
 | 
			
		||||
static void HandleGamepadDeviceAdded(event_t *ev)
 | 
			
		||||
{
 | 
			
		||||
	I_Assert(ev != NULL);
 | 
			
		||||
	I_Assert(ev->type == ev_gamepad_device_added);
 | 
			
		||||
 | 
			
		||||
	G_RegisterAvailableGamepad(ev->device);
 | 
			
		||||
	CONS_Debug(DBG_GAMELOGIC, "Registered available gamepad device %d\n", ev->device);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void HandleGamepadDeviceRemoved(event_t *ev)
 | 
			
		||||
{
 | 
			
		||||
	int i = 0;
 | 
			
		||||
	I_Assert(ev != NULL);
 | 
			
		||||
	I_Assert(ev->type == ev_gamepad_device_removed);
 | 
			
		||||
 | 
			
		||||
	G_UnregisterAvailableGamepad(ev->device);
 | 
			
		||||
	CONS_Debug(DBG_GAMELOGIC, "Unregistered available gamepad device %d\n", ev->device);
 | 
			
		||||
 | 
			
		||||
	// Downstream responders need to update player gamepad assignments, pause, etc
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
 | 
			
		||||
	{
 | 
			
		||||
		INT32 device = G_GetDeviceForPlayer(i);
 | 
			
		||||
		if (device == ev->device)
 | 
			
		||||
		{
 | 
			
		||||
			G_SetDeviceForPlayer(i, -1);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Respond to added/removed device events, for bookkeeping available gamepads.
 | 
			
		||||
static void HandleGamepadDeviceEvents(event_t *ev)
 | 
			
		||||
{
 | 
			
		||||
	I_Assert(ev != NULL);
 | 
			
		||||
 | 
			
		||||
	switch (ev->type)
 | 
			
		||||
	{
 | 
			
		||||
	case ev_gamepad_device_added:
 | 
			
		||||
		HandleGamepadDeviceAdded(ev);
 | 
			
		||||
		break;
 | 
			
		||||
	case ev_gamepad_device_removed:
 | 
			
		||||
		HandleGamepadDeviceRemoved(ev);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// D_ProcessEvents
 | 
			
		||||
// Send all the events of the given timestamp down the responder chain
 | 
			
		||||
| 
						 | 
				
			
			@ -183,11 +231,13 @@ void D_ProcessEvents(void)
 | 
			
		|||
	boolean eaten;
 | 
			
		||||
	boolean menuresponse = false;
 | 
			
		||||
 | 
			
		||||
	memset(deviceResponding, false, sizeof (deviceResponding));
 | 
			
		||||
	G_ResetAllDeviceResponding();
 | 
			
		||||
	for (; eventtail != eventhead; eventtail = (eventtail+1) & (MAXEVENTS-1))
 | 
			
		||||
	{
 | 
			
		||||
		ev = &events[eventtail];
 | 
			
		||||
 | 
			
		||||
		HandleGamepadDeviceEvents(ev);
 | 
			
		||||
 | 
			
		||||
		// Screenshots over everything so that they can be taken anywhere.
 | 
			
		||||
		if (M_ScreenshotResponder(ev))
 | 
			
		||||
			continue; // ate the event
 | 
			
		||||
| 
						 | 
				
			
			@ -976,7 +1026,7 @@ void D_ClearState(void)
 | 
			
		|||
 | 
			
		||||
	// clear cmd building stuff
 | 
			
		||||
	memset(gamekeydown, 0, sizeof (gamekeydown));
 | 
			
		||||
	memset(deviceResponding, false, sizeof (deviceResponding));
 | 
			
		||||
	G_ResetAllDeviceResponding();
 | 
			
		||||
 | 
			
		||||
	// Reset the palette
 | 
			
		||||
	if (rendermode != render_none)
 | 
			
		||||
| 
						 | 
				
			
			@ -1507,6 +1557,8 @@ void D_SRB2Main(void)
 | 
			
		|||
	CONS_Printf("I_StartupGraphics()...\n");
 | 
			
		||||
	I_StartupGraphics();
 | 
			
		||||
 | 
			
		||||
	I_StartupInput();
 | 
			
		||||
 | 
			
		||||
	if (rendermode != render_none)
 | 
			
		||||
	{
 | 
			
		||||
		I_NewTwodeeFrame();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -237,9 +237,6 @@ static CV_PossibleValue_t usemouse_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Force
 | 
			
		|||
#ifdef LJOYSTICK
 | 
			
		||||
static CV_PossibleValue_t joyport_cons_t[] = {{1, "/dev/js0"}, {2, "/dev/js1"}, {3, "/dev/js2"},
 | 
			
		||||
	{4, "/dev/js3"}, {0, NULL}};
 | 
			
		||||
#else
 | 
			
		||||
// accept whatever value - it is in fact the joystick device number
 | 
			
		||||
static CV_PossibleValue_t usejoystick_cons_t[] = {{-1, "MIN"}, {MAXGAMEPADS, "MAX"}, {0, NULL}};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static CV_PossibleValue_t teamscramble_cons_t[] = {{0, "Off"}, {1, "Random"}, {2, "Points"}, {0, NULL}};
 | 
			
		||||
| 
						 | 
				
			
			@ -332,13 +329,6 @@ consvar_t cv_skipmapcheck = CVAR_INIT ("skipmapcheck", "Off", CV_SAVE, CV_OnOff,
 | 
			
		|||
 | 
			
		||||
consvar_t cv_usemouse = CVAR_INIT ("use_mouse", "Off", CV_SAVE|CV_CALL,usemouse_cons_t, I_StartupMouse);
 | 
			
		||||
 | 
			
		||||
consvar_t cv_usejoystick[MAXSPLITSCREENPLAYERS] = {
 | 
			
		||||
	CVAR_INIT ("use_device", "1", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitJoystick1),
 | 
			
		||||
	CVAR_INIT ("use_device2", "2", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitJoystick2),
 | 
			
		||||
	CVAR_INIT ("use_device3", "3", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitJoystick3),
 | 
			
		||||
	CVAR_INIT ("use_device4", "4", CV_SAVE|CV_CALL, usejoystick_cons_t, I_InitJoystick4)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if (defined (LJOYSTICK) || defined (HAVE_SDL))
 | 
			
		||||
consvar_t cv_joyscale[MAXSPLITSCREENPLAYERS] = {
 | 
			
		||||
	CVAR_INIT ("padscale", "1", CV_SAVE|CV_CALL, NULL, I_JoyScale),
 | 
			
		||||
| 
						 | 
				
			
			@ -1039,7 +1029,6 @@ void D_RegisterClientCommands(void)
 | 
			
		|||
 | 
			
		||||
	for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
 | 
			
		||||
	{
 | 
			
		||||
		CV_RegisterVar(&cv_usejoystick[i]);
 | 
			
		||||
		CV_RegisterVar(&cv_joyscale[i]);
 | 
			
		||||
#ifdef LJOYSTICK
 | 
			
		||||
		CV_RegisterVar(&cv_joyport[i]);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -47,7 +47,6 @@ extern consvar_t cv_splitplayers;
 | 
			
		|||
 | 
			
		||||
extern consvar_t cv_seenames;
 | 
			
		||||
extern consvar_t cv_usemouse;
 | 
			
		||||
extern consvar_t cv_usejoystick[MAXSPLITSCREENPLAYERS];
 | 
			
		||||
extern consvar_t cv_joyscale[MAXSPLITSCREENPLAYERS];
 | 
			
		||||
#ifdef LJOYSTICK
 | 
			
		||||
extern consvar_t cv_joyport[MAXSPLITSCREENPLAYERS];
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										48
									
								
								src/g_game.c
									
										
									
									
									
								
							
							
						
						
									
										48
									
								
								src/g_game.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -513,7 +513,7 @@ void G_UpdateTimeStickerMedals(UINT16 map, boolean showownrecord)
 | 
			
		|||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			case ET_MAP:
 | 
			
		||||
			{	
 | 
			
		||||
			{
 | 
			
		||||
				if (emblem->flags & ME_SPBATTACK && cv_dummyspbattack.value)
 | 
			
		||||
					break;
 | 
			
		||||
				goto bademblem;
 | 
			
		||||
| 
						 | 
				
			
			@ -884,6 +884,7 @@ static INT32 keyboardMenuDefaults[][2] = {
 | 
			
		|||
INT32 G_PlayerInputAnalog(UINT8 p, INT32 gc, UINT8 menuPlayers)
 | 
			
		||||
{
 | 
			
		||||
	INT32 deviceID;
 | 
			
		||||
	INT32 avail_gamepad_id = 0;
 | 
			
		||||
	INT32 i, j;
 | 
			
		||||
	INT32 deadzone = 0;
 | 
			
		||||
	boolean trydefaults = true;
 | 
			
		||||
| 
						 | 
				
			
			@ -900,7 +901,22 @@ INT32 G_PlayerInputAnalog(UINT8 p, INT32 gc, UINT8 menuPlayers)
 | 
			
		|||
 | 
			
		||||
	deadzone = (JOYAXISRANGE * cv_deadzone[p].value) / FRACUNIT;
 | 
			
		||||
 | 
			
		||||
	deviceID = cv_usejoystick[p].value;
 | 
			
		||||
	deviceID = G_GetDeviceForPlayer(p);
 | 
			
		||||
 | 
			
		||||
	if (deviceID == -1)
 | 
			
		||||
	{
 | 
			
		||||
		INT32 keyboard_player = G_GetPlayerForDevice(KEYBOARD_MOUSE_DEVICE);
 | 
			
		||||
 | 
			
		||||
		// Player 1 is always allowed to use the keyboard in 1P (there is a check for splitscreen later in this func)
 | 
			
		||||
		if (p == KEYBOARD_MOUSE_DEVICE && keyboard_player == -1)
 | 
			
		||||
		{
 | 
			
		||||
			deviceID = KEYBOARD_MOUSE_DEVICE;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			goto deviceunassigned;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
retrygetcontrol:
 | 
			
		||||
	for (i = 0; i < MAXINPUTMAPPING; i++)
 | 
			
		||||
| 
						 | 
				
			
			@ -910,7 +926,6 @@ retrygetcontrol:
 | 
			
		|||
		INT32 value = 0;
 | 
			
		||||
		boolean processinput = true;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		// for menus, keyboards have defaults!
 | 
			
		||||
		if (deviceID == 0)
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			@ -951,9 +966,9 @@ retrygetcontrol:
 | 
			
		|||
			// It's possible to access this control right now, so let's disable the default control backup for later.
 | 
			
		||||
			trydefaults = false;
 | 
			
		||||
 | 
			
		||||
			value = gamekeydown[deviceID][key];
 | 
			
		||||
			if (menukey && gamekeydown[deviceID][menukey])
 | 
			
		||||
				value = gamekeydown[deviceID][menukey];
 | 
			
		||||
			value = G_GetDeviceGameKeyDownArray(deviceID)[key];
 | 
			
		||||
			if (menukey && G_GetDeviceGameKeyDownArray(deviceID)[menukey])
 | 
			
		||||
				value = G_GetDeviceGameKeyDownArray(deviceID)[menukey];
 | 
			
		||||
 | 
			
		||||
			if (value >= deadzone)
 | 
			
		||||
			{
 | 
			
		||||
| 
						 | 
				
			
			@ -962,11 +977,13 @@ retrygetcontrol:
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
deviceunassigned:
 | 
			
		||||
 | 
			
		||||
	// If you're on controller, try your keyboard-based binds as an immediate backup.
 | 
			
		||||
	// Do not do this if there are more than 1 local player.
 | 
			
		||||
	if (p == 0 && deviceID > 0 && !tryingotherID && menuPlayers < 2 && !splitscreen)
 | 
			
		||||
	{
 | 
			
		||||
		deviceID = 0;
 | 
			
		||||
		deviceID = KEYBOARD_MOUSE_DEVICE;
 | 
			
		||||
		goto retrygetcontrol;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -981,16 +998,21 @@ retrygetcontrol:
 | 
			
		|||
 | 
			
		||||
	if (!tryingotherID)
 | 
			
		||||
	{
 | 
			
		||||
		deviceID = MAXDEVICES;
 | 
			
		||||
		avail_gamepad_id = 0;
 | 
			
		||||
		tryingotherID = true;
 | 
			
		||||
	}
 | 
			
		||||
loweringid:
 | 
			
		||||
	deviceID--;
 | 
			
		||||
	if (avail_gamepad_id >= G_GetNumAvailableGamepads())
 | 
			
		||||
	{
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	deviceID = G_GetAvailableGamepadDevice(avail_gamepad_id);
 | 
			
		||||
	avail_gamepad_id += 1;
 | 
			
		||||
	if (deviceID > 0)
 | 
			
		||||
	{
 | 
			
		||||
		for (i = 0; i < menuPlayers; i++)
 | 
			
		||||
		{
 | 
			
		||||
			if (deviceID != cv_usejoystick[i].value)
 | 
			
		||||
			if (deviceID != G_GetDeviceForPlayer(i))
 | 
			
		||||
				continue;
 | 
			
		||||
			// Controller taken? Try again...
 | 
			
		||||
			goto loweringid;
 | 
			
		||||
| 
						 | 
				
			
			@ -1005,7 +1027,7 @@ loweringid:
 | 
			
		|||
		trydefaults = false;
 | 
			
		||||
		controltable = &(gamecontroldefault[gc][0]);
 | 
			
		||||
		tryingotherID = false;
 | 
			
		||||
		deviceID = cv_usejoystick[p].value;
 | 
			
		||||
		deviceID = G_GetDeviceForPlayer(p);
 | 
			
		||||
		goto retrygetcontrol;
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -1530,7 +1552,7 @@ void G_DoLoadLevel(boolean resetplayer)
 | 
			
		|||
 | 
			
		||||
	// clear cmd building stuff
 | 
			
		||||
	memset(gamekeydown, 0, sizeof (gamekeydown));
 | 
			
		||||
	memset(deviceResponding, false, sizeof (deviceResponding));
 | 
			
		||||
	G_ResetAllDeviceResponding();
 | 
			
		||||
 | 
			
		||||
	// clear hud messages remains (usually from game startup)
 | 
			
		||||
	CON_ClearHUD();
 | 
			
		||||
| 
						 | 
				
			
			@ -1828,7 +1850,7 @@ boolean G_Responder(event_t *ev)
 | 
			
		|||
		case ev_mouse:
 | 
			
		||||
			return true; // eat events
 | 
			
		||||
 | 
			
		||||
		case ev_joystick:
 | 
			
		||||
		case ev_gamepad_axis:
 | 
			
		||||
			return true; // eat events
 | 
			
		||||
 | 
			
		||||
		default:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										298
									
								
								src/g_input.c
									
										
									
									
									
								
							
							
						
						
									
										298
									
								
								src/g_input.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -19,6 +19,7 @@
 | 
			
		|||
#include "d_net.h"
 | 
			
		||||
#include "console.h"
 | 
			
		||||
#include "i_joy.h" // JOYAXISRANGE
 | 
			
		||||
#include "z_zone.h"
 | 
			
		||||
 | 
			
		||||
#define MAXMOUSESENSITIVITY 100 // sensitivity steps
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -35,7 +36,6 @@ consvar_t cv_controlperkey = CVAR_INIT ("controlperkey", "One", CV_SAVE, onecont
 | 
			
		|||
// current state of the keys
 | 
			
		||||
// FRACUNIT for fully pressed, 0 for not pressed
 | 
			
		||||
INT32 gamekeydown[MAXDEVICES][NUMINPUTS];
 | 
			
		||||
boolean deviceResponding[MAXDEVICES];
 | 
			
		||||
 | 
			
		||||
// two key codes (or virtual key) per game control
 | 
			
		||||
INT32 gamecontrol[MAXSPLITSCREENPLAYERS][num_gamecontrols][MAXINPUTMAPPING];
 | 
			
		||||
| 
						 | 
				
			
			@ -68,13 +68,82 @@ const INT32 gcl_full[num_gcl_full] = {
 | 
			
		|||
};
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
INT32 G_GetDevicePlayer(INT32 deviceID)
 | 
			
		||||
static INT32 g_gamekeydown_device0[NUMINPUTS];
 | 
			
		||||
 | 
			
		||||
static INT32 g_available_gamepad_devices;
 | 
			
		||||
static INT32 g_gamepad_device_ids[MAXGAMEPADS];
 | 
			
		||||
static INT32* g_gamepad_gamekeydown[MAXGAMEPADS];
 | 
			
		||||
static boolean g_device0_responding;
 | 
			
		||||
static boolean g_gamepad_responding[MAXGAMEPADS];
 | 
			
		||||
static INT32 g_player_devices[MAXSPLITSCREENPLAYERS] = {-1, -1, -1, -1};
 | 
			
		||||
 | 
			
		||||
void G_RegisterAvailableGamepad(INT32 device_id)
 | 
			
		||||
{
 | 
			
		||||
	I_Assert(device_id >= 1);
 | 
			
		||||
 | 
			
		||||
	if (g_available_gamepad_devices == MAXGAMEPADS)
 | 
			
		||||
	{
 | 
			
		||||
		// too many!
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	g_gamepad_device_ids[g_available_gamepad_devices] = device_id;
 | 
			
		||||
 | 
			
		||||
	g_gamepad_gamekeydown[g_available_gamepad_devices] = Z_CallocAlign(NUMINPUTS * sizeof(INT32), PU_STATIC, NULL, 4);
 | 
			
		||||
 | 
			
		||||
	g_gamepad_responding[g_available_gamepad_devices] = false;
 | 
			
		||||
 | 
			
		||||
	g_available_gamepad_devices += 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void G_UnregisterAvailableGamepad(INT32 device_id)
 | 
			
		||||
{
 | 
			
		||||
	int i = 0;
 | 
			
		||||
 | 
			
		||||
	I_Assert(device_id >= 1);
 | 
			
		||||
 | 
			
		||||
	if (g_available_gamepad_devices <= 0)
 | 
			
		||||
	{
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < g_available_gamepad_devices; i++)
 | 
			
		||||
	{
 | 
			
		||||
		if (g_gamepad_device_ids[i] == device_id)
 | 
			
		||||
		{
 | 
			
		||||
			int32_t *old_gamekeydown = g_gamepad_gamekeydown[i];
 | 
			
		||||
			g_gamepad_device_ids[i] = g_gamepad_device_ids[g_available_gamepad_devices - 1];
 | 
			
		||||
			g_gamepad_gamekeydown[i] = g_gamepad_gamekeydown[g_available_gamepad_devices - 1];
 | 
			
		||||
			g_gamepad_responding[i] = g_gamepad_responding[g_available_gamepad_devices - 1];
 | 
			
		||||
			Z_Free(old_gamekeydown);
 | 
			
		||||
			g_available_gamepad_devices -= 1;
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
INT32 G_GetNumAvailableGamepads(void)
 | 
			
		||||
{
 | 
			
		||||
	return g_available_gamepad_devices;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
INT32 G_GetAvailableGamepadDevice(INT32 available_index)
 | 
			
		||||
{
 | 
			
		||||
	if (available_index < 0 || available_index >= G_GetNumAvailableGamepads())
 | 
			
		||||
	{
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return g_gamepad_device_ids[available_index];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
INT32 G_GetPlayerForDevice(INT32 device_id)
 | 
			
		||||
{
 | 
			
		||||
	INT32 i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
 | 
			
		||||
	{
 | 
			
		||||
		if (deviceID == cv_usejoystick[i].value)
 | 
			
		||||
		if (device_id == g_player_devices[i])
 | 
			
		||||
		{
 | 
			
		||||
			return i;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -83,6 +152,172 @@ INT32 G_GetDevicePlayer(INT32 deviceID)
 | 
			
		|||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
INT32 G_GetDeviceForPlayer(INT32 player)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	if (G_GetPlayerForDevice(KEYBOARD_MOUSE_DEVICE) == player)
 | 
			
		||||
	{
 | 
			
		||||
		return KEYBOARD_MOUSE_DEVICE;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < G_GetNumAvailableGamepads() + 1; i++)
 | 
			
		||||
	{
 | 
			
		||||
		INT32 device = G_GetAvailableGamepadDevice(i);
 | 
			
		||||
		if (G_GetPlayerForDevice(device) == player)
 | 
			
		||||
		{
 | 
			
		||||
			return device;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void G_SetDeviceForPlayer(INT32 player, INT32 device)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	I_Assert(player >= 0 && player < MAXSPLITSCREENPLAYERS);
 | 
			
		||||
	I_Assert(device >= -1);
 | 
			
		||||
 | 
			
		||||
	g_player_devices[player] = device;
 | 
			
		||||
 | 
			
		||||
	if (device == -1)
 | 
			
		||||
	{
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (device != KEYBOARD_MOUSE_DEVICE)
 | 
			
		||||
	{
 | 
			
		||||
		I_SetGamepadPlayerIndex(device, player);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
 | 
			
		||||
	{
 | 
			
		||||
		if (i == player)
 | 
			
		||||
		{
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (g_player_devices[i] == device)
 | 
			
		||||
		{
 | 
			
		||||
			g_player_devices[i] = -1;
 | 
			
		||||
			if (device > 0)
 | 
			
		||||
			{
 | 
			
		||||
				I_SetGamepadPlayerIndex(device, -1);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
INT32* G_GetDeviceGameKeyDownArray(INT32 device)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	I_Assert(device >= 0);
 | 
			
		||||
 | 
			
		||||
	if (device == KEYBOARD_MOUSE_DEVICE)
 | 
			
		||||
	{
 | 
			
		||||
		return g_gamekeydown_device0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < g_available_gamepad_devices; i++)
 | 
			
		||||
	{
 | 
			
		||||
		if (g_gamepad_device_ids[i] == device)
 | 
			
		||||
		{
 | 
			
		||||
			return g_gamepad_gamekeydown[i];
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
boolean G_IsDeviceResponding(INT32 device)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	I_Assert(device >= 0);
 | 
			
		||||
 | 
			
		||||
	if (device == KEYBOARD_MOUSE_DEVICE)
 | 
			
		||||
	{
 | 
			
		||||
		return g_device0_responding;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < g_available_gamepad_devices; i++)
 | 
			
		||||
	{
 | 
			
		||||
		INT32 device_id = G_GetAvailableGamepadDevice(i);
 | 
			
		||||
		if (device_id == device)
 | 
			
		||||
		{
 | 
			
		||||
			return g_gamepad_responding[i];
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void G_SetDeviceResponding(INT32 device, boolean responding)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	I_Assert(device >= 0);
 | 
			
		||||
 | 
			
		||||
	if (device == KEYBOARD_MOUSE_DEVICE)
 | 
			
		||||
	{
 | 
			
		||||
		g_device0_responding = responding;
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < g_available_gamepad_devices; i++)
 | 
			
		||||
	{
 | 
			
		||||
		INT32 device_id = G_GetAvailableGamepadDevice(i);
 | 
			
		||||
		if (device_id == device)
 | 
			
		||||
		{
 | 
			
		||||
			g_gamepad_responding[i] = responding;
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void G_ResetAllDeviceResponding(void)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
	int num_gamepads;
 | 
			
		||||
 | 
			
		||||
	g_device0_responding = false;
 | 
			
		||||
 | 
			
		||||
	num_gamepads = G_GetNumAvailableGamepads();
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < num_gamepads; i++)
 | 
			
		||||
	{
 | 
			
		||||
		g_gamepad_responding[i] = false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static boolean AutomaticControllerReassignmentIsAllowed(INT32 device)
 | 
			
		||||
{
 | 
			
		||||
	boolean device_is_gamepad = device > 0;
 | 
			
		||||
	boolean device_is_unassigned = G_GetPlayerForDevice(device) == -1;
 | 
			
		||||
	boolean gamestate_is_in_level = gamestate == GS_LEVEL;
 | 
			
		||||
 | 
			
		||||
	return device_is_gamepad && device_is_unassigned && gamestate_is_in_level;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static INT32 AssignDeviceToFirstUnassignedPlayer(INT32 device)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < splitscreen + 1; i++)
 | 
			
		||||
	{
 | 
			
		||||
		if (G_GetDeviceForPlayer(i) == -1)
 | 
			
		||||
		{
 | 
			
		||||
			G_SetDeviceForPlayer(i, device);
 | 
			
		||||
			return i;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Remaps the inputs to game controls.
 | 
			
		||||
//
 | 
			
		||||
| 
						 | 
				
			
			@ -94,15 +329,15 @@ void G_MapEventsToControls(event_t *ev)
 | 
			
		|||
{
 | 
			
		||||
	INT32 i;
 | 
			
		||||
 | 
			
		||||
	if (ev->device >= 0 && ev->device < MAXDEVICES)
 | 
			
		||||
	if (ev->device >= 0)
 | 
			
		||||
	{
 | 
			
		||||
		switch (ev->type)
 | 
			
		||||
		{
 | 
			
		||||
			case ev_keydown:
 | 
			
		||||
			//case ev_keyup:
 | 
			
		||||
			//case ev_mouse:
 | 
			
		||||
			//case ev_joystick:
 | 
			
		||||
				deviceResponding[ev->device] = true;
 | 
			
		||||
			//case ev_gamepad_axis:
 | 
			
		||||
				G_SetDeviceResponding(ev->device, true);
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			default:
 | 
			
		||||
| 
						 | 
				
			
			@ -119,7 +354,16 @@ void G_MapEventsToControls(event_t *ev)
 | 
			
		|||
		case ev_keydown:
 | 
			
		||||
			if (ev->data1 < NUMINPUTS)
 | 
			
		||||
			{
 | 
			
		||||
				gamekeydown[ev->device][ev->data1] = JOYAXISRANGE;
 | 
			
		||||
				G_GetDeviceGameKeyDownArray(ev->device)[ev->data1] = JOYAXISRANGE;
 | 
			
		||||
 | 
			
		||||
				if (AutomaticControllerReassignmentIsAllowed(ev->device))
 | 
			
		||||
				{
 | 
			
		||||
					INT32 assigned = AssignDeviceToFirstUnassignedPlayer(ev->device);
 | 
			
		||||
					if (assigned >= 0)
 | 
			
		||||
					{
 | 
			
		||||
						CONS_Alert(CONS_NOTICE, "Player %d device was reassigned\n", assigned + 1);
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
#ifdef PARANOIA
 | 
			
		||||
			else
 | 
			
		||||
| 
						 | 
				
			
			@ -132,7 +376,7 @@ void G_MapEventsToControls(event_t *ev)
 | 
			
		|||
		case ev_keyup:
 | 
			
		||||
			if (ev->data1 < NUMINPUTS)
 | 
			
		||||
			{
 | 
			
		||||
				gamekeydown[ev->device][ev->data1] = 0;
 | 
			
		||||
				G_GetDeviceGameKeyDownArray(ev->device)[ev->data1] = 0;
 | 
			
		||||
			}
 | 
			
		||||
#ifdef PARANOIA
 | 
			
		||||
			else
 | 
			
		||||
| 
						 | 
				
			
			@ -147,32 +391,32 @@ void G_MapEventsToControls(event_t *ev)
 | 
			
		|||
			if (ev->data2 < 0)
 | 
			
		||||
			{
 | 
			
		||||
				// Left
 | 
			
		||||
				gamekeydown[ev->device][KEY_MOUSEMOVE + 2] = abs(ev->data2);
 | 
			
		||||
				gamekeydown[ev->device][KEY_MOUSEMOVE + 3] = 0;
 | 
			
		||||
				G_GetDeviceGameKeyDownArray(ev->device)[KEY_MOUSEMOVE + 2] = abs(ev->data2);
 | 
			
		||||
				G_GetDeviceGameKeyDownArray(ev->device)[KEY_MOUSEMOVE + 3] = 0;
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				// Right
 | 
			
		||||
				gamekeydown[ev->device][KEY_MOUSEMOVE + 2] = 0;
 | 
			
		||||
				gamekeydown[ev->device][KEY_MOUSEMOVE + 3] = abs(ev->data2);
 | 
			
		||||
				G_GetDeviceGameKeyDownArray(ev->device)[KEY_MOUSEMOVE + 2] = 0;
 | 
			
		||||
				G_GetDeviceGameKeyDownArray(ev->device)[KEY_MOUSEMOVE + 3] = abs(ev->data2);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Y axis
 | 
			
		||||
			if (ev->data3 < 0)
 | 
			
		||||
			{
 | 
			
		||||
				// Up
 | 
			
		||||
				gamekeydown[ev->device][KEY_MOUSEMOVE] = abs(ev->data3);
 | 
			
		||||
				gamekeydown[ev->device][KEY_MOUSEMOVE + 1] = 0;
 | 
			
		||||
				G_GetDeviceGameKeyDownArray(ev->device)[KEY_MOUSEMOVE] = abs(ev->data3);
 | 
			
		||||
				G_GetDeviceGameKeyDownArray(ev->device)[KEY_MOUSEMOVE + 1] = 0;
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				// Down
 | 
			
		||||
				gamekeydown[ev->device][KEY_MOUSEMOVE] = 0;
 | 
			
		||||
				gamekeydown[ev->device][KEY_MOUSEMOVE + 1] = abs(ev->data3);
 | 
			
		||||
				G_GetDeviceGameKeyDownArray(ev->device)[KEY_MOUSEMOVE] = 0;
 | 
			
		||||
				G_GetDeviceGameKeyDownArray(ev->device)[KEY_MOUSEMOVE + 1] = abs(ev->data3);
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case ev_joystick: // buttons are virtual keys
 | 
			
		||||
		case ev_gamepad_axis: // buttons are virtual keys
 | 
			
		||||
			if (ev->data1 >= JOYAXISSETS)
 | 
			
		||||
			{
 | 
			
		||||
#ifdef PARANOIA
 | 
			
		||||
| 
						 | 
				
			
			@ -190,12 +434,12 @@ void G_MapEventsToControls(event_t *ev)
 | 
			
		|||
 | 
			
		||||
				if (ev->data2 != INT32_MAX)
 | 
			
		||||
				{
 | 
			
		||||
					gamekeydown[ev->device][KEY_AXIS1 + (JOYANALOGS * 4) + (i * 2)] = max(0, ev->data2);
 | 
			
		||||
					G_GetDeviceGameKeyDownArray(ev->device)[KEY_AXIS1 + (JOYANALOGS * 4) + (i * 2)] = max(0, ev->data2);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (ev->data3 != INT32_MAX)
 | 
			
		||||
				{
 | 
			
		||||
					gamekeydown[ev->device][KEY_AXIS1 + (JOYANALOGS * 4) + (i * 2) + 1] = max(0, ev->data3);
 | 
			
		||||
					G_GetDeviceGameKeyDownArray(ev->device)[KEY_AXIS1 + (JOYANALOGS * 4) + (i * 2) + 1] = max(0, ev->data3);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
| 
						 | 
				
			
			@ -206,14 +450,14 @@ void G_MapEventsToControls(event_t *ev)
 | 
			
		|||
					if (ev->data2 < 0)
 | 
			
		||||
					{
 | 
			
		||||
						// Left
 | 
			
		||||
						gamekeydown[ev->device][KEY_AXIS1 + (i * 4)] = abs(ev->data2);
 | 
			
		||||
						gamekeydown[ev->device][KEY_AXIS1 + (i * 4) + 1] = 0;
 | 
			
		||||
						G_GetDeviceGameKeyDownArray(ev->device)[KEY_AXIS1 + (i * 4)] = abs(ev->data2);
 | 
			
		||||
						G_GetDeviceGameKeyDownArray(ev->device)[KEY_AXIS1 + (i * 4) + 1] = 0;
 | 
			
		||||
					}
 | 
			
		||||
					else
 | 
			
		||||
					{
 | 
			
		||||
						// Right
 | 
			
		||||
						gamekeydown[ev->device][KEY_AXIS1 + (i * 4)] = 0;
 | 
			
		||||
						gamekeydown[ev->device][KEY_AXIS1 + (i * 4) + 1] = abs(ev->data2);
 | 
			
		||||
						G_GetDeviceGameKeyDownArray(ev->device)[KEY_AXIS1 + (i * 4)] = 0;
 | 
			
		||||
						G_GetDeviceGameKeyDownArray(ev->device)[KEY_AXIS1 + (i * 4) + 1] = abs(ev->data2);
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -222,14 +466,14 @@ void G_MapEventsToControls(event_t *ev)
 | 
			
		|||
					if (ev->data3 < 0)
 | 
			
		||||
					{
 | 
			
		||||
						// Up
 | 
			
		||||
						gamekeydown[ev->device][KEY_AXIS1 + (i * 4) + 2] = abs(ev->data3);
 | 
			
		||||
						gamekeydown[ev->device][KEY_AXIS1 + (i * 4) + 3] = 0;
 | 
			
		||||
						G_GetDeviceGameKeyDownArray(ev->device)[KEY_AXIS1 + (i * 4) + 2] = abs(ev->data3);
 | 
			
		||||
						G_GetDeviceGameKeyDownArray(ev->device)[KEY_AXIS1 + (i * 4) + 3] = 0;
 | 
			
		||||
					}
 | 
			
		||||
					else
 | 
			
		||||
					{
 | 
			
		||||
						// Down
 | 
			
		||||
						gamekeydown[ev->device][KEY_AXIS1 + (i * 4) + 2] = 0;
 | 
			
		||||
						gamekeydown[ev->device][KEY_AXIS1 + (i * 4) + 3] = abs(ev->data3);
 | 
			
		||||
						G_GetDeviceGameKeyDownArray(ev->device)[KEY_AXIS1 + (i * 4) + 2] = 0;
 | 
			
		||||
						G_GetDeviceGameKeyDownArray(ev->device)[KEY_AXIS1 + (i * 4) + 3] = abs(ev->data3);
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -107,8 +107,8 @@ extern consvar_t cv_controlperkey;
 | 
			
		|||
// current state of the keys: JOYAXISRANGE or 0 when boolean.
 | 
			
		||||
// Or anything inbetween for analog values
 | 
			
		||||
#define MAXDEVICES (MAXGAMEPADS + 1) // Gamepads + keyboard & mouse
 | 
			
		||||
#define KEYBOARD_MOUSE_DEVICE 0
 | 
			
		||||
extern INT32 gamekeydown[MAXDEVICES][NUMINPUTS];
 | 
			
		||||
extern boolean deviceResponding[MAXDEVICES];
 | 
			
		||||
 | 
			
		||||
// several key codes (or virtual key) per game control
 | 
			
		||||
extern INT32 gamecontrol[MAXSPLITSCREENPLAYERS][num_gamecontrols][MAXINPUTMAPPING];
 | 
			
		||||
| 
						 | 
				
			
			@ -135,7 +135,31 @@ extern const INT32 gcl_full[num_gcl_full];
 | 
			
		|||
// peace to my little coder fingers!
 | 
			
		||||
// check a gamecontrol being active or not
 | 
			
		||||
 | 
			
		||||
INT32 G_GetDevicePlayer(INT32 deviceID);
 | 
			
		||||
/*
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/// Register a device index (from ev_gamepad_device_added) as an Available Gamepad
 | 
			
		||||
void G_RegisterAvailableGamepad(INT32 device_id);
 | 
			
		||||
/// Unregister a device index (from ev_gamepad_device_removed) as an Available Gamepad
 | 
			
		||||
void G_UnregisterAvailableGamepad(INT32 device_id);
 | 
			
		||||
/// Get the number of Available Gamepads registered.
 | 
			
		||||
INT32 G_GetNumAvailableGamepads(void);
 | 
			
		||||
/// Get the device ID for a given Available Gamepad Index, or -1. 0 <= available_index < G_GetNumAvailableGamepads()
 | 
			
		||||
INT32 G_GetAvailableGamepadDevice(INT32 available_index);
 | 
			
		||||
 | 
			
		||||
INT32 G_GetPlayerForDevice(INT32 deviceID);
 | 
			
		||||
/// Get gamepad device for given player, or -1.
 | 
			
		||||
INT32 G_GetDeviceForPlayer(INT32 player);
 | 
			
		||||
 | 
			
		||||
/// Set the given player index's assigned device. If the device is in use by another player, that player is unassigned.
 | 
			
		||||
void G_SetDeviceForPlayer(INT32 player, INT32 device);
 | 
			
		||||
 | 
			
		||||
/// Get the gamekeydown array (NUMINPUTS values) for the given device, or NULL if the device id is invalid.
 | 
			
		||||
INT32* G_GetDeviceGameKeyDownArray(INT32 device);
 | 
			
		||||
 | 
			
		||||
boolean G_IsDeviceResponding(INT32 device);
 | 
			
		||||
void G_SetDeviceResponding(INT32 device, boolean responding);
 | 
			
		||||
void G_ResetAllDeviceResponding(void);
 | 
			
		||||
 | 
			
		||||
// remaps the input event to a game control.
 | 
			
		||||
void G_MapEventsToControls(event_t *ev);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -58,6 +58,9 @@ struct JoyType_t
 | 
			
		|||
 | 
			
		||||
extern JoyType_t Joystick[MAXSPLITSCREENPLAYERS];
 | 
			
		||||
 | 
			
		||||
void I_SetGamepadPlayerIndex(INT32 device_id, INT32 index);
 | 
			
		||||
void I_SetGamepadIndicatorColor(INT32 device_id, UINT8 red, UINT8 green, UINT8 blue);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
} // extern "C"
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -205,9 +205,8 @@ void I_JoyScale4(void);
 | 
			
		|||
 | 
			
		||||
// Called by D_SRB2Main.
 | 
			
		||||
 | 
			
		||||
/**	\brief to startup a joystick
 | 
			
		||||
*/
 | 
			
		||||
void I_InitJoystick(UINT8 index);
 | 
			
		||||
/// Startup input subsystems.
 | 
			
		||||
void I_StartupInput(void);
 | 
			
		||||
 | 
			
		||||
/**	\brief to startup the first joystick
 | 
			
		||||
*/
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -60,13 +60,6 @@
 | 
			
		|||
// And just some randomness for the exits.
 | 
			
		||||
#include "m_random.h"
 | 
			
		||||
 | 
			
		||||
#if defined(HAVE_SDL)
 | 
			
		||||
#include "SDL.h"
 | 
			
		||||
#if SDL_VERSION_ATLEAST(2,0,0)
 | 
			
		||||
#include "sdl/sdlmain.h" // JOYSTICK_HOTPLUG
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef PC_DOS
 | 
			
		||||
#include <stdio.h> // for snprintf
 | 
			
		||||
int	snprintf(char *str, size_t n, const char *fmt, ...);
 | 
			
		||||
| 
						 | 
				
			
			@ -3385,11 +3378,18 @@ void M_DrawProfileControls(void)
 | 
			
		|||
					// Get userbound controls...
 | 
			
		||||
					for (k = 0; k < MAXINPUTMAPPING; k++)
 | 
			
		||||
					{
 | 
			
		||||
						int device;
 | 
			
		||||
						keys[k] = optionsmenu.tempcontrols[gc][k];
 | 
			
		||||
						if (keys[k] == KEY_NULL)
 | 
			
		||||
							continue;
 | 
			
		||||
						set++;
 | 
			
		||||
						if (!G_KeyIsAvailable(keys[k], cv_usejoystick[0].value))
 | 
			
		||||
 | 
			
		||||
						device = G_GetDeviceForPlayer(0);
 | 
			
		||||
						if (device == -1)
 | 
			
		||||
						{
 | 
			
		||||
							device = 0;
 | 
			
		||||
						}
 | 
			
		||||
						if (!G_KeyIsAvailable(keys[k], device))
 | 
			
		||||
							continue;
 | 
			
		||||
						available++;
 | 
			
		||||
					};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -222,6 +222,22 @@ boolean M_Responder(event_t *ev)
 | 
			
		|||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (gamestate == GS_MENU && ev->type == ev_gamepad_device_removed && G_GetPlayerForDevice(ev->device) != -1)
 | 
			
		||||
	{
 | 
			
		||||
		int i;
 | 
			
		||||
		INT32 player = G_GetPlayerForDevice(ev->device);
 | 
			
		||||
 | 
			
		||||
		// Unassign all controllers
 | 
			
		||||
		for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
 | 
			
		||||
		{
 | 
			
		||||
			G_SetDeviceForPlayer(i, -1);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Return to the title because a controller was removed at the menu.
 | 
			
		||||
		CONS_Alert(CONS_NOTICE, "Player %d's assigned gamepad was removed. Returning to the title screen.", player);
 | 
			
		||||
		D_StartTitle();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (ev->type == ev_keydown && ev->data1 < NUMKEYS)
 | 
			
		||||
	{
 | 
			
		||||
		// Record keyboard presses
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -123,7 +123,7 @@ static void SetDeviceOnPress(void)
 | 
			
		|||
	{
 | 
			
		||||
		if (deviceResponding[i])
 | 
			
		||||
		{
 | 
			
		||||
			CV_SetValue(&cv_usejoystick[0], i);	// Force-set this joystick as the current joystick we're using for P1 (which is the only one controlling menus)
 | 
			
		||||
			G_SetDeviceForPlayer(0, i); // Force-set this joystick as the current joystick we're using for P1 (which is the only one controlling menus)
 | 
			
		||||
			CONS_Printf("SetDeviceOnPress: Device for %d set to %d\n", 0, i);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -307,7 +307,7 @@ void M_MapProfileControl(event_t *ev)
 | 
			
		|||
	UINT8 where = n;										// By default, we'll save the bind where we're supposed to map.
 | 
			
		||||
	INT32 i;
 | 
			
		||||
 | 
			
		||||
	//SetDeviceOnPress();	// Update cv_usejoystick
 | 
			
		||||
	//SetDeviceOnPress();	// Update player gamepad assignments
 | 
			
		||||
 | 
			
		||||
	// Only consider keydown and joystick events to make sure we ignore ev_mouse and other events
 | 
			
		||||
	// See also G_MapEventsToControls
 | 
			
		||||
| 
						 | 
				
			
			@ -325,11 +325,11 @@ void M_MapProfileControl(event_t *ev)
 | 
			
		|||
			}
 | 
			
		||||
#endif
 | 
			
		||||
			break;
 | 
			
		||||
		case ev_joystick:
 | 
			
		||||
		case ev_gamepad_axis:
 | 
			
		||||
			if (ev->data1 >= JOYAXES)
 | 
			
		||||
			{
 | 
			
		||||
#ifdef PARANOIA
 | 
			
		||||
				CONS_Debug(DBG_GAMELOGIC, "Bad joystick axis event %d\n", ev->data1);
 | 
			
		||||
				CONS_Debug(DBG_GAMELOGIC, "Bad gamepad axis event %d\n", ev->data1);
 | 
			
		||||
#endif
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -380,10 +380,10 @@ void M_CharacterSelectInit(void)
 | 
			
		|||
	{
 | 
			
		||||
		for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
 | 
			
		||||
		{
 | 
			
		||||
			// Un-set devices for other players.
 | 
			
		||||
			if (i != 0 || optionsmenu.profile)
 | 
			
		||||
			// Un-set devices for all players if not editing profile
 | 
			
		||||
			if (!optionsmenu.profile)
 | 
			
		||||
			{
 | 
			
		||||
				CV_SetValue(&cv_usejoystick[i], -1);
 | 
			
		||||
				G_SetDeviceForPlayer(i, -1);
 | 
			
		||||
				CONS_Printf("M_CharacterSelectInit: Device for %d set to %d\n", i, -1);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -526,7 +526,12 @@ static boolean M_DeviceAvailable(INT32 deviceID, UINT8 numPlayers)
 | 
			
		|||
 | 
			
		||||
	for (i = 0; i < numPlayers; i++)
 | 
			
		||||
	{
 | 
			
		||||
		if (cv_usejoystick[i].value == deviceID)
 | 
			
		||||
		int player_device = G_GetDeviceForPlayer(i);
 | 
			
		||||
		if (player_device == -1)
 | 
			
		||||
		{
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		if (player_device == deviceID)
 | 
			
		||||
		{
 | 
			
		||||
			// This one's already being used.
 | 
			
		||||
			return false;
 | 
			
		||||
| 
						 | 
				
			
			@ -540,6 +545,7 @@ static boolean M_DeviceAvailable(INT32 deviceID, UINT8 numPlayers)
 | 
			
		|||
static boolean M_HandlePressStart(setup_player_t *p, UINT8 num)
 | 
			
		||||
{
 | 
			
		||||
	INT32 i, j;
 | 
			
		||||
	INT32 num_gamepads_available;
 | 
			
		||||
 | 
			
		||||
	if (optionsmenu.profile)
 | 
			
		||||
		return false;	// Don't allow for the possibility of SOMEHOW another player joining in.
 | 
			
		||||
| 
						 | 
				
			
			@ -568,24 +574,32 @@ static boolean M_HandlePressStart(setup_player_t *p, UINT8 num)
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	// Now detect new devices trying to join.
 | 
			
		||||
	for (i = 0; i < MAXDEVICES; i++)
 | 
			
		||||
	num_gamepads_available = G_GetNumAvailableGamepads();
 | 
			
		||||
	for (i = 0; i < num_gamepads_available + 1; i++)
 | 
			
		||||
	{
 | 
			
		||||
		if (deviceResponding[i] != true)
 | 
			
		||||
		INT32 device = 0;
 | 
			
		||||
 | 
			
		||||
		if (i > 0)
 | 
			
		||||
		{
 | 
			
		||||
			device = G_GetAvailableGamepadDevice(i - 1);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (G_IsDeviceResponding(device) != true)
 | 
			
		||||
		{
 | 
			
		||||
			// No buttons are being pushed.
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (M_DeviceAvailable(i, setup_numplayers) == true)
 | 
			
		||||
		if (M_DeviceAvailable(device, setup_numplayers) == true)
 | 
			
		||||
		{
 | 
			
		||||
			// Available!! Let's use this one!!
 | 
			
		||||
 | 
			
		||||
			// if P1 is setting up using keyboard (device 0), save their last used device.
 | 
			
		||||
			// this is to allow them to retain controller usage when they play alone.
 | 
			
		||||
			// Because let's face it, when you test mods, you're often lazy to grab your controller for menuing :)
 | 
			
		||||
			if (!i && !num)
 | 
			
		||||
			if (i == 0 && num == 0)
 | 
			
		||||
			{
 | 
			
		||||
				setup_player[num].ponedevice = cv_usejoystick[num].value;
 | 
			
		||||
				setup_player[num].ponedevice = G_GetDeviceForPlayer(num);
 | 
			
		||||
			}
 | 
			
		||||
			else if (num)
 | 
			
		||||
			{
 | 
			
		||||
| 
						 | 
				
			
			@ -593,14 +607,13 @@ static boolean M_HandlePressStart(setup_player_t *p, UINT8 num)
 | 
			
		|||
				memcpy(&gamecontrol[num], gamecontroldefault, sizeof(gamecontroldefault));
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			G_SetDeviceForPlayer(num, device);
 | 
			
		||||
			CONS_Printf("M_HandlePressStart: Device for %d set to %d\n", num, device);
 | 
			
		||||
 | 
			
		||||
			CV_SetValue(&cv_usejoystick[num], i);
 | 
			
		||||
			CONS_Printf("M_HandlePressStart: Device for %d set to %d\n", num, i);
 | 
			
		||||
 | 
			
		||||
			for (j = num+1; j < MAXSPLITSCREENPLAYERS; j++)
 | 
			
		||||
			for (j = num + 1; j < MAXSPLITSCREENPLAYERS; j++)
 | 
			
		||||
			{
 | 
			
		||||
				// Un-set devices for other players.
 | 
			
		||||
				CV_SetValue(&cv_usejoystick[j], -1);
 | 
			
		||||
				G_SetDeviceForPlayer(j, -1);
 | 
			
		||||
				CONS_Printf("M_HandlePressStart: Device for %d set to %d\n", j, -1);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -616,7 +629,7 @@ static boolean M_HandlePressStart(setup_player_t *p, UINT8 num)
 | 
			
		|||
				menucmd[j].buttonsHeld |= MBT_X;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			memset(deviceResponding, false, sizeof(deviceResponding));
 | 
			
		||||
			G_ResetAllDeviceResponding();
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -668,11 +681,8 @@ static boolean M_HandleCSelectProfile(setup_player_t *p, UINT8 num)
 | 
			
		|||
				menucmd[i].buttonsHeld |= MBT_X;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (num > 0)
 | 
			
		||||
			{
 | 
			
		||||
				CV_StealthSetValue(&cv_usejoystick[num], -1);
 | 
			
		||||
				CONS_Printf("M_HandleCSelectProfile: Device for %d set to %d\n", num, -1);
 | 
			
		||||
			}
 | 
			
		||||
			G_SetDeviceForPlayer(num, -1);
 | 
			
		||||
			CONS_Printf("M_HandleCSelectProfile: Device for %d set to %d\n", num, -1);
 | 
			
		||||
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -1482,18 +1492,12 @@ void M_CharacterSelectTick(void)
 | 
			
		|||
 | 
			
		||||
				CV_StealthSetValue(&cv_splitplayers, setup_numplayers);
 | 
			
		||||
 | 
			
		||||
				// P1 is alone, set their old device just in case.
 | 
			
		||||
				if (setup_numplayers < 2 && setup_player[0].ponedevice)
 | 
			
		||||
				{
 | 
			
		||||
					CV_StealthSetValue(&cv_usejoystick[0], setup_player[0].ponedevice);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				#if defined (TESTERS)
 | 
			
		||||
					M_MPOptSelectInit(0);
 | 
			
		||||
				#else
 | 
			
		||||
					M_SetupNextMenu(&PLAY_MainDef, false);
 | 
			
		||||
				#endif
 | 
			
		||||
				
 | 
			
		||||
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else	// In a game
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -194,48 +194,6 @@ static char returnWadPath[256];
 | 
			
		|||
#include "../byteptr.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void I_StoreExJoystick(SDL_GameController *dev)
 | 
			
		||||
{
 | 
			
		||||
	// ExJoystick is a massive hack to avoid needing to completely
 | 
			
		||||
	// rewrite pretty much all of the controller support from scratch...
 | 
			
		||||
 | 
			
		||||
	// Used in favor of most instances of SDL_GameControllerClose.
 | 
			
		||||
	// If a joystick would've been discarded, then save it in an array,
 | 
			
		||||
	// because we want it have it for the joystick input screen.
 | 
			
		||||
 | 
			
		||||
	int index = 0;
 | 
			
		||||
 | 
			
		||||
	if (dev == NULL)
 | 
			
		||||
	{
 | 
			
		||||
		// No joystick?
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	index = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(dev));
 | 
			
		||||
 | 
			
		||||
	if (index >= MAXGAMEPADS || index < 0)
 | 
			
		||||
	{
 | 
			
		||||
		// Not enough space to save this joystick, completely discard.
 | 
			
		||||
		SDL_GameControllerClose(dev);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (ExJoystick[index] == dev)
 | 
			
		||||
	{
 | 
			
		||||
		// No need to do anything else.
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (ExJoystick[index] != NULL)
 | 
			
		||||
	{
 | 
			
		||||
		// Discard joystick in the old slot.
 | 
			
		||||
		SDL_GameControllerClose(ExJoystick[index]);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Keep for safe-keeping.
 | 
			
		||||
	ExJoystick[index] = dev;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**	\brief	The JoyReset function
 | 
			
		||||
 | 
			
		||||
	\param	JoySet	Joystick info to reset
 | 
			
		||||
| 
						 | 
				
			
			@ -244,10 +202,6 @@ void I_StoreExJoystick(SDL_GameController *dev)
 | 
			
		|||
*/
 | 
			
		||||
static void JoyReset(SDLJoyInfo_t *JoySet)
 | 
			
		||||
{
 | 
			
		||||
	if (JoySet->dev)
 | 
			
		||||
	{
 | 
			
		||||
		I_StoreExJoystick(JoySet->dev);
 | 
			
		||||
	}
 | 
			
		||||
	JoySet->dev = NULL;
 | 
			
		||||
	JoySet->oldjoy = -1;
 | 
			
		||||
	JoySet->axises = JoySet->buttons = JoySet->hats = JoySet->balls = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -261,7 +215,6 @@ static INT32 joystick_started[MAXSPLITSCREENPLAYERS] = {0,0,0,0};
 | 
			
		|||
/**	\brief SDL info about joystick 1
 | 
			
		||||
*/
 | 
			
		||||
SDLJoyInfo_t JoyInfo[MAXSPLITSCREENPLAYERS];
 | 
			
		||||
SDL_GameController *ExJoystick[MAXGAMEPADS];
 | 
			
		||||
 | 
			
		||||
SDL_bool consolevent = SDL_FALSE;
 | 
			
		||||
SDL_bool framebuffer = SDL_FALSE;
 | 
			
		||||
| 
						 | 
				
			
			@ -983,316 +936,78 @@ void I_JoyScale4(void)
 | 
			
		|||
	JoyInfo[3].scale = Joystick[3].bGamepadStyle?1:cv_joyscale[1].value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Cheat to get the device index for a game controller handle
 | 
			
		||||
INT32 I_GetJoystickDeviceIndex(SDL_GameController *dev)
 | 
			
		||||
void I_SetGamepadPlayerIndex(INT32 device_id, INT32 player)
 | 
			
		||||
{
 | 
			
		||||
	SDL_Joystick *joystick = NULL;
 | 
			
		||||
#if !(SDL_VERSION_ATLEAST(2,0,12))
 | 
			
		||||
	(void)device_id;
 | 
			
		||||
	(void)player;
 | 
			
		||||
#else
 | 
			
		||||
	I_Assert(device_id > 0); // Gamepad devices are always ID 1 or higher
 | 
			
		||||
	I_Assert(player >= 0 && player < MAXSPLITSCREENPLAYERS);
 | 
			
		||||
 | 
			
		||||
	joystick = SDL_GameControllerGetJoystick(dev);
 | 
			
		||||
 | 
			
		||||
	if (joystick)
 | 
			
		||||
	SDL_GameController *controller = SDL_GameControllerFromInstanceID(device_id - 1);
 | 
			
		||||
	if (controller == NULL)
 | 
			
		||||
	{
 | 
			
		||||
		return SDL_JoystickInstanceID(joystick);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return -1;
 | 
			
		||||
	SDL_GameControllerSetPlayerIndex(controller, player);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void I_UpdateJoystickDeviceIndex(UINT8 player)
 | 
			
		||||
void I_SetGamepadIndicatorColor(INT32 device_id, UINT8 red, UINT8 green, UINT8 blue)
 | 
			
		||||
{
 | 
			
		||||
	///////////////////////////////////////////////
 | 
			
		||||
	// update this joystick's device index (wow) //
 | 
			
		||||
	///////////////////////////////////////////////
 | 
			
		||||
#if !(SDL_VERSION_ATLEAST(2,0,14))
 | 
			
		||||
	(void)device_id;
 | 
			
		||||
	(void)player;
 | 
			
		||||
#else
 | 
			
		||||
	I_Assert(device_id > 0); // Gamepad devices are always ID 1 or higher
 | 
			
		||||
 | 
			
		||||
	if (JoyInfo[player].dev)
 | 
			
		||||
	SDL_GameController *controller = SDL_GameControllerFromInstanceID(device_id - 1);
 | 
			
		||||
	if (controller == NULL)
 | 
			
		||||
	{
 | 
			
		||||
		cv_usejoystick[player].value = I_GetJoystickDeviceIndex(JoyInfo[player].dev) + 1;
 | 
			
		||||
		CONS_Printf("I_UpdateJoystickDeviceIndex: Device for %d set to %d\n", player, cv_usejoystick[player].value);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		UINT8 joystickID, compareJoystick;
 | 
			
		||||
 | 
			
		||||
		for (joystickID = 0; joystickID < MAXSPLITSCREENPLAYERS; joystickID++)
 | 
			
		||||
		{
 | 
			
		||||
			// is this cv_usejoystick used?
 | 
			
		||||
			const INT32 value = atoi(cv_usejoystick[joystickID].string);
 | 
			
		||||
 | 
			
		||||
			for (compareJoystick = 0; compareJoystick < MAXSPLITSCREENPLAYERS; compareJoystick++)
 | 
			
		||||
			{
 | 
			
		||||
				if (compareJoystick == player)
 | 
			
		||||
					continue;
 | 
			
		||||
 | 
			
		||||
				if (value == JoyInfo[compareJoystick].oldjoy || value == cv_usejoystick[compareJoystick].value)
 | 
			
		||||
					break;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (compareJoystick == MAXSPLITSCREENPLAYERS)
 | 
			
		||||
			{
 | 
			
		||||
				// We DID make it through the whole loop, so we can use this one!
 | 
			
		||||
				cv_usejoystick[player].value = value;
 | 
			
		||||
				CONS_Printf("I_UpdateJoystickDeviceIndex: Device for %d set to %d\n", player, cv_usejoystick[player].value);
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (joystickID == MAXSPLITSCREENPLAYERS)
 | 
			
		||||
		{
 | 
			
		||||
			// We DID NOT make it through the whole loop, so we can't assign this joystick to anything.
 | 
			
		||||
			// When you try your best, but you don't succeed...
 | 
			
		||||
			cv_usejoystick[player].value = 0;
 | 
			
		||||
			CONS_Printf("I_UpdateJoystickDeviceIndex: Device for %d set to %d\n", player, 0);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Misleading function: updates device indices for all players BUT the one specified.
 | 
			
		||||
// Necessary for SDL_JOYDEVICEADDED events
 | 
			
		||||
void I_UpdateJoystickDeviceIndices(UINT8 excludePlayer)
 | 
			
		||||
{
 | 
			
		||||
	UINT8 player;
 | 
			
		||||
 | 
			
		||||
	for (player = 0; player < MAXSPLITSCREENPLAYERS; player++)
 | 
			
		||||
	{
 | 
			
		||||
		if (player == excludePlayer)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		I_UpdateJoystickDeviceIndex(player);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**	\brief	Shuts down joystick
 | 
			
		||||
	\return void
 | 
			
		||||
*/
 | 
			
		||||
void I_ShutdownJoystick(UINT8 index)
 | 
			
		||||
{
 | 
			
		||||
	INT32 i;
 | 
			
		||||
	event_t event;
 | 
			
		||||
 | 
			
		||||
	event.device = I_GetJoystickDeviceIndex(JoyInfo[index].dev);
 | 
			
		||||
	event.type = ev_keyup;
 | 
			
		||||
	event.data2 = 0;
 | 
			
		||||
	event.data3 = 0;
 | 
			
		||||
 | 
			
		||||
	// emulate the up of all joystick buttons
 | 
			
		||||
	for (i = 0; i < JOYBUTTONS; i++)
 | 
			
		||||
	{
 | 
			
		||||
		event.data1 = KEY_JOY1+i;
 | 
			
		||||
		D_PostEvent(&event);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// reset joystick position
 | 
			
		||||
	event.type = ev_joystick;
 | 
			
		||||
	for (i = 0; i < JOYAXES; i++)
 | 
			
		||||
	{
 | 
			
		||||
		event.data1 = i;
 | 
			
		||||
		D_PostEvent(&event);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	joystick_started[index] = 0;
 | 
			
		||||
	JoyReset(&JoyInfo[index]);
 | 
			
		||||
 | 
			
		||||
	// don't shut down the subsystem here, because hotplugging
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**	\brief	Open joystick handle
 | 
			
		||||
 | 
			
		||||
	\param	fname	name of joystick
 | 
			
		||||
 | 
			
		||||
	\return	axises
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
static int joy_open(int playerIndex, int joyIndex)
 | 
			
		||||
{
 | 
			
		||||
	SDL_GameController *newdev = NULL;
 | 
			
		||||
	int num_joy = 0;
 | 
			
		||||
 | 
			
		||||
	if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0)
 | 
			
		||||
	{
 | 
			
		||||
		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;
 | 
			
		||||
 | 
			
		||||
	num_joy = SDL_NumJoysticks();
 | 
			
		||||
 | 
			
		||||
	if (num_joy == 0)
 | 
			
		||||
	{
 | 
			
		||||
		CONS_Printf("%s", M_GetText("Found no joysticks on this system\n"));
 | 
			
		||||
		return -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.
 | 
			
		||||
	//
 | 
			
		||||
	// Example:
 | 
			
		||||
	// 1. Plug Controller A   -> Index 0 opened
 | 
			
		||||
	// 2. Plug Controller B   -> Index 1 opened
 | 
			
		||||
	// 3. Unplug Controller A -> Index 0 closed, Index 1 active
 | 
			
		||||
	// 4. Unplug Controller B -> Index 0 inactive, Index 1 closed
 | 
			
		||||
	// 5. Plug Controller B   -> Index 0 opened
 | 
			
		||||
	// 6. Plug Controller A   -> Index 0 REPLACED, opened as Controller A; Index 1 is now Controller B
 | 
			
		||||
	if (JoyInfo[playerIndex].dev)
 | 
			
		||||
	{
 | 
			
		||||
		if (JoyInfo[playerIndex].dev == newdev // same device, nothing to do
 | 
			
		||||
			|| (newdev == NULL && SDL_GameControllerGetAttached(JoyInfo[playerIndex].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, "Joystick%d device is changing; resetting events...\n", playerIndex+1);
 | 
			
		||||
		I_ShutdownJoystick(playerIndex);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	JoyInfo[playerIndex].dev = newdev;
 | 
			
		||||
 | 
			
		||||
	if (JoyInfo[playerIndex].dev == NULL)
 | 
			
		||||
	{
 | 
			
		||||
		CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick%d: Couldn't open device - %s\n"), playerIndex+1, SDL_GetError());
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick%d: %s\n"), playerIndex+1, SDL_GameControllerName(JoyInfo[playerIndex].dev));
 | 
			
		||||
 | 
			
		||||
		JoyInfo[playerIndex].axises = SDL_CONTROLLER_AXIS_MAX;
 | 
			
		||||
		JoyInfo[playerIndex].buttons = SDL_CONTROLLER_BUTTON_MAX;
 | 
			
		||||
		JoyInfo[playerIndex].hats = 1;
 | 
			
		||||
		JoyInfo[playerIndex].balls = 0;
 | 
			
		||||
 | 
			
		||||
		//JoyInfo[playerIndex].bGamepadStyle = !stricmp(SDL_JoystickName(JoyInfo[playerIndex].dev), "pad");
 | 
			
		||||
 | 
			
		||||
		return JoyInfo[playerIndex].axises;
 | 
			
		||||
	}
 | 
			
		||||
	SDL_GameControllerSetLED(controller, red, green, blue);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// I_InitJoystick
 | 
			
		||||
// I_StartupInput
 | 
			
		||||
//
 | 
			
		||||
void I_InitJoystick(UINT8 index)
 | 
			
		||||
void I_StartupInput(void)
 | 
			
		||||
{
 | 
			
		||||
	SDL_GameController *newcontroller = NULL;
 | 
			
		||||
	UINT8 i;
 | 
			
		||||
 | 
			
		||||
	//I_ShutdownJoystick();
 | 
			
		||||
	//SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE);
 | 
			
		||||
	if (M_CheckParm("-nojoy"))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (SDL_WasInit(SDL_INIT_GAMECONTROLLER))
 | 
			
		||||
	{
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (M_CheckParm("-noxinput"))
 | 
			
		||||
		SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE);
 | 
			
		||||
 | 
			
		||||
	if (M_CheckParm("-nohidapi"))
 | 
			
		||||
		SDL_SetHintWithPriority("SDL_JOYSTICK_HIDAPI", "0", SDL_HINT_OVERRIDE);
 | 
			
		||||
 | 
			
		||||
	if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0)
 | 
			
		||||
	{
 | 
			
		||||
		CONS_Printf("I_InitJoystick()...\n");
 | 
			
		||||
	CONS_Printf("I_StartupInput()...\n");
 | 
			
		||||
 | 
			
		||||
		if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1)
 | 
			
		||||
		{
 | 
			
		||||
			CONS_Printf(M_GetText("Couldn't initialize joystick: %s\n"), SDL_GetError());
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
	if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) == -1)
 | 
			
		||||
	{
 | 
			
		||||
		CONS_Printf(M_GetText("Couldn't initialize game controllers: %s\n"), SDL_GetError());
 | 
			
		||||
		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[index].value)
 | 
			
		||||
		newcontroller = SDL_GameControllerOpen(cv_usejoystick[index].value-1);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
 | 
			
		||||
	{
 | 
			
		||||
		if (i == index)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		if (JoyInfo[i].dev == newcontroller)
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (newcontroller && i < MAXSPLITSCREENPLAYERS) // don't override an active device
 | 
			
		||||
	{
 | 
			
		||||
		cv_usejoystick[index].value = I_GetJoystickDeviceIndex(JoyInfo[index].dev) + 1;
 | 
			
		||||
		CONS_Printf("I_InitJoystick: Device for %d set to %d\n", index, cv_usejoystick[index].value);
 | 
			
		||||
	}
 | 
			
		||||
	else if (newcontroller && joy_open(index, cv_usejoystick[index].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.
 | 
			
		||||
		JoyInfo[index].oldjoy = I_GetJoystickDeviceIndex(JoyInfo[index].dev) + 1;
 | 
			
		||||
		joystick_started[index] = 1;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		if (JoyInfo[index].oldjoy)
 | 
			
		||||
			I_ShutdownJoystick(index);
 | 
			
		||||
		cv_usejoystick[index].value = 0;
 | 
			
		||||
		CONS_Printf("I_InitJoystick: Device for %d set to %d\n", index, cv_usejoystick[index].value);
 | 
			
		||||
		joystick_started[index] = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
 | 
			
		||||
	{
 | 
			
		||||
		if (JoyInfo[i].dev == newcontroller)
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (i == MAXSPLITSCREENPLAYERS)
 | 
			
		||||
	{
 | 
			
		||||
		// Joystick didn't end up being used
 | 
			
		||||
		I_StoreExJoystick(newcontroller);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void I_InitJoystick1(void)
 | 
			
		||||
{
 | 
			
		||||
	I_InitJoystick(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void I_InitJoystick2(void)
 | 
			
		||||
{
 | 
			
		||||
	I_InitJoystick(1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void I_InitJoystick3(void)
 | 
			
		||||
{
 | 
			
		||||
	I_InitJoystick(2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void I_InitJoystick4(void)
 | 
			
		||||
{
 | 
			
		||||
	I_InitJoystick(3);
 | 
			
		||||
	// Upon initialization, the gamecontroller subsystem will automatically dispatch controller device added events
 | 
			
		||||
	// for controllers connected before initialization.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void I_ShutdownInput(void)
 | 
			
		||||
{
 | 
			
		||||
	UINT8 i;
 | 
			
		||||
 | 
			
		||||
	// Yes, the name is misleading: these send neutral events to
 | 
			
		||||
	// clean up the unplugged joystick's input
 | 
			
		||||
	// Note these methods are internal to this file, not called elsewhere.
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
 | 
			
		||||
		I_ShutdownJoystick(i);
 | 
			
		||||
	// The game code is now responsible for resetting its internal state based on ev_gamepad_device_removed events.
 | 
			
		||||
	// In practice, Input should never be shutdown and restarted during runtime.
 | 
			
		||||
 | 
			
		||||
	if (SDL_WasInit(SDL_INIT_GAMECONTROLLER) == SDL_INIT_GAMECONTROLLER)
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -1322,14 +1037,28 @@ static char joyname[255]; // joystick name is straight from the driver
 | 
			
		|||
const char *I_GetJoyName(INT32 joyindex)
 | 
			
		||||
{
 | 
			
		||||
	const char *tempname = NULL;
 | 
			
		||||
	SDL_Joystick* joystick;
 | 
			
		||||
	joyname[0] = 0;
 | 
			
		||||
	joyindex--; //SDL's Joystick System starts at 0, not 1
 | 
			
		||||
	if (SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK)
 | 
			
		||||
 | 
			
		||||
	if (!SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK)
 | 
			
		||||
	{
 | 
			
		||||
		tempname = SDL_JoystickNameForIndex(joyindex);
 | 
			
		||||
		if (tempname)
 | 
			
		||||
			strncpy(joyname, tempname, 255);
 | 
			
		||||
		return joyname;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// joyindex corresponds to the open joystick *instance* ID, not the joystick number
 | 
			
		||||
	joystick = SDL_JoystickFromInstanceID(joyindex);
 | 
			
		||||
	if (joystick == NULL)
 | 
			
		||||
	{
 | 
			
		||||
		return joyname;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tempname = SDL_JoystickNameForIndex(joyindex);
 | 
			
		||||
	if (tempname)
 | 
			
		||||
	{
 | 
			
		||||
		strncpy(joyname, tempname, 255);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return joyname;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -542,7 +542,7 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt)
 | 
			
		|||
			SDLforceUngrabMouse();
 | 
			
		||||
		}
 | 
			
		||||
		memset(gamekeydown, 0, sizeof(gamekeydown)); // TODO this is a scary memset
 | 
			
		||||
		memset(deviceResponding, false, sizeof (deviceResponding));
 | 
			
		||||
		G_ResetAllDeviceResponding();
 | 
			
		||||
 | 
			
		||||
		if (MOUSE_MENU)
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			@ -701,7 +701,7 @@ static void Impl_HandleControllerAxisEvent(SDL_ControllerAxisEvent evt)
 | 
			
		|||
	event_t event;
 | 
			
		||||
	INT32 value;
 | 
			
		||||
 | 
			
		||||
	event.type = ev_joystick;
 | 
			
		||||
	event.type = ev_gamepad_axis;
 | 
			
		||||
 | 
			
		||||
	event.device = 1 + evt.which;
 | 
			
		||||
	if (event.device == INT32_MAX)
 | 
			
		||||
| 
						 | 
				
			
			@ -777,6 +777,40 @@ static void Impl_HandleControllerButtonEvent(SDL_ControllerButtonEvent evt, Uint
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void Impl_HandleControllerDeviceAddedEvent(SDL_ControllerDeviceEvent event)
 | 
			
		||||
{
 | 
			
		||||
	// The game is always interested in controller events, even if they aren't internally assigned to a player.
 | 
			
		||||
	// Thus, we *always* open SDL controllers as they become available, to begin receiving their events.
 | 
			
		||||
 | 
			
		||||
	SDL_GameController* controller = SDL_GameControllerOpen(event.which);
 | 
			
		||||
	if (controller == NULL)
 | 
			
		||||
	{
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	SDL_Joystick* joystick = SDL_GameControllerGetJoystick(controller);
 | 
			
		||||
	SDL_JoystickID joystick_instance_id = SDL_JoystickInstanceID(joystick);
 | 
			
		||||
 | 
			
		||||
	event_t engine_event {};
 | 
			
		||||
 | 
			
		||||
	engine_event.type = ev_gamepad_device_added;
 | 
			
		||||
	engine_event.device = 1 + joystick_instance_id;
 | 
			
		||||
 | 
			
		||||
	D_PostEvent(&engine_event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void Impl_HandleControllerDeviceRemovedEvent(SDL_ControllerDeviceEvent event)
 | 
			
		||||
{
 | 
			
		||||
	// SDL only posts Device Removed events for controllers that have actually been opened.
 | 
			
		||||
	// Thus, we don't need to filter out controllers that may not have opened successfully prior to this event.
 | 
			
		||||
	event_t engine_event {};
 | 
			
		||||
 | 
			
		||||
	engine_event.type = ev_gamepad_device_removed;
 | 
			
		||||
	engine_event.device = 1 + event.which;
 | 
			
		||||
 | 
			
		||||
	D_PostEvent(&engine_event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static ImGuiKey ImGui_ImplSDL2_KeycodeToImGuiKey(int keycode)
 | 
			
		||||
{
 | 
			
		||||
	switch (keycode)
 | 
			
		||||
| 
						 | 
				
			
			@ -983,8 +1017,6 @@ void I_GetEvent(void)
 | 
			
		|||
	// otherwise we'll end up catching the warp back to center.
 | 
			
		||||
	//int mouseMotionOnce = 0;
 | 
			
		||||
 | 
			
		||||
	UINT8 i;
 | 
			
		||||
 | 
			
		||||
	if (!graphics_started)
 | 
			
		||||
	{
 | 
			
		||||
		return;
 | 
			
		||||
| 
						 | 
				
			
			@ -1031,147 +1063,14 @@ void I_GetEvent(void)
 | 
			
		|||
				Impl_HandleControllerButtonEvent(evt.cbutton, evt.type);
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
			case SDL_CONTROLLERDEVICEADDED:
 | 
			
		||||
				{
 | 
			
		||||
					// OH BOY are you in for a good time! #abominationstation
 | 
			
		||||
 | 
			
		||||
					SDL_GameController *newcontroller = SDL_GameControllerOpen(evt.cdevice.which);
 | 
			
		||||
 | 
			
		||||
					CONS_Debug(DBG_GAMELOGIC, "Controller device index %d added\n", evt.cdevice.which + 1);
 | 
			
		||||
 | 
			
		||||
					////////////////////////////////////////////////////////////
 | 
			
		||||
					// Because SDL's device index is unstable, we're going to cheat here a bit:
 | 
			
		||||
					// For the first joystick setting that is NOT active:
 | 
			
		||||
					//
 | 
			
		||||
					// 1. Set cv_usejoystickX.value to the new device index (this does not change what is written to config.cfg)
 | 
			
		||||
					//
 | 
			
		||||
					// 2. Set OTHERS' cv_usejoystickX.value to THEIR new device index, because it likely changed
 | 
			
		||||
					//    * If device doesn't exist, switch cv_usejoystick back to default value (.string)
 | 
			
		||||
					//      * BUT: If that default index is being occupied, use ANOTHER cv_usejoystick's default value!
 | 
			
		||||
					////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
					for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
 | 
			
		||||
					{
 | 
			
		||||
						if (newcontroller && (!JoyInfo[i].dev || !SDL_GameControllerGetAttached(JoyInfo[i].dev)))
 | 
			
		||||
						{
 | 
			
		||||
							UINT8 j;
 | 
			
		||||
 | 
			
		||||
							for (j = 0; j < MAXSPLITSCREENPLAYERS; j++)
 | 
			
		||||
							{
 | 
			
		||||
								if (i == j)
 | 
			
		||||
									continue;
 | 
			
		||||
 | 
			
		||||
								if (JoyInfo[j].dev == newcontroller)
 | 
			
		||||
									break;
 | 
			
		||||
							}
 | 
			
		||||
 | 
			
		||||
							if (j == MAXSPLITSCREENPLAYERS)
 | 
			
		||||
							{
 | 
			
		||||
								// ensures we aren't overriding a currently active device
 | 
			
		||||
								cv_usejoystick[i].value = evt.cdevice.which + 1;
 | 
			
		||||
								I_UpdateJoystickDeviceIndices(0);
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					////////////////////////////////////////////////////////////
 | 
			
		||||
					// Was cv_usejoystick disabled in settings?
 | 
			
		||||
					////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
					for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
 | 
			
		||||
					{
 | 
			
		||||
						if (!strcmp(cv_usejoystick[i].string, "0") || !cv_usejoystick[i].value)
 | 
			
		||||
							cv_usejoystick[i].value = 0;
 | 
			
		||||
						else if (atoi(cv_usejoystick[i].string) <= I_NumJoys() // don't mess if we intentionally set higher than NumJoys
 | 
			
		||||
								 && cv_usejoystick[i].value) // update the cvar ONLY if a device exists
 | 
			
		||||
							CV_SetValue(&cv_usejoystick[i], cv_usejoystick[i].value);
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					////////////////////////////////////////////////////////////
 | 
			
		||||
					// Update all joysticks' init states
 | 
			
		||||
					// This is a little wasteful since cv_usejoystick already calls this, but
 | 
			
		||||
					// we need to do this in case CV_SetValue did nothing because the string was already same.
 | 
			
		||||
					// if the device is already active, this should do nothing, effectively.
 | 
			
		||||
					////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
					for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
 | 
			
		||||
						I_InitJoystick(i);
 | 
			
		||||
 | 
			
		||||
					////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
					for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
 | 
			
		||||
						CONS_Debug(DBG_GAMELOGIC, "Joystick%d device index: %d\n", i+1, JoyInfo[i].oldjoy);
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
					// update the menu
 | 
			
		||||
					if (currentMenu == &OP_JoystickSetDef)
 | 
			
		||||
						M_SetupJoystickMenu(0);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
					for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
 | 
			
		||||
					{
 | 
			
		||||
						if (JoyInfo[i].dev == newcontroller)
 | 
			
		||||
							break;
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					if (i == MAXSPLITSCREENPLAYERS)
 | 
			
		||||
						I_StoreExJoystick(newcontroller);
 | 
			
		||||
				}
 | 
			
		||||
				Impl_HandleControllerDeviceAddedEvent(evt.cdevice);
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
			case SDL_CONTROLLERDEVICEREMOVED:
 | 
			
		||||
				for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
 | 
			
		||||
				{
 | 
			
		||||
					if (JoyInfo[i].dev && !SDL_GameControllerGetAttached(JoyInfo[i].dev))
 | 
			
		||||
					{
 | 
			
		||||
						CONS_Debug(DBG_GAMELOGIC, "Joystick%d removed, device index: %d\n", i+1, JoyInfo[i].oldjoy);
 | 
			
		||||
						I_ShutdownJoystick(i);
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				////////////////////////////////////////////////////////////
 | 
			
		||||
				// Update the device indexes, because they likely changed
 | 
			
		||||
				// * If device doesn't exist, switch cv_usejoystick back to default value (.string)
 | 
			
		||||
				//   * BUT: If that default index is being occupied, use ANOTHER cv_usejoystick's default value!
 | 
			
		||||
				////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
				for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
 | 
			
		||||
				{
 | 
			
		||||
					I_UpdateJoystickDeviceIndex(i);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				////////////////////////////////////////////////////////////
 | 
			
		||||
				// Was cv_usejoystick disabled in settings?
 | 
			
		||||
				////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
				for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
 | 
			
		||||
				{
 | 
			
		||||
					if (!strcmp(cv_usejoystick[i].string, "0"))
 | 
			
		||||
					{
 | 
			
		||||
						cv_usejoystick[i].value = 0;
 | 
			
		||||
					}
 | 
			
		||||
					else if (atoi(cv_usejoystick[i].string) <= I_NumJoys() // don't mess if we intentionally set higher than NumJoys
 | 
			
		||||
						&& cv_usejoystick[i].value) // update the cvar ONLY if a device exists
 | 
			
		||||
					{
 | 
			
		||||
						CV_SetValue(&cv_usejoystick[i], cv_usejoystick[i].value);
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
				for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
 | 
			
		||||
					CONS_Debug(DBG_GAMELOGIC, "Joystick%d device index: %d\n", i+1, JoyInfo[i].oldjoy);
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
				// update the menu
 | 
			
		||||
				if (currentMenu == &OP_JoystickSetDef)
 | 
			
		||||
					M_SetupJoystickMenu(0);
 | 
			
		||||
#endif
 | 
			
		||||
				Impl_HandleControllerDeviceRemovedEvent(evt.cdevice);
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			case SDL_QUIT:
 | 
			
		||||
				LUA_HookBool(true, HOOK(GameQuit));
 | 
			
		||||
				I_Quit();
 | 
			
		||||
| 
						 | 
				
			
			@ -1195,10 +1094,7 @@ void I_GetEvent(void)
 | 
			
		|||
 | 
			
		||||
	// In order to make wheels act like buttons, we have to set their state to Up.
 | 
			
		||||
	// This is because wheel messages don't have an up/down state.
 | 
			
		||||
	for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
 | 
			
		||||
	{
 | 
			
		||||
		gamekeydown[i][KEY_MOUSEWHEELDOWN] = gamekeydown[i][KEY_MOUSEWHEELUP] = 0;
 | 
			
		||||
	}
 | 
			
		||||
	G_GetDeviceGameKeyDownArray(0)[KEY_MOUSEWHEELDOWN] = G_GetDeviceGameKeyDownArray(0)[KEY_MOUSEWHEELUP] = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void half_warp_mouse(uint16_t x, uint16_t y) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -36,9 +36,6 @@ extern "C" {
 | 
			
		|||
#define SDL2STUB() CONS_Printf("SDL2: stubbed: %s:%d\n", __func__, __LINE__)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// So m_menu knows whether to store cv_usejoystick value or string
 | 
			
		||||
#define JOYSTICK_HOTPLUG
 | 
			
		||||
 | 
			
		||||
/**	\brief	The JoyInfo_s struct
 | 
			
		||||
 | 
			
		||||
  info about joystick
 | 
			
		||||
| 
						 | 
				
			
			@ -65,9 +62,6 @@ typedef struct SDLJoyInfo_s
 | 
			
		|||
/**	\brief SDL info about controllers
 | 
			
		||||
*/
 | 
			
		||||
extern SDLJoyInfo_t JoyInfo[MAXSPLITSCREENPLAYERS];
 | 
			
		||||
extern SDL_GameController *ExJoystick[MAXGAMEPADS];
 | 
			
		||||
 | 
			
		||||
void I_StoreExJoystick(SDL_GameController *dev);
 | 
			
		||||
 | 
			
		||||
/**	\brief joystick axis deadzone
 | 
			
		||||
*/
 | 
			
		||||
| 
						 | 
				
			
			@ -76,18 +70,6 @@ void I_StoreExJoystick(SDL_GameController *dev);
 | 
			
		|||
 | 
			
		||||
void I_GetConsoleEvents(void);
 | 
			
		||||
 | 
			
		||||
// So we can call this from i_video event loop
 | 
			
		||||
void I_ShutdownJoystick(UINT8 index);
 | 
			
		||||
 | 
			
		||||
// 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_UpdateJoystickDeviceIndex(UINT8 player);
 | 
			
		||||
void I_UpdateJoystickDeviceIndices(UINT8 excludePlayer);
 | 
			
		||||
 | 
			
		||||
void I_GetConsoleEvents(void);
 | 
			
		||||
 | 
			
		||||
void SDLforceUngrabMouse(void);
 | 
			
		||||
 | 
			
		||||
// Needed for some WIN32 functions
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue