diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 1bdfc94f596dedbf125633ee682f7db5afdbd663..486f4e913057af02c22a6acd6c554bd7b76801b3 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -245,6 +245,7 @@ target_compile_options(SRB2SDL2 PRIVATE
 	# This is a direct translation from versions.mk
 	$<$<AND:$<COMPILE_LANGUAGE:C>,$<C_COMPILER_ID:GNU>>:
 		-Wall
+		-Wextra
 		-Wno-trigraphs
 		-W # Was controlled by RELAXWARNINGS
 		-Wfloat-equal
@@ -312,11 +313,7 @@ target_compile_options(SRB2SDL2 PRIVATE
 
 		$<$<VERSION_GREATER_EQUAL:$<C_COMPILER_VERSION>,8.1.0>:
 			-Wno-error=format-overflow
-			-Wno-error=stringop-truncation
-			-Wno-error=stringop-overflow
 			-Wno-format-overflow
-			-Wno-stringop-truncation
-			-Wno-stringop-overflow
 			-Wno-error=multistatement-macros
 		>
 
@@ -329,7 +326,9 @@ target_compile_options(SRB2SDL2 PRIVATE
 	$<$<AND:$<COMPILE_LANGUAGE:C>,$<OR:$<C_COMPILER_ID:AppleClang>,$<C_COMPILER_ID:Clang>>>:
 		-Wall
 		-Wno-absolute-value
+		-Wextra
 		-Wno-trigraphs
+		-Wconditional-uninitialized
 		-Wno-error=non-literal-null-conversion
 		-Wno-error=constant-conversion
 		-Wno-error=unused-but-set-variable
@@ -346,6 +345,9 @@ target_compile_options(SRB2SDL2 PRIVATE
 	# C++, GNU, Clang and Apple Clang
 	$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<OR:$<C_COMPILER_ID:GNU>,$<C_COMPILER_ID:AppleClang>,$<C_COMPILER_ID:Clang>>>:
 		-Wall
+		-Wextra
+		-Wno-trigraphs
+		-Wconditional-uninitialized
 	>
 
 	# C++, MSVC
diff --git a/src/Makefile.d/versions.mk b/src/Makefile.d/versions.mk
index b639ad9a13cb45a898d5c3d5b9d773b3203c2daf..7c130d90846ab6f4199eb618ee918fdb6999e5cc 100644
--- a/src/Makefile.d/versions.mk
+++ b/src/Makefile.d/versions.mk
@@ -135,11 +135,7 @@ ifdef GCC71
 endif
 ifdef GCC81
  WFLAGS+=-Wno-error=format-overflow
- WFLAGS+=-Wno-error=stringop-truncation
- WFLAGS+=-Wno-error=stringop-overflow
  WFLAGS+=-Wno-format-overflow
- WFLAGS+=-Wno-stringop-truncation
- WFLAGS+=-Wno-stringop-overflow
  WFLAGS+=-Wno-error=multistatement-macros
 endif
 
diff --git a/src/blua/lvm.c b/src/blua/lvm.c
index b74fef4ee3d72d3081fdb11776ab759c337020f3..627685b389dcdea401dffc72ed02ef061394a1b6 100644
--- a/src/blua/lvm.c
+++ b/src/blua/lvm.c
@@ -134,7 +134,7 @@ void luaV_gettable (lua_State *L, TValue *t, TValue *key, StkId val) {
 void luaV_settable (lua_State *L, TValue *t, TValue *key, StkId val) {
   int loop;
   for (loop = 0; loop < MAXTAGLOOP; loop++) {
-    TValue *tm;
+    TValue *tm = NULL;
     if (ttistable(t)) {  /* `t' is a table? */
       Table *h = hvalue(t);
       TValue *oldval = luaH_set(L, h, key); /* do a primitive set */
diff --git a/src/command.c b/src/command.c
index 87d4f893fe6683cd21e93a8663dd71b30dce57af..a46cc98bcde4ad01557a31e439994135341a5c06 100644
--- a/src/command.c
+++ b/src/command.c
@@ -2060,16 +2060,16 @@ void CV_StealthSet(consvar_t *var, const char *value)
   */
 static void CV_SetValueMaybeStealth(consvar_t *var, INT32 value, boolean stealth)
 {
-	char val[SKINNAMESIZE+1];
+	char val[SKINNAMESIZE+1] = "None";
 
 	if (var == &cv_forceskin) // Special handling.
 	{
 		const char *tmpskin = NULL;
 		if ((value < 0) || (value >= numskins))
-			tmpskin = "None";
+			;
 		else
 			tmpskin = skins[value]->name;
-		strncpy(val, tmpskin, SKINNAMESIZE);
+		memcpy(val, tmpskin, SKINNAMESIZE);
 	}
 	else
 		sprintf(val, "%d", value);
diff --git a/src/d_player.h b/src/d_player.h
index 26f17a1a09e114a1d73887acd19338c1245b14a0..098b4485ca5e602328a4b03b5e0c6719fe6d154b 100644
--- a/src/d_player.h
+++ b/src/d_player.h
@@ -603,6 +603,7 @@ typedef struct player_s
 	boolean spectator;
 	boolean outofcoop;
 	boolean removing;
+	boolean muted;
 	UINT8 bot;
 	struct player_s *botleader;
 	UINT16 lastbuttons;
diff --git a/src/deh_soc.c b/src/deh_soc.c
index 41eb28a90f91f77c3672b7b35ea919f9a0edf6ef..beaf7cbf0cd4f861ce413fc9c504755a2b4965e8 100644
--- a/src/deh_soc.c
+++ b/src/deh_soc.c
@@ -324,7 +324,7 @@ void readPlayer(MYFILE *f, INT32 num)
 			if (fastcmp(word, "PICNAME"))
 			{
 				SLOTFOUND
-				strncpy(description[num].picname, word2, 8);
+				strncpy(description[num].picname, word2, sizeof(description[num].picname)-1);
 			}
 			else if (fastcmp(word, "DISPLAYNAME"))
 			{
@@ -355,7 +355,7 @@ void readPlayer(MYFILE *f, INT32 num)
 			else if (fastcmp(word, "NAMETAG") || fastcmp(word, "TAGNAME"))
 			{
 				SLOTFOUND
-				strncpy(description[num].nametag, word2, 8);
+				strncpy(description[num].nametag, word2, sizeof(description[num].nametag)-1);
 			}
 			else if (fastcmp(word, "TAGTEXTCOLOR") || fastcmp(word, "TAGTEXTCOLOUR"))
 			{
@@ -1163,7 +1163,7 @@ void readgametype(MYFILE *f, char *gtname)
 	INT16 newgtrankingstype = -1;
 	int newgtinttype = 0;
 	char gtdescription[441];
-	char gtconst[MAXLINELEN];
+	char gtconst[MAXLINELEN+1];
 
 	// Empty strings.
 	gtdescription[0] = '\0';
@@ -1677,7 +1677,7 @@ void readlevelheader(MYFILE *f, INT32 num)
 			else if (fastcmp(word, "SKYNUM"))
 				mapheaderinfo[num-1]->skynum = (INT16)i;
 			else if (fastcmp(word, "INTERSCREEN"))
-				strncpy(mapheaderinfo[num-1]->interscreen, word2, 8);
+				strncpy(mapheaderinfo[num-1]->interscreen, word2, sizeof(mapheaderinfo[num-1]->interscreen)-1);
 			else if (fastcmp(word, "PRECUTSCENENUM"))
 				mapheaderinfo[num-1]->precutscenenum = (UINT8)i;
 			else if (fastcmp(word, "CUTSCENENUM"))
@@ -2294,7 +2294,7 @@ static void readtextpromptpage(MYFILE *f, INT32 num, INT32 pagenum)
 					char name[34];
 					name[0] = '\x82'; // color yellow
 					name[1] = 0;
-					strncat(name, word2, 33);
+					strncat(name, word2, 32);
 					name[33] = 0;
 
 					// Replace _ with ' '
@@ -2304,7 +2304,7 @@ static void readtextpromptpage(MYFILE *f, INT32 num, INT32 pagenum)
 							name[j] = ' ';
 					}
 
-					strncpy(textprompts[num]->page[pagenum].name, name, 32);
+					strncpy(textprompts[num]->page[pagenum].name, name, sizeof(textprompts[num]->page[pagenum].name));
 				}
 				else
 					*textprompts[num]->page[pagenum].name = '\0';
@@ -3794,7 +3794,7 @@ void readmaincfg(MYFILE *f)
 			}
 			else if (fastcmp(word, "TITLEPICSNAME"))
 			{
-				strncpy(ttname, word2, 9);
+				strncpy(ttname, word2, sizeof(ttname)-1);
 				titlechanged = true;
 			}
 			else if (fastcmp(word, "TITLEPICSX"))
@@ -3878,8 +3878,12 @@ void readmaincfg(MYFILE *f)
 				savemoddata = true;
 
 				// Also save a time attack folder
-				filenamelen = strlen(gamedatafilename)-4;  // Strip off the extension
-				strncpy(timeattackfolder, gamedatafilename, min(filenamelen, sizeof (timeattackfolder)));
+				filenamelen = strlen(gamedatafilename);  // Strip off the extension
+				if (filenamelen >= 4)
+					filenamelen -= 4;
+				if (filenamelen >= sizeof(timeattackfolder))
+					filenamelen = sizeof(timeattackfolder)-1;
+				strncpy(timeattackfolder, gamedatafilename, filenamelen);
 				timeattackfolder[min(filenamelen, sizeof (timeattackfolder) - 1)] = '\0';
 
 				strcpy(savegamename, timeattackfolder);
diff --git a/src/deh_tables.c b/src/deh_tables.c
index fa86518e2e0eaf51555d6ee334a97cad22b3afa3..8a3aae58654ea7f162efb31496ef5b88772d4325 100644
--- a/src/deh_tables.c
+++ b/src/deh_tables.c
@@ -4834,6 +4834,7 @@ const char *const POWERS_LIST[] = {
 
 const char *const HUDITEMS_LIST[] = {
 	"LIVES",
+	"INPUT",
 
 	"RINGS",
 	"RINGSNUM",
diff --git a/src/doomstat.h b/src/doomstat.h
index 6a2d6acf00f816804c1ec8830b69c9848deadcbe..c2fc963478b56682a03acf6d592398c134e861bc 100644
--- a/src/doomstat.h
+++ b/src/doomstat.h
@@ -165,7 +165,7 @@ extern boolean exitfadestarted;
 typedef struct
 {
 	UINT8 numpics;
-	char picname[8][8];
+	char picname[8][8+1];
 	UINT8 pichires[8];
 	char *text;
 	UINT16 xcoord[8];
@@ -296,69 +296,69 @@ typedef struct
 typedef struct
 {
 	// The original eight, plus one.
-	char lvlttl[22];       ///< Level name without "Zone". (21 character limit instead of 32, 21 characters can display on screen max anyway)
-	char subttl[33];       ///< Subtitle for level
-	UINT8 actnum;          ///< Act number or 0 for none.
-	UINT32 typeoflevel;    ///< Combination of typeoflevel flags.
-	INT16 nextlevel;       ///< Map number of next level, or 1100-1102 to end.
-	INT16 marathonnext;    ///< See nextlevel, but for Marathon mode. Necessary to support hub worlds ala SUGOI.
-	char keywords[33];     ///< Keywords separated by space to search for. 32 characters.
-	char musname[7];       ///< Music track to play. "" for no music.
-	UINT16 mustrack;       ///< Subsong to play. Only really relevant for music modules and specific formats supported by GME. 0 to ignore.
-	UINT32 muspos;    ///< Music position to jump to.
-	char forcecharacter[17];  ///< (SKINNAMESIZE+1) Skin to switch to or "" to disable.
-	UINT8 weather;         ///< 0 = sunny day, 1 = storm, 2 = snow, 3 = rain, 4 = blank, 5 = thunder w/o rain, 6 = rain w/o lightning, 7 = heat wave.
-	INT16 skynum;          ///< Sky number to use.
-	INT16 skybox_scalex;   ///< Skybox X axis scale. (0 = no movement, 1 = 1:1 movement, 16 = 16:1 slow movement, -4 = 1:4 fast movement, etc.)
-	INT16 skybox_scaley;   ///< Skybox Y axis scale.
-	INT16 skybox_scalez;   ///< Skybox Z axis scale.
+	char lvlttl[21+1];          ///< Level name without "Zone". (21 character limit instead of 32, 21 characters can display on screen max anyway)
+	char subttl[32+1];          ///< Subtitle for level
+	UINT8 actnum;               ///< Act number or 0 for none.
+	UINT32 typeoflevel;         ///< Combination of typeoflevel flags.
+	INT16 nextlevel;            ///< Map number of next level, or 1100-1102 to end.
+	INT16 marathonnext;         ///< See nextlevel, but for Marathon mode. Necessary to support hub worlds ala SUGOI.
+	char keywords[32+1];        ///< Keywords separated by space to search for. 32 characters.
+	char musname[7];            ///< Music track to play. "" for no music.
+	UINT16 mustrack;            ///< Subsong to play. Only really relevant for music modules and specific formats supported by GME. 0 to ignore.
+	UINT32 muspos;              ///< Music position to jump to.
+	char forcecharacter[16+1];  ///< (SKINNAMESIZE+1) Skin to switch to or "" to disable.
+	UINT8 weather;              ///< 0 = sunny day, 1 = storm, 2 = snow, 3 = rain, 4 = blank, 5 = thunder w/o rain, 6 = rain w/o lightning, 7 = heat wave.
+	INT16 skynum;               ///< Sky number to use.
+	INT16 skybox_scalex;        ///< Skybox X axis scale. (0 = no movement, 1 = 1:1 movement, 16 = 16:1 slow movement, -4 = 1:4 fast movement, etc.)
+	INT16 skybox_scaley;        ///< Skybox Y axis scale.
+	INT16 skybox_scalez;        ///< Skybox Z axis scale.
 
 	// Extra information.
-	char interscreen[8];  ///< 320x200 patch to display at intermission.
-	char runsoc[33];      ///< SOC to execute at start of level (32 character limit instead of 63)
-	char scriptname[33];  ///< Script to use when the map is switched to. (32 character limit instead of 191)
-	UINT8 precutscenenum; ///< Cutscene number to play BEFORE a level starts.
-	UINT8 cutscenenum;    ///< Cutscene number to use, 0 for none.
-	INT16 countdown;      ///< Countdown until level end?
-	UINT16 palette;       ///< PAL lump to use on this map
-	UINT8 numlaps;        ///< Number of laps in circuit mode, unless overridden.
-	SINT8 unlockrequired; ///< Is an unlockable required to play this level? -1 if no.
-	UINT8 levelselect;    ///< Is this map available in the level select? If so, which map list is it available in?
-	SINT8 bonustype;      ///< What type of bonus does this level have? (-1 for null.)
-	SINT8 maxbonuslives;  ///< How many bonus lives to award at Intermission? (-1 for unlimited.)
-
-	UINT16 levelflags;     ///< LF_flags:  merged booleans into one UINT16 for space, see below
-	UINT8 menuflags;      ///< LF2_flags: options that affect record attack / nights mode menus
-
-	char selectheading[22]; ///< Level select heading. Allows for controllable grouping.
-	UINT16 startrings;      ///< Number of rings players start with.
-	INT32 sstimer;          ///< Timer for special stages.
-	UINT32 ssspheres;       ///< Sphere requirement in special stages.
-	fixed_t gravity;        ///< Map-wide gravity.
+	char interscreen[8+1];      ///< 320x200 patch to display at intermission.
+	char runsoc[32+1];          ///< SOC to execute at start of level (32 character limit instead of 63)
+	char scriptname[32+1];      ///< Script to use when the map is switched to. (32 character limit instead of 191)
+	UINT8 precutscenenum;       ///< Cutscene number to play BEFORE a level starts.
+	UINT8 cutscenenum;          ///< Cutscene number to use, 0 for none.
+	INT16 countdown;            ///< Countdown until level end?
+	UINT16 palette;             ///< PAL lump to use on this map
+	UINT8 numlaps;              ///< Number of laps in circuit mode, unless overridden.
+	SINT8 unlockrequired;       ///< Is an unlockable required to play this level? -1 if no.
+	UINT8 levelselect;          ///< Is this map available in the level select? If so, which map list is it available in?
+	SINT8 bonustype;            ///< What type of bonus does this level have? (-1 for null.)
+	SINT8 maxbonuslives;        ///< How many bonus lives to award at Intermission? (-1 for unlimited.)
+
+	UINT16 levelflags;          ///< LF_flags:  merged booleans into one UINT16 for space, see below
+	UINT8 menuflags;            ///< LF2_flags: options that affect record attack / nights mode menus
+
+	char selectheading[22];     ///< Level select heading. Allows for controllable grouping.
+	UINT16 startrings;          ///< Number of rings players start with.
+	INT32 sstimer;              ///< Timer for special stages.
+	UINT32 ssspheres;           ///< Sphere requirement in special stages.
+	fixed_t gravity;            ///< Map-wide gravity.
 
 	// Title card.
-	char ltzzpatch[9];      ///< Zig zag patch.
-	char ltzztext[9];       ///< Zig zag text.
-	char ltactdiamond[9];   ///< Act diamond.
+	char ltzzpatch[8+1];        ///< Zig zag patch.
+	char ltzztext[8+1];         ///< Zig zag text.
+	char ltactdiamond[8+1];     ///< Act diamond.
 
 	// Freed animals stuff.
-	UINT8 numFlickies;     ///< Internal. For freed flicky support.
-	mobjtype_t *flickies;  ///< List of freeable flickies in this level. Allocated dynamically for space reasons. Be careful.
+	UINT8 numFlickies;          ///< Internal. For freed flicky support.
+	mobjtype_t *flickies;       ///< List of freeable flickies in this level. Allocated dynamically for space reasons. Be careful.
 
 	// NiGHTS stuff.
-	UINT8 numGradedMares;   ///< Internal. For grade support.
-	nightsgrades_t *grades; ///< NiGHTS grades. Allocated dynamically for space reasons. Be careful.
+	UINT8 numGradedMares;       ///< Internal. For grade support.
+	nightsgrades_t *grades;     ///< NiGHTS grades. Allocated dynamically for space reasons. Be careful.
 
 	// Music stuff.
-	UINT32 musinterfadeout;  ///< Fade out level music on intermission screen in milliseconds
-	char musintername[7];    ///< Intermission screen music.
+	UINT32 musinterfadeout;     ///< Fade out level music on intermission screen in milliseconds
+	char musintername[7];       ///< Intermission screen music.
 
 	char muspostbossname[7];    ///< Post-bossdeath music.
 	UINT16 muspostbosstrack;    ///< Post-bossdeath track.
 	UINT32 muspostbosspos;      ///< Post-bossdeath position
 	UINT32 muspostbossfadein;   ///< Post-bossdeath fade-in milliseconds.
 
-	SINT8 musforcereset; ///< Force resetmusic (-1 for default; 0 for force off; 1 for force on)
+	SINT8 musforcereset;        ///< Force resetmusic (-1 for default; 0 for force off; 1 for force on)
 
 	// Lua stuff.
 	// (This is not ifdeffed so the map header structure can stay identical, just in case.)
@@ -638,6 +638,7 @@ extern boolean singletics;
 
 extern consvar_t cv_timetic; // display high resolution timer
 extern consvar_t cv_powerupdisplay; // display powerups
+extern consvar_t cv_showinput; // display input viewer outside of time attack
 extern consvar_t cv_showinputjoy; // display joystick in time attack
 extern consvar_t cv_forceskin; // force clients to use the server's skin
 extern consvar_t cv_downloading; // allow clients to downloading WADs.
diff --git a/src/f_finale.c b/src/f_finale.c
index 0b618a1e3f53acd74a01b82116bd60eb698fec14..c221ed52ffd3643d835848f98f30abc232c3b7da 100644
--- a/src/f_finale.c
+++ b/src/f_finale.c
@@ -4387,11 +4387,10 @@ void F_GetPromptPageByNamedTag(const char *tag, INT32 *promptnum, INT32 *pagenum
 	if (!tag || !tag[0])
 		return;
 
-	strncpy(suffixedtag, tag, 33);
-	suffixedtag[32] = 0;
+	strncpy(suffixedtag, tag, sizeof(suffixedtag)-1);
 
 	if (tutorialmode)
-		suffixed = F_GetTextPromptTutorialTag(suffixedtag, 33);
+		suffixed = F_GetTextPromptTutorialTag(suffixedtag, sizeof(suffixedtag)-1);
 
 	for (*promptnum = 0 + tutorialpromptnum; *promptnum < MAX_PROMPTS; (*promptnum)++)
 	{
diff --git a/src/f_finale.h b/src/f_finale.h
index cb71775d05fc109aa4c3468c19cfe381eff72635..4b777eb11fe45e65b6df4a81a24d47955763551b 100644
--- a/src/f_finale.h
+++ b/src/f_finale.h
@@ -96,7 +96,7 @@ typedef enum
 extern ttmode_enum ttmode;
 extern UINT8 ttscale;
 // ttmode user vars
-extern char ttname[9];
+extern char ttname[8+1];
 extern INT16 ttx;
 extern INT16 tty;
 extern INT16 ttloop;
diff --git a/src/g_demo.c b/src/g_demo.c
index 78b2242d4b51f63cc0b414dda04f2d7166b2dfff..05ee577884ae82c160857142165d29fb236b39f5 100644
--- a/src/g_demo.c
+++ b/src/g_demo.c
@@ -1650,7 +1650,7 @@ static void G_LoadDemoExtraFiles(UINT8 **pp, UINT16 this_demo_version)
 	UINT16 totalfiles;
 	char filename[MAX_WADPATH];
 	UINT8 md5sum[16];
-	filestatus_t ncs;
+	filestatus_t ncs = FS_NOTFOUND;
 	boolean toomany = false;
 	boolean alreadyloaded;
 	UINT16 i, j;
diff --git a/src/g_game.c b/src/g_game.c
index 6a99381e741544030ad9208f93860ffbc0f249d6..0e7e2b344e9d08b78df1246d5af45cc8e26696f5 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -5403,7 +5403,7 @@ void G_FreeMapSearch(mapsearchfreq_t *freq, INT32 freqc)
 INT32 G_FindMapByNameOrCode(const char *mapname, char **realmapnamep)
 {
 	boolean usemapcode = false;
-	INT32 newmapnum;
+	INT32 newmapnum = -1;
 	size_t mapnamelen = strlen(mapname);
 	char *p;
 
diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c
index acd09f614318f433567a5764f2cf453d26315e9d..75a92c2fb33ad542b0931786a9b4688a9f9dccbc 100644
--- a/src/hardware/r_opengl/r_opengl.c
+++ b/src/hardware/r_opengl/r_opengl.c
@@ -180,7 +180,7 @@ FUNCPRINTF void GL_DBG_Printf(const char *format, ...)
 // GL_MSG_Warning   : Raises a warning.
 // -----------------+
 
-static void GL_MSG_Warning(const char *format, ...)
+FUNCPRINTF static void GL_MSG_Warning(const char *format, ...)
 {
 	char str[4096] = "";
 	va_list arglist;
@@ -203,7 +203,7 @@ static void GL_MSG_Warning(const char *format, ...)
 // GL_MSG_Error     : Raises an error.
 // -----------------+
 
-static void GL_MSG_Error(const char *format, ...)
+FUNCPRINTF static void GL_MSG_Error(const char *format, ...)
 {
 	char str[4096] = "";
 	va_list arglist;
diff --git a/src/hu_stuff.c b/src/hu_stuff.c
index c9744e5980da341af12eea3e7620808195395377..13d499495535c4320aee7a498154cbfec9c256c2 100644
--- a/src/hu_stuff.c
+++ b/src/hu_stuff.c
@@ -465,9 +465,12 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags)
 	numwords = COM_Argc() - usedargs;
 	I_Assert(numwords > 0);
 
-	if (CHAT_MUTE) // TODO: Per Player mute.
+	if (CHAT_MUTE)
 	{
-		HU_AddChatText(va("%s>ERROR: The chat is muted. You can't say anything.", "\x85"), false);
+		if (cv_mute.value)
+			HU_AddChatText(va("%s>ERROR: The chat is muted. You can't say anything.", "\x85"), false);
+		else
+			HU_AddChatText(va("%s>ERROR: You have been muted. You can't say anything.", "\x85"), false);
 		return;
 	}
 
@@ -496,10 +499,10 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags)
 		// what we're gonna do now is check if the player exists
 		// with that logic, characters 4 and 5 are our numbers:
 		const char *newmsg;
-		char playernum[3];
+		char playernum[3+1];
 		INT32 spc = 1; // used if playernum[1] is a space.
 
-		strncpy(playernum, msg+3, 3);
+		strncpy(playernum, msg+3, sizeof(playernum)-1);
 		// check for undesirable characters in our "number"
 		if (((playernum[0] < '0') || (playernum[0] > '9')) || ((playernum[1] < '0') || (playernum[1] > '9')))
 		{
@@ -644,9 +647,9 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
 	msg = (char *)*p;
 	SKIPSTRINGL(*p, HU_MAXMSGLEN + 1);
 
-	if ((cv_mute.value || flags & (HU_CSAY|HU_SERVER_SAY)) && playernum != serverplayer && !(IsPlayerAdmin(playernum)))
+	if ((cv_mute.value || players[playernum].muted || flags & (HU_CSAY|HU_SERVER_SAY)) && playernum != serverplayer && !(IsPlayerAdmin(playernum)))
 	{
-		CONS_Alert(CONS_WARNING, cv_mute.value ?
+		CONS_Alert(CONS_WARNING, (cv_mute.value || players[playernum].muted) ?
 			M_GetText("Illegal say command received from %s while muted\n") : M_GetText("Illegal csay command received from non-admin %s\n"),
 			player_names[playernum]);
 		if (server)
@@ -962,14 +965,17 @@ static void HU_sendChatMessage(void)
 	// last minute mute check
 	if (CHAT_MUTE)
 	{
-		HU_AddChatText(va("%s>ERROR: The chat is muted. You can't say anything.", "\x85"), false);
+		if (cv_mute.value)
+			HU_AddChatText(va("%s>ERROR: The chat is muted. You can't say anything.", "\x85"), false);
+		else
+			HU_AddChatText(va("%s>ERROR: You have been muted. You can't say anything.", "\x85"), false);
 		return;
 	}
 
 	if (strlen(msg) > 4 && strnicmp(msg, "/pm", 3) == 0) // used /pm
 	{
 		INT32 spc = 1; // used if playernum[1] is a space.
-		char playernum[3];
+		char playernum[3+1];
 		const char *newmsg;
 
 		// what we're gonna do now is check if the player exists
@@ -982,7 +988,7 @@ static void HU_sendChatMessage(void)
 			return;
 		}
 
-		strncpy(playernum, msg+3, 3);
+		strncpy(playernum, msg+3, sizeof(playernum)-1);
 		// check for undesirable characters in our "number"
 		if (!(isdigit(playernum[0]) && isdigit(playernum[1])))
 		{
@@ -1567,7 +1573,6 @@ static void HU_DrawChat(void)
 	INT32 cflag = 0;
 	const char *ntalk = "Say: ", *ttalk = "Team: ";
 	const char *talk = ntalk;
-	const char *mute = "Chat has been muted.";
 
 #ifdef NETSPLITSCREEN
 	if (splitscreen)
@@ -1594,7 +1599,10 @@ static void HU_DrawChat(void)
 
 	if (CHAT_MUTE)
 	{
-		talk = mute;
+		if (cv_mute.value)
+			talk = "Chat has been muted.";
+		else
+			talk = "You have been muted.";
 		typelines = 1;
 		cflag = V_GRAYMAP; // set text in gray if chat is muted.
 	}
@@ -1679,13 +1687,14 @@ static void HU_DrawChat(void)
 			// filter: (code needs optimization pls help I'm bad with C)
 			if (w_chat[3])
 			{
-				char playernum[3];
+				char playernum[3+1];
 				UINT32 n;
 				// right, that's half important: (w_chat[4] may be a space since /pm0 msg is perfectly acceptable!)
 				if ( ( ((w_chat[3] != 0) && ((w_chat[3] < '0') || (w_chat[3] > '9'))) || ((w_chat[4] != 0) && (((w_chat[4] < '0') || (w_chat[4] > '9'))))) && (w_chat[4] != ' '))
 					break;
 
-				strncpy(playernum, w_chat+3, 3);
+				strncpy(playernum, w_chat+3, sizeof(playernum)-1);
+				playernum[3] = 0;
 				n = atoi(playernum); // turn that into a number
 				// special cases:
 
@@ -2982,7 +2991,7 @@ void HU_DoCEcho(const char *msg)
 {
 	I_OutputMsg("%s\n", msg); // print to log
 
-	strncpy(cechotext, msg, sizeof(cechotext));
+	strncpy(cechotext, msg, sizeof(cechotext)-1);
 	strncat(cechotext, "\\", sizeof(cechotext) - strlen(cechotext) - 1);
 	cechotext[sizeof(cechotext) - 1] = '\0';
 	cechotimer = cechoduration;
diff --git a/src/hu_stuff.h b/src/hu_stuff.h
index b3069c215f1d6f7e09d471c9393c7b250057d942..9ca50e6e1b49e2b0f45b4e5d71a1fe70641693ca 100644
--- a/src/hu_stuff.h
+++ b/src/hu_stuff.h
@@ -69,8 +69,8 @@ typedef struct
 #else
 #define OLDCHAT (cv_consolechat.value == 1 || dedicated || vid.width < 640 || splitscreen)
 #endif
-#define CHAT_MUTE (cv_mute.value && !(server || IsPlayerAdmin(consoleplayer)))	// this still allows to open the chat but not to type. That's used for scrolling and whatnot.
-#define OLD_MUTE (OLDCHAT && cv_mute.value && !(server || IsPlayerAdmin(consoleplayer)))	// this is used to prevent oldchat from opening when muted.
+#define CHAT_MUTE ((cv_mute.value || players[consoleplayer].muted) && !(server || IsPlayerAdmin(consoleplayer)))	// this still allows to open the chat but not to type. That's used for scrolling and whatnot.
+#define OLD_MUTE (OLDCHAT && (cv_mute.value || players[consoleplayer].muted) && !(server || IsPlayerAdmin(consoleplayer)))	// this is used to prevent oldchat from opening when muted.
 
 // some functions
 void HU_AddChatText(const char *text, boolean playsound);
diff --git a/src/info.c b/src/info.c
index 9f8c2b8115169d5da5ce4e98f4ec12bba22966ae..8dd1aac80679d17ae21b0fe43ad6b042d35ed627 100644
--- a/src/info.c
+++ b/src/info.c
@@ -648,13 +648,13 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = {
 
 	0, // SPR2_TRNS,
 
-	FF_SPR2SUPER|SPR2_STND, // SPR2_NSTD,
-	FF_SPR2SUPER|SPR2_FALL, // SPR2_NFLT,
+	SPR2_STND, // SPR2_NSTD,
+	SPR2_FALL, // SPR2_NFLT,
 	0, // SPR2_NFLY, (will never be referenced unless skin 0 lacks this)
 	SPR2_NFLY, // SPR2_NDRL,
-	FF_SPR2SUPER|SPR2_STUN, // SPR2_NSTN,
+	SPR2_STUN, // SPR2_NSTN,
 	SPR2_NSTN, // SPR2_NPUL,
-	FF_SPR2SUPER|SPR2_ROLL, // SPR2_NATK,
+	SPR2_ROLL, // SPR2_NATK,
 
 	0, // SPR2_TAL0, (this will look mighty stupid but oh well)
 	SPR2_TAL0, // SPR2_TAL1,
diff --git a/src/lua_hud.h b/src/lua_hud.h
index ba102f2f4a13d6c1606e71b08b0198cd742d212b..36ce230ed2a384a73e1f988c41ef79d6d91986a5 100644
--- a/src/lua_hud.h
+++ b/src/lua_hud.h
@@ -19,11 +19,13 @@ enum hud {
 	hud_stagetitle = 0,
 	hud_textspectator,
 	hud_crosshair,
+	hud_powerups,
 	// Singleplayer / Co-op
 	hud_score,
 	hud_time,
 	hud_rings,
 	hud_lives,
+	hud_input,
 	// Match / CTF / Tag / Ringslinger
 	hud_weaponrings,
 	hud_powerstones,
diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c
index 52a875e50c0c550f2c10dbb1acd56647955baf01..d665212636530ee8e5610d2175510a2bc7d97444 100644
--- a/src/lua_hudlib.c
+++ b/src/lua_hudlib.c
@@ -41,6 +41,7 @@ static const char *const hud_disable_options[] = {
 	"stagetitle",
 	"textspectator",
 	"crosshair",
+	"powerups",
 
 	"score",
 	"time",
diff --git a/src/m_cheat.c b/src/m_cheat.c
index 36438a47575ab2028223245096424ad04b398119..07f10071711025f93f91d7b7ea2d9d65f3d5ad1d 100644
--- a/src/m_cheat.c
+++ b/src/m_cheat.c
@@ -1432,14 +1432,22 @@ void OP_ObjectplaceMovement(player_t *player)
 //
 // Objectplace related commands.
 //
-/*void Command_Writethings_f(void)
+void Command_Writethings_f(void)
 {
 	REQUIRE_INLEVEL;
 	REQUIRE_SINGLEPLAYER;
 	REQUIRE_OBJECTPLACE;
 
-	P_WriteThings();
-}*/
+	if (COM_Argc() > 1)
+	{
+		P_WriteThings(COM_Argv(1));
+	}
+	else
+	{
+		CONS_Printf(M_GetText("writethings <filename>: write out map things to a file, .txt or .lmp automatically appended.\n"));
+		return;
+	}
+}
 
 void Command_ObjectPlace_f(void)
 {
diff --git a/src/m_cheat.h b/src/m_cheat.h
index f4ac01d842eba583da08a2d1634bd09ad11f1b84..564c6da77ff7e0761faaff529ac4ed7a87ff3734 100644
--- a/src/m_cheat.h
+++ b/src/m_cheat.h
@@ -26,7 +26,7 @@ void cht_Init(void);
 // ObjectPlace
 //
 void Command_ObjectPlace_f(void);
-//void Command_Writethings_f(void);
+void Command_Writethings_f(void);
 
 extern consvar_t cv_opflags, cv_ophoopflags, cv_mapthingnum, cv_speed;
 //extern consvar_t cv_snapto, cv_grid;
diff --git a/src/m_menu.c b/src/m_menu.c
index fcde0d148212d848f6270b723823d2d9cd8f7c93..0f6f427cf293e66ca7271bb9b384ca2b34b02b4c 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -2692,7 +2692,7 @@ static boolean MIT_SetCurTitlePics(UINT32 menutype, INT32 level, INT32 *retval,
 			curhidepics = menupres[menutype].hidetitlepics;
 			curttmode = menupres[menutype].ttmode;
 			curttscale = (menupres[menutype].ttscale != UINT8_MAX ? menupres[menutype].ttscale : ttscale);
-			strncpy(curttname, menupres[menutype].ttname, 9);
+			strncpy(curttname, menupres[menutype].ttname, sizeof(curttname)-1);
 			curttx = (menupres[menutype].ttx != INT16_MAX ? menupres[menutype].ttx : ttx);
 			curtty = (menupres[menutype].tty != INT16_MAX ? menupres[menutype].tty : tty);
 			curttloop = (menupres[menutype].ttloop != INT16_MAX ? menupres[menutype].ttloop : ttloop);
@@ -11235,7 +11235,8 @@ static void M_DrawRoomMenu(void)
 			if (dot_frame < 0)
 				dot_frame = 0;
 
-			strncpy(&text[dot_frame], "...", min(dots, 3 - dot_frame));
+			if (dot_frame != 3)
+				strncpy(&text[dot_frame], "...", min(dots, 3 - dot_frame));
 		}
 
 		frame += renderdeltatics;
diff --git a/src/m_menu.h b/src/m_menu.h
index 3cd2f66d37c78a2c6d7c6e14ff4e48c3f9cc56ec..99a5b6de4266be02b1cba0e98a26addac5524548 100644
--- a/src/m_menu.h
+++ b/src/m_menu.h
@@ -378,7 +378,7 @@ typedef struct
 	char displayname[SKINNAMESIZE+1];
 	INT16 skinnum[2];
 	UINT16 oppositecolor;
-	char nametag[8];
+	char nametag[8+1];
 	patch_t *namepic;
 	UINT16 tagtextcolor;
 	UINT16 tagoutlinecolor;
diff --git a/src/netcode/client_connection.c b/src/netcode/client_connection.c
index 36ed718265b3cfa42acc3ef238c436882bb918a1..917e32b598e03d86f8540b997329069f279817fb 100644
--- a/src/netcode/client_connection.c
+++ b/src/netcode/client_connection.c
@@ -307,7 +307,7 @@ boolean CL_SendJoin(void)
 	else
 		player2name = cv_playername2.zstring;
 
-	strncpy(netbuffer->u.clientcfg.names[0], cv_playername.zstring, MAXPLAYERNAME);
+	strncpy(netbuffer->u.clientcfg.names[0], cv_playername.zstring, sizeof(netbuffer->u.clientcfg.names[0])-1);
 	strncpy(netbuffer->u.clientcfg.names[1], player2name, MAXPLAYERNAME);
 
 	return HSendPacket(servernode, true, 0, sizeof (clientconfig_pak));
diff --git a/src/netcode/commands.c b/src/netcode/commands.c
index 46dfbc741d9c8f036bf53e0ba6d77bed60ac39f3..f3bbc8a8616224b65a481559bd96eccbb3577f5e 100644
--- a/src/netcode/commands.c
+++ b/src/netcode/commands.c
@@ -41,6 +41,8 @@ typedef struct banreason_s
 static banreason_t *reasontail = NULL; //last entry, use prev
 static banreason_t *reasonhead = NULL; //1st entry, use next
 
+static boolean bans_loaded = false;
+
 void Ban_Add(const char *reason)
 {
 	banreason_t *reasonlist = malloc(sizeof(*reasonlist));
@@ -85,6 +87,8 @@ void Ban_Load_File(boolean warning)
 	if (!I_ClearBans)
 		return;
 
+	bans_loaded = true;
+
 	f = fopen(va("%s"PATHSEP"%s", srb2home, "ban.txt"), "r");
 
 	if (!f)
@@ -124,6 +128,12 @@ void D_SaveBan(void)
 	const char *address, *mask;
 	const char *path = va("%s"PATHSEP"%s", srb2home, "ban.txt");
 
+	if (!bans_loaded)
+	{
+		// don't save bans if they were never loaded.
+		return;
+	}
+
 	if (!reasonhead)
 	{
 		remove(path);
diff --git a/src/netcode/d_net.c b/src/netcode/d_net.c
index 5a2e229d3f47c9eadf66729a1250a1d2b0719343..b24409db158909970a73fb5bd7630500a4f3d63f 100644
--- a/src/netcode/d_net.c
+++ b/src/netcode/d_net.c
@@ -940,7 +940,7 @@ void Command_Droprate(void)
 static boolean ShouldDropPacket(void)
 {
 	return (packetdropquantity[netbuffer->packettype])
-		|| (packetdroprate != 0 && rand() < (RAND_MAX * (packetdroprate / 100.f))) || packetdroprate == 100;
+		|| (packetdroprate != 0 && rand() < (((double)RAND_MAX) * (packetdroprate / 100.f))) || packetdroprate == 100;
 }
 #endif
 
diff --git a/src/netcode/d_netcmd.c b/src/netcode/d_netcmd.c
index 6bdcaa650f3b703082aa9fd4255b7d1aed7dc15e..760833b7977e7c5b009e84de859ddfae835f0fe3 100644
--- a/src/netcode/d_netcmd.c
+++ b/src/netcode/d_netcmd.c
@@ -149,6 +149,10 @@ static void Command_Teamchange_f(void);
 static void Command_Teamchange2_f(void);
 static void Command_ServerTeamChange_f(void);
 
+static void Command_MutePlayer_f(void);
+static void Command_UnmutePlayer_f(void);
+static void Got_MutePlayer(UINT8 **cp, INT32 playernum);
+
 static void Command_Clearscores_f(void);
 
 // Remote Administration
@@ -209,6 +213,7 @@ static CV_PossibleValue_t matchboxes_cons_t[] = {{0, "Normal"}, {1, "Mystery"},
 static CV_PossibleValue_t chances_cons_t[] = {{0, "MIN"}, {9, "MAX"}, {0, NULL}};
 static CV_PossibleValue_t pause_cons_t[] = {{0, "Server"}, {1, "All"}, {0, NULL}};
 
+consvar_t cv_showinput = CVAR_INIT ("showinput", "Off", CV_ALLOWLUA, CV_OnOff, NULL);
 consvar_t cv_showinputjoy = CVAR_INIT ("showinputjoy", "Off", CV_ALLOWLUA, CV_OnOff, NULL);
 
 #ifdef NETGAME_DEVMODE
@@ -487,6 +492,10 @@ void D_RegisterServerCommands(void)
 	RegisterNetXCmd(XD_TEAMCHANGE, Got_Teamchange);
 	COM_AddCommand("serverchangeteam", Command_ServerTeamChange_f, COM_LUA);
 
+	RegisterNetXCmd(XD_MUTEPLAYER, Got_MutePlayer);
+	COM_AddCommand("muteplayer", Command_MutePlayer_f, COM_LUA);
+	COM_AddCommand("unmuteplayer", Command_UnmutePlayer_f, COM_LUA);
+
 	RegisterNetXCmd(XD_CLEARSCORES, Got_Clearscores);
 	COM_AddCommand("clearscores", Command_Clearscores_f, COM_LUA);
 	COM_AddCommand("map", Command_Map_f, COM_LUA);
@@ -736,6 +745,7 @@ void D_RegisterClientCommands(void)
 	CV_RegisterVar(&cv_timetic);
 	CV_RegisterVar(&cv_powerupdisplay);
 	CV_RegisterVar(&cv_itemfinder);
+	CV_RegisterVar(&cv_showinput);
 	CV_RegisterVar(&cv_showinputjoy);
 
 	// time attack ghost options are also saved to config
@@ -911,7 +921,7 @@ void D_RegisterClientCommands(void)
 
 	// ingame object placing
 	COM_AddCommand("objectplace", Command_ObjectPlace_f, COM_LUA);
-	//COM_AddCommand("writethings", Command_Writethings_f);
+	COM_AddCommand("writethings", Command_Writethings_f, COM_LUA);
 	CV_RegisterVar(&cv_speed);
 	CV_RegisterVar(&cv_opflags);
 	CV_RegisterVar(&cv_ophoopflags);
@@ -1313,7 +1323,7 @@ static void SendNameAndColor(void)
 		CV_StealthSet(&cv_playername, player_names[consoleplayer]);
 		HU_AddChatText("\x85*You must wait to change your name again", false);
 	}
-	else if (cv_mute.value && !(server || IsPlayerAdmin(consoleplayer)))
+	else if ((cv_mute.value || players[consoleplayer].muted) && !(server || IsPlayerAdmin(consoleplayer)))
 		CV_StealthSet(&cv_playername, player_names[consoleplayer]);
 	else // Cleanup name if changing it
 		CleanupPlayerName(consoleplayer, cv_playername.zstring);
@@ -2488,6 +2498,91 @@ static void Command_Teamchange2_f(void)
 	SendNetXCmd2(XD_TEAMCHANGE, &usvalue, sizeof(usvalue));
 }
 
+static void MutePlayer(boolean mute)
+{
+	UINT8 data[2];
+	if (!(server || (IsPlayerAdmin(consoleplayer))))
+	{
+		CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n"));
+		return;
+	}
+
+	if (COM_Argc() < 2)
+	{
+		CONS_Printf(M_GetText("muteplayer <playernum>: mute a player\n"));
+		return;
+	}
+
+	data[0] = atoi(COM_Argv(1));
+	if (data[0] >= MAXPLAYERS || !playeringame[data[0]])
+	{
+		CONS_Alert(CONS_NOTICE, M_GetText("There is no player %u!\n"), (unsigned int)data[0]);
+		return;
+	}
+
+	if (players[data[0]].muted && mute)
+	{
+		CONS_Printf(M_GetText("%s is already muted!\n"), player_names[data[0]]);
+		return;
+	}
+	else if (!players[data[0]].muted && !mute)
+	{
+		CONS_Printf(M_GetText("%s is not muted!\n"), player_names[data[0]]);
+		return;
+	}
+
+	data[1] = mute;
+	SendNetXCmd(XD_MUTEPLAYER, &data, sizeof(data));
+}
+
+static void Command_MutePlayer_f(void)
+{
+	MutePlayer(true);
+}
+
+static void Command_UnmutePlayer_f(void)
+{
+	MutePlayer(false);
+}
+
+static void Got_MutePlayer(UINT8 **cp, INT32 playernum)
+{
+	UINT8 player = READUINT8(*cp);
+	UINT8 muted = READUINT8(*cp);
+	if (playernum != serverplayer && !IsPlayerAdmin(playernum))
+	{
+		CONS_Alert(CONS_WARNING, M_GetText("Illegal mute received from player %s\n"), player_names[playernum]);
+		if (server)
+			SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
+		return;
+	}
+
+	if (player >= MAXPLAYERS || !playeringame[player])
+	{
+		CONS_Alert(CONS_WARNING, M_GetText("Illegal mute received from player %s\n"), player_names[playernum]);
+		if (server)
+			SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
+		return;
+	}
+
+	if (!players[player].muted && muted)
+	{
+		if (player == consoleplayer)
+			CONS_Printf(M_GetText("You have been muted.\n"));
+		else
+			CONS_Printf(M_GetText("%s has been muted.\n"), player_names[player]);
+	}
+	else if (players[player].muted && !muted)
+	{
+		if (player == consoleplayer)
+			CONS_Printf(M_GetText("You are no longer muted.\n"));
+		else
+			CONS_Printf(M_GetText("%s is no longer muted.\n"), player_names[player]);
+	}
+
+	players[player].muted = muted;
+}
+
 static void Command_ServerTeamChange_f(void)
 {
 	changeteam_union NetPacket;
@@ -4785,7 +4880,7 @@ static void ForceSkin_OnChange(void)
 //Allows the player's name to be changed if cv_mute is off.
 static void Name_OnChange(void)
 {
-	if (cv_mute.value && !(server || IsPlayerAdmin(consoleplayer)))
+	if ((cv_mute.value || players[consoleplayer].muted) && !(server || IsPlayerAdmin(consoleplayer)))
 	{
 		CONS_Alert(CONS_NOTICE, M_GetText("You may not change your name when chat is muted.\n"));
 		CV_StealthSet(&cv_playername, player_names[consoleplayer]);
@@ -4796,7 +4891,7 @@ static void Name_OnChange(void)
 
 static void Name2_OnChange(void)
 {
-	if (cv_mute.value) //Secondary player can't be admin.
+	if (cv_mute.value || players[consoleplayer].muted) //Secondary player can't be admin.
 	{
 		CONS_Alert(CONS_NOTICE, M_GetText("You may not change your name when chat is muted.\n"));
 		CV_StealthSet(&cv_playername2, player_names[secondarydisplayplayer]);
diff --git a/src/netcode/d_netcmd.h b/src/netcode/d_netcmd.h
index e30fa4a0245b1dd2b54617b1f7df4f3700c75188..de7097f7e4b872efbef924537712a52eaa8f3182 100644
--- a/src/netcode/d_netcmd.h
+++ b/src/netcode/d_netcmd.h
@@ -147,6 +147,7 @@ typedef enum
 	XD_LUACMD,      // 22
 	XD_LUAVAR,      // 23
 	XD_LUAFILE,     // 24
+	XD_MUTEPLAYER,  // 25
 	MAXNETXCMD
 } netxcmd_t;
 
diff --git a/src/netcode/http-mserv.c b/src/netcode/http-mserv.c
index 2b52380cf506f00f119dc01b5f0ab3b47ff4e6f6..b8c662a51e215965470310d758331236359378b7 100644
--- a/src/netcode/http-mserv.c
+++ b/src/netcode/http-mserv.c
@@ -134,7 +134,7 @@ HMS_on_read (char *s, size_t _1, size_t n, void *userdata)
 	return n;
 }
 
-static struct HMS_buffer *
+FUNCDEBUG static struct HMS_buffer *
 HMS_connect (int proto, const char *format, ...)
 {
 	va_list ap;
diff --git a/src/netcode/server_connection.c b/src/netcode/server_connection.c
index bbabc8f1dc9a5d82030159a281c2ffae137d1054..f4601e4acac08a187b982f8e286e9e53d46b2396 100644
--- a/src/netcode/server_connection.c
+++ b/src/netcode/server_connection.c
@@ -115,12 +115,12 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime)
 	netbuffer->u.serverinfo.refusereason = GetRefuseReason(node);
 
 	strncpy(netbuffer->u.serverinfo.gametypename, Gametype_Names[gametype],
-			sizeof netbuffer->u.serverinfo.gametypename);
+			sizeof(netbuffer->u.serverinfo.gametypename)-1);
 	netbuffer->u.serverinfo.modifiedgame = (UINT8)modifiedgame;
 	netbuffer->u.serverinfo.cheatsenabled = CV_CheatsEnabled();
 	netbuffer->u.serverinfo.flags = (dedicated ? SV_DEDICATED : 0);
 	strncpy(netbuffer->u.serverinfo.servername, cv_servername.string,
-		MAXSERVERNAME);
+		sizeof(netbuffer->u.serverinfo.servername)-1);
 	strncpy(netbuffer->u.serverinfo.mapname, G_BuildMapName(gamemap), 7);
 
 	M_Memcpy(netbuffer->u.serverinfo.mapmd5, mapmd5, 16);
@@ -184,7 +184,9 @@ static void SV_SendPlayerInfo(INT32 node)
 		}
 
 		netbuffer->u.playerinfo[i].num = i;
-		strncpy(netbuffer->u.playerinfo[i].name, (const char *)&player_names[i], MAXPLAYERNAME+1);
+		memset(netbuffer->u.playerinfo[i].name, 0x00, sizeof(netbuffer->u.playerinfo[i].name));
+		memcpy(netbuffer->u.playerinfo[i].name, player_names[i], sizeof(player_names[i]));
+
 		netbuffer->u.playerinfo[i].name[MAXPLAYERNAME] = '\0';
 
 		//fetch IP address
diff --git a/src/p_mobj.c b/src/p_mobj.c
index 518c731da16c35ded6f89f7a542e4df1897be543..55be8e54fc4e36684e20279ac134d7de4772780f 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -402,9 +402,9 @@ static boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
 				UINT16 stateframe = st->frame;
 
 				// Add/Remove FF_SPR2SUPER based on certain conditions
-				if (player->charflags & SF_NOSUPERSPRITES)
+				if (player->charflags & SF_NOSUPERSPRITES || (player->powers[pw_carry] == CR_NIGHTSMODE && (player->charflags & SF_NONIGHTSSUPER)))
 					stateframe = stateframe & ~FF_SPR2SUPER;
-				else if (player->powers[pw_super])
+				else if (player->powers[pw_super] || (player->powers[pw_carry] == CR_NIGHTSMODE && (player->charflags & SF_SUPER)))
 					stateframe = stateframe | FF_SPR2SUPER;
 
 				if (stateframe & FF_SPR2SUPER)
diff --git a/src/p_saveg.c b/src/p_saveg.c
index 6c6548c567f195cfc7bbc884e1e45dea18afde1a..c385bd8e1aff3a8b57b978e70ac1941878dcc764 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -170,6 +170,7 @@ static void P_NetArchivePlayers(void)
 		WRITEUINT8(save_p, players[i].panim);
 		WRITEUINT8(save_p, players[i].stronganim);
 		WRITEUINT8(save_p, players[i].spectator);
+		WRITEUINT8(save_p, players[i].muted);
 
 		WRITEUINT16(save_p, players[i].flashpal);
 		WRITEUINT16(save_p, players[i].flashcount);
@@ -399,6 +400,7 @@ static void P_NetUnArchivePlayers(void)
 		players[i].panim = READUINT8(save_p);
 		players[i].stronganim = READUINT8(save_p);
 		players[i].spectator = READUINT8(save_p);
+		players[i].muted = READUINT8(save_p);
 
 		players[i].flashpal = READUINT16(save_p);
 		players[i].flashcount = READUINT16(save_p);
diff --git a/src/p_setup.c b/src/p_setup.c
index 396639b7263e7801f8bc0b8ce0fc48213c153cff..1cb3ccd21a5bf246d224cc832d4d3208712fda2e 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -877,14 +877,32 @@ static void P_SpawnMapThings(boolean spawnemblems)
 		P_SpawnEmeraldHunt();
 }
 
+static void P_WriteTextmap_Things(FILE *f, const mapthing_t *wmapthings); // proto
+
 // Experimental groovy write function!
-/*void P_WriteThings(void)
+void P_WriteThings(const char *filepath)
 {
 	size_t i, length;
 	mapthing_t *mt;
 	UINT8 *savebuffer, *savebuf_p;
 	INT16 temp;
 
+	if (udmf)
+	{
+		FILE *f = fopen(va("%s.txt", filepath), "w");
+		if (!f)
+		{
+			CONS_Alert(CONS_ERROR, M_GetText("Couldn't write to file %s\n"), filepath);
+			return;
+		}
+
+		P_WriteTextmap_Things(f, mapthings);
+		fclose(f);
+
+		CONS_Printf(M_GetText("%s.txt saved.\n"), filepath);
+		return;
+	}
+
 	savebuf_p = savebuffer = (UINT8 *)malloc(nummapthings * sizeof (mapthing_t));
 
 	if (!savebuf_p)
@@ -908,12 +926,12 @@ static void P_SpawnMapThings(boolean spawnemblems)
 
 	length = savebuf_p - savebuffer;
 
-	FIL_WriteFile(va("newthings%d.lmp", gamemap), savebuffer, length);
+	FIL_WriteFile(va("%s.lmp", filepath), savebuffer, length);
 	free(savebuffer);
 	savebuf_p = NULL;
 
-	CONS_Printf(M_GetText("newthings%d.lmp saved.\n"), gamemap);
-}*/
+	CONS_Printf(M_GetText("%s.lmp saved.\n"), filepath);
+}
 
 //
 // MAP LOADING FUNCTIONS
@@ -2150,6 +2168,60 @@ typedef struct
 	mapthing_t *angleanchor;
 } sectorspecialthings_t;
 
+static void P_WriteTextmap_Things(FILE *f, const mapthing_t *wmapthings)
+{
+	size_t i, j;
+	mtag_t firsttag;
+
+	// Actual writing
+	for (i = 0; i < nummapthings; i++)
+	{
+		fprintf(f, "thing // %s\n", sizeu1(i));
+		fprintf(f, "{\n");
+		firsttag = Tag_FGet(&wmapthings[i].tags);
+		if (firsttag != 0)
+			fprintf(f, "id = %d;\n", firsttag);
+		if (wmapthings[i].tags.count > 1)
+		{
+			fprintf(f, "moreids = \"");
+			for (j = 1; j < wmapthings[i].tags.count; j++)
+			{
+				if (j > 1)
+					fprintf(f, " ");
+				fprintf(f, "%d", wmapthings[i].tags.tags[j]);
+			}
+			fprintf(f, "\";\n");
+		}
+		fprintf(f, "x = %d;\n", wmapthings[i].x);
+		fprintf(f, "y = %d;\n", wmapthings[i].y);
+		if (wmapthings[i].z != 0)
+			fprintf(f, "height = %d;\n", wmapthings[i].z);
+		fprintf(f, "angle = %d;\n", wmapthings[i].angle);
+		if (wmapthings[i].pitch != 0)
+			fprintf(f, "pitch = %d;\n", wmapthings[i].pitch);
+		if (wmapthings[i].roll != 0)
+			fprintf(f, "roll = %d;\n", wmapthings[i].roll);
+		if (wmapthings[i].type != 0)
+			fprintf(f, "type = %d;\n", wmapthings[i].type);
+		if (wmapthings[i].spritexscale != FRACUNIT)
+			fprintf(f, "scalex = %f;\n", FIXED_TO_FLOAT(wmapthings[i].spritexscale));
+		if (wmapthings[i].spriteyscale != FRACUNIT)
+			fprintf(f, "scaley = %f;\n", FIXED_TO_FLOAT(wmapthings[i].spriteyscale));
+		if (wmapthings[i].scale != FRACUNIT)
+			fprintf(f, "mobjscale = %f;\n", FIXED_TO_FLOAT(wmapthings[i].scale));
+		if (wmapthings[i].options & MTF_OBJECTFLIP)
+			fprintf(f, "flip = true;\n");
+		for (j = 0; j < NUMMAPTHINGARGS; j++)
+			if (wmapthings[i].args[j] != 0)
+				fprintf(f, "arg%s = %d;\n", sizeu1(j), wmapthings[i].args[j]);
+		for (j = 0; j < NUMMAPTHINGSTRINGARGS; j++)
+			if (mapthings[i].stringargs[j])
+				fprintf(f, "stringarg%s = \"%s\";\n", sizeu1(j), mapthings[i].stringargs[j]);
+		fprintf(f, "}\n");
+		fprintf(f, "\n");
+	}
+}
+
 static void P_WriteTextmap(void)
 {
 	size_t i, j;
@@ -2417,52 +2489,7 @@ static void P_WriteTextmap(void)
 	}
 
 	fprintf(f, "namespace = \"srb2\";\n");
-	for (i = 0; i < nummapthings; i++)
-	{
-		fprintf(f, "thing // %s\n", sizeu1(i));
-		fprintf(f, "{\n");
-		firsttag = Tag_FGet(&wmapthings[i].tags);
-		if (firsttag != 0)
-			fprintf(f, "id = %d;\n", firsttag);
-		if (wmapthings[i].tags.count > 1)
-		{
-			fprintf(f, "moreids = \"");
-			for (j = 1; j < wmapthings[i].tags.count; j++)
-			{
-				if (j > 1)
-					fprintf(f, " ");
-				fprintf(f, "%d", wmapthings[i].tags.tags[j]);
-			}
-			fprintf(f, "\";\n");
-		}
-		fprintf(f, "x = %d;\n", wmapthings[i].x);
-		fprintf(f, "y = %d;\n", wmapthings[i].y);
-		if (wmapthings[i].z != 0)
-			fprintf(f, "height = %d;\n", wmapthings[i].z);
-		fprintf(f, "angle = %d;\n", wmapthings[i].angle);
-		if (wmapthings[i].pitch != 0)
-			fprintf(f, "pitch = %d;\n", wmapthings[i].pitch);
-		if (wmapthings[i].roll != 0)
-			fprintf(f, "roll = %d;\n", wmapthings[i].roll);
-		if (wmapthings[i].type != 0)
-			fprintf(f, "type = %d;\n", wmapthings[i].type);
-		if (wmapthings[i].spritexscale != FRACUNIT)
-			fprintf(f, "scalex = %f;\n", FIXED_TO_FLOAT(wmapthings[i].spritexscale));
-		if (wmapthings[i].spriteyscale != FRACUNIT)
-			fprintf(f, "scaley = %f;\n", FIXED_TO_FLOAT(wmapthings[i].spriteyscale));
-		if (wmapthings[i].scale != FRACUNIT)
-			fprintf(f, "mobjscale = %f;\n", FIXED_TO_FLOAT(wmapthings[i].scale));
-		if (wmapthings[i].options & MTF_OBJECTFLIP)
-			fprintf(f, "flip = true;\n");
-		for (j = 0; j < NUMMAPTHINGARGS; j++)
-			if (wmapthings[i].args[j] != 0)
-				fprintf(f, "arg%s = %d;\n", sizeu1(j), wmapthings[i].args[j]);
-		for (j = 0; j < NUMMAPTHINGSTRINGARGS; j++)
-			if (mapthings[i].stringargs[j])
-				fprintf(f, "stringarg%s = \"%s\";\n", sizeu1(j), mapthings[i].stringargs[j]);
-		fprintf(f, "}\n");
-		fprintf(f, "\n");
-	}
+	P_WriteTextmap_Things(f, wmapthings);
 
 	for (i = 0; i < numvertexes; i++)
 	{
diff --git a/src/p_setup.h b/src/p_setup.h
index f9e51024d2dbcf55f61bd193d1e32edc278a31be..61c445c6523ba28a589c54364bd644e701282110 100644
--- a/src/p_setup.h
+++ b/src/p_setup.h
@@ -71,7 +71,7 @@ boolean P_AddFolder(const char *folderpath);
 boolean P_RunSOC(const char *socfilename);
 void P_LoadSoundsRange(UINT16 wadnum, UINT16 first, UINT16 num);
 void P_LoadMusicsRange(UINT16 wadnum, UINT16 first, UINT16 num);
-//void P_WriteThings(void);
+void P_WriteThings(const char *filepath);
 size_t P_PrecacheLevelFlats(void);
 void P_AllocMapHeader(INT16 i);
 
diff --git a/src/p_spec.c b/src/p_spec.c
index 572258165e00386a6f804b65a8fc8e561e0111e4..805817fb033c465b33059c24fbefb52432173444 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -363,7 +363,7 @@ void P_ParseAnimationDefintion(SINT8 istexture)
 		// Increase the size to make room for the new animation definition
 		maxanims++;
 		animdefs = (animdef_t *)Z_Realloc(animdefs, sizeof(animdef_t)*(maxanims + 1), PU_STATIC, NULL);
-		strncpy(animdefs[i].startname, animdefsToken, 9);
+		strncpy(animdefs[i].startname, animdefsToken, sizeof(animdefs[i].startname)-1);
 	}
 
 	// animdefs[i].startname is now set to animdefsToken either way.
diff --git a/src/p_user.c b/src/p_user.c
index b493e1b8b910a5447b2f1f8680e9e0cb5a80654e..b55a9376412b836ce933593108647ee707a17ff2 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -4965,7 +4965,7 @@ void P_DoJumpShield(player_t *player)
 	}
 	else
 	{
-		player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE);
+		player->pflags |= PF_NOJUMPDAMAGE;
 		P_SetMobjState(player->mo, S_PLAY_FALL);
 		S_StartSound(player->mo, sfx_wdjump);
 	}
@@ -11286,7 +11286,7 @@ void P_DoTailsOverlay(player_t *player, mobj_t *tails)
 	fixed_t backwards = -1*FRACUNIT;
 	boolean doswim = (player->panim == PA_ABILITY && (player->mo->eflags & MFE_UNDERWATER));
 	boolean doroll = (player->panim == PA_ROLL || (player->panim == PA_JUMP && !(player->charflags & SF_NOJUMPSPIN)) || doswim);
-	angle_t rollangle;
+	angle_t rollangle = 0;
 	boolean panimchange;
 	INT32 ticnum = 0;
 	statenum_t chosenstate;
@@ -12071,7 +12071,7 @@ void P_PlayerThink(player_t *player)
 	// deez New User eXperiences.
 	{
 		angle_t oldang = player->drawangle, diff = 0;
-		UINT8 factor;
+		UINT8 factor = 0;
 		// Directionchar!
 		// Camera angle stuff.
 		if (player->exiting // no control, no modification
@@ -13181,7 +13181,7 @@ void P_ForceLocalAngle(player_t *player, angle_t angle)
 boolean P_PlayerFullbright(player_t *player)
 {
 	return (player->powers[pw_super]
-		|| ((player->powers[pw_carry] == CR_NIGHTSMODE && (((skin_t *)player->mo->skin)->flags & (SF_SUPER|SF_NONIGHTSSUPER)) == SF_SUPER) // Super colours? Super bright!
+		|| ((player->powers[pw_carry] == CR_NIGHTSMODE && (player->charflags & (SF_SUPER|SF_NONIGHTSSUPER)) == SF_SUPER) // Super colours? Super bright!
 		&& (player->exiting
 			|| !(player->mo->state >= &states[S_PLAY_NIGHTS_TRANS1]
 			&& player->mo->state < &states[S_PLAY_NIGHTS_TRANS6])))); // Note the < instead of <=
diff --git a/src/r_segs.c b/src/r_segs.c
index 683844439a2a294f105a8460b37b51e510912fd4..56a62f10cf5eed0a12fbdc3b709205d7de3f3440 100644
--- a/src/r_segs.c
+++ b/src/r_segs.c
@@ -186,7 +186,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
 	if (frontsector->numlights)
 	{
 		dc_numlights = frontsector->numlights;
-		if (dc_numlights >= dc_maxlights)
+		if (dc_numlights > dc_maxlights)
 		{
 			dc_maxlights = dc_numlights;
 			dc_lightlist = Z_Realloc(dc_lightlist, sizeof (*dc_lightlist) * dc_maxlights, PU_STATIC, NULL);
@@ -342,7 +342,6 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
 			{
 				lighttable_t **xwalllights;
 
-				sprbotscreen = INT32_MAX;
 				sprtopscreen = windowtop = (centeryfrac - FixedMul(dc_texturemid, spryscale));
 
 				realbot = FixedMul(textureheight[texnum], spryscale) + sprtopscreen;
@@ -449,10 +448,13 @@ static void R_DrawRepeatMaskedColumn(column_t *col, unsigned lengthcol)
 
 static void R_DrawRepeatFlippedMaskedColumn(column_t *col, unsigned lengthcol)
 {
-	do {
+	while (sprtopscreen < sprbotscreen) {
 		R_DrawFlippedMaskedColumn(col, lengthcol);
-		sprtopscreen += dc_texheight*spryscale;
-	} while (sprtopscreen < sprbotscreen);
+		if ((INT64)sprtopscreen + (INT64)dc_texheight*spryscale > (INT64)INT32_MAX) // prevent overflow
+			sprtopscreen = INT32_MAX;
+		else
+			sprtopscreen += dc_texheight*spryscale;
+	}
 }
 
 // Returns true if a fake floor is translucent.
@@ -742,7 +744,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 	if (textures[texnum]->flip & 2) // vertically flipped?
 		colfunc_2s = R_DrawRepeatFlippedMaskedColumn;
 	else
-		colfunc_2s = R_DrawRepeatMaskedColumn; // render the usual 2sided single-patch packed texture
+		colfunc_2s = R_DrawRepeatMaskedColumn;
 
 	lengthcol = textures[texnum]->height;
 
@@ -787,6 +789,8 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 		else if (bottom_frac > (INT64)CLAMPMIN) sprbotscreen = windowbottom = (fixed_t)bottom_frac;
 		else                                    sprbotscreen = windowbottom = CLAMPMIN;
 
+		fixed_t bottomclip = sprbotscreen;
+
 		top_frac += top_step;
 		bottom_frac += bottom_step;
 
@@ -819,14 +823,13 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 			lighttable_t **xwalllights;
 			fixed_t height;
 			fixed_t bheight = 0;
-			INT32 solid = 0;
-			INT32 lighteffect = 0;
+			boolean lighteffect = false;
 
 			for (i = 0; i < dc_numlights; i++)
 			{
 				// Check if the current light effects the colormap/lightlevel
 				rlight = &dc_lightlist[i];
-				lighteffect = !(dc_lightlist[i].flags & FOF_NOSHADE);
+				lighteffect = !(rlight->flags & FOF_NOSHADE);
 				if (lighteffect)
 				{
 					lightnum = rlight->lightnum;
@@ -859,11 +862,11 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 					}
 				}
 
-				solid = 0; // don't carry over solid-cutting flag from the previous light
-
 				// Check if the current light can cut the current 3D floor.
+				boolean solid = false;
+
 				if (rlight->flags & FOF_CUTSOLIDS && !(pfloor->fofflags & FOF_EXTRA))
-					solid = 1;
+					solid = true;
 				else if (rlight->flags & FOF_CUTEXTRA && pfloor->fofflags & FOF_EXTRA)
 				{
 					if (rlight->flags & FOF_EXTRA)
@@ -871,13 +874,13 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 						// The light is from an extra 3D floor... Check the flags so
 						// there are no undesired cuts.
 						if ((rlight->flags & (FOF_FOG|FOF_SWIMMABLE)) == (pfloor->fofflags & (FOF_FOG|FOF_SWIMMABLE)))
-							solid = 1;
+							solid = true;
 					}
 					else
-						solid = 1;
+						solid = true;
 				}
 				else
-					solid = 0;
+					solid = false;
 
 				height = rlight->height;
 				rlight->height += rlight->heightstep;
@@ -893,14 +896,14 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 					if (lighteffect)
 						dc_colormap = rlight->rcolormap;
 					if (solid && windowtop < bheight)
-						windowtop = bheight;
+						sprtopscreen = windowtop = bheight;
 					continue;
 				}
 
-				windowbottom = height;
-				if (windowbottom >= sprbotscreen)
+				sprbotscreen = windowbottom = height;
+				if (windowbottom >= bottomclip)
 				{
-					windowbottom = sprbotscreen;
+					sprbotscreen = windowbottom = bottomclip;
 					// draw the texture
 					colfunc_2s (col, lengthcol);
 					for (i++; i < dc_numlights; i++)
@@ -918,10 +921,11 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 					windowtop = bheight;
 				else
 					windowtop = windowbottom + 1;
+				sprtopscreen = windowtop;
 				if (lighteffect)
 					dc_colormap = rlight->rcolormap;
 			}
-			windowbottom = sprbotscreen;
+			sprbotscreen = windowbottom = bottomclip;
 			// draw the texture, if there is any space left
 			if (windowtop < windowbottom)
 				colfunc_2s (col, lengthcol);
@@ -1022,6 +1026,9 @@ static void R_RenderSegLoop (void)
 	if (bottomtexture)
 		R_CheckTextureCache(bottomtexture);
 
+	if (dc_numlights)
+		colfunc = colfuncs[COLDRAWFUNC_SHADOWED];
+
 	for (; rw_x < rw_stopx; rw_x++)
 	{
 		// mark floor / ceiling areas
@@ -1234,8 +1241,6 @@ static void R_RenderSegLoop (void)
 					dc_lightlist[i].rcolormap = dc_lightlist[i].extra_colormap->colormap + (xwalllights[pindex] - colormaps);
 				else
 					dc_lightlist[i].rcolormap = xwalllights[pindex];
-
-				colfunc = colfuncs[COLDRAWFUNC_SHADOWED];
 			}
 		}
 
@@ -2449,7 +2454,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 	if (frontsector->numlights)
 	{
 		dc_numlights = frontsector->numlights;
-		if (dc_numlights >= dc_maxlights)
+		if (dc_numlights > dc_maxlights)
 		{
 			dc_maxlights = dc_numlights;
 			dc_lightlist = Z_Realloc(dc_lightlist, sizeof (*dc_lightlist) * dc_maxlights, PU_STATIC, NULL);
diff --git a/src/r_translation.c b/src/r_translation.c
index 3905458026df20945e566861fc6c7a087bcab244..a53b30e9f6fc6196b72df18b3f6063534bda3219 100644
--- a/src/r_translation.c
+++ b/src/r_translation.c
@@ -556,7 +556,7 @@ static boolean ParseDecimal(tokenizer_t *sc, double *out)
 	return M_StringToDecimal(tkn, out);
 }
 
-static struct PaletteRemapParseResult *ThrowError(const char *format, ...)
+FUNCPRINTF static struct PaletteRemapParseResult *ThrowError(const char *format, ...)
 {
 	const size_t err_size = 512 * sizeof(char);
 
@@ -792,7 +792,7 @@ static struct PaletteRemapParseResult *PaletteRemap_ParseTranslation(const char
 	return result;
 }
 
-static void PrintError(const char *name, const char *format, ...)
+FUNCDEBUG static void PrintError(const char *name, const char *format, ...)
 {
 	char error[256];
 
diff --git a/src/s_sound.c b/src/s_sound.c
index a579292ff3aa791176b389d686901799c47c89a1..aa049899ff602cf6a1f7af4c287d8f3673bf5597 100644
--- a/src/s_sound.c
+++ b/src/s_sound.c
@@ -1910,7 +1910,7 @@ static void S_AddMusicStackEntry(const char *mname, UINT16 mflags, boolean loopi
 	if (!music_stacks)
 	{
 		music_stacks = Z_Calloc(sizeof (*mst), PU_MUSIC, NULL);
-		strncpy(music_stacks->musname, (status == JT_MASTER ? mname : (S_CheckQueue() ? queue_name : mapmusname)), 7);
+		strncpy(music_stacks->musname, (status == JT_MASTER ? mname : (S_CheckQueue() ? queue_name : mapmusname)), sizeof(music_stacks->musname)-1);
 		music_stacks->musflags = (status == JT_MASTER ? mflags : (S_CheckQueue() ? queue_flags : mapmusflags));
 		music_stacks->looping = (status == JT_MASTER ? looping : (S_CheckQueue() ? queue_looping : true));
 		music_stacks->position = (status == JT_MASTER ? position : (S_CheckQueue() ? queue_position : S_GetMusicPosition()));
@@ -2033,7 +2033,7 @@ boolean S_RecallMusic(UINT16 status, boolean fromfirst)
 	if (result)
 	{
 		*entry = *result;
-		strncpy(entry->musname, result->musname, 7);
+		memcpy(entry->musname, result->musname, sizeof(entry->musname));
 	}
 
 	// no result, just grab mapmusname
@@ -2255,7 +2255,7 @@ void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32
 	if (S_MusicDisabled())
 		return;
 
-	strncpy(newmusic, mmusic, 7);
+	strncpy(newmusic, mmusic, sizeof(newmusic)-1);
 	if (LUA_HookMusicChange(music_name, &hook_param))
 		return;
 	newmusic[6] = 0;
diff --git a/src/s_sound.h b/src/s_sound.h
index 288859c8d233dc9696118ef1d93655f98be514b9..d64778fc37db6fffdf8027ad7aa3cb4f338a6a33 100644
--- a/src/s_sound.h
+++ b/src/s_sound.h
@@ -238,7 +238,7 @@ UINT32 S_GetMusicPosition(void);
 
 typedef struct musicstack_s
 {
-	char musname[7];
+	char musname[7+1];
 	UINT16 musflags;
 	boolean looping;
 	UINT32 position;
diff --git a/src/screen.c b/src/screen.c
index c1970d0e8888360511fc0a7990e669b8678a9b3b..813ed91c665eeddc0e5b235c5bfec05bb78425be 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -44,6 +44,8 @@
 // SRB2Kart
 #include "r_fps.h" // R_GetFramerateCap
 
+#include "lua_hud.h" // LUA_HudEnabled
+
 // --------------------------------------------
 // assembly or c drawer routines for 8bpp/16bpp
 // --------------------------------------------
@@ -494,6 +496,7 @@ void SCR_ClosedCaptions(void)
 			basey -= 8;
 		else if ((modeattacking == ATTACKING_NIGHTS)
 		|| (!(maptol & TOL_NIGHTS)
+		&& LUA_HudEnabled(hud_powerups)
 		&& ((cv_powerupdisplay.value == 2) // "Always"
 		 || (cv_powerupdisplay.value == 1 && !camera.chase)))) // "First-person only"
 			basey -= 16;
diff --git a/src/sdl/Srb2SDL-vc10.vcxproj b/src/sdl/Srb2SDL-vc10.vcxproj
index bebecd8d05a10bc9456b3dbb31d8696f737e773b..86ffa7082ac3210321a06c3b477ba3b6239947b9 100644
--- a/src/sdl/Srb2SDL-vc10.vcxproj
+++ b/src/sdl/Srb2SDL-vc10.vcxproj
@@ -191,7 +191,8 @@
     <ClCompile>
       <DisableSpecificWarnings>4244;4267;4146;4003</DisableSpecificWarnings>
       <PreprocessorDefinitions>HAVE_CURL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>..\libs\curl\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>..\..\libs\curl\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <TreatWarningAsError>false</TreatWarningAsError>
     </ClCompile>
     <CustomBuild>
       <Command />
@@ -204,7 +205,7 @@
     </CustomBuild>
     <Link>
       <AdditionalDependencies>libcurl.dll.a;libz32.a;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>..\libs\zlib\win32;..\libs\curl\lib32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>..\..\libs\zlib\win32;..\..\libs\curl\lib32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c
index 173866e8b96d5f1e0b8c2b1cf0d632b9c004dd96..9f0fa0250a664dfe020d649ac65ccb347a63a3c8 100644
--- a/src/sdl/i_system.c
+++ b/src/sdl/i_system.c
@@ -1714,7 +1714,7 @@ const char *I_GetJoyName(INT32 joyindex)
 	{
 		tempname = SDL_JoystickNameForIndex(joyindex);
 		if (tempname)
-			strncpy(joyname, tempname, 255);
+			strncpy(joyname, tempname, sizeof(joyname)-1);
 	}
 	return joyname;
 }
@@ -2857,7 +2857,7 @@ size_t I_GetRandomBytes(char *destination, size_t count)
 {
 #if defined (__unix__) || defined (UNIXCOMMON) || defined(__APPLE__)
 	FILE *rndsource;
-	size_t actual_bytes;
+	size_t actual_bytes = 0;
 
 	if (!(rndsource = fopen("/dev/urandom", "r")))
 		if (!(rndsource = fopen("/dev/random", "r")))
diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c
index a5be3a754ce5a44b5c985f5881300d06a5ad07c7..8f2ca340879d5236822c534b2f9da57774a5356e 100644
--- a/src/sdl/mixer_sound.c
+++ b/src/sdl/mixer_sound.c
@@ -140,15 +140,18 @@ static void Midiplayer_Onchange(void)
 			restart = true;
 	}
 
-	if (stricmp(Mix_GetSoundFonts(), cv_midisoundfontpath.string))
+	if (!Mix_GetSoundFonts() || stricmp(Mix_GetSoundFonts(), cv_midisoundfontpath.string))
 	{
 		if (!Mix_SetSoundFonts(cv_midisoundfontpath.string)) // == 0 means error
 			CONS_Alert(CONS_ERROR, "Sound font error: %s", Mix_GetError());
 		else
 			restart = true;
 	}
-
+#if SDL_MIXER_VERSION_ATLEAST(2,5,0)
+	Mix_SetTimidityCfg(cv_miditimiditypath.string);
+#else
 	Mix_Timidity_addToPathList(cv_miditimiditypath.string);
+#endif
 
 	if (restart)
 		S_StartEx(true);
@@ -159,7 +162,7 @@ static void MidiSoundfontPath_Onchange(void)
 	if (Mix_GetMidiPlayer() != MIDI_Fluidsynth || (I_SongType() != MU_NONE && I_SongType() != MU_MID_EX))
 		return;
 
-	if (stricmp(Mix_GetSoundFonts(), cv_midisoundfontpath.string))
+	if (!Mix_GetSoundFonts() || stricmp(Mix_GetSoundFonts(), cv_midisoundfontpath.string))
 	{
 		char *miditoken;
 		char *source = strdup(cv_midisoundfontpath.string);
@@ -286,8 +289,12 @@ void I_StartupSound(void)
 #ifdef HAVE_MIXERX
 	Mix_SetMidiPlayer(cv_midiplayer.value);
 	Mix_SetSoundFonts(cv_midisoundfontpath.string);
+#if SDL_MIXER_VERSION_ATLEAST(2,5,0)
+	Mix_SetTimidityCfg(cv_miditimiditypath.string);
+#else
 	Mix_Timidity_addToPathList(cv_miditimiditypath.string);
 #endif
+#endif
 #if SDL_MIXER_VERSION_ATLEAST(1,2,11)
 	Mix_Init(MIX_INIT_FLAC|MIX_INIT_MP3|MIX_INIT_OGG|MIX_INIT_MOD);
 #endif
@@ -942,7 +949,12 @@ UINT32 I_GetSongLength(void)
 	else
 	{
 #ifdef HAVE_MIXERX
+#if SDL_MIXER_VERSION_ATLEAST(2,5,0)
+		double xlength = Mix_MusicDuration(music);
+#else
 		double xlength = Mix_GetMusicTotalTime(music);
+#endif
+
 		if (xlength >= 0)
 			return (UINT32)(xlength*1000);
 #endif
@@ -1198,10 +1210,14 @@ boolean I_LoadSong(char *data, size_t len)
 #ifdef HAVE_MIXERX
 	if (Mix_GetMidiPlayer() != cv_midiplayer.value)
 		Mix_SetMidiPlayer(cv_midiplayer.value);
-	if (stricmp(Mix_GetSoundFonts(), cv_midisoundfontpath.string))
+	if (!Mix_GetSoundFonts() || stricmp(Mix_GetSoundFonts(), cv_midisoundfontpath.string))
 		Mix_SetSoundFonts(cv_midisoundfontpath.string);
+#if SDL_MIXER_VERSION_ATLEAST(2,5,0)
+	Mix_SetTimidityCfg(cv_miditimiditypath.string);
+#else
 	Mix_Timidity_addToPathList(cv_miditimiditypath.string); // this overwrites previous custom path
 #endif
+#endif
 
 #ifdef HAVE_OPENMPT
 	/*
diff --git a/src/st_stuff.c b/src/st_stuff.c
index 1f4e61822ba2132debe93c5b800b9308169c61eb..b3e392499e7db22dd027ead283b82de5b5a1ed25 100644
--- a/src/st_stuff.c
+++ b/src/st_stuff.c
@@ -139,6 +139,7 @@ static patch_t *fireflower;
 hudinfo_t hudinfo[NUMHUDITEMS] =
 {
 	{  16, 176, V_SNAPTOLEFT|V_SNAPTOBOTTOM}, // HUD_LIVES
+	{  16, 152, V_SNAPTOLEFT|V_SNAPTOBOTTOM}, // HUD_INPUT
 
 	{  16,  42, V_SNAPTOLEFT|V_SNAPTOTOP}, // HUD_RINGS
 	{  96,  42, V_SNAPTOLEFT|V_SNAPTOTOP}, // HUD_RINGSNUM
@@ -814,7 +815,7 @@ static inline void ST_drawRings(void)
 
 static void ST_drawLivesArea(void)
 {
-	INT32 v_colmap = V_YELLOWMAP, livescount;
+	INT32 v_colmap = V_YELLOWMAP, livescount = -1;
 	boolean notgreyedout = false;
 
 	if (!stplyr->skincolor)
@@ -1037,32 +1038,36 @@ static void ST_drawInput(void)
 	INT32 col;
 	UINT8 offs;
 
-	INT32 x = hudinfo[HUD_LIVES].x, y = hudinfo[HUD_LIVES].y;
+	INT32 x = hudinfo[HUD_INPUT].x, y = hudinfo[HUD_INPUT].y;
 
 	if (stplyr->powers[pw_carry] == CR_NIGHTSMODE)
-		y -= 16;
+		y += 8;
+	else if (modeattacking || !LUA_HudEnabled(hud_lives))
+		y += 24;
+	else if (G_RingSlingerGametype() && LUA_HudEnabled(hud_powerstones))
+		y -= 5;
 
 	if (F_GetPromptHideHud(y))
 		return;
 
 	// O backing
-	V_DrawFill(x, y-1, 16, 16, hudinfo[HUD_LIVES].f|20);
-	V_DrawFill(x, y+15, 16, 1, hudinfo[HUD_LIVES].f|29);
+	V_DrawFill(x, y-1, 16, 16, hudinfo[HUD_INPUT].f|20);
+	V_DrawFill(x, y+15, 16, 1, hudinfo[HUD_INPUT].f|29);
 
 	if (cv_showinputjoy.value) // joystick render!
 	{
-		/*V_DrawFill(x   , y   , 16,  1, hudinfo[HUD_LIVES].f|16);
-		V_DrawFill(x   , y+15, 16,  1, hudinfo[HUD_LIVES].f|16);
-		V_DrawFill(x   , y+ 1,  1, 14, hudinfo[HUD_LIVES].f|16);
-		V_DrawFill(x+15, y+ 1,  1, 14, hudinfo[HUD_LIVES].f|16); -- red's outline*/
+		/*V_DrawFill(x   , y   , 16,  1, hudinfo[HUD_INPUT.f|16);
+		V_DrawFill(x   , y+15, 16,  1, hudinfo[HUD_INPUT].f|16);
+		V_DrawFill(x   , y+ 1,  1, 14, hudinfo[HUD_INPUT].f|16);
+		V_DrawFill(x+15, y+ 1,  1, 14, hudinfo[HUD_INPUT].f|16); -- red's outline*/
 		if (stplyr->cmd.sidemove || stplyr->cmd.forwardmove)
 		{
 			// joystick hole
-			V_DrawFill(x+5, y+4, 6, 6, hudinfo[HUD_LIVES].f|29);
+			V_DrawFill(x+5, y+4, 6, 6, hudinfo[HUD_INPUT].f|29);
 			// joystick top
 			V_DrawFill(x+3+stplyr->cmd.sidemove/12,
 				y+2-stplyr->cmd.forwardmove/12,
-				10, 10, hudinfo[HUD_LIVES].f|29);
+				10, 10, hudinfo[HUD_INPUT].f|29);
 			V_DrawFill(x+3+stplyr->cmd.sidemove/9,
 				y+1-stplyr->cmd.forwardmove/9,
 				10, 10, accent);
@@ -1070,10 +1075,10 @@ static void ST_drawInput(void)
 		else
 		{
 			// just a limited, greyed out joystick top
-			V_DrawFill(x+3, y+11, 10, 1, hudinfo[HUD_LIVES].f|29);
+			V_DrawFill(x+3, y+11, 10, 1, hudinfo[HUD_INPUT].f|29);
 			V_DrawFill(x+3,
 				y+1,
-				10, 10, hudinfo[HUD_LIVES].f|16);
+				10, 10, hudinfo[HUD_INPUT].f|16);
 		}
 	}
 	else // arrows!
@@ -1087,10 +1092,10 @@ static void ST_drawInput(void)
 		else
 		{
 			offs = 1;
-			col = hudinfo[HUD_LIVES].f|16;
-			V_DrawFill(x- 2, y+10,  6,  1, hudinfo[HUD_LIVES].f|29);
-			V_DrawFill(x+ 4, y+ 9,  1,  1, hudinfo[HUD_LIVES].f|29);
-			V_DrawFill(x+ 5, y+ 8,  1,  1, hudinfo[HUD_LIVES].f|29);
+			col = hudinfo[HUD_INPUT].f|16;
+			V_DrawFill(x- 2, y+10,  6,  1, hudinfo[HUD_INPUT].f|29);
+			V_DrawFill(x+ 4, y+ 9,  1,  1, hudinfo[HUD_INPUT].f|29);
+			V_DrawFill(x+ 5, y+ 8,  1,  1, hudinfo[HUD_INPUT].f|29);
 		}
 		V_DrawFill(x- 2, y+ 5-offs,  6,  6, col);
 		V_DrawFill(x+ 4, y+ 6-offs,  1,  4, col);
@@ -1105,12 +1110,12 @@ static void ST_drawInput(void)
 		else
 		{
 			offs = 1;
-			col = hudinfo[HUD_LIVES].f|16;
-			V_DrawFill(x+ 5, y+ 3,  1,  1, hudinfo[HUD_LIVES].f|29);
-			V_DrawFill(x+ 6, y+ 4,  1,  1, hudinfo[HUD_LIVES].f|29);
-			V_DrawFill(x+ 7, y+ 5,  2,  1, hudinfo[HUD_LIVES].f|29);
-			V_DrawFill(x+ 9, y+ 4,  1,  1, hudinfo[HUD_LIVES].f|29);
-			V_DrawFill(x+10, y+ 3,  1,  1, hudinfo[HUD_LIVES].f|29);
+			col = hudinfo[HUD_INPUT].f|16;
+			V_DrawFill(x+ 5, y+ 3,  1,  1, hudinfo[HUD_INPUT].f|29);
+			V_DrawFill(x+ 6, y+ 4,  1,  1, hudinfo[HUD_INPUT].f|29);
+			V_DrawFill(x+ 7, y+ 5,  2,  1, hudinfo[HUD_INPUT].f|29);
+			V_DrawFill(x+ 9, y+ 4,  1,  1, hudinfo[HUD_INPUT].f|29);
+			V_DrawFill(x+10, y+ 3,  1,  1, hudinfo[HUD_INPUT].f|29);
 		}
 		V_DrawFill(x+ 5, y- 2-offs,  6,  6, col);
 		V_DrawFill(x+ 6, y+ 4-offs,  4,  1, col);
@@ -1125,10 +1130,10 @@ static void ST_drawInput(void)
 		else
 		{
 			offs = 1;
-			col = hudinfo[HUD_LIVES].f|16;
-			V_DrawFill(x+12, y+10,  6,  1, hudinfo[HUD_LIVES].f|29);
-			V_DrawFill(x+11, y+ 9,  1,  1, hudinfo[HUD_LIVES].f|29);
-			V_DrawFill(x+10, y+ 8,  1,  1, hudinfo[HUD_LIVES].f|29);
+			col = hudinfo[HUD_INPUT].f|16;
+			V_DrawFill(x+12, y+10,  6,  1, hudinfo[HUD_INPUT].f|29);
+			V_DrawFill(x+11, y+ 9,  1,  1, hudinfo[HUD_INPUT].f|29);
+			V_DrawFill(x+10, y+ 8,  1,  1, hudinfo[HUD_INPUT].f|29);
 		}
 		V_DrawFill(x+12, y+ 5-offs,  6,  6, col);
 		V_DrawFill(x+11, y+ 6-offs,  1,  4, col);
@@ -1143,8 +1148,8 @@ static void ST_drawInput(void)
 		else
 		{
 			offs = 1;
-			col = hudinfo[HUD_LIVES].f|16;
-			V_DrawFill(x+ 5, y+17,  6,  1, hudinfo[HUD_LIVES].f|29);
+			col = hudinfo[HUD_INPUT].f|16;
+			V_DrawFill(x+ 5, y+17,  6,  1, hudinfo[HUD_INPUT].f|29);
 		}
 		V_DrawFill(x+ 5, y+12-offs,  6,  6, col);
 		V_DrawFill(x+ 6, y+11-offs,  4,  1, col);
@@ -1160,16 +1165,16 @@ static void ST_drawInput(void)
 	else\
 	{\
 		offs = 1;\
-		col = hudinfo[HUD_LIVES].f|16;\
-		V_DrawFill(x+16+(xoffs), y+9+(yoffs), 10, 1, hudinfo[HUD_LIVES].f|29);\
+		col = hudinfo[HUD_INPUT].f|16;\
+		V_DrawFill(x+16+(xoffs), y+9+(yoffs), 10, 1, hudinfo[HUD_INPUT].f|29);\
 	}\
 	V_DrawFill(x+16+(xoffs), y+(yoffs)-offs, 10, 10, col);\
-	V_DrawCharacter(x+16+1+(xoffs), y+1+(yoffs)-offs, hudinfo[HUD_LIVES].f|symb, false)
+	V_DrawCharacter(x+16+1+(xoffs), y+1+(yoffs)-offs, hudinfo[HUD_INPUT].f|symb, false)
 
 	drawbutt( 4,-3, BT_JUMP, 'J');
 	drawbutt(15,-3, BT_SPIN, 'S');
 
-	V_DrawFill(x+16+4, y+8, 21, 10, hudinfo[HUD_LIVES].f|20); // sundial backing
+	V_DrawFill(x+16+4, y+8, 21, 10, hudinfo[HUD_INPUT].f|20); // sundial backing
 	if (stplyr->mo)
 	{
 		UINT8 i, precision;
@@ -1189,7 +1194,7 @@ static void ST_drawInput(void)
 		{
 			V_DrawFill(x+16+14-(i*xcomp)/precision,
 				y+12-(i*ycomp)/precision,
-				1, 1, hudinfo[HUD_LIVES].f|16);
+				1, 1, hudinfo[HUD_INPUT].f|16);
 		}
 
 		if (ycomp <= 0)
@@ -1206,7 +1211,7 @@ static void ST_drawInput(void)
 		if (stplyr->pflags & PF_AUTOBRAKE)
 		{
 			V_DrawThinString(x, y,
-				hudinfo[HUD_LIVES].f|
+				hudinfo[HUD_INPUT].f|
 				((!stplyr->powers[pw_carry]
 				&& (stplyr->pflags & PF_APPLYAUTOBRAKE)
 				&& !(stplyr->cmd.sidemove || stplyr->cmd.forwardmove)
@@ -1219,22 +1224,22 @@ static void ST_drawInput(void)
 		switch (P_ControlStyle(stplyr))
 		{
 		case CS_LMAOGALOG:
-			V_DrawThinString(x, y, hudinfo[HUD_LIVES].f, "ANALOG");
+			V_DrawThinString(x, y, hudinfo[HUD_INPUT].f, "ANALOG");
 			y -= 8;
 			break;
 
 		case CS_SIMPLE:
-			V_DrawThinString(x, y, hudinfo[HUD_LIVES].f, "AUTOMATIC");
+			V_DrawThinString(x, y, hudinfo[HUD_INPUT].f, "AUTOMATIC");
 			y -= 8;
 			break;
 
 		case CS_STANDARD:
-			V_DrawThinString(x, y, hudinfo[HUD_LIVES].f, "MANUAL");
+			V_DrawThinString(x, y, hudinfo[HUD_INPUT].f, "MANUAL");
 			y -= 8;
 			break;
 
 		case CS_LEGACY:
-			V_DrawThinString(x, y, hudinfo[HUD_LIVES].f, "STRAFE");
+			V_DrawThinString(x, y, hudinfo[HUD_INPUT].f, "STRAFE");
 			y -= 8;
 			break;
 
@@ -1243,7 +1248,7 @@ static void ST_drawInput(void)
 		}
 	}
 	if (!demosynced) // should always be last, so it doesn't push anything else around
-		V_DrawThinString(x, y, hudinfo[HUD_LIVES].f|((leveltime & 4) ? V_YELLOWMAP : V_REDMAP), "BAD DEMO!!");
+		V_DrawThinString(x, y, hudinfo[HUD_INPUT].f|((leveltime & 4) ? V_YELLOWMAP : V_REDMAP), "BAD DEMO!!");
 }
 
 static patch_t *lt_patches[3];
@@ -2816,14 +2821,14 @@ static void ST_overlayDrawer(void)
 		|| ((splitscreen && stplyr == &players[secondarydisplayplayer]) && !camera2.chase))
 		{
 			ST_drawFirstPersonHUD();
-			if (cv_powerupdisplay.value)
+			if (cv_powerupdisplay.value && LUA_HudEnabled(hud_powerups))
 				ST_drawPowerupHUD();  // same as it ever was...
 		}
-		else if (cv_powerupdisplay.value == 2)
+		else if (cv_powerupdisplay.value == 2 && LUA_HudEnabled(hud_powerups))
 			ST_drawPowerupHUD();  // same as it ever was...
 		
 	}
-	else if (!(netgame || multiplayer) && cv_powerupdisplay.value == 2)
+	else if (!(netgame || multiplayer) && cv_powerupdisplay.value == 2 && LUA_HudEnabled(hud_powerups))
 		ST_drawPowerupHUD(); // same as it ever was...
 
 	if (!(netgame || multiplayer) || !hu_showscores)
@@ -2844,7 +2849,7 @@ static void ST_overlayDrawer(void)
 	if (!hu_showscores && (netgame || multiplayer) && LUA_HudEnabled(hud_textspectator))
 		ST_drawTextHUD();
 
-	if (modeattacking && !(demoplayback && hu_showscores))
+	if ((cv_showinput.value && !players[displayplayer].spectator) || (modeattacking && !(demoplayback && hu_showscores)))
 		ST_drawInput();
 
 	ST_drawDebugInfo();
diff --git a/src/st_stuff.h b/src/st_stuff.h
index 07dfac3eccf6095218bf0f4b16726c41a6f94fd5..6f6bac1fa47fd5b4b71a850383138ad9821456ee 100644
--- a/src/st_stuff.h
+++ b/src/st_stuff.h
@@ -92,6 +92,7 @@ typedef struct
 typedef enum
 {
 	HUD_LIVES,
+	HUD_INPUT,
 
 	HUD_RINGS,
 	HUD_RINGSNUM,
diff --git a/src/v_video.c b/src/v_video.c
index cb7db487e921b88e50fd0b6d97a6d3f631841c90..355bdf860160dced8d8baad8679ba86c68ed4582 100644
--- a/src/v_video.c
+++ b/src/v_video.c
@@ -384,13 +384,14 @@ void V_CubeApply(UINT8 *red, UINT8 *green, UINT8 *blue)
 
 const char *R_GetPalname(UINT16 num)
 {
-	static char palname[9];
-	char newpal[9] = "PLAYPAL";
+	static char palname[8+1];
+	char newpal[9] = "PLAYPAL\0";
 
 	if (num > 0 && num <= 10000)
 		snprintf(newpal, 8, "PAL%04u", num-1);
 
-	strncpy(palname, newpal, 8);
+	strncpy(palname, newpal, sizeof(palname)-1);
+	palname[8] = 0;
 	return palname;
 }