diff --git a/Source/Core/Core/AchievementManager.cpp b/Source/Core/Core/AchievementManager.cpp index f4119ca0c3..1126411228 100644 --- a/Source/Core/Core/AchievementManager.cpp +++ b/Source/Core/Core/AchievementManager.cpp @@ -28,6 +28,7 @@ #include "Core/Config/FreeLookSettings.h" #include "Core/Config/MainSettings.h" #include "Core/Core.h" +#include "Core/GeckoCode.h" #include "Core/HW/Memmap.h" #include "Core/HW/VideoInterface.h" #include "Core/PatchEngine.h" @@ -461,12 +462,36 @@ Common::SHA1::Digest AchievementManager::GetCodeHash(const PatchEngine::Patch& p return context->Finish(); } +Common::SHA1::Digest AchievementManager::GetCodeHash(const Gecko::GeckoCode& code) const +{ + auto context = Common::SHA1::CreateContext(); + context->Update(Common::BitCastToArray(static_cast(code.codes.size()))); + for (const auto& entry : code.codes) + { + context->Update(Common::BitCastToArray(entry.address)); + context->Update(Common::BitCastToArray(entry.data)); + } + return context->Finish(); +} + void AchievementManager::FilterApprovedPatches(std::vector& patches, const std::string& game_ini_id) const { FilterApprovedIni(patches, game_ini_id); } +void AchievementManager::FilterApprovedGeckoCodes(std::vector& codes, + const std::string& game_ini_id) const +{ + FilterApprovedIni(codes, game_ini_id); +} + +bool AchievementManager::CheckApprovedGeckoCode(const Gecko::GeckoCode& code, + const std::string& game_ini_id) const +{ + return CheckApprovedCode(code, game_ini_id); +} + void AchievementManager::SetSpectatorMode() { rc_client_set_spectator_mode_enabled(m_client, Config::Get(Config::RA_SPECTATOR_ENABLED)); diff --git a/Source/Core/Core/AchievementManager.h b/Source/Core/Core/AchievementManager.h index 77859b17d1..5160d23327 100644 --- a/Source/Core/Core/AchievementManager.h +++ b/Source/Core/Core/AchievementManager.h @@ -45,6 +45,11 @@ namespace PatchEngine struct Patch; } // namespace PatchEngine +namespace Gecko +{ +class GeckoCode; +} // namespace Gecko + class AchievementManager { public: @@ -125,8 +130,13 @@ public: void SetHardcoreMode(); bool IsHardcoreModeActive() const; void SetGameIniId(const std::string& game_ini_id) { m_game_ini_id = game_ini_id; } + void FilterApprovedPatches(std::vector& patches, const std::string& game_ini_id) const; + void FilterApprovedGeckoCodes(std::vector& codes, + const std::string& game_ini_id) const; + bool CheckApprovedGeckoCode(const Gecko::GeckoCode& code, const std::string& game_ini_id) const; + void SetSpectatorMode(); std::string_view GetPlayerDisplayName() const; u32 GetPlayerScore() const; @@ -186,6 +196,7 @@ private: template bool CheckApprovedCode(const T& code, const std::string& game_ini_id) const; Common::SHA1::Digest GetCodeHash(const PatchEngine::Patch& patch) const; + Common::SHA1::Digest GetCodeHash(const Gecko::GeckoCode& code) const; static void LeaderboardEntriesCallback(int result, const char* error_message, rc_client_leaderboard_entry_list_t* list, @@ -271,6 +282,12 @@ public: constexpr bool IsHardcoreModeActive() { return false; } + constexpr bool CheckApprovedGeckoCode(const Gecko::GeckoCode& code, + const std::string& game_ini_id) + { + return true; + }; + constexpr void LoadGame(const std::string&, const DiscIO::Volume*) {} constexpr void SetBackgroundExecutionAllowed(bool allowed) {} diff --git a/Source/Core/Core/GeckoCode.cpp b/Source/Core/Core/GeckoCode.cpp index 92f389545d..0d43c5a507 100644 --- a/Source/Core/Core/GeckoCode.cpp +++ b/Source/Core/Core/GeckoCode.cpp @@ -15,6 +15,7 @@ #include "Common/Config/Config.h" #include "Common/FileUtil.h" +#include "Core/AchievementManager.h" #include "Core/Config/MainSettings.h" #include "Core/Core.h" #include "Core/Host.h" @@ -49,7 +50,7 @@ static std::vector s_active_codes; static std::vector s_synced_codes; static std::mutex s_active_codes_lock; -void SetActiveCodes(std::span gcodes) +void SetActiveCodes(std::span gcodes, const std::string& game_id) { std::lock_guard lk(s_active_codes_lock); @@ -57,8 +58,12 @@ void SetActiveCodes(std::span gcodes) if (Config::AreCheatsEnabled()) { s_active_codes.reserve(gcodes.size()); + std::copy_if(gcodes.begin(), gcodes.end(), std::back_inserter(s_active_codes), - [](const GeckoCode& code) { return code.enabled; }); + [&game_id](const GeckoCode& code) { + return code.enabled && + AchievementManager::GetInstance().CheckApprovedGeckoCode(code, game_id); + }); } s_active_codes.shrink_to_fit(); diff --git a/Source/Core/Core/GeckoCode.h b/Source/Core/Core/GeckoCode.h index 3600d1b9ba..2931ed3641 100644 --- a/Source/Core/Core/GeckoCode.h +++ b/Source/Core/Core/GeckoCode.h @@ -60,7 +60,7 @@ constexpr u32 HLE_TRAMPOLINE_ADDRESS = INSTALLER_END_ADDRESS - 4; // preserve the emulation performance. constexpr u32 MAGIC_GAMEID = 0xD01F1BAD; -void SetActiveCodes(std::span gcodes); +void SetActiveCodes(std::span gcodes, const std::string& game_id); void SetSyncedCodesAsActive(); void UpdateSyncedCodes(std::span gcodes); std::vector SetAndReturnActiveCodes(std::span gcodes); diff --git a/Source/Core/Core/NetPlayServer.cpp b/Source/Core/Core/NetPlayServer.cpp index d4a55cf83e..3578893672 100644 --- a/Source/Core/Core/NetPlayServer.cpp +++ b/Source/Core/Core/NetPlayServer.cpp @@ -2070,13 +2070,18 @@ bool NetPlayServer::SyncCodes() } // Sync Gecko Codes { + std::vector codes = Gecko::LoadCodes(globalIni, localIni); + +#ifdef USE_RETRO_ACHIEVEMENTS + AchievementManager::GetInstance().FilterApprovedGeckoCodes(codes, game_id); +#endif // USE_RETRO_ACHIEVEMENTS + // Create a Gecko Code Vector with just the active codes - std::vector s_active_codes = - Gecko::SetAndReturnActiveCodes(Gecko::LoadCodes(globalIni, localIni)); + std::vector active_codes = Gecko::SetAndReturnActiveCodes(codes); // Determine Codelist Size u16 codelines = 0; - for (const Gecko::GeckoCode& active_code : s_active_codes) + for (const Gecko::GeckoCode& active_code : active_codes) { INFO_LOG_FMT(NETPLAY, "Indexing {}", active_code.name); for (const Gecko::GeckoCode::Code& code : active_code.codes) @@ -2104,7 +2109,7 @@ bool NetPlayServer::SyncCodes() pac << MessageID::SyncCodes; pac << SyncCodeID::GeckoData; // Iterate through the active code vector and send each codeline - for (const Gecko::GeckoCode& active_code : s_active_codes) + for (const Gecko::GeckoCode& active_code : active_codes) { INFO_LOG_FMT(NETPLAY, "Sending {}", active_code.name); for (const Gecko::GeckoCode::Code& code : active_code.codes) diff --git a/Source/Core/Core/PatchEngine.cpp b/Source/Core/Core/PatchEngine.cpp index 9880977710..4dc58a6761 100644 --- a/Source/Core/Core/PatchEngine.cpp +++ b/Source/Core/Core/PatchEngine.cpp @@ -197,7 +197,7 @@ void LoadPatches() } else { - Gecko::SetActiveCodes(Gecko::LoadCodes(globalIni, localIni)); + Gecko::SetActiveCodes(Gecko::LoadCodes(globalIni, localIni), sconfig.GetGameID()); ActionReplay::LoadAndApplyCodes(globalIni, localIni); } } diff --git a/Source/Core/DolphinQt/Config/GeckoCodeWidget.cpp b/Source/Core/DolphinQt/Config/GeckoCodeWidget.cpp index 3d2bd020e4..97a93051f5 100644 --- a/Source/Core/DolphinQt/Config/GeckoCodeWidget.cpp +++ b/Source/Core/DolphinQt/Config/GeckoCodeWidget.cpp @@ -202,7 +202,7 @@ void GeckoCodeWidget::OnItemChanged(QListWidgetItem* item) m_gecko_codes[index].enabled = (item->checkState() == Qt::Checked); if (!m_restart_required) - Gecko::SetActiveCodes(m_gecko_codes); + Gecko::SetActiveCodes(m_gecko_codes, m_game_id); SaveCodes(); }