@ -249,6 +249,7 @@ static void DestroyResources();
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
static void SwitchToLanding ( ) ;
static void SwitchToLanding ( ) ;
static ImGuiFullscreen : : FileSelectorFilters GetDiscImageFilters ( ) ;
static ImGuiFullscreen : : FileSelectorFilters GetDiscImageFilters ( ) ;
static ImGuiFullscreen : : FileSelectorFilters GetImageFilters ( ) ;
static void DoStartPath ( std : : string path , std : : string state = std : : string ( ) ,
static void DoStartPath ( std : : string path , std : : string state = std : : string ( ) ,
std : : optional < bool > fast_boot = std : : nullopt ) ;
std : : optional < bool > fast_boot = std : : nullopt ) ;
static void DoResume ( ) ;
static void DoResume ( ) ;
@ -266,6 +267,8 @@ static void DoRequestExit();
static void DoDesktopMode ( ) ;
static void DoDesktopMode ( ) ;
static void DoToggleFullscreen ( ) ;
static void DoToggleFullscreen ( ) ;
static void DoToggleAnalogMode ( ) ;
static void DoToggleAnalogMode ( ) ;
static void DoSetCoverImage ( std : : string entry_path ) ;
static void DoSetCoverImage ( std : : string source_path , std : : string existing_path , std : : string new_path ) ;
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// Settings
// Settings
@ -1079,6 +1082,11 @@ ImGuiFullscreen::FileSelectorFilters FullscreenUI::GetDiscImageFilters()
" *.psexe " , " *.ps-exe " , " *.exe " , " *.psx " , " *.psf " , " *.minipsf " , " *.m3u " , " *.pbp " } ;
" *.psexe " , " *.ps-exe " , " *.exe " , " *.psx " , " *.psf " , " *.minipsf " , " *.m3u " , " *.pbp " } ;
}
}
ImGuiFullscreen : : FileSelectorFilters FullscreenUI : : GetImageFilters ( )
{
return { " *.png " , " *.jpg " , " *.jpeg " , " *.webp " } ;
}
void FullscreenUI : : DoStartPath ( std : : string path , std : : string state , std : : optional < bool > fast_boot )
void FullscreenUI : : DoStartPath ( std : : string path , std : : string state , std : : optional < bool > fast_boot )
{
{
if ( GPUThread : : HasGPUBackend ( ) )
if ( GPUThread : : HasGPUBackend ( ) )
@ -1417,6 +1425,70 @@ void FullscreenUI::DoToggleFullscreen()
Host : : RunOnCPUThread ( [ ] ( ) { Host : : SetFullscreen ( ! Host : : IsFullscreen ( ) ) ; } ) ;
Host : : RunOnCPUThread ( [ ] ( ) { Host : : SetFullscreen ( ! Host : : IsFullscreen ( ) ) ; } ) ;
}
}
void FullscreenUI : : DoSetCoverImage ( std : : string entry_path )
{
OpenFileSelector (
FSUI_ICONSTR ( ICON_FA_IMAGE , " Set Cover Image " ) , false ,
[ entry_path = std : : move ( entry_path ) ] ( std : : string path ) {
if ( path . empty ( ) )
return ;
const auto lock = GameList : : GetLock ( ) ;
const GameList : : Entry * entry = GameList : : GetEntryForPath ( entry_path ) ;
if ( ! entry )
return ;
std : : string existing_path = GameList : : GetCoverImagePathForEntry ( entry ) ;
std : : string new_path = GameList : : GetNewCoverImagePathForEntry ( entry , path . c_str ( ) , false ) ;
if ( ! existing_path . empty ( ) )
{
OpenConfirmMessageDialog (
FSUI_ICONSTR ( ICON_FA_IMAGE , " Set Cover Image " ) ,
FSUI_CSTR ( " A cover already exists for this game. Are you sure that you want to overwrite it? " ) ,
[ path = std : : move ( path ) , existing_path = std : : move ( existing_path ) ,
new_path = std : : move ( new_path ) ] ( bool result ) {
if ( ! result )
return ;
DoSetCoverImage ( std : : move ( path ) , std : : move ( existing_path ) , std : : move ( new_path ) ) ;
} ) ;
}
else
{
DoSetCoverImage ( std : : move ( path ) , std : : move ( existing_path ) , std : : move ( new_path ) ) ;
}
} ,
GetImageFilters ( ) , EmuFolders : : Covers ) ;
}
void FullscreenUI : : DoSetCoverImage ( std : : string source_path , std : : string existing_path , std : : string new_path )
{
Error error ;
if ( ! existing_path . empty ( ) & & existing_path ! = new_path & & FileSystem : : FileExists ( existing_path . c_str ( ) ) )
{
if ( ! FileSystem : : DeleteFile ( existing_path . c_str ( ) , & error ) )
{
ShowToast ( { } , fmt : : format ( FSUI_FSTR ( " Failed to delete existing cover: {} " ) , error . GetDescription ( ) ) ) ;
return ;
}
}
if ( ! FileSystem : : CopyFilePath ( source_path . c_str ( ) , new_path . c_str ( ) , true , & error ) )
{
ShowToast ( { } , fmt : : format ( FSUI_FSTR ( " Failed to copy cover: {} " ) , error . GetDescription ( ) ) ) ;
return ;
}
ShowToast ( { } , FSUI_STR ( " Cover set. " ) ) ;
// Ensure the old one wasn't cached.
if ( ! existing_path . empty ( ) )
ImGuiFullscreen : : InvalidateCachedTexture ( existing_path ) ;
if ( existing_path ! = new_path )
ImGuiFullscreen : : InvalidateCachedTexture ( new_path ) ;
s_state . cover_image_map . clear ( ) ;
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// Landing Window
// Landing Window
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
@ -7726,48 +7798,51 @@ void FullscreenUI::HandleGameListOptions(const GameList::Entry* entry)
ImGuiFullscreen : : ChoiceDialogOptions options = {
ImGuiFullscreen : : ChoiceDialogOptions options = {
{ FSUI_ICONSTR ( ICON_FA_WRENCH , " Game Properties " ) , false } ,
{ FSUI_ICONSTR ( ICON_FA_WRENCH , " Game Properties " ) , false } ,
{ FSUI_ICONSTR ( ICON_FA_FOLDER_OPEN , " Open Containing Directory " ) , false } ,
{ FSUI_ICONSTR ( ICON_FA_FOLDER_OPEN , " Open Containing Directory " ) , false } ,
{ FSUI_ICONSTR ( ICON_FA_IMAGE , " Set Cover Image " ) , false } ,
{ FSUI_ICONSTR ( ICON_FA_PLAY , " Resume Game " ) , false } ,
{ FSUI_ICONSTR ( ICON_FA_PLAY , " Resume Game " ) , false } ,
{ FSUI_ICONSTR ( ICON_FA_UNDO , " Load State " ) , false } ,
{ FSUI_ICONSTR ( ICON_FA_UNDO , " Load State " ) , false } ,
{ FSUI_ICONSTR ( ICON_FA_COMPACT_DISC , " Default Boot " ) , false } ,
{ FSUI_ICONSTR ( ICON_FA_COMPACT_DISC , " Default Boot " ) , false } ,
{ FSUI_ICONSTR ( ICON_FA_LIGHTBULB , " Fast Boot " ) , false } ,
{ FSUI_ICONSTR ( ICON_FA_LIGHTBULB , " Fast Boot " ) , false } ,
{ FSUI_ICONSTR ( ICON_FA_MAGIC , " Slow Boot " ) , false } ,
{ FSUI_ICONSTR ( ICON_FA_MAGIC , " Slow Boot " ) , false } ,
{ FSUI_ICONSTR ( ICON_FA_FOLDER_MINUS , " Reset Play Time " ) , false } ,
{ FSUI_ICONSTR ( ICON_FA_FOLDER_MINUS , " Reset Play Time " ) , false } ,
{ FSUI_ICONSTR ( ICON_FA_WINDOW_CLOSE , " Close Menu " ) , false } ,
} ;
} ;
OpenChoiceDialog (
OpenChoiceDialog ( entry - > title . c_str ( ) , false , std : : move ( options ) ,
entry - > title . c_str ( ) , false , std : : move ( options ) ,
[ entry_path = entry - > path , entry_serial = entry - > serial ] ( s32 index , const std : : string & title ,
[ entry_path = entry - > path , entry_serial = entry - > serial ] ( s32 index , const std : : string & title , bool checked ) {
bool checked ) mutable {
switch ( index )
switch ( index )
{
{
case 0 : // Open Game Properties
case 0 : // Open Game Properties
SwitchToGameSettingsForPath ( entry_path ) ;
SwitchToGameSettingsForPath ( entry_path ) ;
break ;
break ;
case 1 : // Open Containing Directory
case 1 : // Open Containing Directory
ExitFullscreenAndOpenURL ( Path : : CreateFileURL ( Path : : GetDirectory ( entry_path ) ) ) ;
ExitFullscreenAndOpenURL ( Path : : CreateFileURL ( Path : : GetDirectory ( entry_path ) ) ) ;
break ;
break ;
case 2 : // Resume Game
case 2 : // Set Cover Image
DoStartPath ( entry_path , System : : GetGameSaveStateFileName ( entry_serial , - 1 ) ) ;
DoSetCoverImage ( std : : move ( entry_path ) ) ;
break ;
break ;
case 3 : // Load State
case 3 : // Resume Game
OpenLoadStateSelectorForGame ( entry_path ) ;
DoStartPath ( entry_path , System : : GetGameSaveStateFileName ( entry_serial , - 1 ) ) ;
break ;
break ;
case 4 : // Default Boot
case 4 : // Load State
DoStartPath ( entry_path ) ;
OpenLoadStateSelectorForGame ( entry_path ) ;
break ;
break ;
case 5 : // Fast Boot
case 5 : // Default Boot
DoStartPath ( entry_path , { } , true ) ;
DoStartPath ( entry_path ) ;
break ;
break ;
case 6 : // Slow Boot
case 6 : // Fast Boot
DoStartPath ( entry_path , { } , false ) ;
DoStartPath ( entry_path , { } , true ) ;
break ;
break ;
case 7 : // Reset Play Time
case 7 : // Slow Boot
GameList : : ClearPlayedTimeForSerial ( entry_serial ) ;
DoStartPath ( entry_path , { } , false ) ;
break ;
break ;
default :
case 8 : // Reset Play Time
break ;
GameList : : ClearPlayedTimeForSerial ( entry_serial ) ;
}
break ;
} ) ;
default :
break ;
}
} ) ;
}
}
else
else
{
{
@ -7778,19 +7853,22 @@ void FullscreenUI::HandleGameListOptions(const GameList::Entry* entry)
ImGuiFullscreen : : ChoiceDialogOptions options = {
ImGuiFullscreen : : ChoiceDialogOptions options = {
{ FSUI_ICONSTR ( ICON_FA_WRENCH , " Game Properties " ) , false } ,
{ FSUI_ICONSTR ( ICON_FA_WRENCH , " Game Properties " ) , false } ,
{ FSUI_ICONSTR ( ICON_FA_IMAGE , " Set Cover Image " ) , false } ,
{ FSUI_ICONSTR ( ICON_FA_COMPACT_DISC , " Select Disc " ) , false } ,
{ FSUI_ICONSTR ( ICON_FA_COMPACT_DISC , " Select Disc " ) , false } ,
{ FSUI_ICONSTR ( ICON_FA_WINDOW_CLOSE , " Close Menu " ) , false } ,
} ;
} ;
OpenChoiceDialog ( entry - > title . c_str ( ) , false , std : : move ( options ) ,
OpenChoiceDialog ( entry - > title . c_str ( ) , false , std : : move ( options ) ,
[ entry_path = first_disc_entry - > path ,
[ entry_path = first_disc_entry - > path ,
disc_set_name = entry - > path ] ( s32 index , const std : : string & title , bool checked ) {
disc_set_name = entry - > path ] ( s32 index , const std : : string & title , bool checked ) mutable {
switch ( index )
switch ( index )
{
{
case 0 : // Open Game Properties
case 0 : // Open Game Properties
SwitchToGameSettingsForPath ( entry_path ) ;
SwitchToGameSettingsForPath ( entry_path ) ;
break ;
break ;
case 1 : // Select Disc
case 1 : // Set Cover Image
DoSetCoverImage ( std : : move ( disc_set_name ) ) ;
break ;
case 2 : // Select Disc
HandleSelectDiscForDiscSet ( disc_set_name ) ;
HandleSelectDiscForDiscSet ( disc_set_name ) ;
break ;
break ;
default :
default :
@ -8442,6 +8520,7 @@ TRANSLATE_NOOP("FullscreenUI", "900% [540 FPS (NTSC) / 450 FPS (PAL)]");
TRANSLATE_NOOP ( " FullscreenUI " , " 9x " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " 9x " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " 9x (18x Speed) " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " 9x (18x Speed) " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " 9x (for 4K) " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " 9x (for 4K) " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " A cover already exists for this game. Are you sure that you want to overwrite it? " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " A resume save state created at %s was found. \n \n Do you want to load this save and continue? " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " A resume save state created at %s was found. \n \n Do you want to load this save and continue? " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " About " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " About " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " About DuckStation " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " About DuckStation " ) ;
@ -8548,6 +8627,7 @@ TRANSLATE_NOOP("FullscreenUI", "Copy Global Settings");
TRANSLATE_NOOP ( " FullscreenUI " , " Copy Settings " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " Copy Settings " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " Could not find any CD/DVD-ROM devices. Please ensure you have a drive connected and sufficient permissions to access it. " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " Could not find any CD/DVD-ROM devices. Please ensure you have a drive connected and sufficient permissions to access it. " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " Cover Settings " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " Cover Settings " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " Cover set. " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " Covers Directory " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " Covers Directory " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " Create " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " Create " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " Create New... " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " Create New... " ) ;
@ -8660,7 +8740,9 @@ TRANSLATE_NOOP("FullscreenUI", "Exit DuckStation");
TRANSLATE_NOOP ( " FullscreenUI " , " Exit Without Saving " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " Exit Without Saving " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " Exits Big Picture mode, returning to the desktop interface. " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " Exits Big Picture mode, returning to the desktop interface. " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " FMV Chroma Smoothing " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " FMV Chroma Smoothing " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " Failed to copy cover: {} " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " Failed to copy text to clipboard. " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " Failed to copy text to clipboard. " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " Failed to delete existing cover: {} " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " Failed to delete save state. " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " Failed to delete save state. " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " Failed to delete {}. " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " Failed to delete {}. " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " Failed to load '{}'. " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " Failed to load '{}'. " ) ;
@ -8942,6 +9024,7 @@ TRANSLATE_NOOP("FullscreenUI", "Selects the type of emulated controller for this
TRANSLATE_NOOP ( " FullscreenUI " , " Selects the view that the game list will open to. " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " Selects the view that the game list will open to. " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " Serial " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " Serial " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " Session: {} " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " Session: {} " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " Set Cover Image " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " Set Input Binding " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " Set Input Binding " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " Sets a threshold for discarding precise values when exceeded. May help with glitches in some games. " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " Sets a threshold for discarding precise values when exceeded. May help with glitches in some games. " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " Sets a threshold for discarding the emulated depth buffer. May help in some games. " ) ;
TRANSLATE_NOOP ( " FullscreenUI " , " Sets a threshold for discarding the emulated depth buffer. May help in some games. " ) ;