Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
725a825762 | ||
|
|
b81f59d5ae | ||
|
|
39c2b8927b | ||
|
|
89dfdac7bf | ||
|
|
c087edf2ba | ||
|
|
db33c315f2 | ||
|
|
c7e7dd8248 | ||
|
|
b10d82a883 | ||
|
|
e151b3d4ef | ||
|
|
5ccf4a45c1 | ||
|
|
c5369a5cad | ||
|
|
b5eba765a5 | ||
|
|
a5ddc38477 | ||
|
|
8d102256a2 | ||
|
|
2e561f7ea9 | ||
|
|
9656fe1b6f | ||
|
|
48c23f2a43 | ||
|
|
6d82649c3c | ||
|
|
81dea35754 | ||
|
|
fdbe43421b | ||
|
|
0d71560785 | ||
|
|
108e8a0cd4 | ||
|
|
653e81c48e | ||
|
|
0dc0783094 | ||
|
|
13ef1bf6be | ||
|
|
7ea80353f6 |
10
.github/ISSUE_TEMPLATE.md
vendored
10
.github/ISSUE_TEMPLATE.md
vendored
@@ -2,18 +2,12 @@
|
||||
#
|
||||
# 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/
|
||||
# /r/3dshacks: http://reddit.com/r/3dshacks/
|
||||
# Nintendo Hacking: https://discordapp.com/invite/C29hYvh
|
||||
# IRC: #3dshacks@rizon
|
||||
# Nintendo Hacking: https://discord.gg/MjzatM8y
|
||||
#
|
||||
# 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
|
||||
#
|
||||
# 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).
|
||||
# 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)
|
||||
# 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).
|
||||
#
|
||||
-->
|
||||
|
||||
@@ -5,6 +5,7 @@ ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
. = 0;
|
||||
|
||||
.text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); }
|
||||
.rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); }
|
||||
.data : ALIGN(4) { *(.data*); . = ALIGN(8); *(.bss* COMMON); . = ALIGN(8); }
|
||||
|
||||
@@ -5,6 +5,7 @@ ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x01FF7FE0;
|
||||
|
||||
.text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); }
|
||||
.rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); }
|
||||
.data : ALIGN(4) { *(.data*); . = ALIGN(8); *(.bss* COMMON); . = ALIGN(8); }
|
||||
|
||||
Submodule haxloader/CakeBrah updated: b8bc4413d3...1efda4e894
Submodule haxloader/CakeHax updated: f3d05ec3e1...329212a8e0
@@ -103,7 +103,7 @@ diff -uNr a/source/brahma.c b/source/brahma.c
|
||||
diff -uNr a/source/main.c b/source/main.c
|
||||
--- a/source/main.c 2016-09-26 16:05:36.363067000 +0200
|
||||
+++ b/source/main.c 2016-09-26 21:40:35.202513018 +0200
|
||||
@@ -10,7 +10,7 @@
|
||||
@@ -38,7 +38,7 @@
|
||||
|
||||
int main (void) {
|
||||
if (brahma_init()) {
|
||||
@@ -112,7 +112,7 @@ diff -uNr a/source/main.c b/source/main.c
|
||||
goto error;
|
||||
firm_reboot();
|
||||
brahma_exit();
|
||||
@@ -22,7 +22,7 @@
|
||||
@@ -50,7 +50,7 @@
|
||||
error:
|
||||
gfxInitDefault();
|
||||
consoleInit(GFX_BOTTOM, NULL);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
diff -uNr a/source/main.c b/source/main.c
|
||||
--- a/source/main.c 2016-09-11 01:04:25.665231884 +0200
|
||||
+++ b/source/main.c 2016-09-14 12:36:28.601439550 +0200
|
||||
@@ -9,6 +9,7 @@
|
||||
#endif
|
||||
@@ -37,6 +37,7 @@
|
||||
}
|
||||
|
||||
int main (void) {
|
||||
+ svcSleepThread(2500 * 1000000ULL);
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
|
||||
OUTPUT_ARCH(arm)
|
||||
|
||||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x23F00000;
|
||||
.text.start : { *(.text.start) }
|
||||
.text : { *(.text) }
|
||||
.data : { *(.data) }
|
||||
.bss : { *(.bss COMMON) }
|
||||
.rodata : { *(.rodata) }
|
||||
|
||||
.text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); }
|
||||
.rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); }
|
||||
.data : ALIGN(4) { *(.data*); . = ALIGN(8); *(.bss* COMMON); . = ALIGN(8); }
|
||||
|
||||
. = ALIGN(4);
|
||||
}
|
||||
|
||||
@@ -2050,7 +2050,8 @@ FRESULT load_obj_dir (
|
||||
dp->obj.fs = obj->fs;
|
||||
dp->obj.sclust = obj->c_scl;
|
||||
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;
|
||||
|
||||
res = dir_sdi(dp, dp->blk_ofs); /* Goto object's entry block */
|
||||
@@ -2326,19 +2327,22 @@ FRESULT dir_register ( /* FR_OK:succeeded, FR_DENIED:no free entry or too many S
|
||||
if (res != FR_OK) return res;
|
||||
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? */
|
||||
dp->obj.objsize += (DWORD)fs->csize * SS(fs); /* Increase the directory size by cluster size */
|
||||
res = fill_first_frag(&dp->obj); /* Fill first fragment on the FAT if needed */
|
||||
if (res != FR_OK) return res;
|
||||
res = fill_last_frag(&dp->obj, dp->clust, 0xFFFFFFFF); /* Fill last fragment on the FAT if needed */
|
||||
if (res != FR_OK) return res;
|
||||
res = load_obj_dir(&dj, &dp->obj); /* Load the object status */
|
||||
if (res != FR_OK) return res;
|
||||
st_qword(fs->dirbuf + XDIR_FileSize, dp->obj.objsize); /* Update the allocation status */
|
||||
st_qword(fs->dirbuf + XDIR_ValidFileSize, dp->obj.objsize);
|
||||
fs->dirbuf[XDIR_GenFlags] = dp->obj.stat | 1;
|
||||
res = store_xdir(&dj); /* Store the object status */
|
||||
if (dp->obj.stat & 4) { /* Has the directory been stretched? */
|
||||
dp->obj.stat &= ~4;
|
||||
res = fill_first_frag(&dp->obj); /* Fill the first fragment on the FAT if needed */
|
||||
if (res != FR_OK) return res;
|
||||
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 (dp->obj.sclust != 0) { /* Is it a sub directory? */
|
||||
res = load_obj_dir(&dj, &dp->obj); /* Load the object status */
|
||||
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_ValidFileSize, dp->obj.objsize);
|
||||
fs->dirbuf[XDIR_GenFlags] = dp->obj.stat | 1;
|
||||
res = store_xdir(&dj); /* Store the object status */
|
||||
if (res != FR_OK) return res;
|
||||
}
|
||||
}
|
||||
|
||||
create_xdir(fs->dirbuf, fs->lfnbuf); /* Create on-memory directory block to be written later */
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
_start:
|
||||
|
||||
; Jumps here before the fsOpenFileDirectly call
|
||||
_mountSd:
|
||||
b mountSd
|
||||
_mountArchive:
|
||||
b mountArchive
|
||||
.word 0xdead0000 ; Substituted opcode
|
||||
.word 0xdead0001 ; Branch to hooked function
|
||||
|
||||
@@ -25,41 +25,41 @@ _start:
|
||||
.word 0xdead0002 ; Substituted opcode
|
||||
.word 0xdead0003 ; Branch to hooked function
|
||||
|
||||
; Mounts SDMC and registers the archive as 'sdmc:'
|
||||
mountSd:
|
||||
; Mounts the archive and registers it as 'lf:'
|
||||
mountArchive:
|
||||
cmp r3, #3
|
||||
bne _mountSd+4
|
||||
bne _mountArchive + 4
|
||||
stmfd sp!, {r0-r4, lr}
|
||||
sub sp, sp, #4
|
||||
load r1, archive
|
||||
load r1, archiveId
|
||||
mov r0, sp
|
||||
load r4, fsMountArchive
|
||||
blx r4
|
||||
mov r3, #0
|
||||
mov r2, #0
|
||||
ldr r1, [sp]
|
||||
addr r0, sdmcArchiveName
|
||||
addr r0, archiveName
|
||||
load r4, fsRegisterArchive
|
||||
blx r4
|
||||
add sp, sp, #4
|
||||
ldmfd sp!, {r0-r4, lr}
|
||||
b _mountSd+4
|
||||
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 title folder on the sdcard.
|
||||
; If the file cannot be opened from the sdcard, we just open
|
||||
; 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}
|
||||
ldrb r12, [r1]
|
||||
cmp r12, #0x72 ; 'r', should include "rom:" and "rom2:"
|
||||
bne endRedir
|
||||
cmp r12, #0x72 ; 'r', should include "rom:", "rom2:" and "rex:"
|
||||
bne endRedir
|
||||
sub sp, sp, #0x400
|
||||
pathRedir:
|
||||
stmfd sp!, {r0-r3}
|
||||
add r0, sp, #0x10
|
||||
addr r3, sdmcCustomPath
|
||||
addr r3, customPath
|
||||
pathRedir_1:
|
||||
ldrb r2, [r3], #1
|
||||
strh r2, [r0], #2
|
||||
@@ -68,7 +68,7 @@ _start:
|
||||
sub r0, r0, #2
|
||||
pathRedir_2:
|
||||
ldrh r2, [r1], #2
|
||||
cmp r2, #0x3A ; ':'
|
||||
cmp r2, #0x3A ; ':'
|
||||
bne pathRedir_2
|
||||
pathRedir_3:
|
||||
ldrh r2, [r1], #2
|
||||
@@ -77,7 +77,7 @@ _start:
|
||||
bne pathRedir_3
|
||||
ldmfd sp!, {r0-r3}
|
||||
mov r1, sp
|
||||
bl _fsRedir+4
|
||||
bl _fsRedir + 4
|
||||
add sp, sp, #0x400
|
||||
cmp r0, #0
|
||||
|
||||
@@ -85,16 +85,14 @@ _start:
|
||||
ldmfd sp!, {r0-r12, lr}
|
||||
moveq r0, #0
|
||||
bxeq lr
|
||||
b _fsRedir+4
|
||||
b _fsRedir + 4
|
||||
|
||||
.pool
|
||||
.align 4
|
||||
sdmcArchiveName : .word 0xdead0007
|
||||
.dcb ":", 0
|
||||
.align 4
|
||||
fsMountArchive : .word 0xdead0005
|
||||
fsRegisterArchive : .word 0xdead0006
|
||||
archive : .word 0xdead0008
|
||||
sdmcCustomPath : .word 0xdead0004
|
||||
archiveName : .dcb "lf:", 0
|
||||
fsMountArchive : .word 0xdead0005
|
||||
fsRegisterArchive : .word 0xdead0006
|
||||
archiveId : .word 0xdead0007
|
||||
customPath : .word 0xdead0004
|
||||
|
||||
.close
|
||||
|
||||
@@ -163,19 +163,4 @@ Result FSLDR_OpenDirectory(Handle* out, FS_Archive archive, FS_Path path)
|
||||
if(out) *out = cmdbuf[3];
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -9,5 +9,4 @@ Result FSLDR_SetPriority(u32 priority);
|
||||
Result FSLDR_OpenFileDirectly(Handle* out, FS_ArchiveID archiveId, FS_Path archivePath, FS_Path filePath, u32 openFlags, u32 attributes);
|
||||
Result FSLDR_OpenArchive(FS_Archive* archive, FS_ArchiveID id, FS_Path path);
|
||||
Result FSLDR_CloseArchive(FS_Archive archive);
|
||||
Result FSLDR_OpenDirectory(Handle* out, FS_Archive archive, FS_Path path);
|
||||
Result FSDIRLDR_Close(Handle handle);
|
||||
Result FSLDR_OpenDirectory(Handle* out, FS_Archive archive, FS_Path path);
|
||||
@@ -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);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ static u32 patchMemory(u8 *start, u32 size, const void *pattern, u32 patSize, in
|
||||
{
|
||||
u32 i;
|
||||
|
||||
for(i = 0; i < count; i++)
|
||||
for(i = 0; !count || i < count; i++)
|
||||
{
|
||||
u8 *found = memsearch(start, pattern, size, patSize);
|
||||
|
||||
@@ -52,7 +52,7 @@ static u32 dirCheck(FS_ArchiveID archiveId, const char *path)
|
||||
else
|
||||
{
|
||||
ret = R_SUCCEEDED(FSLDR_OpenDirectory(&handle, archive, dirPath)) ? 0 : 2;
|
||||
if(ret) FSDIRLDR_Close(handle);
|
||||
if(!ret) FSDIR_Close(handle);
|
||||
FSLDR_CloseArchive(archive);
|
||||
}
|
||||
|
||||
@@ -87,8 +87,7 @@ static inline void loadCFWInfo(void)
|
||||
svcGetCFWInfo(&info);
|
||||
|
||||
IFile file;
|
||||
if(LOADERFLAG(ISSAFEMODE) && R_SUCCEEDED(fileOpen(&file, ARCHIVE_SDMC, "/", FS_OPEN_READ))) //Init SD card if SAFE_MODE is being booted
|
||||
IFile_Close(&file);
|
||||
if(LOADERFLAG(ISSAFEMODE)) fileOpen(&file, ARCHIVE_SDMC, "/", FS_OPEN_READ); //Init SD card if SAFE_MODE is being booted
|
||||
|
||||
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)
|
||||
{
|
||||
static const u32 CFGU_GetConfigInfoBlk2_endPattern[] = {0xE8BD8010, 0x00010082};
|
||||
|
||||
//There might be multiple implementations of GetConfigInfoBlk2 but let's search for the one we want
|
||||
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++)
|
||||
if(possible[i] == cmp[2])
|
||||
{
|
||||
*CFGUHandleOffset = cmp[2];
|
||||
|
||||
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)
|
||||
{
|
||||
static const u32 cfgSecureInfoGetRegionCmdPattern[] = {0xEE1D0F70, 0xE3A00802};
|
||||
|
||||
u32 *cmp = (u32 *)cmdPos;
|
||||
|
||||
if(*cmp != cfgSecureInfoGetRegionCmdPattern[1]) continue;
|
||||
if(*cmp != 0xE3A00802) continue;
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
@@ -289,45 +285,69 @@ static u32 findFunctionStart(u8* code, u32 pos)
|
||||
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 svcConnectToPort = 0xFFFFFFFF;
|
||||
u32 found = 0,
|
||||
*temp = NULL;
|
||||
|
||||
for(u32 addr = 0; !found && addr <= size - 4; addr += 4)
|
||||
for(u32 addr = 0; addr <= size - 4; addr += 4)
|
||||
{
|
||||
if(*fsMountArchive == 0xFFFFFFFF)
|
||||
switch(*(u32 *)(code + addr))
|
||||
{
|
||||
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);
|
||||
}
|
||||
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(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(temp != NULL)
|
||||
{
|
||||
*temp = 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(*temp != 0xFFFFFFFF)
|
||||
{
|
||||
found++;
|
||||
if(found == 4) break;
|
||||
}
|
||||
|
||||
if(*fsOpenFileDirectly == 0xFFFFFFFF && *(u32 *)(code + addr) == 0x08030204)
|
||||
*fsOpenFileDirectly = findFunctionStart(code, addr);
|
||||
|
||||
if(addr >= 4 && svcConnectToPort == 0xFFFFFFFF && *(u32 *)(code + addr) == 0xEF00002D)
|
||||
svcConnectToPort = addr - 4;
|
||||
|
||||
if(svcConnectToPort != 0xFFFFFFFF && *fsMountArchive != 0xFFFFFFFF && *fsRegisterArchive != 0xFFFFFFFF && *fsTryOpenFile != 0xFFFFFFFF && *fsOpenFileDirectly != 0xFFFFFFFF) found = true;
|
||||
temp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if(found)
|
||||
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;
|
||||
|
||||
for(u32 addr = 4; svcConnectToPort == 0xFFFFFFFF && addr <= size - 4; addr += 4)
|
||||
{
|
||||
if(*(u32 *)(code + addr) == 0xEF00002D)
|
||||
svcConnectToPort = addr - 4;
|
||||
}
|
||||
|
||||
if(svcConnectToPort != 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;
|
||||
}
|
||||
|
||||
*throwFatalError = func;
|
||||
if(func != 0xFFFFFFFF)
|
||||
{
|
||||
*payloadOffset = func;
|
||||
|
||||
if(func != 0xFFFFFFFF) return true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
u32 i,
|
||||
j;
|
||||
static const char *regions[] = {"JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"},
|
||||
*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)
|
||||
{
|
||||
*regionId = (u8)i;
|
||||
@@ -472,26 +495,26 @@ 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"};
|
||||
|
||||
if(memcmp(buf + 4, languages[j], 2) == 0)
|
||||
for(i = 0; i < sizeof(languages) / sizeof(char *); i++)
|
||||
{
|
||||
*languageId = (u8)j;
|
||||
break;
|
||||
if(memcmp(buf + 4, languages[i], 2) == 0)
|
||||
{
|
||||
*languageId = (u8)i;
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = i != 7 && j != 12;
|
||||
|
||||
exit:
|
||||
IFile_Close(&file);
|
||||
|
||||
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"
|
||||
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";
|
||||
progIdToStr(path + 28, progId);
|
||||
|
||||
u32 archive = checkLumaDir(path);
|
||||
u32 archiveId = checkLumaDir(path);
|
||||
|
||||
if(!archive) return true;
|
||||
|
||||
const char *mount = archive == ARCHIVE_SDMC ? "sdmc:" : "nand:";
|
||||
if(!archiveId) return true;
|
||||
|
||||
u32 fsMountArchive = 0xFFFFFFFF,
|
||||
fsRegisterArchive = 0xFFFFFFFF,
|
||||
fsTryOpenFile = 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
|
||||
u8 *payload = code + throwFatalError;
|
||||
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])
|
||||
switch(payload32[i])
|
||||
{
|
||||
case 0xdead0000:
|
||||
payload32[i] = *(u32 *)(code + fsOpenFileDirectly);
|
||||
break;
|
||||
case 0xdead0001:
|
||||
payload32[i] = MAKE_BRANCH(throwFatalError + i * 4, fsOpenFileDirectly + 4);
|
||||
payload32[i] = MAKE_BRANCH(payloadOffset + i * 4, fsOpenFileDirectly + 4);
|
||||
break;
|
||||
case 0xdead0002:
|
||||
payload32[i] = *(u32 *)(code + fsTryOpenFile);
|
||||
break;
|
||||
case 0xdead0003:
|
||||
payload32[i] = MAKE_BRANCH(throwFatalError + i * 4, fsTryOpenFile + 4);
|
||||
payload32[i] = MAKE_BRANCH(payloadOffset + i * 4, fsTryOpenFile + 4);
|
||||
break;
|
||||
case 0xdead0004:
|
||||
memcpy(payload32 + i, mount, 5);
|
||||
memcpy((u8 *)(payload32 + i) + 5, path, sizeof(path));
|
||||
memcpy(payload32 + i, "lf:", 3);
|
||||
memcpy((u8 *)(payload32 + i) + 3, path, sizeof(path));
|
||||
break;
|
||||
case 0xdead0005:
|
||||
payload32[i] = 0x100000 + fsMountArchive;
|
||||
@@ -546,22 +583,19 @@ static inline bool patchLayeredFs(u64 progId, u8* code, u32 size)
|
||||
payload32[i] = 0x100000 + fsRegisterArchive;
|
||||
break;
|
||||
case 0xdead0007:
|
||||
memcpy(payload32 + i, mount, 4);
|
||||
break;
|
||||
case 0xdead0008:
|
||||
payload32[i] = archive;
|
||||
payload32[i] = archiveId;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Place the hooks
|
||||
*(u32 *)(code + fsOpenFileDirectly) = MAKE_BRANCH(fsOpenFileDirectly, throwFatalError);
|
||||
*(u32 *)(code + fsTryOpenFile) = MAKE_BRANCH(fsTryOpenFile, throwFatalError + 12);
|
||||
*(u32 *)(code + fsOpenFileDirectly) = MAKE_BRANCH(fsOpenFileDirectly, payloadOffset);
|
||||
*(u32 *)(code + fsTryOpenFile) = MAKE_BRANCH(fsTryOpenFile, payloadOffset + 12);
|
||||
|
||||
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();
|
||||
|
||||
@@ -582,7 +616,7 @@ void patchCode(u64 progId, u16 progVer, u8 *code, u32 size)
|
||||
};
|
||||
|
||||
//Patch SMDH region checks
|
||||
if(!patchMemory(code, size,
|
||||
if(!patchMemory(code, textSize,
|
||||
pattern,
|
||||
sizeof(pattern), -31,
|
||||
patch,
|
||||
@@ -598,7 +632,7 @@ void patchCode(u64 progId, u16 progVer, u8 *code, u32 size)
|
||||
|
||||
u8 mostRecentFpdVer = 10;
|
||||
|
||||
u8 *off = memsearch(code, pattern, size, sizeof(pattern));
|
||||
u8 *off = memsearch(code, pattern, textSize, sizeof(pattern));
|
||||
|
||||
if(off == NULL) goto error;
|
||||
|
||||
@@ -649,7 +683,7 @@ void patchCode(u64 progId, u16 progVer, u8 *code, u32 size)
|
||||
}
|
||||
|
||||
//Patch Ver. string
|
||||
if(!patchMemory(code, size,
|
||||
if(!patchMemory(code, textSize,
|
||||
pattern,
|
||||
sizeof(pattern) - 2, 0,
|
||||
patch,
|
||||
@@ -669,7 +703,7 @@ void patchCode(u64 progId, u16 progVer, u8 *code, u32 size)
|
||||
};
|
||||
|
||||
//Disable updates from foreign carts (makes carts region-free)
|
||||
u32 ret = patchMemory(code, size,
|
||||
u32 ret = patchMemory(code, textSize,
|
||||
pattern,
|
||||
sizeof(pattern), 0,
|
||||
patch,
|
||||
@@ -689,7 +723,7 @@ void patchCode(u64 progId, u16 progVer, u8 *code, u32 size)
|
||||
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;
|
||||
|
||||
@@ -712,7 +746,7 @@ void patchCode(u64 progId, u16 progVer, u8 *code, u32 size)
|
||||
};
|
||||
|
||||
//Disable SecureInfo signature check
|
||||
if(!patchMemory(code, size,
|
||||
if(!patchMemory(code, textSize,
|
||||
pattern,
|
||||
sizeof(pattern), 0,
|
||||
patch,
|
||||
@@ -725,7 +759,7 @@ void patchCode(u64 progId, u16 progVer, u8 *code, u32 size)
|
||||
patch[] = u"C";
|
||||
|
||||
//Use SecureInfo_C
|
||||
if(patchMemory(code, size,
|
||||
if(patchMemory(code + textSize, roSize,
|
||||
pattern,
|
||||
sizeof(pattern) - 2, 22,
|
||||
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)
|
||||
if(!patchMemory(code, size,
|
||||
if(!patchMemory(code, textSize,
|
||||
pattern,
|
||||
sizeof(pattern), -9,
|
||||
patch,
|
||||
sizeof(patch), 1
|
||||
) ||
|
||||
!patchMemory(code, size,
|
||||
!patchMemory(code, textSize,
|
||||
pattern2,
|
||||
sizeof(pattern2), 1,
|
||||
patch,
|
||||
sizeof(patch), 1
|
||||
) ||
|
||||
!patchMemory(code, size,
|
||||
!patchMemory(code, textSize,
|
||||
pattern3,
|
||||
sizeof(pattern3), -2,
|
||||
patch,
|
||||
@@ -783,13 +817,13 @@ void patchCode(u64 progId, u16 progVer, u8 *code, u32 size)
|
||||
};
|
||||
|
||||
//Patch UNITINFO checks to make ErrDisp more verbose
|
||||
if(!patchMemory(code, size,
|
||||
if(!patchMemory(code, textSize,
|
||||
pattern,
|
||||
sizeof(pattern), -1,
|
||||
patch,
|
||||
sizeof(patch), 1
|
||||
) ||
|
||||
patchMemory(code, size,
|
||||
patchMemory(code, textSize,
|
||||
pattern2,
|
||||
sizeof(pattern2), 0,
|
||||
patch,
|
||||
@@ -807,7 +841,7 @@ void patchCode(u64 progId, u16 progVer, u8 *code, u32 size)
|
||||
};
|
||||
|
||||
//Patch DLP region checks
|
||||
if(!patchMemory(code, size,
|
||||
if(!patchMemory(code, textSize,
|
||||
pattern,
|
||||
sizeof(pattern), 0,
|
||||
patch,
|
||||
@@ -823,17 +857,17 @@ void patchCode(u64 progId, u16 progVer, u8 *code, u32 size)
|
||||
if(!loadTitleCodeSection(progId, code, size) ||
|
||||
!applyCodeIpsPatch(progId, code, size) ||
|
||||
!loadTitleLocaleConfig(progId, ®ionId, &languageId) ||
|
||||
!patchLayeredFs(progId, code, size)) goto error;
|
||||
!patchLayeredFs(progId, code, size, textSize)) goto error;
|
||||
|
||||
if(regionId != 0xFF)
|
||||
{
|
||||
u32 CFGUHandleOffset;
|
||||
u8 *CFGU_GetConfigInfoBlk2_endPos = getCfgOffsets(code, size, &CFGUHandleOffset);
|
||||
u8 *CFGU_GetConfigInfoBlk2_endPos = getCfgOffsets(code, textSize, &CFGUHandleOffset);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,4 +44,4 @@ enum flags
|
||||
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);
|
||||
|
||||
@@ -9,7 +9,6 @@ SECTIONS
|
||||
.text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); }
|
||||
.rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); }
|
||||
.data : ALIGN(4) { *(.data*); . = ALIGN(4); }
|
||||
|
||||
.bss : ALIGN(8) { __bss_start = .; *(.bss* COMMON); . = ALIGN(8); __bss_end = .; }
|
||||
|
||||
. = ALIGN(4);
|
||||
|
||||
@@ -5,6 +5,7 @@ ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x24FFFE00;
|
||||
|
||||
.text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); }
|
||||
.rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); }
|
||||
.data : ALIGN(4) { *(.data*); . = ALIGN(8); *(.bss* COMMON); . = ALIGN(8); }
|
||||
|
||||
@@ -182,11 +182,11 @@ void configMenu(bool isSdMode, bool oldPinStatus, u32 oldPinMode)
|
||||
"The service and archive patches\n"
|
||||
"don't work on New 3DS FIRMs between\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!",
|
||||
|
||||
"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"
|
||||
"and retail CIAs, but allows installing\n"
|
||||
"and booting some developer software).\n\n"
|
||||
|
||||
@@ -155,8 +155,14 @@ void detectAndProcessExceptionDumps(void)
|
||||
|
||||
if(dumpHeader->processor == 11 && dumpHeader->additionalDataSize != 0)
|
||||
{
|
||||
char processName[] = "Current process: ";
|
||||
memcpy(processName + sizeof(processName) - 9, (void *)additionalData, 8);
|
||||
char processName[45] = "Current process: ";
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -2050,7 +2050,8 @@ FRESULT load_obj_dir (
|
||||
dp->obj.fs = obj->fs;
|
||||
dp->obj.sclust = obj->c_scl;
|
||||
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;
|
||||
|
||||
res = dir_sdi(dp, dp->blk_ofs); /* Goto object's entry block */
|
||||
@@ -2326,19 +2327,22 @@ FRESULT dir_register ( /* FR_OK:succeeded, FR_DENIED:no free entry or too many S
|
||||
if (res != FR_OK) return res;
|
||||
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? */
|
||||
dp->obj.objsize += (DWORD)fs->csize * SS(fs); /* Increase the directory size by cluster size */
|
||||
res = fill_first_frag(&dp->obj); /* Fill first fragment on the FAT if needed */
|
||||
if (res != FR_OK) return res;
|
||||
res = fill_last_frag(&dp->obj, dp->clust, 0xFFFFFFFF); /* Fill last fragment on the FAT if needed */
|
||||
if (res != FR_OK) return res;
|
||||
res = load_obj_dir(&dj, &dp->obj); /* Load the object status */
|
||||
if (res != FR_OK) return res;
|
||||
st_qword(fs->dirbuf + XDIR_FileSize, dp->obj.objsize); /* Update the allocation status */
|
||||
st_qword(fs->dirbuf + XDIR_ValidFileSize, dp->obj.objsize);
|
||||
fs->dirbuf[XDIR_GenFlags] = dp->obj.stat | 1;
|
||||
res = store_xdir(&dj); /* Store the object status */
|
||||
if (dp->obj.stat & 4) { /* Has the directory been stretched? */
|
||||
dp->obj.stat &= ~4;
|
||||
res = fill_first_frag(&dp->obj); /* Fill the first fragment on the FAT if needed */
|
||||
if (res != FR_OK) return res;
|
||||
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 (dp->obj.sclust != 0) { /* Is it a sub directory? */
|
||||
res = load_obj_dir(&dj, &dp->obj); /* Load the object status */
|
||||
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_ValidFileSize, dp->obj.objsize);
|
||||
fs->dirbuf[XDIR_GenFlags] = dp->obj.stat | 1;
|
||||
res = store_xdir(&dj); /* Store the object status */
|
||||
if (res != FR_OK) return res;
|
||||
}
|
||||
}
|
||||
|
||||
create_xdir(fs->dirbuf, fs->lfnbuf); /* Create on-memory directory block to be written later */
|
||||
|
||||
@@ -240,7 +240,8 @@ boot:
|
||||
bool loadFromStorage = CONFIG(LOADEXTFIRMSANDMODULES);
|
||||
u32 firmVersion = loadFirm(&firmType, firmSource, loadFromStorage, isSafeMode);
|
||||
|
||||
bool doUnitinfoPatch = CONFIG(PATCHUNITINFO), enableExceptionHandlers = CONFIG(ENABLEEXCEPTIONHANDLERS);
|
||||
bool doUnitinfoPatch = CONFIG(PATCHUNITINFO),
|
||||
enableExceptionHandlers = CONFIG(ENABLEEXCEPTIONHANDLERS);
|
||||
u32 res;
|
||||
switch(firmType)
|
||||
{
|
||||
|
||||
@@ -47,9 +47,6 @@ static const u32 brightness[4] = {0x5F, 0x4C, 0x39, 0x26};
|
||||
|
||||
void __attribute__((naked)) arm11Stub(void)
|
||||
{
|
||||
//Disable interrupts
|
||||
__asm(".word 0xF10C01C0");
|
||||
|
||||
WAIT_FOR_ARM9();
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
#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 SCREEN_TOP_WIDTH 400
|
||||
|
||||
@@ -91,6 +91,7 @@ start:
|
||||
mov r1, #0x340
|
||||
str r1, [r0]
|
||||
|
||||
@ Clear BSS
|
||||
ldr r0, =__bss_start
|
||||
mov r1, #0
|
||||
ldr r2, =__bss_end
|
||||
|
||||
Reference in New Issue
Block a user