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, "\n");
std::fprintf(stderr, " -help: Displays this information and exits.\n"); std::fprintf(stderr, " -help: Displays this information and exits.\n");
std::fprintf(stderr, " -version: Displays version 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, " -fastboot: Force fast boot for provided filename.\n");
std::fprintf(stderr, " -slowboot: Force slow 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" 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) static std::shared_ptr<VMBootParameters>& AutoBoot(std::shared_ptr<VMBootParameters>& autoboot)
{ {
if (!autoboot) if (!autoboot)
{
autoboot = std::make_shared<VMBootParameters>(); autoboot = std::make_shared<VMBootParameters>();
autoboot->source_type = CDVD_SourceType::NoDisc;
}
return autoboot; return autoboot;
} }
@ -134,6 +134,12 @@ static bool ParseCommandLineOptions(int argc, char* argv[], std::shared_ptr<VMBo
AutoBoot(autoboot)->elf_override = argv[++i]; AutoBoot(autoboot)->elf_override = argv[++i];
continue; 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")) else if (CHECK_ARG("-fullscreen"))
{ {
Console.WriteLn("Going fullscreen after booting."); 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 #undef CHECK_ARG_PARAM
} }
if (!AutoBoot(autoboot)->source.empty()) if (!AutoBoot(autoboot)->filename.empty())
AutoBoot(autoboot)->source += ' '; AutoBoot(autoboot)->filename += ' ';
else
AutoBoot(autoboot)->source_type = CDVD_SourceType::Iso;
AutoBoot(autoboot)->source += argv[i]; AutoBoot(autoboot)->filename += argv[i];
} }
return true; return true;

View File

@ -608,7 +608,10 @@ void MainWindow::clearProgressBar()
m_ui.statusBar->removeWidget(m_status_progress_widget); 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() void MainWindow::switchToGameListView()
{ {
@ -641,11 +644,20 @@ void MainWindow::switchToEmulationView()
m_display_widget->setFocus(); 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() bool MainWindow::confirmShutdown()
{ {
@ -666,7 +678,10 @@ void MainWindow::requestExit()
close(); 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) 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); setProgressBar(current, total);
} }
void MainWindow::onGameListRefreshComplete() { clearProgressBar(); } void MainWindow::onGameListRefreshComplete()
{
clearProgressBar();
}
void MainWindow::onGameListSelectionChanged() void MainWindow::onGameListSelectionChanged()
{ {
@ -785,14 +803,13 @@ void MainWindow::onStartFileActionTriggered()
return; return;
std::shared_ptr<VMBootParameters> params = std::make_shared<VMBootParameters>(); 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)); g_emu_thread->startVM(std::move(params));
} }
void MainWindow::onStartBIOSActionTriggered() void MainWindow::onStartBIOSActionTriggered()
{ {
std::shared_ptr<VMBootParameters> params = std::make_shared<VMBootParameters>(); std::shared_ptr<VMBootParameters> params = std::make_shared<VMBootParameters>();
params->source_type = CDVD_SourceType::NoDisc;
g_emu_thread->startVM(std::move(params)); g_emu_thread->startVM(std::move(params));
} }
@ -807,7 +824,10 @@ void MainWindow::onChangeDiscFromFileActionTriggered()
g_emu_thread->changeDisc(filename); g_emu_thread->changeDisc(filename);
} }
void MainWindow::onChangeDiscFromGameListActionTriggered() { switchToGameListView(); } void MainWindow::onChangeDiscFromGameListActionTriggered()
{
switchToGameListView();
}
void MainWindow::onChangeDiscFromDeviceActionTriggered() void MainWindow::onChangeDiscFromDeviceActionTriggered()
{ {
@ -891,11 +911,20 @@ void MainWindow::onViewGamePropertiesActionTriggered()
SettingsDialog::openGamePropertiesDialog(nullptr, m_current_game_crc); 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() 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))); 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() void MainWindow::focusDisplayWidget()
{ {
@ -1404,7 +1436,7 @@ void MainWindow::loadSaveStateFile(const QString& filename, const QString& state
else else
{ {
std::shared_ptr<VMBootParameters> params = std::make_shared<VMBootParameters>(); 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(); params->save_state = state_filename.toStdString();
g_emu_thread->startVM(std::move(params)); 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) 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->source_type = CDVD_SourceType::Iso;
params->elf_override.clear(); params->elf_override.clear();
} }
else if (entry->type == GameList::EntryType::ELF) else if (entry->type == GameList::EntryType::ELF)
{ {
params->source.clear(); params->filename.clear();
params->source_type = CDVD_SourceType::NoDisc; params->source_type = CDVD_SourceType::NoDisc;
params->elf_override = entry->path; params->elf_override = entry->path;
} }
else else
{ {
params->source.clear(); params->filename.clear();
params->source_type = CDVD_SourceType::NoDisc; params->source_type = CDVD_SourceType::NoDisc;
params->elf_override.clear(); params->elf_override.clear();
} }

View File

@ -75,6 +75,9 @@ namespace VMManager
static void CheckForSPU2ConfigChanges(const Pcsx2Config& old_config); static void CheckForSPU2ConfigChanges(const Pcsx2Config& old_config);
static void CheckForDEV9ConfigChanges(const Pcsx2Config& old_config); static void CheckForDEV9ConfigChanges(const Pcsx2Config& old_config);
static void CheckForMemoryCardConfigChanges(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 void UpdateRunningGame(bool force);
static std::string GetCurrentSaveStateFileName(s32 slot); static std::string GetCurrentSaveStateFileName(s32 slot);
@ -519,30 +522,86 @@ static LimiterModeType GetInitialLimiterMode()
return EmuConfig.GS.FrameLimitEnable ? LimiterModeType::Nominal : LimiterModeType::Unlimited; 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); const bool default_fast_boot = Host::GetBoolSettingValue("EmuCore", "EnableFastBoot", true);
EmuConfig.UseBOOT2Injection = EmuConfig.UseBOOT2Injection = params.fast_boot.value_or(default_fast_boot);
(params.source_type != CDVD_SourceType::NoDisc && 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); if (params.source_type.has_value())
CDVDsys_ChangeSource(params.source_type);
if (!params.elf_override.empty())
{ {
Hle_SetElfPath(params.elf_override.c_str()); if (params.source_type.value() == CDVD_SourceType::Iso && !FileSystem::FileExists(params.filename.c_str()))
s_elf_override = std::move(params.elf_override); {
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; EmuConfig.UseBOOT2Injection = true;
} }
else
{
std::string().swap(s_elf_override);
}
if (params.source_type == CDVD_SourceType::Iso) return true;
s_disc_path = params.source;
else
s_disc_path.clear();
} }
bool VMManager::Initialize(const VMBootParameters& boot_params) bool VMManager::Initialize(const VMBootParameters& boot_params)
@ -559,16 +618,8 @@ bool VMManager::Initialize(const VMBootParameters& boot_params)
LoadSettings(); LoadSettings();
if (IsGSDumpFileName(boot_params.source)) if (!ApplyBootParameters(boot_params))
{ return false;
CDVDsys_ChangeSource(CDVD_SourceType::NoDisc);
if (!GSDumpReplayer::Initialize(boot_params.source.c_str()))
return false;
}
else
{
ApplyBootParameters(boot_params);
}
EmuConfig.LimiterMode = GetInitialLimiterMode(); EmuConfig.LimiterMode = GetInitialLimiterMode();
@ -949,11 +1000,7 @@ bool VMManager::ChangeDisc(std::string path)
bool VMManager::IsElfFileName(const std::string& path) bool VMManager::IsElfFileName(const std::string& path)
{ {
const std::string::size_type pos = path.rfind('.'); return StringUtil::EndsWithNoCase(path, ".elf");
if (pos == std::string::npos)
return false;
return (StringUtil::Strcasecmp(&path[pos], ".elf") == 0);
} }
bool VMManager::IsGSDumpFileName(const std::string& path) 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")); 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() void VMManager::Execute()
{ {
Cpu->Execute(); Cpu->Execute();

View File

@ -39,10 +39,11 @@ enum class VMState
struct VMBootParameters struct VMBootParameters
{ {
std::string source; std::string filename;
std::string save_state;
CDVD_SourceType source_type;
std::string elf_override; std::string elf_override;
std::string save_state;
std::optional<CDVD_SourceType> source_type;
std::optional<bool> fast_boot; std::optional<bool> fast_boot;
std::optional<bool> fullscreen; std::optional<bool> fullscreen;
std::optional<bool> batch_mode; std::optional<bool> batch_mode;
@ -138,9 +139,6 @@ namespace VMManager
/// Returns true if the specified path is a GS Dump. /// Returns true if the specified path is a GS Dump.
bool IsGSDumpFileName(const std::string& path); 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. /// Returns the path for the game settings ini file for the specified CRC.
std::string GetGameSettingsPath(u32 game_crc); std::string GetGameSettingsPath(u32 game_crc);