diff --git a/rpcs3/Emu/Cell/PPUAnalyser.h b/rpcs3/Emu/Cell/PPUAnalyser.h index 6270593245..ef10375577 100644 --- a/rpcs3/Emu/Cell/PPUAnalyser.h +++ b/rpcs3/Emu/Cell/PPUAnalyser.h @@ -68,6 +68,7 @@ struct ppu_segment // PPU Module Information struct ppu_module { + uchar sha1[20]; std::string name; std::string path; std::vector relocs; @@ -78,6 +79,7 @@ struct ppu_module // Copy info without functions void copy_part(const ppu_module& info) { + std::memcpy(sha1, info.sha1, sizeof(sha1)); name = info.name; path = info.path; relocs = info.relocs; diff --git a/rpcs3/Emu/Cell/PPUModule.cpp b/rpcs3/Emu/Cell/PPUModule.cpp index afd57d673e..e68cea53ab 100644 --- a/rpcs3/Emu/Cell/PPUModule.cpp +++ b/rpcs3/Emu/Cell/PPUModule.cpp @@ -717,10 +717,18 @@ std::shared_ptr ppu_load_prx(const ppu_prx_object& elf, const std::stri // Initialize HLE modules ppu_initialize_modules(link); + // Library hash + sha1_context sha; + sha1_starts(&sha); + for (const auto& prog : elf.progs) { LOG_NOTICE(LOADER, "** Segment: p_type=0x%x, p_vaddr=0x%llx, p_filesz=0x%llx, p_memsz=0x%llx, flags=0x%x", prog.p_type, prog.p_vaddr, prog.p_filesz, prog.p_memsz, prog.p_flags); + // Hash big-endian values + sha1_update(&sha, (uchar*)&prog.p_type, sizeof(prog.p_type)); + sha1_update(&sha, (uchar*)&prog.p_flags, sizeof(prog.p_flags)); + switch (const u32 p_type = prog.p_type) { case 0x1: // LOAD @@ -743,6 +751,11 @@ std::shared_ptr ppu_load_prx(const ppu_prx_object& elf, const std::stri std::memcpy(vm::base(addr), prog.bin.data(), file_size); LOG_WARNING(LOADER, "**** Loaded to 0x%x (size=0x%x)", addr, mem_size); + // Hash segment + sha1_update(&sha, (uchar*)&prog.p_vaddr, sizeof(prog.p_vaddr)); + sha1_update(&sha, (uchar*)&prog.p_memsz, sizeof(prog.p_memsz)); + sha1_update(&sha, prog.bin.data(), prog.bin.size()); + // Initialize executable code if necessary if (prog.p_flags & 0x1) { @@ -945,6 +958,28 @@ std::shared_ptr ppu_load_prx(const ppu_prx_object& elf, const std::stri prx->name = path.substr(path.find_last_of('/') + 1); prx->path = path; + sha1_finish(&sha, prx->sha1); + + // Format patch name + std::string hash("PRX-0000000000000000000000000000000000000000"); + for (u32 i = 0; i < 20; i++) + { + constexpr auto pal = "0123456789abcdef"; + hash[4 + i * 2] = pal[prx->sha1[i] >> 4]; + hash[5 + i * 2] = pal[prx->sha1[i] & 15]; + } + + // Apply the patch + auto applied = fxm::check_unlocked()->apply(hash, vm::g_base_addr); + + if (!Emu.GetTitleID().empty()) + { + // Alternative patch + applied += fxm::check_unlocked()->apply(Emu.GetTitleID() + '-' + hash, vm::g_base_addr); + } + + LOG_NOTICE(LOADER, "PRX library hash: %s (<- %u)", hash, applied); + if (Emu.IsReady() && fxm::import([&] { return prx; })) { // Special loading mode @@ -1011,7 +1046,6 @@ void ppu_load_exec(const ppu_exec_object& elf) // Executable hash sha1_context sha; sha1_starts(&sha); - u8 sha1_hash[20]; // Allocate memory at fixed positions for (const auto& prog : elf.progs) @@ -1072,15 +1106,15 @@ void ppu_load_exec(const ppu_exec_object& elf) } } - sha1_finish(&sha, sha1_hash); + sha1_finish(&sha, _main->sha1); // Format patch name std::string hash("PPU-0000000000000000000000000000000000000000"); - for (u32 i = 0; i < sizeof(sha1_hash); i++) + for (u32 i = 0; i < 20; i++) { constexpr auto pal = "0123456789abcdef"; - hash[4 + i * 2] = pal[sha1_hash[i] >> 4]; - hash[5 + i * 2] = pal[sha1_hash[i] & 15]; + hash[4 + i * 2] = pal[_main->sha1[i] >> 4]; + hash[5 + i * 2] = pal[_main->sha1[i] & 15]; } // Apply the patch