Qt: Improve boot filename autodetection

This commit is contained in:
Connor McLaughlin 2022-03-13 00:52:52 +10:00 committed by refractionpcsx2
parent 4331ae1925
commit 6a15d46461
5 changed files with 145 additions and 87 deletions

View File

@ -41,7 +41,9 @@ static void PrintCommandLineHelp(const char* 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, " -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, " -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"
@ -64,10 +66,8 @@ static void PrintCommandLineHelp(const char* progname)
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;
}
@ -134,6 +134,12 @@ static bool ParseCommandLineOptions(int argc, char* argv[], std::shared_ptr<VMBo
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("-fullscreen"))
{
Console.WriteLn("Going fullscreen after booting.");
@ -172,12 +178,10 @@ static bool ParseCommandLineOptions(int argc, char* argv[], std::shared_ptr<VMBo
#undef CHECK_ARG_PARAM
}
if (!AutoBoot(autoboot)->source.empty())
AutoBoot(autoboot)->source += ' ';
else
AutoBoot(autoboot)->source_type = CDVD_SourceType::Iso;
if (!AutoBoot(autoboot)->filename.empty())
AutoBoot(autoboot)->filename += ' ';
AutoBoot(autoboot)->source += argv[i];
AutoBoot(autoboot)->filename += argv[i];
}
return true;

View File

