This commit is contained in:
RipleyTom 2024-01-05 09:43:26 +01:00 committed by GitHub
parent bc141831f7
commit b6e9746198
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 2254 additions and 1770 deletions

@ -1 +1 @@
Subproject commit 06c5c7ed0bd987a918cf88caafb094f22cdd1721
Subproject commit 0100f6a5779831fa7a651e4b67ef389a8752bd9b

View File

@ -652,6 +652,11 @@ std::string fmt::to_lower(std::string_view string)
return result;
}
std::string fmt::truncate(std::string_view src, usz length)
{
return std::string(src.begin(), src.begin() + std::min(src.size(), length));
}
bool fmt::match(const std::string& source, const std::string& mask)
{
usz source_position = 0, mask_position = 0;

View File

@ -178,6 +178,8 @@ namespace fmt
std::string to_upper(std::string_view string);
std::string to_lower(std::string_view string);
std::string truncate(std::string_view src, usz length);
bool match(const std::string& source, const std::string& mask);
struct buf_to_hexstring

View File

@ -762,7 +762,7 @@ error_code sceNpBasicRegisterHandler(vm::cptr<SceNpCommunicationId> context, vm:
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
}
if (nph.basic_handler.registered)
if (nph.basic_handler_registered)
{
return SCE_NP_BASIC_ERROR_EXCEEDS_MAX;
}
@ -772,11 +772,7 @@ error_code sceNpBasicRegisterHandler(vm::cptr<SceNpCommunicationId> context, vm:
return SCE_NP_BASIC_ERROR_INVALID_ARGUMENT;
}
memcpy(&nph.basic_handler.context, context.get_ptr(), sizeof(nph.basic_handler.context));
nph.basic_handler.handler_func = handler;
nph.basic_handler.handler_arg = arg;
nph.basic_handler.registered = true;
nph.basic_handler.context_sensitive = false;
nph.register_basic_handler(context, handler, arg, false);
return CELL_OK;
}
@ -792,7 +788,7 @@ error_code sceNpBasicRegisterContextSensitiveHandler(vm::cptr<SceNpCommunication
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
}
if (nph.basic_handler.registered)
if (nph.basic_handler_registered)
{
return SCE_NP_BASIC_ERROR_EXCEEDS_MAX;
}
@ -802,11 +798,7 @@ error_code sceNpBasicRegisterContextSensitiveHandler(vm::cptr<SceNpCommunication
return SCE_NP_BASIC_ERROR_INVALID_ARGUMENT;
}
memcpy(&nph.basic_handler.context, context.get_ptr(), sizeof(nph.basic_handler.context));
nph.basic_handler.handler_func = handler;
nph.basic_handler.handler_arg = arg;
nph.basic_handler.registered = true;
nph.basic_handler.context_sensitive = true;
nph.register_basic_handler(context, handler, arg, true);
return CELL_OK;
}
@ -822,19 +814,19 @@ error_code sceNpBasicUnregisterHandler()
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
}
if (!nph.basic_handler.registered)
if (!nph.basic_handler_registered)
{
return SCE_NP_BASIC_ERROR_NOT_REGISTERED;
}
nph.basic_handler.registered = false;
nph.basic_handler_registered = false;
return CELL_OK;
}
error_code sceNpBasicSetPresence(vm::cptr<u8> data, u32 size)
{
sceNp.todo("sceNpBasicSetPresence(data=*0x%x, size=%d)", data, size);
sceNp.warning("sceNpBasicSetPresence(data=*0x%x, size=%d)", data, size);
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
@ -843,28 +835,28 @@ error_code sceNpBasicSetPresence(vm::cptr<u8> data, u32 size)
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
}
if (!nph.basic_handler.registered)
if (!nph.basic_handler_registered)
{
return SCE_NP_BASIC_ERROR_NOT_REGISTERED;
}
// TODO: Correct but causes issues atm(breaks bomberman ultra)
// if (!data || !data[0])
// {
// return SCE_NP_BASIC_ERROR_INVALID_ARGUMENT;
// }
if (size > SCE_NP_BASIC_MAX_PRESENCE_SIZE)
{
return SCE_NP_BASIC_ERROR_EXCEEDS_MAX;
}
// Not checked by API
ensure(data);
std::vector pr_data(data.get_ptr(), data.get_ptr() + size);
nph.set_presence(std::nullopt, pr_data);
return CELL_OK;
}
error_code sceNpBasicSetPresenceDetails(vm::cptr<SceNpBasicPresenceDetails> pres, u32 options)
{
sceNp.todo("sceNpBasicSetPresenceDetails(pres=*0x%x, options=0x%x)", pres, options);
sceNp.warning("sceNpBasicSetPresenceDetails(pres=*0x%x, options=0x%x)", pres, options);
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
@ -873,27 +865,45 @@ error_code sceNpBasicSetPresenceDetails(vm::cptr<SceNpBasicPresenceDetails> pres
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
}
if (!nph.basic_handler.registered)
if (!nph.basic_handler_registered)
{
return SCE_NP_BASIC_ERROR_NOT_REGISTERED;
}
if (!pres || options > SCE_NP_BASIC_PRESENCE_OPTIONS_ALL_OPTIONS)
if (options < SCE_NP_BASIC_PRESENCE_OPTIONS_SET_DATA || options > SCE_NP_BASIC_PRESENCE_OPTIONS_ALL_OPTIONS)
{
return SCE_NP_BASIC_ERROR_INVALID_ARGUMENT;
}
// Not checked by API
ensure(pres);
if (pres->size > SCE_NP_BASIC_MAX_PRESENCE_SIZE)
{
return SCE_NP_BASIC_ERROR_EXCEEDS_MAX;
}
std::optional<std::string> pr_status;
if (options & SCE_NP_BASIC_PRESENCE_OPTIONS_SET_STATUS)
{
pr_status = std::optional(std::string(reinterpret_cast<const char*>(&pres->status[0])));
}
std::optional<std::vector<u8>> pr_data;
if (options & SCE_NP_BASIC_PRESENCE_OPTIONS_SET_DATA)
{
const u8* ptr = &pres->data[0];
pr_data = std::vector(ptr, ptr + pres->size);
}
nph.set_presence(pr_status, pr_data);
return CELL_OK;
}
error_code sceNpBasicSetPresenceDetails2(vm::cptr<SceNpBasicPresenceDetails2> pres, u32 options)
{
sceNp.todo("sceNpBasicSetPresenceDetails2(pres=*0x%x, options=0x%x)", pres, options);
sceNp.warning("sceNpBasicSetPresenceDetails2(pres=*0x%x, options=0x%x)", pres, options);
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
@ -902,21 +912,39 @@ error_code sceNpBasicSetPresenceDetails2(vm::cptr<SceNpBasicPresenceDetails2> pr
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
}
if (!nph.basic_handler.registered)
if (!nph.basic_handler_registered)
{
return SCE_NP_BASIC_ERROR_NOT_REGISTERED;
}
if (!pres || options > SCE_NP_BASIC_PRESENCE_OPTIONS_ALL_OPTIONS)
if (options < SCE_NP_BASIC_PRESENCE_OPTIONS_SET_DATA || options > SCE_NP_BASIC_PRESENCE_OPTIONS_ALL_OPTIONS || pres->struct_size != sizeof(SceNpBasicPresenceDetails2))
{
return SCE_NP_BASIC_ERROR_INVALID_ARGUMENT;
}
// Not checked by API
ensure(pres);
if (pres->size > SCE_NP_BASIC_MAX_PRESENCE_SIZE)
{
return SCE_NP_BASIC_ERROR_EXCEEDS_MAX;
}
std::optional<std::string> pr_status;
if (options & SCE_NP_BASIC_PRESENCE_OPTIONS_SET_STATUS)
{
pr_status = std::optional(std::string(reinterpret_cast<const char*>(&pres->status[0])));
}
std::optional<std::vector<u8>> pr_data;
if (options & SCE_NP_BASIC_PRESENCE_OPTIONS_SET_DATA)
{
const u8* ptr = &pres->data[0];
pr_data = std::vector(ptr, ptr + pres->size);
}
nph.set_presence(pr_status, pr_data);
return CELL_OK;
}
@ -931,7 +959,7 @@ error_code sceNpBasicSendMessage(vm::cptr<SceNpId> to, vm::cptr<void> data, u32
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
}
if (!nph.basic_handler.registered)
if (!nph.basic_handler_registered)
{
return SCE_NP_BASIC_ERROR_NOT_REGISTERED;
}
@ -971,7 +999,7 @@ error_code sceNpBasicSendMessageGui(vm::cptr<SceNpBasicMessageDetails> msg, sys_
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
}
if (!nph.basic_handler.registered)
if (!nph.basic_handler_registered)
{
return SCE_NP_BASIC_ERROR_NOT_REGISTERED;
}
@ -996,7 +1024,7 @@ error_code sceNpBasicSendMessageGui(vm::cptr<SceNpBasicMessageDetails> msg, sys_
// Prepare message data
message_data msg_data = {
.commId = nph.basic_handler.context,
.commId = nph.get_basic_handler_context(),
.msgId = msg->msgId,
.mainType = msg->mainType,
.subType = msg->subType,
@ -1078,7 +1106,7 @@ error_code sceNpBasicSendMessageAttachment(vm::cptr<SceNpId> to, vm::cptr<char>
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
}
if (!nph.basic_handler.registered)
if (!nph.basic_handler_registered)
{
return SCE_NP_BASIC_ERROR_NOT_REGISTERED;
}
@ -1114,7 +1142,7 @@ error_code sceNpBasicRecvMessageAttachment(sys_memory_container_t containerId)
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
}
if (!nph.basic_handler.registered)
if (!nph.basic_handler_registered)
{
return SCE_NP_BASIC_ERROR_NOT_REGISTERED;
}
@ -1133,7 +1161,7 @@ error_code sceNpBasicRecvMessageAttachmentLoad(SceNpBasicAttachmentDataId id, vm
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
}
if (!nph.basic_handler.registered)
if (!nph.basic_handler_registered)
{
return SCE_NP_BASIC_ERROR_NOT_REGISTERED;
}
@ -1186,7 +1214,7 @@ error_code sceNpBasicRecvMessageCustom(u16 mainType, u32 recvOptions, sys_memory
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
}
if (!nph.basic_handler.registered)
if (!nph.basic_handler_registered)
{
return SCE_NP_BASIC_ERROR_NOT_REGISTERED;
}
@ -1259,7 +1287,7 @@ error_code sceNpBasicMarkMessageAsUsed(SceNpBasicMessageId msgId)
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
}
if (!nph.basic_handler.registered)
if (!nph.basic_handler_registered)
{
return SCE_NP_BASIC_ERROR_NOT_REGISTERED;
}
@ -1283,7 +1311,7 @@ error_code sceNpBasicAbortGui()
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
}
if (!nph.basic_handler.registered)
if (!nph.basic_handler_registered)
{
return SCE_NP_BASIC_ERROR_NOT_REGISTERED;
}
@ -1304,7 +1332,7 @@ error_code sceNpBasicAddFriend(vm::cptr<SceNpId> contact, vm::cptr<char> body, s
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
}
if (!nph.basic_handler.registered)
if (!nph.basic_handler_registered)
{
return SCE_NP_BASIC_ERROR_NOT_REGISTERED;
}
@ -1392,7 +1420,7 @@ error_code sceNpBasicGetFriendListEntry(u32 index, vm::ptr<SceNpId> npid)
error_code sceNpBasicGetFriendPresenceByIndex(u32 index, vm::ptr<SceNpUserInfo> user, vm::ptr<SceNpBasicPresenceDetails> pres, u32 options)
{
sceNp.todo("sceNpBasicGetFriendPresenceByIndex(index=%d, user=*0x%x, pres=*0x%x, options=%d)", index, user, pres, options);
sceNp.warning("sceNpBasicGetFriendPresenceByIndex(index=%d, user=*0x%x, pres=*0x%x, options=%d)", index, user, pres, options);
if (!pres)
{
@ -1412,12 +1440,12 @@ error_code sceNpBasicGetFriendPresenceByIndex(u32 index, vm::ptr<SceNpUserInfo>
return SCE_NP_BASIC_ERROR_INVALID_ARGUMENT;
}
return CELL_OK;
return nph.get_friend_presence_by_index(index, user.get_ptr(), pres.get_ptr());
}
error_code sceNpBasicGetFriendPresenceByIndex2(u32 index, vm::ptr<SceNpUserInfo> user, vm::ptr<SceNpBasicPresenceDetails2> pres, u32 options)
{
sceNp.todo("sceNpBasicGetFriendPresenceByIndex2(index=%d, user=*0x%x, pres=*0x%x, options=%d)", index, user, pres, options);
sceNp.warning("sceNpBasicGetFriendPresenceByIndex2(index=%d, user=*0x%x, pres=*0x%x, options=%d)", index, user, pres, options);
if (!pres)
{
@ -1437,20 +1465,20 @@ error_code sceNpBasicGetFriendPresenceByIndex2(u32 index, vm::ptr<SceNpUserInfo>
return SCE_NP_BASIC_ERROR_INVALID_ARGUMENT;
}
return CELL_OK;
return nph.get_friend_presence_by_index(index, user.get_ptr(), pres.get_ptr());
}
error_code sceNpBasicGetFriendPresenceByNpId(vm::cptr<SceNpId> npid, vm::ptr<SceNpBasicPresenceDetails> pres, u32 options)
{
sceNp.todo("sceNpBasicGetFriendPresenceByNpId(npid=*0x%x, pres=*0x%x, options=%d)", npid, pres, options);
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
sceNp.warning("sceNpBasicGetFriendPresenceByNpId(npid=*0x%x, pres=*0x%x, options=%d)", npid, pres, options);
if (!pres)
{
return SCE_NP_BASIC_ERROR_INVALID_ARGUMENT;
}
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
if (!nph.is_NP_init)
{
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
@ -1462,20 +1490,20 @@ error_code sceNpBasicGetFriendPresenceByNpId(vm::cptr<SceNpId> npid, vm::ptr<Sce
return SCE_NP_BASIC_ERROR_INVALID_ARGUMENT;
}
return CELL_OK;
return nph.get_friend_presence_by_npid(*npid, pres.get_ptr());
}
error_code sceNpBasicGetFriendPresenceByNpId2(vm::cptr<SceNpId> npid, vm::ptr<SceNpBasicPresenceDetails2> pres, u32 options)
{
sceNp.todo("sceNpBasicGetFriendPresenceByNpId2(npid=*0x%x, pres=*0x%x, options=%d)", npid, pres, options);
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
sceNp.warning("sceNpBasicGetFriendPresenceByNpId2(npid=*0x%x, pres=*0x%x, options=%d)", npid, pres, options);
if (!pres)
{
return SCE_NP_BASIC_ERROR_INVALID_ARGUMENT;
}
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
if (!nph.is_NP_init)
{
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
@ -1487,7 +1515,7 @@ error_code sceNpBasicGetFriendPresenceByNpId2(vm::cptr<SceNpId> npid, vm::ptr<Sc
return SCE_NP_BASIC_ERROR_INVALID_ARGUMENT;
}
return CELL_OK;
return nph.get_friend_presence_by_npid(*npid, pres.get_ptr());
}
error_code sceNpBasicAddPlayersHistory(vm::cptr<SceNpId> npid, vm::ptr<char> description)
@ -1579,7 +1607,7 @@ error_code sceNpBasicGetPlayersHistoryEntryCount(u32 options, vm::ptr<u32> count
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
}
if (!nph.basic_handler.registered)
if (!nph.basic_handler_registered)
{
return SCE_NP_BASIC_ERROR_NOT_REGISTERED;
}
@ -1617,7 +1645,7 @@ error_code sceNpBasicGetPlayersHistoryEntry(u32 options, u32 index, vm::ptr<SceN
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
}
if (!nph.basic_handler.registered)
if (!nph.basic_handler_registered)
{
return SCE_NP_BASIC_ERROR_NOT_REGISTERED;
}
@ -1648,7 +1676,7 @@ error_code sceNpBasicAddBlockListEntry(vm::cptr<SceNpId> npid)
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
}
if (!nph.basic_handler.registered)
if (!nph.basic_handler_registered)
{
return SCE_NP_BASIC_ERROR_NOT_REGISTERED;
}
@ -1731,7 +1759,7 @@ error_code sceNpBasicGetMessageAttachmentEntryCount(vm::ptr<u32> count)
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
}
if (!nph.basic_handler.registered)
if (!nph.basic_handler_registered)
{
return SCE_NP_BASIC_ERROR_NOT_REGISTERED;
}
@ -1764,7 +1792,7 @@ error_code sceNpBasicGetMessageAttachmentEntry(u32 index, vm::ptr<SceNpUserInfo>
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
}
if (!nph.basic_handler.registered)
if (!nph.basic_handler_registered)
{
return SCE_NP_BASIC_ERROR_NOT_REGISTERED;
}
@ -1795,7 +1823,7 @@ error_code sceNpBasicGetCustomInvitationEntryCount(vm::ptr<u32> count)
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
}
if (!nph.basic_handler.registered)
if (!nph.basic_handler_registered)
{
return SCE_NP_BASIC_ERROR_NOT_REGISTERED;
}
@ -1828,7 +1856,7 @@ error_code sceNpBasicGetCustomInvitationEntry(u32 index, vm::ptr<SceNpUserInfo>
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
}
if (!nph.basic_handler.registered)
if (!nph.basic_handler_registered)
{
return SCE_NP_BASIC_ERROR_NOT_REGISTERED;
}
@ -1859,7 +1887,7 @@ error_code sceNpBasicGetMatchingInvitationEntryCount(vm::ptr<u32> count)
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
}
if (!nph.basic_handler.registered)
if (!nph.basic_handler_registered)
{
return SCE_NP_BASIC_ERROR_NOT_REGISTERED;
}
@ -1892,7 +1920,7 @@ error_code sceNpBasicGetMatchingInvitationEntry(u32 index, vm::ptr<SceNpUserInfo
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
}
if (!nph.basic_handler.registered)
if (!nph.basic_handler_registered)
{
return SCE_NP_BASIC_ERROR_NOT_REGISTERED;
}
@ -1923,7 +1951,7 @@ error_code sceNpBasicGetClanMessageEntryCount(vm::ptr<u32> count)
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
}
if (!nph.basic_handler.registered)
if (!nph.basic_handler_registered)
{
return SCE_NP_BASIC_ERROR_NOT_REGISTERED;
}
@ -1956,7 +1984,7 @@ error_code sceNpBasicGetClanMessageEntry(u32 index, vm::ptr<SceNpUserInfo> from)
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
}
if (!nph.basic_handler.registered)
if (!nph.basic_handler_registered)
{
return SCE_NP_BASIC_ERROR_NOT_REGISTERED;
}
@ -2053,7 +2081,7 @@ error_code sceNpBasicGetEvent(vm::ptr<s32> event, vm::ptr<SceNpUserInfo> from, v
return SCE_NP_BASIC_ERROR_NOT_INITIALIZED;
}
if (!nph.basic_handler.registered)
if (!nph.basic_handler_registered)
{
return SCE_NP_BASIC_ERROR_NOT_REGISTERED;
}
@ -3273,7 +3301,7 @@ error_code sceNpManagerGetAccountRegion(vm::ptr<SceNpCountryCode> countryCode, v
return SCE_NP_ERROR_INVALID_STATE;
}
memset(countryCode.get_ptr(), 0, sizeof(countryCode));
memset(countryCode.get_ptr(), 0, sizeof(SceNpCountryCode));
countryCode->data[0] = 'u';
countryCode->data[1] = 's';
@ -5634,7 +5662,7 @@ error_code sceNpUtilCmpNpIdInOrder(vm::cptr<SceNpId> id1, vm::cptr<SceNpId> id2,
return CELL_OK;
}
if (s32 res = memcmp(id1->unk1, id2->unk1, 4))
if (s32 res = std::memcmp(id1->unk1, id2->unk1, 4))
{
*order = std::clamp<s32>(res, -1, 1);
return CELL_OK;
@ -5651,12 +5679,12 @@ error_code sceNpUtilCmpNpIdInOrder(vm::cptr<SceNpId> id1, vm::cptr<SceNpId> id2,
if (opt14 != 0 && opt24 != 0)
{
s32 res = memcmp(id1->unk1 + 1, id2->unk1 + 1, 4);
s32 res = std::memcmp(id1->unk1 + 1, id2->unk1 + 1, 4);
*order = std::clamp<s32>(res, -1, 1);
return CELL_OK;
}
s32 res = memcmp((opt14 != 0 ? id1 : id2)->unk1 + 1, "ps3", 4);
s32 res = std::memcmp((opt14 != 0 ? id1 : id2)->unk1 + 1, "ps3", 4);
*order = std::clamp<s32>(res, -1, 1);
return CELL_OK;
}

View File

@ -288,33 +288,44 @@ error_code sceNpTusPollAsync(s32 transId, vm::ptr<s32> result)
template<typename T>
error_code scenp_tus_set_multislot_variable(s32 transId, T targetNpId, vm::cptr<SceNpTusSlotId> slotIdArray, vm::cptr<s64> variableArray, s32 arrayNum, vm::ptr<void> option, bool vuser, bool async)
{
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
if (!nph.is_NP_TUS_init)
{
return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED;
}
if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID;
}
if (!targetNpId || !slotIdArray || !variableArray || arrayNum <= 0)
if (!slotIdArray || !variableArray)
{
return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT;
}
if (arrayNum == 0 || option)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT;
}
if (arrayNum > SCE_NP_TUS_MAX_SLOT_NUM_PER_TRANS)
{
return SCE_NP_COMMUNITY_ERROR_TOO_MANY_SLOTID;
}
if (option || !is_slot_array_valid(slotIdArray, arrayNum))
if (!is_slot_array_valid(slotIdArray, arrayNum))
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT;
}
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
if (!nph.is_NP_TUS_init)
{
return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED;
}
if (!targetNpId)
{
return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT;
}
// Probable vsh behaviour
if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID;
}
auto trans_ctx = idm::get<tus_transaction_ctx>(transId);
if (!trans_ctx)
@ -359,29 +370,12 @@ error_code sceNpTusSetMultiSlotVariableVUserAsync(s32 transId, vm::cptr<SceNpTus
template<typename T>
error_code scenp_tus_get_multislot_variable(s32 transId, T targetNpId, vm::cptr<SceNpTusSlotId> slotIdArray, vm::ptr<SceNpTusVariable> variableArray, u32 variableArraySize, s32 arrayNum, vm::ptr<void> option, bool vuser, bool async)
{
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
if (!nph.is_NP_TUS_init)
{
return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED;
}
if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID;
}
if (!targetNpId || !slotIdArray || !variableArray || arrayNum <= 0)
if (!slotIdArray || !variableArray)
{
return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT;
}
if (arrayNum > SCE_NP_TUS_MAX_SLOT_NUM_PER_TRANS)
{
return SCE_NP_COMMUNITY_ERROR_TOO_MANY_SLOTID;
}
if (option || !is_slot_array_valid(slotIdArray, arrayNum))
if (arrayNum == 0 || option)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT;
}
@ -391,6 +385,34 @@ error_code scenp_tus_get_multislot_variable(s32 transId, T targetNpId, vm::cptr<
return SCE_NP_COMMUNITY_ERROR_INVALID_ALIGNMENT;
}
if (arrayNum > SCE_NP_TUS_MAX_SLOT_NUM_PER_TRANS)
{
return SCE_NP_COMMUNITY_ERROR_TOO_MANY_SLOTID;
}
if (!is_slot_array_valid(slotIdArray, arrayNum))
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT;
}
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
if (!nph.is_NP_TUS_init)
{
return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED;
}
if (!targetNpId)
{
return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT;
}
// Probable vsh behaviour
if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID;
}
auto trans_ctx = idm::get<tus_transaction_ctx>(transId);
if (!trans_ctx)
@ -435,6 +457,31 @@ error_code sceNpTusGetMultiSlotVariableVUserAsync(s32 transId, vm::cptr<SceNpTus
template<typename T>
error_code scenp_tus_get_multiuser_variable(s32 transId, T targetNpIdArray, SceNpTusSlotId slotId, vm::ptr<SceNpTusVariable> variableArray, u32 variableArraySize, s32 arrayNum, vm::ptr<void> option, bool vuser, bool async)
{
if (!variableArray)
{
return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT;
}
if (arrayNum == 0 || option)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT;
}
if (arrayNum > SCE_NP_SCORE_MAX_NPID_NUM_PER_TRANS)
{
return SCE_NP_COMMUNITY_ERROR_TOO_MANY_NPID;
}
if (variableArraySize != arrayNum * sizeof(SceNpTusVariable))
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ALIGNMENT;
}
if (slotId < 0)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT;
}
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
if (!nph.is_NP_TUS_init)
@ -442,29 +489,15 @@ error_code scenp_tus_get_multiuser_variable(s32 transId, T targetNpIdArray, SceN
return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED;
}
if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID;
}
if (!targetNpIdArray || !variableArray || arrayNum <= 0)
if (!targetNpIdArray)
{
return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT;
}
if (arrayNum > SCE_NP_TUS_MAX_SLOT_NUM_PER_TRANS)
// Probable vsh behaviour
if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE)
{
return SCE_NP_COMMUNITY_ERROR_TOO_MANY_SLOTID;
}
if (option || slotId < 0)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT;
}
if (variableArraySize != arrayNum * sizeof(SceNpTusVariable))
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ALIGNMENT;
return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID;
}
auto trans_ctx = idm::get<tus_transaction_ctx>(transId);
@ -516,6 +549,43 @@ error_code sceNpTusGetMultiUserVariableVUserAsync(s32 transId, vm::cptr<SceNpTus
error_code scenp_tus_get_friends_variable(s32 transId, SceNpTusSlotId slotId, s32 includeSelf, s32 sortType, vm::ptr<SceNpTusVariable> variableArray, u32 variableArraySize, s32 arrayNum, vm::ptr<void> option, bool async)
{
if (!variableArray)
{
return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT;
}
if (arrayNum == 0)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT;
}
// Undocumented behaviour and structure unknown
// Also checks a u32* at offset 4 of the struct for nullptr in which case it behaves like option == nullptr
if (option && *static_cast<u32*>(option.get_ptr()) != 0xC)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT;
}
if (sortType < SCE_NP_TUS_VARIABLE_SORTTYPE_DESCENDING_DATE || sortType > SCE_NP_TUS_VARIABLE_SORTTYPE_ASCENDING_VALUE)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT;
}
if (arrayNum > SCE_NP_SCORE_MAX_SELECTED_FRIENDS_NUM)
{
return SCE_NP_COMMUNITY_ERROR_TOO_MANY_NPID;
}
if (variableArraySize != arrayNum * sizeof(SceNpTusVariable))
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ALIGNMENT;
}
if (slotId < 0)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT;
}
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
if (!nph.is_NP_TUS_init)
@ -523,31 +593,12 @@ error_code scenp_tus_get_friends_variable(s32 transId, SceNpTusSlotId slotId, s3
return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED;
}
// Probable vsh behaviour
if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID;
}
if (!variableArray)
{
return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT;
}
if (arrayNum > SCE_NP_TUS_MAX_SLOT_NUM_PER_TRANS)
{
return SCE_NP_COMMUNITY_ERROR_TOO_MANY_SLOTID;
}
if (option || arrayNum <= 0 || slotId < 0)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT;
}
if (variableArraySize != arrayNum * sizeof(SceNpTusVariable))
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ALIGNMENT;
}
auto trans_ctx = idm::get<tus_transaction_ctx>(transId);
if (!trans_ctx)
@ -587,9 +638,14 @@ error_code scenp_tus_add_and_get_variable(s32 transId, T targetNpId, SceNpTusSlo
return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED;
}
if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE)
if (slotId < 0)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID;
return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT;
}
if ((option && option->size != sizeof(SceNpTusAddAndGetVariableOptParam)) || outVariableSize != sizeof(SceNpTusVariable))
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ALIGNMENT;
}
if (!targetNpId)
@ -597,14 +653,10 @@ error_code scenp_tus_add_and_get_variable(s32 transId, T targetNpId, SceNpTusSlo
return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT;
}
if (slotId < 0)
// Probable vsh behaviour
if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT;
}
if (outVariableSize != sizeof(SceNpTusVariable))
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ALIGNMENT;
return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID;
}
auto trans_ctx = idm::get<tus_transaction_ctx>(transId);
@ -658,12 +710,7 @@ error_code scenp_tus_try_and_set_variable(s32 transId, T targetNpId, SceNpTusSlo
return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED;
}
if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID;
}
if (!targetNpId || !resultVariable)
if (!resultVariable)
{
return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT;
}
@ -673,11 +720,22 @@ error_code scenp_tus_try_and_set_variable(s32 transId, T targetNpId, SceNpTusSlo
return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT;
}
if (resultVariableSize != sizeof(SceNpTusVariable))
if ((option && option->size != sizeof(SceNpTusTryAndSetVariableOptParam)) || resultVariableSize != sizeof(SceNpTusVariable))
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ALIGNMENT;
}
if (!targetNpId)
{
return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT;
}
// Probable vsh behaviour
if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID;
}
auto trans_ctx = idm::get<tus_transaction_ctx>(transId);
if (!trans_ctx)
@ -722,33 +780,39 @@ error_code sceNpTusTryAndSetVariableVUserAsync(s32 transId, vm::cptr<SceNpTusVir
template<typename T>
error_code scenp_tus_delete_multislot_variable(s32 transId, T targetNpId, vm::cptr<SceNpTusSlotId> slotIdArray, s32 arrayNum, vm::ptr<void> option, bool vuser, bool async)
{
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
if (!nph.is_NP_TUS_init)
{
return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED;
}
if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID;
}
if (!targetNpId || !slotIdArray || arrayNum <= 0)
if (!slotIdArray)
{
return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT;
}
if (arrayNum == 0 || option)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT;
}
if (arrayNum > SCE_NP_TUS_MAX_SLOT_NUM_PER_TRANS)
{
return SCE_NP_COMMUNITY_ERROR_TOO_MANY_SLOTID;
}
if (option || !is_slot_array_valid(slotIdArray, arrayNum))
if (!is_slot_array_valid(slotIdArray, arrayNum))
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT;
}
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
if (!nph.is_NP_TUS_init)
{
return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED;
}
// Probable vsh behaviour
if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID;
}
auto trans_ctx = idm::get<tus_transaction_ctx>(transId);
if (!trans_ctx)
@ -793,6 +857,16 @@ error_code sceNpTusDeleteMultiSlotVariableVUserAsync(s32 transId, vm::cptr<SceNp
template<typename T>
error_code scenp_tus_set_data(s32 transId, T targetNpId, SceNpTusSlotId slotId, u32 totalSize, u32 sendSize, vm::cptr<void> data, vm::cptr<SceNpTusDataInfo> info, u32 infoStructSize, vm::ptr<SceNpTusSetDataOptParam> option, bool vuser, bool async)
{
if (slotId < 0 || !data || !totalSize)
{
return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT;
}
if ((option && option->size != sizeof(SceNpTusSetDataOptParam)) || (info && infoStructSize != sizeof(SceNpTusDataInfo)))
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ALIGNMENT;
}
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
if (!nph.is_NP_TUS_init)
@ -800,19 +874,15 @@ error_code scenp_tus_set_data(s32 transId, T targetNpId, SceNpTusSlotId slotId,
return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED;
}
if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID;
}
if (!targetNpId || !data || totalSize == 0)
if (!targetNpId)
{
return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT;
}
if (slotId < 0)
// Probable vsh behaviour
if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT;
return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID;
}
auto trans_ctx = idm::get<tus_transaction_ctx>(transId);
@ -859,18 +929,6 @@ error_code sceNpTusSetDataVUserAsync(s32 transId, vm::cptr<SceNpTusVirtualUserId
template<typename T>
error_code scenp_tus_get_data(s32 transId, T targetNpId, SceNpTusSlotId slotId, vm::ptr<SceNpTusDataStatus> dataStatus, u32 dataStatusSize, vm::ptr<void> data, u32 recvSize, vm::ptr<void> option, bool vuser, bool async)
{
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
if (!nph.is_NP_TUS_init)
{
return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED;
}
if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID;
}
if (!targetNpId)
{
return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT;
@ -881,6 +939,24 @@ error_code scenp_tus_get_data(s32 transId, T targetNpId, SceNpTusSlotId slotId,
return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT;
}
if (dataStatusSize != sizeof(SceNpTusDataStatus))
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ALIGNMENT;
}
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
if (!nph.is_NP_TUS_init)
{
return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED;
}
// Probable vsh behaviour
if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID;
}
auto trans_ctx = idm::get<tus_transaction_ctx>(transId);
if (!trans_ctx)
@ -925,6 +1001,31 @@ error_code sceNpTusGetDataVUserAsync(s32 transId, vm::cptr<SceNpTusVirtualUserId
template<typename T>
error_code scenp_tus_get_multislot_data_status(s32 transId, T targetNpId, vm::cptr<SceNpTusSlotId> slotIdArray, vm::ptr<SceNpTusDataStatus> statusArray, u32 statusArraySize, s32 arrayNum, vm::ptr<void> option, bool vuser, bool async)
{
if (!slotIdArray || !statusArray)
{
return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT;
}
if (arrayNum == 0 || option)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT;
}
if (statusArraySize != arrayNum * sizeof(SceNpTusDataStatus))
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ALIGNMENT;
}
if (arrayNum > SCE_NP_TUS_MAX_SLOT_NUM_PER_TRANS)
{
return SCE_NP_COMMUNITY_ERROR_TOO_MANY_SLOTID;
}
if (!is_slot_array_valid(slotIdArray, arrayNum))
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT;
}
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
if (!nph.is_NP_TUS_init)
@ -932,24 +1033,15 @@ error_code scenp_tus_get_multislot_data_status(s32 transId, T targetNpId, vm::cp
return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED;
}
if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID;
}
if (!targetNpId || !statusArray || arrayNum <= 0)
if (!targetNpId)
{
return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT;
}
if (option || !is_slot_array_valid(slotIdArray, arrayNum))
// Probable vsh behaviour
if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT;
}
if (arrayNum > SCE_NP_TUS_MAX_SLOT_NUM_PER_TRANS)
{
return SCE_NP_COMMUNITY_ERROR_TOO_MANY_SLOTID;
return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID;
}
auto trans_ctx = idm::get<tus_transaction_ctx>(transId);
@ -996,6 +1088,31 @@ error_code sceNpTusGetMultiSlotDataStatusVUserAsync(s32 transId, vm::cptr<SceNpT
template<typename T>
error_code scenp_tus_get_multiuser_data_status(s32 transId, T targetNpIdArray, SceNpTusSlotId slotId, vm::ptr<SceNpTusDataStatus> statusArray, u32 statusArraySize, s32 arrayNum, vm::ptr<void> option, bool vuser, bool async)
{
if (!statusArray)
{
return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT;
}
if (arrayNum == 0 || option)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT;
}
if (arrayNum > SCE_NP_SCORE_MAX_NPID_NUM_PER_TRANS)
{
return SCE_NP_COMMUNITY_ERROR_TOO_MANY_NPID;
}
if (statusArraySize != arrayNum * sizeof(SceNpTusDataStatus))
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ALIGNMENT;
}
if (slotId < 0)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT;
}
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
if (!nph.is_NP_TUS_init)
@ -1003,24 +1120,15 @@ error_code scenp_tus_get_multiuser_data_status(s32 transId, T targetNpIdArray, S
return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED;
}
if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID;
}
if (!targetNpIdArray || !statusArray || arrayNum <= 0)
if (!targetNpIdArray)
{
return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT;
}
if (option || slotId < 0)
// Probable vsh behaviour
if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT;
}
if (arrayNum > SCE_NP_TUS_MAX_USER_NUM_PER_TRANS)
{
return SCE_NP_COMMUNITY_ERROR_TOO_MANY_NPID;
return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID;
}
auto trans_ctx = idm::get<tus_transaction_ctx>(transId);
@ -1072,6 +1180,43 @@ error_code sceNpTusGetMultiUserDataStatusVUserAsync(s32 transId, vm::cptr<SceNpT
error_code scenp_tus_get_friends_data_status(s32 transId, SceNpTusSlotId slotId, s32 includeSelf, s32 sortType, vm::ptr<SceNpTusDataStatus> statusArray, u32 statusArraySize, s32 arrayNum, vm::ptr<void> option, bool async)
{
if (!statusArray)
{
return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT;
}
if (arrayNum == 0)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT;
}
// Undocumented behaviour and structure unknown
// Also checks a u32* at offset 4 of the struct for nullptr in which case it behaves like option == nullptr
if (option && *static_cast<u32*>(option.get_ptr()) != 0xC)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT;
}
if (sortType != SCE_NP_TUS_DATASTATUS_SORTTYPE_DESCENDING_DATE && sortType != SCE_NP_TUS_DATASTATUS_SORTTYPE_ASCENDING_DATE)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT;
}
if (arrayNum > SCE_NP_SCORE_MAX_SELECTED_FRIENDS_NUM)
{
return SCE_NP_COMMUNITY_ERROR_TOO_MANY_NPID;
}
if (statusArraySize != arrayNum * sizeof(SceNpTusDataStatus))
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ALIGNMENT;
}
if (slotId < 0)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT;
}
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
if (!nph.is_NP_TUS_init)
@ -1079,26 +1224,12 @@ error_code scenp_tus_get_friends_data_status(s32 transId, SceNpTusSlotId slotId,
return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED;
}
// Probable vsh behaviour
if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID;
}
if (!statusArray)
{
return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT;
}
if (option || arrayNum < 0 || slotId < 0)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT;
}
if (arrayNum > SCE_NP_TUS_MAX_SELECTED_FRIENDS_NUM)
{
return SCE_NP_COMMUNITY_ERROR_TOO_MANY_NPID;
}
auto trans_ctx = idm::get<tus_transaction_ctx>(transId);
if (!trans_ctx)
@ -1131,24 +1262,12 @@ error_code sceNpTusGetFriendsDataStatusAsync(s32 transId, SceNpTusSlotId slotId,
template<typename T>
error_code scenp_tus_delete_multislot_data(s32 transId, T targetNpId, vm::cptr<SceNpTusSlotId> slotIdArray, s32 arrayNum, vm::ptr<void> option, bool vuser, bool async)
{
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
if (!nph.is_NP_TUS_init)
{
return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED;
}
if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID;
}
if (!targetNpId || !slotIdArray || arrayNum < 0)
if (!slotIdArray)
{
return SCE_NP_COMMUNITY_ERROR_INSUFFICIENT_ARGUMENT;
}
if (option || !is_slot_array_valid(slotIdArray, arrayNum))
if (arrayNum == 0 || option)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT;
}
@ -1158,6 +1277,24 @@ error_code scenp_tus_delete_multislot_data(s32 transId, T targetNpId, vm::cptr<S
return SCE_NP_COMMUNITY_ERROR_TOO_MANY_SLOTID;
}
if (!is_slot_array_valid(slotIdArray, arrayNum))
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ARGUMENT;
}
auto& nph = g_fxo->get<named_thread<np::np_handler>>();
if (!nph.is_NP_TUS_init)
{
return SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED;
}
// Probable vsh behaviour
if (nph.get_psn_status() != SCE_NP_MANAGER_STATUS_ONLINE)
{
return SCE_NP_COMMUNITY_ERROR_INVALID_ONLINE_ID;
}
auto trans_ctx = idm::get<tus_transaction_ctx>(transId);
if (!trans_ctx)

