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
|
||||
endif
|
||||
|
||||
name := ReiNand
|
||||
name := AuReiNand
|
||||
|
||||
dir_source := source
|
||||
dir_data := data
|
||||
@@ -26,7 +26,7 @@ dir_loader := loader
|
||||
|
||||
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
|
||||
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, \
|
||||
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
|
||||
@@ -34,7 +34,7 @@ objects_cfw = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
|
||||
|
||||
|
||||
.PHONY: all
|
||||
all: launcher a9lh emunand reboot ninjhax loader
|
||||
all: launcher a9lh ninjhax
|
||||
|
||||
.PHONY: launcher
|
||||
launcher: $(dir_out)/$(name).dat
|
||||
@@ -42,54 +42,43 @@ launcher: $(dir_out)/$(name).dat
|
||||
.PHONY: a9lh
|
||||
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
|
||||
ninjhax: $(dir_out)/3ds/$(name)
|
||||
|
||||
.PHONY: loader
|
||||
loader: $(dir_out)/rei/loader.bin
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
@$(MAKE) $(FLAGS) -C $(dir_mset) clean
|
||||
@$(MAKE) $(FLAGS) -C $(dir_ninjhax) clean
|
||||
@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
|
||||
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 $@
|
||||
|
||||
$(dir_out)/3ds/$(name):
|
||||
$(dir_out)/3ds/$(name): $(dir_out)
|
||||
@mkdir -p "$(dir_out)/3ds/$(name)"
|
||||
@$(MAKE) $(FLAGS) -C $(dir_ninjhax)
|
||||
@mv $(dir_out)/$(name).3dsx $@
|
||||
@mv $(dir_out)/$(name).smdh $@
|
||||
|
||||
$(dir_out)/rei:
|
||||
@mkdir -p "$(dir_out)/rei"
|
||||
$(dir_out):
|
||||
@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 $<
|
||||
@mkdir -p "$(dir_out)/rei/emunand"
|
||||
@mv emunand.bin $@
|
||||
@mv emunand.bin $(dir_build)
|
||||
@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
|
||||
@armips $<
|
||||
@mkdir -p "$(dir_out)/rei/reboot"
|
||||
@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)/loader.h: $(dir_loader)/Makefile
|
||||
@$(MAKE) -C $(dir_loader)
|
||||
@bin2c -o $@ -n loader $(dir_loader)/loader.bin
|
||||
|
||||
$(dir_build)/main.bin: $(dir_build)/main.elf
|
||||
$(OC) -S -O binary $< $@
|
||||
@@ -98,7 +87,7 @@ $(dir_build)/main.elf: $(objects_cfw)
|
||||
# FatFs requires libgcc for __aeabi_uidiv
|
||||
$(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)"
|
||||
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
||||
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
.nds
|
||||
.arm.little
|
||||
|
||||
sdmmc equ 0x434D4453 ;dummy
|
||||
|
||||
.create "emunand.bin", 0x0801A5C0
|
||||
.org 0x0801A5C0
|
||||
.create "emunand.bin", 0
|
||||
.arm
|
||||
nand_sd:
|
||||
; Original code that still needs to be executed.
|
||||
@@ -15,7 +12,7 @@ nand_sd:
|
||||
|
||||
; If we're already trying to access the SD, return.
|
||||
ldr r2, [r0, #4]
|
||||
ldr r1, =sdmmc
|
||||
ldr r1, [sdmmc]
|
||||
cmp r2, r1
|
||||
beq nand_sd_ret
|
||||
|
||||
@@ -23,12 +20,10 @@ nand_sd:
|
||||
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)
|
||||
|
||||
ldr r3, =nand_offset
|
||||
ldr r3, [r3]
|
||||
ldr r3, [nand_offset]
|
||||
add r2, r3 ; Add the offset to the NAND in the SD.
|
||||
|
||||
ldreq r3, =ncsd_header_offset
|
||||
ldreq r3, [r3]
|
||||
ldreq r3, [ncsd_header_offset]
|
||||
addeq r2, r3 ; If we're reading the ncsd header, add the offset of that sector.
|
||||
|
||||
str r2, [r0, #8] ; Store sector to read
|
||||
@@ -45,6 +40,7 @@ nand_sd:
|
||||
add r0, #4
|
||||
bx r0
|
||||
.pool
|
||||
sdmmc: .ascii "SDMC"
|
||||
nand_offset: .ascii "NAND" ; for rednand this should be 1
|
||||
ncsd_header_offset: .ascii "NCSD" ; depends on nand manufacturer + emunand type (GW/RED)
|
||||
.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
|
||||
|
||||
CFLAGS := -g -Wall -O2\
|
||||
-march=armv5te -mtune=arm946e-s -fomit-frame-pointer\
|
||||
-march=armv5te -mtune=arm946e-s\
|
||||
-ffast-math -Wno-main -std=c99\
|
||||
$(ARCH)
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ DRESULT disk_read (
|
||||
DRESULT disk_write (
|
||||
__attribute__((unused))
|
||||
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 */
|
||||
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 */
|
||||
|
||||
DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */
|
||||
static DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */
|
||||
FATFS* fs, /* File system object */
|
||||
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 */
|
||||
|
||||
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 */
|
||||
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 */
|
||||
|
||||
#if !_FS_READONLY
|
||||
FRESULT put_fat (
|
||||
static FRESULT put_fat (
|
||||
FATFS* fs, /* File system object */
|
||||
DWORD clst, /* FAT index number (cluster number) to be changed */
|
||||
DWORD val /* New value to be set to the entry */
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include "sdmmc.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 "buttons.h"
|
||||
#include "screeninit.h"
|
||||
#include "fatfs/ff.h"
|
||||
|
||||
#define PAYLOAD_ADDRESS 0x23F00000
|
||||
|
||||
u32 loadPayload(const char *path){
|
||||
static u32 loadPayload(const char *path){
|
||||
FIL payload;
|
||||
unsigned int br;
|
||||
if(f_open(&payload, path, FA_READ) == FR_OK)
|
||||
@@ -19,24 +18,22 @@ u32 loadPayload(const char *path){
|
||||
return 0;
|
||||
}
|
||||
|
||||
void main(){
|
||||
void main(void){
|
||||
FATFS fs;
|
||||
f_mount(&fs, "0:", 1);
|
||||
|
||||
//Get pressed buttons
|
||||
u16 pressed = HID_PAD;
|
||||
|
||||
if(((pressed & BUTTON_B) && loadPayload("/rei/payloads/b.bin")) ||
|
||||
((pressed & BUTTON_X) && loadPayload("/rei/payloads/x.bin")) ||
|
||||
((pressed & BUTTON_Y) && loadPayload("/rei/payloads/y.bin")) ||
|
||||
((pressed & BUTTON_SELECT) && loadPayload("/rei/payloads/select.bin")) ||
|
||||
((pressed & BUTTON_START) && loadPayload("/rei/payloads/start.bin")) ||
|
||||
((pressed & BUTTON_RIGHT) && loadPayload("/rei/payloads/right.bin")) ||
|
||||
((pressed & BUTTON_LEFT) && loadPayload("/rei/payloads/left.bin")) ||
|
||||
((pressed & BUTTON_UP) && loadPayload("/rei/payloads/up.bin")) ||
|
||||
((pressed & BUTTON_DOWN) && loadPayload("/rei/payloads/down.bin")) ||
|
||||
loadPayload("/rei/payloads/default.bin")){
|
||||
initLCD();
|
||||
if(((pressed & BUTTON_B) && loadPayload("/aurei/payloads/b.bin")) ||
|
||||
((pressed & BUTTON_X) && loadPayload("/aurei/payloads/x.bin")) ||
|
||||
((pressed & BUTTON_Y) && loadPayload("/aurei/payloads/y.bin")) ||
|
||||
((pressed & BUTTON_SELECT) && loadPayload("/aurei/payloads/select.bin")) ||
|
||||
((pressed & BUTTON_START) && loadPayload("/aurei/payloads/start.bin")) ||
|
||||
((pressed & BUTTON_RIGHT) && loadPayload("/aurei/payloads/right.bin")) ||
|
||||
((pressed & BUTTON_LEFT) && loadPayload("/aurei/payloads/left.bin")) ||
|
||||
((pressed & BUTTON_UP) && loadPayload("/aurei/payloads/up.bin")) ||
|
||||
((pressed & BUTTON_DOWN) && loadPayload("/aurei/payloads/down.bin")) ||
|
||||
loadPayload("/aurei/payloads/default.bin"))
|
||||
((void (*)())PAYLOAD_ADDRESS)();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
|
||||
void initLCD();
|
||||
@@ -2,6 +2,9 @@
|
||||
.align 4
|
||||
.global _start
|
||||
_start:
|
||||
@ Fix payloads like Decrypt9
|
||||
mov r0, #0x5
|
||||
mcr p15, 0, r0, c3, c0, 0 @ data bufferable
|
||||
|
||||
@ Flush caches
|
||||
mov r0, #0
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
.nds
|
||||
.create "reboot.bin", 0
|
||||
.arm.little
|
||||
|
||||
byteswritten equ 0x2000E000
|
||||
externalFirm equ 0x2000A000
|
||||
kernelCode equ 0x080F0000
|
||||
buffer equ 0x24000000
|
||||
fileOpen equ 0x4E45504F ;dummy
|
||||
|
||||
.create "reboot.bin", 0
|
||||
.arm
|
||||
//Code jumps here right after the sprintf call
|
||||
process9Reboot:
|
||||
@@ -34,18 +33,16 @@ process9Reboot:
|
||||
ldreq r1, =(FileName - OpenFirm - 12)
|
||||
addeq r1, pc
|
||||
addne r1, sp, #0x3A8-0x70
|
||||
ldr r0, =externalFirm
|
||||
moveq r2, #1
|
||||
movne r2, #0
|
||||
str r2, [r0]
|
||||
str r2, [externalFirm]
|
||||
mov r2, #1
|
||||
add r0, r7, #8
|
||||
ldr r6, =fileOpen
|
||||
blx r6
|
||||
|
||||
SeekFirm:
|
||||
ldr r0, =externalFirm
|
||||
ldr r0, [r0]
|
||||
ldr r0, [externalFirm]
|
||||
cmp r0, #1
|
||||
moveq r0, r7
|
||||
ldreq r1, =byteswritten
|
||||
@@ -97,11 +94,14 @@ Memcpy:
|
||||
LDMFD SP!, {R0-R4}
|
||||
MOV LR, R12
|
||||
BX LR
|
||||
|
||||
|
||||
FileName:
|
||||
.dcw "sdmc:/rei/patched_firmware_sys.bin"
|
||||
.dcw "sdmc:/aurei/patched_firmware_sys.bin"
|
||||
.word 0x0
|
||||
|
||||
externalFirm:
|
||||
.word 0x2000A000
|
||||
|
||||
.pool
|
||||
|
||||
// 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 "memory.h"
|
||||
@@ -243,14 +249,16 @@ static void getNandCTR(u8 *buf, u32 console){
|
||||
void nandFirm0(u8 *outbuf, u32 size, u32 console){
|
||||
u8 CTR[0x10];
|
||||
getNandCTR(CTR, console);
|
||||
aes_advctr(CTR, 0x0B130000/0x10, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
|
||||
sdmmc_nand_readsectors(0x0B130000 / 0x200, size / 0x200, outbuf);
|
||||
|
||||
aes_advctr(CTR, 0x0B130000/0x10, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
aes_use_keyslot(0x06);
|
||||
aes(outbuf, outbuf, size / AES_BLOCK_SIZE, CTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
}
|
||||
|
||||
//Decrypts the N3DS arm9bin
|
||||
void decArm9Bin(u8 *armHdr, u32 mode){
|
||||
void decryptArm9Bin(u8 *arm9Section, u32 mode){
|
||||
|
||||
//Firm keys
|
||||
u8 keyY[0x10];
|
||||
@@ -258,11 +266,11 @@ void decArm9Bin(u8 *armHdr, u32 mode){
|
||||
u8 slot = mode ? 0x16 : 0x15;
|
||||
|
||||
//Setup keys needed for arm9bin decryption
|
||||
memcpy(keyY, armHdr+0x10, 0x10);
|
||||
memcpy(CTR, armHdr+0x20, 0x10);
|
||||
memcpy(keyY, arm9Section+0x10, 0x10);
|
||||
memcpy(CTR, arm9Section+0x20, 0x10);
|
||||
u32 size = 0;
|
||||
//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';
|
||||
|
||||
if(mode){
|
||||
@@ -271,7 +279,7 @@ void decArm9Bin(u8 *armHdr, u32 mode){
|
||||
//Set 0x11 to key2 for the arm9bin and misc keys
|
||||
aes_setkey(0x11, key2, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -280,13 +288,13 @@ void decArm9Bin(u8 *armHdr, u32 mode){
|
||||
aes_use_keyslot(slot);
|
||||
|
||||
//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
|
||||
void setKeyXs(u8 *armHdr){
|
||||
void setKeyXs(u8 *arm9Section){
|
||||
|
||||
u8 *keyData = armHdr+0x89814;
|
||||
u8 *keyData = arm9Section+0x89814;
|
||||
u8 *decKey = keyData+0x10;
|
||||
|
||||
//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
|
||||
|
||||
@@ -49,5 +55,5 @@
|
||||
|
||||
//NAND/FIRM stuff
|
||||
void nandFirm0(u8 *outbuf, u32 size, u32 console);
|
||||
void decArm9Bin(u8 *armHdr, u32 mode);
|
||||
void setKeyXs(u8 *armHdr);
|
||||
void decryptArm9Bin(u8 *arm9Section, u32 mode);
|
||||
void setKeyXs(u8 *arm9Section);
|
||||
@@ -1,12 +1,18 @@
|
||||
/*
|
||||
* draw.c
|
||||
* by Reisyukaku
|
||||
* Copyright (c) 2015 All Rights Reserved
|
||||
* by Reisyukaku / Aurora Wright
|
||||
* Code to print to the screen by mid-kid @CakesFW
|
||||
*
|
||||
* Copyright (c) 2016 All Rights Reserved
|
||||
*/
|
||||
|
||||
#include "draw.h"
|
||||
#include "fs.h"
|
||||
#include "memory.h"
|
||||
#include "font.h"
|
||||
|
||||
#define SCREEN_TOP_WIDTH 400
|
||||
#define SCREEN_TOP_HEIGHT 240
|
||||
|
||||
static const struct fb {
|
||||
u8 *top_left;
|
||||
@@ -14,35 +20,63 @@ static const struct fb {
|
||||
u8 *bottom;
|
||||
} *const fb = (struct fb *)0x23FFFE00;
|
||||
|
||||
void __attribute__((naked)) shutdownLCD(void){
|
||||
|
||||
vu32 *const arm11 = (u32 *)0x1FFFFFF8;
|
||||
|
||||
//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 int strlen(const char *string){
|
||||
char *stringEnd = (char *)string;
|
||||
while(*stringEnd) stringEnd++;
|
||||
return stringEnd - string;
|
||||
}
|
||||
|
||||
static void clearScreen(void){
|
||||
memset(fb->top_left, 0, 0x46500);
|
||||
memset(fb->top_right, 0, 0x46500);
|
||||
memset(fb->bottom, 0, 0x38400);
|
||||
void clearScreens(void){
|
||||
memset32(fb->top_left, 0, 0x46500);
|
||||
memset32(fb->top_right, 0, 0x46500);
|
||||
memset32(fb->bottom, 0, 0x38400);
|
||||
}
|
||||
|
||||
void loadSplash(void){
|
||||
clearScreen();
|
||||
clearScreens();
|
||||
|
||||
//Don't delay boot if no splash image is on the SD
|
||||
if(fileRead(fb->top_left, "/rei/splash.bin", 0x46500) +
|
||||
fileRead(fb->bottom, "/rei/splashbottom.bin", 0x38400)){
|
||||
u64 i = 0xFFFFFF; while(--i) __asm("mov r0, r0"); //Less Ghetto sleep func
|
||||
if(fileRead(fb->top_left, "/aurei/splash.bin", 0x46500) +
|
||||
fileRead(fb->bottom, "/aurei/splashbottom.bin", 0x38400)){
|
||||
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
|
||||
* by Reisyukaku
|
||||
* Copyright (c) 2015 All Rights Reserved
|
||||
* by Reisyukaku / Aurora Wright
|
||||
* Code to print to the screen by mid-kid @CakesFW
|
||||
*
|
||||
* Copyright (c) 2016 All Rights Reserved
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#define SPACING_VERT 10
|
||||
#define SPACING_HORIZ 8
|
||||
|
||||
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
|
||||
* by Reisyukaku
|
||||
* Copyright (c) 2015 All Rights Reserved
|
||||
* by Reisyukaku / Aurora Wright
|
||||
* Copyright (c) 2016 All Rights Reserved
|
||||
*/
|
||||
|
||||
#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
|
||||
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
|
||||
const unsigned char pattern[] = {0x21, 0x20, 0x18, 0x20};
|
||||
*off = (u32)memsearch(pos, pattern, size, 4) - 1;
|
||||
|
||||
//Get DCD values
|
||||
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;
|
||||
const u8 *off = (u8 *)memsearch(pos, pattern, size, 4) - 1;
|
||||
|
||||
return *(u32 *)(off+0x0A) + *(u32 *)(off+0x0E);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void getMPU(void *pos, u32 *off, u32 size){
|
||||
void *getMPU(void *pos, u32 size){
|
||||
//Look for MPU pattern
|
||||
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
|
||||
* by Reisyukaku
|
||||
* Copyright (c) 2015 All Rights Reserved
|
||||
* by Reisyukaku / Aurora Wright
|
||||
* Copyright (c) 2016 All Rights Reserved
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
@@ -11,6 +11,7 @@
|
||||
#define NCSD_MAGIC (0x4453434E)
|
||||
|
||||
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 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 (
|
||||
__attribute__((unused))
|
||||
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 */
|
||||
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 */
|
||||
|
||||
DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */
|
||||
static DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */
|
||||
FATFS* fs, /* File system object */
|
||||
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 */
|
||||
|
||||
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 */
|
||||
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 */
|
||||
|
||||
#if !_FS_READONLY
|
||||
FRESULT put_fat (
|
||||
static FRESULT put_fat (
|
||||
FATFS* fs, /* File system object */
|
||||
DWORD clst, /* FAT index number (cluster number) to be changed */
|
||||
DWORD val /* New value to be set to the entry */
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include "sdmmc.h"
|
||||
#include "delay.h"
|
||||
|
||||
|
||||
272
source/firm.c
272
source/firm.c
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* firm.c
|
||||
* by Reisyukaku
|
||||
* Copyright (c) 2015 All Rights Reserved
|
||||
* by Reisyukaku / Aurora Wright
|
||||
* Copyright (c) 2016 All Rights Reserved
|
||||
*/
|
||||
|
||||
#include "firm.h"
|
||||
@@ -11,19 +11,29 @@
|
||||
#include "emunand.h"
|
||||
#include "crypto.h"
|
||||
#include "draw.h"
|
||||
#include "screeninit.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 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,
|
||||
console = 1,
|
||||
emuNAND = 0,
|
||||
a9lhSetup = 0,
|
||||
updatedSys = 0,
|
||||
usePatchedFirm = 0;
|
||||
static u16 pressed;
|
||||
static const char *firmPathPatched = NULL;
|
||||
usePatchedFirm = 0,
|
||||
selectedFirm = 0;
|
||||
|
||||
void setupCFW(void){
|
||||
|
||||
@@ -31,53 +41,57 @@ void setupCFW(void){
|
||||
u32 a9lhBoot = (PDN_SPI_CNT == 0x0) ? 1 : 0;
|
||||
//Retrieve the last booted FIRM
|
||||
u8 previousFirm = CFG_BOOTENV;
|
||||
u32 overrideConfig = 0;
|
||||
const char lastConfigPath[] = "rei/lastbootcfg";
|
||||
|
||||
//Detect the console being used
|
||||
if(PDN_MPCORE_CFG == 1) console = 0;
|
||||
|
||||
//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
|
||||
if(a9lhBoot || fileExists("/rei/installeda9lh")){
|
||||
if(a9lhBoot || (config >> 2) & 0x1){
|
||||
a9lhSetup = 1;
|
||||
//Check flag for > 9.2 SysNAND
|
||||
if(fileExists("/rei/updatedsysnand")) updatedSys = 1;
|
||||
//Check setting for > 9.2 sysNAND
|
||||
updatedSys = config & 0x1;
|
||||
}
|
||||
|
||||
//If booting with A9LH and it's a MCU reboot, try to force boot options
|
||||
if(a9lhBoot && previousFirm && fileExists(lastConfigPath)){
|
||||
u8 tempConfig;
|
||||
fileRead(&tempConfig, lastConfigPath, 1);
|
||||
|
||||
/* If booting with A9LH, it's a MCU reboot and a previous configuration exists,
|
||||
try to force boot options */
|
||||
if(a9lhBoot && previousFirm && needConfig == 1){
|
||||
//Always force a sysNAND boot when quitting AGB_FIRM
|
||||
if(previousFirm == 0x7){
|
||||
if(!updatedSys) mode = tempConfig & 0x1;
|
||||
overrideConfig = 1;
|
||||
if(!updatedSys) mode = (config >> 8) & 0x1;
|
||||
needConfig = 0;
|
||||
//Else, force the last used boot options unless A is pressed
|
||||
} else if(!(pressed & BUTTON_A)){
|
||||
mode = tempConfig & 0x1;
|
||||
emuNAND = (tempConfig >> 1) & 0x1;
|
||||
overrideConfig = 1;
|
||||
mode = (config >> 8) & 0x1;
|
||||
emuNAND = (config >> 9) & 0x1;
|
||||
needConfig = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(!overrideConfig){
|
||||
if(needConfig){
|
||||
|
||||
//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 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 */
|
||||
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
|
||||
or R is pressed on a > 9.2 SysNAND, boot emuNAND */
|
||||
/* 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 */
|
||||
if((updatedSys && (!mode || ((pressed & BUTTON_R1) && pressed != SAFEMODE))) ||
|
||||
(!updatedSys && mode && !(pressed & BUTTON_R1))){
|
||||
//If not 9.0 FIRM and B is pressed, attempt booting the second emuNAND
|
||||
@@ -85,27 +99,35 @@ void setupCFW(void){
|
||||
else emuNAND = 1;
|
||||
}
|
||||
|
||||
//Write the current boot options on A9LH
|
||||
if(a9lhBoot){
|
||||
u8 tempConfig = (mode | (emuNAND << 1)) & 0x3;
|
||||
fileWrite(&tempConfig, lastConfigPath, 1);
|
||||
/* If tha FIRM patches version is different or user switched to/from A9LH,
|
||||
and "Use pre-patched FIRMs" is set, delete all patched FIRMs */
|
||||
u16 bootConfig = (PATCH_VER << 11) | (a9lhSetup << 10);
|
||||
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" :
|
||||
"/rei/patched_firmware_em2.bin") :
|
||||
"/rei/patched_firmware_sys.bin";
|
||||
if(mode) selectedFirm = emuNAND ? (emuNAND == 1 ? 2 : 3) : 1;
|
||||
|
||||
//Skip decrypting and patching FIRM
|
||||
if(fileExists("/rei/usepatchedfw")){
|
||||
//Only needed with this flag
|
||||
if(!mode) firmPathPatched = "/rei/patched_firmware90.bin";
|
||||
if(fileExists(firmPathPatched)) usePatchedFirm = 1;
|
||||
if((config >> 1) & 0x1){
|
||||
//Only needed with this setting
|
||||
if(!mode) selectedFirm = 4;
|
||||
if(fileExists(patchedFirms[selectedFirm - 1])) usePatchedFirm = 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Load firm into FCRAM
|
||||
u32 loadFirm(void){
|
||||
//Load FIRM into FCRAM
|
||||
void loadFirm(void){
|
||||
|
||||
//If not using an A9LH setup or the patched FIRM, load 9.0 FIRM from NAND
|
||||
if(!usePatchedFirm && !a9lhSetup && !mode){
|
||||
@@ -113,92 +135,106 @@ u32 loadFirm(void){
|
||||
firmSize = console ? 0xF2000 : 0xE9000;
|
||||
nandFirm0((u8 *)firmLocation, firmSize, console);
|
||||
//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
|
||||
else{
|
||||
const char *path = usePatchedFirm ? firmPathPatched :
|
||||
(mode ? "/rei/firmware.bin" : "/rei/firmware90.bin");
|
||||
const char *path = usePatchedFirm ? patchedFirms[selectedFirm - 1] :
|
||||
(mode ? "/aurei/firmware.bin" : "/aurei/firmware90.bin");
|
||||
firmSize = fileSize(path);
|
||||
if(!firmSize) return 0;
|
||||
if(!firmSize) error("aurei/firmware(90).bin doesn't exist");
|
||||
fileRead((u8 *)firmLocation, path, firmSize);
|
||||
}
|
||||
|
||||
section = firmLocation->section;
|
||||
|
||||
//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)
|
||||
decArm9Bin((u8 *)firmLocation + section[2].offset, mode);
|
||||
arm9Section = (u8 *)firmLocation + section[2].offset;
|
||||
|
||||
return 1;
|
||||
if(console && !usePatchedFirm) decryptArm9Bin(arm9Section, mode);
|
||||
}
|
||||
|
||||
//Nand redirection
|
||||
static u32 loadEmu(void){
|
||||
//NAND redirection
|
||||
static void loadEmu(u8 *proc9Offset){
|
||||
|
||||
u32 emuOffset = 1,
|
||||
emuHeader = 1,
|
||||
emuRead,
|
||||
emuWrite,
|
||||
sdmmcOffset,
|
||||
mpuOffset,
|
||||
emuCodeOffset;
|
||||
emuWrite;
|
||||
|
||||
//Read emunand code from SD
|
||||
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);
|
||||
//Look for emuNAND
|
||||
getEmunandSect(&emuOffset, &emuHeader, emuNAND);
|
||||
getEmuRW(firmLocation, firmSize, &emuRead, &emuWrite);
|
||||
getMPU(firmLocation, &mpuOffset, firmSize);
|
||||
*pos_sdmmc = sdmmcOffset;
|
||||
|
||||
//No emuNAND detected
|
||||
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_header = emuHeader;
|
||||
|
||||
//Patch emuNAND code in memory for O3DS and 9.0 N3DS
|
||||
if(!console || !mode){
|
||||
void *pos_instr = memsearch((void *)emuCodeOffset, "\xA6\x01\x08\x30", size, 4);
|
||||
memcpy(pos_instr, emuInstr, sizeof(emuInstr));
|
||||
}
|
||||
//Find and add the SDMMC struct
|
||||
u32 *pos_sdmmc = (u32 *)memsearch(emuCodeOffset, "SDMC", emunand_size, 4);
|
||||
*pos_sdmmc = getSDMMC(arm9Section, section[2].size);
|
||||
|
||||
//Calculate offset for the hooks
|
||||
*(u32 *)(nandRedir + 4) = (u32)emuCodeOffset - (u32)firmLocation -
|
||||
section[2].offset + (u32)section[2].address;
|
||||
|
||||
//Add emunand hooks
|
||||
getEmuRW(arm9Section, section[2].size, &emuRead, &emuWrite);
|
||||
memcpy((void *)emuRead, nandRedir, sizeof(nandRedir));
|
||||
memcpy((void *)emuWrite, nandRedir, sizeof(nandRedir));
|
||||
|
||||
//Set MPU for emu code region
|
||||
memcpy((void *)mpuOffset, mpu, sizeof(mpu));
|
||||
|
||||
return 1;
|
||||
void *mpuOffset = getMPU(arm9Section, section[2].size);
|
||||
memcpy(mpuOffset, mpu, sizeof(mpu));
|
||||
}
|
||||
|
||||
//Patches
|
||||
u32 patchFirm(void){
|
||||
void patchFirm(void){
|
||||
|
||||
//Skip patching
|
||||
if(usePatchedFirm) return 1;
|
||||
if(usePatchedFirm) return;
|
||||
|
||||
//Apply emuNAND patches
|
||||
if(emuNAND){
|
||||
if(!loadEmu()) return 0;
|
||||
if(mode || emuNAND){
|
||||
//Find the Process9 NCCH location
|
||||
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
|
||||
u32 writeOffset = 0;
|
||||
getFIRMWrite(firmLocation, firmSize, &writeOffset);
|
||||
memcpy((void *)writeOffset, FIRMblock, sizeof(FIRMblock));
|
||||
|
||||
if(a9lhSetup && !emuNAND){
|
||||
//Patch FIRM partitions writes on sysNAND to protect A9LH
|
||||
void *writeOffset = getFirmWrite(arm9Section, section[2].size);
|
||||
memcpy(writeOffset, writeBlock, sizeof(writeBlock));
|
||||
}
|
||||
|
||||
//Disable signature checks
|
||||
@@ -213,55 +249,27 @@ u32 patchFirm(void){
|
||||
if(console)
|
||||
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
|
||||
if(firmPathPatched)
|
||||
if(!fileWrite((u8 *)firmLocation, firmPathPatched, firmSize)) return 0;
|
||||
|
||||
return 1;
|
||||
if(selectedFirm)
|
||||
if(!fileWrite((u8 *)firmLocation, patchedFirms[selectedFirm - 1], firmSize))
|
||||
error("Couldn't write the patched FIRM (no free space?)");
|
||||
}
|
||||
|
||||
void launchFirm(void){
|
||||
|
||||
if(console && mode) setKeyXs((u8 *)firmLocation + section[2].offset);
|
||||
if(console && mode) setKeyXs(arm9Section);
|
||||
|
||||
//Copy firm partitions to respective memory locations
|
||||
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[2].address, (u8 *)firmLocation + section[2].offset, section[2].size);
|
||||
memcpy(section[2].address, arm9Section, section[2].size);
|
||||
|
||||
//Run ARM11 screen stuff
|
||||
vu32 *const arm11 = (u32 *)0x1FFFFFF8;
|
||||
*arm11 = (u32)shutdownLCD;
|
||||
while(*arm11);
|
||||
//Fixes N3DS 3D
|
||||
deinitScreens();
|
||||
|
||||
//Set ARM11 kernel
|
||||
*arm11 = (u32)firmLocation->arm11Entry;
|
||||
//Set ARM11 kernel entrypoint
|
||||
*(vu32 *)0x1FFFFFF8 = (u32)firmLocation->arm11Entry;
|
||||
|
||||
//Final jump to arm9 binary
|
||||
//Final jump to arm9 kernel
|
||||
((void (*)())firmLocation->arm9Entry)();
|
||||
}
|
||||
@@ -1,24 +1,16 @@
|
||||
/*
|
||||
* firm.h
|
||||
* by Reisyukaku
|
||||
* Copyright (c) 2015 All Rights Reserved
|
||||
* by Reisyukaku / Aurora Wright
|
||||
* Copyright (c) 2016 All Rights Reserved
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#define PDN_MPCORE_CFG (*(vu8 *)0x10140FFC)
|
||||
#define HID_PAD ((~*(vu16 *)0x10146000) & 0xFFF)
|
||||
#define PDN_SPI_CNT (*(vu8 *)0x101401C0)
|
||||
#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))
|
||||
#define PDN_MPCORE_CFG (*(vu8 *)0x10140FFC)
|
||||
#define PDN_SPI_CNT (*(vu8 *)0x101401C0)
|
||||
#define CFG_BOOTENV (*(vu8 *)0x10010000)
|
||||
|
||||
//FIRM Header layout
|
||||
typedef struct firmSectionHeader {
|
||||
@@ -39,6 +31,6 @@ typedef struct firmHeader {
|
||||
} firmHeader;
|
||||
|
||||
void setupCFW(void);
|
||||
u32 loadFirm(void);
|
||||
u32 patchFirm(void);
|
||||
void loadFirm(void);
|
||||
void patchFirm(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
|
||||
* by Reisyukaku / Aurora Wright
|
||||
* Copyright (c) 2016 All Rights Reserved
|
||||
*/
|
||||
|
||||
#include "fs.h"
|
||||
@@ -58,4 +60,8 @@ u32 fileExists(const char *path){
|
||||
|
||||
f_close(&fp);
|
||||
return exists;
|
||||
}
|
||||
|
||||
void fileDelete(const char *path){
|
||||
f_unlink(path);
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
/*
|
||||
* fs.h
|
||||
* by Reisyukaku / Aurora Wright
|
||||
* Copyright (c) 2016 All Rights Reserved
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
@@ -10,4 +12,5 @@ u32 mountSD(void);
|
||||
u32 fileRead(u8 *dest, const char *path, u32 size);
|
||||
u32 fileWrite(const u8 *buffer, const char *path, u32 size);
|
||||
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},
|
||||
};
|
||||
|
||||
inline u8 i2cGetDeviceBusId(u8 device_id) {
|
||||
static inline u8 i2cGetDeviceBusId(u8 device_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;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ static vu8* reg_data_addrs[] = {
|
||||
(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];
|
||||
}
|
||||
|
||||
@@ -38,22 +38,22 @@ static vu8* reg_cnt_addrs[] = {
|
||||
(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];
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
inline void i2cWaitBusy(u8 bus_id) {
|
||||
static inline void i2cWaitBusy(u8 bus_id) {
|
||||
while (*i2cGetCntReg(bus_id) & 0x80);
|
||||
}
|
||||
|
||||
inline bool i2cGetResult(u8 bus_id) {
|
||||
static inline u32 i2cGetResult(u8 bus_id) {
|
||||
i2cWaitBusy(bus_id);
|
||||
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;
|
||||
i2cWaitBusy(bus_id);
|
||||
*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);
|
||||
*i2cGetDataReg(bus_id) = dev_reg;
|
||||
*i2cGetCntReg(bus_id) = 0xC2;
|
||||
return i2cGetResult(bus_id);
|
||||
}
|
||||
|
||||
bool i2cSelectRegister(u8 bus_id, u8 reg) {
|
||||
static u32 i2cSelectRegister(u8 bus_id, u8 reg) {
|
||||
i2cWaitBusy(bus_id);
|
||||
*i2cGetDataReg(bus_id) = reg;
|
||||
*i2cGetCntReg(bus_id) = 0xC0;
|
||||
@@ -77,58 +77,7 @@ bool i2cSelectRegister(u8 bus_id, u8 reg) {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
u8 i2cReadRegister(u8 dev_id, u8 reg) {
|
||||
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) {
|
||||
u32 i2cWriteRegister(u8 dev_id, u8 reg, u8 data) {
|
||||
u8 bus_id = i2cGetDeviceBusId(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;
|
||||
i2cStop(bus_id, 0);
|
||||
if (i2cGetResult(bus_id))
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
*i2cGetCntReg(bus_id) = 0xC5;
|
||||
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
|
||||
* by Aurora Wright
|
||||
* Copyright (c) 2016 All Rights Reserved
|
||||
*/
|
||||
|
||||
#include "loader.h"
|
||||
#include "fs.h"
|
||||
#include "memory.h"
|
||||
#include "screeninit.h"
|
||||
#include "../build/loader.h"
|
||||
|
||||
#define PAYLOAD_ADDRESS 0x24F00000
|
||||
|
||||
void loadPayload(void){
|
||||
if(fileExists("rei/payloads/default.bin") &&
|
||||
fileRead((u8 *)PAYLOAD_ADDRESS, "rei/loader.bin", 0))
|
||||
if(fileExists("aurei/payloads/default.bin")){
|
||||
initScreens();
|
||||
memcpy((void *)PAYLOAD_ADDRESS, loader, loader_size);
|
||||
((void (*)())PAYLOAD_ADDRESS)();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
/*
|
||||
* loader.h
|
||||
* by Aurora Wright
|
||||
* Copyright (c) 2016 All Rights Reserved
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
@@ -1,21 +1,18 @@
|
||||
/*
|
||||
* main.c
|
||||
* by Reisyukaku
|
||||
* Copyright (c) 2015 All Rights Reserved
|
||||
* by Reisyukaku / Aurora Wright
|
||||
* Copyright (c) 2016 All Rights Reserved
|
||||
*
|
||||
* Minimalist CFW for N3DS
|
||||
* Minimalist CFW for (N)3DS
|
||||
*/
|
||||
|
||||
#include "fs.h"
|
||||
#include "firm.h"
|
||||
|
||||
void main(){
|
||||
void main(void){
|
||||
mountSD();
|
||||
setupCFW();
|
||||
}
|
||||
|
||||
void startCFW(){
|
||||
if(!loadFirm()) return;
|
||||
if(!patchFirm()) return;
|
||||
loadFirm();
|
||||
patchFirm();
|
||||
launchFirm();
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* memory.c
|
||||
* by Reisyukaku
|
||||
* Copyright (c) 2015 All Rights Reserved
|
||||
* by Reisyukaku / Aurora Wright
|
||||
* Copyright (c) 2016 All Rights Reserved
|
||||
*/
|
||||
|
||||
#include "memory.h"
|
||||
@@ -19,6 +19,12 @@ void memset(void *dest, int filler, u32 size){
|
||||
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){
|
||||
const u8 *buf1c = (const u8 *)buf1;
|
||||
const u8 *buf2c = (const u8 *)buf2;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* memory.h
|
||||
* by Reisyukaku
|
||||
* Copyright (c) 2015 All Rights Reserved
|
||||
* by Reisyukaku / Aurora Wright
|
||||
* Copyright (c) 2016 All Rights Reserved
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
@@ -10,5 +10,6 @@
|
||||
|
||||
void memcpy(void *dest, const void *src, 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);
|
||||
void *memsearch(void *start_pos, const void *search, u32 size, u32 size_search);
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* patches.c
|
||||
* by Reisyukaku
|
||||
* Copyright (c) 2015 All Rights Reserved
|
||||
* by Reisyukaku / Aurora Wright
|
||||
* Copyright (c) 2016 All Rights Reserved
|
||||
*/
|
||||
|
||||
#include "patches.h"
|
||||
@@ -11,25 +11,28 @@
|
||||
* 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,
|
||||
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
|
||||
};
|
||||
};
|
||||
|
||||
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 sigPat2[4] = {0x00, 0x20, 0x70, 0x47};
|
||||
|
||||
const u8 FIRMblock[4] = {0x00, 0x20, 0xC0, 0x46};
|
||||
|
||||
const u8 emuInstr[5] = {0xA5, 0x01, 0x08, 0x30, 0xA5};
|
||||
const u8 writeBlock[4] = {0x00, 0x20, 0xC0, 0x46};
|
||||
|
||||
/**************************************************
|
||||
* Functions
|
||||
**************************************************/
|
||||
|
||||
u8 *getProc9(void *pos, u32 size){
|
||||
return (u8 *)memsearch(pos, "ess9", size, 4);
|
||||
}
|
||||
|
||||
void getSignatures(void *pos, u32 size, u32 *off, u32 *off2){
|
||||
//Look for signature checks
|
||||
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;
|
||||
}
|
||||
|
||||
void getReboot(void *pos, u32 size, u32 *off){
|
||||
void *getReboot(void *pos, u32 size){
|
||||
//Look for FIRM reboot code
|
||||
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
|
||||
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};
|
||||
|
||||
*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
|
||||
u8 *firmwrite = (u8 *)memsearch(pos, "exe:", size, 4);
|
||||
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
|
||||
* by Reisyukaku
|
||||
* Copyright (c) 2015 All Rights Reserved
|
||||
* by Reisyukaku / Aurora Wright
|
||||
* Copyright (c) 2016 All Rights Reserved
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
@@ -15,13 +15,13 @@ const u8 mpu[0x2C];
|
||||
u8 nandRedir[0x08];
|
||||
const u8 sigPat1[2];
|
||||
const u8 sigPat2[4];
|
||||
const u8 FIRMblock[4];
|
||||
const u8 emuInstr[5];
|
||||
const u8 writeBlock[4];
|
||||
|
||||
/**************************************************
|
||||
* Functions
|
||||
**************************************************/
|
||||
u8 *getProc9(void *pos, u32 size);
|
||||
void getSignatures(void *pos, u32 size, u32 *off, u32 *off2);
|
||||
void getReboot(void *pos, u32 size, u32 *off);
|
||||
void getfOpen(void *pos, u32 size, u32 *off);
|
||||
void getFIRMWrite(void *pos, u32 size, u32 *off);
|
||||
void *getReboot(void *pos, u32 size);
|
||||
u32 getfOpen(void *pos, u32 size, u8 *proc9Offset);
|
||||
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 "draw.h"
|
||||
#include "i2c.h"
|
||||
|
||||
void initLCD()
|
||||
{
|
||||
vu32 *const arm11 = (u32 *)0x1FFFFFF8;
|
||||
static vu32 *const arm11 = (vu32 *)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 *)0x10202014 = 0x00000001;
|
||||
*(vu32 *)0x1020200C &= 0xFFFEFFFE;
|
||||
@@ -93,6 +129,11 @@ void initLCD()
|
||||
*(vu32 *)0x10400568 = 0x18346500;
|
||||
*(vu32 *)0x1040056c = 0x18346500;
|
||||
|
||||
//Set CakeBrah framebuffers
|
||||
*((vu32 *)0x23FFFE00) = 0x18300000;
|
||||
*((vu32 *)0x23FFFE04) = 0x18300000;
|
||||
*((vu32 *)0x23FFFE08) = 0x18346500;
|
||||
|
||||
//Clear ARM11 entry offset
|
||||
*arm11 = 0;
|
||||
|
||||
@@ -102,17 +143,10 @@ void initLCD()
|
||||
((void (*)())*arm11)();
|
||||
}
|
||||
|
||||
//Determine if screen was already inited
|
||||
if(*(vu8 *)0x10141200 != 0x1) return;
|
||||
if(PDN_GPU_CNT == 0x1){
|
||||
*arm11 = (u32)ARM11;
|
||||
while(*arm11);
|
||||
}
|
||||
|
||||
//Set CakeBrah framebuffers
|
||||
*(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);
|
||||
clearScreens();
|
||||
}
|
||||
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, 3 @ write instruction access
|
||||
|
||||
@ Set MPU permissions
|
||||
@ Set MPU permissions and cache settings
|
||||
ldr r0, =0xFFFF001D @ ffff0000 32k
|
||||
ldr r1, =0x01FF801D @ 01ff8000 32k
|
||||
ldr r2, =0x08000027 @ 08000000 1M
|
||||
@@ -27,6 +27,10 @@ _start:
|
||||
mcr p15, 0, r5, c6, c5, 0
|
||||
mcr p15, 0, r6, c6, c6, 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
|
||||
mrc p15, 0, r0, c1, c0, 0 @ read control register
|
||||
@@ -48,13 +52,5 @@ _start:
|
||||
|
||||
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:
|
||||
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