error_code sys_tty_read(s32 ch, vm::ptr<char> buf, u32 len, vm::ptr<u32> preadlen) { sys_tty.fatal("sys_tty_read(ch=%d, buf=*0x%x, len=%d, preadlen=*0x%x)", ch, buf, len, preadlen); // We currently do not support reading from the Console fmt::throw_exception("Unimplemented" HERE); }
~content_permission() { try { if (!temp.empty()) { fs::remove_all(temp); } } catch (...) { cellGame.fatal("Failed to clean directory '/dev_hdd1/game/%s'", dir); catch_all_exceptions(); } }
error_code cellGameDataCheckCreate2(ppu_thread& ppu, u32 version, vm::cptr<char> dirName, u32 errDialog, vm::ptr<CellGameDataStatCallback> funcStat, u32 container) { cellGame.error("cellGameDataCheckCreate2(version=0x%x, dirName=%s, errDialog=0x%x, funcStat=*0x%x, container=%d)", version, dirName, errDialog, funcStat, container); //older sdk. it might not care about game type. if (version != CELL_GAMEDATA_VERSION_CURRENT || errDialog > 1) { return CELL_GAMEDATA_ERROR_PARAM; } // TODO: output errors (errDialog) const std::string& dir = "/dev_hdd0/game/"s + dirName.get_ptr(); vm::var<CellGameDataCBResult> cbResult; vm::var<CellGameDataStatGet> cbGet; vm::var<CellGameDataStatSet> cbSet; cbGet->isNewData = fs::is_dir(vfs::get(dir)) ? CELL_GAMEDATA_ISNEWDATA_NO : CELL_GAMEDATA_ISNEWDATA_YES; // TODO: Use the free space of the computer's HDD where RPCS3 is being run. cbGet->hddFreeSizeKB = 40000000; //40 GB strcpy_trunc(cbGet->contentInfoPath, dir); strcpy_trunc(cbGet->gameDataPath, dir + "/USRDIR"); // TODO: set correct time cbGet->st_atime_ = 0; cbGet->st_ctime_ = 0; cbGet->st_mtime_ = 0; // TODO: calculate data size, if necessary cbGet->sizeKB = CELL_GAMEDATA_SIZEKB_NOTCALC; cbGet->sysSizeKB = 0; psf::registry sfo = psf::load_object(fs::file(vfs::get("/app_home/../PARAM.SFO"))); cbGet->getParam.attribute = CELL_GAMEDATA_ATTR_NORMAL; cbGet->getParam.parentalLevel = psf::get_integer(sfo, "PARENTAL_LEVEL", 0); strcpy_trunc(cbGet->getParam.dataVersion, psf::get_string(sfo, "APP_VER", "")); strcpy_trunc(cbGet->getParam.titleId, psf::get_string(sfo, "TITLE_ID", "")); strcpy_trunc(cbGet->getParam.title, psf::get_string(sfo, "TITLE", "")); for (u32 i = 0; i < CELL_HDDGAME_SYSP_LANGUAGE_NUM; i++) { strcpy_trunc(cbGet->getParam.titleLang[i], psf::get_string(sfo, fmt::format("TITLE_%02d", i))); } funcStat(ppu, cbResult, cbGet, cbSet); switch ((s32)cbResult->result) { case CELL_GAMEDATA_CBRESULT_OK_CANCEL: // TODO: do not process game data(directory) cellGame.warning("cellGameDataCheckCreate2(): callback returned CELL_GAMEDATA_CBRESULT_OK_CANCEL"); return CELL_OK; case CELL_GAMEDATA_CBRESULT_OK: //game confirmed that it wants to create directory if (!fs::is_dir(vfs::get(dir + "/USRDIR")) && !fs::create_path(vfs::get(dir + "/USRDIR"))) { cellGame.error("cellGameDataCheckCreate2(): folder creation failed"); return CELL_GAME_ERROR_NOSPACE; //don't know which error. picked one at random } if (cbSet->setParam) { const auto vdir = vfs::get(dir); //older SDK does not define not settable values, hopefully it doesn't just change some values(overwrite) psf::registry sfo_write = { { "TITLE_ID", psf::string(CELL_GAME_SYSP_TITLEID_SIZE, cbSet->setParam->titleId) }, { "TITLE", psf::string(CELL_GAME_SYSP_TITLE_SIZE, cbSet->setParam->title) }, { "VERSION", psf::string(CELL_GAME_SYSP_VERSION_SIZE, cbSet->setParam->dataVersion) }, { "PARENTAL_LEVEL", cbSet->setParam->parentalLevel.value() } }; //sfo_write.emplace("PARENTAL_LEVEL", cbSet->setParam->parentalLevel.value()); // I don't care about age restrictions. for (u32 i = 0; i < CELL_HDDGAME_SYSP_LANGUAGE_NUM; i++) { sfo_write.emplace(fmt::format("TITLE_%02d", i), psf::string(CELL_GAME_SYSP_TITLE_SIZE, cbSet->setParam->titleLang[i])); } if (!fs::is_dir(vdir)) { cellGame.fatal("directory where param.sfo is to be created does not exist"); return CELL_GAME_ERROR_INTERNAL; } psf::save_object(fs::file(vdir + "/PARAM.SFO", fs::rewrite), sfo_write); } return CELL_OK; case CELL_GAMEDATA_CBRESULT_ERR_NOSPACE: // TODO: process errors, error message and needSizeKB result cellGame.error("cellGameDataCheckCreate2(): callback returned CELL_GAMEDATA_CBRESULT_ERR_NOSPACE"); return CELL_GAMEDATA_ERROR_CBRESULT; case CELL_GAMEDATA_CBRESULT_ERR_BROKEN: cellGame.error("cellGameDataCheckCreate2(): callback returned CELL_GAMEDATA_CBRESULT_ERR_BROKEN"); return CELL_GAMEDATA_ERROR_CBRESULT; case CELL_GAMEDATA_CBRESULT_ERR_NODATA: cellGame.error("cellGameDataCheckCreate2(): callback returned CELL_GAMEDATA_CBRESULT_ERR_NODATA"); return CELL_GAMEDATA_ERROR_CBRESULT; case CELL_GAMEDATA_CBRESULT_ERR_INVALID: cellGame.error("cellGameDataCheckCreate2(): callback returned CELL_GAMEDATA_CBRESULT_ERR_INVALID"); return CELL_GAMEDATA_ERROR_CBRESULT; default: cellGame.error("cellGameDataCheckCreate2(): callback returned unknown error (code=0x%x)"); return CELL_GAMEDATA_ERROR_CBRESULT; } }