View File

@ -466,3 +466,9 @@ table TusDeleteMultiSlotDataRequest {
slotIdArray:[int32];
}
table SetPresenceRequest {
title:string;
status:string;
comment:string;
data:[uint8];
}

File diff suppressed because it is too large Load Diff

View File

@ -793,10 +793,79 @@ namespace np
return size_copied;
}
void np_handler::register_basic_handler(vm::cptr<SceNpCommunicationId> context, vm::ptr<SceNpBasicEventHandler> handler, vm::ptr<void> arg, bool context_sensitive)
{
{
std::lock_guard lock(basic_handler.mutex);
memcpy(&basic_handler.context, context.get_ptr(), sizeof(basic_handler.context));
basic_handler.handler_func = handler;
basic_handler.handler_arg = arg;
basic_handler.context_sensitive = context_sensitive;
basic_handler_registered = true;
presence_self.pr_com_id = *context;
presence_self.pr_title = fmt::truncate(Emu.GetTitle(), SCE_NP_BASIC_PRESENCE_TITLE_SIZE_MAX - 1);
}
if (g_cfg.net.psn_status != np_psn_status::psn_rpcn || !is_psn_active)
{
return;
}
std::lock_guard lock(mutex_rpcn);
if (!rpcn)
{
return;
}
auto current_presences = rpcn->get_presence_states();
for (auto& [npid, pr_info] : current_presences)
{
// Only communicates info about online users with presence
if (!pr_info.online || pr_info.pr_com_id.data[0] == 0)
{
continue;
}
basic_event to_add{};
strcpy_trunc(to_add.from.userId.handle.data, npid);
strcpy_trunc(to_add.from.name.data, npid);
if (std::memcmp(pr_info.pr_com_id.data, basic_handler.context.data, sizeof(pr_info.pr_com_id.data)) == 0)
{
to_add.event = SCE_NP_BASIC_EVENT_PRESENCE;
to_add.data = std::move(pr_info.pr_data);
}
else
{
if (basic_handler.context_sensitive)
{
to_add.event = SCE_NP_BASIC_EVENT_OUT_OF_CONTEXT;
}
else
{
to_add.event = SCE_NP_BASIC_EVENT_OFFLINE;
}
}
queue_basic_event(to_add);
send_basic_event(to_add.event, 0, 0);
}
}
SceNpCommunicationId np_handler::get_basic_handler_context()
{
std::lock_guard lock(basic_handler.mutex);
return basic_handler.context;
}
bool np_handler::send_basic_event(s32 event, s32 retCode, u32 reqId)
{
if (basic_handler.registered)
if (basic_handler_registered)
{
std::lock_guard lock(basic_handler.mutex);
sysutil_register_cb([handler_func = this->basic_handler.handler_func, handler_arg = this->basic_handler.handler_arg, event, retCode, reqId](ppu_thread& cb_ppu) -> s32
{
handler_func(cb_ppu, event, retCode, reqId, handler_arg);
@ -983,8 +1052,39 @@ namespace np
}
}
auto presence_updates = rpcn->get_presence_updates();
if (basic_handler_registered)
{
for (auto& [npid, pr_info] : presence_updates)
{
basic_event to_add{};
strcpy_trunc(to_add.from.userId.handle.data, npid);
strcpy_trunc(to_add.from.name.data, npid);
if (std::memcmp(pr_info.pr_com_id.data, basic_handler.context.data, sizeof(pr_info.pr_com_id.data)) == 0)
{
to_add.event = SCE_NP_BASIC_EVENT_PRESENCE;
to_add.data = std::move(pr_info.pr_data);
}
else
{
if (basic_handler.context_sensitive && !pr_info.pr_com_id.data[0] == 0)
{
to_add.event = SCE_NP_BASIC_EVENT_OUT_OF_CONTEXT;
}
else
{
to_add.event = SCE_NP_BASIC_EVENT_OFFLINE;
}
}
queue_basic_event(to_add);
send_basic_event(to_add.event, 0, 0);
}
}
auto messages = rpcn->get_new_messages();
if (basic_handler.registered)
if (basic_handler_registered)
{
for (const auto msg_id : messages)
{
@ -1027,7 +1127,7 @@ namespace np
}
}
if (!replies.empty() || !notifications.empty())
if (!replies.empty() || !notifications.empty() || !presence_updates.empty())
{
sleep = false;
}
@ -1109,16 +1209,7 @@ namespace np
u32 np_handler::add_players_to_history(vm::cptr<SceNpId> /*npids*/, u32 /*count*/)
{
const u32 req_id = get_req_id(REQUEST_ID_HIGH::MISC);
if (basic_handler.handler_func)
{
sysutil_register_cb([req_id, cb = basic_handler.handler_func, cb_arg = basic_handler.handler_arg](ppu_thread& cb_ppu) -> s32
{
cb(cb_ppu, SCE_NP_BASIC_EVENT_ADD_PLAYERS_HISTORY_RESULT, 0, req_id, cb_arg);
return 0;
});
}
send_basic_event(SCE_NP_BASIC_EVENT_ADD_PLAYERS_HISTORY_RESULT, 0, req_id);
return req_id;
}
@ -1147,6 +1238,102 @@ namespace np
return {CELL_OK, npid_friend};
}
void np_handler::set_presence(std::optional<std::string> status, std::optional<std::vector<u8>> data)
{
bool send_update = false;
if (status)
{
if (status != presence_self.pr_status)
{
presence_self.pr_status = *status;
send_update = true;
}
}
if (data)
{
if (data != presence_self.pr_data)
{
presence_self.pr_data = *data;
send_update = true;
}
}
if (send_update && is_psn_active)
{
std::lock_guard lock(mutex_rpcn);
if (!rpcn)
{
return;
}
rpcn->send_presence(presence_self.pr_com_id, presence_self.pr_title, presence_self.pr_status, presence_self.pr_comment, presence_self.pr_data);
}
}
template <typename T>
error_code np_handler::get_friend_presence_by_index(u32 index, SceNpUserInfo* user, T* pres)
{
if (!is_psn_active || g_cfg.net.psn_status != np_psn_status::psn_rpcn)
{
return SCE_NP_BASIC_ERROR_NOT_CONNECTED;
}
std::lock_guard lock(mutex_rpcn);
if (!rpcn)
{
return SCE_NP_BASIC_ERROR_NOT_CONNECTED;
}
auto friend_infos = rpcn->get_friend_presence_by_index(index);
if (!friend_infos)
{
return SCE_NP_BASIC_ERROR_INVALID_ARGUMENT;
}
const bool same_context = (std::memcmp(friend_infos->second.pr_com_id.data, basic_handler.context.data, sizeof(friend_infos->second.pr_com_id.data)) == 0);
strings_to_userinfo(friend_infos->first, friend_infos->first, "", *user);
onlinedata_to_presencedetails(friend_infos->second, same_context, *pres);
return CELL_OK;
}
template error_code np_handler::get_friend_presence_by_index<SceNpBasicPresenceDetails>(u32 index, SceNpUserInfo* user, SceNpBasicPresenceDetails* pres);
template error_code np_handler::get_friend_presence_by_index<SceNpBasicPresenceDetails2>(u32 index, SceNpUserInfo* user, SceNpBasicPresenceDetails2* pres);
template <typename T>
error_code np_handler::get_friend_presence_by_npid(const SceNpId& npid, T* pres)
{
if (!is_psn_active || g_cfg.net.psn_status != np_psn_status::psn_rpcn)
{
return SCE_NP_BASIC_ERROR_NOT_CONNECTED;
}
std::lock_guard lock(mutex_rpcn);
if (!rpcn)
{
return SCE_NP_BASIC_ERROR_NOT_CONNECTED;
}
auto friend_infos = rpcn->get_friend_presence_by_npid(std::string(reinterpret_cast<const char*>(&npid.handle.data[0])));
if (!friend_infos)
{
return SCE_NP_BASIC_ERROR_INVALID_ARGUMENT;
}
const bool same_context = (std::memcmp(friend_infos->second.pr_com_id.data, basic_handler.context.data, sizeof(friend_infos->second.pr_com_id.data)) == 0);
onlinedata_to_presencedetails(friend_infos->second, same_context, *pres);
return CELL_OK;
}
template error_code np_handler::get_friend_presence_by_npid<SceNpBasicPresenceDetails>(const SceNpId& npid, SceNpBasicPresenceDetails* pres);
template error_code np_handler::get_friend_presence_by_npid<SceNpBasicPresenceDetails2>(const SceNpId& npid, SceNpBasicPresenceDetails2* pres);
std::pair<error_code, std::optional<SceNpId>> np_handler::local_get_npid(u64 room_id, u16 member_id)
{
return np_cache.get_npid(room_id, member_id);

View File

@ -120,16 +120,10 @@ namespace np
vm::ptr<SceNpManagerCallback> manager_cb{}; // Connection status and tickets
vm::ptr<void> manager_cb_arg{};
// Basic event handler;
struct
{
SceNpCommunicationId context{};
vm::ptr<SceNpBasicEventHandler> handler_func;
vm::ptr<void> handler_arg;
bool registered = false;
bool context_sensitive = false;
} basic_handler;
atomic_t<bool> basic_handler_registered = false;
void register_basic_handler(vm::cptr<SceNpCommunicationId> context, vm::ptr<SceNpBasicEventHandler> handler, vm::ptr<void> arg, bool context_sensitive);
SceNpCommunicationId get_basic_handler_context();
void queue_basic_event(basic_event to_queue);
bool send_basic_event(s32 event, s32 retCode, u32 reqId);
error_code get_basic_event(vm::ptr<s32> event, vm::ptr<SceNpUserInfo> from, vm::ptr<u8> data, vm::ptr<u32> size);
@ -206,6 +200,13 @@ namespace np
u32 get_num_friends();
u32 get_num_blocks();
std::pair<error_code, std::optional<SceNpId>> get_friend_by_index(u32 index);
void set_presence(std::optional<std::string> status, std::optional<std::vector<u8>> data);
template <typename T>
error_code get_friend_presence_by_index(u32 index, SceNpUserInfo* user, T* pres);
template <typename T>
error_code get_friend_presence_by_npid(const SceNpId& npid, T* pres);
// Misc stuff
void req_ticket(u32 version, const SceNpId* npid, const char* service_id, const u8* cookie, u32 cookie_size, const char* entitlement_id, u32 consumed_count);
@ -350,6 +351,16 @@ namespace np
bool m_inited_np_handler_dependencies = false;
private:
// Basic event handler;
struct
{
shared_mutex mutex;
SceNpCommunicationId context{};
vm::ptr<SceNpBasicEventHandler> handler_func;
vm::ptr<void> handler_arg;
bool context_sensitive = false;
} basic_handler;
bool is_connected = false;
bool is_psn_active = false;
@ -414,5 +425,15 @@ namespace np
// UPNP
upnp_handler upnp;
// Presence
struct
{
SceNpCommunicationId pr_com_id;
std::string pr_title;
std::string pr_status;
std::string pr_comment;
std::vector<u8> pr_data;
} presence_self;
};
} // namespace np

