(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.
This commit is contained in:
aliaspider 2015-10-22 20:35:22 +01:00
parent 9302ce939b
commit ac119b04f6
8 changed files with 132 additions and 26 deletions

View File

@ -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

8
ctr/3dsx_custom.specs Normal file
View File

@ -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

74
ctr/3dsx_custom_crt0.s Normal file
View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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();

View File

@ -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);

View File

@ -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);
}