2013-06-02 11:43:15 +00:00
// Copyright (c) 2013- PPSSPP Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0 or later versions.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
2014-06-21 21:03:50 +00:00
# include <algorithm>
2017-02-24 19:50:27 +00:00
# include "ppsspp_config.h"
2020-10-01 11:05:04 +00:00
2020-10-04 21:24:14 +00:00
# include "Common/Render/DrawBuffer.h"
2020-10-04 18:48:47 +00:00
# include "Common/UI/Context.h"
# include "Common/UI/View.h"
# include "Common/UI/ViewGroup.h"
2020-10-01 11:05:04 +00:00
# include "Common/Data/Text/I18n.h"
2023-11-27 00:10:52 +00:00
# include "Common/Data/Text/Parsers.h"
2020-10-01 11:05:04 +00:00
# include "Common/Data/Encoding/Utf8.h"
2020-10-04 18:48:47 +00:00
# include "Common/File/FileUtil.h"
2021-01-31 20:27:07 +00:00
# include "Common/StringUtils.h"
2020-10-04 08:30:18 +00:00
# include "Common/System/System.h"
2024-09-02 21:04:40 +00:00
# include "Common/System/OSD.h"
2023-03-24 19:05:48 +00:00
# include "Common/System/Request.h"
2020-10-04 08:30:18 +00:00
# include "Common/System/NativeApp.h"
2017-03-26 17:02:34 +00:00
# include "Core/Config.h"
2021-01-31 20:27:07 +00:00
# include "Core/Reporting.h"
2017-03-26 17:02:34 +00:00
# include "Core/System.h"
2021-09-06 17:47:06 +00:00
# include "Core/Loaders.h"
2023-10-22 17:10:42 +00:00
# include "Core/Util/GameDB.h"
2024-04-09 09:58:35 +00:00
# include "Core/HLE/Plugins.h"
2023-10-22 17:10:42 +00:00
# include "UI/OnScreenDisplay.h"
2016-06-19 22:18:35 +00:00
# include "UI/CwCheatScreen.h"
2013-06-08 20:42:31 +00:00
# include "UI/EmuScreen.h"
# include "UI/GameScreen.h"
# include "UI/GameSettingsScreen.h"
# include "UI/GameInfoCache.h"
2013-07-15 15:41:24 +00:00
# include "UI/MiscScreens.h"
2013-06-10 20:06:51 +00:00
# include "UI/MainScreen.h"
2014-06-22 15:02:04 +00:00
# include "UI/BackgroundAudio.h"
2022-11-21 19:15:22 +00:00
# include "UI/SavedataScreen.h"
2021-01-29 23:03:52 +00:00
# include "Core/Reporting.h"
2014-06-22 15:02:04 +00:00
2024-09-18 11:37:38 +00:00
GameScreen : : GameScreen ( const Path & gamePath , bool inGame ) : UIDialogScreenWithGameBackground ( gamePath ) , inGame_ ( inGame ) {
2020-08-02 17:44:48 +00:00
g_BackgroundAudio . SetGame ( gamePath ) ;
2023-12-10 20:57:05 +00:00
System_PostUIMessage ( UIMessage : : GAME_SELECTED , gamePath . ToString ( ) ) ;
2014-06-22 15:02:04 +00:00
}
GameScreen : : ~ GameScreen ( ) {
2021-08-21 18:58:25 +00:00
if ( CRC32string = = " ... " ) {
Reporting : : CancelCRC ( ) ;
}
2023-12-10 20:57:05 +00:00
System_PostUIMessage ( UIMessage : : GAME_SELECTED , " " ) ;
2014-06-22 15:02:04 +00:00
}
2021-01-29 23:03:52 +00:00
template < typename I > std : : string int2hexstr ( I w , size_t hex_len = sizeof ( I ) < < 1 ) {
static const char * digits = " 0123456789ABCDEF " ;
std : : string rc ( hex_len , ' 0 ' ) ;
for ( size_t i = 0 , j = ( hex_len - 1 ) * 4 ; i < hex_len ; + + i , j - = 4 )
rc [ i ] = digits [ ( w > > j ) & 0x0f ] ;
return rc ;
}
void GameScreen : : update ( ) {
UIScreen : : update ( ) ;
// Has the user requested a CRC32?
if ( CRC32string = = " ... " ) {
// Wait until the CRC32 is ready. It might take time on some devices.
if ( Reporting : : HasCRC ( gamePath_ ) ) {
uint32_t crcvalue = Reporting : : RetrieveCRC ( gamePath_ ) ;
CRC32string = int2hexstr ( crcvalue ) ;
2024-10-10 12:36:43 +00:00
if ( tvCRC_ ) {
tvCRC_ - > SetVisibility ( UI : : V_VISIBLE ) ;
tvCRC_ - > SetText ( CRC32string ) ;
}
2024-09-02 20:48:47 +00:00
if ( tvCRCCopy_ ) {
tvCRCCopy_ - > SetVisibility ( UI : : V_VISIBLE ) ;
}
2024-01-30 18:09:11 +00:00
if ( btnCalcCRC_ ) {
btnCalcCRC_ - > SetVisibility ( UI : : V_GONE ) ;
}
2021-01-29 23:03:52 +00:00
}
}
}
2013-06-08 20:42:31 +00:00
void GameScreen : : CreateViews ( ) {
2024-01-28 15:23:27 +00:00
std : : shared_ptr < GameInfo > info = g_gameInfoCache - > GetInfo ( NULL , gamePath_ , GameInfoFlags : : PARAM_SFO | GameInfoFlags : : ICON | GameInfoFlags : : BG ) ;
2013-06-08 20:42:31 +00:00
2024-01-31 21:08:26 +00:00
if ( info - > Ready ( GameInfoFlags : : PARAM_SFO ) ) {
2017-01-31 23:39:59 +00:00
saveDirs = info - > GetSaveDataDirectories ( ) ; // Get's very heavy, let's not do it in update()
2020-06-29 20:47:34 +00:00
}
2017-01-31 23:39:59 +00:00
2023-04-05 22:34:50 +00:00
auto di = GetI18NCategory ( I18NCat : : DIALOG ) ;
auto ga = GetI18NCategory ( I18NCat : : GAME ) ;
2013-07-15 22:29:00 +00:00
2013-06-08 20:42:31 +00:00
// Information in the top left.
// Back button to the bottom left.
// Scrolling action menu to the right.
using namespace UI ;
Margins actionMenuMargins ( 0 , 100 , 15 , 0 ) ;
root_ = new LinearLayout ( ORIENT_HORIZONTAL ) ;
ViewGroup * leftColumn = new AnchorLayout ( new LinearLayoutParams ( 1.0f ) ) ;
root_ - > Add ( leftColumn ) ;
2024-10-10 12:36:43 +00:00
bool fileTypeSupportCRC = false ;
if ( info ) {
switch ( info - > fileType ) {
case IdentifiedFileType : : PSP_PBP :
case IdentifiedFileType : : PSP_PBP_DIRECTORY :
case IdentifiedFileType : : PSP_ISO_NP :
case IdentifiedFileType : : PSP_ISO :
fileTypeSupportCRC = true ;
break ;
default :
break ;
}
}
2015-07-01 21:26:55 +00:00
leftColumn - > Add ( new Choice ( di - > T ( " Back " ) , " " , false , new AnchorLayoutParams ( 150 , WRAP_CONTENT , 10 , NONE , NONE , 10 ) ) ) - > OnClick . Handle ( this , & GameScreen : : OnSwitchBack ) ;
2024-01-31 21:08:26 +00:00
if ( info - > Ready ( GameInfoFlags : : PARAM_SFO ) ) {
2023-11-26 20:58:21 +00:00
ViewGroup * badgeHolder = new LinearLayout ( ORIENT_HORIZONTAL , new AnchorLayoutParams ( 10 , 10 , 110 , NONE ) ) ;
LinearLayout * mainGameInfo = new LinearLayout ( ORIENT_VERTICAL , new LinearLayoutParams ( 1.0f ) ) ;
mainGameInfo - > SetSpacing ( 3.0f ) ;
2023-11-27 00:10:52 +00:00
// Need an explicit size here because homebrew uses screenshots as icons.
badgeHolder - > Add ( new GameIconView ( gamePath_ , 2.0f , new LinearLayoutParams ( 144 * 2 , 80 * 2 , UI : : Margins ( 0 ) ) ) ) ;
2023-11-26 20:58:21 +00:00
badgeHolder - > Add ( mainGameInfo ) ;
leftColumn - > Add ( badgeHolder ) ;
2016-08-07 21:31:54 +00:00
LinearLayout * infoLayout = new LinearLayout ( ORIENT_VERTICAL , new AnchorLayoutParams ( 10 , 200 , NONE , NONE ) ) ;
leftColumn - > Add ( infoLayout ) ;
2023-11-26 20:58:21 +00:00
// TODO: Add non-translated title here if available in gameDB.
tvTitle_ = mainGameInfo - > Add ( new TextView ( info - > GetTitle ( ) , ALIGN_LEFT | FLAG_WRAP_TEXT , false , new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT ) ) ) ;
2015-02-15 10:21:17 +00:00
tvTitle_ - > SetShadow ( true ) ;
2023-11-26 20:58:21 +00:00
tvID_ = mainGameInfo - > Add ( new TextView ( " " , ALIGN_LEFT | FLAG_WRAP_TEXT , true , new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT ) ) ) ;
2022-03-11 06:23:42 +00:00
tvID_ - > SetShadow ( true ) ;
2023-11-26 20:58:21 +00:00
tvRegion_ = mainGameInfo - > Add ( new TextView ( " " , ALIGN_LEFT , true , new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT ) ) ) ;
tvRegion_ - > SetShadow ( true ) ;
tvGameSize_ = mainGameInfo - > Add ( new TextView ( " ... " , ALIGN_LEFT , true , new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT ) ) ) ;
tvGameSize_ - > SetShadow ( true ) ;
2013-12-08 06:48:12 +00:00
// This one doesn't need to be updated.
2021-05-05 23:31:38 +00:00
infoLayout - > Add ( new TextView ( gamePath_ . ToVisualString ( ) , ALIGN_LEFT | FLAG_WRAP_TEXT , true , new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT ) ) ) - > SetShadow ( true ) ;
2016-08-07 21:31:54 +00:00
tvSaveDataSize_ = infoLayout - > Add ( new TextView ( " ... " , ALIGN_LEFT , true , new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT ) ) ) ;
2015-02-15 10:21:17 +00:00
tvSaveDataSize_ - > SetShadow ( true ) ;
2016-08-07 21:31:54 +00:00
tvInstallDataSize_ = infoLayout - > Add ( new TextView ( " " , ALIGN_LEFT , true , new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT ) ) ) ;
2015-02-15 10:21:17 +00:00
tvInstallDataSize_ - > SetShadow ( true ) ;
2016-08-07 21:31:54 +00:00
tvInstallDataSize_ - > SetVisibility ( V_GONE ) ;
2023-11-20 10:46:36 +00:00
tvPlayTime_ = infoLayout - > Add ( new TextView ( " " , ALIGN_LEFT , true , new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT ) ) ) ;
tvPlayTime_ - > SetShadow ( true ) ;
tvPlayTime_ - > SetVisibility ( V_GONE ) ;
2024-09-02 20:48:47 +00:00
LinearLayout * crcHoriz = infoLayout - > Add ( new LinearLayout ( ORIENT_HORIZONTAL ) ) ;
2024-10-10 12:36:43 +00:00
if ( fileTypeSupportCRC ) {
// CRC button makes sense.
tvCRC_ = crcHoriz - > Add ( new TextView ( " " , ALIGN_LEFT , true , new LinearLayoutParams ( 0.0 , G_VCENTER ) ) ) ;
tvCRC_ - > SetShadow ( true ) ;
Visibility crcVisibility = Reporting : : HasCRC ( gamePath_ ) ? V_VISIBLE : V_GONE ;
tvCRC_ - > SetVisibility ( crcVisibility ) ;
if ( System_GetPropertyBool ( SYSPROP_HAS_TEXT_CLIPBOARD ) ) {
tvCRCCopy_ = crcHoriz - > Add ( new Button ( di - > T ( " Copy to clipboard " ) , new LinearLayoutParams ( 0.0 , G_VCENTER ) ) ) ;
tvCRCCopy_ - > OnClick . Add ( [ this ] ( UI : : EventParams & ) {
u32 crc = Reporting : : RetrieveCRC ( gamePath_ ) ;
char buffer [ 16 ] ;
snprintf ( buffer , sizeof ( buffer ) , " %08X " , crc ) ;
System_CopyStringToClipboard ( buffer ) ;
// Success indication. Not worth a translatable string.
g_OSD . Show ( OSDType : : MESSAGE_SUCCESS , buffer , 1.0f ) ;
return UI : : EVENT_DONE ;
} ) ;
tvCRCCopy_ - > SetVisibility ( crcVisibility ) ;
tvCRCCopy_ - > SetScale ( 0.82f ) ;
} else {
tvCRCCopy_ = nullptr ;
}
2024-09-02 20:48:47 +00:00
}
2023-10-28 11:50:57 +00:00
tvVerified_ = infoLayout - > Add ( new NoticeView ( NoticeLevel : : INFO , ga - > T ( " Click \" Calculate CRC \" to verify ISO " ) , " " , new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT ) ) ) ;
2023-10-22 17:10:42 +00:00
tvVerified_ - > SetVisibility ( UI : : V_GONE ) ;
2024-01-31 22:17:51 +00:00
tvVerified_ - > SetSquishy ( true ) ;
2024-04-09 09:58:35 +00:00
// Show plugin info, if any. Later might add checkboxes.
auto plugins = HLEPlugins : : FindPlugins ( info - > id , g_Config . sLanguageIni ) ;
if ( ! plugins . empty ( ) ) {
auto sy = GetI18NCategory ( I18NCat : : SYSTEM ) ;
infoLayout - > Add ( new TextView ( sy - > T ( " Plugins " ) , ALIGN_LEFT , true ) ) ;
for ( const auto & plugin : plugins ) {
infoLayout - > Add ( new TextView ( ApplySafeSubstitutions ( " * %1 " , plugin . name ) , ALIGN_LEFT , true ) ) ;
}
}
2016-08-07 20:58:56 +00:00
} else {
tvTitle_ = nullptr ;
2024-02-01 00:23:34 +00:00
tvID_ = nullptr ;
2016-08-07 20:58:56 +00:00
tvGameSize_ = nullptr ;
tvSaveDataSize_ = nullptr ;
tvInstallDataSize_ = nullptr ;
tvRegion_ = nullptr ;
2023-11-20 10:46:36 +00:00
tvPlayTime_ = nullptr ;
2021-01-31 20:27:07 +00:00
tvCRC_ = nullptr ;
2024-09-02 20:48:47 +00:00
tvCRCCopy_ = nullptr ;
2024-02-01 00:23:34 +00:00
tvVerified_ = nullptr ;
2013-06-08 20:42:31 +00:00
}
ViewGroup * rightColumn = new ScrollView ( ORIENT_VERTICAL , new LinearLayoutParams ( 300 , FILL_PARENT , actionMenuMargins ) ) ;
root_ - > Add ( rightColumn ) ;
2023-03-21 09:42:23 +00:00
2013-10-16 17:02:51 +00:00
LinearLayout * rightColumnItems = new LinearLayout ( ORIENT_VERTICAL ) ;
rightColumnItems - > SetSpacing ( 0.0f ) ;
2013-06-08 20:42:31 +00:00
rightColumn - > Add ( rightColumnItems ) ;
2016-08-07 20:58:56 +00:00
2024-09-18 13:17:20 +00:00
if ( ! inGame_ ) {
rightColumnItems - > Add ( new Choice ( ga - > T ( " Play " ) ) ) - > OnClick . Handle ( this , & GameScreen : : OnPlay ) ;
}
2016-08-07 20:58:56 +00:00
2017-03-26 17:02:34 +00:00
btnGameSettings_ = rightColumnItems - > Add ( new Choice ( ga - > T ( " Game Settings " ) ) ) ;
btnGameSettings_ - > OnClick . Handle ( this , & GameScreen : : OnGameSettings ) ;
2024-09-18 11:37:38 +00:00
2017-03-26 17:02:34 +00:00
btnDeleteGameConfig_ = rightColumnItems - > Add ( new Choice ( ga - > T ( " Delete Game Config " ) ) ) ;
btnDeleteGameConfig_ - > OnClick . Handle ( this , & GameScreen : : OnDeleteConfig ) ;
2024-09-18 11:37:38 +00:00
if ( inGame_ )
btnDeleteGameConfig_ - > SetEnabled ( false ) ;
2017-03-26 17:02:34 +00:00
btnCreateGameConfig_ = rightColumnItems - > Add ( new Choice ( ga - > T ( " Create Game Config " ) ) ) ;
btnCreateGameConfig_ - > OnClick . Handle ( this , & GameScreen : : OnCreateConfig ) ;
2024-09-18 11:37:38 +00:00
if ( inGame_ )
btnCreateGameConfig_ - > SetEnabled ( false ) ;
2017-03-26 17:02:34 +00:00
btnGameSettings_ - > SetVisibility ( V_GONE ) ;
btnDeleteGameConfig_ - > SetVisibility ( V_GONE ) ;
btnCreateGameConfig_ - > SetVisibility ( V_GONE ) ;
btnDeleteSaveData_ = new Choice ( ga - > T ( " Delete Save Data " ) ) ;
rightColumnItems - > Add ( btnDeleteSaveData_ ) - > OnClick . Handle ( this , & GameScreen : : OnDeleteSaveData ) ;
btnDeleteSaveData_ - > SetVisibility ( V_GONE ) ;
2016-08-07 20:58:56 +00:00
2020-06-29 20:47:34 +00:00
otherChoices_ . clear ( ) ;
2016-08-07 20:58:56 +00:00
2024-09-18 11:37:38 +00:00
// Don't want to be able to delete the game while it's running.
Choice * deleteChoice = rightColumnItems - > Add ( AddOtherChoice ( new Choice ( ga - > T ( " Delete Game " ) ) ) ) ;
deleteChoice - > OnClick . Handle ( this , & GameScreen : : OnDeleteGame ) ;
if ( inGame_ ) {
deleteChoice - > SetEnabled ( false ) ;
}
2023-03-21 09:54:43 +00:00
if ( System_GetPropertyBool ( SYSPROP_CAN_CREATE_SHORTCUT ) ) {
2023-08-18 08:42:50 +00:00
rightColumnItems - > Add ( AddOtherChoice ( new Choice ( ga - > T ( " Create Shortcut " ) ) ) ) - > OnClick . Add ( [ = ] ( UI : : EventParams & e ) {
2024-01-28 15:23:27 +00:00
std : : shared_ptr < GameInfo > info = g_gameInfoCache - > GetInfo ( NULL , gamePath_ , GameInfoFlags : : PARAM_SFO ) ;
if ( info - > Ready ( GameInfoFlags : : PARAM_SFO ) ) {
// TODO: Should we block on Ready?
2023-08-18 08:42:50 +00:00
System_CreateGameShortcut ( gamePath_ , info - > GetTitle ( ) ) ;
}
return UI : : EVENT_DONE ;
} ) ;
2013-08-26 17:00:16 +00:00
}
2024-09-18 11:37:38 +00:00
2013-09-19 08:10:31 +00:00
if ( isRecentGame ( gamePath_ ) ) {
2024-09-18 11:37:38 +00:00
Choice * removeButton = rightColumnItems - > Add ( AddOtherChoice ( new Choice ( ga - > T ( " Remove From Recent " ) ) ) ) ;
removeButton - > OnClick . Handle ( this , & GameScreen : : OnRemoveFromRecent ) ;
if ( inGame_ ) {
removeButton - > SetEnabled ( false ) ;
}
2013-09-19 08:10:31 +00:00
}
2024-09-18 11:37:38 +00:00
2021-10-09 22:56:39 +00:00
# if (defined(USING_QT_UI) || PPSSPP_PLATFORM(WINDOWS) || PPSSPP_PLATFORM(MAC)) && !PPSSPP_PLATFORM(UWP)
2016-08-07 20:58:56 +00:00
rightColumnItems - > Add ( AddOtherChoice ( new Choice ( ga - > T ( " Show In Folder " ) ) ) ) - > OnClick . Handle ( this , & GameScreen : : OnShowInFolder ) ;
2013-12-11 19:19:30 +00:00
# endif
2016-06-19 22:18:35 +00:00
if ( g_Config . bEnableCheats ) {
2023-12-20 09:35:02 +00:00
auto pa = GetI18NCategory ( I18NCat : : PAUSE ) ;
2016-08-07 20:58:56 +00:00
rightColumnItems - > Add ( AddOtherChoice ( new Choice ( pa - > T ( " Cheats " ) ) ) ) - > OnClick . Handle ( this , & GameScreen : : OnCwCheat ) ;
2016-06-19 22:18:35 +00:00
}
2017-03-26 17:02:34 +00:00
btnSetBackground_ = rightColumnItems - > Add ( new Choice ( ga - > T ( " Use UI background " ) ) ) ;
btnSetBackground_ - > OnClick . Handle ( this , & GameScreen : : OnSetBackground ) ;
btnSetBackground_ - > SetVisibility ( V_GONE ) ;
2021-08-21 18:58:25 +00:00
2023-10-22 17:10:42 +00:00
isHomebrew_ = info & & info - > region > GAMEREGION_MAX ;
if ( fileTypeSupportCRC & & ! isHomebrew_ & & ! Reporting : : HasCRC ( gamePath_ ) ) {
2023-04-05 22:34:50 +00:00
btnCalcCRC_ = rightColumnItems - > Add ( new ChoiceWithValueDisplay ( & CRC32string , ga - > T ( " Calculate CRC " ) , I18NCat : : NONE ) ) ;
2021-08-21 18:58:25 +00:00
btnCalcCRC_ - > OnClick . Handle ( this , & GameScreen : : OnDoCRC32 ) ;
} else {
btnCalcCRC_ = nullptr ;
}
2013-06-08 20:42:31 +00:00
}
2016-08-07 20:58:56 +00:00
UI : : Choice * GameScreen : : AddOtherChoice ( UI : : Choice * choice ) {
otherChoices_ . push_back ( choice ) ;
// While loading.
choice - > SetVisibility ( UI : : V_GONE ) ;
return choice ;
}
2017-03-25 05:02:22 +00:00
UI : : EventReturn GameScreen : : OnCreateConfig ( UI : : EventParams & e ) {
2024-01-28 15:23:27 +00:00
std : : shared_ptr < GameInfo > info = g_gameInfoCache - > GetInfo ( nullptr , gamePath_ , GameInfoFlags : : PARAM_SFO ) ;
if ( ! info - > Ready ( GameInfoFlags : : PARAM_SFO ) ) {
2017-03-25 05:02:22 +00:00
return UI : : EVENT_SKIPPED ;
}
2014-12-14 19:33:20 +00:00
g_Config . createGameConfig ( info - > id ) ;
2019-07-14 22:04:09 +00:00
g_Config . saveGameConfig ( info - > id , info - > GetTitle ( ) ) ;
2015-09-10 15:17:26 +00:00
info - > hasConfig = true ;
2014-12-19 13:52:44 +00:00
2014-12-14 19:33:20 +00:00
screenManager ( ) - > topScreen ( ) - > RecreateViews ( ) ;
return UI : : EVENT_DONE ;
}
2017-03-25 05:02:22 +00:00
void GameScreen : : CallbackDeleteConfig ( bool yes ) {
if ( yes ) {
2024-01-28 15:23:27 +00:00
std : : shared_ptr < GameInfo > info = g_gameInfoCache - > GetInfo ( nullptr , gamePath_ , GameInfoFlags : : PARAM_SFO ) ;
if ( ! info - > Ready ( GameInfoFlags : : PARAM_SFO ) ) {
2017-03-25 05:02:22 +00:00
return ;
}
2014-12-14 19:33:20 +00:00
g_Config . deleteGameConfig ( info - > id ) ;
2015-10-03 20:56:18 +00:00
info - > hasConfig = false ;
2014-12-14 19:33:20 +00:00
screenManager ( ) - > RecreateAllViews ( ) ;
}
}
UI : : EventReturn GameScreen : : OnDeleteConfig ( UI : : EventParams & e )
{
2023-04-05 22:34:50 +00:00
auto di = GetI18NCategory ( I18NCat : : DIALOG ) ;
auto ga = GetI18NCategory ( I18NCat : : GAME ) ;
2014-12-14 19:33:20 +00:00
screenManager ( ) - > push (
2022-11-29 15:29:43 +00:00
new PromptScreen ( gamePath_ , di - > T ( " DeleteConfirmGameConfig " , " Do you really want to delete the settings for this game? " ) , ga - > T ( " ConfirmDelete " ) , di - > T ( " Cancel " ) ,
2016-10-12 09:32:24 +00:00
std : : bind ( & GameScreen : : CallbackDeleteConfig , this , std : : placeholders : : _1 ) ) ) ;
2014-12-14 19:33:20 +00:00
return UI : : EVENT_DONE ;
}
2023-12-11 11:41:44 +00:00
ScreenRenderFlags GameScreen : : render ( ScreenRenderMode mode ) {
ScreenRenderFlags flags = UIScreen : : render ( mode ) ;
2013-06-08 20:42:31 +00:00
2023-04-05 22:34:50 +00:00
auto ga = GetI18NCategory ( I18NCat : : GAME ) ;
2014-08-17 19:29:36 +00:00
2023-12-11 11:41:44 +00:00
Draw : : DrawContext * draw = screenManager ( ) - > getDrawContext ( ) ;
2014-08-17 19:29:36 +00:00
2024-01-28 15:23:27 +00:00
std : : shared_ptr < GameInfo > info = g_gameInfoCache - > GetInfo ( draw , gamePath_ , GameInfoFlags : : BG | GameInfoFlags : : SIZE | GameInfoFlags : : UNCOMPRESSED_SIZE ) ;
2013-06-09 11:41:15 +00:00
2019-10-11 15:34:38 +00:00
if ( tvTitle_ ) {
2022-03-11 06:23:42 +00:00
tvTitle_ - > SetText ( info - > GetTitle ( ) ) ;
2013-06-09 11:41:15 +00:00
}
2024-01-31 22:17:51 +00:00
if ( info - > Ready ( GameInfoFlags : : SIZE | GameInfoFlags : : UNCOMPRESSED_SIZE ) ) {
2013-06-09 10:41:12 +00:00
char temp [ 256 ] ;
2020-06-29 20:47:34 +00:00
if ( tvGameSize_ ) {
2024-01-19 12:44:49 +00:00
snprintf ( temp , sizeof ( temp ) , " %s: %s " , ga - > T_cstr ( " Game " ) , NiceSizeFormat ( info - > gameSizeOnDisk ) . c_str ( ) ) ;
2023-11-27 00:10:52 +00:00
if ( info - > gameSizeUncompressed ! = info - > gameSizeOnDisk ) {
size_t len = strlen ( temp ) ;
2024-01-19 12:44:49 +00:00
snprintf ( temp + len , sizeof ( temp ) - len , " (%s: %s) " , ga - > T_cstr ( " Uncompressed " ) , NiceSizeFormat ( info - > gameSizeUncompressed ) . c_str ( ) ) ;
2023-11-27 00:10:52 +00:00
}
2020-06-29 20:47:34 +00:00
tvGameSize_ - > SetText ( temp ) ;
}
if ( tvSaveDataSize_ ) {
2024-02-01 00:23:34 +00:00
if ( info - > saveDataSize > 0 ) {
2024-01-19 12:44:49 +00:00
snprintf ( temp , sizeof ( temp ) , " %s: %s " , ga - > T_cstr ( " SaveData " ) , NiceSizeFormat ( info - > saveDataSize ) . c_str ( ) ) ;
2024-02-01 00:23:34 +00:00
tvSaveDataSize_ - > SetText ( temp ) ;
} else {
tvSaveDataSize_ - > SetVisibility ( UI : : V_GONE ) ;
}
2020-06-29 20:47:34 +00:00
}
if ( info - > installDataSize > 0 & & tvInstallDataSize_ ) {
2024-01-19 12:44:49 +00:00
snprintf ( temp , sizeof ( temp ) , " %s: %1.2f %s " , ga - > T_cstr ( " InstallData " ) , ( float ) ( info - > installDataSize ) / 1024.f / 1024.f , ga - > T_cstr ( " MB " ) ) ;
2013-10-03 12:44:16 +00:00
tvInstallDataSize_ - > SetText ( temp ) ;
2016-08-07 21:31:54 +00:00
tvInstallDataSize_ - > SetVisibility ( UI : : V_VISIBLE ) ;
2013-10-03 12:44:16 +00:00
}
2013-06-09 10:41:12 +00:00
}
2013-12-10 16:23:03 +00:00
2020-06-29 20:47:34 +00:00
if ( tvRegion_ ) {
if ( info - > region > = 0 & & info - > region < GAMEREGION_MAX & & info - > region ! = GAMEREGION_OTHER ) {
static const char * regionNames [ GAMEREGION_MAX ] = {
" Japan " ,
" USA " ,
" Europe " ,
" Hong Kong " ,
" Asia " ,
" Korea "
} ;
tvRegion_ - > SetText ( ga - > T ( regionNames [ info - > region ] ) ) ;
} else if ( info - > region > GAMEREGION_MAX ) {
tvRegion_ - > SetText ( ga - > T ( " Homebrew " ) ) ;
}
2013-12-10 16:23:03 +00:00
}
2016-08-07 20:58:56 +00:00
2023-11-20 10:46:36 +00:00
if ( tvPlayTime_ ) {
std : : string str ;
if ( g_Config . TimeTracker ( ) . GetPlayedTimeString ( info - > id , & str ) ) {
tvPlayTime_ - > SetText ( str ) ;
tvPlayTime_ - > SetVisibility ( UI : : V_VISIBLE ) ;
}
}
2021-05-09 16:38:48 +00:00
if ( tvCRC_ & & Reporting : : HasCRC ( gamePath_ ) ) {
2023-04-05 22:34:50 +00:00
auto rp = GetI18NCategory ( I18NCat : : REPORTING ) ;
2023-10-22 17:10:42 +00:00
uint32_t crcVal = Reporting : : RetrieveCRC ( gamePath_ ) ;
std : : string crc = StringFromFormat ( " %08X " , crcVal ) ;
2022-01-10 19:04:47 +00:00
tvCRC_ - > SetText ( ReplaceAll ( rp - > T ( " FeedbackCRCValue " , " Disc CRC: %1 " ) , " %1 " , crc ) ) ;
2021-01-31 20:27:07 +00:00
tvCRC_ - > SetVisibility ( UI : : V_VISIBLE ) ;
2024-09-02 20:48:47 +00:00
if ( tvCRCCopy_ ) {
tvCRCCopy_ - > SetVisibility ( UI : : V_VISIBLE ) ;
}
2023-10-22 17:10:42 +00:00
// Let's check the CRC in the game database, looking up the ID and also matching the crc.
std : : vector < GameDBInfo > dbInfos ;
2024-01-31 22:17:51 +00:00
if ( tvVerified_ & & info - > Ready ( GameInfoFlags : : PARAM_SFO ) & & g_gameDB . GetGameInfos ( info - > id_version , & dbInfos ) ) {
2023-10-22 17:10:42 +00:00
bool found = false ;
for ( auto & dbInfo : dbInfos ) {
if ( dbInfo . crc = = crcVal ) {
found = true ;
}
}
if ( found ) {
2024-07-07 12:49:47 +00:00
tvVerified_ - > SetText ( ga - > T ( " ISO OK according to the ReDump project " ) ) ;
2023-10-22 17:10:42 +00:00
tvVerified_ - > SetLevel ( NoticeLevel : : SUCCESS ) ;
2023-10-30 06:22:49 +00:00
tvVerified_ - > SetVisibility ( UI : : V_VISIBLE ) ;
2023-10-22 17:10:42 +00:00
} else {
2023-10-30 06:22:49 +00:00
// Like the other messages below, disabled until we have a database we have confidence in.
// tvVerified_->SetText(ga->T("CRC checksum does not match, bad or modified ISO"));
// tvVerified_->SetLevel(NoticeLevel::ERROR);
2024-01-31 22:17:51 +00:00
tvVerified_ - > SetVisibility ( UI : : V_GONE ) ;
2023-10-22 17:10:42 +00:00
}
2024-01-31 22:17:51 +00:00
} else if ( tvVerified_ ) {
2024-07-07 12:49:47 +00:00
// tvVerified_->SetText(ga->T("Game ID unknown - not in the ReDump database"));
2023-10-30 06:22:49 +00:00
// tvVerified_->SetVisibility(UI::V_VISIBLE);
// tvVerified_->SetLevel(NoticeLevel::WARN);
2024-01-31 22:17:51 +00:00
tvVerified_ - > SetVisibility ( UI : : V_GONE ) ;
2023-10-22 17:10:42 +00:00
}
} else if ( ! isHomebrew_ ) {
GameDBInfo dbInfo ;
if ( tvVerified_ ) {
std : : vector < GameDBInfo > dbInfos ;
2024-01-31 22:17:51 +00:00
if ( info - > Ready ( GameInfoFlags : : PARAM_SFO ) & & ! g_gameDB . GetGameInfos ( info - > id_version , & dbInfos ) ) {
2023-10-30 06:22:49 +00:00
// tvVerified_->SetText(ga->T("Game ID unknown - not in the ReDump database"));
// tvVerified_->SetVisibility(UI::V_VISIBLE);
// tvVerified_->SetLevel(NoticeLevel::WARN);
2024-01-31 22:17:51 +00:00
} else if ( info - > Ready ( GameInfoFlags : : UNCOMPRESSED_SIZE ) & & info - > gameSizeUncompressed ! = 0 ) { // don't do this check if info still pending
2023-10-22 17:10:42 +00:00
bool found = false ;
for ( auto & dbInfo : dbInfos ) {
// TODO: Doesn't take CSO/CHD into account.
if ( info - > gameSizeUncompressed = = dbInfo . size ) {
found = true ;
}
}
if ( ! found ) {
2023-10-30 06:22:49 +00:00
// tvVerified_->SetText(ga->T("File size incorrect, bad or modified ISO"));
// tvVerified_->SetVisibility(UI::V_VISIBLE);
// tvVerified_->SetLevel(NoticeLevel::ERROR);
2024-07-14 12:42:59 +00:00
// INFO_LOG(Log::Loader, "File size %d not matching game DB", (int)info->gameSizeUncompressed);
2023-10-22 17:10:42 +00:00
} else {
tvVerified_ - > SetText ( ga - > T ( " Click \" Calculate CRC \" to verify ISO " ) ) ;
tvVerified_ - > SetVisibility ( UI : : V_VISIBLE ) ;
tvVerified_ - > SetLevel ( NoticeLevel : : INFO ) ;
}
}
}
2021-01-31 20:27:07 +00:00
}
2022-03-11 06:23:42 +00:00
if ( tvID_ ) {
tvID_ - > SetText ( ReplaceAll ( info - > id_version , " _ " , " v " ) ) ;
}
2016-08-07 20:58:56 +00:00
if ( ! info - > id . empty ( ) ) {
btnGameSettings_ - > SetVisibility ( info - > hasConfig ? UI : : V_VISIBLE : UI : : V_GONE ) ;
btnDeleteGameConfig_ - > SetVisibility ( info - > hasConfig ? UI : : V_VISIBLE : UI : : V_GONE ) ;
btnCreateGameConfig_ - > SetVisibility ( info - > hasConfig ? UI : : V_GONE : UI : : V_VISIBLE ) ;
if ( saveDirs . size ( ) ) {
btnDeleteSaveData_ - > SetVisibility ( UI : : V_VISIBLE ) ;
}
2017-03-26 17:02:34 +00:00
if ( info - > pic0 . texture | | info - > pic1 . texture ) {
btnSetBackground_ - > SetVisibility ( UI : : V_VISIBLE ) ;
}
2016-08-07 20:58:56 +00:00
}
2019-10-11 15:34:38 +00:00
2024-01-28 15:23:27 +00:00
if ( info - > Ready ( GameInfoFlags : : PARAM_SFO ) ) {
2016-08-07 20:58:56 +00:00
// At this point, the above buttons won't become visible. We can show these now.
for ( UI : : Choice * choice : otherChoices_ ) {
choice - > SetVisibility ( UI : : V_VISIBLE ) ;
}
}
2023-12-11 11:41:44 +00:00
return flags ;
2013-06-09 10:41:12 +00:00
}
2013-12-11 19:19:30 +00:00
UI : : EventReturn GameScreen : : OnShowInFolder ( UI : : EventParams & e ) {
2023-08-24 11:04:41 +00:00
System_ShowFileInFolder ( gamePath_ ) ;
2013-12-11 19:19:30 +00:00
return UI : : EVENT_DONE ;
}
2016-06-19 22:18:35 +00:00
UI : : EventReturn GameScreen : : OnCwCheat ( UI : : EventParams & e ) {
screenManager ( ) - > push ( new CwCheatScreen ( gamePath_ ) ) ;
return UI : : EVENT_DONE ;
}
2021-01-29 23:03:52 +00:00
UI : : EventReturn GameScreen : : OnDoCRC32 ( UI : : EventParams & e ) {
CRC32string = " ... " ;
2021-08-21 18:58:25 +00:00
Reporting : : QueueCRC ( gamePath_ ) ;
2024-01-30 18:09:11 +00:00
if ( btnCalcCRC_ ) {
btnCalcCRC_ - > SetEnabled ( false ) ;
}
2021-01-29 23:03:52 +00:00
return UI : : EVENT_DONE ;
}
2013-06-09 10:41:12 +00:00
UI : : EventReturn GameScreen : : OnSwitchBack ( UI : : EventParams & e ) {
2017-03-20 00:43:03 +00:00
TriggerFinish ( DR_OK ) ;
2013-06-09 10:41:12 +00:00
return UI : : EVENT_DONE ;
2013-06-08 20:42:31 +00:00
}
UI : : EventReturn GameScreen : : OnPlay ( UI : : EventParams & e ) {
screenManager ( ) - > switchScreen ( new EmuScreen ( gamePath_ ) ) ;
return UI : : EVENT_DONE ;
}
UI : : EventReturn GameScreen : : OnGameSettings ( UI : : EventParams & e ) {
2024-01-28 15:23:27 +00:00
std : : shared_ptr < GameInfo > info = g_gameInfoCache - > GetInfo ( NULL , gamePath_ , GameInfoFlags : : PARAM_SFO ) ;
if ( info & & info - > Ready ( GameInfoFlags : : PARAM_SFO ) ) {
2024-09-07 13:01:13 +00:00
std : : string discID = info - > GetParamSFO ( ) . GetValueString ( " DISC_ID " ) ;
2021-12-16 19:37:05 +00:00
if ( ( discID . empty ( ) | | ! info - > disc_total ) & & gamePath_ . FilePathContainsNoCase ( " PSP/GAME/ " ) )
2024-01-22 22:46:28 +00:00
discID = g_paramSFO . GenerateFakeID ( gamePath_ ) ;
2014-12-14 19:33:20 +00:00
screenManager ( ) - > push ( new GameSettingsScreen ( gamePath_ , discID , true ) ) ;
2013-06-08 20:42:31 +00:00
}
return UI : : EVENT_DONE ;
}
UI : : EventReturn GameScreen : : OnDeleteSaveData ( UI : : EventParams & e ) {
2024-01-28 15:23:27 +00:00
std : : shared_ptr < GameInfo > info = g_gameInfoCache - > GetInfo ( NULL , gamePath_ , GameInfoFlags : : PARAM_SFO ) ;
2013-06-08 20:42:31 +00:00
if ( info ) {
2014-07-21 18:59:03 +00:00
// Check that there's any savedata to delete
if ( saveDirs . size ( ) ) {
2023-12-20 09:35:02 +00:00
auto di = GetI18NCategory ( I18NCat : : DIALOG ) ;
auto ga = GetI18NCategory ( I18NCat : : GAME ) ;
2014-07-21 18:59:03 +00:00
screenManager ( ) - > push (
2022-11-29 15:29:43 +00:00
new PromptScreen ( gamePath_ , di - > T ( " DeleteConfirmAll " , " Do you really want to delete all \n your save data for this game? " ) , ga - > T ( " ConfirmDelete " ) , di - > T ( " Cancel " ) ,
2016-10-12 09:32:24 +00:00
std : : bind ( & GameScreen : : CallbackDeleteSaveData , this , std : : placeholders : : _1 ) ) ) ;
2014-07-21 18:59:03 +00:00
}
2013-06-08 20:42:31 +00:00
}
RecreateViews ( ) ;
return UI : : EVENT_DONE ;
}
2013-06-09 10:41:12 +00:00
void GameScreen : : CallbackDeleteSaveData ( bool yes ) {
if ( yes ) {
2024-01-28 15:23:27 +00:00
std : : shared_ptr < GameInfo > info = g_gameInfoCache - > GetInfo ( NULL , gamePath_ , GameInfoFlags : : PARAM_SFO ) ;
2013-06-09 10:41:12 +00:00
info - > DeleteAllSaveData ( ) ;
2013-10-09 11:34:36 +00:00
info - > saveDataSize = 0 ;
info - > installDataSize = 0 ;
2013-06-09 10:41:12 +00:00
}
}
2013-06-08 20:42:31 +00:00
UI : : EventReturn GameScreen : : OnDeleteGame ( UI : : EventParams & e ) {
2024-01-28 15:23:27 +00:00
std : : shared_ptr < GameInfo > info = g_gameInfoCache - > GetInfo ( NULL , gamePath_ , GameInfoFlags : : PARAM_SFO ) ;
2024-01-28 15:56:07 +00:00
if ( info - > Ready ( GameInfoFlags : : PARAM_SFO ) ) {
2023-12-20 09:35:02 +00:00
auto di = GetI18NCategory ( I18NCat : : DIALOG ) ;
auto ga = GetI18NCategory ( I18NCat : : GAME ) ;
2024-09-04 15:00:26 +00:00
std : : string prompt ;
prompt = di - > T ( " DeleteConfirmGame " , " Do you really want to delete this game \n from your device? You can't undo this. " ) ;
prompt + = " \n \n " + gamePath_ . ToVisualString ( g_Config . memStickDirectory . c_str ( ) ) ;
2013-06-09 10:41:12 +00:00
screenManager ( ) - > push (
2024-09-04 15:00:26 +00:00
new PromptScreen ( gamePath_ , prompt , ga - > T ( " ConfirmDelete " ) , di - > T ( " Cancel " ) ,
2016-10-12 09:32:24 +00:00
std : : bind ( & GameScreen : : CallbackDeleteGame , this , std : : placeholders : : _1 ) ) ) ;
2013-06-08 20:42:31 +00:00
}
2013-06-09 10:41:12 +00:00
return UI : : EVENT_DONE ;
}
void GameScreen : : CallbackDeleteGame ( bool yes ) {
if ( yes ) {
2024-01-28 15:23:27 +00:00
std : : shared_ptr < GameInfo > info = g_gameInfoCache - > GetInfo ( NULL , gamePath_ , GameInfoFlags : : PARAM_SFO ) ;
2015-06-11 18:22:16 +00:00
info - > Delete ( ) ;
2016-02-14 21:07:10 +00:00
g_gameInfoCache - > Clear ( ) ;
2013-06-10 20:06:51 +00:00
screenManager ( ) - > switchScreen ( new MainScreen ( ) ) ;
2013-06-09 10:41:12 +00:00
}
}
2021-05-05 23:31:38 +00:00
bool GameScreen : : isRecentGame ( const Path & gamePath ) {
2014-06-29 03:44:24 +00:00
if ( g_Config . iMaxRecent < = 0 )
return false ;
2021-05-05 23:31:38 +00:00
const std : : string resolved = File : : ResolvePath ( gamePath . ToString ( ) ) ;
2023-12-12 14:38:50 +00:00
for ( const auto & iso : g_Config . RecentIsos ( ) ) {
2022-07-12 03:44:13 +00:00
const std : : string recent = File : : ResolvePath ( iso ) ;
2018-08-12 15:24:33 +00:00
if ( resolved = = recent )
2013-09-19 08:10:31 +00:00
return true ;
}
return false ;
}
UI : : EventReturn GameScreen : : OnRemoveFromRecent ( UI : : EventParams & e ) {
2021-05-05 23:31:38 +00:00
g_Config . RemoveRecent ( gamePath_ . ToString ( ) ) ;
2018-08-12 15:24:33 +00:00
screenManager ( ) - > switchScreen ( new MainScreen ( ) ) ;
2013-09-19 08:10:31 +00:00
return UI : : EVENT_DONE ;
2013-09-21 16:56:34 +00:00
}
2017-03-26 17:02:34 +00:00
class SetBackgroundPopupScreen : public PopupScreen {
public :
2024-01-19 12:44:49 +00:00
SetBackgroundPopupScreen ( std : : string_view title , const Path & gamePath )
2023-03-21 09:54:43 +00:00
: PopupScreen ( title ) , gamePath_ ( gamePath ) {
timeStart_ = time_now_d ( ) ;
}
2022-09-16 08:14:00 +00:00
const char * tag ( ) const override { return " SetBackgroundPopup " ; }
2017-03-26 17:02:34 +00:00
protected :
bool FillVertical ( ) const override { return false ; }
bool ShowButtons ( ) const override { return false ; }
void CreatePopupContents ( UI : : ViewGroup * parent ) override ;
void update ( ) override ;
private :
2021-05-05 23:31:38 +00:00
Path gamePath_ ;
2017-03-26 17:02:34 +00:00
double timeStart_ ;
double timeDone_ = 0.0 ;
enum class Status {
PENDING ,
DELAY ,
DONE ,
} ;
Status status_ = Status : : PENDING ;
} ;
void SetBackgroundPopupScreen : : CreatePopupContents ( UI : : ViewGroup * parent ) {
2023-04-05 22:34:50 +00:00
auto ga = GetI18NCategory ( I18NCat : : GAME ) ;
2017-03-26 17:02:34 +00:00
parent - > Add ( new UI : : TextView ( ga - > T ( " One moment please... " ) , ALIGN_LEFT | ALIGN_VCENTER , false , new UI : : LinearLayoutParams ( UI : : Margins ( 10 , 0 , 10 , 10 ) ) ) ) ;
}
void SetBackgroundPopupScreen : : update ( ) {
PopupScreen : : update ( ) ;
2024-01-28 15:23:27 +00:00
std : : shared_ptr < GameInfo > info = g_gameInfoCache - > GetInfo ( nullptr , gamePath_ , GameInfoFlags : : BG ) ;
2024-01-28 15:56:07 +00:00
if ( status_ = = Status : : PENDING & & info - > Ready ( GameInfoFlags : : BG ) ) {
2017-03-26 17:02:34 +00:00
GameInfoTex * pic = nullptr ;
if ( info - > pic1 . dataLoaded & & info - > pic1 . data . size ( ) ) {
pic = & info - > pic1 ;
} else if ( info - > pic0 . dataLoaded & & info - > pic0 . data . size ( ) ) {
pic = & info - > pic0 ;
}
if ( pic ) {
2021-05-05 23:31:38 +00:00
const Path bgPng = GetSysDirectory ( DIRECTORY_SYSTEM ) / " background.png " ;
2021-05-09 13:02:46 +00:00
File : : WriteStringToFile ( false , pic - > data , bgPng ) ;
2017-03-26 17:02:34 +00:00
}
2023-03-22 13:14:15 +00:00
UIBackgroundShutdown ( ) ;
2017-03-26 17:02:34 +00:00
// It's worse if it flickers, stay open for at least 1s.
timeDone_ = timeStart_ + 1.0 ;
status_ = Status : : DELAY ;
}
if ( status_ = = Status : : DELAY & & timeDone_ < = time_now_d ( ) ) {
TriggerFinish ( DR_OK ) ;
status_ = Status : : DONE ;
}
}
UI : : EventReturn GameScreen : : OnSetBackground ( UI : : EventParams & e ) {
2023-04-05 22:34:50 +00:00
auto ga = GetI18NCategory ( I18NCat : : GAME ) ;
2017-04-02 17:56:41 +00:00
// This popup is used to prevent any race condition:
// g_gameInfoCache may take time to load the data, and a crash could happen if they exit before then.
2017-03-26 17:02:34 +00:00
SetBackgroundPopupScreen * pop = new SetBackgroundPopupScreen ( ga - > T ( " Setting Background " ) , gamePath_ ) ;
if ( e . v )
pop - > SetPopupOrigin ( e . v ) ;
screenManager ( ) - > push ( pop ) ;
return UI : : EVENT_DONE ;
}