mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 02:32:36 +01:00
patch manager: move title + serials to patch level
Also bump patch file version to 1.1
This commit is contained in:
parent
cc5c89539b
commit
2323cd2a2d
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
LOG_CHANNEL(patch_log);
|
LOG_CHANNEL(patch_log);
|
||||||
|
|
||||||
static const std::string patch_engine_version = "1.0";
|
static const std::string patch_engine_version = "1.1";
|
||||||
static const std::string yml_key_enable_legacy_patches = "Enable Legacy Patches";
|
static const std::string yml_key_enable_legacy_patches = "Enable Legacy Patches";
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
@ -160,10 +160,10 @@ bool patch_engine::load(patch_map& patches_map, const std::string& path, bool im
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Find or create an entry matching the key/hash in our map
|
// Find or create an entry matching the key/hash in our map
|
||||||
auto& title_info = patches_map[main_key];
|
auto& container = patches_map[main_key];
|
||||||
title_info.hash = main_key;
|
container.hash = main_key;
|
||||||
title_info.is_legacy = true;
|
container.is_legacy = true;
|
||||||
title_info.patch_info_map["legacy"] = info;
|
container.patch_info_map["legacy"] = info;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,19 +183,6 @@ bool patch_engine::load(patch_map& patches_map, const std::string& path, bool im
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string title;
|
|
||||||
std::string serials;
|
|
||||||
|
|
||||||
if (const auto title_node = pair.second["Title"])
|
|
||||||
{
|
|
||||||
title = title_node.Scalar();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (const auto serials_node = pair.second["Serials"])
|
|
||||||
{
|
|
||||||
serials = serials_node.Scalar();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (const auto patches_node = pair.second["Patches"])
|
if (const auto patches_node = pair.second["Patches"])
|
||||||
{
|
{
|
||||||
if (const auto yml_type = patches_node.Type(); yml_type != YAML::NodeType::Map)
|
if (const auto yml_type = patches_node.Type(); yml_type != YAML::NodeType::Map)
|
||||||
@ -207,12 +194,10 @@ bool patch_engine::load(patch_map& patches_map, const std::string& path, bool im
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Find or create an entry matching the key/hash in our map
|
// Find or create an entry matching the key/hash in our map
|
||||||
auto& title_info = patches_map[main_key];
|
auto& container = patches_map[main_key];
|
||||||
title_info.is_legacy = false;
|
container.is_legacy = false;
|
||||||
title_info.hash = main_key;
|
container.hash = main_key;
|
||||||
title_info.title = title;
|
container.version = version;
|
||||||
title_info.serials = serials;
|
|
||||||
title_info.version = version;
|
|
||||||
|
|
||||||
// Go through each patch
|
// Go through each patch
|
||||||
for (auto patches_entry : patches_node)
|
for (auto patches_entry : patches_node)
|
||||||
@ -238,8 +223,16 @@ bool patch_engine::load(patch_map& patches_map, const std::string& path, bool im
|
|||||||
info.description = description;
|
info.description = description;
|
||||||
info.hash = main_key;
|
info.hash = main_key;
|
||||||
info.version = version;
|
info.version = version;
|
||||||
info.serials = serials;
|
|
||||||
info.title = title;
|
if (const auto title_node = patches_entry.second["Title"])
|
||||||
|
{
|
||||||
|
info.title = title_node.Scalar();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const auto serials_node = patches_entry.second["Serials"])
|
||||||
|
{
|
||||||
|
info.serials = serials_node.Scalar();
|
||||||
|
}
|
||||||
|
|
||||||
if (const auto author_node = patches_entry.second["Author"])
|
if (const auto author_node = patches_entry.second["Author"])
|
||||||
{
|
{
|
||||||
@ -265,7 +258,7 @@ bool patch_engine::load(patch_map& patches_map, const std::string& path, bool im
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Insert patch information
|
// Insert patch information
|
||||||
title_info.patch_info_map[description] = info;
|
container.patch_info_map[description] = info;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -482,10 +475,10 @@ std::size_t patch_engine::apply_patch(const std::string& name, u8* dst, u32 file
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t applied_total = 0;
|
size_t applied_total = 0;
|
||||||
const auto& title_info = m_map.at(name);
|
const auto& container = m_map.at(name);
|
||||||
|
|
||||||
// Apply modifications sequentially
|
// Apply modifications sequentially
|
||||||
for (const auto& [description, patch] : title_info.patch_info_map)
|
for (const auto& [description, patch] : container.patch_info_map)
|
||||||
{
|
{
|
||||||
if (!patch.enabled)
|
if (!patch.enabled)
|
||||||
{
|
{
|
||||||
@ -579,7 +572,7 @@ std::size_t patch_engine::apply_patch(const std::string& name, u8* dst, u32 file
|
|||||||
++applied;
|
++applied;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (title_info.is_legacy)
|
if (container.is_legacy)
|
||||||
{
|
{
|
||||||
patch_log.notice("Applied legacy patch (<- %d)", applied);
|
patch_log.notice("Applied legacy patch (<- %d)", applied);
|
||||||
}
|
}
|
||||||
@ -615,14 +608,14 @@ void patch_engine::save_config(const patch_map& patches_map, bool enable_legacy_
|
|||||||
// Save 'enabled' state per hash and description
|
// Save 'enabled' state per hash and description
|
||||||
patch_config_map config_map;
|
patch_config_map config_map;
|
||||||
|
|
||||||
for (const auto& [hash, title_info] : patches_map)
|
for (const auto& [hash, container] : patches_map)
|
||||||
{
|
{
|
||||||
if (title_info.is_legacy)
|
if (container.is_legacy)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& [description, patch] : title_info.patch_info_map)
|
for (const auto& [description, patch] : container.patch_info_map)
|
||||||
{
|
{
|
||||||
config_map[hash][description] = patch.enabled;
|
config_map[hash][description] = patch.enabled;
|
||||||
}
|
}
|
||||||
@ -648,28 +641,25 @@ void patch_engine::save_config(const patch_map& patches_map, bool enable_legacy_
|
|||||||
|
|
||||||
static void append_patches(patch_engine::patch_map& existing_patches, const patch_engine::patch_map& new_patches)
|
static void append_patches(patch_engine::patch_map& existing_patches, const patch_engine::patch_map& new_patches)
|
||||||
{
|
{
|
||||||
for (const auto& [hash, new_title_info] : new_patches)
|
for (const auto& [hash, new_container] : new_patches)
|
||||||
{
|
{
|
||||||
if (existing_patches.find(hash) == existing_patches.end())
|
if (existing_patches.find(hash) == existing_patches.end())
|
||||||
{
|
{
|
||||||
existing_patches[hash] = new_title_info;
|
existing_patches[hash] = new_container;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& title_info = existing_patches[hash];
|
auto& container = existing_patches[hash];
|
||||||
|
|
||||||
if (!new_title_info.title.empty()) title_info.title = new_title_info.title;
|
for (const auto& [description, new_info] : new_container.patch_info_map)
|
||||||
if (!new_title_info.serials.empty()) title_info.serials = new_title_info.serials;
|
|
||||||
|
|
||||||
for (const auto& [description, new_info] : new_title_info.patch_info_map)
|
|
||||||
{
|
{
|
||||||
if (title_info.patch_info_map.find(description) == title_info.patch_info_map.end())
|
if (container.patch_info_map.find(description) == container.patch_info_map.end())
|
||||||
{
|
{
|
||||||
title_info.patch_info_map[description] = new_info;
|
container.patch_info_map[description] = new_info;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& info = title_info.patch_info_map[description];
|
auto& info = container.patch_info_map[description];
|
||||||
|
|
||||||
const auto version_is_bigger = [](const std::string& v0, const std::string& v1, const std::string& hash, const std::string& description)
|
const auto version_is_bigger = [](const std::string& v0, const std::string& v1, const std::string& hash, const std::string& description)
|
||||||
{
|
{
|
||||||
@ -692,6 +682,8 @@ static void append_patches(patch_engine::patch_map& existing_patches, const patc
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!new_info.patch_version.empty()) info.patch_version = new_info.patch_version;
|
if (!new_info.patch_version.empty()) info.patch_version = new_info.patch_version;
|
||||||
|
if (!new_info.title.empty()) info.title = new_info.title;
|
||||||
|
if (!new_info.serials.empty()) info.serials = new_info.serials;
|
||||||
if (!new_info.author.empty()) info.author = new_info.author;
|
if (!new_info.author.empty()) info.author = new_info.author;
|
||||||
if (!new_info.notes.empty()) info.notes = new_info.notes;
|
if (!new_info.notes.empty()) info.notes = new_info.notes;
|
||||||
if (!new_info.data_list.empty()) info.data_list = new_info.data_list;
|
if (!new_info.data_list.empty()) info.data_list = new_info.data_list;
|
||||||
@ -710,23 +702,21 @@ bool patch_engine::save_patches(const patch_map& patches, const std::string& pat
|
|||||||
|
|
||||||
YAML::Emitter out;
|
YAML::Emitter out;
|
||||||
out << YAML::BeginMap;
|
out << YAML::BeginMap;
|
||||||
out << "Version" << "1.0";
|
out << "Version" << patch_engine_version;
|
||||||
|
|
||||||
for (const auto& [hash, title_info] : patches)
|
for (const auto& [hash, container] : patches)
|
||||||
{
|
{
|
||||||
out << YAML::Newline << YAML::Newline;
|
out << YAML::Newline << YAML::Newline;
|
||||||
out << hash << YAML::BeginMap;
|
out << hash << YAML::BeginMap;
|
||||||
|
|
||||||
if (!title_info.title.empty()) out << "Title" << title_info.title;
|
|
||||||
if (!title_info.serials.empty()) out << "Serials" << title_info.serials;
|
|
||||||
|
|
||||||
out << "Patches" << YAML::BeginMap;
|
out << "Patches" << YAML::BeginMap;
|
||||||
|
|
||||||
for (auto [description, info] : title_info.patch_info_map)
|
for (auto [description, info] : container.patch_info_map)
|
||||||
{
|
{
|
||||||
out << description;
|
out << description;
|
||||||
out << YAML::BeginMap;
|
out << YAML::BeginMap;
|
||||||
|
|
||||||
|
if (!info.title.empty()) out << "Title" << info.title;
|
||||||
|
if (!info.serials.empty()) out << "Serials" << info.serials;
|
||||||
if (!info.author.empty()) out << "Author" << info.author;
|
if (!info.author.empty()) out << "Author" << info.author;
|
||||||
if (!info.patch_version.empty()) out << "Version" << info.patch_version;
|
if (!info.patch_version.empty()) out << "Version" << info.patch_version;
|
||||||
if (!info.notes.empty()) out << "Notes" << info.notes;
|
if (!info.notes.empty()) out << "Notes" << info.notes;
|
||||||
|
@ -43,30 +43,28 @@ public:
|
|||||||
// Patch information
|
// Patch information
|
||||||
std::vector<patch_engine::patch_data> data_list;
|
std::vector<patch_engine::patch_data> data_list;
|
||||||
std::string description;
|
std::string description;
|
||||||
|
std::string title;
|
||||||
|
std::string serials;
|
||||||
std::string patch_version;
|
std::string patch_version;
|
||||||
std::string author;
|
std::string author;
|
||||||
std::string notes;
|
std::string notes;
|
||||||
bool enabled = false;
|
bool enabled = false;
|
||||||
|
|
||||||
// Redundant information for accessibility (see patch_title_info)
|
// Redundant information for accessibility (see patch_container)
|
||||||
std::string hash;
|
std::string hash;
|
||||||
std::string version;
|
std::string version;
|
||||||
std::string title;
|
|
||||||
std::string serials;
|
|
||||||
bool is_legacy = false;
|
bool is_legacy = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct patch_title_info
|
struct patch_container
|
||||||
{
|
{
|
||||||
std::unordered_map<std::string /*description*/, patch_engine::patch_info> patch_info_map;
|
std::unordered_map<std::string /*description*/, patch_engine::patch_info> patch_info_map;
|
||||||
std::string hash;
|
std::string hash;
|
||||||
std::string version;
|
std::string version;
|
||||||
std::string title;
|
|
||||||
std::string serials;
|
|
||||||
bool is_legacy = false;
|
bool is_legacy = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
using patch_map = std::unordered_map<std::string /*hash*/, patch_title_info>;
|
using patch_map = std::unordered_map<std::string /*hash*/, patch_container>;
|
||||||
using patch_config_map = std::unordered_map<std::string /*hash*/, std::unordered_map<std::string /*description*/, bool /*enabled*/>>;
|
using patch_config_map = std::unordered_map<std::string /*hash*/, std::unordered_map<std::string /*description*/, bool /*enabled*/>>;
|
||||||
|
|
||||||
patch_engine();
|
patch_engine();
|
||||||
@ -78,10 +76,10 @@ public:
|
|||||||
// Example entry:
|
// Example entry:
|
||||||
//
|
//
|
||||||
// PPU-8007056e52279bea26c15669d1ee08c2df321d00:
|
// PPU-8007056e52279bea26c15669d1ee08c2df321d00:
|
||||||
// Title: Fancy Game
|
|
||||||
// Serials: ABCD12345, SUPA13337 v.1.3
|
|
||||||
// Patches:
|
// Patches:
|
||||||
// 60fps:
|
// 60fps:
|
||||||
|
// Title: Fancy Game
|
||||||
|
// Serials: ABCD12345, SUPA13337 v.1.3
|
||||||
// Author: Batman bin Suparman
|
// Author: Batman bin Suparman
|
||||||
// Version: 1.3
|
// Version: 1.3
|
||||||
// Notes: This is super
|
// Notes: This is super
|
||||||
|
@ -120,33 +120,30 @@ void patch_manager_dialog::populate_tree()
|
|||||||
{
|
{
|
||||||
ui->patch_tree->clear();
|
ui->patch_tree->clear();
|
||||||
|
|
||||||
for (const auto& [hash, title_info] : m_map)
|
for (const auto& [hash, container] : m_map)
|
||||||
{
|
{
|
||||||
// Don't show legacy patches, because you can't configure them anyway
|
// Don't show legacy patches, because you can't configure them anyway
|
||||||
if (title_info.is_legacy)
|
if (container.is_legacy)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
QTreeWidgetItem* title_level_item = nullptr;
|
const QString q_hash = QString::fromStdString(hash);
|
||||||
QTreeWidgetItem* serial_level_item = nullptr;
|
|
||||||
|
|
||||||
const QString q_hash = QString::fromStdString(hash);
|
|
||||||
const QString q_serials = title_info.serials.empty() ? tr("Unknown Version") : QString::fromStdString(title_info.serials);
|
|
||||||
const QString q_title = QString::fromStdString(title_info.title);
|
|
||||||
|
|
||||||
// Find top level item for this title
|
|
||||||
if (const auto list = ui->patch_tree->findItems(q_title, Qt::MatchFlag::MatchExactly, 0); list.size() > 0)
|
|
||||||
{
|
|
||||||
title_level_item = list[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find out if there is a node item for this serial
|
|
||||||
serial_level_item = gui::utils::find_child(title_level_item, q_serials);
|
|
||||||
|
|
||||||
// Add patch items
|
// Add patch items
|
||||||
for (const auto& [description, patch] : title_info.patch_info_map)
|
for (const auto& [description, patch] : container.patch_info_map)
|
||||||
{
|
{
|
||||||
|
const QString q_title = patch.title.empty() ? tr("Unknown Title") : QString::fromStdString(patch.title);
|
||||||
|
const QString q_serials = patch.serials.empty() ? tr("Unknown Version") : QString::fromStdString(patch.serials);
|
||||||
|
|
||||||
|
QTreeWidgetItem* title_level_item = nullptr;
|
||||||
|
|
||||||
|
// Find top level item for this title
|
||||||
|
if (const auto list = ui->patch_tree->findItems(q_title, Qt::MatchFlag::MatchExactly, 0); list.size() > 0)
|
||||||
|
{
|
||||||
|
title_level_item = list[0];
|
||||||
|
}
|
||||||
|
|
||||||
// Add a top level item for this title if it doesn't exist yet
|
// Add a top level item for this title if it doesn't exist yet
|
||||||
if (!title_level_item)
|
if (!title_level_item)
|
||||||
{
|
{
|
||||||
@ -158,6 +155,9 @@ void patch_manager_dialog::populate_tree()
|
|||||||
}
|
}
|
||||||
assert(title_level_item);
|
assert(title_level_item);
|
||||||
|
|
||||||
|
// Find out if there is a node item for this serial
|
||||||
|
QTreeWidgetItem* serial_level_item = gui::utils::find_child(title_level_item, q_serials);
|
||||||
|
|
||||||
// Add a node item for this serial if it doesn't exist yet
|
// Add a node item for this serial if it doesn't exist yet
|
||||||
if (!serial_level_item)
|
if (!serial_level_item)
|
||||||
{
|
{
|
||||||
@ -191,18 +191,25 @@ void patch_manager_dialog::populate_tree()
|
|||||||
|
|
||||||
serial_level_item->addChild(patch_level_item);
|
serial_level_item->addChild(patch_level_item);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (title_level_item)
|
|
||||||
{
|
|
||||||
title_level_item->sortChildren(0, Qt::SortOrder::AscendingOrder);
|
|
||||||
}
|
|
||||||
if (serial_level_item)
|
|
||||||
{
|
|
||||||
serial_level_item->sortChildren(0, Qt::SortOrder::AscendingOrder);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ui->patch_tree->sortByColumn(0, Qt::SortOrder::AscendingOrder);
|
ui->patch_tree->sortByColumn(0, Qt::SortOrder::AscendingOrder);
|
||||||
|
|
||||||
|
for (int i = 0; i < ui->patch_tree->topLevelItemCount(); i++)
|
||||||
|
{
|
||||||
|
if (auto title_level_item = ui->patch_tree->topLevelItem(i))
|
||||||
|
{
|
||||||
|
title_level_item->sortChildren(0, Qt::SortOrder::AscendingOrder);
|
||||||
|
|
||||||
|
for (int i = 0; i < title_level_item->childCount(); i++)
|
||||||
|
{
|
||||||
|
if (auto serial_level_item = title_level_item->child(i))
|
||||||
|
{
|
||||||
|
serial_level_item->sortChildren(0, Qt::SortOrder::AscendingOrder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void patch_manager_dialog::save_config()
|
void patch_manager_dialog::save_config()
|
||||||
@ -265,21 +272,19 @@ void patch_manager_dialog::on_item_selected(QTreeWidgetItem *current, QTreeWidge
|
|||||||
|
|
||||||
if (m_map.find(hash) != m_map.end())
|
if (m_map.find(hash) != m_map.end())
|
||||||
{
|
{
|
||||||
const auto& title_info = m_map.at(hash);
|
const auto& container = m_map.at(hash);
|
||||||
|
|
||||||
// Find the patch for this item and show its metadata
|
// Find the patch for this item and show its metadata
|
||||||
if (!title_info.is_legacy && title_info.patch_info_map.find(description) != title_info.patch_info_map.end())
|
if (!container.is_legacy && container.patch_info_map.find(description) != container.patch_info_map.end())
|
||||||
{
|
{
|
||||||
update_patch_info(title_info.patch_info_map.at(description));
|
update_patch_info(container.patch_info_map.at(description));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show shared info if no patch was found
|
// Show shared info if no patch was found
|
||||||
patch_engine::patch_info info{};
|
patch_engine::patch_info info{};
|
||||||
info.hash = hash;
|
info.hash = hash;
|
||||||
info.title = title_info.title;
|
info.version = container.version;
|
||||||
info.serials = title_info.serials;
|
|
||||||
info.version = title_info.version;
|
|
||||||
update_patch_info(info);
|
update_patch_info(info);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -306,9 +311,9 @@ void patch_manager_dialog::on_item_changed(QTreeWidgetItem *item, int /*column*/
|
|||||||
// Enable/disable the patch for this item and show its metadata
|
// Enable/disable the patch for this item and show its metadata
|
||||||
if (m_map.find(hash) != m_map.end())
|
if (m_map.find(hash) != m_map.end())
|
||||||
{
|
{
|
||||||
auto& title_info = m_map[hash];
|
auto& container = m_map[hash];
|
||||||
|
|
||||||
if (!title_info.is_legacy && title_info.patch_info_map.find(description) != title_info.patch_info_map.end())
|
if (!container.is_legacy && container.patch_info_map.find(description) != container.patch_info_map.end())
|
||||||
{
|
{
|
||||||
auto& patch = m_map[hash].patch_info_map[description];
|
auto& patch = m_map[hash].patch_info_map[description];
|
||||||
patch.enabled = enabled;
|
patch.enabled = enabled;
|
||||||
|
Loading…
Reference in New Issue
Block a user