diff options
Diffstat (limited to '')
46 files changed, 452 insertions, 437 deletions
diff --git a/src/citra/CMakeLists.txt b/src/citra/CMakeLists.txt index f9c488a1a..ecb5d2dfe 100644 --- a/src/citra/CMakeLists.txt +++ b/src/citra/CMakeLists.txt @@ -1,3 +1,5 @@ +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/CMakeModules) + set(SRCS emu_window/emu_window_sdl2.cpp citra.cpp @@ -28,11 +30,6 @@ if(UNIX AND NOT APPLE) endif() if (MSVC) - include(WindowsCopyFiles) - - set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/$<CONFIG>/") - - windows_copy_files(citra ${SDL2_DLL_DIR} ${DLL_DEST} SDL2.dll) - - unset(DLL_DEST) + include(CopyCitraSDLDeps) + copy_citra_SDL_deps(citra) endif() diff --git a/src/citra/citra.cpp b/src/citra/citra.cpp index f9387e61c..99c096ac7 100644 --- a/src/citra/citra.cpp +++ b/src/citra/citra.cpp @@ -18,7 +18,7 @@ #endif #ifdef _WIN32 -#include <Windows.h> +#include <windows.h> #endif #include "citra/config.h" @@ -33,7 +33,6 @@ #include "core/gdbstub/gdbstub.h" #include "core/loader/loader.h" #include "core/settings.h" -#include "core/system.h" #include "video_core/video_core.h" static void PrintHelp(const char* argv0) { @@ -64,7 +63,7 @@ int main(int argc, char** argv) { return -1; } #endif - std::string boot_filename; + std::string filepath; static struct option long_options[] = { {"gdbport", required_argument, 0, 'g'}, @@ -97,9 +96,9 @@ int main(int argc, char** argv) { } } else { #ifdef _WIN32 - boot_filename = Common::UTF16ToUTF8(argv_w[optind]); + filepath = Common::UTF16ToUTF8(argv_w[optind]); #else - boot_filename = argv[optind]; + filepath = argv[optind]; #endif optind++; } @@ -115,7 +114,7 @@ int main(int argc, char** argv) { MicroProfileOnThreadCreate("EmuThread"); SCOPE_EXIT({ MicroProfileShutdown(); }); - if (boot_filename.empty()) { + if (filepath.empty()) { LOG_CRITICAL(Frontend, "Failed to load ROM: No ROM specified"); return -1; } @@ -127,32 +126,25 @@ int main(int argc, char** argv) { Settings::values.use_gdbstub = use_gdbstub; Settings::Apply(); - std::unique_ptr<EmuWindow_SDL2> emu_window = std::make_unique<EmuWindow_SDL2>(); + std::unique_ptr<EmuWindow_SDL2> emu_window{std::make_unique<EmuWindow_SDL2>()}; - std::unique_ptr<Loader::AppLoader> loader = Loader::GetLoader(boot_filename); - if (!loader) { - LOG_CRITICAL(Frontend, "Failed to obtain loader for %s!", boot_filename.c_str()); - return -1; - } - - boost::optional<u32> system_mode = loader->LoadKernelSystemMode(); + Core::System& system{Core::System::GetInstance()}; - if (!system_mode) { - LOG_CRITICAL(Frontend, "Failed to load ROM (Could not determine system mode)!"); - return -1; - } + SCOPE_EXIT({ system.Shutdown(); }); - System::Init(emu_window.get(), system_mode.get()); - SCOPE_EXIT({ System::Shutdown(); }); + const Core::System::ResultStatus load_result{system.Load(emu_window.get(), filepath)}; - Loader::ResultStatus load_result = loader->Load(); - if (Loader::ResultStatus::Success != load_result) { - LOG_CRITICAL(Frontend, "Failed to load ROM (Error %i)!", load_result); + switch (load_result) { + case Core::System::ResultStatus::ErrorGetLoader: + LOG_CRITICAL(Frontend, "Failed to obtain loader for %s!", filepath.c_str()); + return -1; + case Core::System::ResultStatus::ErrorLoader: + LOG_CRITICAL(Frontend, "Failed to load ROM!"); return -1; } while (emu_window->IsOpen()) { - Core::RunLoop(); + system.RunLoop(); } return 0; diff --git a/src/citra/citra.rc b/src/citra/citra.rc index b0edb2e6b..fea603004 100644 --- a/src/citra/citra.rc +++ b/src/citra/citra.rc @@ -5,5 +5,5 @@ // Icon with lowest ID value placed first to ensure application icon // remains consistent on all systems. -GLFW_ICON ICON "..\\..\\dist\\citra.ico" +CITRA_ICON ICON "../../dist/citra.ico" diff --git a/src/citra/emu_window/emu_window_sdl2.cpp b/src/citra/emu_window/emu_window_sdl2.cpp index 8abe48984..b0d82b670 100644 --- a/src/citra/emu_window/emu_window_sdl2.cpp +++ b/src/citra/emu_window/emu_window_sdl2.cpp @@ -9,10 +9,10 @@ #include <SDL.h> #include <glad/glad.h> #include "citra/emu_window/emu_window_sdl2.h" -#include "common/key_map.h" #include "common/logging/log.h" #include "common/scm_rev.h" #include "common/string_util.h" +#include "core/frontend/key_map.h" #include "core/hle/service/hid/hid.h" #include "core/settings.h" #include "video_core/video_core.h" diff --git a/src/citra/emu_window/emu_window_sdl2.h b/src/citra/emu_window/emu_window_sdl2.h index e4d14ef12..c8cd919c6 100644 --- a/src/citra/emu_window/emu_window_sdl2.h +++ b/src/citra/emu_window/emu_window_sdl2.h @@ -5,7 +5,7 @@ #pragma once #include <utility> -#include "common/emu_window.h" +#include "core/frontend/emu_window.h" struct SDL_Window; diff --git a/src/citra_qt/CMakeLists.txt b/src/citra_qt/CMakeLists.txt index a9dacd5f1..93f1c339d 100644 --- a/src/citra_qt/CMakeLists.txt +++ b/src/citra_qt/CMakeLists.txt @@ -1,17 +1,18 @@ set(CMAKE_AUTOMOC ON) set(CMAKE_INCLUDE_CURRENT_DIR ON) +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/CMakeModules) set(SRCS config.cpp debugger/callstack.cpp debugger/disassembler.cpp - debugger/graphics.cpp - debugger/graphics_breakpoint_observer.cpp - debugger/graphics_breakpoints.cpp - debugger/graphics_cmdlists.cpp - debugger/graphics_surface.cpp - debugger/graphics_tracing.cpp - debugger/graphics_vertex_shader.cpp + debugger/graphics/graphics.cpp + debugger/graphics/graphics_breakpoint_observer.cpp + debugger/graphics/graphics_breakpoints.cpp + debugger/graphics/graphics_cmdlists.cpp + debugger/graphics/graphics_surface.cpp + debugger/graphics/graphics_tracing.cpp + debugger/graphics/graphics_vertex_shader.cpp debugger/profiler.cpp debugger/ramview.cpp debugger/registers.cpp @@ -38,14 +39,14 @@ set(HEADERS config.h debugger/callstack.h debugger/disassembler.h - debugger/graphics.h - debugger/graphics_breakpoint_observer.h - debugger/graphics_breakpoints.h - debugger/graphics_breakpoints_p.h - debugger/graphics_cmdlists.h - debugger/graphics_surface.h - debugger/graphics_tracing.h - debugger/graphics_vertex_shader.h + debugger/graphics/graphics.h + debugger/graphics/graphics_breakpoint_observer.h + debugger/graphics/graphics_breakpoints.h + debugger/graphics/graphics_breakpoints_p.h + debugger/graphics/graphics_cmdlists.h + debugger/graphics/graphics_surface.h + debugger/graphics/graphics_tracing.h + debugger/graphics/graphics_vertex_shader.h debugger/profiler.h debugger/ramview.h debugger/registers.h @@ -107,27 +108,9 @@ if(UNIX AND NOT APPLE) install(TARGETS citra-qt RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/bin") endif() -if (Qt5_FOUND AND MSVC) - include(WindowsCopyFiles) - - set(Qt5_DLL_DIR "${Qt5_DIR}/../../../bin") - set(Qt5_PLATFORMS_DIR "${Qt5_DIR}/../../../plugins/platforms/") - set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/$<CONFIG>/") - set(PLATFORMS ${DLL_DEST}platforms/) - - windows_copy_files(citra-qt ${Qt5_DLL_DIR} ${DLL_DEST} - icudt*.dll - icuin*.dll - icuuc*.dll - Qt5Core$<$<CONFIG:Debug>:d>.* - Qt5Gui$<$<CONFIG:Debug>:d>.* - Qt5OpenGL$<$<CONFIG:Debug>:d>.* - Qt5Widgets$<$<CONFIG:Debug>:d>.* - ) - windows_copy_files(citra-qt ${Qt5_PLATFORMS_DIR} ${PLATFORMS} qwindows$<$<CONFIG:Debug>:d>.*) - - unset(Qt5_DLL_DIR) - unset(Qt5_PLATFORMS_DIR) - unset(DLL_DEST) - unset(PLATFORMS) +if (MSVC) + include(CopyCitraQt5Deps) + include(CopyCitraSDLDeps) + copy_citra_Qt5_deps(citra-qt) + copy_citra_SDL_deps(citra-qt) endif() diff --git a/src/citra_qt/bootmanager.cpp b/src/citra_qt/bootmanager.cpp index 7699ca8d0..57fde6caa 100644 --- a/src/citra_qt/bootmanager.cpp +++ b/src/citra_qt/bootmanager.cpp @@ -9,21 +9,14 @@ #endif #include "citra_qt/bootmanager.h" -#include "common/key_map.h" #include "common/microprofile.h" #include "common/scm_rev.h" #include "common/string_util.h" #include "core/core.h" -#include "core/settings.h" -#include "core/system.h" +#include "core/frontend/key_map.h" #include "video_core/debug_utils/debug_utils.h" #include "video_core/video_core.h" -#define APP_NAME "citra" -#define APP_VERSION "0.1-" VERSION -#define APP_TITLE APP_NAME " " APP_VERSION -#define COPYRIGHT "Copyright (C) 2013-2014 Citra Team" - EmuThread::EmuThread(GRenderWindow* render_window) : exec_step(false), running(false), stop_run(false), render_window(render_window) {} @@ -43,7 +36,7 @@ void EmuThread::run() { if (!was_active) emit DebugModeLeft(); - Core::RunLoop(); + Core::System::GetInstance().RunLoop(); was_active = running || exec_step; if (!was_active && !stop_run) @@ -53,7 +46,7 @@ void EmuThread::run() { emit DebugModeLeft(); exec_step = false; - Core::SingleStep(); + Core::System::GetInstance().SingleStep(); emit DebugModeEntered(); yieldCurrentThread(); @@ -65,7 +58,7 @@ void EmuThread::run() { } // Shutdown the core emulation - System::Shutdown(); + Core::System::GetInstance().Shutdown(); #if MICROPROFILE_ENABLED MicroProfileOnThreadExit(); diff --git a/src/citra_qt/bootmanager.h b/src/citra_qt/bootmanager.h index 67228b94f..43015390b 100644 --- a/src/citra_qt/bootmanager.h +++ b/src/citra_qt/bootmanager.h @@ -2,13 +2,15 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#pragma once + #include <atomic> #include <condition_variable> #include <mutex> #include <QGLWidget> #include <QThread> -#include "common/emu_window.h" #include "common/thread.h" +#include "core/frontend/emu_window.h" class QKeyEvent; class QScreen; @@ -21,7 +23,7 @@ class EmuThread : public QThread { Q_OBJECT public: - EmuThread(GRenderWindow* render_window); + explicit EmuThread(GRenderWindow* render_window); /** * Start emulation (on new thread) diff --git a/src/citra_qt/citra-qt.rc b/src/citra_qt/citra-qt.rc index 3c7239853..fea603004 100644 --- a/src/citra_qt/citra-qt.rc +++ b/src/citra_qt/citra-qt.rc @@ -5,5 +5,5 @@ // Icon with lowest ID value placed first to ensure application icon // remains consistent on all systems. -IDI_ICON1 ICON "..\\..\\dist\\citra.ico" +CITRA_ICON ICON "../../dist/citra.ico" diff --git a/src/citra_qt/configure_general.cpp b/src/citra_qt/configure_general.cpp index 0b802d081..ac90a6df4 100644 --- a/src/citra_qt/configure_general.cpp +++ b/src/citra_qt/configure_general.cpp @@ -4,8 +4,8 @@ #include "citra_qt/configure_general.h" #include "citra_qt/ui_settings.h" +#include "core/core.h" #include "core/settings.h" -#include "core/system.h" #include "ui_configure_general.h" ConfigureGeneral::ConfigureGeneral(QWidget* parent) @@ -14,7 +14,7 @@ ConfigureGeneral::ConfigureGeneral(QWidget* parent) ui->setupUi(this); this->setConfiguration(); - ui->toggle_cpu_jit->setEnabled(!System::IsPoweredOn()); + ui->toggle_cpu_jit->setEnabled(!Core::System::GetInstance().IsPoweredOn()); } ConfigureGeneral::~ConfigureGeneral() {} diff --git a/src/citra_qt/configure_graphics.cpp b/src/citra_qt/configure_graphics.cpp index 36f10c8d7..cea7db388 100644 --- a/src/citra_qt/configure_graphics.cpp +++ b/src/citra_qt/configure_graphics.cpp @@ -3,8 +3,8 @@ // Refer to the license.txt file included. #include "citra_qt/configure_graphics.h" +#include "core/core.h" #include "core/settings.h" -#include "core/system.h" #include "ui_configure_graphics.h" ConfigureGraphics::ConfigureGraphics(QWidget* parent) @@ -13,7 +13,7 @@ ConfigureGraphics::ConfigureGraphics(QWidget* parent) ui->setupUi(this); this->setConfiguration(); - ui->toggle_vsync->setEnabled(!System::IsPoweredOn()); + ui->toggle_vsync->setEnabled(!Core::System::GetInstance().IsPoweredOn()); } ConfigureGraphics::~ConfigureGraphics() {} diff --git a/src/citra_qt/configure_input.cpp b/src/citra_qt/configure_input.cpp index d321db71f..3e6803b8a 100644 --- a/src/citra_qt/configure_input.cpp +++ b/src/citra_qt/configure_input.cpp @@ -5,15 +5,33 @@ #include <memory> #include <utility> #include <QTimer> +#include "citra_qt/config.h" #include "citra_qt/configure_input.h" +static QString getKeyName(Qt::Key key_code) { + switch (key_code) { + case Qt::Key_Shift: + return QObject::tr("Shift"); + case Qt::Key_Control: + return QObject::tr("Ctrl"); + case Qt::Key_Alt: + return QObject::tr("Alt"); + case Qt::Key_Meta: + case -1: + return ""; + default: + return QKeySequence(key_code).toString(); + } +} + ConfigureInput::ConfigureInput(QWidget* parent) - : QWidget(parent), ui(std::make_unique<Ui::ConfigureInput>()) { + : QWidget(parent), ui(std::make_unique<Ui::ConfigureInput>()), + timer(std::make_unique<QTimer>()) { ui->setupUi(this); + setFocusPolicy(Qt::ClickFocus); - // Initialize mapping of input enum to UI button. - input_mapping = { + button_map = { {Settings::NativeInput::Values::A, ui->buttonA}, {Settings::NativeInput::Values::B, ui->buttonB}, {Settings::NativeInput::Values::X, ui->buttonX}, @@ -40,114 +58,89 @@ ConfigureInput::ConfigureInput(QWidget* parent) {Settings::NativeInput::Values::CIRCLE_MODIFIER, ui->buttonCircleMod}, }; - // Attach handle click method to each button click. - for (const auto& entry : input_mapping) { - connect(entry.second, SIGNAL(released()), this, SLOT(handleClick())); + for (const auto& entry : button_map) { + const Settings::NativeInput::Values input_id = entry.first; + connect(entry.second, &QPushButton::released, + [this, input_id]() { handleClick(input_id); }); } - connect(ui->buttonRestoreDefaults, SIGNAL(released()), this, SLOT(restoreDefaults())); - setFocusPolicy(Qt::ClickFocus); - timer = new QTimer(this); + + connect(ui->buttonRestoreDefaults, &QPushButton::released, [this]() { restoreDefaults(); }); + timer->setSingleShot(true); - connect(timer, &QTimer::timeout, this, [&]() { - key_pressed = Qt::Key_Escape; - setKey(); + connect(timer.get(), &QTimer::timeout, [this]() { + releaseKeyboard(); + releaseMouse(); + current_input_id = boost::none; + updateButtonLabels(); }); - this->setConfiguration(); -} -void ConfigureInput::handleClick() { - QPushButton* sender = qobject_cast<QPushButton*>(QObject::sender()); - previous_mapping = sender->text(); - sender->setText(tr("[waiting]")); - sender->setFocus(); - grabKeyboard(); - grabMouse(); - changing_button = sender; - timer->start(5000); // Cancel after 5 seconds + this->loadConfiguration(); } void ConfigureInput::applyConfiguration() { - for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) { - int value = getKeyValue(input_mapping[Settings::NativeInput::Values(i)]->text()); - Settings::values.input_mappings[Settings::NativeInput::All[i]] = value; + for (const auto& input_id : Settings::NativeInput::All) { + const size_t index = static_cast<size_t>(input_id); + Settings::values.input_mappings[index] = static_cast<int>(key_map[input_id]); } Settings::Apply(); } -void ConfigureInput::setConfiguration() { - for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) { - QString keyValue = getKeyName(Settings::values.input_mappings[i]); - input_mapping[Settings::NativeInput::Values(i)]->setText(keyValue); +void ConfigureInput::loadConfiguration() { + for (const auto& input_id : Settings::NativeInput::All) { + const size_t index = static_cast<size_t>(input_id); + key_map[input_id] = static_cast<Qt::Key>(Settings::values.input_mappings[index]); } + updateButtonLabels(); } -void ConfigureInput::keyPressEvent(QKeyEvent* event) { - if (!changing_button) - return; - if (!event || event->key() == Qt::Key_unknown) - return; - key_pressed = event->key(); - timer->stop(); - setKey(); +void ConfigureInput::restoreDefaults() { + for (const auto& input_id : Settings::NativeInput::All) { + const size_t index = static_cast<size_t>(input_id); + key_map[input_id] = static_cast<Qt::Key>(Config::defaults[index].toInt()); + } + updateButtonLabels(); + applyConfiguration(); } -void ConfigureInput::setKey() { - const QString key_value = getKeyName(key_pressed); - if (key_pressed == Qt::Key_Escape) - changing_button->setText(previous_mapping); - else - changing_button->setText(key_value); - removeDuplicates(key_value); - key_pressed = Qt::Key_unknown; - releaseKeyboard(); - releaseMouse(); - changing_button = nullptr; - previous_mapping = nullptr; +void ConfigureInput::updateButtonLabels() { + for (const auto& input_id : Settings::NativeInput::All) { + button_map[input_id]->setText(getKeyName(key_map[input_id])); + } } -QString ConfigureInput::getKeyName(int key_code) const { - if (key_code == Qt::Key_Shift) - return tr("Shift"); - if (key_code == Qt::Key_Control) - return tr("Ctrl"); - if (key_code == Qt::Key_Alt) - return tr("Alt"); - if (key_code == Qt::Key_Meta) - return ""; - if (key_code == -1) - return ""; +void ConfigureInput::handleClick(Settings::NativeInput::Values input_id) { + QPushButton* button = button_map[input_id]; + button->setText(tr("[press key]")); + button->setFocus(); - return QKeySequence(key_code).toString(); -} + current_input_id = input_id; -Qt::Key ConfigureInput::getKeyValue(const QString& text) const { - if (text == "Shift") - return Qt::Key_Shift; - if (text == "Ctrl") - return Qt::Key_Control; - if (text == "Alt") - return Qt::Key_Alt; - if (text == "Meta") - return Qt::Key_unknown; - if (text == "") - return Qt::Key_unknown; - - return Qt::Key(QKeySequence(text)[0]); + grabKeyboard(); + grabMouse(); + timer->start(5000); // Cancel after 5 seconds } -void ConfigureInput::removeDuplicates(const QString& newValue) { - for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) { - if (changing_button != input_mapping[Settings::NativeInput::Values(i)]) { - const QString oldValue = input_mapping[Settings::NativeInput::Values(i)]->text(); - if (newValue == oldValue) - input_mapping[Settings::NativeInput::Values(i)]->setText(""); - } - } +void ConfigureInput::keyPressEvent(QKeyEvent* event) { + releaseKeyboard(); + releaseMouse(); + + if (!current_input_id || !event) + return; + + if (event->key() != Qt::Key_Escape) + setInput(*current_input_id, static_cast<Qt::Key>(event->key())); + + updateButtonLabels(); + current_input_id = boost::none; + timer->stop(); } -void ConfigureInput::restoreDefaults() { - for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) { - const QString keyValue = getKeyName(Config::defaults[i].toInt()); - input_mapping[Settings::NativeInput::Values(i)]->setText(keyValue); +void ConfigureInput::setInput(Settings::NativeInput::Values input_id, Qt::Key key_pressed) { + // Remove duplicates + for (auto& pair : key_map) { + if (pair.second == key_pressed) + pair.second = Qt::Key_unknown; } + + key_map[input_id] = key_pressed; } diff --git a/src/citra_qt/configure_input.h b/src/citra_qt/configure_input.h index 5183b904d..bc343db83 100644 --- a/src/citra_qt/configure_input.h +++ b/src/citra_qt/configure_input.h @@ -7,7 +7,7 @@ #include <memory> #include <QKeyEvent> #include <QWidget> -#include "citra_qt/config.h" +#include <boost/optional.hpp> #include "core/settings.h" #include "ui_configure_input.h" @@ -30,35 +30,28 @@ public: private: std::unique_ptr<Ui::ConfigureInput> ui; - std::map<Settings::NativeInput::Values, QPushButton*> input_mapping; - int key_pressed; - QPushButton* changing_button = nullptr; ///< button currently waiting for key press. - QString previous_mapping; - QTimer* timer; - /// Load configuration settings into button text - void setConfiguration(); + /// This input is currently awaiting configuration. + /// (i.e.: its corresponding QPushButton has been pressed.) + boost::optional<Settings::NativeInput::Values> current_input_id; + std::unique_ptr<QTimer> timer; - /// Check all inputs for duplicate keys. Clears out any other button with the same value as this - /// button's new value. - void removeDuplicates(const QString& newValue); - - /// Handle key press event for input tab when a button is 'waiting'. - void keyPressEvent(QKeyEvent* event) override; - - /// Convert key ASCII value to its' letter/name - QString getKeyName(int key_code) const; - - /// Convert letter/name of key to its ASCII value. - Qt::Key getKeyValue(const QString& text) const; - - /// Set button text to name of key pressed. - void setKey(); - -private slots: - /// Event handler for all button released() event. - void handleClick(); + /// Each input is represented by a QPushButton. + std::map<Settings::NativeInput::Values, QPushButton*> button_map; + /// Each input is configured to respond to the press of a Qt::Key. + std::map<Settings::NativeInput::Values, Qt::Key> key_map; + /// Load configuration settings. + void loadConfiguration(); /// Restore all buttons to their default values. void restoreDefaults(); + /// Update UI to reflect current configuration. + void updateButtonLabels(); + + /// Called when the button corresponding to input_id was pressed. + void handleClick(Settings::NativeInput::Values input_id); + /// Handle key press events. + void keyPressEvent(QKeyEvent* event) override; + /// Configure input input_id to respond to key key_pressed. + void setInput(Settings::NativeInput::Values input_id, Qt::Key key_pressed); }; diff --git a/src/citra_qt/configure_system.cpp b/src/citra_qt/configure_system.cpp index 873d314ec..eb1276ef3 100644 --- a/src/citra_qt/configure_system.cpp +++ b/src/citra_qt/configure_system.cpp @@ -6,7 +6,6 @@ #include "citra_qt/ui_settings.h" #include "core/hle/service/cfg/cfg.h" #include "core/hle/service/fs/archive.h" -#include "core/system.h" #include "ui_configure_system.h" static const std::array<int, 12> days_in_month = {{ @@ -24,7 +23,7 @@ ConfigureSystem::ConfigureSystem(QWidget* parent) : QWidget(parent), ui(new Ui:: ConfigureSystem::~ConfigureSystem() {} void ConfigureSystem::setConfiguration() { - enabled = !System::IsPoweredOn(); + enabled = !Core::System::GetInstance().IsPoweredOn(); if (!enabled) { ReadSystemSettings(); diff --git a/src/citra_qt/debugger/callstack.cpp b/src/citra_qt/debugger/callstack.cpp index c66f2b96a..c1db93583 100644 --- a/src/citra_qt/debugger/callstack.cpp +++ b/src/citra_qt/debugger/callstack.cpp @@ -25,7 +25,7 @@ CallstackWidget::CallstackWidget(QWidget* parent) : QDockWidget(parent) { void CallstackWidget::OnDebugModeEntered() { // Stack pointer - const u32 sp = Core::g_app_core->GetReg(13); + const u32 sp = Core::CPU().GetReg(13); Clear(); diff --git a/src/citra_qt/debugger/callstack.h b/src/citra_qt/debugger/callstack.h index 765757986..f04ab9c7e 100644 --- a/src/citra_qt/debugger/callstack.h +++ b/src/citra_qt/debugger/callstack.h @@ -2,6 +2,8 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#pragma once + #include <QDockWidget> #include "ui_callstack.h" @@ -11,7 +13,7 @@ class CallstackWidget : public QDockWidget { Q_OBJECT public: - CallstackWidget(QWidget* parent = nullptr); + explicit CallstackWidget(QWidget* parent = nullptr); public slots: void OnDebugModeEntered(); diff --git a/src/citra_qt/debugger/disassembler.cpp b/src/citra_qt/debugger/disassembler.cpp index 1ee6bbd6a..e9c8ad858 100644 --- a/src/citra_qt/debugger/disassembler.cpp +++ b/src/citra_qt/debugger/disassembler.cpp @@ -185,13 +185,13 @@ DisassemblerWidget::DisassemblerWidget(QWidget* parent, EmuThread* emu_thread) } void DisassemblerWidget::Init() { - model->ParseFromAddress(Core::g_app_core->GetPC()); + model->ParseFromAddress(Core::CPU().GetPC()); disasm_ui.treeView->resizeColumnToContents(0); disasm_ui.treeView->resizeColumnToContents(1); disasm_ui.treeView->resizeColumnToContents(2); - QModelIndex model_index = model->IndexFromAbsoluteAddress(Core::g_app_core->GetPC()); + QModelIndex model_index = model->IndexFromAbsoluteAddress(Core::CPU().GetPC()); disasm_ui.treeView->scrollTo(model_index); disasm_ui.treeView->selectionModel()->setCurrentIndex( model_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); @@ -214,8 +214,8 @@ void DisassemblerWidget::OnPause() { emu_thread->SetRunning(false); // TODO: By now, the CPU might not have actually stopped... - if (Core::g_app_core) { - model->SetNextInstruction(Core::g_app_core->GetPC()); + if (Core::System::GetInstance().IsPoweredOn()) { + model->SetNextInstruction(Core::CPU().GetPC()); } } @@ -224,7 +224,7 @@ void DisassemblerWidget::OnToggleStartStop() { } void DisassemblerWidget::OnDebugModeEntered() { - u32 next_instr = Core::g_app_core->GetPC(); + u32 next_instr = Core::CPU().GetPC(); if (model->GetBreakPoints().IsAddressBreakPoint(next_instr)) emu_thread->SetRunning(false); diff --git a/src/citra_qt/debugger/disassembler.h b/src/citra_qt/debugger/disassembler.h index 2ca6c2bd4..a6e59515c 100644 --- a/src/citra_qt/debugger/disassembler.h +++ b/src/citra_qt/debugger/disassembler.h @@ -17,7 +17,7 @@ class DisassemblerModel : public QAbstractListModel { Q_OBJECT public: - DisassemblerModel(QObject* parent); + explicit DisassemblerModel(QObject* parent); int columnCount(const QModelIndex& parent = QModelIndex()) const override; int rowCount(const QModelIndex& parent = QModelIndex()) const override; @@ -38,9 +38,7 @@ private: unsigned int program_counter; QModelIndex selection; - - // TODO: Make BreakPoints less crappy (i.e. const-correct) so that this needn't be mutable. - mutable BreakPoints breakpoints; + BreakPoints breakpoints; }; class DisassemblerWidget : public QDockWidget { diff --git a/src/citra_qt/debugger/graphics.cpp b/src/citra_qt/debugger/graphics/graphics.cpp index ef6712bfa..6a76adeae 100644 --- a/src/citra_qt/debugger/graphics.cpp +++ b/src/citra_qt/debugger/graphics/graphics.cpp @@ -3,7 +3,7 @@ // Refer to the license.txt file included. #include <QListView> -#include "citra_qt/debugger/graphics.h" +#include "citra_qt/debugger/graphics/graphics.h" #include "citra_qt/util/util.h" extern GraphicsDebugger g_debugger; @@ -22,15 +22,15 @@ QVariant GPUCommandStreamItemModel::data(const QModelIndex& index, int role) con return QVariant(); int command_index = index.row(); - const GSP_GPU::Command& command = GetDebugger()->ReadGXCommandHistory(command_index); + const Service::GSP::Command& command = GetDebugger()->ReadGXCommandHistory(command_index); if (role == Qt::DisplayRole) { - std::map<GSP_GPU::CommandId, const char*> command_names = { - {GSP_GPU::CommandId::REQUEST_DMA, "REQUEST_DMA"}, - {GSP_GPU::CommandId::SUBMIT_GPU_CMDLIST, "SUBMIT_GPU_CMDLIST"}, - {GSP_GPU::CommandId::SET_MEMORY_FILL, "SET_MEMORY_FILL"}, - {GSP_GPU::CommandId::SET_DISPLAY_TRANSFER, "SET_DISPLAY_TRANSFER"}, - {GSP_GPU::CommandId::SET_TEXTURE_COPY, "SET_TEXTURE_COPY"}, - {GSP_GPU::CommandId::CACHE_FLUSH, "CACHE_FLUSH"}, + std::map<Service::GSP::CommandId, const char*> command_names = { + {Service::GSP::CommandId::REQUEST_DMA, "REQUEST_DMA"}, + {Service::GSP::CommandId::SUBMIT_GPU_CMDLIST, "SUBMIT_GPU_CMDLIST"}, + {Service::GSP::CommandId::SET_MEMORY_FILL, "SET_MEMORY_FILL"}, + {Service::GSP::CommandId::SET_DISPLAY_TRANSFER, "SET_DISPLAY_TRANSFER"}, + {Service::GSP::CommandId::SET_TEXTURE_COPY, "SET_TEXTURE_COPY"}, + {Service::GSP::CommandId::CACHE_FLUSH, "CACHE_FLUSH"}, }; const u32* command_data = reinterpret_cast<const u32*>(&command); QString str = QString("%1 %2 %3 %4 %5 %6 %7 %8 %9") diff --git a/src/citra_qt/debugger/graphics.h b/src/citra_qt/debugger/graphics/graphics.h index bedf3e596..8837fb792 100644 --- a/src/citra_qt/debugger/graphics.h +++ b/src/citra_qt/debugger/graphics/graphics.h @@ -13,7 +13,7 @@ class GPUCommandStreamItemModel : public QAbstractListModel, Q_OBJECT public: - GPUCommandStreamItemModel(QObject* parent); + explicit GPUCommandStreamItemModel(QObject* parent); int rowCount(const QModelIndex& parent = QModelIndex()) const override; QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; diff --git a/src/citra_qt/debugger/graphics_breakpoint_observer.cpp b/src/citra_qt/debugger/graphics/graphics_breakpoint_observer.cpp index e01d3440e..dc6070dea 100644 --- a/src/citra_qt/debugger/graphics_breakpoint_observer.cpp +++ b/src/citra_qt/debugger/graphics/graphics_breakpoint_observer.cpp @@ -3,7 +3,7 @@ // Refer to the license.txt file included. #include <QMetaType> -#include "citra_qt/debugger/graphics_breakpoint_observer.h" +#include "citra_qt/debugger/graphics/graphics_breakpoint_observer.h" BreakPointObserverDock::BreakPointObserverDock(std::shared_ptr<Pica::DebugContext> debug_context, const QString& title, QWidget* parent) diff --git a/src/citra_qt/debugger/graphics_breakpoint_observer.h b/src/citra_qt/debugger/graphics/graphics_breakpoint_observer.h index e77df4f5b..e77df4f5b 100644 --- a/src/citra_qt/debugger/graphics_breakpoint_observer.h +++ b/src/citra_qt/debugger/graphics/graphics_breakpoint_observer.h diff --git a/src/citra_qt/debugger/graphics_breakpoints.cpp b/src/citra_qt/debugger/graphics/graphics_breakpoints.cpp index d2a036dfa..030828ba8 100644 --- a/src/citra_qt/debugger/graphics_breakpoints.cpp +++ b/src/citra_qt/debugger/graphics/graphics_breakpoints.cpp @@ -7,8 +7,8 @@ #include <QPushButton> #include <QTreeView> #include <QVBoxLayout> -#include "citra_qt/debugger/graphics_breakpoints.h" -#include "citra_qt/debugger/graphics_breakpoints_p.h" +#include "citra_qt/debugger/graphics/graphics_breakpoints.h" +#include "citra_qt/debugger/graphics/graphics_breakpoints_p.h" #include "common/assert.h" BreakPointModel::BreakPointModel(std::shared_ptr<Pica::DebugContext> debug_context, QObject* parent) diff --git a/src/citra_qt/debugger/graphics_breakpoints.h b/src/citra_qt/debugger/graphics/graphics_breakpoints.h index 5fc40c916..bec72a2db 100644 --- a/src/citra_qt/debugger/graphics_breakpoints.h +++ b/src/citra_qt/debugger/graphics/graphics_breakpoints.h @@ -20,8 +20,8 @@ class GraphicsBreakPointsWidget : public QDockWidget, Pica::DebugContext::BreakP using Event = Pica::DebugContext::Event; public: - GraphicsBreakPointsWidget(std::shared_ptr<Pica::DebugContext> debug_context, - QWidget* parent = nullptr); + explicit GraphicsBreakPointsWidget(std::shared_ptr<Pica::DebugContext> debug_context, + QWidget* parent = nullptr); void OnPicaBreakPointHit(Pica::DebugContext::Event event, void* data) override; void OnPicaResume() override; diff --git a/src/citra_qt/debugger/graphics_breakpoints_p.h b/src/citra_qt/debugger/graphics/graphics_breakpoints_p.h index dc64706bd..dc64706bd 100644 --- a/src/citra_qt/debugger/graphics_breakpoints_p.h +++ b/src/citra_qt/debugger/graphics/graphics_breakpoints_p.h diff --git a/src/citra_qt/debugger/graphics_cmdlists.cpp b/src/citra_qt/debugger/graphics/graphics_cmdlists.cpp index 8a784d108..dab529e3a 100644 --- a/src/citra_qt/debugger/graphics_cmdlists.cpp +++ b/src/citra_qt/debugger/graphics/graphics_cmdlists.cpp @@ -13,7 +13,7 @@ #include <QSpinBox> #include <QTreeView> #include <QVBoxLayout> -#include "citra_qt/debugger/graphics_cmdlists.h" +#include "citra_qt/debugger/graphics/graphics_cmdlists.h" #include "citra_qt/util/spinbox.h" #include "citra_qt/util/util.h" #include "common/vector_math.h" @@ -21,7 +21,8 @@ #include "video_core/pica.h" #include "video_core/pica_state.h" -QImage LoadTexture(u8* src, const Pica::DebugUtils::TextureInfo& info) { +namespace { +QImage LoadTexture(const u8* src, const Pica::DebugUtils::TextureInfo& info) { QImage decoded_image(info.width, info.height, QImage::Format_ARGB32); for (int y = 0; y < info.height; ++y) { for (int x = 0; x < info.width; ++x) { @@ -35,7 +36,8 @@ QImage LoadTexture(u8* src, const Pica::DebugUtils::TextureInfo& info) { class TextureInfoWidget : public QWidget { public: - TextureInfoWidget(u8* src, const Pica::DebugUtils::TextureInfo& info, QWidget* parent = nullptr) + TextureInfoWidget(const u8* src, const Pica::DebugUtils::TextureInfo& info, + QWidget* parent = nullptr) : QWidget(parent) { QLabel* image_widget = new QLabel; QPixmap image_pixmap = QPixmap::fromImage(LoadTexture(src, info)); @@ -47,6 +49,7 @@ public: setLayout(layout); } }; +} // Anonymous namespace GPUCommandListModel::GPUCommandListModel(QObject* parent) : QAbstractListModel(parent) {} @@ -65,7 +68,6 @@ QVariant GPUCommandListModel::data(const QModelIndex& index, int role) const { const auto& write = pica_trace.writes[index.row()]; if (role == Qt::DisplayRole) { - QString content; switch (index.column()) { case 0: return QString::fromLatin1(Pica::Regs::GetCommandName(write.cmd_id).c_str()); @@ -122,19 +124,21 @@ void GPUCommandListWidget::OnCommandDoubleClicked(const QModelIndex& index) { if (COMMAND_IN_RANGE(command_id, texture0) || COMMAND_IN_RANGE(command_id, texture1) || COMMAND_IN_RANGE(command_id, texture2)) { - unsigned index; + unsigned texture_index; if (COMMAND_IN_RANGE(command_id, texture0)) { - index = 0; + texture_index = 0; } else if (COMMAND_IN_RANGE(command_id, texture1)) { - index = 1; + texture_index = 1; } else if (COMMAND_IN_RANGE(command_id, texture2)) { - index = 2; + texture_index = 2; } else { UNREACHABLE_MSG("Unknown texture command"); } - auto config = Pica::g_state.regs.GetTextures()[index].config; - auto format = Pica::g_state.regs.GetTextures()[index].format; - auto info = Pica::DebugUtils::TextureInfo::FromPicaRegister(config, format); + + const auto texture = Pica::g_state.regs.GetTextures()[texture_index]; + const auto config = texture.config; + const auto format = texture.format; + const auto info = Pica::DebugUtils::TextureInfo::FromPicaRegister(config, format); // TODO: Open a surface debugger } @@ -148,19 +152,21 @@ void GPUCommandListWidget::SetCommandInfo(const QModelIndex& index) { if (COMMAND_IN_RANGE(command_id, texture0) || COMMAND_IN_RANGE(command_id, texture1) || COMMAND_IN_RANGE(command_id, texture2)) { - unsigned index; + unsigned texture_index; if (COMMAND_IN_RANGE(command_id, texture0)) { - index = 0; + texture_index = 0; } else if (COMMAND_IN_RANGE(command_id, texture1)) { - index = 1; + texture_index = 1; } else { - index = 2; + texture_index = 2; } - auto config = Pica::g_state.regs.GetTextures()[index].config; - auto format = Pica::g_state.regs.GetTextures()[index].format; - auto info = Pica::DebugUtils::TextureInfo::FromPicaRegister(config, format); - u8* src = Memory::GetPhysicalPointer(config.GetPhysicalAddress()); + const auto texture = Pica::g_state.regs.GetTextures()[texture_index]; + const auto config = texture.config; + const auto format = texture.format; + + const auto info = Pica::DebugUtils::TextureInfo::FromPicaRegister(config, format); + const u8* src = Memory::GetPhysicalPointer(config.GetPhysicalAddress()); new_info_widget = new TextureInfoWidget(src, info); } if (command_info_widget) { diff --git a/src/citra_qt/debugger/graphics_cmdlists.h b/src/citra_qt/debugger/graphics/graphics_cmdlists.h index fa2b9122b..8f40b94c5 100644 --- a/src/citra_qt/debugger/graphics_cmdlists.h +++ b/src/citra_qt/debugger/graphics/graphics_cmdlists.h @@ -20,7 +20,7 @@ public: CommandIdRole = Qt::UserRole, }; - GPUCommandListModel(QObject* parent); + explicit GPUCommandListModel(QObject* parent); int columnCount(const QModelIndex& parent = QModelIndex()) const override; int rowCount(const QModelIndex& parent = QModelIndex()) const override; @@ -39,7 +39,7 @@ class GPUCommandListWidget : public QDockWidget { Q_OBJECT public: - GPUCommandListWidget(QWidget* parent = nullptr); + explicit GPUCommandListWidget(QWidget* parent = nullptr); public slots: void OnToggleTracing(); diff --git a/src/citra_qt/debugger/graphics_surface.cpp b/src/citra_qt/debugger/graphics/graphics_surface.cpp index 906daaa50..4efd95d3c 100644 --- a/src/citra_qt/debugger/graphics_surface.cpp +++ b/src/citra_qt/debugger/graphics/graphics_surface.cpp @@ -11,7 +11,7 @@ #include <QPushButton> #include <QScrollArea> #include <QSpinBox> -#include "citra_qt/debugger/graphics_surface.h" +#include "citra_qt/debugger/graphics/graphics_surface.h" #include "citra_qt/util/spinbox.h" #include "common/color.h" #include "core/hw/gpu.h" diff --git a/src/citra_qt/debugger/graphics_surface.h b/src/citra_qt/debugger/graphics/graphics_surface.h index 21e6b5b8b..28f5650a7 100644 --- a/src/citra_qt/debugger/graphics_surface.h +++ b/src/citra_qt/debugger/graphics/graphics_surface.h @@ -6,7 +6,7 @@ #include <QLabel> #include <QPushButton> -#include "citra_qt/debugger/graphics_breakpoint_observer.h" +#include "citra_qt/debugger/graphics/graphics_breakpoint_observer.h" class QComboBox; class QSpinBox; @@ -18,7 +18,8 @@ class SurfacePicture : public QLabel { Q_OBJECT public: - SurfacePicture(QWidget* parent = 0, GraphicsSurfaceWidget* surface_widget = nullptr); + explicit SurfacePicture(QWidget* parent = nullptr, + GraphicsSurfaceWidget* surface_widget = nullptr); ~SurfacePicture(); protected slots: @@ -71,8 +72,8 @@ class GraphicsSurfaceWidget : public BreakPointObserverDock { static unsigned int NibblesPerPixel(Format format); public: - GraphicsSurfaceWidget(std::shared_ptr<Pica::DebugContext> debug_context, - QWidget* parent = nullptr); + explicit GraphicsSurfaceWidget(std::shared_ptr<Pica::DebugContext> debug_context, + QWidget* parent = nullptr); void Pick(int x, int y); public slots: diff --git a/src/citra_qt/debugger/graphics_tracing.cpp b/src/citra_qt/debugger/graphics/graphics_tracing.cpp index 5c6b74034..716ed50b8 100644 --- a/src/citra_qt/debugger/graphics_tracing.cpp +++ b/src/citra_qt/debugger/graphics/graphics_tracing.cpp @@ -12,7 +12,7 @@ #include <QMessageBox> #include <QPushButton> #include <boost/range/algorithm/copy.hpp> -#include "citra_qt/debugger/graphics_tracing.h" +#include "citra_qt/debugger/graphics/graphics_tracing.h" #include "common/common_types.h" #include "core/hw/gpu.h" #include "core/hw/lcd.h" diff --git a/src/citra_qt/debugger/graphics_tracing.h b/src/citra_qt/debugger/graphics/graphics_tracing.h index e04a3dac3..3f73bcd2e 100644 --- a/src/citra_qt/debugger/graphics_tracing.h +++ b/src/citra_qt/debugger/graphics/graphics_tracing.h @@ -4,7 +4,7 @@ #pragma once -#include "citra_qt/debugger/graphics_breakpoint_observer.h" +#include "citra_qt/debugger/graphics/graphics_breakpoint_observer.h" class EmuThread; @@ -12,8 +12,8 @@ class GraphicsTracingWidget : public BreakPointObserverDock { Q_OBJECT public: - GraphicsTracingWidget(std::shared_ptr<Pica::DebugContext> debug_context, - QWidget* parent = nullptr); + explicit GraphicsTracingWidget(std::shared_ptr<Pica::DebugContext> debug_context, + QWidget* parent = nullptr); private slots: void StartRecording(); diff --git a/src/citra_qt/debugger/graphics_vertex_shader.cpp b/src/citra_qt/debugger/graphics/graphics_vertex_shader.cpp index 96b40db1e..b75b94ef8 100644 --- a/src/citra_qt/debugger/graphics_vertex_shader.cpp +++ b/src/citra_qt/debugger/graphics/graphics_vertex_shader.cpp @@ -14,7 +14,7 @@ #include <QSignalMapper> #include <QSpinBox> #include <QTreeView> -#include "citra_qt/debugger/graphics_vertex_shader.h" +#include "citra_qt/debugger/graphics/graphics_vertex_shader.h" #include "citra_qt/util/util.h" #include "video_core/pica.h" #include "video_core/pica_state.h" diff --git a/src/citra_qt/debugger/graphics_vertex_shader.h b/src/citra_qt/debugger/graphics/graphics_vertex_shader.h index ec42f24bb..bedea0bed 100644 --- a/src/citra_qt/debugger/graphics_vertex_shader.h +++ b/src/citra_qt/debugger/graphics/graphics_vertex_shader.h @@ -6,7 +6,7 @@ #include <QAbstractTableModel> #include <QTreeView> -#include "citra_qt/debugger/graphics_breakpoint_observer.h" +#include "citra_qt/debugger/graphics/graphics_breakpoint_observer.h" #include "nihstro/parser_shbin.h" #include "video_core/shader/shader.h" @@ -19,7 +19,7 @@ class GraphicsVertexShaderModel : public QAbstractTableModel { Q_OBJECT public: - GraphicsVertexShaderModel(GraphicsVertexShaderWidget* parent); + explicit GraphicsVertexShaderModel(GraphicsVertexShaderWidget* parent); int columnCount(const QModelIndex& parent = QModelIndex()) const override; int rowCount(const QModelIndex& parent = QModelIndex()) const override; diff --git a/src/citra_qt/debugger/profiler.h b/src/citra_qt/debugger/profiler.h index d8c6487aa..c8912fd5a 100644 --- a/src/citra_qt/debugger/profiler.h +++ b/src/citra_qt/debugger/profiler.h @@ -15,7 +15,7 @@ class ProfilerModel : public QAbstractItemModel { Q_OBJECT public: - ProfilerModel(QObject* parent); + explicit ProfilerModel(QObject* parent); QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; @@ -37,7 +37,7 @@ class ProfilerWidget : public QDockWidget { Q_OBJECT public: - ProfilerWidget(QWidget* parent = nullptr); + explicit ProfilerWidget(QWidget* parent = nullptr); private slots: void setProfilingInfoUpdateEnabled(bool enable); @@ -53,7 +53,7 @@ class MicroProfileDialog : public QWidget { Q_OBJECT public: - MicroProfileDialog(QWidget* parent = nullptr); + explicit MicroProfileDialog(QWidget* parent = nullptr); /// Returns a QAction that can be used to toggle visibility of this dialog. QAction* toggleViewAction(); diff --git a/src/citra_qt/debugger/ramview.h b/src/citra_qt/debugger/ramview.h index 8043c59e8..d01cea93b 100644 --- a/src/citra_qt/debugger/ramview.h +++ b/src/citra_qt/debugger/ramview.h @@ -2,13 +2,15 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#pragma once + #include "qhexedit.h" class GRamView : public QHexEdit { Q_OBJECT public: - GRamView(QWidget* parent = nullptr); + explicit GRamView(QWidget* parent = nullptr); public slots: void OnCPUStepped(); diff --git a/src/citra_qt/debugger/registers.cpp b/src/citra_qt/debugger/registers.cpp index 4c529d3c3..b982bc58b 100644 --- a/src/citra_qt/debugger/registers.cpp +++ b/src/citra_qt/debugger/registers.cpp @@ -58,16 +58,16 @@ RegistersWidget::RegistersWidget(QWidget* parent) : QDockWidget(parent) { } void RegistersWidget::OnDebugModeEntered() { - if (!Core::g_app_core) + if (!Core::System::GetInstance().IsPoweredOn()) return; for (int i = 0; i < core_registers->childCount(); ++i) core_registers->child(i)->setText( - 1, QString("0x%1").arg(Core::g_app_core->GetReg(i), 8, 16, QLatin1Char('0'))); + 1, QString("0x%1").arg(Core::CPU().GetReg(i), 8, 16, QLatin1Char('0'))); for (int i = 0; i < vfp_registers->childCount(); ++i) vfp_registers->child(i)->setText( - 1, QString("0x%1").arg(Core::g_app_core->GetVFPReg(i), 8, 16, QLatin1Char('0'))); + 1, QString("0x%1").arg(Core::CPU().GetVFPReg(i), 8, 16, QLatin1Char('0'))); UpdateCPSRValues(); UpdateVFPSystemRegisterValues(); @@ -127,7 +127,7 @@ void RegistersWidget::CreateCPSRChildren() { } void RegistersWidget::UpdateCPSRValues() { - const u32 cpsr_val = Core::g_app_core->GetCPSR(); + const u32 cpsr_val = Core::CPU().GetCPSR(); cpsr->setText(1, QString("0x%1").arg(cpsr_val, 8, 16, QLatin1Char('0'))); cpsr->child(0)->setText( @@ -191,10 +191,10 @@ void RegistersWidget::CreateVFPSystemRegisterChildren() { } void RegistersWidget::UpdateVFPSystemRegisterValues() { - const u32 fpscr_val = Core::g_app_core->GetVFPSystemReg(VFP_FPSCR); - const u32 fpexc_val = Core::g_app_core->GetVFPSystemReg(VFP_FPEXC); - const u32 fpinst_val = Core::g_app_core->GetVFPSystemReg(VFP_FPINST); - const u32 fpinst2_val = Core::g_app_core->GetVFPSystemReg(VFP_FPINST2); + const u32 fpscr_val = Core::CPU().GetVFPSystemReg(VFP_FPSCR); + const u32 fpexc_val = Core::CPU().GetVFPSystemReg(VFP_FPEXC); + const u32 fpinst_val = Core::CPU().GetVFPSystemReg(VFP_FPINST); + const u32 fpinst2_val = Core::CPU().GetVFPSystemReg(VFP_FPINST2); QTreeWidgetItem* const fpscr = vfp_system_registers->child(0); fpscr->setText(1, QString("0x%1").arg(fpscr_val, 8, 16, QLatin1Char('0'))); diff --git a/src/citra_qt/debugger/registers.h b/src/citra_qt/debugger/registers.h index 54c9a8155..55bda5b59 100644 --- a/src/citra_qt/debugger/registers.h +++ b/src/citra_qt/debugger/registers.h @@ -2,6 +2,8 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#pragma once + #include <QDockWidget> #include "ui_registers.h" @@ -13,7 +15,7 @@ class RegistersWidget : public QDockWidget { Q_OBJECT public: - RegistersWidget(QWidget* parent = nullptr); + explicit RegistersWidget(QWidget* parent = nullptr); public slots: void OnDebugModeEntered(); diff --git a/src/citra_qt/debugger/wait_tree.cpp b/src/citra_qt/debugger/wait_tree.cpp index be5a51e52..1d2de5185 100644 --- a/src/citra_qt/debugger/wait_tree.cpp +++ b/src/citra_qt/debugger/wait_tree.cpp @@ -8,7 +8,6 @@ #include "core/hle/kernel/event.h" #include "core/hle/kernel/mutex.h" #include "core/hle/kernel/semaphore.h" -#include "core/hle/kernel/session.h" #include "core/hle/kernel/thread.h" #include "core/hle/kernel/timer.h" @@ -230,7 +229,8 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const { list.push_back(std::make_unique<WaitTreeMutexList>(thread.held_mutexes)); } if (thread.status == THREADSTATUS_WAIT_SYNCH) { - list.push_back(std::make_unique<WaitTreeObjectList>(thread.wait_objects, thread.wait_all)); + list.push_back(std::make_unique<WaitTreeObjectList>(thread.wait_objects, + thread.IsSleepingOnWaitAll())); } return list; @@ -391,7 +391,7 @@ WaitTreeWidget::WaitTreeWidget(QWidget* parent) : QDockWidget(tr("Wait Tree"), p } void WaitTreeWidget::OnDebugModeEntered() { - if (!Core::g_app_core) + if (!Core::System::GetInstance().IsPoweredOn()) return; model->InitItems(); view->setModel(model); diff --git a/src/citra_qt/debugger/wait_tree.h b/src/citra_qt/debugger/wait_tree.h index 5d1d964d1..ee9708fc1 100644 --- a/src/citra_qt/debugger/wait_tree.h +++ b/src/citra_qt/debugger/wait_tree.h @@ -2,6 +2,8 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#pragma once + #include <boost/container/flat_set.hpp> #include <QAbstractItemModel> @@ -49,7 +51,7 @@ private: class WaitTreeText : public WaitTreeItem { Q_OBJECT public: - WaitTreeText(const QString& text); + explicit WaitTreeText(const QString& text); QString GetText() const override; private: @@ -65,7 +67,7 @@ public: class WaitTreeWaitObject : public WaitTreeExpandableItem { Q_OBJECT public: - WaitTreeWaitObject(const Kernel::WaitObject& object); + explicit WaitTreeWaitObject(const Kernel::WaitObject& object); static std::unique_ptr<WaitTreeWaitObject> make(const Kernel::WaitObject& object); QString GetText() const override; std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override; @@ -92,7 +94,7 @@ private: class WaitTreeThread : public WaitTreeWaitObject { Q_OBJECT public: - WaitTreeThread(const Kernel::Thread& thread); + explicit WaitTreeThread(const Kernel::Thread& thread); QString GetText() const override; QColor GetColor() const override; std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override; @@ -101,35 +103,37 @@ public: class WaitTreeEvent : public WaitTreeWaitObject { Q_OBJECT public: - WaitTreeEvent(const Kernel::Event& object); + explicit WaitTreeEvent(const Kernel::Event& object); std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override; }; class WaitTreeMutex : public WaitTreeWaitObject { Q_OBJECT public: - WaitTreeMutex(const Kernel::Mutex& object); + explicit WaitTreeMutex(const Kernel::Mutex& object); std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override; }; class WaitTreeSemaphore : public WaitTreeWaitObject { Q_OBJECT public: - WaitTreeSemaphore(const Kernel::Semaphore& object); + explicit WaitTreeSemaphore(const Kernel::Semaphore& object); std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override; }; class WaitTreeTimer : public WaitTreeWaitObject { Q_OBJECT public: - WaitTreeTimer(const Kernel::Timer& object); + explicit WaitTreeTimer(const Kernel::Timer& object); std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override; }; class WaitTreeMutexList : public WaitTreeExpandableItem { Q_OBJECT public: - WaitTreeMutexList(const boost::container::flat_set<Kernel::SharedPtr<Kernel::Mutex>>& list); + explicit WaitTreeMutexList( + const boost::container::flat_set<Kernel::SharedPtr<Kernel::Mutex>>& list); + QString GetText() const override; std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override; @@ -140,7 +144,7 @@ private: class WaitTreeThreadList : public WaitTreeExpandableItem { Q_OBJECT public: - WaitTreeThreadList(const std::vector<Kernel::SharedPtr<Kernel::Thread>>& list); + explicit WaitTreeThreadList(const std::vector<Kernel::SharedPtr<Kernel::Thread>>& list); QString GetText() const override; std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override; @@ -152,7 +156,7 @@ class WaitTreeModel : public QAbstractItemModel { Q_OBJECT public: - WaitTreeModel(QObject* parent = nullptr); + explicit WaitTreeModel(QObject* parent = nullptr); QVariant data(const QModelIndex& index, int role) const override; QModelIndex index(int row, int column, const QModelIndex& parent) const override; @@ -171,7 +175,7 @@ class WaitTreeWidget : public QDockWidget { Q_OBJECT public: - WaitTreeWidget(QWidget* parent = nullptr); + explicit WaitTreeWidget(QWidget* parent = nullptr); public slots: void OnDebugModeEntered(); diff --git a/src/citra_qt/game_list.cpp b/src/citra_qt/game_list.cpp index 07bc35308..09469f3c5 100644 --- a/src/citra_qt/game_list.cpp +++ b/src/citra_qt/game_list.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include <QHeaderView> +#include <QMenu> #include <QThreadPool> #include <QVBoxLayout> #include "common/common_paths.h" @@ -13,7 +14,7 @@ #include "game_list_p.h" #include "ui_settings.h" -GameList::GameList(QWidget* parent) { +GameList::GameList(QWidget* parent) : QWidget{parent} { QVBoxLayout* layout = new QVBoxLayout; tree_view = new QTreeView; @@ -28,18 +29,18 @@ GameList::GameList(QWidget* parent) { tree_view->setSortingEnabled(true); tree_view->setEditTriggers(QHeaderView::NoEditTriggers); tree_view->setUniformRowHeights(true); + tree_view->setContextMenuPolicy(Qt::CustomContextMenu); item_model->insertColumns(0, COLUMN_COUNT); item_model->setHeaderData(COLUMN_NAME, Qt::Horizontal, "Name"); item_model->setHeaderData(COLUMN_FILE_TYPE, Qt::Horizontal, "File type"); item_model->setHeaderData(COLUMN_SIZE, Qt::Horizontal, "Size"); - connect(tree_view, SIGNAL(activated(const QModelIndex&)), this, - SLOT(ValidateEntry(const QModelIndex&))); + connect(tree_view, &QTreeView::activated, this, &GameList::ValidateEntry); + connect(tree_view, &QTreeView::customContextMenuRequested, this, &GameList::PopupContextMenu); // We must register all custom types with the Qt Automoc system so that we are able to use it - // with - // signals/slots. In this case, QList falls under the umbrells of custom types. + // with signals/slots. In this case, QList falls under the umbrells of custom types. qRegisterMetaType<QList<QStandardItem*>>("QList<QStandardItem*>"); layout->addWidget(tree_view); @@ -50,7 +51,7 @@ GameList::~GameList() { emit ShouldCancelWorker(); } -void GameList::AddEntry(QList<QStandardItem*> entry_items) { +void GameList::AddEntry(const QList<QStandardItem*>& entry_items) { item_model->invisibleRootItem()->appendRow(entry_items); } @@ -72,6 +73,23 @@ void GameList::DonePopulating() { tree_view->setEnabled(true); } +void GameList::PopupContextMenu(const QPoint& menu_location) { + QModelIndex item = tree_view->indexAt(menu_location); + if (!item.isValid()) + return; + + int row = item_model->itemFromIndex(item)->row(); + QStandardItem* child_file = item_model->invisibleRootItem()->child(row, COLUMN_NAME); + u64 program_id = child_file->data(GameListItemPath::ProgramIdRole).toULongLong(); + + QMenu context_menu; + QAction* open_save_location = context_menu.addAction(tr("Open Save Data Location")); + open_save_location->setEnabled(program_id != 0); + connect(open_save_location, &QAction::triggered, + [&]() { emit OpenSaveFolderRequested(program_id); }); + context_menu.exec(tree_view->viewport()->mapToGlobal(menu_location)); +} + void GameList::PopulateAsync(const QString& dir_path, bool deep_scan) { if (!FileUtil::Exists(dir_path.toStdString()) || !FileUtil::IsDirectory(dir_path.toStdString())) { @@ -86,12 +104,13 @@ void GameList::PopulateAsync(const QString& dir_path, bool deep_scan) { emit ShouldCancelWorker(); GameListWorker* worker = new GameListWorker(dir_path, deep_scan); - connect(worker, SIGNAL(EntryReady(QList<QStandardItem*>)), this, - SLOT(AddEntry(QList<QStandardItem*>)), Qt::QueuedConnection); - connect(worker, SIGNAL(Finished()), this, SLOT(DonePopulating()), Qt::QueuedConnection); + connect(worker, &GameListWorker::EntryReady, this, &GameList::AddEntry, Qt::QueuedConnection); + connect(worker, &GameListWorker::Finished, this, &GameList::DonePopulating, + Qt::QueuedConnection); // Use DirectConnection here because worker->Cancel() is thread-safe and we want it to cancel // without delay. - connect(this, SIGNAL(ShouldCancelWorker()), worker, SLOT(Cancel()), Qt::DirectConnection); + connect(this, &GameList::ShouldCancelWorker, worker, &GameListWorker::Cancel, + Qt::DirectConnection); QThreadPool::globalInstance()->start(worker); current_worker = std::move(worker); @@ -128,8 +147,11 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsign std::vector<u8> smdh; loader->ReadIcon(smdh); + u64 program_id = 0; + loader->ReadProgramId(program_id); + emit EntryReady({ - new GameListItemPath(QString::fromStdString(physical_name), smdh), + new GameListItemPath(QString::fromStdString(physical_name), smdh, program_id), new GameListItem( QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType()))), new GameListItemSize(FileUtil::GetSize(physical_name)), @@ -151,6 +173,6 @@ void GameListWorker::run() { } void GameListWorker::Cancel() { - disconnect(this, 0, 0, 0); + disconnect(this, nullptr, nullptr, nullptr); stop_processing = true; } diff --git a/src/citra_qt/game_list.h b/src/citra_qt/game_list.h index a22e9bc60..1abf10051 100644 --- a/src/citra_qt/game_list.h +++ b/src/citra_qt/game_list.h @@ -25,7 +25,7 @@ public: COLUMN_COUNT, // Number of columns }; - GameList(QWidget* parent = nullptr); + explicit GameList(QWidget* parent = nullptr); ~GameList() override; void PopulateAsync(const QString& dir_path, bool deep_scan); @@ -33,18 +33,18 @@ public: void SaveInterfaceLayout(); void LoadInterfaceLayout(); -public slots: - void AddEntry(QList<QStandardItem*> entry_items); - -private slots: - void ValidateEntry(const QModelIndex& item); - void DonePopulating(); - signals: void GameChosen(QString game_path); void ShouldCancelWorker(); + void OpenSaveFolderRequested(u64 program_id); private: + void AddEntry(const QList<QStandardItem*>& entry_items); + void ValidateEntry(const QModelIndex& item); + void DonePopulating(); + + void PopupContextMenu(const QPoint& menu_location); + QTreeView* tree_view = nullptr; QStandardItemModel* item_model = nullptr; GameListWorker* current_worker = nullptr; diff --git a/src/citra_qt/game_list_p.h b/src/citra_qt/game_list_p.h index 5ca3fe991..a15f06c5f 100644 --- a/src/citra_qt/game_list_p.h +++ b/src/citra_qt/game_list_p.h @@ -71,10 +71,13 @@ class GameListItemPath : public GameListItem { public: static const int FullPathRole = Qt::UserRole + 1; static const int TitleRole = Qt::UserRole + 2; + static const int ProgramIdRole = Qt::UserRole + 3; GameListItemPath() : GameListItem() {} - GameListItemPath(const QString& game_path, const std::vector<u8>& smdh_data) : GameListItem() { + GameListItemPath(const QString& game_path, const std::vector<u8>& smdh_data, u64 program_id) + : GameListItem() { setData(game_path, FullPathRole); + setData(qulonglong(program_id), ProgramIdRole); if (!Loader::IsValidSMDH(smdh_data)) { // SMDH is not valid, set a default icon diff --git a/src/citra_qt/hotkeys.h b/src/citra_qt/hotkeys.h index 350103c6f..46f48c2d8 100644 --- a/src/citra_qt/hotkeys.h +++ b/src/citra_qt/hotkeys.h @@ -55,7 +55,7 @@ class GHotkeysDialog : public QWidget { Q_OBJECT public: - GHotkeysDialog(QWidget* parent = nullptr); + explicit GHotkeysDialog(QWidget* parent = nullptr); private: Ui::hotkeys ui; diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index a3887f9ab..6d59cf640 100644 --- a/src/citra_qt/main.cpp +++ b/src/citra_qt/main.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include <cinttypes> #include <clocale> #include <memory> #include <thread> @@ -16,12 +17,12 @@ #include "citra_qt/configure_dialog.h" #include "citra_qt/debugger/callstack.h" #include "citra_qt/debugger/disassembler.h" -#include "citra_qt/debugger/graphics.h" -#include "citra_qt/debugger/graphics_breakpoints.h" -#include "citra_qt/debugger/graphics_cmdlists.h" -#include "citra_qt/debugger/graphics_surface.h" -#include "citra_qt/debugger/graphics_tracing.h" -#include "citra_qt/debugger/graphics_vertex_shader.h" +#include "citra_qt/debugger/graphics/graphics.h" +#include "citra_qt/debugger/graphics/graphics_breakpoints.h" +#include "citra_qt/debugger/graphics/graphics_cmdlists.h" +#include "citra_qt/debugger/graphics/graphics_surface.h" +#include "citra_qt/debugger/graphics/graphics_tracing.h" +#include "citra_qt/debugger/graphics/graphics_vertex_shader.h" #include "citra_qt/debugger/profiler.h" #include "citra_qt/debugger/ramview.h" #include "citra_qt/debugger/registers.h" @@ -41,10 +42,10 @@ #include "common/string_util.h" #include "core/arm/disassembler/load_symbol_map.h" #include "core/core.h" +#include "core/file_sys/archive_source_sd_savedata.h" #include "core/gdbstub/gdbstub.h" #include "core/loader/loader.h" #include "core/settings.h" -#include "core/system.h" #include "qhexedit.h" #include "video_core/video_core.h" @@ -58,6 +59,36 @@ GMainWindow::GMainWindow() : config(new Config()), emu_thread(nullptr) { ui.setupUi(this); statusBar()->hide(); + InitializeWidgets(); + InitializeDebugMenuActions(); + InitializeRecentFileMenuActions(); + InitializeHotkeys(); + + SetDefaultUIGeometry(); + RestoreUIState(); + + ConnectWidgetEvents(); + + setWindowTitle(QString("Citra | %1-%2").arg(Common::g_scm_branch, Common::g_scm_desc)); + show(); + + game_list->PopulateAsync(UISettings::values.gamedir, UISettings::values.gamedir_deepscan); + + QStringList args = QApplication::arguments(); + if (args.length() >= 2) { + BootGame(args[1].toStdString()); + } +} + +GMainWindow::~GMainWindow() { + // will get automatically deleted otherwise + if (render_window->parent() == nullptr) + delete render_window; + + Pica::g_debug_context.reset(); +} + +void GMainWindow::InitializeWidgets() { render_window = new GRenderWindow(this, emu_thread.get()); render_window->hide(); @@ -93,25 +124,27 @@ GMainWindow::GMainWindow() : config(new Config()), emu_thread(nullptr) { addDockWidget(Qt::RightDockWidgetArea, graphicsCommandsWidget); graphicsCommandsWidget->hide(); - auto graphicsBreakpointsWidget = new GraphicsBreakPointsWidget(Pica::g_debug_context, this); + graphicsBreakpointsWidget = new GraphicsBreakPointsWidget(Pica::g_debug_context, this); addDockWidget(Qt::RightDockWidgetArea, graphicsBreakpointsWidget); graphicsBreakpointsWidget->hide(); - auto graphicsVertexShaderWidget = new GraphicsVertexShaderWidget(Pica::g_debug_context, this); + graphicsVertexShaderWidget = new GraphicsVertexShaderWidget(Pica::g_debug_context, this); addDockWidget(Qt::RightDockWidgetArea, graphicsVertexShaderWidget); graphicsVertexShaderWidget->hide(); - auto graphicsTracingWidget = new GraphicsTracingWidget(Pica::g_debug_context, this); + graphicsTracingWidget = new GraphicsTracingWidget(Pica::g_debug_context, this); addDockWidget(Qt::RightDockWidgetArea, graphicsTracingWidget); graphicsTracingWidget->hide(); - auto graphicsSurfaceViewerAction = new QAction(tr("Create Pica Surface Viewer"), this); - connect(graphicsSurfaceViewerAction, SIGNAL(triggered()), this, - SLOT(OnCreateGraphicsSurfaceViewer())); - waitTreeWidget = new WaitTreeWidget(this); addDockWidget(Qt::LeftDockWidgetArea, waitTreeWidget); waitTreeWidget->hide(); +} + +void GMainWindow::InitializeDebugMenuActions() { + auto graphicsSurfaceViewerAction = new QAction(tr("Create Pica Surface Viewer"), this); + connect(graphicsSurfaceViewerAction, SIGNAL(triggered()), this, + SLOT(OnCreateGraphicsSurfaceViewer())); QMenu* debug_menu = ui.menu_View->addMenu(tr("Debugging")); debug_menu->addAction(graphicsSurfaceViewerAction); @@ -129,19 +162,47 @@ GMainWindow::GMainWindow() : config(new Config()), emu_thread(nullptr) { debug_menu->addAction(graphicsVertexShaderWidget->toggleViewAction()); debug_menu->addAction(graphicsTracingWidget->toggleViewAction()); debug_menu->addAction(waitTreeWidget->toggleViewAction()); +} - // Set default UI state +void GMainWindow::InitializeRecentFileMenuActions() { + for (int i = 0; i < max_recent_files_item; ++i) { + actions_recent_files[i] = new QAction(this); + actions_recent_files[i]->setVisible(false); + connect(actions_recent_files[i], SIGNAL(triggered()), this, SLOT(OnMenuRecentFile())); + + ui.menu_recent_files->addAction(actions_recent_files[i]); + } + + UpdateRecentFiles(); +} + +void GMainWindow::InitializeHotkeys() { + RegisterHotkey("Main Window", "Load File", QKeySequence::Open); + RegisterHotkey("Main Window", "Swap Screens", QKeySequence::NextChild); + RegisterHotkey("Main Window", "Start Emulation"); + 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())); + connect(GetHotkey("Main Window", "Swap Screens", render_window), SIGNAL(activated()), this, + SLOT(OnSwapScreens())); +} + +void GMainWindow::SetDefaultUIGeometry() { // geometry: 55% of the window contents are in the upper screen half, 45% in the lower half - QDesktopWidget* desktop = ((QApplication*)QApplication::instance())->desktop(); - QRect screenRect = desktop->screenGeometry(this); - int x, y, w, h; - w = screenRect.width() * 2 / 3; - h = screenRect.height() / 2; - x = (screenRect.x() + screenRect.width()) / 2 - w / 2; - y = (screenRect.y() + screenRect.height()) / 2 - h * 55 / 100; + const QRect screenRect = QApplication::desktop()->screenGeometry(this); + + const int w = screenRect.width() * 2 / 3; + const int h = screenRect.height() / 2; + const int x = (screenRect.x() + screenRect.width()) / 2 - w / 2; + const int y = (screenRect.y() + screenRect.height()) / 2 - h * 55 / 100; + setGeometry(x, y, w, h); +} - // Restore UI state +void GMainWindow::RestoreUIState() { restoreGeometry(UISettings::values.geometry); restoreState(UISettings::values.state); render_window->restoreGeometry(UISettings::values.renderwindow_geometry); @@ -157,20 +218,13 @@ GMainWindow::GMainWindow() : config(new Config()), emu_thread(nullptr) { ui.actionDisplay_widget_title_bars->setChecked(UISettings::values.display_titlebar); OnDisplayTitleBars(ui.actionDisplay_widget_title_bars->isChecked()); +} - // Prepare actions for recent files - for (int i = 0; i < max_recent_files_item; ++i) { - actions_recent_files[i] = new QAction(this); - actions_recent_files[i]->setVisible(false); - connect(actions_recent_files[i], SIGNAL(triggered()), this, SLOT(OnMenuRecentFile())); - - ui.menu_recent_files->addAction(actions_recent_files[i]); - } - UpdateRecentFiles(); - - // Setup connections +void GMainWindow::ConnectWidgetEvents() { connect(game_list, SIGNAL(GameChosen(QString)), this, SLOT(OnGameListLoadFile(QString)), Qt::DirectConnection); + connect(game_list, SIGNAL(OpenSaveFolderRequested(u64)), this, + SLOT(OnGameListOpenSaveFolder(u64)), Qt::DirectConnection); connect(ui.action_Configure, SIGNAL(triggered()), this, SLOT(OnConfigure())); connect(ui.action_Load_File, SIGNAL(triggered()), this, SLOT(OnMenuLoadFile()), Qt::DirectConnection); @@ -197,40 +251,6 @@ GMainWindow::GMainWindow() : config(new Config()), emu_thread(nullptr) { connect(this, SIGNAL(EmulationStarting(EmuThread*)), waitTreeWidget, SLOT(OnEmulationStarting(EmuThread*))); connect(this, SIGNAL(EmulationStopping()), waitTreeWidget, SLOT(OnEmulationStopping())); - - // Setup hotkeys - RegisterHotkey("Main Window", "Load File", QKeySequence::Open); - RegisterHotkey("Main Window", "Swap Screens", QKeySequence::NextChild); - RegisterHotkey("Main Window", "Start Emulation"); - 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())); - connect(GetHotkey("Main Window", "Swap Screens", this), SIGNAL(activated()), this, - SLOT(OnSwapScreens())); - - std::string window_title = - Common::StringFromFormat("Citra | %s-%s", Common::g_scm_branch, Common::g_scm_desc); - setWindowTitle(window_title.c_str()); - - show(); - - game_list->PopulateAsync(UISettings::values.gamedir, UISettings::values.gamedir_deepscan); - - QStringList args = QApplication::arguments(); - if (args.length() >= 2) { - BootGame(args[1].toStdString()); - } -} - -GMainWindow::~GMainWindow() { - // will get automatically deleted otherwise - if (render_window->parent() == nullptr) - delete render_window; - - Pica::g_debug_context.reset(); } void GMainWindow::OnDisplayTitleBars(bool show) { @@ -253,7 +273,7 @@ void GMainWindow::OnDisplayTitleBars(bool show) { } } -bool GMainWindow::InitializeSystem(u32 system_mode) { +bool GMainWindow::LoadROM(const std::string& filename) { // Shutdown previous session if the emu thread is still active... if (emu_thread != nullptr) ShutdownGame(); @@ -269,54 +289,25 @@ bool GMainWindow::InitializeSystem(u32 system_mode) { return false; } - // Initialize the core emulation - System::Result system_result = System::Init(render_window, system_mode); - if (System::Result::Success != system_result) { - switch (system_result) { - case System::Result::ErrorInitVideoCore: - QMessageBox::critical(this, tr("Error while starting Citra!"), - tr("Failed to initialize the video core!\n\n" - "Please ensure that your GPU supports OpenGL 3.3 and that you " - "have the latest graphics driver.")); - break; - - default: - QMessageBox::critical(this, tr("Error while starting Citra!"), - tr("Unknown error (please check the log)!")); - break; - } - return false; - } - return true; -} + Core::System& system{Core::System::GetInstance()}; -bool GMainWindow::LoadROM(const std::string& filename) { - std::unique_ptr<Loader::AppLoader> app_loader = Loader::GetLoader(filename); - if (!app_loader) { - LOG_CRITICAL(Frontend, "Failed to obtain loader for %s!", filename.c_str()); - QMessageBox::critical(this, tr("Error while loading ROM!"), - tr("The ROM format is not supported.")); - return false; - } + const Core::System::ResultStatus result{system.Load(render_window, filename)}; - boost::optional<u32> system_mode = app_loader->LoadKernelSystemMode(); - if (!system_mode) { - LOG_CRITICAL(Frontend, "Failed to load ROM!"); - QMessageBox::critical(this, tr("Error while loading ROM!"), - tr("Could not determine the system mode.")); - return false; - } - - if (!InitializeSystem(system_mode.get())) - return false; + if (result != Core::System::ResultStatus::Success) { + switch (result) { + case Core::System::ResultStatus::ErrorGetLoader: + LOG_CRITICAL(Frontend, "Failed to obtain loader for %s!", filename.c_str()); + QMessageBox::critical(this, tr("Error while loading ROM!"), + tr("The ROM format is not supported.")); + break; - Loader::ResultStatus result = app_loader->Load(); - if (Loader::ResultStatus::Success != result) { - System::Shutdown(); - LOG_CRITICAL(Frontend, "Failed to load ROM!"); + case Core::System::ResultStatus::ErrorSystemMode: + LOG_CRITICAL(Frontend, "Failed to load ROM!"); + QMessageBox::critical(this, tr("Error while loading ROM!"), + tr("Could not determine the system mode.")); + break; - switch (result) { - case Loader::ResultStatus::ErrorEncrypted: { + case Core::System::ResultStatus::ErrorLoader_ErrorEncrypted: { // Build the MessageBox ourselves to have clickable link QMessageBox popup_error; popup_error.setTextFormat(Qt::RichText); @@ -331,11 +322,10 @@ bool GMainWindow::LoadROM(const std::string& filename) { popup_error.exec(); break; } - case Loader::ResultStatus::ErrorInvalidFormat: + case Core::System::ResultStatus::ErrorLoader_ErrorInvalidFormat: QMessageBox::critical(this, tr("Error while loading ROM!"), tr("The ROM format is not supported.")); break; - case Loader::ResultStatus::Error: default: QMessageBox::critical(this, tr("Error while loading ROM!"), tr("Unknown error!")); @@ -386,6 +376,7 @@ void GMainWindow::BootGame(const std::string& filename) { game_list->hide(); } render_window->show(); + render_window->setFocus(); emulation_running = true; OnStartGame(); @@ -460,6 +451,21 @@ void GMainWindow::OnGameListLoadFile(QString game_path) { BootGame(game_path.toStdString()); } +void GMainWindow::OnGameListOpenSaveFolder(u64 program_id) { + std::string sdmc_dir = FileUtil::GetUserPath(D_SDMC_IDX); + std::string path = FileSys::ArchiveSource_SDSaveData::GetSaveDataPathFor(sdmc_dir, program_id); + QString qpath = QString::fromStdString(path); + + QDir dir(qpath); + if (!dir.exists()) { + QMessageBox::critical(this, tr("Error Opening Save Folder"), tr("Folder does not exist!")); + return; + } + + LOG_INFO(Frontend, "Opening save data path for program_id=%" PRIu64, program_id); + QDesktopServices::openUrl(QUrl::fromLocalFile(qpath)); +} + void GMainWindow::OnMenuLoadFile() { QString filename = QFileDialog::getOpenFileName(this, tr("Load File"), UISettings::values.roms_path, diff --git a/src/citra_qt/main.h b/src/citra_qt/main.h index f87178227..a2fd45c47 100644 --- a/src/citra_qt/main.h +++ b/src/citra_qt/main.h @@ -9,18 +9,21 @@ #include <QMainWindow> #include "ui_main.h" +class CallstackWidget; class Config; +class DisassemblerWidget; +class EmuThread; class GameList; class GImageInfo; +class GPUCommandStreamWidget; +class GPUCommandListWidget; +class GraphicsBreakPointsWidget; +class GraphicsTracingWidget; +class GraphicsVertexShaderWidget; class GRenderWindow; -class EmuThread; -class ProfilerWidget; class MicroProfileDialog; -class DisassemblerWidget; +class ProfilerWidget; class RegistersWidget; -class CallstackWidget; -class GPUCommandStreamWidget; -class GPUCommandListWidget; class WaitTreeWidget; class GMainWindow : public QMainWindow { @@ -60,6 +63,16 @@ signals: void EmulationStopping(); private: + void InitializeWidgets(); + void InitializeDebugMenuActions(); + void InitializeRecentFileMenuActions(); + void InitializeHotkeys(); + + void SetDefaultUIGeometry(); + void RestoreUIState(); + + void ConnectWidgetEvents(); + /** * Initializes the emulation system. * @param system_mode The system mode with which to intialize the kernel. @@ -105,6 +118,7 @@ private slots: void OnStopGame(); /// Called whenever a user selects a game in the game list widget. void OnGameListLoadFile(QString game_path); + void OnGameListOpenSaveFolder(u64 program_id); void OnMenuLoadFile(); void OnMenuLoadSymbolMap(); /// Called whenever a user selects the "File->Select Game List Root" menu item @@ -135,6 +149,9 @@ private: CallstackWidget* callstackWidget; GPUCommandStreamWidget* graphicsWidget; GPUCommandListWidget* graphicsCommandsWidget; + GraphicsBreakPointsWidget* graphicsBreakpointsWidget; + GraphicsVertexShaderWidget* graphicsVertexShaderWidget; + GraphicsTracingWidget* graphicsTracingWidget; WaitTreeWidget* waitTreeWidget; QAction* actions_recent_files[max_recent_files_item]; diff --git a/src/citra_qt/util/spinbox.h b/src/citra_qt/util/spinbox.h index a57355cd6..2fa1db3a4 100644 --- a/src/citra_qt/util/spinbox.h +++ b/src/citra_qt/util/spinbox.h @@ -42,7 +42,7 @@ class CSpinBox : public QAbstractSpinBox { Q_OBJECT public: - CSpinBox(QWidget* parent = nullptr); + explicit CSpinBox(QWidget* parent = nullptr); void stepBy(int steps) override; StepEnabled stepEnabled() const override; |