mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-04-05 14:37:08 +00:00
Implement standalone OVL (overlay) loading mode
* Allow to load OVL alone. * Add error checks in ppu_load_exec(), do not crash on error. * Fix crash on exit from standalone PRX mode, allow kernel explorer to work with it as well for the added OVL mode.
This commit is contained in:
parent
9077563dac
commit
82c86ed2f7
4 changed files with 113 additions and 27 deletions
|
|
@ -786,6 +786,27 @@ static void ppu_check_patch_spu_images(const ppu_segment& seg)
|
|||
}
|
||||
}
|
||||
|
||||
void try_spawn_ppu_if_exclusive_program(const ppu_module& m)
|
||||
{
|
||||
// If only PRX/OVL has been loaded at Emu.BootGame(), launch a single PPU thread so its memory can be viewed
|
||||
if (Emu.IsReady() && g_fxo->get<ppu_module>()->segs.empty())
|
||||
{
|
||||
ppu_thread_params p
|
||||
{
|
||||
.stack_addr = vm::cast(vm::alloc(0x100000, vm::stack, 4096)),
|
||||
.stack_size = 0x100000,
|
||||
};
|
||||
|
||||
auto ppu = idm::make_ptr<named_thread<ppu_thread>>("PPU[0x1000000] Thread (test_thread)", p, "test_thread", 0);
|
||||
|
||||
ppu->cmd_push({ppu_cmd::initialize, 0});
|
||||
ppu->cia = m.funcs[0].addr;
|
||||
|
||||
// For kernel explorer
|
||||
g_fxo->init<lv2_memory_container>(4096);
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<lv2_prx> ppu_load_prx(const ppu_prx_object& elf, const std::string& path)
|
||||
{
|
||||
// Create new PRX object
|
||||
|
|
@ -1080,18 +1101,7 @@ std::shared_ptr<lv2_prx> ppu_load_prx(const ppu_prx_object& elf, const std::stri
|
|||
|
||||
ppu_loader.success("PRX library hash: %s (<- %u)", hash, applied);
|
||||
|
||||
if (Emu.IsReady() && g_fxo->get<ppu_module>()->segs.empty())
|
||||
{
|
||||
// Special loading mode
|
||||
ppu_thread_params p{
|
||||
.stack_addr = vm::cast(vm::alloc(0x100000, vm::stack, 4096)),
|
||||
.stack_size = 0x100000,
|
||||
};
|
||||
|
||||
auto ppu = idm::make_ptr<named_thread<ppu_thread>>("PPU[0x1000000] Thread (test_thread)", p, "test_thread", 0);
|
||||
|
||||
ppu->cmd_push({ppu_cmd::initialize, 0});
|
||||
}
|
||||
try_spawn_ppu_if_exclusive_program(*prx);
|
||||
|
||||
return prx;
|
||||
}
|
||||
|
|
@ -1129,8 +1139,24 @@ void ppu_unload_prx(const lv2_prx& prx)
|
|||
}
|
||||
}
|
||||
|
||||
void ppu_load_exec(const ppu_exec_object& elf)
|
||||
bool ppu_load_exec(const ppu_exec_object& elf)
|
||||
{
|
||||
// Check if it is a standalone executable first
|
||||
for (const auto& prog : elf.progs)
|
||||
{
|
||||
if (prog.p_type == 0x1u /* LOAD */ && prog.p_memsz)
|
||||
{
|
||||
using addr_range = utils::address_range;
|
||||
|
||||
const addr_range r = addr_range::start_length(static_cast<u32>(prog.p_vaddr), static_cast<u32>(prog.p_memsz));
|
||||
|
||||
if ((prog.p_vaddr | prog.p_memsz) > UINT32_MAX || !r.valid() || !r.inside(addr_range::start_length(0x00000000, 0x30000000)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set for delayed initialization in ppu_initialize()
|
||||
const auto _main = g_fxo->get<ppu_module>();
|
||||
|
||||
|
|
@ -1153,6 +1179,27 @@ void ppu_load_exec(const ppu_exec_object& elf)
|
|||
sha1_context sha;
|
||||
sha1_starts(&sha);
|
||||
|
||||
struct on_fatal_error
|
||||
{
|
||||
ppu_module* _main;
|
||||
bool errored = true;
|
||||
|
||||
~on_fatal_error()
|
||||
{
|
||||
if (!errored)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Revert previous allocations on an error
|
||||
for (const auto& seg : _main->segs)
|
||||
{
|
||||
vm::dealloc(seg.addr);
|
||||
}
|
||||
}
|
||||
|
||||
} error_handler{_main};
|
||||
|
||||
// Allocate memory at fixed positions
|
||||
for (const auto& prog : elf.progs)
|
||||
{
|
||||
|
|
@ -1173,7 +1220,10 @@ void ppu_load_exec(const ppu_exec_object& elf)
|
|||
if (type == 0x1 /* LOAD */ && prog.p_memsz)
|
||||
{
|
||||
if (prog.bin.size() > size || prog.bin.size() != prog.p_filesz)
|
||||
fmt::throw_exception("Invalid binary size (0x%llx, memsz=0x%x)", prog.bin.size(), size);
|
||||
{
|
||||
ppu_loader.fatal("ppu_load_exec(): Invalid binary size (0x%llx, memsz=0x%x)", prog.bin.size(), size);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!vm::falloc(addr, size, vm::main))
|
||||
{
|
||||
|
|
@ -1181,7 +1231,8 @@ void ppu_load_exec(const ppu_exec_object& elf)
|
|||
|
||||
if (!vm::falloc(addr, size))
|
||||
{
|
||||
fmt::throw_exception("vm::falloc() failed (addr=0x%x, memsz=0x%x)", addr, size);
|
||||
ppu_loader.fatal("ppu_load_exec(): vm::falloc() failed (addr=0x%x, memsz=0x%x)", addr, size);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1299,11 +1350,17 @@ void ppu_load_exec(const ppu_exec_object& elf)
|
|||
|
||||
case 0x00000007: // TLS
|
||||
{
|
||||
ppu_loader.notice("TLS info segment found: tls-image=*0x%x, image-size=0x%x, tls-size=0x%x", prog.p_vaddr, prog.p_filesz, prog.p_memsz);
|
||||
|
||||
if ((prog.p_vaddr | prog.p_filesz | prog.p_memsz) > UINT32_MAX)
|
||||
{
|
||||
ppu_loader.fatal("ppu_load_exec(): TLS segment is invalid!");
|
||||
return false;
|
||||
}
|
||||
|
||||
tls_vaddr = vm::cast(prog.p_vaddr);
|
||||
tls_fsize = ::narrow<u32>(prog.p_filesz);
|
||||
tls_vsize = ::narrow<u32>(prog.p_memsz);
|
||||
|
||||
ppu_loader.notice("TLS info segment found: tls-image=*0x%x, image-size=0x%x, tls-size=0x%x", tls_vaddr, tls_fsize, tls_vsize);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -1388,7 +1445,8 @@ void ppu_load_exec(const ppu_exec_object& elf)
|
|||
|
||||
if (proc_prx_param.magic != 0x1b434cecu)
|
||||
{
|
||||
fmt::throw_exception("Bad magic! (0x%x)", proc_prx_param.magic);
|
||||
ppu_loader.fatal("ppu_load_exec(): Bad magic! (0x%x)", proc_prx_param.magic);
|
||||
return false;
|
||||
}
|
||||
|
||||
ppu_load_exports(link, proc_prx_param.libent_start, proc_prx_param.libent_end);
|
||||
|
|
@ -1647,6 +1705,9 @@ void ppu_load_exec(const ppu_exec_object& elf)
|
|||
ensure(vm::page_protect(addr, utils::align(size, 0x1000), 0, 0, vm::page_writable));
|
||||
}
|
||||
}
|
||||
|
||||
error_handler.errored = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::pair<std::shared_ptr<lv2_overlay>, CellError> ppu_load_overlay(const ppu_exec_object& elf, const std::string& path)
|
||||
|
|
@ -1875,5 +1936,8 @@ std::pair<std::shared_ptr<lv2_overlay>, CellError> ppu_load_overlay(const ppu_ex
|
|||
ovlm->path = path;
|
||||
|
||||
idm::import_existing<lv2_obj, lv2_overlay>(ovlm);
|
||||
|
||||
try_spawn_ppu_if_exclusive_program(*ovlm);
|
||||
|
||||
return {std::move(ovlm), {}};
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue