mirror of https://github.com/PCSX2/pcsx2.git
264 lines
7.5 KiB
C++
264 lines
7.5 KiB
C++
|
/* 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"
|
||
|
|
||
|
#include <QtWidgets/QApplication>
|
||
|
#include <cstdlib>
|
||
|
|
||
|
#include "MainWindow.h"
|
||
|
#include "EmuThread.h"
|
||
|
#include "QtHost.h"
|
||
|
|
||
|
#include "CDVD/CDVD.h"
|
||
|
#include "Frontend/GameList.h"
|
||
|
#include "svnrev.h"
|
||
|
|
||
|
static void PrintCommandLineVersion()
|
||
|
{
|
||
|
std::fprintf(stderr, "PCSX2 Version %s\n", GIT_REV);
|
||
|
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 powering off).\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, " -resume: Load resume save state. If a boot filename is provided,\n"
|
||
|
" that game's resume state will be loaded, otherwise the most\n"
|
||
|
" recent resume save state will be loaded.\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"
|
||
|
" No boot filename is required with this option.\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, " -portable: Forces \"portable mode\", data in same directory.\n");
|
||
|
std::fprintf(stderr, " -settings <filename>: Loads a custom settings configuration from the\n"
|
||
|
" specified filename. Default settings applied if file not found.\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<VMBootParameters>& AutoBoot(std::shared_ptr<VMBootParameters>& autoboot)
|
||
|
{
|
||
|
if (!autoboot)
|
||
|
{
|
||
|
autoboot = std::make_shared<VMBootParameters>();
|
||
|
autoboot->source_type = CDVD_SourceType::NoDisc;
|
||
|
}
|
||
|
return autoboot;
|
||
|
}
|
||
|
|
||
|
static bool ParseCommandLineOptions(int argc, char* argv[], std::shared_ptr<VMBootParameters>& autoboot)
|
||
|
{
|
||
|
std::optional<bool> fast_boot;
|
||
|
std::optional<bool> start_fullscreen;
|
||
|
std::optional<s32> state_index;
|
||
|
std::string state_filename;
|
||
|
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"))
|
||
|
{
|
||
|
Console.WriteLn("Enabling batch mode.");
|
||
|
AutoBoot(autoboot)->batch_mode = true;
|
||
|
continue;
|
||
|
}
|
||
|
else if (CHECK_ARG("-fastboot"))
|
||
|
{
|
||
|
Console.WriteLn("Forcing fast boot.");
|
||
|
fast_boot = true;
|
||
|
continue;
|
||
|
}
|
||
|
else if (CHECK_ARG("-slowboot"))
|
||
|
{
|
||
|
Console.WriteLn("Forcing slow boot.");
|
||
|
fast_boot = false;
|
||
|
continue;
|
||
|
}
|
||
|
else if (CHECK_ARG("-resume"))
|
||
|
{
|
||
|
state_index = -1;
|
||
|
continue;
|
||
|
}
|
||
|
else if (CHECK_ARG_PARAM("-state"))
|
||
|
{
|
||
|
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("-fullscreen"))
|
||
|
{
|
||
|
Console.WriteLn("Going fullscreen after booting.");
|
||
|
start_fullscreen = true;
|
||
|
continue;
|
||
|
}
|
||
|
else if (CHECK_ARG("-nofullscreen"))
|
||
|
{
|
||
|
Console.WriteLn("Preventing fullscreen after booting.");
|
||
|
start_fullscreen = false;
|
||
|
continue;
|
||
|
}
|
||
|
else if (CHECK_ARG("-portable"))
|
||
|
{
|
||
|
Console.WriteLn("Using portable mode.");
|
||
|
// SetUserDirectoryToProgramDirectory();
|
||
|
continue;
|
||
|
}
|
||
|
else if (CHECK_ARG("-resume"))
|
||
|
{
|
||
|
state_index = -1;
|
||
|
continue;
|
||
|
}
|
||
|
else if (CHECK_ARG("--"))
|
||
|
{
|
||
|
no_more_args = true;
|
||
|
continue;
|
||
|
}
|
||
|
else if (argv[i][0] == '-')
|
||
|
{
|
||
|
Console.Error("Unknown parameter: '%s'", argv[i]);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
#undef CHECK_ARG
|
||
|
#undef CHECK_ARG_PARAM
|
||
|
}
|
||
|
|
||
|
if (!AutoBoot(autoboot)->source.empty())
|
||
|
AutoBoot(autoboot)->source += ' ';
|
||
|
else
|
||
|
AutoBoot(autoboot)->source_type = CDVD_SourceType::Iso;
|
||
|
|
||
|
AutoBoot(autoboot)->source += argv[i];
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
int main(int argc, char* argv[])
|
||
|
{
|
||
|
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||
|
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||
|
QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
||
|
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
QApplication app(argc, argv);
|
||
|
std::shared_ptr<VMBootParameters> 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;
|
||
|
}
|
||
|
|
||
|
main_window->initialize();
|
||
|
EmuThread::start();
|
||
|
|
||
|
main_window->refreshGameList(false);
|
||
|
main_window->show();
|
||
|
|
||
|
if (autoboot)
|
||
|
g_emu_thread->startVM(std::move(autoboot));
|
||
|
|
||
|
const int result = app.exec();
|
||
|
|
||
|
EmuThread::stop();
|
||
|
QtHost::Shutdown();
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
#ifdef _WIN32
|
||
|
|
||
|
// Apparently Qt6 got rid of this?
|
||
|
#include "common/RedtapeWindows.h"
|
||
|
#include <shellapi.h>
|
||
|
|
||
|
/*
|
||
|
WinMain() - Initializes Windows and calls user's startup function main().
|
||
|
NOTE: WinMain() won't be called if the application was linked as a "console"
|
||
|
application.
|
||
|
*/
|
||
|
|
||
|
// Convert a wchar_t to char string, equivalent to QString::toLocal8Bit()
|
||
|
// when passed CP_ACP.
|
||
|
static inline char* wideToMulti(unsigned int codePage, const wchar_t* aw)
|
||
|
{
|
||
|
const int required = WideCharToMultiByte(codePage, 0, aw, -1, nullptr, 0, nullptr, nullptr);
|
||
|
char* result = new char[required];
|
||
|
WideCharToMultiByte(codePage, 0, aw, -1, result, required, nullptr, nullptr);
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
extern "C" int APIENTRY WinMain(HINSTANCE, HINSTANCE, LPSTR /*cmdParamarg*/, int /* cmdShow */)
|
||
|
{
|
||
|
int argc = 0;
|
||
|
wchar_t** argvW = CommandLineToArgvW(GetCommandLineW(), &argc);
|
||
|
if (argvW == nullptr)
|
||
|
return -1;
|
||
|
char** argv = new char*[argc + 1];
|
||
|
for (int i = 0; i != argc; ++i)
|
||
|
argv[i] = wideToMulti(CP_ACP, argvW[i]);
|
||
|
argv[argc] = nullptr;
|
||
|
LocalFree(argvW);
|
||
|
const int exitCode = main(argc, argv);
|
||
|
for (int i = 0; (i != argc) && (argv[i] != nullptr); ++i)
|
||
|
delete[] argv[i];
|
||
|
delete[] argv;
|
||
|
return exitCode;
|
||
|
}
|
||
|
|
||
|
#endif
|