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
+1 -1
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.
+1
View File
@@ -0,0 +1 @@
This directory is used for temporary gamedata functionality, so don't store any data here.
+35
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;
}
}
+98 -54
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);