diff --git a/src/hu_stuff.c b/src/hu_stuff.c
index 2e9aad62a24359b8214c80b621425d34a66d5cee..ae16078efe9231dd4426e1fb94ad295ed06aae31 100644
--- a/src/hu_stuff.c
+++ b/src/hu_stuff.c
@@ -1197,67 +1197,10 @@ boolean HU_Responder(event_t *ev)
 
 #ifndef NONET
 
-// Precompile a wordwrapped string to any given width.
-// This is a muuuch better method than V_WORDWRAP.
-// again stolen and modified a bit from video.c, don't mind me, will need to rearrange this one day.
-// this one is simplified for the chat drawer.
-static char *CHAT_WordWrap(INT32 x, INT32 w, INT32 option, const char *string)
-{
-	INT32 c;
-	size_t chw, i, lastusablespace = 0;
-	size_t slen;
-	char *newstring = Z_StrDup(string);
-	INT32 spacewidth = (vid.width < 640) ? 8 : 4, charwidth = (vid.width < 640) ? 8 : 4;
-
-	slen = strlen(string);
-	x = 0;
-
-	for (i = 0; i < slen; ++i)
-	{
-		c = newstring[i];
-		if ((UINT8)c >= 0x80 && (UINT8)c <= 0x89) //color parsing! -Inuyasha 2.16.09
-			continue;
-
-		if (c == '\n')
-		{
-			x = 0;
-			lastusablespace = 0;
-			continue;
-		}
-
-		if (!(option & V_ALLOWLOWERCASE))
-			c = toupper(c);
-		c -= FONTSTART;
-
-		if (c < 0 || c >= FONTSIZE || !hu_font.chars[c])
-		{
-			chw = spacewidth;
-			lastusablespace = i;
-		}
-		else
-			chw = charwidth;
-
-		x += chw;
-
-		if (lastusablespace != 0 && x > w)
-		{
-			//CONS_Printf("Wrap at index %d\n", i);
-			newstring[lastusablespace] = '\n';
-			i = lastusablespace+1;
-			lastusablespace = 0;
-			x = 0;
-		}
-	}
-	return newstring;
-}
-
-
 // 30/7/18: chaty is now the distance at which the lowest point of the chat will be drawn if that makes any sense.
 
 INT16 chatx = 13, chaty = 169; // let's use this as our coordinates
 
-// chat stuff by VincyTM LOL XD!
-
 // HU_DrawMiniChat
 
 static void HU_drawMiniChat(void)
@@ -1281,7 +1224,7 @@ static void HU_drawMiniChat(void)
 
 	for (; i>0; i--)
 	{
-		char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i-1]);
+		char *msg = V_ChatWordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i-1]);
 		size_t j = 0;
 		INT32 linescount = 0;
 
@@ -1348,7 +1291,7 @@ static void HU_drawMiniChat(void)
 		INT32 timer = ((cv_chattime.value*TICRATE)-chat_timers[i]) - cv_chattime.value*TICRATE+9; // see below...
 		INT32 transflag = (timer >= 0 && timer <= 9) ? (timer*V_10TRANS) : 0; // you can make bad jokes out of this one.
 		size_t j = 0;
-		char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i]); // get the current message, and word wrap it.
+		char *msg = V_ChatWordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i]); // get the current message, and word wrap it.
 		UINT8 *colormap = NULL;
 
 		while(msg[j]) // iterate through msg
@@ -1448,7 +1391,7 @@ static void HU_drawChatLog(INT32 offset)
 	{
 		INT32 clrflag = 0;
 		INT32 j = 0;
-		char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_log[i]); // get the current message, and word wrap it.
+		char *msg = V_ChatWordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_log[i]); // get the current message, and word wrap it.
 		UINT8 *colormap = NULL;
 		while(msg[j]) // iterate through msg
 		{
diff --git a/src/v_video.c b/src/v_video.c
index b879838e36717d128cbaebb6565fd09294226102..a9fbceb3d49a19ca99ac354e1cd0832884544777 100644
--- a/src/v_video.c
+++ b/src/v_video.c
@@ -1940,39 +1940,53 @@ void V_DrawPromptBack(INT32 boxheight, INT32 color)
 		*buf = promptbgmap[*buf];
 }
 
-// Writes a single character (draw WHITE if bit 7 set)
+// Gets string colormap, used for 0x80 color codes
 //
