diff --git a/src/d_main.c b/src/d_main.c
index a27d3874ec45426b3fa6521e3f9da73f5929c1f6..b5fa50f13b81684b4391688db70c27d93c692b1d 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -318,6 +318,12 @@ static void D_Display(void)
 	// do buffered drawing
 	switch (gamestate)
 	{
+		case GS_TITLESCREEN:
+			if (!gamemap) {
+				F_TitleScreenDrawer();
+				break;
+			}
+			// Intentional fall-through
 		case GS_LEVEL:
 			if (!gametic)
 				break;
@@ -366,10 +372,6 @@ static void D_Display(void)
 			HU_Drawer();
 			break;
 
-		case GS_TITLESCREEN:
-			F_TitleScreenDrawer();
-			break;
-
 		case GS_WAITINGPLAYERS:
 			// The clientconnect drawer is independent...
 		case GS_DEDICATEDSERVER:
@@ -379,9 +381,10 @@ static void D_Display(void)
 
 	// clean up border stuff
 	// see if the border needs to be initially drawn
-	if (gamestate == GS_LEVEL)
+	if (gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && gamemap))
 	{
 		// draw the view directly
+
 		if (!automapactive && !dedicated && cv_renderview.value)
 		{
 			if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD)
@@ -436,7 +439,10 @@ static void D_Display(void)
 			lastdraw = false;
 		}
 
-		ST_Drawer();
+		if (gamestate == GS_LEVEL)
+			ST_Drawer();
+		else
+			F_TitleScreenDrawer();
 
 		HU_Drawer();
 	}
@@ -483,17 +489,17 @@ 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)
-			{
-				F_WipeStartScreen();
-				V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, mapheaderinfo[gamemap-1]->wipecolor);
-				F_WipeEndScreen();
-				F_RunWipe(mapheaderinfo[gamemap-1]->postlevelwipe,  gamestate != GS_TIMEATTACK);
-			}
-			else
-			{
-				F_WipeEndScreen();
-				F_RunWipe(wipedefs[wipedefindex], gamestate != GS_TIMEATTACK);
+			if (mapheaderinfo[gamemap-1]->postlevelwipe && mapheaderinfo[gamemap-1]->postlevelwipe < 100)
+			{
+				F_WipeStartScreen();
+				V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, mapheaderinfo[gamemap-1]->wipecolor);
+				F_WipeEndScreen();
+				F_RunWipe(mapheaderinfo[gamemap-1]->postlevelwipe,  gamestate != GS_TIMEATTACK);
+			}
+			else
+			{
+				F_WipeEndScreen();
+				F_RunWipe(wipedefs[wipedefindex], gamestate != GS_TIMEATTACK);
 			}
 		}
 	}
diff --git a/src/f_finale.c b/src/f_finale.c
index 692abb35f4837a921a97ff0a8fefb13189e10a9c..ef9a28fd3ef9e74c073197913010d230fa1b4a10 100644
--- a/src/f_finale.c
+++ b/src/f_finale.c
@@ -31,6 +31,7 @@
 #include "m_random.h"
 #include "y_inter.h"
 #include "m_cond.h"
+#include "p_local.h"
 
 // Stage of animation:
 // 0 = text, 1 = art screen
@@ -1421,13 +1422,16 @@ void F_StartTitleScreen(void)
 		finalecount = 0;
 	else
 		wipegamestate = GS_TITLESCREEN;
+
+	gamemap = 533; titlescrollspeed = (int32_t)ANG1; //@TODO don't hardcode bich
+	G_DoLoadLevel(true);
 	G_SetGamestate(GS_TITLESCREEN);
-	CON_ClearHUD();
+	players[displayplayer].playerstate = PST_DEAD; // Don't spawn the player in dummy (I'm still a filthy cheater)
+	//CON_ClearHUD();
 
 	// IWAD dependent stuff.
 
 	S_ChangeMusicInternal("titles", looptitle);
-
 	animtimer = 0;
 
 	demoDelayLeft = demoDelayTime;
@@ -1457,7 +1461,9 @@ void F_TitleScreenDrawer(void)
 		return; // We likely came here from retrying. Don't do a damn thing.
 
 	// Draw that sky!
-	F_SkyScroll(titlescrollspeed);
+	if (!gamemap) {
+		F_SkyScroll(titlescrollspeed);
+	}
 
 	// Don't draw outside of the title screewn, or if the patch isn't there.
 	if (!ttwing || (gamestate != GS_TITLESCREEN && gamestate != GS_WAITINGPLAYERS))
@@ -1511,6 +1517,13 @@ void F_TitleScreenTicker(boolean run)
 	if (gameaction != ga_nothing || gamestate != GS_TITLESCREEN)
 		return;
 
+	// Do a lil' camera spin if a title map is loaded.
+	if (gamemap) {
+		camera.x = camera.y = camera.height = camera.aiming = 0;
+		camera.z = 128*FRACUNIT;
+		camera.angle += titlescrollspeed;
+	}
+
 	// no demos to play? or, are they disabled?
 	if (!cv_rollingdemos.value || !numDemos)
 		return;
diff --git a/src/g_game.c b/src/g_game.c
index 919e9004799a5016f06011877d873a914747d921..b83655a6ca8d9c0353f4270b6a1364f0f97007ed 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -1987,6 +1987,7 @@ void G_Ticker(boolean run)
 			break;
 
 		case GS_TITLESCREEN:
+			if (gamemap) P_Ticker(run); // then intentionally fall through
 		case GS_WAITINGPLAYERS:
 			F_TitleScreenTicker(run);
 			break;
diff --git a/src/p_user.c b/src/p_user.c
index ff8133e67f411eecec3d47e033c9ec1dfd0bdb80..13916df66f92c3a61bc3521d22e7cb30157674ab 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -165,7 +165,7 @@ fixed_t P_ReturnThrustY(mobj_t *mo, angle_t angle, fixed_t move)
 boolean P_AutoPause(void)
 {
 	// Don't pause even on menu-up or focus-lost in netgames or record attack
-	if (netgame || modeattacking)
+	if (netgame || modeattacking || gamestate == GS_TITLESCREEN)
 		return false;
 
 	return (menuactive || window_notinfocus);