rosalina menu: add scrolling, cpad and inputredir support (note: no ZL/ZR due to technical reasons)

This commit is contained in:
TuxSH 2020-05-14 21:05:27 +01:00
parent 6417720d7d
commit 22db3445a0
5 changed files with 87 additions and 89 deletions

View File

@ -46,6 +46,7 @@
#define BUTTON_Y (1 << 11) #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_APPLICATION 0
#define CORE_SYSTEM 1 #define CORE_SYSTEM 1
@ -75,10 +76,10 @@ extern Handle terminationRequestEvent;
extern u32 menuCombo; extern u32 menuCombo;
u32 waitInputWithTimeout(u32 msec); u32 waitInputWithTimeout(s32 msec);
u32 waitInput(void); u32 waitInput(void);
u32 waitComboWithTimeout(u32 msec); u32 waitComboWithTimeout(s32 msec);
u32 waitCombo(void); u32 waitCombo(void);
MyThread *menuCreateThread(void); MyThread *menuCreateThread(void);

View File

@ -27,6 +27,7 @@
#pragma once #pragma once
#include <3ds/svc.h> #include <3ds/svc.h>
#include <3ds/srv.h>
#include <3ds/result.h> #include <3ds/result.h>
#include "csvc.h" #include "csvc.h"
@ -56,4 +57,10 @@ static inline void *decodeArmBranch(const void *src)
return (void *)((const u8 *)src + 8 + off); 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); Result OpenProcessByName(const char *name, Handle *h);

View File

@ -36,7 +36,6 @@
#include "gdb/server.h" #include "gdb/server.h"
#include "pmdbgext.h" #include "pmdbgext.h"
#define MAP_BASE 0x10000000
#define SYSCOREVER (*(vu32 *)0x1FF80010) #define SYSCOREVER (*(vu32 *)0x1FF80010)
#define APPMEMTYPE (*(vu32 *)0x1FF80030) #define APPMEMTYPE (*(vu32 *)0x1FF80030)
@ -249,8 +248,10 @@ void HBLDR_HandleCommands(void *ctx)
break; break;
} }
// note: mappableFree doesn't do anything
u32 tmp = 0; 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)) if (R_FAILED(res))
{ {
IFile_Close(&file); IFile_Close(&file);
@ -258,12 +259,12 @@ void HBLDR_HandleCommands(void *ctx)
break; break;
} }
Handle hCodeset = Ldr_CodesetFrom3dsx(name, (u32*)MAP_BASE, baseAddr, &file, tid); Handle hCodeset = Ldr_CodesetFrom3dsx(name, addr, baseAddr, &file, tid);
IFile_Close(&file); IFile_Close(&file);
if (!hCodeset) 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)); error(cmdbuf, MAKERESULT(RL_PERMANENT, RS_INTERNAL, RM_LDR, RD_NOT_FOUND));
break; break;
} }

View File

