diff --git a/src/d_netcmd.c b/src/d_netcmd.c
index 75f1296ab..a597bad83 100644
--- a/src/d_netcmd.c
+++ b/src/d_netcmd.c
@@ -1199,7 +1199,7 @@ static INT32 snacpending = 0, snac2pending = 0, chmappending = 0;
 //
 static void SendNameAndColor(void)
 {
-	char buf[MAXPLAYERNAME+2];
+	char buf[MAXPLAYERNAME+6];
 	char *p;
 
 	p = buf;
diff --git a/src/g_game.c b/src/g_game.c
index dd7540ae8..646147e73 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -352,8 +352,8 @@ static CV_PossibleValue_t chattime_cons_t[] = {{5, "MIN"}, {999, "MAX"}, {0, NUL
 consvar_t cv_chattime = {"chattime", "8", CV_SAVE, chattime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 
 // chatwidth
-static CV_PossibleValue_t chatwidth_cons_t[] = {{64, "MIN"}, {150, "MAX"}, {0, NULL}};
-consvar_t cv_chatwidth = {"chatwidth", "128", CV_SAVE, chatwidth_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
+static CV_PossibleValue_t chatwidth_cons_t[] = {{64, "MIN"}, {300, "MAX"}, {0, NULL}};
+consvar_t cv_chatwidth = {"chatwidth", "150", CV_SAVE, chatwidth_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 
 // chatheight
 static CV_PossibleValue_t chatheight_cons_t[] = {{6, "MIN"}, {22, "MAX"}, {0, NULL}};
diff --git a/src/hu_stuff.c b/src/hu_stuff.c
index 2c71ee71c..073b21b92 100644
--- a/src/hu_stuff.c
+++ b/src/hu_stuff.c
@@ -502,37 +502,31 @@ 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 = (char*) malloc(3);
+		char playernum[3];
 		INT32 spc = 1; // used if playernum[1] is a space.
 
 		strncpy(playernum, msg+3, 3);
 		// check for undesirable characters in our "number"
-		if 	(((playernum[0] < '0') || (playernum[0] > '9')) || ((playernum[1] < '0') || (playernum[1] > '9')))
+		if (((playernum[0] < '0') || (playernum[0] > '9')) || ((playernum[1] < '0') || (playernum[1] > '9')))
 		{
 			// check if playernum[1] is a space
 			if (playernum[1] == ' ')
 				spc = 0;
-				// let it slide
+			// let it slide
 			else
 			{
 				HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<playernum> \'.", false);
-				free(playernum);
 				return;
 			}
 		}
 		// I'm very bad at C, I swear I am, additional checks eww!
-			if (spc != 0)
-			{
-				if (msg[5] != ' ')
-				{
-					HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<playernum> \'.", false);
-					free(playernum);
-					return;
-				}
-			}
+		if (spc != 0 && msg[5] != ' ')
+		{
+			HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<playernum> \'.", false);
+			return;
+		}
 
-		target = atoi((const char*) playernum); // turn that into a number
-		free(playernum);
+		target = atoi(playernum); // turn that into a number
 		//CONS_Printf("%d\n", target);
 
 		// check for target player, if it doesn't exist then we can't send the message!
@@ -1022,9 +1016,6 @@ void HU_Ticker(void)
 #ifndef NONET
 
 static boolean teamtalk = false;
-/*static char chatchars[QUEUESIZE];
-static INT32 head = 0, tail = 0;*/
-// WHY DO YOU OVERCOMPLICATE EVERYTHING?????????
 
 // Clear spaces so we don't end up with messages only made out of emptiness
 static boolean HU_clearChatSpaces(void)
@@ -1083,11 +1074,11 @@ static void HU_queueChatChar(char c)
 
 		if (strlen(msg) > 4 && strnicmp(msg, "/pm", 3) == 0) // used /pm
 		{
-			INT32 spc = 1; // used if nodenum[1] is a space.
-			char *nodenum = (char*) malloc(3);
+			INT32 spc = 1; // used if playernum[1] is a space.
+			char playernum[3];
 			const char *newmsg;
 
-			// what we're gonna do now is check if the node exists
+			// what we're gonna do now is check if the player exists
 			// with that logic, characters 4 and 5 are our numbers:
 
 			// teamtalk can't send PMs, just don't send it, else everyone would be able to see it, and no one wants to see your sex RP sicko.
@@ -1097,18 +1088,17 @@ static void HU_queueChatChar(char c)
 				return;
 			}
 
-			strncpy(nodenum, msg+3, 3);
+			strncpy(playernum, msg+3, 3);
 			// check for undesirable characters in our "number"
-			if 	(((nodenum[0] < '0') || (nodenum[0] > '9')) || ((nodenum[1] < '0') || (nodenum[1] > '9')))
+			if (((playernum[0] < '0') || (playernum[0] > '9')) || ((playernum[1] < '0') || (playernum[1] > '9')))
 			{
-				// check if nodenum[1] is a space
-				if (nodenum[1] == ' ')
+				// check if playernum[1] is a space
+				if (playernum[1] == ' ')
 					spc = 0;
 					// let it slide
 				else
 				{
-					HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<node> \'.", false);
-					free(nodenum);
+					HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<player num> \'.", false);
 					return;
 				}
 			}
@@ -1117,14 +1107,12 @@ static void HU_queueChatChar(char c)
 			{
 				if (msg[5] != ' ')
 				{
-					HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<node> \'.", false);
-					free(nodenum);
+					HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<player num> \'.", false);
 					return;
 				}
 			}
 
-			target = atoi((const char*) nodenum); // turn that into a number
-			free(nodenum);
+			target = atoi(playernum); // turn that into a number
 			//CONS_Printf("%d\n", target);
 
 			// check for target player, if it doesn't exist then we can't send the message!
@@ -1136,7 +1124,7 @@ static void HU_queueChatChar(char c)
 				return;
 			}
 
-			// we need to get rid of the /pm<node>
+			// we need to get rid of the /pm<player num>
 			newmsg = msg+5+spc;
 			strlcpy(msg, newmsg, 255);
 		}
@@ -1659,12 +1647,9 @@ static void HU_drawChatLog(INT32 offset)
 	}
 	chat_scrollmedown = false;
 
-	// getmaxscroll through a lazy hack. We do all these loops, so let's not do more loops that are gonna lag the game more. :P
-	chat_maxscroll = (dy/charheight); // welcome to C, we don't know what min() and max() are.
-	if (chat_maxscroll <= (UINT32)cv_chatheight.value)
-		chat_maxscroll = 0;
-	else
-		chat_maxscroll -= cv_chatheight.value;
+	// getmaxscroll through a lazy hack. We do all these loops,
+	// so let's not do more loops that are gonna lag the game more. :P
+	chat_maxscroll = max(dy / charheight - cv_chatheight.value, 0);
 
 	// if we're not bound by the time, autoscroll for next frame:
 	if (atbottom)
@@ -1805,21 +1790,17 @@ static void HU_DrawChat(void)
 		i = 0;
 		for(i=0; (i<MAXPLAYERS); i++)
 		{
-
 			// filter: (code needs optimization pls help I'm bad with C)
 			if (w_chat[3])
 			{
-				char *nodenum;
+				char playernum[3];
 				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;
 
-
-				nodenum = (char*) malloc(3);
-				strncpy(nodenum, w_chat+3, 3);
-				n = atoi((const char*) nodenum); // turn that into a number
-				free(nodenum);
+				strncpy(playernum, w_chat+3, 3);
+				n = atoi(playernum); // turn that into a number
 				// special cases:
 
 				if ((n == 0) && !(w_chat[4] == '0'))
@@ -1866,7 +1847,6 @@ static void HU_DrawChat(void)
 	}
 
 	HU_drawChatLog(typelines-1); // typelines is the # of lines we're typing. If there's more than 1 then the log should scroll up to give us more space.
-
 }
 
 
diff --git a/src/mserv.c b/src/mserv.c
index ddabdb6c0..4ddab05b9 100644
--- a/src/mserv.c
+++ b/src/mserv.c
@@ -323,13 +323,9 @@ static INT32 GetServersList(void)
 //
 // MS_Connect()
 //
-static INT32 MS_Connect(const char *ip_addr, const char *str_port, INT32 async)
+#ifndef NONET
+static INT32 MS_SubConnect(const char *ip_addr, const char *str_port, INT32 async, struct sockaddr *bindaddr, socklen_t bindaddrlen)
 {
-#ifdef NONET
-	(void)ip_addr;
-	(void)str_port;
-	(void)async;
-#else
 	struct my_addrinfo *ai, *runp, hints;
 	int gaie;
 
@@ -356,50 +352,100 @@ static INT32 MS_Connect(const char *ip_addr, const char *str_port, INT32 async)
 		socket_fd = socket(runp->ai_family, runp->ai_socktype, runp->ai_protocol);
 		if (socket_fd != (SOCKET_TYPE)ERRSOCKET)
 		{
-			if (async) // do asynchronous connection
+			if (!bindaddr || bind(socket_fd, bindaddr, bindaddrlen) == 0)
 			{
+				if (async) // do asynchronous connection
+				{
 #ifdef FIONBIO
 #ifdef WATTCP
-				char res = 1;
+					char res = 1;
 #else
-				unsigned long res = 1;
+					unsigned long res = 1;
 #endif
 
-				ioctl(socket_fd, FIONBIO, &res);
+					ioctl(socket_fd, FIONBIO, &res);
 #endif
 
-				if (connect(socket_fd, runp->ai_addr, (socklen_t)runp->ai_addrlen) == ERRSOCKET)
-				{
-#ifdef _WIN32 // humm, on win32/win64 it doesn't work with EINPROGRESS (stupid windows)
-					if (WSAGetLastError() != WSAEWOULDBLOCK)
-#else
-					if (errno != EINPROGRESS)
-#endif
+					if (connect(socket_fd, runp->ai_addr, (socklen_t)runp->ai_addrlen) == ERRSOCKET)
 					{
-						con_state = MSCS_FAILED;
-						CloseConnection();
-						I_freeaddrinfo(ai);
-						return MS_CONNECT_ERROR;
+#ifdef _WIN32 // humm, on win32/win64 it doesn't work with EINPROGRESS (stupid windows)
+						if (WSAGetLastError() != WSAEWOULDBLOCK)
+#else
+							if (errno != EINPROGRESS)
+#endif
+							{
+								con_state = MSCS_FAILED;
+								CloseConnection();
+								I_freeaddrinfo(ai);
+								return MS_CONNECT_ERROR;
+							}
 					}
+					con_state = MSCS_WAITING;
+					FD_ZERO(&wset);
+					FD_SET(socket_fd, &wset);
+					select_timeout.tv_sec = 0, select_timeout.tv_usec = 0;
+					I_freeaddrinfo(ai);
+					return 0;
+				}
+				else if (connect(socket_fd, runp->ai_addr, (socklen_t)runp->ai_addrlen) != ERRSOCKET)
+				{
+					I_freeaddrinfo(ai);
+					return 0;
 				}
-				con_state = MSCS_WAITING;
-				FD_ZERO(&wset);
-				FD_SET(socket_fd, &wset);
-				select_timeout.tv_sec = 0, select_timeout.tv_usec = 0;
-				I_freeaddrinfo(ai);
-				return 0;
 			}
-			else if (connect(socket_fd, runp->ai_addr, (socklen_t)runp->ai_addrlen) != ERRSOCKET)
+			close(socket_fd);
+		}
+		runp = runp->ai_next;
+	}
+	I_freeaddrinfo(ai);
+	return MS_CONNECT_ERROR;
+}
+#endif/*NONET xd*/
+
+static INT32 MS_Connect(const char *ip_addr, const char *str_port, INT32 async)
+{
+#ifdef NONET
+	(void)ip_addr;
+	(void)str_port;
+	(void)async;
+	return MS_CONNECT_ERROR;
+#else
+	const char *lhost;
+	struct my_addrinfo hints;
+	struct my_addrinfo *ai, *aip;
+	int c;
+	if (M_CheckParm("-bindaddr") && ( lhost = M_GetNextParm() ))
+	{
+		memset (&hints, 0x00, sizeof(hints));
+#ifdef AI_ADDRCONFIG
+		hints.ai_flags = AI_ADDRCONFIG;
+#endif
+		hints.ai_family = AF_INET;
+		hints.ai_socktype = SOCK_STREAM;
+		hints.ai_protocol = IPPROTO_TCP;
+		if (( c = I_getaddrinfo(lhost, 0, &hints, &ai) ) != 0)
+		{
+			CONS_Printf(
+					"mserv.c: bind to %s: %s\n",
+					lhost,
+					gai_strerror(c));
+			return MS_GETHOSTBYNAME_ERROR;
+		}
+		for (aip = ai; aip; aip = aip->ai_next)
+		{
+			c = MS_SubConnect(ip_addr, str_port, async, aip->ai_addr, aip->ai_addrlen);
+			if (c == 0)
 			{
 				I_freeaddrinfo(ai);
 				return 0;
 			}
 		}
-		runp = runp->ai_next;
+		I_freeaddrinfo(ai);
+		return c;
 	}
-	I_freeaddrinfo(ai);
-#endif
-	return MS_CONNECT_ERROR;
+	else
+		return MS_SubConnect(ip_addr, str_port, async, 0, 0);
+#endif/*NONET xd*/
 }
 
 #define NUM_LIST_SERVER MAXSERVERLIST