diff --git a/.gitignore b/.gitignore
index 7b2304ec087ee359208e867bc6f944252ecc7b9b..922fac4aaf187f58ab2145c69641397c4ff81dc5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,3 +18,4 @@ Win32_LIB_ASM_Release
 *.user
 *.db
 *.opendb
+/.vs
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f9364fdd2c1b20ea8c3fa2afa744cbe8360a62de..eb91866f003bd53629bdfbfcfcda362873d54ea2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 3.0)
 project(SRB2
-	VERSION 2.1.19
+	VERSION 2.1.20
 	LANGUAGES C)
 
 if(${PROJECT_SOURCE_DIR} MATCHES ${PROJECT_BINARY_DIR})
diff --git a/SRB2_Debug.props b/SRB2_Debug.props
index 2c16f7cb60253e4834ccd2c11681dfa4d727b975..8be11c58a9376343e7d679ad454806dd0ff5b0b9 100644
--- a/SRB2_Debug.props
+++ b/SRB2_Debug.props
@@ -17,7 +17,7 @@
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <AssemblerOutput>All</AssemblerOutput>
-      <SmallerTypeCheck>true</SmallerTypeCheck>
+      <SmallerTypeCheck>false</SmallerTypeCheck>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
     </ClCompile>
     <Link>
diff --git a/appveyor.yml b/appveyor.yml
index ae3f82f58c84ea343e2bd4e32a4797daf4d06c88..69913cfc87f8e4097fa397e1f2a8a1f87146454c 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,4 +1,4 @@
-version: 2.1.19.{branch}-{build}
+version: 2.1.20.{branch}-{build}
 os: MinGW
 
 environment:
diff --git a/src/d_clisrv.c b/src/d_clisrv.c
index 33f826432db689ec2e04dce04c54a5a44fbd42c0..72f60aa9f68c6ec57e9bc9605dfcb8e25500f454 100644
--- a/src/d_clisrv.c
+++ b/src/d_clisrv.c
@@ -103,7 +103,7 @@ static INT16 consistancy[BACKUPTICS];
 static UINT32 resynch_score[MAXNETNODES]; // "score" for kicking -- if this gets too high then cfail kick
 static UINT16 resynch_delay[MAXNETNODES]; // delay time before the player can be considered to have desynched
 static UINT32 resynch_status[MAXNETNODES]; // 0 bit means synched for that player, 1 means possibly desynched
-static UINT8 resynch_sent[MAXNETNODES][MAXNETNODES]; // what synch packets have we attempted to send to the player
+static UINT8 resynch_sent[MAXNETNODES][MAXPLAYERS]; // what synch packets have we attempted to send to the player
 static UINT8 resynch_inprogress[MAXNETNODES];
 static UINT8 resynch_local_inprogress = false; // WE are desynched and getting packets to fix it.
 static UINT8 player_joining = false;
@@ -944,7 +944,7 @@ static void SV_InitResynchVars(INT32 node)
 	resynch_score[node] = 0; // clean slate
 	resynch_status[node] = 0x00;
 	resynch_inprogress[node] = false;
-	memset(resynch_sent[node], 0, MAXNETNODES);
+	memset(resynch_sent[node], 0, MAXPLAYERS);
 }
 
 static void SV_RequireResynch(INT32 node)
@@ -953,16 +953,16 @@ static void SV_RequireResynch(INT32 node)
 
 	resynch_delay[node] = 10; // Delay before you can fail sync again
 	resynch_score[node] += 200; // Add score for initial desynch
-	resynch_status[node] = 0xFF; // No players assumed synched
+	resynch_status[node] = 0xFFFFFFFF; // No players assumed synched
 	resynch_inprogress[node] = true; // so we know to send a PT_RESYNCHEND after sync
 
 	// Initial setup
-	memset(resynch_sent[node], 0, MAXNETNODES);
+	memset(resynch_sent[node], 0, MAXPLAYERS);
 	for (i = 0; i < MAXPLAYERS; ++i)
 	{
 		if (!playeringame[i]) // Player not in game so just drop it from required synch
 			resynch_status[node] &= ~(1<<i);
-		else if (i == node); // instantly update THEIR position
+		else if (playernode[i] == node); // instantly update THEIR position
 		else // Send at random times based on num players
 			resynch_sent[node][i] = M_RandomKey(D_NumPlayers()>>1)+1;
 	}
