From 0d01f0c9d7cedcd401da2072991bc654c2981626 Mon Sep 17 00:00:00 2001 From: WerWolv Date: Thu, 2 Feb 2023 14:13:37 +0100 Subject: [PATCH] feat: Added function to import patches from a modified file --- plugins/builtin/romfs/lang/en_US.json | 1 + .../source/content/main_menu_items.cpp | 74 ++++++++++++++----- 2 files changed, 58 insertions(+), 17 deletions(-) diff --git a/plugins/builtin/romfs/lang/en_US.json b/plugins/builtin/romfs/lang/en_US.json index d9397ec00..76c4114ae 100644 --- a/plugins/builtin/romfs/lang/en_US.json +++ b/plugins/builtin/romfs/lang/en_US.json @@ -154,6 +154,7 @@ "hex.builtin.menu.file.import.base64.popup.open_error": "Failed to open file!", "hex.builtin.menu.file.import.ips": "IPS Patch", "hex.builtin.menu.file.import.ips32": "IPS32 Patch", + "hex.builtin.menu.file.import.modified_file": "Modified File", "hex.builtin.menu.file.open_file": "Open File...", "hex.builtin.menu.file.open_other": "Open Other...", "hex.builtin.menu.file.open_project": "Open Project...", diff --git a/plugins/builtin/source/content/main_menu_items.cpp b/plugins/builtin/source/content/main_menu_items.cpp index 8ad895521..100e28ab7 100644 --- a/plugins/builtin/source/content/main_menu_items.cpp +++ b/plugins/builtin/source/content/main_menu_items.cpp @@ -18,23 +18,25 @@ namespace hex::plugin::builtin { static bool g_demoWindowOpen = false; void handleIPSError(IPSError error) { - switch (error) { - case IPSError::InvalidPatchHeader: - View::showErrorPopup("hex.builtin.menu.file.export.ips.popup.invalid_patch_header_error"_lang); - break; - case IPSError::AddressOutOfRange: - View::showErrorPopup("hex.builtin.menu.file.export.ips.popup.address_out_of_range_error"_lang); - break; - case IPSError::PatchTooLarge: - View::showErrorPopup("hex.builtin.menu.file.export.ips.popup.patch_too_large_error"_lang); - break; - case IPSError::InvalidPatchFormat: - View::showErrorPopup("hex.builtin.menu.file.export.ips.popup.invalid_patch_format_error"_lang); - break; - case IPSError::MissingEOF: - View::showErrorPopup("hex.builtin.menu.file.export.ips.popup.missing_eof_error"_lang); - break; - } + TaskManager::doLater([error]{ + switch (error) { + case IPSError::InvalidPatchHeader: + View::showErrorPopup("hex.builtin.menu.file.export.ips.popup.invalid_patch_header_error"_lang); + break; + case IPSError::AddressOutOfRange: + View::showErrorPopup("hex.builtin.menu.file.export.ips.popup.address_out_of_range_error"_lang); + break; + case IPSError::PatchTooLarge: + View::showErrorPopup("hex.builtin.menu.file.export.ips.popup.patch_too_large_error"_lang); + break; + case IPSError::InvalidPatchFormat: + View::showErrorPopup("hex.builtin.menu.file.export.ips.popup.invalid_patch_format_error"_lang); + break; + case IPSError::MissingEOF: + View::showErrorPopup("hex.builtin.menu.file.export.ips.popup.missing_eof_error"_lang); + break; + } + }); } static void createFileMenu() { @@ -204,6 +206,44 @@ namespace hex::plugin::builtin { }); } + ImGui::Separator(); + + if (ImGui::MenuItem("hex.builtin.menu.file.import.modified_file"_lang, nullptr, false)) { + fs::openFileBrowser(fs::DialogMode::Open, {}, [](const auto &path) { + TaskManager::createTask("hex.builtin.common.processing", TaskManager::NoProgress, [path](auto &task) { + auto provider = ImHexApi::Provider::get(); + auto patchData = fs::File(path, fs::File::Mode::Read).readBytes(); + + if (patchData.size() != provider->getActualSize()) { + View::showErrorPopup("hex.builtin.menu.file.import.modified_file.popup.invalid_size"_lang); + return; + } + + const auto baseAddress = provider->getBaseAddress(); + + std::map patches; + for (u64 i = 0; i < patchData.size(); i++) { + u8 value = 0; + provider->read(baseAddress + i, &value, 1); + + if (value != patchData[i]) + patches[baseAddress + i] = patchData[i]; + } + + task.setMaxValue(patches.size()); + + u64 progress = 0; + for (auto &[address, value] : patches) { + provider->addPatch(address, &value, 1); + progress++; + task.update(progress); + } + + provider->createUndoPoint(); + }); + }); + } + ImGui::EndMenu(); }