Qt: Deduplicate interface code and reduce core coupling

This enables more code sharing between interfaces in the future (e.g.
nogui, gsrunner, etc). Eventually I'll move everything in Frontend/ to
its own project.

 - VMManager now no longer depends on anything in Frontend.
 - Moved INISettingsInterface out of Frontend.
 - Log settings can now be overridden per-game (if you really want to)..
 - Hotkeys get their own file.
This commit is contained in:
Connor McLaughlin 2022-09-14 22:41:50 +10:00 committed by refractionpcsx2
parent c96f1d28e6
commit 6810a9d593
24 changed files with 525 additions and 361 deletions

View File

@ -309,23 +309,17 @@ void MainWindow::connectSignals()
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionViewStatusBarVerbose, "UI", "VerboseStatusBar", false); SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionViewStatusBarVerbose, "UI", "VerboseStatusBar", false);
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionEnableSystemConsole, "Logging", "EnableSystemConsole", false); SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionEnableSystemConsole, "Logging", "EnableSystemConsole", false);
connect(m_ui.actionEnableSystemConsole, &QAction::triggered, this, &MainWindow::onLoggingOptionChanged);
#ifndef PCSX2_DEVBUILD #ifndef PCSX2_DEVBUILD
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionEnableVerboseLogging, "Logging", "EnableVerbose", false); SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionEnableVerboseLogging, "Logging", "EnableVerbose", false);
connect(m_ui.actionEnableVerboseLogging, &QAction::triggered, this, &MainWindow::onLoggingOptionChanged);
#else #else
// Dev builds always have verbose logging. // Dev builds always have verbose logging.
m_ui.actionEnableVerboseLogging->setChecked(true); m_ui.actionEnableVerboseLogging->setChecked(true);
m_ui.actionEnableVerboseLogging->setEnabled(false); m_ui.actionEnableVerboseLogging->setEnabled(false);
#endif #endif
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionEnableEEConsoleLogging, "Logging", "EnableEEConsole", true); SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionEnableEEConsoleLogging, "Logging", "EnableEEConsole", true);
connect(m_ui.actionEnableEEConsoleLogging, &QAction::triggered, this, &MainWindow::onLoggingOptionChanged);
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionEnableIOPConsoleLogging, "Logging", "EnableIOPConsole", true); SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionEnableIOPConsoleLogging, "Logging", "EnableIOPConsole", true);
connect(m_ui.actionEnableIOPConsoleLogging, &QAction::triggered, this, &MainWindow::onLoggingOptionChanged);
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionEnableFileLogging, "Logging", "EnableFileLogging", false); SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionEnableFileLogging, "Logging", "EnableFileLogging", false);
connect(m_ui.actionEnableFileLogging, &QAction::triggered, this, &MainWindow::onLoggingOptionChanged);
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionEnableLogTimestamps, "Logging", "EnableTimestamps", true); SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionEnableLogTimestamps, "Logging", "EnableTimestamps", true);
connect(m_ui.actionEnableLogTimestamps, &QAction::triggered, this, &MainWindow::onLoggingOptionChanged);
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionEnableCDVDVerboseReads, "EmuCore", "CdvdVerboseReads", false); SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionEnableCDVDVerboseReads, "EmuCore", "CdvdVerboseReads", false);
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionSaveBlockDump, "EmuCore", "CdvdDumpBlocks", false); SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionSaveBlockDump, "EmuCore", "CdvdDumpBlocks", false);
connect(m_ui.actionSaveBlockDump, &QAction::toggled, this, &MainWindow::onBlockDumpActionToggled); connect(m_ui.actionSaveBlockDump, &QAction::toggled, this, &MainWindow::onBlockDumpActionToggled);
@ -337,9 +331,7 @@ void MainWindow::connectSignals()
connect(m_ui.actionInputRecPlay, &QAction::triggered, this, &MainWindow::onInputRecPlayActionTriggered); connect(m_ui.actionInputRecPlay, &QAction::triggered, this, &MainWindow::onInputRecPlayActionTriggered);
connect(m_ui.actionInputRecStop, &QAction::triggered, this, &MainWindow::onInputRecStopActionTriggered); connect(m_ui.actionInputRecStop, &QAction::triggered, this, &MainWindow::onInputRecStopActionTriggered);
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionInputRecConsoleLogs, "Logging", "EnableInputRecordingLogs", false); SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionInputRecConsoleLogs, "Logging", "EnableInputRecordingLogs", false);
connect(m_ui.actionInputRecConsoleLogs, &QAction::triggered, this, &MainWindow::onLoggingOptionChanged);
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionInputRecControllerLogs, "Logging", "EnableControllerLogs", false); SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionInputRecControllerLogs, "Logging", "EnableControllerLogs", false);
connect(m_ui.actionInputRecControllerLogs, &QAction::triggered, this, &MainWindow::onLoggingOptionChanged);
// These need to be queued connections to stop crashing due to menus opening/closing and switching focus. // These need to be queued connections to stop crashing due to menus opening/closing and switching focus.
connect(m_game_list_widget, &GameListWidget::refreshProgress, this, &MainWindow::onGameListRefreshProgress); connect(m_game_list_widget, &GameListWidget::refreshProgress, this, &MainWindow::onGameListRefreshProgress);
@ -1509,11 +1501,6 @@ void MainWindow::updateTheme()
m_game_list_widget->refreshImages(); m_game_list_widget->refreshImages();
} }
void MainWindow::onLoggingOptionChanged()
{
Host::UpdateLogging(QtHost::InNoGUIMode());
}
void MainWindow::onInputRecNewActionTriggered() void MainWindow::onInputRecNewActionTriggered()
{ {
const bool wasPaused = s_vm_paused; const bool wasPaused = s_vm_paused;

View File

@ -149,7 +149,6 @@ private Q_SLOTS:
void onCheckForUpdatesActionTriggered(); void onCheckForUpdatesActionTriggered();
void onToolsOpenDataDirectoryTriggered(); void onToolsOpenDataDirectoryTriggered();
void updateTheme(); void updateTheme();
void onLoggingOptionChanged();
void onScreenshotActionTriggered(); void onScreenshotActionTriggered();
void onSaveGSDumpActionTriggered(); void onSaveGSDumpActionTriggered();
void onBlockDumpActionToggled(bool checked); void onBlockDumpActionToggled(bool checked);

View File

@ -37,13 +37,13 @@
#include "pcsx2/Frontend/GameList.h" #include "pcsx2/Frontend/GameList.h"
#include "pcsx2/Frontend/InputManager.h" #include "pcsx2/Frontend/InputManager.h"
#include "pcsx2/Frontend/ImGuiManager.h" #include "pcsx2/Frontend/ImGuiManager.h"
#include "pcsx2/Frontend/INISettingsInterface.h"
#include "pcsx2/Frontend/LogSink.h" #include "pcsx2/Frontend/LogSink.h"
#include "pcsx2/GS.h" #include "pcsx2/GS.h"
#include "pcsx2/GS/GS.h" #include "pcsx2/GS/GS.h"
#include "pcsx2/GSDumpReplayer.h" #include "pcsx2/GSDumpReplayer.h"
#include "pcsx2/HostDisplay.h" #include "pcsx2/HostDisplay.h"
#include "pcsx2/HostSettings.h" #include "pcsx2/HostSettings.h"
#include "pcsx2/INISettingsInterface.h"
#include "pcsx2/PAD/Host/PAD.h" #include "pcsx2/PAD/Host/PAD.h"
#include "pcsx2/PerformanceMetrics.h" #include "pcsx2/PerformanceMetrics.h"
#include "pcsx2/VMManager.h" #include "pcsx2/VMManager.h"
@ -230,14 +230,11 @@ void EmuThread::startVM(std::shared_ptr<VMBootParameters> boot_params)
pxAssertRel(!VMManager::HasValidVM(), "VM is shut down"); pxAssertRel(!VMManager::HasValidVM(), "VM is shut down");
// Only initialize fullscreen/render-to-main when we're not running big picture. // Determine whether to start fullscreen or not.
if (!m_run_fullscreen_ui)
loadOurInitialSettings();
if (boot_params->fullscreen.has_value()) if (boot_params->fullscreen.has_value())
m_is_fullscreen = boot_params->fullscreen.value(); m_is_fullscreen = boot_params->fullscreen.value();
else
emit onVMStarting(); m_is_fullscreen = Host::GetBaseBoolSettingValue("UI", "StartFullscreen", false);
if (!VMManager::Initialize(*boot_params)) if (!VMManager::Initialize(*boot_params))
return; return;
@ -359,26 +356,19 @@ void EmuThread::saveStateToSlot(qint32 slot)
void EmuThread::run() void EmuThread::run()
{ {
Threading::SetNameOfCurrentThread("EmuThread"); // Qt-specific initialization.
PerformanceMetrics::SetCPUThread(Threading::ThreadHandle::GetForCallingThread());
m_event_loop = new QEventLoop(); m_event_loop = new QEventLoop();
m_started_semaphore.release(); m_started_semaphore.release();
connectSignals();
// neither of these should ever fail. // Common host initialization (VM setup, etc).
if (!VMManager::Internal::InitializeGlobals() || !VMManager::Internal::InitializeMemory()) CommonHost::CPUThreadInitialize();
pxFailRel("Failed to allocate memory map");
// We want settings loaded so we choose the correct renderer for big picture mode.
// This also sorts out input sources.
loadOurSettings();
loadOurInitialSettings();
VMManager::LoadSettings();
// Start background polling because the VM won't do it for us. // Start background polling because the VM won't do it for us.
createBackgroundControllerPollTimer(); createBackgroundControllerPollTimer();
startBackgroundControllerPollTimer(); startBackgroundControllerPollTimer();
connectSignals();
// Main CPU thread loop.
while (!m_shutdown_flag.load()) while (!m_shutdown_flag.load())
{ {
if (!VMManager::HasValidVM()) if (!VMManager::HasValidVM())
@ -390,13 +380,12 @@ void EmuThread::run()
executeVM(); executeVM();
} }
// Teardown in reverse order.
stopBackgroundControllerPollTimer(); stopBackgroundControllerPollTimer();
destroyBackgroundControllerPollTimer(); destroyBackgroundControllerPollTimer();
InputManager::CloseSources(); CommonHost::CPUThreadShutdown();
VMManager::WaitForSaveStateFlush();
VMManager::Internal::ReleaseMemory(); // Move back to the UI thread, since we're no longer running.
VMManager::Internal::ReleaseGlobals();
PerformanceMetrics::SetCPUThread(Threading::ThreadHandle());
moveToThread(m_ui_thread); moveToThread(m_ui_thread);
deleteLater(); deleteLater();
} }
@ -410,6 +399,7 @@ void EmuThread::destroyVM()
m_last_internal_height = 0; m_last_internal_height = 0;
m_was_paused_by_focus_loss = false; m_was_paused_by_focus_loss = false;
VMManager::Shutdown(m_save_state_on_shutdown); VMManager::Shutdown(m_save_state_on_shutdown);
m_save_state_on_shutdown = false;
} }
void EmuThread::executeVM() void EmuThread::executeVM()
@ -540,7 +530,6 @@ void EmuThread::applySettings()
return; return;
} }
checkForSettingChanges();
VMManager::ApplySettings(); VMManager::ApplySettings();
} }
@ -553,11 +542,7 @@ void EmuThread::reloadGameSettings()
} }
// this will skip applying settings when they're not active // this will skip applying settings when they're not active
if (VMManager::ReloadGameSettings()) VMManager::ReloadGameSettings();
{
// none of these settings below are per-game.. for now. but in case they are in the future.
checkForSettingChanges();
}
} }
void EmuThread::updateEmuFolders() void EmuThread::updateEmuFolders()
@ -571,26 +556,24 @@ void EmuThread::updateEmuFolders()
Host::Internal::UpdateEmuFolders(); Host::Internal::UpdateEmuFolders();
} }
void EmuThread::loadOurSettings()
{
m_verbose_status = Host::GetBaseBoolSettingValue("UI", "VerboseStatusBar", false);
m_pause_on_focus_loss = Host::GetBaseBoolSettingValue("UI", "PauseOnFocusLoss", false);
}
void EmuThread::connectSignals() void EmuThread::connectSignals()
{ {
connect(qApp, &QGuiApplication::applicationStateChanged, this, &EmuThread::onApplicationStateChanged); connect(qApp, &QGuiApplication::applicationStateChanged, this, &EmuThread::onApplicationStateChanged);
} }
void EmuThread::loadOurInitialSettings() void EmuThread::loadSettings(SettingsInterface& si, std::unique_lock<std::mutex>& lock)
{ {
m_is_fullscreen = Host::GetBaseBoolSettingValue("UI", "StartFullscreen", false); m_verbose_status = si.GetBoolValue("UI", "VerboseStatusBar", false);
m_is_rendering_to_main = shouldRenderToMain(); m_pause_on_focus_loss = si.GetBoolValue("UI", "PauseOnFocusLoss", false);
m_is_surfaceless = false;
m_save_state_on_shutdown = false;
} }
void EmuThread::checkForSettingChanges() void Host::LoadSettings(SettingsInterface& si, std::unique_lock<std::mutex>& lock)
{
CommonHost::LoadSettings(si, lock);
g_emu_thread->loadSettings(si, lock);
}
void EmuThread::checkForSettingChanges(const Pcsx2Config& old_config)
{ {
QMetaObject::invokeMethod(g_main_window, &MainWindow::checkForSettingChanges, Qt::QueuedConnection); QMetaObject::invokeMethod(g_main_window, &MainWindow::checkForSettingChanges, Qt::QueuedConnection);
@ -605,12 +588,13 @@ void EmuThread::checkForSettingChanges()
} }
} }
const bool last_verbose_status = m_verbose_status; updatePerformanceMetrics(true);
}
loadOurSettings(); void Host::CheckForSettingsChanges(const Pcsx2Config& old_config)
{
if (m_verbose_status != last_verbose_status) CommonHost::CheckForSettingsChanges(old_config);
updatePerformanceMetrics(true); g_emu_thread->checkForSettingChanges(old_config);
} }
bool EmuThread::shouldRenderToMain() const bool EmuThread::shouldRenderToMain() const
@ -855,6 +839,8 @@ void EmuThread::updateDisplay()
bool EmuThread::acquireHostDisplay(HostDisplay::RenderAPI api) bool EmuThread::acquireHostDisplay(HostDisplay::RenderAPI api)
{ {
pxAssertRel(!g_host_display, "Host display does not exist on create"); pxAssertRel(!g_host_display, "Host display does not exist on create");
m_is_rendering_to_main = shouldRenderToMain();
m_is_surfaceless = false;
g_host_display = HostDisplay::CreateDisplayForAPI(api); g_host_display = HostDisplay::CreateDisplayForAPI(api);
if (!g_host_display) if (!g_host_display)
@ -967,29 +953,35 @@ void Host::UpdateHostDisplay()
void Host::OnVMStarting() void Host::OnVMStarting()
{ {
CommonHost::OnVMStarting();
g_emu_thread->stopBackgroundControllerPollTimer(); g_emu_thread->stopBackgroundControllerPollTimer();
emit g_emu_thread->onVMStarting(); emit g_emu_thread->onVMStarting();
} }
void Host::OnVMStarted() void Host::OnVMStarted()
{ {
CommonHost::OnVMStarted();
emit g_emu_thread->onVMStarted(); emit g_emu_thread->onVMStarted();
} }
void Host::OnVMDestroyed() void Host::OnVMDestroyed()
{ {
CommonHost::OnVMDestroyed();
emit g_emu_thread->onVMStopped(); emit g_emu_thread->onVMStopped();
g_emu_thread->startBackgroundControllerPollTimer(); g_emu_thread->startBackgroundControllerPollTimer();
} }
void Host::OnVMPaused() void Host::OnVMPaused()
{ {
CommonHost::OnVMPaused();
g_emu_thread->startBackgroundControllerPollTimer(); g_emu_thread->startBackgroundControllerPollTimer();
emit g_emu_thread->onVMPaused(); emit g_emu_thread->onVMPaused();
} }
void Host::OnVMResumed() void Host::OnVMResumed()
{ {
CommonHost::OnVMResumed();
// exit the event loop when we eventually return // exit the event loop when we eventually return
g_emu_thread->getEventLoop()->quit(); g_emu_thread->getEventLoop()->quit();
g_emu_thread->stopBackgroundControllerPollTimer(); g_emu_thread->stopBackgroundControllerPollTimer();
@ -1001,11 +993,10 @@ void Host::OnVMResumed()
emit g_emu_thread->onVMResumed(); emit g_emu_thread->onVMResumed();
} }
void Host::OnGameChanged(const std::string& disc_path, const std::string& game_serial, const std::string& game_name, void Host::OnGameChanged(const std::string& disc_path, const std::string& game_serial, const std::string& game_name, u32 game_crc)
u32 game_crc)
{ {
emit g_emu_thread->onGameChanged(QString::fromStdString(disc_path), QString::fromStdString(game_serial), CommonHost::OnGameChanged(disc_path, game_serial, game_name, game_crc);
QString::fromStdString(game_name), game_crc); emit g_emu_thread->onGameChanged(QString::fromStdString(disc_path), QString::fromStdString(game_serial), QString::fromStdString(game_name), game_crc);
} }
void EmuThread::updatePerformanceMetrics(bool force) void EmuThread::updatePerformanceMetrics(bool force)
@ -1117,9 +1108,10 @@ void Host::OnSaveStateSaved(const std::string_view& filename)
emit g_emu_thread->onSaveStateSaved(QtUtils::StringViewToQString(filename)); emit g_emu_thread->onSaveStateSaved(QtUtils::StringViewToQString(filename));
} }
void Host::PumpMessagesOnCPUThread() void Host::CPUThreadVSync()
{ {
g_emu_thread->getEventLoop()->processEvents(QEventLoop::AllEvents); g_emu_thread->getEventLoop()->processEvents(QEventLoop::AllEvents);
CommonHost::CPUThreadVSync();
} }
void Host::RunOnCPUThread(std::function<void()> function, bool block /* = false */) void Host::RunOnCPUThread(std::function<void()> function, bool block /* = false */)
@ -1211,15 +1203,13 @@ bool QtHost::InitializeConfig()
SaveSettings(); SaveSettings();
} }
CommonHost::SetBlockSystemConsole(QtHost::InNoGUIMode());
CommonHost::LoadStartupSettings(); CommonHost::LoadStartupSettings();
Host::UpdateLogging(QtHost::InNoGUIMode());
return true; return true;
} }
void Host::SetDefaultUISettings(SettingsInterface& si) void Host::SetDefaultUISettings(SettingsInterface& si)
{ {
Host::SetDefaultLoggingSettings(si);
si.SetBoolValue("UI", "InhibitScreensaver", true); si.SetBoolValue("UI", "InhibitScreensaver", true);
si.SetBoolValue("UI", "ConfirmShutdown", true); si.SetBoolValue("UI", "ConfirmShutdown", true);
si.SetBoolValue("UI", "StartPaused", false); si.SetBoolValue("UI", "StartPaused", false);
@ -1472,7 +1462,7 @@ void QtHost::HookSignals()
void QtHost::PrintCommandLineVersion() void QtHost::PrintCommandLineVersion()
{ {
Host::InitializeEarlyConsole(); CommonHost::InitializeEarlyConsole();
std::fprintf(stderr, "%s\n", (GetAppNameAndVersion() + GetAppConfigSuffix()).toUtf8().constData()); std::fprintf(stderr, "%s\n", (GetAppNameAndVersion() + GetAppConfigSuffix()).toUtf8().constData());
std::fprintf(stderr, "https://pcsx2.net/\n"); std::fprintf(stderr, "https://pcsx2.net/\n");
std::fprintf(stderr, "\n"); std::fprintf(stderr, "\n");
@ -1592,7 +1582,7 @@ bool QtHost::ParseCommandLineOptions(int argc, char* argv[], std::shared_ptr<VMB
} }
else if (CHECK_ARG("-earlyconsolelog")) else if (CHECK_ARG("-earlyconsolelog"))
{ {
Host::InitializeEarlyConsole(); CommonHost::InitializeEarlyConsole();
continue; continue;
} }
else if (CHECK_ARG("-bigpicture")) else if (CHECK_ARG("-bigpicture"))
@ -1607,7 +1597,7 @@ bool QtHost::ParseCommandLineOptions(int argc, char* argv[], std::shared_ptr<VMB
} }
else if (argv[i][0] == '-') else if (argv[i][0] == '-')
{ {
Host::InitializeEarlyConsole(); CommonHost::InitializeEarlyConsole();
std::fprintf(stderr, "Unknown parameter: '%s'", argv[i]); std::fprintf(stderr, "Unknown parameter: '%s'", argv[i]);
return false; return false;
} }
@ -1626,7 +1616,7 @@ bool QtHost::ParseCommandLineOptions(int argc, char* argv[], std::shared_ptr<VMB
// or disc, we don't want to actually start. // or disc, we don't want to actually start.
if (autoboot && !autoboot->source_type.has_value() && autoboot->filename.empty() && autoboot->elf_override.empty()) if (autoboot && !autoboot->source_type.has_value() && autoboot->filename.empty() && autoboot->elf_override.empty())
{ {
Host::InitializeEarlyConsole(); CommonHost::InitializeEarlyConsole();
Console.Warning("Skipping autoboot due to no boot parameters."); Console.Warning("Skipping autoboot due to no boot parameters.");
autoboot.reset(); autoboot.reset();
} }

View File

@ -80,6 +80,8 @@ public:
public Q_SLOTS: public Q_SLOTS:
bool confirmMessage(const QString& title, const QString& message); bool confirmMessage(const QString& title, const QString& message);
void loadSettings(SettingsInterface& si, std::unique_lock<std::mutex>& lock);
void checkForSettingChanges(const Pcsx2Config& old_config);
void startFullscreenUI(bool fullscreen); void startFullscreenUI(bool fullscreen);
void stopFullscreenUI(); void stopFullscreenUI();
void startVM(std::shared_ptr<VMBootParameters> boot_params); void startVM(std::shared_ptr<VMBootParameters> boot_params);
@ -161,14 +163,11 @@ private:
void destroyVM(); void destroyVM();
void executeVM(); void executeVM();
void checkForSettingChanges();
bool shouldRenderToMain() const; bool shouldRenderToMain() const;
void createBackgroundControllerPollTimer(); void createBackgroundControllerPollTimer();
void destroyBackgroundControllerPollTimer(); void destroyBackgroundControllerPollTimer();
void connectSignals(); void connectSignals();
void loadOurSettings();
void loadOurInitialSettings();
private Q_SLOTS: private Q_SLOTS:
void stopInThread(); void stopInThread();

View File

@ -22,7 +22,7 @@
#include "Settings/HotkeySettingsWidget.h" #include "Settings/HotkeySettingsWidget.h"
#include "pcsx2/Frontend/CommonHost.h" #include "pcsx2/Frontend/CommonHost.h"
#include "pcsx2/Frontend/INISettingsInterface.h" #include "pcsx2/INISettingsInterface.h"
#include "pcsx2/PAD/Host/PAD.h" #include "pcsx2/PAD/Host/PAD.h"
#include "pcsx2/Sio.h" #include "pcsx2/Sio.h"
#include "pcsx2/VMManager.h" #include "pcsx2/VMManager.h"

View File

@ -24,13 +24,13 @@
#include "common/StringUtil.h" #include "common/StringUtil.h"
#include "pcsx2/HostSettings.h" #include "pcsx2/HostSettings.h"
#include "pcsx2/INISettingsInterface.h"
#include "DEV9SettingsWidget.h" #include "DEV9SettingsWidget.h"
#include "QtHost.h" #include "QtHost.h"
#include "QtUtils.h" #include "QtUtils.h"
#include "SettingWidgetBinder.h" #include "SettingWidgetBinder.h"
#include "SettingsDialog.h" #include "SettingsDialog.h"
#include "Frontend/INISettingsInterface.h"
#include "HddCreateQt.h" #include "HddCreateQt.h"

View File

@ -19,9 +19,9 @@
#include "common/Path.h" #include "common/Path.h"
#include "common/StringUtil.h" #include "common/StringUtil.h"
#include "pcsx2/HostSettings.h"
#include "pcsx2/Frontend/GameList.h" #include "pcsx2/Frontend/GameList.h"
#include "pcsx2/Frontend/INISettingsInterface.h" #include "pcsx2/HostSettings.h"
#include "pcsx2/INISettingsInterface.h"
#include "MainWindow.h" #include "MainWindow.h"
#include "QtHost.h" #include "QtHost.h"

View File

@ -1064,16 +1064,17 @@ endif()
if(PCSX2_CORE) if(PCSX2_CORE)
list(APPEND pcsx2FrontendSources list(APPEND pcsx2FrontendSources
Frontend/CommonHost.cpp Frontend/CommonHost.cpp
Frontend/CommonHotkeys.cpp
Frontend/FullscreenUI.cpp Frontend/FullscreenUI.cpp
Frontend/GameList.cpp Frontend/GameList.cpp
Frontend/HostSettings.cpp Frontend/HostSettings.cpp
Frontend/ImGuiFullscreen.cpp Frontend/ImGuiFullscreen.cpp
Frontend/INISettingsInterface.cpp
Frontend/InputManager.cpp Frontend/InputManager.cpp
Frontend/InputSource.cpp Frontend/InputSource.cpp
Frontend/LayeredSettingsInterface.cpp Frontend/LayeredSettingsInterface.cpp
Frontend/LogSink.cpp Frontend/LogSink.cpp
GSDumpReplayer.cpp GSDumpReplayer.cpp
INISettingsInterface.cpp
VMManager.cpp VMManager.cpp
) )
list(APPEND pcsx2FrontendHeaders list(APPEND pcsx2FrontendHeaders
@ -1081,13 +1082,13 @@ if(PCSX2_CORE)
Frontend/FullscreenUI.h Frontend/FullscreenUI.h
Frontend/GameList.h Frontend/GameList.h
Frontend/ImGuiFullscreen.h Frontend/ImGuiFullscreen.h
Frontend/INISettingsInterface.h
Frontend/InputManager.h Frontend/InputManager.h
Frontend/InputSource.h Frontend/InputSource.h
Frontend/LayeredSettingsInterface.h Frontend/LayeredSettingsInterface.h
Frontend/LogSink.h Frontend/LogSink.h
GSDumpReplayer.h GSDumpReplayer.h
HostSettings.h HostSettings.h
INISettingsInterface.h
VMManager.h) VMManager.h)
endif() endif()

View File

@ -18,14 +18,21 @@
#include "common/CrashHandler.h" #include "common/CrashHandler.h"
#include "common/FileSystem.h" #include "common/FileSystem.h"
#include "common/Path.h" #include "common/Path.h"
#include "common/Threading.h"
#include "Frontend/CommonHost.h" #include "Frontend/CommonHost.h"
#include "Frontend/FullscreenUI.h"
#include "Frontend/GameList.h"
#include "Frontend/LayeredSettingsInterface.h" #include "Frontend/LayeredSettingsInterface.h"
#include "Frontend/InputManager.h"
#include "Frontend/LogSink.h"
#include "GS.h" #include "GS.h"
#include "GS/Renderers/HW/GSTextureReplacements.h" #include "GS/Renderers/HW/GSTextureReplacements.h"
#include "Host.h" #include "Host.h"
#include "HostSettings.h" #include "HostSettings.h"
#include "IconsFontAwesome5.h"
#include "MemoryCardFile.h" #include "MemoryCardFile.h"
#include "PAD/Host/PAD.h" #include "PAD/Host/PAD.h"
#include "PerformanceMetrics.h"
#include "Sio.h" #include "Sio.h"
#include "VMManager.h" #include "VMManager.h"
@ -175,6 +182,7 @@ void CommonHost::LoadStartupSettings()
SettingsInterface* bsi = Host::Internal::GetBaseSettingsLayer(); SettingsInterface* bsi = Host::Internal::GetBaseSettingsLayer();
EmuFolders::LoadConfig(*bsi); EmuFolders::LoadConfig(*bsi);
EmuFolders::EnsureFoldersExist(); EmuFolders::EnsureFoldersExist();
UpdateLogging(*bsi);
} }
void CommonHost::SetDefaultSettings(SettingsInterface& si, bool folders, bool core, bool controllers, bool hotkeys, bool ui) void CommonHost::SetDefaultSettings(SettingsInterface& si, bool folders, bool core, bool controllers, bool hotkeys, bool ui)
@ -199,5 +207,106 @@ void CommonHost::SetDefaultSettings(SettingsInterface& si, bool folders, bool co
void CommonHost::SetCommonDefaultSettings(SettingsInterface& si) void CommonHost::SetCommonDefaultSettings(SettingsInterface& si)
{ {
// Nothing here yet. SetDefaultLoggingSettings(si);
}
void CommonHost::CPUThreadInitialize()
{
Threading::SetNameOfCurrentThread("CPU Thread");
PerformanceMetrics::SetCPUThread(Threading::ThreadHandle::GetForCallingThread());
// neither of these should ever fail.
if (!VMManager::Internal::InitializeGlobals() || !VMManager::Internal::InitializeMemory())
pxFailRel("Failed to allocate memory map");
// We want settings loaded so we choose the correct renderer for big picture mode.
// This also sorts out input sources.
VMManager::LoadSettings();
}
void CommonHost::CPUThreadShutdown()
{
InputManager::CloseSources();
VMManager::WaitForSaveStateFlush();
VMManager::Internal::ReleaseMemory();
VMManager::Internal::ReleaseGlobals();
PerformanceMetrics::SetCPUThread(Threading::ThreadHandle());
}
void CommonHost::LoadSettings(SettingsInterface& si, std::unique_lock<std::mutex>& lock)
{
SettingsInterface* binding_si = Host::GetSettingsInterfaceForBindings();
InputManager::ReloadSources(si, lock);
InputManager::ReloadBindings(si, *binding_si);
UpdateLogging(si);
}
void CommonHost::CheckForSettingsChanges(const Pcsx2Config& old_config)
{
// Nothing yet.
}
void CommonHost::OnVMStarting()
{
CommonHost::Internal::ResetVMHotkeyState();
}
void CommonHost::OnVMStarted()
{
FullscreenUI::OnVMStarted();
}
void CommonHost::OnVMDestroyed()
{
FullscreenUI::OnVMDestroyed();
}
void CommonHost::OnVMPaused()
{
InputManager::PauseVibration();
FullscreenUI::OnVMPaused();
}
void CommonHost::OnVMResumed()
{
FullscreenUI::OnVMResumed();
}
void CommonHost::OnGameChanged(const std::string& disc_path, const std::string& game_serial, const std::string& game_name, u32 game_crc)
{
if (FullscreenUI::IsInitialized())
{
GetMTGS().RunOnGSThread([disc_path, game_serial, game_name, game_crc]() {
FullscreenUI::OnRunningGameChanged(std::move(disc_path), std::move(game_serial), std::move(game_name), game_crc);
});
}
}
void CommonHost::CPUThreadVSync()
{
InputManager::PollSources();
}
bool Host::GetSerialAndCRCForFilename(const char* filename, std::string* serial, u32* crc)
{
{
auto lock = GameList::GetLock();
if (const GameList::Entry* entry = GameList::GetEntryForPath(filename); entry)
{
*serial = entry->serial;
*crc = entry->crc;
return true;
}
}
// Just scan it.. hopefully it'll come back okay.
GameList::Entry temp_entry;
if (GameList::PopulateEntryFromPath(filename, &temp_entry))
{
*serial = std::move(temp_entry.serial);
*crc = temp_entry.crc;
return true;
}
return false;
} }

View File

@ -19,6 +19,8 @@
#include <string> #include <string>
#include <mutex> #include <mutex>
#include "Config.h"
class SettingsInterface; class SettingsInterface;
namespace Host namespace Host
@ -40,4 +42,43 @@ namespace CommonHost
/// Sets default settings for the specified categories. /// Sets default settings for the specified categories.
void SetDefaultSettings(SettingsInterface& si, bool folders, bool core, bool controllers, bool hotkeys, bool ui); void SetDefaultSettings(SettingsInterface& si, bool folders, bool core, bool controllers, bool hotkeys, bool ui);
/// Initializes common host state, called on the CPU thread.
void CPUThreadInitialize();
/// Cleans up common host state, called on the CPU thread.
void CPUThreadShutdown();
/// Loads common host settings (including input bindings).
void LoadSettings(SettingsInterface& si, std::unique_lock<std::mutex>& lock);
/// Called after settings are updated.
void CheckForSettingsChanges(const Pcsx2Config& old_config);
/// Called when the VM is starting initialization, but has not been completed yet.
void OnVMStarting();
/// Called when the VM is created.
void OnVMStarted();
/// Called when the VM is shut down or destroyed.
void OnVMDestroyed();
/// Called when the VM is paused.
void OnVMPaused();
/// Called when the VM is resumed after being paused.
void OnVMResumed();
/// Called when the running executable changes.
void OnGameChanged(const std::string& disc_path, const std::string& game_serial, const std::string& game_name, u32 game_crc);
/// Provided by the host; called once per frame at guest vsync.
void CPUThreadVSync();
namespace Internal
{
/// Resets any state for hotkey-related VMs, called on VM startup.
void ResetVMHotkeyState();
} // namespace Internal
} // namespace CommonHost } // namespace CommonHost

View File

@ -0,0 +1,240 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2022 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "common/Assertions.h"
#include "common/FileSystem.h"
#include "common/Path.h"
#include "Frontend/CommonHost.h"
#include "Frontend/FullscreenUI.h"
#include "Frontend/InputManager.h"
#include "GS.h"
#include "Host.h"
#include "IconsFontAwesome5.h"
#include "Recording/InputRecordingControls.h"
#include "VMManager.h"
static s32 s_current_save_slot = 1;
static std::optional<LimiterModeType> s_limiter_mode_prior_to_hold_interaction;
void CommonHost::Internal::ResetVMHotkeyState()
{
s_current_save_slot = 1;
s_limiter_mode_prior_to_hold_interaction.reset();
}
static void HotkeyAdjustTargetSpeed(double delta)
{
EmuConfig.Framerate.NominalScalar = EmuConfig.GS.LimitScalar + delta;
VMManager::SetLimiterMode(LimiterModeType::Nominal);
gsUpdateFrequency(EmuConfig);
GetMTGS().SetVSync(EmuConfig.GetEffectiveVsyncMode());
Host::AddIconOSDMessage("SpeedChanged", ICON_FA_CLOCK,
fmt::format("Target speed set to {:.0f}%.", std::round(EmuConfig.Framerate.NominalScalar * 100.0)), 5.0f);
}
static constexpr s32 CYCLE_SAVE_STATE_SLOTS = 10;
static void HotkeyCycleSaveSlot(s32 delta)
{
// 1..10
s_current_save_slot = ((s_current_save_slot - 1) + delta);
if (s_current_save_slot < 0)
s_current_save_slot = CYCLE_SAVE_STATE_SLOTS;
else
s_current_save_slot = (s_current_save_slot % CYCLE_SAVE_STATE_SLOTS) + 1;
const u32 crc = VMManager::GetGameCRC();
const std::string serial(VMManager::GetGameSerial());
const std::string filename(VMManager::GetSaveStateFileName(serial.c_str(), crc, s_current_save_slot));
FILESYSTEM_STAT_DATA sd;
if (!filename.empty() && FileSystem::StatFile(filename.c_str(), &sd))
{
char date_buf[128] = {};
#ifdef _WIN32
ctime_s(date_buf, std::size(date_buf), &sd.ModificationTime);
#else
ctime_r(&sd.ModificationTime, date_buf);
#endif
// remove terminating \n
size_t len = std::strlen(date_buf);
if (len > 0 && date_buf[len - 1] == '\n')
date_buf[len - 1] = 0;
Host::AddIconOSDMessage(
"CycleSaveSlot", ICON_FA_SEARCH, fmt::format("Save slot {} selected (last save: {}).", s_current_save_slot, date_buf), 5.0f);
}
else
{
Host::AddIconOSDMessage(
"CycleSaveSlot", ICON_FA_SEARCH, fmt::format("Save slot {} selected (no save yet).", s_current_save_slot), 5.0f);
}
}
static void HotkeyLoadStateSlot(s32 slot)
{
const u32 crc = VMManager::GetGameCRC();
if (crc == 0)
{
Host::AddIconOSDMessage(
"LoadStateFromSlot", ICON_FA_EXCLAMATION_TRIANGLE, "Cannot load state from a slot without a game running.", 10.0f);
return;
}
const std::string serial(VMManager::GetGameSerial());
if (!VMManager::HasSaveStateInSlot(serial.c_str(), crc, slot))
{
Host::AddIconOSDMessage("LoadStateFromSlot", ICON_FA_EXCLAMATION_TRIANGLE, fmt::format("No save state found in slot {}.", slot));
return;
}
VMManager::LoadStateFromSlot(slot);
}
static void HotkeySaveStateSlot(s32 slot)
{
if (VMManager::GetGameCRC() == 0)
{
Host::AddIconOSDMessage(
"SaveStateToSlot", ICON_FA_EXCLAMATION_TRIANGLE, "Cannot save state to a slot without a game running.", 10.0f);
return;
}
VMManager::SaveStateToSlot(slot);
}
BEGIN_HOTKEY_LIST(g_common_hotkeys)
DEFINE_HOTKEY("OpenPauseMenu", "System", "Open Pause Menu", [](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
FullscreenUI::OpenPauseMenu();
})
DEFINE_HOTKEY("TogglePause", "System", "Toggle Pause", [](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
VMManager::SetPaused(VMManager::GetState() != VMState::Paused);
})
DEFINE_HOTKEY("ToggleFullscreen", "System", "Toggle Fullscreen", [](s32 pressed) {
if (!pressed)
Host::SetFullscreen(!Host::IsFullscreen());
})
DEFINE_HOTKEY("ToggleFrameLimit", "System", "Toggle Frame Limit", [](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
{
VMManager::SetLimiterMode(
(EmuConfig.LimiterMode != LimiterModeType::Unlimited) ? LimiterModeType::Unlimited : LimiterModeType::Nominal);
}
})
DEFINE_HOTKEY("ToggleTurbo", "System", "Toggle Turbo", [](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
{
VMManager::SetLimiterMode((EmuConfig.LimiterMode != LimiterModeType::Turbo) ? LimiterModeType::Turbo : LimiterModeType::Nominal);
}
})
DEFINE_HOTKEY("ToggleSlowMotion", "System", "Toggle Slow Motion", [](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
{
VMManager::SetLimiterMode((EmuConfig.LimiterMode != LimiterModeType::Slomo) ? LimiterModeType::Slomo : LimiterModeType::Nominal);
}
})
DEFINE_HOTKEY("HoldTurbo", "System", "Turbo (Hold)", [](s32 pressed) {
if (!VMManager::HasValidVM())
return;
if (pressed > 0 && !s_limiter_mode_prior_to_hold_interaction.has_value())
{
s_limiter_mode_prior_to_hold_interaction = VMManager::GetLimiterMode();
VMManager::SetLimiterMode((s_limiter_mode_prior_to_hold_interaction.value() != LimiterModeType::Turbo) ? LimiterModeType::Turbo :
LimiterModeType::Nominal);
}
else if (pressed >= 0 && s_limiter_mode_prior_to_hold_interaction.has_value())
{
VMManager::SetLimiterMode(s_limiter_mode_prior_to_hold_interaction.value());
s_limiter_mode_prior_to_hold_interaction.reset();
}
})
DEFINE_HOTKEY("IncreaseSpeed", "System", "Increase Target Speed", [](s32 pressed) {
if (!pressed)
HotkeyAdjustTargetSpeed(0.1);
})
DEFINE_HOTKEY("DecreaseSpeed", "System", "Decrease Target Speed", [](s32 pressed) {
if (!pressed)
HotkeyAdjustTargetSpeed(-0.1);
})
DEFINE_HOTKEY("FrameAdvance", "System", "Frame Advance", [](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
VMManager::FrameAdvance(1);
})
DEFINE_HOTKEY("ShutdownVM", "System", "Shut Down Virtual Machine", [](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
Host::RequestVMShutdown(true, true, EmuConfig.SaveStateOnShutdown);
})
DEFINE_HOTKEY("ResetVM", "System", "Reset Virtual Machine", [](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
VMManager::Reset();
})
DEFINE_HOTKEY("InputRecToggleMode", "System", "Toggle Input Recording Mode", [](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
g_InputRecordingControls.RecordModeToggle();
})
DEFINE_HOTKEY("PreviousSaveStateSlot", "Save States", "Select Previous Save Slot", [](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
HotkeyCycleSaveSlot(-1);
})
DEFINE_HOTKEY("NextSaveStateSlot", "Save States", "Select Next Save Slot", [](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
HotkeyCycleSaveSlot(1);
})
DEFINE_HOTKEY("SaveStateToSlot", "Save States", "Save State To Selected Slot", [](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
VMManager::SaveStateToSlot(s_current_save_slot);
})
DEFINE_HOTKEY("LoadStateFromSlot", "Save States", "Load State From Selected Slot", [](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
HotkeyLoadStateSlot(s_current_save_slot);
})
#define DEFINE_HOTKEY_SAVESTATE_X(slotnum) \
DEFINE_HOTKEY("SaveStateToSlot" #slotnum, "Save States", "Save State To Slot " #slotnum, [](s32 pressed) { \
if (!pressed) \
HotkeySaveStateSlot(slotnum); \
})
#define DEFINE_HOTKEY_LOADSTATE_X(slotnum) \
DEFINE_HOTKEY("LoadStateFromSlot" #slotnum, "Save States", "Load State From Slot " #slotnum, [](s32 pressed) { \
if (!pressed) \
HotkeyLoadStateSlot(slotnum); \
})
DEFINE_HOTKEY_SAVESTATE_X(1)
DEFINE_HOTKEY_LOADSTATE_X(1)
DEFINE_HOTKEY_SAVESTATE_X(2)
DEFINE_HOTKEY_LOADSTATE_X(2)
DEFINE_HOTKEY_SAVESTATE_X(3)
DEFINE_HOTKEY_LOADSTATE_X(3)
DEFINE_HOTKEY_SAVESTATE_X(4)
DEFINE_HOTKEY_LOADSTATE_X(4)
DEFINE_HOTKEY_SAVESTATE_X(5)
DEFINE_HOTKEY_LOADSTATE_X(5)
DEFINE_HOTKEY_SAVESTATE_X(6)
DEFINE_HOTKEY_LOADSTATE_X(6)
DEFINE_HOTKEY_SAVESTATE_X(7)
DEFINE_HOTKEY_LOADSTATE_X(7)
DEFINE_HOTKEY_SAVESTATE_X(8)
DEFINE_HOTKEY_LOADSTATE_X(8)
DEFINE_HOTKEY_SAVESTATE_X(9)
DEFINE_HOTKEY_LOADSTATE_X(9)
DEFINE_HOTKEY_SAVESTATE_X(10)
DEFINE_HOTKEY_LOADSTATE_X(10)
#undef DEFINE_HOTKEY_SAVESTATE_X
#undef DEFINE_HOTKEY_LOADSTATE_X
END_HOTKEY_LIST()

