patch manager: move title + serials to patch level

Also bump patch file version to 1.1
This commit is contained in:
Megamouse 2020-06-19 13:46:56 +02:00
parent cc5c89539b
commit 2323cd2a2d
3 changed files with 88 additions and 95 deletions

View File

@ -4,7 +4,7 @@
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";
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
auto& title_info = patches_map[main_key];
title_info.hash = main_key;
title_info.is_legacy = true;
title_info.patch_info_map["legacy"] = info;
auto& container = patches_map[main_key];
container.hash = main_key;
container.is_legacy = true;
container.patch_info_map["legacy"] = info;
continue;
}
@ -183,19 +183,6 @@ bool patch_engine::load(patch_map& patches_map, const std::string& path, bool im
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 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
auto& title_info = patches_map[main_key];
title_info.is_legacy = false;
title_info.hash = main_key;
title_info.title = title;
title_info.serials = serials;
title_info.version = version;
auto& container = patches_map[main_key];
container.is_legacy = false;
container.hash = main_key;
container.version = version;
// Go through each patch
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.hash = main_key;
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"])
{
@ -265,7 +258,7 @@ bool patch_engine::load(patch_map& patches_map, const std::string& path, bool im
}
// 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;
const auto& title_info = m_map.at(name);
const auto& container = m_map.at(name);
// 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)
{
@ -579,7 +572,7 @@ std::size_t patch_engine::apply_patch(const std::string& name, u8* dst, u32 file
++applied;
}
if (title_info.is_legacy)
if (container.is_legacy)
{
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
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;
}
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;
}
@ -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)
{
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())
{
existing_patches[hash] = new_title_info;
existing_patches[hash] = new_container;
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;
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)
for (const auto& [description, new_info] : new_container.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;
}
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)
{
@ -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.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.notes.empty()) info.notes = new_info.notes;
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;
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 << 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;
for (auto [description, info] : title_info.patch_info_map)
for (auto [description, info] : container.patch_info_map)
{
out << description;
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.patch_version.empty()) out << "Version" << info.patch_version;
if (!info.notes.empty()) out << "Notes" << info.notes;

View File

@ -43,30 +43,28 @@ public:
// Patch information
std::vector<patch_engine::patch_data> data_list;
std::string description;
std::string title;
std::string serials;
std::string patch_version;
std::string author;
std::string notes;
bool enabled = false;
// Redundant information for accessibility (see patch_title_info)
// Redundant information for accessibility (see patch_container)
std::string hash;
std::string version;
std::string title;
std::string serials;
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::string hash;
std::string version;
std::string title;
std::string serials;
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*/>>;
patch_engine();
@ -78,10 +76,10 @@ public:
// Example entry:
//
// PPU-8007056e52279bea26c15669d1ee08c2df321d00:
// Title: Fancy Game
// Serials: ABCD12345, SUPA13337 v.1.3
// Patches:
// 60fps:
// Title: Fancy Game
// Serials: ABCD12345, SUPA13337 v.1.3
// Author: Batman bin Suparman
// Version: 1.3
// Notes: This is super

View File

@ -120,33 +120,30 @@ void patch_manager_dialog::populate_tree()
{
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
if (title_info.is_legacy)
if (container.is_legacy)
{
continue;
}
QTreeWidgetItem* title_level_item = nullptr;
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);
const QString q_hash = QString::fromStdString(hash);
// 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
if (!title_level_item)
{
@ -158,6 +155,9 @@ void patch_manager_dialog::populate_tree()
}
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
if (!serial_level_item)
{
@ -191,18 +191,25 @@ void patch_manager_dialog::populate_tree()
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);
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()
@ -265,21 +272,19 @@ void patch_manager_dialog::on_item_selected(QTreeWidgetItem *current, QTreeWidge
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
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;
}
// Show shared info if no patch was found
patch_engine::patch_info info{};
info.hash = hash;
info.title = title_info.title;
info.serials = title_info.serials;
info.version = title_info.version;
info.hash = hash;
info.version = container.version;
update_patch_info(info);
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
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];
patch.enabled = enabled;