Skip to content
Permalink
Browse files

PatchEngine: Fix code review comments

  • Loading branch information...
phire committed Apr 23, 2019
1 parent f64bc5a commit c4977feb467f1c5647d067797b3fd6eade9133a3
@@ -506,7 +506,7 @@ bool CBoot::BootUp(std::unique_ptr<BootParameters> boot)
};

PatchEngine::LoadPatches();

if (!std::visit(BootTitle(), boot->parameters))
return false;

@@ -89,7 +89,7 @@ static Common::SPSCQueue<ReadResult, false> s_result_queue;
static std::map<u64, ReadResult> s_result_map;

static std::unique_ptr<DiscIO::Volume> s_disc;
static std::unique_ptr<std::map<u64, std::vector<u8>>> s_disc_patches;
static std::map<u64, std::vector<u8>> s_disc_patches;

void Start()
{
@@ -363,32 +363,37 @@ static void FinishRead(u64 id, s64 cycles_late)
buffer);
}

static void PatchReadRequest(std::vector<u8> &buffer, u64 offset) {
if(!s_disc_patches)
return;

static void PatchReadRequest(std::vector<u8>& buffer, u64 offset)
{
u64 end_offset = offset + buffer.size();

// Scan through patches which might overlap our current read request and apply them
for (auto it = s_disc_patches->begin(); it != s_disc_patches->end(); it++) {
if (it->first > end_offset) // Patch starts after the end of the read request

// Because the patches are variably sized, we scan in reverse order to take advantage
// of upper_bound, which gives us the first patch that starts after the read buffer.
auto it = s_disc_patches.upper_bound(end_offset);

while (it-- != s_disc_patches.begin()) // Loop backwards until start of s_disc_patches
{
if (it->first + it->second.size() < offset)
{
// Patch is before the read request, we can stop searching
return;
}
else if (it->first >= offset) // Patch starts inside the read request
else if (it->first >= offset)
{
// Patch starts inside the read request
u64 start = it->first - offset;
u32 old_data;
u32 new_data;
std::memcpy(&old_data, buffer.data() + start, 4);
std::memmove(buffer.data() + start, it->second.data(), std::min(it->second.size(), buffer.size() - start));
std::memcpy(&new_data, buffer.data() + start, 4);
INFO_LOG(DVDINTERFACE, "patch applied at %08lx - old: %08x new: %08x", offset + start, old_data, new_data);
std::memmove(buffer.data() + start, it->second.data(),
std::min(it->second.size(), buffer.size() - start));
INFO_LOG(DVDINTERFACE, "patch applied at %08lx", offset + start);
}
else if (it->first + it->second.size() > offset) // Patch overlaps the start of the read request
else if (it->first + it->second.size() > offset)
{
// Patch overlaps with the start of the read request
u64 start = offset - it->first;
std::memmove(buffer.data(), it->second.data() + start, std::min(it->second.size() - start, buffer.size()));
std::memmove(buffer.data(), it->second.data() + start,
std::min(it->second.size() - start, buffer.size()));
INFO_LOG(DVDINTERFACE, "patch applied at %08lx", offset);
}
}
@@ -415,7 +420,6 @@ static void DVDThread()
buffer.resize(0);
else
PatchReadRequest(buffer, request.dvd_offset);


request.realtime_done_us = Common::Timer::GetTimeUs();

@@ -427,4 +431,4 @@ static void DVDThread()
}
}
}
}
} // namespace DVDThread
@@ -92,9 +92,11 @@ void LoadPatchSection(const std::string& section, std::vector<Patch>& patches, I
currentPatch.active = enabledNames.find(currentPatch.name) != enabledNames.end();
currentPatch.user_defined = (ini == &localIni);
}
else if (line[0] == '/') {
// Split mult-file patches
if(!currentPatch.path.empty()) {
else if (line[0] == '/')
{
// Split multi-file patches
if (!currentPatch.path.empty())
{
patches.push_back(currentPatch);
}
currentPatch.entries.clear();
@@ -224,50 +226,55 @@ static void ApplyPatches(const std::vector<Patch>& patches)
}
}

std::unique_ptr<std::map<u64, std::vector<u8>>> CalculateDiscPatches(const DiscIO::Volume &disc) {
if (s_file_patches.empty())
return nullptr;

std::map<u64, std::vector<u8>> CalculateDiscPatches(const DiscIO::Volume& disc)
{
auto partition = disc.GetGamePartition();
const DiscIO::FileSystem *fs = disc.GetFileSystem(partition);
const DiscIO::FileSystem* fs = disc.GetFileSystem(partition);

auto patches = std::make_unique<std::map<u64, std::vector<u8>>>();
auto patches = std::map<u64, std::vector<u8>>();

for (const auto& patch : s_file_patches) {
for (const auto& patch : s_file_patches)
{
if (!patch.active)
continue;

const auto& file = fs->FindFileInfo(patch.path);
if (file) {
for (const auto& entry : patch.entries) {
u64 disc_offset = disc.PartitionOffsetToRawOffset(file->GetOffset(), partition) + entry.address;
if (file)
{
for (const auto& entry : patch.entries)
{
u64 disc_offset =
disc.PartitionOffsetToRawOffset(file->GetOffset(), partition) + entry.address;
std::vector<u8> data;
switch (entry.type)
{
case PatchType::Patch32Bit:
data.push_back(static_cast<u8>(entry.value>>24));
data.push_back(static_cast<u8>(entry.value>>16));
case PatchType::Patch16Bit:
data.push_back(static_cast<u8>(entry.value>>8));
case PatchType::Patch8Bit:
data.push_back(static_cast<u8>(entry.value));
break;
default:
// unknown patch type
// In the future we could add support for larger patch entries.
break;
}
case PatchType::Patch32Bit:
data.push_back(static_cast<u8>(entry.value >> 24));
data.push_back(static_cast<u8>(entry.value >> 16));
// [[fallthrough]];
case PatchType::Patch16Bit:
data.push_back(static_cast<u8>(entry.value >> 8));
// [[fallthrough]];
case PatchType::Patch8Bit:
data.push_back(static_cast<u8>(entry.value));
break;
default:
// unknown patch type
// In the future we could add support for larger patch entries.

//std::reverse(data.begin(), data.end()); // Reverse for endianness
patches->emplace(disc_offset, data);
// Downstream code deals with vectors of bytes which could be arbitrary length
break;
}
patches.emplace(disc_offset, data);
}

INFO_LOG(ACTIONREPLAY, "Applied patch '%s' to file '%s'", patch.name.c_str(), patch.path.c_str());
INFO_LOG(ACTIONREPLAY, "Applied patch '%s' to file '%s'", patch.name.c_str(),
patch.path.c_str());
}
}

// Return null
return patches->empty() ? nullptr : std::move(patches);
// Return null
return patches;
}

// Requires MSR.DR, MSR.IR
@@ -332,4 +339,4 @@ void Reload()
LoadPatches();
}

} // namespace
} // namespace PatchEngine
@@ -11,8 +11,10 @@

#include "Common/CommonTypes.h"

#include "DiscIO/Volume.h"

namespace DiscIO
{
class Volume;
}
class IniFile;

namespace PatchEngine
@@ -45,7 +47,7 @@ struct Patch
const char* PatchTypeAsString(PatchType type);

int GetSpeedhackCycles(const u32 addr);
std::unique_ptr<std::map<u64, std::vector<u8>>> CalculateDiscPatches(const DiscIO::Volume& disc);
std::map<u64, std::vector<u8>> CalculateDiscPatches(const DiscIO::Volume& disc);
void LoadPatchSection(const std::string& section, std::vector<Patch>& patches, IniFile& globalIni,
IniFile& localIni);
void LoadPatches();

0 comments on commit c4977fe

Please sign in to comment.
You can’t perform that action at this time.