error_code prx_load_module(std::string path, u64 flags, vm::ptr<sys_prx_load_module_option_t> pOpt) { if (s_prx_ignore.count(path)) { sys_prx.warning("Ignored module: %s", path); const auto prx = idm::make_ptr<lv2_obj, lv2_prx>(); prx->name = path.substr(path.find_last_of('/') + 1); return not_an_error(idm::last_id()); } const auto loadedkeys = fxm::get_always<LoadedNpdrmKeys_t>(); const ppu_prx_object obj = decrypt_self(fs::file(vfs::get(path)), loadedkeys->devKlic.data()); if (obj != elf_error::ok) { return CELL_PRX_ERROR_ILLEGAL_LIBRARY; } const auto prx = ppu_load_prx(obj, path.substr(path.find_last_of('/') + 1)); if (!prx) { return CELL_PRX_ERROR_ILLEGAL_LIBRARY; } ppu_initialize(*prx); sys_prx.success("Loaded module: %s", path); return not_an_error(idm::last_id()); }
error_code cellGameContentPermit(vm::ptr<char[CELL_GAME_PATH_MAX]> contentInfoPath, vm::ptr<char[CELL_GAME_PATH_MAX]> usrdirPath) { cellGame.warning("cellGameContentPermit(contentInfoPath=*0x%x, usrdirPath=*0x%x)", contentInfoPath, usrdirPath); if (!contentInfoPath && !usrdirPath) { return CELL_GAME_ERROR_PARAM; } const auto prm = fxm::get<content_permission>(); if (!prm) { return CELL_GAME_ERROR_FAILURE; } const std::string dir = prm->dir.empty() ? "/dev_bdvd/PS3_GAME"s : "/dev_hdd0/game/" + prm->dir; if (!prm->temp.empty()) { // Make temporary directory persistent const auto vdir = vfs::get(dir); if (fs::exists(vdir)) { fmt::throw_exception("cellGameContentPermit(): epic fail: directory '%s' already exists", dir); } if (fs::rename(prm->temp, vdir)) { cellGame.success("cellGameContentPermit(): directory '%s' has been created", dir); } else { fmt::throw_exception("cellGameContentPermit(): failed to initialize directory '%s'", dir); } // Create PARAM.SFO psf::save_object(fs::file(vdir + "/PARAM.SFO", fs::rewrite), prm->sfo); // Disable deletion prm->temp.clear(); } strcpy_trunc(*contentInfoPath, dir); strcpy_trunc(*usrdirPath, dir + "/USRDIR"); verify(HERE), fxm::remove<content_permission>(); return CELL_OK; }
s32 sys_process_exit(ppu_thread& ppu, s32 status) { vm::temporary_unlock(ppu); sys_process.warning("sys_process_exit(status=0x%x)", status); Emu.CallAfter([]() { sys_process.success("Process finished"); Emu.Stop(); }); thread_ctrl::eternalize(); return CELL_OK; }
error_code cellGameCreateGameData(vm::ptr<CellGameSetInitParams> init, vm::ptr<char[CELL_GAME_PATH_MAX]> tmp_contentInfoPath, vm::ptr<char[CELL_GAME_PATH_MAX]> tmp_usrdirPath) { cellGame.error("cellGameCreateGameData(init=*0x%x, tmp_contentInfoPath=*0x%x, tmp_usrdirPath=*0x%x)", init, tmp_contentInfoPath, tmp_usrdirPath); const auto prm = fxm::get<content_permission>(); if (!prm || prm->dir.empty()) { return CELL_GAME_ERROR_FAILURE; } std::string tmp_contentInfo = "/dev_hdd1/game/" + prm->dir; std::string tmp_usrdir = "/dev_hdd1/game/" + prm->dir + "/USRDIR"; if (!fs::create_dir(vfs::get(tmp_contentInfo))) { cellGame.error("cellGameCreateGameData(): failed to create directory '%s'", tmp_contentInfo); return CELL_GAME_ERROR_ACCESS_ERROR; // ??? } if (!fs::create_dir(vfs::get(tmp_usrdir))) { cellGame.error("cellGameCreateGameData(): failed to create directory '%s'", tmp_usrdir); return CELL_GAME_ERROR_ACCESS_ERROR; // ??? } // cellGameContentPermit should then move files in non-temporary location and return their non-temporary displacement strcpy_trunc(*tmp_contentInfoPath, tmp_contentInfo); strcpy_trunc(*tmp_usrdirPath, tmp_usrdir); prm->temp = vfs::get(tmp_contentInfo); cellGame.success("cellGameCreateGameData(): temporary directory '%s' has been created", tmp_contentInfo); // Initial PARAM.SFO parameters (overwrite) prm->sfo = { { "CATEGORY", psf::string(3, "GD") }, { "TITLE_ID", psf::string(CELL_GAME_SYSP_TITLEID_SIZE, init->titleId) }, { "TITLE", psf::string(CELL_GAME_SYSP_TITLE_SIZE, init->title) }, { "VERSION", psf::string(CELL_GAME_SYSP_VERSION_SIZE, init->version) }, }; return CELL_OK; }
void sys_game_process_exitspawn(vm::cptr<char> path, u32 argv_addr, u32 envp_addr, u32 data_addr, u32 data_size, u32 prio, u64 flags) { std::string _path = path.get_ptr(); const std::string& from = "//"; const std::string& to = "/"; size_t start_pos = 0; while ((start_pos = _path.find(from, start_pos)) != std::string::npos) { _path.replace(start_pos, from.length(), to); start_pos += to.length(); } sysPrxForUser.todo("sys_game_process_exitspawn()"); sysPrxForUser.warning("path: %s", _path.c_str()); sysPrxForUser.warning("argv: 0x%x", argv_addr); sysPrxForUser.warning("envp: 0x%x", envp_addr); sysPrxForUser.warning("data: 0x%x", data_addr); sysPrxForUser.warning("data_size: 0x%x", data_size); sysPrxForUser.warning("prio: %d", prio); sysPrxForUser.warning("flags: %d", flags); std::vector<std::string> argv; std::vector<std::string> env; if (argv_addr) { auto argvp = vm::cpptr<char>::make(argv_addr); while (argvp && *argvp) { argv.push_back(argvp[0].get_ptr()); argvp++; } for (auto &arg : argv) { sysPrxForUser.trace("argument: %s", arg.c_str()); } } if (envp_addr) { auto envp = vm::cpptr<char>::make(envp_addr); while (envp && *envp) { env.push_back(envp[0].get_ptr()); envp++; } for (auto &en : env) { sysPrxForUser.trace("env_argument: %s", en.c_str()); } } // TODO: execute the file in <path> with the args in argv // and the environment parameters in envp and copy the data // from data_addr into the adress space of the new process // then kill the current process Emu.Pause(); sysPrxForUser.success("Process finished"); Emu.CallAfter([=, path = vfs::get(_path)]() { Emu.Stop(); Emu.BootGame(path, true); }); }