diff --git a/src/command.c b/src/command.c
index 464bf52162c72a316f6ddeb1c2bd6cabeaf0b2fd..d39730f98e74ab976b0a529b373f46f8f869b41e 100644
--- a/src/command.c
+++ b/src/command.c
@@ -49,6 +49,7 @@ static void COM_Exec_f(void);
 static void COM_Wait_f(void);
 static void COM_Help_f(void);
 static void COM_Toggle_f(void);
+static void COM_Add_f(void);
 
 static void CV_EnforceExecVersion(void);
 static boolean CV_FilterVarByVersion(consvar_t *v, const char *valstr);
@@ -291,6 +292,7 @@ void COM_Init(void)
 	COM_AddCommand("wait", COM_Wait_f);
 	COM_AddCommand("help", COM_Help_f);
 	COM_AddCommand("toggle", COM_Toggle_f);
+	COM_AddCommand("add", COM_Add_f);
 	RegisterNetXCmd(XD_NETVAR, Got_NetVar);
 }
 
@@ -876,6 +878,30 @@ static void COM_Toggle_f(void)
 	CV_AddValue(cvar, +1);
 }
 
+/** Command variant of CV_AddValue
+  */
+static void COM_Add_f(void)
+{
+	consvar_t *cvar;
+
+	if (COM_Argc() != 3)
+	{
+		CONS_Printf(M_GetText("Add <cvar_name> <value>: Add to the value of a cvar. Negative values work too!\n"));
+		return;
+	}
+	cvar = CV_FindVar(COM_Argv(1));
+	if (!cvar)
+	{
+		CONS_Alert(CONS_NOTICE, M_GetText("%s is not a cvar\n"), COM_Argv(1));
+		return;
+	}
+
+	if (( cvar->flags & CV_FLOAT ))
+		CV_Set(cvar, va("%f", FIXED_TO_FLOAT (cvar->value) + atof(COM_Argv(2))));
+	else
+		CV_AddValue(cvar, atoi(COM_Argv(2)));
+}
+
 // =========================================================================
 //                      VARIABLE SIZE BUFFERS
 // =========================================================================
diff --git a/src/d_clisrv.c b/src/d_clisrv.c
index ad232426af8072db9d094e71521b84f3f220d68f..88c855f65cdbbd2a51690d1eca898f8f4efd186b 100644
--- a/src/d_clisrv.c
+++ b/src/d_clisrv.c
@@ -83,11 +83,9 @@ tic_t jointimeout = (10*TICRATE);
 static boolean sendingsavegame[MAXNETNODES]; // Are we sending the savegame?
 static tic_t freezetimeout[MAXNETNODES]; // Until when can this node freeze the server before getting a timeout?
 
-#ifdef NEWPING
 UINT16 pingmeasurecount = 1;
 UINT32 realpingtable[MAXPLAYERS]; //the base table of ping where an average will be sent to everyone.
 UINT32 playerpingtable[MAXPLAYERS]; //table of player latency values.
-#endif
 SINT8 nodetoplayer[MAXNETNODES];
 SINT8 nodetoplayer2[MAXNETNODES]; // say the numplayer for this node if any (splitscreen)
 UINT8 playerpernode[MAXNETNODES]; // used specialy for scplitscreen
@@ -1325,33 +1323,13 @@ static void SV_SendPlayerInfo(INT32 node)
 			continue;
 		}
 
-		netbuffer->u.playerinfo[i].node = (UINT8)playernode[i];
+		netbuffer->u.playerinfo[i].node = i;
 		strncpy(netbuffer->u.playerinfo[i].name, (const char *)&player_names[i], MAXPLAYERNAME+1);
 		netbuffer->u.playerinfo[i].name[MAXPLAYERNAME] = '\0';
 
 		//fetch IP address
