1
// Copyright (c) 2013- PPSSPP Project.
3
// This program is free software: you can redistribute it and/or modify
4
// it under the terms of the GNU General Public License as published by
5
// the Free Software Foundation, version 2.0 or later versions.
7
// This program is distributed in the hope that it will be useful,
8
// but WITHOUT ANY WARRANTY; without even the implied warranty of
9
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
// GNU General Public License 2.0 for more details.
12
// A copy of the GPL 2.0 should have been included with the program.
13
// If not, see http://www.gnu.org/licenses/
15
// Official git repository and contact information can be found at
16
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
18
#include "base/display.h" // Only to check screen aspect ratio with pixel_yres/pixel_xres
20
#include "base/colorutil.h"
21
#include "base/timeutil.h"
22
#include "math/curves.h"
23
#include "gfx_es2/gpu_features.h"
24
#include "gfx_es2/draw_buffer.h"
25
#include "i18n/i18n.h"
27
#include "ui/viewgroup.h"
28
#include "ui/ui_context.h"
29
#include "UI/EmuScreen.h"
30
#include "UI/GameSettingsScreen.h"
31
#include "UI/GameInfoCache.h"
32
#include "UI/GamepadEmu.h"
33
#include "UI/MiscScreens.h"
34
#include "UI/ControlMappingScreen.h"
35
#include "UI/DevScreens.h"
36
#include "UI/DisplayLayoutScreen.h"
37
#include "UI/RemoteISOScreen.h"
38
#include "UI/SavedataScreen.h"
39
#include "UI/TouchControlLayoutScreen.h"
40
#include "UI/TouchControlVisibilityScreen.h"
41
#include "UI/TiltAnalogSettingsScreen.h"
42
#include "UI/TiltEventProcessor.h"
43
#include "UI/ComboKeyMappingScreen.h"
45
#include "Common/KeyMap.h"
46
#include "Common/FileUtil.h"
47
#include "Core/Config.h"
48
#include "Core/Host.h"
49
#include "Core/System.h"
50
#include "Core/Reporting.h"
51
#include "android/jni/TestRunner.h"
52
#include "GPU/GPUInterface.h"
53
#include "GPU/GLES/Framebuffer.h"
56
#pragma warning(disable:4091) // workaround bug in VS2015 headers
57
#include "Windows/MainWindow.h"
59
#include "util/text/utf8.h"
60
#include "Windows/W32Util/ShellUtil.h"
61
#include "Windows/W32Util/Misc.h"
66
extern bool iosCanUseJit;
67
extern bool targetIsJailbroken;
70
GameSettingsScreen::GameSettingsScreen(std::string gamePath, std::string gameID, bool editThenRestore)
71
: UIDialogScreenWithGameBackground(gamePath), gameID_(gameID), enableReports_(false), editThenRestore_(editThenRestore) {
72
lastVertical_ = UseVerticalLayout();
75
bool GameSettingsScreen::UseVerticalLayout() const {
76
return dp_yres > dp_xres * 1.1f;
79
void GameSettingsScreen::CreateViews() {
80
GameInfo *info = g_gameInfoCache->GetInfo(NULL, gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE);
82
if (editThenRestore_) {
83
g_Config.loadGameConfig(gameID_);
86
cap60FPS_ = g_Config.iForceMaxEmulatedFPS == 60;
88
iAlternateSpeedPercent_ = (g_Config.iFpsLimit * 100) / 60;
90
bool vertical = UseVerticalLayout();
92
// Information in the top left.
93
// Back button to the bottom left.
94
// Scrolling action menu to the right.
97
I18NCategory *di = GetI18NCategory("Dialog");
98
I18NCategory *gr = GetI18NCategory("Graphics");
99
I18NCategory *co = GetI18NCategory("Controls");
100
I18NCategory *a = GetI18NCategory("Audio");
101
I18NCategory *sa = GetI18NCategory("Savedata");
102
I18NCategory *sy = GetI18NCategory("System");
103
I18NCategory *n = GetI18NCategory("Networking");
104
I18NCategory *ms = GetI18NCategory("MainSettings");
105
I18NCategory *dev = GetI18NCategory("Developer");
107
root_ = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT));
109
TabHolder *tabHolder;
111
LinearLayout *verticalLayout = new LinearLayout(ORIENT_VERTICAL, new LayoutParams(FILL_PARENT, FILL_PARENT));
112
tabHolder = new TabHolder(ORIENT_HORIZONTAL, 200, new LinearLayoutParams(1.0f));
113
verticalLayout->Add(tabHolder);
114
verticalLayout->Add(new Choice(di->T("Back"), "", false, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 0.0f, Margins(0))))->OnClick.Handle<UIScreen>(this, &UIScreen::OnBack);
115
root_->Add(verticalLayout);
117
tabHolder = new TabHolder(ORIENT_VERTICAL, 200, new AnchorLayoutParams(10, 0, 10, 0, false));
118
root_->Add(tabHolder);
119
AddStandardBack(root_);
121
tabHolder->SetTag("GameSettings");
122
root_->SetDefaultFocusView(tabHolder);
124
float leftSide = 40.0f;
128
settingInfo_ = new SettingInfoMessage(ALIGN_CENTER | FLAG_WRAP_TEXT, new AnchorLayoutParams(dp_xres - leftSide - 40.0f, WRAP_CONTENT, leftSide, dp_yres - 80.0f - 40.0f, NONE, NONE));
129
settingInfo_->SetBottomCutoff(dp_yres - 200.0f);
130
root_->Add(settingInfo_);
132
// TODO: These currently point to global settings, not game specific ones.
135
ViewGroup *graphicsSettingsScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT));
136
graphicsSettingsScroll->SetTag("GameSettingsGraphics");
137
LinearLayout *graphicsSettings = new LinearLayout(ORIENT_VERTICAL);
138
graphicsSettings->SetSpacing(0);
139
graphicsSettingsScroll->Add(graphicsSettings);
140
tabHolder->AddTab(ms->T("Graphics"), graphicsSettingsScroll);
142
graphicsSettings->Add(new ItemHeader(gr->T("Rendering Mode")));
143
static const char *renderingBackend[] = { "OpenGL", "Direct3D 9", "Direct3D 11", "Vulkan (experimental)" };
144
PopupMultiChoice *renderingBackendChoice = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iGPUBackend, gr->T("Backend"), renderingBackend, GPU_BACKEND_OPENGL, ARRAY_SIZE(renderingBackend), gr->GetName(), screenManager()));
145
renderingBackendChoice->OnChoice.Handle(this, &GameSettingsScreen::OnRenderingBackend);
147
renderingBackendChoice->HideChoice(1); // D3D9
148
renderingBackendChoice->HideChoice(2); // D3D11
150
renderingBackendChoice->HideChoice(2); // D3D11
153
// TODO: Add dynamic runtime check for Vulkan support on Android
154
renderingBackendChoice->HideChoice(3);
156
static const char *renderingMode[] = { "Non-Buffered Rendering", "Buffered Rendering", "Read Framebuffers To Memory (CPU)", "Read Framebuffers To Memory (GPU)"};
157
PopupMultiChoice *renderingModeChoice = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iRenderingMode, gr->T("Mode"), renderingMode, 0, ARRAY_SIZE(renderingMode), gr->GetName(), screenManager()));
158
renderingModeChoice->OnChoice.Add([=](EventParams &e) {
159
switch (g_Config.iRenderingMode) {
160
case FB_NON_BUFFERED_MODE:
161
settingInfo_->Show(gr->T("RenderingMode NonBuffered Tip", "Faster, but nothing may draw in some games"), e.v);
163
case FB_BUFFERED_MODE:
166
case FB_READFBOMEMORY_CPU:
168
case FB_READFBOMEMORY_GPU:
169
settingInfo_->Show(gr->T("RenderingMode ReadFromMemory Tip", "Causes crashes in many games, not recommended"), e.v);
172
return UI::EVENT_CONTINUE;
174
renderingModeChoice->OnChoice.Handle(this, &GameSettingsScreen::OnRenderingMode);
175
renderingModeChoice->SetDisabledPtr(&g_Config.bSoftwareRendering);
176
CheckBox *blockTransfer = graphicsSettings->Add(new CheckBox(&g_Config.bBlockTransferGPU, gr->T("Simulate Block Transfer", "Simulate Block Transfer (unfinished)")));
177
blockTransfer->SetDisabledPtr(&g_Config.bSoftwareRendering);
179
graphicsSettings->Add(new ItemHeader(gr->T("Frame Rate Control")));
180
static const char *frameSkip[] = {"Off", "1", "2", "3", "4", "5", "6", "7", "8"};
181
graphicsSettings->Add(new PopupMultiChoice(&g_Config.iFrameSkip, gr->T("Frame Skipping"), frameSkip, 0, ARRAY_SIZE(frameSkip), gr->GetName(), screenManager()));
182
frameSkipAuto_ = graphicsSettings->Add(new CheckBox(&g_Config.bAutoFrameSkip, gr->T("Auto FrameSkip")));
183
frameSkipAuto_->OnClick.Handle(this, &GameSettingsScreen::OnAutoFrameskip);
184
graphicsSettings->Add(new CheckBox(&cap60FPS_, gr->T("Force max 60 FPS (helps GoW)")));
186
PopupSliderChoice *altSpeed = graphicsSettings->Add(new PopupSliderChoice(&iAlternateSpeedPercent_, 0, 600, gr->T("Alternative Speed", "Alternative speed"), 5, screenManager(), gr->T("%, 0:unlimited")));
187
altSpeed->SetFormat("%i%%");
188
altSpeed->SetZeroLabel(gr->T("Unlimited"));
190
graphicsSettings->Add(new ItemHeader(gr->T("Features")));
191
I18NCategory *ps = GetI18NCategory("PostShaders");
192
postProcChoice_ = graphicsSettings->Add(new ChoiceWithValueDisplay(&g_Config.sPostShaderName, gr->T("Postprocessing Shader"), ps->GetName()));
193
postProcChoice_->OnClick.Handle(this, &GameSettingsScreen::OnPostProcShader);
194
postProcEnable_ = !g_Config.bSoftwareRendering && (g_Config.iRenderingMode != FB_NON_BUFFERED_MODE);
195
postProcChoice_->SetEnabledPtr(&postProcEnable_);
197
#if !defined(MOBILE_DEVICE)
198
graphicsSettings->Add(new CheckBox(&g_Config.bFullScreen, gr->T("FullScreen")))->OnClick.Handle(this, &GameSettingsScreen::OnFullscreenChange);
200
// Display Layout Editor: To avoid overlapping touch controls on large tablets, meet geeky demands for integer zoom/unstretched image etc.
201
displayEditor_ = graphicsSettings->Add(new Choice(gr->T("Display layout editor")));
202
displayEditor_->OnClick.Handle(this, &GameSettingsScreen::OnDisplayLayoutEditor);
205
// Hide Immersive Mode on pre-kitkat Android
206
if (System_GetPropertyInt(SYSPROP_SYSTEMVERSION) >= 19) {
207
graphicsSettings->Add(new CheckBox(&g_Config.bImmersiveMode, gr->T("Immersive Mode")))->OnClick.Handle(this, &GameSettingsScreen::OnImmersiveModeChange);
211
graphicsSettings->Add(new ItemHeader(gr->T("Performance")));
212
#ifndef MOBILE_DEVICE
213
static const char *internalResolutions[] = {"Auto (1:1)", "1x PSP", "2x PSP", "3x PSP", "4x PSP", "5x PSP", "6x PSP", "7x PSP", "8x PSP", "9x PSP", "10x PSP" };
215
static const char *internalResolutions[] = {"Auto (1:1)", "1x PSP", "2x PSP", "3x PSP", "4x PSP", "5x PSP" };
217
resolutionChoice_ = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iInternalResolution, gr->T("Rendering Resolution"), internalResolutions, 0, ARRAY_SIZE(internalResolutions), gr->GetName(), screenManager()));
218
resolutionChoice_->OnChoice.Handle(this, &GameSettingsScreen::OnResolutionChange);
219
resolutionEnable_ = !g_Config.bSoftwareRendering && (g_Config.iRenderingMode != FB_NON_BUFFERED_MODE);
220
resolutionChoice_->SetEnabledPtr(&resolutionEnable_);
223
static const char *deviceResolutions[] = { "Native device resolution", "Auto (same as Rendering)", "1x PSP", "2x PSP", "3x PSP", "4x PSP", "5x PSP" };
224
int max_res_temp = std::max(System_GetPropertyInt(SYSPROP_DISPLAY_XRES), System_GetPropertyInt(SYSPROP_DISPLAY_YRES)) / 480 + 2;
225
if (max_res_temp == 3)
226
max_res_temp = 4; // At least allow 2x
227
int max_res = std::min(max_res_temp, (int)ARRAY_SIZE(deviceResolutions));
228
UI::PopupMultiChoice *hwscale = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iAndroidHwScale, gr->T("Display Resolution (HW scaler)"), deviceResolutions, 0, max_res, gr->GetName(), screenManager()));
229
hwscale->OnChoice.Handle(this, &GameSettingsScreen::OnHwScaleChange); // To refresh the display mode
233
graphicsSettings->Add(new CheckBox(&g_Config.bVSync, gr->T("VSync")));
235
CheckBox *mipmapping = graphicsSettings->Add(new CheckBox(&g_Config.bMipMap, gr->T("Mipmapping")));
236
mipmapping->SetDisabledPtr(&g_Config.bSoftwareRendering);
238
CheckBox *hwTransform = graphicsSettings->Add(new CheckBox(&g_Config.bHardwareTransform, gr->T("Hardware Transform")));
239
hwTransform->OnClick.Handle(this, &GameSettingsScreen::OnHardwareTransform);
240
hwTransform->SetDisabledPtr(&g_Config.bSoftwareRendering);
242
CheckBox *swSkin = graphicsSettings->Add(new CheckBox(&g_Config.bSoftwareSkinning, gr->T("Software Skinning")));
243
swSkin->SetDisabledPtr(&g_Config.bSoftwareRendering);
245
CheckBox *vtxCache = graphicsSettings->Add(new CheckBox(&g_Config.bVertexCache, gr->T("Vertex Cache")));
246
vtxCache->OnClick.Add([=](EventParams &e) {
247
settingInfo_->Show(gr->T("VertexCache Tip", "Faster, but may cause temporary flicker"), e.v);
248
return UI::EVENT_CONTINUE;
250
vtxCacheEnable_ = !g_Config.bSoftwareRendering && g_Config.bHardwareTransform;
251
vtxCache->SetEnabledPtr(&vtxCacheEnable_);
253
CheckBox *texBackoff = graphicsSettings->Add(new CheckBox(&g_Config.bTextureBackoffCache, gr->T("Lazy texture caching", "Lazy texture caching (speedup)")));
254
texBackoff->SetDisabledPtr(&g_Config.bSoftwareRendering);
256
CheckBox *texSecondary_ = graphicsSettings->Add(new CheckBox(&g_Config.bTextureSecondaryCache, gr->T("Retain changed textures", "Retain changed textures (speedup, mem hog)")));
257
texSecondary_->OnClick.Add([=](EventParams &e) {
258
settingInfo_->Show(gr->T("RetainChangedTextures Tip", "Makes many games slower, but some games a lot faster"), e.v);
259
return UI::EVENT_CONTINUE;
261
texSecondary_->SetDisabledPtr(&g_Config.bSoftwareRendering);
263
CheckBox *framebufferSlowEffects = graphicsSettings->Add(new CheckBox(&g_Config.bDisableSlowFramebufEffects, gr->T("Disable slower effects (speedup)")));
264
framebufferSlowEffects->SetDisabledPtr(&g_Config.bSoftwareRendering);
266
// Seems solid, so we hide the setting.
267
// CheckBox *vtxJit = graphicsSettings->Add(new CheckBox(&g_Config.bVertexDecoderJit, gr->T("Vertex Decoder JIT")));
269
// if (PSP_IsInited()) {
270
// vtxJit->SetEnabled(false);
273
static const char *quality[] = { "Low", "Medium", "High"};
274
PopupMultiChoice *beziersChoice = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iSplineBezierQuality, gr->T("LowCurves", "Spline/Bezier curves quality"), quality, 0, ARRAY_SIZE(quality), gr->GetName(), screenManager()));
275
beziersChoice->SetDisabledPtr(&g_Config.bSoftwareRendering);
277
// In case we're going to add few other antialiasing option like MSAA in the future.
278
// graphicsSettings->Add(new CheckBox(&g_Config.bFXAA, gr->T("FXAA")));
279
graphicsSettings->Add(new ItemHeader(gr->T("Texture Scaling")));
280
#ifndef MOBILE_DEVICE
281
static const char *texScaleLevelsNPOT[] = {"Auto", "Off", "2x", "3x", "4x", "5x"};
283
static const char *texScaleLevelsNPOT[] = {"Auto", "Off", "2x", "3x"};
286
static const char **texScaleLevels = texScaleLevelsNPOT;
287
static int numTexScaleLevels = ARRAY_SIZE(texScaleLevelsNPOT);
288
PopupMultiChoice *texScalingChoice = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iTexScalingLevel, gr->T("Upscale Level"), texScaleLevels, 0, numTexScaleLevels, gr->GetName(), screenManager()));
289
// TODO: Better check? When it won't work, it scales down anyway.
290
if (!gl_extensions.OES_texture_npot && GetGPUBackend() == GPUBackend::OPENGL) {
291
texScalingChoice->HideChoice(3); // 3x
292
texScalingChoice->HideChoice(5); // 5x
294
texScalingChoice->OnChoice.Add([=](EventParams &e) {
295
if (g_Config.iTexScalingLevel != 1) {
296
settingInfo_->Show(gr->T("UpscaleLevel Tip", "CPU heavy - some scaling may be delayed to avoid stutter"), e.v);
298
return UI::EVENT_CONTINUE;
300
texScalingChoice->SetDisabledPtr(&g_Config.bSoftwareRendering);
302
static const char *texScaleAlgos[] = { "xBRZ", "Hybrid", "Bicubic", "Hybrid + Bicubic", };
303
PopupMultiChoice *texScalingType = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iTexScalingType, gr->T("Upscale Type"), texScaleAlgos, 0, ARRAY_SIZE(texScaleAlgos), gr->GetName(), screenManager()));
304
texScalingType->SetDisabledPtr(&g_Config.bSoftwareRendering);
306
CheckBox *deposterize = graphicsSettings->Add(new CheckBox(&g_Config.bTexDeposterize, gr->T("Deposterize")));
307
deposterize->SetDisabledPtr(&g_Config.bSoftwareRendering);
309
graphicsSettings->Add(new ItemHeader(gr->T("Texture Filtering")));
310
static const char *anisoLevels[] = { "Off", "2x", "4x", "8x", "16x" };
311
PopupMultiChoice *anisoFiltering = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iAnisotropyLevel, gr->T("Anisotropic Filtering"), anisoLevels, 0, ARRAY_SIZE(anisoLevels), gr->GetName(), screenManager()));
312
anisoFiltering->SetDisabledPtr(&g_Config.bSoftwareRendering);
314
static const char *texFilters[] = { "Auto", "Nearest", "Linear", "Linear on FMV", };
315
PopupMultiChoice *texFilter = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iTexFiltering, gr->T("Texture Filter"), texFilters, 1, ARRAY_SIZE(texFilters), gr->GetName(), screenManager()));
316
texFilter->SetDisabledPtr(&g_Config.bSoftwareRendering);
318
static const char *bufFilters[] = { "Linear", "Nearest", };
319
graphicsSettings->Add(new PopupMultiChoice(&g_Config.iBufFilter, gr->T("Screen Scaling Filter"), bufFilters, 1, ARRAY_SIZE(bufFilters), gr->GetName(), screenManager()));
322
graphicsSettings->Add(new ItemHeader(gr->T("Cardboard Settings", "Cardboard Settings")));
323
CheckBox *cardboardMode = graphicsSettings->Add(new CheckBox(&g_Config.bEnableCardboard, gr->T("Enable Cardboard", "Enable Cardboard")));
324
cardboardMode->SetDisabledPtr(&g_Config.bSoftwareRendering);
325
PopupSliderChoice * cardboardScreenSize = graphicsSettings->Add(new PopupSliderChoice(&g_Config.iCardboardScreenSize, 30, 100, gr->T("Cardboard Screen Size", "Screen Size (in % of the viewport)"), 1, screenManager(), gr->T("% of viewport")));
326
cardboardScreenSize->SetDisabledPtr(&g_Config.bSoftwareRendering);
327
PopupSliderChoice *cardboardXShift = graphicsSettings->Add(new PopupSliderChoice(&g_Config.iCardboardXShift, -100, 100, gr->T("Cardboard Screen X Shift", "X Shift (in % of the void)"), 1, screenManager(), gr->T("% of the void")));
328
cardboardXShift->SetDisabledPtr(&g_Config.bSoftwareRendering);
329
PopupSliderChoice *cardboardYShift = graphicsSettings->Add(new PopupSliderChoice(&g_Config.iCardboardYShift, -100, 100, gr->T("Cardboard Screen Y Shift", "Y Shift (in % of the void)"), 1, screenManager(), gr->T("% of the void")));
330
cardboardYShift->SetDisabledPtr(&g_Config.bSoftwareRendering);
333
graphicsSettings->Add(new ItemHeader(gr->T("Hack Settings", "Hack Settings (these WILL cause glitches)")));
334
graphicsSettings->Add(new CheckBox(&g_Config.bTimerHack, gr->T("Timer Hack")));
335
CheckBox *alphaHack = graphicsSettings->Add(new CheckBox(&g_Config.bDisableAlphaTest, gr->T("Disable Alpha Test (PowerVR speedup)")));
336
alphaHack->OnClick.Add([=](EventParams &e) {
337
settingInfo_->Show(gr->T("DisableAlphaTest Tip", "Faster by sometimes drawing ugly boxes around things"), e.v);
338
return UI::EVENT_CONTINUE;
340
alphaHack->OnClick.Handle(this, &GameSettingsScreen::OnShaderChange);
341
alphaHack->SetDisabledPtr(&g_Config.bSoftwareRendering);
343
CheckBox *stencilTest = graphicsSettings->Add(new CheckBox(&g_Config.bDisableStencilTest, gr->T("Disable Stencil Test")));
344
stencilTest->SetDisabledPtr(&g_Config.bSoftwareRendering);
346
CheckBox *depthWrite = graphicsSettings->Add(new CheckBox(&g_Config.bAlwaysDepthWrite, gr->T("Always Depth Write")));
347
depthWrite->SetDisabledPtr(&g_Config.bSoftwareRendering);
349
graphicsSettings->Add(new CheckBox(&g_Config.bPrescaleUV, gr->T("Texture Coord Speedhack")));
350
depthWrite->SetDisabledPtr(&g_Config.bSoftwareRendering);
352
static const char *bloomHackOptions[] = { "Off", "Safe", "Balanced", "Aggressive" };
353
PopupMultiChoice *bloomHack = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iBloomHack, gr->T("Lower resolution for effects (reduces artifacts)"), bloomHackOptions, 0, ARRAY_SIZE(bloomHackOptions), gr->GetName(), screenManager()));
354
bloomHackEnable_ = !g_Config.bSoftwareRendering && (g_Config.iInternalResolution != 1);
355
bloomHack->SetEnabledPtr(&bloomHackEnable_);
357
graphicsSettings->Add(new ItemHeader(gr->T("Overlay Information")));
358
static const char *fpsChoices[] = {
359
"None", "Speed", "FPS", "Both"
364
graphicsSettings->Add(new PopupMultiChoice(&g_Config.iShowFPSCounter, gr->T("Show FPS Counter"), fpsChoices, 0, ARRAY_SIZE(fpsChoices), gr->GetName(), screenManager()));
365
graphicsSettings->Add(new CheckBox(&g_Config.bShowDebugStats, gr->T("Show Debug Statistics")))->OnClick.Handle(this, &GameSettingsScreen::OnJitAffectingSetting);
367
// Developer tools are not accessible ingame, so it goes here.
368
graphicsSettings->Add(new ItemHeader(gr->T("Debugging")));
369
Choice *dump = graphicsSettings->Add(new Choice(gr->T("Dump next frame to log")));
370
dump->OnClick.Handle(this, &GameSettingsScreen::OnDumpNextFrameToLog);
372
dump->SetEnabled(false);
374
// We normally use software rendering to debug so put it in debugging.
375
CheckBox *softwareGPU = graphicsSettings->Add(new CheckBox(&g_Config.bSoftwareRendering, gr->T("Software Rendering", "Software Rendering (experimental)")));
376
softwareGPU->OnClick.Add([=](EventParams &e) {
377
settingInfo_->Show(gr->T("SoftGPU Tip", "Currently VERY slow"), e.v);
378
return UI::EVENT_CONTINUE;
380
softwareGPU->OnClick.Handle(this, &GameSettingsScreen::OnSoftwareRendering);
383
softwareGPU->SetEnabled(false);
386
ViewGroup *audioSettingsScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT));
387
audioSettingsScroll->SetTag("GameSettingsAudio");
388
LinearLayout *audioSettings = new LinearLayout(ORIENT_VERTICAL);
389
audioSettings->SetSpacing(0);
390
audioSettingsScroll->Add(audioSettings);
391
tabHolder->AddTab(ms->T("Audio"), audioSettingsScroll);
393
audioSettings->Add(new ItemHeader(ms->T("Audio")));
395
audioSettings->Add(new CheckBox(&g_Config.bEnableSound, a->T("Enable Sound")));
397
PopupSliderChoice *volume = audioSettings->Add(new PopupSliderChoice(&g_Config.iGlobalVolume, VOLUME_OFF, VOLUME_MAX, a->T("Global volume"), screenManager()));
398
volume->SetEnabledPtr(&g_Config.bEnableSound);
401
if (IsVistaOrHigher()) {
402
static const char *backend[] = { "Auto", "DSound (compatible)", "WASAPI (fast)" };
403
PopupMultiChoice *audioBackend = audioSettings->Add(new PopupMultiChoice(&g_Config.iAudioBackend, a->T("Audio backend", "Audio backend (restart req.)"), backend, 0, ARRAY_SIZE(backend), a->GetName(), screenManager()));
404
audioBackend->SetEnabledPtr(&g_Config.bEnableSound);
408
static const char *latency[] = { "Low", "Medium", "High" };
409
PopupMultiChoice *lowAudio = audioSettings->Add(new PopupMultiChoice(&g_Config.iAudioLatency, a->T("Audio Latency"), latency, 0, ARRAY_SIZE(latency), gr->GetName(), screenManager()));
411
lowAudio->SetEnabledPtr(&g_Config.bEnableSound);
412
if (System_GetPropertyInt(SYSPROP_AUDIO_SAMPLE_RATE) == 44100) {
413
CheckBox *resampling = audioSettings->Add(new CheckBox(&g_Config.bAudioResampler, a->T("Audio sync", "Audio sync (resampling)")));
414
resampling->SetEnabledPtr(&g_Config.bEnableSound);
417
audioSettings->Add(new ItemHeader(a->T("Audio hacks")));
418
audioSettings->Add(new CheckBox(&g_Config.bSoundSpeedHack, a->T("Sound speed hack (DOA etc.)")));
421
ViewGroup *controlsSettingsScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT));
422
controlsSettingsScroll->SetTag("GameSettingsControls");
423
LinearLayout *controlsSettings = new LinearLayout(ORIENT_VERTICAL);
424
controlsSettings->SetSpacing(0);
425
controlsSettingsScroll->Add(controlsSettings);
426
tabHolder->AddTab(ms->T("Controls"), controlsSettingsScroll);
427
controlsSettings->Add(new ItemHeader(ms->T("Controls")));
428
controlsSettings->Add(new Choice(co->T("Control Mapping")))->OnClick.Handle(this, &GameSettingsScreen::OnControlMapping);
430
#if defined(USING_WIN_UI)
431
controlsSettings->Add(new CheckBox(&g_Config.bGamepadOnlyFocused, co->T("Ignore gamepads when not focused")));
434
#if defined(MOBILE_DEVICE)
435
controlsSettings->Add(new CheckBox(&g_Config.bHapticFeedback, co->T("HapticFeedback", "Haptic Feedback (vibration)")));
436
static const char *tiltTypes[] = { "None (Disabled)", "Analog Stick", "D-PAD", "PSP Action Buttons", "L/R Trigger Buttons"};
437
controlsSettings->Add(new PopupMultiChoice(&g_Config.iTiltInputType, co->T("Tilt Input Type"), tiltTypes, 0, ARRAY_SIZE(tiltTypes), co->GetName(), screenManager()))->OnClick.Handle(this, &GameSettingsScreen::OnTiltTypeChange);
439
Choice *customizeTilt = controlsSettings->Add(new Choice(co->T("Customize tilt")));
440
customizeTilt->OnClick.Handle(this, &GameSettingsScreen::OnTiltCustomize);
441
customizeTilt->SetEnabledPtr((bool *)&g_Config.iTiltInputType); //<- dirty int-to-bool cast
444
// TVs don't have touch control, at least not yet.
445
if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) != DEVICE_TYPE_TV) {
446
controlsSettings->Add(new ItemHeader(co->T("OnScreen", "On-Screen Touch Controls")));
447
controlsSettings->Add(new CheckBox(&g_Config.bShowTouchControls, co->T("OnScreen", "On-Screen Touch Controls")));
448
layoutEditorChoice_ = controlsSettings->Add(new Choice(co->T("Custom layout...")));
449
layoutEditorChoice_->OnClick.Handle(this, &GameSettingsScreen::OnTouchControlLayout);
450
layoutEditorChoice_->SetEnabledPtr(&g_Config.bShowTouchControls);
452
// Re-centers itself to the touch location on touch-down.
453
CheckBox *floatingAnalog = controlsSettings->Add(new CheckBox(&g_Config.bAutoCenterTouchAnalog, co->T("Auto-centering analog stick")));
454
floatingAnalog->SetEnabledPtr(&g_Config.bShowTouchControls);
457
Choice *comboKey = controlsSettings->Add(new Choice(co->T("Combo Key Setup")));
458
comboKey->OnClick.Handle(this, &GameSettingsScreen::OnCombo_key);
459
comboKey->SetEnabledPtr(&g_Config.bShowTouchControls);
461
// On systems that aren't Symbian, iOS, and Maemo, offer to let the user see this button.
462
// Some Windows touch devices don't have a back button or other button to call up the menu.
463
#if !defined(__SYMBIAN32__) && !defined(IOS) && !defined(MAEMO)
464
CheckBox *enablePauseBtn = controlsSettings->Add(new CheckBox(&g_Config.bShowTouchPause, co->T("Show Touch Pause Menu Button")));
466
// Don't allow the user to disable it once in-game, so they can't lock themselves out of the menu.
467
if (!PSP_IsInited()) {
468
enablePauseBtn->SetEnabledPtr(&g_Config.bShowTouchControls);
470
enablePauseBtn->SetEnabled(false);
474
CheckBox *disableDiags = controlsSettings->Add(new CheckBox(&g_Config.bDisableDpadDiagonals, co->T("Disable D-Pad diagonals (4-way touch)")));
475
disableDiags->SetEnabledPtr(&g_Config.bShowTouchControls);
476
PopupSliderChoice *opacity = controlsSettings->Add(new PopupSliderChoice(&g_Config.iTouchButtonOpacity, 0, 100, co->T("Button Opacity"), screenManager(), "%"));
477
opacity->SetEnabledPtr(&g_Config.bShowTouchControls);
478
opacity->SetFormat("%i%%");
479
PopupSliderChoice *autoHide = controlsSettings->Add(new PopupSliderChoice(&g_Config.iTouchButtonHideSeconds, 0, 300, co->T("Auto-hide buttons after seconds"), screenManager(), co->T("seconds, 0 : off")));
480
autoHide->SetEnabledPtr(&g_Config.bShowTouchControls);
481
autoHide->SetFormat("%is");
482
autoHide->SetZeroLabel(co->T("Off"));
483
static const char *touchControlStyles[] = {"Classic", "Thin borders"};
484
View *style = controlsSettings->Add(new PopupMultiChoice(&g_Config.iTouchButtonStyle, co->T("Button style"), touchControlStyles, 0, ARRAY_SIZE(touchControlStyles), co->GetName(), screenManager()));
485
style->SetEnabledPtr(&g_Config.bShowTouchControls);
489
static const char *inverseDeadzoneModes[] = { "Off", "X", "Y", "X + Y" };
491
controlsSettings->Add(new ItemHeader(co->T("DInput Analog Settings", "DInput Analog Settings")));
492
controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fDInputAnalogDeadzone, 0.0f, 1.0f, co->T("Deadzone Radius"), 0.01f, screenManager(), "/ 1.0"));
493
controlsSettings->Add(new PopupMultiChoice(&g_Config.iDInputAnalogInverseMode, co->T("Analog Mapper Mode"), inverseDeadzoneModes, 0, ARRAY_SIZE(inverseDeadzoneModes), co->GetName(), screenManager()));
494
controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fDInputAnalogInverseDeadzone, 0.0f, 1.0f, co->T("Analog Mapper Low End", "Analog Mapper Low End (Inverse Deadzone)"), 0.01f, screenManager(), "/ 1.0"));
495
controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fDInputAnalogSensitivity, 0.0f, 10.0f, co->T("Analog Mapper High End", "Analog Mapper High End (Axis Sensitivity)"), 0.01f, screenManager(), "x"));
497
controlsSettings->Add(new ItemHeader(co->T("XInput Analog Settings", "XInput Analog Settings")));
498
controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fXInputAnalogDeadzone, 0.0f, 1.0f, co->T("Deadzone Radius"), 0.01f, screenManager(), "/ 1.0"));
499
controlsSettings->Add(new PopupMultiChoice(&g_Config.iXInputAnalogInverseMode, co->T("Analog Mapper Mode"), inverseDeadzoneModes, 0, ARRAY_SIZE(inverseDeadzoneModes), co->GetName(), screenManager()));
500
controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fXInputAnalogInverseDeadzone, 0.0f, 1.0f, co->T("Analog Mapper Low End", "Analog Mapper Low End (Inverse Deadzone)"), 0.01f, screenManager(), "/ 1.0"));
501
controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fXInputAnalogSensitivity, 0.0f, 10.0f, co->T("Analog Mapper High End", "Analog Mapper High End (Axis Sensitivity)"), 0.01f, screenManager(), "x"));
504
controlsSettings->Add(new ItemHeader(co->T("Keyboard", "Keyboard Control Settings")));
505
#if defined(USING_WIN_UI)
506
controlsSettings->Add(new CheckBox(&g_Config.bIgnoreWindowsKey, co->T("Ignore Windows Key")));
507
#endif // #if defined(USING_WIN_UI)
508
auto analogLimiter = new PopupSliderChoiceFloat(&g_Config.fAnalogLimiterDeadzone, 0.0f, 1.0f, co->T("Analog Limiter"), 0.10f, screenManager(), "/ 1.0");
509
controlsSettings->Add(analogLimiter);
510
analogLimiter->OnChange.Add([=](EventParams &e) {
511
settingInfo_->Show(co->T("AnalogLimiter Tip", "When the analog limiter button is pressed"), e.v);
512
return UI::EVENT_CONTINUE;
515
ViewGroup *networkingSettingsScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT));
516
networkingSettingsScroll->SetTag("GameSettingsNetworking");
517
LinearLayout *networkingSettings = new LinearLayout(ORIENT_VERTICAL);
518
networkingSettings->SetSpacing(0);
519
networkingSettingsScroll->Add(networkingSettings);
520
tabHolder->AddTab(ms->T("Networking"), networkingSettingsScroll);
522
networkingSettings->Add(new ItemHeader(ms->T("Networking")));
524
networkingSettings->Add(new Choice(n->T("Adhoc Multiplayer forum")))->OnClick.Handle(this, &GameSettingsScreen::OnAdhocGuides);
526
networkingSettings->Add(new CheckBox(&g_Config.bEnableWlan, n->T("Enable networking", "Enable networking/wlan (beta)")));
529
networkingSettings->Add(new PopupTextInputChoice(&g_Config.proAdhocServer, n->T("Change proAdhocServer Address"), "", 255, screenManager()));
530
#elif defined(ANDROID)
531
networkingSettings->Add(new ChoiceWithValueDisplay(&g_Config.proAdhocServer, n->T("Change proAdhocServer Address"), nullptr))->OnClick.Handle(this, &GameSettingsScreen::OnChangeproAdhocServerAddress);
533
networkingSettings->Add(new ChoiceWithValueDisplay(&g_Config.proAdhocServer, n->T("Change proAdhocServer Address"), nullptr))->OnClick.Handle(this, &GameSettingsScreen::OnChangeproAdhocServerAddress);
535
networkingSettings->Add(new CheckBox(&g_Config.bEnableAdhocServer, n->T("Enable built-in PRO Adhoc Server", "Enable built-in PRO Adhoc Server")));
536
networkingSettings->Add(new ChoiceWithValueDisplay(&g_Config.sMACAddress, n->T("Change Mac Address"), nullptr))->OnClick.Handle(this, &GameSettingsScreen::OnChangeMacAddress);
537
networkingSettings->Add(new PopupSliderChoice(&g_Config.iPortOffset, 0, 60000, n->T("Port offset", "Port offset(0 = PSP compatibility)"), 100, screenManager()));
539
ViewGroup *toolsScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT));
540
toolsScroll->SetTag("GameSettingsTools");
541
LinearLayout *tools = new LinearLayout(ORIENT_VERTICAL);
542
tools->SetSpacing(0);
543
toolsScroll->Add(tools);
544
tabHolder->AddTab(ms->T("Tools"), toolsScroll);
546
tools->Add(new ItemHeader(ms->T("Tools")));
547
// These were moved here so use the wrong translation objects, to avoid having to change all inis... This isn't a sustainable situation :P
548
tools->Add(new Choice(sa->T("Savedata Manager")))->OnClick.Handle(this, &GameSettingsScreen::OnSavedataManager);
549
tools->Add(new Choice(dev->T("System Information")))->OnClick.Handle(this, &GameSettingsScreen::OnSysInfo);
550
tools->Add(new Choice(sy->T("Developer Tools")))->OnClick.Handle(this, &GameSettingsScreen::OnDeveloperTools);
551
tools->Add(new Choice(sy->T("Remote disc streaming")))->OnClick.Handle(this, &GameSettingsScreen::OnRemoteISO);
554
ViewGroup *systemSettingsScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT));
555
systemSettingsScroll->SetTag("GameSettingsSystem");
556
LinearLayout *systemSettings = new LinearLayout(ORIENT_VERTICAL);
557
systemSettings->SetSpacing(0);
558
systemSettingsScroll->Add(systemSettings);
559
tabHolder->AddTab(ms->T("System"), systemSettingsScroll);
561
systemSettings->Add(new ItemHeader(sy->T("UI Language")));
562
systemSettings->Add(new Choice(dev->T("Language", "Language")))->OnClick.Handle(this, &GameSettingsScreen::OnLanguage);
564
systemSettings->Add(new ItemHeader(sy->T("Help the PPSSPP team")));
565
enableReports_ = Reporting::IsEnabled();
566
enableReportsCheckbox_ = new CheckBox(&enableReports_, sy->T("Enable Compatibility Server Reports"));
567
enableReportsCheckbox_->SetEnabled(Reporting::IsSupported());
568
systemSettings->Add(enableReportsCheckbox_);
570
systemSettings->Add(new ItemHeader(sy->T("Emulation")));
572
systemSettings->Add(new CheckBox(&g_Config.bFastMemory, sy->T("Fast Memory", "Fast Memory (Unstable)")))->OnClick.Handle(this, &GameSettingsScreen::OnJitAffectingSetting);
574
auto separateCPUThread = new CheckBox(&g_Config.bSeparateCPUThread, sy->T("Multithreaded (experimental)"));
575
systemSettings->Add(separateCPUThread);
576
separateCPUThread->OnClick.Add([=](EventParams &e) {
577
settingInfo_->Show(sy->T("Mulithreaded Tip", "Not always faster, causes glitches/crashing"), e.v);
578
return UI::EVENT_CONTINUE;
580
systemSettings->Add(new CheckBox(&g_Config.bSeparateIOThread, sy->T("I/O on thread (experimental)")))->SetEnabled(!PSP_IsInited());
581
static const char *ioTimingMethods[] = { "Fast (lag on slow storage)", "Host (bugs, less lag)", "Simulate UMD delays" };
582
View *ioTimingMethod = systemSettings->Add(new PopupMultiChoice(&g_Config.iIOTimingMethod, sy->T("IO timing method"), ioTimingMethods, 0, ARRAY_SIZE(ioTimingMethods), sy->GetName(), screenManager()));
583
ioTimingMethod->SetEnabledPtr(&g_Config.bSeparateIOThread);
584
systemSettings->Add(new CheckBox(&g_Config.bForceLagSync, sy->T("Force real clock sync (slower, less lag)")));
585
PopupSliderChoice *lockedMhz = systemSettings->Add(new PopupSliderChoice(&g_Config.iLockedCPUSpeed, 0, 1000, sy->T("Change CPU Clock", "Change CPU Clock (unstable)"), screenManager(), sy->T("MHz, 0:default")));
586
lockedMhz->SetZeroLabel(sy->T("Auto"));
587
PopupSliderChoice *rewindFreq = systemSettings->Add(new PopupSliderChoice(&g_Config.iRewindFlipFrequency, 0, 1800, sy->T("Rewind Snapshot Frequency", "Rewind Snapshot Frequency (mem hog)"), screenManager(), sy->T("frames, 0:off")));
588
rewindFreq->SetZeroLabel(sy->T("Off"));
590
systemSettings->Add(new CheckBox(&g_Config.bMemStickInserted, sy->T("Memory Stick inserted")));
592
systemSettings->Add(new ItemHeader(sy->T("General")));
595
if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) == DEVICE_TYPE_MOBILE) {
596
static const char *screenRotation[] = {"Auto", "Landscape", "Portrait", "Landscape Reversed", "Portrait Reversed"};
597
PopupMultiChoice *rot = systemSettings->Add(new PopupMultiChoice(&g_Config.iScreenRotation, co->T("Screen Rotation"), screenRotation, 0, ARRAY_SIZE(screenRotation), co->GetName(), screenManager()));
598
rot->OnChoice.Handle(this, &GameSettingsScreen::OnScreenRotation);
602
systemSettings->Add(new CheckBox(&g_Config.bCheckForNewVersion, sy->T("VersionCheck", "Check for new versions of PPSSPP")));
603
if (g_Config.iMaxRecent > 0)
604
systemSettings->Add(new Choice(sy->T("Clear Recent Games List")))->OnClick.Handle(this, &GameSettingsScreen::OnClearRecents);
605
systemSettings->Add(new Choice(sy->T("Restore Default Settings")))->OnClick.Handle(this, &GameSettingsScreen::OnRestoreDefaultSettings);
606
systemSettings->Add(new CheckBox(&g_Config.bEnableAutoLoad, sy->T("Auto Load Newest Savestate")));
608
#if defined(USING_WIN_UI)
609
systemSettings->Add(new CheckBox(&g_Config.bBypassOSKWithKeyboard, sy->T("Enable Windows native keyboard", "Enable Windows native keyboard")));
612
SavePathInMyDocumentChoice = systemSettings->Add(new CheckBox(&installed_, sy->T("Save path in My Documents", "Save path in My Documents")));
613
SavePathInMyDocumentChoice->OnClick.Handle(this, &GameSettingsScreen::OnSavePathMydoc);
614
SavePathInOtherChoice = systemSettings->Add(new CheckBox(&otherinstalled_, sy->T("Save path in installed.txt", "Save path in installed.txt")));
615
SavePathInOtherChoice->SetEnabled(false);
616
SavePathInOtherChoice->OnClick.Handle(this, &GameSettingsScreen::OnSavePathOther);
617
wchar_t myDocumentsPath[MAX_PATH];
618
const HRESULT result = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, myDocumentsPath);
619
const std::string PPSSPPpath = File::GetExeDirectory();
620
const std::string installedFile = PPSSPPpath + "installed.txt";
621
installed_ = File::Exists(installedFile);
622
otherinstalled_ = false;
623
if (!installed_ && result == S_OK) {
624
if (File::CreateEmptyFile(PPSSPPpath + "installedTEMP.txt")) {
625
// Disable the setting whether cannot create & delete file
626
if (!(File::Delete(PPSSPPpath + "installedTEMP.txt")))
627
SavePathInMyDocumentChoice->SetEnabled(false);
629
SavePathInOtherChoice->SetEnabled(true);
631
SavePathInMyDocumentChoice->SetEnabled(false);
633
if (installed_ && (result == S_OK)) {
634
std::ifstream inputFile(ConvertUTF8ToWString(installedFile));
635
if (!inputFile.fail() && inputFile.is_open()) {
636
std::string tempString;
637
std::getline(inputFile, tempString);
639
// Skip UTF-8 encoding bytes if there are any. There are 3 of them.
640
if (tempString.substr(0, 3) == "\xEF\xBB\xBF")
641
tempString = tempString.substr(3);
642
SavePathInOtherChoice->SetEnabled(true);
643
if (!(tempString == "")) {
645
otherinstalled_ = true;
649
} else if (result != S_OK)
650
SavePathInMyDocumentChoice->SetEnabled(false);
655
systemSettings->Add(new CheckBox(&g_Config.bCacheFullIsoInRam, sy->T("Cache ISO in RAM", "Cache full ISO in RAM")));
659
systemSettings->Add(new ItemHeader(sy->T("Cheats", "Cheats (experimental, see forums)")));
660
systemSettings->Add(new CheckBox(&g_Config.bEnableCheats, sy->T("Enable Cheats")));
662
systemSettings->SetSpacing(0);
664
systemSettings->Add(new ItemHeader(sy->T("PSP Settings")));
665
static const char *models[] = {"PSP-1000" , "PSP-2000/3000"};
666
systemSettings->Add(new PopupMultiChoice(&g_Config.iPSPModel, sy->T("PSP Model"), models, 0, ARRAY_SIZE(models), sy->GetName(), screenManager()))->SetEnabled(!PSP_IsInited());
667
// TODO: Come up with a way to display a keyboard for mobile users,
668
// so until then, this is Windows/Desktop only.
669
#if defined(_WIN32) // TODO: Add all platforms where KEY_CHAR support is added
670
systemSettings->Add(new PopupTextInputChoice(&g_Config.sNickName, sy->T("Change Nickname"), "", 32, screenManager()));
671
#elif defined(USING_QT_UI)
672
systemSettings->Add(new Choice(sy->T("Change Nickname")))->OnClick.Handle(this, &GameSettingsScreen::OnChangeNickname);
673
#elif defined(ANDROID)
674
systemSettings->Add(new ChoiceWithValueDisplay(&g_Config.sNickName, sy->T("Change Nickname"), nullptr))->OnClick.Handle(this, &GameSettingsScreen::OnChangeNickname);
676
#if defined(_WIN32) || (defined(USING_QT_UI) && !defined(MOBILE_DEVICE))
677
// Screenshot functionality is not yet available on non-Windows/non-Qt
678
systemSettings->Add(new CheckBox(&g_Config.bScreenshotsAsPNG, sy->T("Screenshots as PNG")));
679
systemSettings->Add(new CheckBox(&g_Config.bDumpFrames, sy->T("Record Display")));
680
systemSettings->Add(new CheckBox(&g_Config.bUseFFV1, sy->T("Use Lossless Video Codec (FFV1)")));
681
systemSettings->Add(new CheckBox(&g_Config.bDumpAudio, sy->T("Record Audio")));
683
systemSettings->Add(new CheckBox(&g_Config.bDayLightSavings, sy->T("Day Light Saving")));
684
static const char *dateFormat[] = { "YYYYMMDD", "MMDDYYYY", "DDMMYYYY"};
685
systemSettings->Add(new PopupMultiChoice(&g_Config.iDateFormat, sy->T("Date Format"), dateFormat, 1, 3, sy->GetName(), screenManager()));
686
static const char *timeFormat[] = { "12HR", "24HR"};
687
systemSettings->Add(new PopupMultiChoice(&g_Config.iTimeFormat, sy->T("Time Format"), timeFormat, 1, 2, sy->GetName(), screenManager()));
688
static const char *buttonPref[] = { "Use O to confirm", "Use X to confirm" };
689
systemSettings->Add(new PopupMultiChoice(&g_Config.iButtonPreference, sy->T("Confirmation Button"), buttonPref, 0, 2, sy->GetName(), screenManager()));
692
UI::EventReturn GameSettingsScreen::OnAutoFrameskip(UI::EventParams &e) {
693
if (g_Config.bAutoFrameSkip && g_Config.iFrameSkip == 0) {
694
g_Config.iFrameSkip = 1;
696
if (g_Config.bAutoFrameSkip && g_Config.iRenderingMode == FB_NON_BUFFERED_MODE) {
697
g_Config.iRenderingMode = FB_BUFFERED_MODE;
699
return UI::EVENT_DONE;
702
UI::EventReturn GameSettingsScreen::OnSoftwareRendering(UI::EventParams &e) {
703
vtxCacheEnable_ = !g_Config.bSoftwareRendering && g_Config.bHardwareTransform;
704
postProcEnable_ = !g_Config.bSoftwareRendering && (g_Config.iRenderingMode != FB_NON_BUFFERED_MODE);
705
resolutionEnable_ = !g_Config.bSoftwareRendering && (g_Config.iRenderingMode != FB_NON_BUFFERED_MODE);
706
return UI::EVENT_DONE;
709
UI::EventReturn GameSettingsScreen::OnHardwareTransform(UI::EventParams &e) {
710
vtxCacheEnable_ = !g_Config.bSoftwareRendering && g_Config.bHardwareTransform;
711
return UI::EVENT_DONE;
714
UI::EventReturn GameSettingsScreen::OnScreenRotation(UI::EventParams &e) {
715
ILOG("New display rotation: %d", g_Config.iScreenRotation);
716
ILOG("Sending rotate");
717
System_SendMessage("rotate", "");
718
ILOG("Got back from rotate");
719
return UI::EVENT_DONE;
722
static void RecreateActivity() {
723
const int SYSTEM_JELLYBEAN = 16;
724
if (System_GetPropertyInt(SYSPROP_SYSTEMVERSION) >= SYSTEM_JELLYBEAN) {
725
ILOG("Sending recreate");
726
System_SendMessage("recreate", "");
727
ILOG("Got back from recreate");
729
I18NCategory *gr = GetI18NCategory("Graphics");
730
System_SendMessage("toast", gr->T("Must Restart", "You must restart PPSSPP for this change to take effect"));
734
UI::EventReturn GameSettingsScreen::OnAdhocGuides(UI::EventParams &e) {
735
LaunchBrowser("http://forums.ppsspp.org/forumdisplay.php?fid=34");
736
return UI::EVENT_DONE;
739
UI::EventReturn GameSettingsScreen::OnImmersiveModeChange(UI::EventParams &e) {
740
System_SendMessage("immersive", "");
741
const int SYSTEM_JELLYBEAN = 16;
742
// recreate doesn't seem reliable on earlier versions.
743
if (g_Config.iAndroidHwScale != 0) {
746
return UI::EVENT_DONE;
749
UI::EventReturn GameSettingsScreen::OnRenderingMode(UI::EventParams &e) {
750
// We do not want to report when rendering mode is Framebuffer to memory - so many issues
751
// are caused by that (framebuffer copies overwriting display lists, etc).
752
Reporting::UpdateConfig();
753
enableReports_ = Reporting::IsEnabled();
754
enableReportsCheckbox_->SetEnabled(Reporting::IsSupported());
756
postProcEnable_ = !g_Config.bSoftwareRendering && (g_Config.iRenderingMode != FB_NON_BUFFERED_MODE);
757
resolutionEnable_ = !g_Config.bSoftwareRendering && (g_Config.iRenderingMode != FB_NON_BUFFERED_MODE);
759
if (g_Config.iRenderingMode == FB_NON_BUFFERED_MODE) {
760
g_Config.bAutoFrameSkip = false;
762
return UI::EVENT_DONE;
765
UI::EventReturn GameSettingsScreen::OnJitAffectingSetting(UI::EventParams &e) {
766
NativeMessageReceived("clear jit", "");
767
return UI::EVENT_DONE;
772
UI::EventReturn GameSettingsScreen::OnSavePathMydoc(UI::EventParams &e) {
773
const std::string PPSSPPpath = File::GetExeDirectory();
774
const std::string installedFile = PPSSPPpath + "installed.txt";
775
installed_ = File::Exists(installedFile);
776
if (otherinstalled_) {
777
File::Delete(PPSSPPpath + "installed.txt");
778
File::CreateEmptyFile(PPSSPPpath + "installed.txt");
779
otherinstalled_ = false;
780
wchar_t myDocumentsPath[MAX_PATH];
781
const HRESULT result = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, myDocumentsPath);
782
const std::string myDocsPath = ConvertWStringToUTF8(myDocumentsPath) + "/PPSSPP/";
783
g_Config.memStickDirectory = myDocsPath;
785
else if (installed_) {
786
File::Delete(PPSSPPpath + "installed.txt");
788
g_Config.memStickDirectory = PPSSPPpath + "memstick/";
791
std::ofstream myfile;
792
myfile.open(PPSSPPpath + "installed.txt");
793
if (myfile.is_open()){
797
wchar_t myDocumentsPath[MAX_PATH];
798
const HRESULT result = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, myDocumentsPath);
799
const std::string myDocsPath = ConvertWStringToUTF8(myDocumentsPath) + "/PPSSPP/";
800
g_Config.memStickDirectory = myDocsPath;
803
return UI::EVENT_DONE;
806
UI::EventReturn GameSettingsScreen::OnSavePathOther(UI::EventParams &e) {
807
const std::string PPSSPPpath = File::GetExeDirectory();
808
if (otherinstalled_) {
809
I18NCategory *di = GetI18NCategory("Dialog");
810
std::string folder = W32Util::BrowseForFolder(MainWindow::GetHWND(), di->T("Choose PPSSPP save folder"));
812
g_Config.memStickDirectory = folder;
813
FILE *f = File::OpenCFile(PPSSPPpath + "installed.txt", "wb");
815
std::string utfstring("\xEF\xBB\xBF");
816
utfstring.append(folder);
817
fwrite(utfstring.c_str(), 1, utfstring.length(), f);
823
otherinstalled_ = false;
826
File::Delete(PPSSPPpath + "installed.txt");
827
SavePathInMyDocumentChoice->SetEnabled(true);
828
otherinstalled_ = false;
830
g_Config.memStickDirectory = PPSSPPpath + "memstick/";
832
return UI::EVENT_DONE;
837
UI::EventReturn GameSettingsScreen::OnClearRecents(UI::EventParams &e) {
838
g_Config.recentIsos.clear();
839
OnRecentChanged.Trigger(e);
840
return UI::EVENT_DONE;
843
UI::EventReturn GameSettingsScreen::OnReloadCheats(UI::EventParams &e) {
844
// Hmm, strange mechanism.
845
g_Config.bReloadCheats = true;
846
return UI::EVENT_DONE;
849
UI::EventReturn GameSettingsScreen::OnFullscreenChange(UI::EventParams &e) {
850
#if defined(USING_WIN_UI) || defined(USING_QT_UI)
851
host->GoFullscreen(g_Config.bFullScreen);
854
System_SendMessage("toggle_fullscreen", "");
856
return UI::EVENT_DONE;
859
UI::EventReturn GameSettingsScreen::OnDisplayLayoutEditor(UI::EventParams &e) {
860
screenManager()->push(new DisplayLayoutScreen());
861
return UI::EVENT_DONE;
864
UI::EventReturn GameSettingsScreen::OnResolutionChange(UI::EventParams &e) {
868
if (g_Config.iAndroidHwScale == 1) {
871
Reporting::UpdateConfig();
872
return UI::EVENT_DONE;
875
UI::EventReturn GameSettingsScreen::OnHwScaleChange(UI::EventParams &e) {
877
return UI::EVENT_DONE;
880
UI::EventReturn GameSettingsScreen::OnShaderChange(UI::EventParams &e) {
882
gpu->ClearShaderCache();
884
return UI::EVENT_DONE;
887
UI::EventReturn GameSettingsScreen::OnDumpNextFrameToLog(UI::EventParams &e) {
889
gpu->DumpNextFrame();
891
return UI::EVENT_DONE;
894
void GameSettingsScreen::update(InputState &input) {
895
UIScreen::update(input);
896
g_Config.iForceMaxEmulatedFPS = cap60FPS_ ? 60 : 0;
898
g_Config.iFpsLimit = (iAlternateSpeedPercent_ * 60) / 100;
900
bool vertical = UseVerticalLayout();
901
if (vertical != lastVertical_) {
903
lastVertical_ = vertical;
907
void GameSettingsScreen::sendMessage(const char *message, const char *value) {
908
// Always call the base class method first to handle the most common messages.
909
UIDialogScreenWithBackground::sendMessage(message, value);
911
if (!strcmp(message, "control mapping")) {
912
UpdateUIState(UISTATE_MENU);
913
screenManager()->push(new ControlMappingScreen());
915
if (!strcmp(message, "display layout editor")) {
916
UpdateUIState(UISTATE_MENU);
917
screenManager()->push(new DisplayLayoutScreen());
921
void GameSettingsScreen::onFinish(DialogResult result) {
922
if (g_Config.bEnableSound) {
923
if (PSP_IsInited() && !IsAudioInitialised())
927
Reporting::Enable(enableReports_, "report.ppsspp.org");
928
Reporting::UpdateConfig();
930
if (editThenRestore_) {
931
g_Config.unloadGameConfig();
936
KeyMap::UpdateNativeMenuKeys();
940
void GlobalSettingsScreen::CreateViews() {
942
root_ = new ScrollView(ORIENT_VERTICAL);
944
enableReports_ = Reporting::IsEnabled();
947
void GameSettingsScreen::CallbackRenderingBackend(bool yes) {
949
// If the user ends up deciding not to restart, set the config back to the current backend
950
// so it doesn't get switched by accident.
952
g_Config.bRestartRequired = true;
953
PostMessage(MainWindow::GetHWND(), WM_CLOSE, 0, 0);
955
g_Config.iGPUBackend = (int)GetGPUBackend();
960
UI::EventReturn GameSettingsScreen::OnRenderingBackend(UI::EventParams &e) {
962
I18NCategory *di = GetI18NCategory("Dialog");
964
// It only makes sense to show the restart prompt if the backend was actually changed.
965
if (g_Config.iGPUBackend != (int)GetGPUBackend()) {
966
screenManager()->push(new PromptScreen(di->T("ChangingGPUBackends", "Changing GPU backends requires PPSSPP to restart. Restart now?"), di->T("Yes"), di->T("No"),
967
std::bind(&GameSettingsScreen::CallbackRenderingBackend, this, placeholder::_1)));
970
return UI::EVENT_DONE;
973
UI::EventReturn GameSettingsScreen::OnChangeNickname(UI::EventParams &e) {
974
#if defined(_WIN32) || defined(USING_QT_UI)
975
const size_t name_len = 256;
978
memset(name, 0, sizeof(name));
980
if (System_InputBoxGetString("Enter a new PSP nickname", g_Config.sNickName.c_str(), name, name_len)) {
981
g_Config.sNickName = name;
983
#elif defined(ANDROID)
984
System_SendMessage("inputbox", ("nickname:" + g_Config.sNickName).c_str());
986
return UI::EVENT_DONE;
989
UI::EventReturn GameSettingsScreen::OnChangeproAdhocServerAddress(UI::EventParams &e) {
990
#if defined(_WIN32) || defined(USING_QT_UI)
991
if (!g_Config.bFullScreen) {
992
const size_t name_len = 256;
995
memset(name, 0, sizeof(name));
997
if (System_InputBoxGetString("Enter an IP address", g_Config.proAdhocServer.c_str(), name, name_len)) {
998
g_Config.proAdhocServer = name;
1002
screenManager()->push(new ProAdhocServerScreen);
1003
#elif defined(ANDROID)
1004
System_SendMessage("inputbox", ("IP:" + g_Config.proAdhocServer).c_str());
1006
screenManager()->push(new ProAdhocServerScreen);
1009
return UI::EVENT_DONE;
1012
UI::EventReturn GameSettingsScreen::OnChangeMacAddress(UI::EventParams &e) {
1013
g_Config.sMACAddress = std::string(CreateRandMAC());
1015
return UI::EVENT_DONE;
1018
UI::EventReturn GameSettingsScreen::OnCombo_key(UI::EventParams &e) {
1019
screenManager()->push(new Combo_keyScreen(&g_Config.iComboMode));
1020
return UI::EVENT_DONE;
1023
UI::EventReturn GameSettingsScreen::OnLanguage(UI::EventParams &e) {
1024
I18NCategory *dev = GetI18NCategory("Developer");
1025
auto langScreen = new NewLanguageScreen(dev->T("Language"));
1026
langScreen->OnChoice.Handle(this, &GameSettingsScreen::OnLanguageChange);
1027
screenManager()->push(langScreen);
1028
return UI::EVENT_DONE;
1031
UI::EventReturn GameSettingsScreen::OnLanguageChange(UI::EventParams &e) {
1032
screenManager()->RecreateAllViews();
1037
return UI::EVENT_DONE;
1040
UI::EventReturn GameSettingsScreen::OnPostProcShader(UI::EventParams &e) {
1041
I18NCategory *gr = GetI18NCategory("Graphics");
1042
auto procScreen = new PostProcScreen(gr->T("Postprocessing Shader"));
1043
procScreen->OnChoice.Handle(this, &GameSettingsScreen::OnPostProcShaderChange);
1044
screenManager()->push(procScreen);
1045
return UI::EVENT_DONE;
1048
UI::EventReturn GameSettingsScreen::OnPostProcShaderChange(UI::EventParams &e) {
1052
Reporting::UpdateConfig();
1053
return UI::EVENT_DONE;
1056
UI::EventReturn GameSettingsScreen::OnDeveloperTools(UI::EventParams &e) {
1057
screenManager()->push(new DeveloperToolsScreen());
1058
return UI::EVENT_DONE;
1061
UI::EventReturn GameSettingsScreen::OnRemoteISO(UI::EventParams &e) {
1062
screenManager()->push(new RemoteISOScreen());
1063
return UI::EVENT_DONE;
1066
UI::EventReturn GameSettingsScreen::OnControlMapping(UI::EventParams &e) {
1067
screenManager()->push(new ControlMappingScreen());
1068
return UI::EVENT_DONE;
1071
UI::EventReturn GameSettingsScreen::OnTouchControlLayout(UI::EventParams &e) {
1072
screenManager()->push(new TouchControlLayoutScreen());
1073
return UI::EVENT_DONE;
1076
//when the tilt event type is modified, we need to reset all tilt settings.
1077
//refer to the ResetTiltEvents() function for a detailed explanation.
1078
UI::EventReturn GameSettingsScreen::OnTiltTypeChange(UI::EventParams &e){
1079
TiltEventProcessor::ResetTiltEvents();
1080
return UI::EVENT_DONE;
1083
UI::EventReturn GameSettingsScreen::OnTiltCustomize(UI::EventParams &e){
1084
screenManager()->push(new TiltAnalogSettingsScreen());
1085
return UI::EVENT_DONE;
1088
UI::EventReturn GameSettingsScreen::OnSavedataManager(UI::EventParams &e) {
1089
auto saveData = new SavedataScreen("");
1090
screenManager()->push(saveData);
1091
return UI::EVENT_DONE;
1094
UI::EventReturn GameSettingsScreen::OnSysInfo(UI::EventParams &e) {
1095
screenManager()->push(new SystemInfoScreen());
1096
return UI::EVENT_DONE;
1099
void DeveloperToolsScreen::CreateViews() {
1101
root_ = new ScrollView(ORIENT_VERTICAL);
1102
root_->SetTag("DevToolsSettings");
1104
I18NCategory *di = GetI18NCategory("Dialog");
1105
I18NCategory *dev = GetI18NCategory("Developer");
1106
I18NCategory *gr = GetI18NCategory("Graphics");
1107
I18NCategory *a = GetI18NCategory("Audio");
1108
I18NCategory *sy = GetI18NCategory("System");
1110
LinearLayout *list = root_->Add(new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(1.0f)));
1111
list->SetSpacing(0);
1112
list->Add(new ItemHeader(sy->T("General")));
1114
bool canUseJit = true;
1115
// iOS can now use JIT on all modes, apparently.
1116
// The bool may come in handy for future non-jit platforms though (UWP XB1?)
1118
static const char *cpuCores[] = { "Interpreter", "Dynarec (JIT)", "IR Interpreter" };
1119
PopupMultiChoice *core = list->Add(new PopupMultiChoice(&g_Config.iCpuCore, gr->T("CPU Core"), cpuCores, 0, ARRAY_SIZE(cpuCores), sy->GetName(), screenManager()));
1120
core->OnChoice.Handle(this, &DeveloperToolsScreen::OnJitAffectingSetting);
1122
core->HideChoice(1);
1125
list->Add(new CheckBox(&g_Config.bShowDeveloperMenu, dev->T("Show Developer Menu")));
1126
list->Add(new CheckBox(&g_Config.bDumpDecryptedEboot, dev->T("Dump Decrypted Eboot", "Dump Decrypted EBOOT.BIN (If Encrypted) When Booting Game")));
1128
Choice *cpuTests = new Choice(dev->T("Run CPU Tests"));
1129
list->Add(cpuTests)->OnClick.Handle(this, &DeveloperToolsScreen::OnRunCPUTests);
1131
const std::string testDirectory = g_Config.flash0Directory + "../";
1133
const std::string testDirectory = g_Config.memStickDirectory;
1135
if (!File::Exists(testDirectory + "pspautotests/tests/")) {
1136
cpuTests->SetEnabled(false);
1139
list->Add(new CheckBox(&g_Config.bEnableLogging, dev->T("Enable Logging")))->OnClick.Handle(this, &DeveloperToolsScreen::OnLoggingChanged);
1140
list->Add(new Choice(dev->T("Logging Channels")))->OnClick.Handle(this, &DeveloperToolsScreen::OnLogConfig);
1141
list->Add(new ItemHeader(dev->T("Language")));
1142
list->Add(new Choice(dev->T("Load language ini")))->OnClick.Handle(this, &DeveloperToolsScreen::OnLoadLanguageIni);
1143
list->Add(new Choice(dev->T("Save language ini")))->OnClick.Handle(this, &DeveloperToolsScreen::OnSaveLanguageIni);
1144
list->Add(new ItemHeader(dev->T("Texture Replacement")));
1145
list->Add(new CheckBox(&g_Config.bSaveNewTextures, dev->T("Save new textures")));
1146
list->Add(new CheckBox(&g_Config.bReplaceTextures, dev->T("Replace textures")));
1147
#if !defined(MOBILE_DEVICE)
1148
list->Add(new Choice(dev->T("Create/Open textures.ini file for current game")))->OnClick.Handle(this, &DeveloperToolsScreen::OnOpenTexturesIniFile);
1150
list->Add(new ItemHeader(""));
1151
list->Add(new Choice(di->T("Back")))->OnClick.Handle<UIScreen>(this, &UIScreen::OnBack);
1154
void DeveloperToolsScreen::onFinish(DialogResult result) {
1158
void GameSettingsScreen::CallbackRestoreDefaults(bool yes) {
1160
g_Config.RestoreDefaults();
1164
UI::EventReturn GameSettingsScreen::OnRestoreDefaultSettings(UI::EventParams &e) {
1165
I18NCategory *dev = GetI18NCategory("Developer");
1166
I18NCategory *di = GetI18NCategory("Dialog");
1167
if (g_Config.bGameSpecific)
1169
screenManager()->push(
1170
new PromptScreen(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"),
1171
std::bind(&GameSettingsScreen::CallbackRestoreDefaults, this, placeholder::_1)));
1175
screenManager()->push(
1176
new PromptScreen(dev->T("RestoreDefaultSettings", "Are you sure you want to restore all settings(except control mapping)\nback to their defaults?\nYou can't undo this.\nPlease restart PPSSPP after restoring settings."), di->T("OK"), di->T("Cancel"),
1177
std::bind(&GameSettingsScreen::CallbackRestoreDefaults, this, placeholder::_1)));
1180
return UI::EVENT_DONE;
1183
UI::EventReturn DeveloperToolsScreen::OnLoggingChanged(UI::EventParams &e) {
1184
host->ToggleDebugConsoleVisibility();
1185
return UI::EVENT_DONE;
1188
UI::EventReturn DeveloperToolsScreen::OnRunCPUTests(UI::EventParams &e) {
1190
return UI::EVENT_DONE;
1193
UI::EventReturn DeveloperToolsScreen::OnSaveLanguageIni(UI::EventParams &e) {
1194
i18nrepo.SaveIni(g_Config.sLanguageIni);
1195
return UI::EVENT_DONE;
1198
UI::EventReturn DeveloperToolsScreen::OnLoadLanguageIni(UI::EventParams &e) {
1199
i18nrepo.LoadIni(g_Config.sLanguageIni);
1200
return UI::EVENT_DONE;
1203
UI::EventReturn DeveloperToolsScreen::OnOpenTexturesIniFile(UI::EventParams &e) {
1204
std::string gameID = g_paramSFO.GetValueString("DISC_ID");
1205
std::string texturesDirectory = GetSysDirectory(DIRECTORY_TEXTURES) + gameID + "/";
1206
bool enabled_ = !gameID.empty();
1208
if (!File::Exists(texturesDirectory)) {
1209
File::CreateFullPath(texturesDirectory);
1211
if (!File::Exists(texturesDirectory + "textures.ini")) {
1212
FILE *f = File::OpenCFile(texturesDirectory + "textures.ini", "wb");
1214
fwrite("\xEF\xBB\xBF", 0, 3, f);
1216
// Let's also write some defaults
1218
File::OpenCPPFile(fs, texturesDirectory + "textures.ini", std::ios::out | std::ios::ate);
1219
fs << "# This file is optional\n";
1220
fs << "# for syntax explanation check:\n";
1221
fs << "# - https://github.com/hrydgard/ppsspp/pull/8715 \n";
1222
fs << "# - https://github.com/hrydgard/ppsspp/pull/8792 \n";
1223
fs << "[options]\n";
1224
fs << "version = 1\n";
1225
fs << "hash = quick\n";
1229
fs << "[hashranges]\n";
1233
enabled_ = File::Exists(texturesDirectory + "textures.ini");
1236
File::openIniFile(texturesDirectory + "textures.ini");
1238
return UI::EVENT_DONE;
1241
UI::EventReturn DeveloperToolsScreen::OnLogConfig(UI::EventParams &e) {
1242
screenManager()->push(new LogConfigScreen());
1243
return UI::EVENT_DONE;
1246
UI::EventReturn DeveloperToolsScreen::OnJitAffectingSetting(UI::EventParams &e) {
1247
NativeMessageReceived("clear jit", "");
1248
return UI::EVENT_DONE;
1251
void ProAdhocServerScreen::CreateViews() {
1253
I18NCategory *sy = GetI18NCategory("System");
1254
I18NCategory *di = GetI18NCategory("Dialog");
1256
tempProAdhocServer = g_Config.proAdhocServer;
1257
root_ = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT));
1258
LinearLayout *leftColumn = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT));
1260
leftColumn->Add(new ItemHeader(sy->T("proAdhocServer Address:")));
1261
addrView_ = new TextView(tempProAdhocServer, ALIGN_LEFT, false);
1262
leftColumn->Add(addrView_);
1263
LinearLayout *rightColumn = new LinearLayout(ORIENT_HORIZONTAL, new AnchorLayoutParams(0, 120, 10, NONE, NONE,10));
1264
rightColumn->Add(new Button("0"))->OnClick.Handle(this, &ProAdhocServerScreen::On0Click);
1265
rightColumn->Add(new Button("1"))->OnClick.Handle(this, &ProAdhocServerScreen::On1Click);
1266
rightColumn->Add(new Button("2"))->OnClick.Handle(this, &ProAdhocServerScreen::On2Click);
1267
rightColumn->Add(new Button("3"))->OnClick.Handle(this, &ProAdhocServerScreen::On3Click);
1268
rightColumn->Add(new Button("4"))->OnClick.Handle(this, &ProAdhocServerScreen::On4Click);
1269
rightColumn->Add(new Button("5"))->OnClick.Handle(this, &ProAdhocServerScreen::On5Click);
1270
rightColumn->Add(new Button("6"))->OnClick.Handle(this, &ProAdhocServerScreen::On6Click);
1271
rightColumn->Add(new Button("7"))->OnClick.Handle(this, &ProAdhocServerScreen::On7Click);
1272
rightColumn->Add(new Button("8"))->OnClick.Handle(this, &ProAdhocServerScreen::On8Click);
1273
rightColumn->Add(new Button("9"))->OnClick.Handle(this, &ProAdhocServerScreen::On9Click);
1274
rightColumn->Add(new Button("."))->OnClick.Handle(this, &ProAdhocServerScreen::OnPointClick);
1275
rightColumn->Add(new Button(di->T("Delete")))->OnClick.Handle(this, &ProAdhocServerScreen::OnDeleteClick);
1276
rightColumn->Add(new Button(di->T("Delete all")))->OnClick.Handle(this, &ProAdhocServerScreen::OnDeleteAllClick);
1277
rightColumn->Add(new Button(di->T("OK")))->OnClick.Handle(this, &ProAdhocServerScreen::OnOKClick);
1278
rightColumn->Add(new Button(di->T("Cancel")))->OnClick.Handle(this, &ProAdhocServerScreen::OnCancelClick);
1279
root_->Add(leftColumn);
1280
root_->Add(rightColumn);
1283
UI::EventReturn ProAdhocServerScreen::On0Click(UI::EventParams &e) {
1284
if (tempProAdhocServer.length() > 0)
1285
tempProAdhocServer.append("0");
1286
addrView_->SetText(tempProAdhocServer);
1287
return UI::EVENT_DONE;
1290
UI::EventReturn ProAdhocServerScreen::On1Click(UI::EventParams &e) {
1291
tempProAdhocServer.append("1");
1292
addrView_->SetText(tempProAdhocServer);
1293
return UI::EVENT_DONE;
1296
UI::EventReturn ProAdhocServerScreen::On2Click(UI::EventParams &e) {
1297
tempProAdhocServer.append("2");
1298
addrView_->SetText(tempProAdhocServer);
1299
return UI::EVENT_DONE;
1302
UI::EventReturn ProAdhocServerScreen::On3Click(UI::EventParams &e) {
1303
tempProAdhocServer.append("3");
1304
addrView_->SetText(tempProAdhocServer);
1305
return UI::EVENT_DONE;
1308
UI::EventReturn ProAdhocServerScreen::On4Click(UI::EventParams &e) {
1309
tempProAdhocServer.append("4");
1310
addrView_->SetText(tempProAdhocServer);
1311
return UI::EVENT_DONE;
1314
UI::EventReturn ProAdhocServerScreen::On5Click(UI::EventParams &e) {
1315
tempProAdhocServer.append("5");
1316
addrView_->SetText(tempProAdhocServer);
1317
return UI::EVENT_DONE;
1320
UI::EventReturn ProAdhocServerScreen::On6Click(UI::EventParams &e) {
1321
tempProAdhocServer.append("6");
1322
addrView_->SetText(tempProAdhocServer);
1323
return UI::EVENT_DONE;
1326
UI::EventReturn ProAdhocServerScreen::On7Click(UI::EventParams &e) {
1327
tempProAdhocServer.append("7");
1328
addrView_->SetText(tempProAdhocServer);
1329
return UI::EVENT_DONE;
1332
UI::EventReturn ProAdhocServerScreen::On8Click(UI::EventParams &e) {
1333
tempProAdhocServer.append("8");
1334
addrView_->SetText(tempProAdhocServer);
1335
return UI::EVENT_DONE;
1338
UI::EventReturn ProAdhocServerScreen::On9Click(UI::EventParams &e) {
1339
tempProAdhocServer.append("9");
1340
addrView_->SetText(tempProAdhocServer);
1341
return UI::EVENT_DONE;
1345
UI::EventReturn ProAdhocServerScreen::OnPointClick(UI::EventParams &e) {
1346
if (tempProAdhocServer.length() > 0 && tempProAdhocServer.at(tempProAdhocServer.length() - 1) != '.')
1347
tempProAdhocServer.append(".");
1348
addrView_->SetText(tempProAdhocServer);
1349
return UI::EVENT_DONE;
1352
UI::EventReturn ProAdhocServerScreen::OnDeleteClick(UI::EventParams &e) {
1353
if (tempProAdhocServer.length() > 0)
1354
tempProAdhocServer.erase(tempProAdhocServer.length() -1, 1);
1355
addrView_->SetText(tempProAdhocServer);
1356
return UI::EVENT_DONE;
1359
UI::EventReturn ProAdhocServerScreen::OnDeleteAllClick(UI::EventParams &e) {
1360
tempProAdhocServer = "";
1361
addrView_->SetText(tempProAdhocServer);
1362
return UI::EVENT_DONE;
1365
UI::EventReturn ProAdhocServerScreen::OnOKClick(UI::EventParams &e) {
1366
g_Config.proAdhocServer = tempProAdhocServer;
1367
UIScreen::OnBack(e);
1368
return UI::EVENT_DONE;
1371
UI::EventReturn ProAdhocServerScreen::OnCancelClick(UI::EventParams &e) {
1372
tempProAdhocServer = g_Config.proAdhocServer;
1373
UIScreen::OnBack(e);
1374
return UI::EVENT_DONE;
1377
void SettingInfoMessage::Show(const std::string &text, UI::View *refView) {
1379
Bounds b = refView->GetBounds();
1380
const UI::AnchorLayoutParams *lp = GetLayoutParams()->As<UI::AnchorLayoutParams>();
1381
if (b.y >= cutOffY_) {
1382
ReplaceLayoutParams(new UI::AnchorLayoutParams(lp->width, lp->height, lp->left, 80.0f, lp->right, lp->bottom, lp->center));
1384
ReplaceLayoutParams(new UI::AnchorLayoutParams(lp->width, lp->height, lp->left, dp_yres - 80.0f - 40.0f, lp->right, lp->bottom, lp->center));
1388
timeShown_ = time_now_d();
1391
void SettingInfoMessage::GetContentDimensionsBySpec(const UIContext &dc, UI::MeasureSpec horiz, UI::MeasureSpec vert, float &w, float &h) const {
1392
TextView::GetContentDimensionsBySpec(dc, horiz, vert, w, h);
1397
void SettingInfoMessage::Draw(UIContext &dc) {
1398
static const double FADE_TIME = 1.0;
1399
static const float MAX_ALPHA = 0.9f;
1401
// Let's show longer messages for more time (guesstimate at reading speed.)
1402
// Note: this will give multibyte characters more time, but they often have shorter words anyway.
1403
double timeToShow = std::max(1.5, GetText().size() * 0.05);
1405
double sinceShow = time_now_d() - timeShown_;
1406
float alpha = MAX_ALPHA;
1407
if (timeShown_ == 0.0 || sinceShow > timeToShow + FADE_TIME) {
1409
} else if (sinceShow > timeToShow) {
1410
alpha = MAX_ALPHA - MAX_ALPHA * (float)((sinceShow - timeToShow) / FADE_TIME);
1413
if (alpha >= 0.1f) {
1414
UI::Style style = dc.theme->popupTitle;
1415
style.background.color = colorAlpha(style.background.color, alpha - 0.1f);
1416
dc.FillRect(style.background, bounds_);
1419
SetTextColor(whiteAlpha(alpha));
1420
// Fake padding by adjusting bounds.
1421
SetBounds(bounds_.Expand(-10.0f));
1423
SetBounds(bounds_.Expand(10.0f));