2020-06-02 08:39:24 +00:00
|
|
|
|
#pragma once
|
2017-03-28 23:54:05 +00:00
|
|
|
|
|
|
|
|
|
#include "BEType.h"
|
|
|
|
|
#include <vector>
|
|
|
|
|
#include <string>
|
|
|
|
|
#include <unordered_map>
|
|
|
|
|
|
2020-06-02 08:39:24 +00:00
|
|
|
|
#include "util/yaml.hpp"
|
|
|
|
|
|
2017-03-28 23:54:05 +00:00
|
|
|
|
enum class patch_type
|
|
|
|
|
{
|
2020-06-13 00:16:28 +00:00
|
|
|
|
invalid,
|
2017-09-17 14:33:59 +00:00
|
|
|
|
load,
|
2017-03-28 23:54:05 +00:00
|
|
|
|
byte,
|
|
|
|
|
le16,
|
|
|
|
|
le32,
|
|
|
|
|
le64,
|
2017-07-17 13:34:04 +00:00
|
|
|
|
lef32,
|
|
|
|
|
lef64,
|
2017-03-28 23:54:05 +00:00
|
|
|
|
be16,
|
|
|
|
|
be32,
|
|
|
|
|
be64,
|
2017-07-17 13:34:04 +00:00
|
|
|
|
bef32,
|
|
|
|
|
bef64,
|
2017-03-28 23:54:05 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class patch_engine
|
|
|
|
|
{
|
2020-06-02 08:39:24 +00:00
|
|
|
|
public:
|
|
|
|
|
struct patch_data
|
2017-03-28 23:54:05 +00:00
|
|
|
|
{
|
2020-06-02 08:39:24 +00:00
|
|
|
|
patch_type type = patch_type::load;
|
|
|
|
|
u32 offset = 0;
|
2020-06-19 12:04:39 +00:00
|
|
|
|
std::string original_value; // Used for import consistency (avoid rounding etc.)
|
2020-06-12 19:09:08 +00:00
|
|
|
|
union
|
|
|
|
|
{
|
|
|
|
|
u64 long_value;
|
|
|
|
|
f64 double_value;
|
|
|
|
|
} value { 0 };
|
2017-03-28 23:54:05 +00:00
|
|
|
|
};
|
|
|
|
|
|
2020-06-02 08:39:24 +00:00
|
|
|
|
struct patch_info
|
|
|
|
|
{
|
|
|
|
|
// Patch information
|
|
|
|
|
std::vector<patch_engine::patch_data> data_list;
|
|
|
|
|
std::string description;
|
2020-06-19 11:46:56 +00:00
|
|
|
|
std::string title;
|
|
|
|
|
std::string serials;
|
2020-06-02 08:39:24 +00:00
|
|
|
|
std::string patch_version;
|
|
|
|
|
std::string author;
|
|
|
|
|
std::string notes;
|
2020-06-19 14:13:36 +00:00
|
|
|
|
std::string source_path;
|
2020-06-02 08:39:24 +00:00
|
|
|
|
bool enabled = false;
|
2017-03-28 23:54:05 +00:00
|
|
|
|
|
2020-06-19 11:46:56 +00:00
|
|
|
|
// Redundant information for accessibility (see patch_container)
|
2020-06-02 08:39:24 +00:00
|
|
|
|
std::string hash;
|
|
|
|
|
std::string version;
|
|
|
|
|
bool is_legacy = false;
|
|
|
|
|
};
|
|
|
|
|
|
2020-06-19 11:46:56 +00:00
|
|
|
|
struct patch_container
|
2020-06-02 08:39:24 +00:00
|
|
|
|
{
|
|
|
|
|
std::unordered_map<std::string /*description*/, patch_engine::patch_info> patch_info_map;
|
|
|
|
|
std::string hash;
|
|
|
|
|
std::string version;
|
|
|
|
|
bool is_legacy = false;
|
|
|
|
|
};
|
|
|
|
|
|
2020-06-19 11:46:56 +00:00
|
|
|
|
using patch_map = std::unordered_map<std::string /*hash*/, patch_container>;
|
2020-06-02 08:39:24 +00:00
|
|
|
|
using patch_config_map = std::unordered_map<std::string /*hash*/, std::unordered_map<std::string /*description*/, bool /*enabled*/>>;
|
|
|
|
|
|
|
|
|
|
patch_engine();
|
|
|
|
|
|
|
|
|
|
// Returns the directory in which patch_config.yml is located
|
|
|
|
|
static std::string get_patch_config_path();
|
|
|
|
|
|
2020-06-19 17:47:51 +00:00
|
|
|
|
// Returns the filepath for the imported_patch.yml
|
|
|
|
|
static std::string get_imported_patch_path();
|
|
|
|
|
|
2020-06-02 08:39:24 +00:00
|
|
|
|
// Load from file and append to specified patches map
|
|
|
|
|
// Example entry:
|
|
|
|
|
//
|
|
|
|
|
// PPU-8007056e52279bea26c15669d1ee08c2df321d00:
|
|
|
|
|
// Patches:
|
|
|
|
|
// 60fps:
|
2020-06-19 12:37:49 +00:00
|
|
|
|
// Game Title: Fancy Game
|
2020-06-19 11:46:56 +00:00
|
|
|
|
// Serials: ABCD12345, SUPA13337 v.1.3
|
2020-06-02 08:39:24 +00:00
|
|
|
|
// Author: Batman bin Suparman
|
|
|
|
|
// Notes: This is super
|
2020-06-19 12:37:49 +00:00
|
|
|
|
// Patch Version: 1.3
|
2020-06-02 08:39:24 +00:00
|
|
|
|
// Patch:
|
|
|
|
|
// - [ be32, 0x000e522c, 0x995d0072 ]
|
|
|
|
|
// - [ be32, 0x000e5234, 0x995d0074 ]
|
2020-06-12 19:09:08 +00:00
|
|
|
|
static bool load(patch_map& patches, const std::string& path, bool importing = false, std::stringstream* log_messages = nullptr);
|
2020-06-02 08:39:24 +00:00
|
|
|
|
|
|
|
|
|
// Read and add a patch node to the patch info
|
2020-06-12 19:09:08 +00:00
|
|
|
|
static bool read_patch_node(patch_info& info, YAML::Node node, const YAML::Node& root, std::stringstream* log_messages = nullptr);
|
2020-06-02 08:39:24 +00:00
|
|
|
|
|
|
|
|
|
// Get the patch type of a patch node
|
|
|
|
|
static patch_type get_patch_type(YAML::Node node);
|
|
|
|
|
|
|
|
|
|
// Add the data of a patch node
|
2020-06-12 19:09:08 +00:00
|
|
|
|
static bool add_patch_data(YAML::Node node, patch_info& info, u32 modifier, const YAML::Node& root, std::stringstream* log_messages = nullptr);
|
2020-06-02 08:39:24 +00:00
|
|
|
|
|
|
|
|
|
// Save to patch_config.yml
|
2020-06-11 13:12:44 +00:00
|
|
|
|
static void save_config(const patch_map& patches_map, bool enable_legacy_patches);
|
2020-06-02 08:39:24 +00:00
|
|
|
|
|
2020-06-12 19:09:08 +00:00
|
|
|
|
// Save a patch file
|
2020-06-19 13:38:51 +00:00
|
|
|
|
static bool save_patches(const patch_map& patches, const std::string& path, std::stringstream* log_messages = nullptr);
|
2020-06-12 19:09:08 +00:00
|
|
|
|
|
|
|
|
|
// Create or append patches to a file
|
2020-06-19 19:48:59 +00:00
|
|
|
|
static bool import_patches(const patch_map& patches, const std::string& path, size_t& count, size_t& total, std::stringstream* log_messages = nullptr);
|
2020-06-12 19:09:08 +00:00
|
|
|
|
|
2020-06-19 17:47:51 +00:00
|
|
|
|
// Remove a patch from a file
|
|
|
|
|
static bool remove_patch(const patch_info& info);
|
|
|
|
|
|
2020-06-02 08:39:24 +00:00
|
|
|
|
// Load patch_config.yml
|
2020-06-11 13:12:44 +00:00
|
|
|
|
static patch_config_map load_config(bool& enable_legacy_patches);
|
2020-06-02 08:39:24 +00:00
|
|
|
|
|
|
|
|
|
// Load from file and append to member patches map
|
|
|
|
|
void append_global_patches();
|
|
|
|
|
|
|
|
|
|
// Load from title relevant files and append to member patches map
|
|
|
|
|
void append_title_patches(const std::string& title_id);
|
2017-03-28 23:54:05 +00:00
|
|
|
|
|
2017-07-17 13:34:04 +00:00
|
|
|
|
// Apply patch (returns the number of entries applied)
|
|
|
|
|
std::size_t apply(const std::string& name, u8* dst) const;
|
2020-06-02 08:39:24 +00:00
|
|
|
|
|
2020-01-07 09:10:23 +00:00
|
|
|
|
// Apply patch with a check that the address exists in SPU local storage
|
2020-06-02 08:39:24 +00:00
|
|
|
|
std::size_t apply_with_ls_check(const std::string& name, u8* dst, u32 filesz, u32 ls_addr) const;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
// Load from file and append to member patches map
|
|
|
|
|
void append(const std::string& path);
|
|
|
|
|
|
|
|
|
|
// Internal: Apply patch (returns the number of entries applied)
|
|
|
|
|
template <bool check_local_storage>
|
|
|
|
|
std::size_t apply_patch(const std::string& name, u8* dst, u32 filesz, u32 ls_addr) const;
|
|
|
|
|
|
|
|
|
|
// Database
|
|
|
|
|
patch_map m_map;
|
2017-03-28 23:54:05 +00:00
|
|
|
|
};
|