diff --git a/src/d_main.c b/src/d_main.c
index b5fa50f13b81684b4391688db70c27d93c692b1d..d6115964c6eb860682280eab09c6969429c1b1df 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -489,7 +489,7 @@ static void D_Display(void)
 		if (rendermode != render_none)
 		{
 			// miru: we can use the mapheaderinfo to change the forced wipe the instant the map loads
-			if (mapheaderinfo[gamemap-1]->postlevelwipe && mapheaderinfo[gamemap-1]->postlevelwipe < 100)
+			if (mapheaderinfo[gamemap-1] && mapheaderinfo[gamemap-1]->postlevelwipe && mapheaderinfo[gamemap-1]->postlevelwipe < 100)
 			{
 				F_WipeStartScreen();
 				V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, mapheaderinfo[gamemap-1]->wipecolor);
diff --git a/src/dehacked.c b/src/dehacked.c
index 2a3e7ca3bc4361118f73708cfe6537aa819718fa..9c30f50cd7a36087c23572988b6df9551774504d 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -3018,6 +3018,25 @@ static void readmaincfg(MYFILE *f)
 				DEH_WriteUndoline(word, va("%d", looptitle), UNDO_NONE);
 				looptitle = (boolean)(value || word2[0] == 'T' || word2[0] == 'Y');
 			}
+			else if (fastcmp(word, "TITLEMAP"))
+			{
+				// Support using the actual map name,
+				// i.e., Level AB, Level FZ, etc.
+
+				// Convert to map number
+				if (word2[0] >= 'A' && word2[0] <= 'Z')
+					value = M_MapNumber(word2[0], word2[1]);
+				else
+					value = get_number(word2);
+
+				DEH_WriteUndoline(word, va("%d", titlemap), UNDO_NONE);
+				titlemap = (INT16)value;
+			}
+			else if (fastcmp(word, "HIDETITLEPICS"))
+			{
+				DEH_WriteUndoline(word, va("%d", hidetitlepics), UNDO_NONE);
+				hidetitlepics = (boolean)(value || word2[0] == 'T' || word2[0] == 'Y');
+			}
 			else if (fastcmp(word, "TITLESCROLLSPEED"))
 			{
 				DEH_WriteUndoline(word, va("%d", titlescrollspeed), UNDO_NONE);
diff --git a/src/doomstat.h b/src/doomstat.h
index e8b59109cf5831e3402198ae12e92493ea96c9ee..18d95735e35ec1c5791eea42fbc5721caf6b1adc 100644
--- a/src/doomstat.h
+++ b/src/doomstat.h
@@ -127,6 +127,9 @@ extern INT16 sstage_end;
 extern INT16 bootmap; // rei/miru: bootmap for loading a map on startup (skips intro+title)
 //extern INT16 returnTobootmap; // rei/miru: return to bootmap when attempting to go to the REAL title?
 
+extern INT16 titlemap;
+extern boolean hidetitlepics;
+
 extern boolean looptitle;
 extern boolean useNightsSS;
 
diff --git a/src/f_finale.c b/src/f_finale.c
index ef9a28fd3ef9e74c073197913010d230fa1b4a10..4fec54da8b5503962b92d93eca080c41a291aa09 100644
--- a/src/f_finale.c
+++ b/src/f_finale.c
@@ -1423,11 +1423,28 @@ void F_StartTitleScreen(void)
 	else
 		wipegamestate = GS_TITLESCREEN;
 
-	gamemap = 533; titlescrollspeed = (int32_t)ANG1; //@TODO don't hardcode bich
-	G_DoLoadLevel(true);
-	G_SetGamestate(GS_TITLESCREEN);
-	players[displayplayer].playerstate = PST_DEAD; // Don't spawn the player in dummy (I'm still a filthy cheater)
-	//CON_ClearHUD();
+	if (titlemap)
+	{
+		gamemap = titlemap;
+
+		if (!mapheaderinfo[gamemap-1])
+			P_AllocMapHeader(gamemap-1);
+
+		G_DoLoadLevel(true);
+		G_SetGamestate(GS_TITLESCREEN);
+		players[displayplayer].playerstate = PST_DEAD; // Don't spawn the player in dummy (I'm still a filthy cheater)
+		//CON_ClearHUD();
+	}
+	else
+	{
+		gamemap = 0;
+
+		if (!mapheaderinfo[gamemap-1])
+			P_AllocMapHeader(gamemap-1);
+
+		G_SetGamestate(GS_TITLESCREEN);
+		CON_ClearHUD();
+	}
 
 	// IWAD dependent stuff.
 
@@ -1469,42 +1486,51 @@ void F_TitleScreenDrawer(void)
 	if (!ttwing || (gamestate != GS_TITLESCREEN && gamestate != GS_WAITINGPLAYERS))
 		return;
 
-	V_DrawScaledPatch(30, 14, 0, ttwing);
-
-	if (finalecount < 57)
+	// rei|miru: use title pics?
+	if (hidetitlepics)
 	{
-		if (finalecount == 35)
-			V_DrawScaledPatch(115, 15, 0, ttspop1);
-		else if (finalecount == 36)
-			V_DrawScaledPatch(114, 15, 0,ttspop2);
-		else if (finalecount == 37)
-			V_DrawScaledPatch(113, 15, 0,ttspop3);
-		else if (finalecount == 38)
-			V_DrawScaledPatch(112, 15, 0,ttspop4);
-		else if (finalecount == 39)
-			V_DrawScaledPatch(111, 15, 0,ttspop5);
-		else if (finalecount == 40)
-			V_DrawScaledPatch(110, 15, 0, ttspop6);
-		else if (finalecount >= 41 && finalecount <= 44)
-			V_DrawScaledPatch(109, 15, 0, ttspop7);
-		else if (finalecount >= 45 && finalecount <= 48)
-			V_DrawScaledPatch(108, 12, 0, ttsprep1);
-		else if (finalecount >= 49 && finalecount <= 52)
-			V_DrawScaledPatch(107, 9, 0, ttsprep2);
-		else if (finalecount >= 53 && finalecount <= 56)
-			V_DrawScaledPatch(106, 6, 0, ttswip1);
-		V_DrawScaledPatch(93, 106, 0, ttsonic);
+		return;
 	}
 	else
 	{
-		V_DrawScaledPatch(93, 106, 0,ttsonic);
-		if (finalecount/5 & 1)
-			V_DrawScaledPatch(100, 3, 0,ttswave1);
+		V_DrawScaledPatch(30, 14, 0, ttwing);
+
+		if (finalecount < 57)
+		{
+			if (finalecount == 35)
+				V_DrawScaledPatch(115, 15, 0, ttspop1);
+			else if (finalecount == 36)
+				V_DrawScaledPatch(114, 15, 0,ttspop2);
+			else if (finalecount == 37)
+				V_DrawScaledPatch(113, 15, 0,ttspop3);
+			else if (finalecount == 38)
+				V_DrawScaledPatch(112, 15, 0,ttspop4);
+			else if (finalecount == 39)
+				V_DrawScaledPatch(111, 15, 0,ttspop5);
+			else if (finalecount == 40)
+				V_DrawScaledPatch(110, 15, 0, ttspop6);
+			else if (finalecount >= 41 && finalecount <= 44)
+				V_DrawScaledPatch(109, 15, 0, ttspop7);
+			else if (finalecount >= 45 && finalecount <= 48)
+				V_DrawScaledPatch(108, 12, 0, ttsprep1);
+			else if (finalecount >= 49 && finalecount <= 52)
+				V_DrawScaledPatch(107, 9, 0, ttsprep2);
+			else if (finalecount >= 53 && finalecount <= 56)
+				V_DrawScaledPatch(106, 6, 0, ttswip1);
+			V_DrawScaledPatch(93, 106, 0, ttsonic);
+		}
 		else
-			V_DrawScaledPatch(100,3, 0,ttswave2);
-	}
+		{
+			V_DrawScaledPatch(93, 106, 0,ttsonic);
+			if (finalecount/5 & 1)
+				V_DrawScaledPatch(100, 3, 0,ttswave1);
+			else
+				V_DrawScaledPatch(100,3, 0,ttswave2);
+		}
 
-	V_DrawScaledPatch(48, 142, 0,ttbanner);
+		V_DrawScaledPatch(48, 142, 0,ttbanner);
+
+	}
 }
 
 // (no longer) De-Demo'd Title Screen
