s32 sys_prx_load_module(vm::ptr<const char> path, u64 flags, vm::ptr<sys_prx_load_module_option_t> pOpt) { sys_prx.Todo("sys_prx_load_module(path=\"%s\", flags=0x%llx, pOpt=0x%x)", path.get_ptr(), flags, pOpt.addr()); std::string _path = path.get_ptr(); // Check if the file is SPRX std::string local_path; Emu.GetVFS().GetDevice(_path, local_path); if (IsSelf(local_path)) { if (!DecryptSelf(local_path+".prx", local_path)) { return CELL_PRX_ERROR_ILLEGAL_LIBRARY; } _path += ".prx"; } vfsFile f(_path); if (!f.IsOpened()) { return CELL_PRX_ERROR_UNKNOWN_MODULE; } // Create the PRX object and return its id sys_prx_t* prx = new sys_prx_t(); prx->size = (u32)f.GetSize(); prx->address = (u32)Memory.Alloc(prx->size, 4); prx->path = (const char*)path; // Load the PRX into memory f.Read(vm::get_ptr(prx->address), prx->size); u32 id = sys_prx.GetNewId(prx, TYPE_PRX); return id; }
void MainFrame::DecryptSPRXLibraries(wxCommandEvent& WXUNUSED(event)) { wxFileDialog ctrl(this, L"Select SPRX files", wxEmptyString, wxEmptyString, "SPRX files (*.sprx)|*sprx", wxFD_OPEN | wxFD_MULTIPLE); if (ctrl.ShowModal() == wxID_CANCEL) { return; } wxArrayString modules; ctrl.GetPaths(modules); LOG_NOTICE(GENERAL, "Decrypting SPRX libraries..."); for (const wxString& module : modules) { std::string prx_path = fmt::ToUTF8(module); const std::string& prx_dir = fs::get_parent_dir(prx_path); if (IsSelf(prx_path)) { const std::size_t prx_ext_pos = prx_path.find_last_of('.'); const std::string& prx_ext = fmt::to_upper(prx_path.substr(prx_ext_pos != -1 ? prx_ext_pos : prx_path.size())); const std::string& prx_name = prx_path.substr(prx_dir.size()); prx_path.erase(prx_path.size() - 4, 1); // change *.sprx to *.prx if (DecryptSelf(prx_path, prx_dir + prx_name)) { LOG_SUCCESS(GENERAL, "Decrypted %s", prx_dir + prx_name); } else { LOG_ERROR(GENERAL, "Failed to decrypt %s", prx_dir + prx_name); } } } LOG_NOTICE(GENERAL, "Finished decrypting all SPRX libraries."); }
void Emulator::Load() { Stop(); try { Init(); if (!fs::is_file(m_path)) { LOG_ERROR(LOADER, "File not found: %s", m_path); return; } const std::string& elf_dir = fs::get_parent_dir(m_path); if (IsSelf(m_path)) { const std::size_t elf_ext_pos = m_path.find_last_of('.'); const std::string& elf_ext = fmt::to_upper(m_path.substr(elf_ext_pos != -1 ? elf_ext_pos : m_path.size())); const std::string& elf_name = m_path.substr(elf_dir.size()); if (elf_name.compare(elf_name.find_last_of("/\\", -1, 2) + 1, 9, "EBOOT.BIN", 9) == 0) { m_path.erase(m_path.size() - 9, 1); // change EBOOT.BIN to BOOT.BIN } else if (elf_ext == ".SELF" || elf_ext == ".SPRX") { m_path.erase(m_path.size() - 4, 1); // change *.self to *.elf, *.sprx to *.prx } else { m_path += ".decrypted.elf"; } if (!DecryptSelf(m_path, elf_dir + elf_name)) { LOG_ERROR(LOADER, "Failed to decrypt %s", elf_dir + elf_name); return; } } SetCPUThreadStop(0); LOG_NOTICE(LOADER, "Path: %s", m_path); // Load custom config if (fs::file cfg_file{ m_path + ".yml" }) { LOG_NOTICE(LOADER, "Custom config: %s.yml", m_path); cfg::root.from_string(cfg_file.to_string()); } const fs::file elf_file(m_path); ppu_exec_object ppu_exec; ppu_prx_object ppu_prx; spu_exec_object spu_exec; arm_exec_object arm_exec; if (!elf_file) { LOG_ERROR(LOADER, "Failed to open %s", m_path); return; } else if (ppu_exec.open(elf_file) == elf_error::ok) { // PS3 executable m_status = Ready; vm::ps3::init(); if (m_elf_path.empty()) { m_elf_path = "/host_root/" + m_path; LOG_NOTICE(LOADER, "Elf path: %s", m_elf_path); } // Load PARAM.SFO const auto _psf = psf::load_object(fs::file(elf_dir + "/../PARAM.SFO")); m_title = psf::get_string(_psf, "TITLE", m_path); m_title_id = psf::get_string(_psf, "TITLE_ID"); fs::get_data_dir(m_title_id, m_path); LOG_NOTICE(LOADER, "Title: %s", GetTitle()); LOG_NOTICE(LOADER, "Serial: %s", GetTitleID()); // Mount all devices const std::string& emu_dir_ = g_cfg_vfs_emulator_dir; const std::string& emu_dir = emu_dir_.empty() ? fs::get_executable_dir() : emu_dir_; const std::string& bdvd_dir = g_cfg_vfs_dev_bdvd; const std::string& home_dir = g_cfg_vfs_app_home; vfs::mount("dev_hdd0", fmt::replace_all(g_cfg_vfs_dev_hdd0, "$(EmulatorDir)", emu_dir)); vfs::mount("dev_hdd1", fmt::replace_all(g_cfg_vfs_dev_hdd1, "$(EmulatorDir)", emu_dir)); vfs::mount("dev_flash", fmt::replace_all(g_cfg_vfs_dev_flash, "$(EmulatorDir)", emu_dir)); vfs::mount("dev_usb", fmt::replace_all(g_cfg_vfs_dev_usb000, "$(EmulatorDir)", emu_dir)); vfs::mount("dev_usb000", fmt::replace_all(g_cfg_vfs_dev_usb000, "$(EmulatorDir)", emu_dir)); vfs::mount("app_home", home_dir.empty() ? elf_dir + '/' : fmt::replace_all(home_dir, "$(EmulatorDir)", emu_dir)); // Mount /dev_bdvd/ if necessary if (bdvd_dir.empty() && fs::is_file(elf_dir + "/../../PS3_DISC.SFB")) { const auto dir_list = fmt::split(elf_dir, { "/", "\\" }); // Check latest two directories if (dir_list.size() >= 2 && dir_list.back() == "USRDIR" && *(dir_list.end() - 2) == "PS3_GAME") { vfs::mount("dev_bdvd", elf_dir.substr(0, elf_dir.length() - 15)); } else { vfs::mount("dev_bdvd", elf_dir + "/../../"); } LOG_NOTICE(LOADER, "Disc: %s", vfs::get("/dev_bdvd")); } else if (bdvd_dir.size()) { vfs::mount("dev_bdvd", fmt::replace_all(bdvd_dir, "$(EmulatorDir)", emu_dir)); } // Mount /host_root/ if necessary if (g_cfg_vfs_allow_host_root) { vfs::mount("host_root", {}); } LOG_NOTICE(LOADER, "Used configuration:\n%s\n", cfg::root.to_string()); ppu_load_exec(ppu_exec); fxm::import<GSRender>(PURE_EXPR(Emu.GetCallbacks().get_gs_render())); // TODO: must be created in appropriate sys_rsx syscall } else if (ppu_prx.open(elf_file) == elf_error::ok) { // PPU PRX (experimental) m_status = Ready; vm::ps3::init(); ppu_load_prx(ppu_prx); } else if (spu_exec.open(elf_file) == elf_error::ok) { // SPU executable (experimental) m_status = Ready; vm::ps3::init(); spu_load_exec(spu_exec); } else if (arm_exec.open(elf_file) == elf_error::ok) { // ARMv7 executable m_status = Ready; vm::psv::init(); arm_load_exec(arm_exec); } else { LOG_ERROR(LOADER, "Invalid or unsupported file format: %s", m_path); LOG_WARNING(LOADER, "** ppu_exec -> %s", ppu_exec.get_error()); LOG_WARNING(LOADER, "** ppu_prx -> %s", ppu_prx.get_error()); LOG_WARNING(LOADER, "** spu_exec -> %s", spu_exec.get_error()); LOG_WARNING(LOADER, "** arm_exec -> %s", arm_exec.get_error()); return; } debug::autopause::reload(); SendDbgCommand(DID_READY_EMU); if (g_cfg_autostart) Run(); } catch (const std::exception& e) { LOG_FATAL(LOADER, "%s thrown: %s", typeid(e).name(), e.what()); Stop(); } }
void Emulator::Load() { Stop(); try { Init(); if (!fs::is_file(m_path)) { LOG_ERROR(LOADER, "File not found: %s", m_path); return; } const std::string& elf_dir = fs::get_parent_dir(m_path); if (IsSelf(m_path)) { const std::size_t elf_ext_pos = m_path.find_last_of('.'); const std::string& elf_ext = fmt::to_upper(m_path.substr(elf_ext_pos != -1 ? elf_ext_pos : m_path.size())); const std::string& elf_name = m_path.substr(elf_dir.size()); if (elf_name.compare(elf_name.find_last_of("/\\", -1, 2) + 1, 9, "EBOOT.BIN", 9) == 0) { m_path.erase(m_path.size() - 9, 1); // change EBOOT.BIN to BOOT.BIN } else if (elf_ext == ".SELF" || elf_ext == ".SPRX") { m_path.erase(m_path.size() - 4, 1); // change *.self to *.elf, *.sprx to *.prx } else { m_path += ".decrypted.elf"; } if (!DecryptSelf(m_path, elf_dir + elf_name)) { LOG_ERROR(LOADER, "Failed to decrypt %s", elf_dir + elf_name); return; } } ResetInfo(); LOG_NOTICE(LOADER, "Path: %s", m_path); // Load custom config if (fs::file cfg_file{ m_path + ".yml" }) { LOG_NOTICE(LOADER, "Custom config: %s.yml", m_path); cfg::root.from_string(cfg_file.to_string()); } const fs::file elf_file(m_path); ppu_exec_loader ppu_exec; ppu_prx_loader ppu_prx; spu_exec_loader spu_exec; arm_exec_loader arm_exec; if (!elf_file) { LOG_ERROR(LOADER, "Failed to open %s", m_path); return; } else if (ppu_exec.open(elf_file) == elf_error::ok) { // PS3 executable m_status = Ready; vm::ps3::init(); if (m_elf_path.empty()) { m_elf_path = "/host_root/" + m_path; LOG_NOTICE(LOADER, "Elf path: %s", m_elf_path); } // Load PARAM.SFO m_psf = psf::load_object(fs::file(elf_dir + "/../PARAM.SFO")); m_title = psf::get_string(m_psf, "TITLE", m_path); m_title_id = psf::get_string(m_psf, "TITLE_ID"); LOG_NOTICE(LOADER, "Title: %s", GetTitle()); LOG_NOTICE(LOADER, "Serial: %s", GetTitleID()); LOG_NOTICE(LOADER, ""); LOG_NOTICE(LOADER, "Used configuration:\n%s\n", cfg::root.to_string()); // Mount /dev_bdvd/ if (g_cfg_vfs_dev_bdvd.size() == 0 && fs::is_file(elf_dir + "/../../PS3_DISC.SFB")) { const auto dir_list = fmt::split(elf_dir, { "/", "\\" }); // Check latest two directories if (dir_list.size() >= 2 && dir_list.back() == "USRDIR" && *(dir_list.end() - 2) == "PS3_GAME") { g_cfg_vfs_dev_bdvd = elf_dir.substr(0, elf_dir.length() - 15); } else { g_cfg_vfs_dev_bdvd = elf_dir + "/../../"; } } // Mount /app_home/ if (g_cfg_vfs_app_home.size() == 0) { g_cfg_vfs_app_home = elf_dir + '/'; } vfs::dump(); ppu_exec.load(); Emu.GetCallbackManager().Init(); fxm::import<GSRender>(PURE_EXPR(Emu.GetCallbacks().get_gs_render())); // TODO: must be created in appropriate sys_rsx syscall } else if (ppu_prx.open(elf_file) == elf_error::ok) { // PPU PRX (experimental) m_status = Ready; vm::ps3::init(); ppu_prx.load(); GetCallbackManager().Init(); } else if (spu_exec.open(elf_file) == elf_error::ok) { // SPU executable (experimental) m_status = Ready; vm::ps3::init(); spu_exec.load(); } else if (arm_exec.open(elf_file) == elf_error::ok) { // ARMv7 executable m_status = Ready; vm::psv::init(); arm_exec.load(); } else { LOG_ERROR(LOADER, "Invalid or unsupported file format: %s", m_path); LOG_WARNING(LOADER, "** ppu_exec_loader -> %s", bijective_find<elf_error>(ppu_exec, "???")); LOG_WARNING(LOADER, "** ppu_prx_loader -> %s", bijective_find<elf_error>(ppu_prx, "???")); LOG_WARNING(LOADER, "** spu_exec_loader -> %s", bijective_find<elf_error>(spu_exec, "???")); LOG_WARNING(LOADER, "** arm_exec_loader -> %s", bijective_find<elf_error>(arm_exec, "???")); return; } debug::autopause::reload(); SendDbgCommand(DID_READY_EMU); if (g_cfg_autostart) Run(); } catch (const std::exception& e) { LOG_FATAL(LOADER, "%s thrown: %s", typeid(e).name(), e.what()); Stop(); } }