Added support for the [9.0.0+] friendsLa functionality. Added AccountNetworkServiceAccountId (and updated friendsLa for this). Added FriendsFriendInvitationGameModeDescription, FriendsFriendInvitationId, and FriendsFriendInvitationGroupId.

This commit is contained in:
yellows8 2019-11-12 10:24:27 -05:00
parent 9ca626fd82
commit 67eacc8034
No known key found for this signature in database
GPG Key ID: 0AF90DA3F1E60E43
4 changed files with 202 additions and 31 deletions

View File

@ -11,25 +11,71 @@
/// Arg type values used with \ref FriendsLaArg. /// Arg type values used with \ref FriendsLaArg.
typedef enum { typedef enum {
FriendsLaArgType_ShowFriendList = 0, ///< ShowFriendList. Launches the applet with the "Friend List" menu initially selected. FriendsLaArgType_ShowFriendList = 0, ///< ShowFriendList. Launches the applet with the "Friend List" menu initially selected.
FriendsLaArgType_ShowUserDetailInfo = 1, ///< ShowUserDetailInfo FriendsLaArgType_ShowUserDetailInfo = 1, ///< ShowUserDetailInfo
FriendsLaArgType_StartSendingFriendRequest = 2, ///< StartSendingFriendRequest FriendsLaArgType_StartSendingFriendRequest = 2, ///< StartSendingFriendRequest
FriendsLaArgType_ShowMethodsOfSendingFriendRequest = 3, ///< ShowMethodsOfSendingFriendRequest. Launches the applet with the "Add Friend" menu initially selected. FriendsLaArgType_ShowMethodsOfSendingFriendRequest = 3, ///< ShowMethodsOfSendingFriendRequest. Launches the applet with the "Add Friend" menu initially selected.
FriendsLaArgType_StartFacedFriendRequest = 4, ///< StartFacedFriendRequest. Launches the applet where the "Search for Local Users" menu is initially shown. Returning from this menu will exit the applet. FriendsLaArgType_StartFacedFriendRequest = 4, ///< StartFacedFriendRequest. Launches the applet where the "Search for Local Users" menu is initially shown. Returning from this menu will exit the applet.
FriendsLaArgType_ShowReceivedFriendRequestList = 5, ///< ShowReceivedFriendRequestList. Launches the applet where the "Received Friend Requests" menu is initially shown. Returning from this menu will exit the applet. FriendsLaArgType_ShowReceivedFriendRequestList = 5, ///< ShowReceivedFriendRequestList. Launches the applet where the "Received Friend Requests" menu is initially shown. Returning from this menu will exit the applet.
FriendsLaArgType_ShowBlockedUserList = 6, ///< ShowBlockedUserList. Launches the applet where the "Blocked-User List" menu is initially shown. Returning from this menu will exit the applet. FriendsLaArgType_ShowBlockedUserList = 6, ///< ShowBlockedUserList. Launches the applet where the "Blocked-User List" menu is initially shown. Returning from this menu will exit the applet.
FriendsLaArgType_ShowMyProfile = 7, ///< ShowMyProfile. Launches the applet with the "Profile" menu initially selected. ShowMyProfileForHomeMenu is identical to this except for playStartupSound=true. FriendsLaArgType_ShowMyProfile = 7, ///< ShowMyProfile. Launches the applet with the "Profile" menu initially selected. ShowMyProfileForHomeMenu is identical to this except for playStartupSound=true.
FriendsLaArgType_StartFriendInvitation = 8, ///< [9.0.0+] StartFriendInvitation. Launches the applet for sending online-play invites to friends, where the friends are selected via the UI.
FriendsLaArgType_StartSendingFriendInvitation = 9, ///< [9.0.0+] StartSendingFriendInvitation.
FriendsLaArgType_ShowReceivedInvitationDetail = 10, ///< [9.0.0+] ShowReceivedInvitationDetail.
} FriendsLaArgType; } FriendsLaArgType;
/// Arg struct pushed for the applet input storage. /// Header for the arg struct.
/// The fields following the uid are only set for ::FriendsLaArgType_ShowUserDetailInfo/::FriendsLaArgType_StartSendingFriendRequest, for everything else these are cleared.
typedef struct { typedef struct {
u32 type; ///< \ref FriendsLaArgType u32 type; ///< \ref FriendsLaArgType
u32 pad; ///< Padding. u32 pad; ///< Padding.
AccountUid uid; ///< \ref AccountUid AccountUid uid; ///< \ref AccountUid
u64 networkServiceAccountId; ///< NetworkServiceAccountId for the other account. } FriendsLaArgHeader;
FriendsInAppScreenName first_inAppScreenName; ///< First InAppScreenName.
FriendsInAppScreenName second_inAppScreenName; ///< Second InAppScreenName. /// Common data for the arg struct, for the pre-9.0.0 types.
/// This is only set for ::FriendsLaArgType_ShowUserDetailInfo/::FriendsLaArgType_StartSendingFriendRequest, for everything else this is cleared.
typedef struct {
AccountNetworkServiceAccountId id; ///< \ref AccountNetworkServiceAccountId for the other account.
FriendsInAppScreenName first_inAppScreenName; ///< First InAppScreenName.
FriendsInAppScreenName second_inAppScreenName; ///< Second InAppScreenName.
} FriendsLaArgCommonData;
/// Arg struct pushed for the applet input storage, for pre-9.0.0.
typedef struct {
FriendsLaArgHeader hdr; ///< \ref FriendsLaArgHeader
FriendsLaArgCommonData data; ///< \ref FriendsLaArgCommonData
} FriendsLaArgV1;
/// Arg struct pushed for the applet input storage, for [9.0.0+].
typedef struct {
FriendsLaArgHeader hdr; ///< \ref FriendsLaArgHeader
union {
u8 raw[0x1090]; ///< Raw data.
FriendsLaArgCommonData common; ///< \ref FriendsLaArgCommonData
struct {
s32 id_count; ///< \ref AccountNetworkServiceAccountId count, must be 1-15.
u32 pad; ///< Padding.
u64 userdata_size; ///< User-data size, must be <=0x400.
u8 userdata[0x400]; ///< Arbitrary user-data, see above size.
FriendsFriendInvitationGameModeDescription desc; ///< \ref FriendsFriendInvitationGameModeDescription
} start_friend_invitation; ///< Data for ::FriendsLaArgType_StartFriendInvitation.
struct {
s32 id_count; ///< \ref AccountNetworkServiceAccountId count, must be 1-15.
u32 pad; ///< Padding.
AccountNetworkServiceAccountId id_list[16]; ///< \ref AccountNetworkServiceAccountId list, see above count.
u64 userdata_size; ///< User-data size, must be <=0x400.
u8 userdata[0x400]; ///< Arbitrary user-data, see above size.
FriendsFriendInvitationGameModeDescription desc; ///< \ref FriendsFriendInvitationGameModeDescription
} start_sending_friend_invitation; ///< Data for ::FriendsLaArgType_StartSendingFriendInvitation.
struct {
FriendsFriendInvitationId invitation_id; ///< \ref FriendsFriendInvitationId
FriendsFriendInvitationGroupId invitation_group_id; ///< \ref FriendsFriendInvitationGroupId
} show_received_invitation_detail; ///< Data for ::FriendsLaArgType_ShowReceivedInvitationDetail.
} data; ///< Data for each \ref FriendsLaArgType.
} FriendsLaArg; } FriendsLaArg;
/** /**
@ -41,20 +87,20 @@ Result friendsLaShowFriendList(AccountUid uid);
/** /**
* @brief Launches the applet with ::FriendsLaArgType_ShowUserDetailInfo, the specified input, and playStartupSound=false. * @brief Launches the applet with ::FriendsLaArgType_ShowUserDetailInfo, the specified input, and playStartupSound=false.
* @param[in] uid \ref AccountUid * @param[in] uid \ref AccountUid
* @param[in] networkServiceAccountId NetworkServiceAccountId for the user to show UserDetailInfo for. * @param[in] id \ref AccountNetworkServiceAccountId for the user to show UserDetailInfo for.
* @param[in] first_inAppScreenName First \ref FriendsInAppScreenName. * @param[in] first_inAppScreenName First \ref FriendsInAppScreenName.
* @param[in] second_inAppScreenName Second \ref FriendsInAppScreenName. * @param[in] second_inAppScreenName Second \ref FriendsInAppScreenName.
*/ */
Result friendsLaShowUserDetailInfo(AccountUid uid, u64 networkServiceAccountId, const FriendsInAppScreenName *first_inAppScreenName, const FriendsInAppScreenName *second_inAppScreenName); Result friendsLaShowUserDetailInfo(AccountUid uid, AccountNetworkServiceAccountId id, const FriendsInAppScreenName *first_inAppScreenName, const FriendsInAppScreenName *second_inAppScreenName);
/** /**
* @brief Launches the applet with ::FriendsLaArgType_StartSendingFriendRequest, the specified input, and playStartupSound=false. On success, this will load the output Result from the output storage. * @brief Launches the applet with ::FriendsLaArgType_StartSendingFriendRequest, the specified input, and playStartupSound=false. On success, this will load the output Result from the output storage.
* @param[in] uid \ref AccountUid * @param[in] uid \ref AccountUid
* @param[in] networkServiceAccountId NetworkServiceAccountId to send the friend request to. * @param[in] id \ref AccountNetworkServiceAccountId to send the friend request to.
* @param[in] first_inAppScreenName First \ref FriendsInAppScreenName. * @param[in] first_inAppScreenName First \ref FriendsInAppScreenName.
* @param[in] second_inAppScreenName Second \ref FriendsInAppScreenName. * @param[in] second_inAppScreenName Second \ref FriendsInAppScreenName.
*/ */
Result friendsLaStartSendingFriendRequest(AccountUid uid, u64 networkServiceAccountId, const FriendsInAppScreenName *first_inAppScreenName, const FriendsInAppScreenName *second_inAppScreenName); Result friendsLaStartSendingFriendRequest(AccountUid uid, AccountNetworkServiceAccountId id, const FriendsInAppScreenName *first_inAppScreenName, const FriendsInAppScreenName *second_inAppScreenName);
/** /**
* @brief Launches the applet with ::FriendsLaArgType_ShowMethodsOfSendingFriendRequest, the specified input, and playStartupSound=false. * @brief Launches the applet with ::FriendsLaArgType_ShowMethodsOfSendingFriendRequest, the specified input, and playStartupSound=false.
@ -92,3 +138,35 @@ Result friendsLaShowMyProfile(AccountUid uid);
*/ */
Result friendsLaShowMyProfileForHomeMenu(AccountUid uid); Result friendsLaShowMyProfileForHomeMenu(AccountUid uid);
/**
* @brief Launches the applet with ::FriendsLaArgType_StartFriendInvitation, the specified input, and playStartupSound=false. On success, this will load the output Result from the output storage.
* @note Only available on [9.0.0+].
* @param[in] uid \ref AccountUid
* @param[in] id_count \ref AccountNetworkServiceAccountId count, must be 1-15. Number of friends to invite.
* @param[in] desc \ref FriendsFriendInvitationGameModeDescription
* @param[in] userdata Arbitrary user-data. Can be NULL.
* @param[in] userdata_size User-data size, must be <=0x400. Can be 0 if userdata is NULL.
*/
Result friendsLaStartFriendInvitation(AccountUid uid, s32 id_count, const FriendsFriendInvitationGameModeDescription *desc, const void* userdata, u64 userdata_size);
/**
* @brief Launches the applet with ::FriendsLaArgType_StartSendingFriendInvitation, the specified input, and playStartupSound=false. On success, this will load the output Result from the output storage.
* @note Only available on [9.0.0+].
* @param[in] uid \ref AccountUid
* @param[in] id_list \ref AccountNetworkServiceAccountId list.
* @param[in] id_count Size of the id_list array in entries, must be 1-15. Number of friends to invite.
* @param[in] desc \ref FriendsFriendInvitationGameModeDescription
* @param[in] userdata Arbitrary user-data. Can be NULL.
* @param[in] userdata_size User-data size, must be <=0x400. Can be 0 if userdata is NULL.
*/
Result friendsLaStartSendingFriendInvitation(AccountUid uid, const AccountNetworkServiceAccountId *id_list, s32 id_count, const FriendsFriendInvitationGameModeDescription *desc, const void* userdata, u64 userdata_size);
/**
* @brief Launches the applet with ::FriendsLaArgType_ShowReceivedInvitationDetail, the specified input, and playStartupSound=false.
* @note Only available on [9.0.0+].
* @param[in] uid \ref AccountUid
* @param[in] invitation_id \ref FriendsFriendInvitationId
* @param[in] invitation_group_id \ref FriendsFriendInvitationGroupId
*/
Result friendsLaShowReceivedInvitationDetail(AccountUid uid, FriendsFriendInvitationId invitation_id, FriendsFriendInvitationGroupId invitation_group_id);

View File

@ -44,6 +44,11 @@ typedef struct {
char nickname[0x20]; ///< UTF-8 Nickname. char nickname[0x20]; ///< UTF-8 Nickname.
} AccountProfileBase; } AccountProfileBase;
/// NetworkServiceAccountId
typedef struct {
u64 id; ///< Id.
} AccountNetworkServiceAccountId;
/** /**
* @brief Sets the \ref AccountServiceType for initialization. Call this function before \ref accountInitialize, if needed. * @brief Sets the \ref AccountServiceType for initialization. Call this function before \ref accountInitialize, if needed.
* @note By default ::AccountServiceType_NotInitialized will be used. * @note By default ::AccountServiceType_NotInitialized will be used.

View File

@ -14,3 +14,18 @@ typedef struct {
u64 languageCode; ///< LanguageCode, see set.h. u64 languageCode; ///< LanguageCode, see set.h.
} FriendsInAppScreenName; } FriendsInAppScreenName;
/// FriendInvitationGameModeDescription
typedef struct {
u8 unk_x0[0xc00]; ///< Unknown.
} FriendsFriendInvitationGameModeDescription;
/// FriendInvitationId
typedef struct {
u64 id; ///< Id.
} FriendsFriendInvitationId;
/// FriendInvitationGroupId
typedef struct {
u64 id; ///< Id.
} FriendsFriendInvitationGroupId;

View File

@ -5,20 +5,36 @@
#include "services/applet.h" #include "services/applet.h"
#include "applets/libapplet.h" #include "applets/libapplet.h"
#include "applets/friends_la.h" #include "applets/friends_la.h"
#include "runtime/hosversion.h"
static Result _friendsLaShow(const FriendsLaArg *arg, bool playStartupSound) { static Result _friendsLaShow(const FriendsLaArg *arg, bool playStartupSound) {
Result rc=0; Result rc=0;
Result rc2=0; Result rc2=0;
size_t readsize=0; size_t readsize=0;
u32 version=0x1;
const void* arg_ptr = arg;
size_t arg_size = sizeof(*arg);
LibAppletArgs commonargs; LibAppletArgs commonargs;
FriendsLaArgV1 argv1;
libappletArgsCreate(&commonargs, 0x1); if (hosversionAtLeast(9,0,0))
version = 0x10000;
else {
memset(&argv1, 0, sizeof(argv1));
arg_ptr = &argv1;
arg_size = sizeof(argv1);
memcpy(&argv1.hdr, &arg->hdr, sizeof(FriendsLaArgHeader));
memcpy(&argv1.data, &arg->data.common, sizeof(FriendsLaArgCommonData));
}
libappletArgsCreate(&commonargs, version);
libappletArgsSetPlayStartupSound(&commonargs, playStartupSound); libappletArgsSetPlayStartupSound(&commonargs, playStartupSound);
if (arg->type != FriendsLaArgType_StartSendingFriendRequest) if (arg->hdr.type != FriendsLaArgType_StartSendingFriendRequest && arg->hdr.type != FriendsLaArgType_StartFriendInvitation && arg->hdr.type != FriendsLaArgType_StartSendingFriendInvitation)
rc = libappletLaunch(AppletId_myPage, &commonargs, arg, sizeof(*arg), NULL, 0, NULL); rc = libappletLaunch(AppletId_myPage, &commonargs, arg_ptr, arg_size, NULL, 0, NULL);
else { else {
rc = libappletLaunch(AppletId_myPage, &commonargs, arg, sizeof(*arg), &rc2, sizeof(rc2), &readsize); rc = libappletLaunch(AppletId_myPage, &commonargs, arg_ptr, arg_size, &rc2, sizeof(rc2), &readsize);
if (R_SUCCEEDED(rc) && readsize!=sizeof(rc2)) rc = MAKERESULT(Module_Libnx, LibnxError_BadInput); if (R_SUCCEEDED(rc) && readsize!=sizeof(rc2)) rc = MAKERESULT(Module_Libnx, LibnxError_BadInput);
if (R_SUCCEEDED(rc)) rc = rc2; if (R_SUCCEEDED(rc)) rc = rc2;
} }
@ -27,13 +43,13 @@ static Result _friendsLaShow(const FriendsLaArg *arg, bool playStartupSound) {
} }
static Result _friendsLaShowSimple(FriendsLaArgType type, AccountUid uid, bool playStartupSound) { static Result _friendsLaShowSimple(FriendsLaArgType type, AccountUid uid, bool playStartupSound) {
FriendsLaArg arg = {.type = type, .uid = uid}; FriendsLaArg arg = {.hdr.type = type, .hdr.uid = uid};
return _friendsLaShow(&arg, playStartupSound); return _friendsLaShow(&arg, playStartupSound);
} }
static Result _friendsLaShowAll(FriendsLaArgType type, AccountUid uid, u64 networkServiceAccountId, const FriendsInAppScreenName *first_inAppScreenName, const FriendsInAppScreenName *second_inAppScreenName, bool playStartupSound) { static Result _friendsLaShowAll(FriendsLaArgType type, AccountUid uid, AccountNetworkServiceAccountId id, const FriendsInAppScreenName *first_inAppScreenName, const FriendsInAppScreenName *second_inAppScreenName, bool playStartupSound) {
FriendsLaArg arg = {.type = type, .uid = uid, .networkServiceAccountId = networkServiceAccountId, .first_inAppScreenName = *first_inAppScreenName, .second_inAppScreenName = *second_inAppScreenName}; FriendsLaArg arg = {.hdr.type = type, .hdr.uid = uid, .data.common.id = id, .data.common.first_inAppScreenName = *first_inAppScreenName, .data.common.second_inAppScreenName = *second_inAppScreenName};
return _friendsLaShow(&arg, playStartupSound); return _friendsLaShow(&arg, playStartupSound);
} }
@ -42,12 +58,12 @@ Result friendsLaShowFriendList(AccountUid uid) {
return _friendsLaShowSimple(FriendsLaArgType_ShowFriendList, uid, false); return _friendsLaShowSimple(FriendsLaArgType_ShowFriendList, uid, false);
} }
Result friendsLaShowUserDetailInfo(AccountUid uid, u64 networkServiceAccountId, const FriendsInAppScreenName *first_inAppScreenName, const FriendsInAppScreenName *second_inAppScreenName) { Result friendsLaShowUserDetailInfo(AccountUid uid, AccountNetworkServiceAccountId id, const FriendsInAppScreenName *first_inAppScreenName, const FriendsInAppScreenName *second_inAppScreenName) {
return _friendsLaShowAll(FriendsLaArgType_ShowUserDetailInfo, uid, networkServiceAccountId, first_inAppScreenName, second_inAppScreenName, false); return _friendsLaShowAll(FriendsLaArgType_ShowUserDetailInfo, uid, id, first_inAppScreenName, second_inAppScreenName, false);
} }
Result friendsLaStartSendingFriendRequest(AccountUid uid, u64 networkServiceAccountId, const FriendsInAppScreenName *first_inAppScreenName, const FriendsInAppScreenName *second_inAppScreenName) { Result friendsLaStartSendingFriendRequest(AccountUid uid, AccountNetworkServiceAccountId id, const FriendsInAppScreenName *first_inAppScreenName, const FriendsInAppScreenName *second_inAppScreenName) {
return _friendsLaShowAll(FriendsLaArgType_StartSendingFriendRequest, uid, networkServiceAccountId, first_inAppScreenName, second_inAppScreenName, false); return _friendsLaShowAll(FriendsLaArgType_StartSendingFriendRequest, uid, id, first_inAppScreenName, second_inAppScreenName, false);
} }
Result friendsLaShowMethodsOfSendingFriendRequest(AccountUid uid) { Result friendsLaShowMethodsOfSendingFriendRequest(AccountUid uid) {
@ -74,3 +90,60 @@ Result friendsLaShowMyProfileForHomeMenu(AccountUid uid) {
return _friendsLaShowSimple(FriendsLaArgType_ShowMyProfile, uid, true); return _friendsLaShowSimple(FriendsLaArgType_ShowMyProfile, uid, true);
} }
Result friendsLaStartFriendInvitation(AccountUid uid, s32 id_count, const FriendsFriendInvitationGameModeDescription *desc, const void* userdata, u64 userdata_size) {
if (hosversionBefore(9,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
FriendsLaArg arg;
memset(&arg, 0, sizeof(arg));
if (id_count<1 || id_count>15 || userdata_size>=sizeof(arg.data.start_friend_invitation.userdata) || (userdata==NULL && userdata_size!=0))
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
arg.hdr.type = FriendsLaArgType_StartFriendInvitation;
arg.hdr.uid = uid;
arg.data.start_friend_invitation.id_count = id_count;
arg.data.start_friend_invitation.userdata_size = userdata_size;
if (userdata && userdata_size) memcpy(arg.data.start_friend_invitation.userdata, userdata, userdata_size);
memcpy(&arg.data.start_friend_invitation.desc, desc, sizeof(*desc));
return _friendsLaShow(&arg, false);
}
Result friendsLaStartSendingFriendInvitation(AccountUid uid, const AccountNetworkServiceAccountId *id_list, s32 id_count, const FriendsFriendInvitationGameModeDescription *desc, const void* userdata, u64 userdata_size) {
if (hosversionBefore(9,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
FriendsLaArg arg;
memset(&arg, 0, sizeof(arg));
if (id_count<1 || id_count>15 || userdata_size>=sizeof(arg.data.start_sending_friend_invitation.userdata) || (userdata==NULL && userdata_size!=0))
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
arg.hdr.type = FriendsLaArgType_StartSendingFriendInvitation;
arg.hdr.uid = uid;
arg.data.start_sending_friend_invitation.id_count = id_count;
arg.data.start_sending_friend_invitation.userdata_size = userdata_size;
memcpy(arg.data.start_sending_friend_invitation.id_list, id_list, id_count*sizeof(AccountNetworkServiceAccountId));
if (userdata && userdata_size) memcpy(arg.data.start_sending_friend_invitation.userdata, userdata, userdata_size);
memcpy(&arg.data.start_sending_friend_invitation.desc, desc, sizeof(*desc));
return _friendsLaShow(&arg, false);
}
Result friendsLaShowReceivedInvitationDetail(AccountUid uid, FriendsFriendInvitationId invitation_id, FriendsFriendInvitationGroupId invitation_group_id) {
if (hosversionBefore(9,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
FriendsLaArg arg;
memset(&arg, 0, sizeof(arg));
arg.hdr.type = FriendsLaArgType_ShowReceivedInvitationDetail;
arg.hdr.uid = uid;
arg.data.show_received_invitation_detail.invitation_id = invitation_id;
arg.data.show_received_invitation_detail.invitation_group_id = invitation_group_id;
return _friendsLaShow(&arg, false);
}