-void V_DrawCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed)
+UINT8 *V_GetStringColormap(INT32 colorflags)
 {
-	INT32 w, flags;
-	const UINT8 *colormap = V_GetStringColormap(c);
-
-	flags = c & ~(V_CHARCOLORMASK | V_PARAMMASK);
-	c &= 0x7f;
-	if (lowercaseallowed)
-		c -= FONTSTART;
-	else
-		c = toupper(c) - FONTSTART;
-	if (c < 0 || c >= FONTSIZE || !hu_font.chars[c])
-		return;
-
-	w = hu_font.chars[c]->width;
-	if (x + w > vid.width)
-		return;
-
-	if (colormap != NULL)
-		V_DrawMappedPatch(x, y, flags, hu_font.chars[c], colormap);
-	else
-		V_DrawScaledPatch(x, y, flags, hu_font.chars[c]);
+	switch ((colorflags & V_CHARCOLORMASK) >> V_CHARCOLORSHIFT)
+	{
+	case  1: // 0x81, magenta
+		return magentamap;
+	case  2: // 0x82, yellow
+		return yellowmap;
+	case  3: // 0x83, lgreen
+		return lgreenmap;
+	case  4: // 0x84, blue
+		return bluemap;
+	case  5: // 0x85, red
+		return redmap;
+	case  6: // 0x86, gray
+		return graymap;
+	case  7: // 0x87, orange
+		return orangemap;
+	case  8: // 0x88, sky
+		return skymap;
+	case  9: // 0x89, purple
+		return purplemap;
+	case 10: // 0x8A, aqua
+		return aquamap;
+	case 11: // 0x8B, peridot
+		return peridotmap;
+	case 12: // 0x8C, azure
+		return azuremap;
+	case 13: // 0x8D, brown
+		return brownmap;
+	case 14: // 0x8E, rosy
+		return rosymap;
+	case 15: // 0x8F, invert
+		return invertmap;
+	default: // reset
+		return NULL;
+	}
 }
 
-// Writes a single character for the chat. (draw WHITE if bit 7 set)
-// Essentially the same as the above but it's small or big depending on what resolution you've chosen to huge..
+// Generalized character drawing function, combining console & chat functionality with a specified font.
 //
-void V_DrawChatCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed, UINT8 *colormap)
+void V_DrawFontCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed, fixed_t scale, UINT8 *colormap, fontdef_t font)
 {
 	INT32 w, flags;
-	//const UINT8 *colormap = V_GetStringColormap(c);
+	const UINT8 *color = colormap ? colormap : V_GetStringColormap(c);
 
 	flags = c & ~(V_CHARCOLORMASK | V_PARAMMASK);
 	c &= 0x7f;
@@ -1980,28 +1994,28 @@ void V_DrawChatCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed, UI
 		c -= FONTSTART;
 	else
 		c = toupper(c) - FONTSTART;
-	if (c < 0 || c >= FONTSIZE || !hu_font.chars[c])
+	if (c < 0 || c >= FONTSIZE || !font.chars[c])
 		return;
 
-	w = (vid.width < 640 ) ? ((hu_font.chars[c]->width / 2)) : (hu_font.chars[c]->width);	// use normal sized characters if we're using a terribly low resolution.
+	w = FixedMul(font.chars[c]->width / 2, scale);	// use normal sized characters if we're using a terribly low resolution.
 	if (x + w > vid.width)
 		return;
 
-	V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, (vid.width < 640) ? (FRACUNIT) : (FRACUNIT/2), flags, hu_font.chars[c], colormap);
+	V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, scale, flags, font.chars[c], color);
 }
 
-// Precompile a wordwrapped string to any given width.
-// This is a muuuch better method than V_WORDWRAP.
-char *V_WordWrap(INT32 x, INT32 w, INT32 option, const char *string)
+// Precompile a wordwrapped string to any given width, using a specified font.
+//
+char *V_FontWordWrap(INT32 x, INT32 w, INT32 option, fixed_t scale, const char *string, fontdef_t font)
 {
 	int c;
 	size_t chw, i, lastusablespace = 0;
 	size_t slen;
 	char *newstring = Z_StrDup(string);
-	INT32 spacewidth = 4, charwidth = 0;
+	INT32 spacewidth = font.spacewidth, charwidth = 0;
 
 	slen = strlen(string);
-
+	
 	if (w == 0)
 		w = BASEVIDWIDTH;
 	w -= x;
@@ -2010,10 +2024,10 @@ char *V_WordWrap(INT32 x, INT32 w, INT32 option, const char *string)
 	switch (option & V_SPACINGMASK)
 	{
 		case V_MONOSPACE:
-			spacewidth = 8;
+			spacewidth = font.spacewidth*2;
 			/* FALLTHRU */
 		case V_OLDSPACING:
-			charwidth = 8;
+			charwidth = font.spacewidth*2;
 			break;
 		case V_6WIDTHSPACE:
 			spacewidth = 6;
@@ -2038,68 +2052,26 @@ char *V_WordWrap(INT32 x, INT32 w, INT32 option, const char *string)
 			c = toupper(c);
 		c -= FONTSTART;
 
-		if (c < 0 || c >= FONTSIZE || !hu_font.chars[c])
+		if (c < 0 || c >= FONTSIZE || !font.chars[c])
 		{
 			chw = spacewidth;
 			lastusablespace = i;
 		}
 		else
-			chw = (charwidth ? charwidth : hu_font.chars[c]->width);
+			chw = (charwidth ? charwidth : font.chars[c]->width);
 
-		x += chw;
+		x +=  FixedMul(chw, scale);
 
 		if (lastusablespace != 0 && x > w)
 		{
 			newstring[lastusablespace] = '\n';
 			i = lastusablespace;
-			lastusablespace = 0;
-			x = 0;
+			lastusablespace = x = 0;
 		}
 	}
 	return newstring;
 }
 
-// Gets string colormap, used for 0x80 color codes
-//
-UINT8 *V_GetStringColormap(INT32 colorflags)
-{
-	switch ((colorflags & V_CHARCOLORMASK) >> V_CHARCOLORSHIFT)
-	{
-	case  1: // 0x81, magenta
-		return magentamap;
-	case  2: // 0x82, yellow
-		return yellowmap;
-	case  3: // 0x83, lgreen
-		return lgreenmap;
-	case  4: // 0x84, blue
-		return bluemap;
-	case  5: // 0x85, red
-		return redmap;
-	case  6: // 0x86, gray
-		return graymap;
-	case  7: // 0x87, orange
-		return orangemap;
-	case  8: // 0x88, sky
-		return skymap;
-	case  9: // 0x89, purple
-		return purplemap;
-	case 10: // 0x8A, aqua
-		return aquamap;
-	case 11: // 0x8B, peridot
-		return peridotmap;
-	case 12: // 0x8C, azure
-		return azuremap;
-	case 13: // 0x8D, brown
-		return brownmap;
-	case 14: // 0x8E, rosy
-		return rosymap;
-	case 15: // 0x8F, invert
-		return invertmap;
-	default: // reset
-		return NULL;
-	}
-}
-
 // Draw a string, using a supplied font and scale.
 // NOTE: The text is centered for screens larger than the base width.
 void V_DrawFontString(INT32 x, INT32 y, INT32 option, fixed_t pscale, fixed_t vscale, const char *string, fontdef_t font)
diff --git a/src/v_video.h b/src/v_video.h
index b454da748713e1a928c0effb32ad324010f1ff4c..0a5bbfc5190a1d53bf58a1e270325c770263fd9e 100644
--- a/src/v_video.h
+++ b/src/v_video.h
@@ -195,15 +195,17 @@ void V_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c, UINT16 color, U
 
 void V_DrawFadeConsBack(INT32 plines);
 void V_DrawPromptBack(INT32 boxheight, INT32 color);
+UINT8 *V_GetStringColormap(INT32 colorflags);
 
-// draw a single character
-void V_DrawCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed);
-// draw a single character, but for the chat
-void V_DrawChatCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed, UINT8 *colormap);
+// Generalized character drawing function, combining console & chat functionality with a specified font.
+void V_DrawFontCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed, fixed_t scale, UINT8 *colormap, fontdef_t font);
+#define V_DrawCharacter(x,y,c,l) V_DrawFontCharacter(x,y,c,l,FRACUNIT,NULL,hu_font)
+#define V_DrawChatCharacter(x,y,c,l,cm) V_DrawFontCharacter(x,y,c,l,FRACUNIT/2,cm,hu_font)
 
-// wordwrap a string using the hu_font
-char *V_WordWrap(INT32 x, INT32 w, INT32 option, const char *string);
-UINT8 *V_GetStringColormap(INT32 colorflags);
+// Precompile a wordwrapped string to any given width, using a specified font.
+char *V_FontWordWrap(INT32 x, INT32 w, INT32 option, fixed_t scale, const char *string, fontdef_t font);
+#define V_WordWrap(x,w,o,str) V_FontWordWrap(x, w, o, FRACUNIT, str, hu_font)
+#define V_ChatWordWrap(x,w,o,str) V_FontWordWrap(x, w, o, FRACUNIT/2, str, hu_font)
 
 // Draw a string, using a supplied font and scale.
 void V_DrawFontString(INT32 x, INT32 y, INT32 option, fixed_t pscale, fixed_t vscale, const char *string, fontdef_t font);