slightly optimise hbl by reading nro in a single pass and remove dynamic memory.

This commit is contained in:
ITotalJustice
2025-06-25 17:37:28 +01:00
parent 6f8300fb32
commit 168f4b0303

View File

@@ -1,10 +1,9 @@
#include <switch.h> #include <switch.h>
#include <string.h> #include <string.h>
#include <stdlib.h>
#define EXIT_DETECTION_STR "if this isn't replaced i will exit :)" #define EXIT_DETECTION_STR "if this isn't replaced i will exit :)"
// this uses 3-4KiB more than nx-hbloader. // this uses 16KiB less than nx-hbloader.
static char g_argv[2048] = {0}; static char g_argv[2048] = {0};
// this can and will be modified by libnx if launched nro calls envSetNextLoad(). // this can and will be modified by libnx if launched nro calls envSetNextLoad().
static char g_nextArgv[2048] = {0}; static char g_nextArgv[2048] = {0};
@@ -47,7 +46,7 @@ static void fix_nro_path(char* path) {
// Credit to behemoth // Credit to behemoth
// SOURCE: https://github.com/HookedBehemoth/nx-hbloader/commit/7f8000a41bc5e8a6ad96a097ef56634cfd2fabcb // SOURCE: https://github.com/HookedBehemoth/nx-hbloader/commit/7f8000a41bc5e8a6ad96a097ef56634cfd2fabcb
static NX_NORETURN void selfExit(void) { static void NX_NORETURN selfExit(void) {
Result rc = smInitialize(); Result rc = smInitialize();
if (R_FAILED(rc)) if (R_FAILED(rc))
goto fail0; goto fail0;
@@ -162,7 +161,8 @@ static void getOwnProcessHandle(void) {
diagAbortWithResult(MAKERESULT(Module_HomebrewLoader, 12)); diagAbortWithResult(MAKERESULT(Module_HomebrewLoader, 12));
Thread t; Thread t;
rc = threadCreate(&t, &procHandleReceiveThread, (void*)(uintptr_t)server_handle, NULL, 0x1000, 0x20, 0); u8* stack = g_heapAddr;
rc = threadCreate(&t, &procHandleReceiveThread, (void*)(uintptr_t)server_handle, stack, 0x1000, 0x20, 0);
if (R_FAILED(rc)) if (R_FAILED(rc))
diagAbortWithResult(MAKERESULT(Module_HomebrewLoader, 10)); diagAbortWithResult(MAKERESULT(Module_HomebrewLoader, 10));
@@ -290,10 +290,10 @@ void NX_NORETURN loadNro(void) {
diagAbortWithResult(rc); diagAbortWithResult(rc);
} }
u8* romfs_dirs = malloc(romfs_header.dirTableSize); // should be 1 entry ("/") u8 romfs_dirs[1024 * 2]; // should be 1 entry ("/")
u8* romfs_files = malloc(romfs_header.fileTableSize); // should be 2 entries (argv and nro) u8 romfs_files[1024 * 4]; // should be 2 entries (argv and nro)
if (!romfs_dirs || !romfs_files) { if (romfs_header.dirTableSize > sizeof(romfs_dirs) || romfs_header.fileTableSize > sizeof(romfs_files)) {
diagAbortWithResult(MAKERESULT(Module_HomebrewLoader, LibnxError_OutOfMemory)); diagAbortWithResult(MAKERESULT(Module_HomebrewLoader, LibnxError_OutOfMemory));
} }
@@ -317,8 +317,6 @@ void NX_NORETURN loadNro(void) {
diagAbortWithResult(rc); diagAbortWithResult(rc);
} }
free(romfs_dirs);
free(romfs_files);
fsStorageClose(&s); fsStorageClose(&s);
strcpy(g_defaultNroPath, g_nextNroPath); strcpy(g_defaultNroPath, g_nextNroPath);
@@ -337,40 +335,24 @@ void NX_NORETURN loadNro(void) {
} }
uint8_t *nrobuf = (uint8_t*) g_heapAddr; uint8_t *nrobuf = (uint8_t*) g_heapAddr;
NroStart* start = (NroStart*) (nrobuf + 0); NroStart* start = (NroStart*) (nrobuf + 0);
header = (NroHeader*) (nrobuf + sizeof(NroStart)); header = (NroHeader*) (nrobuf + sizeof(NroStart));
uint8_t* rest = (uint8_t*) (nrobuf + sizeof(NroStart) + sizeof(NroHeader));
FsFileSystem fs; FsFileSystem fs;
FsFile f;
u64 bytes_read = 0;
s64 offset = 0;
if (R_FAILED(rc = fsOpenSdCardFileSystem(&fs))) { if (R_FAILED(rc = fsOpenSdCardFileSystem(&fs))) {
diagAbortWithResult(rc); diagAbortWithResult(rc);
} }
// don't fatal if we don't find the nro, exit to menu // don't fatal if we don't find the nro, exit to menu
FsFile f;
if (R_FAILED(rc = fsFsOpenFile(&fs, fixedNextNroPath, FsOpenMode_Read, &f))) { if (R_FAILED(rc = fsFsOpenFile(&fs, fixedNextNroPath, FsOpenMode_Read, &f))) {
diagAbortWithResult(rc); diagAbortWithResult(rc);
} }
if (R_FAILED(rc = fsFileRead(&f, offset, start, sizeof(*start), FsReadOption_None, &bytes_read)) || u64 bytes_read;
bytes_read != sizeof(*start)) { if (R_FAILED(rc = fsFileRead(&f, 0, start, g_heapSize, FsReadOption_None, &bytes_read)) ||
diagAbortWithResult(rc); header->magic != NROHEADER_MAGIC ||
} bytes_read < sizeof(*start) + sizeof(*header) + header->size) {
offset += sizeof(*start);
if (R_FAILED(rc = fsFileRead(&f, offset, header, sizeof(*header), FsReadOption_None, &bytes_read)) ||
bytes_read != sizeof(*header) || header->magic != NROHEADER_MAGIC) {
diagAbortWithResult(rc);
}
offset += sizeof(*header);
const size_t rest_size = header->size - (sizeof(NroStart) + sizeof(NroHeader));
if (R_FAILED(rc = fsFileRead(&f, offset, rest, rest_size, FsReadOption_None, &bytes_read)) ||
bytes_read != rest_size) {
diagAbortWithResult(rc); diagAbortWithResult(rc);
} }
@@ -513,13 +495,11 @@ bool __nx_fsdev_support_cwd = false;
// u32 __nx_applet_exit_mode = 0; // u32 __nx_applet_exit_mode = 0;
void __libnx_initheap(void) { void __libnx_initheap(void) {
static char g_innerheap[0x4000];
extern char* fake_heap_start; extern char* fake_heap_start;
extern char* fake_heap_end; extern char* fake_heap_end;
fake_heap_start = &g_innerheap[0]; fake_heap_start = NULL;
fake_heap_end = &g_innerheap[sizeof(g_innerheap)]; fake_heap_end = NULL;
} }
void __appInit(void) { void __appInit(void) {
@@ -557,7 +537,20 @@ void __appExit(void) {
} }
void __wrap_exit(void) {
// exit() effectively never gets called, so let's stub it out. // exit() effectively never gets called, so let's stub it out.
void __wrap_exit(void) {
diagAbortWithResult(MAKERESULT(Module_HomebrewLoader, 39)); diagAbortWithResult(MAKERESULT(Module_HomebrewLoader, 39));
} }
// stub alloc calls as they're not used (saves 4KiB).
void* __libnx_alloc(size_t size) {
diagAbortWithResult(MAKERESULT(Module_HomebrewLoader, 40));
}
void* __libnx_aligned_alloc(size_t alignment, size_t size) {
diagAbortWithResult(MAKERESULT(Module_HomebrewLoader, 41));
}
void __libnx_free(void* p) {
diagAbortWithResult(MAKERESULT(Module_HomebrewLoader, 43));
}