From 5a8140c301aff3250976c4d9da3e0cec57343556 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 5 Apr 2024 11:07:57 +0200 Subject: [PATCH 1/3] Initialize RAIntegration support if available. Untested. --- .gitignore | 2 + Common/System/System.h | 4 +- Core/Config.cpp | 1 + Core/Config.h | 1 + Core/Core.vcxproj | 8 +- Core/RetroAchievements.cpp | 129 ++++++++++++++++++-- Core/RetroAchievements.h | 17 +-- Qt/QtMain.cpp | 2 +- SDL/SDLMain.cpp | 2 +- UI/MiscScreens.cpp | 4 +- UI/PauseScreen.cpp | 24 +++- UI/PauseScreen.h | 2 + UI/RetroAchievementScreens.cpp | 3 + UI/UI.vcxproj | 8 +- UWP/PPSSPP_UWPMain.cpp | 2 +- Windows/MainWindowMenu.cpp | 11 +- Windows/PPSSPP.vcxproj | 8 +- Windows/main.cpp | 4 +- android/jni/app-android.cpp | 2 +- ext/rcheevos-build/rcheevos.vcxproj | 9 +- ext/rcheevos-build/rcheevos.vcxproj.filters | 3 + headless/Headless.cpp | 2 +- ios/main.mm | 2 +- libretro/libretro.cpp | 2 +- unittest/UnitTest.cpp | 2 +- 25 files changed, 201 insertions(+), 53 deletions(-) diff --git a/.gitignore b/.gitignore index 71c0425320e0..cc442f2568d0 100644 --- a/.gitignore +++ b/.gitignore @@ -136,6 +136,8 @@ build libretro/obj/local ppsspp_retroachievements.dat +RACache +RAPrefs_PPSSPP.cfg # For CLion cmake-build-*/ diff --git a/Common/System/System.h b/Common/System/System.h index 08129300908e..f0d1575de4e5 100644 --- a/Common/System/System.h +++ b/Common/System/System.h @@ -192,6 +192,8 @@ enum SystemProperty { SYSPROP_USER_DOCUMENTS_DIR, SYSPROP_OK_BUTTON_LEFT, + + SYSPROP_MAIN_WINDOW_HANDLE, }; enum class SystemNotification { @@ -252,7 +254,7 @@ enum class UIMessage { std::string System_GetProperty(SystemProperty prop); std::vector System_GetPropertyStringVec(SystemProperty prop); -int System_GetPropertyInt(SystemProperty prop); +int64_t System_GetPropertyInt(SystemProperty prop); float System_GetPropertyFloat(SystemProperty prop); bool System_GetPropertyBool(SystemProperty prop); diff --git a/Core/Config.cpp b/Core/Config.cpp index b62a5e2dfa30..c063bb154622 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -314,6 +314,7 @@ static bool DefaultSasThread() { static const ConfigSetting achievementSettings[] = { // Core settings ConfigSetting("AchievementsEnable", &g_Config.bAchievementsEnable, true, CfgFlag::DEFAULT), + ConfigSetting("AchievementsEnableRAIntegration", &g_Config.bAchievementsEnableRAIntegration, false, CfgFlag::DEFAULT), ConfigSetting("AchievementsChallengeMode", &g_Config.bAchievementsChallengeMode, true, CfgFlag::PER_GAME | CfgFlag::DEFAULT), ConfigSetting("AchievementsEncoreMode", &g_Config.bAchievementsEncoreMode, false, CfgFlag::PER_GAME | CfgFlag::DEFAULT), ConfigSetting("AchievementsUnofficial", &g_Config.bAchievementsUnofficial, false, CfgFlag::PER_GAME | CfgFlag::DEFAULT), diff --git a/Core/Config.h b/Core/Config.h index c6f6e55a9add..399a5266989a 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -528,6 +528,7 @@ struct Config { bool bAchievementsSoundEffects; bool bAchievementsLogBadMemReads; bool bAchievementsSaveStateInHardcoreMode; + bool bAchievementsEnableRAIntegration; // Positioning of the various notifications int iAchievementsLeaderboardTrackerPos; diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index c9acd32dc19f..7c24591a85e7 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -139,7 +139,7 @@ Level3 ..\ffmpeg\WindowsInclude;..\ext\libchdr\include;..\ffmpeg\Windows\x86\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib - _CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;USE_FFMPEG;WITH_UPNP;WIN32;_ARCH_32=1;_M_IX86=1;_DEBUG;_LIB;_UNICODE;UNICODE;MINIUPNP_STATICLIB;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions) + RC_CLIENT_SUPPORTS_RAINTEGRATION;_CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;USE_FFMPEG;WITH_UPNP;WIN32;_ARCH_32=1;_M_IX86=1;_DEBUG;_LIB;_UNICODE;UNICODE;MINIUPNP_STATICLIB;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions) StreamingSIMDExtensions2 Precise true @@ -166,7 +166,7 @@ Level3 ..\ffmpeg\WindowsInclude;..\ext\libchdr\include;..\ffmpeg\Windows\x86_64\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib;../ext/zstd/lib - _CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;USE_FFMPEG;WITH_UPNP;WIN32;_ARCH_64=1;_M_X64=1;_DEBUG;_LIB;_UNICODE;UNICODE;MINIUPNP_STATICLIB;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions) + RC_CLIENT_SUPPORTS_RAINTEGRATION;_CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;USE_FFMPEG;WITH_UPNP;WIN32;_ARCH_64=1;_M_X64=1;_DEBUG;_LIB;_UNICODE;UNICODE;MINIUPNP_STATICLIB;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions) NotSet Precise false @@ -257,7 +257,7 @@ false StreamingSIMDExtensions2 Precise - USING_WIN_UI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;USE_FFMPEG;WITH_UPNP;WIN32;_ARCH_32=1;_M_IX86=1;_LIB;NDEBUG;_UNICODE;UNICODE;MINIUPNP_STATICLIB;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions) + RC_CLIENT_SUPPORTS_RAINTEGRATION;USING_WIN_UI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;USE_FFMPEG;WITH_UPNP;WIN32;_ARCH_32=1;_M_IX86=1;_LIB;NDEBUG;_UNICODE;UNICODE;MINIUPNP_STATICLIB;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions) Speed MultiThreaded true @@ -294,7 +294,7 @@ Speed false true - USING_WIN_UI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;USE_FFMPEG;WITH_UPNP;WIN32;_ARCH_64=1;_M_X64=1;_LIB;NDEBUG;_UNICODE;UNICODE;MINIUPNP_STATICLIB;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions) + RC_CLIENT_SUPPORTS_RAINTEGRATION;USING_WIN_UI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;USE_FFMPEG;WITH_UPNP;WIN32;_ARCH_64=1;_M_X64=1;_LIB;NDEBUG;_UNICODE;UNICODE;MINIUPNP_STATICLIB;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions) false MultiThreaded true diff --git a/Core/RetroAchievements.cpp b/Core/RetroAchievements.cpp index 8ef5be7b896f..9b743bc99b2a 100644 --- a/Core/RetroAchievements.cpp +++ b/Core/RetroAchievements.cpp @@ -25,6 +25,7 @@ #include "ext/rcheevos/include/rcheevos.h" #include "ext/rcheevos/include/rc_client.h" +#include "ext/rcheevos/include/rc_client_raintegration.h" #include "ext/rcheevos/include/rc_api_user.h" #include "ext/rcheevos/include/rc_api_info.h" #include "ext/rcheevos/include/rc_api_request.h" @@ -38,8 +39,6 @@ #include "Common/Log.h" #include "Common/File/Path.h" #include "Common/File/FileUtil.h" -#include "Core/FileLoaders/LocalFileLoader.h" -#include "Core/FileSystems/BlockDevices.h" #include "Common/Net/HTTPClient.h" #include "Common/System/OSD.h" #include "Common/System/System.h" @@ -55,19 +54,28 @@ #include "Core/MemMap.h" #include "Core/Config.h" #include "Core/CoreParameter.h" -#include "Core/ELF/ParamSFO.h" +#include "Core/Core.h" #include "Core/System.h" +#include "Core/FileLoaders/LocalFileLoader.h" +#include "Core/FileSystems/BlockDevices.h" +#include "Core/ELF/ParamSFO.h" #include "Core/FileSystems/MetaFileSystem.h" #include "Core/FileSystems/ISOFileSystem.h" #include "Core/RetroAchievements.h" +#if RC_CLIENT_SUPPORTS_RAINTEGRATION + +#include "Windows/MainWindow.h" + +#endif + static bool HashISOFile(ISOFileSystem *fs, const std::string filename, md5_context *md5) { int handle = fs->OpenFile(filename, FILEACCESS_READ); if (handle < 0) { return false; } - uint32_t sz = fs->SeekFile(handle, 0, FILEMOVE_END); + uint32_t sz = (uint32_t)fs->SeekFile(handle, 0, FILEMOVE_END); fs->SeekFile(handle, 0, FILEMOVE_BEGIN); if (!sz) { return false; @@ -131,7 +139,7 @@ static Achievements::Statistics g_stats; const std::string g_gameIconCachePrefix = "game:"; const std::string g_iconCachePrefix = "badge:"; -Path s_game_path; +Path g_gamePath; std::string s_game_hash; std::set g_activeChallenges; @@ -461,6 +469,93 @@ static void login_token_callback(int result, const char *error_message, rc_clien g_isLoggingIn = false; } +bool RAIntegrationDirty() { +#ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION + return rc_client_raintegration_has_modifications(g_rcClient); +#else + return false; +#endif +} + +#ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION + +static void raintegration_get_game_name_handler(char *buffer, uint32_t buffer_size, rc_client_t *client) { + snprintf(buffer, buffer_size, "%s", g_gamePath.GetFilename().c_str()); +} + +static void raintegration_write_memory_handler(uint32_t address, uint8_t *buffer, uint32_t num_bytes, rc_client_t *client) { + // convert_retroachievements_address_to_real_address + uint32_t realAddress = address + PSP_MEMORY_OFFSET; + uint8_t *writePtr = Memory::GetPointerWriteRange(address, num_bytes); + if (writePtr) { + memcpy(writePtr, buffer, num_bytes); + } +} + +static void raintegration_event_handler(const rc_client_raintegration_event_t *event, rc_client_t *client) { + switch (event->type) { + case RC_CLIENT_RAINTEGRATION_EVENT_MENUITEM_CHECKED_CHANGED: + // The checked state of one of the menu items has changed and should be reflected in the UI. + // Call the handy helper function if the menu was created by rc_client_raintegration_rebuild_submenu. + rc_client_raintegration_update_menu_item(client, event->menu_item); + break; + case RC_CLIENT_RAINTEGRATION_EVENT_PAUSE: + // The toolkit has hit a breakpoint and wants to pause the emulator. Do so. + Core_EnableStepping(true, "ra_breakpoint"); + break; + case RC_CLIENT_RAINTEGRATION_EVENT_HARDCORE_CHANGED: + // Hardcore mode has been changed (either directly by the user, or disabled through the use of the tools). + // The frontend doesn't necessarily need to know that this value changed, they can still query it whenever + // it's appropriate, but the event lets the frontend do things like enable/disable rewind or cheats. + // handle_hardcore_changed(); + break; + default: + ERROR_LOG(ACHIEVEMENTS, "Unsupported raintegration event %u\n", event->type); + break; + } +} + +static void load_integration_callback(int result, const char *error_message, rc_client_t *client, void *userdata) { + auto ac = GetI18NCategory(I18NCat::ACHIEVEMENTS); + + // If DLL not present, do nothing. User can still play without the toolkit. + switch (result) { + case RC_OK: + { + // If not successful, just report the error and bail. Shouldn't happen. + + // DLL was loaded. + g_OSD.Show(OSDType::MESSAGE_SUCCESS, ac->T("RAIntegration DLL loaded.")); + + // Hook up menu. + HWND hWnd = (HWND)userdata; + rc_client_raintegration_set_event_handler(g_rcClient, &raintegration_event_handler); + rc_client_raintegration_set_write_memory_function(g_rcClient, &raintegration_write_memory_handler); + rc_client_raintegration_set_get_game_name_function(g_rcClient, &raintegration_get_game_name_handler); + rc_client_raintegration_rebuild_submenu(g_rcClient, GetMenu(hWnd)); + break; + } + case RC_MISSING_VALUE: + // This is fine, proceeding to login. + g_OSD.Show(OSDType::MESSAGE_WARNING, ac->T("RAIntegration is enabled, but RAIntegration-x64.dll was not found.")); + break; + case RC_ABORTED: + // This is fine, proceeding to login. + g_OSD.Show(OSDType::MESSAGE_WARNING, ac->T("Wrong version of RAIntegration-x64.dll?")); + break; + default: + g_OSD.Show(OSDType::MESSAGE_ERROR, StringFromFormat("RAIntegration init failed: %s", error_message)); + // Bailing. + return; + } + + // Things are ready to load a game. If the DLL was initialized, calling rc_client_begin_load_game will be redirected + // through the DLL so the toolkit has access to the game data. Similarly, things like rc_create_leaderboard_list will + // be redirected through the DLL to reflect any local changes made by the user. + TryLoginByToken(true); +} +#endif + void Initialize() { if (!g_Config.bAchievementsEnable) { _dbg_assert_(!g_rcClient); @@ -477,7 +572,6 @@ void Initialize() { // Provide a logging function to simplify debugging rc_client_enable_logging(g_rcClient, RC_CLIENT_LOG_LEVEL_VERBOSE, log_message_callback); - if (!System_GetPropertyBool(SYSPROP_SUPPORTS_HTTPS)) { // Disable SSL if not supported by our platform implementation. rc_client_set_host(g_rcClient, "http://retroachievements.org"); @@ -485,6 +579,21 @@ void Initialize() { rc_client_set_event_handler(g_rcClient, event_handler_callback); +#ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION + if (g_Config.bAchievementsEnableRAIntegration) { + wchar_t szFilePath[MAX_PATH]; + GetModuleFileNameW(NULL, szFilePath, MAX_PATH); + for (int64_t i = wcslen(szFilePath) - 1; i > 0; i--) { + if (szFilePath[i] == '\\') { + szFilePath[i] = '\0'; + break; + } + } + HWND hWnd = (HWND)System_GetPropertyInt(SYSPROP_MAIN_WINDOW_HANDLE); + rc_client_begin_load_raintegration(g_rcClient, szFilePath, hWnd, "PPSSPP", "1.0", &load_integration_callback, hWnd); + return; + } +#endif TryLoginByToken(true); } @@ -551,7 +660,7 @@ static void login_password_callback(int result, const char *error_message, rc_cl bool LoginAsync(const char *username, const char *password) { auto di = GetI18NCategory(I18NCat::DIALOG); - if (IsLoggedIn() || std::strlen(username) == 0 || std::strlen(password) == 0 || IsUsingRAIntegration()) + if (IsLoggedIn() || std::strlen(username) == 0 || std::strlen(password) == 0) return false; g_OSD.SetProgressBar("cheevos_async_login", di->T("Logging in..."), 0, 0, 0, 0.0f); @@ -587,6 +696,9 @@ void UpdateSettings() { bool Shutdown() { g_activeChallenges.clear(); +#ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION + rc_client_unload_raintegration(g_rcClient); +#endif rc_client_destroy(g_rcClient); g_rcClient = nullptr; INFO_LOG(ACHIEVEMENTS, "Achievements shut down."); @@ -832,6 +944,7 @@ void SetGame(const Path &path, IdentifiedFileType fileType, FileLoader *fileLoad } // The caller should hold off on executing game code until this turns false, checking with IsBlockingExecution() + g_gamePath = path; g_isIdentifying = true; // TODO: Fish the block device out of the loading process somewhere else. Though, probably easier to just do it here. @@ -861,6 +974,8 @@ void SetGame(const Path &path, IdentifiedFileType fileType, FileLoader *fileLoad void UnloadGame() { if (g_rcClient) { rc_client_unload_game(g_rcClient); + g_gamePath.clear(); + s_game_hash.clear(); } } diff --git a/Core/RetroAchievements.h b/Core/RetroAchievements.h index 324976128b01..2d68258a3b36 100644 --- a/Core/RetroAchievements.h +++ b/Core/RetroAchievements.h @@ -34,20 +34,6 @@ struct Statistics { int badMemoryAccessCount; }; -// RAIntegration only exists for Windows, so no point checking it on other platforms. -#ifdef WITH_RAINTEGRATION - -bool IsUsingRAIntegration(); - -#else - -static inline bool IsUsingRAIntegration() -{ - return false; -} - -#endif - // Returns true if the user is logged in properly, and everything is set up for playing games with achievements. bool IsLoggedIn(); @@ -80,6 +66,9 @@ bool WarnUserIfHardcoreModeActive(bool isSaveStateAction, std::string_view messa // Returns the length of the string. If (size_t)-1, there's no message. size_t GetRichPresenceMessage(char *buffer, size_t bufSize); +// Returns true if the user has unsaved RAIntegration changes. Should prompt the user to be sure they want to exit. +bool RAIntegrationDirty(); + // The new API is so much nicer that we can use it directly instead of wrapping it. So let's expose the client. // Will of course return nullptr if not active. rc_client_t *GetClient(); diff --git a/Qt/QtMain.cpp b/Qt/QtMain.cpp index c20058af25d8..85151fc1b553 100644 --- a/Qt/QtMain.cpp +++ b/Qt/QtMain.cpp @@ -185,7 +185,7 @@ std::vector System_GetPropertyStringVec(SystemProperty prop) { } } -int System_GetPropertyInt(SystemProperty prop) { +int64_t System_GetPropertyInt(SystemProperty prop) { switch (prop) { #if defined(SDL) case SYSPROP_AUDIO_SAMPLE_RATE: diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index cbd90ae51417..9a5044be8a2e 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -492,7 +492,7 @@ std::vector System_GetPropertyStringVec(SystemProperty prop) { } } -int System_GetPropertyInt(SystemProperty prop) { +int64_t System_GetPropertyInt(SystemProperty prop) { switch (prop) { case SYSPROP_AUDIO_SAMPLE_RATE: return g_retFmt.freq; diff --git a/UI/MiscScreens.cpp b/UI/MiscScreens.cpp index a038f5e6f56a..dc5764ecea53 100644 --- a/UI/MiscScreens.cpp +++ b/UI/MiscScreens.cpp @@ -553,7 +553,9 @@ UI::EventReturn PromptScreen::OnNo(UI::EventParams &e) { } void PromptScreen::TriggerFinish(DialogResult result) { - callback_(result == DR_OK || result == DR_YES); + if (callback_) { + callback_(result == DR_OK || result == DR_YES); + } UIDialogScreenWithBackground::TriggerFinish(result); } diff --git a/UI/PauseScreen.cpp b/UI/PauseScreen.cpp index 2b384e44bb18..fbf939f25e78 100644 --- a/UI/PauseScreen.cpp +++ b/UI/PauseScreen.cpp @@ -258,7 +258,7 @@ void GamePauseScreen::update() { UIScreen::update(); if (finishNextFrame_) { - TriggerFinish(DR_CANCEL); + TriggerFinish(finishNextFrameResult_); finishNextFrame_ = false; } @@ -494,10 +494,26 @@ UI::EventReturn GamePauseScreen::OnScreenshotClicked(UI::EventParams &e) { } UI::EventReturn GamePauseScreen::OnExitToMenu(UI::EventParams &e) { - if (g_Config.bPauseMenuExitsEmulator) { - System_ExitApp(); + // If RAIntegration has dirty info, ask for confirmation. + if (Achievements::RAIntegrationDirty()) { + auto ac = GetI18NCategory(I18NCat::ACHIEVEMENTS); + auto di = GetI18NCategory(I18NCat::DIALOG); + screenManager()->push(new PromptScreen(gamePath_, ac->T("You have unsaved RAIntegration changes. Exit?"), di->T("Yes"), di->T("No"), [=](bool result) { + if (result) { + if (g_Config.bPauseMenuExitsEmulator) { + System_ExitApp(); + } else { + finishNextFrameResult_ = DR_OK; // exit game + finishNextFrame_ = true; + } + } + })); } else { - TriggerFinish(DR_OK); + if (g_Config.bPauseMenuExitsEmulator) { + System_ExitApp(); + } else { + TriggerFinish(DR_OK); + } } return UI::EVENT_DONE; } diff --git a/UI/PauseScreen.h b/UI/PauseScreen.h index 64f2c6cf8e8c..3e039338a26a 100644 --- a/UI/PauseScreen.h +++ b/UI/PauseScreen.h @@ -24,6 +24,7 @@ #include "Common/UI/UIScreen.h" #include "Common/UI/ViewGroup.h" #include "UI/MiscScreens.h" +#include "UI/Screen.h" enum class PauseScreenMode { MAIN, @@ -65,6 +66,7 @@ class GamePauseScreen : public UIDialogScreenWithGameBackground { // hack bool finishNextFrame_ = false; + DialogResult finishNextFrameResult_ = DR_CANCEL; PauseScreenMode mode_ = PauseScreenMode::MAIN; UI::Button *playButton_ = nullptr; diff --git a/UI/RetroAchievementScreens.cpp b/UI/RetroAchievementScreens.cpp index 71535bc81ae8..f7efd65fac0c 100644 --- a/UI/RetroAchievementScreens.cpp +++ b/UI/RetroAchievementScreens.cpp @@ -382,6 +382,9 @@ void RetroAchievementsSettingsScreen::CreateDeveloperToolsTab(UI::ViewGroup *vie using namespace UI; viewGroup->Add(new ItemHeader(di->T("Settings"))); +#ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION + viewGroup->Add(new CheckBox(&g_Config.bAchievementsEnableRAIntegration, ac->T("Enable RAIntegration (for achievement development)")))->SetEnabledPtr(&g_Config.bAchievementsEnable); +#endif viewGroup->Add(new CheckBox(&g_Config.bAchievementsEncoreMode, ac->T("Encore Mode")))->SetEnabledPtr(&g_Config.bAchievementsEnable); viewGroup->Add(new CheckBox(&g_Config.bAchievementsUnofficial, ac->T("Unofficial achievements")))->SetEnabledPtr(&g_Config.bAchievementsEnable); viewGroup->Add(new CheckBox(&g_Config.bAchievementsLogBadMemReads, ac->T("Log bad memory accesses")))->SetEnabledPtr(&g_Config.bAchievementsEnable); diff --git a/UI/UI.vcxproj b/UI/UI.vcxproj index aff7187e61a4..74aefd02e64d 100644 --- a/UI/UI.vcxproj +++ b/UI/UI.vcxproj @@ -221,7 +221,7 @@ Level3 - _CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;_ARCH_32=1;WIN32;_DEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions) + RC_CLIENT_SUPPORTS_RAINTEGRATION;_CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;_ARCH_32=1;WIN32;_DEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions) ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86_64\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/zlib;../ext true false @@ -242,7 +242,7 @@ Level3 - _CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;_ARCH_64=1;WIN32;_DEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions) + RC_CLIENT_SUPPORTS_RAINTEGRATION;_CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;_ARCH_64=1;WIN32;_DEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions) ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86_64\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/zlib;../ext true false @@ -312,7 +312,7 @@ MaxSpeed true true - USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;_ARCH_32=1;WIN32;NDEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions) + RC_CLIENT_SUPPORTS_RAINTEGRATION;USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;_ARCH_32=1;WIN32;NDEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions) ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86_64\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/zlib;../ext false Size @@ -339,7 +339,7 @@ MaxSpeed true true - USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;_ARCH_64=1;WIN32;NDEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions) + RC_CLIENT_SUPPORTS_RAINTEGRATION;USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;_ARCH_64=1;WIN32;NDEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions) ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86_64\include;../common;..;../ext/native;../ext/glew;../ext/snappy;../ext/zlib;../ext false true diff --git a/UWP/PPSSPP_UWPMain.cpp b/UWP/PPSSPP_UWPMain.cpp index f90e96ae50b4..17ab3a38ab5d 100644 --- a/UWP/PPSSPP_UWPMain.cpp +++ b/UWP/PPSSPP_UWPMain.cpp @@ -354,7 +354,7 @@ std::vector System_GetPropertyStringVec(SystemProperty prop) { } } -int System_GetPropertyInt(SystemProperty prop) { +int64_t System_GetPropertyInt(SystemProperty prop) { switch (prop) { case SYSPROP_AUDIO_SAMPLE_RATE: return winAudioBackend ? winAudioBackend->GetSampleRate() : -1; diff --git a/Windows/MainWindowMenu.cpp b/Windows/MainWindowMenu.cpp index 22ab1e0e8680..af6a81f5c517 100644 --- a/Windows/MainWindowMenu.cpp +++ b/Windows/MainWindowMenu.cpp @@ -53,6 +53,10 @@ #include "Core/Core.h" #include "Core/RetroAchievements.h" +#ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION +#include "ext/rcheevos/include/rc_client_raintegration.h" +#endif + extern bool g_TakeScreenshot; namespace MainWindow { @@ -946,7 +950,12 @@ namespace MainWindow { break; default: - MessageBox(hWnd, L"Unimplemented", L"Sorry", 0); +#ifdef RC_CLIENT_SUPPORTS_RAINTEGRATION + if (rc_client_raintegration_activate_menu_item(Achievements::GetClient(), LOWORD(wParam))) { + break; + } +#endif + MessageBox(hWnd, L"Unhandled menu item", L"Sorry", 0); break; } } diff --git a/Windows/PPSSPP.vcxproj b/Windows/PPSSPP.vcxproj index 01128f75fbac..c9835d7268df 100644 --- a/Windows/PPSSPP.vcxproj +++ b/Windows/PPSSPP.vcxproj @@ -231,7 +231,7 @@ - _CRTDBG_MAP_ALLOC;USING_WIN_UI;GLEW_STATIC;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_ARCH_32=1;_WINDOWS;_UNICODE;UNICODE;%(PreprocessorDefinitions) + RC_CLIENT_SUPPORTS_RAINTEGRATION;_CRTDBG_MAP_ALLOC;USING_WIN_UI;GLEW_STATIC;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_ARCH_32=1;_WINDOWS;_UNICODE;UNICODE;%(PreprocessorDefinitions) false Sync Use @@ -271,7 +271,7 @@ false - _CRTDBG_MAP_ALLOC;USING_WIN_UI;GLEW_STATIC;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_ARCH_64=1;_WINDOWS;_UNICODE;UNICODE;%(PreprocessorDefinitions) + RC_CLIENT_SUPPORTS_RAINTEGRATION;_CRTDBG_MAP_ALLOC;USING_WIN_UI;GLEW_STATIC;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_ARCH_64=1;_WINDOWS;_UNICODE;UNICODE;%(PreprocessorDefinitions) Sync Use Level3 @@ -378,7 +378,7 @@ AnySuitable true Speed - USING_WIN_UI;GLEW_STATIC;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_ARCH_32=1;_WINDOWS;_UNICODE;UNICODE;%(PreprocessorDefinitions) + RC_CLIENT_SUPPORTS_RAINTEGRATION;USING_WIN_UI;GLEW_STATIC;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_ARCH_32=1;_WINDOWS;_UNICODE;UNICODE;%(PreprocessorDefinitions) true Sync MultiThreaded @@ -428,7 +428,7 @@ true Speed false - USING_WIN_UI;GLEW_STATIC;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_ARCH_64=1;_WINDOWS;_UNICODE;UNICODE;%(PreprocessorDefinitions) + RC_CLIENT_SUPPORTS_RAINTEGRATION;USING_WIN_UI;GLEW_STATIC;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_ARCH_64=1;_WINDOWS;_UNICODE;UNICODE;%(PreprocessorDefinitions) true Sync MultiThreaded diff --git a/Windows/main.cpp b/Windows/main.cpp index 2e0eed488f23..12c259ce70a8 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -307,8 +307,10 @@ static int ScreenRefreshRateHz() { return rate; } -int System_GetPropertyInt(SystemProperty prop) { +int64_t System_GetPropertyInt(SystemProperty prop) { switch (prop) { + case SYSPROP_MAIN_WINDOW_HANDLE: + return (int64_t)MainWindow::GetHWND(); case SYSPROP_AUDIO_SAMPLE_RATE: return winAudioBackend ? winAudioBackend->GetSampleRate() : -1; case SYSPROP_DEVICE_TYPE: diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 6dcb3d79a5f7..c81cf9efeb23 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -441,7 +441,7 @@ std::vector System_GetPropertyStringVec(SystemProperty prop) { } } -int System_GetPropertyInt(SystemProperty prop) { +int64_t System_GetPropertyInt(SystemProperty prop) { switch (prop) { case SYSPROP_SYSTEMVERSION: return androidVersion; diff --git a/ext/rcheevos-build/rcheevos.vcxproj b/ext/rcheevos-build/rcheevos.vcxproj index 79b363f0d17e..cf48da65c50d 100644 --- a/ext/rcheevos-build/rcheevos.vcxproj +++ b/ext/rcheevos-build/rcheevos.vcxproj @@ -55,6 +55,7 @@ + @@ -174,7 +175,7 @@ Level3 - RC_DISABLE_LUA;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + RC_DISABLE_LUA;RC_CLIENT_SUPPORTS_RAINTEGRATION;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) true pch.h ../rcheevos/include @@ -217,7 +218,7 @@ MaxSpeed true true - RC_DISABLE_LUA;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + RC_DISABLE_LUA;RC_CLIENT_SUPPORTS_RAINTEGRATION;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) true pch.h ../rcheevos/include @@ -268,7 +269,7 @@ Level3 true - RC_DISABLE_LUA;_DEBUG;_LIB;%(PreprocessorDefinitions) + RC_DISABLE_LUA;RC_CLIENT_SUPPORTS_RAINTEGRATION;_DEBUG;_LIB;%(PreprocessorDefinitions) true pch.h ../rcheevos/include @@ -314,7 +315,7 @@ MaxSpeed true true - RC_DISABLE_LUA;NDEBUG;_LIB;%(PreprocessorDefinitions) + RC_DISABLE_LUA;RC_CLIENT_SUPPORTS_RAINTEGRATION;NDEBUG;_LIB;%(PreprocessorDefinitions) true pch.h ../rcheevos/include diff --git a/ext/rcheevos-build/rcheevos.vcxproj.filters b/ext/rcheevos-build/rcheevos.vcxproj.filters index ecfebb17c13d..3428444b591a 100644 --- a/ext/rcheevos-build/rcheevos.vcxproj.filters +++ b/ext/rcheevos-build/rcheevos.vcxproj.filters @@ -84,6 +84,9 @@ rhash + + rcheevos + diff --git a/headless/Headless.cpp b/headless/Headless.cpp index 815d1d622ed3..2a802a2cc22e 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -99,7 +99,7 @@ void NativeResized() { } std::string System_GetProperty(SystemProperty prop) { return ""; } std::vector System_GetPropertyStringVec(SystemProperty prop) { return std::vector(); } -int System_GetPropertyInt(SystemProperty prop) { +int64_t System_GetPropertyInt(SystemProperty prop) { if (prop == SYSPROP_SYSTEMVERSION) return 31; return -1; diff --git a/ios/main.mm b/ios/main.mm index f9c0c1143069..2425469e6eef 100644 --- a/ios/main.mm +++ b/ios/main.mm @@ -303,7 +303,7 @@ bool jb_enable_ptrace_hack(void) { } } -int System_GetPropertyInt(SystemProperty prop) { +int64_t System_GetPropertyInt(SystemProperty prop) { switch (prop) { case SYSPROP_AUDIO_SAMPLE_RATE: return 44100; diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index 9ec91fc3cea7..220afbda3a7f 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -1640,7 +1640,7 @@ void retro_cheat_set(unsigned index, bool enabled, const char *code) { } } -int System_GetPropertyInt(SystemProperty prop) +int64_t System_GetPropertyInt(SystemProperty prop) { switch (prop) { diff --git a/unittest/UnitTest.cpp b/unittest/UnitTest.cpp index 8cea9a53290a..c71a19bf4b8c 100644 --- a/unittest/UnitTest.cpp +++ b/unittest/UnitTest.cpp @@ -85,7 +85,7 @@ std::string System_GetProperty(SystemProperty prop) { return ""; } std::vector System_GetPropertyStringVec(SystemProperty prop) { return std::vector(); } -int System_GetPropertyInt(SystemProperty prop) { +int64_t System_GetPropertyInt(SystemProperty prop) { return -1; } float System_GetPropertyFloat(SystemProperty prop) { From 8a1ec96626de713dbbd5cfd34c5829a563f29524 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 5 Apr 2024 18:16:46 +0200 Subject: [PATCH 2/3] Correctly submit the version string --- Core/RetroAchievements.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/RetroAchievements.cpp b/Core/RetroAchievements.cpp index 9b743bc99b2a..506cb2532531 100644 --- a/Core/RetroAchievements.cpp +++ b/Core/RetroAchievements.cpp @@ -590,7 +590,7 @@ void Initialize() { } } HWND hWnd = (HWND)System_GetPropertyInt(SYSPROP_MAIN_WINDOW_HANDLE); - rc_client_begin_load_raintegration(g_rcClient, szFilePath, hWnd, "PPSSPP", "1.0", &load_integration_callback, hWnd); + rc_client_begin_load_raintegration(g_rcClient, szFilePath, hWnd, "PPSSPP", PPSSPP_GIT_VERSION, &load_integration_callback, hWnd); return; } #endif From 6f825e4ff37f24e8e02d8fdada8e7b7b578110e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 5 Apr 2024 18:21:02 +0200 Subject: [PATCH 3/3] Minor comment fix --- Core/RetroAchievements.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Core/RetroAchievements.cpp b/Core/RetroAchievements.cpp index 506cb2532531..1db3cc138f8e 100644 --- a/Core/RetroAchievements.cpp +++ b/Core/RetroAchievements.cpp @@ -522,16 +522,13 @@ static void load_integration_callback(int result, const char *error_message, rc_ switch (result) { case RC_OK: { - // If not successful, just report the error and bail. Shouldn't happen. - - // DLL was loaded. + // DLL was loaded correctly. g_OSD.Show(OSDType::MESSAGE_SUCCESS, ac->T("RAIntegration DLL loaded.")); - // Hook up menu. - HWND hWnd = (HWND)userdata; rc_client_raintegration_set_event_handler(g_rcClient, &raintegration_event_handler); rc_client_raintegration_set_write_memory_function(g_rcClient, &raintegration_write_memory_handler); rc_client_raintegration_set_get_game_name_function(g_rcClient, &raintegration_get_game_name_handler); + HWND hWnd = (HWND)userdata; rc_client_raintegration_rebuild_submenu(g_rcClient, GetMenu(hWnd)); break; }