@ -111,6 +111,7 @@ void initSystem(void)
s64 out; s64 out;
Result res; Result res;
__sync_init(); __sync_init();
mappableInit(0x10000000, 0x14000000);
isN3DS = svcGetSystemInfo(&out, 0x10001, 0) == 0; isN3DS = svcGetSystemInfo(&out, 0x10001, 0) == 0;
@ -156,16 +157,14 @@ void initSystem(void)
bool terminationRequest = false; bool terminationRequest = false;
Handle terminationRequestEvent; Handle terminationRequestEvent;
extern bool isHidInitialized;
static void handleTermNotification(u32 notificationId) static void handleTermNotification(u32 notificationId)
{ {
(void)notificationId; (void)notificationId;
// Termination request
terminationRequest = true;
svcSignalEvent(terminationRequestEvent);
} }
static void relinquishConnectionSessions(u32 notificationId) static void handlePreTermNotification(u32 notificationId)
{ {
(void)notificationId; (void)notificationId;
// Might be subject to a race condition, but heh. // Might be subject to a race condition, but heh.
@ -183,6 +182,13 @@ static void relinquishConnectionSessions(u32 notificationId)
isConnectionForced = false; isConnectionForced = false;
SysConfigMenu_UpdateStatus(true); SysConfigMenu_UpdateStatus(true);
} }
if (isHidInitialized)
hidExit();
// Termination request
terminationRequest = true;
svcSignalEvent(terminationRequestEvent);
} }
static void handleNextApplicationDebuggedByForce(u32 notificationId) static void handleNextApplicationDebuggedByForce(u32 notificationId)
@ -205,9 +211,9 @@ static const ServiceManagerServiceEntry services[] = {
static const ServiceManagerNotificationEntry notifications[] = { static const ServiceManagerNotificationEntry notifications[] = {
{ 0x100 , handleTermNotification }, { 0x100 , handleTermNotification },
//{ 0x103 , relinquishConnectionSessions }, // Sleep mode entry <=== causes issues //{ 0x103 , handlePreTermNotification }, // Sleep mode entry <=== causes issues
{ 0x1000, handleNextApplicationDebuggedByForce }, { 0x1000, handleNextApplicationDebuggedByForce },
{ 0x2000, relinquishConnectionSessions }, { 0x2000, handlePreTermNotification },
{ 0x3000, handleRestartHbAppNotification }, { 0x3000, handleRestartHbAppNotification },
{ 0x000, NULL }, { 0x000, NULL },
}; };
@ -240,6 +246,7 @@ int main(void)
TaskRunner_Terminate(); TaskRunner_Terminate();
MyThread_Join(menuThread, -1LL); MyThread_Join(menuThread, -1LL);
MyThread_Join(taskRunnerThread, -1LL); MyThread_Join(taskRunnerThread, -1LL);
MyThread_Join(errDispThread, -1LL); MyThread_Join(errDispThread, -1LL);

View File

@ -36,92 +36,76 @@
#include "menus/cheats.h" #include "menus/cheats.h"
#include "minisoc.h" #include "minisoc.h"
u32 waitInputWithTimeout(u32 msec) bool isHidInitialized = false;
{
bool pressedKey = false;
u32 key = 0;
u32 n = 0;
//Wait for no keys to be pressed // libctru redefinition:
while(HID_PAD && !terminationRequest && (msec == 0 || n < msec))
bool hidShouldUseIrrst(void)
{ {
svcSleepThread(1 * 1000 * 1000LL); // ir:rst exposes only two sessions :(
n++; return false;
} }
if(terminationRequest || (msec != 0 && n >= msec)) static u32 convertHidKeys(u32 keys)
return 0; {
u32 buttons = keys & 0xFFF;
// 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 do
{
//Wait for a key to be pressed
while(!HID_PAD && !terminationRequest && (msec == 0 || n < msec))
{ {
svcSleepThread(1 * 1000 * 1000LL); svcSleepThread(1 * 1000 * 1000LL);
n++; if (!isHidInitialized || terminationRequest) break;
} n += 1;
if(terminationRequest || (msec != 0 && n >= msec)) hidScanInput();
return 0; keys = convertHidKeys(hidKeysDown()) | (convertHidKeys(hidKeysDownRepeat()) & DIRECTIONAL_KEYS);
} while (keys == 0 && !terminationRequest && isHidInitialized && n < msec);
key = HID_PAD;
//Make sure it's pressed return keys;
for(u32 i = 0x26000; i > 0; i --)
{
if(key != HID_PAD) break;
if(i == 1) pressedKey = true;
}
}
while(!pressedKey);
return key;
} }
u32 waitInput(void) u32 waitInput(void)
{ {
return waitInputWithTimeout(0); return waitInputWithTimeout(-1);
} }
u32 waitComboWithTimeout(u32 msec) u32 waitComboWithTimeout(s32 msec)
{ {
u32 key = 0; s32 n = 0;
u32 n = 0; u32 keys;
//Wait for no keys to be pressed hidScanInput();
while(HID_PAD && !terminationRequest && (msec == 0 || n < msec)) keys = convertHidKeys(hidKeysHeld());
{
svcSleepThread(1 * 1000 * 1000LL);
n++;
}
if(terminationRequest || (msec != 0 && n >= msec))
return 0;
do do
{ {
svcSleepThread(1 * 1000 * 1000LL); 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; return keys;
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;
} }
u32 waitCombo(void) u32 waitCombo(void)
{ {
return waitComboWithTimeout(0); return waitComboWithTimeout(-1);
} }
static MyThread menuThread; static MyThread menuThread;
@ -149,28 +133,26 @@ void menuThreadMain(void)
else else
N3DSMenu_UpdateStatus(); 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) while(!terminationRequest)
{ {
if((HID_PAD & menuCombo) == menuCombo) u32 keys = waitComboWithTimeout(1);
{ Cheat_ApplyCheats();
if (!isAcURegistered)
isAcURegistered = R_SUCCEEDED(srvIsServiceRegistered(&isAcURegistered, "ac:u"))
&& isAcURegistered;
if (isAcURegistered) if((keys & menuCombo) == menuCombo)
{ {
menuEnter(); menuEnter();
if(isN3DS) N3DSMenu_UpdateStatus(); if(isN3DS) N3DSMenu_UpdateStatus();
menuShow(&rosalinaMenu); menuShow(&rosalinaMenu);
menuLeave(); menuLeave();
} }
}
else
{
Cheat_ApplyCheats();
}
svcSleepThread(50 * 1000 * 1000LL); svcSleepThread(50 * 1000 * 1000LL);
} }
} }