@@ -3155,16 +3155,68 @@ static boolean SV_AddWaitingPlayers(void)
 		{
 			newplayer = true;
 
-			// search for a free playernum
-			// we can't use playeringame since it is not updated here
-			for (; newplayernum < MAXPLAYERS; newplayernum++)
-			{
-				for (n = 0; n < MAXNETNODES; n++)
-					if (nodetoplayer[n] == newplayernum || nodetoplayer2[n] == newplayernum)
+			if (netgame)
+				// !!!!!!!!! EXTREMELY SUPER MEGA GIGA ULTRA ULTIMATELY TERRIBLY IMPORTANT !!!!!!!!!
+				//
+				// The line just after that comment is an awful, horrible, terrible, TERRIBLE hack.
+				//
+				// Basically, the fix I did in order to fix the download freezes happens
+				// to cause situations in which a player number does not match
+				// the node number associated to that player.
+				// That is totally normal, there is absolutely *nothing* wrong with that.
+				// Really. Player 7 being tied to node 29, for instance, is totally fine.
+				//
+				// HOWEVER. A few (broken) parts of the netcode do the TERRIBLE mistake
+				// of mixing up the concepts of node and player, resulting in
+				// incorrect handling of cases where a player is tied to a node that has
+				// a different number (which is a totally normal case, or at least should be).
+				// This incorrect handling can go as far as literally
+				// anyone from joining your server at all, forever.
+				//
+				// Given those two facts, there are two options available
+				// in order to let this download freeze fix be:
+				//  1) Fix the broken parts that assume a node is a player or similar bullshit.
+				//  2) Change the part this comment is located at, so that any player who joins
+				//     is given the same number as their associated node.
+				//
+				// No need to say, 1) is by far the obvious best, whereas 2) is a terrible hack.
+				// Unfortunately, after trying 1), I most likely didn't manage to find all
+				// of those broken parts, and thus 2) has become the only safe option that remains.
+				//
+				// So I did this hack.
+				//
+				// If it isn't clear enough, in order to get rid of this ugly hack,
+				// you will have to fix all parts of the netcode that
+				// make a confusion between nodes and players.
+				//
+				// And if it STILL isn't clear enough, a node and a player
+				// is NOT the same thing. Never. NEVER. *NEVER*.
+				//
+				// And if someday you make the terrible mistake of
+				// daring to have the unforgivable idea to try thinking
+				// that a node might possibly be the same as a player,
+				// or that a player should have the same number as its node,
+				// be sure that I will somehow know about it and
+				// hunt you down tirelessly and make you regret it,
+				// even if you live on the other side of the world.
+				//
+				// TODO:            vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
+				// \todo >>>>>>>>>> Remove this horrible hack as soon as possible <<<<<<<<<<
+				// TODO:            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+				//
+				// !!!!!!!!! EXTREMELY SUPER MEGA GIGA ULTRA ULTIMATELY TERRIBLY IMPORTANT !!!!!!!!!
+				newplayernum = node; // OMFG SAY WELCOME TO TEH NEW HACK FOR FIX FIL DOWNLOAD!!1!
+			else // Don't use the hack if we don't have to
+				// search for a free playernum
+				// we can't use playeringame since it is not updated here
+				for (; newplayernum < MAXPLAYERS; newplayernum++)
+				{
+					for (n = 0; n < MAXNETNODES; n++)
+						if (nodetoplayer[n] == newplayernum || nodetoplayer2[n] == newplayernum)
+							break;
+					if (n == MAXNETNODES)
 						break;
-				if (n == MAXNETNODES)
-					break;
-			}
+				}
 
 			// should never happen since we check the playernum
 			// before accepting the join
diff --git a/src/d_netcmd.c b/src/d_netcmd.c
index 3bb83716cc513c70b179a933e9ed5c7d0a38c0f6..b1e3bc9d2540e032a11dfe0a0aa384719bec3ebc 100644
--- a/src/d_netcmd.c
+++ b/src/d_netcmd.c
@@ -26,6 +26,7 @@
 #include "p_local.h"
 #include "p_setup.h"
 #include "s_sound.h"
+#include "i_sound.h"
 #include "m_misc.h"
 #include "am_map.h"
 #include "byteptr.h"
@@ -126,6 +127,7 @@ static void Command_Playintro_f(void);
 
 static void Command_Displayplayer_f(void);
 static void Command_Tunes_f(void);
+static void Command_RestartAudio_f(void);
 
 static void Command_ExitLevel_f(void);
 static void Command_Showmap_f(void);
@@ -683,6 +685,7 @@ void D_RegisterClientCommands(void)
 
 	COM_AddCommand("displayplayer", Command_Displayplayer_f);
 	COM_AddCommand("tunes", Command_Tunes_f);
+	COM_AddCommand("restartaudio", Command_RestartAudio_f);
 	CV_RegisterVar(&cv_resetmusic);
 
 	// FIXME: not to be here.. but needs be done for config loading
@@ -3072,8 +3075,31 @@ static void Command_Addfile(void)
 		if (*p == '\\' || *p == '/' || *p == ':')
 			break;
 	++p;
+	// check total packet size and no of files currently loaded
+	{
+		size_t packetsize = 0;
+		serverinfo_pak *dummycheck = NULL;
+
+		// Shut the compiler up.
+		(void)dummycheck;
+
+		// See W_LoadWadFile in w_wad.c
+		for (i = 0; i < numwadfiles; i++)
+			packetsize += nameonlylength(wadfiles[i]->filename) + 22;
+
+		packetsize += nameonlylength(fn) + 22;
+
+		if ((numwadfiles >= MAX_WADFILES)
+		|| (packetsize > sizeof(dummycheck->fileneeded)))
+		{
+			CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn);
+			return;
+		}
+	}
+
 	WRITESTRINGN(buf_p,p,240);
 
+	// calculate and check md5
 	{
 		UINT8 md5sum[16];
 #ifdef NOMD5
@@ -3091,6 +3117,15 @@ static void Command_Addfile(void)
 		}
 		else // file not found
 			return;
+
+		for (i = 0; i < numwadfiles; i++)
+		{
+			if (!memcmp(wadfiles[i]->md5sum, md5sum, 16))
+			{
+				CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), fn);
+				return;
+			}
+		}
 #endif
 		WRITEMEM(buf_p, md5sum, 16);
 	}
@@ -4015,6 +4050,27 @@ static void Command_Tunes_f(void)
 	}
 }
 
+static void Command_RestartAudio_f(void)
+{
+	if (dedicated)  // No point in doing anything if game is a dedicated server.
+		return;
+
+	S_StopMusic();
+	I_ShutdownMusic();
+	I_ShutdownSound();
+	I_StartupSound();
+	I_InitMusic();
+	
+// These must be called or no sound and music until manually set.
+
+	I_SetSfxVolume(cv_soundvolume.value);
+	I_SetDigMusicVolume(cv_digmusicvolume.value);
+	I_SetMIDIMusicVolume(cv_midimusicvolume.value);
+	if (Playing()) // Gotta make sure the player is in a level
+		P_RestoreMusic(&players[consoleplayer]);
+	
+}
+
 /** Quits a game and returns to the title screen.
   *
   */
diff --git a/src/doomdef.h b/src/doomdef.h
index ee21cf308f9e253511395d974611d773bf4cc83b..32771163e2fc1e7c336e6ee48e45bf0e7f802152 100644
--- a/src/doomdef.h
+++ b/src/doomdef.h
@@ -194,7 +194,7 @@ extern FILE *logstream;
 // Will always resemble the versionstring, 205 = 2.0.5, 210 = 2.1, etc.
 #define CODEBASE 220
 
-// The Modification ID; must be obtained from Inuyasha ( http://mb.srb2.org/private.php?do=newpm&u=2604 ).
+// The Modification ID; must be obtained from Rob ( https://mb.srb2.org/private.php?do=newpm&u=546 ).
 // DO NOT try to set this otherwise, or your modification will be unplayable through the Master Server.
 // "12" is the default mod ID for version 2.1
 #define MODID 12
@@ -203,7 +203,7 @@ extern FILE *logstream;
 // it's only for detection of the version the player is using so the MS can alert them of an update.
 // Only set it higher, not lower, obviously.
 // Note that we use this to help keep internal testing in check; this is why v2.1.0 is not version "1".
-#define MODVERSION 24
+#define MODVERSION 25
 
 // =========================================================================
 
