Compare commits

...

26 Commits
v7.0 ... v7.0.4

Author SHA1 Message Date
Aurora Wright
725a825762 Update FatFs 2017-04-28 23:38:15 +02:00
Aurora Wright
b81f59d5ae Rewrite the LayeredFS pattern searching, small cleanup 2017-04-28 23:09:33 +02:00
Aurora Wright
39c2b8927b Fix mistake 2017-04-28 19:16:57 +02:00
Aurora Wright
89dfdac7bf This always fails 2017-04-28 12:43:56 +02:00
Aurora Wright
c087edf2ba Minor cleanup 2017-04-28 12:40:07 +02:00
Aurora Wright
db33c315f2 Instead of filtering mountpoints in the LayeredFS payload by their first letters, change known mountpoints not starting with "r" to start with "r" throughout the code 2017-04-28 00:33:30 +02:00
Aurora Wright
c7e7dd8248 Minor stuff 2017-04-27 22:32:46 +02:00
Aurora Wright
b10d82a883 Merge branch 'master' of https://github.com/AuroraWright/Luma3DS 2017-04-27 22:17:43 +02:00
Aurora Wright
e151b3d4ef Add displaying title IDs for ARM11 exceptions 2017-04-27 22:17:19 +02:00
ihaveamac
5ccf4a45c1 update ISSUE_TEMPLATE 2017-04-26 17:10:59 -07:00
Aurora Wright
c5369a5cad Minor stuff 2017-04-26 18:04:02 +02:00
Aurora Wright
b5eba765a5 Fix update RomFSes mounted as "ext:" (such as Taiko no Tatsujin: Don Don! Mystery Adventure) 2017-04-26 17:26:39 +02:00
Aurora Wright
a5ddc38477 Minor stuff 2017-04-23 19:22:38 +02:00
Aurora Wright
8d102256a2 Improve fsTryOpenFile pattern (fixes Zelda Triforce Heroes) 2017-04-23 18:44:46 +02:00
Aurora Wright
2e561f7ea9 Cleanup 2017-04-23 05:40:22 +02:00
Aurora Wright
9656fe1b6f Change variable names for consistency 2017-04-23 03:13:38 +02:00
Aurora Wright
48c23f2a43 Attempt to fix NSMB2 by changing archive name 2017-04-23 03:11:02 +02:00
TuxSH
6d82649c3c Update config.c 2017-04-17 12:24:58 +02:00
Aurora Wright
81dea35754 Minor stuff 2017-04-17 03:59:45 +02:00
Aurora Wright
fdbe43421b Fix diffs offsets 2017-04-17 02:31:04 +02:00
Aurora Wright
0d71560785 Minor stuff (2) 2017-04-17 02:18:34 +02:00
Aurora Wright
108e8a0cd4 Make loader search for patterns in just the appropriate code.bin segment, tentatively fix compatibility with Daigasso updates 2017-04-17 02:14:17 +02:00
Aurora Wright
653e81c48e Minor stuff 2017-04-17 01:01:03 +02:00
Aurora Wright
0dc0783094 Update submodules 2017-04-17 00:48:54 +02:00
Aurora
13ef1bf6be Merge pull request #408 from svanheulen/master
Use .text segment padding for LayeredFS payload
2017-04-17 00:40:20 +02:00
Seth VanHeulen
7ea80353f6 Use .text segment padding for LayeredFS payload 2017-04-16 17:59:20 -04:00
24 changed files with 218 additions and 190 deletions

View File

@@ -2,18 +2,12 @@
# #
# THIS IS NOT A SUPPORT FORUM! For support please go to: # THIS IS NOT A SUPPORT FORUM! For support please go to:
# Luma3DS GBATemp thread: https://gbatemp.net/threads/luma3ds-noob-proof-3ds-custom-firmware.411110/ # Luma3DS GBATemp thread: https://gbatemp.net/threads/luma3ds-noob-proof-3ds-custom-firmware.411110/
# /r/3dshacks: http://reddit.com/r/3dshacks/ # Nintendo Hacking: https://discord.gg/MjzatM8y
# Nintendo Hacking: https://discordapp.com/invite/C29hYvh
# IRC: #3dshacks@rizon
# #
# Also check the Wiki (https://github.com/AuroraWright/Luma3DS/wiki) before making an issue. # Also check the Wiki (https://github.com/AuroraWright/Luma3DS/wiki) before making an issue.
# #
# For those with GBA/DSiWare/DS/AGB_FIRM/TWL_FIRM problems: https://3ds.guide/troubleshooting # For those with GBA/DSiWare/DS/AGB_FIRM/TWL_FIRM problems: https://3ds.guide/troubleshooting
# #
# Please make sure to read "Enable region/language emulation and external .code" https://github.com/AuroraWright/Luma3DS/wiki/Options-and-usage before posting any issues about the "Enable region/language emulation and external .code" option(s). # Please make sure to read "Enable game patching" https://github.com/AuroraWright/Luma3DS/wiki/Options-and-usage before posting any issues about the "Enable game patching" option(s).
# Keep in mind that Wiki page only applies to nightly builds. It will NOT WORK with 6.6 Stable Luma3DS.
# As of 0.02 (https://github.com/Possum/LumaLocaleSwitcher/releases) LumaLocaleSwitcher's path(s) are for 6.6 Stable and won't work with Luma3DS nightly builds newer or equal to https://github.com/AuroraWright/Luma3DS/commit/b5336c81cc82b6c5e8115249342beb5b065cdce9.
# Use this version for Luma3DS nightlies newer or equal to https://github.com/AuroraWright/Luma3DS/commit/b5336c81cc82b6c5e8115249342beb5b065cdce9 :
# https://puu.sh/uC5zW/5470adc347.7z (from https://github.com/Possum/LumaLocaleSwitcher/issues/9#issuecomment-285564014)
# #
--> -->

View File

@@ -5,6 +5,7 @@ ENTRY(_start)
SECTIONS SECTIONS
{ {
. = 0; . = 0;
.text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); } .text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); }
.rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); } .rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); }
.data : ALIGN(4) { *(.data*); . = ALIGN(8); *(.bss* COMMON); . = ALIGN(8); } .data : ALIGN(4) { *(.data*); . = ALIGN(8); *(.bss* COMMON); . = ALIGN(8); }

View File

@@ -5,6 +5,7 @@ ENTRY(_start)
SECTIONS SECTIONS
{ {
. = 0x01FF7FE0; . = 0x01FF7FE0;
.text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); } .text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); }
.rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); } .rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); }
.data : ALIGN(4) { *(.data*); . = ALIGN(8); *(.bss* COMMON); . = ALIGN(8); } .data : ALIGN(4) { *(.data*); . = ALIGN(8); *(.bss* COMMON); . = ALIGN(8); }

