diff --git a/rpcs3/Emu/Cell/PPUAnalyser.cpp b/rpcs3/Emu/Cell/PPUAnalyser.cpp index 5c0e10b9d5..0d1ff789ac 100644 --- a/rpcs3/Emu/Cell/PPUAnalyser.cpp +++ b/rpcs3/Emu/Cell/PPUAnalyser.cpp @@ -529,7 +529,7 @@ namespace ppu_patterns }; } -void ppu_module::analyse(u32 lib_toc, u32 entry, const u32 sec_end) +void ppu_module::analyse(u32 lib_toc, u32 entry, const u32 sec_end, const std::basic_string& applied) { // Assume first segment is executable const u32 start = segs[0].addr; @@ -1637,6 +1637,16 @@ void ppu_module::analyse(u32 lib_toc, u32 entry, const u32 sec_end) block_queue.emplace_back(exp, lim); } + // Add entries from patches (on per-instruction basis) + for (u32 addr : applied) + { + if (addr % 4 == 0 && addr >= start && addr < segs[0].addr + segs[0].size && !block_set.count(addr)) + { + block_queue.emplace_back(addr, addr + 4); + block_set.emplace(addr); + } + } + // block_queue may grow for (usz i = 0; i < block_queue.size(); i++) { @@ -1693,7 +1703,7 @@ void ppu_module::analyse(u32 lib_toc, u32 entry, const u32 sec_end) const u32 target = (opc & 2 ? 0 : i_pos) + (type == ppu_itype::B ? +ppu_opcode_t{opc}.bt24 : +ppu_opcode_t{opc}.bt14); - if (target < start || target >= end) + if (target < segs[0].addr || target >= segs[0].addr + segs[0].size) { // Sanity check is_good = false; diff --git a/rpcs3/Emu/Cell/PPUAnalyser.h b/rpcs3/Emu/Cell/PPUAnalyser.h index 6e9e1c2473..458d74b79f 100644 --- a/rpcs3/Emu/Cell/PPUAnalyser.h +++ b/rpcs3/Emu/Cell/PPUAnalyser.h @@ -89,7 +89,7 @@ struct ppu_module secs = info.secs; } - void analyse(u32 lib_toc, u32 entry, u32 end = 0); + void analyse(u32 lib_toc, u32 entry, u32 end, const std::basic_string& applied); void validate(u32 reloc); }; diff --git a/rpcs3/Emu/Cell/PPUModule.cpp b/rpcs3/Emu/Cell/PPUModule.cpp index ddcccf4ac0..03866ce38d 100644 --- a/rpcs3/Emu/Cell/PPUModule.cpp +++ b/rpcs3/Emu/Cell/PPUModule.cpp @@ -1101,19 +1101,13 @@ std::shared_ptr ppu_load_prx(const ppu_prx_object& elf, const std::stri applied += g_fxo->get()->apply(Emu.GetTitleID() + '-' + hash, vm::g_base_addr); } - if (!applied.empty()) - { - // TODO (invalidate constraints if patches were applied) - end = 0; - } - // Embedded SPU elf patching for (const auto& seg : prx->segs) { ppu_check_patch_spu_images(seg); } - prx->analyse(toc, 0, end); + prx->analyse(toc, 0, end, applied); ppu_loader.success("PRX library hash: %s (<- %u)", hash, applied.size()); @@ -1558,14 +1552,8 @@ bool ppu_load_exec(const ppu_exec_object& elf) _main->name.clear(); _main->path = vfs::get(Emu.argv[0]); - if (!applied.empty()) - { - // TODO (invalidate constraints if patches were applied) - end = 0; - } - // Analyse executable (TODO) - _main->analyse(0, static_cast(elf.header.e_entry), end); + _main->analyse(0, static_cast(elf.header.e_entry), end, applied); // Validate analyser results (not required) _main->validate(0); @@ -1962,14 +1950,8 @@ std::pair, CellError> ppu_load_overlay(const ppu_ex ovlm->entry = static_cast(elf.header.e_entry); - if (!applied.empty()) - { - // TODO (invalidate constraints if patches were applied) - end = 0; - } - // Analyse executable (TODO) - ovlm->analyse(0, ovlm->entry, end); + ovlm->analyse(0, ovlm->entry, end, applied); // Validate analyser results (not required) ovlm->validate(0);