@ -608,7 +608,10 @@ void MainWindow::clearProgressBar()
m_ui.statusBar->removeWidget(m_status_progress_widget);
}
bool MainWindow::isShowingGameList() const { return m_ui.mainContainer->currentIndex() == 0; }
bool MainWindow::isShowingGameList() const
{
return m_ui.mainContainer->currentIndex() == 0;
}
void MainWindow::switchToGameListView()
{
@ -641,11 +644,20 @@ void MainWindow::switchToEmulationView()
m_display_widget->setFocus();
}
void MainWindow::refreshGameList(bool invalidate_cache) { m_game_list_widget->refresh(invalidate_cache); }
void MainWindow::refreshGameList(bool invalidate_cache)
{
m_game_list_widget->refresh(invalidate_cache);
}
void MainWindow::invalidateSaveStateCache() { m_save_states_invalidated = true; }
void MainWindow::invalidateSaveStateCache()
{
m_save_states_invalidated = true;
}
void MainWindow::reportError(const QString& title, const QString& message) { QMessageBox::critical(this, title, message); }
void MainWindow::reportError(const QString& title, const QString& message)
{
QMessageBox::critical(this, title, message);
}
bool MainWindow::confirmShutdown()
{
@ -666,7 +678,10 @@ void MainWindow::requestExit()
close();
}
void Host::InvalidateSaveStateCache() { QMetaObject::invokeMethod(g_main_window, &MainWindow::invalidateSaveStateCache, Qt::QueuedConnection); }
void Host::InvalidateSaveStateCache()
{
QMetaObject::invokeMethod(g_main_window, &MainWindow::invalidateSaveStateCache, Qt::QueuedConnection);
}
void MainWindow::onGameListRefreshProgress(const QString& status, int current, int total)
{
@ -674,7 +689,10 @@ void MainWindow::onGameListRefreshProgress(const QString& status, int current, i
setProgressBar(current, total);
}
void MainWindow::onGameListRefreshComplete() { clearProgressBar(); }
void MainWindow::onGameListRefreshComplete()
{
clearProgressBar();
}
void MainWindow::onGameListSelectionChanged()
{
@ -785,14 +803,13 @@ void MainWindow::onStartFileActionTriggered()
return;
std::shared_ptr<VMBootParameters> params = std::make_shared<VMBootParameters>();
VMManager::SetBootParametersForPath(filename.toStdString(), params.get());
params->filename = filename.toStdString();
g_emu_thread->startVM(std::move(params));
}
void MainWindow::onStartBIOSActionTriggered()
{
std::shared_ptr<VMBootParameters> params = std::make_shared<VMBootParameters>();
params->source_type = CDVD_SourceType::NoDisc;
g_emu_thread->startVM(std::move(params));
}
@ -807,7 +824,10 @@ void MainWindow::onChangeDiscFromFileActionTriggered()
g_emu_thread->changeDisc(filename);
}
void MainWindow::onChangeDiscFromGameListActionTriggered() { switchToGameListView(); }
void MainWindow::onChangeDiscFromGameListActionTriggered()
{
switchToGameListView();
}
void MainWindow::onChangeDiscFromDeviceActionTriggered()
{
@ -891,11 +911,20 @@ void MainWindow::onViewGamePropertiesActionTriggered()
SettingsDialog::openGamePropertiesDialog(nullptr, m_current_game_crc);
}
void MainWindow::onGitHubRepositoryActionTriggered() { QtUtils::OpenURL(this, AboutDialog::getGitHubRepositoryUrl()); }
void MainWindow::onGitHubRepositoryActionTriggered()
{
QtUtils::OpenURL(this, AboutDialog::getGitHubRepositoryUrl());
}
void MainWindow::onSupportForumsActionTriggered() { QtUtils::OpenURL(this, AboutDialog::getSupportForumsUrl()); }
void MainWindow::onSupportForumsActionTriggered()
{
QtUtils::OpenURL(this, AboutDialog::getSupportForumsUrl());
}
void MainWindow::onDiscordServerActionTriggered() { QtUtils::OpenURL(this, AboutDialog::getDiscordServerUrl()); }
void MainWindow::onDiscordServerActionTriggered()
{
QtUtils::OpenURL(this, AboutDialog::getDiscordServerUrl());
}
void MainWindow::onAboutActionTriggered()
{
@ -1197,7 +1226,10 @@ void MainWindow::displayResizeRequested(qint32 width, qint32 height)
resize(QSize(std::max<qint32>(width, 1), std::max<qint32>(height + extra_height, 1)));
}
void MainWindow::destroyDisplay() { destroyDisplayWidget(); }
void MainWindow::destroyDisplay()
{
destroyDisplayWidget();
}
void MainWindow::focusDisplayWidget()
{
@ -1404,7 +1436,7 @@ void MainWindow::loadSaveStateFile(const QString& filename, const QString& state
else
{
std::shared_ptr<VMBootParameters> params = std::make_shared<VMBootParameters>();
VMManager::SetBootParametersForPath(filename.toStdString(), params.get());
params->filename = filename.toStdString();
params->save_state = state_filename.toStdString();
g_emu_thread->startVM(std::move(params));
}

View File

@ -123,19 +123,19 @@ void GameList::FillBootParametersForEntry(VMBootParameters* params, const Entry*
{
if (entry->type == GameList::EntryType::PS1Disc || entry->type == GameList::EntryType::PS2Disc)
{
params->source = entry->path;
params->filename = entry->path;
params->source_type = CDVD_SourceType::Iso;
params->elf_override.clear();
}
else if (entry->type == GameList::EntryType::ELF)
{
params->source.clear();
params->filename.clear();
params->source_type = CDVD_SourceType::NoDisc;
params->elf_override = entry->path;
}
else
{
params->source.clear();
params->filename.clear();
params->source_type = CDVD_SourceType::NoDisc;
params->elf_override.clear();
}

View File

@ -75,6 +75,9 @@ namespace VMManager
static void CheckForSPU2ConfigChanges(const Pcsx2Config& old_config);
static void CheckForDEV9ConfigChanges(const Pcsx2Config& old_config);
static void CheckForMemoryCardConfigChanges(const Pcsx2Config& old_config);
static bool AutoDetectSource(const std::string& filename);
static bool ApplyBootParameters(const VMBootParameters& params);
static void UpdateRunningGame(bool force);
static std::string GetCurrentSaveStateFileName(s32 slot);
@ -519,30 +522,86 @@ static LimiterModeType GetInitialLimiterMode()
return EmuConfig.GS.FrameLimitEnable ? LimiterModeType::Nominal : LimiterModeType::Unlimited;
}
static void ApplyBootParameters(const VMBootParameters& params)
bool VMManager::AutoDetectSource(const std::string& filename)
{
if (!filename.empty())
{
if (!FileSystem::FileExists(filename.c_str()))
{
Host::ReportFormattedErrorAsync("Error", "Requested filename '%s' does not exist.", filename.c_str());
return false;
}
const std::string display_name(FileSystem::GetDisplayNameFromPath(filename));
if (IsGSDumpFileName(display_name))
{
CDVDsys_ChangeSource(CDVD_SourceType::NoDisc);
return GSDumpReplayer::Initialize(filename.c_str());
}
else if (IsElfFileName(display_name))
{
// alternative way of booting an elf, change the elf override, and use no disc.
CDVDsys_ChangeSource(CDVD_SourceType::NoDisc);
s_elf_override = filename;
return true;
}
else
{
// TODO: Maybe we should check if it's a valid iso here...
CDVDsys_SetFile(CDVD_SourceType::Iso, filename);
CDVDsys_ChangeSource(CDVD_SourceType::Iso);
s_disc_path = filename;
return true;
}
}
else
{
// make sure we're not fast booting when we have no filename
CDVDsys_ChangeSource(CDVD_SourceType::NoDisc);
EmuConfig.UseBOOT2Injection = false;
return true;
}
}
bool VMManager::ApplyBootParameters(const VMBootParameters& params)
{
const bool default_fast_boot = Host::GetBoolSettingValue("EmuCore", "EnableFastBoot", true);
EmuConfig.UseBOOT2Injection =
(params.source_type != CDVD_SourceType::NoDisc && params.fast_boot.value_or(default_fast_boot));
EmuConfig.UseBOOT2Injection = params.fast_boot.value_or(default_fast_boot);
s_elf_override = params.elf_override;
s_disc_path.clear();
CDVDsys_SetFile(CDVD_SourceType::Iso, params.source);
CDVDsys_ChangeSource(params.source_type);
if (!params.elf_override.empty())
if (params.source_type.has_value())
{
Hle_SetElfPath(params.elf_override.c_str());
s_elf_override = std::move(params.elf_override);
if (params.source_type.value() == CDVD_SourceType::Iso && !FileSystem::FileExists(params.filename.c_str()))
{
Host::ReportFormattedErrorAsync("Error", "Requested filename '%s' does not exist.", params.filename.c_str());
return false;
}
// Use specified source type.
CDVDsys_SetFile(params.source_type.value(), params.filename);
CDVDsys_ChangeSource(params.source_type.value());
}
else
{
// Automatic type detection of boot parameter based on filename.
if (!AutoDetectSource(params.filename))
return false;
}
if (!s_elf_override.empty())
{
if (!FileSystem::FileExists(s_elf_override.c_str()))
{
Host::ReportFormattedErrorAsync("Error", "Requested boot ELF '%s' does not exist.", s_elf_override.c_str());
return false;
}
Hle_SetElfPath(s_elf_override.c_str());
EmuConfig.UseBOOT2Injection = true;
}
else
{
std::string().swap(s_elf_override);
}
if (params.source_type == CDVD_SourceType::Iso)
s_disc_path = params.source;
else
s_disc_path.clear();
return true;
}
bool VMManager::Initialize(const VMBootParameters& boot_params)
@ -559,16 +618,8 @@ bool VMManager::Initialize(const VMBootParameters& boot_params)
LoadSettings();
if (IsGSDumpFileName(boot_params.source))
{
CDVDsys_ChangeSource(CDVD_SourceType::NoDisc);
if (!GSDumpReplayer::Initialize(boot_params.source.c_str()))
return false;
}
else
{
ApplyBootParameters(boot_params);
}
if (!ApplyBootParameters(boot_params))
return false;
EmuConfig.LimiterMode = GetInitialLimiterMode();
@ -949,11 +1000,7 @@ bool VMManager::ChangeDisc(std::string path)
bool VMManager::IsElfFileName(const std::string& path)
{
const std::string::size_type pos = path.rfind('.');
if (pos == std::string::npos)
return false;
return (StringUtil::Strcasecmp(&path[pos], ".elf") == 0);
return StringUtil::EndsWithNoCase(path, ".elf");
}
bool VMManager::IsGSDumpFileName(const std::string& path)
@ -961,29 +1008,6 @@ bool VMManager::IsGSDumpFileName(const std::string& path)
return (StringUtil::EndsWithNoCase(path, ".gs") || StringUtil::EndsWithNoCase(path, ".gs.xz"));
}
void VMManager::SetBootParametersForPath(const std::string& path, VMBootParameters* params)
{
if (IsElfFileName(path))
{
params->elf_override = path;
params->source_type = CDVD_SourceType::NoDisc;
}
else if (IsGSDumpFileName(path))
{
params->source_type = CDVD_SourceType::NoDisc;
params->source = path;
}
else if (!path.empty())
{
params->source_type = CDVD_SourceType::Iso;
params->source = path;
}
else
{
params->source_type = CDVD_SourceType::NoDisc;
}
}
void VMManager::Execute()
{
Cpu->Execute();

View File

@ -39,10 +39,11 @@ enum class VMState
struct VMBootParameters
{
std::string source;
std::string save_state;
CDVD_SourceType source_type;
std::string filename;
std::string elf_override;
std::string save_state;
std::optional<CDVD_SourceType> source_type;
std::optional<bool> fast_boot;
std::optional<bool> fullscreen;
std::optional<bool> batch_mode;
@ -138,9 +139,6 @@ namespace VMManager
/// Returns true if the specified path is a GS Dump.
bool IsGSDumpFileName(const std::string& path);
/// Updates boot parameters for a given start filename. If it's an elf, it'll set elf_override, otherwise source.
void SetBootParametersForPath(const std::string& path, VMBootParameters* params);
/// Returns the path for the game settings ini file for the specified CRC.
std::string GetGameSettingsPath(u32 game_crc);