From e115853aee0ecea7ee6764b71b9f0a8375f60da7 Mon Sep 17 00:00:00 2001 From: smea Date: Sat, 25 Oct 2014 18:30:19 -0700 Subject: [PATCH] added c-stick, ZL and ZR support via ir:rst --- libctru/include/3ds.h | 1 + libctru/include/3ds/services/hid.h | 48 +++++---- libctru/include/3ds/services/irrst.h | 25 +++++ libctru/source/services/hid.c | 3 + libctru/source/services/irrst.c | 140 +++++++++++++++++++++++++++ 5 files changed, 196 insertions(+), 21 deletions(-) create mode 100644 libctru/include/3ds/services/irrst.h create mode 100644 libctru/source/services/irrst.c diff --git a/libctru/include/3ds.h b/libctru/include/3ds.h index 1f17a92..2111f04 100644 --- a/libctru/include/3ds.h +++ b/libctru/include/3ds.h @@ -19,6 +19,7 @@ extern "C" { #include <3ds/services/fs.h> #include <3ds/services/gsp.h> #include <3ds/services/hid.h> +#include <3ds/services/irrst.h> #include <3ds/services/httpc.h> #include <3ds/services/ir.h> #include <3ds/services/ptm.h> diff --git a/libctru/include/3ds/services/hid.h b/libctru/include/3ds/services/hid.h index 3333abb..4ba6aa7 100644 --- a/libctru/include/3ds/services/hid.h +++ b/libctru/include/3ds/services/hid.h @@ -6,29 +6,35 @@ 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 diff --git a/libctru/include/3ds/services/irrst.h b/libctru/include/3ds/services/irrst.h new file mode 100644 index 0000000..2390eb4 --- /dev/null +++ b/libctru/include/3ds/services/irrst.h @@ -0,0 +1,25 @@ +#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); diff --git a/libctru/source/services/hid.c b/libctru/source/services/hid.c index 9e32566..eb14c5d 100644 --- a/libctru/source/services/hid.c +++ b/libctru/source/services/hid.c @@ -84,6 +84,7 @@ void hidScanInput() u32 Id=0; kOld = kHeld; + irrstScanInput(); kHeld = 0; memset(&cPos, 0, sizeof(circlePosition)); @@ -108,6 +109,8 @@ void hidScanInput() kHeld |= KEY_TOUCH; } + kHeld |= irrstKeysHeld(); + kDown = (~kOld) & kHeld; kUp = kOld & (~kHeld); diff --git a/libctru/source/services/irrst.c b/libctru/source/services/irrst.c new file mode 100644 index 0000000..f00aaa2 --- /dev/null +++ b/libctru/source/services/irrst.c @@ -0,0 +1,140 @@ +/* + _irrst.c - C-stick, ZL/ZR +*/ +#include +#include +#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]; +}