diff --git a/Data/Sys/GameSettings/GV4E69.ini b/Data/Sys/GameSettings/GV4E69.ini index c5bd832acb..77ffcaf749 100644 --- a/Data/Sys/GameSettings/GV4E69.ini +++ b/Data/Sys/GameSettings/GV4E69.ini @@ -3,3 +3,5 @@ [OnFrame] $Fix 2D Rendering 0x80319214:dword:0x48113250 +[OnFrame_Enabled] +$Fix 2D Rendering diff --git a/Data/Sys/GameSettings/GVPE69.ini b/Data/Sys/GameSettings/GVPE69.ini index d9b5cb4f4a..afc48b4b43 100644 --- a/Data/Sys/GameSettings/GVPE69.ini +++ b/Data/Sys/GameSettings/GVPE69.ini @@ -3,3 +3,5 @@ [OnFrame] $Fix 2D Rendering 0x803C92D4:dword:0x480DA8E4 +[OnFrame_Enabled] +$Fix 2D Rendering diff --git a/Data/Sys/GameSettings/GWLE6L.ini b/Data/Sys/GameSettings/GWLE6L.ini index a6a33eaa41..579430712f 100644 --- a/Data/Sys/GameSettings/GWLE6L.ini +++ b/Data/Sys/GameSettings/GWLE6L.ini @@ -3,3 +3,5 @@ [OnFrame] $Bypass FIFO reset 0x8028EF00:dword:0x48000638 +[OnFrame_Enabled] +$Bypass FIFO reset diff --git a/Data/Sys/GameSettings/GWLX6L.ini b/Data/Sys/GameSettings/GWLX6L.ini index fa5d56e4c2..fdf558ac8c 100644 --- a/Data/Sys/GameSettings/GWLX6L.ini +++ b/Data/Sys/GameSettings/GWLX6L.ini @@ -3,3 +3,5 @@ [OnFrame] $Bypass FIFO reset 0x8028EE80:dword:0x48000638 +[OnFrame_Enabled] +$Bypass FIFO reset diff --git a/Data/Sys/GameSettings/RX4E4Z.ini b/Data/Sys/GameSettings/RX4E4Z.ini index 6a6e25ca91..093e76cca6 100644 --- a/Data/Sys/GameSettings/RX4E4Z.ini +++ b/Data/Sys/GameSettings/RX4E4Z.ini @@ -24,3 +24,5 @@ # $Fix file reads (dcache bypass) 0x800d2e68:dword:0x60000000 +[OnFrame_Enabled] +$Fix file reads (dcache bypass) diff --git a/Data/Sys/GameSettings/RX4PMT.ini b/Data/Sys/GameSettings/RX4PMT.ini index c8ad7c3ff4..d23a807744 100644 --- a/Data/Sys/GameSettings/RX4PMT.ini +++ b/Data/Sys/GameSettings/RX4PMT.ini @@ -24,3 +24,5 @@ # $Fix file reads (dcache bypass) 0x80164b90:dword:0x60000000 +[OnFrame_Enabled] +$Fix file reads (dcache bypass) diff --git a/Source/Core/Core/ActionReplay.cpp b/Source/Core/Core/ActionReplay.cpp index 8a432b99ec..f3641f72bc 100644 --- a/Source/Core/Core/ActionReplay.cpp +++ b/Source/Core/Core/ActionReplay.cpp @@ -26,7 +26,6 @@ #include #include #include -#include #include #include @@ -39,6 +38,7 @@ #include "Common/MsgHandler.h" #include "Core/ARDecrypt.h" +#include "Core/CheatCodes.h" #include "Core/ConfigManager.h" #include "Core/PowerPC/MMU.h" @@ -120,7 +120,7 @@ void ApplyCodes(const std::vector& codes) s_disable_logging = false; s_active_codes.clear(); std::copy_if(codes.begin(), codes.end(), std::back_inserter(s_active_codes), - [](const ARCode& code) { return code.active; }); + [](const ARCode& code) { return code.enabled; }); s_active_codes.shrink_to_fit(); } @@ -136,7 +136,7 @@ void UpdateSyncedCodes(const std::vector& codes) s_synced_codes.clear(); s_synced_codes.reserve(codes.size()); std::copy_if(codes.begin(), codes.end(), std::back_inserter(s_synced_codes), - [](const ARCode& code) { return code.active; }); + [](const ARCode& code) { return code.enabled; }); s_synced_codes.shrink_to_fit(); } @@ -148,7 +148,7 @@ std::vector ApplyAndReturnCodes(const std::vector& codes) s_disable_logging = false; s_active_codes.clear(); std::copy_if(codes.begin(), codes.end(), std::back_inserter(s_active_codes), - [](const ARCode& code) { return code.active; }); + [](const ARCode& code) { return code.enabled; }); } s_active_codes.shrink_to_fit(); @@ -160,7 +160,7 @@ void AddCode(ARCode code) if (!SConfig::GetInstance().bEnableCheats) return; - if (code.active) + if (code.enabled) { std::lock_guard guard(s_lock); s_disable_logging = false; @@ -178,20 +178,6 @@ std::vector LoadCodes(const IniFile& global_ini, const IniFile& local_in { std::vector codes; - std::unordered_set enabled_names; - { - std::vector enabled_lines; - local_ini.GetLines("ActionReplay_Enabled", &enabled_lines); - for (const std::string& line : enabled_lines) - { - if (!line.empty() && line[0] == '$') - { - std::string name = line.substr(1, line.size() - 1); - enabled_names.insert(name); - } - } - } - const IniFile* inis[2] = {&global_ini, &local_ini}; for (const IniFile* ini : inis) { @@ -225,7 +211,6 @@ std::vector LoadCodes(const IniFile& global_ini, const IniFile& local_in } current_code.name = line.substr(1, line.size() - 1); - current_code.active = enabled_names.find(current_code.name) != enabled_names.end(); current_code.user_defined = (ini == &local_ini); } else @@ -279,6 +264,14 @@ std::vector LoadCodes(const IniFile& global_ini, const IniFile& local_in DecryptARCode(encrypted_lines, ¤t_code.ops); codes.push_back(current_code); } + + ReadEnabledAndDisabled(*ini, "ActionReplay", &codes); + + if (ini == &global_ini) + { + for (ARCode& code : codes) + code.default_enabled = code.enabled; + } } return codes; @@ -288,21 +281,27 @@ void SaveCodes(IniFile* local_ini, const std::vector& codes) { std::vector lines; std::vector enabled_lines; + std::vector disabled_lines; + for (const ActionReplay::ARCode& code : codes) { - if (code.active) - enabled_lines.emplace_back("$" + code.name); + if (code.enabled) + enabled_lines.emplace_back('$' + code.name); + else if (code.default_enabled) + disabled_lines.emplace_back('$' + code.name); if (code.user_defined) { - lines.emplace_back("$" + code.name); + lines.emplace_back('$' + code.name); for (const ActionReplay::AREntry& op : code.ops) { lines.emplace_back(fmt::format("{:08X} {:08X}", op.cmd_addr, op.value)); } } } + local_ini->SetLines("ActionReplay_Enabled", enabled_lines); + local_ini->SetLines("ActionReplay_Disabled", disabled_lines); local_ini->SetLines("ActionReplay", lines); } diff --git a/Source/Core/Core/ActionReplay.h b/Source/Core/Core/ActionReplay.h index b42e2f08b0..e79c6d4f38 100644 --- a/Source/Core/Core/ActionReplay.h +++ b/Source/Core/Core/ActionReplay.h @@ -28,8 +28,9 @@ struct ARCode { std::string name; std::vector ops; - bool active; - bool user_defined; + bool enabled = false; + bool default_enabled = false; + bool user_defined = false; }; void RunAllActive(); diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt index 6da101c42e..72835324a7 100644 --- a/Source/Core/Core/CMakeLists.txt +++ b/Source/Core/Core/CMakeLists.txt @@ -7,6 +7,7 @@ add_library(core ARDecrypt.h BootManager.cpp BootManager.h + CheatCodes.h CommonTitles.h ConfigManager.cpp ConfigManager.h diff --git a/Source/Core/Core/CheatCodes.h b/Source/Core/Core/CheatCodes.h new file mode 100644 index 0000000000..a440f9ed6a --- /dev/null +++ b/Source/Core/Core/CheatCodes.h @@ -0,0 +1,38 @@ +// Copyright 2020 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include +#include + +#include "Common/IniFile.h" + +template +void ReadEnabledOrDisabled(const IniFile& ini, const std::string& section, bool enabled, + std::vector* codes) +{ + std::vector lines; + ini.GetLines(section, &lines, false); + + for (const std::string& line : lines) + { + if (line.empty() || line[0] != '$') + continue; + + for (T& code : *codes) + { + // Exclude the initial '$' from the comparison. + if (line.compare(1, std::string::npos, code.name) == 0) + code.enabled = enabled; + } + } +} + +template +void ReadEnabledAndDisabled(const IniFile& ini, const std::string& section, std::vector* codes) +{ + ReadEnabledOrDisabled(ini, section + "_Enabled", true, codes); + ReadEnabledOrDisabled(ini, section + "_Disabled", false, codes); +} diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj index 35dd58d202..a7ada5b18e 100644 --- a/Source/Core/Core/Core.vcxproj +++ b/Source/Core/Core/Core.vcxproj @@ -384,6 +384,7 @@ + diff --git a/Source/Core/Core/Core.vcxproj.filters b/Source/Core/Core/Core.vcxproj.filters index 73b159219f..749b81b9c2 100644 --- a/Source/Core/Core/Core.vcxproj.filters +++ b/Source/Core/Core/Core.vcxproj.filters @@ -1765,6 +1765,7 @@ HW %28Flipper/Hollywood%29\EXI - Expansion Interface\BBA + diff --git a/Source/Core/Core/GeckoCode.h b/Source/Core/Core/GeckoCode.h index 9c6c7c7a14..74d750bcf4 100644 --- a/Source/Core/Core/GeckoCode.h +++ b/Source/Core/Core/GeckoCode.h @@ -29,6 +29,7 @@ public: std::vector notes; bool enabled = false; + bool default_enabled = false; bool user_defined = false; bool Exist(u32 address, u32 data) const; diff --git a/Source/Core/Core/GeckoCodeConfig.cpp b/Source/Core/Core/GeckoCodeConfig.cpp index d11035306f..605fb82533 100644 --- a/Source/Core/Core/GeckoCodeConfig.cpp +++ b/Source/Core/Core/GeckoCodeConfig.cpp @@ -13,6 +13,7 @@ #include "Common/IniFile.h" #include "Common/Logging/Log.h" #include "Common/StringUtil.h" +#include "Core/CheatCodes.h" namespace Gecko { @@ -190,23 +191,12 @@ std::vector LoadCodes(const IniFile& globalIni, const IniFile& localI gcodes.push_back(gcode); } - ini->GetLines("Gecko_Enabled", &lines, false); + ReadEnabledAndDisabled(*ini, "Gecko", &gcodes); - for (const std::string& line : lines) + if (ini == &globalIni) { - if (line.empty() || line[0] != '$') - { - continue; - } - - for (GeckoCode& ogcode : gcodes) - { - // Exclude the initial '$' from the comparison. - if (line.compare(1, std::string::npos, ogcode.name) == 0) - { - ogcode.enabled = true; - } - } + for (GeckoCode& code : gcodes) + code.default_enabled = code.enabled; } } @@ -226,12 +216,8 @@ static std::string MakeGeckoCodeTitle(const GeckoCode& code) } // used by the SaveGeckoCodes function -static void SaveGeckoCode(std::vector& lines, std::vector& enabledLines, - const GeckoCode& gcode) +static void SaveGeckoCode(std::vector& lines, const GeckoCode& gcode) { - if (gcode.enabled) - enabledLines.push_back('$' + gcode.name); - if (!gcode.user_defined) return; @@ -251,14 +237,21 @@ static void SaveGeckoCode(std::vector& lines, std::vector& gcodes) { std::vector lines; - std::vector enabledLines; + std::vector enabled_lines; + std::vector disabled_lines; for (const GeckoCode& geckoCode : gcodes) { - SaveGeckoCode(lines, enabledLines, geckoCode); + if (geckoCode.enabled) + enabled_lines.emplace_back('$' + geckoCode.name); + else if (geckoCode.default_enabled) + disabled_lines.emplace_back('$' + geckoCode.name); + + SaveGeckoCode(lines, geckoCode); } inifile.SetLines("Gecko", lines); - inifile.SetLines("Gecko_Enabled", enabledLines); + inifile.SetLines("Gecko_Enabled", enabled_lines); + inifile.SetLines("Gecko_Disabled", disabled_lines); } } // namespace Gecko diff --git a/Source/Core/Core/NetPlayClient.cpp b/Source/Core/Core/NetPlayClient.cpp index 4a2d168173..5dee4b3405 100644 --- a/Source/Core/Core/NetPlayClient.cpp +++ b/Source/Core/Core/NetPlayClient.cpp @@ -1158,7 +1158,7 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet) arcode = ActionReplay::ARCode(); // Initialize arcode arcode.name = "Synced Codes"; - arcode.active = true; + arcode.enabled = true; // Receive code contents from packet for (int i = 0; i < m_sync_ar_codes_count; i++) diff --git a/Source/Core/Core/PatchEngine.cpp b/Source/Core/Core/PatchEngine.cpp index f249d33c7a..4f4daafcd7 100644 --- a/Source/Core/Core/PatchEngine.cpp +++ b/Source/Core/Core/PatchEngine.cpp @@ -12,7 +12,6 @@ #include #include #include -#include #include #include @@ -21,6 +20,7 @@ #include "Common/StringUtil.h" #include "Core/ActionReplay.h" +#include "Core/CheatCodes.h" #include "Core/Config/MainSettings.h" #include "Core/ConfigManager.h" #include "Core/GeckoCode.h" @@ -47,20 +47,6 @@ const char* PatchTypeAsString(PatchType type) void LoadPatchSection(const std::string& section, std::vector& patches, IniFile& globalIni, IniFile& localIni) { - // Load the name of all enabled patches - std::string enabledSectionName = section + "_Enabled"; - std::vector enabledLines; - std::set enabledNames; - localIni.GetLines(enabledSectionName, &enabledLines); - for (const std::string& line : enabledLines) - { - if (!line.empty() && line[0] == '$') - { - std::string name = line.substr(1, line.size() - 1); - enabledNames.insert(name); - } - } - const IniFile* inis[2] = {&globalIni, &localIni}; for (const IniFile* ini : inis) @@ -83,9 +69,8 @@ void LoadPatchSection(const std::string& section, std::vector& patches, I } currentPatch.entries.clear(); - // Set active and name + // Set name and whether the patch is user defined currentPatch.name = line.substr(1, line.size() - 1); - currentPatch.active = enabledNames.find(currentPatch.name) != enabledNames.end(); currentPatch.user_defined = (ini == &localIni); } else @@ -123,6 +108,14 @@ void LoadPatchSection(const std::string& section, std::vector& patches, I { patches.push_back(currentPatch); } + + ReadEnabledAndDisabled(*ini, section, &patches); + + if (ini == &globalIni) + { + for (Patch& patch : patches) + patch.default_enabled = patch.enabled; + } } } @@ -185,7 +178,7 @@ static void ApplyPatches(const std::vector& patches) { for (const Patch& patch : patches) { - if (patch.active) + if (patch.enabled) { for (const PatchEntry& entry : patch.entries) { diff --git a/Source/Core/Core/PatchEngine.h b/Source/Core/Core/PatchEngine.h index 7e3ae628db..a496f04936 100644 --- a/Source/Core/Core/PatchEngine.h +++ b/Source/Core/Core/PatchEngine.h @@ -33,7 +33,8 @@ struct Patch { std::string name; std::vector entries; - bool active = false; + bool enabled = false; + bool default_enabled = false; bool user_defined = false; // False if this code is shipped with Dolphin. }; diff --git a/Source/Core/DolphinQt/CheatsManager.cpp b/Source/Core/DolphinQt/CheatsManager.cpp index 3c0dc72e76..860f6e6110 100644 --- a/Source/Core/DolphinQt/CheatsManager.cpp +++ b/Source/Core/DolphinQt/CheatsManager.cpp @@ -292,7 +292,7 @@ void CheatsManager::GenerateARCode() int index = item->data(INDEX_ROLE).toInt(); ActionReplay::ARCode ar_code; - ar_code.active = true; + ar_code.enabled = true; ar_code.user_defined = true; ar_code.name = tr("Generated by search (Address %1)") .arg(m_watch[index].address, 8, 16, QLatin1Char('0')) diff --git a/Source/Core/DolphinQt/Config/ARCodeWidget.cpp b/Source/Core/DolphinQt/Config/ARCodeWidget.cpp index eca7ccf705..4a1769ff3b 100644 --- a/Source/Core/DolphinQt/Config/ARCodeWidget.cpp +++ b/Source/Core/DolphinQt/Config/ARCodeWidget.cpp @@ -89,7 +89,7 @@ void ARCodeWidget::ConnectWidgets() void ARCodeWidget::OnItemChanged(QListWidgetItem* item) { - m_ar_codes[m_code_list->row(item)].active = (item->checkState() == Qt::Checked); + m_ar_codes[m_code_list->row(item)].enabled = (item->checkState() == Qt::Checked); if (!m_restart_required) ActionReplay::ApplyCodes(m_ar_codes); @@ -159,7 +159,7 @@ void ARCodeWidget::UpdateList() item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsDragEnabled); - item->setCheckState(ar.active ? Qt::Checked : Qt::Unchecked); + item->setCheckState(ar.enabled ? Qt::Checked : Qt::Unchecked); item->setData(Qt::UserRole, static_cast(i)); m_code_list->addItem(item); @@ -190,7 +190,7 @@ void ARCodeWidget::AddCode(ActionReplay::ARCode code) void ARCodeWidget::OnCodeAddClicked() { ActionReplay::ARCode ar; - ar.active = true; + ar.enabled = true; CheatCodeEditor ed(this); ed.SetARCode(&ar); diff --git a/Source/Core/DolphinQt/Config/NewPatchDialog.cpp b/Source/Core/DolphinQt/Config/NewPatchDialog.cpp index 9ee9e76218..b72506be49 100644 --- a/Source/Core/DolphinQt/Config/NewPatchDialog.cpp +++ b/Source/Core/DolphinQt/Config/NewPatchDialog.cpp @@ -34,7 +34,7 @@ NewPatchDialog::NewPatchDialog(QWidget* parent, PatchEngine::Patch& patch) if (m_patch.entries.empty()) { AddEntry(); - m_patch.active = true; + m_patch.enabled = true; } } diff --git a/Source/Core/DolphinQt/Config/PatchesWidget.cpp b/Source/Core/DolphinQt/Config/PatchesWidget.cpp index bb9025008a..1ac7f55154 100644 --- a/Source/Core/DolphinQt/Config/PatchesWidget.cpp +++ b/Source/Core/DolphinQt/Config/PatchesWidget.cpp @@ -65,7 +65,7 @@ void PatchesWidget::ConnectWidgets() void PatchesWidget::OnItemChanged(QListWidgetItem* item) { - m_patches[m_list->row(item)].active = (item->checkState() == Qt::Checked); + m_patches[m_list->row(item)].enabled = (item->checkState() == Qt::Checked); SavePatches(); } @@ -129,21 +129,24 @@ void PatchesWidget::SavePatches() { std::vector lines; std::vector lines_enabled; + std::vector lines_disabled; for (const auto& patch : m_patches) { - if (patch.active) - lines_enabled.push_back("$" + patch.name); + if (patch.enabled) + lines_enabled.emplace_back('$' + patch.name); + else if (patch.default_enabled) + lines_disabled.emplace_back('$' + patch.name); if (!patch.user_defined) continue; - lines.push_back("$" + patch.name); + lines.emplace_back('$' + patch.name); for (const auto& entry : patch.entries) { - lines.push_back(StringFromFormat("0x%08X:%s:0x%08X", entry.address, - PatchEngine::PatchTypeAsString(entry.type), entry.value)); + lines.emplace_back(StringFromFormat("0x%08X:%s:0x%08X", entry.address, + PatchEngine::PatchTypeAsString(entry.type), entry.value)); } } @@ -151,6 +154,7 @@ void PatchesWidget::SavePatches() game_ini_local.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + m_game_id + ".ini"); game_ini_local.SetLines("OnFrame_Enabled", lines_enabled); + game_ini_local.SetLines("OnFrame_Disabled", lines_disabled); game_ini_local.SetLines("OnFrame", lines); game_ini_local.Save(File::GetUserPath(D_GAMESETTINGS_IDX) + m_game_id + ".ini"); @@ -164,7 +168,7 @@ void PatchesWidget::Update() { auto* item = new QListWidgetItem(QString::fromStdString(patch.name)); item->setFlags(item->flags() | Qt::ItemIsUserCheckable); - item->setCheckState(patch.active ? Qt::Checked : Qt::Unchecked); + item->setCheckState(patch.enabled ? Qt::Checked : Qt::Unchecked); item->setData(Qt::UserRole, patch.user_defined); m_list->addItem(item);