mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-12 22:14:58 +00:00
Patches: Virtual move/remove game files patches
This commit is contained in:
parent
1d7a00666e
commit
382a7c94a2
@ -4,6 +4,7 @@
|
|||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "Emu/Memory/vm.h"
|
#include "Emu/Memory/vm.h"
|
||||||
#include "Emu/System.h"
|
#include "Emu/System.h"
|
||||||
|
#include "Emu/VFS.h"
|
||||||
|
|
||||||
#include "util/types.hpp"
|
#include "util/types.hpp"
|
||||||
#include "util/endian.hpp"
|
#include "util/endian.hpp"
|
||||||
@ -76,6 +77,8 @@ void fmt_class_string<patch_type>::format(std::string& out, u64 arg)
|
|||||||
case patch_type::lef32: return "lef32";
|
case patch_type::lef32: return "lef32";
|
||||||
case patch_type::lef64: return "lef64";
|
case patch_type::lef64: return "lef64";
|
||||||
case patch_type::utf8: return "utf8";
|
case patch_type::utf8: return "utf8";
|
||||||
|
case patch_type::move_file: return "move_file";
|
||||||
|
case patch_type::hide_file: return "hide_file";
|
||||||
}
|
}
|
||||||
|
|
||||||
return unknown;
|
return unknown;
|
||||||
@ -682,7 +685,7 @@ bool patch_engine::add_patch_data(YAML::Node node, patch_info& info, u32 modifie
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!addr_node.Scalar().starts_with("0x"))
|
if (patch_type_uses_hex_offset(type) && !addr_node.Scalar().starts_with("0x"))
|
||||||
{
|
{
|
||||||
append_log_message(log_messages, fmt::format("Skipping patch node %s. Address element has wrong format %s. (key: %s, location: %s)", info.description, addr_node.Scalar(), info.hash, get_yaml_node_location(node)), &patch_log.error);
|
append_log_message(log_messages, fmt::format("Skipping patch node %s. Address element has wrong format %s. (key: %s, location: %s)", info.description, addr_node.Scalar(), info.hash, get_yaml_node_location(node)), &patch_log.error);
|
||||||
return false;
|
return false;
|
||||||
@ -691,6 +694,7 @@ bool patch_engine::add_patch_data(YAML::Node node, patch_info& info, u32 modifie
|
|||||||
struct patch_data p_data{};
|
struct patch_data p_data{};
|
||||||
p_data.type = type;
|
p_data.type = type;
|
||||||
p_data.offset = addr_node.as<u32>(0) + modifier;
|
p_data.offset = addr_node.as<u32>(0) + modifier;
|
||||||
|
p_data.original_offset = addr_node.Scalar();
|
||||||
p_data.original_value = value_node.Scalar();
|
p_data.original_value = value_node.Scalar();
|
||||||
|
|
||||||
const bool is_config_value = info.default_config_values.contains(p_data.original_value);
|
const bool is_config_value = info.default_config_values.contains(p_data.original_value);
|
||||||
@ -1191,6 +1195,51 @@ static usz apply_modification(std::basic_string<u32>& applied, patch_engine::pat
|
|||||||
std::memcpy(ptr, p.original_value.data(), p.original_value.size());
|
std::memcpy(ptr, p.original_value.data(), p.original_value.size());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case patch_type::move_file:
|
||||||
|
case patch_type::hide_file:
|
||||||
|
{
|
||||||
|
const bool is_hide = p.type == patch_type::hide_file;
|
||||||
|
std::string original_vfs_path = p.original_offset;
|
||||||
|
std::string dest_vfs_path = p.original_value;
|
||||||
|
|
||||||
|
if (original_vfs_path.empty())
|
||||||
|
{
|
||||||
|
patch_log.error("Failed to patch file: original path is empty", original_vfs_path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_hide && dest_vfs_path.empty())
|
||||||
|
{
|
||||||
|
patch_log.error("Failed to patch file: destination path is empty", dest_vfs_path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!original_vfs_path.starts_with("/dev_"))
|
||||||
|
{
|
||||||
|
original_vfs_path.insert(0, "/dev_");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_hide && !dest_vfs_path.starts_with("/dev_"))
|
||||||
|
{
|
||||||
|
dest_vfs_path.insert(0, "/dev_");
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string dest_path = is_hide ? fs::get_config_dir() + "delete_this_dir.../delete_this..." : vfs::get(dest_vfs_path);
|
||||||
|
|
||||||
|
if (dest_path.empty())
|
||||||
|
{
|
||||||
|
patch_log.error("Failed to patch file path at '%s': destination is not mounted", original_vfs_path, dest_vfs_path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!vfs::mount(original_vfs_path, dest_path))
|
||||||
|
{
|
||||||
|
patch_log.error("Failed to patch file path at '%s': vfs::mount(dest='%s') failed", original_vfs_path, dest_vfs_path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Possibly an executable instruction
|
// Possibly an executable instruction
|
||||||
|
@ -52,8 +52,15 @@ enum class patch_type
|
|||||||
bef32,
|
bef32,
|
||||||
bef64,
|
bef64,
|
||||||
utf8, // Text of string (not null-terminated automatically)
|
utf8, // Text of string (not null-terminated automatically)
|
||||||
|
move_file, // Move file
|
||||||
|
hide_file, // Hide file
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static constexpr bool patch_type_uses_hex_offset(patch_type type)
|
||||||
|
{
|
||||||
|
return type >= patch_type::alloc && type <= patch_type::utf8;
|
||||||
|
}
|
||||||
|
|
||||||
enum class patch_configurable_type
|
enum class patch_configurable_type
|
||||||
{
|
{
|
||||||
double_range,
|
double_range,
|
||||||
@ -69,6 +76,7 @@ public:
|
|||||||
{
|
{
|
||||||
patch_type type = patch_type::load;
|
patch_type type = patch_type::load;
|
||||||
u32 offset = 0;
|
u32 offset = 0;
|
||||||
|
std::string original_offset{}; // Used for specifying paths
|
||||||
std::string original_value{}; // Used for import consistency (avoid rounding etc.)
|
std::string original_value{}; // Used for import consistency (avoid rounding etc.)
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user