Added applying of IPS and IPS32 patches
This commit is contained in:
parent
7316be0bc2
commit
9e8523470d
@ -12,4 +12,6 @@ namespace hex {
|
||||
std::vector<u8> generateIPSPatch(const Patches &patches);
|
||||
std::vector<u8> generateIPS32Patch(const Patches &patches);
|
||||
|
||||
Patches loadIPSPatch(const std::vector<u8> &ipsPatch);
|
||||
Patches loadIPS32Patch(const std::vector<u8> &ipsPatch);
|
||||
}
|
@ -99,6 +99,8 @@ namespace hex {
|
||||
throw std::invalid_argument("Invalid value size!");
|
||||
}
|
||||
|
||||
std::vector<u8> readFile(std::string_view path);
|
||||
|
||||
class ScopeExit {
|
||||
public:
|
||||
ScopeExit(std::function<void()> func) : m_func(func) {}
|
||||
|
@ -20,7 +20,7 @@ namespace hex {
|
||||
buffer.resize(buffer.size() + sizeof(T));
|
||||
std::memcpy((&buffer.back() - sizeof(T)) + 1, &bytes, sizeof(T));
|
||||
}
|
||||
|
||||
|
||||
std::vector<u8> generateIPSPatch(const Patches &patches) {
|
||||
std::vector<u8> result;
|
||||
|
||||
@ -113,4 +113,106 @@ namespace hex {
|
||||
return result;
|
||||
}
|
||||
|
||||
Patches loadIPSPatch(const std::vector<u8> &ipsPatch) {
|
||||
if (ipsPatch.size() < (5 + 3))
|
||||
return { };
|
||||
|
||||
if (std::memcmp(ipsPatch.data(), "PATCH", 5) != 0)
|
||||
return { };
|
||||
|
||||
Patches result;
|
||||
bool foundEOF = false;
|
||||
|
||||
u32 ipsOffset = 5;
|
||||
while (ipsOffset < ipsPatch.size() - (5 + 3)) {
|
||||
u32 offset = ipsPatch[ipsOffset + 2] | (ipsPatch[ipsOffset + 1] << 8) | (ipsPatch[ipsOffset + 0] << 16);
|
||||
u16 size = ipsPatch[ipsOffset + 4] | (ipsPatch[ipsOffset + 3] << 8);
|
||||
|
||||
ipsOffset += 5;
|
||||
|
||||
// Handle normal record
|
||||
if (size > 0x0000) {
|
||||
if (ipsOffset + size > ipsPatch.size() - 3)
|
||||
return { };
|
||||
|
||||
for (u16 i = 0; i < size; i++)
|
||||
result[offset + i] = ipsPatch[ipsOffset + i];
|
||||
ipsOffset += size;
|
||||
}
|
||||
// Handle RLE record
|
||||
else {
|
||||
if (ipsOffset + 3 > ipsPatch.size() - 3)
|
||||
return { };
|
||||
|
||||
u16 rleSize = ipsPatch[ipsOffset + 0] | (ipsPatch[ipsOffset + 1] << 8);
|
||||
|
||||
ipsOffset += 2;
|
||||
|
||||
for (u16 i = 0; i < rleSize; i++)
|
||||
result[offset + i] = ipsPatch[ipsOffset + 0];
|
||||
|
||||
ipsOffset += 1;
|
||||
}
|
||||
|
||||
if (std::memcmp(ipsPatch.data(), "EOF", 3))
|
||||
foundEOF = true;
|
||||
}
|
||||
|
||||
if (foundEOF)
|
||||
return result;
|
||||
else
|
||||
return { };
|
||||
}
|
||||
|
||||
Patches loadIPS32Patch(const std::vector<u8> &ipsPatch) {
|
||||
if (ipsPatch.size() < (5 + 4))
|
||||
return { };
|
||||
|
||||
if (std::memcmp(ipsPatch.data(), "IPS32", 5) != 0)
|
||||
return { };
|
||||
|
||||
Patches result;
|
||||
bool foundEEOF = false;
|
||||
|
||||
u32 ipsOffset = 5;
|
||||
while (ipsOffset < ipsPatch.size() - (5 + 4)) {
|
||||
u32 offset = ipsPatch[ipsOffset + 3] | (ipsPatch[ipsOffset + 2] << 8) | (ipsPatch[ipsOffset + 1] << 16) | (ipsPatch[ipsOffset + 0] << 24);
|
||||
u16 size = ipsPatch[ipsOffset + 5] | (ipsPatch[ipsOffset + 4] << 8);
|
||||
|
||||
ipsOffset += 6;
|
||||
|
||||
// Handle normal record
|
||||
if (size > 0x0000) {
|
||||
if (ipsOffset + size > ipsPatch.size() - 3)
|
||||
return { };
|
||||
|
||||
for (u16 i = 0; i < size; i++)
|
||||
result[offset + i] = ipsPatch[ipsOffset + i];
|
||||
ipsOffset += size;
|
||||
}
|
||||
// Handle RLE record
|
||||
else {
|
||||
if (ipsOffset + 3 > ipsPatch.size() - 3)
|
||||
return { };
|
||||
|
||||
u16 rleSize = ipsPatch[ipsOffset + 0] | (ipsPatch[ipsOffset + 1] << 8);
|
||||
|
||||
ipsOffset += 2;
|
||||
|
||||
for (u16 i = 0; i < rleSize; i++)
|
||||
result[offset + i] = ipsPatch[ipsOffset + 0];
|
||||
|
||||
ipsOffset += 1;
|
||||
}
|
||||
|
||||
if (std::memcmp(ipsPatch.data(), "EEOF", 4))
|
||||
foundEEOF = true;
|
||||
}
|
||||
|
||||
if (foundEEOF)
|
||||
return result;
|
||||
else
|
||||
return { };
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
#include "helpers/utils.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
#include <codecvt>
|
||||
#include <locale>
|
||||
|
||||
@ -73,4 +74,20 @@ namespace hex {
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<u8> readFile(std::string_view path) {
|
||||
FILE *file = fopen(path.data(), "rb");
|
||||
|
||||
if (file == nullptr) return { };
|
||||
|
||||
std::vector<u8> result;
|
||||
|
||||
fseek(file, 0, SEEK_END);
|
||||
result.resize(ftell(file));
|
||||
rewind(file);
|
||||
|
||||
fread(result.data(), 1, result.size(), file);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@ -142,6 +142,24 @@ namespace hex {
|
||||
this->saveToFile(this->m_fileBrowser.selected_path, this->m_dataToSave);
|
||||
}
|
||||
|
||||
if (this->m_fileBrowser.showFileDialog("Apply IPS Patch", imgui_addons::ImGuiFileBrowser::DialogMode::OPEN)) {
|
||||
auto patchData = hex::readFile(this->m_fileBrowser.selected_path);
|
||||
auto patch = hex::loadIPSPatch(patchData);
|
||||
|
||||
for (auto &[address, value] : patch) {
|
||||
this->m_dataProvider->write(address, &value, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (this->m_fileBrowser.showFileDialog("Apply IPS32 Patch", imgui_addons::ImGuiFileBrowser::DialogMode::OPEN)) {
|
||||
auto patchData = hex::readFile(this->m_fileBrowser.selected_path);
|
||||
auto patch = hex::loadIPS32Patch(patchData);
|
||||
|
||||
for (auto &[address, value] : patch) {
|
||||
this->m_dataProvider->write(address, &value, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (this->m_fileBrowser.showFileDialog("Save As", imgui_addons::ImGuiFileBrowser::DialogMode::SAVE)) {
|
||||
FILE *file = fopen(this->m_fileBrowser.selected_path.c_str(), "wb");
|
||||
|
||||
@ -187,6 +205,18 @@ namespace hex {
|
||||
View::doLater([]{ ImGui::OpenPopup("Open Base64 File"); });
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::MenuItem("IPS Patch")) {
|
||||
this->getWindowOpenState() = true;
|
||||
View::doLater([]{ ImGui::OpenPopup("Apply IPS Patch"); });
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("IPS32 Patch")) {
|
||||
this->getWindowOpenState() = true;
|
||||
View::doLater([]{ ImGui::OpenPopup("Apply IPS32 Patch"); });
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user