View File

@ -20,7 +20,6 @@
#include "Frontend/FullscreenUI.h" #include "Frontend/FullscreenUI.h"
#include "Frontend/ImGuiManager.h" #include "Frontend/ImGuiManager.h"
#include "Frontend/ImGuiFullscreen.h" #include "Frontend/ImGuiFullscreen.h"
#include "Frontend/INISettingsInterface.h"
#include "Frontend/InputManager.h" #include "Frontend/InputManager.h"
#include "Frontend/GameList.h" #include "Frontend/GameList.h"
#include "IconsFontAwesome5.h" #include "IconsFontAwesome5.h"
@ -40,6 +39,7 @@
#include "Host.h" #include "Host.h"
#include "HostDisplay.h" #include "HostDisplay.h"
#include "HostSettings.h" #include "HostSettings.h"
#include "INISettingsInterface.h"
#include "MemoryCardFile.h" #include "MemoryCardFile.h"
#include "PAD/Host/PAD.h" #include "PAD/Host/PAD.h"
#include "ps2/BiosTools.h" #include "ps2/BiosTools.h"
@ -855,7 +855,7 @@ void FullscreenUI::DoChangeDiscFromFile()
auto callback = [](const std::string& path) { auto callback = [](const std::string& path) {
if (!path.empty()) if (!path.empty())
{ {
if (!GameList::IsScannableFilename(path)) if (!VMManager::IsDiscFileName(path))
{ {
ShowToast({}, fmt::format("{} is not a valid disc image.", FileSystem::GetDisplayNameFromPath(path))); ShowToast({}, fmt::format("{} is not a valid disc image.", FileSystem::GetDisplayNameFromPath(path)));
} }

View File

@ -46,6 +46,8 @@ namespace GameList
{ {
using CacheMap = std::unordered_map<std::string, GameList::Entry>; using CacheMap = std::unordered_map<std::string, GameList::Entry>;
static bool IsScannableFilename(const std::string_view& path);
static Entry* GetMutableEntryForPath(const char* path); static Entry* GetMutableEntryForPath(const char* path);
static bool GetElfListEntry(const std::string& path, GameList::Entry* entry); static bool GetElfListEntry(const std::string& path, GameList::Entry* entry);
@ -119,15 +121,7 @@ const char* GameList::EntryCompatibilityRatingToString(CompatibilityRating ratin
bool GameList::IsScannableFilename(const std::string_view& path) bool GameList::IsScannableFilename(const std::string_view& path)
{ {
static const char* extensions[] = {".iso", ".mdf", ".nrg", ".bin", ".img", ".gz", ".cso", ".chd", ".elf", ".irx"}; return VMManager::IsDiscFileName(path) || VMManager::IsElfFileName(path);
for (const char* test_extension : extensions)
{
if (StringUtil::EndsWithNoCase(path, test_extension))
return true;
}
return false;
} }
void GameList::FillBootParametersForEntry(VMBootParameters* params, const Entry* entry) void GameList::FillBootParametersForEntry(VMBootParameters* params, const Entry* entry)

View File

@ -100,8 +100,6 @@ namespace GameList
const char* RegionToString(Region region); const char* RegionToString(Region region);
const char* EntryCompatibilityRatingToString(CompatibilityRating rating); const char* EntryCompatibilityRatingToString(CompatibilityRating rating);
bool IsScannableFilename(const std::string_view& path);
/// Fills in boot parameters (iso or elf) based on the game list entry. /// Fills in boot parameters (iso or elf) based on the game list entry.
void FillBootParametersForEntry(VMBootParameters* params, const Entry* entry); void FillBootParametersForEntry(VMBootParameters* params, const Entry* entry);

View File

@ -134,7 +134,7 @@ static std::array<std::unique_ptr<InputSource>, static_cast<u32>(InputSourceType
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// Hotkeys // Hotkeys
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
static const HotkeyInfo* const s_hotkey_list[] = {g_host_hotkeys, g_vm_manager_hotkeys, g_gs_hotkeys}; static const HotkeyInfo* const s_hotkey_list[] = {g_common_hotkeys, g_gs_hotkeys, g_host_hotkeys};
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// Tracking host mouse movement and turning into relative events // Tracking host mouse movement and turning into relative events

View File

@ -131,7 +131,7 @@ struct HotkeyInfo
} \ } \
; ;
DECLARE_HOTKEY_LIST(g_vm_manager_hotkeys); DECLARE_HOTKEY_LIST(g_common_hotkeys);
DECLARE_HOTKEY_LIST(g_gs_hotkeys); DECLARE_HOTKEY_LIST(g_gs_hotkeys);
DECLARE_HOTKEY_LIST(g_host_hotkeys); DECLARE_HOTKEY_LIST(g_host_hotkeys);

View File

@ -66,6 +66,7 @@ static const char s_console_colors[][ConsoleColors_Count] = {
}; };
#undef CC #undef CC
static bool s_block_system_console = false;
static Common::Timer::Value s_log_start_timestamp = Common::Timer::GetCurrentValue(); static Common::Timer::Value s_log_start_timestamp = Common::Timer::GetCurrentValue();
static bool s_log_timestamps = false; static bool s_log_timestamps = false;
static std::mutex s_log_mutex; static std::mutex s_log_mutex;
@ -364,31 +365,36 @@ static void UpdateLoggingSinks(bool system_console, bool file_log)
Console_SetActiveHandler(ConsoleWriter_Null); Console_SetActiveHandler(ConsoleWriter_Null);
} }
void Host::InitializeEarlyConsole() void CommonHost::SetBlockSystemConsole(bool block)
{
s_block_system_console = block;
}
void CommonHost::InitializeEarlyConsole()
{ {
UpdateLoggingSinks(true, false); UpdateLoggingSinks(true, false);
} }
void Host::UpdateLogging(bool disable_system_console) void CommonHost::UpdateLogging(SettingsInterface& si)
{ {
const bool system_console_enabled = !disable_system_console && Host::GetBaseBoolSettingValue("Logging", "EnableSystemConsole", false); const bool system_console_enabled = !s_block_system_console && si.GetBoolValue("Logging", "EnableSystemConsole", false);
const bool file_logging_enabled = Host::GetBaseBoolSettingValue("Logging", "EnableFileLogging", false); const bool file_logging_enabled = si.GetBoolValue("Logging", "EnableFileLogging", false);
s_log_timestamps = Host::GetBaseBoolSettingValue("Logging", "EnableTimestamps", true); s_log_timestamps = si.GetBoolValue("Logging", "EnableTimestamps", true);
const bool any_logging_sinks = system_console_enabled || file_logging_enabled; const bool any_logging_sinks = system_console_enabled || file_logging_enabled;
DevConWriterEnabled = any_logging_sinks && (IsDevBuild || Host::GetBaseBoolSettingValue("Logging", "EnableVerbose", false)); DevConWriterEnabled = any_logging_sinks && (IsDevBuild || si.GetBoolValue("Logging", "EnableVerbose", false));
SysConsole.eeConsole.Enabled = any_logging_sinks && Host::GetBaseBoolSettingValue("Logging", "EnableEEConsole", false); SysConsole.eeConsole.Enabled = any_logging_sinks && si.GetBoolValue("Logging", "EnableEEConsole", false);
SysConsole.iopConsole.Enabled = any_logging_sinks && Host::GetBaseBoolSettingValue("Logging", "EnableIOPConsole", false); SysConsole.iopConsole.Enabled = any_logging_sinks && si.GetBoolValue("Logging", "EnableIOPConsole", false);
// Input Recording Logs // Input Recording Logs
SysConsole.recordingConsole.Enabled = any_logging_sinks && Host::GetBaseBoolSettingValue("Logging", "EnableInputRecordingLogs", true); SysConsole.recordingConsole.Enabled = any_logging_sinks && si.GetBoolValue("Logging", "EnableInputRecordingLogs", true);
SysConsole.controlInfo.Enabled = any_logging_sinks && Host::GetBaseBoolSettingValue("Logging", "EnableControllerLogs", false); SysConsole.controlInfo.Enabled = any_logging_sinks && si.GetBoolValue("Logging", "EnableControllerLogs", false);
UpdateLoggingSinks(system_console_enabled, file_logging_enabled); UpdateLoggingSinks(system_console_enabled, file_logging_enabled);
} }
void Host::SetDefaultLoggingSettings(SettingsInterface& si) void CommonHost::SetDefaultLoggingSettings(SettingsInterface& si)
{ {
si.SetBoolValue("Logging", "EnableSystemConsole", false); si.SetBoolValue("Logging", "EnableSystemConsole", false);
si.SetBoolValue("Logging", "EnableFileLogging", false); si.SetBoolValue("Logging", "EnableFileLogging", false);

View File

@ -17,10 +17,13 @@
class SettingsInterface; class SettingsInterface;
namespace Host namespace CommonHost
{ {
/// Prevents the system console from being displayed.
void SetBlockSystemConsole(bool block);
/// Updates the Console handler based on the current configuration. /// Updates the Console handler based on the current configuration.
void UpdateLogging(bool disable_system_console); void UpdateLogging(SettingsInterface& si);
/// Initializes early console logging (for printing command line arguments). /// Initializes early console logging (for printing command line arguments).
void InitializeEarlyConsole(); void InitializeEarlyConsole();

View File

@ -39,6 +39,7 @@
#include "GSDumpReplayer.h" #include "GSDumpReplayer.h"
#include "HostDisplay.h" #include "HostDisplay.h"
#include "HostSettings.h" #include "HostSettings.h"
#include "INISettingsInterface.h"
#include "IopBios.h" #include "IopBios.h"
#include "MTVU.h" #include "MTVU.h"
#include "MemoryCardFile.h" #include "MemoryCardFile.h"
@ -56,10 +57,6 @@
#include "DebugTools/MIPSAnalyst.h" #include "DebugTools/MIPSAnalyst.h"
#include "DebugTools/SymbolMap.h" #include "DebugTools/SymbolMap.h"
#include "Frontend/FullscreenUI.h"
#include "Frontend/INISettingsInterface.h"
#include "Frontend/InputManager.h"
#include "Frontend/GameList.h"
#include "IconsFontAwesome5.h" #include "IconsFontAwesome5.h"
#include "common/emitter/tools.h" #include "common/emitter/tools.h"
@ -135,10 +132,8 @@ static std::vector<u8> s_no_interlacing_cheats_data;
static bool s_no_interlacing_cheats_loaded = false; static bool s_no_interlacing_cheats_loaded = false;
static s32 s_active_widescreen_patches = 0; static s32 s_active_widescreen_patches = 0;
static u32 s_active_no_interlacing_patches = 0; static u32 s_active_no_interlacing_patches = 0;
static s32 s_current_save_slot = 1;
static u32 s_frame_advance_count = 0; static u32 s_frame_advance_count = 0;
static u32 s_mxcsr_saved; static u32 s_mxcsr_saved;
static std::optional<LimiterModeType> s_limiter_mode_prior_to_hold_interaction;
static bool s_gs_open_on_initialize = false; static bool s_gs_open_on_initialize = false;
bool VMManager::PerformEarlyHardwareChecks(const char** error) bool VMManager::PerformEarlyHardwareChecks(const char** error)
@ -193,7 +188,6 @@ void VMManager::SetState(VMState state)
if (THREAD_VU1) if (THREAD_VU1)
vu1Thread.WaitVU(); vu1Thread.WaitVU();
GetMTGS().WaitGS(false); GetMTGS().WaitGS(false);
InputManager::PauseVibration();
} }
else else
{ {
@ -203,15 +197,9 @@ void VMManager::SetState(VMState state)
SPU2SetOutputPaused(state == VMState::Paused); SPU2SetOutputPaused(state == VMState::Paused);
if (state == VMState::Paused) if (state == VMState::Paused)
{
Host::OnVMPaused(); Host::OnVMPaused();
FullscreenUI::OnVMPaused();
}
else else
{
Host::OnVMResumed(); Host::OnVMResumed();
FullscreenUI::OnVMResumed();
}
} }
} }
@ -319,12 +307,10 @@ void VMManager::LoadSettings()
{ {
std::unique_lock<std::mutex> lock = Host::GetSettingsLock(); std::unique_lock<std::mutex> lock = Host::GetSettingsLock();
SettingsInterface* si = Host::GetSettingsInterface(); SettingsInterface* si = Host::GetSettingsInterface();
SettingsInterface* binding_si = Host::GetSettingsInterfaceForBindings();
SettingsLoadWrapper slw(*si); SettingsLoadWrapper slw(*si);
EmuConfig.LoadSave(slw); EmuConfig.LoadSave(slw);
PAD::LoadConfig(*binding_si); PAD::LoadConfig(*si);
InputManager::ReloadSources(*si, lock); Host::LoadSettings(*si, lock);
InputManager::ReloadBindings(*si, *binding_si);
// Remove any user-specified hacks in the config (we don't want stale/conflicting values when it's globally disabled). // Remove any user-specified hacks in the config (we don't want stale/conflicting values when it's globally disabled).
EmuConfig.GS.MaskUserHacks(); EmuConfig.GS.MaskUserHacks();
@ -703,12 +689,6 @@ void VMManager::UpdateRunningGame(bool resetting, bool game_starting)
GetMTGS().SendGameCRC(new_crc); GetMTGS().SendGameCRC(new_crc);
Host::OnGameChanged(s_disc_path, s_game_serial, s_game_name, s_game_crc); Host::OnGameChanged(s_disc_path, s_game_serial, s_game_name, s_game_crc);
if (FullscreenUI::IsInitialized())
{
GetMTGS().RunOnGSThread([disc_path = s_disc_path, game_serial = s_game_serial, game_name = s_game_name, game_crc = s_game_crc]() {
FullscreenUI::OnRunningGameChanged(std::move(disc_path), std::move(game_serial), std::move(game_name), game_crc);
});
}
#if 0 #if 0
// TODO: Enable this when the debugger is added to Qt, and it's active. Otherwise, this is just a waste of time. // TODO: Enable this when the debugger is added to Qt, and it's active. Otherwise, this is just a waste of time.
@ -992,7 +972,6 @@ bool VMManager::Initialize(VMBootParameters boot_params)
Console.WriteLn("VM subsystems initialized in %.2f ms", init_timer.GetTimeMilliseconds()); Console.WriteLn("VM subsystems initialized in %.2f ms", init_timer.GetTimeMilliseconds());
s_state.store(VMState::Paused, std::memory_order_release); s_state.store(VMState::Paused, std::memory_order_release);
Host::OnVMStarted(); Host::OnVMStarted();
FullscreenUI::OnVMStarted();
UpdateRunningGame(true, false); UpdateRunningGame(true, false);
@ -1055,7 +1034,6 @@ void VMManager::Shutdown(bool save_resume_state)
s_active_game_fixes = 0; s_active_game_fixes = 0;
s_active_widescreen_patches = 0; s_active_widescreen_patches = 0;
s_active_no_interlacing_patches = 0; s_active_no_interlacing_patches = 0;
s_limiter_mode_prior_to_hold_interaction.reset();
UpdateGameSettingsLayer(); UpdateGameSettingsLayer();
@ -1094,7 +1072,6 @@ void VMManager::Shutdown(bool save_resume_state)
s_state.store(VMState::Shutdown, std::memory_order_release); s_state.store(VMState::Shutdown, std::memory_order_release);
Host::OnVMDestroyed(); Host::OnVMDestroyed();
FullscreenUI::OnVMDestroyed();
} }
void VMManager::Reset() void VMManager::Reset()
@ -1104,7 +1081,6 @@ void VMManager::Reset()
s_active_game_fixes = 0; s_active_game_fixes = 0;
s_active_widescreen_patches = 0; s_active_widescreen_patches = 0;
s_active_no_interlacing_patches = 0; s_active_no_interlacing_patches = 0;
s_limiter_mode_prior_to_hold_interaction.reset();
SysClearExecutionCache(); SysClearExecutionCache();
memBindConditionalHandlers(); memBindConditionalHandlers();
@ -1138,22 +1114,10 @@ std::string VMManager::GetSaveStateFileName(const char* filename, s32 slot)
pxAssertRel(!HasValidVM(), "Should not have a VM when calling the non-gamelist GetSaveStateFileName()"); pxAssertRel(!HasValidVM(), "Should not have a VM when calling the non-gamelist GetSaveStateFileName()");
std::string ret; std::string ret;
std::string serial;
// try the game list first, but this won't work if we're in batch mode u32 crc;
auto lock = GameList::GetLock(); if (Host::GetSerialAndCRCForFilename(filename, &serial, &crc))
if (const GameList::Entry* entry = GameList::GetEntryForPath(filename); entry) ret = GetSaveStateFileName(serial.c_str(), crc, slot);
{
ret = GetSaveStateFileName(entry->serial.c_str(), entry->crc, slot);
}
else
{
// just scan it.. hopefully it'll come back okay
GameList::Entry temp_entry;
if (GameList::PopulateEntryFromPath(filename, &temp_entry))
{
ret = GetSaveStateFileName(temp_entry.serial.c_str(), temp_entry.crc, slot);
}
}
return ret; return ret;
} }
@ -1409,9 +1373,22 @@ bool VMManager::IsSaveStateFileName(const std::string_view& path)
return StringUtil::EndsWithNoCase(path, ".p2s"); return StringUtil::EndsWithNoCase(path, ".p2s");
} }
bool VMManager::IsDiscFileName(const std::string_view& path)
{
static const char* extensions[] = {".iso", ".bin", ".img", ".gz", ".cso", ".chd"};
for (const char* test_extension : extensions)
{
if (StringUtil::EndsWithNoCase(path, test_extension))
return true;
}
return false;
}
bool VMManager::IsLoadableFileName(const std::string_view& path) bool VMManager::IsLoadableFileName(const std::string_view& path)
{ {
return IsElfFileName(path) || IsGSDumpFileName(path) || IsBlockDumpFileName(path) || GameList::IsScannableFilename(path); return IsDiscFileName(path) || IsElfFileName(path) || IsGSDumpFileName(path) || IsBlockDumpFileName(path);
} }
void VMManager::Execute() void VMManager::Execute()
@ -1482,8 +1459,7 @@ void VMManager::Internal::VSyncOnCPUThread()
} }
} }
Host::PumpMessagesOnCPUThread(); Host::CPUThreadVSync();
InputManager::PollSources();
} }
void VMManager::CheckForCPUConfigChanges(const Pcsx2Config& old_config) void VMManager::CheckForCPUConfigChanges(const Pcsx2Config& old_config)
@ -1681,6 +1657,8 @@ void VMManager::CheckForConfigChanges(const Pcsx2Config& old_config)
// and we don't update its config when we start the VM. // and we don't update its config when we start the VM.
if (HasValidVM() || GetMTGS().IsOpen()) if (HasValidVM() || GetMTGS().IsOpen())
CheckForGSConfigChanges(old_config); CheckForGSConfigChanges(old_config);
Host::CheckForSettingsChanges(old_config);
} }
void VMManager::ApplySettings() void VMManager::ApplySettings()
@ -1808,204 +1786,6 @@ void VMManager::WarnAboutUnsafeSettings()
} }
} }
static void HotkeyAdjustTargetSpeed(double delta)
{
EmuConfig.Framerate.NominalScalar = EmuConfig.GS.LimitScalar + delta;
VMManager::SetLimiterMode(LimiterModeType::Nominal);
gsUpdateFrequency(EmuConfig);
GetMTGS().SetVSync(EmuConfig.GetEffectiveVsyncMode());
Host::AddIconOSDMessage("SpeedChanged", ICON_FA_CLOCK, fmt::format("Target speed set to {:.0f}%.", std::round(EmuConfig.Framerate.NominalScalar * 100.0)), 5.0f);
}
static constexpr s32 CYCLE_SAVE_STATE_SLOTS = 10;
static void HotkeyCycleSaveSlot(s32 delta)
{
// 1..10
s_current_save_slot = ((s_current_save_slot - 1) + delta);
if (s_current_save_slot < 0)
s_current_save_slot = CYCLE_SAVE_STATE_SLOTS;
else
s_current_save_slot = (s_current_save_slot % CYCLE_SAVE_STATE_SLOTS) + 1;
const std::string filename(VMManager::GetSaveStateFileName(s_game_serial.c_str(), s_game_crc, s_current_save_slot));
FILESYSTEM_STAT_DATA sd;
if (!filename.empty() && FileSystem::StatFile(filename.c_str(), &sd))
{
char date_buf[128] = {};
#ifdef _WIN32
ctime_s(date_buf, std::size(date_buf), &sd.ModificationTime);
#else
ctime_r(&sd.ModificationTime, date_buf);
#endif
// remove terminating \n
size_t len = std::strlen(date_buf);
if (len > 0 && date_buf[len - 1] == '\n')
date_buf[len - 1] = 0;
Host::AddIconOSDMessage("CycleSaveSlot", ICON_FA_SEARCH, fmt::format("Save slot {} selected (last save: {}).", s_current_save_slot, date_buf), 5.0f);
}
else
{
Host::AddIconOSDMessage("CycleSaveSlot", ICON_FA_SEARCH, fmt::format("Save slot {} selected (no save yet).", s_current_save_slot), 5.0f);
}
}
static void HotkeyLoadStateSlot(s32 slot)
{
if (s_game_crc == 0)
{
Host::AddIconOSDMessage("LoadStateFromSlot", ICON_FA_EXCLAMATION_TRIANGLE, "Cannot load state from a slot without a game running.", 10.0f);
return;
}
if (!VMManager::HasSaveStateInSlot(s_game_serial.c_str(), s_game_crc, slot))
{
Host::AddIconOSDMessage("LoadStateFromSlot", ICON_FA_EXCLAMATION_TRIANGLE, fmt::format("No save state found in slot {}.", slot));
return;
}
VMManager::LoadStateFromSlot(slot);
}
static void HotkeySaveStateSlot(s32 slot)
{
if (s_game_crc == 0)
{
Host::AddIconOSDMessage("SaveStateToSlot", ICON_FA_EXCLAMATION_TRIANGLE, "Cannot save state to a slot without a game running.", 10.0f);
return;
}
VMManager::SaveStateToSlot(slot);
}
BEGIN_HOTKEY_LIST(g_vm_manager_hotkeys)
DEFINE_HOTKEY("OpenPauseMenu", "System", "Open Pause Menu", [](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
FullscreenUI::OpenPauseMenu();
})
DEFINE_HOTKEY("TogglePause", "System", "Toggle Pause", [](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
VMManager::SetPaused(VMManager::GetState() != VMState::Paused);
})
DEFINE_HOTKEY("ToggleFullscreen", "System", "Toggle Fullscreen", [](s32 pressed) {
if (!pressed)
Host::SetFullscreen(!Host::IsFullscreen());
})
DEFINE_HOTKEY("ToggleFrameLimit", "System", "Toggle Frame Limit", [](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
{
VMManager::SetLimiterMode((EmuConfig.LimiterMode != LimiterModeType::Unlimited) ?
LimiterModeType::Unlimited :
LimiterModeType::Nominal);
}
})
DEFINE_HOTKEY("ToggleTurbo", "System", "Toggle Turbo", [](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
{
VMManager::SetLimiterMode((EmuConfig.LimiterMode != LimiterModeType::Turbo) ?
LimiterModeType::Turbo :
LimiterModeType::Nominal);
}
})
DEFINE_HOTKEY("ToggleSlowMotion", "System", "Toggle Slow Motion", [](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
{
VMManager::SetLimiterMode((EmuConfig.LimiterMode != LimiterModeType::Slomo) ?
LimiterModeType::Slomo :
LimiterModeType::Nominal);
}
})
DEFINE_HOTKEY("HoldTurbo", "System", "Turbo (Hold)", [](s32 pressed) {
if (!VMManager::HasValidVM())
return;
if (pressed > 0 && !s_limiter_mode_prior_to_hold_interaction.has_value())
{
s_limiter_mode_prior_to_hold_interaction = VMManager::GetLimiterMode();
VMManager::SetLimiterMode((s_limiter_mode_prior_to_hold_interaction.value() != LimiterModeType::Turbo) ?
LimiterModeType::Turbo :
LimiterModeType::Nominal);
}
else if (pressed >= 0 && s_limiter_mode_prior_to_hold_interaction.has_value())
{
VMManager::SetLimiterMode(s_limiter_mode_prior_to_hold_interaction.value());
s_limiter_mode_prior_to_hold_interaction.reset();
}
})
DEFINE_HOTKEY("IncreaseSpeed", "System", "Increase Target Speed", [](s32 pressed) {
if (!pressed)
HotkeyAdjustTargetSpeed(0.1);
})
DEFINE_HOTKEY("DecreaseSpeed", "System", "Decrease Target Speed", [](s32 pressed) {
if (!pressed)
HotkeyAdjustTargetSpeed(-0.1);
})
DEFINE_HOTKEY("FrameAdvance", "System", "Frame Advance", [](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
VMManager::FrameAdvance(1);
})
DEFINE_HOTKEY("ShutdownVM", "System", "Shut Down Virtual Machine", [](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
Host::RequestVMShutdown(true, true, EmuConfig.SaveStateOnShutdown);
})
DEFINE_HOTKEY("ResetVM", "System", "Reset Virtual Machine", [](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
VMManager::Reset();
})
DEFINE_HOTKEY("InputRecToggleMode", "System", "Toggle Input Recording Mode", [](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
g_InputRecordingControls.RecordModeToggle();
})
DEFINE_HOTKEY("PreviousSaveStateSlot", "Save States", "Select Previous Save Slot", [](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
HotkeyCycleSaveSlot(-1);
})
DEFINE_HOTKEY("NextSaveStateSlot", "Save States", "Select Next Save Slot", [](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
HotkeyCycleSaveSlot(1);
})
DEFINE_HOTKEY("SaveStateToSlot", "Save States", "Save State To Selected Slot", [](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
VMManager::SaveStateToSlot(s_current_save_slot);
})
DEFINE_HOTKEY("LoadStateFromSlot", "Save States", "Load State From Selected Slot", [](s32 pressed) {
if (!pressed && VMManager::HasValidVM())
HotkeyLoadStateSlot(s_current_save_slot);
})
#define DEFINE_HOTKEY_SAVESTATE_X(slotnum) DEFINE_HOTKEY("SaveStateToSlot" #slotnum, \
"Save States", "Save State To Slot " #slotnum, [](s32 pressed) { if (!pressed) HotkeySaveStateSlot(slotnum); })
#define DEFINE_HOTKEY_LOADSTATE_X(slotnum) DEFINE_HOTKEY("LoadStateFromSlot" #slotnum, \
"Save States", "Load State From Slot " #slotnum, [](s32 pressed) { \
if (!pressed) \
HotkeyLoadStateSlot(slotnum); \
})
DEFINE_HOTKEY_SAVESTATE_X(1)
DEFINE_HOTKEY_LOADSTATE_X(1)
DEFINE_HOTKEY_SAVESTATE_X(2)
DEFINE_HOTKEY_LOADSTATE_X(2)
DEFINE_HOTKEY_SAVESTATE_X(3)
DEFINE_HOTKEY_LOADSTATE_X(3)
DEFINE_HOTKEY_SAVESTATE_X(4)
DEFINE_HOTKEY_LOADSTATE_X(4)
DEFINE_HOTKEY_SAVESTATE_X(5)
DEFINE_HOTKEY_LOADSTATE_X(5)
DEFINE_HOTKEY_SAVESTATE_X(6)
DEFINE_HOTKEY_LOADSTATE_X(6)
DEFINE_HOTKEY_SAVESTATE_X(7)
DEFINE_HOTKEY_LOADSTATE_X(7)
DEFINE_HOTKEY_SAVESTATE_X(8)
DEFINE_HOTKEY_LOADSTATE_X(8)
DEFINE_HOTKEY_SAVESTATE_X(9)
DEFINE_HOTKEY_LOADSTATE_X(9)
DEFINE_HOTKEY_SAVESTATE_X(10)
DEFINE_HOTKEY_LOADSTATE_X(10)
#undef DEFINE_HOTKEY_SAVESTATE_X
#undef DEFINE_HOTKEY_LOADSTATE_X
END_HOTKEY_LIST()
#ifdef _WIN32 #ifdef _WIN32
#include "common/RedtapeWindows.h" #include "common/RedtapeWindows.h"

