Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/Qt/mainwindow.cpp
5654 views
1
// Qt Desktop UI: works on Linux, Windows and Mac OSX
2
#include "ppsspp_config.h"
3
4
#include <QApplication>
5
#include <QDesktopServices>
6
#include <QDesktopWidget>
7
#include <QFile>
8
#include <QFileDialog>
9
#include <QMessageBox>
10
11
#include "mainwindow.h"
12
13
#include "Common/System/Display.h"
14
#include "Common/System/NativeApp.h"
15
#include "Common/System/System.h"
16
#include "Common/File/Path.h"
17
#include "Core/MIPS/MIPSDebugInterface.h"
18
#include "Core/Debugger/SymbolMap.h"
19
#include "Core/HLE/sceUmd.h"
20
#include "Core/SaveState.h"
21
#include "Core/System.h"
22
#include "GPU/GPUCommon.h"
23
#include "UI/GamepadEmu.h"
24
25
MainWindow::MainWindow(QWidget *parent, bool fullscreen) :
26
QMainWindow(parent),
27
currentLanguage("en"),
28
nextState(CORE_POWERDOWN),
29
lastUIState(UISTATE_MENU)
30
{
31
#if defined(ASSETS_DIR)
32
if (QFile::exists(ASSETS_DIR "ui_images/icon.png"))
33
setWindowIcon(QIcon(ASSETS_DIR "ui_images/icon.png"));
34
else
35
setWindowIcon(QIcon(qApp->applicationDirPath() + "/assets/ui_images/icon.png"));
36
#else
37
setWindowIcon(QIcon(qApp->applicationDirPath() + "/assets/ui_images/icon.png"));
38
#endif
39
40
SetGameTitle("");
41
emugl = new MainUI(this);
42
43
setCentralWidget(emugl);
44
createMenus();
45
updateMenus();
46
47
SetFullScreen(fullscreen);
48
49
QObject::connect(emugl, SIGNAL(doubleClick()), this, SLOT(fullscrAct()));
50
QObject::connect(emugl, SIGNAL(newFrame()), this, SLOT(newFrame()));
51
}
52
53
inline float clamp1(float x) {
54
if (x > 1.0f) return 1.0f;
55
if (x < -1.0f) return -1.0f;
56
return x;
57
}
58
59
void MainWindow::newFrame()
60
{
61
if (lastUIState != GetUIState()) {
62
lastUIState = GetUIState();
63
if (lastUIState == UISTATE_INGAME && g_Config.bFullScreen && !QApplication::overrideCursor() && !g_Config.bShowTouchControls)
64
QApplication::setOverrideCursor(QCursor(Qt::BlankCursor));
65
if (lastUIState != UISTATE_INGAME && g_Config.bFullScreen && QApplication::overrideCursor())
66
QApplication::restoreOverrideCursor();
67
68
updateMenus();
69
}
70
71
if (g_Config.bFullScreen != isFullScreen())
72
SetFullScreen(g_Config.bFullScreen);
73
74
std::unique_lock<std::mutex> lock(msgMutex_);
75
while (!msgQueue_.empty()) {
76
MainWindowMsg msg = msgQueue_.front();
77
msgQueue_.pop();
78
switch (msg) {
79
case MainWindowMsg::BOOT_DONE:
80
bootDone();
81
break;
82
case MainWindowMsg::WINDOW_TITLE_CHANGED:
83
std::unique_lock<std::mutex> lock(titleMutex_);
84
setWindowTitle(QString::fromUtf8(newWindowTitle_.c_str()));
85
break;
86
}
87
}
88
}
89
90
void MainWindow::updateMenuGroupInt(QActionGroup *group, int value) {
91
foreach (QAction *action, group->actions()) {
92
action->setChecked(action->data().toInt() == value);
93
}
94
}
95
96
void MainWindow::updateMenus()
97
{
98
const DisplayLayoutConfig &config = g_Config.GetDisplayLayoutConfig(g_display.GetDeviceOrientation());
99
100
updateMenuGroupInt(saveStateGroup, g_Config.iCurrentStateSlot);
101
updateMenuGroupInt(displayRotationGroup, config.iInternalScreenRotation);
102
updateMenuGroupInt(renderingResolutionGroup, g_Config.iInternalResolution);
103
updateMenuGroupInt(frameSkippingGroup, g_Config.iFrameSkip);
104
updateMenuGroupInt(textureFilteringGroup, g_Config.iTexFiltering);
105
updateMenuGroupInt(screenScalingFilterGroup, config.iDisplayFilter);
106
updateMenuGroupInt(textureScalingLevelGroup, g_Config.iTexScalingLevel);
107
updateMenuGroupInt(textureScalingTypeGroup, g_Config.iTexScalingType);
108
109
bool internalPortrait = config.InternalRotationIsPortrait();
110
foreach(QAction * action, windowGroup->actions()) {
111
int width = (internalPortrait ? 272 : 480) * action->data().toInt();
112
int height = (internalPortrait ? 480 : 272) * action->data().toInt();
113
if (g_Config.iWindowWidth == width && g_Config.iWindowHeight == height) {
114
action->setChecked(true);
115
break;
116
}
117
}
118
emit updateMenu();
119
}
120
121
void MainWindow::bootDone()
122
{
123
if (nextState == CORE_RUNNING_CPU)
124
runAct();
125
updateMenus();
126
}
127
128
/* SIGNALS */
129
void MainWindow::loadAct()
130
{
131
QString filename = QFileDialog::getOpenFileName(NULL, "Load File", g_Config.currentDirectory.c_str(), "PSP ROMs (*.pbp *.elf *.iso *.cso *.chd *.prx)");
132
if (QFile::exists(filename))
133
{
134
QFileInfo info(filename);
135
g_Config.currentDirectory = Path(info.absolutePath().toStdString());
136
System_PostUIMessage(UIMessage::REQUEST_GAME_BOOT, filename.toStdString());
137
}
138
}
139
140
void MainWindow::closeAct()
141
{
142
updateMenus();
143
144
System_PostUIMessage(UIMessage::REQUEST_GAME_STOP);
145
SetGameTitle("");
146
}
147
148
void MainWindow::openmsAct()
149
{
150
QString confighome = getenv("XDG_CONFIG_HOME");
151
QString memorystick = confighome + "/ppsspp";
152
QDesktopServices::openUrl(QUrl(memorystick));
153
}
154
155
static void SaveStateActionFinished(SaveState::Status status, std::string_view message)
156
{
157
// TODO: Improve messaging?
158
if (status == SaveState::Status::FAILURE)
159
{
160
QMessageBox msgBox;
161
msgBox.setWindowTitle("Load Save State");
162
msgBox.setText("Savestate failure. Please try again later");
163
msgBox.exec();
164
return;
165
}
166
}
167
168
void MainWindow::qlstateAct()
169
{
170
Path gamePath = PSP_CoreParameter().fileToStart;
171
SaveState::LoadSlot(SaveState::GetGamePrefix(g_paramSFO), 0, SaveStateActionFinished);
172
}
173
174
void MainWindow::qsstateAct()
175
{
176
Path gamePath = PSP_CoreParameter().fileToStart;
177
SaveState::SaveSlot(SaveState::GetGamePrefix(g_paramSFO), 0, SaveStateActionFinished);
178
}
179
180
void MainWindow::lstateAct()
181
{
182
QFileDialog dialog(0,"Load state");
183
dialog.setFileMode(QFileDialog::ExistingFile);
184
QStringList filters;
185
filters << "Save States (*.ppst)" << "|All files (*.*)";
186
dialog.setNameFilters(filters);
187
dialog.setAcceptMode(QFileDialog::AcceptOpen);
188
if (dialog.exec())
189
{
190
QStringList fileNames = dialog.selectedFiles();
191
SaveState::Load(Path(fileNames[0].toStdString()), -1, SaveStateActionFinished);
192
}
193
}
194
195
void MainWindow::sstateAct()
196
{
197
QFileDialog dialog(0,"Save state");
198
dialog.setFileMode(QFileDialog::AnyFile);
199
dialog.setAcceptMode(QFileDialog::AcceptSave);
200
QStringList filters;
201
filters << "Save States (*.ppst)" << "|All files (*.*)";
202
dialog.setNameFilters(filters);
203
if (dialog.exec())
204
{
205
QStringList fileNames = dialog.selectedFiles();
206
SaveState::Save(Path(fileNames[0].toStdString()), -1, SaveStateActionFinished);
207
}
208
}
209
210
void MainWindow::recordDisplayAct()
211
{
212
g_Config.bDumpFrames = !g_Config.bDumpFrames;
213
}
214
215
void MainWindow::useLosslessVideoCodecAct()
216
{
217
g_Config.bUseFFV1 = !g_Config.bUseFFV1;
218
}
219
220
void MainWindow::useOutputBufferAct()
221
{
222
g_Config.bDumpVideoOutput = !g_Config.bDumpVideoOutput;
223
}
224
225
void MainWindow::recordAudioAct()
226
{
227
g_Config.bDumpAudio = !g_Config.bDumpAudio;
228
}
229
230
void MainWindow::exitAct()
231
{
232
closeAct();
233
QApplication::exit(0);
234
}
235
236
void MainWindow::runAct()
237
{
238
System_PostUIMessage(UIMessage::REQUEST_GAME_RUN);
239
}
240
241
void MainWindow::pauseAct()
242
{
243
System_PostUIMessage(UIMessage::REQUEST_GAME_PAUSE);
244
}
245
246
void MainWindow::stopAct()
247
{
248
Core_Stop();
249
System_PostUIMessage(UIMessage::REQUEST_GAME_STOP);
250
}
251
252
void MainWindow::resetAct()
253
{
254
updateMenus();
255
System_PostUIMessage(UIMessage::REQUEST_GAME_RESET);
256
}
257
258
void MainWindow::switchUMDAct()
259
{
260
QString filename = QFileDialog::getOpenFileName(NULL, "Switch UMD", g_Config.currentDirectory.c_str(), "PSP ROMs (*.pbp *.elf *.iso *.cso *.chd *.prx)");
261
if (QFile::exists(filename))
262
{
263
QFileInfo info(filename);
264
g_Config.currentDirectory = Path(info.absolutePath().toStdString());
265
__UmdReplace(Path(filename.toStdString()));
266
}
267
}
268
269
void MainWindow::breakonloadAct()
270
{
271
g_Config.bAutoRun = !g_Config.bAutoRun;
272
}
273
274
void MainWindow::lmapAct()
275
{
276
QFileDialog dialog(0,"Load .MAP");
277
dialog.setFileMode(QFileDialog::ExistingFile);
278
QStringList filters;
279
filters << "Maps (*.map)" << "|All files (*.*)";
280
dialog.setNameFilters(filters);
281
dialog.setAcceptMode(QFileDialog::AcceptOpen);
282
QStringList fileNames;
283
if (dialog.exec())
284
fileNames = dialog.selectedFiles();
285
286
if (fileNames.count() > 0)
287
{
288
QString fileName = QFileInfo(fileNames[0]).absoluteFilePath();
289
g_symbolMap->LoadSymbolMap(Path(fileName.toStdString()));
290
}
291
}
292
293
void MainWindow::smapAct()
294
{
295
QFileDialog dialog(0,"Save .MAP");
296
dialog.setFileMode(QFileDialog::AnyFile);
297
dialog.setAcceptMode(QFileDialog::AcceptSave);
298
QStringList filters;
299
filters << "Save .MAP (*.map)" << "|All files (*.*)";
300
dialog.setNameFilters(filters);
301
QStringList fileNames;
302
if (dialog.exec())
303
{
304
fileNames = dialog.selectedFiles();
305
g_symbolMap->SaveSymbolMap(Path(fileNames[0].toStdString()));
306
}
307
}
308
309
void MainWindow::lsymAct()
310
{
311
QFileDialog dialog(0,"Load .SYM");
312
dialog.setFileMode(QFileDialog::ExistingFile);
313
QStringList filters;
314
filters << "Symbols (*.sym)" << "|All files (*.*)";
315
dialog.setNameFilters(filters);
316
dialog.setAcceptMode(QFileDialog::AcceptOpen);
317
QStringList fileNames;
318
if (dialog.exec())
319
fileNames = dialog.selectedFiles();
320
321
if (fileNames.count() > 0)
322
{
323
QString fileName = QFileInfo(fileNames[0]).absoluteFilePath();
324
g_symbolMap->LoadNocashSym(Path(fileName.toStdString()));
325
}
326
}
327
328
void MainWindow::ssymAct()
329
{
330
QFileDialog dialog(0,"Save .SYM");
331
dialog.setFileMode(QFileDialog::AnyFile);
332
dialog.setAcceptMode(QFileDialog::AcceptSave);
333
QStringList filters;
334
filters << "Save .SYM (*.sym)" << "|All files (*.*)";
335
dialog.setNameFilters(filters);
336
QStringList fileNames;
337
if (dialog.exec())
338
{
339
fileNames = dialog.selectedFiles();
340
g_symbolMap->SaveNocashSym(Path(fileNames[0].toStdString()));
341
}
342
}
343
344
void MainWindow::resetTableAct()
345
{
346
g_symbolMap->Clear();
347
}
348
349
void MainWindow::dumpNextAct()
350
{
351
gpu->DumpNextFrame();
352
}
353
354
void MainWindow::consoleAct()
355
{
356
#if PPSSPP_PLATFORM(WINDOWS)
357
LogManager::GetInstance()->GetConsoleListener()->Show(LogManager::GetInstance()->GetConsoleListener()->Hidden());
358
#endif
359
}
360
361
void MainWindow::raiseTopMost()
362
{
363
setWindowState( (windowState() & ~Qt::WindowMinimized) | Qt::WindowActive);
364
raise();
365
activateWindow();
366
}
367
368
void MainWindow::SetFullScreen(bool fullscreen) {
369
if (fullscreen) {
370
#if !PPSSPP_PLATFORM(MAC)
371
menuBar()->hide();
372
373
emugl->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
374
// TODO: Shouldn't this be physicalSize()?
375
emugl->resizeGL(emugl->size().width(), emugl->size().height());
376
// TODO: Won't showFullScreen do this for us?
377
setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
378
setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
379
#endif
380
381
showFullScreen();
382
383
if (GetUIState() == UISTATE_INGAME && !g_Config.bShowTouchControls)
384
QApplication::setOverrideCursor(QCursor(Qt::BlankCursor));
385
} else {
386
#if !PPSSPP_PLATFORM(MAC)
387
menuBar()->show();
388
updateMenus();
389
#endif
390
391
showNormal();
392
SetWindowScale(-1);
393
394
if (GetUIState() == UISTATE_INGAME && QApplication::overrideCursor())
395
QApplication::restoreOverrideCursor();
396
397
QDesktopWidget *desktop = QApplication::desktop();
398
int screenNum = QProcessEnvironment::systemEnvironment().value("SDL_VIDEO_FULLSCREEN_HEAD", "0").toInt();
399
400
// Move window to the center of selected screen
401
QRect rect = desktop->screenGeometry(screenNum);
402
move((rect.width() - frameGeometry().width()) / 4, (rect.height() - frameGeometry().height()) / 4);
403
}
404
}
405
406
void MainWindow::fullscrAct()
407
{
408
// Toggle the current state.
409
g_Config.bFullScreen = !isFullScreen();
410
SetFullScreen(g_Config.bFullScreen);
411
412
QTimer::singleShot(1000, this, SLOT(raiseTopMost()));
413
}
414
415
void MainWindow::websiteAct()
416
{
417
QDesktopServices::openUrl(QUrl("https://www.ppsspp.org/"));
418
}
419
420
void MainWindow::forumAct()
421
{
422
QDesktopServices::openUrl(QUrl("https://forums.ppsspp.org/"));
423
}
424
425
void MainWindow::goldAct()
426
{
427
QDesktopServices::openUrl(QUrl("https://www.ppsspp.org/buygold"));
428
}
429
430
void MainWindow::gitAct()
431
{
432
QDesktopServices::openUrl(QUrl("https://github.com/hrydgard/ppsspp/"));
433
}
434
435
void MainWindow::discordAct()
436
{
437
QDesktopServices::openUrl(QUrl("https://discord.gg/5NJB6dD"));
438
}
439
440
void MainWindow::aboutAct()
441
{
442
QMessageBox::about(this, "About", QString("PPSSPP Qt %1\n\n"
443
"PSP emulator and debugger\n\n"
444
"Copyright (c) by Henrik Rydg\xc3\xa5rd and the PPSSPP Project 2012-\n"
445
"Qt port maintained by xSacha\n\n"
446
"Additional credits:\n"
447
" PSPSDK by #pspdev (freenode)\n"
448
" CISO decompression code by BOOSTER\n"
449
" zlib by Jean-loup Gailly (compression) and Mark Adler (decompression)\n"
450
" Qt project by Digia\n\n"
451
"All trademarks are property of their respective owners.\n"
452
"The emulator is for educational and development purposes only and it may not be used to play games you do not legally own.").arg(PPSSPP_GIT_VERSION));
453
}
454
455
/* Private functions */
456
void MainWindow::SetWindowScale(int zoom) {
457
if (isFullScreen())
458
fullscrAct();
459
460
const DisplayLayoutConfig &config = g_Config.GetDisplayLayoutConfig(g_display.GetDeviceOrientation());
461
const bool internalPortrait = config.InternalRotationIsPortrait();
462
463
int width, height;
464
if (zoom == -1 && (g_Config.iWindowWidth <= 0 || g_Config.iWindowHeight <= 0)) {
465
// Default to zoom level 2.
466
zoom = 2;
467
}
468
if (zoom == -1) {
469
// Take the last setting.
470
width = g_Config.iWindowWidth;
471
height = g_Config.iWindowHeight;
472
} else {
473
// Update to the specified factor. Let's clamp first.
474
if (zoom < 1)
475
zoom = 1;
476
if (zoom > 10)
477
zoom = 10;
478
479
width = (internalPortrait ? 272 : 480) * zoom;
480
height = (internalPortrait ? 480 : 272) * zoom;
481
}
482
483
g_Config.iWindowWidth = width;
484
g_Config.iWindowHeight = height;
485
486
#if !PPSSPP_PLATFORM(MAC)
487
emugl->setFixedSize(g_Config.iWindowWidth, g_Config.iWindowHeight);
488
// TODO: Shouldn't this be scaled size?
489
emugl->resizeGL(g_Config.iWindowWidth, g_Config.iWindowHeight);
490
setFixedSize(sizeHint());
491
#else
492
resize(g_Config.iWindowWidth, g_Config.iWindowHeight);
493
#endif
494
updateMenus();
495
}
496
497
void MainWindow::SetGameTitle(QString text)
498
{
499
QString title = QString("PPSSPP %1").arg(PPSSPP_GIT_VERSION);
500
if (text != "")
501
title += QString(" - %1").arg(text);
502
503
setWindowTitle(title);
504
}
505
506
void MainWindow::loadLanguage(const QString& language, bool translate)
507
{
508
if (currentLanguage != language)
509
{
510
QLocale::setDefault(QLocale(language));
511
QApplication::removeTranslator(&translator);
512
513
currentLanguage = language;
514
if (translator.load(QString(":/languages/ppsspp_%1.qm").arg(language))) {
515
QApplication::installTranslator(&translator);
516
}
517
if (translate)
518
emit retranslate();
519
}
520
}
521
522
void MainWindow::createMenus()
523
{
524
// File
525
MenuTree* fileMenu = new MenuTree(this, menuBar(), QT_TR_NOOP("&File"));
526
fileMenu->add(new MenuAction(this, SLOT(loadAct()), QT_TR_NOOP("&Load..."), QKeySequence::Open))
527
->addEnableState(UISTATE_MENU);
528
fileMenu->addSeparator();
529
fileMenu->add(new MenuAction(this, SLOT(openmsAct()), QT_TR_NOOP("Open &Memory Stick")))
530
->addEnableState(UISTATE_MENU);
531
fileMenu->addSeparator();
532
MenuTree* savestateMenu = new MenuTree(this, fileMenu, QT_TR_NOOP("Saves&tate slot"));
533
534
QStringList slotNames;
535
QList<int> slotIndices;
536
for (int i = 0; i < g_Config.iSaveStateSlotCount; ++i) {
537
slotNames << QString::number(i + 1);
538
slotIndices << i;
539
}
540
saveStateGroup = new MenuActionGroup(this, savestateMenu, SLOT(saveStateGroup_triggered(QAction *)),
541
slotNames,
542
slotIndices);
543
544
fileMenu->add(new MenuAction(this, SLOT(qlstateAct()), QT_TR_NOOP("L&oad state"), Qt::Key_F4))
545
->addDisableState(UISTATE_MENU);
546
fileMenu->add(new MenuAction(this, SLOT(qsstateAct()), QT_TR_NOOP("S&ave state"), Qt::Key_F2))
547
->addDisableState(UISTATE_MENU);
548
fileMenu->add(new MenuAction(this, SLOT(lstateAct()), QT_TR_NOOP("&Load state file...")))
549
->addDisableState(UISTATE_MENU);
550
fileMenu->add(new MenuAction(this, SLOT(sstateAct()), QT_TR_NOOP("&Save state file...")))
551
->addDisableState(UISTATE_MENU);
552
MenuTree* recordMenu = new MenuTree(this, fileMenu, QT_TR_NOOP("&Record"));
553
recordMenu->add(new MenuAction(this, SLOT(recordDisplayAct()), QT_TR_NOOP("Record &display")))
554
->addEventChecked(&g_Config.bDumpFrames);
555
recordMenu->add(new MenuAction(this, SLOT(useLosslessVideoCodecAct()), QT_TR_NOOP("&Use lossless video codec (FFV1)")))
556
->addEventChecked(&g_Config.bUseFFV1);
557
recordMenu->add(new MenuAction(this, SLOT(useOutputBufferAct()), QT_TR_NOOP("Use output buffer for video")))
558
->addEventChecked(&g_Config.bDumpVideoOutput);
559
recordMenu->addSeparator();
560
recordMenu->add(new MenuAction(this, SLOT(recordAudioAct()), QT_TR_NOOP("Record &audio")))
561
->addEventChecked(&g_Config.bDumpAudio);
562
fileMenu->addSeparator();
563
fileMenu->add(new MenuAction(this, SLOT(exitAct()), QT_TR_NOOP("E&xit"), QKeySequence::Quit));
564
565
// Emulation
566
MenuTree* emuMenu = new MenuTree(this, menuBar(), QT_TR_NOOP("&Emulation"));
567
emuMenu->add(new MenuAction(this, SLOT(pauseAct()), QT_TR_NOOP("&Pause")))
568
->addEnableState(UISTATE_INGAME);
569
emuMenu->add(new MenuAction(this, SLOT(stopAct()), QT_TR_NOOP("&Stop"), Qt::CTRL + Qt::Key_W))
570
->addEnableState(UISTATE_INGAME);
571
emuMenu->add(new MenuAction(this, SLOT(resetAct()), QT_TR_NOOP("R&eset"), Qt::CTRL + Qt::Key_B))
572
->addEnableState(UISTATE_INGAME);
573
emuMenu->add(new MenuAction(this, SLOT(switchUMDAct()), QT_TR_NOOP("Switch UMD"), Qt::CTRL + Qt::Key_U))
574
->addEnableState(UISTATE_INGAME);
575
MenuTree* displayRotationMenu = new MenuTree(this, emuMenu, QT_TR_NOOP("Display rotation"));
576
displayRotationGroup = new MenuActionGroup(this, displayRotationMenu, SLOT(displayRotationGroup_triggered(QAction *)),
577
QStringList() << "Landscape" << "Portrait" << "Landscape reversed" << "Portrait reversed",
578
QList<int>() << 1 << 2 << 3 << 4);
579
580
// Debug
581
MenuTree* debugMenu = new MenuTree(this, menuBar(), QT_TR_NOOP("&Debug"));
582
debugMenu->add(new MenuAction(this, SLOT(breakonloadAct()), QT_TR_NOOP("Break on load")))
583
->addEventUnchecked(&g_Config.bAutoRun);
584
debugMenu->add(new MenuAction(this, SLOT(ignoreIllegalAct()), QT_TR_NOOP("&Ignore illegal reads/writes")))
585
->addEventChecked(&g_Config.bIgnoreBadMemAccess);
586
debugMenu->addSeparator();
587
debugMenu->add(new MenuAction(this, SLOT(lmapAct()), QT_TR_NOOP("&Load MAP file...")))
588
->addDisableState(UISTATE_MENU);
589
debugMenu->add(new MenuAction(this, SLOT(smapAct()), QT_TR_NOOP("&Save MAP file...")))
590
->addDisableState(UISTATE_MENU);
591
debugMenu->add(new MenuAction(this, SLOT(lsymAct()), QT_TR_NOOP("Lo&ad SYM file...")))
592
->addDisableState(UISTATE_MENU);
593
debugMenu->add(new MenuAction(this, SLOT(ssymAct()), QT_TR_NOOP("Sav&e SYM file...")))
594
->addDisableState(UISTATE_MENU);
595
debugMenu->add(new MenuAction(this, SLOT(resetTableAct()),QT_TR_NOOP("Reset s&ymbol table")))
596
->addDisableState(UISTATE_MENU);
597
debugMenu->addSeparator();
598
debugMenu->add(new MenuAction(this, SLOT(takeScreen()), QT_TR_NOOP("&Take screenshot"), Qt::Key_F12))
599
->addDisableState(UISTATE_MENU);
600
debugMenu->add(new MenuAction(this, SLOT(dumpNextAct()), QT_TR_NOOP("D&ump next frame to log")))
601
->addDisableState(UISTATE_MENU);
602
debugMenu->addSeparator();
603
debugMenu->add(new MenuAction(this, SLOT(consoleAct()), QT_TR_NOOP("&Log console"), Qt::CTRL + Qt::Key_L))
604
->addDisableState(UISTATE_MENU);
605
606
// Game settings
607
MenuTree* gameSettingsMenu = new MenuTree(this, menuBar(), QT_TR_NOOP("&Game settings"));
608
gameSettingsMenu->add(new MenuAction(this, SLOT(languageAct()), QT_TR_NOOP("La&nguage...")));
609
gameSettingsMenu->add(new MenuAction(this, SLOT(controlMappingAct()), QT_TR_NOOP("C&ontrol mapping...")));
610
gameSettingsMenu->add(new MenuAction(this, SLOT(displayLayoutEditorAct()), QT_TR_NOOP("Display layout & effects...")));
611
gameSettingsMenu->add(new MenuAction(this, SLOT(moreSettingsAct()), QT_TR_NOOP("&More settings...")));
612
gameSettingsMenu->addSeparator();
613
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
614
gameSettingsMenu->add(new MenuAction(this, SLOT(fullscrAct()), QT_TR_NOOP("&Fullscreen"), Qt::Key_F11))
615
#else
616
gameSettingsMenu->add(new MenuAction(this, SLOT(fullscrAct()), QT_TR_NOOP("Fu&llscreen"), QKeySequence::FullScreen))
617
#endif
618
->addEventChecked(&g_Config.bFullScreen);
619
gameSettingsMenu->add(new MenuAction(this, SLOT(bufferRenderAct()), QT_TR_NOOP("&Skip buffer effects")))
620
->addEventChecked(&g_Config.bSkipBufferEffects);
621
622
MenuTree* renderingResolutionMenu = new MenuTree(this, gameSettingsMenu, QT_TR_NOOP("&Rendering resolution"));
623
renderingResolutionGroup = new MenuActionGroup(this, renderingResolutionMenu, SLOT(renderingResolutionGroup_triggered(QAction *)),
624
QStringList() << "&Auto" << "&1x" << "&2x" << "&3x" << "&4x" << "&5x" << "&6x" << "&7x" << "&8x" << "&9x" << "1&0x",
625
QList<int>() << 0 << 1 << 2 << 3 << 4 << 5 << 6 << 7 << 8 << 9 << 10);
626
// - Window Size
627
MenuTree* windowMenu = new MenuTree(this, gameSettingsMenu, QT_TR_NOOP("&Window size"));
628
windowGroup = new MenuActionGroup(this, windowMenu, SLOT(windowGroup_triggered(QAction *)),
629
QStringList() << "&1x" << "&2x" << "&3x" << "&4x" << "&5x" << "&6x" << "&7x" << "&8x" << "&9x" << "1&0x",
630
QList<int>() << 1 << 2 << 3 << 4 << 5 << 6 << 7 << 8 << 9 << 10);
631
632
MenuTree* frameSkippingMenu = new MenuTree(this, gameSettingsMenu, QT_TR_NOOP("&Frame skipping"));
633
frameSkippingMenu->add(new MenuAction(this, SLOT(autoframeskipAct()), QT_TR_NOOP("&Auto")))
634
->addEventChecked(&g_Config.bAutoFrameSkip);
635
frameSkippingMenu->addSeparator();
636
frameSkippingGroup = new MenuActionGroup(this, frameSkippingMenu, SLOT(frameSkippinGroup_triggered(QAction *)),
637
QStringList() << "&Off" << "&1" << "&2" << "&3" << "&4" << "&5" << "&6" << "&7" << "&8",
638
QList<int>() << 0 << 1 << 2 << 3 << 4 << 5 << 6 << 7 << 8);
639
MenuTree* textureFilteringMenu = new MenuTree(this, gameSettingsMenu, QT_TR_NOOP("Te&xture filtering"));
640
textureFilteringGroup = new MenuActionGroup(this, textureFilteringMenu, SLOT(textureFilteringGroup_triggered(QAction *)),
641
QStringList() << "&Auto" << "&Nearest" << "&Linear" << "Auto Max &Quality",
642
QList<int>() << 1 << 2 << 3 << 4);
643
MenuTree* screenScalingFilterMenu = new MenuTree(this, gameSettingsMenu, QT_TR_NOOP("Scr&een scaling filter"));
644
screenScalingFilterGroup = new MenuActionGroup(this, screenScalingFilterMenu, SLOT(screenScalingFilterGroup_triggered(QAction *)),
645
QStringList() << "&Linear" << "&Nearest",
646
QList<int>() << 0 << 1);
647
648
MenuTree* textureScalingMenu = new MenuTree(this, gameSettingsMenu, QT_TR_NOOP("&Texture scaling"));
649
textureScalingLevelGroup = new MenuActionGroup(this, textureScalingMenu, SLOT(textureScalingLevelGroup_triggered(QAction *)),
650
QStringList() << "&Off" << "&2x" << "&3x" << "&4x" << "&5x",
651
QList<int>() << 1 << 2 << 3 << 4 << 5);
652
textureScalingMenu->addSeparator();
653
textureScalingTypeGroup = new MenuActionGroup(this, textureScalingMenu, SLOT(textureScalingTypeGroup_triggered(QAction *)),
654
QStringList() << "&xBRZ" << "&Hybrid" << "&Bicubic" << "H&ybrid + bicubic",
655
QList<int>() << 0 << 1 << 2 << 3);
656
textureScalingMenu->addSeparator();
657
textureScalingMenu->add(new MenuAction(this, SLOT(deposterizeAct()), QT_TR_NOOP("&Deposterize")))
658
->addEventChecked(&g_Config.bTexDeposterize);
659
660
gameSettingsMenu->add(new MenuAction(this, SLOT(transformAct()), QT_TR_NOOP("&Hardware transform")))
661
->addEventChecked(&g_Config.bHardwareTransform);
662
gameSettingsMenu->addSeparator();
663
gameSettingsMenu->add(new MenuAction(this, SLOT(audioAct()), QT_TR_NOOP("Enable s&ound")))
664
->addEventChecked(&g_Config.bEnableSound);
665
gameSettingsMenu->addSeparator();
666
gameSettingsMenu->add(new MenuAction(this, SLOT(cheatsAct()), QT_TR_NOOP("Enable &cheats"), Qt::CTRL + Qt::Key_T))
667
->addEventChecked(&g_Config.bEnableCheats);
668
gameSettingsMenu->addSeparator();
669
gameSettingsMenu->add(new MenuAction(this, SLOT(chatAct()), QT_TR_NOOP("Open chat"), Qt::CTRL + Qt::Key_C))
670
->SetEnabledFunc([=]() {
671
return g_Config.bEnableNetworkChat && GetUIState() == UISTATE_INGAME;
672
});
673
674
// Help
675
MenuTree* helpMenu = new MenuTree(this, menuBar(), QT_TR_NOOP("&Help"));
676
helpMenu->add(new MenuAction(this, SLOT(websiteAct()), QT_TR_NOOP("Visit www.&ppsspp.org")));
677
helpMenu->add(new MenuAction(this, SLOT(forumAct()), QT_TR_NOOP("PPSSPP &forums")));
678
helpMenu->add(new MenuAction(this, SLOT(goldAct()), QT_TR_NOOP("Buy &Gold")));
679
helpMenu->add(new MenuAction(this, SLOT(gitAct()), QT_TR_NOOP("Git&Hub")));
680
helpMenu->add(new MenuAction(this, SLOT(discordAct()), QT_TR_NOOP("Discord")));
681
helpMenu->addSeparator();
682
helpMenu->add(new MenuAction(this, SLOT(aboutAct()), QT_TR_NOOP("&About PPSSPP...")));
683
684
retranslate();
685
}
686
687