From a35990ee4c1b996e100fab8541bedcc950796732 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Sat, 9 Jul 2022 19:07:28 +1000 Subject: [PATCH] Qt: Move Main.cpp to QtHost.cpp --- pcsx2-qt/CMakeLists.txt | 1 - pcsx2-qt/Main.cpp | 255 ------------------------- pcsx2-qt/QtHost.cpp | 304 +++++++++++++++++++++++++----- pcsx2-qt/QtHost.h | 4 - pcsx2-qt/pcsx2-qt.vcxproj | 1 - pcsx2-qt/pcsx2-qt.vcxproj.filters | 1 - 6 files changed, 261 insertions(+), 305 deletions(-) delete mode 100644 pcsx2-qt/Main.cpp diff --git a/pcsx2-qt/CMakeLists.txt b/pcsx2-qt/CMakeLists.txt index bc0e88d4e8..7b1c1c6b56 100644 --- a/pcsx2-qt/CMakeLists.txt +++ b/pcsx2-qt/CMakeLists.txt @@ -22,7 +22,6 @@ target_sources(pcsx2-qt PRIVATE EarlyHardwareCheck.cpp EmuThread.cpp EmuThread.h - Main.cpp MainWindow.cpp MainWindow.h MainWindow.ui diff --git a/pcsx2-qt/Main.cpp b/pcsx2-qt/Main.cpp deleted file mode 100644 index 980877a3d6..0000000000 --- a/pcsx2-qt/Main.cpp +++ /dev/null @@ -1,255 +0,0 @@ -/* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2022 PCSX2 Dev Team - * - * PCSX2 is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with PCSX2. - * If not, see . - */ - -#include "PrecompiledHeader.h" - -#include -#include -#include -#include - -#include "MainWindow.h" -#include "EmuThread.h" -#include "QtHost.h" - -#include "CDVD/CDVD.h" -#include "Frontend/GameList.h" -#include "Frontend/LogSink.h" - -#include "common/CrashHandler.h" - -static void PrintCommandLineVersion() -{ - Host::InitializeEarlyConsole(); - std::fprintf(stderr, "%s\n", (QtHost::GetAppNameAndVersion() + QtHost::GetAppConfigSuffix()).toUtf8().constData()); - std::fprintf(stderr, "https://pcsx2.net/\n"); - std::fprintf(stderr, "\n"); -} - -static void PrintCommandLineHelp(const char* progname) -{ - PrintCommandLineVersion(); - std::fprintf(stderr, "Usage: %s [parameters] [--] [boot filename]\n", progname); - std::fprintf(stderr, "\n"); - std::fprintf(stderr, " -help: Displays this information and exits.\n"); - std::fprintf(stderr, " -version: Displays version information and exits.\n"); - std::fprintf(stderr, " -batch: Enables batch mode (exits after shutting down).\n"); - std::fprintf(stderr, " -elf : Overrides the boot ELF with the specified filename.\n"); - std::fprintf(stderr, " -disc : Uses the specified host DVD drive as a source.\n"); - std::fprintf(stderr, " -bios: Starts the BIOS (System Menu/OSDSYS).\n"); - std::fprintf(stderr, " -fastboot: Force fast boot for provided filename.\n"); - std::fprintf(stderr, " -slowboot: Force slow boot for provided filename.\n"); - std::fprintf(stderr, " -state : Loads specified save state by index.\n"); - std::fprintf(stderr, " -statefile : Loads state from the specified filename.\n"); - std::fprintf(stderr, " -fullscreen: Enters fullscreen mode immediately after starting.\n"); - std::fprintf(stderr, " -nofullscreen: Prevents fullscreen mode from triggering if enabled.\n"); - std::fprintf(stderr, " -earlyconsolelog: Forces logging of early console messages to console.\n"); - std::fprintf(stderr, " --: Signals that no more arguments will follow and the remaining\n" - " parameters make up the filename. Use when the filename contains\n" - " spaces or starts with a dash.\n"); - std::fprintf(stderr, "\n"); -} - -static std::shared_ptr& AutoBoot(std::shared_ptr& autoboot) -{ - if (!autoboot) - autoboot = std::make_shared(); - - return autoboot; -} - -static bool ParseCommandLineOptions(int argc, char* argv[], std::shared_ptr& autoboot) -{ - bool no_more_args = false; - - for (int i = 1; i < argc; i++) - { - if (!no_more_args) - { -#define CHECK_ARG(str) !std::strcmp(argv[i], str) -#define CHECK_ARG_PARAM(str) (!std::strcmp(argv[i], str) && ((i + 1) < argc)) - - if (CHECK_ARG("-help")) - { - PrintCommandLineHelp(argv[0]); - return false; - } - else if (CHECK_ARG("-version")) - { - PrintCommandLineVersion(); - return false; - } - else if (CHECK_ARG("-batch")) - { - QtHost::SetBatchMode(true); - continue; - } - else if (CHECK_ARG("-fastboot")) - { - AutoBoot(autoboot)->fast_boot = true; - continue; - } - else if (CHECK_ARG("-slowboot")) - { - AutoBoot(autoboot)->fast_boot = false; - continue; - } - else if (CHECK_ARG_PARAM("-state")) - { - AutoBoot(autoboot)->state_index = std::atoi(argv[++i]); - continue; - } - else if (CHECK_ARG_PARAM("-statefile")) - { - AutoBoot(autoboot)->save_state = argv[++i]; - continue; - } - else if (CHECK_ARG_PARAM("-elf")) - { - AutoBoot(autoboot)->elf_override = argv[++i]; - continue; - } - else if (CHECK_ARG_PARAM("-disc")) - { - AutoBoot(autoboot)->source_type = CDVD_SourceType::Disc; - AutoBoot(autoboot)->filename = argv[++i]; - continue; - } - else if (CHECK_ARG("-bios")) - { - AutoBoot(autoboot)->source_type = CDVD_SourceType::NoDisc; - continue; - } - else if (CHECK_ARG("-fullscreen")) - { - AutoBoot(autoboot)->fullscreen = true; - continue; - } - else if (CHECK_ARG("-nofullscreen")) - { - AutoBoot(autoboot)->fullscreen = false; - continue; - } - else if (CHECK_ARG("-earlyconsolelog")) - { - Host::InitializeEarlyConsole(); - continue; - } - else if (CHECK_ARG("--")) - { - no_more_args = true; - continue; - } - else if (argv[i][0] == '-') - { - Host::InitializeEarlyConsole(); - std::fprintf(stderr, "Unknown parameter: '%s'", argv[i]); - return false; - } - -#undef CHECK_ARG -#undef CHECK_ARG_PARAM - } - - if (!AutoBoot(autoboot)->filename.empty()) - AutoBoot(autoboot)->filename += ' '; - - AutoBoot(autoboot)->filename += argv[i]; - } - - // check autoboot parameters, if we set something like fullscreen without a bios - // or disc, we don't want to actually start. - if (autoboot && !autoboot->source_type.has_value() && autoboot->filename.empty() && autoboot->elf_override.empty()) - { - Host::InitializeEarlyConsole(); - Console.Warning("Skipping autoboot due to no boot parameters."); - autoboot.reset(); - } - - // if we don't have autoboot, we definitely don't want batch mode (because that'll skip - // scanning the game list). - if (QtHost::InBatchMode() && !autoboot) - { - Host::InitializeEarlyConsole(); - Console.Warning("Disabling batch mode, because we have no autoboot."); - QtHost::SetBatchMode(false); - } - - return true; -} - -#ifndef _WIN32 - -// See note at the end of the file as to why we don't do this on Windows. -static bool PerformEarlyHardwareChecks() -{ - // NOTE: No point translating this message, because the configuration isn't loaded yet, so we - // won't know which language to use, and loading the configuration uses float instructions. - const char* error; - if (VMManager::PerformEarlyHardwareChecks(&error)) - return true; - - QMessageBox::critical(nullptr, QStringLiteral("Hardware Check Failed"), QString::fromUtf8(error)); - return false; -} - -#endif - -int main(int argc, char* argv[]) -{ - CrashHandler::Install(); - - QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); - QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); - QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); - - QApplication app(argc, argv); - -#ifndef _WIN32 - if (!PerformEarlyHardwareChecks()) - return EXIT_FAILURE; -#endif - - std::shared_ptr autoboot; - if (!ParseCommandLineOptions(argc, argv, autoboot)) - return EXIT_FAILURE; - - MainWindow* main_window = new MainWindow(QApplication::style()->objectName()); - - if (!QtHost::Initialize()) - { - delete main_window; - return EXIT_FAILURE; - } - - // actually show the window, the emuthread might still be starting up at this point - main_window->initialize(); - - // skip scanning the game list when running in batch mode - if (!QtHost::InBatchMode()) - main_window->refreshGameList(false); - - main_window->show(); - - if (autoboot) - g_emu_thread->startVM(std::move(autoboot)); - else - main_window->startupUpdateCheck(); - - const int result = app.exec(); - - QtHost::Shutdown(); - return result; -} diff --git a/pcsx2-qt/QtHost.cpp b/pcsx2-qt/QtHost.cpp index e7e1805c24..48f1424dcc 100644 --- a/pcsx2-qt/QtHost.cpp +++ b/pcsx2-qt/QtHost.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #ifdef _WIN32 @@ -35,6 +36,7 @@ #include "common/StringUtil.h" #include "common/Timer.h" +#include "pcsx2/CDVD/CDVDaccess.h" #include "pcsx2/DebugTools/Debug.h" #include "pcsx2/Frontend/GameList.h" #include "pcsx2/Frontend/INISettingsInterface.h" @@ -55,6 +57,10 @@ static constexpr u32 SETTINGS_SAVE_DELAY = 1000; // Local function declarations ////////////////////////////////////////////////////////////////////////// namespace QtHost { +static void PrintCommandLineVersion(); +static void PrintCommandLineHelp(const char* progname); +static std::shared_ptr& AutoBoot(std::shared_ptr& autoboot); +static bool ParseCommandLineOptions(int argc, char* argv[], std::shared_ptr& autoboot); static bool InitializeConfig(); static bool ShouldUsePortableMode(); static void SetAppRoot(); @@ -78,44 +84,6 @@ static bool s_batch_mode = false; // Initialization/Shutdown ////////////////////////////////////////////////////////////////////////// -bool QtHost::Initialize() -{ - qRegisterMetaType>(); - qRegisterMetaType>(); - qRegisterMetaType>(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - qRegisterMetaType(); - - if (!InitializeConfig()) - { - // NOTE: No point translating this, because no config means the language won't be loaded anyway. - QMessageBox::critical(nullptr, QStringLiteral("Error"), QStringLiteral("Failed to initialize config.")); - return false; - } - - HookSignals(); - EmuThread::start(); - return true; -} - -void QtHost::Shutdown() -{ - EmuThread::stop(); - if (g_main_window) - { - g_main_window->close(); - delete g_main_window; - } - - if (emuLog) - { - std::fclose(emuLog); - emuLog = nullptr; - } -} - bool QtHost::SetCriticalFolders() { SetAppRoot(); @@ -373,11 +341,6 @@ bool QtHost::InBatchMode() return s_batch_mode; } -void QtHost::SetBatchMode(bool enabled) -{ - s_batch_mode = enabled; -} - void QtHost::RunOnUIThread(const std::function& func, bool block /*= false*/) { // main window always exists, so it's fine to attach it to that. @@ -509,3 +472,258 @@ void QtHost::HookSignals() std::signal(SIGINT, SignalHandler); std::signal(SIGTERM, SignalHandler); } + +void QtHost::PrintCommandLineVersion() +{ + Host::InitializeEarlyConsole(); + std::fprintf(stderr, "%s\n", (GetAppNameAndVersion() + GetAppConfigSuffix()).toUtf8().constData()); + std::fprintf(stderr, "https://pcsx2.net/\n"); + std::fprintf(stderr, "\n"); +} + +void QtHost::PrintCommandLineHelp(const char* progname) +{ + PrintCommandLineVersion(); + std::fprintf(stderr, "Usage: %s [parameters] [--] [boot filename]\n", progname); + std::fprintf(stderr, "\n"); + std::fprintf(stderr, " -help: Displays this information and exits.\n"); + std::fprintf(stderr, " -version: Displays version information and exits.\n"); + std::fprintf(stderr, " -batch: Enables batch mode (exits after shutting down).\n"); + std::fprintf(stderr, " -elf : Overrides the boot ELF with the specified filename.\n"); + std::fprintf(stderr, " -disc : Uses the specified host DVD drive as a source.\n"); + std::fprintf(stderr, " -bios: Starts the BIOS (System Menu/OSDSYS).\n"); + std::fprintf(stderr, " -fastboot: Force fast boot for provided filename.\n"); + std::fprintf(stderr, " -slowboot: Force slow boot for provided filename.\n"); + std::fprintf(stderr, " -state : Loads specified save state by index.\n"); + std::fprintf(stderr, " -statefile : Loads state from the specified filename.\n"); + std::fprintf(stderr, " -fullscreen: Enters fullscreen mode immediately after starting.\n"); + std::fprintf(stderr, " -nofullscreen: Prevents fullscreen mode from triggering if enabled.\n"); + std::fprintf(stderr, " -earlyconsolelog: Forces logging of early console messages to console.\n"); + std::fprintf(stderr, " --: Signals that no more arguments will follow and the remaining\n" + " parameters make up the filename. Use when the filename contains\n" + " spaces or starts with a dash.\n"); + std::fprintf(stderr, "\n"); +} + +std::shared_ptr& QtHost::AutoBoot(std::shared_ptr& autoboot) +{ + if (!autoboot) + autoboot = std::make_shared(); + + return autoboot; +} + +bool QtHost::ParseCommandLineOptions(int argc, char* argv[], std::shared_ptr& autoboot) +{ + bool no_more_args = false; + + for (int i = 1; i < argc; i++) + { + if (!no_more_args) + { +#define CHECK_ARG(str) !std::strcmp(argv[i], str) +#define CHECK_ARG_PARAM(str) (!std::strcmp(argv[i], str) && ((i + 1) < argc)) + + if (CHECK_ARG("-help")) + { + PrintCommandLineHelp(argv[0]); + return false; + } + else if (CHECK_ARG("-version")) + { + PrintCommandLineVersion(); + return false; + } + else if (CHECK_ARG("-batch")) + { + s_batch_mode = true; + continue; + } + else if (CHECK_ARG("-fastboot")) + { + AutoBoot(autoboot)->fast_boot = true; + continue; + } + else if (CHECK_ARG("-slowboot")) + { + AutoBoot(autoboot)->fast_boot = false; + continue; + } + else if (CHECK_ARG_PARAM("-state")) + { + AutoBoot(autoboot)->state_index = std::atoi(argv[++i]); + continue; + } + else if (CHECK_ARG_PARAM("-statefile")) + { + AutoBoot(autoboot)->save_state = argv[++i]; + continue; + } + else if (CHECK_ARG_PARAM("-elf")) + { + AutoBoot(autoboot)->elf_override = argv[++i]; + continue; + } + else if (CHECK_ARG_PARAM("-disc")) + { + AutoBoot(autoboot)->source_type = CDVD_SourceType::Disc; + AutoBoot(autoboot)->filename = argv[++i]; + continue; + } + else if (CHECK_ARG("-bios")) + { + AutoBoot(autoboot)->source_type = CDVD_SourceType::NoDisc; + continue; + } + else if (CHECK_ARG("-fullscreen")) + { + AutoBoot(autoboot)->fullscreen = true; + continue; + } + else if (CHECK_ARG("-nofullscreen")) + { + AutoBoot(autoboot)->fullscreen = false; + continue; + } + else if (CHECK_ARG("-earlyconsolelog")) + { + Host::InitializeEarlyConsole(); + continue; + } + else if (CHECK_ARG("--")) + { + no_more_args = true; + continue; + } + else if (argv[i][0] == '-') + { + Host::InitializeEarlyConsole(); + std::fprintf(stderr, "Unknown parameter: '%s'", argv[i]); + return false; + } + +#undef CHECK_ARG +#undef CHECK_ARG_PARAM + } + + if (!AutoBoot(autoboot)->filename.empty()) + AutoBoot(autoboot)->filename += ' '; + + AutoBoot(autoboot)->filename += argv[i]; + } + + // check autoboot parameters, if we set something like fullscreen without a bios + // or disc, we don't want to actually start. + if (autoboot && !autoboot->source_type.has_value() && autoboot->filename.empty() && autoboot->elf_override.empty()) + { + Host::InitializeEarlyConsole(); + Console.Warning("Skipping autoboot due to no boot parameters."); + autoboot.reset(); + } + + // if we don't have autoboot, we definitely don't want batch mode (because that'll skip + // scanning the game list). + if (s_batch_mode && !autoboot) + { + QMessageBox::critical(nullptr, QStringLiteral("Error"), QStringLiteral("Cannot use batch mode, because no boot filename was specified.")); + return false; + } + + return true; +} + +#ifndef _WIN32 + +// See note in EarlyHardwareChecks.cpp as to why we don't do this on Windows. +static bool PerformEarlyHardwareChecks() +{ + // NOTE: No point translating this message, because the configuration isn't loaded yet, so we + // won't know which language to use, and loading the configuration uses float instructions. + const char* error; + if (VMManager::PerformEarlyHardwareChecks(&error)) + return true; + + QMessageBox::critical(nullptr, QStringLiteral("Hardware Check Failed"), QString::fromUtf8(error)); + return false; +} + +#endif + +static void RegisterTypes() +{ + qRegisterMetaType>(); + qRegisterMetaType>(); + qRegisterMetaType>(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); +} + +int main(int argc, char* argv[]) +{ + CrashHandler::Install(); + + QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); + QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); + RegisterTypes(); + + QApplication app(argc, argv); + +#ifndef _WIN32 + if (!PerformEarlyHardwareChecks()) + return EXIT_FAILURE; +#endif + + std::shared_ptr autoboot; + if (!QtHost::ParseCommandLineOptions(argc, argv, autoboot)) + return EXIT_FAILURE; + + // Bail out if we can't find any config. + if (!QtHost::InitializeConfig()) + { + // NOTE: No point translating this, because no config means the language won't be loaded anyway. + QMessageBox::critical(nullptr, QStringLiteral("Error"), QStringLiteral("Failed to initialize config.")); + return EXIT_FAILURE; + } + + // Start up the CPU thread. + MainWindow* main_window = new MainWindow(QApplication::style()->objectName()); + QtHost::HookSignals(); + EmuThread::start(); + + // Actually show the window, the emuthread might still be starting up at this point. + main_window->initialize(); + + // Skip scanning the game list when running in batch mode. + if (!s_batch_mode) + main_window->refreshGameList(false); + + main_window->show(); + + if (autoboot) + g_emu_thread->startVM(std::move(autoboot)); + else + main_window->startupUpdateCheck(); + + // This doesn't return until we exit. + const int result = app.exec(); + + // Shutting down. + EmuThread::stop(); + if (g_main_window) + { + g_main_window->close(); + delete g_main_window; + } + + // Ensure emulog is flushed. + if (emuLog) + { + std::fclose(emuLog); + emuLog = nullptr; + } + + return result; +} diff --git a/pcsx2-qt/QtHost.h b/pcsx2-qt/QtHost.h index 2f6d27044d..500ce2c35d 100644 --- a/pcsx2-qt/QtHost.h +++ b/pcsx2-qt/QtHost.h @@ -40,12 +40,8 @@ Q_DECLARE_METATYPE(CDVD_SourceType); namespace QtHost { - bool Initialize(); - void Shutdown(); - /// Sets batch mode (exit after game shutdown). bool InBatchMode(); - void SetBatchMode(bool enabled); /// Executes a function on the UI thread. void RunOnUIThread(const std::function& func, bool block = false); diff --git a/pcsx2-qt/pcsx2-qt.vcxproj b/pcsx2-qt/pcsx2-qt.vcxproj index e7e785b412..8f29f2eb6a 100644 --- a/pcsx2-qt/pcsx2-qt.vcxproj +++ b/pcsx2-qt/pcsx2-qt.vcxproj @@ -167,7 +167,6 @@ - Create diff --git a/pcsx2-qt/pcsx2-qt.vcxproj.filters b/pcsx2-qt/pcsx2-qt.vcxproj.filters index aa24a55c49..dcf392a431 100644 --- a/pcsx2-qt/pcsx2-qt.vcxproj.filters +++ b/pcsx2-qt/pcsx2-qt.vcxproj.filters @@ -30,7 +30,6 @@ -