diff --git a/Source/Core/Core/AchievementManager.cpp b/Source/Core/Core/AchievementManager.cpp index aa8f0b1321..4baf09d399 100644 --- a/Source/Core/Core/AchievementManager.cpp +++ b/Source/Core/Core/AchievementManager.cpp @@ -460,15 +460,18 @@ void AchievementManager::FilterApprovedIni(std::vector& codes, const std::str for (auto& code : codes) { - if (code.enabled && !CheckApprovedCode(code, game_id, revision)) + if (code.enabled && !IsApprovedCode(code, game_id, revision)) code.enabled = false; } } template -bool AchievementManager::CheckApprovedCode(const T& code, const std::string& game_id, - u16 revision) const +bool AchievementManager::ShouldCodeBeActivated(const T& code, const std::string& game_id, + u16 revision) const { + if (!code.enabled) + return false; + if (!IsHardcoreModeActive()) return true; @@ -478,33 +481,42 @@ bool AchievementManager::CheckApprovedCode(const T& code, const std::string& gam INFO_LOG_FMT(ACHIEVEMENTS, "Verifying code {}", code.name); - bool verified = false; + if (IsApprovedCode(code, game_id, revision)) + return true; - auto hash = Common::SHA1::DigestToString(GetCodeHash(code)); + OSD::AddMessage(fmt::format("Failed to verify code {} for game ID {}.", code.name, game_id), + OSD::Duration::VERY_LONG, OSD::Color::RED); + OSD::AddMessage("Disable hardcore mode to enable this code.", OSD::Duration::VERY_LONG, + OSD::Color::RED); + + return false; +} + +template +bool AchievementManager::IsApprovedCode(const T& code, const std::string& game_id, + u16 revision) const +{ + // Approved codes list failed to hash + if (!m_ini_root->is()) + return false; + + const auto hash = Common::SHA1::DigestToString(GetCodeHash(code)); for (const std::string& filename : ConfigLoaders::GetGameIniFilenames(game_id, revision)) { - auto config = filename.substr(0, filename.length() - 4); + const auto config = filename.substr(0, filename.length() - 4); if (m_ini_root->contains(config)) { - auto ini_config = m_ini_root->get(config); + const auto ini_config = m_ini_root->get(config); if (ini_config.is() && ini_config.contains(code.name)) { - auto ini_code = ini_config.get(code.name); - if (ini_code.template is()) - verified = (ini_code.template get() == hash); + const auto ini_code = ini_config.get(code.name); + if (ini_code.template is() && ini_code.template get() == hash) + return true; } } } - - if (!verified) - { - OSD::AddMessage(fmt::format("Failed to verify code {} for game ID {}.", code.name, game_id), - OSD::Duration::VERY_LONG, OSD::Color::RED); - OSD::AddMessage("Disable hardcore mode to enable this code.", OSD::Duration::VERY_LONG, - OSD::Color::RED); - } - return verified; + return false; } Common::SHA1::Digest AchievementManager::GetCodeHash(const PatchEngine::Patch& patch) const @@ -564,16 +576,27 @@ void AchievementManager::FilterApprovedARCodes(std::vector FilterApprovedIni(codes, game_id, revision); } -bool AchievementManager::CheckApprovedGeckoCode(const Gecko::GeckoCode& code, - const std::string& game_id, u16 revision) const +bool AchievementManager::ShouldGeckoCodeBeActivated(const Gecko::GeckoCode& code, + const std::string& game_id, u16 revision) const { - return CheckApprovedCode(code, game_id, revision); + return ShouldCodeBeActivated(code, game_id, revision); } -bool AchievementManager::CheckApprovedARCode(const ActionReplay::ARCode& code, +bool AchievementManager::ShouldARCodeBeActivated(const ActionReplay::ARCode& code, + const std::string& game_id, u16 revision) const +{ + return ShouldCodeBeActivated(code, game_id, revision); +} + +bool AchievementManager::IsApprovedGeckoCode(const Gecko::GeckoCode& code, const std::string& game_id, u16 revision) const { - return CheckApprovedCode(code, game_id, revision); + return IsApprovedCode(code, game_id, revision); +} +bool AchievementManager::IsApprovedARCode(const ActionReplay::ARCode& code, + const std::string& game_id, u16 revision) const +{ + return IsApprovedCode(code, game_id, revision); } void AchievementManager::SetSpectatorMode() diff --git a/Source/Core/Core/AchievementManager.h b/Source/Core/Core/AchievementManager.h index ad69f03de6..bea1ae5ea6 100644 --- a/Source/Core/Core/AchievementManager.h +++ b/Source/Core/Core/AchievementManager.h @@ -149,10 +149,14 @@ public: u16 revision) const; void FilterApprovedARCodes(std::vector& codes, const std::string& game_id, u16 revision) const; - bool CheckApprovedGeckoCode(const Gecko::GeckoCode& code, const std::string& game_id, - u16 revision) const; - bool CheckApprovedARCode(const ActionReplay::ARCode& code, const std::string& game_id, + bool ShouldGeckoCodeBeActivated(const Gecko::GeckoCode& code, const std::string& game_id, + u16 revision) const; + bool ShouldARCodeBeActivated(const ActionReplay::ARCode& code, const std::string& game_id, + u16 revision) const; + bool IsApprovedGeckoCode(const Gecko::GeckoCode& code, const std::string& game_id, u16 revision) const; + bool IsApprovedARCode(const ActionReplay::ARCode& code, const std::string& game_id, + u16 revision) const; void SetSpectatorMode(); std::string_view GetPlayerDisplayName() const; @@ -223,7 +227,9 @@ private: template void FilterApprovedIni(std::vector& codes, const std::string& game_id, u16 revision) const; template - bool CheckApprovedCode(const T& code, const std::string& game_id, u16 revision) const; + bool ShouldCodeBeActivated(const T& code, const std::string& game_id, u16 revision) const; + template + bool IsApprovedCode(const T& code, const std::string& game_id, u16 revision) const; Common::SHA1::Digest GetCodeHash(const PatchEngine::Patch& patch) const; Common::SHA1::Digest GetCodeHash(const Gecko::GeckoCode& code) const; Common::SHA1::Digest GetCodeHash(const ActionReplay::ARCode& code) const; @@ -338,14 +344,14 @@ public: constexpr bool IsHardcoreModeActive() { return false; } - constexpr bool CheckApprovedGeckoCode(const Gecko::GeckoCode& code, const std::string& game_id, - u16 revision) + constexpr bool ShouldGeckoCodeBeActivated(const Gecko::GeckoCode& code, + const std::string& game_id, u16 revision) { return true; } - constexpr bool CheckApprovedARCode(const ActionReplay::ARCode& code, const std::string& game_id, - u16 revision) + constexpr bool ShouldARCodeBeActivated(const ActionReplay::ARCode& code, + const std::string& game_id, u16 revision) { return true; } diff --git a/Source/Core/Core/ActionReplay.cpp b/Source/Core/Core/ActionReplay.cpp index 8cef176415..007f3c14bc 100644 --- a/Source/Core/Core/ActionReplay.cpp +++ b/Source/Core/Core/ActionReplay.cpp @@ -122,11 +122,11 @@ void ApplyCodes(std::span codes, const std::string& game_id, u16 r std::lock_guard guard(s_lock); s_disable_logging = false; s_active_codes.clear(); - std::copy_if(codes.begin(), codes.end(), std::back_inserter(s_active_codes), - [&game_id, &revision](const ARCode& code) { - return code.enabled && AchievementManager::GetInstance().CheckApprovedARCode( - code, game_id, revision); - }); + + const auto should_be_activated = [&game_id, &revision](const ARCode& code) { + return AchievementManager::GetInstance().ShouldARCodeBeActivated(code, game_id, revision); + }; + std::copy_if(codes.begin(), codes.end(), std::back_inserter(s_active_codes), should_be_activated); s_active_codes.shrink_to_fit(); } diff --git a/Source/Core/Core/GeckoCode.cpp b/Source/Core/Core/GeckoCode.cpp index 62d2dc5481..0a7eeae6fb 100644 --- a/Source/Core/Core/GeckoCode.cpp +++ b/Source/Core/Core/GeckoCode.cpp @@ -59,11 +59,11 @@ void SetActiveCodes(std::span gcodes, const std::string& game_i { s_active_codes.reserve(gcodes.size()); + const auto should_be_activated = [&game_id, &revision](const GeckoCode& code) { + return AchievementManager::GetInstance().ShouldGeckoCodeBeActivated(code, game_id, revision); + }; std::copy_if(gcodes.begin(), gcodes.end(), std::back_inserter(s_active_codes), - [&game_id, &revision](const GeckoCode& code) { - return code.enabled && AchievementManager::GetInstance().CheckApprovedGeckoCode( - code, game_id, revision); - }); + should_be_activated); } s_active_codes.shrink_to_fit(); diff --git a/Source/Core/DolphinQt/Config/ARCodeWidget.cpp b/Source/Core/DolphinQt/Config/ARCodeWidget.cpp index d2aba6ed92..e1a00c68a9 100644 --- a/Source/Core/DolphinQt/Config/ARCodeWidget.cpp +++ b/Source/Core/DolphinQt/Config/ARCodeWidget.cpp @@ -8,14 +8,21 @@ #include #include +#ifdef USE_RETRO_ACHIEVEMENTS +#include +#endif // USE_RETRO_ACHIEVEMENTS #include #include #include +#ifdef USE_RETRO_ACHIEVEMENTS +#include +#endif // USE_RETRO_ACHIEVEMENTS #include #include "Common/FileUtil.h" #include "Common/IniFile.h" +#include "Core/AchievementManager.h" #include "Core/ActionReplay.h" #include "Core/ConfigManager.h" @@ -23,6 +30,9 @@ #include "DolphinQt/Config/CheatWarningWidget.h" #include "DolphinQt/Config/HardcoreWarningWidget.h" #include "DolphinQt/QtUtils/NonDefaultQPushButton.h" +#ifdef USE_RETRO_ACHIEVEMENTS +#include "DolphinQt/Settings.h" +#endif // USE_RETRO_ACHIEVEMENTS ARCodeWidget::ARCodeWidget(std::string game_id, u16 game_revision, bool restart_required) : m_game_id(std::move(game_id)), m_game_revision(game_revision), @@ -90,6 +100,7 @@ void ARCodeWidget::ConnectWidgets() #ifdef USE_RETRO_ACHIEVEMENTS connect(m_hc_warning, &HardcoreWarningWidget::OpenAchievementSettings, this, &ARCodeWidget::OpenAchievementSettings); + connect(&Settings::Instance(), &Settings::EmulationStateChanged, this, &ARCodeWidget::UpdateList); #endif // USE_RETRO_ACHIEVEMENTS connect(m_code_list, &QListWidget::itemChanged, this, &ARCodeWidget::OnItemChanged); @@ -199,6 +210,21 @@ void ARCodeWidget::UpdateList() item->setCheckState(ar.enabled ? Qt::Checked : Qt::Unchecked); item->setData(Qt::UserRole, static_cast(i)); +#ifdef USE_RETRO_ACHIEVEMENTS + const AchievementManager& achievement_manager = AchievementManager::GetInstance(); + + if (achievement_manager.IsHardcoreModeActive()) + { + const QIcon approved_icon = style()->standardIcon(QStyle::SP_DialogYesButton); + const QIcon warning_icon = style()->standardIcon(QStyle::SP_MessageBoxWarning); + + if (achievement_manager.IsApprovedARCode(ar, m_game_id, m_game_revision)) + item->setIcon(approved_icon); + else + item->setIcon(warning_icon); + } +#endif // USE_RETRO_ACHIEVEMENTS + m_code_list->addItem(item); } diff --git a/Source/Core/DolphinQt/Config/GeckoCodeWidget.cpp b/Source/Core/DolphinQt/Config/GeckoCodeWidget.cpp index ddb6d656ff..aad8086853 100644 --- a/Source/Core/DolphinQt/Config/GeckoCodeWidget.cpp +++ b/Source/Core/DolphinQt/Config/GeckoCodeWidget.cpp @@ -10,16 +10,23 @@ #include #include #include +#ifdef USE_RETRO_ACHIEVEMENTS +#include +#endif // USE_RETRO_ACHIEVEMENTS #include #include #include #include +#ifdef USE_RETRO_ACHIEVEMENTS +#include +#endif // USE_RETRO_ACHIEVEMENTS #include #include #include "Common/FileUtil.h" #include "Common/IniFile.h" +#include "Core/AchievementManager.h" #include "Core/ConfigManager.h" #include "Core/GeckoCode.h" #include "Core/GeckoCodeConfig.h" @@ -31,6 +38,9 @@ #include "DolphinQt/QtUtils/NonDefaultQPushButton.h" #include "DolphinQt/QtUtils/QtUtils.h" #include "DolphinQt/QtUtils/WrapInScrollArea.h" +#ifdef USE_RETRO_ACHIEVEMENTS +#include "DolphinQt/Settings.h" +#endif // USE_RETRO_ACHIEVEMENTS GeckoCodeWidget::GeckoCodeWidget(std::string game_id, std::string gametdb_id, u16 game_revision, bool restart_required) @@ -158,6 +168,8 @@ void GeckoCodeWidget::ConnectWidgets() #ifdef USE_RETRO_ACHIEVEMENTS connect(m_hc_warning, &HardcoreWarningWidget::OpenAchievementSettings, this, &GeckoCodeWidget::OpenAchievementSettings); + connect(&Settings::Instance(), &Settings::EmulationStateChanged, this, + &GeckoCodeWidget::UpdateList); #endif // USE_RETRO_ACHIEVEMENTS } @@ -356,6 +368,21 @@ void GeckoCodeWidget::UpdateList() item->setCheckState(code.enabled ? Qt::Checked : Qt::Unchecked); item->setData(Qt::UserRole, static_cast(i)); +#ifdef USE_RETRO_ACHIEVEMENTS + const AchievementManager& achievement_manager = AchievementManager::GetInstance(); + + if (achievement_manager.IsHardcoreModeActive()) + { + const QIcon approved_icon = style()->standardIcon(QStyle::SP_DialogYesButton); + const QIcon warning_icon = style()->standardIcon(QStyle::SP_MessageBoxWarning); + + if (achievement_manager.IsApprovedGeckoCode(code, m_game_id, m_game_revision)) + item->setIcon(approved_icon); + else + item->setIcon(warning_icon); + } +#endif // USE_RETRO_ACHIEVEMENTS + m_code_list->addItem(item); }