diff --git a/src/f_finale.h b/src/f_finale.h
index 1f23643bec2bd52a91cd3477ded284eb2a842484..1e4d3a1e33aa248ea26de95293f9fedecf9efacc 100644
--- a/src/f_finale.h
+++ b/src/f_finale.h
@@ -60,6 +60,8 @@ void F_StartContinue(void);
 void F_ContinueTicker(void);
 void F_ContinueDrawer(void);
 
+extern INT16 titlemap;
+extern boolean hidetitlepics;
 extern INT32 titlescrollspeed;
 
 //
diff --git a/src/g_game.c b/src/g_game.c
index b83655a6ca8d9c0353f4270b6a1364f0f97007ed..7a1a5e8e14bbf111c83a01764a92ca358aad9cd6 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -122,6 +122,9 @@ INT16 sstage_end;
 INT16 bootmap; // rei/miru: bootmap for loading a map on startup (skips intro+title)
 //INT16 returnTobootmap; // rei/miru: return to bootmap when attempting to go to the REAL title?
 
+INT16 titlemap;
+boolean hidetitlepics = false;
+
 boolean looptitle = false;
 boolean useNightsSS = false;
 
diff --git a/src/p_setup.c b/src/p_setup.c
index 4dc1f934ae248e32dc8ca18a6213aa86eb79eab0..482bf471f4a94d611ecd6812fbff4e46a5eb5cc7 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -2602,22 +2602,22 @@ boolean P_SetupLevel(boolean skipprecip)
 	// But only if we didn't do the special stage wipe
 	if (rendermode != render_none && !ranspecialwipe)
 	{
-		// miru: we could add the option to render different wipes here
-		if (mapheaderinfo[gamemap-1]->levelwipe && mapheaderinfo[gamemap-1]->levelwipe < 100)
-		{
+		// miru: we could add the option to render different wipes here
+		if (mapheaderinfo[gamemap-1] && mapheaderinfo[gamemap-1]->levelwipe && mapheaderinfo[gamemap-1]->levelwipe < 100)
+		{
 			F_WipeStartScreen();
 			V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, mapheaderinfo[gamemap-1]->wipecolor);
 
 			F_WipeEndScreen();
-			F_RunWipe(mapheaderinfo[gamemap-1]->levelwipe, false);
-		}
-		else
-		{
+			F_RunWipe(mapheaderinfo[gamemap-1]->levelwipe, false);
+		}
+		else
+		{
 			F_WipeStartScreen();
-			V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
+			V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
 
 			F_WipeEndScreen();
-			F_RunWipe(wipedefs[wipe_level_toblack], false);
+			F_RunWipe(wipedefs[wipe_level_toblack], false);
 		}
 	}