diff --git a/README.md b/README.md index 8c97187..a6e0278 100644 --- a/README.md +++ b/README.md @@ -13,12 +13,11 @@ Since Luma3DS v8.0, Luma3DS has its own in-game menu, triggerable by `L+Down+Sel ## Compiling -First you need to clone the repository with: `git clone https://github.com/AuroraWright/Luma3DS.git` -To compile, you'll need [armips](https://github.com/Kingcom/armips) and a build of a recent commit of [makerom](https://github.com/profi200/Project_CTR) added to your PATH. You'll also need to install [firmtool](https://github.com/TuxSH/firmtool), its README contains installation instructions. -You'll also need to update your [libctru](https://github.com/smealum/ctrulib) install, building from the latest commit. -Here are [Windows](https://buildbot.orphis.net/armips/) and [Linux](https://ev1l0rd.s-ul.eu/mEIk4atQ) builds of armips (thanks to who compiled them!). -Run `make` and everything should work! -You can find the compiled files in the `out` folder. +First you need to clone the repository with: `git clone https://github.com/AuroraWright/Luma3DS.git` +To compile, you'll need a recent commit of [makerom](https://github.com/profi200/Project_CTR) added to your PATH. You'll also need to install [firmtool](https://github.com/TuxSH/firmtool), its README contains installation instructions. +You'll also need to update your libctru and devkitARM installation to their latest releases. +Then, run `make`. +The produced file is called `boot.firm` and is meant to be copied to the root of your SD card, for usage with boot9strap. --- diff --git a/sysmodules/loader/Makefile b/sysmodules/loader/Makefile index e08ad6a..4aaf9f4 100755 --- a/sysmodules/loader/Makefile +++ b/sysmodules/loader/Makefile @@ -9,7 +9,6 @@ include $(DEVKITARM)/3ds_rules name := $(shell basename $(CURDIR)) dir_source := source -dir_patches := patches dir_build := build dir_out := ../../$(dir_build) @@ -26,12 +25,6 @@ LDFLAGS := -specs=3dsx.specs $(ASFLAGS) -Wl,--section-start,.text=0x14000000 objects = $(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \ $(call rwildcard, $(dir_source), *.s *.c)) -bundled = $(dir_build)/romfsredir.bin.o - -define bin2o - bin2s $< | $(AS) -o $(@) -endef - .PHONY: all all: $(dir_out)/$(name).cxi @@ -47,22 +40,9 @@ $(dir_out)/$(name).cxi: $(dir_build)/$(name).elf $(dir_build)/$(name).elf: $(bundled) $(objects) $(LINK.o) $(OUTPUT_OPTION) $^ $(LIBPATHS) $(LIBS) -$(dir_build)/%.bin.o: $(dir_build)/%.bin - @$(bin2o) - -$(dir_build)/%.bin: $(dir_patches)/%.s - @mkdir -p "$(@D)" - @armips $< - $(dir_build)/memory.o $(dir_build)/strings.o: CFLAGS += -O3 -$(dir_build)/bundled.h: $(bundled) - @$(foreach f, $(bundled),\ - echo "extern const u8" `(echo $(basename $(notdir $(f))) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> $@;\ - echo "extern const u32" `(echo $(basename $(notdir $(f)))| sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> $@;\ - ) - -$(dir_build)/%.o: $(dir_source)/%.c $(dir_build)/bundled.h +$(dir_build)/%.o: $(dir_source)/%.c @mkdir -p "$(@D)" $(COMPILE.c) $(OUTPUT_OPTION) $< diff --git a/sysmodules/loader/patches/romfsredir.s b/sysmodules/loader/patches/romfsredir.s deleted file mode 100644 index 023fff8..0000000 --- a/sysmodules/loader/patches/romfsredir.s +++ /dev/null @@ -1,117 +0,0 @@ -.arm.little -.create "build/romfsredir.bin", 0 - -.macro addr, reg, func - add reg, pc, #func-.-8 -.endmacro -.macro load, reg, func - ldr reg, [pc, #func-.-8] -.endmacro - -; Patch by delebile - -.arm -_start: - - ; Jumps here before the fsOpenFileDirectly call - _mountArchive: - b mountArchive - .word 0xdead0000 ; Substituted opcode - .word 0xdead0001 ; Branch to hooked function - - ; Jumps here before every iFileOpen call - _fsRedir: - b fsRedir - .word 0xdead0002 ; Substituted opcode - .word 0xdead0003 ; Branch to hooked function - - ; Mounts the archive and registers it as 'lf:' - mountArchive: - cmp r3, #3 - bne _mountArchive + 4 - stmfd sp!, {r0-r4, lr} - sub sp, sp, #4 - load r1, archiveId - mov r0, sp - load r4, fsMountArchive - blx r4 - mov r3, #0 - mov r2, #0 - ldr r1, [sp] - addr r0, archiveName - load r4, fsRegisterArchive - blx r4 - add sp, sp, #4 - ldmfd sp!, {r0-r4, lr} - b _mountArchive + 4 - - ; Check the path passed to iFileOpen. - ; If it is trying to access a RomFS file, we try to - ; open it from the LayeredFS folder. - ; If the file cannot be opened, we just open - ; it from its original archive like nothing happened - fsRedir: - stmfd sp!, {r0-r12, lr} - addr r3, romFsMount - bl compare - addne r3, pc, #updateRomFsMount-.-8 - blne compare - bne endRedir - sub sp, sp, #0x400 - pathRedir: - stmfd sp!, {r0-r3} - add r0, sp, #0x10 - load r3, customPath - pathRedir_1: - ldrb r2, [r3], #1 - cmp r2, #0 - strneh r2, [r0], #2 - bne pathRedir_1 - pathRedir_2: - ldrh r2, [r1], #2 - cmp r2, #0x3A ; ':' - bne pathRedir_2 - ; Skip a slash if there are two after the mountpoint, - ; as some games mistakenly have those - ldrh r3, [r1, #2] - cmp r3, #0x2F ; '/' - pathRedir_3: - ldrh r2, [r1], #2 - strneh r2, [r0], #2 - cmp r2, #0 - bne pathRedir_3 - ldmfd sp!, {r0-r3} - mov r1, sp - bl _fsRedir + 4 - add sp, sp, #0x400 - cmp r0, #0 - - endRedir: - ldmfd sp!, {r0-r12, lr} - moveq r0, #0 - bxeq lr - b _fsRedir + 4 - - compare: - mov r9, r1 - add r10, r3, #4 - loop: - ldrb r12, [r3], #1 - ldrb r11, [r9], #2 - cmp r11, r12 - bxne lr - cmp r10, r3 - bne loop - bx lr - -.pool -.align 4 - archiveName : .dcb "lf:", 0 - fsMountArchive : .word 0xdead0005 - fsRegisterArchive : .word 0xdead0006 - archiveId : .word 0xdead0007 - romFsMount : .dcb "rom:" - updateRomFsMount : .word 0xdead0008 - customPath : .word 0xdead0004 - -.close diff --git a/sysmodules/loader/source/patcher.c b/sysmodules/loader/source/patcher.c index c580bfb..41f2105 100644 --- a/sysmodules/loader/source/patcher.c +++ b/sysmodules/loader/source/patcher.c @@ -3,7 +3,7 @@ #include "memory.h" #include "strings.h" #include "fsldr.h" -#include "../build/bundled.h" +#include "romfsredir.h" static u32 patchMemory(u8 *start, u32 size, const void *pattern, u32 patSize, s32 offset, const void *replace, u32 repSize, u32 count) { @@ -204,7 +204,7 @@ static inline bool findLayeredFsPayloadOffset(u8 *code, u32 size, u32 roSize, u3 roundedDataSize = ((dataSize + 4095) & 0xFFFFF000); //First check for sufficient padding at the end of the .text segment - if(roundedTextSize - size >= romfsredir_bin_size) *payloadOffset = size; + if(roundedTextSize - size >= romfsRedirPatchSize) *payloadOffset = size; else { //If there isn't enough padding look for the "throwFatalError" function to replace @@ -528,43 +528,18 @@ static inline bool patchLayeredFs(u64 progId, u8 *code, u32 size, u32 textSize, //Setup the payload u8 *payload = code + payloadOffset; - memcpy(payload, romfsredir_bin, romfsredir_bin_size); - //Insert symbols in the payload - u32 *payload32 = (u32 *)payload; - for(u32 i = 0; i < romfsredir_bin_size / 4; i++) - { - switch(payload32[i]) - { - case 0xdead0000: - payload32[i] = *(u32 *)(code + fsOpenFileDirectly); - break; - case 0xdead0001: - payload32[i] = MAKE_BRANCH(payloadOffset + i * 4, fsOpenFileDirectly + 4); - break; - case 0xdead0002: - payload32[i] = *(u32 *)(code + fsTryOpenFile); - break; - case 0xdead0003: - payload32[i] = MAKE_BRANCH(payloadOffset + i * 4, fsTryOpenFile + 4); - break; - case 0xdead0004: - payload32[i] = pathAddress; - break; - case 0xdead0005: - payload32[i] = 0x100000 + fsMountArchive; - break; - case 0xdead0006: - payload32[i] = 0x100000 + fsRegisterArchive; - break; - case 0xdead0007: - payload32[i] = archiveId; - break; - case 0xdead0008: - memcpy(payload32 + i, updateRomFsMounts[updateRomFsIndex], 4); - break; - } - } + romfsRedirPatchSubstituted1 = *(u32 *)(code + fsOpenFileDirectly); + romfsRedirPatchHook1 = MAKE_BRANCH(payloadOffset + (u32)&romfsRedirPatchHook1 - (u32)romfsRedirPatch, fsOpenFileDirectly + 4); + romfsRedirPatchSubstituted1 = *(u32 *)(code + fsTryOpenFile); + romfsRedirPatchHook2 = MAKE_BRANCH(payloadOffset + (u32)&romfsRedirPatchHook2 - (u32)romfsRedirPatch, fsTryOpenFile + 4); + romfsRedirPatchCustomPath = pathAddress; + romfsRedirPatchFsMountArchive = 0x100000 + fsMountArchive; + romfsRedirPatchFsRegisterArchive = 0x100000 + fsRegisterArchive; + romfsRedirPatchArchiveId = archiveId; + memcpy(&romfsRedirPatchRomFsMount, updateRomFsMounts[updateRomFsIndex], 4); + + memcpy(payload, romfsRedirPatch, romfsRedirPatchSize); memcpy(code + pathOffset, "lf:", 3); memcpy(code + pathOffset + 3, path, sizeof(path)); diff --git a/sysmodules/loader/source/romfsredir.h b/sysmodules/loader/source/romfsredir.h new file mode 100644 index 0000000..75bd3d8 --- /dev/null +++ b/sysmodules/loader/source/romfsredir.h @@ -0,0 +1,17 @@ +#pragma once + +#include <3ds/types.h> + +extern const u8 romfsRedirPatch[]; +extern const u32 romfsRedirPatchSize; + +extern u32 romfsRedirPatchSubstituted1, romfsRedirPatchHook1; +extern u32 romfsRedirPatchSubstituted2, romfsRedirPatchHook2; + +extern u32 romfsRedirPatchArchiveName; +extern u32 romfsRedirPatchFsMountArchive; +extern u32 romfsRedirPatchFsRegisterArchive; +extern u32 romfsRedirPatchArchiveId; +extern u32 romfsRedirPatchRomFsMount; +extern u32 romfsRedirPatchUpdateRomFsMount; +extern u32 romfsRedirPatchCustomPath; diff --git a/sysmodules/loader/source/romfsredir.s b/sysmodules/loader/source/romfsredir.s new file mode 100644 index 0000000..b31a3dd --- /dev/null +++ b/sysmodules/loader/source/romfsredir.s @@ -0,0 +1,130 @@ +@ Patch by delebile + +.section .data.romfsRedirPatch, "aw", %progbits +.align 4 + +.global romfsRedirPatch +romfsRedirPatch: + @ Jumps here before the fsOpenFileDirectly call + _mountArchive: + b mountArchive + .global romfsRedirPatchSubstituted1 + romfsRedirPatchSubstituted1: + .word 0xdead0000 @ Substituted opcode + .global romfsRedirPatchHook1 + romfsRedirPatchHook1: + .word 0xdead0001 @ Branch to hooked function + + @ Jumps here before every iFileOpen call + _fsRedir: + b fsRedir + .global romfsRedirPatchSubstituted2 + romfsRedirPatchSubstituted2: + .word 0xdead0002 @ Substituted opcode + .global romfsRedirPatchHook2 + romfsRedirPatchHook2: + .word 0xdead0002 @ Branch to hooked function + + @ Mounts the archive and registers it as 'lf:' + mountArchive: + cmp r3, #3 + bne romfsRedirPatchSubstituted1 + stmfd sp!, {r0-r4, lr} + sub sp, sp, #4 + adr r1, romfsRedirPatchArchiveId + mov r0, sp + ldr r4, romfsRedirPatchFsMountArchive + blx r4 + mov r3, #0 + mov r2, #0 + ldr r1, [sp] + adr r0, romfsRedirPatchArchiveName + ldr r4, romfsRedirPatchFsRegisterArchive + blx r4 + add sp, sp, #4 + ldmfd sp!, {r0-r4, lr} + b romfsRedirPatchSubstituted1 + + @ Check the path passed to iFileOpen. + @ If it is trying to access a RomFS file, we try to + @ open it from the LayeredFS folder. + @ If the file cannot be opened, we just open + @ it from its original archive like nothing happened + fsRedir: + stmfd sp!, {r0-r12, lr} + adr r3, romfsRedirPatchRomFsMount + bl compare + adrne r3, romfsRedirPatchUpdateRomFsMount + blne compare + bne endRedir + sub sp, sp, #0x400 + pathRedir: + stmfd sp!, {r0-r3} + add r0, sp, #0x10 + ldr r3, romfsRedirPatchCustomPath + pathRedir_1: + ldrb r2, [r3], #1 + cmp r2, #0 + strneh r2, [r0], #2 + bne pathRedir_1 + pathRedir_2: + ldrh r2, [r1], #2 + cmp r2, #0x3A @ ':' + bne pathRedir_2 + @ Skip a slash if there are two after the mountpoint, + @ as some games mistakenly have those + ldrh r3, [r1, #2] + cmp r3, #0x2F @ '/' + pathRedir_3: + ldrh r2, [r1], #2 + strneh r2, [r0], #2 + cmp r2, #0 + bne pathRedir_3 + ldmfd sp!, {r0-r3} + mov r1, sp + bl romfsRedirPatchSubstituted2 + add sp, sp, #0x400 + cmp r0, #0 + + endRedir: + ldmfd sp!, {r0-r12, lr} + moveq r0, #0 + bxeq lr + b romfsRedirPatchSubstituted2 + + compare: + mov r9, r1 + add r10, r3, #4 + loop: + ldrb r12, [r3], #1 + ldrb r11, [r9], #2 + cmp r11, r12 + bxne lr + cmp r10, r3 + bne loop + bx lr + +.pool +.balign 4 + + .global romfsRedirPatchArchiveName + .global romfsRedirPatchFsMountArchive + .global romfsRedirPatchFsRegisterArchive + .global romfsRedirPatchArchiveId + .global romfsRedirPatchRomFsMount + .global romfsRedirPatchUpdateRomFsMount + .global romfsRedirPatchCustomPath + + romfsRedirPatchArchiveName : .ascii "lf:\0" + romfsRedirPatchFsMountArchive : .word 0xdead0005 + romfsRedirPatchFsRegisterArchive : .word 0xdead0006 + romfsRedirPatchArchiveId : .word 0xdead0007 + romfsRedirPatchRomFsMount : .ascii "rom:" + romfsRedirPatchUpdateRomFsMount : .word 0xdead0008 + romfsRedirPatchCustomPath : .word 0xdead0004 + +_romfsRedirPatchEnd: + +.global romfsRedirPatchSize +romfsRedirPatchSize: + .word _romfsRedirPatchEnd - romfsRedirPatch