mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-06-28 01:49:33 -06: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:
@ -28,6 +28,7 @@
|
|||||||
#include "Core/Config/AchievementSettings.h"
|
#include "Core/Config/AchievementSettings.h"
|
||||||
#include "Core/Config/FreeLookSettings.h"
|
#include "Core/Config/FreeLookSettings.h"
|
||||||
#include "Core/Config/MainSettings.h"
|
#include "Core/Config/MainSettings.h"
|
||||||
|
#include "Core/ConfigLoaders/GameConfigLoader.h"
|
||||||
#include "Core/Core.h"
|
#include "Core/Core.h"
|
||||||
#include "Core/GeckoCode.h"
|
#include "Core/GeckoCode.h"
|
||||||
#include "Core/HW/Memmap.h"
|
#include "Core/HW/Memmap.h"
|
||||||
@ -386,8 +387,8 @@ bool AchievementManager::IsHardcoreModeActive() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void AchievementManager::FilterApprovedIni(std::vector<T>& codes,
|
void AchievementManager::FilterApprovedIni(std::vector<T>& codes, const std::string& game_id,
|
||||||
const std::string& game_ini_id) const
|
u16 revision) const
|
||||||
{
|
{
|
||||||
if (codes.empty())
|
if (codes.empty())
|
||||||
{
|
{
|
||||||
@ -409,13 +410,14 @@ void AchievementManager::FilterApprovedIni(std::vector<T>& codes,
|
|||||||
|
|
||||||
for (auto& code : codes)
|
for (auto& code : codes)
|
||||||
{
|
{
|
||||||
if (code.enabled && !CheckApprovedCode(code, game_ini_id))
|
if (code.enabled && !CheckApprovedCode(code, game_id, revision))
|
||||||
code.enabled = false;
|
code.enabled = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
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())
|
if (!IsHardcoreModeActive())
|
||||||
return true;
|
return true;
|
||||||
@ -424,22 +426,22 @@ bool AchievementManager::CheckApprovedCode(const T& code, const std::string& gam
|
|||||||
if (!m_ini_root->is<picojson::value::object>())
|
if (!m_ini_root->is<picojson::value::object>())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const bool known_id = m_ini_root->contains(game_ini_id);
|
|
||||||
|
|
||||||
INFO_LOG_FMT(ACHIEVEMENTS, "Verifying code {}", code.name);
|
INFO_LOG_FMT(ACHIEVEMENTS, "Verifying code {}", code.name);
|
||||||
|
|
||||||
bool verified = false;
|
bool verified = false;
|
||||||
|
|
||||||
if (known_id)
|
auto hash = Common::SHA1::DigestToString(GetCodeHash(code));
|
||||||
{
|
|
||||||
auto digest = 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)
|
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::Duration::VERY_LONG, OSD::Color::RED);
|
||||||
OSD::AddMessage("Disable hardcore mode to enable this code.", OSD::Duration::VERY_LONG,
|
OSD::AddMessage("Disable hardcore mode to enable this code.", OSD::Duration::VERY_LONG,
|
||||||
OSD::Color::RED);
|
OSD::Color::RED);
|
||||||
@ -487,33 +489,33 @@ Common::SHA1::Digest AchievementManager::GetCodeHash(const ActionReplay::ARCode&
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AchievementManager::FilterApprovedPatches(std::vector<PatchEngine::Patch>& patches,
|
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,
|
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,
|
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,
|
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,
|
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()
|
void AchievementManager::SetSpectatorMode()
|
||||||
|
@ -133,16 +133,17 @@ public:
|
|||||||
|
|
||||||
std::recursive_mutex& GetLock();
|
std::recursive_mutex& GetLock();
|
||||||
bool IsHardcoreModeActive() const;
|
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,
|
void FilterApprovedPatches(std::vector<PatchEngine::Patch>& patches, const std::string& game_id,
|
||||||
const std::string& game_ini_id) const;
|
u16 revision) const;
|
||||||
void FilterApprovedGeckoCodes(std::vector<Gecko::GeckoCode>& codes,
|
void FilterApprovedGeckoCodes(std::vector<Gecko::GeckoCode>& codes, const std::string& game_id,
|
||||||
const std::string& game_ini_id) const;
|
u16 revision) const;
|
||||||
void FilterApprovedARCodes(std::vector<ActionReplay::ARCode>& codes,
|
void FilterApprovedARCodes(std::vector<ActionReplay::ARCode>& codes, const std::string& game_id,
|
||||||
const std::string& game_ini_id) const;
|
u16 revision) const;
|
||||||
bool CheckApprovedGeckoCode(const Gecko::GeckoCode& code, const std::string& game_ini_id) const;
|
bool CheckApprovedGeckoCode(const Gecko::GeckoCode& code, const std::string& game_id,
|
||||||
bool CheckApprovedARCode(const ActionReplay::ARCode& code, const std::string& game_ini_id) const;
|
u16 revision) const;
|
||||||
|
bool CheckApprovedARCode(const ActionReplay::ARCode& code, const std::string& game_id,
|
||||||
|
u16 revision) const;
|
||||||
|
|
||||||
void SetSpectatorMode();
|
void SetSpectatorMode();
|
||||||
std::string_view GetPlayerDisplayName() const;
|
std::string_view GetPlayerDisplayName() const;
|
||||||
@ -201,9 +202,9 @@ private:
|
|||||||
void SetHardcoreMode();
|
void SetHardcoreMode();
|
||||||
|
|
||||||
template <typename T>
|
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>
|
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 PatchEngine::Patch& patch) const;
|
||||||
Common::SHA1::Digest GetCodeHash(const Gecko::GeckoCode& code) const;
|
Common::SHA1::Digest GetCodeHash(const Gecko::GeckoCode& code) const;
|
||||||
Common::SHA1::Digest GetCodeHash(const ActionReplay::ARCode& 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();
|
std::chrono::steady_clock::time_point m_last_progress_message = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
Common::Lazy<picojson::value> m_ini_root{LoadApprovedList};
|
Common::Lazy<picojson::value> m_ini_root{LoadApprovedList};
|
||||||
std::string m_game_ini_id;
|
|
||||||
|
|
||||||
std::unordered_map<AchievementId, LeaderboardStatus> m_leaderboard_map;
|
std::unordered_map<AchievementId, LeaderboardStatus> m_leaderboard_map;
|
||||||
bool m_challenges_updated = false;
|
bool m_challenges_updated = false;
|
||||||
@ -302,14 +302,12 @@ public:
|
|||||||
|
|
||||||
constexpr bool IsHardcoreModeActive() { return false; }
|
constexpr bool IsHardcoreModeActive() { return false; }
|
||||||
|
|
||||||
constexpr bool CheckApprovedGeckoCode(const Gecko::GeckoCode& code,
|
constexpr bool CheckApprovedGeckoCode(const Gecko::GeckoCode& code, const std::string& game_id)
|
||||||
const std::string& game_ini_id)
|
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr bool CheckApprovedARCode(const ActionReplay::ARCode& code,
|
constexpr bool CheckApprovedARCode(const ActionReplay::ARCode& code, const std::string& game_id)
|
||||||
const std::string& game_ini_id)
|
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
@ -113,7 +113,7 @@ struct ARAddr
|
|||||||
|
|
||||||
// ----------------------
|
// ----------------------
|
||||||
// AR Remote Functions
|
// 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())
|
if (!Config::AreCheatsEnabled())
|
||||||
return;
|
return;
|
||||||
@ -122,9 +122,9 @@ void ApplyCodes(std::span<const ARCode> codes, const std::string& game_id)
|
|||||||
s_disable_logging = false;
|
s_disable_logging = false;
|
||||||
s_active_codes.clear();
|
s_active_codes.clear();
|
||||||
std::copy_if(codes.begin(), codes.end(), std::back_inserter(s_active_codes),
|
std::copy_if(codes.begin(), codes.end(), std::back_inserter(s_active_codes),
|
||||||
[&game_id](const ARCode& code) {
|
[&game_id, &revision](const ARCode& code) {
|
||||||
return code.enabled &&
|
return code.enabled && AchievementManager::GetInstance().CheckApprovedARCode(
|
||||||
AchievementManager::GetInstance().CheckApprovedARCode(code, game_id);
|
code, game_id, revision);
|
||||||
});
|
});
|
||||||
s_active_codes.shrink_to_fit();
|
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,
|
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.
|
// Parses the Action Replay section of a game ini file.
|
||||||
|
@ -45,13 +45,13 @@ struct ARCode
|
|||||||
|
|
||||||
void RunAllActive(const Core::CPUThreadGuard& cpu_guard);
|
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 SetSyncedCodesAsActive();
|
||||||
void UpdateSyncedCodes(std::span<const ARCode> codes);
|
void UpdateSyncedCodes(std::span<const ARCode> codes);
|
||||||
std::vector<ARCode> ApplyAndReturnCodes(std::span<const ARCode> codes);
|
std::vector<ARCode> ApplyAndReturnCodes(std::span<const ARCode> codes);
|
||||||
void AddCode(ARCode new_code);
|
void AddCode(ARCode new_code);
|
||||||
void LoadAndApplyCodes(const Common::IniFile& global_ini, const Common::IniFile& local_ini,
|
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);
|
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);
|
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::vector<GeckoCode> s_synced_codes;
|
||||||
static std::mutex s_active_codes_lock;
|
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);
|
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());
|
s_active_codes.reserve(gcodes.size());
|
||||||
|
|
||||||
std::copy_if(gcodes.begin(), gcodes.end(), std::back_inserter(s_active_codes),
|
std::copy_if(gcodes.begin(), gcodes.end(), std::back_inserter(s_active_codes),
|
||||||
[&game_id](const GeckoCode& code) {
|
[&game_id, &revision](const GeckoCode& code) {
|
||||||
return code.enabled &&
|
return code.enabled && AchievementManager::GetInstance().CheckApprovedGeckoCode(
|
||||||
AchievementManager::GetInstance().CheckApprovedGeckoCode(code, game_id);
|
code, game_id, revision);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
s_active_codes.shrink_to_fit();
|
s_active_codes.shrink_to_fit();
|
||||||
|
@ -60,7 +60,7 @@ constexpr u32 HLE_TRAMPOLINE_ADDRESS = INSTALLER_END_ADDRESS - 4;
|
|||||||
// preserve the emulation performance.
|
// preserve the emulation performance.
|
||||||
constexpr u32 MAGIC_GAMEID = 0xD01F1BAD;
|
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 SetSyncedCodesAsActive();
|
||||||
void UpdateSyncedCodes(std::span<const GeckoCode> gcodes);
|
void UpdateSyncedCodes(std::span<const GeckoCode> gcodes);
|
||||||
std::vector<GeckoCode> SetAndReturnActiveCodes(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);
|
std::vector<Gecko::GeckoCode> codes = Gecko::LoadCodes(globalIni, localIni);
|
||||||
|
|
||||||
#ifdef USE_RETRO_ACHIEVEMENTS
|
#ifdef USE_RETRO_ACHIEVEMENTS
|
||||||
AchievementManager::GetInstance().FilterApprovedGeckoCodes(codes, game_id);
|
AchievementManager::GetInstance().FilterApprovedGeckoCodes(codes, game_id, revision);
|
||||||
#endif // USE_RETRO_ACHIEVEMENTS
|
#endif // USE_RETRO_ACHIEVEMENTS
|
||||||
|
|
||||||
// Create a Gecko Code Vector with just the active codes
|
// 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);
|
std::vector<ActionReplay::ARCode> codes = ActionReplay::LoadCodes(globalIni, localIni);
|
||||||
#ifdef USE_RETRO_ACHIEVEMENTS
|
#ifdef USE_RETRO_ACHIEVEMENTS
|
||||||
AchievementManager::GetInstance().FilterApprovedARCodes(codes, game_id);
|
AchievementManager::GetInstance().FilterApprovedARCodes(codes, game_id, revision);
|
||||||
#endif // USE_RETRO_ACHIEVEMENTS
|
#endif // USE_RETRO_ACHIEVEMENTS
|
||||||
// Create an AR Code Vector with just the active codes
|
// Create an AR Code Vector with just the active codes
|
||||||
std::vector<ActionReplay::ARCode> active_codes = ActionReplay::ApplyAndReturnCodes(codes);
|
std::vector<ActionReplay::ARCode> active_codes = ActionReplay::ApplyAndReturnCodes(codes);
|
||||||
|
@ -183,7 +183,8 @@ void LoadPatches()
|
|||||||
LoadPatchSection("OnFrame", &s_on_frame, globalIni, localIni);
|
LoadPatchSection("OnFrame", &s_on_frame, globalIni, localIni);
|
||||||
|
|
||||||
#ifdef USE_RETRO_ACHIEVEMENTS
|
#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
|
#endif // USE_RETRO_ACHIEVEMENTS
|
||||||
|
|
||||||
// Check if I'm syncing Codes
|
// Check if I'm syncing Codes
|
||||||
@ -194,8 +195,10 @@ void LoadPatches()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Gecko::SetActiveCodes(Gecko::LoadCodes(globalIni, localIni), sconfig.GetGameID());
|
Gecko::SetActiveCodes(Gecko::LoadCodes(globalIni, localIni), sconfig.GetGameID(),
|
||||||
ActionReplay::LoadAndApplyCodes(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()
|
void Shutdown()
|
||||||
{
|
{
|
||||||
s_on_frame.clear();
|
s_on_frame.clear();
|
||||||
ActionReplay::ApplyCodes({}, "");
|
ActionReplay::ApplyCodes({}, "", 0);
|
||||||
Gecko::Shutdown();
|
Gecko::Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ void ARCodeWidget::OnItemChanged(QListWidgetItem* item)
|
|||||||
m_ar_codes[m_code_list->row(item)].enabled = (item->checkState() == Qt::Checked);
|
m_ar_codes[m_code_list->row(item)].enabled = (item->checkState() == Qt::Checked);
|
||||||
|
|
||||||
if (!m_restart_required)
|
if (!m_restart_required)
|
||||||
ActionReplay::ApplyCodes(m_ar_codes, m_game_id);
|
ActionReplay::ApplyCodes(m_ar_codes, m_game_id, m_game_revision);
|
||||||
|
|
||||||
UpdateList();
|
UpdateList();
|
||||||
SaveCodes();
|
SaveCodes();
|
||||||
|
@ -202,7 +202,7 @@ void GeckoCodeWidget::OnItemChanged(QListWidgetItem* item)
|
|||||||
m_gecko_codes[index].enabled = (item->checkState() == Qt::Checked);
|
m_gecko_codes[index].enabled = (item->checkState() == Qt::Checked);
|
||||||
|
|
||||||
if (!m_restart_required)
|
if (!m_restart_required)
|
||||||
Gecko::SetActiveCodes(m_gecko_codes, m_game_id);
|
Gecko::SetActiveCodes(m_gecko_codes, m_game_id, m_game_revision);
|
||||||
|
|
||||||
SaveCodes();
|
SaveCodes();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user