CommonHost: Purge and move functions to appropriate locations

This commit is contained in:
Stenzek 2023-05-13 20:22:46 +10:00 committed by refractionpcsx2
parent ad0e469f87
commit 0f05967190
28 changed files with 639 additions and 883 deletions

View File

@ -33,14 +33,9 @@
<ClCompile>
<PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>TurnOffAllWarnings</WarningLevel>
<AdditionalIncludeDirectories>$(SolutionDir)3rdparty\glad\include;$(ProjectDir)include;$(ProjectDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(ProjectDir)include;$(ProjectDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ProjectReference Include="$(SolutionDir)3rdparty\glad\glad.vcxproj">
<Project>{c0293b32-5acf-40f0-aa6c-e6da6f3bf33a}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClInclude Include="include\imconfig.h" />
<ClInclude Include="include\imgui.h" />
@ -60,4 +55,4 @@
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets" />
</Project>
</Project>

View File

@ -154,6 +154,10 @@ if(APPLE)
)
target_compile_options(common PRIVATE -fobjc-arc)
target_link_options(common PRIVATE -fobjc-link-runtime)
target_link_libraries(common PRIVATE
"-framework Foundation"
"-framework IOKit"
)
endif()
if(DBUS_API)

View File

@ -37,7 +37,6 @@
#include "pcsx2/PrecompiledHeader.h"
#include "pcsx2/CommonHost.h"
#include "pcsx2/Achievements.h"
#include "pcsx2/CDVD/CDVD.h"
#include "pcsx2/GS.h"
@ -83,14 +82,14 @@ static u32 s_loop_number = s_loop_count;
bool GSRunner::InitializeConfig()
{
if (!CommonHost::InitializeCriticalFolders())
if (!EmuFolders::InitializeCriticalFolders())
return false;
// don't provide an ini path, or bother loading. we'll store everything in memory.
MemorySettingsInterface& si = s_settings_interface;
Host::Internal::SetBaseSettingsLayer(&si);
CommonHost::SetDefaultSettings(si, true, true, true, true, true);
VMManager::SetDefaultSettings(si, true, true, true, true, true);
// complete as quickly as possible
si.SetBoolValue("EmuCore/GS", "FrameLimitEnable", false);
@ -127,7 +126,7 @@ bool GSRunner::InitializeConfig()
si.SetStringValue("MemoryCards", fmt::format("Slot{}_Filename", i + 1).c_str(), "");
}
CommonHost::LoadStartupSettings();
VMManager::Internal::LoadStartupSettings();
return true;
}
@ -138,12 +137,10 @@ void Host::CommitBaseSettingChanges()
void Host::LoadSettings(SettingsInterface& si, std::unique_lock<std::mutex>& lock)
{
CommonHost::LoadSettings(si, lock);
}
void Host::CheckForSettingsChanges(const Pcsx2Config& old_config)
{
CommonHost::CheckForSettingsChanges(old_config);
}
bool Host::RequestResetSettings(bool folders, bool core, bool controllers, bool hotkeys, bool ui)
@ -410,7 +407,7 @@ void GSRunner::InitializeConsole()
const char* var = std::getenv("PCSX2_NOCONSOLE");
s_no_console = (var && StringUtil::FromChars<bool>(var).value_or(false));
if (!s_no_console)
CommonHost::InitializeEarlyConsole();
LogSink::InitializeEarlyConsole();
}
bool GSRunner::ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& params)
@ -536,7 +533,7 @@ bool GSRunner::ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& pa
{
// disable timestamps, since we want to be able to diff the logs
Console.WriteLn("Logging to %s...", logfile);
CommonHost::SetFileLogPath(logfile);
LogSink::SetFileLogPath(logfile);
s_settings_interface.SetBoolValue("Logging", "EnableFileLogging", true);
s_settings_interface.SetBoolValue("Logging", "EnableTimestamps", false);
}
@ -622,12 +619,8 @@ int main(int argc, char* argv[])
if (!GSRunner::ParseCommandLineArgs(argc, argv, params))
return EXIT_FAILURE;
PerformanceMetrics::SetCPUThread(Threading::ThreadHandle::GetForCallingThread());
if (!VMManager::Internal::InitializeGlobals() || !VMManager::Internal::InitializeMemory())
{
Console.Error("Failed to allocate globals/memory.");
if (!VMManager::Internal::CPUThreadInitialize())
return EXIT_FAILURE;
}
if (s_use_window.value_or(true) && !GSRunner::CreatePlatformWindow())
{
@ -649,16 +642,13 @@ int main(int argc, char* argv[])
VMManager::Shutdown(false);
}
InputManager::CloseSources();
VMManager::Internal::ReleaseMemory();
VMManager::Internal::ReleaseGlobals();
PerformanceMetrics::SetCPUThread(Threading::ThreadHandle());
VMManager::Internal::CPUThreadShutdown();
GSRunner::DestroyPlatformWindow();
return EXIT_SUCCESS;
}
void Host::CPUThreadVSync()
void Host::VSyncOnCPUThread()
{
// update GS thread copy of frame number
GetMTGS().RunOnGSThread([frame_number = GSDumpReplayer::GetFrameNumber()]() { s_dump_frame_number = frame_number; });

View File

@ -24,7 +24,6 @@
#include "svnrev.h"
#include "pcsx2/CDVD/CDVDcommon.h"
#include "pcsx2/CommonHost.h"
#include "pcsx2/Achievements.h"
#include "pcsx2/CDVD/CDVD.h"
#include "pcsx2/Counters.h"
@ -371,7 +370,12 @@ void EmuThread::run()
connectSignals();
// Common host initialization (VM setup, etc).
CommonHost::CPUThreadInitialize();
if (!VMManager::Internal::CPUThreadInitialize())
{
VMManager::Internal::CPUThreadShutdown();
QMetaObject::invokeMethod(qApp, &QCoreApplication::quit, Qt::QueuedConnection);
return;
}
// Start background polling because the VM won't do it for us.
createBackgroundControllerPollTimer();
@ -392,7 +396,7 @@ void EmuThread::run()
// Teardown in reverse order.
stopBackgroundControllerPollTimer();
destroyBackgroundControllerPollTimer();
CommonHost::CPUThreadShutdown();
VMManager::Internal::CPUThreadShutdown();
// Move back to the UI thread, since we're no longer running.
moveToThread(m_ui_thread);
@ -566,7 +570,7 @@ void EmuThread::updateEmuFolders()
return;
}
Host::Internal::UpdateEmuFolders();
VMManager::Internal::UpdateEmuFolders();
}
void EmuThread::connectSignals()
@ -582,7 +586,6 @@ void EmuThread::loadSettings(SettingsInterface& si, std::unique_lock<std::mutex>
void Host::LoadSettings(SettingsInterface& si, std::unique_lock<std::mutex>& lock)
{
CommonHost::LoadSettings(si, lock);
g_emu_thread->loadSettings(si, lock);
}
@ -606,7 +609,6 @@ void EmuThread::checkForSettingChanges(const Pcsx2Config& old_config)
void Host::CheckForSettingsChanges(const Pcsx2Config& old_config)
{
CommonHost::CheckForSettingsChanges(old_config);
g_emu_thread->checkForSettingChanges(old_config);
}
@ -928,35 +930,29 @@ void Host::RequestResizeHostDisplay(s32 width, s32 height)
void Host::OnVMStarting()
{
CommonHost::OnVMStarting();
g_emu_thread->stopBackgroundControllerPollTimer();
emit g_emu_thread->onVMStarting();
}
void Host::OnVMStarted()
{
CommonHost::OnVMStarted();
emit g_emu_thread->onVMStarted();
}
void Host::OnVMDestroyed()
{
CommonHost::OnVMDestroyed();
emit g_emu_thread->onVMStopped();
g_emu_thread->startBackgroundControllerPollTimer();
}
void Host::OnVMPaused()
{
CommonHost::OnVMPaused();
g_emu_thread->startBackgroundControllerPollTimer();
emit g_emu_thread->onVMPaused();
}
void Host::OnVMResumed()
{
CommonHost::OnVMResumed();
// exit the event loop when we eventually return
g_emu_thread->getEventLoop()->quit();
g_emu_thread->stopBackgroundControllerPollTimer();
@ -971,7 +967,6 @@ void Host::OnVMResumed()
void Host::OnGameChanged(const std::string& disc_path, const std::string& elf_override, const std::string& game_serial,
const std::string& game_name, u32 game_crc)
{
CommonHost::OnGameChanged(disc_path, elf_override, game_serial, game_name, game_crc);
emit g_emu_thread->onGameChanged(QString::fromStdString(disc_path), QString::fromStdString(elf_override),
QString::fromStdString(game_serial), QString::fromStdString(game_name), game_crc);
}
@ -1118,10 +1113,9 @@ void Host::OnAchievementsRefreshed()
}
#endif
void Host::CPUThreadVSync()
void Host::VSyncOnCPUThread()
{
g_emu_thread->getEventLoop()->processEvents(QEventLoop::AllEvents);
CommonHost::CPUThreadVSync();
}
void Host::RunOnCPUThread(std::function<void()> function, bool block /* = false */)
@ -1197,19 +1191,22 @@ SysMtgsThread& GetMTGS()
bool QtHost::InitializeConfig()
{
if (!CommonHost::InitializeCriticalFolders())
if (!EmuFolders::InitializeCriticalFolders())
{
QMessageBox::critical(nullptr, QStringLiteral("PCSX2"),
QStringLiteral("One or more critical directories are missing, your installation may be incomplete."));
return false;
}
// Write crash dumps to the data directory, since that'll be accessible for certain.
CrashHandler::SetWriteDirectory(EmuFolders::DataRoot);
const std::string path(Path::Combine(EmuFolders::Settings, "PCSX2.ini"));
Console.WriteLn("Loading config from %s.", path.c_str());
s_base_settings_interface = std::make_unique<INISettingsInterface>(std::move(path));
Host::Internal::SetBaseSettingsLayer(s_base_settings_interface.get());
if (!s_base_settings_interface->Load() || !CommonHost::CheckSettingsVersion())
if (!s_base_settings_interface->Load() || !VMManager::Internal::CheckSettingsVersion())
{
// If the config file doesn't exist, assume this is a new install and don't prompt to overwrite.
if (FileSystem::FileExists(s_base_settings_interface->GetFileName().c_str()) &&
@ -1220,12 +1217,12 @@ bool QtHost::InitializeConfig()
return false;
}
CommonHost::SetDefaultSettings(*s_base_settings_interface, true, true, true, true, true);
VMManager::SetDefaultSettings(*s_base_settings_interface, true, true, true, true, true);
SaveSettings();
}
CommonHost::SetBlockSystemConsole(QtHost::InNoGUIMode());
CommonHost::LoadStartupSettings();
LogSink::SetBlockSystemConsole(QtHost::InNoGUIMode());
VMManager::Internal::LoadStartupSettings();
return true;
}
@ -1308,7 +1305,7 @@ bool Host::RequestResetSettings(bool folders, bool core, bool controllers, bool
{
{
auto lock = Host::GetSettingsLock();
CommonHost::SetDefaultSettings(*s_base_settings_interface.get(), folders, core, controllers, hotkeys, ui);
VMManager::SetDefaultSettings(*s_base_settings_interface.get(), folders, core, controllers, hotkeys, ui);
}
Host::CommitBaseSettingChanges();
@ -1513,7 +1510,7 @@ void QtHost::HookSignals()
void QtHost::PrintCommandLineVersion()
{
CommonHost::InitializeEarlyConsole();
LogSink::InitializeEarlyConsole();
std::fprintf(stderr, "%s\n", (GetAppNameAndVersion() + GetAppConfigSuffix()).toUtf8().constData());
std::fprintf(stderr, "https://pcsx2.net/\n");
std::fprintf(stderr, "\n");
@ -1629,7 +1626,7 @@ bool QtHost::ParseCommandLineOptions(const QStringList& args, std::shared_ptr<VM
}
else if (CHECK_ARG_PARAM(QStringLiteral("-logfile")))
{
CommonHost::SetFileLogPath((++it)->toStdString());
LogSink::SetFileLogPath((++it)->toStdString());
continue;
}
else if (CHECK_ARG(QStringLiteral("-bios")))
@ -1650,7 +1647,7 @@ bool QtHost::ParseCommandLineOptions(const QStringList& args, std::shared_ptr<VM
}
else if (CHECK_ARG(QStringLiteral("-earlyconsolelog")))
{
CommonHost::InitializeEarlyConsole();
LogSink::InitializeEarlyConsole();
continue;
}
else if (CHECK_ARG(QStringLiteral("-bigpicture")))
@ -1707,7 +1704,7 @@ bool QtHost::ParseCommandLineOptions(const QStringList& args, std::shared_ptr<VM
// or disc, we don't want to actually start.
if (autoboot && !autoboot->source_type.has_value() && autoboot->filename.empty() && autoboot->elf_override.empty())
{
CommonHost::InitializeEarlyConsole();
LogSink::InitializeEarlyConsole();
Console.Warning("Skipping autoboot due to no boot parameters.");
autoboot.reset();
}

View File

@ -21,7 +21,6 @@
#include "Settings/ControllerBindingWidgets.h"
#include "Settings/HotkeySettingsWidget.h"
#include "pcsx2/CommonHost.h"
#include "pcsx2/INISettingsInterface.h"
#include "pcsx2/PAD/Host/PAD.h"
#include "pcsx2/Sio.h"
@ -208,7 +207,7 @@ void ControllerSettingsDialog::onRestoreDefaultsClicked()
// actually restore it
{
auto lock = Host::GetSettingsLock();
CommonHost::SetDefaultSettings(*Host::Internal::GetBaseSettingsLayer(), false, false, true, true, false);
VMManager::SetDefaultSettings(*Host::Internal::GetBaseSettingsLayer(), false, false, true, true, false);
}
Host::CommitBaseSettingChanges();

View File

@ -63,46 +63,15 @@
<ProjectReference Include="$(SolutionDir)3rdparty\fmt\fmt.vcxproj">
<Project>{449ad25e-424a-4714-babc-68706cdcc33b}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)3rdparty\libjpeg\libjpeg.vcxproj">
<Project>{bc236261-77e8-4567-8d09-45cd02965eb6}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)3rdparty\libpng\projects\vstudio\libpng\libpng.vcxproj">
<Project>{d6973076-9317-4ef2-a0b8-b7a18ac0713e}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)3rdparty\soundtouch\SoundTouch.vcxproj">
<Project>{e9b51944-7e6d-4bcd-83f2-7bbd5a46182d}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)3rdparty\xz\liblzma.vcxproj">
<Project>{12728250-16ec-4dc6-94d7-e21dd88947f8}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)3rdparty\libchdr\libchdr.vcxproj">
<Project>{a0d2b3ad-1f72-4ee3-8b5c-f2c358da35f0}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)3rdparty\zlib\zlib.vcxproj">
<Project>{2f6c0388-20cb-4242-9f6c-a6ebb6a83f47}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)3rdparty\jpgd\jpgd.vcxproj">
<Project>{ed2f21fd-0a36-4a8f-9b90-e7d92a2acb63}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)3rdparty\imgui\imgui.vcxproj">
<Project>{88fb34ec-845e-4f21-a552-f1573b9ed167}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)common\common.vcxproj">
<Project>{4639972e-424e-4e13-8b07-ca403c481346}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)pcsx2\pcsx2.vcxproj">
<Project>{6c7986c4-3e4d-4dcc-b3c6-6bb12b238995}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)3rdparty\glad\glad.vcxproj">
<Project>{c0293b32-5acf-40f0-aa6c-e6da6f3bf33a}</Project>
</ProjectReference>
<ProjectReference Include="..\3rdparty\lzma\lzma.vcxproj">
<Project>{a4323327-3f2b-4271-83d9-7f9a3c66b6b2}</Project>
</ProjectReference>
<ProjectReference Include="..\3rdparty\zydis\zydis.vcxproj">
<Project>{67d0160c-0fe4-44b9-ac2e-82bbcf4104df}</Project>
</ProjectReference>
<ProjectReference Include="..\3rdparty\demangler\demangler.vcxproj">
<Project>{1e3d706c-1d95-4e1b-bdf2-ca3d0007df7f}</Project>
</ProjectReference>

View File

@ -17,7 +17,6 @@
#ifdef ENABLE_ACHIEVEMENTS
#include "CommonHost.h"
#include "Achievements.h"
#include "CDVD/IsoFS/IsoFS.h"
#include "CDVD/IsoFS/IsoFSCDVD.h"
@ -397,10 +396,8 @@ void Achievements::ClearGameInfo(bool clear_achievements, bool clear_leaderboard
s_has_rich_presence = false;
s_game_id = 0;
#ifdef ENABLE_DISCORD_PRESENCE
if (EmuConfig.EnableDiscordPresence)
CommonHost::UpdateDiscordPresence(s_rich_presence_string);
#endif
VMManager::UpdateDiscordPresence(s_rich_presence_string);
}
if (had_game)
@ -879,6 +876,17 @@ const std::string& Achievements::GetRichPresenceString()
return s_rich_presence_string;
}
std::string Achievements::SafeGetRichPresenceString()
{
std::string rich_presence_string;
if (IsActive() && EmuConfig.Achievements.RichPresence)
{
std::unique_lock lock(s_achievements_mutex);
rich_presence_string = s_rich_presence_string;
}
return rich_presence_string;
}
void Achievements::EnsureCacheDirectoriesExist()
{
s_game_icon_cache_directory = Path::Combine(EmuFolders::Cache, "achievement_gameicon");
@ -1550,10 +1558,8 @@ void Achievements::UpdateRichPresence()
Host::OnAchievementsRefreshed();
#ifdef ENABLE_DISCORD_PRESENCE
if (EmuConfig.EnableDiscordPresence)
CommonHost::UpdateDiscordPresence(s_rich_presence_string);
#endif
VMManager::UpdateDiscordPresence(s_rich_presence_string);
}
void Achievements::SendPingCallback(s32 status_code, const std::string& content_type, Common::HTTPDownloader::Request::Data data)

View File

@ -125,6 +125,7 @@ namespace Achievements
const std::string& GetUsername();
const std::string& GetRichPresenceString();
std::string SafeGetRichPresenceString();
bool LoginAsync(const char* username, const char* password);
bool Login(const char* username, const char* password);
@ -185,6 +186,18 @@ namespace Achievements
// Make noops when compiling without cheevos.
namespace Achievements
{
static inline void Initialize()
{
}
static inline void UpdateSettings(const Pcsx2Config::AchievementsOptions& old_config)
{
}
static inline void Shutdown()
{
}
static inline bool OnReset()
{
return true;
@ -219,6 +232,18 @@ namespace Achievements
return true;
}
static inline void OnPaused(bool paused)
{
}
static inline void VSyncUpdate()
{
}
static std::string SafeGetRichPresenceString()
{
return {};
}
} // namespace Achievements
#endif

