function SelectMusicOrCourse()
	if IsNetSMOnline() then
		return "ScreenNetSelectMusic";
	elseif GAMESTATE:IsCourseMode() then
		local pm = GAMESTATE:GetPlayMode();
		if pm == 'PlayMode_Nonstop' then return "ScreenSelectCourseNonstop"; end;
		if pm == 'PlayMode_Oni' then return "ScreenSelectCourseOni"; end;
		if pm == 'PlayMode_Endless' then return "ScreenSelectCourseEndless"; end;
		return "ScreenSelectCourse";
	else
		return "ScreenSelectMusic";
	end;
end;

local function _PostEvaluation(nextScreen,failedScreen,endScreen)
	if GAMESTATE:IsEventMode() then return nextScreen; end;
	if STATSMAN:GetCurStageStats():AllFailed() then return failedScreen; end;

	local IsAStage = not GetTopScreenMetric( "Summary" ) and not GAMESTATE:IsCourseMode()
	if IsAStage then
		local bLastStage = GAMESTATE:GetSmallestNumStagesLeftForAnyHumanPlayer() <= 0
		if not bLastStage then -- lol blast stage
			return nextScreen;
		end;
	end;

	return endScreen;
end;

function SelectEndingScreen()
	local bIsExtraStage = GAMESTATE:IsAnExtraStage()
	if STATSMAN:GetCurStageStats():AllFailed() and not bIsExtraStage then
		return "ScreenGameOver"
	end

	local grade = STATSMAN:GetBestFinalGrade()
	if Grade:Compare( grade, "Grade_Tier03" ) >= 0 then return "ScreenCredits" end
	if GAMESTATE:IsExtraStage2() then return "Screenpopcandycredits"; end;
	return "ScreenMusicScroll";
end

if vFlag then
	Branch.AfterScreenLogo = function()
		-- HowToPlay only works in dance mode; causes crashes on others.
		if GAMESTATE:GetCurrentGame():GetName() == "dance" then
			return "ScreenHowToPlay";
		else
			return "ScreenDemonstration";
		end;
	end;
	Branch.GameStartScreen = function()
		return PREFSMAN:GetPreference("ShowCaution") and "ScreenCaution" or "ScreenSelectStyle";
	end;
	Branch.SelectStyle = function()
		return IsNetConnected() and "ScreenSelectStyle2" or "ScreenSelectStyle";
	end;
	Branch.AfterSelectDifficulty = function()
		if IsNetConnected() then
			ReportStyle();
			return SMOnlineScreen();
		else
			return SelectMusicOrCourse();
		end;
	end;
	Branch.AfterGameInstructions = function()
		local pm = GAMESTATE:GetPlayMode();
		if pm == 'PlayMode_Nonstop' then return "ScreenSelectCourseNonstop"; end;
		if pm == 'PlayMode_Oni' then return "ScreenSelectCourseOni"; end;
		if pm == 'PlayMode_Endless' then return "ScreenSelectCourseEndless"; end;
		return SelectMusicOrCourse();
		--return "ScreenSelectMusic";
	end;
	Branch.PlayerOptions = function()
		local pm = GAMESTATE:GetPlayMode()
		local restricted = { "PlayMode_Oni", "PlayMode_Rave",
			--"PlayMode_Battle" -- ??
		};
		for i=1,#restricted do
			if restricted[i] == pm then
				return "ScreenPlayerOptionsRestricted"
			end;
		end
		if SCREENMAN:GetTopScreen():GetGoToOptions() then
			return "ScreenPlayerOptions";
		else
			return "ScreenStageInformation";
		end
	end;
	Branch.GameplayScreen = function()
		if GAMESTATE:IsCourseMode() then return "ScreenGameplayCourse"; end;
		if GAMESTATE:IsExtraStage() or GAMESTATE:IsExtraStage2() then return "ScreenGameplayExtra"; end;
		return "ScreenGameplay";
	end;
	Branch.AfterGameplay = function()
		-- pick an evaluation screen based on settings.
		if IsNetSMOnline() then
			return "ScreenNetEvaluation"
		else
			local pm = GAMESTATE:GetPlayMode();
			if pm == 'PlayMode_Nonstop' then return "ScreenEvaluationNonstop"; end;
			if pm == 'PlayMode_Oni' then return "ScreenEvaluationOni"; end;
			if pm == 'PlayMode_Endless' then return "ScreenEvaluationEndless"; end;
			return "ScreenEvaluationStage"
		end
	end;
	Branch.AfterEval = function()
		-- okay here's the deal:
		-- in event mode, go to profile save, then back to selmusic.
		-- in non-event mode with stages left, do the same thing
		-- if no stages are left, don't save; go to summary, name entry, then save.
		-- if you failed then uh save profiles and game over.
		return _PostEvaluation("ScreenProfileSave","ScreenGameOver","ScreenNameEntry");
	end;
	Branch.AfterEvalSummary = function()
		return _PostEvaluation("ScreenNameEntry", "ScreenProfileSave", "ScreenNameEntry");
	end;
	Branch.AfterProfileSave = function()
		if GAMESTATE:IsEventMode() then
			return SelectMusicOrCourse();
		else
			local bLastStage = GAMESTATE:GetSmallestNumStagesLeftForAnyHumanPlayer() <= 0
			-- check for extra
			if GAMESTATE:HasEarnedExtraStage() then
				return SelectMusicOrCourse();
			end;
			-- in course mode, go to name entry, then credits.
			if GAMESTATE:IsCourseMode() then
				return "ScreenNameEntry";
			end;
			-- otherwise we should let them play more.
			if not bLastStage then
				return SelectMusicOrCourse();
			end;
		end;

		return SelectEndingScreen()
	end;