diff --git a/src/hardware/r_opengl/r_opengl-vc10.vcxproj b/src/hardware/r_opengl/r_opengl-vc10.vcxproj
index 43da2a3ee34c8e5af52597c2915dd44c08e1a599..f04ae320b36e43cf15f0bf89cf53834b6ef8efcb 100644
--- a/src/hardware/r_opengl/r_opengl-vc10.vcxproj
+++ b/src/hardware/r_opengl/r_opengl-vc10.vcxproj
@@ -122,6 +122,7 @@
       </DataExecutionPrevention>
       <ImportLibrary>$(IntDir)r_opengl.lib</ImportLibrary>
       <TargetMachine>MachineX86</TargetMachine>
+      <SubSystem>Windows</SubSystem>
     </Link>
     <Bscmake>
       <SuppressStartupBanner>true</SuppressStartupBanner>
@@ -166,6 +167,7 @@
       </DataExecutionPrevention>
       <ImportLibrary>$(IntDir)r_opengl.lib</ImportLibrary>
       <TargetMachine>MachineX64</TargetMachine>
+      <SubSystem>Windows</SubSystem>
     </Link>
     <Bscmake>
       <SuppressStartupBanner>true</SuppressStartupBanner>
@@ -212,6 +214,7 @@
       </DataExecutionPrevention>
       <ImportLibrary>$(IntDir)r_opengl.lib</ImportLibrary>
       <TargetMachine>MachineX86</TargetMachine>
+      <SubSystem>Windows</SubSystem>
     </Link>
     <Bscmake>
       <SuppressStartupBanner>true</SuppressStartupBanner>
@@ -258,6 +261,7 @@
       </DataExecutionPrevention>
       <ImportLibrary>$(IntDir)r_opengl.lib</ImportLibrary>
       <TargetMachine>MachineX64</TargetMachine>
+      <SubSystem>Windows</SubSystem>
     </Link>
     <Bscmake>
       <SuppressStartupBanner>true</SuppressStartupBanner>
diff --git a/src/hardware/s_openal/s_openal-vc10.vcxproj b/src/hardware/s_openal/s_openal-vc10.vcxproj
index 67d2d95ac1f4f77847e4114cc319ef511d0fe42a..8b4f6cbbe43a77fff7e49cee6e83a8470da8f04d 100644
--- a/src/hardware/s_openal/s_openal-vc10.vcxproj
+++ b/src/hardware/s_openal/s_openal-vc10.vcxproj
@@ -125,6 +125,7 @@
       </DataExecutionPrevention>
       <ImportLibrary>$(IntDir)s_openal.lib</ImportLibrary>
       <TargetMachine>MachineX86</TargetMachine>
+      <SubSystem>Windows</SubSystem>
     </Link>
     <Bscmake>
       <SuppressStartupBanner>true</SuppressStartupBanner>
@@ -170,6 +171,7 @@
       </DataExecutionPrevention>
       <ImportLibrary>$(IntDir)s_openal.lib</ImportLibrary>
       <TargetMachine>MachineX64</TargetMachine>
+      <SubSystem>Windows</SubSystem>
     </Link>
     <Bscmake>
       <SuppressStartupBanner>true</SuppressStartupBanner>
@@ -216,6 +218,7 @@
       </DataExecutionPrevention>
       <ImportLibrary>$(IntDir)s_openal.lib</ImportLibrary>
       <TargetMachine>MachineX86</TargetMachine>
+      <SubSystem>Windows</SubSystem>
     </Link>
     <Bscmake>
       <SuppressStartupBanner>true</SuppressStartupBanner>
@@ -262,6 +265,7 @@
       </DataExecutionPrevention>
       <ImportLibrary>$(IntDir)s_openal.lib</ImportLibrary>
       <TargetMachine>MachineX64</TargetMachine>
+      <SubSystem>Windows</SubSystem>
     </Link>
     <Bscmake>
       <SuppressStartupBanner>true</SuppressStartupBanner>
diff --git a/src/i_tcp.c b/src/i_tcp.c
index b6c72f8593d92b89fd99485c1ac344084bcf7f7b..9bb4ec630320fb7129bf39f9ad7dd71ce4fc9200 100644
--- a/src/i_tcp.c
+++ b/src/i_tcp.c
@@ -178,7 +178,6 @@ static UINT8 UPNP_support = TRUE;
 
 #if defined (USE_WINSOCK) && !defined (NONET)
 typedef SOCKET SOCKET_TYPE;
-#define BADSOCKET INVALID_SOCKET
 #define ERRSOCKET (SOCKET_ERROR)
 #else
 #if (defined (__unix__) && !defined (MSDOS)) || defined (__APPLE__) || defined (__HAIKU__)
@@ -186,7 +185,6 @@ typedef int SOCKET_TYPE;
 #else
 typedef unsigned long SOCKET_TYPE;
 #endif
-#define BADSOCKET (SOCKET_TYPE)(~0)
 #define ERRSOCKET (-1)
 #endif
 
@@ -195,10 +193,10 @@ typedef int socklen_t;
 #endif
 
 #ifndef NONET
-static SOCKET_TYPE mysockets[MAXNETNODES+1] = {BADSOCKET};
+static SOCKET_TYPE mysockets[MAXNETNODES+1] = {ERRSOCKET};
 static size_t mysocketses = 0;
 static int myfamily[MAXNETNODES+1] = {0};
-static SOCKET_TYPE nodesocket[MAXNETNODES+1] = {BADSOCKET};
+static SOCKET_TYPE nodesocket[MAXNETNODES+1] = {ERRSOCKET};
 static mysockaddr_t clientaddress[MAXNETNODES+1];
 static mysockaddr_t broadcastaddress[MAXNETNODES+1];
 static size_t broadcastaddresses = 0;
@@ -461,8 +459,7 @@ static void cleanupnodes(void)
 
 	// Why can't I start at zero?
 	for (j = 1; j < MAXNETNODES; j++)
-		//if (!(nodeingame[j] || SV_SendingFile(j)))
-		if (!nodeingame[j])
+		if (!(nodeingame[j] || SV_SendingFile(j)))
 			nodeconnected[j] = false;
 }
 
