Qt: Improve file drop handling

Allow switching ELF.

Closes #7681.
This commit is contained in:
Stenzek 2023-09-09 15:37:31 +10:00 committed by Connor McLaughlin
parent 90c6e4cd1b
commit 126c6e1b6c
5 changed files with 121 additions and 27 deletions

View File

@ -1820,25 +1820,61 @@ void MainWindow::dropEvent(QDropEvent* event)
const std::string filename_str(filename.toStdString());
if (VMManager::IsSaveStateFileName(filename_str))
{
event->acceptProposedAction();
// can't load a save state without a current VM
if (s_vm_valid)
{
event->acceptProposedAction();
g_emu_thread->loadState(filename);
}
else
{
QMessageBox::critical(this, tr("Load State Failed"), tr("Cannot load a save state without a running VM."));
}
return;
}
else if (VMManager::IsLoadableFileName(filename_str))
if (!VMManager::IsLoadableFileName(filename_str))
return;
// if we're already running, do a disc change, otherwise start
if (!s_vm_valid)
{
// if we're already running, do a disc change, otherwise start
event->acceptProposedAction();
if (s_vm_valid)
doDiscChange(CDVD_SourceType::Iso, filename);
else
doStartFile(std::nullopt, filename);
doStartFile(std::nullopt, filename);
return;
}
if (VMManager::IsDiscFileName(filename_str) || VMManager::IsBlockDumpFileName(filename_str))
{
event->acceptProposedAction();
doDiscChange(CDVD_SourceType::Iso, filename);
}
else if (VMManager::IsElfFileName(filename_str))
{
const auto lock = pauseAndLockVM();
event->acceptProposedAction();
if (QMessageBox::question(this, tr("Confirm Reset"),
tr("The new ELF cannot be loaded without resetting the virtual machine. Do you want to reset the virtual machine now?")) !=
QMessageBox::Yes)
{
return;
}
g_emu_thread->setELFOverride(filename);
switchToEmulationView();
}
else if (VMManager::IsGSDumpFileName(filename_str))
{
event->acceptProposedAction();
if (!GSDumpReplayer::IsReplayingDump())
{
QMessageBox::critical(this, tr("Error"), tr("Cannot change from game to GS dump without shutting down first."));
return;
}
g_emu_thread->changeGSDump(filename);
switchToEmulationView();
}
}
@ -2610,7 +2646,7 @@ void MainWindow::doStartFile(std::optional<CDVD_SourceType> source, const QStrin
void MainWindow::doDiscChange(CDVD_SourceType source, const QString& path)
{
bool reset_system = false;
if (!m_was_disc_change_request && !GSDumpReplayer::IsReplayingDump())
if (!m_was_disc_change_request)
{
QMessageBox message(QMessageBox::Question, tr("Confirm Disc Change"),
tr("Do you want to swap discs or boot the new image (via system reset)?"), QMessageBox::NoButton, this);
@ -2629,7 +2665,13 @@ void MainWindow::doDiscChange(CDVD_SourceType source, const QString& path)
g_emu_thread->changeDisc(source, path);
if (reset_system)
g_emu_thread->resetVM();
{
// Clearing ELF override will reset the system.
if (!m_current_elf_override.isEmpty())
g_emu_thread->setELFOverride(QString());
else
g_emu_thread->resetVM();
}
}
MainWindow::VMLock MainWindow::pauseAndLockVM()

View File

@ -669,6 +669,34 @@ void EmuThread::changeDisc(CDVD_SourceType source, const QString& path)
VMManager::ChangeDisc(source, path.toStdString());
}
void EmuThread::setELFOverride(const QString& path)
{
if (!isOnEmuThread())
{
QMetaObject::invokeMethod(this, "setELFOverride", Qt::QueuedConnection, Q_ARG(const QString&, path));
return;
}
if (!VMManager::HasValidVM())
return;
VMManager::SetELFOverride(path.toStdString());
}
void EmuThread::changeGSDump(const QString& path)
{
if (!isOnEmuThread())
{
QMetaObject::invokeMethod(this, "changeGSDump", Qt::QueuedConnection, Q_ARG(const QString&, path));
return;
}
if (!VMManager::HasValidVM())
return;
VMManager::ChangeGSDump(path.toStdString());
}
void EmuThread::reloadPatches()
{
if (!isOnEmuThread())

View File

@ -106,6 +106,8 @@ public Q_SLOTS:
void toggleSoftwareRendering();
void switchRenderer(GSRendererType renderer);
void changeDisc(CDVD_SourceType source, const QString& path);
void setELFOverride(const QString& path);
void changeGSDump(const QString& path);
void reloadPatches();
void reloadInputSources();
void reloadInputBindings();

View File

@ -1923,20 +1923,6 @@ void VMManager::FrameAdvance(u32 num_frames /*= 1*/)
bool VMManager::ChangeDisc(CDVD_SourceType source, std::string path)
{
if (GSDumpReplayer::IsReplayingDump())
{
if (!GSDumpReplayer::ChangeDump(path.c_str()))
return false;
UpdateDiscDetails(false);
return true;
}
else if (IsGSDumpFileName(path))
{
Host::ReportErrorAsync("Error", "Cannot change from game to GS dump without shutting down first.");
return false;
}
const CDVD_SourceType old_type = CDVDsys_GetSourceType();
const std::string old_path(CDVDsys_GetFile(old_type));
@ -1983,6 +1969,36 @@ bool VMManager::ChangeDisc(CDVD_SourceType source, std::string path)
return result;
}
bool VMManager::SetELFOverride(std::string path)
{
if (!HasValidVM() || (!path.empty() && !FileSystem::FileExists(path.c_str())))
return false;
s_elf_override = std::move(path);
UpdateDiscDetails(false);
s_fast_boot_requested = !s_elf_override.empty() || EmuConfig.EnableFastBoot;
if (s_elf_override.empty())
Hle_ClearElfPath();
else
Hle_SetElfPath(s_elf_override.c_str());
Reset();
return true;
}
bool VMManager::ChangeGSDump(const std::string& path)
{
if (!HasValidVM() || !GSDumpReplayer::IsReplayingDump() || !IsGSDumpFileName(path))
return false;
if (!GSDumpReplayer::ChangeDump(path.c_str()))
return false;
UpdateDiscDetails(false);
return true;
}
bool VMManager::IsElfFileName(const std::string_view& path)
{
return StringUtil::EndsWithNoCase(path, ".elf");

View File

@ -164,6 +164,12 @@ namespace VMManager
/// Returns false if the new disc can't be opened.
bool ChangeDisc(CDVD_SourceType source, std::string path);
/// Changes the ELF to boot ("ELF override"). The VM will be reset.
bool SetELFOverride(std::string path);
/// Changes the current GS dump being played back.
bool ChangeGSDump(const std::string& path);
/// Returns true if the specified path is an ELF.
bool IsElfFileName(const std::string_view& path);