|
|
|
@ -14,9 +14,11 @@ |
|
|
|
|
|
|
|
#include "citra_qt/bootmanager.h"
|
|
|
|
#include "citra_qt/config.h"
|
|
|
|
#include "citra_qt/configure_dialog.h"
|
|
|
|
#include "citra_qt/game_list.h"
|
|
|
|
#include "citra_qt/hotkeys.h"
|
|
|
|
#include "citra_qt/main.h"
|
|
|
|
#include "citra_qt/ui_settings.h"
|
|
|
|
|
|
|
|
// Debugger
|
|
|
|
#include "citra_qt/debugger/callstack.h"
|
|
|
|
@ -50,12 +52,10 @@ |
|
|
|
|
|
|
|
#include "video_core/video_core.h"
|
|
|
|
|
|
|
|
GMainWindow::GMainWindow() : emu_thread(nullptr) |
|
|
|
GMainWindow::GMainWindow() : config(new Config()), emu_thread(nullptr) |
|
|
|
{ |
|
|
|
Pica::g_debug_context = Pica::DebugContext::Construct(); |
|
|
|
|
|
|
|
Config config; |
|
|
|
|
|
|
|
ui.setupUi(this); |
|
|
|
statusBar()->hide(); |
|
|
|
|
|
|
|
@ -133,33 +133,21 @@ GMainWindow::GMainWindow() : emu_thread(nullptr) |
|
|
|
setGeometry(x, y, w, h); |
|
|
|
|
|
|
|
// Restore UI state
|
|
|
|
QSettings settings; |
|
|
|
|
|
|
|
settings.beginGroup("UILayout"); |
|
|
|
restoreGeometry(settings.value("geometry").toByteArray()); |
|
|
|
restoreState(settings.value("state").toByteArray()); |
|
|
|
render_window->restoreGeometry(settings.value("geometryRenderWindow").toByteArray()); |
|
|
|
microProfileDialog->restoreGeometry(settings.value("microProfileDialogGeometry").toByteArray()); |
|
|
|
microProfileDialog->setVisible(settings.value("microProfileDialogVisible").toBool()); |
|
|
|
settings.endGroup(); |
|
|
|
|
|
|
|
game_list->LoadInterfaceLayout(settings); |
|
|
|
restoreGeometry(UISettings::values.geometry); |
|
|
|
restoreState(UISettings::values.state); |
|
|
|
render_window->restoreGeometry(UISettings::values.renderwindow_geometry); |
|
|
|
microProfileDialog->restoreGeometry(UISettings::values.microprofile_geometry); |
|
|
|
microProfileDialog->setVisible(UISettings::values.microprofile_visible); |
|
|
|
|
|
|
|
ui.action_Use_Gdbstub->setChecked(Settings::values.use_gdbstub); |
|
|
|
SetGdbstubEnabled(ui.action_Use_Gdbstub->isChecked()); |
|
|
|
game_list->LoadInterfaceLayout(); |
|
|
|
|
|
|
|
GDBStub::ToggleServer(Settings::values.use_gdbstub); |
|
|
|
GDBStub::SetServerPort(static_cast<u32>(Settings::values.gdbstub_port)); |
|
|
|
|
|
|
|
ui.action_Use_Hardware_Renderer->setChecked(Settings::values.use_hw_renderer); |
|
|
|
SetHardwareRendererEnabled(ui.action_Use_Hardware_Renderer->isChecked()); |
|
|
|
|
|
|
|
ui.action_Use_Shader_JIT->setChecked(Settings::values.use_shader_jit); |
|
|
|
SetShaderJITEnabled(ui.action_Use_Shader_JIT->isChecked()); |
|
|
|
|
|
|
|
ui.action_Single_Window_Mode->setChecked(settings.value("singleWindowMode", true).toBool()); |
|
|
|
ui.action_Single_Window_Mode->setChecked(UISettings::values.single_window_mode); |
|
|
|
ToggleWindowMode(); |
|
|
|
|
|
|
|
ui.actionDisplay_widget_title_bars->setChecked(settings.value("displayTitleBars", true).toBool()); |
|
|
|
ui.actionDisplay_widget_title_bars->setChecked(UISettings::values.display_titlebar); |
|
|
|
OnDisplayTitleBars(ui.actionDisplay_widget_title_bars->isChecked()); |
|
|
|
|
|
|
|
// Prepare actions for recent files
|
|
|
|
@ -172,21 +160,16 @@ GMainWindow::GMainWindow() : emu_thread(nullptr) |
|
|
|
} |
|
|
|
UpdateRecentFiles(); |
|
|
|
|
|
|
|
confirm_before_closing = settings.value("confirmClose", true).toBool(); |
|
|
|
|
|
|
|
// Setup connections
|
|
|
|
connect(game_list, SIGNAL(GameChosen(QString)), this, SLOT(OnGameListLoadFile(QString))); |
|
|
|
connect(ui.action_Load_File, SIGNAL(triggered()), this, SLOT(OnMenuLoadFile())); |
|
|
|
connect(game_list, SIGNAL(GameChosen(QString)), this, SLOT(OnGameListLoadFile(QString)), Qt::DirectConnection); |
|
|
|
connect(ui.action_Configure, SIGNAL(triggered()), this, SLOT(OnConfigure())); |
|
|
|
connect(ui.action_Load_File, SIGNAL(triggered()), this, SLOT(OnMenuLoadFile()),Qt::DirectConnection); |
|
|
|
connect(ui.action_Load_Symbol_Map, SIGNAL(triggered()), this, SLOT(OnMenuLoadSymbolMap())); |
|
|
|
connect(ui.action_Select_Game_List_Root, SIGNAL(triggered()), this, SLOT(OnMenuSelectGameListRoot())); |
|
|
|
connect(ui.action_Start, SIGNAL(triggered()), this, SLOT(OnStartGame())); |
|
|
|
connect(ui.action_Pause, SIGNAL(triggered()), this, SLOT(OnPauseGame())); |
|
|
|
connect(ui.action_Stop, SIGNAL(triggered()), this, SLOT(OnStopGame())); |
|
|
|
connect(ui.action_Use_Hardware_Renderer, SIGNAL(triggered(bool)), this, SLOT(SetHardwareRendererEnabled(bool))); |
|
|
|
connect(ui.action_Use_Shader_JIT, SIGNAL(triggered(bool)), this, SLOT(SetShaderJITEnabled(bool))); |
|
|
|
connect(ui.action_Use_Gdbstub, SIGNAL(triggered(bool)), this, SLOT(SetGdbstubEnabled(bool))); |
|
|
|
connect(ui.action_Single_Window_Mode, SIGNAL(triggered(bool)), this, SLOT(ToggleWindowMode())); |
|
|
|
connect(ui.action_Hotkeys, SIGNAL(triggered()), this, SLOT(OnOpenHotkeysDialog())); |
|
|
|
|
|
|
|
connect(this, SIGNAL(EmulationStarting(EmuThread*)), disasmWidget, SLOT(OnEmulationStarting(EmuThread*))); |
|
|
|
connect(this, SIGNAL(EmulationStopping()), disasmWidget, SLOT(OnEmulationStopping())); |
|
|
|
@ -201,7 +184,7 @@ GMainWindow::GMainWindow() : emu_thread(nullptr) |
|
|
|
// Setup hotkeys
|
|
|
|
RegisterHotkey("Main Window", "Load File", QKeySequence::Open); |
|
|
|
RegisterHotkey("Main Window", "Start Emulation"); |
|
|
|
LoadHotkeys(settings); |
|
|
|
LoadHotkeys(); |
|
|
|
|
|
|
|
connect(GetHotkey("Main Window", "Load File", this), SIGNAL(activated()), this, SLOT(OnMenuLoadFile())); |
|
|
|
connect(GetHotkey("Main Window", "Start Emulation", this), SIGNAL(activated()), this, SLOT(OnStartGame())); |
|
|
|
@ -211,7 +194,7 @@ GMainWindow::GMainWindow() : emu_thread(nullptr) |
|
|
|
|
|
|
|
show(); |
|
|
|
|
|
|
|
game_list->PopulateAsync(settings.value("gameListRootDir", ".").toString(), settings.value("gameListDeepScan", false).toBool()); |
|
|
|
game_list->PopulateAsync(UISettings::values.gamedir, UISettings::values.gamedir_deepscan); |
|
|
|
|
|
|
|
QStringList args = QApplication::arguments(); |
|
|
|
if (args.length() >= 2) { |
|
|
|
@ -375,32 +358,24 @@ void GMainWindow::ShutdownGame() { |
|
|
|
emulation_running = false; |
|
|
|
} |
|
|
|
|
|
|
|
void GMainWindow::StoreRecentFile(const std::string& filename) |
|
|
|
{ |
|
|
|
QSettings settings; |
|
|
|
QStringList recent_files = settings.value("recentFiles").toStringList(); |
|
|
|
recent_files.prepend(QString::fromStdString(filename)); |
|
|
|
recent_files.removeDuplicates(); |
|
|
|
while (recent_files.size() > max_recent_files_item) { |
|
|
|
recent_files.removeLast(); |
|
|
|
void GMainWindow::StoreRecentFile(const std::string& filename) { |
|
|
|
UISettings::values.recent_files.prepend(QString::fromStdString(filename)); |
|
|
|
UISettings::values.recent_files.removeDuplicates(); |
|
|
|
while (UISettings::values.recent_files.size() > max_recent_files_item) { |
|
|
|
UISettings::values.recent_files.removeLast(); |
|
|
|
} |
|
|
|
|
|
|
|
settings.setValue("recentFiles", recent_files); |
|
|
|
|
|
|
|
UpdateRecentFiles(); |
|
|
|
} |
|
|
|
|
|
|
|
void GMainWindow::UpdateRecentFiles() { |
|
|
|
QSettings settings; |
|
|
|
QStringList recent_files = settings.value("recentFiles").toStringList(); |
|
|
|
|
|
|
|
unsigned int num_recent_files = std::min(recent_files.size(), static_cast<int>(max_recent_files_item)); |
|
|
|
unsigned int num_recent_files = std::min(UISettings::values.recent_files.size(), static_cast<int>(max_recent_files_item)); |
|
|
|
|
|
|
|
for (unsigned int i = 0; i < num_recent_files; i++) { |
|
|
|
QString text = QString("&%1. %2").arg(i + 1).arg(QFileInfo(recent_files[i]).fileName()); |
|
|
|
QString text = QString("&%1. %2").arg(i + 1).arg(QFileInfo(UISettings::values.recent_files[i]).fileName()); |
|
|
|
actions_recent_files[i]->setText(text); |
|
|
|
actions_recent_files[i]->setData(recent_files[i]); |
|
|
|
actions_recent_files[i]->setToolTip(recent_files[i]); |
|
|
|
actions_recent_files[i]->setData(UISettings::values.recent_files[i]); |
|
|
|
actions_recent_files[i]->setToolTip(UISettings::values.recent_files[i]); |
|
|
|
actions_recent_files[i]->setVisible(true); |
|
|
|
} |
|
|
|
|
|
|
|
@ -421,36 +396,28 @@ void GMainWindow::OnGameListLoadFile(QString game_path) { |
|
|
|
} |
|
|
|
|
|
|
|
void GMainWindow::OnMenuLoadFile() { |
|
|
|
QSettings settings; |
|
|
|
QString rom_path = settings.value("romsPath", QString()).toString(); |
|
|
|
|
|
|
|
QString filename = QFileDialog::getOpenFileName(this, tr("Load File"), rom_path, tr("3DS executable (*.3ds *.3dsx *.elf *.axf *.cci *.cxi)")); |
|
|
|
QString filename = QFileDialog::getOpenFileName(this, tr("Load File"), UISettings::values.roms_path, tr("3DS executable (*.3ds *.3dsx *.elf *.axf *.cci *.cxi)")); |
|
|
|
if (!filename.isEmpty()) { |
|
|
|
settings.setValue("romsPath", QFileInfo(filename).path()); |
|
|
|
UISettings::values.roms_path = QFileInfo(filename).path(); |
|
|
|
|
|
|
|
BootGame(filename.toStdString()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void GMainWindow::OnMenuLoadSymbolMap() { |
|
|
|
QSettings settings; |
|
|
|
QString symbol_path = settings.value("symbolsPath", QString()).toString(); |
|
|
|
|
|
|
|
QString filename = QFileDialog::getOpenFileName(this, tr("Load Symbol Map"), symbol_path, tr("Symbol map (*)")); |
|
|
|
QString filename = QFileDialog::getOpenFileName(this, tr("Load Symbol Map"), UISettings::values.symbols_path, tr("Symbol map (*)")); |
|
|
|
if (!filename.isEmpty()) { |
|
|
|
settings.setValue("symbolsPath", QFileInfo(filename).path()); |
|
|
|
UISettings::values.symbols_path = QFileInfo(filename).path(); |
|
|
|
|
|
|
|
LoadSymbolMap(filename.toStdString()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void GMainWindow::OnMenuSelectGameListRoot() { |
|
|
|
QSettings settings; |
|
|
|
|
|
|
|
QString dir_path = QFileDialog::getExistingDirectory(this, tr("Select Directory")); |
|
|
|
if (!dir_path.isEmpty()) { |
|
|
|
settings.setValue("gameListRootDir", dir_path); |
|
|
|
game_list->PopulateAsync(dir_path, settings.value("gameListDeepScan").toBool()); |
|
|
|
UISettings::values.gamedir = dir_path; |
|
|
|
game_list->PopulateAsync(dir_path, UISettings::values.gamedir_deepscan); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -466,10 +433,7 @@ void GMainWindow::OnMenuRecentFile() { |
|
|
|
// Display an error message and remove the file from the list.
|
|
|
|
QMessageBox::information(this, tr("File not found"), tr("File \"%1\" not found").arg(filename)); |
|
|
|
|
|
|
|
QSettings settings; |
|
|
|
QStringList recent_files = settings.value("recentFiles").toStringList(); |
|
|
|
recent_files.removeOne(filename); |
|
|
|
settings.setValue("recentFiles", recent_files); |
|
|
|
UISettings::values.recent_files.removeOne(filename); |
|
|
|
UpdateRecentFiles(); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -496,31 +460,6 @@ void GMainWindow::OnStopGame() { |
|
|
|
ShutdownGame(); |
|
|
|
} |
|
|
|
|
|
|
|
void GMainWindow::OnOpenHotkeysDialog() { |
|
|
|
GHotkeysDialog dialog(this); |
|
|
|
dialog.exec(); |
|
|
|
} |
|
|
|
|
|
|
|
void GMainWindow::SetHardwareRendererEnabled(bool enabled) { |
|
|
|
VideoCore::g_hw_renderer_enabled = enabled; |
|
|
|
|
|
|
|
Config config; |
|
|
|
Settings::values.use_hw_renderer = enabled; |
|
|
|
config.Save(); |
|
|
|
} |
|
|
|
|
|
|
|
void GMainWindow::SetGdbstubEnabled(bool enabled) { |
|
|
|
GDBStub::ToggleServer(enabled); |
|
|
|
} |
|
|
|
|
|
|
|
void GMainWindow::SetShaderJITEnabled(bool enabled) { |
|
|
|
VideoCore::g_shader_jit_enabled = enabled; |
|
|
|
|
|
|
|
Config config; |
|
|
|
Settings::values.use_shader_jit = enabled; |
|
|
|
config.Save(); |
|
|
|
} |
|
|
|
|
|
|
|
void GMainWindow::ToggleWindowMode() { |
|
|
|
if (ui.action_Single_Window_Mode->isChecked()) { |
|
|
|
// Render in the main window...
|
|
|
|
@ -547,11 +486,17 @@ void GMainWindow::ToggleWindowMode() { |
|
|
|
} |
|
|
|
|
|
|
|
void GMainWindow::OnConfigure() { |
|
|
|
//GControllerConfigDialog* dialog = new GControllerConfigDialog(controller_ports, this);
|
|
|
|
ConfigureDialog configureDialog(this); |
|
|
|
auto result = configureDialog.exec(); |
|
|
|
if (result == QDialog::Accepted) |
|
|
|
{ |
|
|
|
configureDialog.applyConfiguration(); |
|
|
|
config->Save(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
bool GMainWindow::ConfirmClose() { |
|
|
|
if (emu_thread == nullptr || !confirm_before_closing) |
|
|
|
if (emu_thread == nullptr || !UISettings::values.confirm_before_closing) |
|
|
|
return true; |
|
|
|
|
|
|
|
auto answer = QMessageBox::question(this, tr("Citra"), |
|
|
|
@ -566,23 +511,18 @@ void GMainWindow::closeEvent(QCloseEvent* event) { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// Save window layout
|
|
|
|
QSettings settings(QSettings::IniFormat, QSettings::UserScope, "Citra team", "Citra"); |
|
|
|
UISettings::values.geometry = saveGeometry(); |
|
|
|
UISettings::values.state = saveState(); |
|
|
|
UISettings::values.renderwindow_geometry = render_window->saveGeometry(); |
|
|
|
UISettings::values.microprofile_geometry = microProfileDialog->saveGeometry(); |
|
|
|
UISettings::values.microprofile_visible = microProfileDialog->isVisible(); |
|
|
|
|
|
|
|
settings.beginGroup("UILayout"); |
|
|
|
settings.setValue("geometry", saveGeometry()); |
|
|
|
settings.setValue("state", saveState()); |
|
|
|
settings.setValue("geometryRenderWindow", render_window->saveGeometry()); |
|
|
|
settings.setValue("microProfileDialogGeometry", microProfileDialog->saveGeometry()); |
|
|
|
settings.setValue("microProfileDialogVisible", microProfileDialog->isVisible()); |
|
|
|
settings.endGroup(); |
|
|
|
UISettings::values.single_window_mode = ui.action_Single_Window_Mode->isChecked(); |
|
|
|
UISettings::values.display_titlebar = ui.actionDisplay_widget_title_bars->isChecked(); |
|
|
|
UISettings::values.first_start = false; |
|
|
|
|
|
|
|
settings.setValue("singleWindowMode", ui.action_Single_Window_Mode->isChecked()); |
|
|
|
settings.setValue("displayTitleBars", ui.actionDisplay_widget_title_bars->isChecked()); |
|
|
|
settings.setValue("firstStart", false); |
|
|
|
settings.setValue("confirmClose", confirm_before_closing); |
|
|
|
game_list->SaveInterfaceLayout(settings); |
|
|
|
SaveHotkeys(settings); |
|
|
|
game_list->SaveInterfaceLayout(); |
|
|
|
SaveHotkeys(); |
|
|
|
|
|
|
|
// Shutdown session if the emu thread is active...
|
|
|
|
if (emu_thread != nullptr) |
|
|
|
@ -607,7 +547,6 @@ int main(int argc, char* argv[]) { |
|
|
|
}); |
|
|
|
|
|
|
|
// Init settings params
|
|
|
|
QSettings::setDefaultFormat(QSettings::IniFormat); |
|
|
|
QCoreApplication::setOrganizationName("Citra team"); |
|
|
|
QCoreApplication::setApplicationName("Citra"); |
|
|
|
|
|
|
|
|