From 240b4a8bd8f05a9a28b6f79da9b7b21798527763 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Thu, 26 Sep 2019 16:10:35 +0300 Subject: [PATCH] cellGameData: use g_fxo for content_permission --- rpcs3/Emu/Cell/Modules/cellGame.cpp | 160 +++++++++++++++++----------- 1 file changed, 100 insertions(+), 60 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/cellGame.cpp b/rpcs3/Emu/Cell/Modules/cellGame.cpp index 0cdea2bdd8..a53561a941 100644 --- a/rpcs3/Emu/Cell/Modules/cellGame.cpp +++ b/rpcs3/Emu/Cell/Modules/cellGame.cpp @@ -9,6 +9,7 @@ #include "Loader/PSF.h" #include "Utilities/StrUtil.h" +#include "util/init_mutex.hpp" #include @@ -111,7 +112,7 @@ void fmt_class_string::format(std::string& out, u64 arg) struct content_permission final { // Content directory name or path - const std::string dir; + std::string dir; // SFO file psf::registry sfo; @@ -119,14 +120,15 @@ struct content_permission final // Temporary directory path std::string temp; - bool can_create = false; + stx::init_mutex init; - template - content_permission(Dir&& dir, Sfo&& sfo) - : dir(std::forward(dir)) - , sfo(std::forward(sfo)) - { - } + atomic_t can_create = 0; + + content_permission() = default; + + content_permission(const content_permission&) = delete; + + content_permission& operator=(const content_permission&) = delete; ~content_permission() { @@ -140,7 +142,6 @@ struct content_permission final catch (...) { cellGame.fatal("Failed to clean directory '%s'", temp); - catch_all_exceptions(); } } }; @@ -315,16 +316,16 @@ error_code cellGameBootCheck(vm::ptr type, vm::ptr attributes, vm::ptr return CELL_GAME_ERROR_PARAM; } + std::string dir; + psf::registry sfo; + if (Emu.GetCat() == "DG") { *type = CELL_GAME_GAMETYPE_DISC; *attributes = 0; // TODO // TODO: dirName might be a read only string when BootCheck is called on a disc game. (e.g. Ben 10 Ultimate Alien: Cosmic Destruction) - if (!fxm::make("", psf::load_object(fs::file(vfs::get("/dev_bdvd/PS3_GAME/PARAM.SFO"))))) - { - return CELL_GAME_ERROR_BUSY; - } + sfo = psf::load_object(fs::file(vfs::get("/dev_bdvd/PS3_GAME/PARAM.SFO"))); } else if (Emu.GetCat() == "GD") { @@ -332,10 +333,7 @@ error_code cellGameBootCheck(vm::ptr type, vm::ptr attributes, vm::ptr *attributes = CELL_GAME_ATTRIBUTE_PATCH; // TODO if (dirName) strcpy_trunc(*dirName, Emu.GetTitleID()); // ??? - if (!fxm::make("", psf::load_object(fs::file(vfs::get(Emu.GetDir() + "PARAM.SFO"))))) - { - return CELL_GAME_ERROR_BUSY; - } + sfo = psf::load_object(fs::file(vfs::get(Emu.GetDir() + "PARAM.SFO"))); } else { @@ -343,12 +341,25 @@ error_code cellGameBootCheck(vm::ptr type, vm::ptr attributes, vm::ptr *attributes = 0; // TODO if (dirName) strcpy_trunc(*dirName, Emu.GetTitleID()); - if (!fxm::make(Emu.GetTitleID(), psf::load_object(fs::file(vfs::get(Emu.GetDir() + "PARAM.SFO"))))) - { - return CELL_GAME_ERROR_BUSY; - } + sfo = psf::load_object(fs::file(vfs::get(Emu.GetDir() + "PARAM.SFO"))); + dir = Emu.GetTitleID(); } + const auto perm = g_fxo->get(); + + const auto init = perm->init.init(); + + if (!init) + { + return CELL_GAME_ERROR_BUSY; + } + + perm->dir = std::move(dir); + perm->sfo = std::move(sfo); + + perm->temp.clear(); + perm->can_create = 0; + return CELL_OK; } @@ -371,11 +382,23 @@ error_code cellGamePatchCheck(vm::ptr size, vm::ptr r return CELL_GAME_ERROR_NOTPATCH; } - if (!fxm::make(Emu.GetTitleID(), psf::load_object(fs::file(vfs::get(Emu.GetDir() + "PARAM.SFO"))))) + psf::registry sfo = psf::load_object(fs::file(vfs::get(Emu.GetDir() + "PARAM.SFO"))); + + const auto perm = g_fxo->get(); + + const auto init = perm->init.init(); + + if (!init) { return CELL_GAME_ERROR_BUSY; } + perm->dir = Emu.GetTitleID(); + perm->sfo = std::move(sfo); + + perm->temp.clear(); + perm->can_create = 0; + return CELL_OK; } @@ -398,28 +421,42 @@ error_code cellGameDataCheck(u32 type, vm::cptr dirName, vm::ptrsysSizeKB = 0; } - // TODO: not sure what should be checked there - const auto prm = fxm::make(type == CELL_GAME_GAMETYPE_DISC ? "" : dirName.get_ptr(), psf::registry{}); + std::string name; - if (!prm) + if (type != CELL_GAME_GAMETYPE_DISC) + { + name = dirName.get_ptr(); + } + + const std::string dir = type == CELL_GAME_GAMETYPE_DISC ? "/dev_bdvd/PS3_GAME"s : "/dev_hdd0/game/" + name; + + // TODO: not sure what should be checked there + + const auto perm = g_fxo->get(); + + const auto init = perm->init.init(); + + if (!init) { return CELL_GAME_ERROR_BUSY; } + perm->dir = std::move(name); + perm->sfo.clear(); + perm->temp.clear(); + if (type == CELL_GAME_GAMETYPE_GAMEDATA) { - prm->can_create = true; + perm->can_create = true; } - const std::string dir = prm->dir.empty() ? "/dev_bdvd/PS3_GAME"s : "/dev_hdd0/game/" + prm->dir; - if (!fs::is_dir(vfs::get(dir))) { cellGame.warning("cellGameDataCheck(): directory '%s' not found", dir); return not_an_error(CELL_GAME_RET_NONE); } - prm->sfo = psf::load_object(fs::file(vfs::get(dir + "/PARAM.SFO"))); + perm->sfo = psf::load_object(fs::file(vfs::get(dir + "/PARAM.SFO"))); return CELL_OK; } @@ -432,52 +469,45 @@ error_code cellGameContentPermit(vm::ptr contentInfoPa return CELL_GAME_ERROR_PARAM; } - const auto prm = fxm::get(); + const auto perm = g_fxo->get(); - if (!prm) + const auto init = perm->init.reset(); + + if (!init) { return CELL_GAME_ERROR_FAILURE; } - const std::string dir = prm->dir.empty() ? "/dev_bdvd/PS3_GAME"s : "/dev_hdd0/game/" + prm->dir; + const std::string dir = perm->dir.empty() ? "/dev_bdvd/PS3_GAME"s : "/dev_hdd0/game/" + perm->dir; - if (prm->can_create && prm->temp.empty() && !fs::is_dir(vfs::get(dir))) + if (perm->can_create && perm->temp.empty() && !fs::is_dir(vfs::get(dir))) { strcpy_trunc(*contentInfoPath, ""); strcpy_trunc(*usrdirPath, ""); - verify(HERE), fxm::remove(); return CELL_OK; } - if (!prm->temp.empty()) + if (!perm->temp.empty()) { - // Make temporary directory persistent - const auto vdir = vfs::get(dir); + // Create PARAM.SFO + psf::save_object(fs::file(perm->temp + "/PARAM.SFO", fs::rewrite), perm->sfo); - if (vfs::host::rename(prm->temp, vdir, false)) + // Make temporary directory persistent (atomically) + if (vfs::host::rename(perm->temp, vfs::get(dir), false)) { cellGame.success("cellGameContentPermit(): directory '%s' has been created", dir); + + // Prevent cleanup + perm->temp.clear(); } else { cellGame.error("cellGameContentPermit(): failed to initialize directory '%s' (%s)", dir, fs::g_tls_error); - strcpy_trunc(*contentInfoPath, dir); - strcpy_trunc(*usrdirPath, dir + "/USRDIR"); - verify(HERE), fxm::remove(); - return CELL_OK; } - - // 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(); - return CELL_OK; } @@ -620,9 +650,11 @@ error_code cellGameCreateGameData(vm::ptr init, vm::ptr(); + const auto prm = g_fxo->get(); - if (!prm || prm->dir.empty()) + const auto _init = prm->init.access(); + + if (!_init || prm->dir.empty()) { return CELL_GAME_ERROR_FAILURE; } @@ -689,9 +721,11 @@ error_code cellGameGetParamInt(s32 id, vm::ptr value) return CELL_GAME_ERROR_PARAM; } - const auto prm = fxm::get(); + const auto prm = g_fxo->get(); - if (!prm) + const auto init = prm->init.access(); + + if (!init) { return CELL_GAME_ERROR_FAILURE; } @@ -758,9 +792,11 @@ error_code cellGameGetParamString(s32 id, vm::ptr buf, u32 bufsize) return CELL_GAME_ERROR_PARAM; } - const auto prm = fxm::get(); + const auto prm = g_fxo->get(); - if (!prm) + const auto init = prm->init.access(); + + if (!init) { return CELL_GAME_ERROR_FAILURE; } @@ -789,9 +825,11 @@ error_code cellGameSetParamString(s32 id, vm::cptr buf) return CELL_GAME_ERROR_PARAM; } - const auto prm = fxm::get(); + const auto prm = g_fxo->get(); - if (!prm) + const auto init = prm->init.access(); + + if (!init) { return CELL_GAME_ERROR_FAILURE; } @@ -827,9 +865,11 @@ error_code cellGameGetSizeKB(vm::ptr size) return CELL_GAME_ERROR_PARAM; } - const auto prm = fxm::get(); + const auto prm = g_fxo->get(); - if (!prm) + const auto init = prm->init.access(); + + if (!init) { return CELL_GAME_ERROR_FAILURE; }