View File

@@ -103,7 +103,7 @@ diff -uNr a/source/brahma.c b/source/brahma.c
diff -uNr a/source/main.c b/source/main.c diff -uNr a/source/main.c b/source/main.c
--- a/source/main.c 2016-09-26 16:05:36.363067000 +0200 --- a/source/main.c 2016-09-26 16:05:36.363067000 +0200
+++ b/source/main.c 2016-09-26 21:40:35.202513018 +0200 +++ b/source/main.c 2016-09-26 21:40:35.202513018 +0200
@@ -10,7 +10,7 @@ @@ -38,7 +38,7 @@
int main (void) { int main (void) {
if (brahma_init()) { if (brahma_init()) {
@@ -112,7 +112,7 @@ diff -uNr a/source/main.c b/source/main.c
goto error; goto error;
firm_reboot(); firm_reboot();
brahma_exit(); brahma_exit();
@@ -22,7 +22,7 @@ @@ -50,7 +50,7 @@
error: error:
gfxInitDefault(); gfxInitDefault();
consoleInit(GFX_BOTTOM, NULL); consoleInit(GFX_BOTTOM, NULL);

View File

@@ -1,8 +1,8 @@
diff -uNr a/source/main.c b/source/main.c diff -uNr a/source/main.c b/source/main.c
--- a/source/main.c 2016-09-11 01:04:25.665231884 +0200 --- a/source/main.c 2016-09-11 01:04:25.665231884 +0200
+++ b/source/main.c 2016-09-14 12:36:28.601439550 +0200 +++ b/source/main.c 2016-09-14 12:36:28.601439550 +0200
@@ -9,6 +9,7 @@ @@ -37,6 +37,7 @@
#endif }
int main (void) { int main (void) {
+ svcSleepThread(2500 * 1000000ULL); + svcSleepThread(2500 * 1000000ULL);

View File

@@ -1,11 +1,14 @@
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start) ENTRY(_start)
SECTIONS SECTIONS
{ {
. = 0x23F00000; . = 0x23F00000;
.text.start : { *(.text.start) }
.text : { *(.text) } .text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); }
.data : { *(.data) } .rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); }
.bss : { *(.bss COMMON) } .data : ALIGN(4) { *(.data*); . = ALIGN(8); *(.bss* COMMON); . = ALIGN(8); }
.rodata : { *(.rodata) }
. = ALIGN(4); . = ALIGN(4);
} }

View File

@@ -2051,6 +2051,7 @@ FRESULT load_obj_dir (
dp->obj.sclust = obj->c_scl; dp->obj.sclust = obj->c_scl;
dp->obj.stat = (BYTE)obj->c_size; dp->obj.stat = (BYTE)obj->c_size;
dp->obj.objsize = obj->c_size & 0xFFFFFF00; dp->obj.objsize = obj->c_size & 0xFFFFFF00;
dp->obj.n_frag = 0;
dp->blk_ofs = obj->c_ofs; dp->blk_ofs = obj->c_ofs;
res = dir_sdi(dp, dp->blk_ofs); /* Goto object's entry block */ res = dir_sdi(dp, dp->blk_ofs); /* Goto object's entry block */
@@ -2326,20 +2327,23 @@ FRESULT dir_register ( /* FR_OK:succeeded, FR_DENIED:no free entry or too many S
if (res != FR_OK) return res; if (res != FR_OK) return res;
dp->blk_ofs = dp->dptr - SZDIRE * (nent - 1); /* Set the allocated entry block offset */ dp->blk_ofs = dp->dptr - SZDIRE * (nent - 1); /* Set the allocated entry block offset */
if (dp->obj.sclust != 0 && (dp->obj.stat & 4)) { /* Has the sub-directory been stretched? */ if (dp->obj.stat & 4) { /* Has the directory been stretched? */
dp->obj.objsize += (DWORD)fs->csize * SS(fs); /* Increase the directory size by cluster size */ dp->obj.stat &= ~4;
res = fill_first_frag(&dp->obj); /* Fill first fragment on the FAT if needed */ res = fill_first_frag(&dp->obj); /* Fill the first fragment on the FAT if needed */
if (res != FR_OK) return res; if (res != FR_OK) return res;
res = fill_last_frag(&dp->obj, dp->clust, 0xFFFFFFFF); /* Fill last fragment on the FAT if needed */ res = fill_last_frag(&dp->obj, dp->clust, 0xFFFFFFFF); /* Fill the last fragment on the FAT if needed */
if (res != FR_OK) return res; if (res != FR_OK) return res;
if (dp->obj.sclust != 0) { /* Is it a sub directory? */
res = load_obj_dir(&dj, &dp->obj); /* Load the object status */ res = load_obj_dir(&dj, &dp->obj); /* Load the object status */
if (res != FR_OK) return res; if (res != FR_OK) return res;
dp->obj.objsize += (DWORD)fs->csize * SS(fs); /* Increase the directory size by cluster size */
st_qword(fs->dirbuf + XDIR_FileSize, dp->obj.objsize); /* Update the allocation status */ st_qword(fs->dirbuf + XDIR_FileSize, dp->obj.objsize); /* Update the allocation status */
st_qword(fs->dirbuf + XDIR_ValidFileSize, dp->obj.objsize); st_qword(fs->dirbuf + XDIR_ValidFileSize, dp->obj.objsize);
fs->dirbuf[XDIR_GenFlags] = dp->obj.stat | 1; fs->dirbuf[XDIR_GenFlags] = dp->obj.stat | 1;
res = store_xdir(&dj); /* Store the object status */ res = store_xdir(&dj); /* Store the object status */
if (res != FR_OK) return res; if (res != FR_OK) return res;
} }
}
create_xdir(fs->dirbuf, fs->lfnbuf); /* Create on-memory directory block to be written later */ create_xdir(fs->dirbuf, fs->lfnbuf); /* Create on-memory directory block to be written later */
return FR_OK; return FR_OK;

View File

@@ -14,8 +14,8 @@
_start: _start:
; Jumps here before the fsOpenFileDirectly call ; Jumps here before the fsOpenFileDirectly call
_mountSd: _mountArchive:
b mountSd b mountArchive
.word 0xdead0000 ; Substituted opcode .word 0xdead0000 ; Substituted opcode
.word 0xdead0001 ; Branch to hooked function .word 0xdead0001 ; Branch to hooked function
@@ -25,41 +25,41 @@ _start:
.word 0xdead0002 ; Substituted opcode .word 0xdead0002 ; Substituted opcode
.word 0xdead0003 ; Branch to hooked function .word 0xdead0003 ; Branch to hooked function
; Mounts SDMC and registers the archive as 'sdmc:' ; Mounts the archive and registers it as 'lf:'
mountSd: mountArchive:
cmp r3, #3 cmp r3, #3
bne _mountSd+4 bne _mountArchive + 4
stmfd sp!, {r0-r4, lr} stmfd sp!, {r0-r4, lr}
sub sp, sp, #4 sub sp, sp, #4
load r1, archive load r1, archiveId
mov r0, sp mov r0, sp
load r4, fsMountArchive load r4, fsMountArchive
blx r4 blx r4
mov r3, #0 mov r3, #0
mov r2, #0 mov r2, #0
ldr r1, [sp] ldr r1, [sp]
addr r0, sdmcArchiveName addr r0, archiveName
load r4, fsRegisterArchive load r4, fsRegisterArchive
blx r4 blx r4
add sp, sp, #4 add sp, sp, #4
ldmfd sp!, {r0-r4, lr} ldmfd sp!, {r0-r4, lr}
b _mountSd+4 b _mountArchive + 4
; Check the path passed to iFileOpen. ; Check the path passed to iFileOpen.
; If it is trying to access a RomFS file, we try to ; If it is trying to access a RomFS file, we try to
; open it from the title folder on the sdcard. ; open it from the LayeredFS folder.
; If the file cannot be opened from the sdcard, we just open ; If the file cannot be opened, we just open
; it from its original archive like nothing happened ; it from its original archive like nothing happened
fsRedir: fsRedir:
stmfd sp!, {r0-r12, lr} stmfd sp!, {r0-r12, lr}
ldrb r12, [r1] ldrb r12, [r1]
cmp r12, #0x72 ; 'r', should include "rom:" and "rom2:" cmp r12, #0x72 ; 'r', should include "rom:", "rom2:" and "rex:"
bne endRedir bne endRedir
sub sp, sp, #0x400 sub sp, sp, #0x400
pathRedir: pathRedir:
stmfd sp!, {r0-r3} stmfd sp!, {r0-r3}
add r0, sp, #0x10 add r0, sp, #0x10
addr r3, sdmcCustomPath addr r3, customPath
pathRedir_1: pathRedir_1:
ldrb r2, [r3], #1 ldrb r2, [r3], #1
strh r2, [r0], #2 strh r2, [r0], #2
@@ -77,7 +77,7 @@ _start:
bne pathRedir_3 bne pathRedir_3
ldmfd sp!, {r0-r3} ldmfd sp!, {r0-r3}
mov r1, sp mov r1, sp
bl _fsRedir+4 bl _fsRedir + 4
add sp, sp, #0x400 add sp, sp, #0x400
cmp r0, #0 cmp r0, #0
@@ -85,16 +85,14 @@ _start:
ldmfd sp!, {r0-r12, lr} ldmfd sp!, {r0-r12, lr}
moveq r0, #0 moveq r0, #0
bxeq lr bxeq lr
b _fsRedir+4 b _fsRedir + 4
.pool .pool
.align 4 .align 4
sdmcArchiveName : .word 0xdead0007 archiveName : .dcb "lf:", 0
.dcb ":", 0
.align 4
fsMountArchive : .word 0xdead0005 fsMountArchive : .word 0xdead0005
fsRegisterArchive : .word 0xdead0006 fsRegisterArchive : .word 0xdead0006
archive : .word 0xdead0008 archiveId : .word 0xdead0007
sdmcCustomPath : .word 0xdead0004 customPath : .word 0xdead0004
.close .close

View File

@@ -164,18 +164,3 @@ Result FSLDR_OpenDirectory(Handle* out, FS_Archive archive, FS_Path path)
return cmdbuf[1]; return cmdbuf[1];
} }
Result FSDIRLDR_Close(Handle handle)
{
u32 *cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = IPC_MakeHeader(0x802,0,0); // 0x8020000
Result ret = 0;
if(R_FAILED(ret = svcSendSyncRequest(handle))) return ret;
ret = cmdbuf[1];
if(R_SUCCEEDED(ret)) ret = svcCloseHandle(handle);
return ret;
}

View File

@@ -10,4 +10,3 @@ Result FSLDR_OpenFileDirectly(Handle* out, FS_ArchiveID archiveId, FS_Path archi
Result FSLDR_OpenArchive(FS_Archive* archive, FS_ArchiveID id, FS_Path path); Result FSLDR_OpenArchive(FS_Archive* archive, FS_ArchiveID id, FS_Path path);
Result FSLDR_CloseArchive(FS_Archive archive); Result FSLDR_CloseArchive(FS_Archive archive);
Result FSLDR_OpenDirectory(Handle* out, FS_Archive archive, FS_Path path); Result FSLDR_OpenDirectory(Handle* out, FS_Archive archive, FS_Path path);
Result FSDIRLDR_Close(Handle handle);

View File

@@ -158,7 +158,7 @@ static Result load_code(u64 progid, prog_addrs_t *shared, u64 prog_handle, int i
u16 progver = g_exheader.codesetinfo.flags.remasterversion[0] | (g_exheader.codesetinfo.flags.remasterversion[1] << 8); u16 progver = g_exheader.codesetinfo.flags.remasterversion[0] | (g_exheader.codesetinfo.flags.remasterversion[1] << 8);
// patch // patch
patchCode(progid, progver, (u8 *)shared->text_addr, shared->total_size << 12); patchCode(progid, progver, (u8 *)shared->text_addr, shared->total_size << 12, g_exheader.codesetinfo.text.codesize, g_exheader.codesetinfo.ro.codesize);
return 0; return 0;
} }

View File

@@ -13,7 +13,7 @@ static u32 patchMemory(u8 *start, u32 size, const void *pattern, u32 patSize, in
{ {
u32 i; u32 i;
for(i = 0; i < count; i++) for(i = 0; !count || i < count; i++)
{ {
u8 *found = memsearch(start, pattern, size, patSize); u8 *found = memsearch(start, pattern, size, patSize);
@@ -52,7 +52,7 @@ static u32 dirCheck(FS_ArchiveID archiveId, const char *path)
else else
{ {
ret = R_SUCCEEDED(FSLDR_OpenDirectory(&handle, archive, dirPath)) ? 0 : 2; ret = R_SUCCEEDED(FSLDR_OpenDirectory(&handle, archive, dirPath)) ? 0 : 2;
if(ret) FSDIRLDR_Close(handle); if(!ret) FSDIR_Close(handle);
FSLDR_CloseArchive(archive); FSLDR_CloseArchive(archive);
} }
@@ -87,8 +87,7 @@ static inline void loadCFWInfo(void)
svcGetCFWInfo(&info); svcGetCFWInfo(&info);
IFile file; IFile file;
if(LOADERFLAG(ISSAFEMODE) && R_SUCCEEDED(fileOpen(&file, ARCHIVE_SDMC, "/", FS_OPEN_READ))) //Init SD card if SAFE_MODE is being booted if(LOADERFLAG(ISSAFEMODE)) fileOpen(&file, ARCHIVE_SDMC, "/", FS_OPEN_READ); //Init SD card if SAFE_MODE is being booted
IFile_Close(&file);
infoLoaded = true; infoLoaded = true;
} }
@@ -187,17 +186,16 @@ static inline u8 *getCfgOffsets(u8 *code, u32 size, u32 *CFGUHandleOffset)
for(u8 *CFGU_GetConfigInfoBlk2_endPos = code; CFGU_GetConfigInfoBlk2_endPos <= code + size - 12; CFGU_GetConfigInfoBlk2_endPos += 4) for(u8 *CFGU_GetConfigInfoBlk2_endPos = code; CFGU_GetConfigInfoBlk2_endPos <= code + size - 12; CFGU_GetConfigInfoBlk2_endPos += 4)
{ {
static const u32 CFGU_GetConfigInfoBlk2_endPattern[] = {0xE8BD8010, 0x00010082};
//There might be multiple implementations of GetConfigInfoBlk2 but let's search for the one we want //There might be multiple implementations of GetConfigInfoBlk2 but let's search for the one we want
u32 *cmp = (u32 *)CFGU_GetConfigInfoBlk2_endPos; u32 *cmp = (u32 *)CFGU_GetConfigInfoBlk2_endPos;
if(cmp[0] != CFGU_GetConfigInfoBlk2_endPattern[0] || cmp[1] != CFGU_GetConfigInfoBlk2_endPattern[1]) continue; if(cmp[0] != 0xE8BD8010 || cmp[1] != 0x00010082) continue;
for(u32 i = 0; i < n; i++) for(u32 i = 0; i < n; i++)
if(possible[i] == cmp[2]) if(possible[i] == cmp[2])
{ {
*CFGUHandleOffset = cmp[2]; *CFGUHandleOffset = cmp[2];
return CFGU_GetConfigInfoBlk2_endPos; return CFGU_GetConfigInfoBlk2_endPos;
} }
@@ -257,14 +255,12 @@ static inline void patchCfgGetRegion(u8 *code, u32 size, u8 regionId, u32 CFGUHa
{ {
for(u8 *cmdPos = code; cmdPos <= code + size - 28; cmdPos += 4) for(u8 *cmdPos = code; cmdPos <= code + size - 28; cmdPos += 4)
{ {
static const u32 cfgSecureInfoGetRegionCmdPattern[] = {0xEE1D0F70, 0xE3A00802};
u32 *cmp = (u32 *)cmdPos; u32 *cmp = (u32 *)cmdPos;
if(*cmp != cfgSecureInfoGetRegionCmdPattern[1]) continue; if(*cmp != 0xE3A00802) continue;
for(u32 i = 1; i < 3; i++) for(u32 i = 1; i < 3; i++)
if((*(cmp - i) & 0xFFFF0FFF) == cfgSecureInfoGetRegionCmdPattern[0] && *((u16 *)cmdPos + 5) == 0xE59F && if((*(cmp - i) & 0xFFFF0FFF) == 0xEE1D0F70 && *((u16 *)cmdPos + 5) == 0xE59F &&
*(u32 *)(cmdPos + 16 + *((u16 *)cmdPos + 4)) == CFGUHandleOffset) *(u32 *)(cmdPos + 16 + *((u16 *)cmdPos + 4)) == CFGUHandleOffset)
{ {
cmp[3] = 0xE3A00000 | regionId; //mov r0, =regionId cmp[3] = 0xE3A00000 | regionId; //mov r0, =regionId
@@ -278,7 +274,7 @@ static inline void patchCfgGetRegion(u8 *code, u32 size, u8 regionId, u32 CFGUHa
} }
} }
static u32 findFunctionStart(u8* code, u32 pos) static u32 findFunctionStart(u8 *code, u32 pos)
{ {
while(pos >= 4) while(pos >= 4)
{ {
@@ -289,45 +285,69 @@ static u32 findFunctionStart(u8* code, u32 pos)
return 0xFFFFFFFF; return 0xFFFFFFFF;
} }
static bool findLayeredFsSymbols(u8* code, u32 size, u32 *fsMountArchive, u32 *fsRegisterArchive, u32 *fsTryOpenFile, u32 *fsOpenFileDirectly, u32 *throwFatalError) static inline bool findLayeredFsSymbols(u8 *code, u32 size, u32 *fsMountArchive, u32 *fsRegisterArchive, u32 *fsTryOpenFile, u32 *fsOpenFileDirectly)
{ {
bool found = false; u32 found = 0,
*temp = NULL;
for(u32 addr = 0; addr <= size - 4; addr += 4)
{
switch(*(u32 *)(code + addr))
{
case 0xE5970010:
if(addr <= size - 12 && *fsMountArchive == 0xFFFFFFFF && *(u32 *)(code + addr + 4) == 0xE1CD20D8 && (*(u32 *)(code + addr + 8) & 0xFFFFFF) == 0x008D0000) temp = fsMountArchive;
break;
case 0xE24DD028:
if(addr <= size - 16 && *fsMountArchive == 0xFFFFFFFF && *(u32 *)(code + addr + 4) == 0xE1A04000 && *(u32 *)(code + addr + 8) == 0xE59F60A8 && *(u32 *)(code + addr + 0xC) == 0xE3A0C001) temp = fsMountArchive;
break;
case 0xE3500008:
if(addr <= size - 12 && *fsRegisterArchive == 0xFFFFFFFF && (*(u32 *)(code + addr + 4) & 0xFFF00FF0) == 0xE1800400 && (*(u32 *)(code + addr + 8) & 0xFFF00FF0) == 0xE1800FC0) temp = fsRegisterArchive;
break;
case 0xE351003A:
if(addr <= size - 0x40 && *fsTryOpenFile == 0xFFFFFFFF && *(u32 *)(code + addr + 4) == 0x1AFFFFFC && *(u32 *)(code + addr + 0x34) == 0xE590C000 && *(u32 *)(code + addr + 0x3C) == 0xE12FFF3C) temp = fsTryOpenFile;
break;
case 0x08030204:
if(*fsOpenFileDirectly == 0xFFFFFFFF) temp = fsOpenFileDirectly;
break;
}
if(temp != NULL)
{
*temp = findFunctionStart(code, addr);
if(*temp != 0xFFFFFFFF)
{
found++;
if(found == 4) break;
}
temp = NULL;
}
}
return found == 4;
}
static inline bool findLayeredFsPayloadOffset(u8 *code, u32 size, u32 *payloadOffset)
{
//First check for sufficient padding at the end of the .text segment
if(((size + 4095) & 0xFFFFF000) - size >= romfsredir_bin_size)
{
*payloadOffset = size;
return true;
}
//If there isn't enough padding look for the "throwFatalError" function to replace
u32 svcConnectToPort = 0xFFFFFFFF; u32 svcConnectToPort = 0xFFFFFFFF;
for(u32 addr = 0; !found && addr <= size - 4; addr += 4) for(u32 addr = 4; svcConnectToPort == 0xFFFFFFFF && addr <= size - 4; addr += 4)
{ {
if(*fsMountArchive == 0xFFFFFFFF) if(*(u32 *)(code + addr) == 0xEF00002D)
{
if(addr <= size - 12 && *(u32 *)(code + addr) == 0xE5970010)
{
if((*(u32 *)(code + addr + 4) == 0xE1CD20D8) && ((*(u32 *)(code + addr + 8) & 0xFFFFFF) == 0x008D0000))
*fsMountArchive = findFunctionStart(code, addr);
}
else if(addr <= size - 16 && *(u32 *)(code + addr) == 0xE24DD028)
{
if((*(u32 *)(code + addr + 4) == 0xE1A04000) && (*(u32 *)(code + addr + 8) == 0xE59F60A8) && (*(u32 *)(code + addr + 0xC) == 0xE3A0C001))
*fsMountArchive = findFunctionStart(code, addr);
}
}
if(addr <= size - 12 && *fsRegisterArchive == 0xFFFFFFFF && *(u32 *)(code + addr) == 0xE3500008 && (*(u32 *)(code + addr + 4) & 0xFFF00FF0) == 0xE1800400 && (*(u32 *)(code + addr + 8) & 0xFFF00FF0) == 0xE1800FC0)
*fsRegisterArchive = findFunctionStart(code, addr);
if(addr <= size - 16 && *fsTryOpenFile == 0xFFFFFFFF && *(u32 *)(code + addr + 0xC) == 0xE12FFF3C &&
((*(u32 *)(code + addr) == 0xE1A0100D) || (*(u32 *)(code + addr) == 0xE28D1010)) && (*(u32 *)(code + addr + 4) == 0xE590C000) &&
((*(u32 *)(code + addr + 8) == 0xE1A00004) || (*(u32 *)(code + addr + 8) == 0xE1A00005)))
*fsTryOpenFile = findFunctionStart(code, addr);
if(*fsOpenFileDirectly == 0xFFFFFFFF && *(u32 *)(code + addr) == 0x08030204)
*fsOpenFileDirectly = findFunctionStart(code, addr);
if(addr >= 4 && svcConnectToPort == 0xFFFFFFFF && *(u32 *)(code + addr) == 0xEF00002D)
svcConnectToPort = addr - 4; svcConnectToPort = addr - 4;
if(svcConnectToPort != 0xFFFFFFFF && *fsMountArchive != 0xFFFFFFFF && *fsRegisterArchive != 0xFFFFFFFF && *fsTryOpenFile != 0xFFFFFFFF && *fsOpenFileDirectly != 0xFFFFFFFF) found = true;
} }
if(found) if(svcConnectToPort != 0xFFFFFFFF)
{ {
u32 func = 0xFFFFFFFF; u32 func = 0xFFFFFFFF;
@@ -341,9 +361,12 @@ static bool findLayeredFsSymbols(u8* code, u32 size, u32 *fsMountArchive, u32 *f
if(*(u32 *)(code + pos) == 0xE200167E) func = 0xFFFFFFFF; if(*(u32 *)(code + pos) == 0xE200167E) func = 0xFFFFFFFF;
} }
*throwFatalError = func; if(func != 0xFFFFFFFF)
{
*payloadOffset = func;
if(func != 0xFFFFFFFF) return true; return true;
}
} }
return false; return false;
@@ -458,13 +481,13 @@ static inline bool loadTitleLocaleConfig(u64 progId, u8 *regionId, u8 *languageI
if(R_FAILED(IFile_Read(&file, &total, buf, fileSize))) goto exit; if(R_FAILED(IFile_Read(&file, &total, buf, fileSize))) goto exit;
u32 i, static const char *regions[] = {"JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"},
j; *languages[] = {"JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"};
for(i = 0; i < 7; i++) u32 i;
for(i = 0; i < sizeof(regions) / sizeof(char *); i++)
{ {
static const char *regions[] = {"JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"};
if(memcmp(buf, regions[i], 3) == 0) if(memcmp(buf, regions[i], 3) == 0)
{ {
*regionId = (u8)i; *regionId = (u8)i;
@@ -472,18 +495,18 @@ static inline bool loadTitleLocaleConfig(u64 progId, u8 *regionId, u8 *languageI
} }
} }
for(j = 0; j < 12; j++) if(i != sizeof(regions) / sizeof(char *))
{ {
static const char *languages[] = {"JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"}; for(i = 0; i < sizeof(languages) / sizeof(char *); i++)
if(memcmp(buf + 4, languages[j], 2) == 0)
{ {
*languageId = (u8)j; if(memcmp(buf + 4, languages[i], 2) == 0)
{
*languageId = (u8)i;
ret = true;
break; break;
} }
} }
}
ret = i != 7 && j != 12;
exit: exit:
IFile_Close(&file); IFile_Close(&file);
@@ -491,7 +514,7 @@ exit:
return ret; return ret;
} }
static inline bool patchLayeredFs(u64 progId, u8* code, u32 size) static inline bool patchLayeredFs(u64 progId, u8 *code, u32 size, u32 textSize)
{ {
/* Here we look for "/luma/titles/[u64 titleID in hex, uppercase]/romfs" /* Here we look for "/luma/titles/[u64 titleID in hex, uppercase]/romfs"
If it exists it should be a folder containing ROMFS files */ If it exists it should be a folder containing ROMFS files */
@@ -499,45 +522,59 @@ static inline bool patchLayeredFs(u64 progId, u8* code, u32 size)
char path[] = "/luma/titles/0000000000000000/romfs"; char path[] = "/luma/titles/0000000000000000/romfs";
progIdToStr(path + 28, progId); progIdToStr(path + 28, progId);
u32 archive = checkLumaDir(path); u32 archiveId = checkLumaDir(path);
if(!archive) return true; if(!archiveId) return true;
const char *mount = archive == ARCHIVE_SDMC ? "sdmc:" : "nand:";
u32 fsMountArchive = 0xFFFFFFFF, u32 fsMountArchive = 0xFFFFFFFF,
fsRegisterArchive = 0xFFFFFFFF, fsRegisterArchive = 0xFFFFFFFF,
fsTryOpenFile = 0xFFFFFFFF, fsTryOpenFile = 0xFFFFFFFF,
fsOpenFileDirectly = 0xFFFFFFFF, fsOpenFileDirectly = 0xFFFFFFFF,
throwFatalError; payloadOffset;
if(!findLayeredFsSymbols(code, size, &fsMountArchive, &fsRegisterArchive, &fsTryOpenFile, &fsOpenFileDirectly, &throwFatalError)) return false; if(!findLayeredFsSymbols(code, textSize, &fsMountArchive, &fsRegisterArchive, &fsTryOpenFile, &fsOpenFileDirectly) ||
!findLayeredFsPayloadOffset(code, textSize, &payloadOffset)) return false;
static const char *updateRomFsMounts[] = { "patch:",
"ext:" },
patch = 'r';
//Change update RomFS mountpoints to start with "r"
for(u32 i = 0, ret = 0; i < sizeof(updateRomFsMounts) / sizeof(char *) && !ret; i++)
{
ret = patchMemory(code, size,
updateRomFsMounts[i],
strnlen(updateRomFsMounts[i], 255), 0,
&patch,
sizeof(patch), 0
);
}
//Setup the payload //Setup the payload
u8 *payload = code + throwFatalError; u8 *payload = code + payloadOffset;
memcpy(payload, romfsredir_bin, romfsredir_bin_size); memcpy(payload, romfsredir_bin, romfsredir_bin_size);
//Insert symbols in the payload //Insert symbols in the payload
u32 *payload32 = (u32 *)payload; u32 *payload32 = (u32 *)payload;
for(u32 i = 0; i < romfsredir_bin_size / 4; i++) for(u32 i = 0; i < romfsredir_bin_size / 4; i++)
{ {
switch (payload32[i]) switch(payload32[i])
{ {
case 0xdead0000: case 0xdead0000:
payload32[i] = *(u32 *)(code + fsOpenFileDirectly); payload32[i] = *(u32 *)(code + fsOpenFileDirectly);
break; break;
case 0xdead0001: case 0xdead0001:
payload32[i] = MAKE_BRANCH(throwFatalError + i * 4, fsOpenFileDirectly + 4); payload32[i] = MAKE_BRANCH(payloadOffset + i * 4, fsOpenFileDirectly + 4);
break; break;
case 0xdead0002: case 0xdead0002:
payload32[i] = *(u32 *)(code + fsTryOpenFile); payload32[i] = *(u32 *)(code + fsTryOpenFile);
break; break;
case 0xdead0003: case 0xdead0003:
payload32[i] = MAKE_BRANCH(throwFatalError + i * 4, fsTryOpenFile + 4); payload32[i] = MAKE_BRANCH(payloadOffset + i * 4, fsTryOpenFile + 4);
break; break;
case 0xdead0004: case 0xdead0004:
memcpy(payload32 + i, mount, 5); memcpy(payload32 + i, "lf:", 3);
memcpy((u8 *)(payload32 + i) + 5, path, sizeof(path)); memcpy((u8 *)(payload32 + i) + 3, path, sizeof(path));
break; break;
case 0xdead0005: case 0xdead0005:
payload32[i] = 0x100000 + fsMountArchive; payload32[i] = 0x100000 + fsMountArchive;
@@ -546,22 +583,19 @@ static inline bool patchLayeredFs(u64 progId, u8* code, u32 size)
payload32[i] = 0x100000 + fsRegisterArchive; payload32[i] = 0x100000 + fsRegisterArchive;
break; break;
case 0xdead0007: case 0xdead0007:
memcpy(payload32 + i, mount, 4); payload32[i] = archiveId;
break;
case 0xdead0008:
payload32[i] = archive;
break; break;
} }
} }
//Place the hooks //Place the hooks
*(u32 *)(code + fsOpenFileDirectly) = MAKE_BRANCH(fsOpenFileDirectly, throwFatalError); *(u32 *)(code + fsOpenFileDirectly) = MAKE_BRANCH(fsOpenFileDirectly, payloadOffset);
*(u32 *)(code + fsTryOpenFile) = MAKE_BRANCH(fsTryOpenFile, throwFatalError + 12); *(u32 *)(code + fsTryOpenFile) = MAKE_BRANCH(fsTryOpenFile, payloadOffset + 12);
return true; return true;
} }
void patchCode(u64 progId, u16 progVer, u8 *code, u32 size) void patchCode(u64 progId, u16 progVer, u8 *code, u32 size, u32 textSize, u32 roSize)
{ {
loadCFWInfo(); loadCFWInfo();
@@ -582,7 +616,7 @@ void patchCode(u64 progId, u16 progVer, u8 *code, u32 size)
}; };
//Patch SMDH region checks //Patch SMDH region checks
if(!patchMemory(code, size, if(!patchMemory(code, textSize,
pattern, pattern,
sizeof(pattern), -31, sizeof(pattern), -31,
patch, patch,
@@ -598,7 +632,7 @@ void patchCode(u64 progId, u16 progVer, u8 *code, u32 size)
u8 mostRecentFpdVer = 10; u8 mostRecentFpdVer = 10;
u8 *off = memsearch(code, pattern, size, sizeof(pattern)); u8 *off = memsearch(code, pattern, textSize, sizeof(pattern));
if(off == NULL) goto error; if(off == NULL) goto error;
@@ -649,7 +683,7 @@ void patchCode(u64 progId, u16 progVer, u8 *code, u32 size)
} }
//Patch Ver. string //Patch Ver. string
if(!patchMemory(code, size, if(!patchMemory(code, textSize,
pattern, pattern,
sizeof(pattern) - 2, 0, sizeof(pattern) - 2, 0,
patch, patch,
@@ -669,7 +703,7 @@ void patchCode(u64 progId, u16 progVer, u8 *code, u32 size)
}; };
//Disable updates from foreign carts (makes carts region-free) //Disable updates from foreign carts (makes carts region-free)
u32 ret = patchMemory(code, size, u32 ret = patchMemory(code, textSize,
pattern, pattern,
sizeof(pattern), 0, sizeof(pattern), 0,
patch, patch,
@@ -689,7 +723,7 @@ void patchCode(u64 progId, u16 progVer, u8 *code, u32 size)
0x0C, 0x00, 0x94, 0x15 0x0C, 0x00, 0x94, 0x15
}; };
u32 *off = (u32 *)memsearch(code, pattern, size, sizeof(pattern)); u32 *off = (u32 *)memsearch(code, pattern, textSize, sizeof(pattern));
if(off == NULL) goto error; if(off == NULL) goto error;
@@ -712,7 +746,7 @@ void patchCode(u64 progId, u16 progVer, u8 *code, u32 size)
}; };
//Disable SecureInfo signature check //Disable SecureInfo signature check
if(!patchMemory(code, size, if(!patchMemory(code, textSize,
pattern, pattern,
sizeof(pattern), 0, sizeof(pattern), 0,
patch, patch,
@@ -725,7 +759,7 @@ void patchCode(u64 progId, u16 progVer, u8 *code, u32 size)
patch[] = u"C"; patch[] = u"C";
//Use SecureInfo_C //Use SecureInfo_C
if(patchMemory(code, size, if(patchMemory(code + textSize, roSize,
pattern, pattern,
sizeof(pattern) - 2, 22, sizeof(pattern) - 2, 22,
patch, patch,
@@ -750,19 +784,19 @@ void patchCode(u64 progId, u16 progVer, u8 *code, u32 size)
}; };
//Disable CRR0 signature (RSA2048 with SHA256) check and CRO0/CRR0 SHA256 hash checks (section hashes, and hash table) //Disable CRR0 signature (RSA2048 with SHA256) check and CRO0/CRR0 SHA256 hash checks (section hashes, and hash table)
if(!patchMemory(code, size, if(!patchMemory(code, textSize,
pattern, pattern,
sizeof(pattern), -9, sizeof(pattern), -9,
patch, patch,
sizeof(patch), 1 sizeof(patch), 1
) || ) ||
!patchMemory(code, size, !patchMemory(code, textSize,
pattern2, pattern2,
sizeof(pattern2), 1, sizeof(pattern2), 1,
patch, patch,
sizeof(patch), 1 sizeof(patch), 1
) || ) ||
!patchMemory(code, size, !patchMemory(code, textSize,
pattern3, pattern3,
sizeof(pattern3), -2, sizeof(pattern3), -2,
patch, patch,
@@ -783,13 +817,13 @@ void patchCode(u64 progId, u16 progVer, u8 *code, u32 size)
}; };
//Patch UNITINFO checks to make ErrDisp more verbose //Patch UNITINFO checks to make ErrDisp more verbose
if(!patchMemory(code, size, if(!patchMemory(code, textSize,
pattern, pattern,
sizeof(pattern), -1, sizeof(pattern), -1,
patch, patch,
sizeof(patch), 1 sizeof(patch), 1
) || ) ||
patchMemory(code, size, patchMemory(code, textSize,
pattern2, pattern2,
sizeof(pattern2), 0, sizeof(pattern2), 0,
patch, patch,
@@ -807,7 +841,7 @@ void patchCode(u64 progId, u16 progVer, u8 *code, u32 size)
}; };
//Patch DLP region checks //Patch DLP region checks
if(!patchMemory(code, size, if(!patchMemory(code, textSize,
pattern, pattern,
sizeof(pattern), 0, sizeof(pattern), 0,
patch, patch,
@@ -823,17 +857,17 @@ void patchCode(u64 progId, u16 progVer, u8 *code, u32 size)
if(!loadTitleCodeSection(progId, code, size) || if(!loadTitleCodeSection(progId, code, size) ||
!applyCodeIpsPatch(progId, code, size) || !applyCodeIpsPatch(progId, code, size) ||
!loadTitleLocaleConfig(progId, &regionId, &languageId) || !loadTitleLocaleConfig(progId, &regionId, &languageId) ||
!patchLayeredFs(progId, code, size)) goto error; !patchLayeredFs(progId, code, size, textSize)) goto error;
if(regionId != 0xFF) if(regionId != 0xFF)
{ {
u32 CFGUHandleOffset; u32 CFGUHandleOffset;
u8 *CFGU_GetConfigInfoBlk2_endPos = getCfgOffsets(code, size, &CFGUHandleOffset); u8 *CFGU_GetConfigInfoBlk2_endPos = getCfgOffsets(code, textSize, &CFGUHandleOffset);
if(CFGU_GetConfigInfoBlk2_endPos == NULL || if(CFGU_GetConfigInfoBlk2_endPos == NULL ||
!patchCfgGetLanguage(code, size, languageId, CFGU_GetConfigInfoBlk2_endPos)) goto error; !patchCfgGetLanguage(code, textSize, languageId, CFGU_GetConfigInfoBlk2_endPos)) goto error;
patchCfgGetRegion(code, size, regionId, CFGUHandleOffset); patchCfgGetRegion(code, textSize, regionId, CFGUHandleOffset);
} }
} }

View File

@@ -44,4 +44,4 @@ enum flags
ISSAFEMODE ISSAFEMODE
}; };
void patchCode(u64 progId, u16 progVer, u8 *code, u32 size); void patchCode(u64 progId, u16 progVer, u8 *code, u32 size, u32 textSize, u32 roSize);

View File

@@ -9,7 +9,6 @@ SECTIONS
.text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); } .text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); }
.rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); } .rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); }
.data : ALIGN(4) { *(.data*); . = ALIGN(4); } .data : ALIGN(4) { *(.data*); . = ALIGN(4); }
.bss : ALIGN(8) { __bss_start = .; *(.bss* COMMON); . = ALIGN(8); __bss_end = .; } .bss : ALIGN(8) { __bss_start = .; *(.bss* COMMON); . = ALIGN(8); __bss_end = .; }
. = ALIGN(4); . = ALIGN(4);

View File

@@ -5,6 +5,7 @@ ENTRY(_start)
SECTIONS SECTIONS
{ {
. = 0x24FFFE00; . = 0x24FFFE00;
.text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); } .text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); }
.rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); } .rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); }
.data : ALIGN(4) { *(.data*); . = ALIGN(8); *(.bss* COMMON); . = ALIGN(8); } .data : ALIGN(4) { *(.data*); . = ALIGN(8); *(.bss* COMMON); . = ALIGN(8); }

View File

@@ -182,11 +182,11 @@ void configMenu(bool isSdMode, bool oldPinStatus, u32 oldPinMode)
"The service and archive patches\n" "The service and archive patches\n"
"don't work on New 3DS FIRMs between\n" "don't work on New 3DS FIRMs between\n"
"9.3 and 10.4.\n\n" "9.3 and 10.4.\n\n"
"Only change this if you know what you\n" "Only select this if you know what you\n"
"are doing!", "are doing!",
"Make the console be always detected\n" "Make the console be always detected\n"
"as a development unit\n" "as a development unit, and conversely.\n"
"(which breaks online features, amiibo\n" "(which breaks online features, amiibo\n"
"and retail CIAs, but allows installing\n" "and retail CIAs, but allows installing\n"
"and booting some developer software).\n\n" "and booting some developer software).\n\n"

View File

@@ -155,8 +155,14 @@ void detectAndProcessExceptionDumps(void)
if(dumpHeader->processor == 11 && dumpHeader->additionalDataSize != 0) if(dumpHeader->processor == 11 && dumpHeader->additionalDataSize != 0)
{ {
char processName[] = "Current process: "; char processName[45] = "Current process: ";
memcpy(processName + sizeof(processName) - 9, (void *)additionalData, 8); memcpy(processName + 17, (void *)additionalData, 8);
hexItoa(*(vu32 *)(additionalData + 12), hexString, 8, true);
concatenateStrings(processName, " (");
concatenateStrings(processName, hexString);
hexItoa(*(vu32 *)(additionalData + 8), hexString, 8, true);
concatenateStrings(processName, hexString);
concatenateStrings(processName, ")");
posY = drawString(processName, true, 10, posY + SPACING_Y, COLOR_WHITE); posY = drawString(processName, true, 10, posY + SPACING_Y, COLOR_WHITE);
} }

View File

@@ -2051,6 +2051,7 @@ FRESULT load_obj_dir (
dp->obj.sclust = obj->c_scl; dp->obj.sclust = obj->c_scl;
dp->obj.stat = (BYTE)obj->c_size; dp->obj.stat = (BYTE)obj->c_size;
dp->obj.objsize = obj->c_size & 0xFFFFFF00; dp->obj.objsize = obj->c_size & 0xFFFFFF00;
dp->obj.n_frag = 0;
dp->blk_ofs = obj->c_ofs; dp->blk_ofs = obj->c_ofs;
res = dir_sdi(dp, dp->blk_ofs); /* Goto object's entry block */ res = dir_sdi(dp, dp->blk_ofs); /* Goto object's entry block */
@@ -2326,20 +2327,23 @@ FRESULT dir_register ( /* FR_OK:succeeded, FR_DENIED:no free entry or too many S
if (res != FR_OK) return res; if (res != FR_OK) return res;
dp->blk_ofs = dp->dptr - SZDIRE * (nent - 1); /* Set the allocated entry block offset */ dp->blk_ofs = dp->dptr - SZDIRE * (nent - 1); /* Set the allocated entry block offset */
if (dp->obj.sclust != 0 && (dp->obj.stat & 4)) { /* Has the sub-directory been stretched? */ if (dp->obj.stat & 4) { /* Has the directory been stretched? */
dp->obj.objsize += (DWORD)fs->csize * SS(fs); /* Increase the directory size by cluster size */ dp->obj.stat &= ~4;
res = fill_first_frag(&dp->obj); /* Fill first fragment on the FAT if needed */ res = fill_first_frag(&dp->obj); /* Fill the first fragment on the FAT if needed */
if (res != FR_OK) return res; if (res != FR_OK) return res;
res = fill_last_frag(&dp->obj, dp->clust, 0xFFFFFFFF); /* Fill last fragment on the FAT if needed */ res = fill_last_frag(&dp->obj, dp->clust, 0xFFFFFFFF); /* Fill the last fragment on the FAT if needed */
if (res != FR_OK) return res; if (res != FR_OK) return res;
if (dp->obj.sclust != 0) { /* Is it a sub directory? */
res = load_obj_dir(&dj, &dp->obj); /* Load the object status */ res = load_obj_dir(&dj, &dp->obj); /* Load the object status */
if (res != FR_OK) return res; if (res != FR_OK) return res;
dp->obj.objsize += (DWORD)fs->csize * SS(fs); /* Increase the directory size by cluster size */
st_qword(fs->dirbuf + XDIR_FileSize, dp->obj.objsize); /* Update the allocation status */ st_qword(fs->dirbuf + XDIR_FileSize, dp->obj.objsize); /* Update the allocation status */
st_qword(fs->dirbuf + XDIR_ValidFileSize, dp->obj.objsize); st_qword(fs->dirbuf + XDIR_ValidFileSize, dp->obj.objsize);
fs->dirbuf[XDIR_GenFlags] = dp->obj.stat | 1; fs->dirbuf[XDIR_GenFlags] = dp->obj.stat | 1;
res = store_xdir(&dj); /* Store the object status */ res = store_xdir(&dj); /* Store the object status */
if (res != FR_OK) return res; if (res != FR_OK) return res;
} }
}
create_xdir(fs->dirbuf, fs->lfnbuf); /* Create on-memory directory block to be written later */ create_xdir(fs->dirbuf, fs->lfnbuf); /* Create on-memory directory block to be written later */
return FR_OK; return FR_OK;

View File

@@ -240,7 +240,8 @@ boot:
bool loadFromStorage = CONFIG(LOADEXTFIRMSANDMODULES); bool loadFromStorage = CONFIG(LOADEXTFIRMSANDMODULES);
u32 firmVersion = loadFirm(&firmType, firmSource, loadFromStorage, isSafeMode); u32 firmVersion = loadFirm(&firmType, firmSource, loadFromStorage, isSafeMode);
bool doUnitinfoPatch = CONFIG(PATCHUNITINFO), enableExceptionHandlers = CONFIG(ENABLEEXCEPTIONHANDLERS); bool doUnitinfoPatch = CONFIG(PATCHUNITINFO),
enableExceptionHandlers = CONFIG(ENABLEEXCEPTIONHANDLERS);
u32 res; u32 res;
switch(firmType) switch(firmType)
{ {

View File

@@ -47,9 +47,6 @@ static const u32 brightness[4] = {0x5F, 0x4C, 0x39, 0x26};
void __attribute__((naked)) arm11Stub(void) void __attribute__((naked)) arm11Stub(void)
{ {
//Disable interrupts
__asm(".word 0xF10C01C0");
WAIT_FOR_ARM9(); WAIT_FOR_ARM9();
} }

View File

@@ -33,7 +33,7 @@
#define ARESCREENSINITIALIZED (PDN_GPU_CNT != 1) #define ARESCREENSINITIALIZED (PDN_GPU_CNT != 1)
#define ARM11_STUB_ADDRESS 0x1FFFFD00 #define ARM11_STUB_ADDRESS 0x1FFFFF00
#define WAIT_FOR_ARM9() *arm11Entry = 0; while(!*arm11Entry); ((void (*)())*arm11Entry)(); #define WAIT_FOR_ARM9() *arm11Entry = 0; while(!*arm11Entry); ((void (*)())*arm11Entry)();
#define SCREEN_TOP_WIDTH 400 #define SCREEN_TOP_WIDTH 400

View File

@@ -91,6 +91,7 @@ start:
mov r1, #0x340 mov r1, #0x340
str r1, [r0] str r1, [r0]
@ Clear BSS
ldr r0, =__bss_start ldr r0, =__bss_start
mov r1, #0 mov r1, #0
ldr r2, =__bss_end ldr r2, =__bss_end