Riivolution: add search_count attribute to memory patches
This allows you to write a single memory search patch that gets applied multiple times at different offsets. Note that for implementation simplicity this count currently resets for each DOL section. This is also the existing behavior for single-match patches.
This commit is contained in:
parent
e87a22fbf4
commit
c9ad4ec68d
|
@ -211,6 +211,7 @@ std::optional<Disc> 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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<u8> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue