From ac119b04f6e8c9b5186b401cbf4af17aadb0f87c Mon Sep 17 00:00:00 2001 From: aliaspider Date: Thu, 22 Oct 2015 20:35:22 +0100 Subject: [PATCH] (CTR/3DS) improve memory management. - use a custom crt0 to allow overriding __heap_size and __linear_heap_size - add a setting for maximum heap size. unallocated memory can be freely mapped by the core. - add better detection of the extra memory available when running from the HBL. --- Makefile.ctr | 13 ++++-- ctr/3dsx_custom.specs | 8 ++++ ctr/3dsx_custom_crt0.s | 74 +++++++++++++++++++++++++++++++++ ctr/Makefile.cores | 3 +- ctr/ctr_config.c | 10 ++++- frontend/drivers/platform_ctr.c | 42 ++++++++++++------- gfx/drivers/ctr_gfx.c | 4 +- gfx/drivers/ctr_gu.h | 4 +- 8 files changed, 132 insertions(+), 26 deletions(-) create mode 100644 ctr/3dsx_custom.specs create mode 100644 ctr/3dsx_custom_crt0.s diff --git a/Makefile.ctr b/Makefile.ctr index bb5b70ed63..574ce21541 100644 --- a/Makefile.ctr +++ b/Makefile.ctr @@ -28,10 +28,11 @@ else CTR_STACK_SIZE = 0x100000 endif CTR_LINEAR_HEAP_SIZE = 0x600000 +CTR_MAX_HEAP_SIZE = 0x6000000 include ctr/Makefile.cores -CONFIG_OBJECT = ctr/ctr_config_$(CTR_STACK_SIZE)_$(CTR_LINEAR_HEAP_SIZE).o +CONFIG_OBJECT = ctr/ctr_config_$(CTR_STACK_SIZE)_$(CTR_LINEAR_HEAP_SIZE)_$(CTR_MAX_HEAP_SIZE).o OBJS := OBJS += gfx/drivers/ctr_sprite.o @@ -289,6 +290,11 @@ ifneq ($(CTR_LINEAR_HEAP_SIZE),) CFLAGS += -DCTR_LINEAR_HEAP_SIZE=$(CTR_LINEAR_HEAP_SIZE) endif +ifneq ($(CTR_MAX_HEAP_SIZE),) + CFLAGS += -DCTR_MAX_HEAP_SIZE=$(CTR_MAX_HEAP_SIZE) +endif + + CFLAGS += -I. -Ideps/zlib -Ideps/7zip -Ilibretro-common/include CFLAGS += -DRARCH_INTERNAL -DRARCH_CONSOLE -DSINC_LOWEST_QUALITY @@ -300,7 +306,7 @@ CFLAGS += -DHAVE_ZLIB -DHAVE_RPNG -DWANT_ZLIB -DHAVE_BUILTIN_AUTOCONFIG CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 ASFLAGS := -g $(ARCH) -O3 -LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) +LDFLAGS = -specs=ctr/3dsx_custom.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) CFLAGS += -std=gnu99 -ffast-math @@ -392,7 +398,7 @@ $(CONFIG_OBJECT): ctr/ctr_config.c %.3dsx: %.elf -3dsxtool $< $@ $(_3DSXFLAGS) -%.elf: +%.elf: ctr/3dsx_custom_crt0.o $(LD) $(LDFLAGS) $(OBJS) $(LIBDIRS) $(LIBS) -o $@ $(NM) -CSn $@ > $(notdir $*.lst) @@ -419,6 +425,7 @@ clean: rm -f $(TARGET).icn rm -f *_shader_shbin.h rm -f ctr/ctr_config_*.o + rm -f ctr/3dsx_custom_crt0.o .PHONY: clean diff --git a/ctr/3dsx_custom.specs b/ctr/3dsx_custom.specs new file mode 100644 index 0000000000..e2bed41c76 --- /dev/null +++ b/ctr/3dsx_custom.specs @@ -0,0 +1,8 @@ +%rename link old_link + +*link: +%(old_link) -T 3dsx.ld%s -d --emit-relocs --use-blx + +*startfile: +ctr/3dsx_custom_crt0%O%s crti%O%s crtbegin%O%s + diff --git a/ctr/3dsx_custom_crt0.s b/ctr/3dsx_custom_crt0.s new file mode 100644 index 0000000000..8ca365dfcc --- /dev/null +++ b/ctr/3dsx_custom_crt0.s @@ -0,0 +1,74 @@ +@--------------------------------------------------------------------------------- +@ 3DS processor selection +@--------------------------------------------------------------------------------- + .cpu mpcore +@--------------------------------------------------------------------------------- + +@--------------------------------------------------------------------------------- + .section ".crt0" + .global _start, __service_ptr, __apt_appid, __heap_size_hbl, __linear_heap_size_hbl, __system_arglist, __system_runflags +@--------------------------------------------------------------------------------- + .align 2 + .arm +@--------------------------------------------------------------------------------- +_start: +@--------------------------------------------------------------------------------- + b startup + .ascii "_prm" +__service_ptr: + .word 0 @ Pointer to service handle override list -- if non-NULL it is assumed that we have been launched from a homebrew launcher +__apt_appid: + .word 0x300 @ Program APPID +__heap_size_hbl: + .word 24*1024*1024 @ Default heap size (24 MiB) +__linear_heap_size_hbl: + .word 32*1024*1024 @ Default linear heap size (32 MiB) +__system_arglist: + .word 0 @ Pointer to argument list (argc (u32) followed by that many NULL terminated strings) +__system_runflags: + .word 0 @ Flags to signal runtime restrictions to ctrulib +startup: + @ Save return address + mov r4, lr + + @ Clear the BSS section + ldr r0, =__bss_start__ + ldr r1, =__bss_end__ + sub r1, r1, r0 + bl ClearMem + + @ System initialization + mov r0, r4 + bl initSystem + + @ Set up argc/argv arguments for main() + ldr r0, =__system_argc + ldr r1, =__system_argv + ldr r0, [r0] + ldr r1, [r1] + + @ Jump to user code + ldr r3, =main + ldr lr, =__ctru_exit + bx r3 + +@--------------------------------------------------------------------------------- +@ Clear memory to 0x00 if length != 0 +@ r0 = Start Address +@ r1 = Length +@--------------------------------------------------------------------------------- +ClearMem: +@--------------------------------------------------------------------------------- + mov r2, #3 @ Round down to nearest word boundary + add r1, r1, r2 @ Shouldn't be needed + bics r1, r1, r2 @ Clear 2 LSB (and set Z) + bxeq lr @ Quit if copy size is 0 + + mov r2, #0 +ClrLoop: + stmia r0!, {r2} + subs r1, r1, #4 + bne ClrLoop + + bx lr + diff --git a/ctr/Makefile.cores b/ctr/Makefile.cores index 5d7e3e1580..be1ce7ec33 100644 --- a/ctr/Makefile.cores +++ b/ctr/Makefile.cores @@ -206,7 +206,8 @@ else ifeq ($(LIBRETRO), fb_alpha_neo) #APP_AUDIO = ctr/silent.wav APP_SYSTEM_MODE = 80MB #APP_SYSTEM_MODE_EXT = Legacy - #CTR_LINEAR_HEAP_SIZE = 0x600000 + CTR_LINEAR_HEAP_SIZE = 0x3A0000 + CTR_MAX_HEAP_SIZE = 0xC00000 else ifeq ($(LIBRETRO), fb_alpha_cps1) APP_TITLE = Final Burn Alpha - CPS-1 diff --git a/ctr/ctr_config.c b/ctr/ctr_config.c index bcde951fa7..e1e7504797 100644 --- a/ctr/ctr_config.c +++ b/ctr/ctr_config.c @@ -8,5 +8,11 @@ #define CTR_LINEAR_HEAP_SIZE 0x600000 #endif -int __stacksize__ = CTR_STACK_SIZE; -unsigned int linear_heap_size = CTR_LINEAR_HEAP_SIZE; +#ifndef CTR_MAX_HEAP_SIZE +#define CTR_MAX_HEAP_SIZE 0x6000000 +#endif + + +int __stacksize__ = CTR_STACK_SIZE; +unsigned int __linear_heap_size = CTR_LINEAR_HEAP_SIZE; +unsigned int __heap_size = CTR_MAX_HEAP_SIZE; diff --git a/frontend/drivers/platform_ctr.c b/frontend/drivers/platform_ctr.c index 5cc91f12fc..9803c0e310 100644 --- a/frontend/drivers/platform_ctr.c +++ b/frontend/drivers/platform_ctr.c @@ -41,6 +41,8 @@ const char* elf_path_cst = "sdmc:/retroarch/test.3dsx"; #ifndef DEBUG_HOLD void wait_for_input(void); #define DEBUG_HOLD() do{printf("%s@%s:%d.\n",__FUNCTION__, __FILE__, __LINE__);fflush(stdout);wait_for_input();}while(0) +#define DEBUG_VAR(X) printf( "%-20s: 0x%08X\n", #X, (u32)(X)) +#define DEBUG_VAR64(X) printf( #X"\r\t\t\t\t : 0x%016llX\n", (u64)(X)) #endif #define CTR_APPMEMALLOC_PTR ((u32*)0x1FF80040) @@ -49,8 +51,10 @@ extern char* fake_heap_start; extern char* fake_heap_end; u32 __linear_heap; u32 __heapBase; -u32 heap_size; -extern u32 linear_heap_size; +extern u32 __linear_heap_size; +extern u32 __heap_size; +extern u32 __linear_heap_size_hbl; +extern u32 __heap_size_hbl; extern void (*__system_retAddr)(void); @@ -62,29 +66,35 @@ void __system_allocateHeaps() { extern unsigned int __service_ptr; u32 tmp=0; int64_t mem_used; - u32 app_memory = 0x04000000; - - if(!__service_ptr) - app_memory = *CTR_APPMEMALLOC_PTR; + u32 mem_available; + u32 app_memory; svcGetSystemInfo(&mem_used, 0, 1); - // For n3DS running with 124MB, only 110MB appears actually available - app_memory = app_memory > 0x6E00000 ? 0x6E00000 : app_memory; + if(__service_ptr) + { + app_memory = mem_used + __linear_heap_size_hbl + __heap_size_hbl; + app_memory = app_memory < 0x04000000 ? 0x04000000 : app_memory; + } + else + app_memory = *CTR_APPMEMALLOC_PTR; - heap_size = (app_memory - mem_used - linear_heap_size - 0x10000) & 0xFFFFF000; - heap_size = heap_size > 0x6000000? 0x6000000 : heap_size; + mem_available = (app_memory - mem_used - __linear_heap_size - 0x10000) & 0xFFFFF000; + + __heap_size = __heap_size > mem_available ? mem_available : __heap_size; + __heap_size = __heap_size > 0x6000000 ? 0x6000000 : __heap_size; + +// __linear_heap_size = (app_memory - mem_used - __heap_size - 0x10000) & 0xFFFFF000; // Allocate the application heap __heapBase = 0x08000000; - svcControlMemory(&tmp, __heapBase, 0x0, heap_size, MEMOP_ALLOC, MEMPERM_READ | MEMPERM_WRITE); + svcControlMemory(&tmp, __heapBase, 0x0, __heap_size, MEMOP_ALLOC, MEMPERM_READ | MEMPERM_WRITE); // Allocate the linear heap - svcControlMemory(&__linear_heap, 0x0, 0x0, linear_heap_size, MEMOP_ALLOC_LINEAR, MEMPERM_READ | MEMPERM_WRITE); + svcControlMemory(&__linear_heap, 0x0, 0x0, __linear_heap_size, MEMOP_ALLOC_LINEAR, MEMPERM_READ | MEMPERM_WRITE); // Set up newlib heap fake_heap_start = (char*)__heapBase; - fake_heap_end = fake_heap_start + heap_size; - + fake_heap_end = fake_heap_start + __heap_size; } void __attribute__((noreturn)) __libctru_exit(int rc) @@ -92,10 +102,10 @@ void __attribute__((noreturn)) __libctru_exit(int rc) u32 tmp=0; // Unmap the linear heap - svcControlMemory(&tmp, __linear_heap, 0x0, linear_heap_size, MEMOP_FREE, 0x0); + svcControlMemory(&tmp, __linear_heap, 0x0, __linear_heap_size, MEMOP_FREE, 0x0); // Unmap the application heap - svcControlMemory(&tmp, __heapBase, 0x0, heap_size, MEMOP_FREE, 0x0); + svcControlMemory(&tmp, __heapBase, 0x0, __heap_size, MEMOP_FREE, 0x0); // Close some handles __destroy_handle_list(); diff --git a/gfx/drivers/ctr_gfx.c b/gfx/drivers/ctr_gfx.c index dce8b80c93..be6086584d 100644 --- a/gfx/drivers/ctr_gfx.c +++ b/gfx/drivers/ctr_gfx.c @@ -463,8 +463,8 @@ static bool ctr_frame(void* data, const void* frame, // extern u32 __linear_heap_size; // extern u32 gpuCmdBufOffset; -// extern u32 heap_size; -// printf("0x%08X 0x%08X 0x%08X\r", heap_size, gpuCmdBufOffset, (__linear_heap_size - linearSpaceFree() +0x3FF) & ~0x3FF); +// extern u32 __heap_size; +// printf("0x%08X 0x%08X 0x%08X\r", __heap_size, gpuCmdBufOffset, (__linear_heap_size - linearSpaceFree() +0x3FF) & ~0x3FF); // printf("fps: %8.4f frames: %i (%X)\r", fps, total_frames++, (__linear_heap_size - linearSpaceFree())); printf("fps: %8.4f frames: %i\r", fps, total_frames++); fflush(stdout); diff --git a/gfx/drivers/ctr_gu.h b/gfx/drivers/ctr_gu.h index c46c563ea9..363a4c80b4 100644 --- a/gfx/drivers/ctr_gu.h +++ b/gfx/drivers/ctr_gu.h @@ -70,7 +70,7 @@ void wait_for_input(void); extern Handle gspEvents[GSPEVENT_MAX]; extern u32* gpuCmdBuf; extern u32 gpuCmdBufOffset; -extern u32 linear_heap_size; +extern u32 __linear_heap_size; extern u32 __linear_heap; __attribute__((always_inline)) @@ -136,7 +136,7 @@ __attribute__((always_inline)) static INLINE void ctrGuFlushAndRun(bool queued) { //take advantage of GX_SetCommandList_First to flush gsp heap - ctrGuSetCommandList_First(queued, gpuCmdBuf, gpuCmdBufOffset*4, (u32*)__linear_heap, linear_heap_size, NULL, 0); + ctrGuSetCommandList_First(queued, gpuCmdBuf, gpuCmdBufOffset*4, (u32*)__linear_heap, __linear_heap_size, NULL, 0); ctrGuSetCommandList_Last(queued, gpuCmdBuf, gpuCmdBufOffset*4, 0x0); }