mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-11 01:08:39 +12:00
cellGameGetParamString: check_mode for category
This commit is contained in:
parent
d8bbec9594
commit
e9af0bb72b
1 changed files with 88 additions and 46 deletions
|
@ -129,9 +129,18 @@ struct content_permission final
|
||||||
|
|
||||||
stx::init_mutex init;
|
stx::init_mutex init;
|
||||||
|
|
||||||
|
enum class check_mode
|
||||||
|
{
|
||||||
|
not_set,
|
||||||
|
game_data,
|
||||||
|
patch,
|
||||||
|
hdd_game,
|
||||||
|
disc_game
|
||||||
|
};
|
||||||
|
|
||||||
atomic_t<u32> can_create = 0;
|
atomic_t<u32> can_create = 0;
|
||||||
atomic_t<bool> exists = false;
|
atomic_t<bool> exists = false;
|
||||||
atomic_t<bool> restrict_sfo_params = true;
|
atomic_t<check_mode> mode = check_mode::not_set;
|
||||||
|
|
||||||
content_permission() = default;
|
content_permission() = default;
|
||||||
|
|
||||||
|
@ -146,7 +155,7 @@ struct content_permission final
|
||||||
temp.clear();
|
temp.clear();
|
||||||
can_create = 0;
|
can_create = 0;
|
||||||
exists = false;
|
exists = false;
|
||||||
restrict_sfo_params = true;
|
mode = check_mode::not_set;
|
||||||
}
|
}
|
||||||
|
|
||||||
~content_permission()
|
~content_permission()
|
||||||
|
@ -476,6 +485,8 @@ error_code cellGameBootCheck(vm::ptr<u32> type, vm::ptr<u32> attributes, vm::ptr
|
||||||
|
|
||||||
if (cat == "DG")
|
if (cat == "DG")
|
||||||
{
|
{
|
||||||
|
perm.mode = content_permission::check_mode::disc_game;
|
||||||
|
|
||||||
*type = CELL_GAME_GAMETYPE_DISC;
|
*type = CELL_GAME_GAMETYPE_DISC;
|
||||||
*attributes = 0; // TODO
|
*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)
|
// TODO: dirName might be a read only string when BootCheck is called on a disc game. (e.g. Ben 10 Ultimate Alien: Cosmic Destruction)
|
||||||
|
@ -484,6 +495,8 @@ error_code cellGameBootCheck(vm::ptr<u32> type, vm::ptr<u32> attributes, vm::ptr
|
||||||
}
|
}
|
||||||
else if (cat == "GD")
|
else if (cat == "GD")
|
||||||
{
|
{
|
||||||
|
perm.mode = content_permission::check_mode::patch;
|
||||||
|
|
||||||
*type = CELL_GAME_GAMETYPE_DISC;
|
*type = CELL_GAME_GAMETYPE_DISC;
|
||||||
*attributes = CELL_GAME_ATTRIBUTE_PATCH; // TODO
|
*attributes = CELL_GAME_ATTRIBUTE_PATCH; // TODO
|
||||||
|
|
||||||
|
@ -491,6 +504,8 @@ error_code cellGameBootCheck(vm::ptr<u32> type, vm::ptr<u32> attributes, vm::ptr
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
perm.mode = content_permission::check_mode::hdd_game;
|
||||||
|
|
||||||
*type = CELL_GAME_GAMETYPE_HDD;
|
*type = CELL_GAME_GAMETYPE_HDD;
|
||||||
*attributes = 0; // TODO
|
*attributes = 0; // TODO
|
||||||
|
|
||||||
|
@ -515,7 +530,6 @@ error_code cellGameBootCheck(vm::ptr<u32> type, vm::ptr<u32> attributes, vm::ptr
|
||||||
|
|
||||||
perm.dir = std::move(dir);
|
perm.dir = std::move(dir);
|
||||||
perm.sfo = std::move(sfo);
|
perm.sfo = std::move(sfo);
|
||||||
perm.restrict_sfo_params = *type == u32{CELL_GAME_GAMETYPE_HDD}; // Ratchet & Clank: All 4 One (PSN versions) rely on this error checking (TODO: Needs proper hw tests)
|
|
||||||
perm.exists = true;
|
perm.exists = true;
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
|
@ -551,7 +565,7 @@ error_code cellGamePatchCheck(vm::ptr<CellGameContentSize> size, vm::ptr<void> r
|
||||||
size->sysSizeKB = 0; // TODO
|
size->sysSizeKB = 0; // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
perm.restrict_sfo_params = false;
|
perm.mode = content_permission::check_mode::patch;
|
||||||
perm.dir = Emu.GetTitleID();
|
perm.dir = Emu.GetTitleID();
|
||||||
perm.sfo = std::move(sfo);
|
perm.sfo = std::move(sfo);
|
||||||
perm.exists = true;
|
perm.exists = true;
|
||||||
|
@ -619,13 +633,8 @@ error_code cellGameDataCheck(u32 type, vm::cptr<char> dirName, vm::ptr<CellGameC
|
||||||
}
|
}
|
||||||
|
|
||||||
perm.dir = std::move(name);
|
perm.dir = std::move(name);
|
||||||
|
perm.can_create = type == CELL_GAME_GAMETYPE_GAMEDATA;
|
||||||
if (type == CELL_GAME_GAMETYPE_GAMEDATA)
|
perm.mode = content_permission::check_mode::game_data;
|
||||||
{
|
|
||||||
perm.can_create = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
perm.restrict_sfo_params = false;
|
|
||||||
|
|
||||||
if (sfo.empty())
|
if (sfo.empty())
|
||||||
{
|
{
|
||||||
|
@ -1063,54 +1072,86 @@ error_code cellGameGetParamInt(s32 id, vm::ptr<s32> value)
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// String key restriction flags
|
// String key flags
|
||||||
enum class strkey_flag : u32
|
enum class strkey_flag : u32
|
||||||
{
|
{
|
||||||
get, // reading is restricted
|
get_game_data, // reading is allowed for game data PARAM.SFO
|
||||||
set, // writing is restricted
|
set_game_data, // writing is allowed for game data PARAM.SFO
|
||||||
read_only, // writing is disallowed (don't mind set flag in this case)
|
get_other, // reading is allowed for other types of PARAM.SFO
|
||||||
|
//set_other, // writing is allowed for other types of PARAM.SFO (not possible)
|
||||||
|
|
||||||
__bitset_enum_max
|
__bitset_enum_max
|
||||||
};
|
};
|
||||||
|
|
||||||
struct string_key_info
|
struct string_key_info
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
string_key_info() = default;
|
||||||
|
string_key_info(std::string_view _name, u32 _max_size, bs_t<strkey_flag> _flags)
|
||||||
|
: name(_name), max_size(_max_size), flags(_flags)
|
||||||
|
{}
|
||||||
|
|
||||||
std::string_view name;
|
std::string_view name;
|
||||||
u32 max_size = 0;
|
u32 max_size = 0;
|
||||||
bs_t<strkey_flag> flags;
|
|
||||||
|
inline bool is_supported(bool is_setter, content_permission::check_mode mode) const
|
||||||
|
{
|
||||||
|
switch (mode)
|
||||||
|
{
|
||||||
|
case content_permission::check_mode::game_data:
|
||||||
|
{
|
||||||
|
return !!(flags & (is_setter ? strkey_flag::set_game_data : strkey_flag::get_game_data));
|
||||||
|
}
|
||||||
|
case content_permission::check_mode::patch:
|
||||||
|
case content_permission::check_mode::hdd_game:
|
||||||
|
case content_permission::check_mode::disc_game:
|
||||||
|
{
|
||||||
|
return !is_setter && (flags & (strkey_flag::get_other));
|
||||||
|
}
|
||||||
|
case content_permission::check_mode::not_set:
|
||||||
|
{
|
||||||
|
fmt::throw_exception("This should never happen!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false; // Fixes some VS warning
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bs_t<strkey_flag> flags{}; // allowed operations
|
||||||
};
|
};
|
||||||
|
|
||||||
static string_key_info get_param_string_key(s32 id)
|
static string_key_info get_param_string_key(s32 id)
|
||||||
{
|
{
|
||||||
switch (id)
|
switch (id)
|
||||||
{
|
{
|
||||||
case CELL_GAME_PARAMID_TITLE: return {"TITLE", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::set}; // TODO: Is this value correct?
|
case CELL_GAME_PARAMID_TITLE: return string_key_info("TITLE", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::get_game_data + strkey_flag::get_other + strkey_flag::set_game_data);
|
||||||
case CELL_GAME_PARAMID_TITLE_DEFAULT: return {"TITLE", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::set};
|
case CELL_GAME_PARAMID_TITLE_DEFAULT: return string_key_info("TITLE", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::get_game_data + strkey_flag::get_other + strkey_flag::set_game_data);
|
||||||
case CELL_GAME_PARAMID_TITLE_JAPANESE: return {"TITLE_00", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::set + strkey_flag::get};
|
case CELL_GAME_PARAMID_TITLE_JAPANESE: return string_key_info("TITLE_00", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::get_game_data + strkey_flag::set_game_data);
|
||||||
case CELL_GAME_PARAMID_TITLE_ENGLISH: return {"TITLE_01", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::set + strkey_flag::get};
|
case CELL_GAME_PARAMID_TITLE_ENGLISH: return string_key_info("TITLE_01", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::get_game_data + strkey_flag::set_game_data);
|
||||||
case CELL_GAME_PARAMID_TITLE_FRENCH: return {"TITLE_02", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::set + strkey_flag::get};
|
case CELL_GAME_PARAMID_TITLE_FRENCH: return string_key_info("TITLE_02", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::get_game_data + strkey_flag::set_game_data);
|
||||||
case CELL_GAME_PARAMID_TITLE_SPANISH: return {"TITLE_03", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::set + strkey_flag::get};
|
case CELL_GAME_PARAMID_TITLE_SPANISH: return string_key_info("TITLE_03", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::get_game_data + strkey_flag::set_game_data);
|
||||||
case CELL_GAME_PARAMID_TITLE_GERMAN: return {"TITLE_04", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::set + strkey_flag::get};
|
case CELL_GAME_PARAMID_TITLE_GERMAN: return string_key_info("TITLE_04", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::get_game_data + strkey_flag::set_game_data);
|
||||||
case CELL_GAME_PARAMID_TITLE_ITALIAN: return {"TITLE_05", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::set + strkey_flag::get};
|
case CELL_GAME_PARAMID_TITLE_ITALIAN: return string_key_info("TITLE_05", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::get_game_data + strkey_flag::set_game_data);
|
||||||
case CELL_GAME_PARAMID_TITLE_DUTCH: return {"TITLE_06", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::set + strkey_flag::get};
|
case CELL_GAME_PARAMID_TITLE_DUTCH: return string_key_info("TITLE_06", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::get_game_data + strkey_flag::set_game_data);
|
||||||
case CELL_GAME_PARAMID_TITLE_PORTUGUESE: return {"TITLE_07", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::set + strkey_flag::get};
|
case CELL_GAME_PARAMID_TITLE_PORTUGUESE: return string_key_info("TITLE_07", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::get_game_data + strkey_flag::set_game_data);
|
||||||
case CELL_GAME_PARAMID_TITLE_RUSSIAN: return {"TITLE_08", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::set + strkey_flag::get};
|
case CELL_GAME_PARAMID_TITLE_RUSSIAN: return string_key_info("TITLE_08", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::get_game_data + strkey_flag::set_game_data);
|
||||||
case CELL_GAME_PARAMID_TITLE_KOREAN: return {"TITLE_09", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::set + strkey_flag::get};
|
case CELL_GAME_PARAMID_TITLE_KOREAN: return string_key_info("TITLE_09", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::get_game_data + strkey_flag::set_game_data);
|
||||||
case CELL_GAME_PARAMID_TITLE_CHINESE_T: return {"TITLE_10", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::set + strkey_flag::get};
|
case CELL_GAME_PARAMID_TITLE_CHINESE_T: return string_key_info("TITLE_10", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::get_game_data + strkey_flag::set_game_data);
|
||||||
case CELL_GAME_PARAMID_TITLE_CHINESE_S: return {"TITLE_11", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::set + strkey_flag::get};
|
case CELL_GAME_PARAMID_TITLE_CHINESE_S: return string_key_info("TITLE_11", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::get_game_data + strkey_flag::set_game_data);
|
||||||
case CELL_GAME_PARAMID_TITLE_FINNISH: return {"TITLE_12", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::set + strkey_flag::get};
|
case CELL_GAME_PARAMID_TITLE_FINNISH: return string_key_info("TITLE_12", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::get_game_data + strkey_flag::set_game_data);
|
||||||
case CELL_GAME_PARAMID_TITLE_SWEDISH: return {"TITLE_13", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::set + strkey_flag::get};
|
case CELL_GAME_PARAMID_TITLE_SWEDISH: return string_key_info("TITLE_13", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::get_game_data + strkey_flag::set_game_data);
|
||||||
case CELL_GAME_PARAMID_TITLE_DANISH: return {"TITLE_14", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::set + strkey_flag::get};
|
case CELL_GAME_PARAMID_TITLE_DANISH: return string_key_info("TITLE_14", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::get_game_data + strkey_flag::set_game_data);
|
||||||
case CELL_GAME_PARAMID_TITLE_NORWEGIAN: return {"TITLE_15", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::set + strkey_flag::get};
|
case CELL_GAME_PARAMID_TITLE_NORWEGIAN: return string_key_info("TITLE_15", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::get_game_data + strkey_flag::set_game_data);
|
||||||
case CELL_GAME_PARAMID_TITLE_POLISH: return {"TITLE_16", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::set + strkey_flag::get};
|
case CELL_GAME_PARAMID_TITLE_POLISH: return string_key_info("TITLE_16", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::get_game_data + strkey_flag::set_game_data);
|
||||||
case CELL_GAME_PARAMID_TITLE_PORTUGUESE_BRAZIL: return {"TITLE_17", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::set + strkey_flag::get};
|
case CELL_GAME_PARAMID_TITLE_PORTUGUESE_BRAZIL: return string_key_info("TITLE_17", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::get_game_data + strkey_flag::set_game_data);
|
||||||
case CELL_GAME_PARAMID_TITLE_ENGLISH_UK: return {"TITLE_18", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::set + strkey_flag::get};
|
case CELL_GAME_PARAMID_TITLE_ENGLISH_UK: return string_key_info("TITLE_18", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::get_game_data + strkey_flag::set_game_data);
|
||||||
case CELL_GAME_PARAMID_TITLE_TURKISH: return {"TITLE_19", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::set + strkey_flag::get};
|
case CELL_GAME_PARAMID_TITLE_TURKISH: return string_key_info("TITLE_19", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::get_game_data + strkey_flag::set_game_data);
|
||||||
|
|
||||||
case CELL_GAME_PARAMID_TITLE_ID: return {"TITLE_ID", CELL_GAME_SYSP_TITLEID_SIZE, strkey_flag::read_only};
|
case CELL_GAME_PARAMID_TITLE_ID: return string_key_info("TITLE_ID", CELL_GAME_SYSP_TITLEID_SIZE, strkey_flag::get_game_data + strkey_flag::get_other);
|
||||||
case CELL_GAME_PARAMID_VERSION: return {"VERSION", CELL_GAME_SYSP_VERSION_SIZE, strkey_flag::get + strkey_flag::read_only};
|
case CELL_GAME_PARAMID_VERSION: return string_key_info("VERSION", CELL_GAME_SYSP_VERSION_SIZE, strkey_flag::get_game_data);
|
||||||
case CELL_GAME_PARAMID_PS3_SYSTEM_VER: return {"PS3_SYSTEM_VER", CELL_GAME_SYSP_PS3_SYSTEM_VER_SIZE}; // TODO
|
case CELL_GAME_PARAMID_PS3_SYSTEM_VER: return string_key_info("PS3_SYSTEM_VER", CELL_GAME_SYSP_PS3_SYSTEM_VER_SIZE, {}); // TODO
|
||||||
case CELL_GAME_PARAMID_APP_VER: return {"APP_VER", CELL_GAME_SYSP_APP_VER_SIZE, strkey_flag::read_only};
|
case CELL_GAME_PARAMID_APP_VER: return string_key_info("APP_VER", CELL_GAME_SYSP_APP_VER_SIZE, strkey_flag::get_game_data + strkey_flag::get_other);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
@ -1129,7 +1170,7 @@ error_code cellGameGetParamString(s32 id, vm::ptr<char> buf, u32 bufsize)
|
||||||
|
|
||||||
const auto init = perm.init.access();
|
const auto init = perm.init.access();
|
||||||
|
|
||||||
if (!init)
|
if (!init || perm.mode == content_permission::check_mode::not_set)
|
||||||
{
|
{
|
||||||
return CELL_GAME_ERROR_FAILURE;
|
return CELL_GAME_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
@ -1141,8 +1182,9 @@ error_code cellGameGetParamString(s32 id, vm::ptr<char> buf, u32 bufsize)
|
||||||
return CELL_GAME_ERROR_INVALID_ID;
|
return CELL_GAME_ERROR_INVALID_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key.flags & strkey_flag::get && perm.restrict_sfo_params)
|
if (!key.is_supported(false, perm.mode))
|
||||||
{
|
{
|
||||||
|
// TODO: this error is possibly only returned during debug mode
|
||||||
return CELL_GAME_ERROR_NOTSUPPORTED;
|
return CELL_GAME_ERROR_NOTSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1172,7 +1214,7 @@ error_code cellGameSetParamString(s32 id, vm::cptr<char> buf)
|
||||||
|
|
||||||
const auto init = perm.init.access();
|
const auto init = perm.init.access();
|
||||||
|
|
||||||
if (!init)
|
if (!init || perm.mode == content_permission::check_mode::not_set)
|
||||||
{
|
{
|
||||||
return CELL_GAME_ERROR_FAILURE;
|
return CELL_GAME_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
@ -1184,7 +1226,7 @@ error_code cellGameSetParamString(s32 id, vm::cptr<char> buf)
|
||||||
return CELL_GAME_ERROR_INVALID_ID;
|
return CELL_GAME_ERROR_INVALID_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!perm.can_create || key.flags & strkey_flag::read_only || (key.flags & strkey_flag::set && perm.restrict_sfo_params))
|
if (!perm.can_create || !key.is_supported(true, perm.mode))
|
||||||
{
|
{
|
||||||
return CELL_GAME_ERROR_NOTSUPPORTED;
|
return CELL_GAME_ERROR_NOTSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue