mirror of
https://github.com/PCSX2/pcsx2.git
synced 2025-12-16 04:08:48 +00:00
CDVD: Synchronise access from different threads
Some checks failed
🐧 Linux Builds / AppImage (push) Has been cancelled
🐧 Linux Builds / Flatpak (push) Has been cancelled
🍎 MacOS Builds / Defaults (push) Has been cancelled
🖥️ Windows Builds / Lint VS Project Files (push) Has been cancelled
🖥️ Windows Builds / CMake (push) Has been cancelled
🖥️ Windows Builds / SSE4 (push) Has been cancelled
🖥️ Windows Builds / AVX2 (push) Has been cancelled
🏭 Update Controller Database / update-controller-db (push) Has been cancelled
Some checks failed
🐧 Linux Builds / AppImage (push) Has been cancelled
🐧 Linux Builds / Flatpak (push) Has been cancelled
🍎 MacOS Builds / Defaults (push) Has been cancelled
🖥️ Windows Builds / Lint VS Project Files (push) Has been cancelled
🖥️ Windows Builds / CMake (push) Has been cancelled
🖥️ Windows Builds / SSE4 (push) Has been cancelled
🖥️ Windows Builds / AVX2 (push) Has been cancelled
🏭 Update Controller Database / update-controller-db (push) Has been cancelled
This commit is contained in:
parent
d02f30ee62
commit
a98cfcf28c
@ -4,14 +4,17 @@
|
||||
#include "GameListRefreshThread.h"
|
||||
|
||||
#include "pcsx2/GameList.h"
|
||||
#include "pcsx2/Host.h"
|
||||
|
||||
#include "common/Assertions.h"
|
||||
#include "common/Console.h"
|
||||
#include "common/ProgressCallback.h"
|
||||
#include "common/Timer.h"
|
||||
|
||||
#include <QtWidgets/QMessageBox>
|
||||
|
||||
AsyncRefreshProgressCallback::AsyncRefreshProgressCallback(GameListRefreshThread* parent)
|
||||
AsyncRefreshProgressCallback::AsyncRefreshProgressCallback(bool popup_on_error, GameListRefreshThread* parent)
|
||||
: m_parent(parent)
|
||||
, m_popup_on_error(popup_on_error)
|
||||
{
|
||||
}
|
||||
|
||||
@ -57,17 +60,20 @@ void AsyncRefreshProgressCallback::SetTitle(const char* title)
|
||||
|
||||
void AsyncRefreshProgressCallback::DisplayError(const char* message)
|
||||
{
|
||||
QMessageBox::critical(nullptr, QStringLiteral("Error"), QString::fromUtf8(message));
|
||||
if (m_popup_on_error)
|
||||
Host::ReportErrorAsync(TRANSLATE_SV("GameListRefreshThread", "Error"), message);
|
||||
else
|
||||
ERROR_LOG("{}", message);
|
||||
}
|
||||
|
||||
void AsyncRefreshProgressCallback::DisplayWarning(const char* message)
|
||||
{
|
||||
QMessageBox::warning(nullptr, QStringLiteral("Warning"), QString::fromUtf8(message));
|
||||
pxFailRel("Not implemented.");
|
||||
}
|
||||
|
||||
void AsyncRefreshProgressCallback::DisplayInformation(const char* message)
|
||||
{
|
||||
QMessageBox::information(nullptr, QStringLiteral("Information"), QString::fromUtf8(message));
|
||||
pxFailRel("Not implemented.");
|
||||
}
|
||||
|
||||
void AsyncRefreshProgressCallback::DisplayDebugMessage(const char* message)
|
||||
@ -77,17 +83,18 @@ void AsyncRefreshProgressCallback::DisplayDebugMessage(const char* message)
|
||||
|
||||
void AsyncRefreshProgressCallback::ModalError(const char* message)
|
||||
{
|
||||
QMessageBox::critical(nullptr, QStringLiteral("Error"), QString::fromUtf8(message));
|
||||
pxFailRel("Not implemented.");
|
||||
}
|
||||
|
||||
bool AsyncRefreshProgressCallback::ModalConfirmation(const char* message)
|
||||
{
|
||||
return QMessageBox::question(nullptr, QStringLiteral("Question"), QString::fromUtf8(message)) == QMessageBox::Yes;
|
||||
pxFailRel("Not implemented.");
|
||||
return false;
|
||||
}
|
||||
|
||||
void AsyncRefreshProgressCallback::ModalInformation(const char* message)
|
||||
{
|
||||
QMessageBox::information(nullptr, QStringLiteral("Information"), QString::fromUtf8(message));
|
||||
pxFailRel("Not implemented.");
|
||||
}
|
||||
|
||||
void AsyncRefreshProgressCallback::fireUpdate()
|
||||
@ -95,9 +102,9 @@ void AsyncRefreshProgressCallback::fireUpdate()
|
||||
m_parent->refreshProgress(m_status_text, m_last_value, m_last_range);
|
||||
}
|
||||
|
||||
GameListRefreshThread::GameListRefreshThread(bool invalidate_cache)
|
||||
GameListRefreshThread::GameListRefreshThread(bool invalidate_cache, bool popup_on_error)
|
||||
: QThread()
|
||||
, m_progress(this)
|
||||
, m_progress(popup_on_error, this)
|
||||
, m_invalidate_cache(invalidate_cache)
|
||||
{
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@ class GameListRefreshThread;
|
||||
class AsyncRefreshProgressCallback : public BaseProgressCallback
|
||||
{
|
||||
public:
|
||||
AsyncRefreshProgressCallback(GameListRefreshThread* parent);
|
||||
AsyncRefreshProgressCallback(bool popup_on_error, GameListRefreshThread* parent);
|
||||
|
||||
void Cancel();
|
||||
|
||||
@ -38,6 +38,7 @@ private:
|
||||
QString m_status_text;
|
||||
int m_last_range = 1;
|
||||
int m_last_value = 0;
|
||||
bool m_popup_on_error = false;
|
||||
};
|
||||
|
||||
class GameListRefreshThread final : public QThread
|
||||
@ -45,7 +46,7 @@ class GameListRefreshThread final : public QThread
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GameListRefreshThread(bool invalidate_cache);
|
||||
GameListRefreshThread(bool invalidate_cache, bool popup_on_error);
|
||||
~GameListRefreshThread();
|
||||
|
||||
void cancel();
|
||||
@ -60,4 +61,5 @@ protected:
|
||||
private:
|
||||
AsyncRefreshProgressCallback m_progress;
|
||||
bool m_invalidate_cache;
|
||||
bool m_popup_on_error;
|
||||
};
|
||||
|
||||
@ -294,7 +294,7 @@ void GameListWidget::initialize()
|
||||
m_empty_ui.setupUi(m_empty_widget);
|
||||
m_empty_ui.supportedFormats->setText(qApp->translate("GameListWidget", SUPPORTED_FORMATS_STRING));
|
||||
connect(m_empty_ui.addGameDirectory, &QPushButton::clicked, this, [this]() { emit addGameDirectoryRequested(); });
|
||||
connect(m_empty_ui.scanForNewGames, &QPushButton::clicked, this, [this]() { refresh(false); });
|
||||
connect(m_empty_ui.scanForNewGames, &QPushButton::clicked, this, [this]() { refresh(false, true); });
|
||||
connect(qApp, &QGuiApplication::applicationStateChanged, this, [this]() { GameListWidget::updateCustomBackgroundState(); });
|
||||
m_ui.stack->insertWidget(2, m_empty_widget);
|
||||
|
||||
@ -453,11 +453,11 @@ bool GameListWidget::getShowGridCoverTitles() const
|
||||
return m_model->getShowCoverTitles();
|
||||
}
|
||||
|
||||
void GameListWidget::refresh(bool invalidate_cache)
|
||||
void GameListWidget::refresh(bool invalidate_cache, bool popup_on_error)
|
||||
{
|
||||
cancelRefresh();
|
||||
|
||||
m_refresh_thread = new GameListRefreshThread(invalidate_cache);
|
||||
m_refresh_thread = new GameListRefreshThread(invalidate_cache, popup_on_error);
|
||||
connect(m_refresh_thread, &GameListRefreshThread::refreshProgress, this, &GameListWidget::onRefreshProgress,
|
||||
Qt::QueuedConnection);
|
||||
connect(m_refresh_thread, &GameListRefreshThread::refreshComplete, this, &GameListWidget::onRefreshComplete,
|
||||
|
||||
@ -46,7 +46,7 @@ public:
|
||||
void initialize();
|
||||
void resizeTableViewColumnsToFit();
|
||||
|
||||
void refresh(bool invalidate_cache);
|
||||
void refresh(bool invalidate_cache, bool popup_on_error);
|
||||
void cancelRefresh();
|
||||
void reloadThemeSpecificImages();
|
||||
void setCustomBackground(bool force = false);
|
||||
|
||||
@ -357,8 +357,8 @@ void MainWindow::connectSignals()
|
||||
[this]() { doControllerSettings(ControllerSettingsWindow::Category::HotkeySettings); });
|
||||
connect(m_ui.actionAddGameDirectory, &QAction::triggered,
|
||||
[this]() { getSettingsWindow()->getGameListSettingsWidget()->addSearchDirectory(this); });
|
||||
connect(m_ui.actionScanForNewGames, &QAction::triggered, [this]() { refreshGameList(false); });
|
||||
connect(m_ui.actionRescanAllGames, &QAction::triggered, [this]() { refreshGameList(true); });
|
||||
connect(m_ui.actionScanForNewGames, &QAction::triggered, [this]() { refreshGameList(false, true); });
|
||||
connect(m_ui.actionRescanAllGames, &QAction::triggered, [this]() { refreshGameList(true, true); });
|
||||
connect(m_ui.actionViewToolbar, &QAction::toggled, this, &MainWindow::onViewToolbarActionToggled);
|
||||
connect(m_ui.actionViewLockToolbar, &QAction::toggled, this, &MainWindow::onViewLockToolbarActionToggled);
|
||||
connect(m_ui.actionViewStatusBar, &QAction::toggled, this, &MainWindow::onViewStatusBarActionToggled);
|
||||
@ -547,7 +547,7 @@ void MainWindow::recreate()
|
||||
MainWindow* new_main_window = new MainWindow();
|
||||
pxAssert(g_main_window == new_main_window);
|
||||
new_main_window->initialize();
|
||||
new_main_window->refreshGameList(false);
|
||||
new_main_window->refreshGameList(false, false);
|
||||
new_main_window->show();
|
||||
deleteLater();
|
||||
|
||||
@ -1137,7 +1137,7 @@ bool MainWindow::shouldMouseLock() const
|
||||
if (!Host::GetBoolSettingValue("EmuCore", "EnableMouseLock", false))
|
||||
return false;
|
||||
|
||||
if(m_display_created == false || m_display_widget == nullptr && !isRenderingToMain())
|
||||
if (m_display_created == false || m_display_widget == nullptr && !isRenderingToMain())
|
||||
return false;
|
||||
|
||||
bool windowsHidden = (!g_debugger_window || g_debugger_window->isHidden()) &&
|
||||
@ -1146,7 +1146,7 @@ bool MainWindow::shouldMouseLock() const
|
||||
|
||||
auto* displayWindow = isRenderingToMain() ? window() : m_display_widget->window();
|
||||
|
||||
if(displayWindow == nullptr)
|
||||
if (displayWindow == nullptr)
|
||||
return false;
|
||||
|
||||
return windowsHidden && (displayWindow->isActiveWindow() || displayWindow->isFullScreen());
|
||||
@ -1215,13 +1215,9 @@ void MainWindow::switchToEmulationView()
|
||||
m_display_widget->setFocus();
|
||||
}
|
||||
|
||||
void MainWindow::refreshGameList(bool invalidate_cache)
|
||||
void MainWindow::refreshGameList(bool invalidate_cache, bool popup_on_error)
|
||||
{
|
||||
// can't do this while the VM is running because of CDVD
|
||||
if (s_vm_valid)
|
||||
return;
|
||||
|
||||
m_game_list_widget->refresh(invalidate_cache);
|
||||
m_game_list_widget->refresh(invalidate_cache, popup_on_error);
|
||||
}
|
||||
|
||||
void MainWindow::cancelGameListRefresh()
|
||||
@ -1466,8 +1462,7 @@ void MainWindow::onGameListEntryContextMenuRequested(const QPoint& point)
|
||||
const time_t entry_played_time = GameList::GetCachedPlayedTimeForSerial(entry->serial);
|
||||
// Best two options given zero play time are to grey this out or to not show it at all.
|
||||
if (entry_played_time)
|
||||
connect(menu.addAction(tr("Reset Play Time")), &QAction::triggered, [this, entry, entry_played_time]()
|
||||
{ clearGameListEntryPlayTime(entry, entry_played_time); });
|
||||
connect(menu.addAction(tr("Reset Play Time")), &QAction::triggered, [this, entry, entry_played_time]() { clearGameListEntryPlayTime(entry, entry_played_time); });
|
||||
|
||||
// Check Wiki Page functionality is based on a serial redirect.
|
||||
if (!entry->serial.empty())
|
||||
@ -2102,7 +2097,7 @@ void MainWindow::onVMStopped()
|
||||
|
||||
// reload played time
|
||||
if (m_game_list_widget->isShowingGameList())
|
||||
m_game_list_widget->refresh(false);
|
||||
m_game_list_widget->refresh(false, false);
|
||||
}
|
||||
|
||||
void MainWindow::onGameChanged(const QString& title, const QString& elf_override, const QString& disc_path,
|
||||
@ -2932,12 +2927,12 @@ void MainWindow::clearGameListEntryPlayTime(const GameList::Entry* entry, const
|
||||
if (QMessageBox::question(this, tr("Confirm Reset"),
|
||||
tr("Are you sure you want to reset the play time for '%1' (%2)?\n\nYour current play time is %3.\n\nThis action cannot be undone.")
|
||||
.arg(entry->title.empty() ? tr("empty title") : QString::fromStdString(entry->title),
|
||||
entry->serial.empty() ? tr("no serial") : QString::fromStdString(entry->serial),
|
||||
QString::fromStdString(GameList::FormatTimespan(entry_played_time, true))),
|
||||
(QMessageBox::Yes | QMessageBox::No), QMessageBox::No) == QMessageBox::Yes)
|
||||
entry->serial.empty() ? tr("no serial") : QString::fromStdString(entry->serial),
|
||||
QString::fromStdString(GameList::FormatTimespan(entry_played_time, true))),
|
||||
(QMessageBox::Yes | QMessageBox::No), QMessageBox::No) == QMessageBox::Yes)
|
||||
{
|
||||
GameList::ClearPlayedTimeForSerial(entry->serial);
|
||||
m_game_list_widget->refresh(false);
|
||||
m_game_list_widget->refresh(false, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -113,7 +113,7 @@ public:
|
||||
void checkMousePosition(int x, int y);
|
||||
public Q_SLOTS:
|
||||
void checkForUpdates(bool display_message, bool force_check);
|
||||
void refreshGameList(bool invalidate_cache);
|
||||
void refreshGameList(bool invalidate_cache, bool popup_on_error);
|
||||
void cancelGameListRefresh();
|
||||
void reportInfo(const QString& title, const QString& message);
|
||||
void reportError(const QString& title, const QString& message);
|
||||
|
||||
@ -1152,7 +1152,7 @@ void Host::OpenHostFileSelectorAsync(std::string_view title, bool select_directo
|
||||
if (!filters.empty())
|
||||
{
|
||||
filters_str.append(QStringLiteral("All File Types (%1)")
|
||||
.arg(QString::fromStdString(StringUtil::JoinString(filters.begin(), filters.end(), " "))));
|
||||
.arg(QString::fromStdString(StringUtil::JoinString(filters.begin(), filters.end(), " "))));
|
||||
for (const std::string& filter : filters)
|
||||
{
|
||||
filters_str.append(
|
||||
@ -2385,7 +2385,7 @@ int main(int argc, char* argv[])
|
||||
|
||||
// When running in batch mode, ensure game list is loaded, but don't scan for any new files.
|
||||
if (!s_batch_mode)
|
||||
g_main_window->refreshGameList(false);
|
||||
g_main_window->refreshGameList(false, false);
|
||||
else
|
||||
GameList::Refresh(false, true);
|
||||
|
||||
|
||||
@ -63,7 +63,7 @@ bool GameListSettingsWidget::addExcludedPath(const std::string& path)
|
||||
|
||||
Host::CommitBaseSettingChanges();
|
||||
m_ui.excludedPaths->addItem(QString::fromStdString(path));
|
||||
g_main_window->refreshGameList(false);
|
||||
g_main_window->refreshGameList(false, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -152,7 +152,7 @@ void GameListSettingsWidget::addSearchDirectory(const QString& path, bool recurs
|
||||
Host::AddBaseValueToStringList("GameList", recursive ? "RecursivePaths" : "Paths", spath.c_str());
|
||||
Host::CommitBaseSettingChanges();
|
||||
refreshDirectoryList();
|
||||
g_main_window->refreshGameList(false);
|
||||
g_main_window->refreshGameList(false, true);
|
||||
}
|
||||
|
||||
void GameListSettingsWidget::removeSearchDirectory(const QString& path)
|
||||
@ -166,7 +166,7 @@ void GameListSettingsWidget::removeSearchDirectory(const QString& path)
|
||||
|
||||
Host::CommitBaseSettingChanges();
|
||||
refreshDirectoryList();
|
||||
g_main_window->refreshGameList(false);
|
||||
g_main_window->refreshGameList(false, true);
|
||||
}
|
||||
|
||||
void GameListSettingsWidget::onDirectoryListContextMenuRequested(const QPoint& point)
|
||||
@ -261,7 +261,7 @@ void GameListSettingsWidget::onRemoveExcludedPathButtonClicked()
|
||||
|
||||
delete item;
|
||||
|
||||
g_main_window->refreshGameList(false);
|
||||
g_main_window->refreshGameList(false, true);
|
||||
}
|
||||
|
||||
void GameListSettingsWidget::onExcludedPathsSelectionChanged()
|
||||
@ -271,10 +271,10 @@ void GameListSettingsWidget::onExcludedPathsSelectionChanged()
|
||||
|
||||
void GameListSettingsWidget::onRescanAllGamesClicked()
|
||||
{
|
||||
g_main_window->refreshGameList(true);
|
||||
g_main_window->refreshGameList(true, true);
|
||||
}
|
||||
|
||||
void GameListSettingsWidget::onScanForNewGamesClicked()
|
||||
{
|
||||
g_main_window->refreshGameList(false);
|
||||
g_main_window->refreshGameList(false, true);
|
||||
}
|
||||
|
||||
@ -280,7 +280,8 @@ void GameSummaryWidget::onVerifyClicked()
|
||||
Error error;
|
||||
if (!hasher.Open(m_entry_path, &error))
|
||||
{
|
||||
setVerifyResult(QString::fromStdString(error.GetDescription()));
|
||||
QString message(QString::fromStdString(error.GetDescription()));
|
||||
QMessageBox::critical(QtUtils::GetRootWidget(this), tr("Error"), message);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -21,6 +21,7 @@
|
||||
#include <ctype.h>
|
||||
#include <exception>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <time.h>
|
||||
|
||||
#include "fmt/format.h"
|
||||
@ -270,6 +271,23 @@ static void DetectDiskType()
|
||||
|
||||
static std::string m_SourceFilename[3];
|
||||
static CDVD_SourceType m_CurrentSourceType = CDVD_SourceType::NoDisc;
|
||||
static std::mutex s_cdvd_lock;
|
||||
|
||||
bool cdvdLock(Error* error)
|
||||
{
|
||||
if (!s_cdvd_lock.try_lock())
|
||||
{
|
||||
Error::SetString(error, TRANSLATE_STR("CDVD", "The CDVD system is currently in use."));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void cdvdUnlock()
|
||||
{
|
||||
s_cdvd_lock.unlock();
|
||||
}
|
||||
|
||||
void CDVDsys_SetFile(CDVD_SourceType srctype, std::string newfile)
|
||||
{
|
||||
@ -579,7 +597,7 @@ static s32 NODISCdummyS32()
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void NODISCnewDiskCB(void (*/* callback */)())
|
||||
static void NODISCnewDiskCB(void (* /* callback */)())
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@ -20,7 +20,6 @@ struct cdvdTrackIndex
|
||||
u8 discM; // current minute location on the disc (BCD encoded)
|
||||
u8 discS; // current sector location on the disc (BCD encoded)
|
||||
u8 discF; // current frame location on the disc (BCD encoded)
|
||||
|
||||
};
|
||||
|
||||
struct cdvdTrack
|
||||
@ -188,6 +187,13 @@ extern u8 strack;
|
||||
extern u8 etrack;
|
||||
extern std::array<cdvdTrack, 100> tracks;
|
||||
|
||||
/// Try to take the CDVD lock, return false if it's already in use.
|
||||
/// Must be called before your first CDVD call.
|
||||
extern bool cdvdLock(Error* error = nullptr);
|
||||
|
||||
/// Release the CDVD lock. Must be called after you're done with CDVD.
|
||||
extern void cdvdUnlock();
|
||||
|
||||
extern void CDVDsys_ChangeSource(CDVD_SourceType type);
|
||||
extern void CDVDsys_SetFile(CDVD_SourceType srctype, std::string newfile);
|
||||
extern const std::string& CDVDsys_GetFile(CDVD_SourceType srctype);
|
||||
|
||||
@ -7,7 +7,6 @@
|
||||
|
||||
#include "common/Error.h"
|
||||
#include "common/MD5Digest.h"
|
||||
#include "common/StringUtil.h"
|
||||
|
||||
#include "fmt/format.h"
|
||||
|
||||
@ -39,6 +38,10 @@ bool IsoHasher::Open(std::string iso_path, Error* error)
|
||||
{
|
||||
Close();
|
||||
|
||||
m_is_locked = cdvdLock(error);
|
||||
if (!m_is_locked)
|
||||
return false;
|
||||
|
||||
CDVDsys_SetFile(CDVD_SourceType::Iso, std::move(iso_path));
|
||||
CDVDsys_ChangeSource(CDVD_SourceType::Iso);
|
||||
|
||||
@ -103,6 +106,12 @@ bool IsoHasher::Open(std::string iso_path, Error* error)
|
||||
|
||||
void IsoHasher::Close()
|
||||
{
|
||||
if (!m_is_locked)
|
||||
return;
|
||||
|
||||
cdvdUnlock();
|
||||
m_is_locked = false;
|
||||
|
||||
if (!m_is_open)
|
||||
return;
|
||||
|
||||
@ -151,7 +160,7 @@ bool IsoHasher::ComputeTrackHash(Track& track, ProgressCallback* callback)
|
||||
const u32 update_interval = std::max<u32>(track.sectors / 100u, 1u);
|
||||
callback->SetStatusText(
|
||||
fmt::format(TRANSLATE_FS("CDVD", "Calculating checksum for track {}..."), track.number).c_str());
|
||||
callback->SetProgressRange(track.sectors);
|
||||
callback->SetProgressRange(track.sectors);
|
||||
|
||||
MD5Digest md5;
|
||||
for (u32 i = 0; i < track.sectors; i++)
|
||||
|
||||
@ -28,6 +28,9 @@ public:
|
||||
IsoHasher();
|
||||
~IsoHasher();
|
||||
|
||||
IsoHasher(const IsoHasher&) = delete;
|
||||
IsoHasher& operator=(const IsoHasher&) = delete;
|
||||
|
||||
static std::string_view GetTrackTypeString(u32 type);
|
||||
|
||||
u32 GetTrackCount() const { return static_cast<u32>(m_tracks.size()); }
|
||||
@ -44,6 +47,7 @@ private:
|
||||
bool ComputeTrackHash(Track& track, ProgressCallback* callback);
|
||||
|
||||
std::vector<Track> m_tracks;
|
||||
bool m_is_locked = false;
|
||||
bool m_is_open = false;
|
||||
bool m_is_cd = false;
|
||||
};
|
||||
|
||||
@ -163,6 +163,9 @@ void SymbolImporter::Reset()
|
||||
|
||||
void SymbolImporter::LoadAndAnalyseElf(Pcsx2Config::DebugAnalysisOptions options)
|
||||
{
|
||||
if (!VMManager::HasValidVM())
|
||||
return;
|
||||
|
||||
const std::string& elf_path = VMManager::GetCurrentELF();
|
||||
|
||||
Error error;
|
||||
@ -192,6 +195,9 @@ void SymbolImporter::AnalyseElf(
|
||||
Pcsx2Config::DebugAnalysisOptions options,
|
||||
bool wait_until_elf_is_loaded)
|
||||
{
|
||||
if (!VMManager::HasValidVM())
|
||||
return;
|
||||
|
||||
// Search for a .sym file to load symbols from.
|
||||
std::string nocash_path;
|
||||
CDVD_SourceType source_type = CDVDsys_GetSourceType();
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
#include "common/HeterogeneousContainers.h"
|
||||
#include "common/Path.h"
|
||||
#include "common/ProgressCallback.h"
|
||||
#include "common/ScopedGuard.h"
|
||||
#include "common/StringUtil.h"
|
||||
|
||||
#include <algorithm>
|
||||
@ -826,6 +827,15 @@ void GameList::Refresh(bool invalidate_cache, bool only_cache, ProgressCallback*
|
||||
if (!progress)
|
||||
progress = ProgressCallback::NullProgressCallback;
|
||||
|
||||
Error cdvd_lock_error;
|
||||
if (!cdvdLock(&cdvd_lock_error))
|
||||
{
|
||||
progress->DisplayError(cdvd_lock_error.GetDescription().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
ScopedGuard unlock_cdvd = &cdvdUnlock;
|
||||
|
||||
if (invalidate_cache)
|
||||
DeleteCacheFile();
|
||||
else
|
||||
|
||||
@ -485,7 +485,7 @@ void VMManager::UpdateLoggingSettings(SettingsInterface& si)
|
||||
if (system_console_enabled != Log::IsConsoleOutputEnabled())
|
||||
Log::SetConsoleOutputLevel(system_console_enabled ? level : LOGLEVEL_NONE);
|
||||
|
||||
// Debug console only exists on Windows.
|
||||
// Debug console only exists on Windows.
|
||||
#ifdef _WIN32
|
||||
const bool debug_console_enabled = IsDebuggerPresent() && si.GetBoolValue("Logging", "EnableDebugConsole", false);
|
||||
Log::SetDebugOutputLevel(debug_console_enabled ? level : LOGLEVEL_NONE);
|
||||
@ -776,8 +776,8 @@ std::string VMManager::GetGameSettingsPath(const std::string_view game_serial, u
|
||||
std::string sanitized_serial(Path::SanitizeFileName(game_serial));
|
||||
|
||||
return game_serial.empty() ?
|
||||
Path::Combine(EmuFolders::GameSettings, fmt::format("{:08X}.ini", game_crc)) :
|
||||
Path::Combine(EmuFolders::GameSettings, fmt::format("{}_{:08X}.ini", sanitized_serial, game_crc));
|
||||
Path::Combine(EmuFolders::GameSettings, fmt::format("{:08X}.ini", game_crc)) :
|
||||
Path::Combine(EmuFolders::GameSettings, fmt::format("{}_{:08X}.ini", sanitized_serial, game_crc));
|
||||
}
|
||||
|
||||
std::string VMManager::GetDiscOverrideFromGameSettings(const std::string& elf_path)
|
||||
@ -1324,6 +1324,15 @@ bool VMManager::Initialize(VMBootParameters boot_params)
|
||||
}
|
||||
}
|
||||
|
||||
Error cdvd_lock_error;
|
||||
if (!cdvdLock(&cdvd_lock_error))
|
||||
{
|
||||
Host::ReportErrorAsync("Startup Error", cdvd_lock_error.GetDescription());
|
||||
return false;
|
||||
}
|
||||
|
||||
ScopedGuard unlock_cdvd = &cdvdUnlock;
|
||||
|
||||
// resolve source type
|
||||
if (boot_params.source_type.has_value())
|
||||
{
|
||||
@ -1355,12 +1364,14 @@ bool VMManager::Initialize(VMBootParameters boot_params)
|
||||
if (!LoadBIOS())
|
||||
{
|
||||
Host::ReportErrorAsync(TRANSLATE_SV("VMManager", "Error – No BIOS Present"),
|
||||
fmt::format(TRANSLATE_FS("VMManager",
|
||||
"PCSX2 requires a PlayStation 2 BIOS in order to run.\n\n"
|
||||
"For legal reasons, you will need to obtain this BIOS from a PlayStation 2 unit which you own.\n\n"
|
||||
"For step-by-step help with this process, please consult the setup guide at {}.\n\n"
|
||||
"PCSX2 will be able to run once you've placed your BIOS image inside the folder named \"bios\" within the data directory "
|
||||
"(Tools Menu -> Open Data Directory)."), PCSX2_DOCUMENTATION_BIOS_URL_SHORTENED));
|
||||
fmt::format(
|
||||
TRANSLATE_FS("VMManager",
|
||||
"PCSX2 requires a PlayStation 2 BIOS in order to run.\n\n"
|
||||
"For legal reasons, you will need to obtain this BIOS from a PlayStation 2 unit which you own.\n\n"
|
||||
"For step-by-step help with this process, please consult the setup guide at {}.\n\n"
|
||||
"PCSX2 will be able to run once you've placed your BIOS image inside the folder named \"bios\" within the data directory "
|
||||
"(Tools Menu -> Open Data Directory)."),
|
||||
PCSX2_DOCUMENTATION_BIOS_URL_SHORTENED));
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1559,6 +1570,7 @@ bool VMManager::Initialize(VMBootParameters boot_params)
|
||||
close_memcards.Cancel();
|
||||
close_cdvd.Cancel();
|
||||
close_cdvd_files.Cancel();
|
||||
unlock_cdvd.Cancel();
|
||||
close_state.Cancel();
|
||||
|
||||
if (EmuConfig.CdvdPrecache)
|
||||
@ -1667,6 +1679,8 @@ void VMManager::Shutdown(bool save_resume_state)
|
||||
else
|
||||
cdvdSaveNVRAM();
|
||||
|
||||
cdvdUnlock();
|
||||
|
||||
s_state.store(VMState::Shutdown, std::memory_order_release);
|
||||
FullscreenUI::OnVMDestroyed();
|
||||
SaveStateSelectorUI::Clear();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user