diff --git a/src/dehacked.c b/src/dehacked.c
index 938699516d20bb29eb9df793091e8bd3f21d0c75..70efc830000e23cbe9e8fca3dc71a6e6879fcc62 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -1520,10 +1520,27 @@ static void readlevelheader(MYFILE *f, INT32 num)
 					deh_warning("Level header %d: invalid bonus type number %d", num, i);
 			}
 
+			// Title card
+			else if (fastcmp(word, "TITLECARDZIGZAG"))
+			{
+				deh_strlcpy(mapheaderinfo[num-1]->ltzzpatch, word2,
+					sizeof(mapheaderinfo[num-1]->ltzzpatch), va("Level header %d: title card zigzag patch name", num));
+			}
+			else if (fastcmp(word, "TITLECARDZIGZAGTEXT"))
+			{
+				deh_strlcpy(mapheaderinfo[num-1]->ltzztext, word2,
+					sizeof(mapheaderinfo[num-1]->ltzztext), va("Level header %d: title card zigzag text patch name", num));
+			}
+			else if (fastcmp(word, "TITLECARDACTDIAMOND"))
+			{
+				deh_strlcpy(mapheaderinfo[num-1]->ltactdiamond, word2,
+					sizeof(mapheaderinfo[num-1]->ltactdiamond), va("Level header %d: title card act diamond patch name", num));
+			}
+
 			else if (fastcmp(word, "MAXBONUSLIVES"))
 				mapheaderinfo[num-1]->maxbonuslives = (SINT8)i;
 			else if (fastcmp(word, "LEVELFLAGS"))
-				mapheaderinfo[num-1]->levelflags = (UINT8)i;
+				mapheaderinfo[num-1]->levelflags = (UINT16)i;
 			else if (fastcmp(word, "MENUFLAGS"))
 				mapheaderinfo[num-1]->menuflags = (UINT8)i;
 
diff --git a/src/doomstat.h b/src/doomstat.h
index 3c0b4773a686adc29c3ce903eb24472e960d86af..a42591f476d8e30d5fab7ad352235b1e1a32b9ed 100644
--- a/src/doomstat.h
+++ b/src/doomstat.h
@@ -310,12 +310,17 @@ typedef struct
 	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.)
 
-	UINT8 levelflags;     ///< LF_flags:  merged booleans into one UINT8 for space, see below
+	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.
 
+	// Title card.
+	char ltzzpatch[8];      ///< Zig zag patch.
+	char ltzztext[8];       ///< Zig zag text.
+	char ltactdiamond[8];   ///< 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.
diff --git a/src/lua_maplib.c b/src/lua_maplib.c
index b35bb6a41cbaddd7cd09d3095f1e60accf4ac87a..8ad66d04f4b26a67cd94302da4357899e0326587 100644
--- a/src/lua_maplib.c
+++ b/src/lua_maplib.c
@@ -2071,6 +2071,12 @@ static int mapheaderinfo_get(lua_State *L)
 		lua_pushinteger(L, header->levelselect);
 	else if (fastcmp(field,"bonustype"))
 		lua_pushinteger(L, header->bonustype);
+	else if (fastcmp(field,"ltzzpatch"))
+		lua_pushstring(L, header->ltzzpatch);
+	else if (fastcmp(field,"ltzztext"))
+		lua_pushstring(L, header->ltzztext);
+	else if (fastcmp(field,"ltactdiamond"))
+		lua_pushstring(L, header->ltactdiamond);
 	else if (fastcmp(field,"maxbonuslives"))
 		lua_pushinteger(L, header->maxbonuslives);
 	else if (fastcmp(field,"levelflags"))
diff --git a/src/p_setup.c b/src/p_setup.c
index 6e6c1a72bd871984846bd3e1f39966287dee084e..12fcd596f4729866f7dab5e477077ab1559e4cac 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -213,6 +213,9 @@ static void P_ClearSingleMapHeaderInfo(INT16 i)
 	mapheaderinfo[num]->lvlttl[0] = '\0';
 	mapheaderinfo[num]->selectheading[0] = '\0';
 	mapheaderinfo[num]->subttl[0] = '\0';
+	mapheaderinfo[num]->ltzzpatch[0] = '\0';
+	mapheaderinfo[num]->ltzztext[0] = '\0';
+	mapheaderinfo[num]->ltactdiamond[0] = '\0';
 	mapheaderinfo[num]->actnum = 0;
 	mapheaderinfo[num]->typeoflevel = 0;
 	mapheaderinfo[num]->nextlevel = (INT16)(i + 1);
diff --git a/src/st_stuff.c b/src/st_stuff.c
index 1b116a7f3d276891088122de4b7b4cace36136d1..963dc24cc3732cede78954cb17179782e9a0b3aa 100644
--- a/src/st_stuff.c
+++ b/src/st_stuff.c
@@ -1177,21 +1177,33 @@ tic_t lt_exitticker = 0, lt_endtime = 0;
 
 //
 // Load the graphics for the title card.
+// Don't let LJ see this
 //
 static void ST_cacheLevelTitle(void)
 {
-	if (!(mapheaderinfo[gamemap-1]->levelflags & LF_WARNINGTITLE))
-	{
-		lt_patches[0] = (patch_t *)W_CachePatchName("LTACTBLU", PU_HUDGFX);
-		lt_patches[1] = (patch_t *)W_CachePatchName("LTZIGZAG", PU_HUDGFX);
-		lt_patches[2] = (patch_t *)W_CachePatchName("LTZZTEXT", PU_HUDGFX);
-	}
-	else // boss map
-	{
-		lt_patches[0] = (patch_t *)W_CachePatchName("LTACTRED", PU_HUDGFX);
-		lt_patches[1] = (patch_t *)W_CachePatchName("LTZIGRED", PU_HUDGFX);
-		lt_patches[2] = (patch_t *)W_CachePatchName("LTZZWARN", PU_HUDGFX);
-	}
+#define SETPATCH(default, warning, custom, idx) \
+{ \
+	lumpnum_t patlumpnum = LUMPERROR; \
+	if (mapheaderinfo[gamemap-1]->custom[0] != '\0') \
+	{ \
+		patlumpnum = W_CheckNumForName(mapheaderinfo[gamemap-1]->custom); \
+		if (patlumpnum != LUMPERROR) \
+			lt_patches[idx] = (patch_t *)W_CachePatchNum(patlumpnum, PU_HUDGFX); \
+	} \
+	if (patlumpnum == LUMPERROR) \
+	{ \
+		if (!(mapheaderinfo[gamemap-1]->levelflags & LF_WARNINGTITLE)) \
+			lt_patches[idx] = (patch_t *)W_CachePatchName(default, PU_HUDGFX); \
+		else \
+			lt_patches[idx] = (patch_t *)W_CachePatchName(warning, PU_HUDGFX); \
+	} \
+}
+
+	SETPATCH("LTACTBLU", "LTACTRED", ltactdiamond, 0)
+	SETPATCH("LTZIGZAG", "LTZIGRED", ltzzpatch, 1)
+	SETPATCH("LTZZTEXT", "LTZZWARN", ltzztext, 2)
+
+#undef SETPATCH
 }
 
 //