-		{
-			const char *claddress;
-			UINT32 numericaddress[4];
-
-			memset(netbuffer->u.playerinfo[i].address, 0, 4);
-			if (playernode[i] == 0)
-			{
-				//127.0.0.1
-				netbuffer->u.playerinfo[i].address[0] = 127;
-				netbuffer->u.playerinfo[i].address[3] = 1;
-			}
-			else if (playernode[i] > 0 && I_GetNodeAddress && (claddress = I_GetNodeAddress(playernode[i])) != NULL)
-			{
-				if (sscanf(claddress, "%d.%d.%d.%d", &numericaddress[0], &numericaddress[1], &numericaddress[2], &numericaddress[3]) < 4)
-					goto badaddress;
-				netbuffer->u.playerinfo[i].address[0] = (UINT8)numericaddress[0];
-				netbuffer->u.playerinfo[i].address[1] = (UINT8)numericaddress[1];
-				netbuffer->u.playerinfo[i].address[2] = (UINT8)numericaddress[2];
-				netbuffer->u.playerinfo[i].address[3] = (UINT8)numericaddress[3];
-			}
-		}
-		badaddress:
+		//No, don't do that, you fuckface.
+		memset(netbuffer->u.playerinfo[i].address, 0, 4);
 
 		if (G_GametypeHasTeams())
 		{
@@ -2883,12 +2861,10 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
 			HU_AddChatText(va("\x82*%s has been kicked (Go away)", player_names[pnum]), false);
 			kickreason = KR_KICK;
 			break;
-#ifdef NEWPING
 		case KICK_MSG_PING_HIGH:
 			HU_AddChatText(va("\x82*%s left the game (Broke ping limit)", player_names[pnum]), false);
 			kickreason = KR_PINGLIMIT;
 			break;
-#endif
 		case KICK_MSG_CON_FAIL:
 			HU_AddChatText(va("\x82*%s left the game (Synch Failure)", player_names[pnum]), false);
 			kickreason = KR_SYNCH;
@@ -2961,10 +2937,8 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
 		D_StartTitle();
 		if (msg == KICK_MSG_CON_FAIL)
 			M_StartMessage(M_GetText("Server closed connection\n(synch failure)\nPress ESC\n"), NULL, MM_NOTHING);
-#ifdef NEWPING
 		else if (msg == KICK_MSG_PING_HIGH)
 			M_StartMessage(M_GetText("Server closed connection\n(Broke ping limit)\nPress ESC\n"), NULL, MM_NOTHING);
-#endif
 		else if (msg == KICK_MSG_BANNED)
 			M_StartMessage(M_GetText("You have been banned by the server\n\nPress ESC\n"), NULL, MM_NOTHING);
 		else if (msg == KICK_MSG_CUSTOM_KICK)
@@ -4188,7 +4162,6 @@ static void HandlePacketFromPlayer(SINT8 node)
 			resynch_local_inprogress = true;
 			CL_AcknowledgeResynch(&netbuffer->u.resynchpak);
 			break;
-#ifdef NEWPING
 		case PT_PING:
 			// Only accept PT_PING from the server.
 			if (node != servernode)
@@ -4216,7 +4189,6 @@ static void HandlePacketFromPlayer(SINT8 node)
 			}
 
 			break;
-#endif
 		case PT_SERVERCFG:
 			break;
 		case PT_FILEFRAGMENT:
@@ -4730,7 +4702,6 @@ void TryRunTics(tic_t realtics)
 	}
 }
 
-#ifdef NEWPING
 static inline void PingUpdate(void)
 {
 	INT32 i;
@@ -4788,7 +4759,6 @@ static inline void PingUpdate(void)
 
 	pingmeasurecount = 1; //Reset count
 }
-#endif
 
 void NetUpdate(void)
 {
@@ -4813,7 +4783,6 @@ void NetUpdate(void)
 
 	gametime = nowtime;
 
-#ifdef NEWPING
 	if (server)
 	{
 		if (netgame && !(gametime % 255))
@@ -4824,7 +4793,6 @@ void NetUpdate(void)
 				realpingtable[i] += G_TicsToMilliseconds(GetLag(playernode[i]));
 		pingmeasurecount++;
 	}
-#endif
 
 	if (client)
 		maketic = neededtic;
diff --git a/src/d_clisrv.h b/src/d_clisrv.h
index 52ca1701d8140cfde886743a4c1f7b451775739a..1656b8e8a1deadaf3f303f11e16fdfd3daa5d0fc 100644
--- a/src/d_clisrv.h
+++ b/src/d_clisrv.h
@@ -73,9 +73,7 @@ typedef enum
 
 	PT_LOGIN,         // Login attempt from the client.
 
-#ifdef NEWPING
 	PT_PING,          // Packet sent to tell clients the other client's latency to server.
-#endif
 	NUMPACKETTYPE
 } packettype_t;
 
@@ -425,9 +423,7 @@ typedef struct
 		msaskinfo_pak msaskinfo;            //          22 bytes
 		plrinfo playerinfo[MAXPLAYERS];     //        1152 bytes (I'd say 36~38)
 		plrconfig playerconfig[MAXPLAYERS]; // (up to) 896 bytes (welp they ARE)
-#ifdef NEWPING
 		UINT32 pingtable[MAXPLAYERS];       //         128 bytes
-#endif
 	} u; // This is needed to pack diff packet types data together
 } ATTRPACK doomdata_t;
 
@@ -461,9 +457,7 @@ extern consvar_t cv_playbackspeed;
 #define KICK_MSG_PLAYER_QUIT 3
 #define KICK_MSG_TIMEOUT     4
 #define KICK_MSG_BANNED      5
-#ifdef NEWPING
 #define KICK_MSG_PING_HIGH   6
-#endif
 #define KICK_MSG_CUSTOM_KICK 7
 #define KICK_MSG_CUSTOM_BAN  8
 
@@ -488,11 +482,9 @@ extern SINT8 servernode;
 void Command_Ping_f(void);
 extern tic_t connectiontimeout;
 extern tic_t jointimeout;
-#ifdef NEWPING
 extern UINT16 pingmeasurecount;
 extern UINT32 realpingtable[MAXPLAYERS];
 extern UINT32 playerpingtable[MAXPLAYERS];
