summaryrefslogtreecommitdiff
path: root/src/citra_qt/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/citra_qt/main.cpp')
-rw-r--r--src/citra_qt/main.cpp184
1 files changed, 69 insertions, 115 deletions
diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp
index ca0ae6f7b..a85c94a4b 100644
--- a/src/citra_qt/main.cpp
+++ b/src/citra_qt/main.cpp
@@ -6,6 +6,9 @@
6#include <memory> 6#include <memory>
7#include <thread> 7#include <thread>
8 8
9#include <glad/glad.h>
10
11#define QT_NO_OPENGL
9#include <QDesktopWidget> 12#include <QDesktopWidget>
10#include <QtGui> 13#include <QtGui>
11#include <QFileDialog> 14#include <QFileDialog>
@@ -14,9 +17,11 @@
14 17
15#include "citra_qt/bootmanager.h" 18#include "citra_qt/bootmanager.h"
16#include "citra_qt/config.h" 19#include "citra_qt/config.h"
20#include "citra_qt/configure_dialog.h"
17#include "citra_qt/game_list.h" 21#include "citra_qt/game_list.h"
18#include "citra_qt/hotkeys.h" 22#include "citra_qt/hotkeys.h"
19#include "citra_qt/main.h" 23#include "citra_qt/main.h"
24#include "citra_qt/ui_settings.h"
20 25
21// Debugger 26// Debugger
22#include "citra_qt/debugger/callstack.h" 27#include "citra_qt/debugger/callstack.h"
@@ -50,12 +55,10 @@
50 55
51#include "video_core/video_core.h" 56#include "video_core/video_core.h"
52 57
53GMainWindow::GMainWindow() : emu_thread(nullptr) 58GMainWindow::GMainWindow() : config(new Config()), emu_thread(nullptr)
54{ 59{
55 Pica::g_debug_context = Pica::DebugContext::Construct(); 60 Pica::g_debug_context = Pica::DebugContext::Construct();
56 61
57 Config config;
58
59 ui.setupUi(this); 62 ui.setupUi(this);
60 statusBar()->hide(); 63 statusBar()->hide();
61 64
@@ -69,8 +72,10 @@ GMainWindow::GMainWindow() : emu_thread(nullptr)
69 addDockWidget(Qt::BottomDockWidgetArea, profilerWidget); 72 addDockWidget(Qt::BottomDockWidgetArea, profilerWidget);
70 profilerWidget->hide(); 73 profilerWidget->hide();
71 74
75#if MICROPROFILE_ENABLED
72 microProfileDialog = new MicroProfileDialog(this); 76 microProfileDialog = new MicroProfileDialog(this);
73 microProfileDialog->hide(); 77 microProfileDialog->hide();
78#endif
74 79
75 disasmWidget = new DisassemblerWidget(this, emu_thread.get()); 80 disasmWidget = new DisassemblerWidget(this, emu_thread.get());
76 addDockWidget(Qt::BottomDockWidgetArea, disasmWidget); 81 addDockWidget(Qt::BottomDockWidgetArea, disasmWidget);
@@ -110,7 +115,9 @@ GMainWindow::GMainWindow() : emu_thread(nullptr)
110 115
111 QMenu* debug_menu = ui.menu_View->addMenu(tr("Debugging")); 116 QMenu* debug_menu = ui.menu_View->addMenu(tr("Debugging"));
112 debug_menu->addAction(profilerWidget->toggleViewAction()); 117 debug_menu->addAction(profilerWidget->toggleViewAction());
118#if MICROPROFILE_ENABLED
113 debug_menu->addAction(microProfileDialog->toggleViewAction()); 119 debug_menu->addAction(microProfileDialog->toggleViewAction());
120#endif
114 debug_menu->addAction(disasmWidget->toggleViewAction()); 121 debug_menu->addAction(disasmWidget->toggleViewAction());
115 debug_menu->addAction(registersWidget->toggleViewAction()); 122 debug_menu->addAction(registersWidget->toggleViewAction());
116 debug_menu->addAction(callstackWidget->toggleViewAction()); 123 debug_menu->addAction(callstackWidget->toggleViewAction());
@@ -133,33 +140,20 @@ GMainWindow::GMainWindow() : emu_thread(nullptr)
133 setGeometry(x, y, w, h); 140 setGeometry(x, y, w, h);
134 141
135 // Restore UI state 142 // Restore UI state
136 QSettings settings; 143 restoreGeometry(UISettings::values.geometry);
137 144 restoreState(UISettings::values.state);
138 settings.beginGroup("UILayout"); 145 render_window->restoreGeometry(UISettings::values.renderwindow_geometry);
139 restoreGeometry(settings.value("geometry").toByteArray()); 146#if MICROPROFILE_ENABLED
140 restoreState(settings.value("state").toByteArray()); 147 microProfileDialog->restoreGeometry(UISettings::values.microprofile_geometry);
141 render_window->restoreGeometry(settings.value("geometryRenderWindow").toByteArray()); 148 microProfileDialog->setVisible(UISettings::values.microprofile_visible);
142 microProfileDialog->restoreGeometry(settings.value("microProfileDialogGeometry").toByteArray()); 149#endif
143 microProfileDialog->setVisible(settings.value("microProfileDialogVisible").toBool());
144 settings.endGroup();
145
146 game_list->LoadInterfaceLayout(settings);
147
148 ui.action_Use_Gdbstub->setChecked(Settings::values.use_gdbstub);
149 SetGdbstubEnabled(ui.action_Use_Gdbstub->isChecked());
150
151 GDBStub::SetServerPort(static_cast<u32>(Settings::values.gdbstub_port));
152
153 ui.action_Use_Hardware_Renderer->setChecked(Settings::values.use_hw_renderer);
154 SetHardwareRendererEnabled(ui.action_Use_Hardware_Renderer->isChecked());
155 150
156 ui.action_Use_Shader_JIT->setChecked(Settings::values.use_shader_jit); 151 game_list->LoadInterfaceLayout();
157 SetShaderJITEnabled(ui.action_Use_Shader_JIT->isChecked());
158 152
159 ui.action_Single_Window_Mode->setChecked(settings.value("singleWindowMode", true).toBool()); 153 ui.action_Single_Window_Mode->setChecked(UISettings::values.single_window_mode);
160 ToggleWindowMode(); 154 ToggleWindowMode();
161 155
162 ui.actionDisplay_widget_title_bars->setChecked(settings.value("displayTitleBars", true).toBool()); 156 ui.actionDisplay_widget_title_bars->setChecked(UISettings::values.display_titlebar);
163 OnDisplayTitleBars(ui.actionDisplay_widget_title_bars->isChecked()); 157 OnDisplayTitleBars(ui.actionDisplay_widget_title_bars->isChecked());
164 158
165 // Prepare actions for recent files 159 // Prepare actions for recent files
@@ -172,21 +166,16 @@ GMainWindow::GMainWindow() : emu_thread(nullptr)
172 } 166 }
173 UpdateRecentFiles(); 167 UpdateRecentFiles();
174 168
175 confirm_before_closing = settings.value("confirmClose", true).toBool();
176
177 // Setup connections 169 // Setup connections
178 connect(game_list, SIGNAL(GameChosen(QString)), this, SLOT(OnGameListLoadFile(QString))); 170 connect(game_list, SIGNAL(GameChosen(QString)), this, SLOT(OnGameListLoadFile(QString)), Qt::DirectConnection);
179 connect(ui.action_Load_File, SIGNAL(triggered()), this, SLOT(OnMenuLoadFile())); 171 connect(ui.action_Configure, SIGNAL(triggered()), this, SLOT(OnConfigure()));
172 connect(ui.action_Load_File, SIGNAL(triggered()), this, SLOT(OnMenuLoadFile()),Qt::DirectConnection);
180 connect(ui.action_Load_Symbol_Map, SIGNAL(triggered()), this, SLOT(OnMenuLoadSymbolMap())); 173 connect(ui.action_Load_Symbol_Map, SIGNAL(triggered()), this, SLOT(OnMenuLoadSymbolMap()));
181 connect(ui.action_Select_Game_List_Root, SIGNAL(triggered()), this, SLOT(OnMenuSelectGameListRoot())); 174 connect(ui.action_Select_Game_List_Root, SIGNAL(triggered()), this, SLOT(OnMenuSelectGameListRoot()));
182 connect(ui.action_Start, SIGNAL(triggered()), this, SLOT(OnStartGame())); 175 connect(ui.action_Start, SIGNAL(triggered()), this, SLOT(OnStartGame()));
183 connect(ui.action_Pause, SIGNAL(triggered()), this, SLOT(OnPauseGame())); 176 connect(ui.action_Pause, SIGNAL(triggered()), this, SLOT(OnPauseGame()));
184 connect(ui.action_Stop, SIGNAL(triggered()), this, SLOT(OnStopGame())); 177 connect(ui.action_Stop, SIGNAL(triggered()), this, SLOT(OnStopGame()));
185 connect(ui.action_Use_Hardware_Renderer, SIGNAL(triggered(bool)), this, SLOT(SetHardwareRendererEnabled(bool)));
186 connect(ui.action_Use_Shader_JIT, SIGNAL(triggered(bool)), this, SLOT(SetShaderJITEnabled(bool)));
187 connect(ui.action_Use_Gdbstub, SIGNAL(triggered(bool)), this, SLOT(SetGdbstubEnabled(bool)));
188 connect(ui.action_Single_Window_Mode, SIGNAL(triggered(bool)), this, SLOT(ToggleWindowMode())); 178 connect(ui.action_Single_Window_Mode, SIGNAL(triggered(bool)), this, SLOT(ToggleWindowMode()));
189 connect(ui.action_Hotkeys, SIGNAL(triggered()), this, SLOT(OnOpenHotkeysDialog()));
190 179
191 connect(this, SIGNAL(EmulationStarting(EmuThread*)), disasmWidget, SLOT(OnEmulationStarting(EmuThread*))); 180 connect(this, SIGNAL(EmulationStarting(EmuThread*)), disasmWidget, SLOT(OnEmulationStarting(EmuThread*)));
192 connect(this, SIGNAL(EmulationStopping()), disasmWidget, SLOT(OnEmulationStopping())); 181 connect(this, SIGNAL(EmulationStopping()), disasmWidget, SLOT(OnEmulationStopping()));
@@ -201,7 +190,7 @@ GMainWindow::GMainWindow() : emu_thread(nullptr)
201 // Setup hotkeys 190 // Setup hotkeys
202 RegisterHotkey("Main Window", "Load File", QKeySequence::Open); 191 RegisterHotkey("Main Window", "Load File", QKeySequence::Open);
203 RegisterHotkey("Main Window", "Start Emulation"); 192 RegisterHotkey("Main Window", "Start Emulation");
204 LoadHotkeys(settings); 193 LoadHotkeys();
205 194
206 connect(GetHotkey("Main Window", "Load File", this), SIGNAL(activated()), this, SLOT(OnMenuLoadFile())); 195 connect(GetHotkey("Main Window", "Load File", this), SIGNAL(activated()), this, SLOT(OnMenuLoadFile()));
207 connect(GetHotkey("Main Window", "Start Emulation", this), SIGNAL(activated()), this, SLOT(OnStartGame())); 196 connect(GetHotkey("Main Window", "Start Emulation", this), SIGNAL(activated()), this, SLOT(OnStartGame()));
@@ -211,7 +200,7 @@ GMainWindow::GMainWindow() : emu_thread(nullptr)
211 200
212 show(); 201 show();
213 202
214 game_list->PopulateAsync(settings.value("gameListRootDir", ".").toString(), settings.value("gameListDeepScan", false).toBool()); 203 game_list->PopulateAsync(UISettings::values.gamedir, UISettings::values.gamedir_deepscan);
215 204
216 QStringList args = QApplication::arguments(); 205 QStringList args = QApplication::arguments();
217 if (args.length() >= 2) { 206 if (args.length() >= 2) {
@@ -254,6 +243,14 @@ bool GMainWindow::InitializeSystem() {
254 if (emu_thread != nullptr) 243 if (emu_thread != nullptr)
255 ShutdownGame(); 244 ShutdownGame();
256 245
246 render_window->MakeCurrent();
247 if (!gladLoadGL()) {
248 QMessageBox::critical(this, tr("Error while starting Citra!"),
249 tr("Failed to initialize the video core!\n\n"
250 "Please ensure that your GPU supports OpenGL 3.3 and that you have the latest graphics driver."));
251 return false;
252 }
253
257 // Initialize the core emulation 254 // Initialize the core emulation
258 System::Result system_result = System::Init(render_window); 255 System::Result system_result = System::Init(render_window);
259 if (System::Result::Success != system_result) { 256 if (System::Result::Success != system_result) {
@@ -375,32 +372,24 @@ void GMainWindow::ShutdownGame() {
375 emulation_running = false; 372 emulation_running = false;
376} 373}
377 374
378void GMainWindow::StoreRecentFile(const std::string& filename) 375void GMainWindow::StoreRecentFile(const std::string& filename) {
379{ 376 UISettings::values.recent_files.prepend(QString::fromStdString(filename));
380 QSettings settings; 377 UISettings::values.recent_files.removeDuplicates();
381 QStringList recent_files = settings.value("recentFiles").toStringList(); 378 while (UISettings::values.recent_files.size() > max_recent_files_item) {
382 recent_files.prepend(QString::fromStdString(filename)); 379 UISettings::values.recent_files.removeLast();
383 recent_files.removeDuplicates();
384 while (recent_files.size() > max_recent_files_item) {
385 recent_files.removeLast();
386 } 380 }
387 381
388 settings.setValue("recentFiles", recent_files);
389
390 UpdateRecentFiles(); 382 UpdateRecentFiles();
391} 383}
392 384
393void GMainWindow::UpdateRecentFiles() { 385void GMainWindow::UpdateRecentFiles() {
394 QSettings settings; 386 unsigned int num_recent_files = std::min(UISettings::values.recent_files.size(), static_cast<int>(max_recent_files_item));
395 QStringList recent_files = settings.value("recentFiles").toStringList();
396
397 unsigned int num_recent_files = std::min(recent_files.size(), static_cast<int>(max_recent_files_item));
398 387
399 for (unsigned int i = 0; i < num_recent_files; i++) { 388 for (unsigned int i = 0; i < num_recent_files; i++) {
400 QString text = QString("&%1. %2").arg(i + 1).arg(QFileInfo(recent_files[i]).fileName()); 389 QString text = QString("&%1. %2").arg(i + 1).arg(QFileInfo(UISettings::values.recent_files[i]).fileName());
401 actions_recent_files[i]->setText(text); 390 actions_recent_files[i]->setText(text);
402 actions_recent_files[i]->setData(recent_files[i]); 391 actions_recent_files[i]->setData(UISettings::values.recent_files[i]);
403 actions_recent_files[i]->setToolTip(recent_files[i]); 392 actions_recent_files[i]->setToolTip(UISettings::values.recent_files[i]);
404 actions_recent_files[i]->setVisible(true); 393 actions_recent_files[i]->setVisible(true);
405 } 394 }
406 395
@@ -421,36 +410,28 @@ void GMainWindow::OnGameListLoadFile(QString game_path) {
421} 410}
422 411
423void GMainWindow::OnMenuLoadFile() { 412void GMainWindow::OnMenuLoadFile() {
424 QSettings settings; 413 QString filename = QFileDialog::getOpenFileName(this, tr("Load File"), UISettings::values.roms_path, tr("3DS executable (*.3ds *.3dsx *.elf *.axf *.cci *.cxi)"));
425 QString rom_path = settings.value("romsPath", QString()).toString();
426
427 QString filename = QFileDialog::getOpenFileName(this, tr("Load File"), rom_path, tr("3DS executable (*.3ds *.3dsx *.elf *.axf *.cci *.cxi)"));
428 if (!filename.isEmpty()) { 414 if (!filename.isEmpty()) {
429 settings.setValue("romsPath", QFileInfo(filename).path()); 415 UISettings::values.roms_path = QFileInfo(filename).path();
430 416
431 BootGame(filename.toStdString()); 417 BootGame(filename.toStdString());
432 } 418 }
433} 419}
434 420
435void GMainWindow::OnMenuLoadSymbolMap() { 421void GMainWindow::OnMenuLoadSymbolMap() {
436 QSettings settings; 422 QString filename = QFileDialog::getOpenFileName(this, tr("Load Symbol Map"), UISettings::values.symbols_path, tr("Symbol map (*)"));
437 QString symbol_path = settings.value("symbolsPath", QString()).toString();
438
439 QString filename = QFileDialog::getOpenFileName(this, tr("Load Symbol Map"), symbol_path, tr("Symbol map (*)"));
440 if (!filename.isEmpty()) { 423 if (!filename.isEmpty()) {
441 settings.setValue("symbolsPath", QFileInfo(filename).path()); 424 UISettings::values.symbols_path = QFileInfo(filename).path();
442 425
443 LoadSymbolMap(filename.toStdString()); 426 LoadSymbolMap(filename.toStdString());
444 } 427 }
445} 428}
446 429
447void GMainWindow::OnMenuSelectGameListRoot() { 430void GMainWindow::OnMenuSelectGameListRoot() {
448 QSettings settings;
449
450 QString dir_path = QFileDialog::getExistingDirectory(this, tr("Select Directory")); 431 QString dir_path = QFileDialog::getExistingDirectory(this, tr("Select Directory"));
451 if (!dir_path.isEmpty()) { 432 if (!dir_path.isEmpty()) {
452 settings.setValue("gameListRootDir", dir_path); 433 UISettings::values.gamedir = dir_path;
453 game_list->PopulateAsync(dir_path, settings.value("gameListDeepScan").toBool()); 434 game_list->PopulateAsync(dir_path, UISettings::values.gamedir_deepscan);
454 } 435 }
455} 436}
456 437
@@ -466,10 +447,7 @@ void GMainWindow::OnMenuRecentFile() {
466 // Display an error message and remove the file from the list. 447 // Display an error message and remove the file from the list.
467 QMessageBox::information(this, tr("File not found"), tr("File \"%1\" not found").arg(filename)); 448 QMessageBox::information(this, tr("File not found"), tr("File \"%1\" not found").arg(filename));
468 449
469 QSettings settings; 450 UISettings::values.recent_files.removeOne(filename);
470 QStringList recent_files = settings.value("recentFiles").toStringList();
471 recent_files.removeOne(filename);
472 settings.setValue("recentFiles", recent_files);
473 UpdateRecentFiles(); 451 UpdateRecentFiles();
474 } 452 }
475} 453}
@@ -496,31 +474,6 @@ void GMainWindow::OnStopGame() {
496 ShutdownGame(); 474 ShutdownGame();
497} 475}
498 476
499void GMainWindow::OnOpenHotkeysDialog() {
500 GHotkeysDialog dialog(this);
501 dialog.exec();
502}
503
504void GMainWindow::SetHardwareRendererEnabled(bool enabled) {
505 VideoCore::g_hw_renderer_enabled = enabled;
506
507 Config config;
508 Settings::values.use_hw_renderer = enabled;
509 config.Save();
510}
511
512void GMainWindow::SetGdbstubEnabled(bool enabled) {
513 GDBStub::ToggleServer(enabled);
514}
515
516void GMainWindow::SetShaderJITEnabled(bool enabled) {
517 VideoCore::g_shader_jit_enabled = enabled;
518
519 Config config;
520 Settings::values.use_shader_jit = enabled;
521 config.Save();
522}
523
524void GMainWindow::ToggleWindowMode() { 477void GMainWindow::ToggleWindowMode() {
525 if (ui.action_Single_Window_Mode->isChecked()) { 478 if (ui.action_Single_Window_Mode->isChecked()) {
526 // Render in the main window... 479 // Render in the main window...
@@ -547,11 +500,17 @@ void GMainWindow::ToggleWindowMode() {
547} 500}
548 501
549void GMainWindow::OnConfigure() { 502void GMainWindow::OnConfigure() {
550 //GControllerConfigDialog* dialog = new GControllerConfigDialog(controller_ports, this); 503 ConfigureDialog configureDialog(this);
504 auto result = configureDialog.exec();
505 if (result == QDialog::Accepted)
506 {
507 configureDialog.applyConfiguration();
508 config->Save();
509 }
551} 510}
552 511
553bool GMainWindow::ConfirmClose() { 512bool GMainWindow::ConfirmClose() {
554 if (emu_thread == nullptr || !confirm_before_closing) 513 if (emu_thread == nullptr || !UISettings::values.confirm_before_closing)
555 return true; 514 return true;
556 515
557 auto answer = QMessageBox::question(this, tr("Citra"), 516 auto answer = QMessageBox::question(this, tr("Citra"),
@@ -566,23 +525,19 @@ void GMainWindow::closeEvent(QCloseEvent* event) {
566 return; 525 return;
567 } 526 }
568 527
569 // Save window layout 528 UISettings::values.geometry = saveGeometry();
570 QSettings settings(QSettings::IniFormat, QSettings::UserScope, "Citra team", "Citra"); 529 UISettings::values.state = saveState();
571 530 UISettings::values.renderwindow_geometry = render_window->saveGeometry();
572 settings.beginGroup("UILayout"); 531#if MICROPROFILE_ENABLED
573 settings.setValue("geometry", saveGeometry()); 532 UISettings::values.microprofile_geometry = microProfileDialog->saveGeometry();
574 settings.setValue("state", saveState()); 533 UISettings::values.microprofile_visible = microProfileDialog->isVisible();
575 settings.setValue("geometryRenderWindow", render_window->saveGeometry()); 534#endif
576 settings.setValue("microProfileDialogGeometry", microProfileDialog->saveGeometry()); 535 UISettings::values.single_window_mode = ui.action_Single_Window_Mode->isChecked();
577 settings.setValue("microProfileDialogVisible", microProfileDialog->isVisible()); 536 UISettings::values.display_titlebar = ui.actionDisplay_widget_title_bars->isChecked();
578 settings.endGroup(); 537 UISettings::values.first_start = false;
579 538
580 settings.setValue("singleWindowMode", ui.action_Single_Window_Mode->isChecked()); 539 game_list->SaveInterfaceLayout();
581 settings.setValue("displayTitleBars", ui.actionDisplay_widget_title_bars->isChecked()); 540 SaveHotkeys();
582 settings.setValue("firstStart", false);
583 settings.setValue("confirmClose", confirm_before_closing);
584 game_list->SaveInterfaceLayout(settings);
585 SaveHotkeys(settings);
586 541
587 // Shutdown session if the emu thread is active... 542 // Shutdown session if the emu thread is active...
588 if (emu_thread != nullptr) 543 if (emu_thread != nullptr)
@@ -607,7 +562,6 @@ int main(int argc, char* argv[]) {
607 }); 562 });
608 563
609 // Init settings params 564 // Init settings params
610 QSettings::setDefaultFormat(QSettings::IniFormat);
611 QCoreApplication::setOrganizationName("Citra team"); 565 QCoreApplication::setOrganizationName("Citra team");
612 QCoreApplication::setApplicationName("Citra"); 566 QCoreApplication::setApplicationName("Citra");
613 567