Add xdelta3 and file patching interface

This commit is contained in:
ManDude
2022-06-20 22:45:30 +01:00
parent d89a97b57c
commit f017106da1
108 changed files with 38670 additions and 49 deletions
+54
View File
@@ -27,6 +27,7 @@
#include "common/log/log.h"
#include "common/util/json_util.h"
#include "common/util/crc32.h"
#include "common/util/xdelta3_util.h"
namespace decompiler {
namespace {
@@ -140,6 +141,59 @@ ObjectFileDB::ObjectFileDB(const std::vector<std::string>& _dgos,
for (auto& obj : object_files) {
auto data = file_util::read_binary_file(obj);
auto name = obj_filename_to_name(obj);
if (auto it = config.object_patches.find(name); it != config.object_patches.end()) {
// print the file CRC
fmt::print("CRC for {} is: 0x{:X}\n", name, crc32(data.data(), data.size()));
// write patch file if necessary
if (config.write_patches) {
// this is the "target" file we want to patch to
auto data2 = file_util::read_binary_file(
(file_util::get_jak_project_dir() / it->second.target_file).string());
// we need to allocate a buffer to store the delta patch
// we make it 2x the source file's size because... it seems like a good size?
// ideally the delta patch should never be that big.
int buf_sz = data.size() * 2;
u8* out_buf = (u8*)malloc(buf_sz);
size_t out_sz = 0; // this is where the actual used size of the delta patch will be stored
int xd3_res = xd3_encode_memory(data2.data(), data2.size(), data.data(), data.size(),
out_buf, &out_sz, buf_sz, 0);
if (xd3_res) {
lg::error("error patching {} with {} (out {}): {}", name, it->second.target_file,
it->second.patch_file, xd3_strerror(xd3_res));
} else {
std::vector<u8> patch_data(out_sz);
memcpy(patch_data.data(), out_buf, patch_data.size());
file_util::write_binary_file(
(file_util::get_jak_project_dir() / it->second.patch_file).string(),
patch_data.data(), patch_data.size());
}
free(out_buf);
}
// apply patch file if necessary
// note that xd3 doesnt really have any safety against bad files so we check crc ourselves
if (config.apply_patches && it->second.crc == crc32(data.data(), data.size())) {
// this is the delta patch file
auto data2 = file_util::read_binary_file(
(file_util::get_jak_project_dir() / it->second.patch_file).string());
// we need to allocate a buffer to store the patched file
// the delta patch isn't gonna be this big but we allocate 2x the source file's size + the
// delta patch's size
int buf_sz = data.size() * 2 + data2.size();
u8* out_buf = (u8*)malloc(buf_sz);
size_t out_sz = 0;
int xd3_res = xd3_decode_memory(data2.data(), data2.size(), data.data(), data.size(),
out_buf, &out_sz, buf_sz, 0);
if (xd3_res) {
lg::error("error patching {} with {} (out {}): {}", name, it->second.target_file,
it->second.patch_file, xd3_strerror(xd3_res));
} else {
data.resize(out_sz);
memcpy(data.data(), out_buf, data.size());
}
free(out_buf);
}
}
add_obj_from_dgo(name, name, data.data(), data.size(), "NO-XGO", config);
}