From 40a84dd477a9e53c354def845f239f34b9601a29 Mon Sep 17 00:00:00 2001 From: Inviuz Date: Sat, 11 Mar 2017 09:59:50 +0100 Subject: [PATCH] Handles directory creation in cellGameDataCheckCreate2 (#2488) * Handle directory creation in cellGameDataCheckCreate2 Stops some games from displaying information about not enough memory on hdd * Returning CELL_OK causes some games to loop on sceNp functions for "shaman magic" * cellGameDataCheckCreate2 added param.sfo creating/rewriting * fix fs::file null and one readability change * For debugging purposes When fs::file problem is located will be improved * Fixed wrong operators * Conversion from vfs to fs Should take care of fs::null * Cleanup removed some unnecessary logging * Fix successive function calls second call was always ending in error since it didn't create the conent permission * Changes according to Neko's review * Change to use u32 value --- rpcs3/Emu/Cell/Modules/cellGame.cpp | 62 +++++++++++++++++++++-------- rpcs3/Emu/Cell/Modules/sceNp2.cpp | 2 +- 2 files changed, 46 insertions(+), 18 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/cellGame.cpp b/rpcs3/Emu/Cell/Modules/cellGame.cpp index 50b584a089..9edbde7e62 100644 --- a/rpcs3/Emu/Cell/Modules/cellGame.cpp +++ b/rpcs3/Emu/Cell/Modules/cellGame.cpp @@ -405,6 +405,8 @@ error_code cellGameDataCheckCreate2(ppu_thread& ppu, u32 version, vm::cptr { 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; @@ -414,21 +416,15 @@ error_code cellGameDataCheckCreate2(ppu_thread& ppu, u32 version, vm::cptr const std::string& dir = "/dev_hdd0/game/"s + dirName.get_ptr(); - if (!fs::is_dir(vfs::get(dir))) - { - cellGame.todo("cellGameDataCheckCreate2(): should create directory '%s'", dir); - // TODO: create data - return CELL_OK; - } - vm::var cbResult; vm::var cbGet; vm::var 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 - cbGet->isNewData = CELL_GAMEDATA_ISNEWDATA_NO; + strcpy_trunc(cbGet->contentInfoPath, dir); strcpy_trunc(cbGet->gameDataPath, dir + "/USRDIR"); @@ -448,23 +444,55 @@ error_code cellGameDataCheckCreate2(ppu_thread& ppu, u32 version, vm::cptr 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", "")); - // TODO: write lang titles + 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); - - if (cbSet->setParam) - { - // TODO: write PARAM.SFO from cbSet - cellGame.todo("cellGameDataCheckCreate2(): writing PARAM.SFO parameters (addr=0x%x)", cbSet->setParam); - } + switch ((s32)cbResult->result) { case CELL_GAMEDATA_CBRESULT_OK_CANCEL: - // TODO: do not process game data + // 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: + + 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 diff --git a/rpcs3/Emu/Cell/Modules/sceNp2.cpp b/rpcs3/Emu/Cell/Modules/sceNp2.cpp index 5709a92640..41086fbfe5 100644 --- a/rpcs3/Emu/Cell/Modules/sceNp2.cpp +++ b/rpcs3/Emu/Cell/Modules/sceNp2.cpp @@ -31,7 +31,7 @@ s32 sceNpMatching2Init(u32 poolsize, s32 priority) { sceNp2.todo("sceNpMatching2Init(poolsize=0x%x, priority=%d)", poolsize, priority); - return CELL_OK; + return SCE_NP_MATCHING2_ERROR_TIMEDOUT; } s32 sceNpMatching2Init2(u32 poolsize, s32 priority, vm::ptr param)