Skip to content

Commit 2aa7b53

Browse files
authored
Merge pull request #19996 from hrydgard/confirm-on-exit
Add confirmation on exit
2 parents 41de9c7 + 6c55a37 commit 2aa7b53

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+360
-25
lines changed

Common/Data/Text/Parsers.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <string>
44

55
#include "Common/Data/Text/Parsers.h"
6+
#include "Common/Data/Text/I18n.h"
67
#include "Common/StringUtils.h"
78

89
// Not strictly a parser...
@@ -29,6 +30,19 @@ std::string NiceSizeFormat(uint64_t size) {
2930
return std::string(buffer);
3031
}
3132

33+
std::string NiceTimeFormat(int seconds) {
34+
auto di = GetI18NCategory(I18NCat::DIALOG);
35+
if (seconds < 60) {
36+
return StringFromFormat("%d seconds", seconds);
37+
} else if (seconds < 60 * 60) {
38+
int minutes = seconds / 60;
39+
return StringFromFormat("%d minutes", minutes);
40+
} else {
41+
int hours = seconds / 3600;
42+
return StringFromFormat("%d hours", hours);
43+
}
44+
}
45+
3246
bool Version::ParseVersionString(std::string str) {
3347
if (str.empty())
3448
return false;

Common/Data/Text/Parsers.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,7 @@ static bool TryParse(const std::string &str, N *const output) {
7474
void NiceSizeFormat(uint64_t size, char *out, size_t bufSize);
7575

7676
std::string NiceSizeFormat(uint64_t size);
77+
78+
// seconds, or minutes, or hours.
79+
// Uses I18N strings.
80+
std::string NiceTimeFormat(int seconds);

Core/Config.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ static const ConfigSetting generalSettings[] = {
300300
ConfigSetting("RemoteTab", &g_Config.bRemoteTab, false, CfgFlag::DEFAULT),
301301
ConfigSetting("RemoteISOSharedDir", &g_Config.sRemoteISOSharedDir, "", CfgFlag::DEFAULT),
302302
ConfigSetting("RemoteISOShareType", &g_Config.iRemoteISOShareType, (int)RemoteISOShareType::RECENT, CfgFlag::DEFAULT),
303+
ConfigSetting("AskForExitConfirmationAfterSeconds", &g_Config.iAskForExitConfirmationAfterSeconds, 60, CfgFlag::PER_GAME),
303304

304305
#ifdef __ANDROID__
305306
ConfigSetting("ScreenRotation", &g_Config.iScreenRotation, ROTATION_AUTO_HORIZONTAL),

Core/Config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ struct Config {
137137
bool bMemStickInserted;
138138
int iMemStickSizeGB;
139139
bool bLoadPlugins;
140+
int iAskForExitConfirmationAfterSeconds;
140141

141142
int iScreenRotation; // The rotation angle of the PPSSPP UI. Only supported on Android and possibly other mobile platforms.
142143
int iInternalScreenRotation; // The internal screen rotation angle. Useful for vertical SHMUPs and similar.

Core/Dialog/PSPSaveDialog.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "Core/Dialog/PSPSaveDialog.h"
3030
#include "Core/FileSystems/MetaFileSystem.h"
3131
#include "Core/Util/PPGeDraw.h"
32+
#include "Common/TimeUtil.h"
3233
#include "Core/HLE/sceCtrl.h"
3334
#include "Core/HLE/sceUtility.h"
3435
#include "Core/HLE/ErrorCodes.h"
@@ -38,6 +39,20 @@
3839
#include "Core/Reporting.h"
3940
#include "Core/SaveState.h"
4041

42+
static double g_lastSaveTime = -1.0;
43+
44+
void ResetSecondsSinceLastGameSave() {
45+
g_lastSaveTime = time_now_d();
46+
}
47+
48+
double SecondsSinceLastGameSave() {
49+
if (g_lastSaveTime < 0) {
50+
return -1.0;
51+
} else {
52+
return time_now_d() - g_lastSaveTime;
53+
}
54+
}
55+
4156
const static float FONT_SCALE = 0.55f;
4257

4358
// These are rough, it seems to take at least 100ms or so to init, and shutdown depends on threads.
@@ -85,8 +100,7 @@ PSPSaveDialog::~PSPSaveDialog() {
85100
JoinIOThread();
86101
}
87102

88-
int PSPSaveDialog::Init(int paramAddr)
89-
{
103+
int PSPSaveDialog::Init(int paramAddr) {
90104
// Ignore if already running
91105
if (GetStatus() != SCE_UTILITY_STATUS_NONE) {
92106
ERROR_LOG_REPORT(Log::sceUtility, "A save request is already running, not starting a new one");
@@ -1068,6 +1082,7 @@ void PSPSaveDialog::ExecuteIOAction() {
10681082
result = param.Load(param.GetPspParam(), GetSelectedSaveDirName(), currentSelectedSave);
10691083
if (result == 0) {
10701084
display = DS_LOAD_DONE;
1085+
g_lastSaveTime = time_now_d();
10711086
} else {
10721087
display = DS_LOAD_FAILED;
10731088
}
@@ -1076,6 +1091,7 @@ void PSPSaveDialog::ExecuteIOAction() {
10761091
SaveState::NotifySaveData();
10771092
if (param.Save(param.GetPspParam(), GetSelectedSaveDirName()) == 0) {
10781093
display = DS_SAVE_DONE;
1094+
g_lastSaveTime = time_now_d();
10791095
} else {
10801096
display = DS_SAVE_FAILED;
10811097
}

Core/Dialog/PSPSaveDialog.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ class PSPSaveDialog : public PSPDialog {
104104

105105
std::thread *ioThread = nullptr;
106106
std::mutex paramLock;
107-
volatile SaveIOStatus ioThreadStatus;
107+
volatile SaveIOStatus ioThreadStatus = SAVEIO_NONE;
108108
};
109109

110+
void ResetSecondsSinceLastGameSave();
111+
double SecondsSinceLastGameSave();

Core/HLE/sceUtility.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,8 @@ void __UtilityInit() {
227227
SavedataParam::Init();
228228
currentlyLoadedModules.clear();
229229
volatileUnlockEvent = CoreTiming::RegisterEvent("UtilityVolatileUnlock", UtilityVolatileUnlock);
230+
231+
ResetSecondsSinceLastGameSave();
230232
}
231233

232234
void __UtilityDoState(PointerWrap &p) {

Core/SaveState.cpp

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,10 @@
6060
// Slot number is visual only, -2 will display special message
6161
constexpr int LOAD_UNDO_SLOT = -2;
6262

63-
namespace SaveState
64-
{
63+
namespace SaveState {
64+
65+
double g_lastSaveTime = -1.0;
66+
6567
struct SaveStart
6668
{
6769
void DoState(PointerWrap &p);
@@ -76,13 +78,10 @@ namespace SaveState
7678
SAVESTATE_SAVE_SCREENSHOT,
7779
};
7880

79-
struct Operation
80-
{
81+
struct Operation {
8182
// The slot number is for visual purposes only. Set to -1 for operations where we don't display a message for example.
8283
Operation(OperationType t, const Path &f, int slot_, Callback cb, void *cbUserData_)
83-
: type(t), filename(f), callback(cb), slot(slot_), cbUserData(cbUserData_)
84-
{
85-
}
84+
: type(t), filename(f), callback(cb), slot(slot_), cbUserData(cbUserData_) {}
8685

8786
OperationType type;
8887
Path filename;
@@ -1005,6 +1004,7 @@ namespace SaveState
10051004
}
10061005
}
10071006
#endif
1007+
g_lastSaveTime = time_now_d();
10081008
} else if (result == CChunkFileReader::ERROR_BROKEN_STATE) {
10091009
HandleLoadFailure(false);
10101010
callbackMessage = std::string(i18nLoadFailure) + ": " + errorString;
@@ -1040,6 +1040,7 @@ namespace SaveState
10401040
}
10411041
}
10421042
#endif
1043+
g_lastSaveTime = time_now_d();
10431044
} else if (result == CChunkFileReader::ERROR_BROKEN_STATE) {
10441045
// TODO: What else might we want to do here? This should be very unusual.
10451046
callbackMessage = i18nSaveFailure;
@@ -1155,11 +1156,21 @@ namespace SaveState
11551156
saveDataGeneration = 0;
11561157
lastSaveDataGeneration = 0;
11571158
saveStateInitialGitVersion.clear();
1159+
1160+
g_lastSaveTime = time_now_d();
11581161
}
11591162

11601163
void Shutdown()
11611164
{
11621165
std::lock_guard<std::mutex> guard(mutex);
11631166
rewindStates.Clear();
11641167
}
1168+
1169+
double SecondsSinceLastSavestate() {
1170+
if (g_lastSaveTime < 0) {
1171+
return -1.0;
1172+
} else {
1173+
return time_now_d() - g_lastSaveTime;
1174+
}
1175+
}
11651176
}

Core/SaveState.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,7 @@
2525
#include "Common/File/Path.h"
2626
#include "Common/Serialize/Serializer.h"
2727

28-
namespace SaveState
29-
{
28+
namespace SaveState {
3029
enum class Status {
3130
FAILURE,
3231
WARNING,
@@ -111,4 +110,7 @@ namespace SaveState
111110

112111
// Cleanup by triggering a restart if needed.
113112
void Cleanup();
114-
};
113+
114+
// Returns the time since last save. -1 if N/A.
115+
double SecondsSinceLastSavestate();
116+
} // namespace SaveState

UI/GameSettingsScreen.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1300,6 +1300,9 @@ void GameSettingsScreen::CreateSystemSettings(UI::ViewGroup *systemSettings) {
13001300

13011301
systemSettings->Add(new ItemHeader(sy->T("General")));
13021302

1303+
PopupSliderChoice *exitConfirmation = systemSettings->Add(new PopupSliderChoice(&g_Config.iAskForExitConfirmationAfterSeconds, 0, 1200, 60, sy->T("Ask for exit confirmation after seconds"), screenManager(), "s"));
1304+
exitConfirmation->SetZeroLabel(sy->T("Off"));
1305+
13031306
#if PPSSPP_PLATFORM(ANDROID)
13041307
if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) == DEVICE_TYPE_MOBILE) {
13051308
auto co = GetI18NCategory(I18NCat::CONTROLS);

0 commit comments

Comments
 (0)