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
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
// libctru redefinition:
|
||||||
|
|
||||||
|
bool hidShouldUseIrrst(void)
|
||||||
{
|
{
|
||||||
bool pressedKey = false;
|
// ir:rst exposes only two sessions :(
|
||||||
u32 key = 0;
|
return false;
|
||||||
u32 n = 0;
|
}
|
||||||
|
|
||||||
//Wait for no keys to be pressed
|
static u32 convertHidKeys(u32 keys)
|
||||||
while(HID_PAD && !terminationRequest && (msec == 0 || n < msec))
|
{
|
||||||
{
|
u32 buttons = keys & 0xFFF;
|
||||||
svcSleepThread(1 * 1000 * 1000LL);
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(terminationRequest || (msec != 0 && n >= msec))
|
// Transform Circle Pad and C-stick into directional keys
|
||||||
return 0;
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user