typedef enum
{
- KEY_A = BIT(0),
- KEY_B = BIT(1),
- KEY_SELECT = BIT(2),
- KEY_START = BIT(3),
- KEY_DRIGHT = BIT(4),
- KEY_DLEFT = BIT(5),
- KEY_DUP = BIT(6),
- KEY_DDOWN = BIT(7),
- KEY_R = BIT(8),
- KEY_L = BIT(9),
- KEY_X = BIT(10),
- KEY_Y = BIT(11),
- KEY_TOUCH = BIT(20), // Not actually provided by HID
- KEY_CRIGHT = BIT(28),
- KEY_CLEFT = BIT(29),
- KEY_CUP = BIT(30),
- KEY_CDOWN = BIT(31),
+ KEY_A = BIT(0),
+ KEY_B = BIT(1),
+ KEY_SELECT = BIT(2),
+ KEY_START = BIT(3),
+ KEY_DRIGHT = BIT(4),
+ KEY_DLEFT = BIT(5),
+ KEY_DUP = BIT(6),
+ KEY_DDOWN = BIT(7),
+ KEY_R = BIT(8),
+ KEY_L = BIT(9),
+ KEY_X = BIT(10),
+ KEY_Y = BIT(11),
+ KEY_ZL = BIT(14), // (new 3DS only)
+ KEY_ZR = BIT(15), // (new 3DS only)
+ KEY_TOUCH = BIT(20), // Not actually provided by HID
+ KEY_CSTICK_RIGHT = BIT(24), // c-stick (new 3DS only)
+ KEY_CSTICK_LEFT = BIT(25), // c-stick (new 3DS only)
+ KEY_CSTICK_UP = BIT(26), // c-stick (new 3DS only)
+ KEY_CSTICK_DOWN = BIT(27), // c-stick (new 3DS only)
+ KEY_CPAD_RIGHT = BIT(28), // circle pad
+ KEY_CPAD_LEFT = BIT(29), // circle pad
+ KEY_CPAD_UP = BIT(30), // circle pad
+ KEY_CPAD_DOWN = BIT(31), // circle pad
// Generic catch-all directions
- KEY_UP = KEY_DUP | KEY_CUP,
- KEY_DOWN = KEY_DDOWN | KEY_CDOWN,
- KEY_LEFT = KEY_DLEFT | KEY_CLEFT,
- KEY_RIGHT = KEY_DRIGHT | KEY_CRIGHT,
+ KEY_UP = KEY_DUP | KEY_CPAD_UP,
+ KEY_DOWN = KEY_DDOWN | KEY_CPAD_DOWN,
+ KEY_LEFT = KEY_DLEFT | KEY_CPAD_LEFT,
+ KEY_RIGHT = KEY_DRIGHT | KEY_CPAD_RIGHT,
} PAD_KEY;
typedef struct
--- /dev/null
+#pragma once
+
+//See also: http://3dbrew.org/wiki/IR_Services http://3dbrew.org/wiki/IRRST_Shared_Memory
+
+#include "3ds/services/hid.h" // for circlePosition definition
+
+#define IRRST_SHAREDMEM_DEFAULT (0x1000A000)
+
+extern Handle irrstMemHandle;
+extern vu32* irrstSharedMem;
+
+Result irrstInit(u32* sharedMem);
+void irrstExit();
+
+void irrstScanInput();
+u32 irrstKeysHeld();
+void irrstCstickRead(circlePosition* pos);
+
+void irrstWaitForEvent(bool nextEvent);
+
+#define hidCstickRead irrstCstickRead // because why not
+
+Result IRRST_GetHandles(Handle* outMemHandle, Handle* outEventHandle);
+Result IRRST_Initialize(u32 unk1, u8 unk2);
+Result IRRST_Shutdown(void);
--- /dev/null
+/*
+ _irrst.c - C-stick, ZL/ZR
+*/
+#include <stdlib.h>
+#include <string.h>
+#include <3ds.h>
+
+Handle irrstHandle;
+Handle irrstMemHandle;
+Handle irrstEvent;
+
+vu32* irrstSharedMem;
+
+static u32 kHeld;
+static circlePosition csPos;
+static bool irrstUsed = false;
+
+Result irrstInit(u32* sharedMem)
+{
+ if(!sharedMem)sharedMem=(u32*)IRRST_SHAREDMEM_DEFAULT;
+ Result ret=0;
+
+ // Request service.
+ if((ret=srvGetServiceHandle(&irrstHandle, "ir:rst")))return ret;
+
+ // Get sharedmem handle.
+ if((ret=IRRST_GetHandles(&irrstMemHandle, &irrstEvent))) goto cleanup1;
+
+ // Map ir:rst shared memory at addr "sharedMem".
+ irrstSharedMem=sharedMem;
+ if((ret=svcMapMemoryBlock(irrstMemHandle, (u32)irrstSharedMem, MEMPERM_READ, 0x10000000)))goto cleanup2;
+
+ // Reset internal state.
+ irrstUsed = true;
+ kHeld = 0;
+ return 0;
+
+cleanup2:
+ svcCloseHandle(irrstMemHandle);
+cleanup1:
+ svcCloseHandle(irrstHandle);
+ return ret;
+}
+
+void irrstExit()
+{
+ irrstUsed = false;
+ // Unmap ir:rst sharedmem and close handles.
+ svcUnmapMemoryBlock(irrstMemHandle, (u32)irrstSharedMem);
+ svcCloseHandle(irrstMemHandle);
+ svcCloseHandle(irrstHandle);
+}
+
+void irrstWaitForEvent(bool nextEvent)
+{
+ if(nextEvent)svcClearEvent(irrstEvent);
+ svcWaitSynchronization(irrstEvent, U64_MAX);
+ if(!nextEvent)svcClearEvent(irrstEvent);
+}
+
+u32 irrstCheckSectionUpdateTime(vu32 *sharedmem_section, u32 id)
+{
+ s64 tick0=0, tick1=0;
+
+ if(id==0)
+ {
+ tick0 = *((u64*)&sharedmem_section[0]);
+ tick1 = *((u64*)&sharedmem_section[2]);
+
+ if(tick0==tick1 || tick0<0 || tick1<0)return 1;
+ }
+
+ return 0;
+}
+
+void irrstScanInput()
+{
+ if(!irrstUsed)return;
+
+ u32 Id=0;
+ kHeld = 0;
+ memset(&csPos, 0, sizeof(circlePosition));
+
+ Id = irrstSharedMem[4]; //PAD / circle-pad
+ if(Id>7)Id=7;
+ if(irrstCheckSectionUpdateTime(irrstSharedMem, Id)==0)
+ {
+ kHeld = irrstSharedMem[6 + Id*4];
+ csPos = *(circlePosition*)&irrstSharedMem[6 + Id*4 + 3];
+ }
+}
+
+u32 irrstKeysHeld()
+{
+ if(irrstUsed)return kHeld;
+ return 0;
+}
+
+void irrstCstickRead(circlePosition* pos)
+{
+ if (pos) *pos = csPos;
+}
+
+Result IRRST_GetHandles(Handle* outMemHandle, Handle* outEventHandle)
+{
+ u32* cmdbuf=getThreadCommandBuffer();
+ cmdbuf[0]=0x00010000; //request header code
+
+ Result ret=0;
+ if((ret=svcSendSyncRequest(irrstHandle)))return ret;
+
+ if(outMemHandle)*outMemHandle=cmdbuf[3];
+ if(outEventHandle)*outEventHandle=cmdbuf[4];
+
+ return cmdbuf[1];
+}
+
+Result IRRST_Initialize(u32 unk1, u8 unk2)
+{
+ u32* cmdbuf=getThreadCommandBuffer();
+ cmdbuf[0]=0x00020080; //request header code
+ cmdbuf[1]=unk1;
+ cmdbuf[2]=unk2;
+
+ Result ret=0;
+ if((ret=svcSendSyncRequest(irrstHandle)))return ret;
+
+ return cmdbuf[1];
+}
+
+Result IRRST_Shutdown(void)
+{
+ u32* cmdbuf=getThreadCommandBuffer();
+ cmdbuf[0]=0x00030000; //request header code
+
+ Result ret=0;
+ if((ret=svcSendSyncRequest(irrstHandle)))return ret;
+
+ return cmdbuf[1];
+}