Compare commits
48 Commits
v9.0
...
v9.0-joyco
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1182d3a627 | ||
|
|
938cb6492f | ||
|
|
fed62855cb | ||
|
|
4f54596658 | ||
|
|
0b41ed04d5 | ||
|
|
9509a86998 | ||
|
|
6d4d80a798 | ||
|
|
76d274cfe2 | ||
|
|
ccf13be964 | ||
|
|
e36b27ccf0 | ||
|
|
34c80ad476 | ||
|
|
97ae106d8e | ||
|
|
7cb74b74d7 | ||
|
|
337205eb08 | ||
|
|
f36977017b | ||
|
|
e40b547bb6 | ||
|
|
1fd689f5da | ||
|
|
c5c8dca14c | ||
|
|
11f820efa7 | ||
|
|
9074688491 | ||
|
|
1de27c54f1 | ||
|
|
3e67e64faa | ||
|
|
553f8d2533 | ||
|
|
ec7ae35da1 | ||
|
|
7e8da0d236 | ||
|
|
b3e6561072 | ||
|
|
41f32ed983 | ||
|
|
bbadf840ef | ||
|
|
acc50aae46 | ||
|
|
6a68a77973 | ||
|
|
0f4d66dd61 | ||
|
|
d28642d2c3 | ||
|
|
ca4685cc42 | ||
|
|
522f10582d | ||
|
|
239d113177 | ||
|
|
fd80294bf2 | ||
|
|
b379d83469 | ||
|
|
27f352fdf1 | ||
|
|
bfec874a7c | ||
|
|
93561003e8 | ||
|
|
1572bfd989 | ||
|
|
cb945612a3 | ||
|
|
1b440f7f3b | ||
|
|
78791f7b66 | ||
|
|
5def0c18e2 | ||
|
|
0e67b0f026 | ||
|
|
8052946517 | ||
|
|
b6d6cc9750 |
6
.gitignore
vendored
6
.gitignore
vendored
@@ -13,4 +13,8 @@ exceptions/arm11/build
|
||||
*.d
|
||||
*.elf
|
||||
*.cxi
|
||||
.DS_Store
|
||||
.DS_Store
|
||||
*.dmp
|
||||
.project
|
||||
.cproject
|
||||
.settings
|
||||
|
||||
@@ -50,7 +50,7 @@ struct fb {
|
||||
u8 *top_left;
|
||||
u8 *top_right;
|
||||
u8 *bottom;
|
||||
} __attribute__((packed));
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
||||
@@ -42,4 +42,4 @@ struct fb {
|
||||
u8 *top_left;
|
||||
u8 *top_right;
|
||||
u8 *bottom;
|
||||
} __attribute__((packed));
|
||||
};
|
||||
|
||||
@@ -13,8 +13,8 @@ dir_build := build
|
||||
dir_out := ../../$(dir_build)
|
||||
|
||||
ASFLAGS := -mcpu=arm946e-s
|
||||
CFLAGS := -Wall -Wextra -mthumb $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math
|
||||
LDFLAGS := -nostdlib
|
||||
CFLAGS := -Wall -Wextra -marm $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -Os -ffast-math
|
||||
LDFLAGS := -nostartfiles -Wl,--nmagic
|
||||
|
||||
objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
|
||||
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
|
||||
|
||||
@@ -4,7 +4,7 @@ OUTPUT_ARCH(arm)
|
||||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x01FF7FE0;
|
||||
. = 0x01FF8000;
|
||||
|
||||
.text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); }
|
||||
.rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); }
|
||||
|
||||
@@ -43,8 +43,9 @@ typedef struct __attribute__((packed))
|
||||
u32 additionalDataSize;
|
||||
} ExceptionDumpHeader;
|
||||
|
||||
u32 readMPUConfig(u32 *regionSettings);
|
||||
void FIQHandler(void);
|
||||
void undefinedInstructionHandler(void);
|
||||
void dataAbortHandler(void);
|
||||
void prefetchAbortHandler(void);
|
||||
|
||||
u32 safecpy(void *dst, const void *src, u32 len);
|
||||
|
||||
@@ -22,92 +22,131 @@
|
||||
@ or requiring that modified versions of such material be marked in
|
||||
@ reasonable ways as different from the original version.
|
||||
|
||||
.macro GEN_HANDLER name
|
||||
.global \name
|
||||
.type \name, %function
|
||||
\name:
|
||||
ldr sp, =#0x02000000 @ We make the (full descending) stack point to the end of ITCM for our exception handlers.
|
||||
@ It doesn't matter if we're overwriting stuff here, since we're going to reboot.
|
||||
.macro GEN_USUAL_HANDLER name, index
|
||||
\name\()Handler:
|
||||
ldr sp, =_regs
|
||||
stmia sp, {r0-r7}
|
||||
|
||||
stmfd sp!, {r0-r7} @ FIQ has its own r8-r14 regs
|
||||
ldr r1, =\@ @ macro expansion counter
|
||||
mov r0, #\index
|
||||
b _commonHandler
|
||||
|
||||
.size \name, . - \name
|
||||
.endm
|
||||
|
||||
.text
|
||||
.arm
|
||||
.align 4
|
||||
.balign 4
|
||||
|
||||
.global _commonHandler
|
||||
.type _commonHandler, %function
|
||||
_commonHandler:
|
||||
mov r1, r0
|
||||
mov r0, sp
|
||||
mrs r2, spsr
|
||||
mov r6, sp
|
||||
mrs r3, cpsr
|
||||
add r6, r0, #(8 * 4)
|
||||
|
||||
orr r3, #0x1c0 @ disable Imprecise Aborts, IRQ and FIQ (equivalent to "cpsid aif" on arm11)
|
||||
orr r3, #0xc0 @ mask interrupts
|
||||
msr cpsr_cx, r3
|
||||
|
||||
tst r2, #0x20
|
||||
bne noSvcBreak
|
||||
cmp r1, #2
|
||||
bne noSvcBreak
|
||||
|
||||
sub r0, lr, #4 @ calling cannotAccessAddress cause more problems that it actually solves... (I've to save a lot of regs and that's a pain tbh)
|
||||
lsr r0, #20 @ we'll just do some address checks (to see if it's in ARM9 internal memory)
|
||||
cmp r0, #0x80
|
||||
bne noSvcBreak
|
||||
ldr r4, [lr, #-4]
|
||||
ldr r5, =#0xe12fff7f
|
||||
cmp r4, r5
|
||||
bne noSvcBreak
|
||||
bic r5, r3, #0xf
|
||||
orr r5, #0x3
|
||||
msr cpsr_c, r5 @ switch to supervisor mode
|
||||
ldmfd sp, {r8-r11}^
|
||||
ldr r2, [sp, #0x1c] @ implementation details of the official svc handler
|
||||
ldr r4, [sp, #0x18]
|
||||
msr cpsr_c, r3 @ restore processor mode
|
||||
tst r2, #0x20
|
||||
addne lr, r4, #2 @ adjust address for later
|
||||
moveq lr, r4
|
||||
|
||||
noSvcBreak:
|
||||
ands r4, r2, #0xf @ get the mode that triggered the exception
|
||||
moveq r4, #0xf @ usr => sys
|
||||
bic r5, r3, #0xf
|
||||
orr r5, r4
|
||||
msr cpsr_c, r5 @ change processor mode
|
||||
stmfd r6!, {r8-lr}
|
||||
stmia r6!, {r8-lr}
|
||||
msr cpsr_c, r3 @ restore processor mode
|
||||
mov sp, r6
|
||||
|
||||
stmfd sp!, {r2,lr} @ it's a bit of a mess, but we will fix that later
|
||||
@ order of saved regs now: cpsr, pc + (2/4/8), r8-r14, r0-r7
|
||||
|
||||
mov r0, sp
|
||||
str lr, [r6], #4
|
||||
str r2, [r6]
|
||||
|
||||
msr cpsr_cxsf, #0xdf @ finally, switch to system mode, mask interrupts and clear flags (in case of double faults)
|
||||
ldr sp, =0x02000000
|
||||
b mainHandler
|
||||
|
||||
GEN_HANDLER FIQHandler
|
||||
GEN_HANDLER undefinedInstructionHandler
|
||||
GEN_HANDLER prefetchAbortHandler
|
||||
GEN_HANDLER dataAbortHandler
|
||||
|
||||
.global readMPUConfig
|
||||
.type readMPUConfig, %function
|
||||
readMPUConfig:
|
||||
stmfd sp!, {r4-r8, lr}
|
||||
mrc p15,0,r1,c6,c0,0
|
||||
mrc p15,0,r2,c6,c1,0
|
||||
mrc p15,0,r3,c6,c2,0
|
||||
mrc p15,0,r4,c6,c3,0
|
||||
mrc p15,0,r5,c6,c4,0
|
||||
mrc p15,0,r6,c6,c5,0
|
||||
mrc p15,0,r7,c6,c6,0
|
||||
mrc p15,0,r8,c6,c7,0
|
||||
stmia r0, {r1-r8}
|
||||
mrc p15,0,r0,c5,c0,2 @ read data access permission bits
|
||||
ldmfd sp!, {r4-r8, pc}
|
||||
.global FIQHandler
|
||||
.type FIQHandler, %function
|
||||
GEN_USUAL_HANDLER FIQ, 0
|
||||
|
||||
.global undefinedInstructionHandler
|
||||
.type undefinedInstructionHandler, %function
|
||||
GEN_USUAL_HANDLER undefinedInstruction, 1
|
||||
|
||||
.global prefetchAbortHandler
|
||||
.type prefetchAbortHandler, %function
|
||||
prefetchAbortHandler:
|
||||
msr cpsr_cx, #0xd7 @ mask interrupts (abort mode)
|
||||
mrs sp, spsr
|
||||
and sp, #0x3f
|
||||
cmp sp, #0x13
|
||||
bne _prefetchAbortNormalHandler
|
||||
|
||||
ldr sp, =BreakPtr
|
||||
ldr sp, [sp]
|
||||
cmp sp, #0
|
||||
beq _prefetchAbortNormalHandler
|
||||
add sp, #(1*4 + 4)
|
||||
cmp lr, sp
|
||||
bne _prefetchAbortNormalHandler
|
||||
|
||||
mov sp, r8
|
||||
pop {r8-r11}
|
||||
ldr lr, [sp, #8]!
|
||||
ldr sp, [sp, #4]
|
||||
msr spsr_cxsf, sp
|
||||
tst sp, #0x20
|
||||
addne lr, #2 @ adjust address for later
|
||||
|
||||
GEN_USUAL_HANDLER _prefetchAbortNormal, 2
|
||||
|
||||
.global dataAbortHandler
|
||||
.type dataAbortHandler, %function
|
||||
dataAbortHandler:
|
||||
msr cpsr_cx, #0xd7 @ mask interrupts (abort mode)
|
||||
mrs sp, spsr
|
||||
and sp, #0x3f
|
||||
cmp sp, #0x1f
|
||||
bne _dataAbortNormalHandler
|
||||
|
||||
sub lr, #8
|
||||
adr sp, safecpy
|
||||
cmp lr, sp
|
||||
blo _j_dataAbortNormalHandler
|
||||
adr sp, _safecpy_end
|
||||
cmp lr, sp
|
||||
bhs _j_dataAbortNormalHandler
|
||||
|
||||
msr spsr_f, #(1 << 30)
|
||||
mov r12, #0
|
||||
adds pc, lr, #4
|
||||
|
||||
_j_dataAbortNormalHandler:
|
||||
add lr, #8
|
||||
|
||||
GEN_USUAL_HANDLER _dataAbortNormal, 3
|
||||
|
||||
|
||||
.global safecpy
|
||||
.type safecpy, %function
|
||||
safecpy:
|
||||
push {r4, lr}
|
||||
mov r3, #0
|
||||
movs r12, #1
|
||||
|
||||
_safecpy_loop:
|
||||
ldrb r4, [r1, r3]
|
||||
cmp r12, #0
|
||||
beq _safecpy_loop_end
|
||||
strb r4, [r0, r3]
|
||||
add r3, #1
|
||||
cmp r3, r2
|
||||
blo _safecpy_loop
|
||||
|
||||
_safecpy_loop_end:
|
||||
mov r0, r3
|
||||
pop {r4, pc}
|
||||
|
||||
_safecpy_end:
|
||||
|
||||
.bss
|
||||
.balign 4
|
||||
_regs: .skip (4 * 17)
|
||||
|
||||
@@ -32,48 +32,10 @@
|
||||
#define REG_DUMP_SIZE 4 * 17
|
||||
#define CODE_DUMP_SIZE 48
|
||||
|
||||
bool cannotAccessAddress(const void *address)
|
||||
{
|
||||
u32 regionSettings[8];
|
||||
u32 addr = (u32)address;
|
||||
|
||||
u32 dataAccessPermissions = readMPUConfig(regionSettings);
|
||||
for(u32 i = 0; i < 8; i++)
|
||||
{
|
||||
if((dataAccessPermissions & 0xF) == 0 || (regionSettings[i] & 1) == 0)
|
||||
continue; //No access / region not enabled
|
||||
|
||||
u32 regionAddrBase = regionSettings[i] & ~0xFFF;
|
||||
u32 regionSize = 1 << (((regionSettings[i] >> 1) & 0x1F) + 1);
|
||||
|
||||
if(addr >= regionAddrBase && addr < regionAddrBase + regionSize)
|
||||
return false;
|
||||
|
||||
dataAccessPermissions >>= 4;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static u32 __attribute__((noinline)) copyMemory(void *dst, const void *src, u32 size, u32 alignment)
|
||||
{
|
||||
u8 *out = (u8 *)dst;
|
||||
const u8 *in = (const u8 *)src;
|
||||
|
||||
if(((u32)src & (alignment - 1)) != 0 || cannotAccessAddress(src) || (size != 0 && cannotAccessAddress((u8 *)src + size - 1)))
|
||||
return 0;
|
||||
|
||||
for(u32 i = 0; i < size; i++)
|
||||
*out++ = *in++;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
void __attribute__((noreturn)) mainHandler(u32 *regs, u32 type)
|
||||
void __attribute__((noreturn)) mainHandler(u32 *registerDump, u32 type)
|
||||
{
|
||||
ExceptionDumpHeader dumpHeader;
|
||||
|
||||
u32 registerDump[REG_DUMP_SIZE / 4];
|
||||
u8 codeDump[CODE_DUMP_SIZE];
|
||||
|
||||
dumpHeader.magic[0] = 0xDEADC0DE;
|
||||
@@ -89,27 +51,22 @@ void __attribute__((noreturn)) mainHandler(u32 *regs, u32 type)
|
||||
dumpHeader.codeDumpSize = CODE_DUMP_SIZE;
|
||||
dumpHeader.additionalDataSize = 0;
|
||||
|
||||
//Dump registers
|
||||
//Current order of saved regs: cpsr, pc, r8-r14, r0-r7
|
||||
u32 cpsr = regs[0];
|
||||
u32 pc = regs[1] - (type < 3 ? (((cpsr & 0x20) != 0 && type == 1) ? 2 : 4) : 8);
|
||||
u32 cpsr = registerDump[16];
|
||||
u32 pc = registerDump[15] - (type < 3 ? (((cpsr & 0x20) != 0 && type == 1) ? 2 : 4) : 8);
|
||||
|
||||
registerDump[15] = pc;
|
||||
registerDump[16] = cpsr;
|
||||
for(u32 i = 0; i < 7; i++) registerDump[8 + i] = regs[2 + i];
|
||||
for(u32 i = 0; i < 8; i++) registerDump[i] = regs[9 + i];
|
||||
|
||||
//Dump code
|
||||
u8 *instr = (u8 *)pc + ((cpsr & 0x20) ? 2 : 4) - dumpHeader.codeDumpSize; //Doesn't work well on 32-bit Thumb instructions, but it isn't much of a problem
|
||||
dumpHeader.codeDumpSize = copyMemory(codeDump, instr, dumpHeader.codeDumpSize, ((cpsr & 0x20) != 0) ? 2 : 4);
|
||||
u8 *instr = (u8 *)pc + ((cpsr & 0x20) ? 2 : 4) - dumpHeader.codeDumpSize; //wouldn't work well on 32-bit Thumb instructions, but it isn't much of a problem
|
||||
dumpHeader.codeDumpSize = ((u32)instr & (((cpsr & 0x20) != 0) ? 1 : 3)) != 0 ? 0 : safecpy(codeDump, instr, dumpHeader.codeDumpSize);
|
||||
|
||||
//Copy register dump and code dump
|
||||
//Copy register dump and code dump
|
||||
u8 *final = (u8 *)(FINAL_BUFFER + sizeof(ExceptionDumpHeader));
|
||||
final += copyMemory(final, registerDump, dumpHeader.registerDumpSize, 1);
|
||||
final += copyMemory(final, codeDump, dumpHeader.codeDumpSize, 1);
|
||||
final += safecpy(final, registerDump, dumpHeader.registerDumpSize);
|
||||
final += safecpy(final, codeDump, dumpHeader.codeDumpSize);
|
||||
|
||||
//Dump stack in place
|
||||
dumpHeader.stackDumpSize = copyMemory(final, (const void *)registerDump[13], 0x1000 - (registerDump[13] & 0xFFF), 1);
|
||||
dumpHeader.stackDumpSize = safecpy(final, (const void *)registerDump[13], 0x1000 - (registerDump[13] & 0xFFF));
|
||||
|
||||
dumpHeader.totalSize = sizeof(ExceptionDumpHeader) + dumpHeader.registerDumpSize + dumpHeader.codeDumpSize + dumpHeader.stackDumpSize + dumpHeader.additionalDataSize;
|
||||
|
||||
|
||||
@@ -26,8 +26,12 @@
|
||||
.align 4
|
||||
.global _start
|
||||
_start:
|
||||
add pc, r0, #(handlers - .) @ Dummy instruction to prevent compiler optimizations
|
||||
add pc, r0, #(handlers - .) @ Dummy instruction
|
||||
|
||||
.global BreakPtr
|
||||
BreakPtr: .word 0
|
||||
|
||||
.global handlers
|
||||
handlers:
|
||||
.word FIQHandler
|
||||
.word undefinedInstructionHandler
|
||||
|
||||
@@ -19,6 +19,7 @@ enum multiOptions
|
||||
DEFAULTEMU = 0,
|
||||
BRIGHTNESS,
|
||||
SPLASH,
|
||||
SPLASH_DURATION,
|
||||
PIN,
|
||||
NEWCPU
|
||||
};
|
||||
|
||||
@@ -159,7 +159,7 @@ _commonHandler:
|
||||
|
||||
_no_L2C:
|
||||
|
||||
cps #0x1F
|
||||
msr cpsr_cxsf, #0xdf @ finally, switch to system mode, mask interrupts and clear flags (in case of double faults)
|
||||
ldr sp, =exceptionStackTop
|
||||
ldr sp, [sp]
|
||||
sub sp, #0x100
|
||||
@@ -221,7 +221,8 @@ prefetchAbortHandler:
|
||||
pop {r8-r11}
|
||||
ldr lr, [sp, #8]!
|
||||
ldr sp, [sp, #4]
|
||||
msr spsr, sp
|
||||
msr spsr_cxsf, sp
|
||||
tst sp, #0x20
|
||||
addne lr, #2 @ adjust address for later
|
||||
|
||||
GEN_USUAL_HANDLER _prefetchAbortNormal, 2, 12
|
||||
|
||||
@@ -37,7 +37,7 @@ bool isExceptionFatal(u32 spsr, u32 *regs, u32 index)
|
||||
{
|
||||
if(CONFIG(DISABLEARM11EXCHANDLERS)) return false;
|
||||
|
||||
if((spsr & 0x1f) != 0x10) return true;
|
||||
if((spsr & 0x1F) != 0x10) return true;
|
||||
|
||||
KThread *thread = currentCoreContext->objectContext.currentThread;
|
||||
KProcess *currentProcess = currentCoreContext->objectContext.currentProcess;
|
||||
@@ -65,7 +65,7 @@ bool isExceptionFatal(u32 spsr, u32 *regs, u32 index)
|
||||
extern u32 safecpy_sz;
|
||||
bool isDataAbortExceptionRangeControlled(u32 spsr, u32 addr)
|
||||
{
|
||||
return ((spsr & 0x1F) != 0x10) && (
|
||||
return (!(spsr & 0x20) && (spsr & 0x1F) != 0x10) && (
|
||||
((u32)kernelUsrCopyFuncsStart <= addr && addr < (u32)kernelUsrCopyFuncsEnd) ||
|
||||
((u32)safecpy <= addr && addr < (u32)safecpy + safecpy_sz)
|
||||
);
|
||||
@@ -96,7 +96,7 @@ void fatalExceptionHandlersMain(u32 *registerDump, u32 type, u32 cpuId)
|
||||
registerDump[15] = pc;
|
||||
|
||||
//Dump code
|
||||
u8 *instr = (u8 *)pc + ((cpsr & 0x20) ? 2 : 4) - dumpHeader.codeDumpSize; //Doesn't work well on 32-bit Thumb instructions, but it isn't much of a problem
|
||||
u8 *instr = (u8 *)pc + ((cpsr & 0x20) ? 2 : 4) - dumpHeader.codeDumpSize; //wouldn't work well on 32-bit Thumb instructions, but it isn't much of a problem
|
||||
dumpHeader.codeDumpSize = ((u32)instr & (((cpsr & 0x20) != 0) ? 1 : 3)) != 0 ? 0 : safecpy(codeDump, instr, dumpHeader.codeDumpSize);
|
||||
|
||||
//Copy register dump and code dump
|
||||
|
||||
@@ -116,9 +116,7 @@ fname: .ascii "FILE"
|
||||
.align 4
|
||||
kernelcode_start:
|
||||
|
||||
mrs r0, cpsr ; disable interrupts
|
||||
orr r0, #0xC0
|
||||
msr cpsr, r0
|
||||
msr cpsr_cxsf, #0xD3 ; disable interrupts and clear flags
|
||||
|
||||
ldr sp, =copy_launch_stub_stack_top
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "config.h"
|
||||
#include "memory.h"
|
||||
#include "fs.h"
|
||||
#include "strings.h"
|
||||
#include "utils.h"
|
||||
#include "screen.h"
|
||||
#include "draw.h"
|
||||
@@ -81,6 +82,7 @@ void configMenu(bool oldPinStatus, u32 oldPinMode)
|
||||
static const char *multiOptionsText[] = { "Default EmuNAND: 1( ) 2( ) 3( ) 4( )",
|
||||
"Screen brightness: 4( ) 3( ) 2( ) 1( )",
|
||||
"Splash: Off( ) Before( ) After( ) payloads",
|
||||
"Splash duration: 1( ) 3( ) 5( ) 7( ) seconds",
|
||||
"PIN lock: Off( ) 4( ) 6( ) 8( ) digits",
|
||||
"New 3DS CPU: Off( ) Clock( ) L2( ) Clock+L2( )",
|
||||
};
|
||||
@@ -109,6 +111,11 @@ void configMenu(bool oldPinStatus, u32 oldPinMode)
|
||||
"\t* 'After payloads' displays it\n"
|
||||
"afterwards.",
|
||||
|
||||
"Select how long the splash screen\n"
|
||||
"displays.\n\n"
|
||||
"This has no effect if the splash\n"
|
||||
"screen is not enabled.",
|
||||
|
||||
"Activate a PIN lock.\n\n"
|
||||
"The PIN will be asked each time\n"
|
||||
"Luma3DS boots.\n\n"
|
||||
@@ -195,11 +202,12 @@ void configMenu(bool oldPinStatus, u32 oldPinMode)
|
||||
u32 enabled;
|
||||
bool visible;
|
||||
} multiOptions[] = {
|
||||
{ .posXs = {19, 24, 29, 34}, .visible = isSdMode },
|
||||
{ .posXs = {21, 26, 31, 36}, .visible = true },
|
||||
{ .posXs = {12, 22, 31, 0}, .visible = true },
|
||||
{ .posXs = {14, 19, 24, 29}, .visible = true },
|
||||
{ .posXs = {17, 26, 32, 44}, .visible = ISN3DS },
|
||||
{ .visible = isSdMode },
|
||||
{ .visible = true },
|
||||
{ .visible = true },
|
||||
{ .visible = true },
|
||||
{ .visible = true },
|
||||
{ .visible = ISN3DS },
|
||||
};
|
||||
|
||||
struct singleOption {
|
||||
@@ -227,7 +235,15 @@ void configMenu(bool oldPinStatus, u32 oldPinMode)
|
||||
|
||||
//Parse the existing options
|
||||
for(u32 i = 0; i < multiOptionsAmount; i++)
|
||||
{
|
||||
//Detect the positions where the "x" should go
|
||||
u32 optionNum = 0;
|
||||
for(u32 j = 0; optionNum < 4 && j < strlen(multiOptionsText[i]); j++)
|
||||
if(multiOptionsText[i][j] == '(') multiOptions[i].posXs[optionNum++] = j + 1;
|
||||
while(optionNum < 4) multiOptions[i].posXs[optionNum++] = 0;
|
||||
|
||||
multiOptions[i].enabled = MULTICONFIG(i);
|
||||
}
|
||||
for(u32 i = 0; i < singleOptionsAmount; i++)
|
||||
singleOptions[i].enabled = CONFIG(i);
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
#define CONFIG_FILE "config.bin"
|
||||
#define CONFIG_VERSIONMAJOR 2
|
||||
#define CONFIG_VERSIONMINOR 2
|
||||
#define CONFIG_VERSIONMINOR 3
|
||||
|
||||
#define BOOTCFG_NAND BOOTCONFIG(0, 7)
|
||||
#define BOOTCFG_FIRM BOOTCONFIG(3, 7)
|
||||
@@ -46,6 +46,7 @@ enum multiOptions
|
||||
DEFAULTEMU = 0,
|
||||
BRIGHTNESS,
|
||||
SPLASH,
|
||||
SPLASH_DURATION,
|
||||
PIN,
|
||||
NEWCPU
|
||||
};
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "fs.h"
|
||||
#include "fmt.h"
|
||||
#include "font.h"
|
||||
#include "config.h"
|
||||
|
||||
bool loadSplash(void)
|
||||
{
|
||||
@@ -56,7 +57,9 @@ bool loadSplash(void)
|
||||
if(!isTopSplashValid && !isBottomSplashValid) return false;
|
||||
|
||||
swapFramebuffers(true);
|
||||
wait(3000ULL);
|
||||
|
||||
u32 durationIndex = MULTICONFIG(SPLASH_DURATION);
|
||||
wait(1000ULL + (durationIndex * 2000ULL));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
void installArm9Handlers(void)
|
||||
{
|
||||
memcpy((void *)0x01FF8000, arm9_exceptions_bin + 32, arm9_exceptions_bin_size - 32);
|
||||
memcpy((void *)0x01FF8000, arm9_exceptions_bin, arm9_exceptions_bin_size);
|
||||
|
||||
/* IRQHandler is at 0x08000000, but we won't handle it for some reasons
|
||||
svcHandler is at 0x08000010, but we won't handle svc either */
|
||||
@@ -47,8 +47,10 @@ void installArm9Handlers(void)
|
||||
for(u32 i = 0; i < 4; i++)
|
||||
{
|
||||
*(vu32 *)(0x08000000 + offsets[i]) = 0xE51FF004;
|
||||
*(vu32 *)(0x08000000 + offsets[i] + 4) = *((u32 *)arm9_exceptions_bin + 1 + i);
|
||||
*(vu32 *)(0x08000000 + offsets[i] + 4) = *(vu32 *)(0x01FF8008 + 4 * i);
|
||||
}
|
||||
|
||||
*(vu32 *)0x01FF8004 = 0; //BreakPtr
|
||||
}
|
||||
|
||||
void detectAndProcessExceptionDumps(void)
|
||||
|
||||
@@ -123,7 +123,7 @@ static inline u32 loadFirmFromStorage(FirmwareType firmType)
|
||||
"cetk_sysupdater"
|
||||
};
|
||||
|
||||
u32 firmSize = fileRead(firm, firmType == NATIVE_FIRM1X2X ? firmwareFiles[0] : firmwareFiles[(u32)firmType], 0x400000 + sizeof(Cxi) + 0x200);
|
||||
u32 firmSize = fileRead(firm, firmwareFiles[(u32)firmType], 0x400000 + sizeof(Cxi) + 0x200);
|
||||
|
||||
if(!firmSize) return 0;
|
||||
|
||||
@@ -137,7 +137,7 @@ static inline u32 loadFirmFromStorage(FirmwareType firmType)
|
||||
|
||||
u8 cetk[0xA50];
|
||||
|
||||
if(fileRead(cetk, firmType == NATIVE_FIRM1X2X ? cetkFiles[0] : cetkFiles[(u32)firmType], sizeof(cetk)) != sizeof(cetk))
|
||||
if(fileRead(cetk, cetkFiles[(u32)firmType], sizeof(cetk)) != sizeof(cetk))
|
||||
error("The cetk is missing or corrupted.");
|
||||
|
||||
firmSize = decryptNusFirm((Ticket *)(cetk + 0x140), (Cxi *)firm, firmSize);
|
||||
@@ -152,18 +152,42 @@ static inline u32 loadFirmFromStorage(FirmwareType firmType)
|
||||
|
||||
u32 loadNintendoFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadFromStorage, bool isSafeMode)
|
||||
{
|
||||
if(isSdMode && !mountFs(false, false)) error("Failed to mount CTRNAND.");
|
||||
u32 firmVersion,
|
||||
firmSize;
|
||||
|
||||
//Load FIRM from CTRNAND
|
||||
u32 firmVersion = firmRead(firm, (u32)*firmType);
|
||||
bool ctrNandError = isSdMode && !mountFs(false, false);
|
||||
|
||||
if(firmVersion == 0xFFFFFFFF) error("Failed to get the CTRNAND FIRM.");
|
||||
if(!ctrNandError)
|
||||
{
|
||||
//Load FIRM from CTRNAND
|
||||
firmVersion = firmRead(firm, (u32)*firmType);
|
||||
|
||||
u32 firmSize = decryptExeFs((Cxi *)firm);
|
||||
if(firmVersion == 0xFFFFFFFF) ctrNandError = true;
|
||||
else
|
||||
{
|
||||
firmSize = decryptExeFs((Cxi *)firm);
|
||||
|
||||
if(!firmSize) error("Failed to decrypt the CTRNAND FIRM.");
|
||||
if(!firmSize || !checkFirm(firmSize)) ctrNandError = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(!checkFirm(firmSize)) error("The CTRNAND FIRM is invalid or corrupted.");
|
||||
bool loadedFromStorage = false;
|
||||
|
||||
if(loadFromStorage || ctrNandError)
|
||||
{
|
||||
u32 result = loadFirmFromStorage(*firmType);
|
||||
|
||||
if(result != 0)
|
||||
{
|
||||
loadedFromStorage = true;
|
||||
firmSize = result;
|
||||
}
|
||||
else if(ctrNandError) error("Unable to mount CTRNAND or load the CTRNAND FIRM.\nPlease use an external one.");
|
||||
}
|
||||
|
||||
//Check that the FIRM is right for the console from the ARM9 section address
|
||||
if((firm->section[3].offset != 0 ? firm->section[3].address : firm->section[2].address) != (ISN3DS ? (u8 *)0x8006000 : (u8 *)0x8006800))
|
||||
error("The %s FIRM is not for this console.", loadedFromStorage ? "external" : "CTRNAND");
|
||||
|
||||
if(!ISN3DS && *firmType == NATIVE_FIRM && firm->section[0].address == (u8 *)0x1FF80000)
|
||||
{
|
||||
@@ -175,23 +199,6 @@ u32 loadNintendoFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadF
|
||||
*firmType = NATIVE_FIRM1X2X;
|
||||
}
|
||||
|
||||
bool loadedFromStorage = false;
|
||||
|
||||
if(loadFromStorage)
|
||||
{
|
||||
u32 result = loadFirmFromStorage(*firmType);
|
||||
|
||||
if(result != 0)
|
||||
{
|
||||
loadedFromStorage = true;
|
||||
firmSize = result;
|
||||
}
|
||||
}
|
||||
|
||||
//Check that the FIRM is right for the console from the ARM9 section address
|
||||
if((firm->section[3].offset != 0 ? firm->section[3].address : firm->section[2].address) != (ISN3DS ? (u8 *)0x8006000 : (u8 *)0x8006800))
|
||||
error("The %s FIRM is not for this console.", loadedFromStorage ? "external" : "CTRNAND");
|
||||
|
||||
if(loadedFromStorage || ISDEVUNIT)
|
||||
{
|
||||
firmVersion = 0xFFFFFFFF;
|
||||
|
||||
@@ -454,7 +454,9 @@ u32 patchArm9ExceptionHandlersInstall(u8 *pos, u32 size)
|
||||
|
||||
if(temp == NULL) return 1;
|
||||
|
||||
u32 *off = (u32 *)(temp - 0xA);
|
||||
u32 *off;
|
||||
|
||||
for(off = (u32 *)(temp - 2); *off != 0xE5801000; off--); //Until str r1, [r0]
|
||||
|
||||
for(u32 r0 = 0x08000000; *off != 0xE3A01040; off++) //Until mov r1, #0x40
|
||||
{
|
||||
@@ -491,7 +493,15 @@ u32 patchSvcBreak9(u8 *pos, u32 size, u32 kernel9Address)
|
||||
while(*arm9SvcTable != 0) arm9SvcTable++; //Look for SVC0 (NULL)
|
||||
|
||||
u32 *addr = (u32 *)(pos + arm9SvcTable[0x3C] - kernel9Address);
|
||||
*addr = 0xE12FFF7F;
|
||||
|
||||
/*
|
||||
mov r8, sp
|
||||
bkpt 0xffff
|
||||
*/
|
||||
addr[0] = 0xE1A0800D;
|
||||
addr[1] = 0xE12FFF7F;
|
||||
|
||||
*(vu32 *)0x01FF8004 = arm9SvcTable[0x3C]; //BreakPtr
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
27
source/pin.c
27
source/pin.c
@@ -146,21 +146,32 @@ bool verifyPin(u32 pinMode)
|
||||
|
||||
initScreens();
|
||||
|
||||
swapFramebuffers(true);
|
||||
|
||||
drawString(true, 10, 10, COLOR_TITLE, "Enter the PIN using ABXY and the DPad to proceed");
|
||||
drawString(true, 10, 10 + SPACING_Y, COLOR_TITLE, "Press START to shutdown, SELECT to clear");
|
||||
|
||||
drawFormattedString(true, 10, 10 + 3 * SPACING_Y, COLOR_WHITE, "PIN (%u digits): ", lengthBlock[0]);
|
||||
|
||||
static const char *messageFile = "pinmessage.txt";
|
||||
char message[801];
|
||||
|
||||
u32 messageSize = fileRead(message, messageFile, sizeof(message) - 1);
|
||||
|
||||
if(messageSize != 0)
|
||||
bool isBottomSplashValid = getFileSize("splashpin.bin") == SCREEN_BOTTOM_FBSIZE;
|
||||
if(isBottomSplashValid)
|
||||
{
|
||||
message[messageSize] = 0;
|
||||
drawString(false, 10, 10, COLOR_WHITE, message);
|
||||
isBottomSplashValid = fileRead(fbs[0].bottom, "splashpin.bin", SCREEN_BOTTOM_FBSIZE) == SCREEN_BOTTOM_FBSIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
static const char *messageFile = "pinmessage.txt";
|
||||
char message[801];
|
||||
|
||||
u32 messageSize = fileRead(message, messageFile, sizeof(message) - 1);
|
||||
|
||||
if(messageSize != 0)
|
||||
{
|
||||
message[messageSize] = 0;
|
||||
drawString(false, 10, 10, COLOR_WHITE, message);
|
||||
}
|
||||
}
|
||||
swapFramebuffers(false);
|
||||
|
||||
//Pad to AES block length with zeroes
|
||||
__attribute__((aligned(4))) u8 enteredPassword[AES_BLOCK_SIZE] = {0};
|
||||
|
||||
@@ -49,7 +49,7 @@ struct fb {
|
||||
u8 *top_left;
|
||||
u8 *top_right;
|
||||
u8 *bottom;
|
||||
} __attribute__((packed));
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
||||
@@ -27,9 +27,7 @@
|
||||
.global _start
|
||||
_start:
|
||||
@ Disable interrupts and switch to supervisor mode (also clear flags)
|
||||
mov r4, #0x13
|
||||
orr r4, #0x1C0
|
||||
msr cpsr_cxsf, r4
|
||||
msr cpsr_cxsf, #0xD3
|
||||
|
||||
@ Check if r0-r2 are 0 (r0-sp are supposed to be 0), and for regions 0, 5 and 7 of the MPU config
|
||||
@ This is not foolproof but should work well enough
|
||||
|
||||
@@ -20,7 +20,7 @@ LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||
INCLUDE := $(foreach dir,$(LIBDIRS),-I$(dir)/include)
|
||||
|
||||
ASFLAGS := -mcpu=mpcore -mfloat-abi=hard
|
||||
CFLAGS := -Wall -Wextra $(ASFLAGS) -fno-builtin -std=c11 -O2 -flto -ffast-math $(INCLUDE) -DARM11 -D_3DS
|
||||
CFLAGS := -Wall -Wextra $(ASFLAGS) -fno-builtin -std=c11 -O2 -ffast-math $(INCLUDE) -DARM11 -D_3DS
|
||||
LDFLAGS := -specs=3dsx.specs $(ASFLAGS) -Wl,--section-start,.text=0x14000000
|
||||
|
||||
objects = $(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
|
||||
@@ -51,7 +51,7 @@ $(dir_build)/%.bin.o: $(dir_build)/%.bin
|
||||
@$(bin2o)
|
||||
|
||||
$(dir_build)/%.bin: $(dir_patches)/%.s
|
||||
@mkdir -p "$(@D)"
|
||||
@mkdir -p "$(@D)"
|
||||
@armips $<
|
||||
|
||||
$(dir_build)/memory.o $(dir_build)/strings.o: CFLAGS += -O3
|
||||
|
||||
@@ -21,6 +21,7 @@ enum multiOptions
|
||||
DEFAULTEMU = 0,
|
||||
BRIGHTNESS,
|
||||
SPLASH,
|
||||
SPLASH_DURATION,
|
||||
PIN,
|
||||
NEWCPU
|
||||
};
|
||||
|
||||
@@ -21,7 +21,7 @@ INCLUDE := $(foreach dir,$(LIBDIRS),-I$(dir)/include)
|
||||
|
||||
ARCH := -mcpu=mpcore -mfloat-abi=hard
|
||||
ASFLAGS := -g $(ARCH)
|
||||
CFLAGS := -Wall -Wextra -MMD -MP -marm $(ASFLAGS) -mtp=soft -fno-builtin -std=c11 -O2 -flto -ffast-math -mword-relocations \
|
||||
CFLAGS := -Wall -Wextra -MMD -MP -marm $(ASFLAGS) -mtp=soft -fno-builtin -std=c11 -O2 -ffast-math -mword-relocations \
|
||||
-fomit-frame-pointer -ffunction-sections -fdata-sections $(INCLUDE) -I$(dir_include) -DARM11 -D_3DS
|
||||
LDFLAGS := -specs=3dsx.specs -g $(ARCH) -mtp=soft -Wl,--section-start,.text=0x14000000 -Wl,--gc-sections
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
GDB_DECLARE_REMOTE_COMMAND_HANDLER(SyncRequestInfo);
|
||||
GDB_DECLARE_REMOTE_COMMAND_HANDLER(TranslateHandle);
|
||||
GDB_DECLARE_REMOTE_COMMAND_HANDLER(GetMmuConfig);
|
||||
GDB_DECLARE_REMOTE_COMMAND_HANDLER(GetMemRegions);
|
||||
GDB_DECLARE_REMOTE_COMMAND_HANDLER(FlushCaches);
|
||||
GDB_DECLARE_REMOTE_COMMAND_HANDLER(ToggleExternalMemoryAccess);
|
||||
|
||||
|
||||
@@ -37,3 +37,4 @@ void RosalinaMenu_ShowCredits(void);
|
||||
void RosalinaMenu_ProcessList(void);
|
||||
void RosalinaMenu_PowerOff(void);
|
||||
void RosalinaMenu_Reboot(void);
|
||||
void RosalinaMenu_Cheats(void);
|
||||
|
||||
36
sysmodules/rosalina/include/menus/cheats.h
Normal file
36
sysmodules/rosalina/include/menus/cheats.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* This file was entirely written by Duckbill */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <3ds/types.h>
|
||||
|
||||
#define CHEATS_PER_MENU_PAGE 18
|
||||
|
||||
void RosalinaMenu_Cheats(void);
|
||||
void Cheat_ApplyKeyCheats();
|
||||
@@ -26,10 +26,22 @@
|
||||
|
||||
#include "MyThread.h"
|
||||
#include "memory.h"
|
||||
#include <3ds/srv.h>
|
||||
|
||||
static void _thread_begin(void* arg)
|
||||
{
|
||||
MyThread *t = (MyThread *)arg;
|
||||
|
||||
// ROSALINA HACKJOB BEGIN
|
||||
// NORMAL APPS SHOULD NOT DO THIS, EVER
|
||||
u32 *tls = (u32 *)getThreadLocalStorage();
|
||||
memset(tls, 0, 0x80);
|
||||
tls[0] = 0x21545624;
|
||||
// ROSALINA HACKJOB END
|
||||
|
||||
// Rosalina specific:
|
||||
srvSetBlockingPolicy(true); // GetServiceHandle nonblocking if service port is full
|
||||
|
||||
t->ep();
|
||||
MyThread_Exit();
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ struct
|
||||
{ "syncrequestinfo" , GDB_REMOTE_COMMAND_HANDLER(SyncRequestInfo) },
|
||||
{ "translatehandle" , GDB_REMOTE_COMMAND_HANDLER(TranslateHandle) },
|
||||
{ "getmmuconfig" , GDB_REMOTE_COMMAND_HANDLER(GetMmuConfig) },
|
||||
{ "getmemregions" , GDB_REMOTE_COMMAND_HANDLER(GetMemRegions) },
|
||||
{ "flushcaches" , GDB_REMOTE_COMMAND_HANDLER(FlushCaches) },
|
||||
{ "toggleextmemaccess", GDB_REMOTE_COMMAND_HANDLER(ToggleExternalMemoryAccess) },
|
||||
};
|
||||
@@ -226,6 +227,84 @@ GDB_DECLARE_REMOTE_COMMAND_HANDLER(GetMmuConfig)
|
||||
return GDB_SendHexPacket(ctx, outbuf, n);
|
||||
}
|
||||
|
||||
static const char *FormatMemPerm(u32 perm)
|
||||
{
|
||||
if (perm == MEMPERM_DONTCARE)
|
||||
return "???";
|
||||
|
||||
static char buf[4] = {0};
|
||||
|
||||
buf[0] = perm & MEMPERM_READ ? 'r' : '-';
|
||||
buf[1] = perm & MEMPERM_WRITE ? 'w' : '-';
|
||||
buf[2] = perm & MEMPERM_EXECUTE ? 'x' : '-';
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static const char *FormatMemState(u32 state)
|
||||
{
|
||||
if (state > 11)
|
||||
return "Unknown";
|
||||
|
||||
static const char *states[12] =
|
||||
{
|
||||
"Free",
|
||||
"Reserved",
|
||||
"IO",
|
||||
"Static",
|
||||
"Code",
|
||||
"Private",
|
||||
"Shared",
|
||||
"Continuous",
|
||||
"Aliased",
|
||||
"Alias",
|
||||
"AliasCode",
|
||||
"Locked"
|
||||
};
|
||||
|
||||
return states[state];
|
||||
}
|
||||
|
||||
GDB_DECLARE_REMOTE_COMMAND_HANDLER(GetMemRegions)
|
||||
{
|
||||
u32 address = 0;
|
||||
u32 posInBuffer = 0;
|
||||
u32 maxPosInBuffer = GDB_BUF_LEN / 2 - 35; ///< 35 is the maximum length of a formatted region
|
||||
Handle handle;
|
||||
MemInfo memi;
|
||||
PageInfo pagei;
|
||||
char outbuf[GDB_BUF_LEN / 2 + 1];
|
||||
|
||||
if(R_FAILED(svcOpenProcess(&handle, ctx->pid)))
|
||||
{
|
||||
posInBuffer = sprintf(outbuf, "Invalid process (wtf?)\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
while (address < 0x40000000 ///< Limit to check for regions
|
||||
&& posInBuffer < maxPosInBuffer
|
||||
&& R_SUCCEEDED(svcQueryProcessMemory(&memi, &pagei, handle, address)))
|
||||
{
|
||||
// Update the address for next region
|
||||
address = memi.base_addr + memi.size;
|
||||
|
||||
// If region isn't FREE then add it to the list
|
||||
if (memi.state != MEMSTATE_FREE)
|
||||
{
|
||||
const char *perm = FormatMemPerm(memi.perm);
|
||||
const char *state = FormatMemState(memi.state);
|
||||
|
||||
posInBuffer += sprintf(outbuf + posInBuffer, "%08X - %08X %s %s\n",
|
||||
memi.base_addr, address, perm, state);
|
||||
}
|
||||
}
|
||||
|
||||
svcCloseHandle(handle);
|
||||
|
||||
end:
|
||||
return GDB_SendHexPacket(ctx, outbuf, posInBuffer);
|
||||
}
|
||||
|
||||
GDB_DECLARE_REMOTE_COMMAND_HANDLER(FlushCaches)
|
||||
{
|
||||
if(ctx->commandData[0] != 0)
|
||||
|
||||
@@ -89,6 +89,16 @@ void initSystem()
|
||||
ProcessPatchesMenu_PatchUnpatchFSDirectly();
|
||||
__sync_init();
|
||||
__appInit();
|
||||
|
||||
// ROSALINA HACKJOB BEGIN
|
||||
// NORMAL APPS SHOULD NOT DO THIS, EVER
|
||||
u32 *tls = (u32 *)getThreadLocalStorage();
|
||||
memset(tls, 0, 0x80);
|
||||
tls[0] = 0x21545624;
|
||||
// ROSALINA HACKJOB END
|
||||
|
||||
// Rosalina specific:
|
||||
srvSetBlockingPolicy(true); // GetServiceHandle nonblocking if service port is full
|
||||
}
|
||||
|
||||
bool terminationRequest = false;
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "menus.h"
|
||||
#include "utils.h"
|
||||
#include "menus/n3ds.h"
|
||||
#include "menus/cheats.h"
|
||||
#include "minisoc.h"
|
||||
|
||||
u32 waitInputWithTimeout(u32 msec)
|
||||
@@ -142,20 +143,35 @@ void menuThreadMain(void)
|
||||
if(!isN3DS)
|
||||
{
|
||||
rosalinaMenu.nbItems--;
|
||||
for(u32 i = 2; i <= rosalinaMenu.nbItems; i++)
|
||||
for(u32 i = 3; i <= rosalinaMenu.nbItems; i++)
|
||||
rosalinaMenu.items[i] = rosalinaMenu.items[i+1];
|
||||
}
|
||||
else
|
||||
N3DSMenu_UpdateStatus();
|
||||
|
||||
bool isAcURegistered = false;
|
||||
|
||||
while(!terminationRequest)
|
||||
{
|
||||
if((HID_PAD & menuCombo) == menuCombo)
|
||||
{
|
||||
menuEnter();
|
||||
if(isN3DS) N3DSMenu_UpdateStatus();
|
||||
menuShow(&rosalinaMenu);
|
||||
menuLeave();
|
||||
if (!isAcURegistered)
|
||||
isAcURegistered = R_SUCCEEDED(srvIsServiceRegistered(&isAcURegistered, "ac:u"))
|
||||
&& isAcURegistered;
|
||||
|
||||
if (isAcURegistered)
|
||||
{
|
||||
menuEnter();
|
||||
if(isN3DS) N3DSMenu_UpdateStatus();
|
||||
menuShow(&rosalinaMenu);
|
||||
menuLeave();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (HID_PAD & 0xFFF) {
|
||||
Cheat_ApplyKeyCheats();
|
||||
}
|
||||
}
|
||||
svcSleepThread(50 * 1000 * 1000LL);
|
||||
}
|
||||
@@ -193,13 +209,16 @@ static void menuDraw(Menu *menu, u32 selected)
|
||||
s64 out;
|
||||
u32 version, commitHash;
|
||||
bool isRelease;
|
||||
bool isMcuHwcRegistered;
|
||||
|
||||
if(R_SUCCEEDED(mcuHwcInit()))
|
||||
if(R_SUCCEEDED(srvIsServiceRegistered(&isMcuHwcRegistered, "mcu::HWC")) && isMcuHwcRegistered && R_SUCCEEDED(mcuHwcInit()))
|
||||
{
|
||||
if(R_FAILED(mcuHwcGetBatteryLevel(&batteryLevel)))
|
||||
if(R_FAILED(MCUHWC_GetBatteryLevel(&batteryLevel)))
|
||||
batteryLevel = 255;
|
||||
mcuHwcExit();
|
||||
}
|
||||
else
|
||||
batteryLevel = 255;
|
||||
|
||||
svcGetSystemInfo(&out, 0x10000, 0);
|
||||
version = (u32)out;
|
||||
|
||||
@@ -41,8 +41,9 @@
|
||||
|
||||
Menu rosalinaMenu = {
|
||||
"Rosalina menu",
|
||||
.nbItems = 9,
|
||||
.nbItems = 10,
|
||||
{
|
||||
{ "Cheats...", METHOD, .method = &RosalinaMenu_Cheats },
|
||||
{ "Process list", METHOD, .method = &RosalinaMenu_ProcessList },
|
||||
{ "Take screenshot (slow!)", METHOD, .method = &RosalinaMenu_TakeScreenshot },
|
||||
{ "New 3DS menu...", MENU, .menu = &N3DSMenu },
|
||||
|
||||
1287
sysmodules/rosalina/source/menus/cheats.c
Normal file
1287
sysmodules/rosalina/source/menus/cheats.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -69,12 +69,10 @@ void DebuggerMenu_EnableDebugger(void)
|
||||
bool done = false, alreadyEnabled = gdbServer.super.running;
|
||||
Result res = 0;
|
||||
char buf[65];
|
||||
bool cantStart;
|
||||
Handle dummy;
|
||||
bool isSocURegistered;
|
||||
|
||||
res = OpenProcessByName("socket", &dummy);
|
||||
cantStart = R_FAILED(res);
|
||||
svcCloseHandle(dummy);
|
||||
res = srvIsServiceRegistered(&isSocURegistered, "soc:U");
|
||||
isSocURegistered = R_SUCCEEDED(res) && isSocURegistered;
|
||||
|
||||
Draw_Lock();
|
||||
Draw_ClearFramebuffer();
|
||||
@@ -88,7 +86,7 @@ void DebuggerMenu_EnableDebugger(void)
|
||||
|
||||
if(alreadyEnabled)
|
||||
Draw_DrawString(10, 30, COLOR_WHITE, "Already enabled!");
|
||||
else if(cantStart)
|
||||
else if(!isSocURegistered)
|
||||
Draw_DrawString(10, 30, COLOR_WHITE, "Can't start the debugger before the system has fi-\nnished loading.");
|
||||
else
|
||||
{
|
||||
|
||||
@@ -258,19 +258,19 @@ void MiscellaneousMenu_InputRedirection(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
Handle dummy;
|
||||
s64 dummyInfo;
|
||||
bool isN3DS = svcGetSystemInfo(&dummyInfo, 0x10001, 0) == 0;
|
||||
s64 dummyInfo;
|
||||
bool isN3DS = svcGetSystemInfo(&dummyInfo, 0x10001, 0) == 0;
|
||||
bool isSocURegistered;
|
||||
|
||||
res = OpenProcessByName("socket", &dummy);
|
||||
cantStart = R_FAILED(res);
|
||||
svcCloseHandle(dummy);
|
||||
res = srvIsServiceRegistered(&isSocURegistered, "soc:U");
|
||||
cantStart = R_FAILED(res) || !isSocURegistered;
|
||||
|
||||
if(!cantStart && isN3DS)
|
||||
{
|
||||
res = OpenProcessByName("ir", &dummy);
|
||||
cantStart = R_FAILED(res);
|
||||
svcCloseHandle(dummy);
|
||||
bool isIrRstRegistered;
|
||||
|
||||
res = srvIsServiceRegistered(&isIrRstRegistered, "ir:rst");
|
||||
cantStart = R_FAILED(res) || !isIrRstRegistered;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,7 +285,7 @@ void MiscellaneousMenu_InputRedirection(void)
|
||||
Draw_DrawString(10, 10, COLOR_TITLE, "Miscellaneous options menu");
|
||||
|
||||
if(!wasEnabled && cantStart)
|
||||
Draw_DrawString(10, 30, COLOR_WHITE, "Can't start the debugger before the system has fi-\nnished loading.");
|
||||
Draw_DrawString(10, 30, COLOR_WHITE, "Can't start the input redirection before the system\nhas finished loading.");
|
||||
else if(!wasEnabled)
|
||||
{
|
||||
Draw_DrawString(10, 30, COLOR_WHITE, "Starting InputRedirection...");
|
||||
|
||||
@@ -66,9 +66,9 @@ void SysConfigMenu_ToggleLEDs(void)
|
||||
{
|
||||
mcuHwcInit();
|
||||
u8 result;
|
||||
mcuHwcReadRegister(0x28, &result, 1);
|
||||
MCUHWC_ReadRegister(0x28, &result, 1);
|
||||
result = ~result;
|
||||
mcuHwcWriteRegister(0x28, &result, 1);
|
||||
MCUHWC_WriteRegister(0x28, &result, 1);
|
||||
mcuHwcExit();
|
||||
}
|
||||
else if(pressed & BUTTON_B)
|
||||
|
||||
@@ -80,6 +80,18 @@ Result miniSocInit()
|
||||
|
||||
u32 tmp = 0;
|
||||
Result ret = 0;
|
||||
bool isSocURegistered;
|
||||
|
||||
ret = srvIsServiceRegistered(&isSocURegistered, "soc:U");
|
||||
if(ret != 0) goto cleanup;
|
||||
if(!isSocURegistered)
|
||||
{
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = srvGetServiceHandle(&SOCU_handle, "soc:U");
|
||||
if(ret != 0) goto cleanup;
|
||||
|
||||
ret = svcControlMemory(&tmp, socContextAddr, 0, socContextSize, MEMOP_ALLOC, MEMPERM_READ | MEMPERM_WRITE);
|
||||
if(ret != 0) goto cleanup;
|
||||
@@ -89,8 +101,7 @@ Result miniSocInit()
|
||||
ret = svcCreateMemoryBlock(&socMemhandle, (u32)socContextAddr, socContextSize, 0, 3);
|
||||
if(ret != 0) goto cleanup;
|
||||
|
||||
ret = srvGetServiceHandle(&SOCU_handle, "soc:U");
|
||||
if(ret != 0) goto cleanup;
|
||||
|
||||
|
||||
ret = SOCU_Initialize(socMemhandle, socContextSize);
|
||||
if(ret != 0) goto cleanup;
|
||||
|
||||
@@ -135,33 +135,30 @@ void server_bind(struct sock_server *serv, u16 port)
|
||||
server_sockfd = socSocket(AF_INET, SOCK_STREAM, 0);
|
||||
}
|
||||
|
||||
if(server_sockfd != -1)
|
||||
struct sockaddr_in saddr;
|
||||
saddr.sin_family = AF_INET;
|
||||
saddr.sin_port = htons(port);
|
||||
saddr.sin_addr.s_addr = gethostid();
|
||||
|
||||
res = socBind(server_sockfd, (struct sockaddr*)&saddr, sizeof(struct sockaddr_in));
|
||||
|
||||
if(res == 0)
|
||||
{
|
||||
struct sockaddr_in saddr;
|
||||
saddr.sin_family = AF_INET;
|
||||
saddr.sin_port = htons(port);
|
||||
saddr.sin_addr.s_addr = gethostid();
|
||||
|
||||
res = socBind(server_sockfd, (struct sockaddr*)&saddr, sizeof(struct sockaddr_in));
|
||||
|
||||
res = socListen(server_sockfd, 2);
|
||||
if(res == 0)
|
||||
{
|
||||
res = socListen(server_sockfd, 2);
|
||||
if(res == 0)
|
||||
{
|
||||
int idx = serv->nfds;
|
||||
serv->nfds++;
|
||||
serv->poll_fds[idx].fd = server_sockfd;
|
||||
serv->poll_fds[idx].events = POLLIN;
|
||||
int idx = serv->nfds;
|
||||
serv->nfds++;
|
||||
serv->poll_fds[idx].fd = server_sockfd;
|
||||
serv->poll_fds[idx].events = POLLIN;
|
||||
|
||||
struct sock_ctx *new_ctx = server_alloc_server_ctx(serv);
|
||||
memcpy(&new_ctx->addr_in, &saddr, sizeof(struct sockaddr_in));
|
||||
new_ctx->type = SOCK_SERVER;
|
||||
new_ctx->sockfd = server_sockfd;
|
||||
new_ctx->n = 0;
|
||||
new_ctx->i = idx;
|
||||
serv->ctx_ptrs[idx] = new_ctx;
|
||||
}
|
||||
struct sock_ctx *new_ctx = server_alloc_server_ctx(serv);
|
||||
memcpy(&new_ctx->addr_in, &saddr, sizeof(struct sockaddr_in));
|
||||
new_ctx->type = SOCK_SERVER;
|
||||
new_ctx->sockfd = server_sockfd;
|
||||
new_ctx->n = 0;
|
||||
new_ctx->i = idx;
|
||||
serv->ctx_ptrs[idx] = new_ctx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,13 +58,16 @@ Result UnregisterProcess(u32 pid)
|
||||
svcCloseHandle(processData->notificationSemaphore);
|
||||
|
||||
// Unregister the services registered by the process
|
||||
for(u32 i = 0; i < nbServices; i++)
|
||||
u32 i = 0;
|
||||
while(i < nbServices)
|
||||
{
|
||||
if(servicesInfo[i].pid == pid)
|
||||
{
|
||||
svcCloseHandle(servicesInfo[i].clientPort);
|
||||
servicesInfo[i] = servicesInfo[--nbServices];
|
||||
}
|
||||
else
|
||||
++i;
|
||||
}
|
||||
|
||||
moveNode(processData, &freeProcessDataList, false);
|
||||
|
||||
Reference in New Issue
Block a user