diff --git a/src/d_clisrv.c b/src/d_clisrv.c
index 8cfab06f39e71532c477864e5dd200a446533783..a27992b5d1173fc07d8ef1f42c24719b34bfb235 100644
--- a/src/d_clisrv.c
+++ b/src/d_clisrv.c
@@ -1337,6 +1337,70 @@ static boolean CL_SendJoin(void)
 	return HSendPacket(servernode, true, 0, sizeof (clientconfig_pak));
 }
 
+void
+CopyCaretColors (char *p, const char *s, int n)
+{
+	char *t;
+	int   m;
+	int   c;
+	if (!n)
+		return;
+	while (( t = strchr(s, '^') ))
+	{
+		m = ( t - s );
+
+		if (m >= n)
+		{
+			memcpy(p, s, n);
+			return;
+		}
+		else
+			memcpy(p, s, m);
+
+		p += m;
+		n -= m;
+		s += m;
+
+		if (!n)
+			return;
+
+		if (s[1])
+		{
+			c = toupper(s[1]);
+			if (isdigit(c))
+				c = 0x80 + ( c - '0' );
+			else if (c >= 'A' && c <= 'F')
+				c = 0x80 + ( c - 'A' );
+			else
+				c = 0;
+
+			if (c)
+			{
+				*p++ = c;
+				n--;
+
+				if (!n)
+					return;
+			}
+			else
+			{
+				if (n < 2)
+					break;
+
+				memcpy(p, s, 2);
+
+				p += 2;
+				n -= 2;
+			}
+
+			s += 2;
+		}
+		else
+			break;
+	}
+	strncpy(p, s, n);
+}
+
 static void SV_SendServerInfo(INT32 node, tic_t servertime)
 {
 	UINT8 *p;
@@ -1360,7 +1424,7 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime)
 		(D_IsJoinPasswordOn() ? SV_PASSWORD : 0)
 	);
 
-	strncpy(netbuffer->u.serverinfo.servername, cv_servername.string,
+	CopyCaretColors(netbuffer->u.serverinfo.servername, cv_servername.string,
 		MAXSERVERNAME);
 	strncpy(netbuffer->u.serverinfo.mapname, G_BuildMapName(gamemap), 7);
 
@@ -3990,12 +4054,15 @@ static void HandleTimeout(SINT8 node)
   */
 static void HandleServerInfo(SINT8 node)
 {
+	char servername[MAXSERVERNAME];
 	// compute ping in ms
 	const tic_t ticnow = I_GetTime();
 	const tic_t ticthen = (tic_t)LONG(netbuffer->u.serverinfo.time);
 	const tic_t ticdiff = (ticnow - ticthen)*1000/NEWTICRATE;
 	netbuffer->u.serverinfo.time = (tic_t)LONG(ticdiff);
 	netbuffer->u.serverinfo.servername[MAXSERVERNAME-1] = 0;
+	memcpy(servername, netbuffer->u.serverinfo.servername, MAXSERVERNAME);
+	CopyCaretColors(netbuffer->u.serverinfo.servername, servername, MAXSERVERNAME);
 	netbuffer->u.serverinfo.gametype = (UINT8)((netbuffer->u.serverinfo.gametype == VANILLA_GT_MATCH) ? GT_MATCH : GT_RACE);
 
 	SL_InsertServer(&netbuffer->u.serverinfo, node);
diff --git a/src/d_clisrv.h b/src/d_clisrv.h
index c9256bc52fca192cb4e7bc763196fad1eda12e89..1919ee055cd5cf25b94557a739146bfd1bc166bd 100644
--- a/src/d_clisrv.h
+++ b/src/d_clisrv.h
@@ -581,6 +581,8 @@ void D_QuitNetGame(void);
 //? How many ticks to run?
 void TryRunTics(tic_t realtic);
 
+void CopyCaretColors(char *p, const char *s, int n);
+
 // extra data for lmps
 // these functions scare me. they contain magic.
 /*boolean AddLmpExtradata(UINT8 **demo_p, INT32 playernum);
diff --git a/src/mserv.c b/src/mserv.c
index c7344b16a7ac6f2cfde07ecd7a501dfb1b52c54d..29b9e6c610c406af275ec7163b07ed13253d9647 100644
--- a/src/mserv.c
+++ b/src/mserv.c
@@ -748,7 +748,7 @@ static INT32 AddToMasterServer(boolean firstadd)
 
 	strcpy(info->ip, "");
 	strcpy(info->port, int2str(current_port));
-	strcpy(info->name, cv_servername.string);
+	CopyCaretColors(info->name, cv_servername.string, MAXSERVERNAME);
 	M_Memcpy(&info->room, & room, sizeof (INT32));
 #if VERSION > 0 || SUBVERSION > 0
 	sprintf(info->version, "%d.%d.%d", VERSION/100, VERSION%100, SUBVERSION);