2013-09-28 04:36:57 +02:00
|
|
|
#include "stdafx.h"
|
2014-06-02 19:27:24 +02:00
|
|
|
#include "Emu/Memory/Memory.h"
|
|
|
|
|
#include "Emu/System.h"
|
2015-08-06 17:55:19 +02:00
|
|
|
#include "Emu/IdManager.h"
|
2014-06-02 19:27:24 +02:00
|
|
|
#include "Emu/SysCalls/Modules.h"
|
2013-09-28 04:36:57 +02:00
|
|
|
|
2014-08-26 01:55:37 +02:00
|
|
|
#include "Emu/FS/VFS.h"
|
2014-08-23 22:40:04 +02:00
|
|
|
#include "Emu/FS/vfsFile.h"
|
2013-11-23 05:47:19 +01:00
|
|
|
#include "Loader/PSF.h"
|
2015-04-13 16:05:44 +02:00
|
|
|
#include "cellSysutil.h"
|
2015-12-19 12:40:52 +01:00
|
|
|
#include "cellMsgDialog.h"
|
2014-07-01 00:53:29 +02:00
|
|
|
#include "cellGame.h"
|
|
|
|
|
|
2015-09-08 15:53:28 +02:00
|
|
|
extern Module<> cellGame;
|
2013-09-28 04:36:57 +02:00
|
|
|
|
2015-08-06 17:55:19 +02:00
|
|
|
// 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;
|
|
|
|
|
|
2015-12-19 12:40:52 +01:00
|
|
|
content_permission_t(const std::string& dir, bool is_temp)
|
2015-08-06 17:55:19 +02:00
|
|
|
: dir(dir)
|
2015-12-19 12:40:52 +01:00
|
|
|
, is_temporary(is_temp)
|
2015-08-06 17:55:19 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
~content_permission_t()
|
|
|
|
|
{
|
|
|
|
|
if (is_temporary)
|
|
|
|
|
{
|
2015-08-08 15:17:28 +02:00
|
|
|
Emu.GetVFS().DeleteAll("/dev_hdd1/game/" + dir);
|
2015-08-06 17:55:19 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
2014-06-28 03:19:44 +02:00
|
|
|
|
2015-08-13 15:28:42 +02:00
|
|
|
s32 cellHddGameCheck(PPUThread& ppu, u32 version, vm::cptr<char> dirName, u32 errDialog, vm::ptr<CellHddGameStatCallback> funcStat, u32 container)
|
2013-11-29 05:56:26 +01:00
|
|
|
{
|
2015-04-13 16:05:44 +02:00
|
|
|
cellGame.Warning("cellHddGameCheck(version=%d, dirName=*0x%x, errDialog=%d, funcStat=*0x%x, container=%d)", version, dirName, errDialog, funcStat, container);
|
|
|
|
|
|
|
|
|
|
std::string dir = dirName.get_ptr();
|
2015-04-16 01:17:42 +02:00
|
|
|
|
2015-04-13 16:05:44 +02:00
|
|
|
if (dir.size() != 9)
|
2015-04-16 01:17:42 +02:00
|
|
|
{
|
2015-04-13 16:05:44 +02:00
|
|
|
return CELL_HDDGAME_ERROR_PARAM;
|
2015-04-16 01:17:42 +02:00
|
|
|
}
|
2015-04-13 16:05:44 +02:00
|
|
|
|
2015-09-26 22:46:04 +02:00
|
|
|
vm::var<CellHddGameSystemFileParam> param;
|
|
|
|
|
vm::var<CellHddGameCBResult> result;
|
|
|
|
|
vm::var<CellHddGameStatGet> get;
|
|
|
|
|
vm::var<CellHddGameStatSet> set;
|
2015-04-13 16:05:44 +02:00
|
|
|
|
|
|
|
|
get->hddFreeSizeKB = 40 * 1024 * 1024; // 40 GB, TODO: Use the free space of the computer's HDD where RPCS3 is being run.
|
|
|
|
|
get->isNewData = CELL_HDDGAME_ISNEWDATA_EXIST;
|
|
|
|
|
get->sysSizeKB = 0; // TODO
|
|
|
|
|
get->atime = 0; // TODO
|
|
|
|
|
get->ctime = 0; // TODO
|
|
|
|
|
get->mtime = 0; // TODO
|
|
|
|
|
get->sizeKB = CELL_HDDGAME_SIZEKB_NOTCALC;
|
2015-04-16 01:17:42 +02:00
|
|
|
strcpy_trunc(get->contentInfoPath, "/dev_hdd0/game/" + dir);
|
|
|
|
|
strcpy_trunc(get->hddGamePath, "/dev_hdd0/game/" + dir + "/USRDIR");
|
2015-04-13 16:05:44 +02:00
|
|
|
|
2015-04-16 01:17:42 +02:00
|
|
|
if (!Emu.GetVFS().ExistsDir("/dev_hdd0/game/" + dir))
|
2015-04-13 16:05:44 +02:00
|
|
|
{
|
|
|
|
|
get->isNewData = CELL_HDDGAME_ISNEWDATA_NODIR;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// TODO: Is cellHddGameCheck really responsible for writing the information in get->getParam ? (If not, delete this else)
|
2015-04-17 15:56:32 +02:00
|
|
|
vfsFile f("/dev_hdd0/game/" + dir + "/PARAM.SFO");
|
|
|
|
|
const PSFLoader psf(f);
|
2015-04-16 01:17:42 +02:00
|
|
|
if (!psf)
|
|
|
|
|
{
|
2015-04-13 16:05:44 +02:00
|
|
|
return CELL_HDDGAME_ERROR_BROKEN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
get->getParam.parentalLevel = psf.GetInteger("PARENTAL_LEVEL");
|
|
|
|
|
get->getParam.attribute = psf.GetInteger("ATTRIBUTE");
|
|
|
|
|
get->getParam.resolution = psf.GetInteger("RESOLUTION");
|
|
|
|
|
get->getParam.soundFormat = psf.GetInteger("SOUND_FORMAT");
|
|
|
|
|
std::string title = psf.GetString("TITLE");
|
|
|
|
|
strcpy_trunc(get->getParam.title, title);
|
|
|
|
|
std::string app_ver = psf.GetString("APP_VER");
|
|
|
|
|
strcpy_trunc(get->getParam.dataVersion, app_ver);
|
|
|
|
|
strcpy_trunc(get->getParam.titleId, dir);
|
|
|
|
|
|
2015-04-16 01:17:42 +02:00
|
|
|
for (u32 i = 0; i < CELL_HDDGAME_SYSP_LANGUAGE_NUM; i++)
|
|
|
|
|
{
|
2015-08-31 05:26:16 +02:00
|
|
|
title = psf.GetString(fmt::format("TITLE_%02d", i));
|
2015-04-13 16:05:44 +02:00
|
|
|
strcpy_trunc(get->getParam.titleLang[i], title);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO ?
|
|
|
|
|
|
2015-09-10 15:09:31 +02:00
|
|
|
funcStat(ppu, result, get, set);
|
2015-04-13 16:05:44 +02:00
|
|
|
|
2015-09-10 15:09:31 +02:00
|
|
|
if (result->result != CELL_HDDGAME_CBRESULT_OK && result->result != CELL_HDDGAME_CBRESULT_OK_CANCEL)
|
|
|
|
|
{
|
|
|
|
|
return CELL_HDDGAME_ERROR_CBRESULT;
|
|
|
|
|
}
|
2015-04-13 16:05:44 +02:00
|
|
|
|
|
|
|
|
// TODO ?
|
|
|
|
|
|
|
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-01 18:14:49 +02:00
|
|
|
s32 cellHddGameCheck2()
|
|
|
|
|
{
|
|
|
|
|
throw EXCEPTION("");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 cellHddGameGetSizeKB()
|
|
|
|
|
{
|
|
|
|
|
throw EXCEPTION("");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 cellHddGameSetSystemVer()
|
|
|
|
|
{
|
|
|
|
|
throw EXCEPTION("");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 cellHddGameExitBroken()
|
|
|
|
|
{
|
|
|
|
|
throw EXCEPTION("");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
s32 cellGameDataGetSizeKB()
|
|
|
|
|
{
|
|
|
|
|
throw EXCEPTION("");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 cellGameDataSetSystemVer()
|
|
|
|
|
{
|
|
|
|
|
throw EXCEPTION("");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 cellGameDataExitBroken()
|
|
|
|
|
{
|
|
|
|
|
throw EXCEPTION("");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2015-04-13 16:05:44 +02:00
|
|
|
s32 cellGameBootCheck(vm::ptr<u32> type, vm::ptr<u32> attributes, vm::ptr<CellGameContentSize> size, vm::ptr<char[CELL_GAME_DIRNAME_SIZE]> dirName)
|
|
|
|
|
{
|
|
|
|
|
cellGame.Warning("cellGameBootCheck(type=*0x%x, attributes=*0x%x, size=*0x%x, dirName=*0x%x)", type, attributes, size, dirName);
|
2013-11-29 05:56:26 +01:00
|
|
|
|
2014-08-12 19:44:28 +02:00
|
|
|
if (size)
|
|
|
|
|
{
|
|
|
|
|
// TODO: Use the free space of the computer's HDD where RPCS3 is being run.
|
|
|
|
|
size->hddFreeSizeKB = 40000000; // 40 GB
|
2014-06-28 03:19:44 +02:00
|
|
|
|
2014-08-12 19:44:28 +02:00
|
|
|
// TODO: Calculate data size for HG and DG games, if necessary.
|
|
|
|
|
size->sizeKB = CELL_GAME_SIZEKB_NOTCALC;
|
|
|
|
|
size->sysSizeKB = 0;
|
|
|
|
|
}
|
2014-03-17 20:34:19 +01:00
|
|
|
|
2015-04-17 15:56:32 +02:00
|
|
|
vfsFile f("/app_home/../PARAM.SFO");
|
|
|
|
|
const PSFLoader psf(f);
|
2015-07-06 13:47:49 +02:00
|
|
|
|
2015-04-16 01:17:42 +02:00
|
|
|
if (!psf)
|
2014-06-28 03:19:44 +02:00
|
|
|
{
|
2015-07-09 19:19:29 +02:00
|
|
|
// According to testing (in debug mode) cellGameBootCheck doesn't return an error code, when PARAM.SFO doesn't exist.
|
|
|
|
|
cellGame.Error("cellGameBootCheck(): Cannot read PARAM.SFO.");
|
2014-06-28 03:19:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string category = psf.GetString("CATEGORY");
|
|
|
|
|
if (category.substr(0, 2) == "DG")
|
|
|
|
|
{
|
2014-09-01 02:51:48 +02:00
|
|
|
*type = CELL_GAME_GAMETYPE_DISC;
|
|
|
|
|
*attributes = 0; // TODO
|
2014-09-05 01:23:36 +02:00
|
|
|
if (dirName) strcpy_trunc(*dirName, ""); // ???
|
2015-08-06 17:55:19 +02:00
|
|
|
|
2015-12-19 12:40:52 +01:00
|
|
|
if (!fxm::make<content_permission_t>("/dev_bdvd/PS3_GAME", false))
|
2015-08-06 17:55:19 +02:00
|
|
|
{
|
|
|
|
|
return CELL_GAME_ERROR_BUSY;
|
|
|
|
|
}
|
2014-06-28 03:19:44 +02:00
|
|
|
}
|
|
|
|
|
else if (category.substr(0, 2) == "HG")
|
|
|
|
|
{
|
|
|
|
|
std::string titleId = psf.GetString("TITLE_ID");
|
2014-09-01 02:51:48 +02:00
|
|
|
*type = CELL_GAME_GAMETYPE_HDD;
|
|
|
|
|
*attributes = 0; // TODO
|
2015-08-06 17:55:19 +02:00
|
|
|
if (dirName) strcpy_trunc(*dirName, titleId);
|
|
|
|
|
|
2015-12-19 12:40:52 +01:00
|
|
|
if (!fxm::make<content_permission_t>("/dev_hdd0/game/" + titleId, false))
|
2015-08-06 17:55:19 +02:00
|
|
|
{
|
|
|
|
|
return CELL_GAME_ERROR_BUSY;
|
|
|
|
|
}
|
2014-06-28 03:19:44 +02:00
|
|
|
}
|
|
|
|
|
else if (category.substr(0, 2) == "GD")
|
|
|
|
|
{
|
|
|
|
|
std::string titleId = psf.GetString("TITLE_ID");
|
2014-09-01 02:51:48 +02:00
|
|
|
*type = CELL_GAME_GAMETYPE_DISC;
|
|
|
|
|
*attributes = CELL_GAME_ATTRIBUTE_PATCH; // TODO
|
2014-09-05 01:23:36 +02:00
|
|
|
if (dirName) strcpy_trunc(*dirName, titleId); // ???
|
2015-08-06 17:55:19 +02:00
|
|
|
|
2015-12-19 12:40:52 +01:00
|
|
|
if (!fxm::make<content_permission_t>("/dev_bdvd/PS3_GAME", false))
|
2015-08-06 17:55:19 +02:00
|
|
|
{
|
|
|
|
|
return CELL_GAME_ERROR_BUSY;
|
|
|
|
|
}
|
2014-06-28 03:19:44 +02:00
|
|
|
}
|
2015-07-06 13:47:49 +02:00
|
|
|
else if (psf)
|
2014-06-28 03:19:44 +02:00
|
|
|
{
|
2015-07-06 13:47:49 +02:00
|
|
|
cellGame.Error("cellGameBootCheck(): Unknown CATEGORY.");
|
2014-06-28 03:19:44 +02:00
|
|
|
}
|
2013-11-29 05:56:26 +01:00
|
|
|
|
2014-06-28 03:19:44 +02:00
|
|
|
return CELL_GAME_RET_OK;
|
2013-09-28 04:36:57 +02:00
|
|
|
}
|
|
|
|
|
|
2015-04-13 16:05:44 +02:00
|
|
|
s32 cellGamePatchCheck(vm::ptr<CellGameContentSize> size, vm::ptr<void> reserved)
|
2013-09-28 04:36:57 +02:00
|
|
|
{
|
2015-04-13 16:05:44 +02:00
|
|
|
cellGame.Warning("cellGamePatchCheck(size=*0x%x, reserved=*0x%x)", size, reserved);
|
2014-06-28 03:19:44 +02:00
|
|
|
|
2014-08-13 09:57:55 +02:00
|
|
|
if (size)
|
|
|
|
|
{
|
|
|
|
|
// TODO: Use the free space of the computer's HDD where RPCS3 is being run.
|
|
|
|
|
size->hddFreeSizeKB = 40000000; // 40 GB
|
2014-06-28 03:19:44 +02:00
|
|
|
|
2014-08-13 09:57:55 +02:00
|
|
|
// TODO: Calculate data size for patch data, if necessary.
|
|
|
|
|
size->sizeKB = CELL_GAME_SIZEKB_NOTCALC;
|
|
|
|
|
size->sysSizeKB = 0;
|
|
|
|
|
}
|
2014-06-28 03:19:44 +02:00
|
|
|
|
2015-04-17 15:56:32 +02:00
|
|
|
vfsFile f("/app_home/../PARAM.SFO");
|
|
|
|
|
const PSFLoader psf(f);
|
2015-04-16 01:17:42 +02:00
|
|
|
if (!psf)
|
2014-06-28 03:19:44 +02:00
|
|
|
{
|
2015-02-18 17:22:06 +01:00
|
|
|
cellGame.Error("cellGamePatchCheck(): CELL_GAME_ERROR_ACCESS_ERROR (cannot read PARAM.SFO)");
|
2014-06-28 03:19:44 +02:00
|
|
|
return CELL_GAME_ERROR_ACCESS_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string category = psf.GetString("CATEGORY");
|
|
|
|
|
if (category.substr(0, 2) != "GD")
|
|
|
|
|
{
|
2015-02-18 17:22:06 +01:00
|
|
|
cellGame.Error("cellGamePatchCheck(): CELL_GAME_ERROR_NOTPATCH");
|
2014-06-28 03:19:44 +02:00
|
|
|
return CELL_GAME_ERROR_NOTPATCH;
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-19 12:40:52 +01:00
|
|
|
if (!fxm::make<content_permission_t>("/dev_hdd0/game/" + psf.GetString("TITLE_ID"), false))
|
2015-08-06 17:55:19 +02:00
|
|
|
{
|
|
|
|
|
return CELL_GAME_ERROR_BUSY;
|
|
|
|
|
}
|
2014-06-28 03:19:44 +02:00
|
|
|
|
2015-08-06 17:55:19 +02:00
|
|
|
return CELL_OK;
|
2013-09-28 04:36:57 +02:00
|
|
|
}
|
|
|
|
|
|
2015-06-22 00:27:58 +02:00
|
|
|
s32 cellGameDataCheck(u32 type, vm::cptr<char> dirName, vm::ptr<CellGameContentSize> size)
|
2013-09-28 04:36:57 +02:00
|
|
|
{
|
2015-04-13 16:05:44 +02:00
|
|
|
cellGame.Warning("cellGameDataCheck(type=%d, dirName=*0x%x, size=*0x%x)", type, dirName, size);
|
2014-06-28 03:19:44 +02:00
|
|
|
|
2014-08-05 12:18:22 +02:00
|
|
|
if ((type - 1) >= 3)
|
2014-06-28 03:19:44 +02:00
|
|
|
{
|
2015-02-18 17:22:06 +01:00
|
|
|
cellGame.Error("cellGameDataCheck(): CELL_GAME_ERROR_PARAM");
|
2014-06-28 03:19:44 +02:00
|
|
|
return CELL_GAME_ERROR_PARAM;
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-13 09:57:55 +02:00
|
|
|
if (size)
|
|
|
|
|
{
|
|
|
|
|
// TODO: Use the free space of the computer's HDD where RPCS3 is being run.
|
|
|
|
|
size->hddFreeSizeKB = 40000000; //40 GB
|
2014-06-28 03:19:44 +02:00
|
|
|
|
2014-08-13 09:57:55 +02:00
|
|
|
// TODO: Calculate data size for game data, if necessary.
|
|
|
|
|
size->sizeKB = CELL_GAME_SIZEKB_NOTCALC;
|
|
|
|
|
size->sysSizeKB = 0;
|
|
|
|
|
}
|
2014-06-28 03:19:44 +02:00
|
|
|
|
|
|
|
|
if (type == CELL_GAME_GAMETYPE_DISC)
|
|
|
|
|
{
|
|
|
|
|
// TODO: not sure what should be checked there
|
|
|
|
|
|
|
|
|
|
if (!Emu.GetVFS().ExistsDir("/dev_bdvd/PS3_GAME"))
|
|
|
|
|
{
|
2015-02-18 17:22:06 +01:00
|
|
|
cellGame.Warning("cellGameDataCheck(): /dev_bdvd/PS3_GAME not found");
|
2014-06-28 03:19:44 +02:00
|
|
|
return CELL_GAME_RET_NONE;
|
|
|
|
|
}
|
2015-02-12 21:10:25 +01:00
|
|
|
|
2015-12-19 12:40:52 +01:00
|
|
|
if (!fxm::make<content_permission_t>("/dev_bdvd/PS3_GAME", false))
|
2015-08-06 17:55:19 +02:00
|
|
|
{
|
|
|
|
|
return CELL_GAME_ERROR_BUSY;
|
|
|
|
|
}
|
2014-06-28 03:19:44 +02:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2015-08-21 13:07:31 +02:00
|
|
|
const std::string dir = "/dev_hdd0/game/"s + dirName.get_ptr();
|
2014-06-28 03:19:44 +02:00
|
|
|
|
|
|
|
|
if (!Emu.GetVFS().ExistsDir(dir))
|
|
|
|
|
{
|
2015-02-18 17:22:06 +01:00
|
|
|
cellGame.Warning("cellGameDataCheck(): '%s' directory not found", dir.c_str());
|
2014-06-28 03:19:44 +02:00
|
|
|
return CELL_GAME_RET_NONE;
|
|
|
|
|
}
|
2015-02-12 21:10:25 +01:00
|
|
|
|
2015-12-19 12:40:52 +01:00
|
|
|
if (!fxm::make<content_permission_t>(dir, false))
|
2015-08-06 17:55:19 +02:00
|
|
|
{
|
|
|
|
|
return CELL_GAME_ERROR_BUSY;
|
|
|
|
|
}
|
2014-06-28 03:19:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return CELL_GAME_RET_OK;
|
2013-09-28 04:36:57 +02:00
|
|
|
}
|
|
|
|
|
|
2015-04-13 16:05:44 +02:00
|
|
|
s32 cellGameContentPermit(vm::ptr<char[CELL_GAME_PATH_MAX]> contentInfoPath, vm::ptr<char[CELL_GAME_PATH_MAX]> usrdirPath)
|
2013-09-28 04:36:57 +02:00
|
|
|
{
|
2015-04-13 16:05:44 +02:00
|
|
|
cellGame.Warning("cellGameContentPermit(contentInfoPath=*0x%x, usrdirPath=*0x%x)", contentInfoPath, usrdirPath);
|
2014-11-19 16:17:29 +01:00
|
|
|
|
2015-04-20 17:53:31 +02:00
|
|
|
if (!contentInfoPath && !usrdirPath)
|
2014-11-19 16:17:29 +01:00
|
|
|
{
|
|
|
|
|
return CELL_GAME_ERROR_PARAM;
|
|
|
|
|
}
|
2015-04-13 16:05:44 +02:00
|
|
|
|
2015-08-06 17:55:19 +02:00
|
|
|
const auto path_set = fxm::withdraw<content_permission_t>();
|
2013-12-07 21:56:42 +01:00
|
|
|
|
2015-02-12 21:10:25 +01:00
|
|
|
if (!path_set)
|
2014-06-28 03:19:44 +02:00
|
|
|
{
|
2014-03-12 23:34:35 +01:00
|
|
|
return CELL_GAME_ERROR_FAILURE;
|
2014-06-28 03:19:44 +02:00
|
|
|
}
|
2014-03-12 23:34:35 +01:00
|
|
|
|
2015-08-06 17:55:19 +02:00
|
|
|
if (path_set->is_temporary)
|
2015-04-20 17:53:31 +02:00
|
|
|
{
|
2015-08-06 17:55:19 +02:00
|
|
|
const std::string dir = "/dev_hdd0/game/" + path_set->dir;
|
|
|
|
|
|
|
|
|
|
// make temporary directory persistent
|
2015-08-08 15:17:28 +02:00
|
|
|
if (Emu.GetVFS().Rename("/dev_hdd1/game/" + path_set->dir, dir))
|
2015-04-20 17:53:31 +02:00
|
|
|
{
|
2015-08-06 17:55:19 +02:00
|
|
|
cellGame.Success("cellGameContentPermit(): '%s' directory created", dir);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
throw EXCEPTION("Cannot create gamedata directory");
|
2015-04-20 17:53:31 +02:00
|
|
|
}
|
|
|
|
|
|
2015-08-06 17:55:19 +02:00
|
|
|
// prevent deleting directory
|
|
|
|
|
path_set->is_temporary = false;
|
2014-06-28 03:19:44 +02:00
|
|
|
|
2015-08-06 17:55:19 +02:00
|
|
|
strcpy_trunc(*contentInfoPath, dir);
|
|
|
|
|
strcpy_trunc(*usrdirPath, dir + "/USRDIR");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
strcpy_trunc(*contentInfoPath, path_set->dir);
|
|
|
|
|
strcpy_trunc(*usrdirPath, path_set->dir + "/USRDIR");
|
|
|
|
|
}
|
2014-06-28 03:19:44 +02:00
|
|
|
|
2015-08-06 17:55:19 +02:00
|
|
|
return CELL_OK;
|
2014-06-28 03:19:44 +02:00
|
|
|
}
|
|
|
|
|
|
2015-08-13 15:28:42 +02:00
|
|
|
s32 cellGameDataCheckCreate2(PPUThread& ppu, u32 version, vm::cptr<char> dirName, u32 errDialog, vm::ptr<CellGameDataStatCallback> funcStat, u32 container)
|
2014-06-28 03:19:44 +02:00
|
|
|
{
|
2015-04-13 16:05:44 +02:00
|
|
|
cellGame.Warning("cellGameDataCheckCreate2(version=0x%x, dirName=*0x%x, errDialog=0x%x, funcStat=*0x%x, container=%d)", version, dirName, errDialog, funcStat, container);
|
2014-07-01 00:53:29 +02:00
|
|
|
|
2014-08-05 12:18:22 +02:00
|
|
|
if (version != CELL_GAMEDATA_VERSION_CURRENT || errDialog > 1)
|
2014-07-01 00:53:29 +02:00
|
|
|
{
|
2015-04-13 16:05:44 +02:00
|
|
|
cellGame.Error("cellGameDataCheckCreate2(): CELL_GAMEDATA_ERROR_PARAM");
|
2014-07-01 00:53:29 +02:00
|
|
|
return CELL_GAMEDATA_ERROR_PARAM;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: output errors (errDialog)
|
|
|
|
|
|
2015-08-21 13:07:31 +02:00
|
|
|
const std::string dir = "/dev_hdd0/game/"s + dirName.get_ptr();
|
2014-07-01 00:53:29 +02:00
|
|
|
|
|
|
|
|
if (!Emu.GetVFS().ExistsDir(dir))
|
|
|
|
|
{
|
2015-04-13 16:05:44 +02:00
|
|
|
cellGame.Todo("cellGameDataCheckCreate2(): creating directory '%s'", dir.c_str());
|
2014-07-01 00:53:29 +02:00
|
|
|
// TODO: create data
|
|
|
|
|
return CELL_GAMEDATA_RET_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-17 15:56:32 +02:00
|
|
|
vfsFile f("/app_home/../PARAM.SFO");
|
|
|
|
|
const PSFLoader psf(f);
|
2015-04-16 01:17:42 +02:00
|
|
|
if (!psf)
|
2014-07-01 00:53:29 +02:00
|
|
|
{
|
2015-04-13 16:05:44 +02:00
|
|
|
cellGame.Error("cellGameDataCheckCreate2(): CELL_GAMEDATA_ERROR_BROKEN (cannot read PARAM.SFO)");
|
2014-07-01 00:53:29 +02:00
|
|
|
return CELL_GAMEDATA_ERROR_BROKEN;
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-26 22:46:04 +02:00
|
|
|
vm::var<CellGameDataCBResult> cbResult;
|
|
|
|
|
vm::var<CellGameDataStatGet> cbGet;
|
|
|
|
|
vm::var<CellGameDataStatSet> cbSet;
|
2014-07-01 00:53:29 +02:00
|
|
|
|
|
|
|
|
// 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;
|
2014-07-01 17:34:25 +02:00
|
|
|
strcpy_trunc(cbGet->contentInfoPath, dir);
|
|
|
|
|
strcpy_trunc(cbGet->gameDataPath, dir + "/USRDIR");
|
2014-07-01 00:53:29 +02:00
|
|
|
|
|
|
|
|
// TODO: set correct time
|
2014-07-01 17:34:25 +02:00
|
|
|
cbGet->st_atime_ = 0;
|
|
|
|
|
cbGet->st_ctime_ = 0;
|
|
|
|
|
cbGet->st_mtime_ = 0;
|
2014-07-01 00:53:29 +02:00
|
|
|
|
|
|
|
|
// TODO: calculate data size, if necessary
|
|
|
|
|
cbGet->sizeKB = CELL_GAMEDATA_SIZEKB_NOTCALC;
|
|
|
|
|
cbGet->sysSizeKB = 0;
|
|
|
|
|
|
|
|
|
|
cbGet->getParam.attribute = CELL_GAMEDATA_ATTR_NORMAL;
|
|
|
|
|
cbGet->getParam.parentalLevel = psf.GetInteger("PARENTAL_LEVEL");
|
2014-07-01 17:34:25 +02:00
|
|
|
strcpy_trunc(cbGet->getParam.dataVersion, psf.GetString("APP_VER"));
|
|
|
|
|
strcpy_trunc(cbGet->getParam.titleId, psf.GetString("TITLE_ID"));
|
|
|
|
|
strcpy_trunc(cbGet->getParam.title, psf.GetString("TITLE"));
|
2014-07-01 00:53:29 +02:00
|
|
|
// TODO: write lang titles
|
|
|
|
|
|
2015-08-13 15:28:42 +02:00
|
|
|
funcStat(ppu, cbResult, cbGet, cbSet);
|
2014-07-01 00:53:29 +02:00
|
|
|
|
2014-09-02 00:22:13 +02:00
|
|
|
if (cbSet->setParam)
|
2014-07-01 00:53:29 +02:00
|
|
|
{
|
|
|
|
|
// TODO: write PARAM.SFO from cbSet
|
2015-04-13 16:05:44 +02:00
|
|
|
cellGame.Todo("cellGameDataCheckCreate2(): writing PARAM.SFO parameters (addr=0x%x)", cbSet->setParam);
|
2014-07-01 00:53:29 +02:00
|
|
|
}
|
|
|
|
|
|
2014-07-01 20:42:05 +02:00
|
|
|
switch ((s32)cbResult->result)
|
2014-07-01 00:53:29 +02:00
|
|
|
{
|
2014-07-01 19:50:57 +02:00
|
|
|
case CELL_GAMEDATA_CBRESULT_OK_CANCEL:
|
2014-07-01 00:53:29 +02:00
|
|
|
// TODO: do not process game data
|
2015-04-13 16:05:44 +02:00
|
|
|
cellGame.Warning("cellGameDataCheckCreate2(): callback returned CELL_GAMEDATA_CBRESULT_OK_CANCEL");
|
2014-07-01 00:53:29 +02:00
|
|
|
|
2014-07-01 19:50:57 +02:00
|
|
|
case CELL_GAMEDATA_CBRESULT_OK:
|
2014-07-01 00:53:29 +02:00
|
|
|
return CELL_GAMEDATA_RET_OK;
|
|
|
|
|
|
2014-07-01 19:50:57 +02:00
|
|
|
case CELL_GAMEDATA_CBRESULT_ERR_NOSPACE: // TODO: process errors, error message and needSizeKB result
|
2015-04-13 16:05:44 +02:00
|
|
|
cellGame.Error("cellGameDataCheckCreate2(): callback returned CELL_GAMEDATA_CBRESULT_ERR_NOSPACE");
|
2014-07-01 00:53:29 +02:00
|
|
|
return CELL_GAMEDATA_ERROR_CBRESULT;
|
|
|
|
|
|
2014-07-01 19:50:57 +02:00
|
|
|
case CELL_GAMEDATA_CBRESULT_ERR_BROKEN:
|
2015-04-13 16:05:44 +02:00
|
|
|
cellGame.Error("cellGameDataCheckCreate2(): callback returned CELL_GAMEDATA_CBRESULT_ERR_BROKEN");
|
2014-07-01 00:53:29 +02:00
|
|
|
return CELL_GAMEDATA_ERROR_CBRESULT;
|
|
|
|
|
|
2014-07-01 19:50:57 +02:00
|
|
|
case CELL_GAMEDATA_CBRESULT_ERR_NODATA:
|
2015-04-13 16:05:44 +02:00
|
|
|
cellGame.Error("cellGameDataCheckCreate2(): callback returned CELL_GAMEDATA_CBRESULT_ERR_NODATA");
|
2014-07-01 00:53:29 +02:00
|
|
|
return CELL_GAMEDATA_ERROR_CBRESULT;
|
|
|
|
|
|
2014-07-01 19:50:57 +02:00
|
|
|
case CELL_GAMEDATA_CBRESULT_ERR_INVALID:
|
2015-04-13 16:05:44 +02:00
|
|
|
cellGame.Error("cellGameDataCheckCreate2(): callback returned CELL_GAMEDATA_CBRESULT_ERR_INVALID");
|
2014-07-01 00:53:29 +02:00
|
|
|
return CELL_GAMEDATA_ERROR_CBRESULT;
|
|
|
|
|
|
|
|
|
|
default:
|
2015-04-13 16:05:44 +02:00
|
|
|
cellGame.Error("cellGameDataCheckCreate2(): callback returned unknown error (code=0x%x)");
|
2014-07-01 00:53:29 +02:00
|
|
|
return CELL_GAMEDATA_ERROR_CBRESULT;
|
|
|
|
|
}
|
2013-09-28 04:36:57 +02:00
|
|
|
}
|
|
|
|
|
|
2015-08-13 15:28:42 +02:00
|
|
|
s32 cellGameDataCheckCreate(PPUThread& ppu, u32 version, vm::cptr<char> dirName, u32 errDialog, vm::ptr<CellGameDataStatCallback> funcStat, u32 container)
|
2014-06-28 03:19:44 +02:00
|
|
|
{
|
2015-04-13 16:05:44 +02:00
|
|
|
cellGame.Warning("cellGameDataCheckCreate(version=0x%x, dirName=*0x%x, errDialog=0x%x, funcStat=*0x%x, container=%d)", version, dirName, errDialog, funcStat, container);
|
|
|
|
|
|
2014-07-01 00:53:29 +02:00
|
|
|
// TODO: almost identical, the only difference is that this function will always calculate the size of game data
|
2015-08-13 15:28:42 +02:00
|
|
|
return cellGameDataCheckCreate2(ppu, version, dirName, errDialog, funcStat, container);
|
2014-06-28 03:19:44 +02:00
|
|
|
}
|
|
|
|
|
|
2015-04-13 16:05:44 +02:00
|
|
|
s32 cellGameCreateGameData(vm::ptr<CellGameSetInitParams> init, vm::ptr<char[CELL_GAME_PATH_MAX]> tmp_contentInfoPath, vm::ptr<char[CELL_GAME_PATH_MAX]> tmp_usrdirPath)
|
2013-09-28 04:36:57 +02:00
|
|
|
{
|
2015-04-13 16:05:44 +02:00
|
|
|
cellGame.Error("cellGameCreateGameData(init=*0x%x, tmp_contentInfoPath=*0x%x, tmp_usrdirPath=*0x%x)", init, tmp_contentInfoPath, tmp_usrdirPath);
|
|
|
|
|
|
2015-04-20 17:53:31 +02:00
|
|
|
std::string dir = init->titleId;
|
2015-08-06 17:55:19 +02:00
|
|
|
std::string tmp_contentInfo = "/dev_hdd1/game/" + dir;
|
|
|
|
|
std::string tmp_usrdir = "/dev_hdd1/game/" + dir + "/USRDIR";
|
2015-04-13 16:05:44 +02:00
|
|
|
|
2015-04-20 17:53:31 +02:00
|
|
|
if (!Emu.GetVFS().CreateDir(tmp_contentInfo))
|
2015-04-13 16:05:44 +02:00
|
|
|
{
|
2015-04-20 17:53:31 +02:00
|
|
|
cellGame.Error("cellGameCreateGameData(): failed to create content directory ('%s')", tmp_contentInfo);
|
2015-04-13 16:05:44 +02:00
|
|
|
return CELL_GAME_ERROR_ACCESS_ERROR; // ???
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-20 17:53:31 +02:00
|
|
|
if (!Emu.GetVFS().CreateDir(tmp_usrdir))
|
2015-04-13 16:05:44 +02:00
|
|
|
{
|
2015-04-20 17:53:31 +02:00
|
|
|
cellGame.Error("cellGameCreateGameData(): failed to create USRDIR directory ('%s')", tmp_usrdir);
|
2015-04-13 16:05:44 +02:00
|
|
|
return CELL_GAME_ERROR_ACCESS_ERROR; // ???
|
|
|
|
|
}
|
2014-06-29 05:21:57 +02:00
|
|
|
|
2015-12-19 12:40:52 +01:00
|
|
|
if (!fxm::make<content_permission_t>(dir, true))
|
2015-08-06 17:55:19 +02:00
|
|
|
{
|
|
|
|
|
return CELL_GAME_ERROR_BUSY;
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-29 05:21:57 +02:00
|
|
|
// cellGameContentPermit should then move files in non-temporary location and return their non-temporary displacement
|
2015-04-20 17:53:31 +02:00
|
|
|
strcpy_trunc(*tmp_contentInfoPath, tmp_contentInfo);
|
|
|
|
|
strcpy_trunc(*tmp_usrdirPath, tmp_usrdir);
|
|
|
|
|
|
|
|
|
|
cellGame.Success("cellGameCreateGameData(): temporary gamedata directory created ('%s')", tmp_contentInfo);
|
2015-04-13 16:05:44 +02:00
|
|
|
|
|
|
|
|
// TODO: set initial PARAM.SFO parameters
|
|
|
|
|
|
2013-09-28 04:36:57 +02:00
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-13 16:05:44 +02:00
|
|
|
s32 cellGameDeleteGameData()
|
2013-09-28 04:36:57 +02:00
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED_FUNC(cellGame);
|
|
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-13 16:05:44 +02:00
|
|
|
s32 cellGameGetParamInt(u32 id, vm::ptr<u32> value)
|
2013-09-28 04:36:57 +02:00
|
|
|
{
|
2015-04-13 16:05:44 +02:00
|
|
|
cellGame.Warning("cellGameGetParamInt(id=%d, value=*0x%x)", id, value);
|
2013-11-23 05:47:19 +01:00
|
|
|
|
2014-06-28 03:19:44 +02:00
|
|
|
// TODO: Access through cellGame***Check functions
|
2015-04-17 15:56:32 +02:00
|
|
|
vfsFile f("/app_home/../PARAM.SFO");
|
|
|
|
|
const PSFLoader psf(f);
|
2016-01-04 10:04:58 +01:00
|
|
|
|
2015-04-16 01:17:42 +02:00
|
|
|
if (!psf)
|
|
|
|
|
{
|
2013-11-23 05:47:19 +01:00
|
|
|
return CELL_GAME_ERROR_FAILURE;
|
2015-04-16 01:17:42 +02:00
|
|
|
}
|
2013-11-23 05:47:19 +01:00
|
|
|
|
|
|
|
|
switch(id)
|
2013-11-24 01:01:57 +01:00
|
|
|
{
|
2016-01-04 10:04:58 +01:00
|
|
|
case CELL_GAME_PARAMID_PARENTAL_LEVEL: *value = psf.GetInteger("PARENTAL_LEVEL"); break;
|
|
|
|
|
case CELL_GAME_PARAMID_RESOLUTION: *value = psf.GetInteger("RESOLUTION"); break;
|
|
|
|
|
case CELL_GAME_PARAMID_SOUND_FORMAT: *value = psf.GetInteger("SOUND_FORMAT"); break;
|
2013-11-23 05:47:19 +01:00
|
|
|
|
|
|
|
|
default:
|
2016-01-04 10:04:58 +01:00
|
|
|
cellGame.Error("cellGameGetParamInt(): Unimplemented parameter (%d)", id);
|
2013-11-23 05:47:19 +01:00
|
|
|
return CELL_GAME_ERROR_INVALID_ID;
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-28 04:36:57 +02:00
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-13 16:05:44 +02:00
|
|
|
s32 cellGameGetParamString(u32 id, vm::ptr<char> buf, u32 bufsize)
|
2013-11-23 05:47:19 +01:00
|
|
|
{
|
2015-04-13 16:05:44 +02:00
|
|
|
cellGame.Warning("cellGameGetParamString(id=%d, buf=*0x%x, bufsize=%d)", id, buf, bufsize);
|
2013-11-23 05:47:19 +01:00
|
|
|
|
2014-06-28 03:19:44 +02:00
|
|
|
// TODO: Access through cellGame***Check functions
|
2015-04-17 15:56:32 +02:00
|
|
|
vfsFile f("/app_home/../PARAM.SFO");
|
|
|
|
|
const PSFLoader psf(f);
|
2015-04-16 01:17:42 +02:00
|
|
|
if (!psf)
|
|
|
|
|
{
|
2013-11-23 05:47:19 +01:00
|
|
|
return CELL_GAME_ERROR_FAILURE;
|
2015-04-16 01:17:42 +02:00
|
|
|
}
|
2013-11-23 05:47:19 +01:00
|
|
|
|
2014-03-28 05:20:13 +01:00
|
|
|
std::string data;
|
2013-11-23 05:47:19 +01:00
|
|
|
switch(id)
|
|
|
|
|
{
|
2014-03-28 05:20:13 +01:00
|
|
|
case CELL_GAME_PARAMID_TITLE: data = psf.GetString("TITLE"); break; // TODO: Is this value correct?
|
|
|
|
|
case CELL_GAME_PARAMID_TITLE_DEFAULT: data = psf.GetString("TITLE"); break;
|
|
|
|
|
case CELL_GAME_PARAMID_TITLE_JAPANESE: data = psf.GetString("TITLE_00"); break;
|
|
|
|
|
case CELL_GAME_PARAMID_TITLE_ENGLISH: data = psf.GetString("TITLE_01"); break;
|
|
|
|
|
case CELL_GAME_PARAMID_TITLE_FRENCH: data = psf.GetString("TITLE_02"); break;
|
|
|
|
|
case CELL_GAME_PARAMID_TITLE_SPANISH: data = psf.GetString("TITLE_03"); break;
|
|
|
|
|
case CELL_GAME_PARAMID_TITLE_GERMAN: data = psf.GetString("TITLE_04"); break;
|
|
|
|
|
case CELL_GAME_PARAMID_TITLE_ITALIAN: data = psf.GetString("TITLE_05"); break;
|
|
|
|
|
case CELL_GAME_PARAMID_TITLE_DUTCH: data = psf.GetString("TITLE_06"); break;
|
|
|
|
|
case CELL_GAME_PARAMID_TITLE_PORTUGUESE: data = psf.GetString("TITLE_07"); break;
|
|
|
|
|
case CELL_GAME_PARAMID_TITLE_RUSSIAN: data = psf.GetString("TITLE_08"); break;
|
|
|
|
|
case CELL_GAME_PARAMID_TITLE_KOREAN: data = psf.GetString("TITLE_09"); break;
|
|
|
|
|
case CELL_GAME_PARAMID_TITLE_CHINESE_T: data = psf.GetString("TITLE_10"); break;
|
|
|
|
|
case CELL_GAME_PARAMID_TITLE_CHINESE_S: data = psf.GetString("TITLE_11"); break;
|
|
|
|
|
case CELL_GAME_PARAMID_TITLE_FINNISH: data = psf.GetString("TITLE_12"); break;
|
|
|
|
|
case CELL_GAME_PARAMID_TITLE_SWEDISH: data = psf.GetString("TITLE_13"); break;
|
|
|
|
|
case CELL_GAME_PARAMID_TITLE_DANISH: data = psf.GetString("TITLE_14"); break;
|
|
|
|
|
case CELL_GAME_PARAMID_TITLE_NORWEGIAN: data = psf.GetString("TITLE_15"); break;
|
|
|
|
|
case CELL_GAME_PARAMID_TITLE_POLISH: data = psf.GetString("TITLE_16"); break;
|
|
|
|
|
case CELL_GAME_PARAMID_TITLE_PORTUGUESE_BRAZIL: data = psf.GetString("TITLE_17"); break;
|
|
|
|
|
case CELL_GAME_PARAMID_TITLE_ENGLISH_UK: data = psf.GetString("TITLE_18"); break;
|
|
|
|
|
|
|
|
|
|
case CELL_GAME_PARAMID_TITLE_ID: data = psf.GetString("TITLE_ID"); break;
|
|
|
|
|
case CELL_GAME_PARAMID_VERSION: data = psf.GetString("PS3_SYSTEM_VER"); break;
|
|
|
|
|
case CELL_GAME_PARAMID_APP_VER: data = psf.GetString("APP_VER"); break;
|
2013-11-23 05:47:19 +01:00
|
|
|
|
|
|
|
|
default:
|
2016-01-04 10:04:58 +01:00
|
|
|
cellGame.Error("cellGameGetParamString(): Unimplemented parameter (%d)", id);
|
2013-11-23 05:47:19 +01:00
|
|
|
return CELL_GAME_ERROR_INVALID_ID;
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-05 01:23:36 +02:00
|
|
|
if (data.size() >= bufsize) data.resize(bufsize - 1);
|
|
|
|
|
memcpy(buf.get_ptr(), data.c_str(), data.size() + 1);
|
2013-09-28 04:36:57 +02:00
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-13 16:05:44 +02:00
|
|
|
s32 cellGameSetParamString()
|
2013-09-28 04:36:57 +02:00
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED_FUNC(cellGame);
|
|
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-13 16:05:44 +02:00
|
|
|
s32 cellGameGetSizeKB()
|
2013-09-28 04:36:57 +02:00
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED_FUNC(cellGame);
|
|
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-13 16:05:44 +02:00
|
|
|
s32 cellGameGetDiscContentInfoUpdatePath()
|
2013-09-28 04:36:57 +02:00
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED_FUNC(cellGame);
|
|
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-13 16:05:44 +02:00
|
|
|
s32 cellGameGetLocalWebContentPath()
|
2013-09-28 04:36:57 +02:00
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED_FUNC(cellGame);
|
|
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-22 00:27:58 +02:00
|
|
|
s32 cellGameContentErrorDialog(s32 type, s32 errNeedSizeKB, vm::cptr<char> dirName)
|
2013-09-28 04:36:57 +02:00
|
|
|
{
|
2015-04-13 16:05:44 +02:00
|
|
|
cellGame.Warning("cellGameContentErrorDialog(type=%d, errNeedSizeKB=%d, dirName=*0x%x)", type, errNeedSizeKB, dirName);
|
2014-08-12 22:27:13 +02:00
|
|
|
|
2014-09-05 19:23:00 +02:00
|
|
|
std::string errorName;
|
2014-08-12 22:27:13 +02:00
|
|
|
switch (type)
|
|
|
|
|
{
|
|
|
|
|
case CELL_GAME_ERRDIALOG_BROKEN_GAMEDATA: errorName = "Game data is corrupted (can be continued)."; break;
|
|
|
|
|
case CELL_GAME_ERRDIALOG_BROKEN_HDDGAME: errorName = "HDD boot game is corrupted (can be continued)."; break;
|
|
|
|
|
case CELL_GAME_ERRDIALOG_NOSPACE: errorName = "Not enough available space (can be continued)."; break;
|
|
|
|
|
case CELL_GAME_ERRDIALOG_BROKEN_EXIT_GAMEDATA: errorName = "Game data is corrupted (terminate application)."; break;
|
|
|
|
|
case CELL_GAME_ERRDIALOG_BROKEN_EXIT_HDDGAME: errorName = "HDD boot game is corrupted (terminate application)."; break;
|
|
|
|
|
case CELL_GAME_ERRDIALOG_NOSPACE_EXIT: errorName = "Not enough available space (terminate application)."; break;
|
|
|
|
|
default: return CELL_GAME_ERROR_PARAM;
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-05 19:23:00 +02:00
|
|
|
std::string errorMsg;
|
2014-08-13 08:39:45 +02:00
|
|
|
if (type == CELL_GAME_ERRDIALOG_NOSPACE || type == CELL_GAME_ERRDIALOG_NOSPACE_EXIT)
|
2014-08-12 22:27:13 +02:00
|
|
|
{
|
2015-01-18 23:54:56 +01:00
|
|
|
errorMsg = fmt::format("ERROR: %s\nSpace needed: %d KB", errorName, errNeedSizeKB);
|
2014-08-12 22:27:13 +02:00
|
|
|
}
|
|
|
|
|
else
|
2014-02-11 03:47:25 +01:00
|
|
|
{
|
2015-01-18 23:54:56 +01:00
|
|
|
errorMsg = fmt::format("ERROR: %s", errorName);
|
2014-02-11 03:47:25 +01:00
|
|
|
}
|
|
|
|
|
|
2014-09-05 19:23:00 +02:00
|
|
|
if (dirName)
|
|
|
|
|
{
|
2015-08-12 20:38:17 +02:00
|
|
|
errorMsg += fmt::format("\nDirectory name: %s", dirName.get_ptr());
|
2014-09-05 19:23:00 +02:00
|
|
|
}
|
|
|
|
|
|
2015-12-19 12:40:52 +01:00
|
|
|
const auto dlg = Emu.GetCallbacks().get_msg_dialog();
|
|
|
|
|
|
|
|
|
|
dlg->type.bg_invisible = true;
|
|
|
|
|
dlg->type.button_type = 2; // OK
|
|
|
|
|
dlg->type.disable_cancel = true;
|
|
|
|
|
|
|
|
|
|
const auto p = std::make_shared<std::promise<void>>();
|
|
|
|
|
std::future<void> future = p->get_future();
|
|
|
|
|
|
|
|
|
|
dlg->on_close = [=](s32 status)
|
|
|
|
|
{
|
|
|
|
|
p->set_value();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
dlg->Create(errorMsg);
|
|
|
|
|
|
|
|
|
|
future.get();
|
2014-08-12 22:27:13 +02:00
|
|
|
|
2013-09-28 04:36:57 +02:00
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-13 16:05:44 +02:00
|
|
|
s32 cellGameThemeInstall()
|
2013-09-28 04:36:57 +02:00
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED_FUNC(cellGame);
|
|
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-13 16:05:44 +02:00
|
|
|
s32 cellGameThemeInstallFromBuffer()
|
2013-09-28 04:36:57 +02:00
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED_FUNC(cellGame);
|
|
|
|
|
return CELL_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-01 18:14:49 +02:00
|
|
|
|
|
|
|
|
s32 cellDiscGameGetBootDiscInfo()
|
|
|
|
|
{
|
|
|
|
|
throw EXCEPTION("");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 cellDiscGameRegisterDiscChangeCallback()
|
|
|
|
|
{
|
|
|
|
|
throw EXCEPTION("");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 cellDiscGameUnregisterDiscChangeCallback()
|
|
|
|
|
{
|
|
|
|
|
throw EXCEPTION("");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 cellGameRegisterDiscChangeCallback()
|
|
|
|
|
{
|
|
|
|
|
throw EXCEPTION("");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s32 cellGameUnregisterDiscChangeCallback()
|
|
|
|
|
{
|
|
|
|
|
throw EXCEPTION("");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void cellSysutil_GameData_init()
|
|
|
|
|
{
|
2015-09-08 15:53:28 +02:00
|
|
|
extern Module<> cellSysutil;
|
2015-08-01 18:14:49 +02:00
|
|
|
|
|
|
|
|
REG_FUNC(cellSysutil, cellHddGameCheck);
|
|
|
|
|
REG_FUNC(cellSysutil, cellHddGameCheck2);
|
|
|
|
|
REG_FUNC(cellSysutil, cellHddGameGetSizeKB);
|
|
|
|
|
REG_FUNC(cellSysutil, cellHddGameSetSystemVer);
|
|
|
|
|
REG_FUNC(cellSysutil, cellHddGameExitBroken);
|
|
|
|
|
|
|
|
|
|
REG_FUNC(cellSysutil, cellGameDataGetSizeKB);
|
|
|
|
|
REG_FUNC(cellSysutil, cellGameDataSetSystemVer);
|
|
|
|
|
REG_FUNC(cellSysutil, cellGameDataExitBroken);
|
|
|
|
|
|
|
|
|
|
REG_FUNC(cellSysutil, cellGameDataCheckCreate);
|
|
|
|
|
REG_FUNC(cellSysutil, cellGameDataCheckCreate2);
|
|
|
|
|
|
|
|
|
|
REG_FUNC(cellSysutil, cellDiscGameGetBootDiscInfo);
|
|
|
|
|
REG_FUNC(cellSysutil, cellDiscGameRegisterDiscChangeCallback);
|
|
|
|
|
REG_FUNC(cellSysutil, cellDiscGameUnregisterDiscChangeCallback);
|
|
|
|
|
REG_FUNC(cellSysutil, cellGameRegisterDiscChangeCallback);
|
|
|
|
|
REG_FUNC(cellSysutil, cellGameUnregisterDiscChangeCallback);
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-08 15:53:28 +02:00
|
|
|
Module<> cellGame("cellGame", []()
|
2013-09-28 04:36:57 +02:00
|
|
|
{
|
2015-02-20 14:58:40 +01:00
|
|
|
REG_FUNC(cellGame, cellGameBootCheck);
|
|
|
|
|
REG_FUNC(cellGame, cellGamePatchCheck);
|
|
|
|
|
REG_FUNC(cellGame, cellGameDataCheck);
|
|
|
|
|
REG_FUNC(cellGame, cellGameContentPermit);
|
2013-09-28 04:36:57 +02:00
|
|
|
|
2015-02-20 14:58:40 +01:00
|
|
|
REG_FUNC(cellGame, cellGameCreateGameData);
|
|
|
|
|
REG_FUNC(cellGame, cellGameDeleteGameData);
|
2013-09-28 04:36:57 +02:00
|
|
|
|
2015-02-20 14:58:40 +01:00
|
|
|
REG_FUNC(cellGame, cellGameGetParamInt);
|
|
|
|
|
REG_FUNC(cellGame, cellGameGetParamString);
|
|
|
|
|
REG_FUNC(cellGame, cellGameSetParamString);
|
|
|
|
|
REG_FUNC(cellGame, cellGameGetSizeKB);
|
|
|
|
|
REG_FUNC(cellGame, cellGameGetDiscContentInfoUpdatePath);
|
|
|
|
|
REG_FUNC(cellGame, cellGameGetLocalWebContentPath);
|
2013-09-28 04:36:57 +02:00
|
|
|
|
2015-02-20 14:58:40 +01:00
|
|
|
REG_FUNC(cellGame, cellGameContentErrorDialog);
|
2013-09-28 04:36:57 +02:00
|
|
|
|
2015-02-20 14:58:40 +01:00
|
|
|
REG_FUNC(cellGame, cellGameThemeInstall);
|
|
|
|
|
REG_FUNC(cellGame, cellGameThemeInstallFromBuffer);
|
2015-02-18 17:22:06 +01:00
|
|
|
});
|