View File

@ -22,6 +22,34 @@ namespace np
return fmt::format("%02X:%02X:%02X:%02X:%02X:%02X", ether[0], ether[1], ether[2], ether[3], ether[4], ether[5]);
}
void strings_to_userinfo(std::string_view npid, std::string_view online_name, std::string_view avatar_url, SceNpUserInfo& user_info)
{
memset(&user_info, 0, sizeof(user_info));
strcpy_trunc(user_info.userId.handle.data, npid);
strcpy_trunc(user_info.name.data, online_name);
strcpy_trunc(user_info.icon.data, avatar_url);
}
template <typename T>
void onlinedata_to_presencedetails(const rpcn::friend_online_data& data, bool same_context, T& details)
{
memset(&details, 0, sizeof(T));
details.state = data.online ? (same_context ? SCE_NP_BASIC_PRESENCE_STATE_IN_CONTEXT : SCE_NP_BASIC_PRESENCE_STATE_OUT_OF_CONTEXT) : SCE_NP_BASIC_PRESENCE_STATE_OFFLINE;
strcpy_trunc(details.title, data.pr_title);
strcpy_trunc(details.status, data.pr_status);
strcpy_trunc(details.comment, data.pr_comment);
details.size = std::min<u32>(::size32(data.pr_data), SCE_NP_BASIC_MAX_PRESENCE_SIZE);
std::memcpy(details.data, data.pr_data.data(), details.size);
if constexpr (std::is_same_v<T, SceNpBasicPresenceDetails2>)
{
details.struct_size = sizeof(SceNpBasicPresenceDetails2);
}
}
template void onlinedata_to_presencedetails<SceNpBasicPresenceDetails>(const rpcn::friend_online_data& data, bool same_context, SceNpBasicPresenceDetails& details);
template void onlinedata_to_presencedetails<SceNpBasicPresenceDetails2>(const rpcn::friend_online_data& data, bool same_context, SceNpBasicPresenceDetails2& details);
void string_to_npid(std::string_view str, SceNpId& npid)
{
memset(&npid, 0, sizeof(npid));

View File

@ -3,6 +3,7 @@
#include "util/types.hpp"
#include "Emu/Cell/Modules/sceNp.h"
#include "Emu/Cell/Modules/sceNp2.h"
#include "rpcn_client.h"
namespace np
{
@ -13,6 +14,10 @@ namespace np
void string_to_online_name(std::string_view str, SceNpOnlineName& online_name);
void string_to_avatar_url(std::string_view str, SceNpAvatarUrl& avatar_url);
void string_to_communication_id(std::string_view str, SceNpCommunicationId& comm_id);
void strings_to_userinfo(std::string_view npid, std::string_view online_name, std::string_view avatar_url, SceNpUserInfo& user_info);
template <typename T>
void onlinedata_to_presencedetails(const rpcn::friend_online_data& data, bool same_context, T& details);
bool is_valid_npid(const SceNpId& npid);
bool is_same_npid(const SceNpId& npid_1, const SceNpId& npid_2);

View File

@ -47,6 +47,11 @@ LOG_CHANNEL(rpcn_log, "rpcn");
int get_native_error();
void vec_stream::dump() const
{
rpcn_log.error("vec_stream dump:\n%s", fmt::buf_to_hexstring(vec.data(), vec.size()));
}
namespace rpcn
{
localized_string_id rpcn_state_to_localized_string_id(rpcn::rpcn_state state)
@ -74,9 +79,8 @@ namespace rpcn
return get_localized_string(rpcn_state_to_localized_string_id(state));
}
constexpr u32 RPCN_PROTOCOL_VERSION = 20;
constexpr u32 RPCN_PROTOCOL_VERSION = 21;
constexpr usz RPCN_HEADER_SIZE = 15;
constexpr usz COMMUNICATION_ID_SIZE = 9;
bool is_error(ErrorType err)
{
@ -293,8 +297,28 @@ namespace rpcn
{
if (msg.size() == 6)
{
addr_sig = read_from_ptr<le_t<u32>>(&msg[0]);
port_sig = read_from_ptr<be_t<u16>>(&msg[4]);
const u32 new_addr_sig = read_from_ptr<le_t<u32>>(&msg[0]);
const u32 new_port_sig = read_from_ptr<be_t<u16>>(&msg[4]);
const u32 old_addr_sig = addr_sig;
const u32 old_port_sig = port_sig;
if (new_addr_sig != old_addr_sig)
{
addr_sig = new_addr_sig;
if (old_addr_sig == 0)
{
addr_sig.notify_one();
}
}
if (new_port_sig != old_port_sig)
{
port_sig = new_port_sig;
if (old_port_sig == 0)
{
port_sig.notify_one();
}
}
last_pong_time = now;
}
@ -351,7 +375,7 @@ namespace rpcn
case recvn_result::recvn_timeout: return error_and_disconnect("Failed to read a packet header on socket");
case recvn_result::recvn_nodata: return true;
case recvn_result::recvn_success: break;
case recvn_result::recvn_terminate: return error_and_disconnect("Recvn was forcefully aborted");
case recvn_result::recvn_terminate: return error_and_disconnect_notice("Recvn was forcefully aborted");
}
const u8 packet_type = header[0];
@ -384,7 +408,8 @@ namespace rpcn
command == CommandType::AddFriend || command == CommandType::RemoveFriend ||
command == CommandType::AddBlock || command == CommandType::RemoveBlock ||
command == CommandType::SendMessage || command == CommandType::SendToken ||
command == CommandType::SendResetToken || command == CommandType::ResetPassword || command == CommandType::GetNetworkTime)
command == CommandType::SendResetToken || command == CommandType::ResetPassword ||
command == CommandType::GetNetworkTime || command == CommandType::SetPresence)
{
std::lock_guard lock(mutex_replies_sync);
replies_sync.insert(std::make_pair(packet_id, std::make_pair(command, std::move(data))));
@ -412,6 +437,7 @@ namespace rpcn
case NotificationType::FriendLost:
case NotificationType::FriendQuery:
case NotificationType::FriendStatus:
case NotificationType::FriendPresenceChanged:
{
handle_friend_notification(command, std::move(data));
break;
@ -918,14 +944,27 @@ namespace rpcn
avatar_url = reply.get_string(false);
user_id = reply.get<s64>();
auto get_usernames_and_status = [](vec_stream& stream, std::map<std::string, std::pair<bool, u64>>& friends)
auto get_usernames_and_status = [](vec_stream& stream, std::map<std::string, friend_online_data>& friends)
{
u32 num_friends = stream.get<u32>();
for (u32 i = 0; i < num_friends; i++)
{
std::string friend_name = stream.get_string(false);
bool online = !!(stream.get<u8>());
friends.insert(std::make_pair(std::move(friend_name), std::make_pair(online, 0)));
SceNpCommunicationId pr_com_id = stream.get_com_id();
std::string pr_title = fmt::truncate(stream.get_string(true), SCE_NP_BASIC_PRESENCE_TITLE_SIZE_MAX - 1);
std::string pr_status = fmt::truncate(stream.get_string(true), SCE_NP_BASIC_PRESENCE_EXTENDED_STATUS_SIZE_MAX - 1);
std::string pr_comment = fmt::truncate(stream.get_string(true), SCE_NP_BASIC_PRESENCE_COMMENT_SIZE_MAX - 1);
std::vector<u8> pr_data = stream.get_rawdata();
if (pr_data.size() > SCE_NP_BASIC_MAX_PRESENCE_SIZE)
{
pr_data.resize(SCE_NP_BASIC_MAX_PRESENCE_SIZE);
}
friend_online_data infos(online, std::move(pr_com_id), std::move(pr_title), std::move(pr_status), std::move(pr_comment), std::move(pr_data));
friends.insert(std::make_pair(std::move(friend_name), std::move(infos)));
}
};
@ -1169,40 +1208,40 @@ namespace rpcn
}
std::vector<std::pair<u16, std::vector<u8>>> rpcn_client::get_notifications()
{
std::vector<std::pair<u16, std::vector<u8>>> notifs;
{
std::lock_guard lock(mutex_notifs);
notifs = std::move(notifications);
std::vector<std::pair<u16, std::vector<u8>>> notifs = std::move(notifications);
notifications.clear();
}
return notifs;
}
std::unordered_map<u32, std::pair<u16, std::vector<u8>>> rpcn_client::get_replies()
{
std::unordered_map<u32, std::pair<u16, std::vector<u8>>> ret_replies;
{
std::lock_guard lock(mutex_replies);
ret_replies = std::move(replies);
std::unordered_map<u32, std::pair<u16, std::vector<u8>>> ret_replies = std::move(replies);
replies.clear();
return ret_replies;
}
return ret_replies;
std::unordered_map<std::string, friend_online_data> rpcn_client::get_presence_updates()
{
std::lock_guard lock(mutex_presence_updates);
std::unordered_map<std::string, friend_online_data> ret_updates = std::move(presence_updates);
presence_updates.clear();
return ret_updates;
}
std::map<std::string, friend_online_data> rpcn_client::get_presence_states()
{
std::lock_guard lock(mutex_friends);
return friend_infos.friends;
}
std::vector<u64> rpcn_client::get_new_messages()
{
std::vector<u64> ret_new_messages;
{
std::lock_guard lock(mutex_messages);
ret_new_messages = std::move(new_messages);
std::vector<u64> ret_new_messages = std::move(new_messages);
new_messages.clear();
}
return ret_new_messages;
}
@ -1415,17 +1454,9 @@ namespace rpcn
auto req_finished = CreateCreateJoinRoomRequest(builder, req->worldId, req->lobbyId, req->maxSlot, req->flagAttr, final_binattrinternal_vec, final_searchintattrexternal_vec,
final_searchbinattrexternal_vec, final_binattrexternal_vec, final_roompassword, final_groupconfigs_vec, final_passwordSlotMask, final_allowedusers_vec, final_blockedusers_vec, final_grouplabel,
final_memberbinattrinternal_vec, req->teamId, final_optparam);
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::CreateRoom, req_id, data);
return forge_request_with_com_id(builder, communication_id, CommandType::CreateRoom, req_id);
}
bool rpcn_client::join_room(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2JoinRoomRequest* req)
@ -1452,17 +1483,9 @@ namespace rpcn
flatbuffers::Offset<PresenceOptionData> final_optdata = CreatePresenceOptionData(builder, builder.CreateVector(req->optData.data, 16), req->optData.length);
auto req_finished = CreateJoinRoomRequest(builder, req->roomId, final_roompassword, final_grouplabel, final_memberbinattrinternal_vec, final_optdata, req->teamId);
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::JoinRoom, req_id, data);
return forge_request_with_com_id(builder, communication_id, CommandType::JoinRoom, req_id);
}
bool rpcn_client::leave_room(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2LeaveRoomRequest* req)
@ -1471,15 +1494,8 @@ namespace rpcn
flatbuffers::Offset<PresenceOptionData> final_optdata = CreatePresenceOptionData(builder, builder.CreateVector(req->optData.data, 16), req->optData.length);
auto req_finished = CreateLeaveRoomRequest(builder, req->roomId, final_optdata);
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::LeaveRoom, req_id, data);
return forge_request_with_com_id(builder, communication_id, CommandType::LeaveRoom, req_id);
}
bool rpcn_client::search_room(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2SearchRoomRequest* req)
@ -1538,15 +1554,8 @@ namespace rpcn
auto req_finished = s_req.Finish();
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + bufsize + sizeof(u32));
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::SearchRoom, req_id, data);
return forge_request_with_com_id(builder, communication_id, CommandType::SearchRoom, req_id);
}
bool rpcn_client::get_roomdata_external_list(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2GetRoomDataExternalListRequest* req)
@ -1564,17 +1573,9 @@ namespace rpcn
}
auto req_finished = CreateGetRoomDataExternalListRequestDirect(builder, &roomIds, &attrIds);
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + bufsize + sizeof(u32));
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::GetRoomDataExternalList, req_id, data);
return forge_request_with_com_id(builder, communication_id, CommandType::GetRoomDataExternalList, req_id);
}
bool rpcn_client::set_roomdata_external(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2SetRoomDataExternalRequest* req)
@ -1614,17 +1615,9 @@ namespace rpcn
final_binattrexternal_vec = builder.CreateVector(davec);
}
auto req_finished = CreateSetRoomDataExternalRequest(builder, req->roomId, final_searchintattrexternal_vec, final_searchbinattrexternal_vec, final_binattrexternal_vec);
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + bufsize + sizeof(u32));
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::SetRoomDataExternal, req_id, data);
return forge_request_with_com_id(builder, communication_id, CommandType::SetRoomDataExternal, req_id);
}
bool rpcn_client::get_roomdata_internal(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2GetRoomDataInternalRequest* req)
@ -1643,17 +1636,9 @@ namespace rpcn
}
auto req_finished = CreateGetRoomDataInternalRequest(builder, req->roomId, final_attr_ids_vec);
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + bufsize + sizeof(u32));
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::GetRoomDataInternal, req_id, data);
return forge_request_with_com_id(builder, communication_id, CommandType::GetRoomDataInternal, req_id);
}
bool rpcn_client::set_roomdata_internal(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2SetRoomDataInternalRequest* req)
@ -1698,17 +1683,9 @@ namespace rpcn
auto req_finished =
CreateSetRoomDataInternalRequest(builder, req->roomId, req->flagFilter, req->flagAttr, final_binattrinternal_vec, final_grouppasswordconfig_vec, final_passwordSlotMask, final_ownerprivilege_vec);
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + bufsize + sizeof(u32));
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::SetRoomDataInternal, req_id, data);
return forge_request_with_com_id(builder, communication_id, CommandType::SetRoomDataInternal, req_id);
}
bool rpcn_client::set_roommemberdata_internal(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpMatching2SetRoomMemberDataInternalRequest* req)
@ -1727,17 +1704,9 @@ namespace rpcn
}
auto req_finished = CreateSetRoomMemberDataInternalRequest(builder, req->roomId, req->memberId, req->teamId, final_binattrinternal_vec);
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + bufsize + sizeof(u32));
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::SetRoomMemberDataInternal, req_id, data);
return forge_request_with_com_id(builder, communication_id, CommandType::SetRoomMemberDataInternal, req_id);
}
bool rpcn_client::ping_room_owner(u32 req_id, const SceNpCommunicationId& communication_id, u64 room_id)
@ -1777,17 +1746,9 @@ namespace rpcn
}
auto req_finished = CreateSendRoomMessageRequest(builder, req->roomId, req->castType, builder.CreateVector(dst.data(), dst.size()), builder.CreateVector(reinterpret_cast<const u8*>(req->msg.get_ptr()), req->msgLen), req->option);
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::SendRoomMessage, req_id, data);
return forge_request_with_com_id(builder, communication_id, CommandType::SendRoomMessage, req_id);
}
bool rpcn_client::req_sign_infos(u32 req_id, const std::string& npid)
@ -1840,9 +1801,7 @@ namespace rpcn
reinterpret_cast<le_t<u32>&>(data[0]) = static_cast<u32>(bufsize);
memcpy(data.data() + sizeof(u32), buf, bufsize);
u64 req_id = rpcn_request_counter.fetch_add(1);
return forge_send(CommandType::SendMessage, req_id, data);
return forge_send(CommandType::SendMessage, rpcn_request_counter.fetch_add(1), data);
}
bool rpcn_client::get_board_infos(u32 req_id, const SceNpCommunicationId& communication_id, SceNpScoreBoardId board_id)
@ -1859,34 +1818,18 @@ namespace rpcn
flatbuffers::FlatBufferBuilder builder(1024);
auto req_finished = CreateRecordScoreRequestDirect(builder, board_id, char_id, score, comment ? (*comment).c_str() : nullptr, score_data ? &*score_data : nullptr);
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::RecordScore, req_id, data);
return forge_request_with_com_id(builder, communication_id, CommandType::RecordScore, req_id);
}
bool rpcn_client::get_score_range(u32 req_id, const SceNpCommunicationId& communication_id, SceNpScoreBoardId board_id, u32 start_rank, u32 num_rank, bool with_comment, bool with_gameinfo)
{
flatbuffers::FlatBufferBuilder builder(1024);
auto req_finished = CreateGetScoreRangeRequest(builder, board_id, start_rank, num_rank, with_comment, with_gameinfo);
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::GetScoreRange, req_id, data);
return forge_request_with_com_id(builder, communication_id, CommandType::GetScoreRange, req_id);
}
bool rpcn_client::get_score_npid(u32 req_id, const SceNpCommunicationId& communication_id, SceNpScoreBoardId board_id, const std::vector<std::pair<SceNpId, s32>>& npids, bool with_comment, bool with_gameinfo)
@ -1903,15 +1846,8 @@ namespace rpcn
auto req_finished = CreateGetScoreNpIdRequest(builder, board_id, builder.CreateVector(davec), with_comment, with_gameinfo);
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::GetScoreNpid, req_id, data);
return forge_request_with_com_id(builder, communication_id, CommandType::GetScoreNpid, req_id);
}
bool rpcn_client::get_score_friend(u32 req_id, const SceNpCommunicationId& communication_id, SceNpScoreBoardId board_id, bool include_self, bool with_comment, bool with_gameinfo, u32 max_entries)
@ -1920,15 +1856,7 @@ namespace rpcn
auto req_finished = CreateGetScoreFriendsRequest(builder, board_id, include_self, max_entries, with_comment, with_gameinfo);
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::GetScoreFriends, req_id, data);
return forge_request_with_com_id(builder, communication_id, CommandType::GetScoreFriends, req_id);
}
bool rpcn_client::record_score_data(u32 req_id, const SceNpCommunicationId& communication_id, SceNpScorePcId pc_id, SceNpScoreBoardId board_id, s64 score, const std::vector<u8>& score_data)
@ -1956,15 +1884,7 @@ namespace rpcn
auto req_finished = CreateGetScoreGameDataRequest(builder, board_id, builder.CreateString(reinterpret_cast<const char*>(npid.handle.data)), pc_id);
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::GetScoreData, req_id, data);
return forge_request_with_com_id(builder, communication_id, CommandType::GetScoreData, req_id);
}
bool rpcn_client::tus_set_multislot_variable(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, vm::cptr<SceNpTusSlotId> slotIdArray, vm::cptr<s64> variableArray, s32 arrayNum, bool vuser)
@ -1976,15 +1896,7 @@ namespace rpcn
auto req_finished = CreateTusSetMultiSlotVariableRequest(builder, CreateTusUser(builder, vuser, builder.CreateString(targetNpId.data)), builder.CreateVector(slotid_array), builder.CreateVector(variable_array));
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::TusSetMultiSlotVariable, req_id, data);
return forge_request_with_com_id(builder, communication_id, CommandType::TusSetMultiSlotVariable, req_id);
}
bool rpcn_client::tus_get_multislot_variable(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, vm::cptr<SceNpTusSlotId> slotIdArray, s32 arrayNum, bool vuser)
@ -1995,15 +1907,7 @@ namespace rpcn
auto req_finished = CreateTusGetMultiSlotVariableRequest(builder, CreateTusUser(builder, vuser, builder.CreateString(targetNpId.data)), builder.CreateVector(slotid_array));
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::TusGetMultiSlotVariable, req_id, data);
return forge_request_with_com_id(builder, communication_id, CommandType::TusGetMultiSlotVariable, req_id);
}
bool rpcn_client::tus_get_multiuser_variable(u32 req_id, const SceNpCommunicationId& communication_id, const std::vector<SceNpOnlineId>& targetNpIdArray, SceNpTusSlotId slotId, s32 arrayNum, bool vuser)
@ -2019,15 +1923,7 @@ namespace rpcn
auto req_finished = CreateTusGetMultiUserVariableRequest(builder, builder.CreateVector(davec), slotId);
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::TusGetMultiUserVariable, req_id, data);
return forge_request_with_com_id(builder, communication_id, CommandType::TusGetMultiUserVariable, req_id);
}
bool rpcn_client::tus_get_friends_variable(u32 req_id, const SceNpCommunicationId& communication_id, SceNpTusSlotId slotId, bool includeSelf, s32 sortType, s32 arrayNum)
@ -2036,15 +1932,7 @@ namespace rpcn
auto req_finished = CreateTusGetFriendsVariableRequest(builder, slotId, includeSelf, sortType, arrayNum);
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::TusGetFriendsVariable, req_id, data);
return forge_request_with_com_id(builder, communication_id, CommandType::TusGetFriendsVariable, req_id);
}
bool rpcn_client::tus_add_and_get_variable(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, s64 inVariable, vm::ptr<SceNpTusAddAndGetVariableOptParam> option, bool vuser)
@ -2072,15 +1960,7 @@ namespace rpcn
auto req_finished = CreateTusAddAndGetVariableRequest(builder, CreateTusUser(builder, vuser, builder.CreateString(targetNpId.data)), slotId, inVariable, isLastChangedDate, isLastChangedAuthorId);
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::TusAddAndGetVariable, req_id, data);
return forge_request_with_com_id(builder, communication_id, CommandType::TusAddAndGetVariable, req_id);
}
bool rpcn_client::tus_try_and_set_variable(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, s32 opeType, s64 variable, vm::ptr<SceNpTusTryAndSetVariableOptParam> option, bool vuser)
@ -2116,15 +1996,7 @@ namespace rpcn
auto req_finished = CreateTusTryAndSetVariableRequest(builder, CreateTusUser(builder, vuser, builder.CreateString(targetNpId.data)), slotId, opeType, variable, isLastChangedDate, isLastChangedAuthorId, compareValue);
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::TusTryAndSetVariable, req_id, data);
return forge_request_with_com_id(builder, communication_id, CommandType::TusTryAndSetVariable, req_id);
}
bool rpcn_client::tus_delete_multislot_variable(u32 req_id, const SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, vm::cptr<SceNpTusSlotId> slotIdArray, s32 arrayNum, bool vuser)
@ -2135,15 +2007,7 @@ namespace rpcn
auto req_finished = CreateTusDeleteMultiSlotVariableRequest(builder, CreateTusUser(builder, vuser, builder.CreateString(targetNpId.data)), builder.CreateVector(slotid_array));
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::TusDeleteMultiSlotVariable, req_id, data);
return forge_request_with_com_id(builder, communication_id, CommandType::TusDeleteMultiSlotVariable, req_id);
}
bool rpcn_client::tus_set_data(u32 req_id, SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, const std::vector<u8>& tus_data, vm::cptr<SceNpTusDataInfo> info, vm::ptr<SceNpTusSetDataOptParam> option, bool vuser)
@ -2178,15 +2042,7 @@ namespace rpcn
auto req_finished = CreateTusSetDataRequest(builder, CreateTusUser(builder, vuser, builder.CreateString(targetNpId.data)), slotId, builder.CreateVector(tus_data), fb_info, isLastChangedDate, isLastChangedAuthorId);
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::TusSetData, req_id, data);
return forge_request_with_com_id(builder, communication_id, CommandType::TusSetData, req_id);
}
bool rpcn_client::tus_get_data(u32 req_id, SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, SceNpTusSlotId slotId, bool vuser)
@ -2195,15 +2051,7 @@ namespace rpcn
auto req_finished = CreateTusGetDataRequest(builder, CreateTusUser(builder, vuser, builder.CreateString(targetNpId.data)), slotId);
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::TusGetData, req_id, data);
return forge_request_with_com_id(builder, communication_id, CommandType::TusGetData, req_id);
}
bool rpcn_client::tus_get_multislot_data_status(u32 req_id, SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, vm::cptr<SceNpTusSlotId> slotIdArray, s32 arrayNum, bool vuser)
@ -2214,15 +2062,7 @@ namespace rpcn
auto req_finished = CreateTusGetMultiSlotDataStatusRequest(builder, CreateTusUser(builder, vuser, builder.CreateString(targetNpId.data)), builder.CreateVector(slotid_array));
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::TusGetMultiSlotDataStatus, req_id, data);
return forge_request_with_com_id(builder, communication_id, CommandType::TusGetMultiSlotDataStatus, req_id);
}
bool rpcn_client::tus_get_multiuser_data_status(u32 req_id, SceNpCommunicationId& communication_id, const std::vector<SceNpOnlineId>& targetNpIdArray, SceNpTusSlotId slotId, s32 arrayNum, bool vuser)
@ -2238,15 +2078,7 @@ namespace rpcn
auto req_finished = CreateTusGetMultiUserDataStatusRequest(builder, builder.CreateVector(davec), slotId);
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::TusGetMultiUserDataStatus, req_id, data);
return forge_request_with_com_id(builder, communication_id, CommandType::TusGetMultiUserDataStatus, req_id);
}
bool rpcn_client::tus_get_friends_data_status(u32 req_id, SceNpCommunicationId& communication_id, SceNpTusSlotId slotId, bool includeSelf, s32 sortType, s32 arrayNum)
@ -2255,15 +2087,7 @@ namespace rpcn
auto req_finished = CreateTusGetFriendsDataStatusRequest(builder, slotId, includeSelf, sortType, arrayNum);
builder.Finish(req_finished);
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::TusGetFriendsDataStatus, req_id, data);
return forge_request_with_com_id(builder, communication_id, CommandType::TusGetFriendsDataStatus, req_id);
}
bool rpcn_client::tus_delete_multislot_data(u32 req_id, SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, vm::cptr<SceNpTusSlotId> slotIdArray, s32 arrayNum, bool vuser)
@ -2274,15 +2098,29 @@ namespace rpcn
auto req_finished = CreateTusDeleteMultiSlotDataRequest(builder, CreateTusUser(builder, vuser, builder.CreateString(targetNpId.data)), builder.CreateVector(slotid_array));
builder.Finish(req_finished);
return forge_request_with_com_id(builder, communication_id, CommandType::TusDeleteMultiSlotData, req_id);
}
bool rpcn_client::send_presence(const SceNpCommunicationId& pr_com_id, const std::string& pr_title, const std::string& pr_status, const std::string& pr_comment, const std::vector<u8>& pr_data)
{
flatbuffers::FlatBufferBuilder builder(1024);
auto req_finished = CreateSetPresenceRequest(builder, builder.CreateString(pr_title), builder.CreateString(pr_status), builder.CreateString(pr_comment), builder.CreateVector(pr_data));
builder.Finish(req_finished);
return forge_request_with_com_id(builder, pr_com_id, CommandType::SetPresence, rpcn_request_counter.fetch_add(1));
}
bool rpcn_client::forge_request_with_com_id(const flatbuffers::FlatBufferBuilder& builder, const SceNpCommunicationId& com_id, CommandType command, u64 packet_id)
{
const u8* buf = builder.GetBufferPointer();
const usz bufsize = builder.GetSize();
std::vector<u8> data(COMMUNICATION_ID_SIZE + sizeof(u32) + bufsize);
memcpy(data.data(), communication_id.data, COMMUNICATION_ID_SIZE);
memcpy(data.data(), com_id.data, COMMUNICATION_ID_SIZE);
reinterpret_cast<le_t<u32>&>(data[COMMUNICATION_ID_SIZE]) = static_cast<u32>(bufsize);
memcpy(data.data() + COMMUNICATION_ID_SIZE + sizeof(u32), buf, bufsize);
return forge_send(CommandType::TusDeleteMultiSlotData, req_id, data);
return forge_send(command, packet_id, data);
}
std::vector<u8> rpcn_client::forge_request(u16 command, u64 packet_id, const std::vector<u8>& data) const
@ -2306,6 +2144,13 @@ namespace rpcn
return false;
}
bool rpcn_client::error_and_disconnect_notice(const std::string& error_msg)
{
connected = false;
rpcn_log.notice("%s", error_msg);
return false;
}
rpcn_state rpcn_client::wait_for_connection()
{
{
@ -2402,12 +2247,12 @@ namespace rpcn
}
friend_infos.requests_received.insert(username);
call_callbacks(ntype, username, 0);
call_callbacks(ntype, username, false);
break;
}
case NotificationType::FriendNew: // Add a friend to the friendlist(either accepted a friend request or friend accepted it)
{
bool status = !!vdata.get<u8>();
bool online = !!vdata.get<u8>();
std::string username = vdata.get_string(false);
if (vdata.is_error())
{
@ -2417,8 +2262,8 @@ namespace rpcn
friend_infos.requests_received.erase(username);
friend_infos.requests_sent.erase(username);
friend_infos.friends.insert(std::make_pair(username, std::make_pair(status, 0)));
call_callbacks(ntype, username, status);
friend_infos.friends.insert(std::make_pair(username, friend_online_data(online, 0)));
call_callbacks(ntype, username, online);
break;
}
@ -2432,12 +2277,12 @@ namespace rpcn
}
friend_infos.friends.erase(username);
call_callbacks(ntype, username, 0);
call_callbacks(ntype, username, false);
break;
}
case NotificationType::FriendStatus: // Set status of friend to Offline or Online
{
bool status = !!vdata.get<u8>();
bool online = !!vdata.get<u8>();
u64 timestamp = vdata.get<u64>();
std::string username = vdata.get_string(false);
if (vdata.is_error())
@ -2448,15 +2293,54 @@ namespace rpcn
if (auto u = friend_infos.friends.find(username); u != friend_infos.friends.end())
{
if (timestamp < u->second.second)
if (timestamp < u->second.timestamp)
{
break;
}
u->second.second = timestamp;
u->second.first = status;
call_callbacks(ntype, username, status);
// clear presence data on online/offline
u->second = friend_online_data(online, timestamp);
{
std::lock_guard lock(mutex_presence_updates);
presence_updates.insert_or_assign(username, u->second);
}
call_callbacks(ntype, username, online);
}
break;
}
case NotificationType::FriendPresenceChanged:
{
std::string npid = vdata.get_string(true);
SceNpCommunicationId pr_com_id = vdata.get_com_id();
std::string pr_title = fmt::truncate(vdata.get_string(true), SCE_NP_BASIC_PRESENCE_TITLE_SIZE_MAX - 1);
std::string pr_status = fmt::truncate(vdata.get_string(true), SCE_NP_BASIC_PRESENCE_EXTENDED_STATUS_SIZE_MAX - 1);
std::string pr_comment = fmt::truncate(vdata.get_string(true), SCE_NP_BASIC_PRESENCE_COMMENT_SIZE_MAX - 1);
std::vector<u8> pr_data = vdata.get_rawdata();
if (pr_data.size() > SCE_NP_BASIC_MAX_PRESENCE_SIZE)
{
pr_data.resize(SCE_NP_BASIC_MAX_PRESENCE_SIZE);
}
if (vdata.is_error())
{
rpcn_log.error("Error parsing FriendPresenceChanged notification");
break;
}
if (auto u = friend_infos.friends.find(npid); u != friend_infos.friends.end())
{
u->second.pr_com_id = std::move(pr_com_id);
u->second.pr_title = std::move(pr_title);
u->second.pr_status = std::move(pr_status);
u->second.pr_comment = std::move(pr_comment);
u->second.pr_data = std::move(pr_data);
std::lock_guard lock(mutex_presence_updates);
presence_updates.insert_or_assign(std::move(npid), u->second);
}
break;
}
default:
@ -2607,4 +2491,25 @@ namespace rpcn
return it->first;
}
std::optional<std::pair<std::string, friend_online_data>> rpcn_client::get_friend_presence_by_index(u32 index)
{
std::lock_guard lock(mutex_friends);
if (index >= friend_infos.friends.size())
{
return std::nullopt;
}
auto it = friend_infos.friends.begin();
std::advance(it, index);
return std::optional(*it);
}
std::optional<std::pair<std::string, friend_online_data>> rpcn_client::get_friend_presence_by_npid(const std::string& npid)
{
std::lock_guard lock(mutex_friends);
const auto it = friend_infos.friends.find(npid);
return it == friend_infos.friends.end() ? std::nullopt : std::optional(*it);
}
} // namespace rpcn

