Added fxm::withdraw, cellGame improved

This commit is contained in:
Nekotekina 2015-08-06 18:55:19 +03:00
parent 6f3c50eba2
commit 544fe531a3
4 changed files with 135 additions and 55 deletions

View File

@ -1 +1 @@
every Folder in this directory gets cleared when cellSysCacheClear() is called, so don't store important data here
This directory is used for cache functionality, so don't store any data here.

View File

@ -0,0 +1 @@
This directory is used for temporary gamedata functionality, so don't store any data here.

View File

@ -269,6 +269,21 @@ namespace fxm
return nullptr;
}
// add fixed object of specified type, replacing previous one if it exists
template<typename T, typename... Args> std::enable_if_t<std::is_constructible<T, Args...>::value, std::shared_ptr<T>> make_always(Args&&... args)
{
extern std::mutex g_fx_mutex;
extern std::unordered_map<std::type_index, std::shared_ptr<void>> g_fx_map;
std::lock_guard<std::mutex> lock(g_fx_mutex);
auto ptr = std::make_shared<T>(std::forward<Args>(args)...);
g_fx_map[typeid(T)] = ptr;
return ptr;
}
// check whether the object exists
template<typename T> bool check()
{
@ -315,4 +330,24 @@ namespace fxm
return g_fx_map.erase(found), true;
}
// remove fixed object created with type T and return it
template<typename T> std::shared_ptr<T> withdraw()
{
extern std::mutex g_fx_mutex;
extern std::unordered_map<std::type_index, std::shared_ptr<void>> g_fx_map;
std::lock_guard<std::mutex> lock(g_fx_mutex);
const auto found = g_fx_map.find(typeid(T));
if (found == g_fx_map.end())
{
return nullptr;
}
auto ptr = std::static_pointer_cast<T>(std::move(found->second));
return g_fx_map.erase(found), ptr;
}
}

View File

