mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-04-06 11:57:09 +02:00
Fixed Multi Config Code Approvals
Refactors the AR/Gecko/Patch code approval process to verify from every possible game ini, not just the base game ID. This fixes codes on specific revisions or codes general to any region.
This commit is contained in:
parent
fd2766f5df
commit
0615ade725
@ -28,6 +28,7 @@
|
||||
#include "Core/Config/AchievementSettings.h"
|
||||
#include "Core/Config/FreeLookSettings.h"
|
||||
#include "Core/Config/MainSettings.h"
|
||||
#include "Core/ConfigLoaders/GameConfigLoader.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/GeckoCode.h"
|
||||
#include "Core/HW/Memmap.h"
|
||||
@ -386,8 +387,8 @@ bool AchievementManager::IsHardcoreModeActive() const
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void AchievementManager::FilterApprovedIni(std::vector<T>& codes,
|
||||
const std::string& game_ini_id) const
|
||||
void AchievementManager::FilterApprovedIni(std::vector<T>& codes, const std::string& game_id,
|
||||
u16 revision) const
|
||||
{
|
||||
if (codes.empty())
|
||||
{
|
||||
@ -409,13 +410,14 @@ void AchievementManager::FilterApprovedIni(std::vector<T>& codes,
|
||||
|
||||
for (auto& code : codes)
|
||||
{
|
||||
if (code.enabled && !CheckApprovedCode(code, game_ini_id))
|
||||
if (code.enabled && !CheckApprovedCode(code, game_id, revision))
|
||||
code.enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool AchievementManager::CheckApprovedCode(const T& code, const std::string& game_ini_id) const
|
||||
bool AchievementManager::CheckApprovedCode(const T& code, const std::string& game_id,
|
||||
u16 revision) const
|
||||
{
|
||||
if (!IsHardcoreModeActive())
|
||||
return true;
|
||||
@ -424,22 +426,22 @@ bool AchievementManager::CheckApprovedCode(const T& code, const std::string& gam
|
||||
if (!m_ini_root->is<picojson::value::object>())
|
||||
return false;
|
||||
|
||||
const bool known_id = m_ini_root->contains(game_ini_id);
|
||||
|
||||
INFO_LOG_FMT(ACHIEVEMENTS, "Verifying code {}", code.name);
|
||||
|
||||
bool verified = false;
|
||||
|
||||
if (known_id)
|
||||
{
|
||||
auto digest = GetCodeHash(code);
|
||||
auto hash = Common::SHA1::DigestToString(GetCodeHash(code));
|
||||
|
||||
verified = m_ini_root->get(game_ini_id).contains(Common::SHA1::DigestToString(digest));
|
||||
for (const std::string& filename : ConfigLoaders::GetGameIniFilenames(game_id, revision))
|
||||
{
|
||||
auto config = filename.substr(0, filename.length() - 4);
|
||||
if (m_ini_root->contains(config) && m_ini_root->get(config).contains(hash))
|
||||
verified = true;
|
||||
}
|
||||
|
||||
if (!verified)
|
||||
{
|
||||
OSD::AddMessage(fmt::format("Failed to verify code {} from file {}.", code.name, game_ini_id),
|
||||
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);
|
||||
@ -487,33 +489,33 @@ Common::SHA1::Digest AchievementManager::GetCodeHash(const ActionReplay::ARCode&
|
||||
}
|
||||
|
||||
void AchievementManager::FilterApprovedPatches(std::vector<PatchEngine::Patch>& patches,
|
||||
const std::string& game_ini_id) const
|
||||
const std::string& game_id, u16 revision) const
|
||||
{
|
||||
FilterApprovedIni(patches, game_ini_id);
|
||||
FilterApprovedIni(patches, game_id, revision);
|
||||
}
|
||||
|
||||
void AchievementManager::FilterApprovedGeckoCodes(std::vector<Gecko::GeckoCode>& codes,
|
||||
const std::string& game_ini_id) const
|
||||
const std::string& game_id, u16 revision) const
|
||||
{
|
||||
FilterApprovedIni(codes, game_ini_id);
|
||||
FilterApprovedIni(codes, game_id, revision);
|
||||
}
|
||||
|
||||
void AchievementManager::FilterApprovedARCodes(std::vector<ActionReplay::ARCode>& codes,
|
||||
const std::string& game_ini_id) const
|
||||
const std::string& game_id, u16 revision) const
|
||||
{
|
||||
FilterApprovedIni(codes, game_ini_id);
|
||||
FilterApprovedIni(codes, game_id, revision);
|
||||
}
|
||||
|
||||
bool AchievementManager::CheckApprovedGeckoCode(const Gecko::GeckoCode& code,
|
||||
const std::string& game_ini_id) const
|
||||
const std::string& game_id, u16 revision) const
|
||||
{
|
||||
return CheckApprovedCode(code, game_ini_id);
|
||||
return CheckApprovedCode(code, game_id, revision);
|
||||
}
|
||||
|
||||
bool AchievementManager::CheckApprovedARCode(const ActionReplay::ARCode& code,
|
||||
const std::string& game_ini_id) const
|
||||
const std::string& game_id, u16 revision) const
|
||||
{
|
||||
return CheckApprovedCode(code, game_ini_id);
|
||||
return CheckApprovedCode(code, game_id, revision);
|
||||
}
|
||||
|
||||
void AchievementManager::SetSpectatorMode()
|
||||
|
@ -133,16 +133,17 @@ public:
|
||||
|
||||
std::recursive_mutex& GetLock();
|
||||
bool IsHardcoreModeActive() const;
|
||||
void SetGameIniId(const std::string& game_ini_id) { m_game_ini_id = game_ini_id; }
|
||||
|
||||
void FilterApprovedPatches(std::vector<PatchEngine::Patch>& patches,
|
||||
const std::string& game_ini_id) const;
|
||||
void FilterApprovedGeckoCodes(std::vector<Gecko::GeckoCode>& codes,
|
||||
const std::string& game_ini_id) const;
|
||||
void FilterApprovedARCodes(std::vector<ActionReplay::ARCode>& codes,
|
||||
const std::string& game_ini_id) const;
|
||||
bool CheckApprovedGeckoCode(const Gecko::GeckoCode& code, const std::string& game_ini_id) const;
|
||||
bool CheckApprovedARCode(const ActionReplay::ARCode& code, const std::string& game_ini_id) const;
|
||||
void FilterApprovedPatches(std::vector<PatchEngine::Patch>& patches, const std::string& game_id,
|
||||
u16 revision) const;
|
||||
void FilterApprovedGeckoCodes(std::vector<Gecko::GeckoCode>& codes, const std::string& game_id,
|
||||
u16 revision) const;
|
||||
void FilterApprovedARCodes(std::vector<ActionReplay::ARCode>& 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,
|
||||
u16 revision) const;
|
||||
|
||||
void SetSpectatorMode();
|
||||
std::string_view GetPlayerDisplayName() const;
|
||||
@ -201,9 +202,9 @@ private:
|
||||
void SetHardcoreMode();
|
||||
|
||||
template <typename T>
|
||||
void FilterApprovedIni(std::vector<T>& codes, const std::string& game_ini_id) const;
|
||||
void FilterApprovedIni(std::vector<T>& codes, const std::string& game_id, u16 revision) const;
|
||||
template <typename T>
|
||||
bool CheckApprovedCode(const T& code, const std::string& game_ini_id) const;
|
||||
bool CheckApprovedCode(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;
|
||||
@ -259,7 +260,6 @@ private:
|
||||
std::chrono::steady_clock::time_point m_last_progress_message = std::chrono::steady_clock::now();
|
||||
|
||||
Common::Lazy<picojson::value> m_ini_root{LoadApprovedList};
|
||||
std::string m_game_ini_id;
|
||||
|
||||
std::unordered_map<AchievementId, LeaderboardStatus> m_leaderboard_map;
|
||||
bool m_challenges_updated = false;
|
||||
@ -302,14 +302,12 @@ public:
|
||||
|
||||
constexpr bool IsHardcoreModeActive() { return false; }
|
||||
|
||||
constexpr bool CheckApprovedGeckoCode(const Gecko::GeckoCode& code,
|
||||
const std::string& game_ini_id)
|
||||
constexpr bool CheckApprovedGeckoCode(const Gecko::GeckoCode& code, const std::string& game_id)
|
||||
{
|
||||
return true;
|
||||
};
|
||||
|
||||
constexpr bool CheckApprovedARCode(const ActionReplay::ARCode& code,
|
||||
const std::string& game_ini_id)
|
||||
constexpr bool CheckApprovedARCode(const ActionReplay::ARCode& code, const std::string& game_id)
|
||||
{
|
||||
return true;
|
||||
};
|
||||
|
@ -113,7 +113,7 @@ struct ARAddr
|
||||
|
||||
// ----------------------
|
||||
// AR Remote Functions
|
||||
void ApplyCodes(std::span<const ARCode> codes, const std::string& game_id)
|
||||
void ApplyCodes(std::span<const ARCode> codes, const std::string& game_id, u16 revision)
|
||||
{
|
||||
if (!Config::AreCheatsEnabled())
|
||||
return;
|
||||
@ -122,9 +122,9 @@ void ApplyCodes(std::span<const ARCode> codes, const std::string& game_id)
|
||||
s_disable_logging = false;
|
||||
s_active_codes.clear();
|
||||
std::copy_if(codes.begin(), codes.end(), std::back_inserter(s_active_codes),
|
||||
[&game_id](const ARCode& code) {
|
||||
return code.enabled &&
|
||||
AchievementManager::GetInstance().CheckApprovedARCode(code, game_id);
|
||||
[&game_id, &revision](const ARCode& code) {
|
||||
return code.enabled && AchievementManager::GetInstance().CheckApprovedARCode(
|
||||
code, game_id, revision);
|
||||
});
|
||||
s_active_codes.shrink_to_fit();
|
||||
}
|
||||
@ -174,9 +174,9 @@ void AddCode(ARCode code)
|
||||
}
|
||||
|
||||
void LoadAndApplyCodes(const Common::IniFile& global_ini, const Common::IniFile& local_ini,
|
||||
const std::string& game_id)
|
||||
const std::string& game_id, u16 revision)
|
||||
{
|
||||
ApplyCodes(LoadCodes(global_ini, local_ini), game_id);
|
||||
ApplyCodes(LoadCodes(global_ini, local_ini), game_id, revision);
|
||||
}
|
||||
|
||||
// Parses the Action Replay section of a game ini file.
|
||||
|
@ -45,13 +45,13 @@ struct ARCode
|
||||
|
||||
void RunAllActive(const Core::CPUThreadGuard& cpu_guard);
|
||||
|
||||
void ApplyCodes(std::span<const ARCode> codes, const std::string& game_id);
|
||||
void ApplyCodes(std::span<const ARCode> codes, const std::string& game_id, u16 revision);
|
||||
void SetSyncedCodesAsActive();
|
||||
void UpdateSyncedCodes(std::span<const ARCode> codes);
|
||||
std::vector<ARCode> ApplyAndReturnCodes(std::span<const ARCode> codes);
|
||||
void AddCode(ARCode new_code);
|
||||
void LoadAndApplyCodes(const Common::IniFile& global_ini, const Common::IniFile& local_ini,
|
||||
const std::string& game_id);
|
||||
const std::string& game_id, u16 revision);
|
||||
|
||||
std::vector<ARCode> LoadCodes(const Common::IniFile& global_ini, const Common::IniFile& local_ini);
|
||||
void SaveCodes(Common::IniFile* local_ini, std::span<const ARCode> codes);
|
||||
|
@ -50,7 +50,7 @@ static std::vector<GeckoCode> s_active_codes;
|
||||
static std::vector<GeckoCode> s_synced_codes;
|
||||
static std::mutex s_active_codes_lock;
|
||||
|
||||
void SetActiveCodes(std::span<const GeckoCode> gcodes, const std::string& game_id)
|
||||
void SetActiveCodes(std::span<const GeckoCode> gcodes, const std::string& game_id, u16 revision)
|
||||
{
|
||||
std::lock_guard lk(s_active_codes_lock);
|
||||
|
||||
@ -60,9 +60,9 @@ void SetActiveCodes(std::span<const GeckoCode> gcodes, const std::string& game_i
|
||||
s_active_codes.reserve(gcodes.size());
|
||||
|
||||
std::copy_if(gcodes.begin(), gcodes.end(), std::back_inserter(s_active_codes),
|
||||
[&game_id](const GeckoCode& code) {
|
||||
return code.enabled &&
|
||||
AchievementManager::GetInstance().CheckApprovedGeckoCode(code, game_id);
|
||||
[&game_id, &revision](const GeckoCode& code) {
|
||||
return code.enabled && AchievementManager::GetInstance().CheckApprovedGeckoCode(
|
||||
code, game_id, revision);
|
||||
});
|
||||
}
|
||||
s_active_codes.shrink_to_fit();
|
||||
|
@ -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<const GeckoCode> gcodes, const std::string& game_id);
|
||||
void SetActiveCodes(std::span<const GeckoCode> gcodes, const std::string& game_id, u16 revision);
|
||||
void SetSyncedCodesAsActive();
|
||||
void UpdateSyncedCodes(std::span<const GeckoCode> gcodes);
|
||||
std::vector<GeckoCode> SetAndReturnActiveCodes(std::span<const GeckoCode> gcodes);
|
||||
|
@ -2075,7 +2075,7 @@ bool NetPlayServer::SyncCodes()
|
||||
std::vector<Gecko::GeckoCode> codes = Gecko::LoadCodes(globalIni, localIni);
|
||||
|
||||
#ifdef USE_RETRO_ACHIEVEMENTS
|
||||
AchievementManager::GetInstance().FilterApprovedGeckoCodes(codes, game_id);
|
||||
AchievementManager::GetInstance().FilterApprovedGeckoCodes(codes, game_id, revision);
|
||||
#endif // USE_RETRO_ACHIEVEMENTS
|
||||
|
||||
// Create a Gecko Code Vector with just the active codes
|
||||
@ -2129,7 +2129,7 @@ bool NetPlayServer::SyncCodes()
|
||||
{
|
||||
std::vector<ActionReplay::ARCode> codes = ActionReplay::LoadCodes(globalIni, localIni);
|
||||
#ifdef USE_RETRO_ACHIEVEMENTS
|
||||
AchievementManager::GetInstance().FilterApprovedARCodes(codes, game_id);
|
||||
AchievementManager::GetInstance().FilterApprovedARCodes(codes, game_id, revision);
|
||||
#endif // USE_RETRO_ACHIEVEMENTS
|
||||
// Create an AR Code Vector with just the active codes
|
||||
std::vector<ActionReplay::ARCode> active_codes = ActionReplay::ApplyAndReturnCodes(codes);
|
||||
|
@ -183,7 +183,8 @@ void LoadPatches()
|
||||
LoadPatchSection("OnFrame", &s_on_frame, globalIni, localIni);
|
||||
|
||||
#ifdef USE_RETRO_ACHIEVEMENTS
|
||||
AchievementManager::GetInstance().FilterApprovedPatches(s_on_frame, sconfig.GetGameID());
|
||||
AchievementManager::GetInstance().FilterApprovedPatches(s_on_frame, sconfig.GetGameID(),
|
||||
sconfig.GetRevision());
|
||||
#endif // USE_RETRO_ACHIEVEMENTS
|
||||
|
||||
// Check if I'm syncing Codes
|
||||
@ -194,8 +195,10 @@ void LoadPatches()
|
||||
}
|
||||
else
|
||||
{
|
||||
Gecko::SetActiveCodes(Gecko::LoadCodes(globalIni, localIni), sconfig.GetGameID());
|
||||
ActionReplay::LoadAndApplyCodes(globalIni, localIni, sconfig.GetGameID());
|
||||
Gecko::SetActiveCodes(Gecko::LoadCodes(globalIni, localIni), sconfig.GetGameID(),
|
||||
sconfig.GetRevision());
|
||||
ActionReplay::LoadAndApplyCodes(globalIni, localIni, sconfig.GetGameID(),
|
||||
sconfig.GetRevision());
|
||||
}
|
||||
}
|
||||
|
||||
@ -340,7 +343,7 @@ bool ApplyFramePatches(Core::System& system)
|
||||
void Shutdown()
|
||||
{
|
||||
s_on_frame.clear();
|
||||
ActionReplay::ApplyCodes({}, "");
|
||||
ActionReplay::ApplyCodes({}, "", 0);
|
||||
Gecko::Shutdown();
|
||||
}
|
||||
|
||||
|
@ -115,7 +115,7 @@ void ARCodeWidget::OnItemChanged(QListWidgetItem* item)
|
||||
m_ar_codes[m_code_list->row(item)].enabled = (item->checkState() == Qt::Checked);
|
||||
|
||||
if (!m_restart_required)
|
||||
ActionReplay::ApplyCodes(m_ar_codes, m_game_id);
|
||||
ActionReplay::ApplyCodes(m_ar_codes, m_game_id, m_game_revision);
|
||||
|
||||
UpdateList();
|
||||
SaveCodes();
|
||||
|
@ -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, m_game_id);
|
||||
Gecko::SetActiveCodes(m_gecko_codes, m_game_id, m_game_revision);
|
||||
|
||||
SaveCodes();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user