mirror of https://github.com/PCSX2/pcsx2.git
CommonHost: Purge and move functions to appropriate locations
This commit is contained in:
parent
ad0e469f87
commit
0f05967190
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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; });
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue