This commit is contained in:
RipleyTom
2024-01-05 09:43:26 +01:00
committed by GitHub
parent bc141831f7
commit b6e9746198
15 changed files with 2254 additions and 1770 deletions
+5
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;
+2
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
+97 -69
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,10 +1024,10 @@ error_code sceNpBasicSendMessageGui(vm::cptr<SceNpBasicMessageDetails> msg, sys_
// Prepare message data
message_data msg_data = {
.commId = nph.basic_handler.context,
.msgId = msg->msgId,
.mainType = msg->mainType,
.subType = msg->subType,
.commId = nph.get_basic_handler_context(),
.msgId = msg->msgId,
.mainType = msg->mainType,
.subType = msg->subType,
.msgFeatures = msg->msgFeatures};
std::set<std::string> npids;
@@ -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;
}
File diff suppressed because it is too large Load Diff
+6
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
+200 -13
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);
+30 -9
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
+28
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));
+5
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);
File diff suppressed because it is too large Load Diff
+73 -11
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
+1 -1
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)
+1 -1
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));
}