View File

@ -83,7 +83,6 @@ set(pcsx2Sources
Cache.cpp
COP0.cpp
COP2.cpp
CommonHost.cpp
Counters.cpp
Dmac.cpp
GameDatabase.cpp
@ -173,7 +172,6 @@ set(pcsx2Headers
AsyncFileReader.h
Cache.h
Common.h
CommonHost.h
Config.h
COP0.h
Counters.h

View File

@ -1,567 +0,0 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2023 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 "CommonHost.h"
#include "Achievements.h"
#include "GS.h"
#include "GS/Renderers/HW/GSTextureReplacements.h"
#include "GameList.h"
#include "Host.h"
#include "IconsFontAwesome5.h"
#include "ImGui/FullscreenUI.h"
#include "Input/InputManager.h"
#include "LayeredSettingsInterface.h"
#include "LogSink.h"
#include "MemoryCardFile.h"
#include "PAD/Host/PAD.h"
#include "PerformanceMetrics.h"
#include "Sio.h"
#include "VMManager.h"
#include "PINE.h"
#include "common/Assertions.h"
#include "common/CrashHandler.h"
#include "common/FileSystem.h"
#include "common/Path.h"
#include "common/Timer.h"
#include "common/Threading.h"
#ifdef ENABLE_DISCORD_PRESENCE
#include "discord_rpc.h"
#endif
#ifdef _WIN32
#include "common/RedtapeWindows.h"
#include <KnownFolders.h>
#include <ShlObj.h>
#endif
static constexpr u32 SETTINGS_VERSION = 1;
namespace CommonHost
{
static void SetAppRoot();
static void SetResourcesDirectory();
static bool ShouldUsePortableMode();
static void SetDataDirectory();
static void SetCommonDefaultSettings(SettingsInterface& si);
static void UpdateInhibitScreensaver(bool allow);
static void UpdateSessionTime(const std::string& new_serial);
#ifdef ENABLE_DISCORD_PRESENCE
static void InitializeDiscordPresence();
static void ShutdownDiscordPresence();
static void PollDiscordPresence();
static std::string GetRichPresenceString();
#endif
} // namespace CommonHost
// Used to track play time. We use a monotonic timer here, in case of clock changes.
static u64 s_session_start_time = 0;
static std::string s_session_serial;
static bool s_screensaver_inhibited = false;
static PINEServer s_pine_server;
#ifdef ENABLE_DISCORD_PRESENCE
static bool s_discord_presence_active = false;
#endif
bool CommonHost::InitializeCriticalFolders()
{
SetAppRoot();
SetResourcesDirectory();
SetDataDirectory();
// logging of directories in case something goes wrong super early
Console.WriteLn("AppRoot Directory: %s", EmuFolders::AppRoot.c_str());
Console.WriteLn("DataRoot Directory: %s", EmuFolders::DataRoot.c_str());
Console.WriteLn("Resources Directory: %s", EmuFolders::Resources.c_str());
// allow SetDataDirectory() to change settings directory (if we want to split config later on)
if (EmuFolders::Settings.empty())
{
EmuFolders::Settings = Path::Combine(EmuFolders::DataRoot, "inis");
// Create settings directory if it doesn't exist. If we're not using portable mode, it won't.
if (!FileSystem::DirectoryExists(EmuFolders::Settings.c_str()))
FileSystem::CreateDirectoryPath(EmuFolders::Settings.c_str(), false);
}
// Write crash dumps to the data directory, since that'll be accessible for certain.
CrashHandler::SetWriteDirectory(EmuFolders::DataRoot);
// the resources directory should exist, bail out if not
if (!FileSystem::DirectoryExists(EmuFolders::Resources.c_str()))
{
Console.Error("Resources directory is missing.");
return false;
}
return true;
}
void CommonHost::SetAppRoot()
{
std::string program_path(FileSystem::GetProgramPath());
Console.WriteLn("Program Path: %s", program_path.c_str());
EmuFolders::AppRoot = Path::Canonicalize(Path::GetDirectory(program_path));
}
void CommonHost::SetResourcesDirectory()
{
#ifndef __APPLE__
// On Windows/Linux, these are in the binary directory.
EmuFolders::Resources = Path::Combine(EmuFolders::AppRoot, "resources");
#else
// On macOS, this is in the bundle resources directory.
EmuFolders::Resources = Path::Canonicalize(Path::Combine(EmuFolders::AppRoot, "../Resources"));
#endif
}
bool CommonHost::ShouldUsePortableMode()
{
// Check whether portable.ini exists in the program directory.
return FileSystem::FileExists(Path::Combine(EmuFolders::AppRoot, "portable.ini").c_str());
}
void CommonHost::SetDataDirectory()
{
if (ShouldUsePortableMode())
{
EmuFolders::DataRoot = EmuFolders::AppRoot;
return;
}
#if defined(_WIN32)
// On Windows, use My Documents\PCSX2 to match old installs.
PWSTR documents_directory;
if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_Documents, 0, NULL, &documents_directory)))
{
if (std::wcslen(documents_directory) > 0)
EmuFolders::DataRoot = Path::Combine(StringUtil::WideStringToUTF8String(documents_directory), "PCSX2");
CoTaskMemFree(documents_directory);
}
#elif defined(__linux__) || defined(__FreeBSD__)
// Use $XDG_CONFIG_HOME/PCSX2 if it exists.
const char* xdg_config_home = getenv("XDG_CONFIG_HOME");
if (xdg_config_home && Path::IsAbsolute(xdg_config_home))
{
EmuFolders::DataRoot = Path::Combine(xdg_config_home, "PCSX2");
}
else
{
// Use ~/PCSX2 for non-XDG, and ~/.config/PCSX2 for XDG.
// Maybe we should drop the former when Qt goes live.
const char* home_dir = getenv("HOME");
if (home_dir)
{
#ifdef USE_LEGACY_USER_DIRECTORY
EmuFolders::DataRoot = Path::Combine(home_dir, "PCSX2");
#else
// ~/.config should exist, but just in case it doesn't and this is a fresh profile..
const std::string config_dir(Path::Combine(home_dir, ".config"));
if (!FileSystem::DirectoryExists(config_dir.c_str()))
FileSystem::CreateDirectoryPath(config_dir.c_str(), false);
EmuFolders::DataRoot = Path::Combine(config_dir, "PCSX2");
#endif
}
}
#elif defined(__APPLE__)
static constexpr char MAC_DATA_DIR[] = "Library/Application Support/PCSX2";
const char* home_dir = getenv("HOME");
if (home_dir)
EmuFolders::DataRoot = Path::Combine(home_dir, MAC_DATA_DIR);
#endif
// make sure it exists
if (!EmuFolders::DataRoot.empty() && !FileSystem::DirectoryExists(EmuFolders::DataRoot.c_str()))
{
// we're in trouble if we fail to create this directory... but try to hobble on with portable
if (!FileSystem::CreateDirectoryPath(EmuFolders::DataRoot.c_str(), false))
EmuFolders::DataRoot.clear();
}
// couldn't determine the data directory? fallback to portable.
if (EmuFolders::DataRoot.empty())
EmuFolders::DataRoot = EmuFolders::AppRoot;
}
bool CommonHost::CheckSettingsVersion()
{
SettingsInterface* bsi = Host::Internal::GetBaseSettingsLayer();
uint settings_version;
return (bsi->GetUIntValue("UI", "SettingsVersion", &settings_version) && settings_version == SETTINGS_VERSION);
}
void CommonHost::LoadStartupSettings()
{
SettingsInterface* bsi = Host::Internal::GetBaseSettingsLayer();
EmuFolders::LoadConfig(*bsi);
EmuFolders::EnsureFoldersExist();
UpdateLogging(*bsi);
#ifdef ENABLE_RAINTEGRATION
// RAIntegration switch must happen before the UI is created.
if (Host::GetBaseBoolSettingValue("Achievements", "UseRAIntegration", false))
Achievements::SwitchToRAIntegration();
#endif
}
void CommonHost::SetDefaultSettings(SettingsInterface& si, bool folders, bool core, bool controllers, bool hotkeys, bool ui)
{
if (si.GetUIntValue("UI", "SettingsVersion", 0u) != SETTINGS_VERSION)
si.SetUIntValue("UI", "SettingsVersion", SETTINGS_VERSION);
if (folders)
EmuFolders::SetDefaults(si);
if (core)
{
VMManager::SetDefaultSettings(si);
SetCommonDefaultSettings(si);
}
if (controllers)
PAD::SetDefaultControllerConfig(si);
if (hotkeys)
PAD::SetDefaultHotkeyConfig(si);
if (ui)
Host::SetDefaultUISettings(si);
}
void CommonHost::SetCommonDefaultSettings(SettingsInterface& si)
{
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();
#ifdef ENABLE_ACHIEVEMENTS
if (EmuConfig.Achievements.Enabled)
Achievements::Initialize();
#endif
#ifdef ENABLE_DISCORD_PRESENCE
if (EmuConfig.EnableDiscordPresence)
InitializeDiscordPresence();
#endif
ReloadPINE();
}
void CommonHost::CPUThreadShutdown()
{
#ifdef ENABLE_DISCORD_PRESENCE
ShutdownDiscordPresence();
#endif
#ifdef ENABLE_ACHIEVEMENTS
Achievements::Shutdown();
#endif
s_pine_server.Deinitialize();
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)
{
#ifdef ENABLE_ACHIEVEMENTS
if (EmuConfig.Achievements != old_config.Achievements)
Achievements::UpdateSettings(old_config.Achievements);
#endif
FullscreenUI::CheckForConfigChanges(old_config);
if (EmuConfig.InhibitScreensaver != old_config.InhibitScreensaver)
UpdateInhibitScreensaver(EmuConfig.InhibitScreensaver && VMManager::GetState() == VMState::Running);
#ifdef ENABLE_DISCORD_PRESENCE
if (EmuConfig.EnableDiscordPresence != old_config.EnableDiscordPresence)
{
if (EmuConfig.EnableDiscordPresence)
InitializeDiscordPresence();
else
ShutdownDiscordPresence();
}
#endif
}
void CommonHost::OnVMStarting()
{
CommonHost::Internal::ResetVMHotkeyState();
}
void CommonHost::OnVMStarted()
{
FullscreenUI::OnVMStarted();
UpdateInhibitScreensaver(EmuConfig.InhibitScreensaver);
}
void CommonHost::OnVMDestroyed()
{
FullscreenUI::OnVMDestroyed();
UpdateInhibitScreensaver(false);
}
void CommonHost::OnVMPaused()
{
InputManager::PauseVibration();
#ifdef ENABLE_ACHIEVEMENTS
Achievements::OnPaused(true);
#endif
UpdateInhibitScreensaver(false);
}
void CommonHost::OnVMResumed()
{
#ifdef ENABLE_ACHIEVEMENTS
Achievements::OnPaused(false);
#endif
UpdateInhibitScreensaver(EmuConfig.InhibitScreensaver);
}
void CommonHost::OnGameChanged(const std::string& disc_path, const std::string& elf_override, const std::string& game_serial,
const std::string& game_name, u32 game_crc)
{
UpdateSessionTime(game_serial);
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);
});
}
#ifdef ENABLE_ACHIEVEMENTS
Achievements::GameChanged(game_crc);
#endif
#ifdef ENABLE_DISCORD_PRESENCE
UpdateDiscordPresence(GetRichPresenceString());
#endif
ReloadPINE();
}
void CommonHost::CPUThreadVSync()
{
#ifdef ENABLE_ACHIEVEMENTS
if (Achievements::IsActive())
Achievements::VSyncUpdate();
#endif
#ifdef ENABLE_DISCORD_PRESENCE
PollDiscordPresence();
#endif
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;
}
void CommonHost::UpdateInhibitScreensaver(bool inhibit)
{
if (s_screensaver_inhibited == inhibit)
return;
WindowInfo wi;
auto top_level_wi = Host::GetTopLevelWindowInfo();
if (top_level_wi.has_value())
wi = top_level_wi.value();
s_screensaver_inhibited = inhibit;
if (!WindowInfo::InhibitScreensaver(wi, inhibit) && inhibit)
Console.Warning("Failed to inhibit screen saver.");
}
void CommonHost::UpdateSessionTime(const std::string& new_serial)
{
if (s_session_serial == new_serial)
return;
const u64 ctime = Common::Timer::GetCurrentValue();
if (!s_session_serial.empty())
{
// round up to seconds
const std::time_t etime = static_cast<std::time_t>(std::round(Common::Timer::ConvertValueToSeconds(ctime - s_session_start_time)));
const std::time_t wtime = std::time(nullptr);
GameList::AddPlayedTimeForSerial(s_session_serial, wtime, etime);
}
s_session_serial = new_serial;
s_session_start_time = ctime;
}
u64 CommonHost::GetSessionPlayedTime()
{
const u64 ctime = Common::Timer::GetCurrentValue();
return static_cast<u64>(std::round(Common::Timer::ConvertValueToSeconds(ctime - s_session_start_time)));
}
#ifdef ENABLE_DISCORD_PRESENCE
void CommonHost::InitializeDiscordPresence()
{
if (s_discord_presence_active)
return;
DiscordEventHandlers handlers = {};
Discord_Initialize("1025789002055430154", &handlers, 0, nullptr);
s_discord_presence_active = true;
UpdateDiscordPresence(GetRichPresenceString());
}
void CommonHost::ShutdownDiscordPresence()
{
if (!s_discord_presence_active)
return;
Discord_ClearPresence();
Discord_RunCallbacks();
Discord_Shutdown();
s_discord_presence_active = false;
}
void CommonHost::UpdateDiscordPresence(const std::string& rich_presence)
{
if (!s_discord_presence_active)
return;
// https://discord.com/developers/docs/rich-presence/how-to#updating-presence-update-presence-payload-fields
DiscordRichPresence rp = {};
rp.largeImageKey = "4k-pcsx2";
rp.largeImageText = "PCSX2 Emulator";
rp.startTimestamp = std::time(nullptr);
std::string details_string;
if (VMManager::HasValidVM())
details_string = VMManager::GetGameName();
else
details_string = "No Game Running";
rp.details = details_string.c_str();
// Trim to 128 bytes as per Discord-RPC requirements
std::string state_string;
if (rich_presence.length() >= 128)
{
// 124 characters + 3 dots + null terminator
state_string = fmt::format("{}...", std::string_view(rich_presence).substr(0, 124));
}
else
{
state_string = rich_presence;
}
rp.state = state_string.c_str();
Discord_UpdatePresence(&rp);
Discord_RunCallbacks();
}
void CommonHost::PollDiscordPresence()
{
if (!s_discord_presence_active)
return;
Discord_RunCallbacks();
}
std::string CommonHost::GetRichPresenceString()
{
std::string rich_presence_string;
#ifdef ENABLE_ACHIEVEMENTS
if (Achievements::IsActive() && EmuConfig.Achievements.RichPresence)
{
auto lock = Achievements::GetLock();
rich_presence_string = Achievements::GetRichPresenceString();
}
#endif
return rich_presence_string;
}
#endif
void CommonHost::ReloadPINE()
{
if (EmuConfig.EnablePINE && (s_pine_server.m_slot != EmuConfig.PINESlot || s_pine_server.m_end))
{
if (!s_pine_server.m_end)
{
s_pine_server.Deinitialize();
}
s_pine_server.Initialize(EmuConfig.PINESlot);
}
else if ((!EmuConfig.EnablePINE && !s_pine_server.m_end))
{
s_pine_server.Deinitialize();
}
}

View File

@ -1,96 +0,0 @@
/* 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/>.
*/
#pragma once
#include "common/Pcsx2Defs.h"
#include <string>
#include <mutex>
#include "Config.h"
class SettingsInterface;
namespace Host
{
/// Sets host-specific default settings.
void SetDefaultUISettings(SettingsInterface& si);
} // namespace Host
namespace CommonHost
{
/// Initializes critical folders (AppRoot, DataRoot, Settings). Call once on startup.
bool InitializeCriticalFolders();
/// Checks settings version. Call once on startup. If it returns false, you should prompt the user to reset.
bool CheckSettingsVersion();
/// Loads early settings. Call once on startup.
void LoadStartupSettings();
/// Sets default settings for the specified categories.
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& elf_override, 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();
/// Returns the time elapsed in the current play session.
u64 GetSessionPlayedTime();
#ifdef ENABLE_DISCORD_PRESENCE
/// Called when the rich presence string, provided by RetroAchievements, changes.
void UpdateDiscordPresence(const std::string& rich_presence);
#endif
/// Reloads PINE IPC Server if needed. Does nothing if it's already running on the correct port.
void ReloadPINE();
namespace Internal
{
/// Resets any state for hotkey-related VMs, called on VM startup.
void ResetVMHotkeyState();
} // namespace Internal
} // namespace CommonHost

View File

@ -1345,6 +1345,9 @@ namespace EmuFolders
extern std::string InputProfiles;
extern std::string Videos;
/// Initializes critical folders (AppRoot, DataRoot, Settings). Call once on startup.
bool InitializeCriticalFolders();
// Assumes that AppRoot and DataRoot have been initialized.
void SetDefaults(SettingsInterface& si);
void LoadConfig(SettingsInterface& si);

View File

@ -816,6 +816,27 @@ bool GameList::RescanPath(const std::string& path)
return true;
}
bool GameList::GetSerialAndCRCForFilename(const char* filename, std::string* serial, u32* crc)
{
if (const GameList::Entry* entry = 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;
}
std::string GameList::GetPlayedTimeFile()
{
return Path::Combine(EmuFolders::Settings, "playtime.dat");

View File

@ -128,6 +128,9 @@ namespace GameList
/// Re-scans a single entry in the game list.
bool RescanPath(const std::string& path);
/// Looks up the serial and CRC for a game in the most efficient manner possible (i.e. cache or scan).
bool GetSerialAndCRCForFilename(const char* filename, std::string* serial, u32* crc);
/// Add played time for the specified serial.
void AddPlayedTimeForSerial(const std::string& serial, std::time_t last_time, std::time_t add_time);
void ClearPlayedTimeForSerial(const std::string& serial);

View File

@ -248,46 +248,3 @@ void Host::Internal::SetInputSettingsLayer(SettingsInterface* sif)
std::unique_lock lock(s_settings_mutex);
s_layered_settings_interface.SetLayer(LayeredSettingsInterface::LAYER_INPUT, sif);
}
void Host::Internal::UpdateEmuFolders()
{
const std::string old_cheats_directory(EmuFolders::Cheats);
const std::string old_cheats_ws_directory(EmuFolders::CheatsWS);
const std::string old_cheats_ni_directory(EmuFolders::CheatsNI);
const std::string old_memcards_directory(EmuFolders::MemoryCards);
const std::string old_textures_directory(EmuFolders::Textures);
const std::string old_videos_directory(EmuFolders::Videos);
EmuFolders::LoadConfig(*GetBaseSettingsLayer());
EmuFolders::EnsureFoldersExist();
if (VMManager::HasValidVM())
{
if (EmuFolders::Cheats != old_cheats_directory || EmuFolders::CheatsWS != old_cheats_ws_directory ||
EmuFolders::CheatsNI != old_cheats_ni_directory)
{
VMManager::ReloadPatches(true, true);
}
if (EmuFolders::MemoryCards != old_memcards_directory)
{
FileMcd_EmuClose();
FileMcd_EmuOpen();
AutoEject::SetAll();
}
if (EmuFolders::Textures != old_textures_directory)
{
GetMTGS().RunOnGSThread([]() {
if (VMManager::HasValidVM())
GSTextureReplacements::ReloadReplacementMap();
});
}
if (EmuFolders::Videos != old_videos_directory)
{
if (VMManager::HasValidVM())
GetMTGS().RunOnGSThread(&GSEndCapture);
}
}
}

View File

@ -132,6 +132,9 @@ namespace Host
/// If an input profile is being used, this will be the input layer, otherwise the layered interface.
SettingsInterface* GetSettingsInterfaceForBindings();
/// Sets host-specific default settings.
void SetDefaultUISettings(SettingsInterface& si);
namespace Internal
{
/// Retrieves the base settings layer. Must call with lock held.
@ -151,8 +154,5 @@ namespace Host
/// Sets the input profile settings layer. Called by VMManager when the game changes.
void SetInputSettingsLayer(SettingsInterface* sif);
/// Updates the variables in the EmuFolders namespace, reloading subsystems if needed. Must call with the lock held.
void UpdateEmuFolders();
} // namespace Internal
} // namespace Host

View File

@ -15,7 +15,6 @@
#include "PrecompiledHeader.h"
#include "CommonHost.h"
#include "Achievements.h"
#include "GS.h"
#include "Host.h"
@ -33,7 +32,7 @@
static s32 s_current_save_slot = 1;
static std::optional<LimiterModeType> s_limiter_mode_prior_to_hold_interaction;
void CommonHost::Internal::ResetVMHotkeyState()
void VMManager::Internal::ResetVMHotkeyState()
{
s_current_save_slot = 1;
s_limiter_mode_prior_to_hold_interaction.reset();

View File

@ -18,7 +18,6 @@
#define IMGUI_DEFINE_MATH_OPERATORS
#include "CDVD/CDVDcommon.h"
#include "CommonHost.h"
#include "GS/Renderers/Common/GSDevice.h"
#include "GS/Renderers/Common/GSTexture.h"
#include "Achievements.h"
@ -652,7 +651,7 @@ void FullscreenUI::OnVMDestroyed()
});
}
void FullscreenUI::OnRunningGameChanged(std::string path, std::string serial, std::string title, u32 crc)
void FullscreenUI::GameChanged(std::string path, std::string serial, std::string title, u32 crc)
{
if (!IsInitialized())
return;
@ -2180,7 +2179,7 @@ void FullscreenUI::DrawFolderSetting(SettingsInterface* bsi, const char* title,
bsi->SetStringValue(section.c_str(), key.c_str(), relative_path.c_str());
SetSettingsChanged(bsi);
Host::RunOnCPUThread(&Host::Internal::UpdateEmuFolders);
Host::RunOnCPUThread(&VMManager::Internal::UpdateEmuFolders);
s_cover_image_map.clear();
CloseFileSelector();
@ -2209,7 +2208,7 @@ void FullscreenUI::DrawPathSetting(SettingsInterface* bsi, const char* title, co
bsi->SetStringValue(section.c_str(), key.c_str(), relative_path.c_str());
SetSettingsChanged(bsi);
Host::RunOnCPUThread(&Host::Internal::UpdateEmuFolders);
Host::RunOnCPUThread(&VMManager::Internal::UpdateEmuFolders);
s_cover_image_map.clear();
CloseFileSelector();
@ -4350,7 +4349,7 @@ void FullscreenUI::DrawPauseMenu(MainWindowType type)
if (!s_current_game_serial.empty())
{
const std::time_t cached_played_time = GameList::GetCachedPlayedTimeForSerial(s_current_game_serial);
const std::time_t session_time = static_cast<std::time_t>(CommonHost::GetSessionPlayedTime());
const std::time_t session_time = static_cast<std::time_t>(VMManager::GetSessionPlayedTime());
const std::string played_time_str(GameList::FormatTimespan(cached_played_time + session_time, true));
const std::string session_time_str(GameList::FormatTimespan(session_time, true));

View File

@ -29,7 +29,7 @@ namespace FullscreenUI
void CheckForConfigChanges(const Pcsx2Config& old_config);
void OnVMStarted();
void OnVMDestroyed();
void OnRunningGameChanged(std::string path, std::string serial, std::string title, u32 crc);
void GameChanged(std::string path, std::string serial, std::string title, u32 crc);
void OpenPauseMenu();
void OpenAchievementsWindow();
void OpenLeaderboardsWindow();

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2021 PCSX2 Dev Team
* Copyright (C) 2002-2023 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-
@ -15,6 +15,10 @@
#pragma once
#include "common/Pcsx2Defs.h"
#include <string>
struct ImFont;
union InputBindingKey;

View File

@ -367,7 +367,7 @@ static void UpdateLoggingSinks(bool system_console, bool file_log)
Console_SetActiveHandler(ConsoleWriter_Null);
}
void CommonHost::SetFileLogPath(std::string path)
void LogSink::SetFileLogPath(std::string path)
{
if (emuLogName == path)
return;
@ -383,17 +383,17 @@ void CommonHost::SetFileLogPath(std::string path)
}
}
void CommonHost::SetBlockSystemConsole(bool block)
void LogSink::SetBlockSystemConsole(bool block)
{
s_block_system_console = block;
}
void CommonHost::InitializeEarlyConsole()
void LogSink::InitializeEarlyConsole()
{
UpdateLoggingSinks(true, false);
}
void CommonHost::UpdateLogging(SettingsInterface& si)
void LogSink::UpdateLogging(SettingsInterface& si)
{
const bool system_console_enabled = !s_block_system_console && si.GetBoolValue("Logging", "EnableSystemConsole", false);
const bool file_logging_enabled = si.GetBoolValue("Logging", "EnableFileLogging", false);
@ -416,7 +416,7 @@ void CommonHost::UpdateLogging(SettingsInterface& si)
UpdateLoggingSinks(system_console_enabled, file_logging_enabled);
}
void CommonHost::SetDefaultLoggingSettings(SettingsInterface& si)
void LogSink::SetDefaultLoggingSettings(SettingsInterface& si)
{
si.SetBoolValue("Logging", "EnableSystemConsole", false);
si.SetBoolValue("Logging", "EnableFileLogging", false);

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2022 PCSX2 Dev Team
* Copyright (C) 2002-2023 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-
@ -17,7 +17,7 @@
class SettingsInterface;
namespace CommonHost
namespace LogSink
{
/// Overrides the filename used for the file log.
void SetFileLogPath(std::string path);

View File

@ -26,6 +26,12 @@
#include "MemoryCardFile.h"
#include "USB/USB.h"
#ifdef _WIN32
#include "common/RedtapeWindows.h"
#include <KnownFolders.h>
#include <ShlObj.h>
#endif
const char* SettingInfo::StringDefaultValue() const
{
return default_value ? default_value : "";
@ -103,6 +109,11 @@ namespace EmuFolders
std::string Textures;
std::string InputProfiles;
std::string Videos;
static void SetAppRoot();
static void SetResourcesDirectory();
static bool ShouldUsePortableMode();
static void SetDataDirectory();
} // namespace EmuFolders
void TraceLogFilters::LoadSave(SettingsWrapper& wrap)
@ -1475,6 +1486,125 @@ void Pcsx2Config::CopyRuntimeConfig(Pcsx2Config& cfg)
}
}
bool EmuFolders::InitializeCriticalFolders()
{
SetAppRoot();
SetResourcesDirectory();
SetDataDirectory();
// logging of directories in case something goes wrong super early
Console.WriteLn("AppRoot Directory: %s", AppRoot.c_str());
Console.WriteLn("DataRoot Directory: %s", DataRoot.c_str());
Console.WriteLn("Resources Directory: %s", Resources.c_str());
// allow SetDataDirectory() to change settings directory (if we want to split config later on)
if (Settings.empty())
{
Settings = Path::Combine(DataRoot, "inis");
// Create settings directory if it doesn't exist. If we're not using portable mode, it won't.
if (!FileSystem::DirectoryExists(Settings.c_str()))
FileSystem::CreateDirectoryPath(Settings.c_str(), false);
}
// the resources directory should exist, bail out if not
if (!FileSystem::DirectoryExists(Resources.c_str()))
{
Console.Error("Resources directory is missing.");
return false;
}
return true;
}
void EmuFolders::SetAppRoot()
{
std::string program_path(FileSystem::GetProgramPath());
Console.WriteLn("Program Path: %s", program_path.c_str());
AppRoot = Path::Canonicalize(Path::GetDirectory(program_path));
}
void EmuFolders::SetResourcesDirectory()
{
#ifndef __APPLE__
// On Windows/Linux, these are in the binary directory.
Resources = Path::Combine(AppRoot, "resources");
#else
// On macOS, this is in the bundle resources directory.
Resources = Path::Canonicalize(Path::Combine(AppRoot, "../Resources"));
#endif
}
bool EmuFolders::ShouldUsePortableMode()
{
// Check whether portable.ini exists in the program directory.
return FileSystem::FileExists(Path::Combine(AppRoot, "portable.ini").c_str());
}
void EmuFolders::SetDataDirectory()
{
if (ShouldUsePortableMode())
{
DataRoot = AppRoot;
return;
}
#if defined(_WIN32)
// On Windows, use My Documents\PCSX2 to match old installs.
PWSTR documents_directory;
if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_Documents, 0, NULL, &documents_directory)))
{
if (std::wcslen(documents_directory) > 0)
DataRoot = Path::Combine(StringUtil::WideStringToUTF8String(documents_directory), "PCSX2");
CoTaskMemFree(documents_directory);
}
#elif defined(__linux__) || defined(__FreeBSD__)
// Use $XDG_CONFIG_HOME/PCSX2 if it exists.
const char* xdg_config_home = getenv("XDG_CONFIG_HOME");
if (xdg_config_home && Path::IsAbsolute(xdg_config_home))
{
DataRoot = Path::Combine(xdg_config_home, "PCSX2");
}
else
{
// Use ~/PCSX2 for non-XDG, and ~/.config/PCSX2 for XDG.
// Maybe we should drop the former when Qt goes live.
const char* home_dir = getenv("HOME");
if (home_dir)
{
#ifdef USE_LEGACY_USER_DIRECTORY
DataRoot = Path::Combine(home_dir, "PCSX2");
#else
// ~/.config should exist, but just in case it doesn't and this is a fresh profile..
const std::string config_dir(Path::Combine(home_dir, ".config"));
if (!FileSystem::DirectoryExists(config_dir.c_str()))
FileSystem::CreateDirectoryPath(config_dir.c_str(), false);
DataRoot = Path::Combine(config_dir, "PCSX2");
#endif
}
}
#elif defined(__APPLE__)
static constexpr char MAC_DATA_DIR[] = "Library/Application Support/PCSX2";
const char* home_dir = getenv("HOME");
if (home_dir)
DataRoot = Path::Combine(home_dir, MAC_DATA_DIR);
#endif
// make sure it exists
if (!DataRoot.empty() && !FileSystem::DirectoryExists(DataRoot.c_str()))
{
// we're in trouble if we fail to create this directory... but try to hobble on with portable
if (!FileSystem::CreateDirectoryPath(DataRoot.c_str(), false))
DataRoot.clear();
}
// couldn't determine the data directory? fallback to portable.
if (DataRoot.empty())
DataRoot = AppRoot;
}
void EmuFolders::SetDefaults(SettingsInterface& si)
{
si.SetStringValue("Folders", "Bios", "bios");

View File

@ -23,15 +23,21 @@
#include "Elfheader.h"
#include "FW.h"
#include "GameDatabase.h"
#include "GameList.h"
#include "GS.h"
#include "GS/Renderers/HW/GSTextureReplacements.h"
#include "GSDumpReplayer.h"
#include "Host.h"
#include "ImGui/FullscreenUI.h"
#include "INISettingsInterface.h"
#include "Input/InputManager.h"
#include "IopBios.h"
#include "LogSink.h"
#include "MTVU.h"
#include "MemoryCardFile.h"
#include "Patch.h"
#include "PerformanceMetrics.h"
#include "PINE.h"
#include "R5900.h"
#include "SPU2/spu2.h"
#include "DEV9/DEV9.h"
@ -71,6 +77,10 @@
#include <timeapi.h>
#endif
#ifdef ENABLE_DISCORD_PRESENCE
#include "discord_rpc.h"
#endif
namespace VMManager
{
static void ApplyGameFixes();
@ -82,6 +92,7 @@ namespace VMManager
static void CheckForPatchConfigChanges(const Pcsx2Config& old_config);
static void CheckForDEV9ConfigChanges(const Pcsx2Config& old_config);
static void CheckForMemoryCardConfigChanges(const Pcsx2Config& old_config);
static void CheckForMiscConfigChanges(const Pcsx2Config& old_config);
static void EnforceAchievementsChallengeModeSettings();
static void LogUnsafeSettingsToConsole(const std::string& messages);
static void WarnAboutUnsafeSettings();
@ -103,12 +114,22 @@ namespace VMManager
std::unique_ptr<SaveStateScreenshotData> screenshot, std::string osd_key,
std::string filename, s32 slot_for_message);
static void UpdateInhibitScreensaver(bool allow);
static void SaveSessionTime();
static void ReloadPINE();
static void SetTimerResolutionIncreased(bool enabled);
static void SetHardwareDependentDefaultSettings(SettingsInterface& si);
static void EnsureCPUInfoInitialized();
static void SetEmuThreadAffinities();
static void InitializeDiscordPresence();
static void ShutdownDiscordPresence();
static void PollDiscordPresence();
} // namespace VMManager
static constexpr u32 SETTINGS_VERSION = 1;
static std::unique_ptr<SysMainMemory> s_vm_memory;
static std::unique_ptr<SysCpuProviderPack> s_cpu_provider_pack;
static std::unique_ptr<INISettingsInterface> s_game_settings_interface;
@ -140,6 +161,17 @@ static u32 s_frame_advance_count = 0;
static u32 s_mxcsr_saved;
static bool s_gs_open_on_initialize = false;
// Used to track play time. We use a monotonic timer here, in case of clock changes.
static u64 s_session_start_time = 0;
static bool s_screensaver_inhibited = false;
static PINEServer s_pine_server;
#ifdef ENABLE_DISCORD_PRESENCE
static bool s_discord_presence_active = false;
#endif
bool VMManager::PerformEarlyHardwareChecks(const char** error)
{
#define COMMON_DOWNLOAD_MESSAGE \
@ -193,6 +225,7 @@ void VMManager::SetState(VMState state)
if (THREAD_VU1)
vu1Thread.WaitVU();
GetMTGS().WaitGS(false);
InputManager::PauseVibration();
}
else
{
@ -200,7 +233,11 @@ void VMManager::SetState(VMState state)
frameLimitReset();
}
SPU2::SetOutputPaused(state == VMState::Paused);
SPU2::SetOutputPaused(paused);
Achievements::OnPaused(paused);
UpdateInhibitScreensaver(!paused && EmuConfig.InhibitScreensaver);
if (state == VMState::Paused)
Host::OnVMPaused();
else
@ -243,8 +280,11 @@ std::string VMManager::GetGameName()
return s_game_name;
}
bool VMManager::Internal::InitializeGlobals()
bool VMManager::Internal::CPUThreadInitialize()
{
Threading::SetNameOfCurrentThread("CPU Thread");
PerformanceMetrics::SetCPUThread(Threading::ThreadHandle::GetForCallingThread());
// On Win32, we have a bunch of things which use COM (e.g. SDL, XAudio2, etc).
// We need to initialize COM first, before anything else does, because otherwise they might
// initialize it in single-threaded/apartment mode, which can't be changed to multithreaded.
@ -263,34 +303,44 @@ bool VMManager::Internal::InitializeGlobals()
x86caps.CalculateMHz();
SysLogMachineCaps();
pxAssert(!s_vm_memory && !s_cpu_provider_pack);
s_vm_memory = std::make_unique<SysMainMemory>();
s_cpu_provider_pack = std::make_unique<SysCpuProviderPack>();
if (!s_vm_memory->Allocate())
{
Host::ReportErrorAsync("Error", "Failed to allocate VM memory.");
return false;
}
GSinit();
USBinit();
// We want settings loaded so we choose the correct renderer for big picture mode.
// This also sorts out input sources.
LoadSettings();
if (EmuConfig.Achievements.Enabled)
Achievements::Initialize();
ReloadPINE();
if (EmuConfig.EnableDiscordPresence)
InitializeDiscordPresence();
return true;
}
void VMManager::Internal::ReleaseGlobals()
void VMManager::Internal::CPUThreadShutdown()
{
USBshutdown();
GSshutdown();
ShutdownDiscordPresence();
#ifdef _WIN32
CoUninitialize();
#endif
}
s_pine_server.Deinitialize();
bool VMManager::Internal::InitializeMemory()
{
pxAssert(!s_vm_memory && !s_cpu_provider_pack);
Achievements::Shutdown();
s_vm_memory = std::make_unique<SysMainMemory>();
s_cpu_provider_pack = std::make_unique<SysCpuProviderPack>();
InputManager::CloseSources();
WaitForSaveStateFlush();
return s_vm_memory->Allocate();
}
void VMManager::Internal::ReleaseMemory()
{
std::vector<u8>().swap(s_widescreen_cheats_data);
s_widescreen_cheats_loaded = false;
std::vector<u8>().swap(s_no_interlacing_cheats_data);
@ -298,6 +348,15 @@ void VMManager::Internal::ReleaseMemory()
s_cpu_provider_pack.reset();
s_vm_memory.reset();
PerformanceMetrics::SetCPUThread(Threading::ThreadHandle());
USBshutdown();
GSshutdown();
#ifdef _WIN32
CoUninitialize();
#endif
}
SysMainMemory& GetVmMemory()
@ -310,6 +369,55 @@ SysCpuProviderPack& GetCpuProviders()
return *s_cpu_provider_pack;
}
bool VMManager::Internal::CheckSettingsVersion()
{
SettingsInterface* bsi = Host::Internal::GetBaseSettingsLayer();
uint settings_version;
return (bsi->GetUIntValue("UI", "SettingsVersion", &settings_version) && settings_version == SETTINGS_VERSION);
}
void VMManager::Internal::LoadStartupSettings()
{
SettingsInterface* bsi = Host::Internal::GetBaseSettingsLayer();
EmuFolders::LoadConfig(*bsi);
EmuFolders::EnsureFoldersExist();
LogSink::UpdateLogging(*bsi);
#ifdef ENABLE_RAINTEGRATION
// RAIntegration switch must happen before the UI is created.
if (Host::GetBaseBoolSettingValue("Achievements", "UseRAIntegration", false))
Achievements::SwitchToRAIntegration();
#endif
}
void VMManager::SetDefaultSettings(SettingsInterface& si, bool folders, bool core, bool controllers, bool hotkeys, bool ui)
{
if (si.GetUIntValue("UI", "SettingsVersion", 0u) != SETTINGS_VERSION)
si.SetUIntValue("UI", "SettingsVersion", SETTINGS_VERSION);
if (folders)
EmuFolders::SetDefaults(si);
if (core)
{
Pcsx2Config temp_config;
SettingsSaveWrapper ssw(si);
temp_config.LoadSave(ssw);
// Settings not part of the Pcsx2Config struct.
si.SetBoolValue("EmuCore", "EnableFastBoot", true);
SetHardwareDependentDefaultSettings(si);
LogSink::SetDefaultLoggingSettings(si);
}
if (controllers)
PAD::SetDefaultControllerConfig(si);
if (hotkeys)
PAD::SetDefaultHotkeyConfig(si);
if (ui)
Host::SetDefaultUISettings(si);
}
void VMManager::LoadSettings()
{
std::unique_lock<std::mutex> lock = Host::GetSettingsLock();
@ -318,6 +426,9 @@ void VMManager::LoadSettings()
EmuConfig.LoadSave(slw);
PAD::LoadConfig(*si);
Host::LoadSettings(*si, lock);
InputManager::ReloadSources(*si, lock);
InputManager::ReloadBindings(*si, *Host::GetSettingsInterfaceForBindings());
LogSink::UpdateLogging(*si);
// Achievements hardcore mode disallows setting some configuration options.
EnforceAchievementsChallengeModeSettings();
@ -399,6 +510,50 @@ std::string VMManager::GetInputProfilePath(const std::string_view& name)
return Path::Combine(EmuFolders::InputProfiles, fmt::format("{}.ini", name));
}
void VMManager::Internal::UpdateEmuFolders()
{
const std::string old_cheats_directory(EmuFolders::Cheats);
const std::string old_cheats_ws_directory(EmuFolders::CheatsWS);
const std::string old_cheats_ni_directory(EmuFolders::CheatsNI);
const std::string old_memcards_directory(EmuFolders::MemoryCards);
const std::string old_textures_directory(EmuFolders::Textures);
const std::string old_videos_directory(EmuFolders::Videos);
auto lock = Host::GetSettingsLock();
EmuFolders::LoadConfig(*Host::Internal::GetBaseSettingsLayer());
EmuFolders::EnsureFoldersExist();
if (VMManager::HasValidVM())
{
if (EmuFolders::Cheats != old_cheats_directory || EmuFolders::CheatsWS != old_cheats_ws_directory ||
EmuFolders::CheatsNI != old_cheats_ni_directory)
{
VMManager::ReloadPatches(true, true);
}
if (EmuFolders::MemoryCards != old_memcards_directory)
{
FileMcd_EmuClose();
FileMcd_EmuOpen();
AutoEject::SetAll();
}
if (EmuFolders::Textures != old_textures_directory)
{
GetMTGS().RunOnGSThread([]() {
if (VMManager::HasValidVM())
GSTextureReplacements::ReloadReplacementMap();
});
}
if (EmuFolders::Videos != old_videos_directory)
{
if (VMManager::HasValidVM())
GetMTGS().RunOnGSThread(&GSEndCapture);
}
}
}
void VMManager::RequestDisplaySize(float scale /*= 0.0f*/)
{
int iwidth, iheight;
@ -696,6 +851,7 @@ void VMManager::UpdateRunningGame(bool resetting, bool game_starting, bool swapp
{
std::unique_lock lock(s_info_mutex);
SaveSessionTime();
s_game_serial = std::move(new_serial);
s_game_crc = new_crc;
s_game_name.clear();
@ -740,16 +896,19 @@ void VMManager::UpdateRunningGame(bool resetting, bool game_starting, bool swapp
// Check this here, for two cases: dynarec on, and when enable cheats is set per-game.
if (s_patches_crc != s_game_crc)
ReloadPatches(game_starting, false);
#ifdef ENABLE_ACHIEVEMENTS
// Per-game ini enabling of hardcore mode. We need to re-enforce the settings if so.
if (game_starting && Achievements::ResetChallengeMode())
ApplySettings();
#endif
}
// Per-game ini enabling of hardcore mode. We need to re-enforce the settings if so.
if (game_starting && Achievements::ResetChallengeMode())
ApplySettings();
GetMTGS().SendGameCRC(new_crc);
FullscreenUI::GameChanged(s_disc_path, s_game_serial, s_game_name, s_game_crc);
Achievements::GameChanged(s_game_crc);
ReloadPINE();
UpdateDiscordPresence(Achievements::GetRichPresenceString());
Host::OnGameChanged(s_disc_path, s_elf_override, s_game_serial, s_game_name, s_game_crc);
MIPSAnalyst::ScanForFunctions(R5900SymbolMap, ElfTextRange.first, ElfTextRange.first + ElfTextRange.second, true);
@ -926,6 +1085,7 @@ bool VMManager::Initialize(VMBootParameters boot_params)
s_state.store(VMState::Initializing, std::memory_order_release);
s_vm_thread_handle = Threading::ThreadHandle::GetForCallingThread();
Host::OnVMStarting();
VMManager::Internal::ResetVMHotkeyState();
ScopedGuard close_state = [] {
if (GSDumpReplayer::IsReplayingDump())
@ -1048,6 +1208,8 @@ bool VMManager::Initialize(VMBootParameters boot_params)
Console.WriteLn("VM subsystems initialized in %.2f ms", init_timer.GetTimeMilliseconds());
s_state.store(VMState::Paused, std::memory_order_release);
Host::OnVMStarted();
FullscreenUI::OnVMStarted();
UpdateInhibitScreensaver(EmuConfig.InhibitScreensaver);
UpdateRunningGame(true, false, false);
@ -1100,12 +1262,16 @@ void VMManager::Shutdown(bool save_resume_state)
ElfTextRange = {};
std::unique_lock lock(s_info_mutex);
SaveSessionTime();
s_disc_path.clear();
s_elf_override.clear();
s_game_crc = 0;
s_patches_crc = 0;
s_game_serial.clear();
s_game_name.clear();
Achievements::GameChanged(s_game_crc);
FullscreenUI::GameChanged(s_disc_path, s_game_serial, s_game_name, 0);
UpdateDiscordPresence(Achievements::GetRichPresenceString());
Host::OnGameChanged(s_disc_path, s_elf_override, s_game_serial, s_game_name, 0);
}
s_active_game_fixes = 0;
@ -1149,6 +1315,8 @@ void VMManager::Shutdown(bool save_resume_state)
DEV9shutdown();
s_state.store(VMState::Shutdown, std::memory_order_release);
FullscreenUI::OnVMDestroyed();
UpdateInhibitScreensaver(false);
Host::OnVMDestroyed();
}
@ -1222,7 +1390,7 @@ std::string VMManager::GetSaveStateFileName(const char* filename, s32 slot)
std::string ret;
std::string serial;
u32 crc;
if (Host::GetSerialAndCRCForFilename(filename, &serial, &crc))
if (GameList::GetSerialAndCRCForFilename(filename, &serial, &crc))
ret = GetSaveStateFileName(serial.c_str(), crc, slot);
return ret;
@ -1637,7 +1805,14 @@ void VMManager::Internal::VSyncOnCPUThread()
}
}
Host::CPUThreadVSync();
if (Achievements::IsActive())
Achievements::VSyncUpdate();
PollDiscordPresence();
InputManager::PollSources();
Host::VSyncOnCPUThread();
if (EmuConfig.EnableRecordingTools)
{
@ -1790,6 +1965,20 @@ void VMManager::CheckForMemoryCardConfigChanges(const Pcsx2Config& old_config)
sioSetGameSerial(sioSerial);
}
void VMManager::CheckForMiscConfigChanges(const Pcsx2Config& old_config)
{
if (EmuConfig.InhibitScreensaver != old_config.InhibitScreensaver)
UpdateInhibitScreensaver(EmuConfig.InhibitScreensaver && VMManager::GetState() == VMState::Running);
if (EmuConfig.EnableDiscordPresence != old_config.EnableDiscordPresence)
{
if (EmuConfig.EnableDiscordPresence)
InitializeDiscordPresence();
else
ShutdownDiscordPresence();
}
}
void VMManager::CheckForConfigChanges(const Pcsx2Config& old_config)
{
if (HasValidVM())
@ -1815,6 +2004,13 @@ void VMManager::CheckForConfigChanges(const Pcsx2Config& old_config)
if (HasValidVM() || GetMTGS().IsOpen())
CheckForGSConfigChanges(old_config);
if (EmuConfig.Achievements != old_config.Achievements)
Achievements::UpdateSettings(old_config.Achievements);
FullscreenUI::CheckForConfigChanges(old_config);
CheckForMiscConfigChanges(old_config);
Host::CheckForSettingsChanges(old_config);
}
@ -1849,20 +2045,6 @@ bool VMManager::ReloadGameSettings()
return true;
}
void VMManager::SetDefaultSettings(SettingsInterface& si)
{
{
Pcsx2Config temp_config;
SettingsSaveWrapper ssw(si);
temp_config.LoadSave(ssw);
}
// Settings not part of the Pcsx2Config struct.
si.SetBoolValue("EmuCore", "EnableFastBoot", true);
SetHardwareDependentDefaultSettings(si);
}
void VMManager::EnforceAchievementsChallengeModeSettings()
{
if (!Achievements::ChallengeModeActive())
@ -2013,6 +2195,41 @@ void VMManager::WarnAboutUnsafeSettings()
}
}
void VMManager::UpdateInhibitScreensaver(bool inhibit)
{
if (s_screensaver_inhibited == inhibit)
return;
WindowInfo wi;
auto top_level_wi = Host::GetTopLevelWindowInfo();
if (top_level_wi.has_value())
wi = top_level_wi.value();
s_screensaver_inhibited = inhibit;
if (!WindowInfo::InhibitScreensaver(wi, inhibit) && inhibit)
Console.Warning("Failed to inhibit screen saver.");
}
void VMManager::SaveSessionTime()
{
const u64 ctime = Common::Timer::GetCurrentValue();
if (!s_game_serial.empty() && s_game_crc != 0)
{
// round up to seconds
const std::time_t etime = static_cast<std::time_t>(std::round(Common::Timer::ConvertValueToSeconds(ctime - s_session_start_time)));
const std::time_t wtime = std::time(nullptr);
GameList::AddPlayedTimeForSerial(s_game_serial, wtime, etime);
}
s_session_start_time = ctime;
}
u64 VMManager::GetSessionPlayedTime()
{
const u64 ctime = Common::Timer::GetCurrentValue();
return static_cast<u64>(std::round(Common::Timer::ConvertValueToSeconds(ctime - s_session_start_time)));
}
#ifdef _WIN32
#include "common/RedtapeWindows.h"
@ -2248,3 +2465,107 @@ const std::vector<u32>& VMManager::GetSortedProcessorList()
EnsureCPUInfoInitialized();
return s_processor_list;
}
void VMManager::ReloadPINE()
{
if (EmuConfig.EnablePINE && (s_pine_server.m_slot != EmuConfig.PINESlot || s_pine_server.m_end))
{
if (!s_pine_server.m_end)
{
s_pine_server.Deinitialize();
}
s_pine_server.Initialize(EmuConfig.PINESlot);
}
else if ((!EmuConfig.EnablePINE && !s_pine_server.m_end))
{
s_pine_server.Deinitialize();
}
}
#ifdef ENABLE_DISCORD_PRESENCE
void VMManager::InitializeDiscordPresence()
{
if (s_discord_presence_active)
return;
DiscordEventHandlers handlers = {};
Discord_Initialize("1025789002055430154", &handlers, 0, nullptr);
s_discord_presence_active = true;
UpdateDiscordPresence(Achievements::GetRichPresenceString());
}
void VMManager::ShutdownDiscordPresence()
{
if (!s_discord_presence_active)
return;
Discord_ClearPresence();
Discord_RunCallbacks();
Discord_Shutdown();
s_discord_presence_active = false;
}
void VMManager::UpdateDiscordPresence(const std::string& rich_presence)
{
if (!s_discord_presence_active)
return;
// https://discord.com/developers/docs/rich-presence/how-to#updating-presence-update-presence-payload-fields
DiscordRichPresence rp = {};
rp.largeImageKey = "4k-pcsx2";
rp.largeImageText = "PCSX2 Emulator";
rp.startTimestamp = std::time(nullptr);
std::string details_string;
if (VMManager::HasValidVM())
details_string = VMManager::GetGameName();
else
details_string = "No Game Running";
rp.details = details_string.c_str();
// Trim to 128 bytes as per Discord-RPC requirements
std::string state_string;
if (rich_presence.length() >= 128)
{
// 124 characters + 3 dots + null terminator
state_string = fmt::format("{}...", std::string_view(rich_presence).substr(0, 124));
}
else
{
state_string = rich_presence;
}
rp.state = state_string.c_str();
Discord_UpdatePresence(&rp);
Discord_RunCallbacks();
}
void VMManager::PollDiscordPresence()
{
if (!s_discord_presence_active)
return;
Discord_RunCallbacks();
}
#else // ENABLE_DISCORD_PRESENCE
void VMManager::InitializeDiscordPresence()
{
}
void VMManager::ShutdownDiscordPresence()
{
}
void VMManager::UpdateDiscordPresence(const std::string& rich_presence)
{
}
void VMManager::PollDiscordPresence()
{
}
#endif // ENABLE_DISCORD_PRESENCE

