Riivolution: memory patch values lent, not copied

A memory patch's value file is lent through File::LoanFile and handed to
the patcher as a span, and a value given inline is used where the parser
left it, instead of either being copied into a fresh std::vector each
time a patch is applied.
This commit is contained in:
LibretroAdmin authored and libretroadmin committed 2026-11-07 05:45:58 +01:00
1 parent e08e1bd766
commit 3074d3caa0
2 files changed
+43 -26

No files matched your search

+38 -24
View File
@@ -172,20 +172,14 @@ FileDataLoaderHostFS::GetExternalFileSize(std::string_view external_relative_pat
return f.GetSize();
}
std::vector<u8> FileDataLoaderHostFS::GetFileContents(std::string_view external_relative_path)
bool FileDataLoaderHostFS::LoanFileContents(std::string_view external_relative_path,
::File::FileLoan* loan)
{
auto path = MakeAbsoluteFromRelative(external_relative_path);
if (!path)
return {};
::File::IOFile f(*path, "rb");
if (!f)
return {};
const u64 length = f.GetSize();
std::vector<u8> value;
value.resize(length);
if (!f.ReadBytes(value.data(), length))
return {};
return value;
loan->data = nullptr;
loan->size = 0;
loan->owned = nullptr;
return path && ::File::LoanFile(loan, path->c_str());
}
std::vector<FileDataLoader::Node>
@@ -524,10 +518,20 @@ static void ApplyMemoryPatch(const Core::CPUThreadGuard& guard, u32 offset,
}
}
static std::vector<u8> GetMemoryPatchValue(const Patch& patch, const Memory& memory_patch)
// The patch's value: lent from its value file, or the parsed bytes as they
// are; File::EndLoan(loan) when done either way.
static std::span<const u8> GetMemoryPatchValue(const Patch& patch, const Memory& memory_patch,
::File::FileLoan* loan)
{
loan->data = nullptr;
loan->size = 0;
loan->owned = nullptr;
if (!memory_patch.m_valuefile.empty())
return patch.m_file_data_loader->GetFileContents(memory_patch.m_valuefile);
{
if (!patch.m_file_data_loader->LoanFileContents(memory_patch.m_valuefile, loan))
return {};
return std::span<const u8>(loan->data, size_t(loan->size));
}
return memory_patch.m_value;
}
@@ -537,8 +541,10 @@ static void ApplyMemoryPatch(const Core::CPUThreadGuard& guard, const Patch& pat
if (memory_patch.m_offset == 0)
return;
::File::FileLoan loan;
ApplyMemoryPatch(guard, memory_patch.m_offset | 0x80000000,
GetMemoryPatchValue(patch, memory_patch), memory_patch.m_original);
GetMemoryPatchValue(patch, memory_patch, &loan), memory_patch.m_original);
::File::EndLoan(&loan);
}
static void ApplySearchMemoryPatch(const Core::CPUThreadGuard& guard, const Patch& patch,
@@ -553,21 +559,17 @@ static void ApplySearchMemoryPatch(const Core::CPUThreadGuard& guard, const Patc
const u32 address = ram_start + i;
if (MemoryMatchesAt(guard, address, memory_patch.m_original))
{
ApplyMemoryPatch(guard, address, GetMemoryPatchValue(patch, memory_patch), {});
::File::FileLoan loan;
ApplyMemoryPatch(guard, address, GetMemoryPatchValue(patch, memory_patch, &loan), {});
::File::EndLoan(&loan);
break;
}
}
}
static void ApplyOcarinaMemoryPatch(const Core::CPUThreadGuard& guard, const Patch& patch,
const Memory& memory_patch, u32 ram_start, u32 length)
static void ApplyOcarinaPattern(const Core::CPUThreadGuard& guard, const Memory& memory_patch,
std::span<const u8> value, u32 ram_start, u32 length)
{
if (memory_patch.m_offset == 0)
return;
const std::vector<u8> value = GetMemoryPatchValue(patch, memory_patch);
if (value.empty())
return;
auto& system = guard.GetSystem();
for (u32 i = 0; i < length; i += 4)
{
@@ -600,6 +602,18 @@ static void ApplyOcarinaMemoryPatch(const Core::CPUThreadGuard& guard, const Pat
}
}
static void ApplyOcarinaMemoryPatch(const Core::CPUThreadGuard& guard, const Patch& patch,
const Memory& memory_patch, u32 ram_start, u32 length)
{
if (memory_patch.m_offset == 0)
return;
::File::FileLoan loan;
const std::span<const u8> value = GetMemoryPatchValue(patch, memory_patch, &loan);
if (!value.empty())
ApplyOcarinaPattern(guard, memory_patch, value, ram_start, length);
::File::EndLoan(&loan);
}
void ApplyGeneralMemoryPatches(const Core::CPUThreadGuard& guard, std::span<const Patch> patches)
{
const auto& system = guard.GetSystem();
+5 -2
View File
@@ -9,6 +9,7 @@
#include <string_view>
#include <vector>
#include "Common/IOFile.h"
#include "DiscIO/DirectoryBlob.h"
#include "DiscIO/RiivolutionParser.h"
@@ -36,7 +37,9 @@ public:
virtual ~FileDataLoader();
virtual std::optional<u64> GetExternalFileSize(std::string_view external_relative_path) = 0;
virtual std::vector<u8> GetFileContents(std::string_view external_relative_path) = 0;
// The whole file, lent; File::EndLoan() when done.
virtual bool LoanFileContents(std::string_view external_relative_path,
::File::FileLoan* loan) = 0;
virtual std::vector<Node> GetFolderContents(std::string_view external_relative_path) = 0;
virtual BuilderContentSource MakeContentSource(std::string_view external_relative_path,
u64 external_offset, u64 external_size,
@@ -55,7 +58,7 @@ public:
std::string_view patch_root);
std::optional<u64> GetExternalFileSize(std::string_view external_relative_path) override;
std::vector<u8> GetFileContents(std::string_view external_relative_path) override;
bool LoanFileContents(std::string_view external_relative_path, ::File::FileLoan* loan) override;
std::vector<FileDataLoader::Node>
GetFolderContents(std::string_view external_relative_path) override;
BuilderContentSource MakeContentSource(std::string_view external_relative_path,