#include <3ds.h> #include #include <3ds/services/apt.h> #include #include #include #include #include #include "ctr_debug.h" #define CTR_APPMEMALLOC_PTR ((u32*)0x1FF80040) /* Global variables */ u32 __stacksize__ = 0x00400000; u32 __linear_heap_size = 0x01000000; u32 __heap_size; u32 __linear_heap; u32 __heapBase; u32 __stack_bottom; u32 __stack_size_extra; u32 __saved_stack; extern u32 __linear_heap_size_hbl; extern u32 __heap_size_hbl; extern void* __service_ptr; extern void (*__system_retAddr)(void); /* Forward declarations */ void envDestroyHandles(void); void __appExit(void); void __libc_fini_array(void); void __appInit(void); void __libc_init_array(void); void __system_initSyscalls(void); void __system_initArgv(void); void __ctru_exit(int rc); int __libctru_gtod(struct _reent* ptr, struct timeval* tp, struct timezone* tz); void (*__system_retAddr)(void); Result __sync_init(void) __attribute__((weak)); void __system_allocateHeaps(void) { extern char* fake_heap_end; u32 tmp = 0; MemInfo stack_memInfo; PageInfo stack_pageInfo; register u32 sp_val __asm__("sp"); svcQueryMemory(&stack_memInfo, &stack_pageInfo, sp_val); __stacksize__ += 0xFFF; __stacksize__ &= ~0xFFF; __stack_size_extra = __stacksize__ > stack_memInfo.size ? __stacksize__ - stack_memInfo.size : 0; __stack_bottom = stack_memInfo.base_addr - __stack_size_extra; if (__stack_size_extra) { svcControlMemory(&tmp, __stack_bottom, 0x0, __stack_size_extra, MEMOP_ALLOC, MEMPERM_READ | MEMPERM_WRITE); memset((void*)__stack_bottom, 0xFC, __stack_size_extra); } /* setup the application heap */ __heapBase = 0x08000000; __heap_size = 0; /* Allocate the linear heap */ svcControlMemory(&__linear_heap, 0x0, 0x0, __linear_heap_size, MEMOP_ALLOC_LINEAR, MEMPERM_READ | MEMPERM_WRITE); #ifdef USE_CTRULIB_2 /* Mappable allocator init */ mappableInit(OS_MAP_AREA_BEGIN, OS_MAP_AREA_END); #endif /* Set up newlib heap */ fake_heap_end = (char*)0x13F00000; } void __attribute__((weak)) __libctru_init(void (*retAddr)(void)) { /* Store the return address */ __system_retAddr = NULL; if (envIsHomebrew()) __system_retAddr = retAddr; /* Initialize the synchronization subsystem */ __sync_init(); /* Initialize newlib support system calls */ __system_initSyscalls(); /* Allocate application and linear heaps */ __system_allocateHeaps(); } Result __sync_fini(void) __attribute__((weak)); extern char** __system_argv; void __attribute__((noreturn)) __libctru_exit(int rc) { u32 tmp = 0; int size = 0; if (__system_argv) free(__system_argv); /* Unmap the linear heap */ /* Do this 1MB at a time to avoid kernel panics, see https://github.com/LumaTeam/Luma3DS/issues/1504 */ while (__linear_heap_size > 0) { size = __linear_heap_size < 0x100000 ? __linear_heap_size : 0x100000; __linear_heap_size -= size; svcControlMemory(&tmp, __linear_heap + __linear_heap_size, 0x0, size, MEMOP_FREE, 0x0); } /* Unmap the application heap */ /* Do this 1MB at a time to avoid kernel panics */ while (__heap_size > 0) { size = __heap_size < 0x100000 ? __heap_size : 0x100000; __heap_size -= size; svcControlMemory(&tmp, __heapBase + __heap_size, 0x0, size, MEMOP_FREE, 0x0); } if (__stack_size_extra) svcControlMemory(&tmp, __stack_bottom, 0x0, __stack_size_extra, MEMOP_FREE, 0x0); /* Close some handles */ envDestroyHandles(); if (__sync_fini) __sync_fini(); /* Jump to the loader if it provided a callback */ if (__system_retAddr) __system_retAddr(); /* Since above did not jump, end this process */ svcExitProcess(); } #include <3ds/types.h> #include /* System globals we define here */ int __system_argc; char** __system_argv; extern const char* __system_arglist; // sha-256 of "ARGV" char __argv_hmac[0x20] = {0x1d, 0x78, 0xff, 0xb9, 0xc5, 0xbc, 0x78, 0xb7, 0xac, 0x29, 0x1d, 0x3e, 0x16, 0xd0, 0xcf, 0x53, 0xef, 0x12, 0x58, 0x83, 0xb6, 0x9e, 0x2f, 0x79, 0x47, 0xf9, 0x35, 0x61, 0xeb, 0x50, 0xd7, 0x67}; Result APT_ReceiveDeliverArg_(void* param, size_t param_size, void* hmac, size_t hmac_size, u64* source_pid, bool* received) { u32 cmdbuf[16]; u32 saved_threadstorage[4]; u32 *staticbufs; Result ret; cmdbuf[0] = IPC_MakeHeader(0x35,2,0); cmdbuf[1] = param_size; cmdbuf[2] = hmac_size; staticbufs = getThreadStaticBuffers(); saved_threadstorage[0] = staticbufs[0]; saved_threadstorage[1] = staticbufs[1]; saved_threadstorage[2] = staticbufs[2]; saved_threadstorage[3] = staticbufs[3]; staticbufs[0] = IPC_Desc_StaticBuffer(param_size, 0); staticbufs[1] = (u32)param; staticbufs[2] = IPC_Desc_StaticBuffer(hmac_size, 2); staticbufs[3] = (u32)hmac; ret = aptSendCommand(cmdbuf); staticbufs[0] = saved_threadstorage[0]; staticbufs[1] = saved_threadstorage[1]; staticbufs[2] = saved_threadstorage[2]; staticbufs[3] = saved_threadstorage[3]; if(R_FAILED(ret)) return ret; if(source_pid) *source_pid = ((u64*)cmdbuf)[1]; if(received) *received = ((bool*)cmdbuf)[16]; return cmdbuf[1]; } void __system_initArgv(void) { int i; struct { u32 argc; char args[]; }*arg_struct = (void*)__system_arglist; static u8 param[0x300]; u8 hmac[0x20]; bool received; if(!__service_ptr && R_SUCCEEDED(APT_ReceiveDeliverArg_(¶m, sizeof(param), hmac, sizeof(hmac), NULL, &received)) && received && !memcmp(hmac, __argv_hmac, sizeof(__argv_hmac))) arg_struct = (void*)param; __system_argc = 0; if (arg_struct) __system_argc = arg_struct->argc; if (__system_argc) { __system_argv = (char**)malloc( (__system_argc + 1) * sizeof(char**)); __system_argv[0] = arg_struct->args; for (i = 1; i < __system_argc; i++) __system_argv[i] = __system_argv[i - 1] + strlen(__system_argv[i - 1]) + 1; i = __system_argc - 1; __system_argc = 1; while (i) { if(__system_argv[i] && isalnum(__system_argv[i][0]) && strncmp(__system_argv[i], "3dslink:/", 9)) { __system_argv[1] = __system_argv[i]; __system_argc = 2; break; } i--; } } else { __system_argc = 1; __system_argv = (char**) malloc(sizeof(char**) * 2); __system_argv[0] = "sdmc:/retroarch/retroarch"; } __system_argv[__system_argc] = NULL; } void initSystem(void (*retAddr)(void)) { register u32 sp_val __asm__("sp"); __saved_stack = sp_val; __libctru_init(retAddr); __appInit(); __system_initArgv(); __libc_init_array(); } void __attribute__((noreturn)) __ctru_exit(int rc) { __libc_fini_array(); __appExit(); asm ("mov sp, %[saved_stack] \n\t" : : [saved_stack] "r" (__saved_stack) : "sp"); __libctru_exit(rc); } typedef union { struct { unsigned description : 10; unsigned module : 8; unsigned : 3; unsigned summary : 6; unsigned level : 5; }; Result val; } ctr_result_value; void dump_result_value(Result val) { ctr_result_value res; res.val = val; printf("result : 0x%08X\n", val); printf("description : %u\n", res.description); printf("module : %u\n", res.module); printf("summary : %u\n", res.summary); printf("level : %u\n", res.level); } void wait_for_input(void) { printf("\n\nPress Start.\n\n"); fflush(stdout); while (aptMainLoop()) { u32 kDown; hidScanInput(); kDown = hidKeysDown(); if (kDown & KEY_START) break; if (kDown & KEY_SELECT) exit(0); svcSleepThread(1000000); } } void error_and_quit(const char* errorStr) { errorConf error; #ifdef IS_SALAMANDER gfxInitDefault(); #endif errorInit(&error, ERROR_TEXT, CFG_LANGUAGE_EN); errorText(&error, errorStr); errorDisp(&error); gfxExit(); exit(0); } long sysconf(int name) { switch (name) { case _SC_NPROCESSORS_ONLN: return 2; } return -1; }