Skip to content

Instantly share code, notes, and snippets.

@hax0kartik
Last active June 10, 2018 19:42
Show Gist options
  • Save hax0kartik/3a919e4c2b008d3679c9c34c11df3616 to your computer and use it in GitHub Desktop.
Save hax0kartik/3a919e4c2b008d3679c9c34c11df3616 to your computer and use it in GitHub Desktop.
#include <3ds.h>
#include <stdio.h>
#include <string.h>
#include <wchar.h>
static Handle frdHandle;
static int frdRefCount;
static Handle s_terminate;
Result frdInit(void)
{
Result ret = 0;
if (AtomicPostIncrement(&frdRefCount))
return 0;
ret = srvGetServiceHandle(&frdHandle, "frd:a");
if (R_FAILED(ret))
AtomicDecrement(&frdRefCount);
return ret;
}
void frdExit(void)
{
if (AtomicDecrement(&frdRefCount))
return;
svcCloseHandle(frdHandle);
}
Result FRD_FriendCodeToPrincipalId(u64 friendCode, u32 * principalId)
{
Result ret = 0;
u32 * cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x25, 2, 0); // 0x00250080
cmdbuf[1] = (u32)(friendCode & 0xFFFFFFFF);
cmdbuf[2] = (u32)(friendCode >> 32);
if (R_FAILED(ret = svcSendSyncRequest(frdHandle)))
return ret;
*principalId = cmdbuf[2];
return cmdbuf[1];
}
typedef struct
{
u32 principal_id;
u32 padding;
u64 local_friend_code;
}frd_key;
Result FRD_RemoveFriend(u32 principal_id, u64 local_friend_code)
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x4090100;
cmdbuf[1] = principal_id;
cmdbuf[2] = local_friend_code & 0xffffffff;
cmdbuf[3] = (local_friend_code >> 32) & 0xffffffff;
if(R_FAILED(ret = svcSendSyncRequest(frdHandle)))
return ret;
return cmdbuf[1];
}
Result FRD_IsValidFriendCode(u64 friendCode, bool * isValid)
{
Result ret = 0;
u32 * cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x26, 2, 0); // 0x00260080
cmdbuf[1] = (u32)(friendCode & 0xFFFFFFFF);
cmdbuf[2] = (u32)(friendCode >> 32);
if (R_FAILED(ret = svcSendSyncRequest(frdHandle)))
return ret;
*isValid = cmdbuf[2] & 0xFF;
return cmdbuf[1];
}
typedef enum
{
self_online = 1,
self_offline,
friend_online,
friend_presence,
friend_mii,
friend_profile,
friend_offline,
friend_became_friend,
friend_invitaton
}friend_notif_types;
typedef struct
{
u8 type;
u8 padding3[3];
u32 padding;
frd_key key;
}friend_notif_event;
Result FRD_GetEventNotification(friend_notif_event *event, size_t size, u32 *recieved_notif_count)
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x220040;
cmdbuf[1] = (u32)size;
u32 *staticbuf = getThreadStaticBuffers();
staticbuf[0] = 0x60000 * size | 2;
staticbuf[1] = (u32)event;
if(R_FAILED(ret = svcSendSyncRequest(frdHandle)))
return ret;
*recieved_notif_count = cmdbuf[3];
return (Result)cmdbuf[1];
}
Result FRD_addFriendOnline(Handle event,u32 principal_id)
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x4060042;
cmdbuf[1] = principal_id;
cmdbuf[2] = 0;
cmdbuf[3] = (u32)event;
if(R_FAILED(ret = svcSendSyncRequest(frdHandle))) return ret;
return (Result)cmdbuf[1];
}
Result FRD_AttachToEventNotification(Handle event)
{
Result ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x200002;
cmdbuf[1] = 0;
cmdbuf[2] = (u32)event;
if(R_FAILED(ret = svcSendSyncRequest(frdHandle))) return ret;
return (Result)cmdbuf[1];
}
void HandleFriendNotification(friend_notif_event *event)
{
switch(event->type)
{
case friend_became_friend:
printf("registered %lx as a friend", event->key.principal_id);
break;
case friend_online:
printf("%lx is online", event->key.principal_id);
break;
case friend_offline:
printf("%lx is offline", event->key.principal_id);
break;
default:
printf("notification %d recieved for %lx", event->type, event->key.principal_id);
break;
}
}
void FriendNotificationHandlerThread(void *n)
{
printf("HandlerThreadCreated()\n");
Handle friendsEvent;
svcCreateEvent(&friendsEvent, RESET_ONESHOT);
Result res = FRD_AttachToEventNotification(friendsEvent);
if(res != 0) printf("Error in AttachingEventHandle %08lX", res);
s32 out;
Handle frd_handles[] = {friendsEvent, s_terminate};
bool run = true;
friend_notif_event events[10];
size_t event_list_size = 10;
while(run)
{
svcWaitSynchronizationN(&out, frd_handles, 2, false, U64_MAX);
printf("out %d\n", out);
switch(out)
{
case 0:
{
size_t size = 0;
do
{
res = FRD_GetEventNotification(events, 10, (u32 *)&size);
printf("GetEventNotification %08lX\n", res);
for(int i = 0; i < size; ++i)
{
HandleFriendNotification(events + i);
}
}while(size!=0);
break;
}
case 1:
run = false;
break;
}
}
svcClearEvent(s_terminate);
printf("Deinitialization finished\n");
}
int main(void)
{
gfxInitDefault();
consoleInit(GFX_TOP, NULL);
Result res = frdInit();
printf("frdinit: %08lX\n", res);
SwkbdState swkbd;
char mybuf[60];
u64 frd_code;
bool pid;
u32 pid_2;
Handle event;
svcCreateEvent(&event, RESET_ONESHOT);
svcCreateEvent(&s_terminate, RESET_ONESHOT);
printf("Going To init thread\n");
Thread thread = threadCreate(FriendNotificationHandlerThread, NULL, 4096 * 2, 0x24, 0, true);
printf("Press A to continue\n");
while(aptMainLoop())
{
hidScanInput();
if(keysDown() & KEY_A)
{
swkbdInit(&swkbd, SWKBD_TYPE_NORMAL, 3, -1);
swkbdSetHintText(&swkbd, "Please enter a friend-code without \"-\" ");
swkbdInputText(&swkbd, mybuf, sizeof(mybuf));
sscanf(mybuf,"%lld", &frd_code);
printf("frd_code %lld\n", frd_code);
//frd_key a;
//a.local_friend_code = frd_code;
printf("FRD_FriendCodeIsValid() %08lX \n", FRD_IsValidFriendCode(frd_code,&pid));
printf("fc is valid: %s\n", (pid == 1) ? "True": "False");
printf("FRD_FriendCodeToPrincipalId() %08lx\n", FRD_FriendCodeToPrincipalId(frd_code,&pid_2));
printf("Principal_id %lx\n", pid_2);
printf("FRD_addFriend() %08lx\n", FRD_addFriendOnline(event, pid_2));
//printf("Reboot tiltle set.");
}
if(keysDown() & KEY_START)
{
break;
}
gfxFlushBuffers();
gfxSwapBuffers();
}
printf("Going to signal Thread");
svcSignalEvent(s_terminate);
threadJoin(thread, U64_MAX);
svcCloseHandle(s_terminate);
frdExit();
gfxExit();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment