Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ea3e45d40a | ||
|
|
8daf3ebe3f | ||
|
|
7ad55ed61e | ||
|
|
96e46b2234 | ||
|
|
094b88b6aa | ||
|
|
03a6e343db | ||
|
|
b42f9ffb41 | ||
|
|
39280e397a | ||
|
|
887707ea87 | ||
|
|
279f39bc13 | ||
|
|
b7b734bad1 | ||
|
|
d01d9b53f2 | ||
|
|
c542bc5cf3 | ||
|
|
1f5b824c27 | ||
|
|
cb84a6c7ea | ||
|
|
61564e5fcf | ||
|
|
a437e533f5 | ||
|
|
6b88953517 | ||
|
|
9b9f784c26 | ||
|
|
6dfb33191f | ||
|
|
078fce4b3d |
49
Makefile
49
Makefile
@@ -12,7 +12,7 @@ ifneq ($(PYTHON_VER_MAJOR), 3)
|
|||||||
PYTHON3 := py -3
|
PYTHON3 := py -3
|
||||||
endif
|
endif
|
||||||
|
|
||||||
name := ReiNand
|
name := AuReiNand
|
||||||
|
|
||||||
dir_source := source
|
dir_source := source
|
||||||
dir_data := data
|
dir_data := data
|
||||||
@@ -26,7 +26,7 @@ dir_loader := loader
|
|||||||
|
|
||||||
ASFLAGS := -mlittle-endian -mcpu=arm946e-s -march=armv5te
|
ASFLAGS := -mlittle-endian -mcpu=arm946e-s -march=armv5te
|
||||||
CFLAGS := -Wall -Wextra -MMD -MP -marm $(ASFLAGS) -fno-builtin -fshort-wchar -std=c11 -Wno-main -O2 -ffast-math
|
CFLAGS := -Wall -Wextra -MMD -MP -marm $(ASFLAGS) -fno-builtin -fshort-wchar -std=c11 -Wno-main -O2 -ffast-math
|
||||||
FLAGS := name=$(name).dat dir_out=$(abspath $(dir_out)) ICON=$(abspath icon.png) --no-print-directory
|
FLAGS := name=$(name).dat dir_out=$(abspath $(dir_out)) ICON=$(abspath icon.png) APP_DESCRIPTION="Noob-friendly 3DS CFW." APP_AUTHOR="Reisyukaku/Aurora Wright" --no-print-directory
|
||||||
|
|
||||||
objects_cfw = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
|
objects_cfw = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
|
||||||
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
|
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
|
||||||
@@ -34,7 +34,7 @@ objects_cfw = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
|
|||||||
|
|
||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
all: launcher a9lh emunand reboot ninjhax loader
|
all: launcher a9lh ninjhax
|
||||||
|
|
||||||
.PHONY: launcher
|
.PHONY: launcher
|
||||||
launcher: $(dir_out)/$(name).dat
|
launcher: $(dir_out)/$(name).dat
|
||||||
@@ -42,54 +42,43 @@ launcher: $(dir_out)/$(name).dat
|
|||||||
.PHONY: a9lh
|
.PHONY: a9lh
|
||||||
a9lh: $(dir_out)/arm9loaderhax.bin
|
a9lh: $(dir_out)/arm9loaderhax.bin
|
||||||
|
|
||||||
.PHONY: emunand
|
|
||||||
emunand: $(dir_out)/rei/emunand/emunand.bin
|
|
||||||
|
|
||||||
.PHONY: reboot
|
|
||||||
reboot: $(dir_out)/rei/reboot/reboot.bin
|
|
||||||
|
|
||||||
.PHONY: ninjhax
|
.PHONY: ninjhax
|
||||||
ninjhax: $(dir_out)/3ds/$(name)
|
ninjhax: $(dir_out)/3ds/$(name)
|
||||||
|
|
||||||
.PHONY: loader
|
|
||||||
loader: $(dir_out)/rei/loader.bin
|
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
@$(MAKE) $(FLAGS) -C $(dir_mset) clean
|
@$(MAKE) $(FLAGS) -C $(dir_mset) clean
|
||||||
@$(MAKE) $(FLAGS) -C $(dir_ninjhax) clean
|
@$(MAKE) $(FLAGS) -C $(dir_ninjhax) clean
|
||||||
@rm -rf $(dir_out) $(dir_build)
|
@rm -rf $(dir_out) $(dir_build)
|
||||||
@cd $(dir_loader) && make clean
|
@$(MAKE) -C $(dir_loader) clean
|
||||||
|
|
||||||
$(dir_out)/$(name).dat: $(dir_build)/main.bin $(dir_out)/rei
|
$(dir_out)/$(name).dat: $(dir_build)/main.bin $(dir_out)
|
||||||
@$(MAKE) $(FLAGS) -C $(dir_mset) launcher
|
@$(MAKE) $(FLAGS) -C $(dir_mset) launcher
|
||||||
dd if=$(dir_build)/main.bin of=$@ bs=512 seek=144
|
dd if=$(dir_build)/main.bin of=$@ bs=512 seek=144
|
||||||
|
|
||||||
$(dir_out)/arm9loaderhax.bin: $(dir_build)/main.bin $(dir_out)/rei
|
$(dir_out)/arm9loaderhax.bin: $(dir_build)/main.bin $(dir_out)
|
||||||
@cp -av $(dir_build)/main.bin $@
|
@cp -av $(dir_build)/main.bin $@
|
||||||
|
|
||||||
$(dir_out)/3ds/$(name):
|
$(dir_out)/3ds/$(name): $(dir_out)
|
||||||
@mkdir -p "$(dir_out)/3ds/$(name)"
|
@mkdir -p "$(dir_out)/3ds/$(name)"
|
||||||
@$(MAKE) $(FLAGS) -C $(dir_ninjhax)
|
@$(MAKE) $(FLAGS) -C $(dir_ninjhax)
|
||||||
@mv $(dir_out)/$(name).3dsx $@
|
@mv $(dir_out)/$(name).3dsx $@
|
||||||
@mv $(dir_out)/$(name).smdh $@
|
@mv $(dir_out)/$(name).smdh $@
|
||||||
|
|
||||||
$(dir_out)/rei:
|
$(dir_out):
|
||||||
@mkdir -p "$(dir_out)/rei"
|
@mkdir -p "$(dir_out)/aurei/payloads"
|
||||||
|
|
||||||
$(dir_out)/rei/emunand/emunand.bin: $(dir_emu)/emuCode.s
|
$(dir_build)/patches.h: $(dir_emu)/emuCode.s $(dir_reboot)/rebootCode.s
|
||||||
|
@mkdir -p "$(dir_build)"
|
||||||
@armips $<
|
@armips $<
|
||||||
@mkdir -p "$(dir_out)/rei/emunand"
|
@mv emunand.bin $(dir_build)
|
||||||
@mv emunand.bin $@
|
@armips $(word 2,$^)
|
||||||
|
@mv reboot.bin $(dir_build)
|
||||||
|
@bin2c -o $@ -n emunand $(dir_build)/emunand.bin -n reboot $(dir_build)/reboot.bin
|
||||||
|
|
||||||
$(dir_out)/rei/reboot/reboot.bin: $(dir_reboot)/rebootCode.s
|
$(dir_build)/loader.h: $(dir_loader)/Makefile
|
||||||
@armips $<
|
@$(MAKE) -C $(dir_loader)
|
||||||
@mkdir -p "$(dir_out)/rei/reboot"
|
@bin2c -o $@ -n loader $(dir_loader)/loader.bin
|
||||||
@mv reboot.bin $@
|
|
||||||
|
|
||||||
$(dir_out)/rei/loader.bin: $(dir_out)/rei $(dir_loader)/Makefile
|
|
||||||
@cd $(dir_loader) && make
|
|
||||||
@mv $(dir_loader)/loader.bin $@
|
|
||||||
|
|
||||||
$(dir_build)/main.bin: $(dir_build)/main.elf
|
$(dir_build)/main.bin: $(dir_build)/main.elf
|
||||||
$(OC) -S -O binary $< $@
|
$(OC) -S -O binary $< $@
|
||||||
@@ -98,7 +87,7 @@ $(dir_build)/main.elf: $(objects_cfw)
|
|||||||
# FatFs requires libgcc for __aeabi_uidiv
|
# FatFs requires libgcc for __aeabi_uidiv
|
||||||
$(CC) -nostartfiles $(LDFLAGS) -T linker.ld $(OUTPUT_OPTION) $^
|
$(CC) -nostartfiles $(LDFLAGS) -T linker.ld $(OUTPUT_OPTION) $^
|
||||||
|
|
||||||
$(dir_build)/%.o: $(dir_source)/%.c
|
$(dir_build)/%.o: $(dir_source)/%.c $(dir_build)/patches.h $(dir_build)/loader.h
|
||||||
@mkdir -p "$(@D)"
|
@mkdir -p "$(@D)"
|
||||||
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
.nds
|
.arm.little
|
||||||
|
|
||||||
sdmmc equ 0x434D4453 ;dummy
|
.create "emunand.bin", 0
|
||||||
|
|
||||||
.create "emunand.bin", 0x0801A5C0
|
|
||||||
.org 0x0801A5C0
|
|
||||||
.arm
|
.arm
|
||||||
nand_sd:
|
nand_sd:
|
||||||
; Original code that still needs to be executed.
|
; Original code that still needs to be executed.
|
||||||
@@ -15,7 +12,7 @@ nand_sd:
|
|||||||
|
|
||||||
; If we're already trying to access the SD, return.
|
; If we're already trying to access the SD, return.
|
||||||
ldr r2, [r0, #4]
|
ldr r2, [r0, #4]
|
||||||
ldr r1, =sdmmc
|
ldr r1, [sdmmc]
|
||||||
cmp r2, r1
|
cmp r2, r1
|
||||||
beq nand_sd_ret
|
beq nand_sd_ret
|
||||||
|
|
||||||
@@ -23,12 +20,10 @@ nand_sd:
|
|||||||
ldr r2, [r0, #8] ; Get sector to read
|
ldr r2, [r0, #8] ; Get sector to read
|
||||||
cmp r2, #0 ; For GW compatibility, see if we're trying to read the ncsd header (sector 0)
|
cmp r2, #0 ; For GW compatibility, see if we're trying to read the ncsd header (sector 0)
|
||||||
|
|
||||||
ldr r3, =nand_offset
|
ldr r3, [nand_offset]
|
||||||
ldr r3, [r3]
|
|
||||||
add r2, r3 ; Add the offset to the NAND in the SD.
|
add r2, r3 ; Add the offset to the NAND in the SD.
|
||||||
|
|
||||||
ldreq r3, =ncsd_header_offset
|
ldreq r3, [ncsd_header_offset]
|
||||||
ldreq r3, [r3]
|
|
||||||
addeq r2, r3 ; If we're reading the ncsd header, add the offset of that sector.
|
addeq r2, r3 ; If we're reading the ncsd header, add the offset of that sector.
|
||||||
|
|
||||||
str r2, [r0, #8] ; Store sector to read
|
str r2, [r0, #8] ; Store sector to read
|
||||||
@@ -45,6 +40,7 @@ nand_sd:
|
|||||||
add r0, #4
|
add r0, #4
|
||||||
bx r0
|
bx r0
|
||||||
.pool
|
.pool
|
||||||
|
sdmmc: .ascii "SDMC"
|
||||||
nand_offset: .ascii "NAND" ; for rednand this should be 1
|
nand_offset: .ascii "NAND" ; for rednand this should be 1
|
||||||
ncsd_header_offset: .ascii "NCSD" ; depends on nand manufacturer + emunand type (GW/RED)
|
ncsd_header_offset: .ascii "NCSD" ; depends on nand manufacturer + emunand type (GW/RED)
|
||||||
.close
|
.close
|
||||||
|
|||||||
BIN
icon.png
BIN
icon.png
Binary file not shown.
|
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 3.1 KiB |
@@ -32,7 +32,7 @@ INCLUDES := include source/fatfs source/fatfs/sdmmc
|
|||||||
ARCH := -mthumb -mthumb-interwork
|
ARCH := -mthumb -mthumb-interwork
|
||||||
|
|
||||||
CFLAGS := -g -Wall -O2\
|
CFLAGS := -g -Wall -O2\
|
||||||
-march=armv5te -mtune=arm946e-s -fomit-frame-pointer\
|
-march=armv5te -mtune=arm946e-s\
|
||||||
-ffast-math -Wno-main -std=c99\
|
-ffast-math -Wno-main -std=c99\
|
||||||
$(ARCH)
|
$(ARCH)
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ DRESULT disk_read (
|
|||||||
DRESULT disk_write (
|
DRESULT disk_write (
|
||||||
__attribute__((unused))
|
__attribute__((unused))
|
||||||
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
||||||
const BYTE *buff, /* Data to be written */
|
const BYTE *buff, /* Data to be written */
|
||||||
DWORD sector, /* Sector address in LBA */
|
DWORD sector, /* Sector address in LBA */
|
||||||
UINT count /* Number of sectors to write */
|
UINT count /* Number of sectors to write */
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -811,7 +811,7 @@ FRESULT sync_fs ( /* FR_OK: successful, FR_DISK_ERR: failed */
|
|||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* Hidden API for hacks and disk tools */
|
/* Hidden API for hacks and disk tools */
|
||||||
|
|
||||||
DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */
|
static DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */
|
||||||
FATFS* fs, /* File system object */
|
FATFS* fs, /* File system object */
|
||||||
DWORD clst /* Cluster# to be converted */
|
DWORD clst /* Cluster# to be converted */
|
||||||
)
|
)
|
||||||
@@ -829,7 +829,7 @@ DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */
|
|||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* Hidden API for hacks and disk tools */
|
/* Hidden API for hacks and disk tools */
|
||||||
|
|
||||||
DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x0FFFFFFF:Cluster status */
|
static DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x0FFFFFFF:Cluster status */
|
||||||
FATFS* fs, /* File system object */
|
FATFS* fs, /* File system object */
|
||||||
DWORD clst /* FAT index number (cluster number) to get the value */
|
DWORD clst /* FAT index number (cluster number) to get the value */
|
||||||
)
|
)
|
||||||
@@ -884,7 +884,7 @@ DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x0FFFFFFF:Cluste
|
|||||||
/* Hidden API for hacks and disk tools */
|
/* Hidden API for hacks and disk tools */
|
||||||
|
|
||||||
#if !_FS_READONLY
|
#if !_FS_READONLY
|
||||||
FRESULT put_fat (
|
static FRESULT put_fat (
|
||||||
FATFS* fs, /* File system object */
|
FATFS* fs, /* File system object */
|
||||||
DWORD clst, /* FAT index number (cluster number) to be changed */
|
DWORD clst, /* FAT index number (cluster number) to be changed */
|
||||||
DWORD val /* New value to be set to the entry */
|
DWORD val /* New value to be set to the entry */
|
||||||
|
|||||||
@@ -2,8 +2,6 @@
|
|||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
#include "sdmmc.h"
|
#include "sdmmc.h"
|
||||||
#include "delay.h"
|
#include "delay.h"
|
||||||
|
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
#define I2C1_REG_OFF 0x10161000
|
|
||||||
#define I2C2_REG_OFF 0x10144000
|
|
||||||
#define I2C3_REG_OFF 0x10148000
|
|
||||||
|
|
||||||
#define I2C_REG_DATA 0
|
|
||||||
#define I2C_REG_CNT 1
|
|
||||||
#define I2C_REG_CNTEX 2
|
|
||||||
#define I2C_REG_SCL 4
|
|
||||||
|
|
||||||
#define I2C_DEV_MCU 3
|
|
||||||
#define I2C_DEV_GYRO 10
|
|
||||||
#define I2C_DEV_IR 13
|
|
||||||
|
|
||||||
u8 i2cGetDeviceBusId(u8 device_id);
|
|
||||||
u8 i2cGetDeviceRegAddr(u8 device_id);
|
|
||||||
|
|
||||||
vu8* i2cGetDataReg(u8 bus_id);
|
|
||||||
vu8* i2cGetCntReg(u8 bus_id);
|
|
||||||
|
|
||||||
void i2cWaitBusy(u8 bus_id);
|
|
||||||
bool i2cGetResult(u8 bus_id);
|
|
||||||
u8 i2cGetData(u8 bus_id);
|
|
||||||
void i2cStop(u8 bus_id, u8 arg0);
|
|
||||||
|
|
||||||
bool i2cSelectDevice(u8 bus_id, u8 dev_reg);
|
|
||||||
bool i2cSelectRegister(u8 bus_id, u8 reg);
|
|
||||||
|
|
||||||
u8 i2cReadRegister(u8 dev_id, u8 reg);
|
|
||||||
bool i2cWriteRegister(u8 dev_id, u8 reg, u8 data);
|
|
||||||
|
|
||||||
bool i2cReadRegisterBuffer(unsigned int dev_id, int reg, u8* buffer, size_t buf_size);
|
|
||||||
@@ -1,11 +1,10 @@
|
|||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "buttons.h"
|
#include "buttons.h"
|
||||||
#include "screeninit.h"
|
|
||||||
#include "fatfs/ff.h"
|
#include "fatfs/ff.h"
|
||||||
|
|
||||||
#define PAYLOAD_ADDRESS 0x23F00000
|
#define PAYLOAD_ADDRESS 0x23F00000
|
||||||
|
|
||||||
u32 loadPayload(const char *path){
|
static u32 loadPayload(const char *path){
|
||||||
FIL payload;
|
FIL payload;
|
||||||
unsigned int br;
|
unsigned int br;
|
||||||
if(f_open(&payload, path, FA_READ) == FR_OK)
|
if(f_open(&payload, path, FA_READ) == FR_OK)
|
||||||
@@ -19,24 +18,22 @@ u32 loadPayload(const char *path){
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void main(){
|
void main(void){
|
||||||
FATFS fs;
|
FATFS fs;
|
||||||
f_mount(&fs, "0:", 1);
|
f_mount(&fs, "0:", 1);
|
||||||
|
|
||||||
//Get pressed buttons
|
//Get pressed buttons
|
||||||
u16 pressed = HID_PAD;
|
u16 pressed = HID_PAD;
|
||||||
|
|
||||||
if(((pressed & BUTTON_B) && loadPayload("/rei/payloads/b.bin")) ||
|
if(((pressed & BUTTON_B) && loadPayload("/aurei/payloads/b.bin")) ||
|
||||||
((pressed & BUTTON_X) && loadPayload("/rei/payloads/x.bin")) ||
|
((pressed & BUTTON_X) && loadPayload("/aurei/payloads/x.bin")) ||
|
||||||
((pressed & BUTTON_Y) && loadPayload("/rei/payloads/y.bin")) ||
|
((pressed & BUTTON_Y) && loadPayload("/aurei/payloads/y.bin")) ||
|
||||||
((pressed & BUTTON_SELECT) && loadPayload("/rei/payloads/select.bin")) ||
|
((pressed & BUTTON_SELECT) && loadPayload("/aurei/payloads/select.bin")) ||
|
||||||
((pressed & BUTTON_START) && loadPayload("/rei/payloads/start.bin")) ||
|
((pressed & BUTTON_START) && loadPayload("/aurei/payloads/start.bin")) ||
|
||||||
((pressed & BUTTON_RIGHT) && loadPayload("/rei/payloads/right.bin")) ||
|
((pressed & BUTTON_RIGHT) && loadPayload("/aurei/payloads/right.bin")) ||
|
||||||
((pressed & BUTTON_LEFT) && loadPayload("/rei/payloads/left.bin")) ||
|
((pressed & BUTTON_LEFT) && loadPayload("/aurei/payloads/left.bin")) ||
|
||||||
((pressed & BUTTON_UP) && loadPayload("/rei/payloads/up.bin")) ||
|
((pressed & BUTTON_UP) && loadPayload("/aurei/payloads/up.bin")) ||
|
||||||
((pressed & BUTTON_DOWN) && loadPayload("/rei/payloads/down.bin")) ||
|
((pressed & BUTTON_DOWN) && loadPayload("/aurei/payloads/down.bin")) ||
|
||||||
loadPayload("/rei/payloads/default.bin")){
|
loadPayload("/aurei/payloads/default.bin"))
|
||||||
initLCD();
|
|
||||||
((void (*)())PAYLOAD_ADDRESS)();
|
((void (*)())PAYLOAD_ADDRESS)();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "types.h"
|
|
||||||
|
|
||||||
void initLCD();
|
|
||||||
@@ -2,6 +2,9 @@
|
|||||||
.align 4
|
.align 4
|
||||||
.global _start
|
.global _start
|
||||||
_start:
|
_start:
|
||||||
|
@ Fix payloads like Decrypt9
|
||||||
|
mov r0, #0x5
|
||||||
|
mcr p15, 0, r0, c3, c0, 0 @ data bufferable
|
||||||
|
|
||||||
@ Flush caches
|
@ Flush caches
|
||||||
mov r0, #0
|
mov r0, #0
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
.nds
|
.arm.little
|
||||||
.create "reboot.bin", 0
|
|
||||||
|
|
||||||
byteswritten equ 0x2000E000
|
byteswritten equ 0x2000E000
|
||||||
externalFirm equ 0x2000A000
|
|
||||||
kernelCode equ 0x080F0000
|
kernelCode equ 0x080F0000
|
||||||
buffer equ 0x24000000
|
buffer equ 0x24000000
|
||||||
fileOpen equ 0x4E45504F ;dummy
|
fileOpen equ 0x4E45504F ;dummy
|
||||||
|
|
||||||
|
.create "reboot.bin", 0
|
||||||
.arm
|
.arm
|
||||||
//Code jumps here right after the sprintf call
|
//Code jumps here right after the sprintf call
|
||||||
process9Reboot:
|
process9Reboot:
|
||||||
@@ -34,18 +33,16 @@ process9Reboot:
|
|||||||
ldreq r1, =(FileName - OpenFirm - 12)
|
ldreq r1, =(FileName - OpenFirm - 12)
|
||||||
addeq r1, pc
|
addeq r1, pc
|
||||||
addne r1, sp, #0x3A8-0x70
|
addne r1, sp, #0x3A8-0x70
|
||||||
ldr r0, =externalFirm
|
|
||||||
moveq r2, #1
|
moveq r2, #1
|
||||||
movne r2, #0
|
movne r2, #0
|
||||||
str r2, [r0]
|
str r2, [externalFirm]
|
||||||
mov r2, #1
|
mov r2, #1
|
||||||
add r0, r7, #8
|
add r0, r7, #8
|
||||||
ldr r6, =fileOpen
|
ldr r6, =fileOpen
|
||||||
blx r6
|
blx r6
|
||||||
|
|
||||||
SeekFirm:
|
SeekFirm:
|
||||||
ldr r0, =externalFirm
|
ldr r0, [externalFirm]
|
||||||
ldr r0, [r0]
|
|
||||||
cmp r0, #1
|
cmp r0, #1
|
||||||
moveq r0, r7
|
moveq r0, r7
|
||||||
ldreq r1, =byteswritten
|
ldreq r1, =byteswritten
|
||||||
@@ -99,9 +96,12 @@ Memcpy:
|
|||||||
BX LR
|
BX LR
|
||||||
|
|
||||||
FileName:
|
FileName:
|
||||||
.dcw "sdmc:/rei/patched_firmware_sys.bin"
|
.dcw "sdmc:/aurei/patched_firmware_sys.bin"
|
||||||
.word 0x0
|
.word 0x0
|
||||||
|
|
||||||
|
externalFirm:
|
||||||
|
.word 0x2000A000
|
||||||
|
|
||||||
.pool
|
.pool
|
||||||
|
|
||||||
// Kernel Code
|
// Kernel Code
|
||||||
|
|||||||
21
source/buttons.h
Normal file
21
source/buttons.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* buttons.h
|
||||||
|
* by Aurora Wright
|
||||||
|
* Copyright (c) 2016 All Rights Reserved
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
#define HID_PAD ((~*(vu16 *)0x10146000) & 0xFFF)
|
||||||
|
#define BUTTON_R1 (1 << 8)
|
||||||
|
#define BUTTON_L1 (1 << 9)
|
||||||
|
#define BUTTON_L1R1 (BUTTON_R1 | BUTTON_L1)
|
||||||
|
#define BUTTON_A 1
|
||||||
|
#define BUTTON_B (1 << 1)
|
||||||
|
#define BUTTON_UP (1 << 6)
|
||||||
|
#define BUTTON_DOWN (1 << 7)
|
||||||
|
#define BUTTON_START (1 << 3)
|
||||||
|
#define BUTTON_SELECT (1 << 2)
|
||||||
|
#define SAFEMODE (BUTTON_L1R1 | BUTTON_A | (1 << 6))
|
||||||
@@ -1,4 +1,10 @@
|
|||||||
// From http://github.com/b1l1s/ctr
|
/*
|
||||||
|
* crypto.c
|
||||||
|
* by Reisyukaku / Aurora Wright
|
||||||
|
* Crypto libs from http://github.com/b1l1s/ctr
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 All Rights Reserved
|
||||||
|
*/
|
||||||
|
|
||||||
#include "crypto.h"
|
#include "crypto.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
@@ -243,14 +249,16 @@ static void getNandCTR(u8 *buf, u32 console){
|
|||||||
void nandFirm0(u8 *outbuf, u32 size, u32 console){
|
void nandFirm0(u8 *outbuf, u32 size, u32 console){
|
||||||
u8 CTR[0x10];
|
u8 CTR[0x10];
|
||||||
getNandCTR(CTR, console);
|
getNandCTR(CTR, console);
|
||||||
aes_advctr(CTR, 0x0B130000/0x10, AES_INPUT_BE | AES_INPUT_NORMAL);
|
|
||||||
sdmmc_nand_readsectors(0x0B130000 / 0x200, size / 0x200, outbuf);
|
sdmmc_nand_readsectors(0x0B130000 / 0x200, size / 0x200, outbuf);
|
||||||
|
|
||||||
|
aes_advctr(CTR, 0x0B130000/0x10, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
aes_use_keyslot(0x06);
|
aes_use_keyslot(0x06);
|
||||||
aes(outbuf, outbuf, size / AES_BLOCK_SIZE, CTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
aes(outbuf, outbuf, size / AES_BLOCK_SIZE, CTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Decrypts the N3DS arm9bin
|
//Decrypts the N3DS arm9bin
|
||||||
void decArm9Bin(u8 *armHdr, u32 mode){
|
void decryptArm9Bin(u8 *arm9Section, u32 mode){
|
||||||
|
|
||||||
//Firm keys
|
//Firm keys
|
||||||
u8 keyY[0x10];
|
u8 keyY[0x10];
|
||||||
@@ -258,11 +266,11 @@ void decArm9Bin(u8 *armHdr, u32 mode){
|
|||||||
u8 slot = mode ? 0x16 : 0x15;
|
u8 slot = mode ? 0x16 : 0x15;
|
||||||
|
|
||||||
//Setup keys needed for arm9bin decryption
|
//Setup keys needed for arm9bin decryption
|
||||||
memcpy(keyY, armHdr+0x10, 0x10);
|
memcpy(keyY, arm9Section+0x10, 0x10);
|
||||||
memcpy(CTR, armHdr+0x20, 0x10);
|
memcpy(CTR, arm9Section+0x20, 0x10);
|
||||||
u32 size = 0;
|
u32 size = 0;
|
||||||
//http://stackoverflow.com/questions/12791077/atoi-implementation-in-c
|
//http://stackoverflow.com/questions/12791077/atoi-implementation-in-c
|
||||||
for(u8 *tmp = armHdr+0x30; *tmp; tmp++)
|
for(u8 *tmp = arm9Section+0x30; *tmp; tmp++)
|
||||||
size = (size<<3)+(size<<1)+(*tmp)-'0';
|
size = (size<<3)+(size<<1)+(*tmp)-'0';
|
||||||
|
|
||||||
if(mode){
|
if(mode){
|
||||||
@@ -271,7 +279,7 @@ void decArm9Bin(u8 *armHdr, u32 mode){
|
|||||||
//Set 0x11 to key2 for the arm9bin and misc keys
|
//Set 0x11 to key2 for the arm9bin and misc keys
|
||||||
aes_setkey(0x11, key2, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
|
aes_setkey(0x11, key2, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
aes_use_keyslot(0x11);
|
aes_use_keyslot(0x11);
|
||||||
aes(keyX, armHdr+0x60, 1, NULL, AES_ECB_DECRYPT_MODE, 0);
|
aes(keyX, arm9Section+0x60, 1, NULL, AES_ECB_DECRYPT_MODE, 0);
|
||||||
aes_setkey(slot, keyX, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
aes_setkey(slot, keyX, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,13 +288,13 @@ void decArm9Bin(u8 *armHdr, u32 mode){
|
|||||||
aes_use_keyslot(slot);
|
aes_use_keyslot(slot);
|
||||||
|
|
||||||
//Decrypt arm9bin
|
//Decrypt arm9bin
|
||||||
aes(armHdr+0x800, armHdr+0x800, size/AES_BLOCK_SIZE, CTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
aes(arm9Section+0x800, arm9Section+0x800, size/AES_BLOCK_SIZE, CTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Sets the N3DS 9.6 KeyXs
|
//Sets the N3DS 9.6 KeyXs
|
||||||
void setKeyXs(u8 *armHdr){
|
void setKeyXs(u8 *arm9Section){
|
||||||
|
|
||||||
u8 *keyData = armHdr+0x89814;
|
u8 *keyData = arm9Section+0x89814;
|
||||||
u8 *decKey = keyData+0x10;
|
u8 *decKey = keyData+0x10;
|
||||||
|
|
||||||
//Set keys 0x19..0x1F keyXs
|
//Set keys 0x19..0x1F keyXs
|
||||||
|
|||||||
@@ -1,4 +1,10 @@
|
|||||||
// From http://github.com/b1l1s/ctr
|
/*
|
||||||
|
* crypto.h
|
||||||
|
* by Reisyukaku / Aurora Wright
|
||||||
|
* Crypto libs from http://github.com/b1l1s/ctr
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 All Rights Reserved
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@@ -49,5 +55,5 @@
|
|||||||
|
|
||||||
//NAND/FIRM stuff
|
//NAND/FIRM stuff
|
||||||
void nandFirm0(u8 *outbuf, u32 size, u32 console);
|
void nandFirm0(u8 *outbuf, u32 size, u32 console);
|
||||||
void decArm9Bin(u8 *armHdr, u32 mode);
|
void decryptArm9Bin(u8 *arm9Section, u32 mode);
|
||||||
void setKeyXs(u8 *armHdr);
|
void setKeyXs(u8 *arm9Section);
|
||||||
@@ -1,12 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* draw.c
|
* draw.c
|
||||||
* by Reisyukaku
|
* by Reisyukaku / Aurora Wright
|
||||||
* Copyright (c) 2015 All Rights Reserved
|
* Code to print to the screen by mid-kid @CakesFW
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 All Rights Reserved
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
#include "font.h"
|
||||||
|
|
||||||
|
#define SCREEN_TOP_WIDTH 400
|
||||||
|
#define SCREEN_TOP_HEIGHT 240
|
||||||
|
|
||||||
static const struct fb {
|
static const struct fb {
|
||||||
u8 *top_left;
|
u8 *top_left;
|
||||||
@@ -14,35 +20,63 @@ static const struct fb {
|
|||||||
u8 *bottom;
|
u8 *bottom;
|
||||||
} *const fb = (struct fb *)0x23FFFE00;
|
} *const fb = (struct fb *)0x23FFFE00;
|
||||||
|
|
||||||
void __attribute__((naked)) shutdownLCD(void){
|
static int strlen(const char *string){
|
||||||
|
char *stringEnd = (char *)string;
|
||||||
vu32 *const arm11 = (u32 *)0x1FFFFFF8;
|
while(*stringEnd) stringEnd++;
|
||||||
|
return stringEnd - string;
|
||||||
//Clear ARM11 entry offset
|
|
||||||
*arm11 = 0;
|
|
||||||
|
|
||||||
//Shutdown LCDs
|
|
||||||
*(vu32 *)0x10202A44 = 0;
|
|
||||||
*(vu32 *)0x10202244 = 0;
|
|
||||||
*(vu32 *)0x10202014 = 0;
|
|
||||||
|
|
||||||
//Wait for the entry to be set
|
|
||||||
while(!*arm11);
|
|
||||||
//Jump to it
|
|
||||||
((void (*)())*arm11)();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clearScreen(void){
|
void clearScreens(void){
|
||||||
memset(fb->top_left, 0, 0x46500);
|
memset32(fb->top_left, 0, 0x46500);
|
||||||
memset(fb->top_right, 0, 0x46500);
|
memset32(fb->top_right, 0, 0x46500);
|
||||||
memset(fb->bottom, 0, 0x38400);
|
memset32(fb->bottom, 0, 0x38400);
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadSplash(void){
|
void loadSplash(void){
|
||||||
clearScreen();
|
clearScreens();
|
||||||
|
|
||||||
//Don't delay boot if no splash image is on the SD
|
//Don't delay boot if no splash image is on the SD
|
||||||
if(fileRead(fb->top_left, "/rei/splash.bin", 0x46500) +
|
if(fileRead(fb->top_left, "/aurei/splash.bin", 0x46500) +
|
||||||
fileRead(fb->bottom, "/rei/splashbottom.bin", 0x38400)){
|
fileRead(fb->bottom, "/aurei/splashbottom.bin", 0x38400)){
|
||||||
u64 i = 0xFFFFFF; while(--i) __asm("mov r0, r0"); //Less Ghetto sleep func
|
u64 i = 0x1300000; while(--i) __asm("mov r0, r0"); //Less Ghetto sleep func
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void drawCharacter(char character, int pos_x, int pos_y, u32 color){
|
||||||
|
u8 *select = fb->top_left;
|
||||||
|
|
||||||
|
for(int y = 0; y < 8; y++){
|
||||||
|
unsigned char char_pos = font[character * 8 + y];
|
||||||
|
|
||||||
|
for(int x = 7; x >= 0; x--){
|
||||||
|
int screen_pos = (pos_x * SCREEN_TOP_HEIGHT * 3 + (SCREEN_TOP_HEIGHT - y - pos_y - 1) * 3) + (7 - x) * 3 * SCREEN_TOP_HEIGHT;
|
||||||
|
|
||||||
|
if ((char_pos >> x) & 1) {
|
||||||
|
select[screen_pos] = color >> 16;
|
||||||
|
select[screen_pos + 1] = color >> 8;
|
||||||
|
select[screen_pos + 2] = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int drawString(const char *string, int pos_x, int pos_y, u32 color){
|
||||||
|
int length = strlen(string);
|
||||||
|
|
||||||
|
for(int i = 0, line_i = 0; i < length; i++, line_i++){
|
||||||
|
if(string[i] == '\n'){
|
||||||
|
pos_y += SPACING_VERT;
|
||||||
|
line_i = 0;
|
||||||
|
i++;
|
||||||
|
} else if(line_i >= (SCREEN_TOP_WIDTH - pos_x) / SPACING_HORIZ){
|
||||||
|
// Make sure we never get out of the screen.
|
||||||
|
pos_y += SPACING_VERT;
|
||||||
|
line_i = 2; // Little offset so we know the same string continues.
|
||||||
|
if(string[i] == ' ') i++; // Spaces at the start look weird
|
||||||
|
}
|
||||||
|
|
||||||
|
drawCharacter(string[i], pos_x + line_i * SPACING_HORIZ, pos_y, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pos_y;
|
||||||
|
}
|
||||||
@@ -1,12 +1,19 @@
|
|||||||
/*
|
/*
|
||||||
* draw.h
|
* draw.h
|
||||||
* by Reisyukaku
|
* by Reisyukaku / Aurora Wright
|
||||||
* Copyright (c) 2015 All Rights Reserved
|
* Code to print to the screen by mid-kid @CakesFW
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 All Rights Reserved
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
|
#define SPACING_VERT 10
|
||||||
|
#define SPACING_HORIZ 8
|
||||||
|
|
||||||
void loadSplash(void);
|
void loadSplash(void);
|
||||||
void __attribute__((naked)) shutdownLCD(void);
|
void clearScreens(void);
|
||||||
|
void drawCharacter(char character, int pos_x, int pos_y, u32 color);
|
||||||
|
int drawString(const char *string, int pos_x, int pos_y, u32 color);
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* emunand.c
|
* emunand.c
|
||||||
* by Reisyukaku
|
* by Reisyukaku / Aurora Wright
|
||||||
* Copyright (c) 2015 All Rights Reserved
|
* Copyright (c) 2016 All Rights Reserved
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "emunand.h"
|
#include "emunand.h"
|
||||||
@@ -22,26 +22,19 @@ void getEmunandSect(u32 *off, u32 *head, u32 emuNAND){
|
|||||||
}
|
}
|
||||||
//Fallback to the first emuNAND if there's no second one
|
//Fallback to the first emuNAND if there's no second one
|
||||||
else if(emuNAND == 2) getEmunandSect(off, head, 1);
|
else if(emuNAND == 2) getEmunandSect(off, head, 1);
|
||||||
|
//Check if a RedNAND is present
|
||||||
|
else if(sdmmc_sdcard_readsectors(1, 1, temp) == 0)
|
||||||
|
if(*(u32 *)(temp + 0x100) != NCSD_MAGIC)
|
||||||
|
*head = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void getSDMMC(void *pos, u32 *off, u32 size){
|
u32 getSDMMC(void *pos, u32 size){
|
||||||
//Look for struct code
|
//Look for struct code
|
||||||
const unsigned char pattern[] = {0x21, 0x20, 0x18, 0x20};
|
const unsigned char pattern[] = {0x21, 0x20, 0x18, 0x20};
|
||||||
*off = (u32)memsearch(pos, pattern, size, 4) - 1;
|
const u8 *off = (u8 *)memsearch(pos, pattern, size, 4) - 1;
|
||||||
|
|
||||||
//Get DCD values
|
return *(u32 *)(off+0x0A) + *(u32 *)(off+0x0E);
|
||||||
u8 buf[4];
|
|
||||||
u32 addr = 0,
|
|
||||||
additive = 0,
|
|
||||||
p;
|
|
||||||
memcpy(buf, (void *)(*off+0x0A), 4);
|
|
||||||
for (p = 0; p < 4; p++) addr |= ((u32) buf[p]) << (8 * p);
|
|
||||||
memcpy(buf, (void *)(*off+0x0E), 4);
|
|
||||||
for (p = 0; p < 4; p++) additive |= ((u32) buf[p]) << (8 * p);
|
|
||||||
|
|
||||||
//Return result
|
|
||||||
*off = addr + additive;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void getEmuRW(void *pos, u32 size, u32 *readOff, u32 *writeOff){
|
void getEmuRW(void *pos, u32 size, u32 *readOff, u32 *writeOff){
|
||||||
@@ -52,9 +45,16 @@ void getEmuRW(void *pos, u32 size, u32 *readOff, u32 *writeOff){
|
|||||||
*readOff = (u32)memsearch((void *)(*writeOff - 0x1000), pattern, 0x1000, 4) - 6;
|
*readOff = (u32)memsearch((void *)(*writeOff - 0x1000), pattern, 0x1000, 4) - 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
void getMPU(void *pos, u32 *off, u32 size){
|
void *getMPU(void *pos, u32 size){
|
||||||
//Look for MPU pattern
|
//Look for MPU pattern
|
||||||
const unsigned char pattern[] = {0x03, 0x00, 0x24, 0x00};
|
const unsigned char pattern[] = {0x03, 0x00, 0x24, 0x00};
|
||||||
|
|
||||||
*off = (u32)memsearch(pos, pattern, size, 4);
|
return memsearch(pos, pattern, size, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *getEmuCode(void *pos, u32 size, u8 *proc9Offset){
|
||||||
|
const unsigned char pattern[] = {0x00, 0xFF, 0xFF, 0xFF};
|
||||||
|
|
||||||
|
//Looking for the last free space before Process9
|
||||||
|
return (u8 *)memsearch(pos, pattern, size - (size - (u32)(proc9Offset - (u8 *)pos)), 4) + 0xD;
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* emunand.h
|
* emunand.h
|
||||||
* by Reisyukaku
|
* by Reisyukaku / Aurora Wright
|
||||||
* Copyright (c) 2015 All Rights Reserved
|
* Copyright (c) 2016 All Rights Reserved
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
#define NCSD_MAGIC (0x4453434E)
|
#define NCSD_MAGIC (0x4453434E)
|
||||||
|
|
||||||
void getEmunandSect(u32 *off, u32 *head, u32 emuNAND);
|
void getEmunandSect(u32 *off, u32 *head, u32 emuNAND);
|
||||||
void getSDMMC(void *pos, u32 *off, u32 size);
|
u32 getSDMMC(void *pos, u32 size);
|
||||||
void getEmuRW(void *pos, u32 size, u32 *readOff, u32 *writeOff);
|
void getEmuRW(void *pos, u32 size, u32 *readOff, u32 *writeOff);
|
||||||
void getMPU(void *pos, u32 *off, u32 size);
|
void *getMPU(void *pos, u32 size);
|
||||||
|
void *getEmuCode(void *pos, u32 size, u8 *proc9Offset);
|
||||||
@@ -69,7 +69,7 @@ DRESULT disk_read (
|
|||||||
DRESULT disk_write (
|
DRESULT disk_write (
|
||||||
__attribute__((unused))
|
__attribute__((unused))
|
||||||
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
||||||
const BYTE *buff, /* Data to be written */
|
const BYTE *buff, /* Data to be written */
|
||||||
DWORD sector, /* Sector address in LBA */
|
DWORD sector, /* Sector address in LBA */
|
||||||
UINT count /* Number of sectors to write */
|
UINT count /* Number of sectors to write */
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -811,7 +811,7 @@ FRESULT sync_fs ( /* FR_OK: successful, FR_DISK_ERR: failed */
|
|||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* Hidden API for hacks and disk tools */
|
/* Hidden API for hacks and disk tools */
|
||||||
|
|
||||||
DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */
|
static DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */
|
||||||
FATFS* fs, /* File system object */
|
FATFS* fs, /* File system object */
|
||||||
DWORD clst /* Cluster# to be converted */
|
DWORD clst /* Cluster# to be converted */
|
||||||
)
|
)
|
||||||
@@ -829,7 +829,7 @@ DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */
|
|||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* Hidden API for hacks and disk tools */
|
/* Hidden API for hacks and disk tools */
|
||||||
|
|
||||||
DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x0FFFFFFF:Cluster status */
|
static DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x0FFFFFFF:Cluster status */
|
||||||
FATFS* fs, /* File system object */
|
FATFS* fs, /* File system object */
|
||||||
DWORD clst /* FAT index number (cluster number) to get the value */
|
DWORD clst /* FAT index number (cluster number) to get the value */
|
||||||
)
|
)
|
||||||
@@ -884,7 +884,7 @@ DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x0FFFFFFF:Cluste
|
|||||||
/* Hidden API for hacks and disk tools */
|
/* Hidden API for hacks and disk tools */
|
||||||
|
|
||||||
#if !_FS_READONLY
|
#if !_FS_READONLY
|
||||||
FRESULT put_fat (
|
static FRESULT put_fat (
|
||||||
FATFS* fs, /* File system object */
|
FATFS* fs, /* File system object */
|
||||||
DWORD clst, /* FAT index number (cluster number) to be changed */
|
DWORD clst, /* FAT index number (cluster number) to be changed */
|
||||||
DWORD val /* New value to be set to the entry */
|
DWORD val /* New value to be set to the entry */
|
||||||
|
|||||||
@@ -2,8 +2,6 @@
|
|||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
#include "sdmmc.h"
|
#include "sdmmc.h"
|
||||||
#include "delay.h"
|
#include "delay.h"
|
||||||
|
|
||||||
|
|||||||
272
source/firm.c
272
source/firm.c
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* firm.c
|
* firm.c
|
||||||
* by Reisyukaku
|
* by Reisyukaku / Aurora Wright
|
||||||
* Copyright (c) 2015 All Rights Reserved
|
* Copyright (c) 2016 All Rights Reserved
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "firm.h"
|
#include "firm.h"
|
||||||
@@ -11,19 +11,29 @@
|
|||||||
#include "emunand.h"
|
#include "emunand.h"
|
||||||
#include "crypto.h"
|
#include "crypto.h"
|
||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
|
#include "screeninit.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "buttons.h"
|
||||||
|
#include "../build/patches.h"
|
||||||
|
|
||||||
|
//FIRM patches version
|
||||||
|
#define PATCH_VER 1
|
||||||
|
|
||||||
static firmHeader *const firmLocation = (firmHeader *)0x24000000;
|
static firmHeader *const firmLocation = (firmHeader *)0x24000000;
|
||||||
static const firmSectionHeader *section;
|
static const firmSectionHeader *section;
|
||||||
static u32 firmSize = 0,
|
static u8 *arm9Section;
|
||||||
|
static const char *patchedFirms[] = { "/aurei/patched_firmware_sys.bin",
|
||||||
|
"/aurei/patched_firmware_emu.bin",
|
||||||
|
"/aurei/patched_firmware_em2.bin",
|
||||||
|
"/aurei/patched_firmware90.bin" };
|
||||||
|
static u32 firmSize,
|
||||||
mode = 1,
|
mode = 1,
|
||||||
console = 1,
|
console = 1,
|
||||||
emuNAND = 0,
|
emuNAND = 0,
|
||||||
a9lhSetup = 0,
|
a9lhSetup = 0,
|
||||||
updatedSys = 0,
|
usePatchedFirm = 0,
|
||||||
usePatchedFirm = 0;
|
selectedFirm = 0;
|
||||||
static u16 pressed;
|
|
||||||
static const char *firmPathPatched = NULL;
|
|
||||||
|
|
||||||
void setupCFW(void){
|
void setupCFW(void){
|
||||||
|
|
||||||
@@ -31,53 +41,57 @@ void setupCFW(void){
|
|||||||
u32 a9lhBoot = (PDN_SPI_CNT == 0x0) ? 1 : 0;
|
u32 a9lhBoot = (PDN_SPI_CNT == 0x0) ? 1 : 0;
|
||||||
//Retrieve the last booted FIRM
|
//Retrieve the last booted FIRM
|
||||||
u8 previousFirm = CFG_BOOTENV;
|
u8 previousFirm = CFG_BOOTENV;
|
||||||
u32 overrideConfig = 0;
|
|
||||||
const char lastConfigPath[] = "rei/lastbootcfg";
|
|
||||||
|
|
||||||
//Detect the console being used
|
//Detect the console being used
|
||||||
if(PDN_MPCORE_CFG == 1) console = 0;
|
if(PDN_MPCORE_CFG == 1) console = 0;
|
||||||
|
|
||||||
//Get pressed buttons
|
//Get pressed buttons
|
||||||
pressed = HID_PAD;
|
u16 pressed = HID_PAD;
|
||||||
|
u32 updatedSys = 0;
|
||||||
|
|
||||||
|
//Attempt to read the configuration file
|
||||||
|
const char configPath[] = "aurei/config.bin";
|
||||||
|
u16 config = 0;
|
||||||
|
u32 needConfig = fileRead((u8 *)&config, configPath, 2) ? 1 : 2;
|
||||||
|
|
||||||
//Determine if A9LH is installed
|
//Determine if A9LH is installed
|
||||||
if(a9lhBoot || fileExists("/rei/installeda9lh")){
|
if(a9lhBoot || (config >> 2) & 0x1){
|
||||||
a9lhSetup = 1;
|
a9lhSetup = 1;
|
||||||
//Check flag for > 9.2 SysNAND
|
//Check setting for > 9.2 sysNAND
|
||||||
if(fileExists("/rei/updatedsysnand")) updatedSys = 1;
|
updatedSys = config & 0x1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//If booting with A9LH and it's a MCU reboot, try to force boot options
|
/* If booting with A9LH, it's a MCU reboot and a previous configuration exists,
|
||||||
if(a9lhBoot && previousFirm && fileExists(lastConfigPath)){
|
try to force boot options */
|
||||||
u8 tempConfig;
|
if(a9lhBoot && previousFirm && needConfig == 1){
|
||||||
fileRead(&tempConfig, lastConfigPath, 1);
|
|
||||||
|
|
||||||
//Always force a sysNAND boot when quitting AGB_FIRM
|
//Always force a sysNAND boot when quitting AGB_FIRM
|
||||||
if(previousFirm == 0x7){
|
if(previousFirm == 0x7){
|
||||||
if(!updatedSys) mode = tempConfig & 0x1;
|
if(!updatedSys) mode = (config >> 8) & 0x1;
|
||||||
overrideConfig = 1;
|
needConfig = 0;
|
||||||
//Else, force the last used boot options unless A is pressed
|
//Else, force the last used boot options unless A is pressed
|
||||||
} else if(!(pressed & BUTTON_A)){
|
} else if(!(pressed & BUTTON_A)){
|
||||||
mode = tempConfig & 0x1;
|
mode = (config >> 8) & 0x1;
|
||||||
emuNAND = (tempConfig >> 1) & 0x1;
|
emuNAND = (config >> 9) & 0x1;
|
||||||
overrideConfig = 1;
|
needConfig = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!overrideConfig){
|
if(needConfig){
|
||||||
|
|
||||||
//If L and R are pressed, chainload an external payload
|
//If L and R are pressed, chainload an external payload
|
||||||
if(a9lhBoot && (pressed & BUTTON_L1R1) == BUTTON_L1R1) loadPayload();
|
if((pressed & BUTTON_L1R1) == BUTTON_L1R1) loadPayload();
|
||||||
|
|
||||||
//Check if it's a no-screen-init A9LH boot
|
//If no configuration file exists or SELECT is held, load configuration menu
|
||||||
|
if(needConfig == 2 || (pressed & BUTTON_SELECT))
|
||||||
|
configureCFW(configPath);
|
||||||
|
|
||||||
|
//If screens are inited, load splash screen
|
||||||
if(PDN_GPU_CNT != 0x1) loadSplash();
|
if(PDN_GPU_CNT != 0x1) loadSplash();
|
||||||
|
|
||||||
/* If L is pressed, and on an updated SysNAND setup the SAFE MODE combo
|
/* If L is pressed, and on an updated sysNAND setup the SAFE MODE combo
|
||||||
is not pressed, boot 9.0 FIRM */
|
is not pressed, boot 9.0 FIRM */
|
||||||
if((pressed & BUTTON_L1) && !(updatedSys && pressed == SAFEMODE)) mode = 0;
|
if((pressed & BUTTON_L1) && !(updatedSys && pressed == SAFEMODE)) mode = 0;
|
||||||
|
|
||||||
/* If L or R aren't pressed on a 9.0/9.2 SysNAND, or the 9.0 FIRM is selected
|
/* If L or R aren't pressed on a 9.0/9.2 sysNAND, or the 9.0 FIRM is selected
|
||||||
or R is pressed on a > 9.2 SysNAND, boot emuNAND */
|
or R is pressed on a > 9.2 sysNAND, boot emuNAND */
|
||||||
if((updatedSys && (!mode || ((pressed & BUTTON_R1) && pressed != SAFEMODE))) ||
|
if((updatedSys && (!mode || ((pressed & BUTTON_R1) && pressed != SAFEMODE))) ||
|
||||||
(!updatedSys && mode && !(pressed & BUTTON_R1))){
|
(!updatedSys && mode && !(pressed & BUTTON_R1))){
|
||||||
//If not 9.0 FIRM and B is pressed, attempt booting the second emuNAND
|
//If not 9.0 FIRM and B is pressed, attempt booting the second emuNAND
|
||||||
@@ -85,27 +99,35 @@ void setupCFW(void){
|
|||||||
else emuNAND = 1;
|
else emuNAND = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Write the current boot options on A9LH
|
/* If tha FIRM patches version is different or user switched to/from A9LH,
|
||||||
if(a9lhBoot){
|
and "Use pre-patched FIRMs" is set, delete all patched FIRMs */
|
||||||
u8 tempConfig = (mode | (emuNAND << 1)) & 0x3;
|
u16 bootConfig = (PATCH_VER << 11) | (a9lhSetup << 10);
|
||||||
fileWrite(&tempConfig, lastConfigPath, 1);
|
if ((config >> 1) & 0x1 && bootConfig != (config & 0xFC00))
|
||||||
|
deleteFirms(patchedFirms, sizeof(patchedFirms) / sizeof(char *));
|
||||||
|
|
||||||
|
//We also need to remember the used boot mode on A9LH
|
||||||
|
if(a9lhBoot) bootConfig |= (mode << 8) | (emuNAND << 9);
|
||||||
|
|
||||||
|
//If the boot configuration is different from previously, overwrite it
|
||||||
|
if(bootConfig != (config & 0xFF00)){
|
||||||
|
//Preserve user settings (first byte)
|
||||||
|
u16 tempConfig = ((config & 0xFF) | bootConfig);
|
||||||
|
fileWrite((u8 *)&tempConfig, configPath, 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mode) firmPathPatched = emuNAND ? (emuNAND == 1 ? "/rei/patched_firmware_emu.bin" :
|
if(mode) selectedFirm = emuNAND ? (emuNAND == 1 ? 2 : 3) : 1;
|
||||||
"/rei/patched_firmware_em2.bin") :
|
|
||||||
"/rei/patched_firmware_sys.bin";
|
|
||||||
|
|
||||||
//Skip decrypting and patching FIRM
|
//Skip decrypting and patching FIRM
|
||||||
if(fileExists("/rei/usepatchedfw")){
|
if((config >> 1) & 0x1){
|
||||||
//Only needed with this flag
|
//Only needed with this setting
|
||||||
if(!mode) firmPathPatched = "/rei/patched_firmware90.bin";
|
if(!mode) selectedFirm = 4;
|
||||||
if(fileExists(firmPathPatched)) usePatchedFirm = 1;
|
if(fileExists(patchedFirms[selectedFirm - 1])) usePatchedFirm = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Load firm into FCRAM
|
//Load FIRM into FCRAM
|
||||||
u32 loadFirm(void){
|
void loadFirm(void){
|
||||||
|
|
||||||
//If not using an A9LH setup or the patched FIRM, load 9.0 FIRM from NAND
|
//If not using an A9LH setup or the patched FIRM, load 9.0 FIRM from NAND
|
||||||
if(!usePatchedFirm && !a9lhSetup && !mode){
|
if(!usePatchedFirm && !a9lhSetup && !mode){
|
||||||
@@ -113,92 +135,106 @@ u32 loadFirm(void){
|
|||||||
firmSize = console ? 0xF2000 : 0xE9000;
|
firmSize = console ? 0xF2000 : 0xE9000;
|
||||||
nandFirm0((u8 *)firmLocation, firmSize, console);
|
nandFirm0((u8 *)firmLocation, firmSize, console);
|
||||||
//Check for correct decryption
|
//Check for correct decryption
|
||||||
if(memcmp(firmLocation, "FIRM", 4) != 0) return 0;
|
if(memcmp(firmLocation, "FIRM", 4) != 0)
|
||||||
|
error("Couldn't decrypt NAND FIRM0 (O3DS not on 9.x?)");
|
||||||
}
|
}
|
||||||
//Load FIRM from SD
|
//Load FIRM from SD
|
||||||
else{
|
else{
|
||||||
const char *path = usePatchedFirm ? firmPathPatched :
|
const char *path = usePatchedFirm ? patchedFirms[selectedFirm - 1] :
|
||||||
(mode ? "/rei/firmware.bin" : "/rei/firmware90.bin");
|
(mode ? "/aurei/firmware.bin" : "/aurei/firmware90.bin");
|
||||||
firmSize = fileSize(path);
|
firmSize = fileSize(path);
|
||||||
if(!firmSize) return 0;
|
if(!firmSize) error("aurei/firmware(90).bin doesn't exist");
|
||||||
fileRead((u8 *)firmLocation, path, firmSize);
|
fileRead((u8 *)firmLocation, path, firmSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
section = firmLocation->section;
|
section = firmLocation->section;
|
||||||
|
|
||||||
//Check that the loaded FIRM matches the console
|
//Check that the loaded FIRM matches the console
|
||||||
if((((u32)section[2].address >> 8) & 0xFF) != (console ? 0x60 : 0x68)) return 0;
|
if((((u32)section[2].address >> 8) & 0xFF) != (console ? 0x60 : 0x68))
|
||||||
|
error("aurei/firmware(90).bin doesn't match this\nconsole, or it's encrypted");
|
||||||
|
|
||||||
if(console && !usePatchedFirm)
|
arm9Section = (u8 *)firmLocation + section[2].offset;
|
||||||
decArm9Bin((u8 *)firmLocation + section[2].offset, mode);
|
|
||||||
|
|
||||||
return 1;
|
if(console && !usePatchedFirm) decryptArm9Bin(arm9Section, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Nand redirection
|
//NAND redirection
|
||||||
static u32 loadEmu(void){
|
static void loadEmu(u8 *proc9Offset){
|
||||||
|
|
||||||
u32 emuOffset = 1,
|
u32 emuOffset = 1,
|
||||||
emuHeader = 1,
|
emuHeader = 1,
|
||||||
emuRead,
|
emuRead,
|
||||||
emuWrite,
|
emuWrite;
|
||||||
sdmmcOffset,
|
|
||||||
mpuOffset,
|
|
||||||
emuCodeOffset;
|
|
||||||
|
|
||||||
//Read emunand code from SD
|
//Look for emuNAND
|
||||||
const char path[] = "/rei/emunand/emunand.bin";
|
|
||||||
u32 size = fileSize(path);
|
|
||||||
if(!size) return 0;
|
|
||||||
if(!console || !mode) nandRedir[5] = 0xA4;
|
|
||||||
//Find offset for emuNAND code from the offset in nandRedir
|
|
||||||
emuCodeOffset = *(u32 *)(nandRedir + 4) - (u32)section[2].address +
|
|
||||||
section[2].offset + (u32)firmLocation;
|
|
||||||
fileRead((u8 *)emuCodeOffset, path, size);
|
|
||||||
|
|
||||||
//Find and patch emunand related offsets
|
|
||||||
u32 *pos_sdmmc = (u32 *)memsearch((void *)emuCodeOffset, "SDMC", size, 4);
|
|
||||||
u32 *pos_offset = (u32 *)memsearch((void *)emuCodeOffset, "NAND", size, 4);
|
|
||||||
u32 *pos_header = (u32 *)memsearch((void *)emuCodeOffset, "NCSD", size, 4);
|
|
||||||
getSDMMC(firmLocation, &sdmmcOffset, firmSize);
|
|
||||||
getEmunandSect(&emuOffset, &emuHeader, emuNAND);
|
getEmunandSect(&emuOffset, &emuHeader, emuNAND);
|
||||||
getEmuRW(firmLocation, firmSize, &emuRead, &emuWrite);
|
|
||||||
getMPU(firmLocation, &mpuOffset, firmSize);
|
//No emuNAND detected
|
||||||
*pos_sdmmc = sdmmcOffset;
|
if(!emuHeader) error("No emuNAND has been detected");
|
||||||
|
|
||||||
|
//Copy the emuNAND patch
|
||||||
|
void *emuCodeOffset = getEmuCode(arm9Section, section[2].size, proc9Offset);
|
||||||
|
memcpy(emuCodeOffset, emunand, emunand_size);
|
||||||
|
|
||||||
|
//Add the data of the found emuNAND
|
||||||
|
u32 *pos_offset = (u32 *)memsearch(emuCodeOffset, "NAND", emunand_size, 4);
|
||||||
|
u32 *pos_header = (u32 *)memsearch(emuCodeOffset, "NCSD", emunand_size, 4);
|
||||||
*pos_offset = emuOffset;
|
*pos_offset = emuOffset;
|
||||||
*pos_header = emuHeader;
|
*pos_header = emuHeader;
|
||||||
|
|
||||||
//Patch emuNAND code in memory for O3DS and 9.0 N3DS
|
//Find and add the SDMMC struct
|
||||||
if(!console || !mode){
|
u32 *pos_sdmmc = (u32 *)memsearch(emuCodeOffset, "SDMC", emunand_size, 4);
|
||||||
void *pos_instr = memsearch((void *)emuCodeOffset, "\xA6\x01\x08\x30", size, 4);
|
*pos_sdmmc = getSDMMC(arm9Section, section[2].size);
|
||||||
memcpy(pos_instr, emuInstr, sizeof(emuInstr));
|
|
||||||
}
|
//Calculate offset for the hooks
|
||||||
|
*(u32 *)(nandRedir + 4) = (u32)emuCodeOffset - (u32)firmLocation -
|
||||||
|
section[2].offset + (u32)section[2].address;
|
||||||
|
|
||||||
//Add emunand hooks
|
//Add emunand hooks
|
||||||
|
getEmuRW(arm9Section, section[2].size, &emuRead, &emuWrite);
|
||||||
memcpy((void *)emuRead, nandRedir, sizeof(nandRedir));
|
memcpy((void *)emuRead, nandRedir, sizeof(nandRedir));
|
||||||
memcpy((void *)emuWrite, nandRedir, sizeof(nandRedir));
|
memcpy((void *)emuWrite, nandRedir, sizeof(nandRedir));
|
||||||
|
|
||||||
//Set MPU for emu code region
|
//Set MPU for emu code region
|
||||||
memcpy((void *)mpuOffset, mpu, sizeof(mpu));
|
void *mpuOffset = getMPU(arm9Section, section[2].size);
|
||||||
|
memcpy(mpuOffset, mpu, sizeof(mpu));
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Patches
|
//Patches
|
||||||
u32 patchFirm(void){
|
void patchFirm(void){
|
||||||
|
|
||||||
//Skip patching
|
//Skip patching
|
||||||
if(usePatchedFirm) return 1;
|
if(usePatchedFirm) return;
|
||||||
|
|
||||||
//Apply emuNAND patches
|
if(mode || emuNAND){
|
||||||
if(emuNAND){
|
//Find the Process9 NCCH location
|
||||||
if(!loadEmu()) return 0;
|
u8 *proc9Offset = getProc9(arm9Section, section[2].size);
|
||||||
|
|
||||||
|
//Apply emuNAND patches
|
||||||
|
if(emuNAND) loadEmu(proc9Offset);
|
||||||
|
|
||||||
|
//Patch FIRM reboots, not on 9.0 FIRM as it breaks firmlaunchhax
|
||||||
|
if(mode){
|
||||||
|
//Read reboot code from SD
|
||||||
|
void *rebootOffset = getReboot(arm9Section, section[2].size);
|
||||||
|
memcpy(rebootOffset, reboot, reboot_size);
|
||||||
|
|
||||||
|
//Calculate the fOpen offset and put it in the right location
|
||||||
|
u32 *pos_fopen = (u32 *)memsearch(rebootOffset, "OPEN", reboot_size, 4);
|
||||||
|
*pos_fopen = getfOpen(arm9Section, section[2].size, proc9Offset);
|
||||||
|
|
||||||
|
//Patch path for emuNAND-patched FIRM
|
||||||
|
if(emuNAND){
|
||||||
|
void *pos_path = memsearch(rebootOffset, L"sy", reboot_size, 4);
|
||||||
|
memcpy(pos_path, emuNAND == 1 ? L"emu" : L"em2", 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if(a9lhSetup){
|
|
||||||
//Patch FIRM partitions writes on SysNAND to protect A9LH
|
if(a9lhSetup && !emuNAND){
|
||||||
u32 writeOffset = 0;
|
//Patch FIRM partitions writes on sysNAND to protect A9LH
|
||||||
getFIRMWrite(firmLocation, firmSize, &writeOffset);
|
void *writeOffset = getFirmWrite(arm9Section, section[2].size);
|
||||||
memcpy((void *)writeOffset, FIRMblock, sizeof(FIRMblock));
|
memcpy(writeOffset, writeBlock, sizeof(writeBlock));
|
||||||
}
|
}
|
||||||
|
|
||||||
//Disable signature checks
|
//Disable signature checks
|
||||||
@@ -213,55 +249,27 @@ u32 patchFirm(void){
|
|||||||
if(console)
|
if(console)
|
||||||
firmLocation->arm9Entry = (u8 *)0x801B01C;
|
firmLocation->arm9Entry = (u8 *)0x801B01C;
|
||||||
|
|
||||||
//Patch FIRM reboots, not on 9.0 FIRM as it breaks firmlaunchhax
|
|
||||||
if(mode){
|
|
||||||
u32 rebootOffset,
|
|
||||||
fOpenOffset;
|
|
||||||
|
|
||||||
//Read reboot code from SD
|
|
||||||
const char path[] = "/rei/reboot/reboot.bin";
|
|
||||||
u32 size = fileSize(path);
|
|
||||||
if(!size) return 0;
|
|
||||||
getReboot(firmLocation, firmSize, &rebootOffset);
|
|
||||||
fileRead((u8 *)rebootOffset, path, size);
|
|
||||||
|
|
||||||
//Calculate the fOpen offset and put it in the right location
|
|
||||||
u32 *pos_fopen = (u32 *)memsearch((void *)rebootOffset, "OPEN", size, 4);
|
|
||||||
getfOpen(firmLocation, firmSize, &fOpenOffset);
|
|
||||||
*pos_fopen = fOpenOffset;
|
|
||||||
|
|
||||||
//Patch path for emuNAND-patched FIRM
|
|
||||||
if(emuNAND){
|
|
||||||
void *pos_path = memsearch((void *)rebootOffset, L"sy", size, 4);
|
|
||||||
const wchar_t *path = emuNAND == 1 ? L"emu" : L"em2";
|
|
||||||
memcpy(pos_path, path, 5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Write patched FIRM to SD if needed
|
//Write patched FIRM to SD if needed
|
||||||
if(firmPathPatched)
|
if(selectedFirm)
|
||||||
if(!fileWrite((u8 *)firmLocation, firmPathPatched, firmSize)) return 0;
|
if(!fileWrite((u8 *)firmLocation, patchedFirms[selectedFirm - 1], firmSize))
|
||||||
|
error("Couldn't write the patched FIRM (no free space?)");
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void launchFirm(void){
|
void launchFirm(void){
|
||||||
|
|
||||||
if(console && mode) setKeyXs((u8 *)firmLocation + section[2].offset);
|
if(console && mode) setKeyXs(arm9Section);
|
||||||
|
|
||||||
//Copy firm partitions to respective memory locations
|
//Copy firm partitions to respective memory locations
|
||||||
memcpy(section[0].address, (u8 *)firmLocation + section[0].offset, section[0].size);
|
memcpy(section[0].address, (u8 *)firmLocation + section[0].offset, section[0].size);
|
||||||
memcpy(section[1].address, (u8 *)firmLocation + section[1].offset, section[1].size);
|
memcpy(section[1].address, (u8 *)firmLocation + section[1].offset, section[1].size);
|
||||||
memcpy(section[2].address, (u8 *)firmLocation + section[2].offset, section[2].size);
|
memcpy(section[2].address, arm9Section, section[2].size);
|
||||||
|
|
||||||
//Run ARM11 screen stuff
|
//Fixes N3DS 3D
|
||||||
vu32 *const arm11 = (u32 *)0x1FFFFFF8;
|
deinitScreens();
|
||||||
*arm11 = (u32)shutdownLCD;
|
|
||||||
while(*arm11);
|
|
||||||
|
|
||||||
//Set ARM11 kernel
|
//Set ARM11 kernel entrypoint
|
||||||
*arm11 = (u32)firmLocation->arm11Entry;
|
*(vu32 *)0x1FFFFFF8 = (u32)firmLocation->arm11Entry;
|
||||||
|
|
||||||
//Final jump to arm9 binary
|
//Final jump to arm9 kernel
|
||||||
((void (*)())firmLocation->arm9Entry)();
|
((void (*)())firmLocation->arm9Entry)();
|
||||||
}
|
}
|
||||||
@@ -1,24 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
* firm.h
|
* firm.h
|
||||||
* by Reisyukaku
|
* by Reisyukaku / Aurora Wright
|
||||||
* Copyright (c) 2015 All Rights Reserved
|
* Copyright (c) 2016 All Rights Reserved
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
#define PDN_MPCORE_CFG (*(vu8 *)0x10140FFC)
|
#define PDN_MPCORE_CFG (*(vu8 *)0x10140FFC)
|
||||||
#define HID_PAD ((~*(vu16 *)0x10146000) & 0xFFF)
|
#define PDN_SPI_CNT (*(vu8 *)0x101401C0)
|
||||||
#define PDN_SPI_CNT (*(vu8 *)0x101401C0)
|
#define CFG_BOOTENV (*(vu8 *)0x10010000)
|
||||||
#define CFG_BOOTENV (*(vu8 *)0x10010000)
|
|
||||||
#define PDN_GPU_CNT (*(vu8 *)0x10141200)
|
|
||||||
#define BUTTON_R1 (1 << 8)
|
|
||||||
#define BUTTON_L1 (1 << 9)
|
|
||||||
#define BUTTON_L1R1 (BUTTON_R1 | BUTTON_L1)
|
|
||||||
#define BUTTON_A 1
|
|
||||||
#define BUTTON_B (1 << 1)
|
|
||||||
#define SAFEMODE (BUTTON_L1R1 | BUTTON_A | (1 << 6))
|
|
||||||
|
|
||||||
//FIRM Header layout
|
//FIRM Header layout
|
||||||
typedef struct firmSectionHeader {
|
typedef struct firmSectionHeader {
|
||||||
@@ -39,6 +31,6 @@ typedef struct firmHeader {
|
|||||||
} firmHeader;
|
} firmHeader;
|
||||||
|
|
||||||
void setupCFW(void);
|
void setupCFW(void);
|
||||||
u32 loadFirm(void);
|
void loadFirm(void);
|
||||||
u32 patchFirm(void);
|
void patchFirm(void);
|
||||||
void launchFirm(void);
|
void launchFirm(void);
|
||||||
144
source/font.h
Normal file
144
source/font.h
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
/*
|
||||||
|
This file was autogenerated by raw2c.
|
||||||
|
Visit http://www.devkitpro.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
#ifndef _font_h_
|
||||||
|
#define _font_h_
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
static const unsigned char font[] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e,
|
||||||
|
0x7e, 0xff, 0xdb, 0xff, 0xc3, 0xe7, 0xff, 0x7e, 0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00,
|
||||||
|
0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x3c, 0x3c, 0x18, 0xff, 0xe7, 0x18, 0x3c, 0x00,
|
||||||
|
0x10, 0x38, 0x7c, 0xfe, 0xee, 0x10, 0x38, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00,
|
||||||
|
0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00,
|
||||||
|
0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0x0f, 0x07, 0x0f, 0x7d, 0xcc, 0xcc, 0xcc, 0x78,
|
||||||
|
0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x08, 0x0c, 0x0a, 0x0a, 0x08, 0x78, 0xf0, 0x00,
|
||||||
|
0x18, 0x14, 0x1a, 0x16, 0x72, 0xe2, 0x0e, 0x1c, 0x10, 0x54, 0x38, 0xee, 0x38, 0x54, 0x10, 0x00,
|
||||||
|
0x80, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0x80, 0x00, 0x02, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x02, 0x00,
|
||||||
|
0x18, 0x3c, 0x5a, 0x18, 0x5a, 0x3c, 0x18, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00,
|
||||||
|
0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x00, 0x1c, 0x22, 0x38, 0x44, 0x44, 0x38, 0x88, 0x70,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x00, 0x18, 0x3c, 0x5a, 0x18, 0x5a, 0x3c, 0x18, 0x7e,
|
||||||
|
0x18, 0x3c, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x5a, 0x3c, 0x18, 0x00,
|
||||||
|
0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x24, 0x42, 0xff, 0x42, 0x24, 0x00, 0x00,
|
||||||
|
0x00, 0x10, 0x38, 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x18, 0x00, 0x18, 0x00,
|
||||||
|
0x6c, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00,
|
||||||
|
0x10, 0x7c, 0xd0, 0x7c, 0x16, 0xfc, 0x10, 0x00, 0x00, 0x66, 0xac, 0xd8, 0x36, 0x6a, 0xcc, 0x00,
|
||||||
|
0x38, 0x4c, 0x38, 0x78, 0xce, 0xcc, 0x7a, 0x00, 0x30, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00, 0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00,
|
||||||
|
0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x10, 0x20, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x00,
|
||||||
|
0x7c, 0xce, 0xde, 0xf6, 0xe6, 0xe6, 0x7c, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x7e, 0x00,
|
||||||
|
0x7c, 0xc6, 0x06, 0x1c, 0x70, 0xc6, 0xfe, 0x00, 0x7c, 0xc6, 0x06, 0x3c, 0x06, 0xc6, 0x7c, 0x00,
|
||||||
|
0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x1e, 0x00, 0xfe, 0xc0, 0xfc, 0x06, 0x06, 0xc6, 0x7c, 0x00,
|
||||||
|
0x7c, 0xc6, 0xc0, 0xfc, 0xc6, 0xc6, 0x7c, 0x00, 0xfe, 0xc6, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x00,
|
||||||
|
0x7c, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0x7e, 0x06, 0xc6, 0x7c, 0x00,
|
||||||
|
0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x10, 0x20,
|
||||||
|
0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00,
|
||||||
|
0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x78, 0xcc, 0x0c, 0x18, 0x30, 0x00, 0x30, 0x00,
|
||||||
|
0x7c, 0x82, 0x9e, 0xa6, 0x9e, 0x80, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00,
|
||||||
|
0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00,
|
||||||
|
0xfc, 0x66, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00,
|
||||||
|
0xfe, 0x62, 0x68, 0x78, 0x68, 0x60, 0xf0, 0x00, 0x7c, 0xc6, 0xc6, 0xc0, 0xce, 0xc6, 0x7e, 0x00,
|
||||||
|
0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00,
|
||||||
|
0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00, 0xe6, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00,
|
||||||
|
0xf0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x82, 0xc6, 0xee, 0xfe, 0xd6, 0xc6, 0xc6, 0x00,
|
||||||
|
0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00,
|
||||||
|
0xfc, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, 0x06,
|
||||||
|
0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xe6, 0x00, 0x7c, 0xc6, 0xc0, 0x7c, 0x06, 0xc6, 0x7c, 0x00,
|
||||||
|
0x7e, 0x5a, 0x5a, 0x18, 0x18, 0x18, 0x3c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00,
|
||||||
|
0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0xc6, 0xc6, 0xd6, 0xfe, 0xee, 0xc6, 0x82, 0x00,
|
||||||
|
0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x3c, 0x00,
|
||||||
|
0xfe, 0xc6, 0x8c, 0x18, 0x32, 0x66, 0xfe, 0x00, 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00,
|
||||||
|
0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x02, 0x00, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00,
|
||||||
|
0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
|
||||||
|
0x30, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00,
|
||||||
|
0xe0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc6, 0x7c, 0x00,
|
||||||
|
0x1c, 0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x00,
|
||||||
|
0x1c, 0x36, 0x30, 0x78, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0x78,
|
||||||
|
0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0xe6, 0x00, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00,
|
||||||
|
0x00, 0x0c, 0x00, 0x1c, 0x0c, 0x0c, 0xcc, 0x78, 0xe0, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0xe6, 0x00,
|
||||||
|
0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0xcc, 0xfe, 0xd6, 0xd6, 0xd6, 0x00,
|
||||||
|
0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00,
|
||||||
|
0x00, 0x00, 0xdc, 0x66, 0x66, 0x7c, 0x60, 0xf0, 0x00, 0x00, 0x7c, 0xcc, 0xcc, 0x7c, 0x0c, 0x1e,
|
||||||
|
0x00, 0x00, 0xde, 0x76, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x7c, 0xc0, 0x7c, 0x06, 0x7c, 0x00,
|
||||||
|
0x10, 0x30, 0xfc, 0x30, 0x30, 0x34, 0x18, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00,
|
||||||
|
0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00,
|
||||||
|
0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8,
|
||||||
|
0x00, 0x00, 0xfc, 0x98, 0x30, 0x64, 0xfc, 0x00, 0x0e, 0x18, 0x18, 0x30, 0x18, 0x18, 0x0e, 0x00,
|
||||||
|
0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, 0xe0, 0x30, 0x30, 0x18, 0x30, 0x30, 0xe0, 0x00,
|
||||||
|
0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00,
|
||||||
|
0x7c, 0xc6, 0xc0, 0xc0, 0xc6, 0x7c, 0x18, 0x70, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00,
|
||||||
|
0x0e, 0x10, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x00, 0x7c, 0x82, 0x38, 0x0c, 0x7c, 0xcc, 0x76, 0x00,
|
||||||
|
0xcc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, 0xe0, 0x10, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00,
|
||||||
|
0x30, 0x30, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x7c, 0xc0, 0xc0, 0x7c, 0x18, 0x70,
|
||||||
|
0x7c, 0x82, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x00,
|
||||||
|
0xe0, 0x10, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x00, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00,
|
||||||
|
0x7c, 0x82, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00, 0xe0, 0x10, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00,
|
||||||
|
0xc6, 0x00, 0x7c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x38, 0x38, 0x7c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00,
|
||||||
|
0x0e, 0x10, 0xfe, 0x60, 0x78, 0x60, 0xfe, 0x00, 0x00, 0x00, 0x7c, 0x12, 0x7e, 0xd0, 0x7e, 0x00,
|
||||||
|
0x7e, 0xc8, 0xc8, 0xfe, 0xc8, 0xc8, 0xce, 0x00, 0x7c, 0x82, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00,
|
||||||
|
0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0xe0, 0x10, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00,
|
||||||
|
0x7c, 0x82, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0xe0, 0x10, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00,
|
||||||
|
0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00,
|
||||||
|
0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x18, 0x7c, 0xd6, 0xd0, 0xd6, 0x7c, 0x18, 0x00,
|
||||||
|
0x38, 0x6c, 0x60, 0xf0, 0x60, 0xf2, 0xdc, 0x00, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x7e, 0x18, 0x00,
|
||||||
|
0xf8, 0xcc, 0xf8, 0xc4, 0xcc, 0xde, 0xcc, 0x06, 0x0e, 0x1b, 0x18, 0x3c, 0x18, 0x18, 0xd8, 0x70,
|
||||||
|
0x0e, 0x10, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, 0x0e, 0x10, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00,
|
||||||
|
0x0e, 0x10, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x0e, 0x10, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00,
|
||||||
|
0x66, 0x98, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x98, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0x00,
|
||||||
|
0x38, 0x0c, 0x3c, 0x34, 0x00, 0x7e, 0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00,
|
||||||
|
0x30, 0x00, 0x30, 0x60, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xc0, 0xc0, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0c, 0x00, 0x00, 0xc0, 0xc8, 0xd0, 0xfe, 0x46, 0x8c, 0x1e, 0x00,
|
||||||
|
0xc0, 0xc8, 0xd0, 0xec, 0x5c, 0xbe, 0x0c, 0x00, 0x18, 0x00, 0x18, 0x18, 0x3c, 0x3c, 0x18, 0x00,
|
||||||
|
0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x6c, 0xd8, 0x00, 0x00,
|
||||||
|
0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
|
||||||
|
0xdb, 0x77, 0xdb, 0xee, 0xdb, 0x77, 0xdb, 0xee, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18,
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36,
|
||||||
|
0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36,
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36,
|
||||||
|
0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00,
|
||||||
|
0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18,
|
||||||
|
0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36,
|
||||||
|
0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36,
|
||||||
|
0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36,
|
||||||
|
0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00,
|
||||||
|
0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00,
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00,
|
||||||
|
0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36,
|
||||||
|
0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
|
||||||
|
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x74, 0xcc, 0xc8, 0xdc, 0x76, 0x00, 0x78, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xdc, 0x40,
|
||||||
|
0xfe, 0x62, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x02, 0x7e, 0xec, 0x6c, 0x6c, 0x48, 0x00,
|
||||||
|
0xfe, 0x62, 0x30, 0x18, 0x30, 0x62, 0xfe, 0x00, 0x00, 0x00, 0x7e, 0xd0, 0xc8, 0xc8, 0x70, 0x00,
|
||||||
|
0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xf8, 0x80, 0x00, 0x00, 0x7e, 0xd8, 0x18, 0x18, 0x10, 0x00,
|
||||||
|
0x38, 0x10, 0x7c, 0xd6, 0xd6, 0x7c, 0x10, 0x38, 0x7c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x7c, 0x00,
|
||||||
|
0x7c, 0xc6, 0xc6, 0xc6, 0x6c, 0x28, 0xee, 0x00, 0x3c, 0x22, 0x18, 0x7c, 0xcc, 0xcc, 0x78, 0x00,
|
||||||
|
0x00, 0x00, 0x66, 0x99, 0x99, 0x66, 0x00, 0x00, 0x00, 0x06, 0x7c, 0x9e, 0xf2, 0x7c, 0xc0, 0x00,
|
||||||
|
0x00, 0x00, 0x7c, 0xc0, 0xf8, 0xc0, 0x7c, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00,
|
||||||
|
0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x7e, 0x00,
|
||||||
|
0x30, 0x18, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0x00, 0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0x7c, 0x00,
|
||||||
|
0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70,
|
||||||
|
0x00, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00,
|
||||||
|
0x38, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x3c, 0x00,
|
||||||
|
0xd8, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x30, 0xc0, 0xf0, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
|
||||||
|
};
|
||||||
|
const int font_size = sizeof(font);
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
#endif //_font_h_
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* fs.c
|
* fs.c
|
||||||
|
* by Reisyukaku / Aurora Wright
|
||||||
|
* Copyright (c) 2016 All Rights Reserved
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
@@ -59,3 +61,7 @@ u32 fileExists(const char *path){
|
|||||||
f_close(&fp);
|
f_close(&fp);
|
||||||
return exists;
|
return exists;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void fileDelete(const char *path){
|
||||||
|
f_unlink(path);
|
||||||
|
}
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* fs.h
|
* fs.h
|
||||||
|
* by Reisyukaku / Aurora Wright
|
||||||
|
* Copyright (c) 2016 All Rights Reserved
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@@ -11,3 +13,4 @@ u32 fileRead(u8 *dest, const char *path, u32 size);
|
|||||||
u32 fileWrite(const u8 *buffer, const char *path, u32 size);
|
u32 fileWrite(const u8 *buffer, const char *path, u32 size);
|
||||||
u32 fileSize(const char *path);
|
u32 fileSize(const char *path);
|
||||||
u32 fileExists(const char *path);
|
u32 fileExists(const char *path);
|
||||||
|
void fileDelete(const char *path);
|
||||||
@@ -10,11 +10,11 @@ static const struct { u8 bus_id, reg_addr; } dev_data[] = {
|
|||||||
{2, 0xA4}, {2, 0x9A}, {2, 0xA0},
|
{2, 0xA4}, {2, 0x9A}, {2, 0xA0},
|
||||||
};
|
};
|
||||||
|
|
||||||
inline u8 i2cGetDeviceBusId(u8 device_id) {
|
static inline u8 i2cGetDeviceBusId(u8 device_id) {
|
||||||
return dev_data[device_id].bus_id;
|
return dev_data[device_id].bus_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline u8 i2cGetDeviceRegAddr(u8 device_id) {
|
static inline u8 i2cGetDeviceRegAddr(u8 device_id) {
|
||||||
return dev_data[device_id].reg_addr;
|
return dev_data[device_id].reg_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ static vu8* reg_data_addrs[] = {
|
|||||||
(vu8*)(I2C3_REG_OFF + I2C_REG_DATA),
|
(vu8*)(I2C3_REG_OFF + I2C_REG_DATA),
|
||||||
};
|
};
|
||||||
|
|
||||||
inline vu8* i2cGetDataReg(u8 bus_id) {
|
static inline vu8* i2cGetDataReg(u8 bus_id) {
|
||||||
return reg_data_addrs[bus_id];
|
return reg_data_addrs[bus_id];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,22 +38,22 @@ static vu8* reg_cnt_addrs[] = {
|
|||||||
(vu8*)(I2C3_REG_OFF + I2C_REG_CNT),
|
(vu8*)(I2C3_REG_OFF + I2C_REG_CNT),
|
||||||
};
|
};
|
||||||
|
|
||||||
inline vu8* i2cGetCntReg(u8 bus_id) {
|
static inline vu8* i2cGetCntReg(u8 bus_id) {
|
||||||
return reg_cnt_addrs[bus_id];
|
return reg_cnt_addrs[bus_id];
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
inline void i2cWaitBusy(u8 bus_id) {
|
static inline void i2cWaitBusy(u8 bus_id) {
|
||||||
while (*i2cGetCntReg(bus_id) & 0x80);
|
while (*i2cGetCntReg(bus_id) & 0x80);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool i2cGetResult(u8 bus_id) {
|
static inline u32 i2cGetResult(u8 bus_id) {
|
||||||
i2cWaitBusy(bus_id);
|
i2cWaitBusy(bus_id);
|
||||||
return (*i2cGetCntReg(bus_id) >> 4) & 1;
|
return (*i2cGetCntReg(bus_id) >> 4) & 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void i2cStop(u8 bus_id, u8 arg0) {
|
static void i2cStop(u8 bus_id, u8 arg0) {
|
||||||
*i2cGetCntReg(bus_id) = (arg0 << 5) | 0xC0;
|
*i2cGetCntReg(bus_id) = (arg0 << 5) | 0xC0;
|
||||||
i2cWaitBusy(bus_id);
|
i2cWaitBusy(bus_id);
|
||||||
*i2cGetCntReg(bus_id) = 0xC5;
|
*i2cGetCntReg(bus_id) = 0xC5;
|
||||||
@@ -61,14 +61,14 @@ void i2cStop(u8 bus_id, u8 arg0) {
|
|||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
bool i2cSelectDevice(u8 bus_id, u8 dev_reg) {
|
static u32 i2cSelectDevice(u8 bus_id, u8 dev_reg) {
|
||||||
i2cWaitBusy(bus_id);
|
i2cWaitBusy(bus_id);
|
||||||
*i2cGetDataReg(bus_id) = dev_reg;
|
*i2cGetDataReg(bus_id) = dev_reg;
|
||||||
*i2cGetCntReg(bus_id) = 0xC2;
|
*i2cGetCntReg(bus_id) = 0xC2;
|
||||||
return i2cGetResult(bus_id);
|
return i2cGetResult(bus_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool i2cSelectRegister(u8 bus_id, u8 reg) {
|
static u32 i2cSelectRegister(u8 bus_id, u8 reg) {
|
||||||
i2cWaitBusy(bus_id);
|
i2cWaitBusy(bus_id);
|
||||||
*i2cGetDataReg(bus_id) = reg;
|
*i2cGetDataReg(bus_id) = reg;
|
||||||
*i2cGetCntReg(bus_id) = 0xC0;
|
*i2cGetCntReg(bus_id) = 0xC0;
|
||||||
@@ -77,58 +77,7 @@ bool i2cSelectRegister(u8 bus_id, u8 reg) {
|
|||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
u8 i2cReadRegister(u8 dev_id, u8 reg) {
|
u32 i2cWriteRegister(u8 dev_id, u8 reg, u8 data) {
|
||||||
u8 bus_id = i2cGetDeviceBusId(dev_id);
|
|
||||||
u8 dev_addr = i2cGetDeviceRegAddr(dev_id);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < 8; i++) {
|
|
||||||
if (i2cSelectDevice(bus_id, dev_addr) && i2cSelectRegister(bus_id, reg)) {
|
|
||||||
if (i2cSelectDevice(bus_id, dev_addr | 1)) {
|
|
||||||
i2cWaitBusy(bus_id);
|
|
||||||
i2cStop(bus_id, 1);
|
|
||||||
i2cWaitBusy(bus_id);
|
|
||||||
return *i2cGetDataReg(bus_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*i2cGetCntReg(bus_id) = 0xC5;
|
|
||||||
i2cWaitBusy(bus_id);
|
|
||||||
}
|
|
||||||
return 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool i2cReadRegisterBuffer(unsigned int dev_id, int reg, u8* buffer, size_t buf_size) {
|
|
||||||
u8 bus_id = i2cGetDeviceBusId(dev_id);
|
|
||||||
u8 dev_addr = i2cGetDeviceRegAddr(dev_id);
|
|
||||||
|
|
||||||
size_t j = 0;
|
|
||||||
while (!i2cSelectDevice(bus_id, dev_addr)
|
|
||||||
|| !i2cSelectRegister(bus_id, reg)
|
|
||||||
|| !i2cSelectDevice(bus_id, dev_addr | 1))
|
|
||||||
{
|
|
||||||
i2cWaitBusy(bus_id);
|
|
||||||
*i2cGetCntReg(bus_id) = 0xC5;
|
|
||||||
i2cWaitBusy(bus_id);
|
|
||||||
if (++j >= 8)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buf_size != 1) {
|
|
||||||
for (size_t i = 0; i < buf_size - 1; i++) {
|
|
||||||
i2cWaitBusy(bus_id);
|
|
||||||
*i2cGetCntReg(bus_id) = 0xF0;
|
|
||||||
i2cWaitBusy(bus_id);
|
|
||||||
buffer[i] = *i2cGetDataReg(bus_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
i2cWaitBusy(bus_id);
|
|
||||||
*i2cGetCntReg(bus_id) = 0xE1;
|
|
||||||
i2cWaitBusy(bus_id);
|
|
||||||
*buffer = *i2cGetDataReg(bus_id);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool i2cWriteRegister(u8 dev_id, u8 reg, u8 data) {
|
|
||||||
u8 bus_id = i2cGetDeviceBusId(dev_id);
|
u8 bus_id = i2cGetDeviceBusId(dev_id);
|
||||||
u8 dev_addr = i2cGetDeviceRegAddr(dev_id);
|
u8 dev_addr = i2cGetDeviceRegAddr(dev_id);
|
||||||
|
|
||||||
@@ -139,11 +88,11 @@ bool i2cWriteRegister(u8 dev_id, u8 reg, u8 data) {
|
|||||||
*i2cGetCntReg(bus_id) = 0xC1;
|
*i2cGetCntReg(bus_id) = 0xC1;
|
||||||
i2cStop(bus_id, 0);
|
i2cStop(bus_id, 0);
|
||||||
if (i2cGetResult(bus_id))
|
if (i2cGetResult(bus_id))
|
||||||
return true;
|
return 1;
|
||||||
}
|
}
|
||||||
*i2cGetCntReg(bus_id) = 0xC5;
|
*i2cGetCntReg(bus_id) = 0xC5;
|
||||||
i2cWaitBusy(bus_id);
|
i2cWaitBusy(bus_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
18
source/i2c.h
Normal file
18
source/i2c.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
#define I2C1_REG_OFF 0x10161000
|
||||||
|
#define I2C2_REG_OFF 0x10144000
|
||||||
|
#define I2C3_REG_OFF 0x10148000
|
||||||
|
|
||||||
|
#define I2C_REG_DATA 0
|
||||||
|
#define I2C_REG_CNT 1
|
||||||
|
#define I2C_REG_CNTEX 2
|
||||||
|
#define I2C_REG_SCL 4
|
||||||
|
|
||||||
|
#define I2C_DEV_MCU 3
|
||||||
|
#define I2C_DEV_GYRO 10
|
||||||
|
#define I2C_DEV_IR 13
|
||||||
|
|
||||||
|
u32 i2cWriteRegister(u8 dev_id, u8 reg, u8 data);
|
||||||
@@ -1,14 +1,21 @@
|
|||||||
/*
|
/*
|
||||||
* loader.c
|
* loader.c
|
||||||
|
* by Aurora Wright
|
||||||
|
* Copyright (c) 2016 All Rights Reserved
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "screeninit.h"
|
||||||
|
#include "../build/loader.h"
|
||||||
|
|
||||||
#define PAYLOAD_ADDRESS 0x24F00000
|
#define PAYLOAD_ADDRESS 0x24F00000
|
||||||
|
|
||||||
void loadPayload(void){
|
void loadPayload(void){
|
||||||
if(fileExists("rei/payloads/default.bin") &&
|
if(fileExists("aurei/payloads/default.bin")){
|
||||||
fileRead((u8 *)PAYLOAD_ADDRESS, "rei/loader.bin", 0))
|
initScreens();
|
||||||
|
memcpy((void *)PAYLOAD_ADDRESS, loader, loader_size);
|
||||||
((void (*)())PAYLOAD_ADDRESS)();
|
((void (*)())PAYLOAD_ADDRESS)();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* loader.h
|
* loader.h
|
||||||
|
* by Aurora Wright
|
||||||
|
* Copyright (c) 2016 All Rights Reserved
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|||||||
@@ -1,21 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* main.c
|
* main.c
|
||||||
* by Reisyukaku
|
* by Reisyukaku / Aurora Wright
|
||||||
* Copyright (c) 2015 All Rights Reserved
|
* Copyright (c) 2016 All Rights Reserved
|
||||||
*
|
*
|
||||||
* Minimalist CFW for N3DS
|
* Minimalist CFW for (N)3DS
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
#include "firm.h"
|
#include "firm.h"
|
||||||
|
|
||||||
void main(){
|
void main(void){
|
||||||
mountSD();
|
mountSD();
|
||||||
setupCFW();
|
setupCFW();
|
||||||
}
|
loadFirm();
|
||||||
|
patchFirm();
|
||||||
void startCFW(){
|
|
||||||
if(!loadFirm()) return;
|
|
||||||
if(!patchFirm()) return;
|
|
||||||
launchFirm();
|
launchFirm();
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* memory.c
|
* memory.c
|
||||||
* by Reisyukaku
|
* by Reisyukaku / Aurora Wright
|
||||||
* Copyright (c) 2015 All Rights Reserved
|
* Copyright (c) 2016 All Rights Reserved
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
@@ -19,6 +19,12 @@ void memset(void *dest, int filler, u32 size){
|
|||||||
destc[i] = (u8)filler;
|
destc[i] = (u8)filler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void memset32(void *dest, u32 filler, u32 size){
|
||||||
|
u32 *dest32 = (u32 *)dest;
|
||||||
|
for (u32 i = 0; i < size / 4; i++)
|
||||||
|
dest32[i] = filler;
|
||||||
|
}
|
||||||
|
|
||||||
int memcmp(const void *buf1, const void *buf2, u32 size){
|
int memcmp(const void *buf1, const void *buf2, u32 size){
|
||||||
const u8 *buf1c = (const u8 *)buf1;
|
const u8 *buf1c = (const u8 *)buf1;
|
||||||
const u8 *buf2c = (const u8 *)buf2;
|
const u8 *buf2c = (const u8 *)buf2;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* memory.h
|
* memory.h
|
||||||
* by Reisyukaku
|
* by Reisyukaku / Aurora Wright
|
||||||
* Copyright (c) 2015 All Rights Reserved
|
* Copyright (c) 2016 All Rights Reserved
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@@ -10,5 +10,6 @@
|
|||||||
|
|
||||||
void memcpy(void *dest, const void *src, u32 size);
|
void memcpy(void *dest, const void *src, u32 size);
|
||||||
void memset(void *dest, int filler, u32 size);
|
void memset(void *dest, int filler, u32 size);
|
||||||
|
void memset32(void *dest, u32 filler, u32 size);
|
||||||
int memcmp(const void *buf1, const void *buf2, u32 size);
|
int memcmp(const void *buf1, const void *buf2, u32 size);
|
||||||
void *memsearch(void *start_pos, const void *search, u32 size, u32 size_search);
|
void *memsearch(void *start_pos, const void *search, u32 size, u32 size_search);
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* patches.c
|
* patches.c
|
||||||
* by Reisyukaku
|
* by Reisyukaku / Aurora Wright
|
||||||
* Copyright (c) 2015 All Rights Reserved
|
* Copyright (c) 2016 All Rights Reserved
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "patches.h"
|
#include "patches.h"
|
||||||
@@ -11,25 +11,28 @@
|
|||||||
* Patches
|
* Patches
|
||||||
**************************************************/
|
**************************************************/
|
||||||
|
|
||||||
const u8 mpu[0x2C] = { //MPU shit
|
const u8 mpu[0x2C] = {
|
||||||
0x03, 0x00, 0x36, 0x00, 0x00, 0x00, 0x10, 0x10, 0x01, 0x00, 0x00, 0x01, 0x03, 0x00, 0x36, 0x00,
|
0x03, 0x00, 0x36, 0x00, 0x00, 0x00, 0x10, 0x10, 0x01, 0x00, 0x00, 0x01, 0x03, 0x00, 0x36, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x20, 0x01, 0x01, 0x01, 0x01, 0x03, 0x06, 0x20, 0x00, 0x00, 0x00, 0x00, 0x08,
|
0x00, 0x00, 0x00, 0x20, 0x01, 0x01, 0x01, 0x01, 0x03, 0x06, 0x20, 0x00, 0x00, 0x00, 0x00, 0x08,
|
||||||
0x01, 0x01, 0x01, 0x01, 0x03, 0x06, 0x1C, 0x00, 0x00, 0x00, 0x02, 0x08
|
0x01, 0x01, 0x01, 0x01, 0x03, 0x06, 0x1C, 0x00, 0x00, 0x00, 0x02, 0x08
|
||||||
};
|
};
|
||||||
|
|
||||||
u8 nandRedir[0x08] = {0x00, 0x4C, 0xA0, 0x47, 0xC0, 0xA5, 0x01, 0x08}; //Branch to emunand function
|
//Branch to emunand function. To be filled in
|
||||||
|
u8 nandRedir[0x08] = {0x00, 0x4C, 0xA0, 0x47, 0x00, 0x00, 0x00, 0x00};
|
||||||
|
|
||||||
const u8 sigPat1[2] = {0x00, 0x20};
|
const u8 sigPat1[2] = {0x00, 0x20};
|
||||||
const u8 sigPat2[4] = {0x00, 0x20, 0x70, 0x47};
|
const u8 sigPat2[4] = {0x00, 0x20, 0x70, 0x47};
|
||||||
|
|
||||||
const u8 FIRMblock[4] = {0x00, 0x20, 0xC0, 0x46};
|
const u8 writeBlock[4] = {0x00, 0x20, 0xC0, 0x46};
|
||||||
|
|
||||||
const u8 emuInstr[5] = {0xA5, 0x01, 0x08, 0x30, 0xA5};
|
|
||||||
|
|
||||||
/**************************************************
|
/**************************************************
|
||||||
* Functions
|
* Functions
|
||||||
**************************************************/
|
**************************************************/
|
||||||
|
|
||||||
|
u8 *getProc9(void *pos, u32 size){
|
||||||
|
return (u8 *)memsearch(pos, "ess9", size, 4);
|
||||||
|
}
|
||||||
|
|
||||||
void getSignatures(void *pos, u32 size, u32 *off, u32 *off2){
|
void getSignatures(void *pos, u32 size, u32 *off, u32 *off2){
|
||||||
//Look for signature checks
|
//Look for signature checks
|
||||||
const unsigned char pattern[] = {0xC0, 0x1C, 0x76, 0xE7};
|
const unsigned char pattern[] = {0xC0, 0x1C, 0x76, 0xE7};
|
||||||
@@ -39,26 +42,29 @@ void getSignatures(void *pos, u32 size, u32 *off, u32 *off2){
|
|||||||
*off2 = (u32)memsearch(pos, pattern2, size, 4) - 1;
|
*off2 = (u32)memsearch(pos, pattern2, size, 4) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void getReboot(void *pos, u32 size, u32 *off){
|
void *getReboot(void *pos, u32 size){
|
||||||
//Look for FIRM reboot code
|
//Look for FIRM reboot code
|
||||||
const unsigned char pattern[] = {0xDE, 0x1F, 0x8D, 0xE2};
|
const unsigned char pattern[] = {0xDE, 0x1F, 0x8D, 0xE2};
|
||||||
|
|
||||||
*off = (u32)memsearch(pos, pattern, size, 4) - 0x10;
|
return (u8 *)memsearch(pos, pattern, size, 4) - 0x10;
|
||||||
}
|
}
|
||||||
|
|
||||||
void getfOpen(void *pos, u32 size, u32 *off){
|
u32 getfOpen(void *pos, u32 size, u8 *proc9Offset){
|
||||||
|
//Offset Process9 code gets loaded to in memory (defined in ExHeader)
|
||||||
|
u32 p9MemAddr = *(u32 *)(proc9Offset + 0xC);
|
||||||
|
//Start of Process9 .code section (start of NCCH + ExeFS offset + ExeFS header size)
|
||||||
|
u32 p9CodeOff = (u32)(proc9Offset - 0x204) + (*(u32 *)(proc9Offset - 0x64) * 0x200) + 0x200;
|
||||||
|
|
||||||
//Calculate fOpen
|
//Calculate fOpen
|
||||||
u32 p9addr = *(u32 *)((u8 *)memsearch(pos, "ess9", size, 4) + 0xC);
|
|
||||||
u32 p9off = (u32)memsearch(pos, "code", size, 4) + 0x1FF;
|
|
||||||
const unsigned char pattern[] = {0xB0, 0x04, 0x98, 0x0D};
|
const unsigned char pattern[] = {0xB0, 0x04, 0x98, 0x0D};
|
||||||
|
|
||||||
*off = (u32)memsearch(pos, pattern, size, 4) - 2 - p9off + p9addr;
|
return (u32)memsearch(pos, pattern, size, 4) - 2 - p9CodeOff + p9MemAddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void getFIRMWrite(void *pos, u32 size, u32 *off){
|
void *getFirmWrite(void *pos, u32 size){
|
||||||
//Look for FIRM writing code
|
//Look for FIRM writing code
|
||||||
u8 *firmwrite = (u8 *)memsearch(pos, "exe:", size, 4);
|
u8 *firmwrite = (u8 *)memsearch(pos, "exe:", size, 4);
|
||||||
const unsigned char pattern[] = {0x00, 0x28, 0x01, 0xDA};
|
const unsigned char pattern[] = {0x00, 0x28, 0x01, 0xDA};
|
||||||
|
|
||||||
*off = (u32)memsearch(firmwrite - 0x100, pattern, 0x100, 4);
|
return memsearch(firmwrite - 0x100, pattern, 0x100, 4);
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* patches.h
|
* patches.h
|
||||||
* by Reisyukaku
|
* by Reisyukaku / Aurora Wright
|
||||||
* Copyright (c) 2015 All Rights Reserved
|
* Copyright (c) 2016 All Rights Reserved
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@@ -15,13 +15,13 @@ const u8 mpu[0x2C];
|
|||||||
u8 nandRedir[0x08];
|
u8 nandRedir[0x08];
|
||||||
const u8 sigPat1[2];
|
const u8 sigPat1[2];
|
||||||
const u8 sigPat2[4];
|
const u8 sigPat2[4];
|
||||||
const u8 FIRMblock[4];
|
const u8 writeBlock[4];
|
||||||
const u8 emuInstr[5];
|
|
||||||
|
|
||||||
/**************************************************
|
/**************************************************
|
||||||
* Functions
|
* Functions
|
||||||
**************************************************/
|
**************************************************/
|
||||||
|
u8 *getProc9(void *pos, u32 size);
|
||||||
void getSignatures(void *pos, u32 size, u32 *off, u32 *off2);
|
void getSignatures(void *pos, u32 size, u32 *off, u32 *off2);
|
||||||
void getReboot(void *pos, u32 size, u32 *off);
|
void *getReboot(void *pos, u32 size);
|
||||||
void getfOpen(void *pos, u32 size, u32 *off);
|
u32 getfOpen(void *pos, u32 size, u8 *proc9Offset);
|
||||||
void getFIRMWrite(void *pos, u32 size, u32 *off);
|
void *getFirmWrite(void *pos, u32 size);
|
||||||
@@ -1,12 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* screeninit.c
|
||||||
|
* by Aurora Wright
|
||||||
|
* Screen init code by dark_samus, bil1s, Normmatt, delebile and others.
|
||||||
|
* Screen deinit code by tiniVi.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 All Rights Reserved
|
||||||
|
*/
|
||||||
|
|
||||||
#include "screeninit.h"
|
#include "screeninit.h"
|
||||||
|
#include "draw.h"
|
||||||
#include "i2c.h"
|
#include "i2c.h"
|
||||||
|
|
||||||
void initLCD()
|
static vu32 *const arm11 = (vu32 *)0x1FFFFFF8;
|
||||||
{
|
|
||||||
vu32 *const arm11 = (u32 *)0x1FFFFFF8;
|
void deinitScreens(void){
|
||||||
|
void __attribute__((naked)) ARM11(void){
|
||||||
|
//Disable interrupts
|
||||||
|
__asm(".word 0xF10C01C0");
|
||||||
|
|
||||||
|
//Clear ARM11 entry offset
|
||||||
|
*arm11 = 0;
|
||||||
|
|
||||||
|
//Shutdown LCDs
|
||||||
|
*(vu32 *)0x10202A44 = 0;
|
||||||
|
*(vu32 *)0x10202244 = 0;
|
||||||
|
*(vu32 *)0x10202014 = 0;
|
||||||
|
|
||||||
|
//Wait for the entry to be set
|
||||||
|
while(!*arm11);
|
||||||
|
//Jump to it
|
||||||
|
((void (*)())*arm11)();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(PDN_GPU_CNT != 0x1){
|
||||||
|
*arm11 = (u32)ARM11;
|
||||||
|
while(*arm11);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void initScreens(void){
|
||||||
|
void __attribute__((naked)) ARM11(void){
|
||||||
|
//Disable interrupts
|
||||||
|
__asm(".word 0xF10C01C0");
|
||||||
|
|
||||||
void __attribute__((naked)) ARM11()
|
|
||||||
{
|
|
||||||
*(vu32 *)0x10141200 = 0x1007F;
|
*(vu32 *)0x10141200 = 0x1007F;
|
||||||
*(vu32 *)0x10202014 = 0x00000001;
|
*(vu32 *)0x10202014 = 0x00000001;
|
||||||
*(vu32 *)0x1020200C &= 0xFFFEFFFE;
|
*(vu32 *)0x1020200C &= 0xFFFEFFFE;
|
||||||
@@ -93,6 +129,11 @@ void initLCD()
|
|||||||
*(vu32 *)0x10400568 = 0x18346500;
|
*(vu32 *)0x10400568 = 0x18346500;
|
||||||
*(vu32 *)0x1040056c = 0x18346500;
|
*(vu32 *)0x1040056c = 0x18346500;
|
||||||
|
|
||||||
|
//Set CakeBrah framebuffers
|
||||||
|
*((vu32 *)0x23FFFE00) = 0x18300000;
|
||||||
|
*((vu32 *)0x23FFFE04) = 0x18300000;
|
||||||
|
*((vu32 *)0x23FFFE08) = 0x18346500;
|
||||||
|
|
||||||
//Clear ARM11 entry offset
|
//Clear ARM11 entry offset
|
||||||
*arm11 = 0;
|
*arm11 = 0;
|
||||||
|
|
||||||
@@ -102,17 +143,10 @@ void initLCD()
|
|||||||
((void (*)())*arm11)();
|
((void (*)())*arm11)();
|
||||||
}
|
}
|
||||||
|
|
||||||
//Determine if screen was already inited
|
if(PDN_GPU_CNT == 0x1){
|
||||||
if(*(vu8 *)0x10141200 != 0x1) return;
|
*arm11 = (u32)ARM11;
|
||||||
|
while(*arm11);
|
||||||
|
}
|
||||||
|
|
||||||
//Set CakeBrah framebuffers
|
clearScreens();
|
||||||
*(vu32 *)0x23FFFE00 = 0x18300000;
|
|
||||||
*(vu32 *)0x23FFFE04 = 0x18300000;
|
|
||||||
*(vu32 *)0x23FFFE08 = 0x18346500;
|
|
||||||
|
|
||||||
*arm11 = (u32)ARM11;
|
|
||||||
|
|
||||||
//This delay is needed for some reason
|
|
||||||
for(vu32 i = 0; i < 0x2000; ++i);
|
|
||||||
while(*arm11);
|
|
||||||
}
|
}
|
||||||
17
source/screeninit.h
Normal file
17
source/screeninit.h
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* screeninit.h
|
||||||
|
* by Aurora Wright
|
||||||
|
* Screen init code by dark_samus, bil1s, Normmatt, delebile and others.
|
||||||
|
* Screen deinit code by tiniVi.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 All Rights Reserved
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
#define PDN_GPU_CNT (*(vu8 *)0x10141200)
|
||||||
|
|
||||||
|
void deinitScreens(void);
|
||||||
|
void initScreens(void);
|
||||||
@@ -10,7 +10,7 @@ _start:
|
|||||||
mcr p15, 0, r0, c5, c0, 2 @ write data access
|
mcr p15, 0, r0, c5, c0, 2 @ write data access
|
||||||
mcr p15, 0, r0, c5, c0, 3 @ write instruction access
|
mcr p15, 0, r0, c5, c0, 3 @ write instruction access
|
||||||
|
|
||||||
@ Set MPU permissions
|
@ Set MPU permissions and cache settings
|
||||||
ldr r0, =0xFFFF001D @ ffff0000 32k
|
ldr r0, =0xFFFF001D @ ffff0000 32k
|
||||||
ldr r1, =0x01FF801D @ 01ff8000 32k
|
ldr r1, =0x01FF801D @ 01ff8000 32k
|
||||||
ldr r2, =0x08000027 @ 08000000 1M
|
ldr r2, =0x08000027 @ 08000000 1M
|
||||||
@@ -27,6 +27,10 @@ _start:
|
|||||||
mcr p15, 0, r5, c6, c5, 0
|
mcr p15, 0, r5, c6, c5, 0
|
||||||
mcr p15, 0, r6, c6, c6, 0
|
mcr p15, 0, r6, c6, c6, 0
|
||||||
mcr p15, 0, r7, c6, c7, 0
|
mcr p15, 0, r7, c6, c7, 0
|
||||||
|
mov r0, #0x25
|
||||||
|
mcr p15, 0, r0, c2, c0, 0 @ data cacheable
|
||||||
|
mcr p15, 0, r0, c2, c0, 1 @ instruction cacheable
|
||||||
|
mcr p15, 0, r0, c3, c0, 0 @ data bufferable
|
||||||
|
|
||||||
@ Enable caches
|
@ Enable caches
|
||||||
mrc p15, 0, r0, c1, c0, 0 @ read control register
|
mrc p15, 0, r0, c1, c0, 0 @ read control register
|
||||||
@@ -48,13 +52,5 @@ _start:
|
|||||||
|
|
||||||
bl main
|
bl main
|
||||||
|
|
||||||
@ Set cache settings
|
|
||||||
mov r0, #0x25
|
|
||||||
mcr p15, 0, r0, c3, c0, 0 @ Write bufferable 0, 2, 5
|
|
||||||
mcr p15, 0, r0, c2, c0, 0 @ Data cacheable 0, 2, 5
|
|
||||||
mcr p15, 0, r0, c2, c0, 1 @ Inst cacheable 0, 2, 5
|
|
||||||
|
|
||||||
bl startCFW
|
|
||||||
|
|
||||||
.die:
|
.die:
|
||||||
b .die
|
b .die
|
||||||
|
|||||||
123
source/utils.c
Normal file
123
source/utils.c
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
* utils.c
|
||||||
|
* by Aurora Wright
|
||||||
|
* Copyright (c) 2016 All Rights Reserved
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
#include "screeninit.h"
|
||||||
|
#include "draw.h"
|
||||||
|
#include "fs.h"
|
||||||
|
#include "i2c.h"
|
||||||
|
#include "buttons.h"
|
||||||
|
|
||||||
|
//Number of options that can be configured
|
||||||
|
#define OPTIONS 3
|
||||||
|
|
||||||
|
#define COLOR_TITLE 0xFF9900
|
||||||
|
#define COLOR_WHITE 0xFFFFFF
|
||||||
|
#define COLOR_RED 0x0000FF
|
||||||
|
#define COLOR_BLACK 0x000000
|
||||||
|
|
||||||
|
struct options {
|
||||||
|
char *text[OPTIONS];
|
||||||
|
int pos_y[OPTIONS];
|
||||||
|
u32 enabled[OPTIONS];
|
||||||
|
u32 selected;
|
||||||
|
};
|
||||||
|
|
||||||
|
static u16 waitInput(void){
|
||||||
|
u32 pressedkey = 0;
|
||||||
|
u16 key;
|
||||||
|
|
||||||
|
//Wait for no keys to be pressed
|
||||||
|
while(HID_PAD);
|
||||||
|
|
||||||
|
do {
|
||||||
|
//Wait for a key to be pressed
|
||||||
|
while(!HID_PAD);
|
||||||
|
key = HID_PAD;
|
||||||
|
|
||||||
|
//Make sure it's pressed
|
||||||
|
for(u32 i = 0x13000; i; i--){
|
||||||
|
if (key != HID_PAD)
|
||||||
|
break;
|
||||||
|
if(i==1) pressedkey = 1;
|
||||||
|
}
|
||||||
|
} while (!pressedkey);
|
||||||
|
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
void configureCFW(const char *configPath){
|
||||||
|
struct options options;
|
||||||
|
|
||||||
|
options.text[0] = "( ) Updated SysNAND mode (A9LH-only)";
|
||||||
|
options.text[1] = "( ) Use pre-patched FIRMs";
|
||||||
|
options.text[2] = "( ) Force A9LH detection";
|
||||||
|
|
||||||
|
initScreens();
|
||||||
|
|
||||||
|
drawString("AuReiNand configuration", 10, 10, COLOR_TITLE);
|
||||||
|
drawString("Press A to select, START to save and reboot", 10, 30, COLOR_WHITE);
|
||||||
|
|
||||||
|
//Read and parse the existing configuration
|
||||||
|
u16 tempConfig = 0;
|
||||||
|
fileRead((u8 *)&tempConfig, configPath, 2);
|
||||||
|
for(u32 i = 0; i < OPTIONS; i++)
|
||||||
|
options.enabled[i] = (tempConfig >> i) & 0x1;
|
||||||
|
|
||||||
|
//Pre-select the first configuration option
|
||||||
|
options.selected = 0;
|
||||||
|
|
||||||
|
//Boring configuration menu
|
||||||
|
while(1){
|
||||||
|
u16 pressed = 0;
|
||||||
|
|
||||||
|
do{
|
||||||
|
for(u32 i = 0; i < OPTIONS; i++){
|
||||||
|
options.pos_y[i] = drawString(options.text[i], 10, !i ? 60 : options.pos_y[i - 1] + SPACING_VERT, options.selected == i ? COLOR_RED : COLOR_WHITE);
|
||||||
|
drawCharacter('x', 10 + SPACING_HORIZ, options.pos_y[i], options.enabled[i] ? (options.selected == i ? COLOR_RED : COLOR_WHITE) : COLOR_BLACK);
|
||||||
|
}
|
||||||
|
pressed = waitInput();
|
||||||
|
} while(!(pressed & (BUTTON_UP | BUTTON_DOWN | BUTTON_A | BUTTON_START)));
|
||||||
|
|
||||||
|
if(pressed == BUTTON_UP) options.selected = !options.selected ? OPTIONS - 1 : options.selected - 1;
|
||||||
|
else if(pressed == BUTTON_DOWN) options.selected = options.selected == OPTIONS - 1 ? 0 : options.selected + 1;
|
||||||
|
else if(pressed == BUTTON_A) options.enabled[options.selected] = !options.enabled[options.selected];
|
||||||
|
else if(pressed == BUTTON_START) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Preserve the last-used boot options (second byte)
|
||||||
|
tempConfig &= 0xFF00;
|
||||||
|
|
||||||
|
//Parse and write the selected options
|
||||||
|
for(u32 i = 0; i < OPTIONS; i++)
|
||||||
|
tempConfig |= options.enabled[i] << i;
|
||||||
|
fileWrite((u8 *)&tempConfig, configPath, 2);
|
||||||
|
|
||||||
|
//Reboot
|
||||||
|
i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2);
|
||||||
|
while(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void deleteFirms(const char *firmPaths[], u32 firms){
|
||||||
|
while(firms){
|
||||||
|
fileDelete(firmPaths[firms - 1]);
|
||||||
|
firms--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void error(const char *message){
|
||||||
|
initScreens();
|
||||||
|
|
||||||
|
drawString("An error has occurred:", 10, 10, COLOR_RED);
|
||||||
|
int pos_y = drawString(message, 10, 30, COLOR_WHITE);
|
||||||
|
drawString("Press any button to shutdown", 10, pos_y + 2 * SPACING_VERT, COLOR_WHITE);
|
||||||
|
|
||||||
|
waitInput();
|
||||||
|
|
||||||
|
//Shutdown
|
||||||
|
i2cWriteRegister(I2C_DEV_MCU, 0x20, 1);
|
||||||
|
while(1);
|
||||||
|
}
|
||||||
13
source/utils.h
Normal file
13
source/utils.h
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* utils.h
|
||||||
|
* by Aurora Wright
|
||||||
|
* Copyright (c) 2016 All Rights Reserved
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
void configureCFW(const char *configPath);
|
||||||
|
void deleteFirms(const char *firmPaths[], u32 firms);
|
||||||
|
void error(const char *message);
|
||||||
Reference in New Issue
Block a user