From 81ab6ab8b4c1e7c5c7ddccecd6eae9f154d15d3c Mon Sep 17 00:00:00 2001 From: Inviuz Date: Mon, 26 Jun 2017 07:37:28 +0200 Subject: [PATCH] FREFS/weak imports and VREFS 4 and 6 --- rpcs3/Emu/Cell/PPUModule.cpp | 50 ++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/rpcs3/Emu/Cell/PPUModule.cpp b/rpcs3/Emu/Cell/PPUModule.cpp index 854e5bd8b1..55458e5b92 100644 --- a/rpcs3/Emu/Cell/PPUModule.cpp +++ b/rpcs3/Emu/Cell/PPUModule.cpp @@ -112,6 +112,7 @@ struct ppu_linkage_info bool hle = false; u32 export_addr = 0; std::set imports; + std::set weak_imports; }; // FNID -> (export; [imports...]) @@ -341,33 +342,50 @@ static void ppu_initialize_modules(const std::shared_ptr& link } } -// Link variable -static void ppu_patch_variable_refs(u32 vref, u32 vaddr) +// Link variables/weak imports, looks to be literally the same as vrefs +// Don't use bool flag in VREFs, originally it didn't have it +static void ppu_patch_refs(u32 fref, u32 faddr, bool f_import) { - struct vref_t + struct ref_t { be_t type; be_t addr; be_t addend; // Note: Treating it as addend seems to be correct for now, but still unknown if theres more in this variable }; - for (auto ref = vm::ptr::make(vref); ref->type; ref++) + for (auto ref = vm::ptr::make(fref); ref->type; ref++) { - if (ref->addend) LOG_WARNING(LOADER, "**** VREF(%u): Addend value(0x%x, 0x%x)", ref->type, ref->addr, ref->addend); + if (ref->addend) LOG_WARNING(LOADER, "**** REF(%u): Addend value(0x%x, 0x%x)", ref->type, ref->addr, ref->addend); + + const auto ref_import = vm::ptr::make(faddr + ref->addend); + + const auto addr = (f_import ? static_cast(*ref_import) : faddr + ref->addend); // OPs are probably similar to relocations switch (u32 type = ref->type) { case 0x1: { - const u32 value = vm::_ref(ref->addr) = vaddr + ref->addend; - LOG_WARNING(LOADER, "**** VREF(1): 0x%x <- 0x%x", ref->addr, value); + const u32 value = vm::_ref(ref->addr) = addr; + LOG_WARNING(LOADER, "**** REF(1): 0x%x <- 0x%x", ref->addr, value); break; } case 0x4: + { + const u16 value = vm::_ref(ref->addr) = static_cast(addr); + LOG_TRACE(LOADER, "**** REF(4): 0x%x <- 0x%04x (0x%llx)", ref->addr, value, faddr); + break; + } + case 0x6: - default: LOG_ERROR(LOADER, "**** VREF(%u): Unknown/Illegal type (0x%x, 0x%x)", ref->type, ref->addr, ref->addend); + { + const u16 value = vm::_ref(ref->addr) = static_cast(addr >> 16) + (addr & 0x8000 ? 1 : 0); + LOG_TRACE(LOADER, "**** REF(6): 0x%x <- 0x%04x (0x%llx)", ref->addr, value, faddr); + break; + } + + default: LOG_ERROR(LOADER, "**** REF(%u): Unknown/Illegal type (0x%x, 0x%x)", ref->type, ref->addr, ref->addend); } } } @@ -497,6 +515,11 @@ static auto ppu_load_exports(const std::shared_ptr& link, u32 vm::write32(addr, faddr); //LOG_WARNING(LOADER, "Exported function '%s' in module '%s'", ppu_get_function_name(module_name, fnid), module_name); } + + for (const u32 weak_import_addr : flink.weak_imports) + { + ppu_patch_refs(weak_import_addr, faddr, false); + } } } } @@ -527,7 +550,7 @@ static auto ppu_load_exports(const std::shared_ptr& link, u32 // Fix imports for (const auto vref : vlink.imports) { - ppu_patch_variable_refs(vref, vaddr); + ppu_patch_refs(vref, vaddr, false); //LOG_WARNING(LOADER, "Exported variable '%s' in module '%s'", ppu_get_variable_name(module_name, vnid), module_name); } } @@ -587,6 +610,13 @@ static void ppu_load_imports(const std::shared_ptr& link, u32 vm::write32(faddr, ppu_function_manager::addr); } + //weak imports, possibly + if (((lib.attributes & 0x2000) == 0x2000) && fnids[i + lib.num_func] != 0) //0x2000 seems to be correct flag + { + flink.weak_imports.emplace(fnids[i + lib.num_func]); + ppu_patch_refs(fnids[i + lib.num_func], faddr, true); + } + //LOG_WARNING(LOADER, "Imported function '%s' in module '%s' (0x%x)", ppu_get_function_name(module_name, fnid), module_name, faddr); } @@ -609,7 +639,7 @@ static void ppu_load_imports(const std::shared_ptr& link, u32 // Link if available if (vlink.export_addr) { - ppu_patch_variable_refs(vref, vlink.export_addr); + ppu_patch_refs(vref, vlink.export_addr, false); } //LOG_WARNING(LOADER, "Imported variable '%s' in module '%s' (0x%x)", ppu_get_variable_name(module_name, vnid), module_name, vlink.first);