@@ -611,7 +608,7 @@ static boolean FD_CPY(fd_set *src, fd_set *dst, SOCKET_TYPE *fd, size_t len)
 	FD_ZERO(dst);
 	for (i = 0; i < len;i++)
 	{
-		if(fd[i] != BADSOCKET && fd[i] != (SOCKET_TYPE)ERRSOCKET &&
+		if(fd[i] != (SOCKET_TYPE)ERRSOCKET &&
 		   FD_ISSET(fd[i], src) && !FD_ISSET(fd[i], dst)) // no checking for dups
 		{
 			FD_SET(fd[i], dst);
@@ -689,7 +686,7 @@ static void SOCK_Send(void)
 		}
 		return;
 	}
-	else if (nodesocket[doomcom->remotenode] == BADSOCKET)
+	else if (nodesocket[doomcom->remotenode] == (SOCKET_TYPE)ERRSOCKET)
 	{
 		for (i = 0; i < mysocketses; i++)
 		{
@@ -741,7 +738,7 @@ static void SOCK_FreeNodenum(INT32 numnode)
 	DEBFILE(va("Free node %d (%s)\n", numnode, SOCK_GetNodeAddress(numnode)));
 
 	nodeconnected[numnode] = false;
-	nodesocket[numnode] = BADSOCKET;
+	nodesocket[numnode] = ERRSOCKET;
 
 	// put invalid address
 	memset(&clientaddress[numnode], 0, sizeof (clientaddress[numnode]));
@@ -768,7 +765,7 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen
 #endif
 	mysockaddr_t straddr;
 
-	if (s == (SOCKET_TYPE)ERRSOCKET || s == BADSOCKET)
+	if (s == (SOCKET_TYPE)ERRSOCKET)
 		return (SOCKET_TYPE)ERRSOCKET;
 #ifdef USE_WINSOCK
 	{ // Alam_GBC: disable the new UDP connection reset behavior for Win2k and up
@@ -875,9 +872,9 @@ static boolean UDP_Socket(void)
 
 
 	for (s = 0; s < mysocketses; s++)
-		mysockets[s] = BADSOCKET;
+		mysockets[s] = ERRSOCKET;
 	for (s = 0; s < MAXNETNODES+1; s++)
-		nodesocket[s] = BADSOCKET;
+		nodesocket[s] = ERRSOCKET;
 	FD_ZERO(&masterset);
 	s = 0;
 
@@ -1205,7 +1202,6 @@ static void SOCK_CloseSocket(void)
 	for (i=0; i < MAXNETNODES+1; i++)
 	{
 		if (mysockets[i] != (SOCKET_TYPE)ERRSOCKET
-		 && mysockets[i] != BADSOCKET
 		 && FD_ISSET(mysockets[i], &masterset))
 		{
 #if !defined (__DJGPP__) || defined (WATTCP)
@@ -1213,7 +1209,7 @@ static void SOCK_CloseSocket(void)
 			close(mysockets[i]);
 #endif
 		}
-		mysockets[i] = BADSOCKET;
+		mysockets[i] = ERRSOCKET;
 	}
 }
 #endif
diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c
index 0a7ef801e00ee1dcf008538745c2fdc6ea30c73d..53886f7bada25666c4d2efc6c53e8b153e9cd721 100644
--- a/src/lua_hooklib.c
+++ b/src/lua_hooklib.c
@@ -241,6 +241,8 @@ boolean LUAh_MobjHook(mobj_t *mo, enum hook which)
 	if (!gL || !(hooksAvailable[which/8] & (1<<(which%8))))
 		return false;
 
+	I_Assert(mo->type < NUMMOBJTYPES);
+
 	lua_settop(gL, 0);
 
 	// Look for all generic mobj hooks
@@ -416,6 +418,8 @@ UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which)
 	if (!gL || !(hooksAvailable[which/8] & (1<<(which%8))))
 		return 0;
 
+	I_Assert(thing1->type < NUMMOBJTYPES);
+
 	lua_settop(gL, 0);
 
 	// Look for all generic mobj collision hooks
@@ -489,6 +493,8 @@ boolean LUAh_MobjThinker(mobj_t *mo)
 	if (!gL || !(hooksAvailable[hook_MobjThinker/8] & (1<<(hook_MobjThinker%8))))
 		return false;
 
+	I_Assert(mo->type < NUMMOBJTYPES);
+
 	lua_settop(gL, 0);
 
 	// Look for all generic mobj thinker hooks
@@ -542,6 +548,8 @@ boolean LUAh_TouchSpecial(mobj_t *special, mobj_t *toucher)
 	if (!gL || !(hooksAvailable[hook_TouchSpecial/8] & (1<<(hook_TouchSpecial%8))))
 		return 0;
 
+	I_Assert(special->type < NUMMOBJTYPES);
+
 	lua_settop(gL, 0);
 
 	// Look for all generic touch special hooks
@@ -605,6 +613,8 @@ UINT8 LUAh_ShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32
 	if (!gL || !(hooksAvailable[hook_ShouldDamage/8] & (1<<(hook_ShouldDamage%8))))
 		return 0;
 
+	I_Assert(target->type < NUMMOBJTYPES);
+
 	lua_settop(gL, 0);
 
 	// Look for all generic should damage hooks
@@ -688,6 +698,8 @@ boolean LUAh_MobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32
 	if (!gL || !(hooksAvailable[hook_MobjDamage/8] & (1<<(hook_MobjDamage%8))))
 		return 0;
 
+	I_Assert(target->type < NUMMOBJTYPES);
+
 	lua_settop(gL, 0);
 
 	// Look for all generic mobj damage hooks
@@ -761,6 +773,8 @@ boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8
 	if (!gL || !(hooksAvailable[hook_MobjDeath/8] & (1<<(hook_MobjDeath%8))))
 		return 0;
 
+	I_Assert(target->type < NUMMOBJTYPES);
+
 	lua_settop(gL, 0);
 
 	// Look for all generic mobj death hooks
diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c
index 68a69cd1d2934e3af83f24c804aad7368b6f7359..97835d845934b95db6bdc1f723ba0fb27c3dcdbc 100644
--- a/src/lua_hudlib.c
+++ b/src/lua_hudlib.c
@@ -407,7 +407,7 @@ static int libd_getSpritePatch(lua_State *L)
 static int libd_getSprite2Patch(lua_State *L)
 {
 	INT32 i; // skin number
-	UINT32 j; // sprite2 prefix
+	playersprite_t j; // sprite2 prefix
 	UINT32 frame = 0; // 'A'
 	UINT8 angle = 0;
 	spritedef_t *sprdef;
diff --git a/src/lua_infolib.c b/src/lua_infolib.c
index 8f2ce67cda3f72791c4cee416b422629f051d824..7d7aab75014a83952dfba1908067f893b6be5d85 100644
--- a/src/lua_infolib.c
+++ b/src/lua_infolib.c
@@ -102,7 +102,7 @@ static int lib_sprnamelen(lua_State *L)
 // push sprite name
 static int lib_getSpr2name(lua_State *L)
 {
-	UINT32 i;
+	playersprite_t i;
 
 	lua_remove(L, 1); // don't care about spr2names[] dummy userdata.
 
@@ -129,7 +129,7 @@ static int lib_getSpr2name(lua_State *L)
 
 static int lib_getSpr2default(lua_State *L)
 {
-	UINT32 i;
+	playersprite_t i;
 
 	lua_remove(L, 1); // don't care about spr2defaults[] dummy userdata.
 
@@ -154,7 +154,7 @@ static int lib_getSpr2default(lua_State *L)
 
 static int lib_setSpr2default(lua_State *L)
 {
-	UINT32 i;
+	playersprite_t i;
 	UINT8 j = 0;
 
 	lua_remove(L, 1); // don't care about spr2defaults[] dummy userdata.
diff --git a/src/lua_script.c b/src/lua_script.c
index 994f81a40bb54880fffcefd061bb909a43e6fead..853ed5a2fd7500c7788123c290f4952ae29b757c 100644
--- a/src/lua_script.c
+++ b/src/lua_script.c
@@ -802,8 +802,15 @@ static void ArchiveExtVars(void *pointer, const char *ptype)
 	for (i = 0; lua_next(gL, -2); i++)
 		lua_pop(gL, 1);
 
-	if (i == 0 && !fastcmp(ptype,"player")) // skip anything that has an empty table and isn't a player.
+	// skip anything that has an empty table and isn't a player.
+	if (i == 0)
+	{
+		if (fastcmp(ptype,"player")) // always include players even if they have no extra variables
+			WRITEUINT16(save_p, 0);
+		lua_pop(gL, 1);
 		return;
+	}
+
 	if (fastcmp(ptype,"mobj")) // mobjs must write their mobjnum as a header
 		WRITEUINT32(save_p, ((mobj_t *)pointer)->mobjnum);
 	WRITEUINT16(save_p, i);
diff --git a/src/m_menu.c b/src/m_menu.c
index 25039c596c3fd8ea2cce92dc79bbbfc7b19837e2..52cf179e7cd75041930d2e06037f46c83a8d7902 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -70,6 +70,10 @@ int	snprintf(char *str, size_t n, const char *fmt, ...);
 //int	vsnprintf(char *str, size_t n, const char *fmt, va_list ap);
 #endif
 
+#if defined (__GNUC__) && (__GNUC__ >= 4)
+#define FIXUPO0
+#endif
+
 #define SKULLXOFF -32
 #define LINEHEIGHT 16
 #define STRINGHEIGHT 8
@@ -4925,7 +4929,7 @@ static boolean M_AddonsRefresh(void)
 
 #define offs 1
 
-#ifdef __GNUC__
+#ifdef FIXUPO0
 #pragma GCC optimize ("0")
 #endif
 
@@ -4936,7 +4940,10 @@ static void M_DrawAddons(void)
 
 	// hack - need to refresh at end of frame to handle addfile...
 	if (refreshdirmenu & M_AddonsRefresh())
-		return M_DrawMessageMenu();
+	{
+		M_DrawMessageMenu();
+		return;
+	}
 
 	if (addonsresponselimit)
 		addonsresponselimit--;
@@ -5050,7 +5057,7 @@ static void M_DrawAddons(void)
 #undef CANSAVE
 }
 
-#ifdef __GNUC__
+#ifdef FIXUPO0
 #pragma GCC reset_options
 #endif
 
diff --git a/src/mserv.c b/src/mserv.c
index e354329ed2cc016af434a70fdb7c8ece290287a3..76383ac35f2575ae8f097a5d10cbaa69cbc74fca 100644
--- a/src/mserv.c
+++ b/src/mserv.c
@@ -73,35 +73,35 @@
 #define PACKET_SIZE 1024
 
 
-#define  MS_NO_ERROR               0
-#define  MS_SOCKET_ERROR        -201
-#define  MS_CONNECT_ERROR       -203
-#define  MS_WRITE_ERROR         -210
-#define  MS_READ_ERROR          -211
-#define  MS_CLOSE_ERROR         -212
-#define  MS_GETHOSTBYNAME_ERROR -220
-#define  MS_GETHOSTNAME_ERROR   -221
-#define  MS_TIMEOUT_ERROR       -231
+#define  MS_NO_ERROR            	   0
+#define  MS_SOCKET_ERROR        	-201
+#define  MS_CONNECT_ERROR       	-203
+#define  MS_WRITE_ERROR         	-210
+#define  MS_READ_ERROR          	-211
+#define  MS_CLOSE_ERROR         	-212
+#define  MS_GETHOSTBYNAME_ERROR 	-220
+#define  MS_GETHOSTNAME_ERROR   	-221
+#define  MS_TIMEOUT_ERROR       	-231
 
 // see master server code for the values
-#define ADD_SERVER_MSG           101
-#define REMOVE_SERVER_MSG        103
-#define ADD_SERVERv2_MSG         104
-#define GET_SERVER_MSG           200
-#define GET_SHORT_SERVER_MSG     205
-#define ASK_SERVER_MSG           206
-#define ANSWER_ASK_SERVER_MSG    207
-#define ASK_SERVER_MSG           206
-#define ANSWER_ASK_SERVER_MSG    207
-#define GET_MOTD_MSG             208
-#define SEND_MOTD_MSG            209
-#define GET_ROOMS_MSG			 210
-#define SEND_ROOMS_MSG			 211
-#define GET_ROOMS_HOST_MSG		 212
-#define GET_VERSION_MSG			 213
-#define SEND_VERSION_MSG		 214
-#define GET_BANNED_MSG			 215 // Someone's been baaaaaad!
-#define PING_SERVER_MSG			 216
+#define ADD_SERVER_MSG          	101
+#define REMOVE_SERVER_MSG       	103
+#define ADD_SERVERv2_MSG        	104
+#define GET_SERVER_MSG          	200
+#define GET_SHORT_SERVER_MSG    	205
+#define ASK_SERVER_MSG          	206
+#define ANSWER_ASK_SERVER_MSG   	207
+#define ASK_SERVER_MSG          	206
+#define ANSWER_ASK_SERVER_MSG   	207
+#define GET_MOTD_MSG            	208
+#define SEND_MOTD_MSG           	209
+#define GET_ROOMS_MSG           	210
+#define SEND_ROOMS_MSG          	211
+#define GET_ROOMS_HOST_MSG      	212
+#define GET_VERSION_MSG         	213
+#define SEND_VERSION_MSG        	214
+#define GET_BANNED_MSG          	215 // Someone's been baaaaaad!
+#define PING_SERVER_MSG         	216
 
 #define HEADER_SIZE (sizeof (INT32)*4)
 
@@ -188,7 +188,6 @@ UINT16 current_port = 0;
 
 #if defined (_WIN32) && !defined (NONET)
 typedef SOCKET SOCKET_TYPE;
-#define BADSOCKET INVALID_SOCKET
 #define ERRSOCKET (SOCKET_ERROR)
 #else
 #if (defined (__unix__) && !defined (MSDOS)) || defined (__APPLE__) || defined (__HAIKU__)
@@ -196,7 +195,6 @@ typedef int SOCKET_TYPE;
 #else
 typedef unsigned long SOCKET_TYPE;
 #endif
-#define BADSOCKET (SOCKET_TYPE)(~0)
 #define ERRSOCKET (-1)
 #endif
 
@@ -205,7 +203,7 @@ typedef int socklen_t;
 #endif
 
 #ifndef NONET
-static SOCKET_TYPE socket_fd = BADSOCKET; // WINSOCK socket
+static SOCKET_TYPE socket_fd = ERRSOCKET; // WINSOCK socket
 static struct timeval select_timeout;
 static fd_set wset;
 static size_t recvfull(SOCKET_TYPE s, char *buf, size_t len, int flags);
@@ -236,9 +234,9 @@ void AddMServCommands(void)
 static void CloseConnection(void)
 {
 #ifndef NONET
-	if (socket_fd != (SOCKET_TYPE)ERRSOCKET && socket_fd != BADSOCKET)
+	if (socket_fd != (SOCKET_TYPE)ERRSOCKET)
 		close(socket_fd);
-	socket_fd = BADSOCKET;
+	socket_fd = ERRSOCKET;
 #endif
 }
 
@@ -356,7 +354,7 @@ static INT32 MS_Connect(const char *ip_addr, const char *str_port, INT32 async)
 	while (runp != NULL)
 	{
 		socket_fd = socket(runp->ai_family, runp->ai_socktype, runp->ai_protocol);
-		if (socket_fd != BADSOCKET && socket_fd != (SOCKET_TYPE)ERRSOCKET)
+		if (socket_fd != (SOCKET_TYPE)ERRSOCKET)
 		{
 			if (async) // do asynchronous connection
 			{
diff --git a/src/p_mobj.c b/src/p_mobj.c
index 6808a6dc6b1e30acee40eae915436aa0b465c3a9..8695d57e4098898e48a24530f718818e861b2bb8 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -8942,6 +8942,16 @@ void P_RespawnSpecials(void)
 			if (mthing->type == mobjinfo[i].doomednum)
 				break;
 
+		if (i == NUMMOBJTYPES) // prevent creation of objects with this type -- Monster Iestyn 17/12/17
+		{
+			// 3D Mode start Thing is unlikely to be added to the que,
+			// so don't bother checking for that specific type
+			CONS_Alert(CONS_WARNING, M_GetText("P_RespawnSpecials: Unknown thing type %d attempted to respawn at (%d, %d)\n"), mthing->type, mthing->x, mthing->y);
+			// pull it from the que
+			iquetail = (iquetail+1)&(ITEMQUESIZE-1);
+			return;
+		}
+
 		//CTF rings should continue to respawn as normal rings outside of CTF.
 		if (gametype != GT_CTF)
 		{
diff --git a/src/p_spec.c b/src/p_spec.c
index dbee873ec5005be318bce9c342dba101e1ad7f8c..797aba049cef29e9622e4f55d60dfe79ad6ca1cc 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -5240,13 +5240,11 @@ static void P_AddOldAirbob(sector_t *sec, line_t *sourceline, boolean noadjust)
 	airbob->vars[2] = FRACUNIT;
 
 	if (noadjust)
-	{
 		airbob->vars[7] = airbob->sector->ceilingheight-16*FRACUNIT;
-		airbob->vars[6] = airbob->vars[7]
-			- (sec->ceilingheight - sec->floorheight);
-	}
 	else
 		airbob->vars[7] = airbob->sector->ceilingheight - P_AproxDistance(sourceline->dx, sourceline->dy);
+	airbob->vars[6] = airbob->vars[7]
+		- (sec->ceilingheight - sec->floorheight);
 
 	airbob->vars[3] = airbob->vars[2];
 
diff --git a/src/sdl/Srb2SDL-vc10.vcxproj b/src/sdl/Srb2SDL-vc10.vcxproj
index abf6d76d2935d7546f445cf9b53880963d0b1433..00ed0db39400a2b7589a3c4726f19d19bcc2ae84 100644
--- a/src/sdl/Srb2SDL-vc10.vcxproj
+++ b/src/sdl/Srb2SDL-vc10.vcxproj
@@ -141,6 +141,7 @@
     <ClInclude Include="..\hardware\hw3dsdrv.h" />
     <ClInclude Include="..\hardware\hw3sound.h" />
     <ClInclude Include="..\hardware\hws_data.h" />
+    <ClInclude Include="..\hardware\hw_clip.h" />
     <ClInclude Include="..\hardware\hw_data.h" />
     <ClInclude Include="..\hardware\hw_defs.h" />
     <ClInclude Include="..\hardware\hw_dll.h" />
@@ -282,6 +283,7 @@
     <ClCompile Include="..\hardware\hw3sound.c" />
     <ClCompile Include="..\hardware\hw_bsp.c" />
     <ClCompile Include="..\hardware\hw_cache.c" />
+    <ClCompile Include="..\hardware\hw_clip.c" />
     <ClCompile Include="..\hardware\hw_draw.c" />
     <ClCompile Include="..\hardware\hw_light.c" />
     <ClCompile Include="..\hardware\hw_main.c" />
diff --git a/src/sdl/Srb2SDL-vc10.vcxproj.filters b/src/sdl/Srb2SDL-vc10.vcxproj.filters
index bdb029cf9437e8c960a84a111bbcbfaf5dc9b82b..1d132faf0e9624e29157ae13a72527e9e98f7627 100644
--- a/src/sdl/Srb2SDL-vc10.vcxproj.filters
+++ b/src/sdl/Srb2SDL-vc10.vcxproj.filters
@@ -444,6 +444,9 @@
     <ClInclude Include="sdlmain.h">
       <Filter>SDLApp</Filter>
     </ClInclude>
+    <ClInclude Include="..\hardware\hw_clip.h">
+      <Filter>Hw_Hardware</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <CustomBuild Include="..\tmap.nas">
@@ -879,6 +882,9 @@
     <ClCompile Include="SDL_main\SDL_windows_main.c">
       <Filter>SDLApp</Filter>
     </ClCompile>
+    <ClCompile Include="..\hardware\hw_clip.c">
+      <Filter>Hw_Hardware</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <Image Include="Srb2SDL.ico">
diff --git a/src/sdl/i_main.c b/src/sdl/i_main.c
index f1cecad4d82654829600bd215ba1a7881c1e4d05..f54f0d7c5496226d84c84a9636bdb899dbdd4414 100644
--- a/src/sdl/i_main.c
+++ b/src/sdl/i_main.c
@@ -103,6 +103,10 @@ static inline VOID MakeCodeWritable(VOID)
 
 	\return	int
 */
+#if defined (__GNUC__) && (__GNUC__ >= 4)
+#pragma GCC diagnostic ignored "-Wmissing-noreturn"
+#endif
+
 #ifdef FORCESDLMAIN
 int SDL_main(int argc, char **argv)
 #else
@@ -148,7 +152,9 @@ int main(int argc, char **argv)
 			LoadLibraryA("exchndl.dll");
 		}
 	}
+#ifndef __MINGW32__
 	prevExceptionFilter = SetUnhandledExceptionFilter(RecordExceptionInfo);
+#endif
 	MakeCodeWritable();
 #endif
 	// startup SRB2
diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c
index 893827a7bd4ace23bdc391ad760606772172091d..365d70729f23c650d7fce7e65e6874c6de55573f 100644
--- a/src/sdl/i_video.c
+++ b/src/sdl/i_video.c
@@ -194,7 +194,7 @@ static void SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen)
 			}
 			// Reposition window only in windowed mode
 			SDL_SetWindowSize(window, width, height);
-			SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED_DISPLAY(1), SDL_WINDOWPOS_CENTERED_DISPLAY(1));
+			SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
 		}
 	}
 	else
diff --git a/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj b/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj
index 68391f99ca9168b9f5c68d62657df71fae5ba167..eaac87debe38e36f549942a7d2e00775b99414e1 100644
--- a/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj
+++ b/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj
@@ -1214,7 +1214,7 @@
 		C01FCF4B08A954540054247B /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
-				CURRENT_PROJECT_VERSION = 2.1.19;
+				CURRENT_PROJECT_VERSION = 2.1.20;
 				GCC_PREPROCESSOR_DEFINITIONS = (
 					"$(inherited)",
 					NORMALSRB2,
@@ -1226,7 +1226,7 @@
 		C01FCF4C08A954540054247B /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
-				CURRENT_PROJECT_VERSION = 2.1.19;
+				CURRENT_PROJECT_VERSION = 2.1.20;
 				GCC_ENABLE_FIX_AND_CONTINUE = NO;
 				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
 				GCC_PREPROCESSOR_DEFINITIONS = (
diff --git a/src/w_wad.c b/src/w_wad.c
index 75bf40983831d655ad0317aa908b72b2bc23f06c..f25711e4e741a8c86ab86d0936744f167c20b679 100644
--- a/src/w_wad.c
+++ b/src/w_wad.c
@@ -448,7 +448,7 @@ UINT16 W_InitFile(const char *filename)
 		// We must look for the central directory through the file. (Thanks to JTE for this algorithm.)
 		// All of the central directory entry headers have a signature of 0x50 0x4b 0x01 0x02.
 		// The first entry found means the beginning of the central directory.
-		fseek(handle, -min(size, (22 + 65536)), SEEK_CUR);
+		fseek(handle, 0-min(size, (22 + 65536)), SEEK_CUR);
 		s = endPat;
 		while((c = fgetc(handle)) != EOF)
 		{
@@ -1198,6 +1198,7 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si
 	default:
 		I_Error("wad %d, lump %d: unsupported compression type!", wad, lump);
 	}
+	return 0;
 }
 
 size_t W_ReadLumpHeader(lumpnum_t lumpnum, void *dest, size_t size, size_t offset)
diff --git a/src/win32/Makefile.cfg b/src/win32/Makefile.cfg
index 99b8bc9b2ca4b6949944429546b3e379808e804a..749734a727512fe87d3856d74e94a2902b31cb3a 100644
--- a/src/win32/Makefile.cfg
+++ b/src/win32/Makefile.cfg
@@ -64,7 +64,7 @@ endif
 
 ifdef SDL
 	i_system_o+=$(OBJDIR)/SRB2.res
-	i_main_o+=$(OBJDIR)/win_dbg.o
+	#i_main_o+=$(OBJDIR)/win_dbg.o
 ifndef NOHW
 	OPTS+=-DUSE_WGL_SWAP
 endif
@@ -81,7 +81,8 @@ endif
 	i_net_o=$(OBJDIR)/win_net.o
 	i_system_o=$(OBJDIR)/win_sys.o $(OBJDIR)/SRB2.res
 	i_sound_o=$(OBJDIR)/win_snd.o
-	i_main_o=$(OBJDIR)/win_dbg.o $(OBJDIR)/win_main.o
+	i_main_o=$(OBJDIR)/win_main.o
+	#i_main_o+=$(OBJDIR)/win_dbg.o
 	OBJS=$(OBJDIR)/dx_error.o $(OBJDIR)/fabdxlib.o $(OBJDIR)/win_vid.o $(OBJDIR)/win_dll.o
 endif
 
diff --git a/src/win32/Srb2win-vc10.vcxproj b/src/win32/Srb2win-vc10.vcxproj
index 95f9c85f94aeb1e6b62b2ac9447402a01c811840..ed6b46b8ffb939a2bbf632690418b840f486894d 100644
--- a/src/win32/Srb2win-vc10.vcxproj
+++ b/src/win32/Srb2win-vc10.vcxproj
@@ -119,6 +119,7 @@
     <ClCompile Include="..\hardware\hw3sound.c" />
     <ClCompile Include="..\hardware\hw_bsp.c" />
     <ClCompile Include="..\hardware\hw_cache.c" />
+    <ClCompile Include="..\hardware\hw_clip.c" />
     <ClCompile Include="..\hardware\hw_draw.c" />
     <ClCompile Include="..\hardware\hw_light.c" />
     <ClCompile Include="..\hardware\hw_main.c" />
@@ -276,6 +277,7 @@
     <ClInclude Include="..\hardware\hw3dsdrv.h" />
     <ClInclude Include="..\hardware\hw3sound.h" />
     <ClInclude Include="..\hardware\hws_data.h" />
+    <ClInclude Include="..\hardware\hw_clip.h" />
     <ClInclude Include="..\hardware\hw_data.h" />
     <ClInclude Include="..\hardware\hw_defs.h" />
     <ClInclude Include="..\hardware\hw_dll.h" />
diff --git a/src/win32/Srb2win-vc10.vcxproj.filters b/src/win32/Srb2win-vc10.vcxproj.filters
index cfd46f1f81d260f7f9645759f7601626c6a64dad..6319749a9e8cfdb7d61f0899c9e63db60e098dc5 100644
--- a/src/win32/Srb2win-vc10.vcxproj.filters
+++ b/src/win32/Srb2win-vc10.vcxproj.filters
@@ -450,6 +450,9 @@
     <ClCompile Include="..\string.c">
       <Filter>M_Misc</Filter>
     </ClCompile>
+    <ClCompile Include="..\hardware\hw_clip.c">
+      <Filter>Hw_Hardware</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="afxres.h">
@@ -845,6 +848,9 @@
     <ClInclude Include="..\fastcmp.h">
       <Filter>O_Other</Filter>
     </ClInclude>
+    <ClInclude Include="..\hardware\hw_clip.h">
+      <Filter>Hw_Hardware</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <Image Include="Srb2win.ico">
diff --git a/src/win32/win_main.c b/src/win32/win_main.c
index 4ac05f94f4cc02d88cebc2ec9dc645d0c0031476..6c774f5576dad667e64f990b2082df815049b563 100644
--- a/src/win32/win_main.c
+++ b/src/win32/win_main.c
@@ -244,7 +244,7 @@ static LRESULT CALLBACK MainWndproc(HWND hWnd, UINT message, WPARAM wParam, LPAR
 				D_PostEvent(&ev);
 				return TRUE;
 			}
-
+			break;
 		case WM_XBUTTONDOWN:
 			if (nodinput)
 			{
@@ -253,7 +253,7 @@ static LRESULT CALLBACK MainWndproc(HWND hWnd, UINT message, WPARAM wParam, LPAR
 				D_PostEvent(&ev);
 				return TRUE;
 			}
-
+			break;
 		case WM_MOUSEWHEEL:
 			//I_OutputMsg("MW_WHEEL dispatched.\n");
 			ev.type = ev_keydown;
@@ -666,7 +666,9 @@ int WINAPI WinMain (HINSTANCE hInstance,
 #endif
 			LoadLibraryA("exchndl.dll");
 
+#ifndef __MINGW32__
 		prevExceptionFilter = SetUnhandledExceptionFilter(RecordExceptionInfo);
+#endif
 
 		Result = HandledWinMain(hInstance);
 #ifdef BUGTRAP
diff --git a/src/win32/win_sys.c b/src/win32/win_sys.c
index 80b89a6e64ccc549242b60ee216d0721c4f0096f..316da61d4923d07c934915f88570d75bd98d31ef 100644
--- a/src/win32/win_sys.c
+++ b/src/win32/win_sys.c
@@ -2581,7 +2581,7 @@ acquire:
 		UINT64 newbuttons = joybuttons ^ lastjoybuttons;
 		lastjoybuttons = joybuttons;
 
-		for (i = 0; i < JOYBUTTONS && i < JOYBUTTONS_MAX; i++, j <<= 1)
+		for (i = 0; i < JOYBUTTONS_MIN; i++, j <<= 1)
 		{
 			if (newbuttons & j) // button changed state?
 			{
@@ -2601,7 +2601,7 @@ acquire:
 		UINT64 newhats = joyhats ^ lastjoyhats;
 		lastjoyhats = joyhats;
 
-		for (i = 0; i < JOYHATS*4 && i < JOYHATS_MAX*4; i++, j <<= 1)
+		for (i = 0; i < JOYHATS_MIN*4; i++, j <<= 1)
 		{
 			if (newhats & j) // button changed state?
 			{
@@ -2825,7 +2825,7 @@ acquire:
 		UINT64 newbuttons = joybuttons ^ lastjoy2buttons;
 		lastjoy2buttons = joybuttons;
 
-		for (i = 0; i < JOYBUTTONS && i < JOYBUTTONS_MAX; i++, j <<= 1)
+		for (i = 0; i < JOYBUTTONS_MIN; i++, j <<= 1)
 		{
 			if (newbuttons & j) // button changed state?
 			{
@@ -2845,7 +2845,7 @@ acquire:
 		UINT64 newhats = joyhats ^ lastjoy2hats;
 		lastjoy2hats = joyhats;
 
-		for (i = 0; i < JOYHATS*4 && i < JOYHATS_MAX*4; i++, j <<= 1)
+		for (i = 0; i < JOYHATS_MIN*4; i++, j <<= 1)
 		{
 			if (newhats & j) // button changed state?
 			{
diff --git a/src/win32/win_vid.c b/src/win32/win_vid.c
index 5560751de3c858b8c4f424f2b0154dde891e47e7..e9b5d7e9f95a29b45b538fc20de5fa23f09501dd 100644
--- a/src/win32/win_vid.c
+++ b/src/win32/win_vid.c
@@ -322,6 +322,7 @@ static inline boolean I_SkipFrame(void)
 		case GS_LEVEL:
 			if (!paused)
 				return false;
+			/* FALLTHRU */
 		//case GS_TIMEATTACK: -- sorry optimisation but now we have a cool level platter and that being laggardly looks terrible
 #ifndef CLIENT_LOADINGSCREEN
 		case GS_WAITINGPLAYERS: