From 96fa65a5ff4727730e9b36e836643b820a9b6b33 Mon Sep 17 00:00:00 2001 From: Maschell Date: Mon, 24 Feb 2020 20:19:21 +0100 Subject: [PATCH] Add intial support for displaying the splashscreen when using as a system menu replacement --- src/Application.cpp | 18 +++++++--- src/menu/GameSplashScreen.cpp | 66 +++++++++++++++++++++++++++++++++++ src/menu/GameSplashScreen.h | 19 ++++++++++ src/menu/MainWindow.cpp | 56 +++++++++++++++++++++++++---- src/menu/MainWindow.h | 7 ++-- 5 files changed, 154 insertions(+), 12 deletions(-) create mode 100644 src/menu/GameSplashScreen.cpp create mode 100644 src/menu/GameSplashScreen.h diff --git a/src/Application.cpp b/src/Application.cpp index 77e4866..0e7b590 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -168,9 +168,9 @@ bool Application::procUI(void) { case PROCUI_STATUS_RELEASE_FOREGROUND: { DEBUG_FUNCTION_LINE("PROCUI_STATUS_RELEASE_FOREGROUND\n"); if(video != NULL) { - // we can turn of the screen but we don't need to and it will display the last image - video->tvEnable(false); - video->drcEnable(false); + // we can turn ofF the screen but we don't need to and it will display the last image + video->tvEnable(true); + video->drcEnable(true); DEBUG_FUNCTION_LINE("delete fontSystem\n"); delete fontSystem; @@ -274,9 +274,19 @@ void Application::executeThread(void) { video->waitForVSync(); } + if(bgMusic) { + bgMusic->SetVolume(0); + } + //! in case we exit to a homebrew let's smoothly fade out if(video) { - fadeOut(); + uint64_t titleID = OSGetTitleID(); + if (titleID == HBL_TITLE_ID || + titleID == MII_MAKER_JPN_TITLE_ID || + titleID == MII_MAKER_USA_TITLE_ID || + titleID == MII_MAKER_EUR_TITLE_ID) { + fadeOut(); + } } DEBUG_FUNCTION_LINE("delete mainWindow\n"); diff --git a/src/menu/GameSplashScreen.cpp b/src/menu/GameSplashScreen.cpp new file mode 100644 index 0000000..a0eaceb --- /dev/null +++ b/src/menu/GameSplashScreen.cpp @@ -0,0 +1,66 @@ +#include "GameSplashScreen.h" +#include "utils/logger.h" +#include "common/common.h" +#include "fs/FSUtils.h" +#include "utils/AsyncExecutor.h" + +GameSplashScreen::GameSplashScreen(int32_t w, int32_t h, gameInfo * info, bool onTV) : GuiFrame(w, h), + bgImageColor(w, h, (GX2Color) { + 0, 0, 0, 0 +}) { + bgImageColor.setImageColor((GX2Color) { + 79, 153, 239, 255 + }, 0); + bgImageColor.setImageColor((GX2Color) { + 79, 153, 239, 255 + }, 1); + bgImageColor.setImageColor((GX2Color) { + 59, 159, 223, 255 + }, 2); + bgImageColor.setImageColor((GX2Color) { + 59, 159, 223, 255 + }, 3); + append(&bgImageColor); + this->onTV = onTV; + this->info = info; + + std::string filepath = "fs:" + info->gamePath + META_PATH + "/bootDRCTex.tga"; + if(onTV) { + filepath = "fs:" + info->gamePath + META_PATH + "/bootTVTex.tga"; + } + uint8_t *buffer = NULL; + uint32_t bufferSize = 0; + int iResult = FSUtils::LoadFileToMem(filepath.c_str(), &buffer, &bufferSize); + if(iResult > 0) { + splashScreenData = new GuiImageData(buffer, bufferSize, GX2_TEX_CLAMP_MODE_MIRROR); + if(splashScreenData) { + bgImageColor.setImageData(splashScreenData); + bgImageColor.setScale(((float) h) / splashScreenData->getHeight()); + } + + //! free original image buffer which is converted to texture now and not needed anymore + free(buffer); + } + this->effectFinished.connect(this, &GameSplashScreen::OnSplashScreenFadeInDone); +} + +void GameSplashScreen::OnSplashScreenFadeInDone(GuiElement *element) { + // we need to wait one more frame becaus the effects get calculated before drawing. + launchGame = true; + +} + +void GameSplashScreen::draw(CVideo * v) { + GuiFrame::draw(v); + if(launchGame && frameCounter++ > 1) { + DEBUG_FUNCTION_LINE("Launch game %d\n", onTV); + gameGameSplashScreenFinished(this, info, onTV); + } +} + +GameSplashScreen::~GameSplashScreen() { + DEBUG_FUNCTION_LINE("Destroy me\n"); + if(splashScreenData) { + AsyncExecutor::pushForDelete(splashScreenData); + } +} diff --git a/src/menu/GameSplashScreen.h b/src/menu/GameSplashScreen.h new file mode 100644 index 0000000..a9540fb --- /dev/null +++ b/src/menu/GameSplashScreen.h @@ -0,0 +1,19 @@ +#pragma once +#include "game/GameList.h" +#include +#include +class GameSplashScreen : public GuiFrame, public sigslot::has_slots<> { +public: + GameSplashScreen(int32_t w, int32_t h, gameInfo * info, bool onTV); + virtual ~GameSplashScreen(); + void OnSplashScreenFadeInDone(GuiElement * element); + virtual void draw(CVideo * v); + sigslot::signal3 gameGameSplashScreenFinished; +private: + GuiImage bgImageColor; + GuiImageData* splashScreenData = NULL; + gameInfo * info = NULL; + bool launchGame = false; + uint32_t frameCounter = 0; + bool onTV = false; +}; diff --git a/src/menu/MainWindow.cpp b/src/menu/MainWindow.cpp index 44d442f..b07e227 100644 --- a/src/menu/MainWindow.cpp +++ b/src/menu/MainWindow.cpp @@ -26,6 +26,7 @@ #include #include #include "utils/AsyncExecutor.h" +#include "GameSplashScreen.h" MainWindow::MainWindow(int32_t w, int32_t h) : width(w) @@ -251,11 +252,11 @@ void MainWindow::SetupMainView() { if(currentTvFrame != currentDrcFrame) { currentTvFrame->gameSelectionChanged.connect(this, &MainWindow::OnGameSelectionChange); - currentTvFrame->gameLaunchClicked.connect(this, &MainWindow::OnGameLaunch); + currentTvFrame->gameLaunchClicked.connect(this, &MainWindow::OnGameLaunchSplashScreen); } currentDrcFrame->gameSelectionChanged.connect(this, &MainWindow::OnGameSelectionChange); - currentDrcFrame->gameLaunchClicked.connect(this, &MainWindow::OnGameLaunch); + currentDrcFrame->gameLaunchClicked.connect(this, &MainWindow::OnGameLaunchSplashScreen); mainSwitchButtonFrame = new MainDrcButtonsFrame(width, height); mainSwitchButtonFrame->settingsButtonClicked.connect(this, &MainWindow::OnSettingsButtonClicked); @@ -338,9 +339,9 @@ void MainWindow::OnLayoutSwitchEffectFinish(GuiElement *element) { currentDrcFrame->gameLaunchClicked.disconnect(this); currentTvFrame->gameSelectionChanged.connect(this, &MainWindow::OnGameSelectionChange); - currentTvFrame->gameLaunchClicked.connect(this, &MainWindow::OnGameLaunch); + currentTvFrame->gameLaunchClicked.connect(this, &MainWindow::OnGameLaunchSplashScreen); currentDrcFrame->gameSelectionChanged.connect(this, &MainWindow::OnGameSelectionChange); - currentDrcFrame->gameLaunchClicked.connect(this, &MainWindow::OnGameLaunch); + currentDrcFrame->gameLaunchClicked.connect(this, &MainWindow::OnGameLaunchSplashScreen); } void MainWindow::OnOpenEffectFinish(GuiElement *element) { @@ -377,11 +378,52 @@ void MainWindow::OnGameSelectionChange(GuiTitleBrowser *element, uint64_t select extern "C" void _SYSLaunchTitleByPathFromLauncher(const char * path, int len, int); -void MainWindow::OnGameLaunch(GuiTitleBrowser *element, uint64_t titleID) { +void MainWindow::OnGameLaunchSplashScreen(GuiTitleBrowser * element, uint64_t titleID) { + gameInfo * info = gameList.getGameInfo(titleID); + if(info != NULL) { + uint64_t ownTitleId = OSGetTitleID(); + if (ownTitleId == HBL_TITLE_ID || + ownTitleId == MII_MAKER_JPN_TITLE_ID || + ownTitleId == MII_MAKER_USA_TITLE_ID || + ownTitleId == MII_MAKER_EUR_TITLE_ID) { + OnGameLaunch(titleID); + } else { + GameSplashScreen * gameSettingsDRC = new GameSplashScreen(width,height,info, false); + gameSettingsDRC->setEffect(EFFECT_FADE, 15, 255); + gameSettingsDRC->setState(GuiElement::STATE_DISABLED); + gameSettingsDRC->effectFinished.connect(this, &MainWindow::OnOpenEffectFinish); + gameSettingsDRC->gameGameSplashScreenFinished.connect(this, &MainWindow::OnGameLaunchSplashScreenFinished); + appendDrc(gameSettingsDRC); + + GameSplashScreen * gameSettingsTV = new GameSplashScreen(width,height,info, true); + gameSettingsTV->setEffect(EFFECT_FADE, 15, 255); + gameSettingsTV->setState(GuiElement::STATE_DISABLED); + gameSettingsTV->effectFinished.connect(this, &MainWindow::OnOpenEffectFinish); + gameSettingsTV->gameGameSplashScreenFinished.connect(this, &MainWindow::OnGameLaunchSplashScreenFinished); + appendTv(gameSettingsTV); + } + } else { + DEBUG_FUNCTION_LINE("Failed to find gameInfo for titleId %016llX\n", titleID); + } +} + +void MainWindow::OnGameLaunchSplashScreenFinished(GuiElement * element, gameInfo * info, bool launchGame) { + if(info == NULL) { + return; + } + if(launchGame) { + OnGameLaunch(info->titleId); + } + if(element) { + element->setState(GuiElement::STATE_DISABLED); + element->setEffect(EFFECT_FADE, 15, 255); + element->effectFinished.connect(this, &MainWindow::OnCloseEffectFinish); + } +} +void MainWindow::OnGameLaunch(uint64_t titleID) { gameInfo * info = gameList.getGameInfo(titleID); if(info != NULL) { uint64_t titleID = OSGetTitleID(); - if (titleID == HBL_TITLE_ID || titleID == MII_MAKER_JPN_TITLE_ID || titleID == MII_MAKER_USA_TITLE_ID || @@ -391,5 +433,7 @@ void MainWindow::OnGameLaunch(GuiTitleBrowser *element, uint64_t titleID) { const char* path = info->gamePath.c_str(); _SYSLaunchTitleByPathFromLauncher(path, strlen(path),0); } + } else { + DEBUG_FUNCTION_LINE("Failed to find gameInfo for titleId %016llX\n", titleID); } } diff --git a/src/menu/MainWindow.h b/src/menu/MainWindow.h index e1a24e8..a89a3f9 100644 --- a/src/menu/MainWindow.h +++ b/src/menu/MainWindow.h @@ -117,8 +117,11 @@ private: void OnOpenEffectFinish(GuiElement *element); void OnCloseEffectFinish(GuiElement *element); - void OnGameLaunch(GuiTitleBrowser *element, uint64_t gameIdx); - void OnGameSelectionChange(GuiTitleBrowser *element, uint64_t selectedIdx); + void OnGameLaunch(uint64_t titleId); + void OnGameLaunchSplashScreenFinished(GuiElement * element, gameInfo * info, bool launchGame); + void OnGameLaunchSplashScreen(GuiTitleBrowser *element, uint64_t titleId); + + void OnGameSelectionChange(GuiTitleBrowser *element, uint64_t titleId); void OnSettingsButtonClicked(GuiElement *element); void OnLayoutSwitchClicked(GuiElement *element);