View File

@ -181,27 +181,39 @@ namespace VMManager
/// If the scale is set to 0, the internal resolution will be used, otherwise it is treated as a multiplier to 1x.
void RequestDisplaySize(float scale = 0.0f);
/// Initializes default configuration in the specified file.
void SetDefaultSettings(SettingsInterface& si);
/// Initializes default configuration in the specified file for the specified categories.
void SetDefaultSettings(SettingsInterface& si, bool folders, bool core, bool controllers, bool hotkeys, bool ui);
/// Returns a list of processors in the system, and their corresponding affinity mask.
/// This list is ordered by most performant to least performant for pinning threads to.
const std::vector<u32>& GetSortedProcessorList();
/// Returns the time elapsed in the current play session.
u64 GetSessionPlayedTime();
/// Called when the rich presence string, provided by RetroAchievements, changes.
void UpdateDiscordPresence(const std::string& rich_presence);
/// Internal callbacks, implemented in the emu core.
namespace Internal
{
/// Performs early global initialization.
bool InitializeGlobals();
/// Checks settings version. Call once on startup. If it returns false, you should prompt the user to reset.
bool CheckSettingsVersion();
/// Releases resources allocated in InitializeGlobals().
void ReleaseGlobals();
/// Loads early settings. Call once on startup.
void LoadStartupSettings();
/// Reserves memory for the virtual machines.
bool InitializeMemory();
/// Initializes common host state, called on the CPU thread.
bool CPUThreadInitialize();
/// Completely releases all memory for the virtual machine.
void ReleaseMemory();
/// Cleans up common host state, called on the CPU thread.
void CPUThreadShutdown();
/// Resets any state for hotkey-related VMs, called on VM startup.
void ResetVMHotkeyState();
/// Updates the variables in the EmuFolders namespace, reloading subsystems if needed.
void UpdateEmuFolders();
const std::string& GetElfOverride();
bool IsExecutionInterrupted();
@ -239,10 +251,6 @@ namespace Host
/// Called when performance metrics are updated, approximately once a second.
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.
void OnSaveStateLoading(const std::string_view& filename);
@ -258,5 +266,5 @@ namespace Host
const std::string& game_name, u32 game_crc);
/// Provided by the host; called once per frame at guest vsync.
void CPUThreadVSync();
void VSyncOnCPUThread();
} // namespace Host

