mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-01 03:57:17 +01:00
Also Cardboard VR, though should probably just remove it, it's pretty useless. This PR also serves as a demonstration of how to do that. It's easy!
560 lines
19 KiB
C++
560 lines
19 KiB
C++
// Copyright (c) 2012- 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/.
|
|
|
|
#include "ppsspp_config.h"
|
|
|
|
#include <cstdio>
|
|
#include <cstring>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "Common/Common.h"
|
|
#include "Common/Data/Text/I18n.h"
|
|
#include "Common/File/FileUtil.h"
|
|
#include "Common/File/Path.h"
|
|
#include "Common/GPU/thin3d.h"
|
|
#include "Common/Log.h"
|
|
#include "Common/Render/ManagedTexture.h"
|
|
#include "Common/System/Display.h"
|
|
#include "Common/System/NativeApp.h"
|
|
#include "Common/System/OSD.h"
|
|
#include "Common/System/Request.h"
|
|
#include "Common/System/System.h"
|
|
#include "Common/UI/Context.h"
|
|
#include "Common/UI/PopupScreens.h"
|
|
#include "Common/UI/ScreenManager.h"
|
|
#include "Common/UI/View.h"
|
|
#include "Core/Config.h"
|
|
#include "Core/ConfigValues.h"
|
|
#include "Core/HLE/sceUsbCam.h"
|
|
#include "Core/HLE/sceUtility.h"
|
|
#include "Core/Reporting.h"
|
|
#include "Core/System.h"
|
|
#include "Core/Util/PathUtil.h"
|
|
#include "UI/Background.h"
|
|
#include "UI/GameSettingsScreen.h"
|
|
#include "UI/MemStickScreen.h"
|
|
#include "UI/MiscScreens.h"
|
|
#include "UI/MiscViews.h"
|
|
#include "UI/SettingsPage.h"
|
|
#include "UI/Settings/MainSettingsPages.h"
|
|
#include "UI/Theme.h"
|
|
|
|
#if PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS)
|
|
#include "Core/Util/DarwinFileSystemServices.h"
|
|
#endif
|
|
|
|
#if defined(_WIN32) && !PPSSPP_PLATFORM(UWP)
|
|
#pragma warning(disable:4091) // workaround bug in VS2015 headers
|
|
#include "Windows/MainWindow.h"
|
|
#include "Windows/W32Util/ShellUtil.h"
|
|
#endif
|
|
|
|
void ReadSystemPageState(SystemPageState *state) {
|
|
// Written back on exit, so it must be read even if the System tab is never opened.
|
|
state->enableReports = Reporting::IsEnabled();
|
|
}
|
|
|
|
#if defined(_WIN32) && !PPSSPP_PLATFORM(UWP)
|
|
// Works out where the memstick is (installed.txt next to the exe means My Documents or a custom
|
|
// folder), and which of the two checkboxes can be changed.
|
|
void CheckMemstickInstallState(SystemPageState *state) {
|
|
const Path &PPSSPPpath = File::GetExeDirectory();
|
|
const Path installedFile = PPSSPPpath / "installed.txt";
|
|
const bool myDocsExists = W32Util::UserDocumentsPath().size() != 0;
|
|
|
|
state->installed = File::Exists(installedFile);
|
|
state->otherinstalled = false;
|
|
state->memstickMyDocEnabled = !PSP_IsInited();
|
|
state->memstickOtherEnabled = false;
|
|
if (!state->installed && myDocsExists) {
|
|
// Disable the setting if we can't create & delete a file next to the exe.
|
|
if (File::CreateEmptyFile(PPSSPPpath / "installedTEMP.txt")) {
|
|
if (!(File::Delete(PPSSPPpath / "installedTEMP.txt")))
|
|
state->memstickMyDocEnabled = false;
|
|
else
|
|
state->memstickOtherEnabled = !PSP_IsInited();
|
|
} else
|
|
state->memstickMyDocEnabled = false;
|
|
} else {
|
|
if (state->installed && myDocsExists) {
|
|
FILE *testInstalled = File::OpenCFile(installedFile, "rt");
|
|
if (testInstalled) {
|
|
char temp[2048];
|
|
char *tempStr = fgets(temp, sizeof(temp), testInstalled);
|
|
// Skip UTF-8 encoding bytes if there are any. There are 3 of them.
|
|
if (tempStr && strncmp(tempStr, "\xEF\xBB\xBF", 3) == 0) {
|
|
tempStr += 3;
|
|
}
|
|
state->memstickOtherEnabled = !PSP_IsInited();
|
|
if (tempStr && strlen(tempStr) != 0 && strcmp(tempStr, "\n") != 0) {
|
|
state->installed = false;
|
|
state->otherinstalled = true;
|
|
}
|
|
fclose(testInstalled);
|
|
}
|
|
} else if (!myDocsExists) {
|
|
state->memstickMyDocEnabled = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void OnMemoryStickMyDoc(SystemPageState *state) {
|
|
const Path &PPSSPPpath = File::GetExeDirectory();
|
|
const Path installedFile = PPSSPPpath / "installed.txt";
|
|
state->installed = File::Exists(installedFile);
|
|
if (state->otherinstalled) {
|
|
File::Delete(PPSSPPpath / "installed.txt");
|
|
File::CreateEmptyFile(PPSSPPpath / "installed.txt");
|
|
state->otherinstalled = false;
|
|
const std::string myDocsPath = W32Util::UserDocumentsPath() + "/PPSSPP/";
|
|
g_Config.memStickDirectory = Path(myDocsPath);
|
|
} else if (state->installed) {
|
|
File::Delete(PPSSPPpath / "installed.txt");
|
|
state->installed = false;
|
|
g_Config.memStickDirectory = PPSSPPpath / "memstick";
|
|
} else {
|
|
FILE *f = File::OpenCFile(PPSSPPpath / "installed.txt", "wb");
|
|
if (f) {
|
|
fclose(f);
|
|
}
|
|
|
|
const std::string myDocsPath = W32Util::UserDocumentsPath() + "/PPSSPP/";
|
|
g_Config.memStickDirectory = Path(myDocsPath);
|
|
state->installed = true;
|
|
}
|
|
}
|
|
|
|
static void OnMemoryStickOther(SystemPageState *state) {
|
|
const Path &PPSSPPpath = File::GetExeDirectory();
|
|
if (state->otherinstalled) {
|
|
auto di = GetI18NCategory(I18NCat::DIALOG);
|
|
std::string initialPath = g_Config.memStickDirectory.ToCString();
|
|
std::string folder = W32Util::BrowseForFolder2(MainWindow::GetHWND(), di->T("Choose PPSSPP save folder"), initialPath);
|
|
if (folder.size()) {
|
|
g_Config.memStickDirectory = Path(folder);
|
|
FILE *f = File::OpenCFile(PPSSPPpath / "installed.txt", "wb");
|
|
if (f) {
|
|
std::string utfstring("\xEF\xBB\xBF");
|
|
utfstring.append(folder);
|
|
fwrite(utfstring.c_str(), 1, utfstring.length(), f);
|
|
fclose(f);
|
|
}
|
|
state->installed = false;
|
|
}
|
|
else
|
|
state->otherinstalled = false;
|
|
}
|
|
else {
|
|
File::Delete(PPSSPPpath / "installed.txt");
|
|
state->memstickMyDocEnabled = true;
|
|
state->otherinstalled = false;
|
|
state->installed = false;
|
|
g_Config.memStickDirectory = PPSSPPpath / "memstick";
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
static void OnImmersiveModeChange() {
|
|
System_Notify(SystemNotification::IMMERSIVE_MODE_CHANGE);
|
|
if (g_Config.iAndroidHwScale != 0) {
|
|
System_RecreateActivity();
|
|
}
|
|
}
|
|
|
|
static void OnSustainedPerformanceModeChange() {
|
|
System_Notify(SystemNotification::SUSTAINED_PERF_CHANGE);
|
|
}
|
|
|
|
static void OnJitAffectingSetting() {
|
|
System_PostUIMessage(UIMessage::REQUEST_CLEAR_JIT);
|
|
}
|
|
|
|
static void OnChangeBackground(SettingsPageHost *host) {
|
|
const Path bgPng = GetSysDirectory(DIRECTORY_SYSTEM) / "background.png";
|
|
const Path bgJpg = GetSysDirectory(DIRECTORY_SYSTEM) / "background.jpg";
|
|
|
|
if (File::Exists(bgPng) || File::Exists(bgJpg)) {
|
|
INFO_LOG(Log::UI, "Clearing background image.");
|
|
// The button is in clear mode.
|
|
File::Delete(bgPng);
|
|
File::Delete(bgJpg);
|
|
UIBackgroundShutdown();
|
|
host->RecreatePageViews();
|
|
return;
|
|
}
|
|
|
|
auto sy = GetI18NCategory(I18NCat::SYSTEM);
|
|
System_BrowseForImage(host->PageRequesterToken(), sy->T("Set UI background..."), bgJpg, [host](std::string_view value, int converted) {
|
|
if (converted == 1) {
|
|
// The platform code converted and saved the file to the desired path already.
|
|
INFO_LOG(Log::UI, "Platform converted the file: %.*s", STR_VIEW(value));
|
|
} else if (!value.empty()) {
|
|
Path path(value);
|
|
|
|
// Check the file format. Don't rely on the file extension here due to scoped storage URLs.
|
|
FILE *f = File::OpenCFile(path, "rb");
|
|
uint8_t buffer[8];
|
|
ImageFileType type = ImageFileType::UNKNOWN;
|
|
if (f != nullptr && 8 == fread(buffer, 1, ARRAY_SIZE(buffer), f)) {
|
|
type = DetectImageFileType(buffer, ARRAY_SIZE(buffer));
|
|
}
|
|
if (f) {
|
|
fclose(f);
|
|
}
|
|
|
|
std::string filename;
|
|
switch (type) {
|
|
case ImageFileType::JPEG:
|
|
filename = "background.jpg";
|
|
break;
|
|
case ImageFileType::PNG:
|
|
filename = "background.png";
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (!filename.empty()) {
|
|
Path dest = GetSysDirectory(DIRECTORY_SYSTEM) / filename;
|
|
File::Copy(path, dest);
|
|
if (path.FilePathContainsNoCase("temp_import.jpg")) {
|
|
INFO_LOG(Log::UI, "Deleting temp file: %s", GetFriendlyPath(path).c_str());
|
|
File::Delete(path);
|
|
}
|
|
} else {
|
|
auto sy = GetI18NCategory(I18NCat::SYSTEM);
|
|
g_OSD.Show(OSDType::MESSAGE_ERROR, sy->T("Only JPG and PNG images are supported"), path.GetFilename(), 5.0);
|
|
}
|
|
}
|
|
// It will init again automatically. We can't init outside a frame on Vulkan.
|
|
UIBackgroundShutdown();
|
|
host->RecreatePageViews();
|
|
});
|
|
|
|
// Change to a browse or clear button.
|
|
}
|
|
|
|
static void CallbackRestoreDefaults(SystemPageState *state, bool yes) {
|
|
if (yes) {
|
|
g_Config.RestoreDefaults(RestoreSettingsBits::SETTINGS);
|
|
ReadSystemPageState(state);
|
|
}
|
|
System_Notify(SystemNotification::UI);
|
|
}
|
|
|
|
static void OnRestoreDefaultSettings(SettingsPageHost *host, SystemPageState *state) {
|
|
auto sy = GetI18NCategory(I18NCat::SYSTEM);
|
|
if (g_Config.IsGameSpecific()) {
|
|
auto dev = GetI18NCategory(I18NCat::DEVELOPER);
|
|
auto di = GetI18NCategory(I18NCat::DIALOG);
|
|
auto sy = GetI18NCategory(I18NCat::SYSTEM);
|
|
host->PageScreenManager()->push(
|
|
new UI::MessagePopupScreen(sy->T("Restore Default Settings"), dev->T("RestoreGameDefaultSettings", "Are you sure you want to restore the game-specific settings back to the ppsspp defaults?\n"),
|
|
di->T("OK"), di->T("Cancel"), [state](bool yes) { CallbackRestoreDefaults(state, yes); }));
|
|
} else {
|
|
std::string_view title = sy->T("Restore Default Settings");
|
|
host->PageScreenManager()->push(new RestoreSettingsScreen(title));
|
|
}
|
|
}
|
|
|
|
// Using SYSTEM translations
|
|
static void BuildPSPSettingsPage(SettingsPage *page) {
|
|
SettingsPageHost *host = page->Host();
|
|
|
|
page->Header("PSP Settings");
|
|
|
|
// The ordering here is simply mapping directly to PSP_SYSTEMPARAM_LANGUAGE_*.
|
|
page->Setting(&g_Config.iLanguage);
|
|
page->Setting(&g_Config.iPSPModel).EnabledFunc([] {
|
|
return !PSP_IsInited();
|
|
});
|
|
page->Custom("Nickname", [host](UI::ViewGroup *parent) {
|
|
return AddNicknameChoice(host, parent);
|
|
});
|
|
page->Setting(&g_Config.bDayLightSavings);
|
|
page->Setting(&g_Config.iDateFormat);
|
|
page->Setting(&g_Config.iTimeFormat);
|
|
page->Setting(&g_Config.iButtonPreference);
|
|
}
|
|
|
|
void BuildSystemSettings(SettingsPage *page, SystemPageState *state) {
|
|
using namespace UI;
|
|
|
|
SettingsPageHost *host = page->Host();
|
|
|
|
page->Header("UI");
|
|
|
|
page->Custom("Language", [host](UI::ViewGroup *parent) -> UI::View * {
|
|
auto langCodeToName = [](std::string_view value) -> std::string {
|
|
auto &mapping = GetLangValuesMapping();
|
|
auto iter = mapping.find(value);
|
|
if (iter != mapping.end()) {
|
|
return iter->second.first;
|
|
}
|
|
return std::string(value);
|
|
};
|
|
|
|
Choice *language = parent->Add(new ChoiceWithValueDisplay(&g_Config.sLanguageIni, T(I18NCat::SYSTEM, "Language"), langCodeToName));
|
|
language->OnClick.Add([host](UI::EventParams &e) {
|
|
auto sy = GetI18NCategory(I18NCat::SYSTEM);
|
|
auto langScreen = new NewLanguageScreen(sy->T("Language"));
|
|
// The actual switching is handled in OnCompleted in NewLanguageScreen.
|
|
if (e.v)
|
|
langScreen->SetPopupOrigin(e.v);
|
|
host->PageScreenManager()->push(langScreen);
|
|
});
|
|
return language;
|
|
});
|
|
|
|
#if PPSSPP_PLATFORM(IOS)
|
|
static const char *indicator[] = {
|
|
"Swipe once to switch app (indicator auto-hides)",
|
|
"Swipe twice to switch app (indicator stays visible)"
|
|
};
|
|
page->Setting(&g_Config.iAppSwitchMode);
|
|
|
|
{
|
|
// Note: On iPhone, iOS hides the status bar in landscape no matter what this is set to.
|
|
DisplayLayoutConfig &config = g_Config.GetDisplayLayoutConfig(g_display.GetDeviceOrientation());
|
|
page->Setting(&config.bImmersiveMode).OnChange([](EventParams &e) {
|
|
System_Notify(SystemNotification::IMMERSIVE_MODE_CHANGE);
|
|
});
|
|
}
|
|
#endif
|
|
|
|
#if PPSSPP_PLATFORM(ANDROID)
|
|
// Hide Immersive Mode on pre-kitkat Android
|
|
if (System_GetPropertyInt(SYSPROP_SYSTEMVERSION) >= 19) {
|
|
DisplayLayoutConfig &config = g_Config.GetDisplayLayoutConfig(g_display.GetDeviceOrientation());
|
|
page->Setting(&config.bImmersiveMode).OnChange([](EventParams &e) {
|
|
OnImmersiveModeChange();
|
|
});
|
|
}
|
|
#endif
|
|
|
|
UIContext *ctx = host->PageScreenManager()->getUIContext();
|
|
page->Setting(&g_Config.iUIScaleFactor).OnChange([ctx](UI::EventParams &e) {
|
|
const float dpiMul = UIScaleFactorToMultiplier(g_Config.iUIScaleFactor);
|
|
g_display.Recalculate(-1, -1, -1, -1, dpiMul);
|
|
ctx->InvalidateAtlas();
|
|
NativeResized();
|
|
});
|
|
|
|
const Path bgPng = GetSysDirectory(DIRECTORY_SYSTEM) / "background.png";
|
|
const Path bgJpg = GetSysDirectory(DIRECTORY_SYSTEM) / "background.jpg";
|
|
if (File::Exists(bgPng) || File::Exists(bgJpg)) {
|
|
page->Choice("Clear UI background").OnClick([host](UI::EventParams &e) {
|
|
OnChangeBackground(host);
|
|
});
|
|
} else if (System_GetPropertyBool(SYSPROP_HAS_IMAGE_BROWSER) || System_GetPropertyBool(SYSPROP_HAS_FILE_BROWSER)) {
|
|
page->Choice("Set UI background...").OnClick([host](UI::EventParams &e) {
|
|
OnChangeBackground(host);
|
|
});
|
|
}
|
|
|
|
page->Setting(&g_Config.bTransparentBackground);
|
|
|
|
// Shared with achievements.
|
|
|
|
page->Setting(&g_Config.iNotificationPos);
|
|
|
|
page->Setting(&g_Config.iBackgroundAnimation);
|
|
|
|
page->Custom("Theme", [host](UI::ViewGroup *parent) -> UI::View * {
|
|
PopupMultiChoiceDynamic *theme = parent->Add(new PopupMultiChoiceDynamic(&g_Config.sThemeName, T(I18NCat::SYSTEM, "Theme"), GetThemeInfoNames(), I18NCat::THEMES, host->PageScreenManager()));
|
|
theme->OnChoice.Add([](EventParams &e) {
|
|
UpdateTheme();
|
|
// Reset the tint/saturation if the theme changed.
|
|
if (e.b) {
|
|
g_Config.fUITint = 0.0f;
|
|
g_Config.fUISaturation = 1.0f;
|
|
}
|
|
});
|
|
return theme;
|
|
});
|
|
|
|
Draw::DrawContext *draw = host->PageScreenManager()->getDrawContext();
|
|
|
|
if (!draw->GetBugs().Has(Draw::Bugs::RASPBERRY_SHADER_COMP_HANG)) {
|
|
// We use shaders without tint capability on hardware with this driver bug.
|
|
auto noDropShadow = [](View *view) {
|
|
static_cast<PopupSliderChoiceFloat *>(view)->SetHasDropShadow(false);
|
|
};
|
|
page->Setting(&g_Config.fUITint).LiveUpdate().Setup(noDropShadow);
|
|
page->Setting(&g_Config.fUISaturation).LiveUpdate().Setup(noDropShadow);
|
|
}
|
|
|
|
page->Header();
|
|
page->Link({I18NCat::SYSTEM, "PSP Settings"}, I18NCat::SYSTEM, &BuildPSPSettingsPage);
|
|
|
|
page->Header("PSP Memory Stick");
|
|
|
|
if (System_GetPropertyBool(SYSPROP_HAS_OPEN_DIRECTORY)) {
|
|
page->Choice("Show Memory Stick folder").OnClick([](UI::EventParams &p) {
|
|
System_LaunchUrl(LaunchUrlType::LOCAL_FOLDER, g_Config.memStickDirectory.ToString());
|
|
});
|
|
}
|
|
|
|
#if PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS)
|
|
bool showItHere = true;
|
|
#if PPSSPP_PLATFORM(IOS_APP_STORE)
|
|
if (g_Config.memStickDirectory == DarwinFileSystemServices::defaultMemoryStickPath()) {
|
|
// We still keep a way to access it on the developer tools screen.
|
|
showItHere = false;
|
|
}
|
|
#endif
|
|
if (showItHere) {
|
|
page->Choice("Set Memory Stick folder").OnClick([host](UI::EventParams &) {
|
|
SetMemStickDirDarwin(host->PageRequesterToken());
|
|
});
|
|
}
|
|
#endif
|
|
|
|
auto addMemstickPath = [host, &page]() {
|
|
page->Custom("Memory Stick folder", [host](UI::ViewGroup *parent) -> UI::View * {
|
|
Choice *memstickPath = parent->Add(new ChoiceWithCallbackValueDisplay(T(I18NCat::SYSTEM, "Memory Stick folder"), []() {
|
|
return g_Config.memStickDirectory.ToVisualString();
|
|
}));
|
|
memstickPath->OnClick.Add([host](UI::EventParams &e) {
|
|
host->PageScreenManager()->push(new MemStickScreen(false));
|
|
});
|
|
return memstickPath;
|
|
}).EnabledFunc([] {
|
|
return !PSP_IsInited();
|
|
});
|
|
};
|
|
|
|
#if PPSSPP_PLATFORM(ANDROID)
|
|
if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) != DEVICE_TYPE_VR) {
|
|
addMemstickPath();
|
|
}
|
|
#elif defined(_WIN32)
|
|
#if PPSSPP_PLATFORM(UWP)
|
|
addMemstickPath();
|
|
#else
|
|
page->Bool(&state->installed, "Memory Stick in My Documents").Enabled(&state->memstickMyDocEnabled).OnChange([state](UI::EventParams &e) {
|
|
OnMemoryStickMyDoc(state);
|
|
});
|
|
page->Bool(&state->otherinstalled, "Memory Stick in installed.txt").Enabled(&state->memstickOtherEnabled).OnChange([state](UI::EventParams &e) {
|
|
OnMemoryStickOther(state);
|
|
});
|
|
|
|
if (!System_GetPropertyBool(SYSPROP_CAN_GET_FREE_SPACE_FAST)) {
|
|
// It might be slow, so use an option.
|
|
page->Setting(&g_Config.bReportAccurateFreeStorageSpace);
|
|
}
|
|
#endif
|
|
#endif
|
|
page->Setting(&g_Config.bMemStickInserted);
|
|
page->Setting(&g_Config.iMemStickSizeGB);
|
|
|
|
page->Header("Help the PPSSPP team");
|
|
page->Bool(&state->enableReports, "Enable Compatibility Server Reports").EnabledFunc([]() {
|
|
return Reporting::IsSupported();
|
|
});
|
|
|
|
page->Header("Emulation");
|
|
|
|
page->Setting(&g_Config.bFastMemory).OnChange([](UI::EventParams &e) {
|
|
OnJitAffectingSetting();
|
|
});
|
|
page->Setting(&g_Config.bIgnoreBadMemAccess);
|
|
|
|
page->Setting(&g_Config.iIOTimingMethod);
|
|
page->Setting(&g_Config.bForceLagSync).Disabled(&g_Config.bAutoFrameSkip);
|
|
page->Setting(&g_Config.iLockedCPUSpeed);
|
|
|
|
page->Header({ I18NCat::SAVEDATA, "Save states" }); // Borrow this string from the savedata manager
|
|
|
|
page->Setting(&g_Config.bEnableStateUndo);
|
|
page->Setting(&g_Config.bConfirmLoadState);
|
|
|
|
page->Setting(&g_Config.iSaveStateSlotCount);
|
|
|
|
// NOTE: We will soon support more states, but we'll keep this niche feature limited to the first five.
|
|
page->Setting(&g_Config.iAutoLoadSaveState).Setup([](View *view) {
|
|
if (g_Config.iAutoLoadSaveState != 1) {
|
|
static_cast<PopupMultiChoice *>(view)->HideChoice(1); // Hide "Oldest Save" if not using that mode. It doesn't make sense.
|
|
}
|
|
});
|
|
|
|
page->Setting(&g_Config.iRewindSnapshotInterval);
|
|
|
|
page->Header("General");
|
|
|
|
page->Setting(&g_Config.iAskForExitConfirmationAfterSeconds);
|
|
|
|
if (System_GetPropertyBool(SYSPROP_CAN_RESTRICT_ORIENTATION)) {
|
|
// Display rotation
|
|
page->Custom({ I18NCat::CONTROLS, "Screen Rotation" }, [host](UI::ViewGroup *parent) -> UI::View * {
|
|
AddRotationPicker(host->PageScreenManager(), parent, true);
|
|
return parent->GetViewByIndex(parent->GetNumSubviews() - 1);
|
|
});
|
|
}
|
|
|
|
if (System_GetPropertyBool(SYSPROP_SUPPORTS_SUSTAINED_PERF_MODE)) {
|
|
page->Setting(&g_Config.bSustainedPerformanceMode).OnChange([](UI::EventParams &e) {
|
|
OnSustainedPerformanceModeChange();
|
|
});
|
|
}
|
|
|
|
page->Choice("Restore Default Settings").OnClick([host, state](UI::EventParams &e) {
|
|
OnRestoreDefaultSettings(host, state);
|
|
});
|
|
|
|
if (System_GetPropertyBool(SYSPROP_HAS_KEYBOARD))
|
|
page->Setting(&g_Config.bBypassOSKWithKeyboard);
|
|
|
|
if (System_GetPropertyBool(SYSPROP_ENOUGH_RAM_FOR_FULL_ISO)) {
|
|
page->Setting(&g_Config.bCacheFullIsoInRam).EnabledFunc([] {
|
|
return !PSP_IsInited();
|
|
});
|
|
}
|
|
|
|
page->Setting(&g_Config.bCheckForNewVersion);
|
|
page->Setting(&g_Config.bScreenshotsAsPNG);
|
|
page->Setting(&g_Config.iScreenshotMode);
|
|
// TODO: Make this setting available on Mac too.
|
|
#if PPSSPP_PLATFORM(WINDOWS) || (defined (SDL) && !defined(MOBILE_DEVICE))
|
|
page->Setting(&g_Config.bPauseOnLostFocus);
|
|
#endif
|
|
|
|
std::vector<std::string> cameraList = Camera::getDeviceList();
|
|
if (cameraList.size() >= 1) {
|
|
page->Header({ I18NCat::GRAPHICS, "Camera" });
|
|
page->Setting(&g_Config.sCameraDevice, std::move(cameraList));
|
|
#if PPSSPP_PLATFORM(WINDOWS) && !PPSSPP_PLATFORM(UWP)
|
|
page->Setting(&g_Config.bCameraMirrorHorizontal);
|
|
#endif
|
|
}
|
|
|
|
page->Header("Cheats");
|
|
page->Setting(&g_Config.bEnableCheats);
|
|
page->Setting(&g_Config.bEnablePlugins);
|
|
|
|
#if defined(_WIN32)
|
|
page->Header("Recording");
|
|
page->Setting(&g_Config.bDumpFrames);
|
|
page->Setting(&g_Config.bUseFFV1);
|
|
page->Setting(&g_Config.bDumpVideoOutput);
|
|
page->Setting(&g_Config.bDumpAudio);
|
|
page->Setting(&g_Config.bSaveLoadResetsAVdumping);
|
|
#endif
|
|
}
|