View File

@ -39,6 +39,8 @@
#pragma GCC diagnostic pop
#endif
constexpr usz COMMUNICATION_ID_SIZE = 9;
class vec_stream
{
public:
@ -50,15 +52,17 @@ public:
return error;
}
void dump() const;
// Getters
template <typename T>
T get()
{
if (sizeof(T) + i > vec.size())
if (sizeof(T) + i > vec.size() || error)
{
error = true;
return 0;
return static_cast<T>(0);
}
T res = read_from_ptr<le_t<T>>(&vec[i]);
i += sizeof(T);
@ -83,16 +87,34 @@ public:
}
std::vector<u8> get_rawdata()
{
std::vector<u8> ret;
u32 size = get<u32>();
if ((vec.begin() + i + size) <= vec.end())
std::copy(vec.begin() + i, vec.begin() + i + size, std::back_inserter(ret));
else
if (i + size > vec.size())
{
error = true;
return {};
}
std::vector<u8> ret;
std::copy(vec.begin() + i, vec.begin() + i + size, std::back_inserter(ret));
i += size;
return ret;
}
SceNpCommunicationId get_com_id()
{
if (i + COMMUNICATION_ID_SIZE > vec.size() || error)
{
error = true;
return {};
}
SceNpCommunicationId com_id{};
std::memcpy(&com_id.data[0], &vec[i], COMMUNICATION_ID_SIZE);
i += COMMUNICATION_ID_SIZE;
return com_id;
}
template <typename T>
const T* get_flatbuffer()
{
@ -197,6 +219,8 @@ namespace rpcn
TusGetMultiUserDataStatus,
TusGetFriendsDataStatus,
TusDeleteMultiSlotData,
ClearPresence,
SetPresence,
};
enum NotificationType : u16
@ -214,6 +238,7 @@ namespace rpcn
FriendStatus, // Set status of friend to Offline or Online
RoomMessageReceived,
MessageReceived,
FriendPresenceChanged,
};
enum class rpcn_state
@ -276,9 +301,26 @@ namespace rpcn
using friend_cb_func = void (*)(void* param, NotificationType ntype, const std::string& username, bool status);
using message_cb_func = void (*)(void* param, const std::shared_ptr<std::pair<std::string, message_data>> new_msg, u64 msg_id);
struct friend_online_data
{
friend_online_data(bool online, SceNpCommunicationId&& pr_com_id, std::string&& pr_title, std::string&& pr_status, std::string&& pr_comment, std::vector<u8>&& pr_data)
: online(online), timestamp(0), pr_com_id(pr_com_id), pr_title(pr_title), pr_status(pr_status), pr_comment(pr_comment), pr_data(pr_data) {}
friend_online_data(bool online, u64 timestamp)
: online(online), timestamp(timestamp) {}
bool online = false;
u64 timestamp = 0;
SceNpCommunicationId pr_com_id{};
std::string pr_title;
std::string pr_status;
std::string pr_comment;
std::vector<u8> pr_data;
};
struct friend_data
{
std::map<std::string, std::pair<bool, u64>> friends;
std::map<std::string, friend_online_data> friends;
std::set<std::string> requests_sent;
std::set<std::string> requests_received;
std::set<std::string> blocked;
@ -375,9 +417,13 @@ namespace rpcn
u32 get_num_friends();
u32 get_num_blocks();
std::optional<std::string> get_friend_by_index(u32 index);
std::optional<std::pair<std::string, friend_online_data>> get_friend_presence_by_index(u32 index);
std::optional<std::pair<std::string, friend_online_data>> get_friend_presence_by_npid(const std::string& npid);
std::vector<std::pair<u16, std::vector<u8>>> get_notifications();
std::unordered_map<u32, std::pair<u16, std::vector<u8>>> get_replies();
std::unordered_map<std::string, friend_online_data> get_presence_updates();
std::map<std::string, friend_online_data> get_presence_states();
std::vector<u64> get_new_messages();
std::optional<std::shared_ptr<std::pair<std::string, message_data>>> get_message(u64 id);
@ -439,6 +485,7 @@ namespace rpcn
bool tus_get_multiuser_data_status(u32 req_id, SceNpCommunicationId& communication_id, const std::vector<SceNpOnlineId>& targetNpIdArray, SceNpTusSlotId slotId, s32 arrayNum, bool vuser);
bool tus_get_friends_data_status(u32 req_id, SceNpCommunicationId& communication_id, SceNpTusSlotId slotId, bool includeSelf, s32 sortType, s32 arrayNum);
bool tus_delete_multislot_data(u32 req_id, SceNpCommunicationId& communication_id, const SceNpOnlineId& targetNpId, vm::cptr<SceNpTusSlotId> slotIdArray, s32 arrayNum, bool vuser);
bool send_presence(const SceNpCommunicationId& pr_com_id, const std::string& pr_title, const std::string& pr_status, const std::string& pr_comment, const std::vector<u8>& pr_data);
const std::string& get_online_name() const
{
@ -451,12 +498,24 @@ namespace rpcn
u32 get_addr_sig() const
{
if (!addr_sig)
{
addr_sig.wait(0, static_cast<atomic_wait_timeout>(10'000'000'000));
}
return addr_sig.load();
}
u16 get_port_sig() const
{
if (!port_sig)
{
port_sig.wait(0, static_cast<atomic_wait_timeout>(10'000'000'000));
}
return port_sig.load();
}
u32 get_addr_local() const
{
return local_addr_sig.load();
@ -472,9 +531,11 @@ namespace rpcn
std::vector<u8> forge_request(u16 command, u64 packet_id, const std::vector<u8>& data) const;
bool forge_send(u16 command, u64 packet_id, const std::vector<u8>& data);
bool forge_request_with_com_id(const flatbuffers::FlatBufferBuilder& builder, const SceNpCommunicationId& com_id, CommandType command, u64 packet_id);
bool forge_send_reply(u16 command, u64 packet_id, const std::vector<u8>& data, std::vector<u8>& reply_data);
bool error_and_disconnect(const std::string& error_mgs);
bool error_and_disconnect_notice(const std::string& error_msg);
std::string get_wolfssl_error(WOLFSSL* wssl, int error) const;
@ -499,10 +560,11 @@ namespace rpcn
atomic_t<u64> rpcn_request_counter = 0x100000001; // Counter used for commands whose result is not forwarded to NP handler(login, create, sendmessage, etc)
shared_mutex mutex_notifs, mutex_replies, mutex_replies_sync;
shared_mutex mutex_notifs, mutex_replies, mutex_replies_sync, mutex_presence_updates;
std::vector<std::pair<u16, std::vector<u8>>> notifications; // notif type / data
std::unordered_map<u32, std::pair<u16, std::vector<u8>>> replies; // req id / (command / data)
std::unordered_map<u64, std::pair<u16, std::vector<u8>>> replies_sync; // same but for sync replies(see handle_input())
std::unordered_map<std::string, friend_online_data> presence_updates; // npid / presence data
// Messages
struct message_cb_t
@ -531,9 +593,9 @@ namespace rpcn
s64 user_id = 0;
atomic_t<u32> addr_sig{};
atomic_t<u16> port_sig{};
atomic_t<u32> local_addr_sig{};
atomic_t<u32> addr_sig = 0;
atomic_t<u32> port_sig = 0; // Stores an u16, u32 is used for atomic_t::wait convenience
atomic_t<u32> local_addr_sig = 0;
static constexpr int RPCN_TIMEOUT_INTERVAL = 50; // 50ms
static constexpr int RPCN_TIMEOUT = 10'000; // 10s

View File

@ -925,7 +925,7 @@ rpcn_friends_dialog::rpcn_friends_dialog(QWidget* parent)
for (const auto& fr : data.friends)
{
add_update_list(m_lst_friends, QString::fromStdString(fr.first), fr.second.first ? m_green_icon : m_red_icon, fr.second.first);
add_update_list(m_lst_friends, QString::fromStdString(fr.first), fr.second.online ? m_green_icon : m_red_icon, fr.second.online);
}
for (const auto& fr_req : data.requests_sent)

View File

@ -82,7 +82,7 @@ bool sendmessage_dialog_frame::Exec(message_data& msg_data, std::set<std::string
for (const auto& fr : data.friends)
{
// Only add online friends to the list
if (fr.second.first)
if (fr.second.online)
{
add_friend(m_lst_friends, QString::fromStdString(fr.first));
}