View File

@ -152,6 +152,9 @@ namespace VMManager
/// Returns true if the specified path is a save state. /// Returns true if the specified path is a save state.
bool IsSaveStateFileName(const std::string_view& path); bool IsSaveStateFileName(const std::string_view& path);
/// Returns true if the specified path is a disc image.
bool IsDiscFileName(const std::string_view& path);
/// Returns true if the specified path is a disc/elf/etc. /// Returns true if the specified path is a disc/elf/etc.
bool IsLoadableFileName(const std::string_view& path); bool IsLoadableFileName(const std::string_view& path);
@ -198,6 +201,12 @@ namespace VMManager
namespace Host namespace Host
{ {
/// Called with the settings lock held, when system settings are being loaded (should load input sources, etc).
void LoadSettings(SettingsInterface& si, std::unique_lock<std::mutex>& lock);
/// Called after settings are updated.
void CheckForSettingsChanges(const Pcsx2Config& old_config);
/// Called when the VM is starting initialization, but has not been completed yet. /// Called when the VM is starting initialization, but has not been completed yet.
void OnVMStarting(); void OnVMStarting();
@ -216,6 +225,10 @@ namespace Host
/// Called when performance metrics are updated, approximately once a second. /// Called when performance metrics are updated, approximately once a second.
void OnPerformanceMetricsUpdated(); void OnPerformanceMetricsUpdated();
/// Looks up the serial and CRC for a game in the most efficient manner possible.
/// Implemented in the host because it may have a game list cache.
bool GetSerialAndCRCForFilename(const char* filename, std::string* serial, u32* crc);
/// Called when a save state is loading, before the file is processed. /// Called when a save state is loading, before the file is processed.
void OnSaveStateLoading(const std::string_view& filename); void OnSaveStateLoading(const std::string_view& filename);
@ -230,7 +243,7 @@ namespace Host
void OnGameChanged(const std::string& disc_path, const std::string& game_serial, const std::string& game_name, u32 game_crc); void OnGameChanged(const std::string& disc_path, const std::string& game_serial, const std::string& game_name, u32 game_crc);
/// Provided by the host; called once per frame at guest vsync. /// Provided by the host; called once per frame at guest vsync.
void PumpMessagesOnCPUThread(); void CPUThreadVSync();
/// Provided by the host; called when a state is saved, and the frontend should invalidate its save state cache. /// Provided by the host; called when a state is saved, and the frontend should invalidate its save state cache.
void InvalidateSaveStateCache(); void InvalidateSaveStateCache();

View File

@ -187,6 +187,7 @@
<ClCompile Include="DEV9\net.cpp" /> <ClCompile Include="DEV9\net.cpp" />
<ClCompile Include="DEV9\Win32\tap-win32.cpp" /> <ClCompile Include="DEV9\Win32\tap-win32.cpp" />
<ClCompile Include="Frontend\CommonHost.cpp" /> <ClCompile Include="Frontend\CommonHost.cpp" />
<ClCompile Include="Frontend\CommonHotkeys.cpp" />
<ClCompile Include="Frontend\D3D11HostDisplay.cpp" /> <ClCompile Include="Frontend\D3D11HostDisplay.cpp" />
<ClCompile Include="Frontend\D3D12HostDisplay.cpp" /> <ClCompile Include="Frontend\D3D12HostDisplay.cpp" />
<ClCompile Include="Frontend\FullscreenUI.cpp" /> <ClCompile Include="Frontend\FullscreenUI.cpp" />
@ -197,7 +198,7 @@
<ClCompile Include="Frontend\imgui_impl_dx12.cpp" /> <ClCompile Include="Frontend\imgui_impl_dx12.cpp" />
<ClCompile Include="Frontend\imgui_impl_opengl3.cpp" /> <ClCompile Include="Frontend\imgui_impl_opengl3.cpp" />
<ClCompile Include="Frontend\imgui_impl_vulkan.cpp" /> <ClCompile Include="Frontend\imgui_impl_vulkan.cpp" />
<ClCompile Include="Frontend\INISettingsInterface.cpp" /> <ClCompile Include="INISettingsInterface.cpp" />
<ClCompile Include="Frontend\InputManager.cpp" /> <ClCompile Include="Frontend\InputManager.cpp" />
<ClCompile Include="Frontend\InputSource.cpp" /> <ClCompile Include="Frontend\InputSource.cpp" />
<ClCompile Include="Frontend\LayeredSettingsInterface.cpp" /> <ClCompile Include="Frontend\LayeredSettingsInterface.cpp" />
@ -520,7 +521,7 @@
<ClInclude Include="Frontend\imgui_impl_dx12.h" /> <ClInclude Include="Frontend\imgui_impl_dx12.h" />
<ClInclude Include="Frontend\imgui_impl_opengl3.h" /> <ClInclude Include="Frontend\imgui_impl_opengl3.h" />
<ClInclude Include="Frontend\imgui_impl_vulkan.h" /> <ClInclude Include="Frontend\imgui_impl_vulkan.h" />
<ClInclude Include="Frontend\INISettingsInterface.h" /> <ClInclude Include="INISettingsInterface.h" />
<ClInclude Include="Frontend\InputManager.h" /> <ClInclude Include="Frontend\InputManager.h" />
<ClInclude Include="Frontend\InputSource.h" /> <ClInclude Include="Frontend\InputSource.h" />
<ClInclude Include="Frontend\LayeredSettingsInterface.h" /> <ClInclude Include="Frontend\LayeredSettingsInterface.h" />
@ -817,4 +818,4 @@
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets" /> <ImportGroup Label="ExtensionTargets" />
</Project> </Project>

View File

@ -1172,7 +1172,7 @@
<ClCompile Include="Frontend\GameList.cpp"> <ClCompile Include="Frontend\GameList.cpp">
<Filter>Host</Filter> <Filter>Host</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Frontend\INISettingsInterface.cpp"> <ClCompile Include="INISettingsInterface.cpp">
<Filter>Host</Filter> <Filter>Host</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Frontend\InputManager.cpp"> <ClCompile Include="Frontend\InputManager.cpp">
@ -1284,6 +1284,9 @@
<ClCompile Include="Frontend\CommonHost.cpp"> <ClCompile Include="Frontend\CommonHost.cpp">
<Filter>Host</Filter> <Filter>Host</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Frontend\CommonHotkeys.cpp">
<Filter>Host</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Patch.h"> <ClInclude Include="Patch.h">
@ -2037,7 +2040,7 @@
<ClInclude Include="Frontend\GameList.h"> <ClInclude Include="Frontend\GameList.h">
<Filter>Host</Filter> <Filter>Host</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Frontend\INISettingsInterface.h"> <ClInclude Include="INISettingsInterface.h">
<Filter>Host</Filter> <Filter>Host</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Frontend\InputManager.h"> <ClInclude Include="Frontend\InputManager.h">