rosalina menu: add scrolling, cpad and inputredir support (note: no ZL/ZR due to technical reasons)
This commit is contained in:
parent
6417720d7d
commit
22db3445a0
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user