diff options
Diffstat (limited to 'src/citra_qt')
-rw-r--r-- | src/citra_qt/CMakeLists.txt | 27 | ||||
-rw-r--r-- | src/citra_qt/debugger/callstack.cpp | 12 | ||||
-rw-r--r-- | src/citra_qt/debugger/graphics_cmdlists.cpp | 1 | ||||
-rw-r--r-- | src/citra_qt/debugger/graphics_framebuffer.cpp | 1 | ||||
-rw-r--r-- | src/citra_qt/debugger/graphics_tracing.cpp | 2 | ||||
-rw-r--r-- | src/citra_qt/debugger/graphics_vertex_shader.cpp | 6 | ||||
-rw-r--r-- | src/citra_qt/debugger/registers.cpp | 8 | ||||
-rw-r--r-- | src/citra_qt/main.cpp | 89 | ||||
-rw-r--r-- | src/citra_qt/main.h | 10 |
9 files changed, 114 insertions, 42 deletions
diff --git a/src/citra_qt/CMakeLists.txt b/src/citra_qt/CMakeLists.txt index bbf6ae001..9b3eb2cd6 100644 --- a/src/citra_qt/CMakeLists.txt +++ b/src/citra_qt/CMakeLists.txt @@ -79,7 +79,7 @@ if (APPLE) else() add_executable(citra-qt ${SRCS} ${HEADERS} ${UI_HDRS}) endif() -target_link_libraries(citra-qt core video_core common qhexedit) +target_link_libraries(citra-qt core video_core audio_core common qhexedit) target_link_libraries(citra-qt ${OPENGL_gl_LIBRARY} ${CITRA_QT_LIBS}) target_link_libraries(citra-qt ${PLATFORM_LIBRARIES}) @@ -88,9 +88,14 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Linux|FreeBSD|OpenBSD|NetBSD") endif() if (Qt5_FOUND AND MSVC) + include(WindowsCopyFiles) + set(Qt5_DLL_DIR "${Qt5_DIR}/../../../bin") set(Qt5_PLATFORMS_DIR "${Qt5_DIR}/../../../plugins/platforms/") - set(Qt5_DLLS + 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 @@ -99,24 +104,8 @@ if (Qt5_FOUND AND MSVC) Qt5OpenGL$<$<CONFIG:Debug>:d>.* Qt5Widgets$<$<CONFIG:Debug>:d>.* ) - set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/$<CONFIG>/") - set(PLATFORMS ${DLL_DEST}platforms/) + windows_copy_files(citra-qt ${Qt5_PLATFORMS_DIR} ${PLATFORMS} qwindows$<$<CONFIG:Debug>:d>.*) - # windows commandline expects the / to be \ so switch them - string(REPLACE "/" "\\\\" Qt5_DLL_DIR ${Qt5_DLL_DIR}) - string(REPLACE "/" "\\\\" Qt5_PLATFORMS_DIR ${Qt5_PLATFORMS_DIR}) - string(REPLACE "/" "\\\\" DLL_DEST ${DLL_DEST}) - string(REPLACE "/" "\\\\" PLATFORMS ${PLATFORMS}) - - # /NJH /NJS /NDL /NFL /NC /NS /NP - Silence any output - # cmake adds an extra check for command success which doesn't work too well with robocopy - # so trick it into thinking the command was successful with the || cmd /c "exit /b 0" - add_custom_command(TARGET citra-qt POST_BUILD - COMMAND robocopy ${Qt5_DLL_DIR} ${DLL_DEST} ${Qt5_DLLS} /NJH /NJS /NDL /NFL /NC /NS /NP || cmd /c "exit /b 0" - COMMAND if not exist ${PLATFORMS} mkdir ${PLATFORMS} 2> nul - COMMAND robocopy ${Qt5_PLATFORMS_DIR} ${PLATFORMS} qwindows$<$<CONFIG:Debug>:d>.* /NJH /NJS /NDL /NFL /NC /NS /NP || cmd /c "exit /b 0" - ) - unset(Qt5_DLLS) unset(Qt5_DLL_DIR) unset(Qt5_PLATFORMS_DIR) unset(DLL_DEST) diff --git a/src/citra_qt/debugger/callstack.cpp b/src/citra_qt/debugger/callstack.cpp index d45eed179..793944639 100644 --- a/src/citra_qt/debugger/callstack.cpp +++ b/src/citra_qt/debugger/callstack.cpp @@ -29,18 +29,16 @@ CallstackWidget::CallstackWidget(QWidget* parent): QDockWidget(parent) void CallstackWidget::OnDebugModeEntered() { - ARM_Interface* app_core = Core::g_app_core; - - u32 sp = app_core->GetReg(13); //stack pointer - u32 ret_addr, call_addr, func_addr; + // Stack pointer + const u32 sp = Core::g_app_core->GetReg(13); Clear(); int counter = 0; for (u32 addr = 0x10000000; addr >= sp; addr -= 4) { - ret_addr = Memory::Read32(addr); - call_addr = ret_addr - 4; //get call address??? + const u32 ret_addr = Memory::Read32(addr); + const u32 call_addr = ret_addr - 4; //get call address??? if (Memory::GetPointer(call_addr) == nullptr) break; @@ -60,7 +58,7 @@ void CallstackWidget::OnDebugModeEntered() // Pre-compute the left-shift and the prefetch offset i_offset <<= 2; i_offset += 8; - func_addr = call_addr + i_offset; + const u32 func_addr = call_addr + i_offset; callstack_model->setItem(counter, 0, new QStandardItem(QString("0x%1").arg(addr, 8, 16, QLatin1Char('0')))); callstack_model->setItem(counter, 1, new QStandardItem(QString("0x%1").arg(ret_addr, 8, 16, QLatin1Char('0')))); diff --git a/src/citra_qt/debugger/graphics_cmdlists.cpp b/src/citra_qt/debugger/graphics_cmdlists.cpp index ab97c8d2d..5186d2b44 100644 --- a/src/citra_qt/debugger/graphics_cmdlists.cpp +++ b/src/citra_qt/debugger/graphics_cmdlists.cpp @@ -21,6 +21,7 @@ #include "common/vector_math.h" #include "video_core/pica.h" +#include "video_core/pica_state.h" #include "video_core/debug_utils/debug_utils.h" QImage LoadTexture(u8* src, const Pica::DebugUtils::TextureInfo& info) { diff --git a/src/citra_qt/debugger/graphics_framebuffer.cpp b/src/citra_qt/debugger/graphics_framebuffer.cpp index 80b32eaff..c30e75933 100644 --- a/src/citra_qt/debugger/graphics_framebuffer.cpp +++ b/src/citra_qt/debugger/graphics_framebuffer.cpp @@ -18,6 +18,7 @@ #include "core/hw/gpu.h" #include "video_core/pica.h" +#include "video_core/pica_state.h" #include "video_core/utils.h" GraphicsFramebufferWidget::GraphicsFramebufferWidget(std::shared_ptr<Pica::DebugContext> debug_context, diff --git a/src/citra_qt/debugger/graphics_tracing.cpp b/src/citra_qt/debugger/graphics_tracing.cpp index b0bc782df..e06498744 100644 --- a/src/citra_qt/debugger/graphics_tracing.cpp +++ b/src/citra_qt/debugger/graphics_tracing.cpp @@ -22,7 +22,7 @@ #include "nihstro/float24.h" #include "video_core/pica.h" - +#include "video_core/pica_state.h" GraphicsTracingWidget::GraphicsTracingWidget(std::shared_ptr<Pica::DebugContext> debug_context, QWidget* parent) diff --git a/src/citra_qt/debugger/graphics_vertex_shader.cpp b/src/citra_qt/debugger/graphics_vertex_shader.cpp index a5a5fe6b0..4b676f1b1 100644 --- a/src/citra_qt/debugger/graphics_vertex_shader.cpp +++ b/src/citra_qt/debugger/graphics_vertex_shader.cpp @@ -19,6 +19,8 @@ #include "citra_qt/debugger/graphics_vertex_shader.h" #include "citra_qt/util/util.h" +#include "video_core/pica.h" +#include "video_core/pica_state.h" #include "video_core/shader/shader.h" using nihstro::OpCode; @@ -496,8 +498,8 @@ void GraphicsVertexShaderWidget::Reload(bool replace_vertex_data, void* vertex_d // Reload widget state for (int attr = 0; attr < num_attributes; ++attr) { unsigned source_attr = shader_config.input_register_map.GetRegisterForAttribute(attr); - input_data_mapping[source_attr]->setText(QString("-> v%1").arg(attr)); - input_data_container[source_attr]->setVisible(true); + input_data_mapping[attr]->setText(QString("-> v%1").arg(source_attr)); + input_data_container[attr]->setVisible(true); } // Only show input attributes which are used as input to the shader for (unsigned int attr = num_attributes; attr < 16; ++attr) { diff --git a/src/citra_qt/debugger/registers.cpp b/src/citra_qt/debugger/registers.cpp index 6100d67c5..1bd0bfebc 100644 --- a/src/citra_qt/debugger/registers.cpp +++ b/src/citra_qt/debugger/registers.cpp @@ -59,16 +59,14 @@ RegistersWidget::RegistersWidget(QWidget* parent) : QDockWidget(parent) { } void RegistersWidget::OnDebugModeEntered() { - ARM_Interface* app_core = Core::g_app_core; - - if (app_core == nullptr) + if (!Core::g_app_core) return; for (int i = 0; i < core_registers->childCount(); ++i) - core_registers->child(i)->setText(1, QString("0x%1").arg(app_core->GetReg(i), 8, 16, QLatin1Char('0'))); + core_registers->child(i)->setText(1, QString("0x%1").arg(Core::g_app_core->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(app_core->GetVFPReg(i), 8, 16, QLatin1Char('0'))); + vfp_registers->child(i)->setText(1, QString("0x%1").arg(Core::g_app_core->GetVFPReg(i), 8, 16, QLatin1Char('0'))); UpdateCPSRValues(); UpdateVFPSystemRegisterValues(); diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index d6c27f0df..57adbc136 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 <clocale> #include <thread> #include <QDesktopWidget> @@ -171,6 +172,8 @@ 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())); @@ -208,7 +211,7 @@ GMainWindow::GMainWindow() : emu_thread(nullptr) show(); - game_list->PopulateAsync(settings.value("gameListRootDir").toString(), settings.value("gameListDeepScan").toBool()); + game_list->PopulateAsync(settings.value("gameListRootDir", ".").toString(), settings.value("gameListDeepScan", false).toBool()); QStringList args = QApplication::arguments(); if (args.length() >= 2) { @@ -246,22 +249,73 @@ void GMainWindow::OnDisplayTitleBars(bool show) } } -void GMainWindow::BootGame(const std::string& filename) { - LOG_INFO(Frontend, "Citra starting..."); - +bool GMainWindow::InitializeSystem() { // Shutdown previous session if the emu thread is still active... if (emu_thread != nullptr) ShutdownGame(); // Initialize the core emulation - System::Init(render_window); + System::Result system_result = System::Init(render_window); + 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; +} - // Load the game - if (Loader::ResultStatus::Success != Loader::LoadFile(filename)) { +bool GMainWindow::LoadROM(const std::string& filename) { + Loader::ResultStatus result = Loader::LoadFile(filename); + if (Loader::ResultStatus::Success != result) { LOG_CRITICAL(Frontend, "Failed to load ROM!"); System::Shutdown(); - return; + + switch (result) { + case Loader::ResultStatus::ErrorEncrypted: { + // Build the MessageBox ourselves to have clickable link + QMessageBox popup_error; + popup_error.setTextFormat(Qt::RichText); + popup_error.setWindowTitle(tr("Error while loading ROM!")); + popup_error.setText(tr("The game that you are trying to load must be decrypted before being used with Citra.<br/><br/>" + "For more information on dumping and decrypting games, please see: <a href='https://citra-emu.org/wiki/Dumping-Game-Cartridges'>https://citra-emu.org/wiki/Dumping-Game-Cartridges</a>")); + popup_error.setIcon(QMessageBox::Critical); + popup_error.exec(); + break; + } + case Loader::ResultStatus::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!")); + break; + } + return false; } + return true; +} + +void GMainWindow::BootGame(const std::string& filename) { + LOG_INFO(Frontend, "Citra starting..."); + + if (!InitializeSystem()) + return; + + if (!LoadROM(filename)) + return; // Create and start the emulation thread emu_thread = Common::make_unique<EmuThread>(render_window); @@ -497,7 +551,22 @@ void GMainWindow::OnConfigure() { //GControllerConfigDialog* dialog = new GControllerConfigDialog(controller_ports, this); } +bool GMainWindow::ConfirmClose() { + if (emu_thread == nullptr || !confirm_before_closing) + return true; + + auto answer = QMessageBox::question(this, tr("Citra"), + tr("Are you sure you want to close Citra?"), + QMessageBox::Yes | QMessageBox::No, QMessageBox::No); + return answer != QMessageBox::No; +} + void GMainWindow::closeEvent(QCloseEvent* event) { + if (!ConfirmClose()) { + event->ignore(); + return; + } + // Save window layout QSettings settings(QSettings::IniFormat, QSettings::UserScope, "Citra team", "Citra"); @@ -512,6 +581,7 @@ void GMainWindow::closeEvent(QCloseEvent* event) { 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); @@ -545,6 +615,9 @@ int main(int argc, char* argv[]) { QApplication::setAttribute(Qt::AA_X11InitThreads); QApplication app(argc, argv); + // Qt changes the locale and causes issues in float conversion using std::to_string() when generating shaders + setlocale(LC_ALL, "C"); + GMainWindow main_window; // After settings have been loaded by GMainWindow, apply the filter log_filter.ParseFilterString(Settings::values.log_filter); diff --git a/src/citra_qt/main.h b/src/citra_qt/main.h index f6d429cd9..945aea0cd 100644 --- a/src/citra_qt/main.h +++ b/src/citra_qt/main.h @@ -59,6 +59,8 @@ signals: void EmulationStopping(); private: + bool InitializeSystem(); + bool LoadROM(const std::string& filename); void BootGame(const std::string& filename); void ShutdownGame(); @@ -82,6 +84,13 @@ private: */ void UpdateRecentFiles(); + /** + * If the emulation is running, + * asks the user if he really want to close the emulator + * + * @return true if the user confirmed + */ + bool ConfirmClose(); void closeEvent(QCloseEvent* event) override; private slots: @@ -122,6 +131,7 @@ private: GPUCommandListWidget* graphicsCommandsWidget; QAction* actions_recent_files[max_recent_files_item]; + bool confirm_before_closing; }; #endif // _CITRA_QT_MAIN_HXX_ |