View File

@ -124,7 +124,6 @@
</ClCompile>
<ClCompile Include="CDVD\Windows\DriveUtility.cpp" />
<ClCompile Include="CDVD\Windows\IOCtlSrc.cpp" />
<ClCompile Include="CommonHost.cpp" />
<ClCompile Include="DebugTools\Breakpoints.cpp" />
<ClCompile Include="DebugTools\DebugInterface.cpp" />
<ClCompile Include="DebugTools\DisassemblyManager.cpp" />
@ -484,7 +483,6 @@
<ClInclude Include="CDVD\GzippedFileReader.h" />
<ClInclude Include="CDVD\ThreadedFileReader.h" />
<ClInclude Include="CDVD\zlib_indexed.h" />
<ClInclude Include="CommonHost.h" />
<ClInclude Include="DebugTools\Breakpoints.h" />
<ClInclude Include="DebugTools\DebugInterface.h" />
<ClInclude Include="DebugTools\DisassemblyManager.h" />

View File

@ -1388,9 +1388,6 @@
<ClCompile Include="Achievements.cpp">
<Filter>Tools</Filter>
</ClCompile>
<ClCompile Include="CommonHost.cpp">
<Filter>Misc</Filter>
</ClCompile>
<ClCompile Include="Hotkeys.cpp">
<Filter>Misc</Filter>
</ClCompile>
@ -2342,9 +2339,6 @@
<ClInclude Include="GameList.h">
<Filter>Misc</Filter>
</ClInclude>
<ClInclude Include="CommonHost.h">
<Filter>Misc</Filter>
</ClInclude>
<ClInclude Include="INISettingsInterface.h">
<Filter>Misc</Filter>
</ClInclude>

View File

@ -13,7 +13,6 @@
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "pcsx2/CommonHost.h"
#include "pcsx2/ImGui/ImGuiManager.h"
#include "pcsx2/Input/InputManager.h"
#include "pcsx2/GS.h"
@ -188,7 +187,7 @@ void Host::RequestVMShutdown(bool allow_confirm, bool allow_save_state, bool def
{
}
void Host::CPUThreadVSync()
void Host::VSyncOnCPUThread()
{
}