diff --git a/pcsx2-qt/MainWindow.cpp b/pcsx2-qt/MainWindow.cpp index fd62dd8139..a165b5082e 100644 --- a/pcsx2-qt/MainWindow.cpp +++ b/pcsx2-qt/MainWindow.cpp @@ -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 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() diff --git a/pcsx2-qt/QtHost.cpp b/pcsx2-qt/QtHost.cpp index d71e45bd5b..03e0f8b912 100644 --- a/pcsx2-qt/QtHost.cpp +++ b/pcsx2-qt/QtHost.cpp @@ -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()) diff --git a/pcsx2-qt/QtHost.h b/pcsx2-qt/QtHost.h index c57f8d4c92..aa40243dad 100644 --- a/pcsx2-qt/QtHost.h +++ b/pcsx2-qt/QtHost.h @@ -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(); diff --git a/pcsx2/VMManager.cpp b/pcsx2/VMManager.cpp index 8c90091acd..c6e27c0b16 100644 --- a/pcsx2/VMManager.cpp +++ b/pcsx2/VMManager.cpp @@ -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"); diff --git a/pcsx2/VMManager.h b/pcsx2/VMManager.h index 5701c5aef2..6bdb244f9b 100644 --- a/pcsx2/VMManager.h +++ b/pcsx2/VMManager.h @@ -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);