diff --git a/Source/Core/DiscIO/RiivolutionParser.cpp b/Source/Core/DiscIO/RiivolutionParser.cpp index f120335f56..98ea299b13 100644 --- a/Source/Core/DiscIO/RiivolutionParser.cpp +++ b/Source/Core/DiscIO/RiivolutionParser.cpp @@ -211,6 +211,7 @@ std::optional ParseString(std::string_view xml, std::string xml_path) memory.m_original = ReadHexString(patch_subnode.attribute("original").as_string()); memory.m_ocarina = patch_subnode.attribute("ocarina").as_bool(false); memory.m_search = patch_subnode.attribute("search").as_bool(false); + memory.m_search_count = patch_subnode.attribute("search_count").as_uint(1); memory.m_align = patch_subnode.attribute("align").as_uint(1); } } diff --git a/Source/Core/DiscIO/RiivolutionParser.h b/Source/Core/DiscIO/RiivolutionParser.h index a52cb8f7cc..a2d4486cca 100644 --- a/Source/Core/DiscIO/RiivolutionParser.h +++ b/Source/Core/DiscIO/RiivolutionParser.h @@ -146,9 +146,12 @@ struct Memory bool m_ocarina = false; // If true, the offset is not known, and instead we should search for the m_original bytes in - // memory and replace them where found. Only searches in MEM1, and only replaces the first match. + // memory and replace them where found. Only searches in MEM1. bool m_search = false; + // For m_search. Replaces up to m_search_count occurrences. + u32 m_search_count = 1; + // For m_search. The byte stride between search points. u32 m_align = 1; }; diff --git a/Source/Core/DiscIO/RiivolutionPatcher.cpp b/Source/Core/DiscIO/RiivolutionPatcher.cpp index 8c54968c35..6292452797 100644 --- a/Source/Core/DiscIO/RiivolutionPatcher.cpp +++ b/Source/Core/DiscIO/RiivolutionPatcher.cpp @@ -565,17 +565,21 @@ static void ApplyMemoryPatch(const Core::CPUThreadGuard& guard, const Patch& pat static void ApplySearchMemoryPatch(const Core::CPUThreadGuard& guard, const Patch& patch, const Memory& memory_patch, u32 ram_start, u32 length) { - if (memory_patch.m_original.empty() || memory_patch.m_align == 0) + if (memory_patch.m_original.empty() || memory_patch.m_align == 0 || memory_patch.m_search_count == 0) return; const u32 stride = memory_patch.m_align; + u32 times = memory_patch.m_search_count; for (u32 i = 0; i < length - (stride - 1); i += stride) { const u32 address = ram_start + i; if (MemoryMatchesAt(guard, address, memory_patch.m_original)) { - ApplyMemoryPatch(guard, address, GetMemoryPatchValue(patch, memory_patch), {}); - break; + const std::vector value = GetMemoryPatchValue(patch, memory_patch); + INFO_LOG_FMT(BOOT, "Applying memory patch at [0x{:08X}, 0x{:08X})", address, address + value.size()); + ApplyMemoryPatch(guard, address, value, {}); + if (--times == 0) + break; } } }