diff --git a/libctru/Makefile b/libctru/Makefile index 37ed8e8..5ee809b 100644 --- a/libctru/Makefile +++ b/libctru/Makefile @@ -29,7 +29,9 @@ SOURCES := source \ source/gpu \ source/services \ source/services/soc \ - source/util + source/util \ + source/system + DATA := data INCLUDES := include diff --git a/libctru/source/initSystem.c b/libctru/source/initSystem.c deleted file mode 100644 index 7d6c222..0000000 --- a/libctru/source/initSystem.c +++ /dev/null @@ -1,119 +0,0 @@ -#include -#include -#include <3ds/types.h> -#include <3ds/svc.h> - -// System globals we define here -int __system_argc; -char** __system_argv; -void (*__system_retAddr)(void); -u32 __linear_heap; - -// Data from _prm structure -extern void* __service_ptr; // used to detect if we're run from a homebrew launcher -extern u32 __heap_size, __linear_heap_size; -extern const char* __system_arglist; - -// newlib definitions we need -void __libc_init_array(void); -void __libc_fini_array(void); -extern char* fake_heap_start; -extern char* fake_heap_end; - -static void initArgv(); -static u32 heapBase; - -void __destroy_handle_list(void); - -void __attribute__((noreturn)) __ctru_exit(int rc) -{ - u32 tmp=0; - - // Run the global destructors - __libc_fini_array(); - - // TODO: APT exit goes here - - // Unmap the linear heap - svcControlMemory(&tmp, __linear_heap, 0x0, __linear_heap_size, MEMOP_FREE, 0x0); - - // Unmap the application heap - svcControlMemory(&tmp, heapBase, 0x0, __heap_size, MEMOP_FREE, 0x0); - - // Close some handles - __destroy_handle_list(); - - // Jump to the loader if it provided a callback - if (__system_retAddr) - __system_retAddr(); - - // Since above did not jump, end this process - svcExitProcess(); -} - -void initSystem(void (*retAddr)(void)) -{ - u32 tmp=0; - - // Register newlib exit() syscall - __syscalls.exit = __ctru_exit; - __system_retAddr = __service_ptr ? retAddr : NULL; - - // Allocate the application heap - heapBase = 0x08000000; - svcControlMemory(&tmp, heapBase, 0x0, __heap_size, MEMOP_ALLOC, 0x3); - - // Allocate the linear heap - svcControlMemory(&__linear_heap, 0x0, 0x0, __linear_heap_size, MEMOP_ALLOC_LINEAR, 0x3); - - // Set up newlib heap - fake_heap_start = (char*)heapBase; - fake_heap_end = fake_heap_start + __heap_size; - - // Build argc/argv if present - initArgv(); - - // TODO: APT init goes here - - // Run the global constructors - __libc_init_array(); -} - -void initArgv() -{ - int i; - const char* temp = __system_arglist; - - // Check if the argument list is present - if (!temp) - return; - - // Retrieve argc - __system_argc = *(u32*)temp; - temp += sizeof(u32); - - // Find the end of the argument data - for (i = 0; i < __system_argc; i ++) - { - for (; *temp; temp ++); - temp ++; - } - - // Reserve heap memory for argv data - u32 argSize = temp - __system_arglist - sizeof(u32); - __system_argv = (char**)fake_heap_start; - fake_heap_start += sizeof(char**)*(__system_argc + 1); - char* argCopy = fake_heap_start; - fake_heap_start += argSize; - - // Fill argv array - memcpy(argCopy, &__system_arglist[4], argSize); - temp = argCopy; - for (i = 0; i < __system_argc; i ++) - { - __system_argv[i] = (char*)temp; - for (; *temp; temp ++); - temp ++; - } - __system_argv[__system_argc] = NULL; -} diff --git a/libctru/source/system/allocateHeaps.c b/libctru/source/system/allocateHeaps.c new file mode 100644 index 0000000..1714a77 --- /dev/null +++ b/libctru/source/system/allocateHeaps.c @@ -0,0 +1,24 @@ +#include <3ds/types.h> +#include <3ds/svc.h> + +extern char* fake_heap_start; +extern char* fake_heap_end; +u32 __linear_heap; +u32 __heapBase; +extern u32 __heap_size, __linear_heap_size; + + +void __attribute__((weak)) __allocateHeaps() { + u32 tmp=0; + + // Allocate the application heap + __heapBase = 0x08000000; + svcControlMemory(&tmp, __heapBase, 0x0, __heap_size, MEMOP_ALLOC, 0x3); + + // Allocate the linear heap + svcControlMemory(&__linear_heap, 0x0, 0x0, __linear_heap_size, MEMOP_ALLOC_LINEAR, 0x3); + // Set up newlib heap + fake_heap_start = (char*)__heapBase; + fake_heap_end = fake_heap_start + __heap_size; + +} \ No newline at end of file diff --git a/libctru/source/system/ctru_exit.c b/libctru/source/system/ctru_exit.c new file mode 100644 index 0000000..9a86609 --- /dev/null +++ b/libctru/source/system/ctru_exit.c @@ -0,0 +1,37 @@ +#include <3ds/types.h> +#include <3ds/svc.h> + +extern u32 __linear_heap; +extern u32 __heapBase; +extern u32 __heap_size, __linear_heap_size; +extern void (*__system_retAddr)(void); + +void __destroy_handle_list(void); + +void __libc_fini_array(void); + +void __attribute__((weak)) __attribute__((noreturn)) __ctru_exit(int rc) +{ + u32 tmp=0; + + // Run the global destructors + __libc_fini_array(); + + // TODO: APT exit goes here + + // Unmap the linear heap + svcControlMemory(&tmp, __linear_heap, 0x0, __linear_heap_size, MEMOP_FREE, 0x0); + + // Unmap the application heap + svcControlMemory(&tmp, __heapBase, 0x0, __heap_size, MEMOP_FREE, 0x0); + + // Close some handles + __destroy_handle_list(); + + // Jump to the loader if it provided a callback + if (__system_retAddr) + __system_retAddr(); + + // Since above did not jump, end this process + svcExitProcess(); +} diff --git a/libctru/source/system/initArgv.c b/libctru/source/system/initArgv.c new file mode 100644 index 0000000..6fb12d8 --- /dev/null +++ b/libctru/source/system/initArgv.c @@ -0,0 +1,48 @@ +#include <3ds/types.h> + +// System globals we define here +int __system_argc; +char** __system_argv; +extern const char* __system_arglist; + +extern char* fake_heap_start; +extern char* fake_heap_end; + +void __system_initArgv() +{ + int i; + const char* temp = __system_arglist; + + // Check if the argument list is present + if (!temp) + return; + + // Retrieve argc + __system_argc = *(u32*)temp; + temp += sizeof(u32); + + // Find the end of the argument data + for (i = 0; i < __system_argc; i ++) + { + for (; *temp; temp ++); + temp ++; + } + + // Reserve heap memory for argv data + u32 argSize = temp - __system_arglist - sizeof(u32); + __system_argv = (char**)fake_heap_start; + fake_heap_start += sizeof(char**)*(__system_argc + 1); + char* argCopy = fake_heap_start; + fake_heap_start += argSize; + + // Fill argv array + memcpy(argCopy, &__system_arglist[4], argSize); + temp = argCopy; + for (i = 0; i < __system_argc; i ++) + { + __system_argv[i] = (char*)temp; + for (; *temp; temp ++); + temp ++; + } + __system_argv[__system_argc] = NULL; +} diff --git a/libctru/source/system/initSystem.c b/libctru/source/system/initSystem.c new file mode 100644 index 0000000..be5c118 --- /dev/null +++ b/libctru/source/system/initSystem.c @@ -0,0 +1,36 @@ +#include +#include +#include <3ds/types.h> +#include <3ds/svc.h> + +void (*__system_retAddr)(void); + +// Data from _prm structure +extern void* __service_ptr; // used to detect if we're run from a homebrew launcher + +void __system_allocateHeaps(); +void __system_initArgv(); + +// newlib definitions we need +void __libc_init_array(void); + + +void __ctru_exit(int rc); + +void __attribute__((weak)) initSystem(void (*retAddr)(void)) +{ + + // Register newlib exit() syscall + __syscalls.exit = __ctru_exit; + __system_retAddr = __service_ptr ? retAddr : NULL; + + __system_allocateHeaps(); + + // Build argc/argv if present + __system_initArgv(); + + // TODO: APT init goes here + + // Run the global constructors + __libc_init_array(); +}