1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-25 20:22:30 +01:00

cellGameGetParamString: check_mode for category

This commit is contained in:
Megamouse 2022-03-25 10:31:27 +01:00
parent d8bbec9594
commit e9af0bb72b

View File

@ -129,9 +129,18 @@ struct content_permission final
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<bool> exists = false;
atomic_t<bool> restrict_sfo_params = true;
atomic_t<check_mode> mode = check_mode::not_set;
content_permission() = default;
@ -146,7 +155,7 @@ struct content_permission final
temp.clear();
can_create = 0;
exists = false;
restrict_sfo_params = true;
mode = check_mode::not_set;
}
~content_permission()
@ -476,6 +485,8 @@ error_code cellGameBootCheck(vm::ptr<u32> type, vm::ptr<u32> attributes, vm::ptr
if (cat == "DG")
{
perm.mode = content_permission::check_mode::disc_game;
*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)
@ -484,6 +495,8 @@ error_code cellGameBootCheck(vm::ptr<u32> type, vm::ptr<u32> attributes, vm::ptr
}
else if (cat == "GD")
{
perm.mode = content_permission::check_mode::patch;
*type = CELL_GAME_GAMETYPE_DISC;
*attributes = CELL_GAME_ATTRIBUTE_PATCH; // TODO
@ -491,6 +504,8 @@ error_code cellGameBootCheck(vm::ptr<u32> type, vm::ptr<u32> attributes, vm::ptr
}
else
{
perm.mode = content_permission::check_mode::hdd_game;
*type = CELL_GAME_GAMETYPE_HDD;
*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.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;
return CELL_OK;
@ -551,7 +565,7 @@ error_code cellGamePatchCheck(vm::ptr<CellGameContentSize> size, vm::ptr<void> r
size->sysSizeKB = 0; // TODO
}
perm.restrict_sfo_params = false;
perm.mode = content_permission::check_mode::patch;
perm.dir = Emu.GetTitleID();
perm.sfo = std::move(sfo);
perm.exists = true;
@ -619,13 +633,8 @@ error_code cellGameDataCheck(u32 type, vm::cptr<char> dirName, vm::ptr<CellGameC
}
perm.dir = std::move(name);
if (type == CELL_GAME_GAMETYPE_GAMEDATA)
{
perm.can_create = true;
}
perm.restrict_sfo_params = false;
perm.can_create = type == CELL_GAME_GAMETYPE_GAMEDATA;
perm.mode = content_permission::check_mode::game_data;
if (sfo.empty())
{
@ -1063,54 +1072,86 @@ error_code cellGameGetParamInt(s32 id, vm::ptr<s32> value)
return CELL_OK;
}
// String key restriction flags
// String key flags
enum class strkey_flag : u32
{
get, // reading is restricted
set, // writing is restricted
read_only, // writing is disallowed (don't mind set flag in this case)
get_game_data, // reading is allowed for game data PARAM.SFO
set_game_data, // writing is allowed for game data PARAM.SFO
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
};
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;
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)
{
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_DEFAULT: return {"TITLE", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::set};
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_ENGLISH: return {"TITLE_01", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::set + strkey_flag::get};
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_SPANISH: return {"TITLE_03", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::set + strkey_flag::get};
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_ITALIAN: return {"TITLE_05", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::set + strkey_flag::get};
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_PORTUGUESE: return {"TITLE_07", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::set + strkey_flag::get};
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_KOREAN: return {"TITLE_09", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::set + strkey_flag::get};
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_S: return {"TITLE_11", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::set + strkey_flag::get};
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_SWEDISH: return {"TITLE_13", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::set + strkey_flag::get};
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_NORWEGIAN: return {"TITLE_15", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::set + strkey_flag::get};
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_PORTUGUESE_BRAZIL: return {"TITLE_17", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::set + strkey_flag::get};
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_TURKISH: return {"TITLE_19", CELL_GAME_SYSP_TITLE_SIZE, strkey_flag::set + strkey_flag::get};
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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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_VERSION: return {"VERSION", CELL_GAME_SYSP_VERSION_SIZE, strkey_flag::get + strkey_flag::read_only};
case CELL_GAME_PARAMID_PS3_SYSTEM_VER: return {"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_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 string_key_info("VERSION", CELL_GAME_SYSP_VERSION_SIZE, strkey_flag::get_game_data);
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 string_key_info("APP_VER", CELL_GAME_SYSP_APP_VER_SIZE, strkey_flag::get_game_data + strkey_flag::get_other);
}
return {};
@ -1129,7 +1170,7 @@ error_code cellGameGetParamString(s32 id, vm::ptr<char> buf, u32 bufsize)
const auto init = perm.init.access();
if (!init)
if (!init || perm.mode == content_permission::check_mode::not_set)
{
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;
}
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;
}
@ -1172,7 +1214,7 @@ error_code cellGameSetParamString(s32 id, vm::cptr<char> buf)
const auto init = perm.init.access();
if (!init)
if (!init || perm.mode == content_permission::check_mode::not_set)
{
return CELL_GAME_ERROR_FAILURE;
}
@ -1184,7 +1226,7 @@ error_code cellGameSetParamString(s32 id, vm::cptr<char> buf)
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;
}