2021-12-13 12:12:54 +00:00
/* 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 < http : //www.gnu.org/licenses/>.
*/
# include "PrecompiledHeader.h"
2022-03-04 10:40:03 +00:00
# include <csignal>
# include <QtCore/QTimer>
2022-07-09 09:07:28 +00:00
# include <QtWidgets/QApplication>
2022-03-04 10:40:03 +00:00
# include <QtWidgets/QMessageBox>
2022-08-20 10:20:36 +00:00
# include <QtGui/QClipboard>
2022-03-04 10:40:03 +00:00
# ifdef _WIN32
# include "common/RedtapeWindows.h"
# endif
2021-12-13 12:12:54 +00:00
# include "common/Assertions.h"
# include "common/Console.h"
2022-04-18 14:58:34 +00:00
# include "common/CrashHandler.h"
2021-12-13 12:12:54 +00:00
# include "common/FileSystem.h"
2022-05-19 14:46:33 +00:00
# include "common/Path.h"
2021-12-13 12:12:54 +00:00
# include "common/SettingsWrapper.h"
# include "common/StringUtil.h"
2022-05-24 14:15:41 +00:00
# include "common/Timer.h"
2021-12-13 12:12:54 +00:00
2022-07-18 22:13:02 +00:00
# include "pcsx2/CDVD/CDVDcommon.h"
2022-05-24 12:02:05 +00:00
# include "pcsx2/DebugTools/Debug.h"
2022-09-07 07:44:10 +00:00
# include "pcsx2/Frontend/CommonHost.h"
2021-12-13 12:12:54 +00:00
# include "pcsx2/Frontend/GameList.h"
# include "pcsx2/Frontend/INISettingsInterface.h"
2022-06-18 09:35:17 +00:00
# include "pcsx2/Frontend/LogSink.h"
2021-12-13 12:12:54 +00:00
# include "pcsx2/HostSettings.h"
# include "pcsx2/PAD/Host/PAD.h"
# include "EmuThread.h"
# include "GameList/GameListWidget.h"
# include "MainWindow.h"
# include "QtHost.h"
2022-08-20 10:20:36 +00:00
# include "QtUtils.h"
2022-05-11 08:24:56 +00:00
# include "svnrev.h"
2021-12-13 12:12:54 +00:00
static constexpr u32 SETTINGS_SAVE_DELAY = 1000 ;
//////////////////////////////////////////////////////////////////////////
// Local function declarations
//////////////////////////////////////////////////////////////////////////
2022-03-04 10:40:03 +00:00
namespace QtHost {
2022-07-09 09:07:28 +00:00
static void PrintCommandLineVersion ( ) ;
static void PrintCommandLineHelp ( const char * progname ) ;
static std : : shared_ptr < VMBootParameters > & AutoBoot ( std : : shared_ptr < VMBootParameters > & autoboot ) ;
static bool ParseCommandLineOptions ( int argc , char * argv [ ] , std : : shared_ptr < VMBootParameters > & autoboot ) ;
2021-12-13 12:12:54 +00:00
static bool InitializeConfig ( ) ;
static void SaveSettings ( ) ;
2022-09-07 07:44:10 +00:00
static void HookSignals ( ) ;
2022-03-04 10:40:03 +00:00
}
2021-12-13 12:12:54 +00:00
//////////////////////////////////////////////////////////////////////////
// Local variable declarations
//////////////////////////////////////////////////////////////////////////
2022-05-24 13:10:39 +00:00
const IConsoleWriter * PatchesCon = & Console ;
2021-12-13 12:12:54 +00:00
static std : : unique_ptr < QTimer > s_settings_save_timer ;
static std : : unique_ptr < INISettingsInterface > s_base_settings_interface ;
2022-05-03 04:26:49 +00:00
static bool s_batch_mode = false ;
2022-07-09 09:14:48 +00:00
static bool s_nogui_mode = false ;
2022-05-15 08:20:21 +00:00
static bool s_start_fullscreen_ui = false ;
static bool s_start_fullscreen_ui_fullscreen = false ;
2021-12-13 12:12:54 +00:00
//////////////////////////////////////////////////////////////////////////
// Initialization/Shutdown
//////////////////////////////////////////////////////////////////////////
2022-09-07 07:44:10 +00:00
bool QtHost : : InitializeConfig ( )
2021-12-13 12:12:54 +00:00
{
2022-09-07 07:44:10 +00:00
if ( ! CommonHost : : InitializeCriticalFolders ( ) )
2021-12-13 12:12:54 +00:00
{
2022-09-07 07:44:10 +00:00
QMessageBox : : critical ( nullptr , QStringLiteral ( " PCSX2 " ) ,
QStringLiteral ( " One or more critical directories are missing, your installation may be incomplete. " ) ) ;
2021-12-13 12:12:54 +00:00
return false ;
}
2022-05-19 14:46:33 +00:00
const std : : string path ( Path : : Combine ( EmuFolders : : Settings , " PCSX2.ini " ) ) ;
2022-05-29 14:22:16 +00:00
Console . WriteLn ( " Loading config from %s. " , path . c_str ( ) ) ;
2022-09-07 07:44:10 +00:00
2021-12-13 12:12:54 +00:00
s_base_settings_interface = std : : make_unique < INISettingsInterface > ( std : : move ( path ) ) ;
Host : : Internal : : SetBaseSettingsLayer ( s_base_settings_interface . get ( ) ) ;
2022-09-07 07:44:10 +00:00
if ( ! s_base_settings_interface - > Load ( ) | | ! CommonHost : : CheckSettingsVersion ( ) )
2021-12-13 12:12:54 +00:00
{
2022-09-07 07:44:10 +00:00
// If the config file doesn't exist, assume this is a new install and don't prompt to overwrite.
if ( FileSystem : : FileExists ( s_base_settings_interface - > GetFileName ( ) . c_str ( ) ) & &
QMessageBox : : question ( nullptr , QStringLiteral ( " PCSX2 " ) ,
QStringLiteral ( " Settings failed to load, or are the incorrect version. Clicking Yes will reset all settings to defaults. Do you want to continue? " ) ) ! = QMessageBox : : Yes )
{
return false ;
}
CommonHost : : SetDefaultSettings ( * s_base_settings_interface , true , true , true , true , true ) ;
SaveSettings ( ) ;
2021-12-13 12:12:54 +00:00
}
2022-09-07 07:44:10 +00:00
CommonHost : : LoadStartupSettings ( ) ;
2022-07-17 14:54:48 +00:00
Host : : UpdateLogging ( QtHost : : InNoGUIMode ( ) ) ;
2021-12-13 12:12:54 +00:00
return true ;
}
2022-09-07 07:44:10 +00:00
void Host : : SetDefaultUISettings ( SettingsInterface & si )
2021-12-13 12:12:54 +00:00
{
2022-09-07 07:44:10 +00:00
Host : : SetDefaultLoggingSettings ( si ) ;
2021-12-13 12:12:54 +00:00
2022-09-07 07:44:10 +00:00
si . SetBoolValue ( " UI " , " InhibitScreensaver " , true ) ;
si . SetBoolValue ( " UI " , " ConfirmShutdown " , true ) ;
si . SetBoolValue ( " UI " , " StartPaused " , false ) ;
si . SetBoolValue ( " UI " , " PauseOnFocusLoss " , false ) ;
si . SetBoolValue ( " UI " , " StartFullscreen " , false ) ;
si . SetBoolValue ( " UI " , " DoubleClickTogglesFullscreen " , true ) ;
si . SetBoolValue ( " UI " , " HideMouseCursor " , false ) ;
si . SetBoolValue ( " UI " , " RenderToSeparateWindow " , false ) ;
si . SetBoolValue ( " UI " , " HideMainWindowWhenRunning " , false ) ;
si . SetBoolValue ( " UI " , " DisableWindowResize " , false ) ;
si . SetStringValue ( " UI " , " Theme " , MainWindow : : DEFAULT_THEME_NAME ) ;
2021-12-13 12:12:54 +00:00
}
2022-03-04 10:40:03 +00:00
void QtHost : : SaveSettings ( )
2021-12-13 12:12:54 +00:00
{
pxAssertRel ( ! g_emu_thread - > isOnEmuThread ( ) , " Saving should happen on the UI thread. " ) ;
{
auto lock = Host : : GetSettingsLock ( ) ;
if ( ! s_base_settings_interface - > Save ( ) )
Console . Error ( " Failed to save settings. " ) ;
}
s_settings_save_timer - > deleteLater ( ) ;
s_settings_save_timer . release ( ) ;
}
2022-09-07 07:44:10 +00:00
void Host : : CommitBaseSettingChanges ( )
2021-12-13 12:12:54 +00:00
{
2022-09-07 07:44:10 +00:00
if ( ! QtHost : : IsOnUIThread ( ) )
{
QtHost : : RunOnUIThread ( & Host : : CommitBaseSettingChanges ) ;
return ;
}
auto lock = Host : : GetSettingsLock ( ) ;
2021-12-13 12:12:54 +00:00
if ( s_settings_save_timer )
return ;
s_settings_save_timer = std : : make_unique < QTimer > ( ) ;
2022-09-07 07:44:10 +00:00
s_settings_save_timer - > connect ( s_settings_save_timer . get ( ) , & QTimer : : timeout , & QtHost : : SaveSettings ) ;
2021-12-13 12:12:54 +00:00
s_settings_save_timer - > setSingleShot ( true ) ;
s_settings_save_timer - > start ( SETTINGS_SAVE_DELAY ) ;
}
2022-05-03 04:26:49 +00:00
bool QtHost : : InBatchMode ( )
{
return s_batch_mode ;
}
2022-07-09 09:14:48 +00:00
bool QtHost : : InNoGUIMode ( )
{
return s_nogui_mode ;
}
2022-09-07 07:44:10 +00:00
bool QtHost : : IsOnUIThread ( )
{
QThread * ui_thread = qApp - > thread ( ) ;
return ( QThread : : currentThread ( ) = = ui_thread ) ;
}
2022-04-06 10:49:00 +00:00
void QtHost : : RunOnUIThread ( const std : : function < void ( ) > & func , bool block /*= false*/ )
{
// main window always exists, so it's fine to attach it to that.
QMetaObject : : invokeMethod ( g_main_window , " runOnUIThread " ,
block ? Qt : : BlockingQueuedConnection : Qt : : QueuedConnection ,
Q_ARG ( const std : : function < void ( ) > & , func ) ) ;
}
2022-09-07 07:44:10 +00:00
bool Host : : RequestResetSettings ( bool folders , bool core , bool controllers , bool hotkeys , bool ui )
{
{
auto lock = Host : : GetSettingsLock ( ) ;
CommonHost : : SetDefaultSettings ( * s_base_settings_interface . get ( ) , folders , core , controllers , hotkeys , ui ) ;
}
Host : : CommitBaseSettingChanges ( ) ;
g_emu_thread - > applySettings ( ) ;
if ( folders )
g_emu_thread - > updateEmuFolders ( ) ;
return true ;
}
2022-05-11 08:24:56 +00:00
QString QtHost : : GetAppNameAndVersion ( )
{
QString ret ;
if constexpr ( ! PCSX2_isReleaseVersion & & GIT_TAGGED_COMMIT )
{
ret = QStringLiteral ( " PCSX2 Nightly - " GIT_TAG ) ;
}
else if constexpr ( PCSX2_isReleaseVersion )
{
# define APPNAME_STRINGIZE(x) #x
ret = QStringLiteral ( " PCSX2 "
APPNAME_STRINGIZE ( PCSX2_VersionHi ) " . "
APPNAME_STRINGIZE ( PCSX2_VersionMid ) " . "
APPNAME_STRINGIZE ( PCSX2_VersionLo ) ) ;
# undef APPNAME_STRINGIZE
}
else
{
return QStringLiteral ( " PCSX2 " GIT_REV ) ;
}
return ret ;
}
QString QtHost : : GetAppConfigSuffix ( )
{
# if defined(PCSX2_DEBUG)
return QStringLiteral ( " [Debug] " ) ;
# elif defined(PCSX2_DEVBUILD)
return QStringLiteral ( " [Devel] " ) ;
# else
return QString ( ) ;
# endif
}
2022-06-04 05:53:31 +00:00
QString QtHost : : GetResourcesBasePath ( )
{
return QString : : fromStdString ( EmuFolders : : Resources ) ;
}
2021-12-13 12:12:54 +00:00
std : : optional < std : : vector < u8 > > Host : : ReadResourceFile ( const char * filename )
{
2022-05-19 14:46:33 +00:00
const std : : string path ( Path : : Combine ( EmuFolders : : Resources , filename ) ) ;
2021-12-13 12:12:54 +00:00
std : : optional < std : : vector < u8 > > ret ( FileSystem : : ReadBinaryFile ( path . c_str ( ) ) ) ;
if ( ! ret . has_value ( ) )
Console . Error ( " Failed to read resource file '%s' " , filename ) ;
return ret ;
}
std : : optional < std : : string > Host : : ReadResourceFileToString ( const char * filename )
{
2022-05-19 14:46:33 +00:00
const std : : string path ( Path : : Combine ( EmuFolders : : Resources , filename ) ) ;
2021-12-13 12:12:54 +00:00
std : : optional < std : : string > ret ( FileSystem : : ReadFileToString ( path . c_str ( ) ) ) ;
if ( ! ret . has_value ( ) )
Console . Error ( " Failed to read resource file to string '%s' " , filename ) ;
return ret ;
}
void Host : : ReportErrorAsync ( const std : : string_view & title , const std : : string_view & message )
{
if ( ! title . empty ( ) & & ! message . empty ( ) )
{
2022-03-20 03:40:47 +00:00
Console . Error ( " ReportErrorAsync: %.*s: %.*s " ,
2021-12-13 12:12:54 +00:00
static_cast < int > ( title . size ( ) ) , title . data ( ) ,
static_cast < int > ( message . size ( ) ) , message . data ( ) ) ;
}
else if ( ! message . empty ( ) )
{
2022-03-20 03:40:47 +00:00
Console . Error ( " ReportErrorAsync: %.*s " ,
2021-12-13 12:12:54 +00:00
static_cast < int > ( message . size ( ) ) , message . data ( ) ) ;
}
QMetaObject : : invokeMethod ( g_main_window , " reportError " , Qt : : QueuedConnection ,
Q_ARG ( const QString & , title . empty ( ) ? QString ( ) : QString : : fromUtf8 ( title . data ( ) , title . size ( ) ) ) ,
Q_ARG ( const QString & , message . empty ( ) ? QString ( ) : QString : : fromUtf8 ( message . data ( ) , message . size ( ) ) ) ) ;
}
2022-08-20 10:20:36 +00:00
bool Host : : ConfirmMessage ( const std : : string_view & title , const std : : string_view & message )
{
const QString qtitle ( QString : : fromUtf8 ( title . data ( ) , title . size ( ) ) ) ;
const QString qmessage ( QString : : fromUtf8 ( message . data ( ) , message . size ( ) ) ) ;
return g_emu_thread - > confirmMessage ( qtitle , qmessage ) ;
}
void Host : : OpenURL ( const std : : string_view & url )
{
QtHost : : RunOnUIThread ( [ url = QtUtils : : StringViewToQString ( url ) ] ( ) {
QtUtils : : OpenURL ( g_main_window , QUrl ( url ) ) ;
} ) ;
}
bool Host : : CopyTextToClipboard ( const std : : string_view & text )
{
QtHost : : RunOnUIThread ( [ text = QtUtils : : StringViewToQString ( text ) ] ( ) {
QClipboard * clipboard = QGuiApplication : : clipboard ( ) ;
if ( clipboard )
clipboard - > setText ( text ) ;
} ) ;
return true ;
}
2021-12-13 12:12:54 +00:00
void Host : : OnInputDeviceConnected ( const std : : string_view & identifier , const std : : string_view & device_name )
{
emit g_emu_thread - > onInputDeviceConnected (
identifier . empty ( ) ? QString ( ) : QString : : fromUtf8 ( identifier . data ( ) , identifier . size ( ) ) ,
device_name . empty ( ) ? QString ( ) : QString : : fromUtf8 ( device_name . data ( ) , device_name . size ( ) ) ) ;
}
void Host : : OnInputDeviceDisconnected ( const std : : string_view & identifier )
{
emit g_emu_thread - > onInputDeviceDisconnected (
identifier . empty ( ) ? QString ( ) : QString : : fromUtf8 ( identifier . data ( ) , identifier . size ( ) ) ) ;
}
//////////////////////////////////////////////////////////////////////////
// Interface Stuff
//////////////////////////////////////////////////////////////////////////
2022-03-04 10:40:03 +00:00
static void SignalHandler ( int signal )
{
// First try the normal (graceful) shutdown/exit.
static bool graceful_shutdown_attempted = false ;
if ( ! graceful_shutdown_attempted & & g_main_window )
{
std : : fprintf ( stderr , " Received CTRL+C, attempting graceful shutdown. Press CTRL+C again to force. \n " ) ;
graceful_shutdown_attempted = true ;
// This could be a bit risky invoking from a signal handler... hopefully it's okay.
QMetaObject : : invokeMethod ( g_main_window , & MainWindow : : requestExit , Qt : : QueuedConnection ) ;
return ;
}
std : : signal ( signal , SIG_DFL ) ;
// MacOS is missing std::quick_exit() despite it being C++11...
# ifndef __APPLE__
std : : quick_exit ( 1 ) ;
# else
_Exit ( 1 ) ;
# endif
}
void QtHost : : HookSignals ( )
{
std : : signal ( SIGINT , SignalHandler ) ;
std : : signal ( SIGTERM , SignalHandler ) ;
}
2022-07-09 09:07:28 +00:00
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 " ) ;
2022-07-09 09:14:48 +00:00
std : : fprintf ( stderr , " -nogui: Hides main window while running (implies batch mode). \n " ) ;
2022-07-09 09:07:28 +00:00
std : : fprintf ( stderr , " -elf <file>: Overrides the boot ELF with the specified filename. \n " ) ;
std : : fprintf ( stderr , " -disc <path>: 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 <index>: Loads specified save state by index. \n " ) ;
std : : fprintf ( stderr , " -statefile <filename>: 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 < VMBootParameters > & QtHost : : AutoBoot ( std : : shared_ptr < VMBootParameters > & autoboot )
{
if ( ! autoboot )
autoboot = std : : make_shared < VMBootParameters > ( ) ;
return autoboot ;
}
bool QtHost : : ParseCommandLineOptions ( int argc , char * argv [ ] , std : : shared_ptr < VMBootParameters > & 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 ;
}
2022-07-09 09:14:48 +00:00
else if ( CHECK_ARG ( " -nogui " ) )
{
s_batch_mode = true ;
s_nogui_mode = true ;
continue ;
}
2022-07-09 09:07:28 +00:00
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 ;
2022-05-15 08:20:21 +00:00
s_start_fullscreen_ui_fullscreen = true ;
2022-07-09 09:07:28 +00:00
continue ;
}
else if ( CHECK_ARG ( " -nofullscreen " ) )
{
AutoBoot ( autoboot ) - > fullscreen = false ;
continue ;
}
else if ( CHECK_ARG ( " -earlyconsolelog " ) )
{
Host : : InitializeEarlyConsole ( ) ;
continue ;
}
2022-05-15 08:20:21 +00:00
else if ( CHECK_ARG ( " -bigpicture " ) )
{
s_start_fullscreen_ui = true ;
continue ;
}
2022-07-09 09:07:28 +00:00
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).
2022-05-15 08:20:21 +00:00
if ( s_batch_mode & & ! s_start_fullscreen_ui & & ! autoboot )
2022-07-09 09:07:28 +00:00
{
2022-07-09 09:14:48 +00:00
QMessageBox : : critical ( nullptr , QStringLiteral ( " Error " ) , s_nogui_mode ?
QStringLiteral ( " Cannot use no-gui mode, because no boot filename was specified. " ) :
QStringLiteral ( " Cannot use batch mode, because no boot filename was specified. " ) ) ;
2022-07-09 09:07:28 +00:00
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 < std : : optional < bool > > ( ) ;
qRegisterMetaType < std : : function < void ( ) > > ( ) ;
qRegisterMetaType < std : : shared_ptr < VMBootParameters > > ( ) ;
qRegisterMetaType < GSRendererType > ( ) ;
qRegisterMetaType < InputBindingKey > ( ) ;
qRegisterMetaType < CDVD_SourceType > ( ) ;
qRegisterMetaType < const GameList : : Entry * > ( ) ;
}
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 < VMBootParameters > autoboot ;
if ( ! QtHost : : ParseCommandLineOptions ( argc , argv , autoboot ) )
return EXIT_FAILURE ;
// Bail out if we can't find any config.
if ( ! QtHost : : InitializeConfig ( ) )
return EXIT_FAILURE ;
2022-07-24 13:52:22 +00:00
// Set theme before creating any windows.
MainWindow : : updateApplicationTheme ( ) ;
2022-07-09 09:07:28 +00:00
MainWindow * main_window = new MainWindow ( QApplication : : style ( ) - > objectName ( ) ) ;
2022-07-24 13:52:22 +00:00
// Start up the CPU thread.
2022-07-09 09:07:28 +00:00
QtHost : : HookSignals ( ) ;
EmuThread : : start ( ) ;
2022-06-23 11:58:14 +00:00
// Create all window objects, the emuthread might still be starting up at this point.
2022-07-09 09:07:28 +00:00
main_window - > initialize ( ) ;
2022-06-23 11:58:14 +00:00
// When running in batch mode, ensure game list is loaded, but don't scan for any new files.
2022-07-09 09:07:28 +00:00
if ( ! s_batch_mode )
main_window - > refreshGameList ( false ) ;
2022-06-23 11:58:14 +00:00
else
GameList : : Refresh ( false , true ) ;
2022-07-09 09:07:28 +00:00
2022-06-23 11:58:14 +00:00
// Don't bother showing the window in no-gui mode.
2022-07-09 09:14:48 +00:00
if ( ! s_nogui_mode )
main_window - > show ( ) ;
2022-07-09 09:07:28 +00:00
2022-05-15 08:20:21 +00:00
// Initialize big picture mode if requested.
if ( s_start_fullscreen_ui )
g_emu_thread - > startFullscreenUI ( s_start_fullscreen_ui_fullscreen ) ;
2022-06-23 11:58:14 +00:00
// Skip the update check if we're booting a game directly.
2022-07-09 09:07:28 +00:00
if ( autoboot )
g_emu_thread - > startVM ( std : : move ( autoboot ) ) ;
2022-05-15 08:20:21 +00:00
else if ( ! s_nogui_mode )
2022-07-09 09:07:28 +00:00
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 ;
}