Compare commits

...

31 Commits
v8.1 ... v8.1.1

Author SHA1 Message Date
Aurora Wright
f6483ec602 Merge branch 'master' of https://github.com/AuroraWright/Luma3DS 2017-08-07 21:20:18 +02:00
Aurora Wright
36c1da1d61 Add mention of exheaders in the Enable game patching description 2017-08-07 21:20:08 +02:00
Stary 2001
6bcb1f8679 Merge pull request #763 from Streetwalrus/ir-title
Fix input redirection title index in the menu
2017-08-06 22:15:21 +01:00
Dan Elkouby
62932a9639 Fix input redirection title index in the menu
This option is the third, not the fourth, and toggling it will override
the "save settings" option's title instead.
2017-08-06 23:56:00 +03:00
Hikari-chin
a4629e4b65 Cleaned up and rearranged the Rosalina menu in preparation for future features 2017-08-01 17:38:48 +02:00
Aurora Wright
a0c2b43b34 Implement loading of exheaders from SD/CTRNAND (must be called luma/titles/TITLEID/exheader.bin), thanks to @HiddenRambler! 2017-08-01 17:38:23 +02:00
TuxSH
3907c46980 Follow ARM's documentation on hw watchpoints to the letter 2017-07-20 00:56:08 +02:00
TuxSH
7e7ab124a3 Log "logged" errdisp messages in /luma/errdisp.txt, fixes #707 2017-07-19 00:59:47 +02:00
TuxSH
cfc6cf24bf Some kext refactoring 2017-07-16 18:58:20 +02:00
TuxSH
46e9cb6b23 Fix fallthrough bug 2017-07-16 13:29:02 +02:00
TuxSH
ba14efe1f4 Suppress future -Wimplicit-fallthrough=3 warnings 2017-07-15 00:41:42 +02:00
TuxSH
3d8f62d38f Fix MaxCpuTime for 3dsx 2017-07-09 22:14:00 +02:00
Hikari-chin
3edaf0af64 Whoops 2017-07-09 14:36:06 -04:00
Aurora Wright
9273a88db7 It seems FB setup needs to be done first 2017-07-09 19:21:12 +02:00
Aurora Wright
37ba2c15de Reinstate framebuffer setup on initScreens to allow old Luma to be chainloaded if FB address changes in b9s/new Luma, remove useless clearScreens for the alternate FBs after the first init 2017-07-09 19:06:42 +02:00
Aurora Wright
557f2057f7 Fix spacing 2017-07-06 18:09:18 +02:00
Aurora Wright
6b5cc93780 Merge branch 'master' of https://github.com/AuroraWright/Luma3DS 2017-07-06 17:29:43 +02:00
Aurora Wright
9760191af8 Fix conflict between emunand selection and payload booting when "Autoboot EmuNAND" is checked, you now need to press L + DPad to boot payloads if that option is checked 2017-07-06 17:29:38 +02:00
TuxSH
8845e4dd20 Merge pull request #704 from Hikari-chin/master
LED toggle switch in Rosalina's misc menu + updated README
2017-07-05 19:26:56 +02:00
Yuuki Hikari
8cf823f548 Update README.md 2017-07-05 02:13:03 -04:00
Hikari-chin
2538769f3a Added LED toggling from the Rosalina misc. menu 2017-07-04 23:50:40 -04:00
Aurora Wright
89fca38807 Merge master into local branch 2017-07-05 01:37:36 +02:00
Aurora Wright
dcc0eed69c Fix LayeredFS for games like Pokemon Art Academy which mistakenly use two forward slashes after the mountpoint 2017-07-05 01:31:04 +02:00
Yuuki Hikari
817475257e Merge pull request #700 from LiquidFenrir/wifi-toggle
Add wireless toggling in rosalina
2017-07-04 15:09:16 -04:00
LiquidFenrir
f2861058ba add wireless toggling in rosalina
https://github.com/AuroraWright/Luma3DS/issues/619#issuecomment-309239178

ligne 353: CFG11_WIFICNT, nothing includes it in rosalina so I hardcoded it here
ligne 363: could also use svc 0x5A (SetWifiEnabled) but not sure how
2017-07-04 18:35:55 +02:00
TuxSH
5d2a7315d5 Fix SetWifiEnabled 2017-07-03 19:28:34 +02:00
TuxSH
1520ab7555 Update ISSUE_TEMPLATE.md
7.1 => 8.1
2017-07-02 22:52:49 +02:00
Aurora Wright
d4d0fbd73b Re-add dir_build variable 2017-07-02 00:46:57 +02:00
Aurora Wright
ddb8e98e95 Merge branch 'master' of https://github.com/AuroraWright/Luma3DS 2017-07-02 00:44:29 +02:00
Aurora Wright
fd69b4169f Use GNU/BSD agnostic syntax instead of detecting the OS (thanks @smartperson) 2017-07-02 00:44:14 +02:00
TuxSH
b48e0b5c5b Update ISSUE_TEMPLATE.md 2017-06-30 23:52:44 +02:00
46 changed files with 879 additions and 304 deletions

View File

@@ -26,7 +26,7 @@
**Luma3DS version:**
[e.g. 7.1 stable or if using nightly/hourly specify the commit like this https://github.com/AuroraWright/Luma3DS/commit/9570e6cbeca53128433abbf5e3473cb8a07fe69e]
[e.g. 8.1 stable or if using nightly/hourly specify the commit like this https://github.com/AuroraWright/Luma3DS/commit/9570e6cbeca53128433abbf5e3473cb8a07fe69e]
<!--You can check which version you're on in System Settings. It will be on the bottom right of the top screen.-->
@@ -53,8 +53,6 @@ Enable loading external FIRMs and modules: ( )
<!--Firmware (.bin) files are not required by Luma, or NTR CFW anymore.
-- If you're having issues with this option enabled try deleting them from the luma folder on the root of the SD card and disabling this option.-->
Use custom path: ( )
Enable game patching: ( )
Show NAND or user string in System Settings: ( )
@@ -65,6 +63,8 @@ Patch ARM9 access: ( )
Set developer UNITINFO: ( )
Disable ARM11 exception handlers: ( )
--

View File

@@ -10,13 +10,6 @@ endif
include $(DEVKITARM)/base_tools
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Darwin)
size := stat -f%z
else
size := stat -c%s
endif
name := Luma3DS
revision := $(shell git describe --tags --match v[0-9]* --abbrev=8 | sed 's/-[0-9]*-g/-/')
version_major := $(shell git describe --tags --match v[0-9]* | cut -c2- | cut -f1 -d- | cut -f1 -d.)
@@ -152,7 +145,7 @@ $(dir_build)/config.o: CFLAGS += -DCONFIG_TITLE="\"$(name) $(revision) configura
$(dir_build)/patches.o: CFLAGS += -DVERSION_MAJOR="$(version_major)" -DVERSION_MINOR="$(version_minor)"\
-DVERSION_BUILD="$(version_build)" -DISRELEASE="$(is_release)" -DCOMMIT_HASH="0x$(commit)"
$(dir_build)/firm.o: $(dir_build)/modules.bin
$(dir_build)/firm.o: CFLAGS += -DLUMA_SECTION0_SIZE="$(shell $(size) $(dir_build)/modules.bin)"
$(dir_build)/firm.o: CFLAGS += -DLUMA_SECTION0_SIZE="$(shell wc -c $(dir_build)/modules.bin | tr -d [:space:][:alpha:][:punct:])"
$(dir_build)/bundled.h: $(bundled)
@$(foreach f, $(bundled),\

View File

@@ -16,7 +16,7 @@ Since Luma3DS v8.0, Luma3DS has its own in-game menu, triggerable by `L+Down+Sel
First you need to clone the repository with: `git clone https://github.com/AuroraWright/Luma3DS.git`
To compile, you'll need [armips](https://github.com/Kingcom/armips) and a build of a recent commit of [makerom](https://github.com/profi200/Project_CTR) added to your PATH. You'll also need to install [firmtool](https://github.com/TuxSH/firmtool), its README contains installation instructions.
For now, you'll also need to update your [libctru](https://github.com/smealum/ctrulib) install, building from the latest commit.
For your convenience, here are [Windows](http://www91.zippyshare.com/v/ePGpjk9r/file.html) and [Linux](https://mega.nz/#!uQ1T1IAD!Q91O0e12LXKiaXh_YjXD3D5m8_W3FuMI-hEa6KVMRDQ) builds of armips (thanks to who compiled them!).
For your convenience, here are [Windows](http://www91.zippyshare.com/v/ePGpjk9r/file.html) and [Linux](https://mega.nz/#!uQ1T1IAD!Q91O0e12LXKiaXh_YjXD3D5m8_W3FuMI-hEa6KVMRDQ) builds of armips (thanks to who compiled them!) and [makerom](https://github.com/Steveice10/buildtools/tree/master/3ds) (thanks @Steveice10!).
Finally just run `make` and everything should work!
You can find the compiled files in the `out` folder.

View File

@@ -37,7 +37,7 @@ extern u32 prepareForFirmlaunchSize;
extern volatile Arm11Operation operation;
static void initScreens(u32 brightnessLevel, struct fb *fbs)
static void initScreens(u32 brightnessLevel)
{
*(vu32 *)0x10141200 = 0x1007F;
*(vu32 *)0x10202014 = 0x00000001;
@@ -70,13 +70,9 @@ static void initScreens(u32 brightnessLevel, struct fb *fbs)
*(vu32 *)0x1040045C = 0x00f00190;
*(vu32 *)0x10400460 = 0x01c100d1;
*(vu32 *)0x10400464 = 0x01920002;
*(vu32 *)0x10400468 = (u32)fbs[0].top_left;
*(vu32 *)0x1040046C = (u32)fbs[1].top_left;
*(vu32 *)0x10400470 = 0x80341;
*(vu32 *)0x10400474 = 0x00010501;
*(vu32 *)0x10400478 = 0;
*(vu32 *)0x10400494 = (u32)fbs[0].top_right;
*(vu32 *)0x10400498 = (u32)fbs[1].top_right;
*(vu32 *)0x10400490 = 0x000002D0;
*(vu32 *)0x1040049C = 0x00000000;
@@ -107,8 +103,6 @@ static void initScreens(u32 brightnessLevel, struct fb *fbs)
*(vu32 *)0x1040055C = 0x00f00140;
*(vu32 *)0x10400560 = 0x01c100d1;
*(vu32 *)0x10400564 = 0x01920052;
*(vu32 *)0x10400568 = (u32)fbs[0].bottom;
*(vu32 *)0x1040056C = (u32)fbs[1].bottom;
*(vu32 *)0x10400570 = 0x80301;
*(vu32 *)0x10400574 = 0x00010501;
*(vu32 *)0x10400578 = 0;
@@ -120,6 +114,16 @@ static void initScreens(u32 brightnessLevel, struct fb *fbs)
*(vu32 *)0x10400584 = 0x10101 * i;
}
static void setupFramebuffers(struct fb *fbs)
{
*(vu32 *)0x10400468 = (u32)fbs[0].top_left;
*(vu32 *)0x1040046c = (u32)fbs[1].top_left;
*(vu32 *)0x10400494 = (u32)fbs[0].top_right;
*(vu32 *)0x10400498 = (u32)fbs[1].top_right;
*(vu32 *)0x10400568 = (u32)fbs[0].bottom;
*(vu32 *)0x1040056c = (u32)fbs[1].bottom;
}
static void clearScreens(struct fb *fb)
{
//Setting up two simultaneous memory fills using the GPU
@@ -173,7 +177,10 @@ void main(void)
case ARM11_READY:
continue;
case INIT_SCREENS:
initScreens(*(vu32 *)ARM11_PARAMETERS_ADDRESS, (struct fb *)(ARM11_PARAMETERS_ADDRESS + 4));
initScreens(*(vu32 *)ARM11_PARAMETERS_ADDRESS);
break;
case SETUP_FRAMEBUFFERS:
setupFramebuffers((struct fb *)ARM11_PARAMETERS_ADDRESS);
break;
case CLEAR_SCREENS:
clearScreens((struct fb *)ARM11_PARAMETERS_ADDRESS);

View File

@@ -55,6 +55,7 @@ struct fb {
typedef enum
{
INIT_SCREENS = 0,
SETUP_FRAMEBUFFERS,
CLEAR_SCREENS,
SWAP_FRAMEBUFFERS,
UPDATE_BRIGHTNESS,

View File

@@ -56,6 +56,7 @@ extern void (*KScheduler__AttemptSwitchingThreadContext)(KScheduler *this);
extern Result (*ControlMemory)(u32 *addrOut, u32 addr0, u32 addr1, u32 size, MemOp op, MemPerm perm, bool isLoader);
extern void (*SleepThread)(s64 ns);
extern Result (*CloseHandle)(Handle handle);
extern Result (*GetHandleInfo)(s64 *out, Handle handle, u32 type);
extern Result (*GetSystemInfo)(s64 *out, s32 type, s32 param);
extern Result (*GetProcessInfo)(s64 *out, Handle processHandle, u32 type);
extern Result (*GetThreadInfo)(s64 *out, Handle threadHandle, u32 type);

View File

@@ -1137,21 +1137,29 @@ typedef struct FcramLayout
extern bool isN3DS;
extern void *officialSVCs[0x7E];
#define KPROCESS_OFFSETOF(field) (isN3DS ? offsetof(KProcessN3DS, field) :\
((kernelVersion >= SYSTEM_VERSION(2, 44, 6)) ? offsetof(KProcessO3DS8x, field) :\
offsetof(KProcessO3DSPre8x, field)))
#define KPROCESSRELATED_OFFSETOFF(classname, field) (isN3DS ? offsetof(classname##N3DS, field) :\
((kernelVersion >= SYSTEM_VERSION(2, 44, 6)) ? offsetof(classname##O3DS8x, field) :\
offsetof(classname##O3DSPre8x, field)))
#define KPROCESS_GET_PTR(obj, field) (isN3DS ? &(obj)->N3DS.field :\
#define KPROCESSRELATED_GET_PTR(obj, field) (isN3DS ? &(obj)->N3DS.field :\
((kernelVersion >= SYSTEM_VERSION(2, 44, 6)) ? &(obj)->O3DS8x.field :\
&(obj)->O3DSPre8x.field ))
&(obj)->O3DSPre8x.field))
#define KPROCESS_GET_PTR_TYPE(type, obj, field) (isN3DS ? (type *)(&(obj)->N3DS.field) :\
#define KPROCESSRELATED_GET_PTR_TYPE(type, obj, field) (isN3DS ? (type *)(&(obj)->N3DS.field) :\
((kernelVersion >= SYSTEM_VERSION(2, 44, 6)) ? (type *)(&(obj)->O3DS8x.field) :\
(type *)(&(obj)->O3DSPre8x.field) ))
(type *)(&(obj)->O3DSPre8x.field)))
#define KPROCESS_GET_RVALUE(obj, field) *(KPROCESS_GET_PTR(obj, field))
#define KPROCESS_OFFSETOF(field) KPROCESSRELATED_OFFSETOFF(KProcess, field)
#define KPROCESS_GET_PTR(obj, field) KPROCESSRELATED_GET_PTR(obj, field)
#define KPROCESS_GET_PTR_TYPE(type, obj, field) KPROCESSRELATED_GET_PTR_TYPE(type, obj, field)
#define KPROCESS_GET_RVALUE(obj, field) *(KPROCESS_GET_PTR(obj, field))
#define KPROCESS_GET_RVALUE_TYPE(type, obj, field) *(KPROCESS_GET_PTR_TYPE(type, obj, field))
#define KPROCESS_GET_RVALUE_TYPE(type, obj, field) *(KPROCESS_GET_PTR(type, obj, field))
#define KPROCESSHWINFO_OFFSETOF(field) KPROCESSRELATED_OFFSETOFF(KProcessHwInfo, field)
#define KPROCESSHWINFO_GET_PTR(obj, field) KPROCESSRELATED_GET_PTR(obj, field)
#define KPROCESSHWINFO_GET_PTR_TYPE(type, obj, field) KPROCESSRELATED_GET_PTR_TYPE(type, obj, field)
#define KPROCESSHWINFO_GET_RVALUE(obj, field) *(KPROCESSHWINFO_GET_PTR(obj, field))
#define KPROCESSHWINFO_GET_RVALUE_TYPE(type, obj, field) *(KPROCESSHWINFO_GET_PTR_TYPE(type, obj, field))
static inline u32 idOfProcess(KProcess *process)
{
@@ -1178,6 +1186,20 @@ static inline KDebug *debugOfProcess(KProcess *process)
return KPROCESS_GET_RVALUE(process, debug);
}
static inline const char *classNameOfAutoObject(KAutoObject *object)
{
const char *name;
if(kernelVersion >= SYSTEM_VERSION(2, 46, 0))
{
KClassToken tok;
object->vtable->GetClassToken(&tok, object);
name = tok.name;
}
else
name = object->vtable->GetClassName(object);
return name;
}
extern Result (*KProcessHandleTable__CreateHandle)(KProcessHandleTable *this, Handle *out, KAutoObject *obj, u8 token);
static inline Result createHandleForProcess(Handle *out, KProcess *process, KAutoObject *obj)

View File

@@ -0,0 +1,34 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
* * Requiring preservation of specified reasonable legal notices or
* author attributions in that material or in the Appropriate Legal
* Notices displayed by works containing it.
* * Prohibiting misrepresentation of the origin of that material,
* or requiring that modified versions of such material be marked in
* reasonable ways as different from the original version.
*/
#pragma once
#include "utils.h"
#include "kernel.h"
#include "svc.h"
Result GetHandleInfoHookWrapper(u32 dummy, Handle handle, u32 type);
Result GetHandleInfoHook(s64 *out, Handle handle, u32 type);

View File

@@ -30,4 +30,4 @@
#include "kernel.h"
#include "svc.h"
void SetWifiEnabled(bool enable);
Result SetWifiEnabled(bool enable);

View File

@@ -52,6 +52,7 @@ void (*KScheduler__AttemptSwitchingThreadContext)(KScheduler *this);
Result (*ControlMemory)(u32 *addrOut, u32 addr0, u32 addr1, u32 size, MemOp op, MemPerm perm, bool isLoader);
void (*SleepThread)(s64 ns);
Result (*CloseHandle)(Handle handle);
Result (*GetHandleInfo)(s64 *out, Handle handle, u32 type);
Result (*GetSystemInfo)(s64 *out, s32 type, s32 param);
Result (*GetProcessInfo)(s64 *out, Handle processHandle, u32 type);
Result (*GetThreadInfo)(s64 *out, Handle threadHandle, u32 type);

View File

@@ -208,6 +208,7 @@ static void findUsefulSymbols(void)
decodeARMBranch((u32 *)officialSVCs[0x01] + 5);
SleepThread = (void (*)(s64))officialSVCs[0x0A];
CloseHandle = (Result (*)(Handle))officialSVCs[0x23];
GetHandleInfo = (Result (*)(s64 *, Handle, u32))decodeARMBranch((u32 *)officialSVCs[0x29] + 3);
GetSystemInfo = (Result (*)(s64 *, s32, s32))decodeARMBranch((u32 *)officialSVCs[0x2A] + 3);
GetProcessInfo = (Result (*)(s64 *, Handle, u32))decodeARMBranch((u32 *)officialSVCs[0x2B] + 3);
GetThreadInfo = (Result (*)(s64 *, Handle, u32))decodeARMBranch((u32 *)officialSVCs[0x2C] + 3);

View File

@@ -28,9 +28,10 @@
#include "synchronization.h"
#include "svc.h"
#include "svc/ControlMemory.h"
#include "svc/GetHandleInfo.h"
#include "svc/GetSystemInfo.h"
#include "svc/GetProcessInfo.h"
#include "svc/GetThreadInfo.h"
#include "svc/GetSystemInfo.h"
#include "svc/GetCFWInfo.h"
#include "svc/ConnectToPort.h"
#include "svc/SendSyncRequest.h"
@@ -103,6 +104,8 @@ void *svcHook(u8 *pageEnd)
doingVeryShittyPmResLimitWorkaround = true;
}
return officialSVCs[0x17];
case 0x29:
return GetHandleInfoHookWrapper;
case 0x2A:
return GetSystemInfoHookWrapper;
case 0x2B:

View File

@@ -42,20 +42,12 @@ Result ControlService(ServiceOp op, u32 varg1, u32 varg2)
KAutoObject *obj = KProcessHandleTable__ToKAutoObject(handleTable, (Handle)varg2);
if(obj == NULL)
return 0xD8E007F7; // invalid handle
else if(kernelVersion >= SYSTEM_VERSION(2, 46, 0))
{
KClassToken tok;
obj->vtable->GetClassToken(&tok, obj);
if(tok.flags == 0x95)
session = ((KServerSession *)obj)->parentSession;
else if(tok.flags == 0xA5)
session = ((KClientSession *)obj)->parentSession;
}
else
{ // not the exact same tests but it should work
if(strcmp(obj->vtable->GetClassName(obj), "KServerSession") == 0)
{
// not the exact same tests but it should work
if(strcmp(classNameOfAutoObject(obj), "KServerSession") == 0)
session = ((KServerSession *)obj)->parentSession;
else if(strcmp(obj->vtable->GetClassName(obj), "KClientSession") == 0)
else if(strcmp(classNameOfAutoObject(obj), "KClientSession") == 0)
session = ((KClientSession *)obj)->parentSession;
}

View File

@@ -0,0 +1,62 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
* * Requiring preservation of specified reasonable legal notices or
* author attributions in that material or in the Appropriate Legal
* Notices displayed by works containing it.
* * Prohibiting misrepresentation of the origin of that material,
* or requiring that modified versions of such material be marked in
* reasonable ways as different from the original version.
*/
#include "svc/GetThreadInfo.h"
#include "memory.h"
Result GetHandleInfoHook(s64 *out, Handle handle, u32 type)
{
if(type == 0x10000) // KDebug and KProcess: get context ID
{
KProcessHwInfo *hwInfo;
KProcessHandleTable *handleTable = handleTableOfProcess(currentCoreContext->objectContext.currentProcess);
KAutoObject *obj;
if(handle == CUR_PROCESS_HANDLE)
{
obj = (KAutoObject *)(currentCoreContext->objectContext.currentProcess);
KAutoObject__AddReference(obj);
}
else
obj = KProcessHandleTable__ToKAutoObject(handleTable, handle);
if(obj == NULL)
return 0xD8E007F7;
if(strcmp(classNameOfAutoObject(obj), "KDebug") == 0)
hwInfo = hwInfoOfProcess(((KDebug *)obj)->owner);
else if(strcmp(classNameOfAutoObject(obj), "KProcess") == 0)
hwInfo = hwInfoOfProcess((KProcess *)obj);
else
hwInfo = NULL;
*out = hwInfo != NULL ? KPROCESSHWINFO_GET_RVALUE(hwInfo, contextId) : -1;
obj->vtable->DecrementReferenceCount(obj);
return 0;
}
else
return GetHandleInfo(out, handle, type);
}

View File

@@ -73,12 +73,12 @@ Result GetProcessInfoHook(s64 *out, Handle processHandle, u32 type)
*out = (s64)(u64)(u32)codeSetOfProcess(process)->dataSection.section.loadAddress;
break;
case 0x10008:
*out = (isN3DS ? hwInfoOfProcess(process)->N3DS.translationTableBase :
(kernelVersion >= SYSTEM_VERSION(2, 44, 6)
? hwInfoOfProcess(process)->O3DS8x.translationTableBase
: hwInfoOfProcess(process)->O3DSPre8x.translationTableBase)
) & ~((1 << (14 - TTBCR)) - 1);
{
KProcessHwInfo *hwInfo = hwInfoOfProcess(process);
u32 ttb = KPROCESSHWINFO_GET_RVALUE(hwInfo, translationTableBase);
*out = ttb & ~((1 << (14 - TTBCR)) - 1);
break;
}
default:
res = 0xD8E007ED; // invalid enum value
break;

View File

@@ -37,15 +37,8 @@ Result SendSyncRequestHook(Handle handle)
bool skip = false;
Result res = 0;
bool isValidClientSession = false;
if(clientSession != NULL && kernelVersion >= SYSTEM_VERSION(2, 46, 0))
{
KClassToken tok;
clientSession->syncObject.autoObject.vtable->GetClassToken(&tok, &clientSession->syncObject.autoObject);
isValidClientSession = tok.flags == 0xA5;
}
else if(clientSession != NULL) // not the exact same test but it should work
isValidClientSession = strcmp(clientSession->syncObject.autoObject.vtable->GetClassName(&clientSession->syncObject.autoObject), "KClientSession") == 0;
// not the exact same test but it should work
bool isValidClientSession = clientSession != NULL && strcmp(classNameOfAutoObject(&clientSession->syncObject.autoObject), "KClientSession") == 0;
if(isValidClientSession)
{
@@ -54,7 +47,7 @@ Result SendSyncRequestHook(Handle handle)
case 0x10042:
{
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);
if(info != NULL && strcmp(info->name, "srv:pm") == 0)
if(info != NULL && kernelVersion >= SYSTEM_VERSION(2, 39, 4) && strcmp(info->name, "srv:pm") == 0)
{
res = doPublishToProcessHook(handle, cmdbuf);
skip = true;
@@ -112,7 +105,7 @@ Result SendSyncRequestHook(Handle handle)
case 0x50100:
{
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);
if(info != NULL && strcmp(info->name, "srv:") == 0)
if(info != NULL && (strcmp(info->name, "srv:") == 0 || (kernelVersion < SYSTEM_VERSION(2, 39, 4) && strcmp(info->name, "srv:pm") == 0)))
{
char name[9] = { 0 };
memcpy(name, cmdbuf + 1, 8);
@@ -126,7 +119,8 @@ Result SendSyncRequestHook(Handle handle)
outClientSession = (KClientSession *)KProcessHandleTable__ToKAutoObject(handleTable, (Handle)cmdbuf[3]);
if(outClientSession != NULL)
{
SessionInfo_Add(outClientSession->parentSession, name);
if(strcmp(classNameOfAutoObject(&outClientSession->syncObject.autoObject), "KClientSession") == 0)
SessionInfo_Add(outClientSession->parentSession, name);
outClientSession->syncObject.autoObject.vtable->DecrementReferenceCount(&outClientSession->syncObject.autoObject);
}
}
@@ -163,7 +157,7 @@ Result SendSyncRequestHook(Handle handle)
case 0x4010042:
{
SessionInfo *info = SessionInfo_Lookup(clientSession->parentSession);
if(info != NULL && strcmp(info->name, "srv:pm") == 0)
if(info != NULL && kernelVersion < SYSTEM_VERSION(2, 39, 4) && strcmp(info->name, "srv:pm") == 0)
{
res = doPublishToProcessHook(handle, cmdbuf);
skip = true;

View File

@@ -26,10 +26,12 @@
#include "svc/SetWifiEnabled.h"
void SetWifiEnabled(bool enable)
Result SetWifiEnabled(bool enable)
{
if(enable)
CFG11_WIFICNT |= 1;
else
CFG11_WIFICNT &= ~1;
return 0;
}

View File

@@ -50,14 +50,7 @@ Result TranslateHandle(u32 *outKAddr, char *outClassName, Handle handle)
if(obj == NULL)
return 0xD8E007F7; // invalid handle
if(kernelVersion >= SYSTEM_VERSION(2, 46, 0))
{
KClassToken tok;
obj->vtable->GetClassToken(&tok, obj);
name = tok.name;
}
else
name = obj->vtable->GetClassName(obj);
name = classNameOfAutoObject(obj);
if(name == NULL) // shouldn't happen
name = "KAutoObject";

View File

@@ -37,6 +37,7 @@
pop {r1, r2, r12, pc}
.endm
GEN_GETINFO_WRAPPER Handle
GEN_GETINFO_WRAPPER System
GEN_GETINFO_WRAPPER Process
GEN_GETINFO_WRAPPER Thread

View File

@@ -45,7 +45,7 @@
#define DPAD_BUTTONS (BUTTON_LEFT | BUTTON_RIGHT | BUTTON_UP | BUTTON_DOWN)
#define SAFE_MODE (BUTTON_R1 | BUTTON_L1 | BUTTON_A | BUTTON_UP)
#define SINGLE_PAYLOAD_BUTTONS (DPAD_BUTTONS | BUTTON_B | BUTTON_X | BUTTON_Y)
#define SINGLE_PAYLOAD_BUTTONS (BUTTON_B | BUTTON_X | BUTTON_Y)
#define L_PAYLOAD_BUTTONS (BUTTON_R1 | BUTTON_A | BUTTON_START | BUTTON_SELECT)
#define MENU_BUTTONS (DPAD_BUTTONS | BUTTON_A | BUTTON_START)
#define PIN_BUTTONS (BUTTON_A | BUTTON_B | BUTTON_X | BUTTON_Y | DPAD_BUTTONS | BUTTON_START | BUTTON_SELECT)

View File

@@ -152,7 +152,7 @@ void configMenu(bool oldPinStatus, u32 oldPinMode)
"Enable overriding the region and\n"
"language configuration and the usage\n"
"of patched code binaries,\n"
"of patched code binaries, exHeaders,\n"
"IPS code patches and LayeredFS\n"
"for specific games.\n\n"
"Also makes certain DLCs\n"

View File

@@ -49,7 +49,6 @@ bool loadSplash(void)
if(!isTopSplashValid && !isBottomSplashValid) return false;
initScreens();
clearScreens(true);
if(isTopSplashValid) isTopSplashValid = fileRead(fbs[1].top_left, topSplashFile, SCREEN_TOP_FBSIZE) == SCREEN_TOP_FBSIZE;
if(isBottomSplashValid) isBottomSplashValid = fileRead(fbs[1].bottom, bottomSplashFile, SCREEN_BOTTOM_FBSIZE) == SCREEN_BOTTOM_FBSIZE;

View File

@@ -263,7 +263,7 @@ u32 vsprintf(char *buf, const char *fmt, va_list args)
//Integer number formats - set up the flags and "break"
case 'X':
flags |= UPPERCASE;
//Falls through
case 'x':
isHex = true;
break;
@@ -271,7 +271,7 @@ u32 vsprintf(char *buf, const char *fmt, va_list args)
case 'd':
case 'i':
flags |= SIGN;
//Falls through
case 'u':
isHex = false;
break;

View File

@@ -205,13 +205,15 @@ void main(int argc, char **argv, u32 magicWord)
if(splashMode == 1 && loadSplash()) pressed = HID_PAD;
bool autoBootEmu = CONFIG(AUTOBOOTEMU);
if((pressed & (BUTTON_START | BUTTON_L1)) == BUTTON_START)
{
loadHomebrewFirm(0);
pressed = HID_PAD;
}
else if(((pressed & SINGLE_PAYLOAD_BUTTONS) && !(pressed & (BUTTON_L1 | BUTTON_R1 | BUTTON_A))) ||
((pressed & L_PAYLOAD_BUTTONS) && (pressed & BUTTON_L1))) loadHomebrewFirm(pressed);
else if((((pressed & SINGLE_PAYLOAD_BUTTONS) || (!autoBootEmu && (pressed & DPAD_BUTTONS))) && !(pressed & (BUTTON_L1 | BUTTON_R1))) ||
(((pressed & L_PAYLOAD_BUTTONS) || (autoBootEmu && (pressed & DPAD_BUTTONS))) && (pressed & BUTTON_L1))) loadHomebrewFirm(pressed);
if(splashMode == 2) loadSplash();
@@ -235,7 +237,7 @@ void main(int argc, char **argv, u32 magicWord)
/* Else, boot the NAND the user set to autoboot or the opposite one, depending on L,
with their own FIRM */
else firmSource = nandType = (CONFIG(AUTOBOOTEMU) == ((pressed & BUTTON_L1) == BUTTON_L1)) ? FIRMWARE_SYSNAND : FIRMWARE_EMUNAND;
else firmSource = nandType = (autoBootEmu == ((pressed & BUTTON_L1) == BUTTON_L1)) ? FIRMWARE_SYSNAND : FIRMWARE_EMUNAND;
//If we're booting EmuNAND or using EmuNAND FIRM, determine which one from the directional pad buttons, or otherwise from the config
if(nandType == FIRMWARE_EMUNAND || firmSource == FIRMWARE_EMUNAND)

View File

@@ -96,10 +96,12 @@ void initScreens(void)
if(needToSetup)
{
memcpy((void *)ARM11_PARAMETERS_ADDRESS, fbs, sizeof(fbs));
invokeArm11Function(SETUP_FRAMEBUFFERS);
if(!ARESCREENSINITIALIZED)
{
*(vu32 *)ARM11_PARAMETERS_ADDRESS = brightness[MULTICONFIG(BRIGHTNESS)];
memcpy((void *)(ARM11_PARAMETERS_ADDRESS + 4), fbs, sizeof(fbs));
invokeArm11Function(INIT_SCREENS);
//Turn on backlight
@@ -107,10 +109,10 @@ void initScreens(void)
}
else updateBrightness(MULTICONFIG(BRIGHTNESS));
clearScreens(true);
needToSetup = false;
}
clearScreens(false);
clearScreens(true);
swapFramebuffers(false);
}

View File

@@ -54,6 +54,7 @@ struct fb {
typedef enum
{
INIT_SCREENS = 0,
SETUP_FRAMEBUFFERS,
CLEAR_SCREENS,
SWAP_FRAMEBUFFERS,
UPDATE_BRIGHTNESS,

View File

@@ -64,17 +64,20 @@ _start:
load r3, customPath
pathRedir_1:
ldrb r2, [r3], #1
strh r2, [r0], #2
cmp r2, #0
strneh r2, [r0], #2
bne pathRedir_1
sub r0, r0, #2
pathRedir_2:
ldrh r2, [r1], #2
cmp r2, #0x3A ; ':'
bne pathRedir_2
; Skip a slash if there are two after the mountpoint,
; as some games mistakenly have those
ldrh r3, [r1, #2]
cmp r3, #0x2F ; '/'
pathRedir_3:
ldrh r2, [r1], #2
strh r2, [r0], #2
strneh r2, [r0], #2
cmp r2, #0
bne pathRedir_3
ldmfd sp!, {r0-r3}

View File

@@ -11,6 +11,9 @@
#define MAX_SESSIONS 1
#define HBLDR_3DSX_TID (*(vu64 *)0x1FF81100)
u32 config, multiConfig, bootConfig;
bool isN3DS, isSafeMode, isSdMode;
const char CODE_PATH[] = {0x01, 0x00, 0x00, 0x00, 0x2E, 0x63, 0x6F, 0x64, 0x65, 0x00, 0x00, 0x00};
typedef struct
@@ -30,6 +33,28 @@ static u64 g_cached_prog_handle;
static exheader_header g_exheader;
static char g_ret_buf[1024];
static inline void loadCFWInfo(void)
{
s64 out;
if(R_FAILED(svcGetSystemInfo(&out, 0x10000, 3))) svcBreak(USERBREAK_ASSERT);
config = (u32)out;
if(R_FAILED(svcGetSystemInfo(&out, 0x10000, 4))) svcBreak(USERBREAK_ASSERT);
multiConfig = (u32)out;
if(R_FAILED(svcGetSystemInfo(&out, 0x10000, 5))) svcBreak(USERBREAK_ASSERT);
bootConfig = (u32)out;
if(R_FAILED(svcGetSystemInfo(&out, 0x10000, 0x201))) svcBreak(USERBREAK_ASSERT);
isN3DS = (bool)out;
if(R_FAILED(svcGetSystemInfo(&out, 0x10000, 0x202))) svcBreak(USERBREAK_ASSERT);
isSafeMode = (bool)out;
if(R_FAILED(svcGetSystemInfo(&out, 0x10000, 0x203))) svcBreak(USERBREAK_ASSERT);
isSdMode = (bool)out;
IFile file;
if(isSafeMode) fileOpen(&file, ARCHIVE_SDMC, "/", FS_OPEN_READ); //Init SD card if SAFE_MODE is being booted
}
static int lzss_decompress(u8 *end)
{
unsigned int v1; // r1@2
@@ -116,44 +141,47 @@ static Result load_code(u64 progid, prog_addrs_t *shared, u64 prog_handle, int i
u64 size;
u64 total;
archivePath.type = PATH_BINARY;
archivePath.data = &prog_handle;
archivePath.size = 8;
filePath.type = PATH_BINARY;
filePath.data = CODE_PATH;
filePath.size = sizeof(CODE_PATH);
if (R_FAILED(IFile_Open(&file, ARCHIVE_SAVEDATA_AND_CONTENT2, archivePath, filePath, FS_OPEN_READ)))
if(!CONFIG(PATCHGAMES) || !loadTitleCodeSection(progid, (u8 *)shared->text_addr, (u64)shared->total_size << 12))
{
svcBreak(USERBREAK_ASSERT);
}
archivePath.type = PATH_BINARY;
archivePath.data = &prog_handle;
archivePath.size = 8;
// get file size
if (R_FAILED(IFile_GetSize(&file, &size)))
{
IFile_Close(&file);
svcBreak(USERBREAK_ASSERT);
}
filePath.type = PATH_BINARY;
filePath.data = CODE_PATH;
filePath.size = sizeof(CODE_PATH);
if (R_FAILED(IFile_Open(&file, ARCHIVE_SAVEDATA_AND_CONTENT2, archivePath, filePath, FS_OPEN_READ)))
{
svcBreak(USERBREAK_ASSERT);
}
// check size
if (size > (u64)shared->total_size << 12)
{
IFile_Close(&file);
return 0xC900464F;
}
// get file size
if (R_FAILED(IFile_GetSize(&file, &size)))
{
IFile_Close(&file);
svcBreak(USERBREAK_ASSERT);
}
// read code
res = IFile_Read(&file, &total, (void *)shared->text_addr, size);
IFile_Close(&file); // done reading
if (R_FAILED(res))
{
svcBreak(USERBREAK_ASSERT);
}
// check size
if (size > (u64)shared->total_size << 12)
{
IFile_Close(&file);
return 0xC900464F;
}
// decompress
if (is_compressed)
{
lzss_decompress((u8 *)shared->text_addr + size);
// read code
res = IFile_Read(&file, &total, (void *)shared->text_addr, size);
IFile_Close(&file); // done reading
if (R_FAILED(res))
{
svcBreak(USERBREAK_ASSERT);
}
// decompress
if (is_compressed)
{
lzss_decompress((u8 *)shared->text_addr + size);
}
}
u16 progver = g_exheader.codesetinfo.flags.remasterversion[0] | (g_exheader.codesetinfo.flags.remasterversion[1] << 8);
@@ -212,21 +240,31 @@ static Result loader_GetProgramInfo(exheader_header *exheader, u64 prog_handle)
exheader->accessdesc.arm11systemlocalcaps.storageinfo.accessinfo[0] |= 0x480;
// Tweak 3dsx placeholder title exheader
if (nbSection0Modules == 6 && exheader->arm11systemlocalcaps.programid == HBLDR_3DSX_TID)
if (nbSection0Modules == 6)
{
Handle hbldr = 0;
res = HBLDR_Init(&hbldr);
if (R_SUCCEEDED(res))
if(exheader->arm11systemlocalcaps.programid == HBLDR_3DSX_TID)
{
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(4,0,2);
cmdbuf[1] = IPC_Desc_Buffer(sizeof(*exheader), IPC_BUFFER_RW);
cmdbuf[2] = (u32)exheader;
res = svcSendSyncRequest(hbldr);
svcCloseHandle(hbldr);
if (R_SUCCEEDED(res)) {
res = cmdbuf[1];
}
Handle hbldr = 0;
res = HBLDR_Init(&hbldr);
if (R_SUCCEEDED(res))
{
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(4,0,2);
cmdbuf[1] = IPC_Desc_Buffer(sizeof(*exheader), IPC_BUFFER_RW);
cmdbuf[2] = (u32)exheader;
res = svcSendSyncRequest(hbldr);
svcCloseHandle(hbldr);
if (R_SUCCEEDED(res)) {
res = cmdbuf[1];
}
}
}
u64 originalProgId = exheader->arm11systemlocalcaps.programid;
if(CONFIG(PATCHGAMES) && loadTitleExheader(exheader->arm11systemlocalcaps.programid, exheader))
{
exheader->arm11systemlocalcaps.programid = originalProgId;
exheader->accessdesc.arm11systemlocalcaps.programid = originalProgId;
}
}
}
@@ -586,6 +624,8 @@ int main()
svcBreak(USERBREAK_ASSERT);
}
loadCFWInfo();
g_active_handles = 2;
g_cached_prog_handle = 0;
index = 1;

View File

@@ -3,12 +3,8 @@
#include "memory.h"
#include "strings.h"
#include "fsldr.h"
#include "ifile.h"
#include "../build/bundled.h"
static u32 config, multiConfig, bootConfig;
static bool isN3DS, isSafeMode, isSdMode;
static u32 patchMemory(u8 *start, u32 size, const void *pattern, u32 patSize, s32 offset, const void *replace, u32 repSize, u32 count)
{
u32 i;
@@ -32,7 +28,7 @@ static u32 patchMemory(u8 *start, u32 size, const void *pattern, u32 patSize, s3
return i;
}
static Result fileOpen(IFile *file, FS_ArchiveID archiveId, const char *path, int flags)
Result fileOpen(IFile *file, FS_ArchiveID archiveId, const char *path, int flags)
{
FS_Path filePath = {PATH_ASCII, strnlen(path, 255) + 1, path},
archivePath = {PATH_EMPTY, 1, (u8 *)""};
@@ -73,32 +69,6 @@ static u32 checkLumaDir(const char *path)
return dirCheck(archiveId, path) ? archiveId : 0;
}
static inline void loadCFWInfo(void)
{
static bool infoLoaded = false;
s64 out;
if(infoLoaded) return;
if(R_FAILED(svcGetSystemInfo(&out, 0x10000, 3))) svcBreak(USERBREAK_ASSERT);
config = (u32)out;
if(R_FAILED(svcGetSystemInfo(&out, 0x10000, 4))) svcBreak(USERBREAK_ASSERT);
multiConfig = (u32)out;
if(R_FAILED(svcGetSystemInfo(&out, 0x10000, 5))) svcBreak(USERBREAK_ASSERT);
bootConfig = (u32)out;
if(R_FAILED(svcGetSystemInfo(&out, 0x10000, 0x201))) svcBreak(USERBREAK_ASSERT);
isN3DS = (bool)out;
if(R_FAILED(svcGetSystemInfo(&out, 0x10000, 0x202))) svcBreak(USERBREAK_ASSERT);
isSafeMode = (bool)out;
if(R_FAILED(svcGetSystemInfo(&out, 0x10000, 0x203))) svcBreak(USERBREAK_ASSERT);
isSdMode = (bool)out;
IFile file;
if(isSafeMode) fileOpen(&file, ARCHIVE_SDMC, "/", FS_OPEN_READ); //Init SD card if SAFE_MODE is being booted
infoLoaded = true;
}
static inline bool secureInfoExists(void)
{
static bool exists = false;
@@ -353,7 +323,7 @@ exit:
return ret;
}
static inline bool loadTitleCodeSection(u64 progId, u8 *code, u32 size)
bool loadTitleCodeSection(u64 progId, u8 *code, u32 size)
{
/* Here we look for "/luma/titles/[u64 titleID in hex, uppercase]/code.bin"
If it exists it should be a decrypted and decompressed binary code file */
@@ -363,22 +333,60 @@ static inline bool loadTitleCodeSection(u64 progId, u8 *code, u32 size)
IFile file;
if(!openLumaFile(&file, path)) return true;
if(!openLumaFile(&file, path)) return false;
bool ret;
u64 fileSize;
if(R_FAILED(IFile_GetSize(&file, &fileSize)) || fileSize > size) ret = false;
if(R_FAILED(IFile_GetSize(&file, &fileSize)) || fileSize > size) goto error;
else
{
u64 total;
ret = R_SUCCEEDED(IFile_Read(&file, &total, code, fileSize)) && total == fileSize;
if(R_FAILED(IFile_Read(&file, &total, code, fileSize)) || total != fileSize) goto error;
}
IFile_Close(&file);
return ret;
return true;
error:
IFile_Close(&file);
svcBreak(USERBREAK_ASSERT);
while(true);
}
bool loadTitleExheader(u64 progId, exheader_header *exheader)
{
/* Here we look for "/luma/titles/[u64 titleID in hex, uppercase]/exheader.bin"
If it exists it should be a decrypted exheader */
char path[] = "/luma/titles/0000000000000000/exheader.bin";
progIdToStr(path + 28, progId);
IFile file;
if(!openLumaFile(&file, path)) return false;
u64 fileSize;
if(R_FAILED(IFile_GetSize(&file, &fileSize)) || fileSize != sizeof(exheader_header)) goto error;
else
{
u64 total;
if(R_FAILED(IFile_Read(&file, &total, exheader, fileSize)) || total != fileSize) goto error;
}
IFile_Close(&file);
return true;
error:
IFile_Close(&file);
svcBreak(USERBREAK_ASSERT);
while(true);
}
static inline bool loadTitleLocaleConfig(u64 progId, u8 *mask, u8 *regionId, u8 *languageId, u8 *countryId, u8 *stateId)
@@ -570,8 +578,6 @@ static inline bool patchLayeredFs(u64 progId, u8 *code, u32 size, u32 textSize,
void patchCode(u64 progId, u16 progVer, u8 *code, u32 size, u32 textSize, u32 roSize, u32 dataSize, u32 roAddress, u32 dataAddress)
{
loadCFWInfo();
if(progId == 0x0004003000008F02LL || //USA Home Menu
progId == 0x0004003000008202LL || //JPN Home Menu
progId == 0x0004003000009802LL || //EUR Home Menu
@@ -873,8 +879,7 @@ void patchCode(u64 progId, u16 progVer, u8 *code, u32 size, u32 textSize, u32 ro
if(CONFIG(PATCHGAMES))
{
if(!loadTitleCodeSection(progId, code, size) ||
!applyCodeIpsPatch(progId, code, size)) goto error;
if(!applyCodeIpsPatch(progId, code, size)) goto error;
if((u32)((progId >> 0x20) & 0xFFFFFFEDULL) == 0x00040000)
{
@@ -894,5 +899,4 @@ void patchCode(u64 progId, u16 progVer, u8 *code, u32 size, u32 textSize, u32 ro
error:
svcBreak(USERBREAK_ASSERT);
while(true);
}

View File

@@ -1,6 +1,8 @@
#pragma once
#include <3ds/types.h>
#include "exheader.h"
#include "ifile.h"
#define MAKE_BRANCH(src,dst) (0xEA000000 | ((u32)((((u8 *)(dst) - (u8 *)(src)) >> 2) - 2) & 0xFFFFFF))
#define MAKE_BRANCH_LINK(src,dst) (0xEB000000 | ((u32)((((u8 *)(dst) - (u8 *)(src)) >> 2) - 2) & 0xFFFFFF))
@@ -35,4 +37,10 @@ enum singleOptions
DISABLEARM11EXCHANDLERS
};
extern u32 config, multiConfig, bootConfig;
extern bool isN3DS, isSafeMode, isSdMode;
void patchCode(u64 progId, u16 progVer, u8 *code, u32 size, u32 textSize, u32 roSize, u32 dataSize, u32 roAddress, u32 dataAddress);
Result fileOpen(IFile *file, FS_ArchiveID archiveId, const char *path, int flags);
bool loadTitleCodeSection(u64 progId, u8 *code, u32 size);
bool loadTitleExheader(u64 progId, exheader_header *exheader);

View File

@@ -63,6 +63,7 @@
#define COLOR_TITLE RGB565(0x00, 0x26, 0x1F)
#define COLOR_WHITE RGB565(0x1F, 0x3F, 0x1F)
#define COLOR_RED RGB565(0x1F, 0x00, 0x00)
#define COLOR_GREEN RGB565(0x00, 0x1F, 0x00)
#define COLOR_BLACK RGB565(0x00, 0x00, 0x00)
#define DRAW_MAX_FORMATTED_STRING_SIZE 512

View File

@@ -0,0 +1,37 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
* * Requiring preservation of specified reasonable legal notices or
* author attributions in that material or in the Appropriate Legal
* Notices displayed by works containing it.
* * Prohibiting misrepresentation of the origin of that material,
* or requiring that modified versions of such material be marked in
* reasonable ways as different from the original version.
*/
#pragma once
#include <3ds.h>
Handle mcuhwcHandle;
Result mcuInit(void);
Result mcuExit(void);
Result mcuReadRegister(u8 reg, u8* data, u32 size);
Result mcuWriteRegister(u8 reg, u8* data, u32 size);
Result mcuGetLEDState(u8* out);

View File

@@ -35,3 +35,5 @@ extern Menu rosalinaMenu;
void RosalinaMenu_TakeScreenshot(void);
void RosalinaMenu_ShowCredits(void);
void RosalinaMenu_ProcessList(void);
void RosalinaMenu_PowerOff(void);
void RosalinaMenu_Reboot(void);

View File

@@ -35,5 +35,3 @@ void MiscellaneousMenu_SwitchBoot3dsxTargetTitle(void);
void MiscellaneousMenu_ChangeMenuCombo(void);
void MiscellaneousMenu_SaveSettings(void);
void MiscellaneousMenu_InputRedirection(void);
void MiscellaneousMenu_PowerOff(void);
void MiscellaneousMenu_Reboot(void);

View File

@@ -0,0 +1,35 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
* * Requiring preservation of specified reasonable legal notices or
* author attributions in that material or in the Appropriate Legal
* Notices displayed by works containing it.
* * Prohibiting misrepresentation of the origin of that material,
* or requiring that modified versions of such material be marked in
* reasonable ways as different from the original version.
*/
#pragma once
#include <3ds/types.h>
#include "menu.h"
extern Menu sysconfigMenu;
void SysConfigMenu_ToggleLEDs(void);
void SysConfigMenu_ToggleWireless(void);

View File

@@ -1,7 +1,7 @@
BasicInfo:
Title : rosalina
CompanyCode : "00"
ProductCode : 0828builder
ProductCode : lennybuilder
ContentType : Application
Logo : None
@@ -47,13 +47,13 @@ AccessControlInfo:
# We're using the global custom bit31 mapping
SystemCallAccess:
# The kernel extension removes svc perms checks, so...
SendSyncRequest2: 47 # CustomBackdoor
UnmapProcessMemory: 114
# The kernel extension removes svc perms checks, so below is just to avoid a makerom error
Backdoor: 123
KernelSetState: 124
InterruptNumbers:
ServiceAccessControl:
- srv:pm
- fs:USER # Not strictly needed as rosalina has access to everything, it's rather to avoid a makerom warning
FileSystemAccess:
- DirectSdmc
- CtrNandRw

View File

@@ -29,6 +29,8 @@
#include "draw.h"
#include "menu.h"
#include "memory.h"
#include "fmt.h"
#include "ifile.h"
static inline void assertSuccess(Result res)
{
@@ -37,13 +39,13 @@ static inline void assertSuccess(Result res)
}
static MyThread errDispThread;
static u8 ALIGN(8) errDispThreadStack[THREAD_STACK_SIZE];
static u8 ALIGN(8) errDispThreadStack[0x2000];
static char userString[0x100 + 1] = {0};
MyThread *errDispCreateThread(void)
{
if(R_FAILED(MyThread_Create(&errDispThread, errDispThreadMain, errDispThreadStack, THREAD_STACK_SIZE, 0x18, CORE_SYSTEM)))
if(R_FAILED(MyThread_Create(&errDispThread, errDispThreadMain, errDispThreadStack, 0x2000, 0x18, CORE_SYSTEM)))
svcBreak(USERBREAK_PANIC);
return &errDispThread;
}
@@ -53,12 +55,14 @@ static inline u32 ERRF_DisplayRegisterValue(u32 posX, u32 posY, const char *name
return Draw_DrawFormattedString(posX, posY, COLOR_WHITE, "%-9s %08x", name, value);
}
void ERRF_DisplayError(ERRF_FatalErrInfo *info)
static inline int ERRF_FormatRegisterValue(char *out, const char *name, u32 value)
{
Draw_Lock();
u32 posY = Draw_DrawString(10, 10, COLOR_RED, userString[0] == 0 ? "An error occurred (ErrDisp)" : userString);
return sprintf(out, "%-9s %08x", name, value);
}
static int ERRF_FormatError(char *out, ERRF_FatalErrInfo *info)
{
char *outStart = out;
static const char *types[] = {
"generic", "corrupted", "card removed", "exception", "result failure", "logged", "invalid"
};
@@ -68,25 +72,23 @@ void ERRF_DisplayError(ERRF_FatalErrInfo *info)
};
const char *type = (u32)info->type > (u32)ERRF_ERRTYPE_LOGGED ? types[6] : types[(u32)info->type];
posY = posY < 30 ? 30 : posY;
if(info->type == ERRF_ERRTYPE_EXCEPTION)
{
const char *exceptionType = (u32)info->data.exception_data.excep.type > (u32)ERRF_EXCEPTION_VFP ?
exceptionTypes[4] : exceptionTypes[(u32)info->data.exception_data.excep.type];
Draw_DrawFormattedString(10, posY, COLOR_WHITE, "Error type: exception (%s)", exceptionType);
out += sprintf(out, "Error type: exception (%s)\n", exceptionType);
}
else
Draw_DrawFormattedString(10, posY, COLOR_WHITE, "Error type: %s", type);
out += sprintf(out, "Error type: %s\n", type);
if(info->type != ERRF_ERRTYPE_CARD_REMOVED)
{
Handle processHandle;
Result res;
posY += SPACING_Y;
posY = Draw_DrawFormattedString(10, posY + SPACING_Y, COLOR_WHITE, "Process ID: %u", info->procId);
out += sprintf(out, "\nProcess ID: %u\n", info->procId);
res = svcOpenProcess(&processHandle, info->procId);
if(R_SUCCEEDED(res))
@@ -96,11 +98,11 @@ void ERRF_DisplayError(ERRF_FatalErrInfo *info)
svcGetProcessInfo((s64 *)name, processHandle, 0x10000);
svcGetProcessInfo((s64 *)&titleId, processHandle, 0x10001);
svcCloseHandle(processHandle);
posY = Draw_DrawFormattedString(10, posY + SPACING_Y, COLOR_WHITE, "Process name: %s", name);
posY = Draw_DrawFormattedString(10, posY + SPACING_Y, COLOR_WHITE, "Process title ID: 0x%016llx", titleId);
out += sprintf(out, "Process name: %s\n", name);
out += sprintf(out, "Process title ID: 0x%016llx\n", titleId);
}
posY += SPACING_Y;
out += sprintf(out, "\n");
}
if(info->type == ERRF_ERRTYPE_EXCEPTION)
@@ -113,33 +115,43 @@ void ERRF_DisplayError(ERRF_FatalErrInfo *info)
u32 *regs = (u32 *)(&info->data.exception_data.regs);
for(u32 i = 0; i < 17; i += 2)
{
posY = ERRF_DisplayRegisterValue(10, posY + SPACING_Y, registerNames[i], regs[i]);
out += ERRF_FormatRegisterValue(out, registerNames[i], regs[i]);
if(i != 16)
ERRF_DisplayRegisterValue(10 + 28 * SPACING_X, posY, registerNames[i + 1], i == 16 ? regs[20] : regs[i + 1]);
{
out += sprintf(out, " ");
out += ERRF_FormatRegisterValue(out, registerNames[i + 1], i == 16 ? regs[20] : regs[i + 1]);
out += sprintf(out, "\n");
}
}
if(info->data.exception_data.excep.type == ERRF_EXCEPTION_PREFETCH_ABORT
|| info->data.exception_data.excep.type == ERRF_EXCEPTION_DATA_ABORT)
{
ERRF_DisplayRegisterValue(10 + 28 * SPACING_X, posY, "far", info->data.exception_data.excep.far);
posY = ERRF_DisplayRegisterValue(10, posY + SPACING_Y, "fsr", info->data.exception_data.excep.fsr);
out += sprintf(out, " ");
out += ERRF_FormatRegisterValue(out, "far", info->data.exception_data.excep.far);
out += sprintf(out, "\n");
out += ERRF_FormatRegisterValue(out, "fsr", info->data.exception_data.excep.fsr);
}
else if(info->data.exception_data.excep.type == ERRF_EXCEPTION_VFP)
{
ERRF_DisplayRegisterValue(10 + 28 * SPACING_X, posY, "fpexc", info->data.exception_data.excep.fpexc);
posY = ERRF_DisplayRegisterValue(10, posY + SPACING_Y, "fpinst", info->data.exception_data.excep.fpinst);
ERRF_DisplayRegisterValue(10 + 28 * SPACING_X, posY, "fpinst2", info->data.exception_data.excep.fpinst2);
out += sprintf(out, " ");
out += ERRF_FormatRegisterValue(out, "fpexc", info->data.exception_data.excep.fpexc);
out += sprintf(out, "\n");
out += ERRF_FormatRegisterValue(out, "fpinst", info->data.exception_data.excep.fpinst);
out += sprintf(out, " ");
out += ERRF_FormatRegisterValue(out, "fpinst2", info->data.exception_data.excep.fpinst2);
out += sprintf(out, "\n");
}
}
out += sprintf(out, "\n");
}
else if(info->type != ERRF_ERRTYPE_CARD_REMOVED)
{
if(info->type != ERRF_ERRTYPE_FAILURE)
posY = Draw_DrawFormattedString(10, posY + SPACING_Y, COLOR_WHITE, "Address: 0x%08x", info->pcAddr);
out += sprintf(out, "Address: 0x%08x\n", info->pcAddr);
posY = Draw_DrawFormattedString(10, posY + SPACING_Y, COLOR_WHITE, "Error code: 0x%08x", info->resCode);
out += sprintf(out, "Error code: 0x%08x\n", info->resCode);
}
const char *desc;
@@ -160,16 +172,70 @@ void ERRF_DisplayError(ERRF_FatalErrInfo *info)
break;
}
posY += SPACING_Y;
if(desc[0] != 0)
posY = Draw_DrawString(10, posY + SPACING_Y, COLOR_WHITE, desc) + SPACING_Y;
posY = Draw_DrawString(10, posY + SPACING_Y, COLOR_WHITE, "Press any button to reboot");
out += sprintf(out, "\n%s\n", desc);
out += sprintf(out, "\n");
return out - outStart;
}
static void ERRF_DisplayError(ERRF_FatalErrInfo *info)
{
Draw_Lock();
u32 posY = Draw_DrawString(10, 10, COLOR_RED, userString[0] == 0 ? "An error occurred (ErrDisp)" : userString);
char buf[0x400];
ERRF_FormatError(buf, info);
posY = posY < 30 ? 30 : posY;
posY = Draw_DrawString(10, posY, COLOR_WHITE, buf);
posY = Draw_DrawString(10, posY + SPACING_Y, COLOR_WHITE, "Press any button to reboot.");
Draw_FlushFramebuffer();
Draw_Unlock();
}
void ERRF_HandleCommands(void)
static Result ERRF_SaveErrorToFile(ERRF_FatalErrInfo *info)
{
char buf[0x400];
FS_ArchiveID archiveId;
s64 out;
u64 size, total;
bool isSdMode;
int n = 0;
Result res = 0;
IFile file;
n = ERRF_FormatError(buf, info);
n += sprintf(buf + n, "-------------------------------------\n\n");
if(R_FAILED(svcGetSystemInfo(&out, 0x10000, 0x203))) svcBreak(USERBREAK_ASSERT);
isSdMode = (bool)out;
archiveId = isSdMode ? ARCHIVE_SDMC : ARCHIVE_NAND_RW;
res = IFile_Open(&file, archiveId, fsMakePath(PATH_EMPTY, ""), fsMakePath(PATH_ASCII, "/luma/errdisp.txt"), FS_OPEN_WRITE | FS_OPEN_CREATE);
if(R_FAILED(res))
return res;
res = IFile_GetSize(&file, &size);
if(R_FAILED(res))
{
IFile_Close(&file);
return res;
}
file.pos = size;
res = IFile_Write(&file, &total, buf, (u32)n, 0);
IFile_Close(&file);
return res;
}
static void ERRF_HandleCommands(void)
{
u32 *cmdbuf = getThreadCommandBuffer();
@@ -178,27 +244,30 @@ void ERRF_HandleCommands(void)
case 1: // Throw
{
ERRF_FatalErrInfo *info = (ERRF_FatalErrInfo *)(cmdbuf + 1);
menuEnter();
if(info->type != ERRF_ERRTYPE_LOGGED || info->procId == 0 || R_FAILED(ERRF_SaveErrorToFile(info)))
{
menuEnter();
Draw_Lock();
Draw_ClearFramebuffer();
Draw_FlushFramebuffer();
Draw_Lock();
Draw_ClearFramebuffer();
Draw_FlushFramebuffer();
ERRF_DisplayError(info);
ERRF_DisplayError(info);
/*
If we ever wanted to return:
draw_unlock();
menuLeave();
/*
If we ever wanted to return:
Draw_Unlock();
menuLeave();
but we don't
*/
waitInput();
svcKernelSetState(7);
__builtin_unreachable();
}
cmdbuf[0] = 0x10040;
cmdbuf[1] = 0;
but we don't
*/
waitInput();
svcKernelSetState(7);
__builtin_unreachable();
break;
}

View File

@@ -259,7 +259,7 @@ int vsprintf(char *buf, const char *fmt, va_list args)
//Integer number formats - set up the flags and "break"
case 'X':
flags |= UPPERCASE;
//Falls through
case 'x':
isHex = true;
break;
@@ -267,7 +267,7 @@ int vsprintf(char *buf, const char *fmt, va_list args)
case 'd':
case 'i':
flags |= SIGN;
//Falls through
case 'u':
isHex = false;
break;

View File

@@ -416,6 +416,8 @@ int GDB_SendStopReply(GDBContext *ctx, const DebugEventInfo *info)
default:
break;
}
break;
}
case DBGEVENT_SYSCALL_IN:

View File

@@ -25,6 +25,8 @@
*/
#include "gdb/watchpoints.h"
#include "csvc.h"
#define _REENT_ONLY
#include <errno.h>
@@ -53,6 +55,92 @@ typedef struct WatchpointManager
static WatchpointManager manager;
static void K_EnableMonitorModeDebugging(void)
{
__asm__ __volatile__("cpsid aif");
u32 DSCR;
__asm__ __volatile__("mrc p15, 0, %[val], c0, c1, 0" : [val] "=r" (DSCR));
DSCR |= 0x8000;
__asm__ __volatile__("mcr p14, 0, %[val], c0, c1, 0" :: [val] "r" (DSCR));
}
static void K_DisableWatchpoint(u32 id)
{
u32 control;
__asm__ __volatile__("cpsid aif");
if(id == 0)
{
// WCR0
__asm__ __volatile__("mrc p14, 0, %[val], c0, c0, 7" : [val] "=r" (control));
control &= ~1;
__asm__ __volatile__("mcr p14, 0, %[val], c0, c0, 7" :: [val] "r" (control));
// BCR4
__asm__ __volatile__("mrc p14, 0, %[val], c0, c4, 5" : [val] "=r" (control));
control &= ~1;
__asm__ __volatile__("mcr p14, 0, %[val], c0, c4, 5" :: [val] "r" (control));
}
else if(id == 1)
{
// WCR1
__asm__ __volatile__("mrc p14, 0, %[val], c0, c1, 7" : [val] "=r" (control));
control &= ~1;
__asm__ __volatile__("mcr p14, 0, %[val], c0, c1, 7" :: [val] "r" (control));
// BCR5
__asm__ __volatile__("mrc p14, 0, %[val], c0, c5, 5" : [val] "=r" (control));
control &= ~1;
__asm__ __volatile__("mcr p14, 0, %[val], c0, c5, 5" :: [val] "r" (control));
}
}
static void K_SetWatchpoint0WithContextId(u32 DVA, u32 WCR, u32 contextId)
{
// http://infocenter.arm.com/help/topic/com.arm.doc.ddi0360f/CEGCFFDF.html
u32 BCR =
(1 << 21) | /* compare with context ID */
(1 << 20) | /* linked (with a WRP in our case) */
(0xf << 5) | /* byte address select, +0 to +3 as mandated when linking with a WRP */
(3 << 1) | /* either privileged modes or user mode, as mandated when linking with a WRP */
(1 << 0) ; /* enabled */
__asm__ __volatile__("cpsid aif");
K_DisableWatchpoint(0);
__asm__ __volatile__("mcr p14, 0, %[val], c0, c0, 6" :: [val] "r" (DVA));
__asm__ __volatile__("mcr p14, 0, %[val], c0, c4, 4" :: [val] "r" (contextId));
__asm__ __volatile__("mcr p14, 0, %[val], c0, c0, 7" :: [val] "r" (WCR));
__asm__ __volatile__("mcr p14, 0, %[val], c0, c4, 5" :: [val] "r" (BCR));
__asm__ __volatile__("mcr p15, 0, %[val], c7, c10, 5" :: [val] "r" (0) : "memory"); // DMB
}
static void K_SetWatchpoint1WithContextId(u32 DVA, u32 WCR, u32 contextId)
{
// http://infocenter.arm.com/help/topic/com.arm.doc.ddi0360f/CEGCFFDF.html
u32 BCR =
(1 << 21) | /* compare with context ID */
(1 << 20) | /* linked (with a WRP in our case) */
(0xf << 5) | /* byte address select, +0 to +3 as mandated when linking with a WRP */
(3 << 1) | /* either privileged modes or user mode, as mandated when linking with a WRP */
(1 << 0) ; /* enabled */
__asm__ __volatile__("cpsid aif");
K_DisableWatchpoint(1);
__asm__ __volatile__("mcr p14, 0, %[val], c0, c1, 6" :: [val] "r" (DVA));
__asm__ __volatile__("mcr p14, 0, %[val], c0, c5, 4" :: [val] "r" (contextId));
__asm__ __volatile__("mcr p14, 0, %[val], c0, c1, 7" :: [val] "r" (WCR));
__asm__ __volatile__("mcr p14, 0, %[val], c0, c5, 5" :: [val] "r" (BCR));
__asm__ __volatile__("mcr p15, 0, %[val], c7, c10, 5" :: [val] "r" (0) : "memory"); // DMB
}
void GDB_ResetWatchpoints(void)
{
static bool lockInitialized = false;
@@ -63,11 +151,9 @@ void GDB_ResetWatchpoints(void)
}
RecursiveLock_Lock(&watchpointManagerLock);
svcSetHardwareBreakPoint(4, 0, 0);
svcSetHardwareBreakPoint(0x100, 0, 0);
svcSetHardwareBreakPoint(5, 0, 0);
svcSetHardwareBreakPoint(0x101, 0, 0);
svcCustomBackdoor(K_EnableMonitorModeDebugging);
svcCustomBackdoor(K_DisableWatchpoint, 0);
svcCustomBackdoor(K_DisableWatchpoint, 1);
memset(&manager, 0, sizeof(WatchpointManager));
@@ -93,26 +179,20 @@ int GDB_AddWatchpoint(GDBContext *ctx, u32 address, u32 size, WatchpointKind kin
u32 id = manager.watchpoints[0].kind == WATCHPOINT_DISABLED ? 0 : 1;
u32 selectMask = ((1 << size) - 1) << offset;
u32 BCR = (1 << 21) | /* compare with context ID */
(1 << 20) | /* linked (with a WRP in our case) */
(0xf << 5) | /* byte address select, +0 to +3 as mandated when linking with a WRP */
(3 << 1) | /* either privileged modes or user mode, as mandated when linking with a WRP */
(1 << 0) ; /* enabled */
u32 WCR = (1 << 20) | /* linked */
((4 + id) << 16) | /* ID of the linked BRP */
(selectMask << 5) | /* byte address select */
((u32)kind << 3) | /* kind */
(2 << 1) | /* user mode only */
(1 << 0) ; /* enabled */
s64 out;
Result r = svcSetHardwareBreakPoint(0x100 | id, WCR, address & ~3);
if(R_SUCCEEDED(r))
r = svcSetHardwareBreakPoint(4 + id, BCR, (u32)ctx->debug);
Result r = svcGetHandleInfo(&out, ctx->debug, 0x10000); // context ID
if(R_SUCCEEDED(r))
{
svcCustomBackdoor(id == 0 ? K_SetWatchpoint0WithContextId : K_SetWatchpoint1WithContextId, address, WCR, (u32)out);
Watchpoint *watchpoint = &manager.watchpoints[id];
manager.total++;
watchpoint->address = address;
@@ -144,8 +224,7 @@ int GDB_RemoveWatchpoint(GDBContext *ctx, u32 address, WatchpointKind kind)
}
else
{
svcSetHardwareBreakPoint(4 + id, 0, 0);
svcSetHardwareBreakPoint(0x100 | id, 0, 0);
svcCustomBackdoor(K_DisableWatchpoint, id);
memset(&manager.watchpoints[id], 0, sizeof(Watchpoint));
manager.total--;

View File

@@ -280,6 +280,8 @@ static void HBLDR_HandleCommands(void)
localcaps1->priority = 0;
memset(localcaps0->resourcelimitdescriptor, 0, 0x10);
memset(localcaps1->resourcelimitdescriptor, 0, 0x10);
localcaps0->resourcelimitdescriptor[0] = 0x9E;
localcaps0->resourcelimitdescriptor[1] = 0x9E;
memset(localcaps0->storageinfo.accessinfo, 0xFF, 7);
memset(localcaps1->storageinfo.accessinfo, 0xFF, 7);
memcpy(localcaps0->serviceaccesscontrol, serviceList, sizeof(serviceList));

View File

@@ -0,0 +1,68 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
* * Requiring preservation of specified reasonable legal notices or
* author attributions in that material or in the Appropriate Legal
* Notices displayed by works containing it.
* * Prohibiting misrepresentation of the origin of that material,
* or requiring that modified versions of such material be marked in
* reasonable ways as different from the original version.
*/
#include "mcu.h"
Result mcuInit(void)
{
return srvGetServiceHandle(&mcuhwcHandle, "mcu::HWC");
}
Result mcuExit(void)
{
return svcCloseHandle(mcuhwcHandle);
}
Result mcuReadRegister(u8 reg, u8* data, u32 size)
{
u32* ipc = getThreadCommandBuffer();
ipc[0] = 0x10082;
ipc[1] = reg;
ipc[2] = size;
ipc[3] = size << 4 | 0xC;
ipc[4] = (u32)data;
Result ret = svcSendSyncRequest(mcuhwcHandle);
if(ret < 0) return ret;
return ipc[1];
}
Result mcuWriteRegister(u8 reg, u8* data, u32 size)
{
u32* ipc = getThreadCommandBuffer();
ipc[0] = 0x20082;
ipc[1] = reg;
ipc[2] = size;
ipc[3] = size << 4 | 0xA;
ipc[4] = (u32)data;
Result ret = svcSendSyncRequest(mcuhwcHandle);
if(ret < 0) return ret;
return ipc[1];
}
Result mcuGetLEDState(u8* out)
{
return mcuReadRegister(0x28, out, 1);
}

View File

@@ -28,6 +28,7 @@
#include "menu.h"
#include "draw.h"
#include "fmt.h"
#include "mcu.h"
#include "memory.h"
#include "ifile.h"
#include "menus.h"
@@ -125,11 +126,10 @@ u32 waitCombo(void)
static Result _MCUHWC_GetBatteryLevel(u8 *out)
{
#define TRY(expr) if(R_FAILED(res = (expr))) { svcCloseHandle(mcuhwcHandle); return res; }
#define TRY(expr) if(R_FAILED(res = (expr))) { mcuExit(); return res; }
Result res;
Handle mcuhwcHandle;
TRY(srvGetServiceHandle(&mcuhwcHandle, "mcu::HWC"));
TRY(mcuInit());
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x50000;

View File

@@ -33,20 +33,24 @@
#include "menus/n3ds.h"
#include "menus/debugger.h"
#include "menus/miscellaneous.h"
#include "menus/sysconfig.h"
#include "ifile.h"
#include "memory.h"
#include "fmt.h"
Menu rosalinaMenu = {
"Rosalina menu",
.nbItems = 7,
.nbItems = 10,
{
{ "Process list", METHOD, .method = &RosalinaMenu_ProcessList },
{ "Process patches menu...", MENU, .menu = &processPatchesMenu },
{ "Take screenshot (slow!)", METHOD, .method = &RosalinaMenu_TakeScreenshot },
{ "New 3DS menu...", MENU, .menu = &N3DSMenu },
{ "Debugger options...", MENU, .menu = &debuggerMenu },
{ "System configuration...", MENU, .menu = &sysconfigMenu },
{ "Miscellaneous options...", MENU, .menu = &miscellaneousMenu },
{ "Power off", METHOD, .method = &RosalinaMenu_PowerOff },
{ "Reboot", METHOD, .method = &RosalinaMenu_Reboot },
{ "Credits", METHOD, .method = &RosalinaMenu_ShowCredits }
}
};
@@ -85,6 +89,59 @@ void RosalinaMenu_ShowCredits(void)
while(!(waitInput() & BUTTON_B) && !terminationRequest);
}
void RosalinaMenu_Reboot(void)
{
Draw_Lock();
Draw_ClearFramebuffer();
Draw_FlushFramebuffer();
Draw_Unlock();
do
{
Draw_Lock();
Draw_DrawString(10, 10, COLOR_TITLE, "Rosalina menu");
Draw_DrawString(10, 30, COLOR_WHITE, "Press A to reboot, press B to go back.");
Draw_FlushFramebuffer();
Draw_Unlock();
u32 pressed = waitInputWithTimeout(1000);
if(pressed & BUTTON_A)
svcKernelSetState(7);
else if(pressed & BUTTON_B)
return;
}
while(!terminationRequest);
}
void RosalinaMenu_PowerOff(void) // Soft shutdown.
{
Draw_Lock();
Draw_ClearFramebuffer();
Draw_FlushFramebuffer();
Draw_Unlock();
do
{
Draw_Lock();
Draw_DrawString(10, 10, COLOR_TITLE, "Rosalina menu");
Draw_DrawString(10, 30, COLOR_WHITE, "Press A to power off, press B to go back.");
Draw_FlushFramebuffer();
Draw_Unlock();
u32 pressed = waitInputWithTimeout(1000);
if(pressed & BUTTON_A)
{
menuLeave();
srvPublishToSubscriber(0x203, 0);
}
else if(pressed & BUTTON_B)
return;
}
while(!terminationRequest);
}
extern u8 framebufferCache[FB_BOTTOM_SIZE];
void RosalinaMenu_TakeScreenshot(void)
{

View File

@@ -27,6 +27,7 @@
#include <3ds.h>
#include "menus/miscellaneous.h"
#include "input_redirection.h"
#include "mcu.h"
#include "memory.h"
#include "draw.h"
#include "hbloader.h"
@@ -37,14 +38,12 @@
Menu miscellaneousMenu = {
"Miscellaneous options menu",
.nbItems = 6,
.nbItems = 4,
{
{ "Switch the hb. title to the current app.", METHOD, .method = &MiscellaneousMenu_SwitchBoot3dsxTargetTitle },
{ "Change the menu combo", METHOD, .method = MiscellaneousMenu_ChangeMenuCombo },
{ "Save settings", METHOD, .method = &MiscellaneousMenu_SaveSettings },
{ "Start InputRedirection", METHOD, .method = &MiscellaneousMenu_InputRedirection },
{ "Power off", METHOD, .method = &MiscellaneousMenu_PowerOff },
{ "Reboot", METHOD, .method = &MiscellaneousMenu_Reboot },
{ "Save settings", METHOD, .method = &MiscellaneousMenu_SaveSettings },
}
};
@@ -129,6 +128,7 @@ static void MiscellaneousMenu_ConvertComboToString(char *out, u32 combo)
out[-1] = 0;
}
void MiscellaneousMenu_ChangeMenuCombo(void)
{
char comboStrOrig[64], comboStr[64];
@@ -255,7 +255,7 @@ void MiscellaneousMenu_InputRedirection(void)
if(res != 0)
sprintf(buf, "Failed to stop InputRedirection (0x%08x).", (u32)res);
else
miscellaneousMenu.items[3].title = "Start InputRedirection";
miscellaneousMenu.items[2].title = "Start InputRedirection";
}
else
{
@@ -311,7 +311,7 @@ void MiscellaneousMenu_InputRedirection(void)
if(res != 0)
sprintf(buf, "Starting InputRedirection... failed (0x%08x).", (u32)res);
else
miscellaneousMenu.items[3].title = "Stop InputRedirection";
miscellaneousMenu.items[2].title = "Stop InputRedirection";
done = true;
}
@@ -334,56 +334,3 @@ void MiscellaneousMenu_InputRedirection(void)
}
while(!(waitInput() & BUTTON_B) && !terminationRequest);
}
void MiscellaneousMenu_Reboot(void)
{
Draw_Lock();
Draw_ClearFramebuffer();
Draw_FlushFramebuffer();
Draw_Unlock();
do
{
Draw_Lock();
Draw_DrawString(10, 10, COLOR_TITLE, "Miscellaneous options menu");
Draw_DrawString(10, 30, COLOR_WHITE, "Press A to reboot, press B to go back.");
Draw_FlushFramebuffer();
Draw_Unlock();
u32 pressed = waitInputWithTimeout(1000);
if(pressed & BUTTON_A)
svcKernelSetState(7);
else if(pressed & BUTTON_B)
return;
}
while(!terminationRequest);
}
void MiscellaneousMenu_PowerOff(void) // Soft shutdown.
{
Draw_Lock();
Draw_ClearFramebuffer();
Draw_FlushFramebuffer();
Draw_Unlock();
do
{
Draw_Lock();
Draw_DrawString(10, 10, COLOR_TITLE, "Miscellaneous options menu");
Draw_DrawString(10, 30, COLOR_WHITE, "Press A to power off, press B to go back.");
Draw_FlushFramebuffer();
Draw_Unlock();
u32 pressed = waitInputWithTimeout(1000);
if(pressed & BUTTON_A)
{
menuLeave();
srvPublishToSubscriber(0x203, 0);
}
else if(pressed & BUTTON_B)
return;
}
while(!terminationRequest);
}

View File

@@ -0,0 +1,112 @@
/*
* This file is part of Luma3DS
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
* * Requiring preservation of specified reasonable legal notices or
* author attributions in that material or in the Appropriate Legal
* Notices displayed by works containing it.
* * Prohibiting misrepresentation of the origin of that material,
* or requiring that modified versions of such material be marked in
* reasonable ways as different from the original version.
*/
#include <3ds.h>
#include "menus/sysconfig.h"
#include "mcu.h"
#include "memory.h"
#include "draw.h"
#include "fmt.h"
#include "utils.h"
#include "ifile.h"
Menu sysconfigMenu = {
"System configuration menu",
.nbItems = 2,
{
{ "Toggle LEDs", METHOD, .method = &SysConfigMenu_ToggleLEDs },
{ "Toggle Wireless", METHOD, .method = &SysConfigMenu_ToggleWireless },
}
};
void SysConfigMenu_ToggleLEDs(void)
{
Draw_Lock();
Draw_ClearFramebuffer();
Draw_FlushFramebuffer();
Draw_Unlock();
do
{
Draw_Lock();
Draw_DrawString(10, 10, COLOR_TITLE, "System configuration menu");
Draw_DrawString(10, 30, COLOR_WHITE, "Press A to toggle, press B to go back.");
Draw_DrawString(10, 50, COLOR_RED, "WARNING:");
Draw_DrawString(10, 60, COLOR_WHITE, " * Entering sleep mode will reset the LED state!");
Draw_DrawString(10, 70, COLOR_WHITE, " * LEDs cannot be toggled when the battery is low!");
Draw_FlushFramebuffer();
Draw_Unlock();
u32 pressed = waitInputWithTimeout(1000);
if(pressed & BUTTON_A)
{
mcuInit();
u8 result;
mcuGetLEDState(&result);
u8 value = ~result;
mcuWriteRegister(40, &value, 1);
mcuExit();
}
else if(pressed & BUTTON_B)
return;
}
while(!terminationRequest);
}
void SysConfigMenu_ToggleWireless(void)
{
Draw_Lock();
Draw_ClearFramebuffer();
Draw_FlushFramebuffer();
Draw_Unlock();
do
{
Draw_Lock();
Draw_DrawString(10, 10, COLOR_TITLE, "System configuration menu");
Draw_DrawString(10, 30, COLOR_WHITE, "Press A to toggle, press B to go back.");
Draw_DrawString(10, 50, COLOR_WHITE, "Current status:");
u8 wireless = (*(vu8 *)((0x10140000 | (1u << 31)) + 0x180));
Draw_DrawString(100, 50, (wireless ? COLOR_GREEN : COLOR_RED), (wireless ? " ON " : " OFF"));
Draw_FlushFramebuffer();
Draw_Unlock();
u32 pressed = waitInputWithTimeout(1000);
if(pressed & BUTTON_A)
{
nwmExtInit();
NWMEXT_ControlWirelessEnabled(!wireless);
nwmExtExit();
}
else if(pressed & BUTTON_B)
return;
}
while(!terminationRequest);
}