diff --git a/src/f_finale.c b/src/f_finale.c
index cb64618535659f329bb357f65c2cec0bbe006b2d..a86ce53c7354975e29afde7a5b268d25ad246549 100644
--- a/src/f_finale.c
+++ b/src/f_finale.c
@@ -1308,25 +1308,39 @@ void F_CreditDrawer(void)
 	{
 		switch(credits[i][0])
 		{
-		case 0:
-			y += 80<<FRACBITS;
-			break;
-		case 1:
-			if (y>>FRACBITS > -20)
-				V_DrawCreditString((160 - (V_CreditStringWidth(&credits[i][1])>>1))<<FRACBITS, y, 0, &credits[i][1]);
-			y += 30<<FRACBITS;
-			break;
-		case 2:
-			if (y>>FRACBITS > -10)
-				V_DrawStringAtFixed((BASEVIDWIDTH-V_StringWidth(&credits[i][1], V_ALLOWLOWERCASE|V_YELLOWMAP))<<FRACBITS>>1, y, V_ALLOWLOWERCASE|V_YELLOWMAP, &credits[i][1]);
-			y += 12<<FRACBITS;
-			break;
-		default:
-			if (y>>FRACBITS > -10)
-				V_DrawStringAtFixed(32<<FRACBITS, y, V_ALLOWLOWERCASE, credits[i]);
-			y += 12<<FRACBITS;
-			break;
+			case 0:
+				y += 80<<FRACBITS;
+				break;
+			case 1:
+			{
+				INT32 height = V_CreditStringHeight(&credits[i][1], 0) * vid.dup;
+				height <<= FRACBITS;
+				if (y > -height)
+					V_DrawCreditString((160 - (V_CreditStringWidth(&credits[i][1]) >> 1)) << FRACBITS, y, 0, &credits[i][1]);
+				y += 30 << FRACBITS;
+				break;
+			}
+			case 2:
+			{
+				// Because of how the text is drawn, assuming a line height of 12, measuring the string height here won't work.
+				INT32 height = /*V_StringHeight(&credits[i][1], V_ALLOWLOWERCASE | V_YELLOWMAP)*/ 12 * vid.dup;
+				height <<= FRACBITS;
+				if (y > -height)
+					V_DrawStringAtFixed((BASEVIDWIDTH - V_StringWidth(&credits[i][1], V_ALLOWLOWERCASE | V_YELLOWMAP)) << FRACBITS >> 1, y, V_ALLOWLOWERCASE | V_YELLOWMAP, &credits[i][1]);
+				y += 12 << FRACBITS;
+				break;
+			}
+			default:
+			{
+				INT32 height = /*V_StringHeight(credits[i], V_ALLOWLOWERCASE)*/ 12 * vid.dup;
+				height <<= FRACBITS;
+				if (y > -height)
+					V_DrawStringAtFixed(32 << FRACBITS, y, V_ALLOWLOWERCASE, credits[i]);
+				y += 12 << FRACBITS;
+				break;
+			}
 		}
+
 		if (FixedMul(y,vid.dup) > vid.height)
 			break;
 	}
diff --git a/src/v_video.c b/src/v_video.c
index cb7db487e921b88e50fd0b6d97a6d3f631841c90..304771a9dd92caf846fcd3ac7ff6ea813bfcdf2c 100644
--- a/src/v_video.c
+++ b/src/v_video.c
@@ -3213,6 +3213,65 @@ INT32 V_CreditStringWidth(const char *string)
 	return w;
 }
 
+//
+// V_CreditStringHeight
+//
+// Returns the UNSCALED height of the credit string, including line breaks.
+//
+INT32 V_CreditStringHeight(const char *string)
+{
+	fixed_t x = 0;
+	fixed_t y = 0;
+	INT32 w, c;
+	fixed_t cx = x, cy = y;
+	const char *ch = string;
+
+	INT32 textHeight = 0;
+	INT32 lineHeight = 0;
+	INT32 verticalPad = 0;
+
+	// It's possible for string to be a null pointer
+	if (!string)
+		return;
+
+	for (;;)
+	{
+		c = *ch++;
+		if (!c)
+		{
+			textHeight += lineHeight;
+			break;
+		}
+
+		if (c == '\n')
+		{
+			cx = x;
+			cy += 12;
+			textHeight += lineHeight;
+			lineHeight = 0;
+			verticalPad += 4;
+			continue;
+		}
+
+		c = toupper(c) - CRED_FONTSTART;
+		if (c < 0 || c >= CRED_FONTSIZE)
+		{
+			cx += 16;
+			continue;
+		}
+
+		w = cred_font[c]->width;
+
+		INT16 charHeight = cred_font[c]->height;
+		if (charHeight > lineHeight)
+			lineHeight = charHeight;
+
+		cx += w;
+	}
+
+	return textHeight + verticalPad;
+}
+
 // Write a string using the level title font
 // NOTE: the text is centered for screens larger than the base width
 //
@@ -3380,6 +3439,100 @@ INT32 V_StringWidth(const char *string, INT32 option)
 	return w;
 }
 
+//
+// V_StringHeight
+//
+// Returns the UNSCALED height of the string, including line breaks.
+//
+INT32 V_StringHeight(const char *string, INT32 option)
+{
+	INT32 x = 0;
+	INT32 y = 0;
+	INT32 w, c, cx = x, cy = y, center = 0;
+	const char *ch = string;
+	INT32 charflags = (option & V_CHARCOLORMASK);
+	INT32 spacewidth = 4, charwidth = 0;
+
+	INT32 lowercase = (option & V_ALLOWLOWERCASE);
+	option &= ~V_FLIP; // which is also shared with V_ALLOWLOWERCASE...
+
+	switch (option & V_SPACINGMASK)
+	{
+	case V_MONOSPACE:
+		spacewidth = 8;
+		/* FALLTHRU */
+	case V_OLDSPACING:
+		charwidth = 8;
+		break;
+	case V_6WIDTHSPACE:
+		spacewidth = 6;
+	default:
+		break;
+	}
+
+	INT32 textHeight = 0;
+	INT32 lineHeight = 0;
+	INT32 verticalPad = 0;
+
+	for (;; ch++)
+	{
+		if (!*ch)
+		{
+			textHeight += lineHeight;
+			break;
+		}
+		if (*ch & 0x80) //color parsing -x 2.16.09
+		{
+			// manually set flags override color codes
+			if (!(option & V_CHARCOLORMASK))
+				charflags = ((*ch & 0x7f) << V_CHARCOLORSHIFT) & V_CHARCOLORMASK;
+			continue;
+		}
+		if (*ch == '\n')
+		{
+			cx = x;
+
+			if (option & V_RETURN8)
+				cy += 8;
+			else
+			{
+				cy += 12;
+				verticalPad += 4;
+			}
+
+			textHeight += lineHeight;
+			lineHeight = 0;
+
+			continue;
+		}
+
+		c = *ch;
+		if (!lowercase)
+			c = toupper(c);
+		c -= HU_FONTSTART;
+
+		// character does not exist or is a space
+		if (c < 0 || c >= HU_FONTSIZE || !hu_font[c])
+		{
+			cx += spacewidth;
+			continue;
+		}
+
+		if (charwidth)
+			w = charwidth;
+		else
+			w = hu_font[c]->width;
+
+		INT16 charHeight = hu_font[c]->height;
+		if (charHeight > lineHeight)
+			lineHeight = charHeight;
+
+		cx += w;
+	}
+
+	return textHeight + verticalPad;
+}
+
 //
 // Find string width from hu_font chars, 0.5x scale
 //
diff --git a/src/v_video.h b/src/v_video.h
index 5a3df5a4499588df56e4a6d152f1445f82a60926..c440e6978b36717a784a4b33ddd562e4ffafc96b 100644
--- a/src/v_video.h
+++ b/src/v_video.h
@@ -257,6 +257,7 @@ INT16 V_LevelActNumWidth(UINT8 num); // act number width
 
 void V_DrawCreditString(fixed_t x, fixed_t y, INT32 option, const char *string);
 INT32 V_CreditStringWidth(const char *string);
+INT32 V_CreditStringHeight(const char *string, INT32 option);
 
 // Draw a string using the nt_font
 void V_DrawNameTag(INT32 x, INT32 y, INT32 option, fixed_t scale, UINT8 *basecolormap, UINT8 *outlinecolormap, const char *string);
@@ -265,6 +266,7 @@ INT32 V_NameTagWidth(const char *string);
 
 // Find string width from hu_font chars
 INT32 V_StringWidth(const char *string, INT32 option);
+INT32 V_StringHeight(const char *string, INT32 option);
 // Find string width from hu_font chars, 0.5x scale
 INT32 V_SmallStringWidth(const char *string, INT32 option);
 // Find string width from tny_font chars