mirror of https://github.com/PCSX2/pcsx2.git
Qt: Implement more command line arguments
This commit is contained in:
parent
119b6bdfd5
commit
378588c67d
|
@ -143,16 +143,15 @@ void EmuThread::setVMPaused(bool paused)
|
|||
VMManager::SetPaused(paused);
|
||||
}
|
||||
|
||||
bool EmuThread::shutdownVM(bool allow_save_to_state /* = true */)
|
||||
void EmuThread::shutdownVM(bool allow_save_to_state /* = true */)
|
||||
{
|
||||
const VMState state = VMManager::GetState();
|
||||
if (state == VMState::Paused)
|
||||
m_event_loop->quit();
|
||||
else if (state != VMState::Running)
|
||||
return true;
|
||||
return;
|
||||
|
||||
VMManager::SetState(VMState::Stopping);
|
||||
return true;
|
||||
}
|
||||
|
||||
void EmuThread::loadState(const QString& filename)
|
||||
|
|
|
@ -59,7 +59,7 @@ public Q_SLOTS:
|
|||
void startVM(std::shared_ptr<VMBootParameters> boot_params);
|
||||
void resetVM();
|
||||
void setVMPaused(bool paused);
|
||||
bool shutdownVM(bool allow_save_to_state = true);
|
||||
void shutdownVM(bool allow_save_to_state = true);
|
||||
void loadState(const QString& filename);
|
||||
void loadStateFromSlot(qint32 slot);
|
||||
void saveState(const QString& filename);
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
static void PrintCommandLineVersion()
|
||||
{
|
||||
QtHost::InitializeEarlyConsole();
|
||||
std::fprintf(stderr, "PCSX2 Version %s\n", GIT_REV);
|
||||
std::fprintf(stderr, "https://pcsx2.net/\n");
|
||||
std::fprintf(stderr, "\n");
|
||||
|
@ -46,19 +47,13 @@ static void PrintCommandLineHelp(const char* progname)
|
|||
std::fprintf(stderr, " -batch: Enables batch mode (exits after shutting down).\n");
|
||||
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, " -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, " -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, " -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");
|
||||
|
@ -75,10 +70,6 @@ static std::shared_ptr<VMBootParameters>& AutoBoot(std::shared_ptr<VMBootParamet
|
|||
|
||||
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++)
|
||||
|
@ -100,30 +91,22 @@ static bool ParseCommandLineOptions(int argc, char* argv[], std::shared_ptr<VMBo
|
|||
}
|
||||
else if (CHECK_ARG("-batch"))
|
||||
{
|
||||
Console.WriteLn("Enabling batch mode.");
|
||||
AutoBoot(autoboot)->batch_mode = true;
|
||||
QtHost::SetBatchMode(true);
|
||||
continue;
|
||||
}
|
||||
else if (CHECK_ARG("-fastboot"))
|
||||
{
|
||||
Console.WriteLn("Forcing fast boot.");
|
||||
fast_boot = true;
|
||||
AutoBoot(autoboot)->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;
|
||||
AutoBoot(autoboot)->fast_boot = false;
|
||||
continue;
|
||||
}
|
||||
else if (CHECK_ARG_PARAM("-state"))
|
||||
{
|
||||
state_index = std::atoi(argv[++i]);
|
||||
AutoBoot(autoboot)->state_index = std::atoi(argv[++i]);
|
||||
continue;
|
||||
}
|
||||
else if (CHECK_ARG_PARAM("-statefile"))
|
||||
|
@ -142,27 +125,19 @@ static bool ParseCommandLineOptions(int argc, char* argv[], std::shared_ptr<VMBo
|
|||
AutoBoot(autoboot)->filename = argv[++i];
|
||||
continue;
|
||||
}
|
||||
else if (CHECK_ARG("-bios"))
|
||||
{
|
||||
AutoBoot(autoboot)->source_type = CDVD_SourceType::NoDisc;
|
||||
continue;
|
||||
}
|
||||
else if (CHECK_ARG("-fullscreen"))
|
||||
{
|
||||
Console.WriteLn("Going fullscreen after booting.");
|
||||
start_fullscreen = true;
|
||||
AutoBoot(autoboot)->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;
|
||||
AutoBoot(autoboot)->fullscreen = false;
|
||||
continue;
|
||||
}
|
||||
else if (CHECK_ARG("--"))
|
||||
|
@ -172,7 +147,8 @@ static bool ParseCommandLineOptions(int argc, char* argv[], std::shared_ptr<VMBo
|
|||
}
|
||||
else if (argv[i][0] == '-')
|
||||
{
|
||||
Console.Error("Unknown parameter: '%s'", argv[i]);
|
||||
QtHost::InitializeEarlyConsole();
|
||||
std::fprintf(stderr, "Unknown parameter: '%s'", argv[i]);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -186,6 +162,24 @@ static bool ParseCommandLineOptions(int argc, char* argv[], std::shared_ptr<VMBo
|
|||
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())
|
||||
{
|
||||
QtHost::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)
|
||||
{
|
||||
QtHost::InitializeEarlyConsole();
|
||||
Console.Warning("Disabling batch mode, because we have no autoboot.");
|
||||
QtHost::SetBatchMode(false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -213,7 +207,10 @@ int main(int argc, char* argv[])
|
|||
main_window->initialize();
|
||||
EmuThread::start();
|
||||
|
||||
main_window->refreshGameList(false);
|
||||
// skip scanning the game list when running in batch mode
|
||||
if (!QtHost::InBatchMode())
|
||||
main_window->refreshGameList(false);
|
||||
|
||||
main_window->show();
|
||||
|
||||
if (autoboot)
|
||||
|
|
|
@ -720,13 +720,19 @@ bool MainWindow::requestShutdown(bool allow_confirm /* = true */, bool allow_sav
|
|||
|
||||
g_emu_thread->shutdownVM(allow_save_to_state);
|
||||
|
||||
if (block_until_done)
|
||||
if (block_until_done || QtHost::InBatchMode())
|
||||
{
|
||||
// we need to yield here, since the display gets destroyed
|
||||
while (VMManager::HasValidVM())
|
||||
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents, 1);
|
||||
}
|
||||
|
||||
if (QtHost::InBatchMode())
|
||||
{
|
||||
// closing the window should shut down everything.
|
||||
close();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -68,6 +68,7 @@ static void SaveSettings();
|
|||
//////////////////////////////////////////////////////////////////////////
|
||||
static std::unique_ptr<QTimer> s_settings_save_timer;
|
||||
static std::unique_ptr<INISettingsInterface> s_base_settings_interface;
|
||||
static bool s_batch_mode = false;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Initialization/Shutdown
|
||||
|
@ -377,6 +378,16 @@ void QtHost::QueueSettingsSave()
|
|||
s_settings_save_timer->start(SETTINGS_SAVE_DELAY);
|
||||
}
|
||||
|
||||
bool QtHost::InBatchMode()
|
||||
{
|
||||
return s_batch_mode;
|
||||
}
|
||||
|
||||
void QtHost::SetBatchMode(bool enabled)
|
||||
{
|
||||
s_batch_mode = enabled;
|
||||
}
|
||||
|
||||
void QtHost::RunOnUIThread(const std::function<void()>& func, bool block /*= false*/)
|
||||
{
|
||||
// main window always exists, so it's fine to attach it to that.
|
||||
|
|
|
@ -45,6 +45,10 @@ namespace QtHost
|
|||
/// Initializes early console logging (for printing command line arguments).
|
||||
void InitializeEarlyConsole();
|
||||
|
||||
/// 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<void()>& func, bool block = false);
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ namespace GameList
|
|||
static Entry* GetMutableEntryForPath(const char* path);
|
||||
|
||||
static bool GetElfListEntry(const std::string& path, GameList::Entry* entry);
|
||||
static bool GetGameListEntry(const std::string& path, GameList::Entry* entry);
|
||||
static bool GetIsoListEntry(const std::string& path, GameList::Entry* entry);
|
||||
|
||||
static bool GetGameListEntryFromCache(const std::string& path, GameList::Entry* entry);
|
||||
static void ScanDirectory(const char* path, bool recursive, const std::vector<std::string>& excluded_paths,
|
||||
|
@ -169,11 +169,8 @@ bool GameList::GetElfListEntry(const std::string& path, GameList::Entry* entry)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool GameList::GetGameListEntry(const std::string& path, GameList::Entry* entry)
|
||||
bool GameList::GetIsoListEntry(const std::string& path, GameList::Entry* entry)
|
||||
{
|
||||
if (VMManager::IsElfFileName(path.c_str()))
|
||||
return GetElfListEntry(path.c_str(), entry);
|
||||
|
||||
FILESYSTEM_STAT_DATA sd;
|
||||
if (!FileSystem::StatFile(path.c_str(), &sd))
|
||||
return false;
|
||||
|
@ -241,6 +238,14 @@ bool GameList::GetGameListEntry(const std::string& path, GameList::Entry* entry)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool GameList::PopulateEntryFromPath(const std::string& path, GameList::Entry* entry)
|
||||
{
|
||||
if (VMManager::IsElfFileName(path.c_str()))
|
||||
return GetElfListEntry(path, entry);
|
||||
else
|
||||
return GetIsoListEntry(path, entry);
|
||||
}
|
||||
|
||||
bool GameList::GetGameListEntryFromCache(const std::string& path, GameList::Entry* entry)
|
||||
{
|
||||
auto iter = m_cache_map.find(path);
|
||||
|
@ -529,7 +534,7 @@ bool GameList::ScanFile(std::string path, std::time_t timestamp)
|
|||
DevCon.WriteLn("Scanning '%s'...", path.c_str());
|
||||
|
||||
Entry entry;
|
||||
if (!GetGameListEntry(path, &entry))
|
||||
if (!PopulateEntryFromPath(path, &entry))
|
||||
return false;
|
||||
|
||||
entry.path = std::move(path);
|
||||
|
|
|
@ -76,6 +76,10 @@ namespace GameList
|
|||
/// Fills in boot parameters (iso or elf) based on the game list entry.
|
||||
void FillBootParametersForEntry(VMBootParameters* params, const Entry* entry);
|
||||
|
||||
/// Populates a game list entry struct with information from the iso/elf.
|
||||
/// Do *not* call while the system is running, it will mess with CDVD state.
|
||||
bool PopulateEntryFromPath(const std::string& path, GameList::Entry* entry);
|
||||
|
||||
// Game list access. It's the caller's responsibility to hold the lock while manipulating the entry in any way.
|
||||
std::unique_lock<std::recursive_mutex> GetLock();
|
||||
const Entry* GetEntryByIndex(u32 index);
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
|
||||
#include "Frontend/INISettingsInterface.h"
|
||||
#include "Frontend/InputManager.h"
|
||||
#include "Frontend/GameList.h"
|
||||
|
||||
#include "common/emitter/tools.h"
|
||||
#ifdef _M_X86
|
||||
|
@ -78,7 +79,7 @@ namespace VMManager
|
|||
static void CheckForMemoryCardConfigChanges(const Pcsx2Config& old_config);
|
||||
|
||||
static bool AutoDetectSource(const std::string& filename);
|
||||
static bool ApplyBootParameters(const VMBootParameters& params);
|
||||
static bool ApplyBootParameters(const VMBootParameters& params, std::string* state_to_load);
|
||||
static bool CheckBIOSAvailability();
|
||||
static void UpdateRunningGame(bool force);
|
||||
|
||||
|
@ -515,14 +516,53 @@ bool VMManager::AutoDetectSource(const std::string& filename)
|
|||
}
|
||||
}
|
||||
|
||||
bool VMManager::ApplyBootParameters(const VMBootParameters& params)
|
||||
bool VMManager::ApplyBootParameters(const VMBootParameters& params, std::string* state_to_load)
|
||||
{
|
||||
const bool default_fast_boot = Host::GetBoolSettingValue("EmuCore", "EnableFastBoot", true);
|
||||
EmuConfig.UseBOOT2Injection = params.fast_boot.value_or(default_fast_boot);
|
||||
|
||||
s_elf_override = params.elf_override;
|
||||
s_disc_path.clear();
|
||||
if (!params.save_state.empty())
|
||||
*state_to_load = params.save_state;
|
||||
|
||||
// if we're loading an indexed save state, we need to get the serial/crc from the disc.
|
||||
if (params.state_index.has_value())
|
||||
{
|
||||
if (params.filename.empty())
|
||||
{
|
||||
Host::ReportErrorAsync("Error", "Cannot load an indexed save state without a boot filename.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// try the game list first, but this won't work if we're in batch mode
|
||||
{
|
||||
auto lock = GameList::GetLock();
|
||||
if (const GameList::Entry* entry = GameList::GetEntryForPath(params.filename.c_str()); entry)
|
||||
{
|
||||
*state_to_load = GetSaveStateFileName(entry->serial.c_str(), entry->crc, params.state_index.value());
|
||||
}
|
||||
else
|
||||
{
|
||||
// just scan it.. hopefully it'll come back okay
|
||||
GameList::Entry temp_entry;
|
||||
if (!GameList::PopulateEntryFromPath(params.filename.c_str(), &temp_entry))
|
||||
{
|
||||
Host::ReportFormattedErrorAsync("Error", "Could not scan path '%s' for indexed save state load.", params.filename.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
*state_to_load = GetSaveStateFileName(temp_entry.serial.c_str(), temp_entry.crc, params.state_index.value());
|
||||
}
|
||||
if (state_to_load->empty())
|
||||
{
|
||||
Host::ReportFormattedErrorAsync("Error", "Could not resolve path indexed save state load.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// resolve source type
|
||||
if (params.source_type.has_value())
|
||||
{
|
||||
if (params.source_type.value() == CDVD_SourceType::Iso && !FileSystem::FileExists(params.filename.c_str()))
|
||||
|
@ -591,7 +631,8 @@ bool VMManager::Initialize(const VMBootParameters& boot_params)
|
|||
|
||||
LoadSettings();
|
||||
|
||||
if (!ApplyBootParameters(boot_params))
|
||||
std::string state_to_load;
|
||||
if (!ApplyBootParameters(boot_params, &state_to_load))
|
||||
return false;
|
||||
|
||||
EmuConfig.LimiterMode = GetInitialLimiterMode();
|
||||
|
@ -727,9 +768,9 @@ bool VMManager::Initialize(const VMBootParameters& boot_params)
|
|||
PerformanceMetrics::Clear();
|
||||
|
||||
// do we want to load state?
|
||||
if (!GSDumpReplayer::IsReplayingDump() && !boot_params.save_state.empty())
|
||||
if (!GSDumpReplayer::IsReplayingDump() && !state_to_load.empty())
|
||||
{
|
||||
if (!DoLoadState(boot_params.save_state.c_str()))
|
||||
if (!DoLoadState(state_to_load.c_str()))
|
||||
{
|
||||
Shutdown();
|
||||
return false;
|
||||
|
|
|
@ -42,11 +42,11 @@ struct VMBootParameters
|
|||
std::string filename;
|
||||
std::string elf_override;
|
||||
std::string save_state;
|
||||
std::optional<s32> state_index;
|
||||
std::optional<CDVD_SourceType> source_type;
|
||||
|
||||
std::optional<bool> fast_boot;
|
||||
std::optional<bool> fullscreen;
|
||||
std::optional<bool> batch_mode;
|
||||
};
|
||||
|
||||
namespace VMManager
|
||||
|
|
Loading…
Reference in New Issue