diff --git a/rpcs3/Emu/SysCalls/Modules.cpp b/rpcs3/Emu/SysCalls/Modules.cpp index fe14360ac4..a781784c06 100644 --- a/rpcs3/Emu/SysCalls/Modules.cpp +++ b/rpcs3/Emu/SysCalls/Modules.cpp @@ -88,7 +88,7 @@ void execute_ppu_func_by_index(PPUThread& CPU, u32 index) auto old_last_syscall = CPU.m_last_syscall; CPU.m_last_syscall = func->id; - if (!(index & EIF_DONT_SAVE_RTOC)) + if (index & EIF_SAVE_RTOC) { // save RTOC if necessary vm::write64(vm::cast(CPU.GPR[1] + 0x28), CPU.GPR[2]); @@ -109,6 +109,12 @@ void execute_ppu_func_by_index(PPUThread& CPU, u32 index) CPU.GPR[3] = 0; } + if (index & EIF_PERFORM_BLR) + { + // return if necessary + CPU.SetBranch(vm::cast(CPU.LR & ~3), true); + } + CPU.m_last_syscall = old_last_syscall; } else @@ -219,9 +225,7 @@ void hook_ppu_funcs(u32* base, u32 size) { LOG_NOTICE(LOADER, "Function '%s' hooked (addr=0x%x)", g_ppu_func_subs[j].name, vm::get_addr(base + i * 4)); g_ppu_func_subs[j].found++; - base[i + 0] = re32(0x04000000 | g_ppu_func_subs[j].index | EIF_DONT_SAVE_RTOC); // hack - base[i + 1] = se32(0x4e800020); // blr - i += 1; // skip modified code + base[i] = re32(0x04000000 | g_ppu_func_subs[j].index | EIF_PERFORM_BLR); // hack } } } diff --git a/rpcs3/Emu/SysCalls/Modules.h b/rpcs3/Emu/SysCalls/Modules.h index 3167cfa09f..c013bae9f1 100644 --- a/rpcs3/Emu/SysCalls/Modules.h +++ b/rpcs3/Emu/SysCalls/Modules.h @@ -15,9 +15,10 @@ enum : u32 // flags passed with index enum : u32 { - EIF_DONT_SAVE_RTOC = (1 << 25), // don't save RTOC before calling + EIF_SAVE_RTOC = (1 << 25), // save RTOC in [SP+0x28] before calling HLE/LLE function + EIF_PERFORM_BLR = (1 << 24), // do BLR after calling HLE/LLE function - EIF_FLAGS = 0x2000000, // all flags + EIF_FLAGS = 0x3000000, // all flags }; struct ModuleFunc diff --git a/rpcs3/Loader/ELF32.cpp b/rpcs3/Loader/ELF32.cpp index 9ea6b2b090..a6885f93ce 100644 --- a/rpcs3/Loader/ELF32.cpp +++ b/rpcs3/Loader/ELF32.cpp @@ -249,7 +249,7 @@ namespace loader index = add_psv_func(psv_func(nid, 0, nullptr, "UNKNOWN", nullptr)); } - vm::psv::write32(addr + 0, 0xe0700090 | (index & 0xfff0) << 4 | (index & 0xf)); // HACK instruction (ARM) + vm::psv::write32(addr, 0xe0700090 | (index & 0xfff0) << 4 | (index & 0xf)); // HACK instruction (ARM) code_end = std::min(addr, code_end); } diff --git a/rpcs3/Loader/ELF64.cpp b/rpcs3/Loader/ELF64.cpp index 7a5fd2ff88..3e3942b62b 100644 --- a/rpcs3/Loader/ELF64.cpp +++ b/rpcs3/Loader/ELF64.cpp @@ -417,14 +417,13 @@ namespace loader { u32 i_addr = 0; - if (!vm::check_addr(addr, 8) || !vm::check_addr(i_addr = vm::read32(addr), 8)) + if (!vm::check_addr(addr, 8) || !vm::check_addr(i_addr = vm::read32(addr), 4)) { - LOG_ERROR(LOADER, "Failed to inject code for function '%s' (opd=0x%x, 0x%x)", SysCalls::GetHLEFuncName(nid), addr, i_addr); + LOG_ERROR(LOADER, "Failed to inject code for exported function '%s' (opd=0x%x, 0x%x)", SysCalls::GetHLEFuncName(nid), addr, i_addr); } else { - vm::write32(i_addr + 0, HACK(index | EIF_DONT_SAVE_RTOC)); - vm::write32(i_addr + 4, BLR()); + vm::write32(i_addr, HACK(index | EIF_PERFORM_BLR)); } } } @@ -450,14 +449,13 @@ namespace loader LOG_NOTICE(LOADER, "Imported function '%s' (0x%x)", SysCalls::GetHLEFuncName(nid), addr); } - if (!vm::check_addr(addr, 8)) + if (!vm::check_addr(addr, 4)) { LOG_ERROR(LOADER, "Failed to inject code for function '%s' (0x%x)", SysCalls::GetHLEFuncName(nid), addr); } else { - vm::write32(addr + 0, HACK(index)); - vm::write32(addr + 4, BLR()); + vm::write32(addr, HACK(index | EIF_SAVE_RTOC | EIF_PERFORM_BLR)); } } } @@ -671,8 +669,7 @@ namespace loader LOG_NOTICE(LOADER, "Imported %sfunction '%s' in '%s' module (0x%x)", func->lle_func ? "LLE " : "", SysCalls::GetHLEFuncName(nid), module_name, addr); } - vm::write32(addr + 0, HACK(index)); - vm::write32(addr + 4, BLR()); + vm::write32(addr, HACK(index | EIF_SAVE_RTOC | EIF_PERFORM_BLR)); //if (!func || !func->lle_func) //{