diff --git a/rpcs3/Emu/Cell/Modules/sceNp.cpp b/rpcs3/Emu/Cell/Modules/sceNp.cpp index 82ef4b9bd7..21478efcb4 100644 --- a/rpcs3/Emu/Cell/Modules/sceNp.cpp +++ b/rpcs3/Emu/Cell/Modules/sceNp.cpp @@ -4227,12 +4227,26 @@ error_code sceNpUtilCmpNpId(vm::ptr id1, vm::ptr id2) return SCE_NP_UTIL_ERROR_INVALID_ARGUMENT; } - // TODO: Improve the comparison. - if (memcmp(id1->handle.data, id2->handle.data, 16) != 0) + // Unknown what this constant means + if (id1->reserved[0] != 1 || id2->reserved[0] != 1) + { + return SCE_NP_UTIL_ERROR_INVALID_NP_ID; + } + + if (strncmp(id1->handle.data, id2->handle.data, 16) || id1->unk1[0] != id2->unk1[0]) { return SCE_NP_UTIL_ERROR_NOT_MATCH; } + if (id1->unk1[1] != id2->unk1[1]) + { + // If either is zero they match + if (id1->opt[4] && id2->opt[4]) + { + return SCE_NP_UTIL_ERROR_NOT_MATCH; + } + } + return CELL_OK; } @@ -4245,10 +4259,41 @@ error_code sceNpUtilCmpNpIdInOrder(vm::cptr id1, vm::cptr id2, return SCE_NP_UTIL_ERROR_INVALID_ARGUMENT; } - // TODO: Improve the comparison. - // TODO: check for nullptr - *order = memcmp(id1->handle.data, id2->handle.data, 16); + if (id1->reserved[0] != 1 || id2->reserved[0] != 1) + { + return SCE_NP_UTIL_ERROR_INVALID_NP_ID; + } + if (s32 res = strncmp(id1->handle.data, id2->handle.data, 16)) + { + *order = std::clamp(res, -1, 1); + return CELL_OK; + } + + if (s32 res = memcmp(id1->unk1, id2->unk1, 4)) + { + *order = std::clamp(res, -1, 1); + return CELL_OK; + } + + const u8 opt14 = id1->opt[4]; + const u8 opt24 = id2->opt[4]; + + if (opt14 == 0 && opt24 == 0) + { + *order = 0; + return CELL_OK; + } + + if (opt14 != 0 && opt24 != 0) + { + s32 res = memcmp(id1->unk1 + 1, id2->unk1 + 1, 4); + *order = std::clamp(res, -1, 1); + return CELL_OK; + } + + s32 res = memcmp((opt14 != 0 ? id1 : id2)->unk1 + 1, "ps3", 4); + *order = std::clamp(res, -1, 1); return CELL_OK; } @@ -4261,8 +4306,12 @@ error_code sceNpUtilCmpOnlineId(vm::cptr id1, vm::cptr id2) return SCE_NP_UTIL_ERROR_INVALID_ARGUMENT; } - // TODO: Improve the comparison. - if (memcmp(id1->handle.data, id2->handle.data, 16) != 0) + if (id1->reserved[0] != 1 || id2->reserved[0] != 1) + { + return SCE_NP_UTIL_ERROR_INVALID_NP_ID; + } + + if (strncmp(id1->handle.data, id2->handle.data, 16) != 0) { return SCE_NP_UTIL_ERROR_NOT_MATCH; } @@ -4279,12 +4328,21 @@ error_code sceNpUtilGetPlatformType(vm::cptr npId) return SCE_NP_UTIL_ERROR_INVALID_ARGUMENT; } - //if (unknown_platform) - //{ - // return SCE_NP_UTIL_ERROR_UNKNOWN_PLATFORM_TYPE; - //} + switch (npId->unk1[1]) + { + case "ps4\0"_u32: + return not_an_error(SCE_NP_PLATFORM_TYPE_PS4); + case "psp2"_u32: + return not_an_error(SCE_NP_PLATFORM_TYPE_VITA); + case "ps3\0"_u32: + return not_an_error(SCE_NP_PLATFORM_TYPE_PS3); + case 0u: + return not_an_error(SCE_NP_PLATFORM_TYPE_NONE); + default: + break; + } - return CELL_OK; // SCE_NP_PLATFORM_TYPE_NONE + return SCE_NP_UTIL_ERROR_UNKNOWN_PLATFORM_TYPE; } error_code sceNpUtilSetPlatformType(vm::ptr npId, SceNpPlatformType platformType) @@ -4296,8 +4354,17 @@ error_code sceNpUtilSetPlatformType(vm::ptr npId, SceNpPlatformType pla return SCE_NP_UTIL_ERROR_INVALID_ARGUMENT; } - if (platformType < SCE_NP_PLATFORM_TYPE_NONE || platformType > SCE_NP_PLATFORM_TYPE_VITA) + switch (platformType) { + case SCE_NP_PLATFORM_TYPE_PS4: + npId->unk1[1] = "ps4\0"_u32; break; + case SCE_NP_PLATFORM_TYPE_VITA: + npId->unk1[1] = "psp2"_u32; break; + case SCE_NP_PLATFORM_TYPE_PS3: + npId->unk1[1] = "ps3\0"_u32; break; + case SCE_NP_PLATFORM_TYPE_NONE: + npId->unk1[1] = 0; break; + default: return SCE_NP_UTIL_ERROR_UNKNOWN_PLATFORM_TYPE; } diff --git a/rpcs3/Emu/Cell/Modules/sceNp.h b/rpcs3/Emu/Cell/Modules/sceNp.h index c9122b5ed9..4170a34b8e 100644 --- a/rpcs3/Emu/Cell/Modules/sceNp.h +++ b/rpcs3/Emu/Cell/Modules/sceNp.h @@ -795,7 +795,8 @@ enum : SceNpPlatformType { SCE_NP_PLATFORM_TYPE_NONE = 0, SCE_NP_PLATFORM_TYPE_PS3 = 1, - SCE_NP_PLATFORM_TYPE_VITA = 2 + SCE_NP_PLATFORM_TYPE_VITA = 2, + SCE_NP_PLATFORM_TYPE_PS4 = 3, // Note: unknown on which fw versions it appears, but sdk version is unchecked }; enum @@ -844,10 +845,20 @@ struct SceNpOnlineId struct SceNpId { SceNpOnlineId handle; - u8 opt[8]; + + union + { + // This field (system reserved) seems to be combined of two parts + // The second is used by sceNpUtilSetPlatformType and sceNpUtilGetPlatformType + u8 opt[8]; + nse_t unk1[2]; + }; + u8 reserved[8]; }; +CHECK_SIZE_ALIGN(SceNpId, 0x24, 1); + // Online Name structure struct SceNpOnlineName {