-#endif
 
 extern consvar_t cv_joinnextround, cv_allownewplayer, cv_maxplayers, cv_resynchattempts, cv_blamecfail, cv_maxsend, cv_noticedownload, cv_downloadspeed;
 
diff --git a/src/d_main.c b/src/d_main.c
index 37637edd60c708a01034385c62bd9945b6ffd356..41fa98408b869cce8fbfed3ec3852ca86a586faa 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -1244,24 +1244,40 @@ void D_SRB2Main(void)
 		sound_disabled = true;
 		midi_disabled = digital_disabled = true;
 	}
-	else
+	if (M_CheckParm("-noaudio")) // combines -nosound and -nomusic
 	{
-		CONS_Printf("S_InitSfxChannels(): Setting up sound channels.\n");
-	}
-	if (M_CheckParm("-nosound"))
 		sound_disabled = true;
-	if (M_CheckParm("-nomusic")) // combines -nomidimusic and -nodigmusic
-		midi_disabled = digital_disabled = true;
+		digital_disabled = true;
+		midi_disabled = true;
+	}
 	else
 	{
-		if (M_CheckParm("-nomidimusic"))
-			midi_disabled = true; // WARNING: DOS version initmusic in I_StartupSound
-		if (M_CheckParm("-nodigmusic"))
-			digital_disabled = true; // WARNING: DOS version initmusic in I_StartupSound
+		if (M_CheckParm("-nosound"))
+			sound_disabled = true;
+		if (M_CheckParm("-nomusic")) // combines -nomidimusic and -nodigmusic
+		{
+			digital_disabled = true;
+			midi_disabled = true;
+		}
+		else
+		{
+			if (M_CheckParm("-nomidimusic"))
+				midi_disabled = true; // WARNING: DOS version initmusic in I_StartupSound
+			if (M_CheckParm("-nodigmusic"))
+				digital_disabled = true; // WARNING: DOS version initmusic in I_StartupSound
+		}
+	}
+	if (!( sound_disabled && digital_disabled
+#ifndef NO_MIDI
+				&& midi_disabled
+#endif
+	 ))
+	{
+		CONS_Printf("S_InitSfxChannels(): Setting up sound channels.\n");
+		I_StartupSound();
+		I_InitMusic();
+		S_InitSfxChannels(cv_soundvolume.value);
 	}
-	I_StartupSound();
-	I_InitMusic();
-	S_InitSfxChannels(cv_soundvolume.value);
 
 	CONS_Printf("ST_Init(): Init status bar.\n");
 	ST_Init();
diff --git a/src/d_net.c b/src/d_net.c
index 9f68c187c472e7cf73175c0f1ed55dcaccdba31b..cbfef7726ab8e5e96077c4c09b900193eb07582c 100644
--- a/src/d_net.c
+++ b/src/d_net.c
@@ -185,22 +185,10 @@ typedef struct
 	UINT8 nextacknum;
 
 	UINT8 flags;
-#ifndef NEWPING
-	// jacobson tcp timeout evaluation algorithm (Karn variation)
-	fixed_t ping;
-	fixed_t varping;
-	INT32 timeout; // computed with ping and varping
-#endif
 } node_t;
 
 static node_t nodes[MAXNETNODES];
-#ifndef NEWPING
-#define PINGDEFAULT ((200*TICRATE*FRACUNIT)/1000)
-#define VARPINGDEFAULT ((50*TICRATE*FRACUNIT)/1000)
-#define TIMEOUT(p,v) (p+4*v+FRACUNIT/2)>>FRACBITS;
-#else
-#define NODETIMEOUT 14 //What the above boiled down to...
-#endif
+#define NODETIMEOUT 14
 
 #ifndef NONET
 // return <0 if a < b (mod 256)
@@ -320,19 +308,7 @@ static UINT8 GetAcktosend(INT32 node)
 static void RemoveAck(INT32 i)
 {
 	INT32 node = ackpak[i].destinationnode;
-#ifndef NEWPING
-	fixed_t trueping = (I_GetTime() - ackpak[i].senttime)<<FRACBITS;
-	if (ackpak[i].resentnum)
-	{
-		// +FRACUNIT/2 for round
-		nodes[node].ping = (nodes[node].ping*7 + trueping)/8;
-		nodes[node].varping = (nodes[node].varping*7 + abs(nodes[node].ping-trueping))/8;
-		nodes[node].timeout = TIMEOUT(nodes[node].ping,nodes[node].varping);
-	}
-	DEBFILE(va("Remove ack %d trueping %d ping %f var %f timeout %d\n",ackpak[i].acknum,trueping>>FRACBITS,(double)FIXED_TO_FLOAT(nodes[node].ping),(double)FIXED_TO_FLOAT(nodes[node].varping),nodes[node].timeout));
-#else
 	DEBFILE(va("Remove ack %d\n",ackpak[i].acknum));
-#endif
 	ackpak[i].acknum = 0;
 	if (nodes[node].flags & NF_CLOSE)
 		Net_CloseConnection(node);
@@ -519,11 +495,7 @@ void Net_AckTicker(void)
 	{
 		const INT32 nodei = ackpak[i].destinationnode;
 		node_t *node = &nodes[nodei];
-#ifdef NEWPING
 		if (ackpak[i].acknum && ackpak[i].senttime + NODETIMEOUT < I_GetTime())
-#else
-		if (ackpak[i].acknum && ackpak[i].senttime + node->timeout < I_GetTime())
-#endif
 		{
 			if (ackpak[i].resentnum > 10 && (node->flags & NF_CLOSE))
 			{
@@ -534,13 +506,8 @@ void Net_AckTicker(void)
 				ackpak[i].acknum = 0;
 				continue;
 			}
-#ifdef NEWPING
 			DEBFILE(va("Resend ack %d, %u<%d at %u\n", ackpak[i].acknum, ackpak[i].senttime,
 				NODETIMEOUT, I_GetTime()));
-#else
-			DEBFILE(va("Resend ack %d, %u<%d at %u\n", ackpak[i].acknum, ackpak[i].senttime,
-				node->timeout, I_GetTime()));
-#endif
 			M_Memcpy(netbuffer, ackpak[i].pak.raw, ackpak[i].length);
 			ackpak[i].senttime = I_GetTime();
 			ackpak[i].resentnum++;
@@ -658,11 +625,6 @@ void Net_WaitAllAckReceived(UINT32 timeout)
 static void InitNode(node_t *node)
 {
 	node->acktosend_head = node->acktosend_tail = 0;
-#ifndef NEWPING
-	node->ping = PINGDEFAULT;
-	node->varping = VARPINGDEFAULT;
-	node->timeout = TIMEOUT(node->ping, node->varping);
-#endif
 	node->firstacktosend = 0;
 	node->nextacknum = 1;
 	node->remotefirstack = 0;
@@ -843,9 +805,7 @@ static const char *packettypename[NUMPACKETTYPE] =
 	"CLIENTJOIN",
 	"NODETIMEOUT",
 	"RESYNCHING",
-#ifdef NEWPING
 	"PING"
-#endif
 };
 
 static void DebugPrintpacket(const char *header)
@@ -1384,30 +1344,73 @@ boolean D_CheckNetGame(void)
 	return ret;
 }
 
+struct pingcell
+{
+	INT32 num;
+	INT32 ms;
+};
+
+static int pingcellcmp(const void *va, const void *vb)
+{
+	const struct pingcell *a, *b;
+	a = va;
+	b = vb;
+	return ( a->ms - b->ms );
+}
+
+/*
+New ping command formatted nicely to present ping in
+ascending order. And with equally spaced columns.
+The caller's ping is presented at the bottom too, for
+convenience.
+*/
+
 void Command_Ping_f(void)
 {
-#ifndef NEWPING
-	if(server)
+	struct pingcell pingv[MAXPLAYERS];
+	INT32           pingc;
+
+	int name_width = 0;
+	int   ms_width = 0;
+
+	int n;
+	INT32 i;
+
+	pingc = 0;
+	for (i = 1; i < MAXPLAYERS; ++i)
+		if (playeringame[i])
 	{
-#endif
-		INT32 i;
-		for (i = 0; i < MAXPLAYERS;i++)
-		{
-#ifndef NEWPING
-			const INT32 node = playernode[i];
-			if (playeringame[i] && node != 0)
-				CONS_Printf(M_GetText("%.2d : %s\n %d tics, %d ms.\n"), i, player_names[i],
-				GetLag(node), G_TicsToMilliseconds(GetLag(node)));
-#else
-			if (playeringame[i] && i != 0)
-				CONS_Printf(M_GetText("%.2d : %s\n %d ms\n"), i, player_names[i], playerpingtable[i]);
-#endif
-		}
-#ifndef NEWPING
+		n = strlen(player_names[i]);
+		if (n > name_width)
+			name_width = n;
+
+		n = playerpingtable[i];
+		if (n > ms_width)
+			ms_width = n;
+
+		pingv[pingc].num = i;
+		pingv[pingc].ms  = playerpingtable[i];
+		pingc++;
+	}
+
+	     if (ms_width < 10)  ms_width = 1;
+	else if (ms_width < 100) ms_width = 2;
+	else                     ms_width = 3;
+
+	qsort(pingv, pingc, sizeof (struct pingcell), &pingcellcmp);
+
+	for (i = 0; i < pingc; ++i)
+	{
+		CONS_Printf("%02d : %-*s %*d ms\n",
+				pingv[i].num,
+				name_width, player_names[pingv[i].num],
+				ms_width,   pingv[i].ms);
+	}
+
+	if (!server && playeringame[consoleplayer])
+	{
+		CONS_Printf("\nYour ping is %d ms\n", playerpingtable[consoleplayer]);
 	}
-	else
-		CONS_Printf(M_GetText("Only the server can use this.\n"));
-#endif
 }
 
 void D_CloseConnection(void)
diff --git a/src/d_netcmd.c b/src/d_netcmd.c
index 33e350286d835078ac85d40cadccddc2cc92c29c..20b1ef19b34268deff361dac9c95d04f33f139ea 100644
--- a/src/d_netcmd.c
+++ b/src/d_netcmd.c
@@ -342,9 +342,7 @@ static CV_PossibleValue_t nettimeout_cons_t[] = {{TICRATE/7, "MIN"}, {60*TICRATE
 consvar_t cv_nettimeout = {"nettimeout", "350", CV_CALL|CV_SAVE, nettimeout_cons_t, NetTimeout_OnChange, 0, NULL, NULL, 0, 0, NULL};
 static CV_PossibleValue_t jointimeout_cons_t[] = {{5*TICRATE, "MIN"}, {60*TICRATE, "MAX"}, {0, NULL}};
 consvar_t cv_jointimeout = {"jointimeout", "350", CV_CALL|CV_SAVE, jointimeout_cons_t, JoinTimeout_OnChange, 0, NULL, NULL, 0, 0, NULL};
-#ifdef NEWPING
 consvar_t cv_maxping = {"maxping", "0", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL};
-#endif
 // Intermission time Tails 04-19-2002
 static CV_PossibleValue_t inttime_cons_t[] = {{0, "MIN"}, {3600, "MAX"}, {0, NULL}};
 consvar_t cv_inttime = {"inttime", "10", CV_NETVAR, inttime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@@ -575,9 +573,7 @@ void D_RegisterServerCommands(void)
 
 	CV_RegisterVar(&cv_skipmapcheck);
 	CV_RegisterVar(&cv_sleep);
-#ifdef NEWPING
 	CV_RegisterVar(&cv_maxping);
-#endif
 
 #ifdef SEENAMES
 	 CV_RegisterVar(&cv_allowseenames);
@@ -742,6 +738,8 @@ void D_RegisterClientCommands(void)
 	CV_RegisterVar(&cv_chasefreelook);
 	CV_RegisterVar(&cv_chasefreelook2);
 	CV_RegisterVar(&cv_tutorialprompt);
+	CV_RegisterVar(&cv_showfocuslost);
+	CV_RegisterVar(&cv_pauseifunfocused);
 
 	// g_input.c
 	CV_RegisterVar(&cv_sideaxis);
diff --git a/src/d_netcmd.h b/src/d_netcmd.h
index 3e3c61112b5337df1a3f4450045cc79f2e9b473e..b5ca9d374b89454290115876dcb4dfc875d99e1f 100644
--- a/src/d_netcmd.h
+++ b/src/d_netcmd.h
@@ -107,9 +107,7 @@ extern consvar_t cv_ringslinger, cv_soundtest;
 
 extern consvar_t cv_specialrings, cv_powerstones, cv_matchboxes, cv_competitionboxes;
 
-#ifdef NEWPING
 extern consvar_t cv_maxping;
-#endif
 
 extern consvar_t cv_skipmapcheck;
 
diff --git a/src/doomdef.h b/src/doomdef.h
index 8d44d0896758316e60eb93afe845fe249d505477..676c86e0d68b8c844c6edf042804f3a68589b048 100644
--- a/src/doomdef.h
+++ b/src/doomdef.h
@@ -509,13 +509,17 @@ INT32 I_GetKey(void);
 // Max gamepad/joysticks that can be detected/used.
 #define MAX_JOYSTICKS 4
 
+#ifndef M_PIl
+#define M_PIl 3.1415926535897932384626433832795029L
+#endif
+
 // Floating point comparison epsilons from float.h
 #ifndef FLT_EPSILON
 #define FLT_EPSILON 1.1920928955078125e-7f
 #endif
 
 #ifndef DBL_EPSILON
-#define DBL_EPSILON 2.2204460492503131e-16
+#define DBL_EPSILON 2.2204460492503131e-16l
 #endif
 
 // An assert-type mechanism.
@@ -561,9 +565,6 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
 ///	Polyobject fake flat code
 #define POLYOBJECTS_PLANES
 
-///	Improved way of dealing with ping values and a ping limit.
-#define NEWPING
-
 ///	See name of player in your crosshair
 #define SEENAMES
 
diff --git a/src/g_game.c b/src/g_game.c
index 6c31ce9e32b9716494ea7915da4ff55e755bd8e7..246fb965abc5a53e9720c586549f615285054d37 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -361,6 +361,8 @@ consvar_t cv_chatbacktint = {"chatbacktint", "On", CV_SAVE, CV_OnOff, NULL, 0, N
 static CV_PossibleValue_t consolechat_cons_t[] = {{0, "Window"}, {1, "Console"}, {2, "Window (Hidden)"}, {0, NULL}};
 consvar_t cv_consolechat = {"chatmode", "Window", CV_SAVE, consolechat_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 
+// Pause game upon window losing focus
+consvar_t cv_pauseifunfocused = {"pauseifunfocused", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
 
 consvar_t cv_crosshair = {"crosshair", "Cross", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_crosshair2 = {"crosshair2", "Cross", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@@ -1713,65 +1715,6 @@ static INT32 camtoggledelay, camtoggledelay2 = 0;
 //
 boolean G_Responder(event_t *ev)
 {
-	// allow spy mode changes even during the demo
-	if (gamestate == GS_LEVEL && ev->type == ev_keydown
-		&& (ev->data1 == KEY_F12 || ev->data1 == gamecontrol[gc_viewpoint][0] || ev->data1 == gamecontrol[gc_viewpoint][1]))
-	{
-		if (splitscreen || !netgame)
-			displayplayer = consoleplayer;
-		else
-		{
-			// spy mode
-			do
-			{
-				displayplayer++;
-				if (displayplayer == MAXPLAYERS)
-					displayplayer = 0;
-
-				if (!playeringame[displayplayer])
-					continue;
-
-				if (players[displayplayer].spectator)
-					continue;
-
-				if (G_GametypeHasTeams())
-				{
-					if (players[consoleplayer].ctfteam
-					 && players[displayplayer].ctfteam != players[consoleplayer].ctfteam)
-						continue;
-				}
-				else if (gametype == GT_HIDEANDSEEK)
-				{
-					if (players[consoleplayer].pflags & PF_TAGIT)
-						continue;
-				}
-				// Other Tag-based gametypes?
-				else if (G_TagGametype())
-				{
-					if (!players[consoleplayer].spectator
-					 && (players[consoleplayer].pflags & PF_TAGIT) != (players[displayplayer].pflags & PF_TAGIT))
-						continue;
-				}
-				else if (G_GametypeHasSpectators() && G_RingSlingerGametype())
-				{
-					if (!players[consoleplayer].spectator)
-						continue;
-				}
-
-				break;
-			} while (displayplayer != consoleplayer);
-
-			// change statusbar also if playing back demo
-			if (singledemo)
-				ST_changeDemoView();
-
-			// tell who's the view
-			CONS_Printf(M_GetText("Viewpoint: %s\n"), player_names[displayplayer]);
-
-			return true;
-		}
-	}
-
 	// any other key pops up menu if in demos
 	if (gameaction == ga_nothing && !singledemo &&
 		((demoplayback && !modeattacking && !titledemo) || gamestate == GS_TITLESCREEN))
@@ -1848,6 +1791,65 @@ boolean G_Responder(event_t *ev)
 		if (HU_Responder(ev))
 			return true; // chat ate the event
 
+	// allow spy mode changes even during the demo
+	if (gamestate == GS_LEVEL && ev->type == ev_keydown
+		&& (ev->data1 == KEY_F12 || ev->data1 == gamecontrol[gc_viewpoint][0] || ev->data1 == gamecontrol[gc_viewpoint][1]))
+	{
+		if (splitscreen || !netgame)
+			displayplayer = consoleplayer;
+		else
+		{
+			// spy mode
+			do
+			{
+				displayplayer++;
+				if (displayplayer == MAXPLAYERS)
+					displayplayer = 0;
+
+				if (!playeringame[displayplayer])
+					continue;
+
+				if (players[displayplayer].spectator)
+					continue;
+
+				if (G_GametypeHasTeams())
+				{
+					if (players[consoleplayer].ctfteam
+					 && players[displayplayer].ctfteam != players[consoleplayer].ctfteam)
+						continue;
+				}
+				else if (gametype == GT_HIDEANDSEEK)
+				{
+					if (players[consoleplayer].pflags & PF_TAGIT)
+						continue;
+				}
+				// Other Tag-based gametypes?
+				else if (G_TagGametype())
+				{
+					if (!players[consoleplayer].spectator
+					 && (players[consoleplayer].pflags & PF_TAGIT) != (players[displayplayer].pflags & PF_TAGIT))
+						continue;
+				}
+				else if (G_GametypeHasSpectators() && G_RingSlingerGametype())
+				{
+					if (!players[consoleplayer].spectator)
+						continue;
+				}
+
+				break;
+			} while (displayplayer != consoleplayer);
+
+			// change statusbar also if playing back demo
+			if (singledemo)
+				ST_changeDemoView();
+
+			// tell who's the view
+			CONS_Printf(M_GetText("Viewpoint: %s\n"), player_names[displayplayer]);
+
+			return true;
+		}
+	}
+
 	// update keys current state
 	G_MapEventsToControls(ev);
 
diff --git a/src/g_game.h b/src/g_game.h
index df1301dd7c392071a14fa66870c9f8fc7f099883..198cbc396ccb5d76b1596d3ef7d45b89ee755d98 100644
--- a/src/g_game.h
+++ b/src/g_game.h
@@ -59,6 +59,8 @@ extern boolean pausebreakkey;
 
 extern boolean promptactive;
 
+extern consvar_t cv_pauseifunfocused;
+
 // used in game menu
 extern consvar_t cv_tutorialprompt;
 extern consvar_t cv_chatwidth, cv_chatnotifications, cv_chatheight, cv_chattime, cv_consolechat, cv_chatbacktint, cv_chatspamprotection, cv_compactscoreboard;
diff --git a/src/hardware/hw_bsp.c b/src/hardware/hw_bsp.c
index 48393249214ff7dc7dd13051d88f5b50c2478a44..9e454bcd5275dd28150e33f053fc5ee20c79ddb0 100644
--- a/src/hardware/hw_bsp.c
+++ b/src/hardware/hw_bsp.c
@@ -201,7 +201,7 @@ static polyvertex_t *fracdivline(fdivline_t *bsp, polyvertex_t *v1,
 	// (do not accept hit with the extensions)
 	num = (v2x - v1x)*v2dy + (v1y - v2y)*v2dx;
 	frac = num / den;
-	if (frac < 0.0 || frac > 1.0)
+	if (frac < 0.0l || frac > 1.0l)
 		return NULL;
 
 	// now get the frac along the BSP line
diff --git a/src/hardware/hw_dll.h b/src/hardware/hw_dll.h
index 452e9037c2dab8f14bf1798113a22b87f3f95049..3fa5852d88d844060f6a3601e148d1a540461493 100644
--- a/src/hardware/hw_dll.h
+++ b/src/hardware/hw_dll.h
@@ -61,9 +61,6 @@ typedef void (*I_Error_t) (const char *error, ...) FUNCIERROR;
 // ==========================================================================
 
 // Constants
-#ifndef M_PIl
-#define M_PIl 3.1415926535897932384626433832795029L
-#endif
 #define DEGREE (0.017453292519943295769236907684883l) // 2*PI/360
 
 void DBG_Printf(const char *lpFmt, ...) /*FUNCPRINTF*/;
diff --git a/src/m_menu.c b/src/m_menu.c
index 43bd133e2cdc060e1f3e6091650528c8f533180f..2bd0c3e44f1b05e3080da7e58292591719ba46d0 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -387,6 +387,8 @@ static void Dummymares_OnChange(void);
 // CONSOLE VARIABLES AND THEIR POSSIBLE VALUES GO HERE.
 // ==========================================================================
 
+consvar_t cv_showfocuslost = {"showfocuslost", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL };
+
 static CV_PossibleValue_t map_cons_t[] = {
 	{1,"MIN"},
 	{NUMMAPS, "MAX"}
@@ -407,7 +409,7 @@ static CV_PossibleValue_t serversort_cons_t[] = {
 	{1,"Modified State"},
 	{2,"Most Players"},
 	{3,"Least Players"},
-	{4,"Max Players"},
+	{4,"Max Player Slots"},
 	{5,"Gametype"},
 	{0,NULL}
 };
@@ -1231,6 +1233,7 @@ static menuitem_t OP_VideoOptionsMenu[] =
 	{IT_HEADER, NULL, "Diagnostic", NULL, 180},
 	{IT_STRING | IT_CVAR, NULL, "Show FPS",                  &cv_ticrate,         186},
 	{IT_STRING | IT_CVAR, NULL, "Clear Before Redraw",       &cv_homremoval,      191},
+	{IT_STRING | IT_CVAR, NULL, "Show \"FOCUS LOST\"",       &cv_showfocuslost,   196},
 };
 
 static menuitem_t OP_VideoModeMenu[] =
@@ -3316,7 +3319,7 @@ void M_Drawer(void)
 	}
 
 	// focus lost notification goes on top of everything, even the former everything
-	if (window_notinfocus)
+	if (window_notinfocus && cv_showfocuslost.value)
 	{
 		M_DrawTextBox((BASEVIDWIDTH/2) - (60), (BASEVIDHEIGHT/2) - (16), 13, 2);
 		if (gamestate == GS_LEVEL && (P_AutoPause() || paused))
diff --git a/src/m_menu.h b/src/m_menu.h
index 05962d2b19072eda900642223db6f042f7790c8e..d568a1b5369ebd30aef5be51605c119d14c2881e 100644
--- a/src/m_menu.h
+++ b/src/m_menu.h
@@ -374,6 +374,7 @@ typedef struct
 
 extern description_t description[MAXSKINS];
 
+extern consvar_t cv_showfocuslost;
 extern consvar_t cv_newgametype, cv_nextmap, cv_chooseskin, cv_serversort;
 extern CV_PossibleValue_t gametype_cons_t[];
 
diff --git a/src/p_user.c b/src/p_user.c
index 62f797c464affc3384e4584e521b47005b1a6df4..64f67570f10705d5ce8653ee3ca1bcefe6f02321 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -191,7 +191,7 @@ boolean P_AutoPause(void)
 	if (netgame || modeattacking || gamestate == GS_TITLESCREEN)
 		return false;
 
-	return (menuactive || window_notinfocus);
+	return (menuactive || ( window_notinfocus && cv_pauseifunfocused.value ));
 }
 
 //
diff --git a/src/r_plane.c b/src/r_plane.c
index 481af3913a00defaca0af602350b009a27718ef8..9f417ee6bff85de8aa409b6d6db677d33b2bff2f 100644
--- a/src/r_plane.c
+++ b/src/r_plane.c
@@ -1113,7 +1113,7 @@ void R_DrawSinglePlane(visplane_t *pl)
 		temp = P_GetZAt(pl->slope, pl->viewx, pl->viewy);
 		zeroheight = FIXED_TO_FLOAT(temp);
 
-#define ANG2RAD(angle) ((float)((angle)*M_PI)/ANGLE_180)
+#define ANG2RAD(angle) ((float)((angle)*M_PIl)/ANGLE_180)
 
 		// p is the texture origin in view space
 		// Don't add in the offsets at this stage, because doing so can result in
diff --git a/src/s_sound.c b/src/s_sound.c
index 299e4b88976935c271852f024d412bc70a6e635a..1a719d97259cd1382c3fea1d669a309c9b843dea 100644
--- a/src/s_sound.c
+++ b/src/s_sound.c
@@ -2202,7 +2202,7 @@ static void Command_RestartAudio_f(void)
 
 void GameSounds_OnChange(void)
 {
-	if (M_CheckParm("-nosound"))
+	if (M_CheckParm("-nosound") || M_CheckParm("-noaudio"))
 		return;
 
 	if (sound_disabled)
@@ -2220,7 +2220,7 @@ void GameSounds_OnChange(void)
 
 void GameDigiMusic_OnChange(void)
 {
-	if (M_CheckParm("-nomusic"))
+	if (M_CheckParm("-nomusic") || M_CheckParm("-noaudio"))
 		return;
 	else if (M_CheckParm("-nodigmusic"))
 		return;
@@ -2262,7 +2262,7 @@ void GameDigiMusic_OnChange(void)
 
 void GameMIDIMusic_OnChange(void)
 {
-	if (M_CheckParm("-nomusic"))
+	if (M_CheckParm("-nomusic") || M_CheckParm("-noaudio"))
 		return;
 	else if (M_CheckParm("-nomidimusic"))
 		return;
diff --git a/src/screen.c b/src/screen.c
index 547036a60bf7b7624d0f4f58622df2f2d44feadf..9939aff93388dcdb816404be9b4795963fc41960 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -421,9 +421,9 @@ void SCR_DisplayTicRate(void)
 	else if (totaltics == TICRATE) ticcntcolor = V_GREENMAP;
 
 	V_DrawString(vid.width-(72*vid.dupx), h,
-		V_YELLOWMAP|V_NOSCALESTART, "FPS:");
+		V_YELLOWMAP|V_NOSCALESTART|V_HUDTRANS, "FPS:");
 	V_DrawString(vid.width-(40*vid.dupx), h,
-		ticcntcolor|V_NOSCALESTART, va("%02d/%02u", totaltics, TICRATE));
+		ticcntcolor|V_NOSCALESTART|V_HUDTRANS, va("%02d/%02u", totaltics, TICRATE));
 
 	lasttic = ontic;
 }
diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c
index f5c7e3714d17fc72ae36622c0c81c21f33d898f8..be6017aa924a518468b764b7bf043399c53d06a0 100644
--- a/src/sdl/i_video.c
+++ b/src/sdl/i_video.c
@@ -357,6 +357,14 @@ static INT32 Impl_SDL_Scancode_To_Keycode(SDL_Scancode code)
 	return 0;
 }
 
+static void SDLdoGrabMouse(void)
+{
+	SDL_ShowCursor(SDL_DISABLE);
+	SDL_SetWindowGrab(window, SDL_TRUE);
+	if (SDL_SetRelativeMouseMode(SDL_TRUE) == 0) // already warps mouse if successful
+		wrapmouseok = SDL_TRUE; // TODO: is wrapmouseok or HalfWarpMouse needed anymore?
+}
+
 static void SDLdoUngrabMouse(void)
 {
 	SDL_ShowCursor(SDL_ENABLE);
@@ -579,6 +587,9 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt)
 			if (cv_usemouse.value) I_StartupMouse();
 		}
 		//else firsttimeonmouse = SDL_FALSE;
+
+		if (USE_MOUSEINPUT)
+			SDLdoGrabMouse();
 	}
 	else if (!mousefocus && !kbfocus)
 	{
@@ -655,9 +666,7 @@ static void Impl_HandleMouseMotionEvent(SDL_MouseMotionEvent evt)
 		// -- Monster Iestyn
 		if (SDL_GetMouseFocus() == window && SDL_GetKeyboardFocus() == window)
 		{
-			SDL_SetWindowGrab(window, SDL_TRUE);
-			if (SDL_SetRelativeMouseMode(SDL_TRUE) == 0) // already warps mouse if successful
-				wrapmouseok = SDL_TRUE; // TODO: is wrapmouseok or HalfWarpMouse needed anymore?
+			SDLdoGrabMouse();
 		}
 	}
 }
@@ -1056,7 +1065,7 @@ void I_StartupMouse(void)
 	else
 		firsttimeonmouse = SDL_FALSE;
 	if (cv_usemouse.value)
-		return;
+		SDLdoGrabMouse();
 	else
 		SDLdoUngrabMouse();
 }
@@ -1164,8 +1173,11 @@ void I_FinishUpdate(void)
 	if (cv_closedcaptioning.value)
 		SCR_ClosedCaptions();
 
-	if (cv_ticrate.value)
-		SCR_DisplayTicRate();
+	if (st_overlay)
+	{
+		if (cv_ticrate.value)
+			SCR_DisplayTicRate();
+	}
 
 	if (rendermode == render_soft && screens[0])
 	{