else
	function SMOnlineScreen()
		for pn in ivalues(GAMESTATE:GetHumanPlayers()) do
			if not IsSMOnlineLoggedIn(pn) then return "ScreenSMOnlineLogin" end;
		end;
		return "ScreenNetRoom"
	end;
	Branch = {
		AfterScreenLogo = function()
			-- HowToPlay only works in dance mode; causes crashes on others.
			if GAMESTATE:GetCurrentGame():GetName() == "dance" then
				return "ScreenHowToPlay";
			else
				return "ScreenDemonstration";
			end;
		end,
		GameStartScreen = function()
			return PREFSMAN:GetPreference("ShowCaution") and "ScreenCaution" or "ScreenSelectStyle";
		end,
		SelectStyle = function()
			return IsNetConnected() and "ScreenSelectStyle2" or "ScreenSelectStyle";
		end,
		AfterSelectDifficulty = function()
			if IsNetConnected() then
				ReportStyle();
				return SMOnlineScreen();
			else
				return SelectMusicOrCourse();
			end;
		end,
		AfterGameInstructions = function()
			local pm = GAMESTATE:GetPlayMode();
			if pm == 'PlayMode_Nonstop' then return "ScreenSelectCourseNonstop"; end;
			if pm == 'PlayMode_Oni' then return "ScreenSelectCourseOni"; end;
			if pm == 'PlayMode_Endless' then return "ScreenSelectCourseEndless"; end;
			return SelectMusicOrCourse();
		end,
		PlayerOptions = function()
			local pm = GAMESTATE:GetPlayMode()
			local restricted = { "PlayMode_Oni", "PlayMode_Rave",
				--"PlayMode_Battle" -- ??
			};
			for i=1,#restricted do
				if restricted[i] == pm then
					return "ScreenPlayerOptionsRestricted"
				end;
			end
			if SCREENMAN:GetTopScreen():GetGoToOptions() then
				return "ScreenPlayerOptions";
			else
				return "ScreenStageInformation";
			end
		end,
		SongOptions = function()
			if SCREENMAN:GetTopScreen():GetGoToOptions() then
				return "ScreenSongOptions"
			else
				return "ScreenStageInformation"
			end
		end,
		GameplayScreen = function()
			if GAMESTATE:IsCourseMode() then return "ScreenGameplayCourse"; end;
			if GAMESTATE:IsExtraStage() or GAMESTATE:IsExtraStage2() then return "ScreenGameplayExtra"; end;
			return "ScreenGameplay";
		end;
		AfterGameplay = function()
			-- pick an evaluation screen based on settings.
			if IsNetSMOnline() then
				return "ScreenNetEvaluation"
			else
				local pm = GAMESTATE:GetPlayMode();
				if pm == 'PlayMode_Nonstop' then return "ScreenEvaluationNonstop"; end;
				if pm == 'PlayMode_Oni' then return "ScreenEvaluationOni"; end;
				if pm == 'PlayMode_Endless' then return "ScreenEvaluationEndless"; end;
				return "ScreenEvaluationStage"
			end
		end,
		AfterEval = function()
			-- okay here's the deal:
			-- in event mode, go to profile save, then back to selmusic.
			-- in non-event mode with stages left, do the same thing
			-- if no stages are left, don't save; go to summary, name entry, then save.
			-- if you failed then uh save profiles and game over.
			return _PostEvaluation("ScreenProfileSave","ScreenGameOver","ScreenNameEntry");
		end,
		AfterEvalSummary = function()
			return _PostEvaluation("ScreenNameEntry", "ScreenProfileSave", "ScreenNameEntry");
		end,
		AfterProfileSave = function()
			if GAMESTATE:IsEventMode() then
				return SelectMusicOrCourse();
			else
				local bLastStage = GAMESTATE:GetSmallestNumStagesLeftForAnyHumanPlayer() <= 0
				-- check for extra
				if GAMESTATE:HasEarnedExtraStage() then
					return SelectMusicOrCourse();
				end;
				-- in course mode, go to name entry, then credits.
				if GAMESTATE:IsCourseMode() then
					return "ScreenNameEntry";
				end;
			end;

			return SelectEndingScreen()
		end,
	};
end;