diff --git a/src/AddressTranslator.cc b/src/AddressTranslator.cc index d86b998e..72737991 100644 --- a/src/AddressTranslator.cc +++ b/src/AddressTranslator.cc @@ -661,3 +661,46 @@ vector diff_dol_files(const string& a_filename, const string& b_filen } return ret; } + +vector diff_xbe_files(const string& a_filename, const string& b_filename) { + ResourceDASM::XBEFile a(a_filename.c_str()); + ResourceDASM::XBEFile b(b_filename.c_str()); + auto a_mem = make_shared(); + auto b_mem = make_shared(); + a.load_into(a_mem); + b.load_into(b_mem); + + uint32_t min_addr = 0xFFFFFFFF; + uint32_t max_addr = 0x00000000; + for (const auto& sec : a.sections) { + min_addr = min(min_addr, sec.addr); + max_addr = max(max_addr, sec.addr + sec.size); + } + for (const auto& sec : b.sections) { + min_addr = min(min_addr, sec.addr); + max_addr = max(max_addr, sec.addr + sec.size); + } + + vector ret; + for (uint32_t addr = min_addr; addr < max_addr; addr++) { + bool a_exists = a_mem->exists(addr, 1); + bool b_exists = b_mem->exists(addr, 1); + if (a_exists && b_exists) { + uint8_t a_value = a_mem->read_u8(addr); + uint8_t b_value = b_mem->read_u8(addr); + if (a_value != b_value) { + if (!ret.empty() && (ret.back().address + ret.back().b_data.size() == addr)) { + auto& entry = ret.back(); + entry.a_data.push_back(a_value); + entry.b_data.push_back(b_value); + } else { + auto& entry = ret.emplace_back(); + entry.address = addr; + entry.a_data.push_back(a_value); + entry.b_data.push_back(b_value); + } + } + } + } + return ret; +} diff --git a/src/AddressTranslator.hh b/src/AddressTranslator.hh index a9e5140e..0b7be0b7 100644 --- a/src/AddressTranslator.hh +++ b/src/AddressTranslator.hh @@ -14,3 +14,4 @@ struct DiffEntry { void run_address_translator(const std::string& directory, const std::string& use_filename, const std::string& command); std::vector diff_dol_files(const std::string& a_filename, const std::string& b_filename); +std::vector diff_xbe_files(const std::string& a_filename, const std::string& b_filename); diff --git a/src/Main.cc b/src/Main.cc index 2660d0b0..2e8b58e8 100644 --- a/src/Main.cc +++ b/src/Main.cc @@ -2868,12 +2868,23 @@ Action a_address_translator( run_address_translator(dir, args.get(2, false), args.get(3, false)); }); -Action a_diff_dol_files( - "diff-dol-files", nullptr, +[](phosg::Arguments& args) { +Action a_diff_executables( + "diff-executables", nullptr, +[](phosg::Arguments& args) { const string& a_filename = args.get(1); const string& b_filename = args.get(2); bool show_pre = args.get("show-pre"); - auto result = diff_dol_files(a_filename, b_filename); + bool a_is_dol = phosg::ends_with(a_filename, ".dol"); + bool b_is_dol = phosg::ends_with(b_filename, ".dol"); + bool a_is_xbe = phosg::ends_with(a_filename, ".xbe"); + bool b_is_xbe = phosg::ends_with(b_filename, ".xbe"); + std::vector result; + if (a_is_dol && b_is_dol) { + result = diff_dol_files(a_filename, b_filename); + } else if (a_is_xbe && b_is_xbe) { + result = diff_xbe_files(a_filename, b_filename); + } else { + throw runtime_error("the two files are not the same type of executable, or are neither dol nor xbe"); + } for (const auto& it : result) { string b_str = phosg::format_data_string(it.b_data, nullptr, phosg::FormatDataFlags::HEX_ONLY); if (show_pre) {