From 22db3445a0b27666909045e7fd11ef9f70cd5b3e Mon Sep 17 00:00:00 2001 From: TuxSH <1922548+TuxSH@users.noreply.github.com> Date: Thu, 14 May 2020 21:05:27 +0100 Subject: [PATCH] rosalina menu: add scrolling, cpad and inputredir support (note: no ZL/ZR due to technical reasons) --- sysmodules/rosalina/include/menu.h | 7 +- sysmodules/rosalina/include/utils.h | 7 ++ sysmodules/rosalina/source/hbloader.c | 9 +- sysmodules/rosalina/source/main.c | 19 ++-- sysmodules/rosalina/source/menu.c | 134 +++++++++++--------------- 5 files changed, 87 insertions(+), 89 deletions(-) diff --git a/sysmodules/rosalina/include/menu.h b/sysmodules/rosalina/include/menu.h index 329e0c9..bcf162b 100644 --- a/sysmodules/rosalina/include/menu.h +++ b/sysmodules/rosalina/include/menu.h @@ -45,7 +45,8 @@ #define BUTTON_X (1 << 10) #define BUTTON_Y (1 << 11) -#define DEFAULT_MENU_COMBO (BUTTON_L1 | BUTTON_DOWN | BUTTON_SELECT) +#define DEFAULT_MENU_COMBO (BUTTON_L1 | BUTTON_DOWN | BUTTON_SELECT) +#define DIRECTIONAL_KEYS (BUTTON_DOWN | BUTTON_UP | BUTTON_LEFT | BUTTON_RIGHT) #define CORE_APPLICATION 0 #define CORE_SYSTEM 1 @@ -75,10 +76,10 @@ extern Handle terminationRequestEvent; extern u32 menuCombo; -u32 waitInputWithTimeout(u32 msec); +u32 waitInputWithTimeout(s32 msec); u32 waitInput(void); -u32 waitComboWithTimeout(u32 msec); +u32 waitComboWithTimeout(s32 msec); u32 waitCombo(void); MyThread *menuCreateThread(void); diff --git a/sysmodules/rosalina/include/utils.h b/sysmodules/rosalina/include/utils.h index 2c3e6b8..c48fcc7 100644 --- a/sysmodules/rosalina/include/utils.h +++ b/sysmodules/rosalina/include/utils.h @@ -27,6 +27,7 @@ #pragma once #include <3ds/svc.h> +#include <3ds/srv.h> #include <3ds/result.h> #include "csvc.h" @@ -56,4 +57,10 @@ static inline void *decodeArmBranch(const void *src) return (void *)((const u8 *)src + 8 + off); } +static inline bool isServiceUsable(const char *name) +{ + bool r; + return R_SUCCEEDED(srvIsServiceRegistered(&r, name)) && r; +} + Result OpenProcessByName(const char *name, Handle *h); diff --git a/sysmodules/rosalina/source/hbloader.c b/sysmodules/rosalina/source/hbloader.c index 8dcb4e7..8d2959b 100644 --- a/sysmodules/rosalina/source/hbloader.c +++ b/sysmodules/rosalina/source/hbloader.c @@ -36,7 +36,6 @@ #include "gdb/server.h" #include "pmdbgext.h" -#define MAP_BASE 0x10000000 #define SYSCOREVER (*(vu32 *)0x1FF80010) #define APPMEMTYPE (*(vu32 *)0x1FF80030) @@ -249,8 +248,10 @@ void HBLDR_HandleCommands(void *ctx) break; } + // note: mappableFree doesn't do anything u32 tmp = 0; - res = svcControlMemoryEx(&tmp, MAP_BASE, 0, totalSize, MEMOP_ALLOC | flags, MEMPERM_READ | MEMPERM_WRITE, true); + u32 *addr = mappableAlloc(totalSize); + res = svcControlMemoryEx(&tmp, (u32)addr, 0, totalSize, MEMOP_ALLOC | flags, MEMPERM_READ | MEMPERM_WRITE, true); if (R_FAILED(res)) { IFile_Close(&file); @@ -258,12 +259,12 @@ void HBLDR_HandleCommands(void *ctx) break; } - Handle hCodeset = Ldr_CodesetFrom3dsx(name, (u32*)MAP_BASE, baseAddr, &file, tid); + Handle hCodeset = Ldr_CodesetFrom3dsx(name, addr, baseAddr, &file, tid); IFile_Close(&file); if (!hCodeset) { - svcControlMemory(&tmp, MAP_BASE, 0, totalSize, MEMOP_FREE, 0); + svcControlMemory(&tmp, (u32)addr, 0, totalSize, MEMOP_FREE, 0); error(cmdbuf, MAKERESULT(RL_PERMANENT, RS_INTERNAL, RM_LDR, RD_NOT_FOUND)); break; } diff --git a/sysmodules/rosalina/source/main.c b/sysmodules/rosalina/source/main.c index 0e8c552..afe17ad 100644 --- a/sysmodules/rosalina/source/main.c +++ b/sysmodules/rosalina/source/main.c @@ -111,6 +111,7 @@ void initSystem(void) s64 out; Result res; __sync_init(); + mappableInit(0x10000000, 0x14000000); isN3DS = svcGetSystemInfo(&out, 0x10001, 0) == 0; @@ -156,16 +157,14 @@ void initSystem(void) bool terminationRequest = false; Handle terminationRequestEvent; +extern bool isHidInitialized; static void handleTermNotification(u32 notificationId) { (void)notificationId; - // Termination request - terminationRequest = true; - svcSignalEvent(terminationRequestEvent); } -static void relinquishConnectionSessions(u32 notificationId) +static void handlePreTermNotification(u32 notificationId) { (void)notificationId; // Might be subject to a race condition, but heh. @@ -183,6 +182,13 @@ static void relinquishConnectionSessions(u32 notificationId) isConnectionForced = false; SysConfigMenu_UpdateStatus(true); } + + if (isHidInitialized) + hidExit(); + + // Termination request + terminationRequest = true; + svcSignalEvent(terminationRequestEvent); } static void handleNextApplicationDebuggedByForce(u32 notificationId) @@ -205,9 +211,9 @@ static const ServiceManagerServiceEntry services[] = { static const ServiceManagerNotificationEntry notifications[] = { { 0x100 , handleTermNotification }, - //{ 0x103 , relinquishConnectionSessions }, // Sleep mode entry <=== causes issues + //{ 0x103 , handlePreTermNotification }, // Sleep mode entry <=== causes issues { 0x1000, handleNextApplicationDebuggedByForce }, - { 0x2000, relinquishConnectionSessions }, + { 0x2000, handlePreTermNotification }, { 0x3000, handleRestartHbAppNotification }, { 0x000, NULL }, }; @@ -240,6 +246,7 @@ int main(void) TaskRunner_Terminate(); MyThread_Join(menuThread, -1LL); + MyThread_Join(taskRunnerThread, -1LL); MyThread_Join(errDispThread, -1LL); diff --git a/sysmodules/rosalina/source/menu.c b/sysmodules/rosalina/source/menu.c index bb82990..6b5e5dc 100644 --- a/sysmodules/rosalina/source/menu.c +++ b/sysmodules/rosalina/source/menu.c @@ -36,92 +36,76 @@ #include "menus/cheats.h" #include "minisoc.h" -u32 waitInputWithTimeout(u32 msec) +bool isHidInitialized = false; + +// libctru redefinition: + +bool hidShouldUseIrrst(void) { - bool pressedKey = false; - u32 key = 0; - u32 n = 0; + // ir:rst exposes only two sessions :( + return false; +} - //Wait for no keys to be pressed - while(HID_PAD && !terminationRequest && (msec == 0 || n < msec)) - { - svcSleepThread(1 * 1000 * 1000LL); - n++; - } +static u32 convertHidKeys(u32 keys) +{ + u32 buttons = keys & 0xFFF; - if(terminationRequest || (msec != 0 && n >= msec)) - return 0; + // Transform Circle Pad and C-stick into directional keys + if (keys & KEY_LEFT) buttons |= BUTTON_LEFT; + if (keys & KEY_RIGHT) buttons |= BUTTON_RIGHT; + if (keys & KEY_UP) buttons |= BUTTON_UP; + if (keys & KEY_DOWN) buttons |= BUTTON_DOWN; + + return buttons; +} + +u32 waitInputWithTimeout(s32 msec) +{ + s32 n = 0; + u32 keys; do { - //Wait for a key to be pressed - while(!HID_PAD && !terminationRequest && (msec == 0 || n < msec)) - { - svcSleepThread(1 * 1000 * 1000LL); - n++; - } + svcSleepThread(1 * 1000 * 1000LL); + if (!isHidInitialized || terminationRequest) break; + n += 1; - if(terminationRequest || (msec != 0 && n >= msec)) - return 0; + hidScanInput(); + keys = convertHidKeys(hidKeysDown()) | (convertHidKeys(hidKeysDownRepeat()) & DIRECTIONAL_KEYS); + } while (keys == 0 && !terminationRequest && isHidInitialized && n < msec); - key = HID_PAD; - //Make sure it's pressed - for(u32 i = 0x26000; i > 0; i --) - { - if(key != HID_PAD) break; - if(i == 1) pressedKey = true; - } - } - while(!pressedKey); - - return key; + return keys; } u32 waitInput(void) { - return waitInputWithTimeout(0); + return waitInputWithTimeout(-1); } -u32 waitComboWithTimeout(u32 msec) +u32 waitComboWithTimeout(s32 msec) { - u32 key = 0; - u32 n = 0; + s32 n = 0; + u32 keys; - //Wait for no keys to be pressed - while(HID_PAD && !terminationRequest && (msec == 0 || n < msec)) - { - svcSleepThread(1 * 1000 * 1000LL); - n++; - } - - if(terminationRequest || (msec != 0 && n >= msec)) - return 0; + hidScanInput(); + keys = convertHidKeys(hidKeysHeld()); do { svcSleepThread(1 * 1000 * 1000LL); - n++; + if (!isHidInitialized || terminationRequest) break; + n += 1; + hidScanInput(); + keys = convertHidKeys(hidKeysHeld()); + } while (keys == 0 && !terminationRequest && isHidInitialized && n < msec); - u32 tempKey = HID_PAD; - - for(u32 i = 0x26000; i > 0; i--) - { - if(tempKey != HID_PAD) break; - if(i == 1) key = tempKey; - } - } - while((!key || HID_PAD) && !terminationRequest && (msec == 0 || n < msec)); - - if(terminationRequest || (msec != 0 && n >= msec)) - return 0; - - return key; + return keys; } u32 waitCombo(void) { - return waitComboWithTimeout(0); + return waitComboWithTimeout(-1); } static MyThread menuThread; @@ -149,28 +133,26 @@ void menuThreadMain(void) else N3DSMenu_UpdateStatus(); - bool isAcURegistered = false; + while (!isServiceUsable("ac:u") || !isServiceUsable("hid:USER")) + svcSleepThread(500 * 1000 * 1000LL); + + hidInit(); // assume this doesn't fail + hidSetRepeatParameters(250, 100); + isHidInitialized = true; while(!terminationRequest) { - if((HID_PAD & menuCombo) == menuCombo) - { - if (!isAcURegistered) - isAcURegistered = R_SUCCEEDED(srvIsServiceRegistered(&isAcURegistered, "ac:u")) - && isAcURegistered; + u32 keys = waitComboWithTimeout(1); + Cheat_ApplyCheats(); - if (isAcURegistered) - { - menuEnter(); - if(isN3DS) N3DSMenu_UpdateStatus(); - menuShow(&rosalinaMenu); - menuLeave(); - } - } - else + if((keys & menuCombo) == menuCombo) { - Cheat_ApplyCheats(); + menuEnter(); + if(isN3DS) N3DSMenu_UpdateStatus(); + menuShow(&rosalinaMenu); + menuLeave(); } + svcSleepThread(50 * 1000 * 1000LL); } }