Initial bring up of the Friend Service
This commit is contained in:
parent
d1ca5c4ea6
commit
18267ef6fb
@ -40,6 +40,7 @@ extern "C" {
|
||||
#include <3ds/services/csnd.h>
|
||||
#include <3ds/services/dsp.h>
|
||||
#include <3ds/services/fs.h>
|
||||
#include <3ds/services/frd.h>
|
||||
#include <3ds/services/gspgpu.h>
|
||||
#include <3ds/services/gsplcd.h>
|
||||
#include <3ds/services/hid.h>
|
||||
|
171
libctru/include/3ds/services/frd.h
Normal file
171
libctru/include/3ds/services/frd.h
Normal file
@ -0,0 +1,171 @@
|
||||
/**
|
||||
* @file frd.h
|
||||
* @brief Friend Services
|
||||
*/
|
||||
#pragma once
|
||||
#include <3ds.h>
|
||||
|
||||
#define FRIENDS_SCREEN_NAME_SIZE 0x16 // 11 (0x16 because UTF-16)
|
||||
#define FRIENDS_COMMENT_SIZE 0x22 // 16 (0x21 because UTF-16 + null character)
|
||||
#define FRIEND_LIST_SIZE 0x64 // 100 (Number of Friends)
|
||||
#define FRIEND_MII_STORE_DATA_SIZE 0x60 // 96 (Mii data)
|
||||
|
||||
/// Friend key data
|
||||
typedef struct
|
||||
{
|
||||
u32 principalId;
|
||||
u32 padding;
|
||||
u64 localFriendCode;
|
||||
} FriendKey;
|
||||
|
||||
/// Structure containing basic Mii information.
|
||||
typedef struct
|
||||
{
|
||||
u32 mii_id;
|
||||
u64 system_id;
|
||||
u32 cdate;
|
||||
u8 mac[0x6];
|
||||
u16 padding;
|
||||
u16 misc1;
|
||||
u16 mii_name[0xB];
|
||||
u8 width;
|
||||
u8 height;
|
||||
u32 misc2;
|
||||
u32 unknown1;
|
||||
u32 misc3;
|
||||
u32 unknown2;
|
||||
u8 allow_copy;
|
||||
u8 unknown3[0x7];
|
||||
u16 author[0xB];
|
||||
} MiiData;
|
||||
|
||||
/// Friend profile data
|
||||
typedef struct
|
||||
{
|
||||
u8 region; // The region code for the hardware.
|
||||
u8 country; // Country code.
|
||||
u8 area; // Area code.
|
||||
u8 language; // Language code.
|
||||
u8 platform; // Platform code.
|
||||
u32 padding;
|
||||
} Profile;
|
||||
|
||||
/// Initializes FRD service.
|
||||
Result frdInit(void);
|
||||
|
||||
/// Exists FRD.
|
||||
void frdExit(void);
|
||||
|
||||
/**
|
||||
* @brief Gets the login status of the current user.
|
||||
* @param state Pointer to write the current user's login status to.
|
||||
*/
|
||||
Result FRDU_HasLoggedIn(bool *state);
|
||||
|
||||
/**
|
||||
* @brief Gets the online status of the current user.
|
||||
* @param state Pointer to write the current user's online status to.
|
||||
*/
|
||||
Result FRDU_IsOnline(bool *state);
|
||||
|
||||
/// Logs out of Nintendo's friend server.
|
||||
Result FRD_Logout(void);
|
||||
|
||||
/**
|
||||
* @brief Gets the current user's friend key.
|
||||
* @param key Pointer to write the current user's friend key to.
|
||||
*/
|
||||
Result FRD_GetMyFriendKey(FriendKey *key);
|
||||
|
||||
/**
|
||||
* @brief Gets the current user's privacy information.
|
||||
* @param isPublicMode Determines whether friends are notified of the current user's online status.
|
||||
* @param isShowGameName Determines whether friends are notified of the application that the current user is running.
|
||||
* @param isShowPlayedGame Determiens whether to display the current user's game history.
|
||||
*/
|
||||
Result FRD_GetMyPreference(bool *isPublicMode, bool *isShowGameName, bool *isShowPlayedGame);
|
||||
|
||||
/**
|
||||
* @brief Gets the current user's profile information.
|
||||
* @param profile Pointer to write the current user's profile information to.
|
||||
*/
|
||||
Result FRD_GetMyProfile(Profile *profile);
|
||||
|
||||
/**
|
||||
* @brief Gets the current user's screen name.
|
||||
* @param name Pointer to write the current user's screen name to. 11-byte UTF-16 screen name (with null terminator)
|
||||
*/
|
||||
Result FRD_GetMyScreenName(u16 *name);
|
||||
|
||||
/**
|
||||
* @brief Gets the current user's Mii data.
|
||||
* @param mii Pointer to write the current user's mii data to.
|
||||
*/
|
||||
Result FRD_GetMyMii(MiiData *mii);
|
||||
|
||||
/**
|
||||
* @brief Gets the current user's playing game.
|
||||
* @param titleId Pointer to write the current user's playing game to.
|
||||
*/
|
||||
Result FRD_GetMyPlayingGame(u64 *titleId);
|
||||
|
||||
/**
|
||||
* @brief Gets the current user's favourite game.
|
||||
* @param titleId Pointer to write the title ID of current user's favourite game to.
|
||||
*/
|
||||
Result FRD_GetMyFavoriteGame(u64 *titleId);
|
||||
|
||||
/**
|
||||
* @brief Gets the current user's comment on their friend profile.
|
||||
* @param comment Pointer to write the current user's comment to.
|
||||
*/
|
||||
Result FRD_GetMyComment(u16 *comment);
|
||||
|
||||
/**
|
||||
* @brief Gets the current user's firend key list
|
||||
* @param friendKeyList Pointer to write the friend key list to.
|
||||
* @param num Stores the number of friend keys obtained.
|
||||
* @param offset the index of the friend key to start with.
|
||||
* @param size Size of the friend key list. (FRIEND_LIST_SIZE)
|
||||
*/
|
||||
Result FRD_GetFriendKeyList(FriendKey *friendKeyList, size_t *num, size_t offset, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Determines if the application was started using the join game option in the friends applet.
|
||||
* @param friendKeyList Pointer to a list of friend keys.
|
||||
* @param isFromList Pointer to a write the friendship status to.
|
||||
*/
|
||||
Result FRD_IsFromFriendList(FriendKey *friendKeyList, bool *isFromList);
|
||||
|
||||
/**
|
||||
* @brief Updates the game mode description string.
|
||||
* @param desc Pointer to write the game mode description to.
|
||||
*/
|
||||
Result FRD_UpdateGameModeDescription(u16 *desc);
|
||||
|
||||
/**
|
||||
* @brief Returns the friend code using the given principal ID.
|
||||
* @param principalId The principal ID being used.
|
||||
* @param friendCode Pointer to write the friend code to.
|
||||
*/
|
||||
Result FRD_PrincipalIdToFriendCode(u32 principalId, u64 *friendCode);
|
||||
|
||||
/**
|
||||
* @brief Returns the principal ID using the given friend code.
|
||||
* @param friendCode The friend code being used.
|
||||
* @param principalId Pointer to write the principal ID to.
|
||||
*/
|
||||
Result FRD_FriendCodeToPrincipalId(u64 friendCode, u32 *principalId);
|
||||
|
||||
/**
|
||||
* @brief Checks if the friend code is valid.
|
||||
* @param friendCode The friend code being used.
|
||||
* @param isValid Pointer to write the validity of the friend code to.
|
||||
*/
|
||||
Result FRD_IsValidFriendCode(u64 friendCode, bool *isValid);
|
||||
|
||||
/**
|
||||
* @brief Sets the Friend API to use a specific SDK version.
|
||||
* @param sdkVer The SDK version needed to be used.
|
||||
*/
|
||||
Result FRD_SetClientSdkVersion(u32 sdkVer);
|
288
libctru/source/services/frd.c
Normal file
288
libctru/source/services/frd.c
Normal file
@ -0,0 +1,288 @@
|
||||
#include <string.h>
|
||||
#include <3ds/services/frd.h>
|
||||
|
||||
static Handle frdHandle;
|
||||
static int frdRefCount;
|
||||
|
||||
Result frdInit(void)
|
||||
{
|
||||
Result ret = 0;
|
||||
|
||||
if (AtomicPostIncrement(&frdRefCount)) return 0;
|
||||
|
||||
ret = srvGetServiceHandle(&frdHandle, "frd:u");
|
||||
if (R_FAILED(ret)) ret = srvGetServiceHandle(&frdHandle, "frd:n");
|
||||
if (R_FAILED(ret)) ret = srvGetServiceHandle(&frdHandle, "frd:a");
|
||||
if (R_FAILED(ret)) AtomicDecrement(&frdRefCount);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void frdExit(void)
|
||||
{
|
||||
if (AtomicDecrement(&frdRefCount)) return;
|
||||
svcCloseHandle(frdHandle);
|
||||
}
|
||||
|
||||
Result FRDU_HasLoggedIn(bool *state)
|
||||
{
|
||||
Result ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(0x01,0,0); // 0x10000
|
||||
|
||||
if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) return ret;
|
||||
|
||||
*state = cmdbuf[2] & 0xFF;
|
||||
|
||||
return (Result)cmdbuf[1];
|
||||
}
|
||||
|
||||
Result FRDU_IsOnline(bool *state)
|
||||
{
|
||||
Result ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(0x02,0,0); // 0x20000
|
||||
|
||||
if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) return ret;
|
||||
|
||||
*state = cmdbuf[2] & 0xFF;
|
||||
|
||||
return (Result)cmdbuf[1];
|
||||
}
|
||||
|
||||
Result FRD_Logout(void)
|
||||
{
|
||||
Result ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(0x04,0,0); // 0x40000
|
||||
|
||||
if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) return ret;
|
||||
|
||||
return (Result)cmdbuf[1];
|
||||
}
|
||||
|
||||
Result FRD_GetMyFriendKey(FriendKey *key)
|
||||
{
|
||||
Result ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(0x05,0,0); // 0x50000
|
||||
|
||||
if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) return ret;
|
||||
|
||||
memcpy(key, &cmdbuf[2], sizeof(FriendKey));
|
||||
|
||||
return (Result)cmdbuf[1];
|
||||
}
|
||||
|
||||
Result FRD_GetMyPreference(bool *isPublicMode, bool *isShowGameName, bool *isShowPlayedGame)
|
||||
{
|
||||
Result ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(0x06,0,0); // 0x60000
|
||||
|
||||
if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) return ret;
|
||||
|
||||
*isPublicMode = cmdbuf[2] & 0xFF; // Public mode
|
||||
*isShowGameName = cmdbuf[3] & 0xFF; // Show current game
|
||||
*isShowPlayedGame = cmdbuf[4] & 0xFF; // Show game history.
|
||||
|
||||
return (Result)cmdbuf[1];
|
||||
}
|
||||
|
||||
Result FRD_GetMyProfile(Profile *profile)
|
||||
{
|
||||
Result ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(0x07, 0, 0); // 0x70000
|
||||
|
||||
if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) return ret;
|
||||
|
||||
memcpy(profile, &cmdbuf[2], sizeof(Profile));
|
||||
|
||||
return (Result)cmdbuf[1];
|
||||
}
|
||||
|
||||
Result FRD_GetMyScreenName(u16 *name)
|
||||
{
|
||||
Result ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(0x09,0,0); // 0x90000
|
||||
|
||||
if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) return ret;
|
||||
|
||||
memcpy(name, &cmdbuf[2], FRIENDS_SCREEN_NAME_SIZE); // 11-byte UTF-16 screen name (with null terminator)
|
||||
|
||||
return (Result)cmdbuf[1];
|
||||
}
|
||||
|
||||
Result FRD_GetMyMii(MiiData *mii)
|
||||
{
|
||||
Result ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(0x0A,0,0); // 0xA0000
|
||||
|
||||
if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) return ret;
|
||||
|
||||
memcpy(mii, &cmdbuf[2], FRIEND_MII_STORE_DATA_SIZE);
|
||||
|
||||
return (Result)cmdbuf[1];
|
||||
}
|
||||
|
||||
Result FRD_GetMyPlayingGame(u64 *titleId)
|
||||
{
|
||||
Result ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(0x0C,0,0); // 0xC0000
|
||||
|
||||
if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) return ret;
|
||||
|
||||
*titleId = (((u64)cmdbuf[3]) << 32 | (u64)cmdbuf[2]);
|
||||
|
||||
return (Result)cmdbuf[1];
|
||||
}
|
||||
|
||||
Result FRD_GetMyFavoriteGame(u64 *titleId)
|
||||
{
|
||||
Result ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(0x0D,0,0); // 0xD0000
|
||||
|
||||
if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) return ret;
|
||||
|
||||
*titleId = (((u64)cmdbuf[3]) << 32 | (u64)cmdbuf[2]);
|
||||
|
||||
return (Result)cmdbuf[1];
|
||||
}
|
||||
|
||||
Result FRD_GetMyComment(u16 *comment)
|
||||
{
|
||||
Result ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(0x0F,0,0); // 0xF0000
|
||||
|
||||
if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) return ret;
|
||||
|
||||
memcpy(comment, &cmdbuf[2], FRIENDS_COMMENT_SIZE); // 16-byte UTF-16 comment
|
||||
|
||||
return (Result)cmdbuf[1];
|
||||
}
|
||||
|
||||
Result FRD_GetFriendKeyList(FriendKey *friendKeyList, size_t *num, size_t offset, size_t size)
|
||||
{
|
||||
Result ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(0x11,2,0); // 0x110080
|
||||
cmdbuf[1] = 0;
|
||||
cmdbuf[2] = size;
|
||||
cmdbuf[64] = (size << 18) | 2;
|
||||
cmdbuf[65] = (u32)friendKeyList;
|
||||
|
||||
if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) return ret;
|
||||
|
||||
*num = cmdbuf[2];
|
||||
|
||||
return (Result)cmdbuf[1];
|
||||
}
|
||||
|
||||
Result FRD_IsFromFriendList(FriendKey *friendKeyList, bool *isFromList)
|
||||
{
|
||||
Result ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(0x1B,2,0); // 0x1B0080
|
||||
cmdbuf[1] = (u32)(friendKeyList->localFriendCode & 0xFFFFFFFF);
|
||||
cmdbuf[2] = (u32)(friendKeyList->localFriendCode >> 32);
|
||||
|
||||
if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) return ret;
|
||||
|
||||
*isFromList = cmdbuf[2] & 0xFF;
|
||||
|
||||
return (Result)cmdbuf[1];
|
||||
}
|
||||
|
||||
Result FRD_UpdateGameModeDescription(u16 *desc)
|
||||
{
|
||||
Result ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(0x1D,0,2); // 0x1D0002
|
||||
cmdbuf[1] = 0x400802;
|
||||
cmdbuf[2] = (uintptr_t)desc;
|
||||
|
||||
if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) return ret;
|
||||
|
||||
return (Result)cmdbuf[1];
|
||||
}
|
||||
|
||||
Result FRD_PrincipalIdToFriendCode(u32 principalId, u64 *friendCode)
|
||||
{
|
||||
Result ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(0x24,1,0); // 0x240040
|
||||
cmdbuf[1] = principalId;
|
||||
|
||||
if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) return ret;
|
||||
|
||||
*friendCode = (((u64)cmdbuf[3]) << 32 | (u64)cmdbuf[2]);
|
||||
|
||||
return (Result)cmdbuf[1];
|
||||
}
|
||||
|
||||
Result FRD_FriendCodeToPrincipalId(u64 friendCode, u32 *principalId)
|
||||
{
|
||||
Result ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(0x25,2,0); // 0x250080
|
||||
cmdbuf[1] = (u32)(friendCode & 0xFFFFFFFF);
|
||||
cmdbuf[2] = (u32)(friendCode >> 32);
|
||||
|
||||
if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) return ret;
|
||||
|
||||
*principalId = cmdbuf[2];
|
||||
|
||||
return (Result)cmdbuf[1];
|
||||
}
|
||||
|
||||
Result FRD_IsValidFriendCode(u64 friendCode, bool *isValid)
|
||||
{
|
||||
Result ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(0x26,2,0); // 0x260080
|
||||
cmdbuf[1] = (u32)(friendCode & 0xFFFFFFFF);
|
||||
cmdbuf[2] = (u32)(friendCode >> 32);
|
||||
|
||||
if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) return ret;
|
||||
|
||||
*isValid = cmdbuf[2] & 0xFF;
|
||||
|
||||
return (Result)cmdbuf[1];
|
||||
}
|
||||
|
||||
Result FRD_SetClientSdkVersion(u32 sdkVer)
|
||||
{
|
||||
Result ret = 0;
|
||||
u32 *cmdbuf = getThreadCommandBuffer();
|
||||
|
||||
cmdbuf[0] = IPC_MakeHeader(0x32,1,2); // 0x320042
|
||||
cmdbuf[1] = sdkVer;
|
||||
cmdbuf[2] = IPC_Desc_CurProcessHandle();
|
||||
|
||||
if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) return ret;
|
||||
|
||||
return (Result)cmdbuf[1];
|
||||
}
|
Loading…
Reference in New Issue
Block a user