@ -1,6 +1,7 @@
#include "stdafx.h"
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/IdManager.h"
#include "Emu/SysCalls/Modules.h"
#include "Utilities/rMsgBox.h"
@ -12,9 +13,45 @@
extern Module cellGame;
std::string contentInfo;
std::string usrdir;
bool path_set = false;
// Specified as second content_permission_t constructor argument to inform temporary directory
static struct temporary_content_dir_tag_t{} const temporary_content_dir_tag{};
// Normal content directory (if is_temporary is not involved):
// contentInfo = dir
// usrdir = dir + "/USRDIR"
// Temporary content directory:
// contentInfo = "/dev_hdd1/game/" + dir
// usrdir = "/dev_hdd1/game/" + dir + "/USRDIR"
// Usual (persistent) content directory (if is_temporary):
// contentInfo = "/dev_hdd0/game/" + dir
// usrdir = "/dev_hdd0/game/" + dir + "/USRDIR"
struct content_permission_t final
{
// content directory name or path
const std::string dir;
// true if temporary directory is created and must be moved or deleted
bool is_temporary = false;
content_permission_t(const std::string& dir)
: dir(dir)
{
}
content_permission_t(const std::string& dir, const temporary_content_dir_tag_t&)
: dir(dir)
, is_temporary(true)
{
}
~content_permission_t()
{
if (is_temporary)
{
// TODO: delete temporary directory and all its contents
}
}
};
s32 cellHddGameCheck(PPUThread& CPU, u32 version, vm::cptr<char> dirName, u32 errDialog, vm::ptr<CellHddGameStatCallback> funcStat, u32 container)
{
@ -155,19 +192,23 @@ s32 cellGameBootCheck(vm::ptr<u32> type, vm::ptr<u32> attributes, vm::ptr<CellGa
*type = CELL_GAME_GAMETYPE_DISC;
*attributes = 0; // TODO
if (dirName) strcpy_trunc(*dirName, ""); // ???
contentInfo = "/dev_bdvd/PS3_GAME";
usrdir = "/dev_bdvd/PS3_GAME/USRDIR";
path_set = true;
if (!fxm::make<content_permission_t>("/dev_bdvd/PS3_GAME"))
{
return CELL_GAME_ERROR_BUSY;
}
}
else if (category.substr(0, 2) == "HG")
{
std::string titleId = psf.GetString("TITLE_ID");
*type = CELL_GAME_GAMETYPE_HDD;
*attributes = 0; // TODO
if (dirName) strcpy_trunc(*dirName, titleId);
contentInfo = "/dev_hdd0/game/" + titleId;
usrdir = "/dev_hdd0/game/" + titleId + "/USRDIR";
path_set = true;
if (dirName) strcpy_trunc(*dirName, titleId);
if (!fxm::make<content_permission_t>("/dev_hdd0/game/" + titleId))
{
return CELL_GAME_ERROR_BUSY;
}
}
else if (category.substr(0, 2) == "GD")
{
@ -175,9 +216,11 @@ s32 cellGameBootCheck(vm::ptr<u32> type, vm::ptr<u32> attributes, vm::ptr<CellGa
*type = CELL_GAME_GAMETYPE_DISC;
*attributes = CELL_GAME_ATTRIBUTE_PATCH; // TODO
if (dirName) strcpy_trunc(*dirName, titleId); // ???
contentInfo = "/dev_bdvd/PS3_GAME";
usrdir = "/dev_bdvd/PS3_GAME/USRDIR";
path_set = true;
if (!fxm::make<content_permission_t>("/dev_bdvd/PS3_GAME"))
{
return CELL_GAME_ERROR_BUSY;
}
}
else if (psf)
{
@ -216,12 +259,12 @@ s32 cellGamePatchCheck(vm::ptr<CellGameContentSize> size, vm::ptr<void> reserved
return CELL_GAME_ERROR_NOTPATCH;
}
std::string titleId = psf.GetString("TITLE_ID");
contentInfo = "/dev_hdd0/game/" + titleId;
usrdir = "/dev_hdd0/game/" + titleId + "/USRDIR";
path_set = true;
if (!fxm::make<content_permission_t>("/dev_hdd0/game/" + psf.GetString("TITLE_ID")))
{
return CELL_GAME_ERROR_BUSY;
}
return CELL_GAME_RET_OK;
return CELL_OK;
}
s32 cellGameDataCheck(u32 type, vm::cptr<char> dirName, vm::ptr<CellGameContentSize> size)
@ -251,15 +294,13 @@ s32 cellGameDataCheck(u32 type, vm::cptr<char> dirName, vm::ptr<CellGameContentS
if (!Emu.GetVFS().ExistsDir("/dev_bdvd/PS3_GAME"))
{
cellGame.Warning("cellGameDataCheck(): /dev_bdvd/PS3_GAME not found");
contentInfo = "";
usrdir = "";
path_set = true;
return CELL_GAME_RET_NONE;
}
contentInfo = "/dev_bdvd/PS3_GAME";
usrdir = "/dev_bdvd/PS3_GAME/USRDIR";
path_set = true;
if (!fxm::make<content_permission_t>("/dev_bdvd/PS3_GAME"))
{
return CELL_GAME_ERROR_BUSY;
}
}
else
{
@ -268,15 +309,13 @@ s32 cellGameDataCheck(u32 type, vm::cptr<char> dirName, vm::ptr<CellGameContentS
if (!Emu.GetVFS().ExistsDir(dir))
{
cellGame.Warning("cellGameDataCheck(): '%s' directory not found", dir.c_str());
contentInfo = "";
usrdir = "";
path_set = true;
return CELL_GAME_RET_NONE;
}
contentInfo = dir;
usrdir = dir + "/USRDIR";
path_set = true;
if (!fxm::make<content_permission_t>(dir))
{
return CELL_GAME_ERROR_BUSY;
}
}
return CELL_GAME_RET_OK;
@ -291,32 +330,40 @@ s32 cellGameContentPermit(vm::ptr<char[CELL_GAME_PATH_MAX]> contentInfoPath, vm:
return CELL_GAME_ERROR_PARAM;
}
cellGame.Warning("cellGameContentPermit(): path_set=%d, contentInfo='%s', usrdir='%s'", path_set, contentInfo, usrdir);
const auto path_set = fxm::withdraw<content_permission_t>();
if (!path_set)
{
return CELL_GAME_ERROR_FAILURE;
}
if (contentInfo.size() == 9 && usrdir.empty())
if (path_set->is_temporary)
{
if (Emu.GetVFS().RenameDir("/dev_hdd0/game/TMP_" + contentInfo, "/dev_hdd0/game/" + contentInfo))
const std::string dir = "/dev_hdd0/game/" + path_set->dir;
// make temporary directory persistent
if (Emu.GetVFS().RenameDir("/dev_hdd1/game/" + path_set->dir, dir))
{
cellGame.Success("cellGameContentPermit(): gamedata directory created ('/dev_hdd0/game/%s')", contentInfo);
cellGame.Success("cellGameContentPermit(): '%s' directory created", dir);
}
else
{
throw EXCEPTION("Cannot create gamedata directory");
}
contentInfo = "/dev_hdd0/game/" + contentInfo;
usrdir = contentInfo + "/USRDIR";
// prevent deleting directory
path_set->is_temporary = false;
strcpy_trunc(*contentInfoPath, dir);
strcpy_trunc(*usrdirPath, dir + "/USRDIR");
}
else
{
strcpy_trunc(*contentInfoPath, path_set->dir);
strcpy_trunc(*usrdirPath, path_set->dir + "/USRDIR");
}
strcpy_trunc(*contentInfoPath, contentInfo);
strcpy_trunc(*usrdirPath, usrdir);
contentInfo = "";
usrdir = "";
path_set = false;
return CELL_GAME_RET_OK;
return CELL_OK;
}
s32 cellGameDataCheckCreate2(PPUThread& CPU, u32 version, vm::cptr<char> dirName, u32 errDialog, vm::ptr<CellGameDataStatCallback> funcStat, u32 container)
@ -429,8 +476,8 @@ s32 cellGameCreateGameData(vm::ptr<CellGameSetInitParams> init, vm::ptr<char[CEL
cellGame.Error("cellGameCreateGameData(init=*0x%x, tmp_contentInfoPath=*0x%x, tmp_usrdirPath=*0x%x)", init, tmp_contentInfoPath, tmp_usrdirPath);
std::string dir = init->titleId;
std::string tmp_contentInfo = "/dev_hdd0/game/TMP_" + dir;
std::string tmp_usrdir = "/dev_hdd0/game/TMP_" + dir + "/USRDIR";
std::string tmp_contentInfo = "/dev_hdd1/game/" + dir;
std::string tmp_usrdir = "/dev_hdd1/game/" + dir + "/USRDIR";
if (!Emu.GetVFS().CreateDir(tmp_contentInfo))
{
@ -444,14 +491,15 @@ s32 cellGameCreateGameData(vm::ptr<CellGameSetInitParams> init, vm::ptr<char[CEL
return CELL_GAME_ERROR_ACCESS_ERROR; // ???
}
if (!fxm::make<content_permission_t>(dir, temporary_content_dir_tag))
{
return CELL_GAME_ERROR_BUSY;
}
// 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);
contentInfo = dir;
usrdir.clear();
path_set = true;
cellGame.Success("cellGameCreateGameData(): temporary gamedata directory created ('%s')", tmp_contentInfo);
// TODO: set initial PARAM.SFO parameters
@ -665,10 +713,6 @@ void cellSysutil_GameData_init()
Module cellGame("cellGame", []()
{
contentInfo = "";
usrdir = "";
path_set = false;
REG_FUNC(cellGame, cellGameBootCheck);
REG_FUNC(cellGame, cellGamePatchCheck);
REG_FUNC(cellGame, cellGameDataCheck);