mirror of
https://github.com/libretro/RetroArch.git
synced 2024-11-24 00:20:01 +00:00
(3DS) implement dynamic memory management.
heap/linear heap and stack sizes can now change dynamically at runtime, depending on usage, no need to specify those on a per-core basis anymore.
This commit is contained in:
parent
d4f037f6d7
commit
8741ec48d5
72
Makefile.ctr
72
Makefile.ctr
@ -1,42 +1,34 @@
|
||||
TARGET := retroarch_3ds
|
||||
LIBRETRO =
|
||||
|
||||
DEBUG = 0
|
||||
GRIFFIN_BUILD = 1
|
||||
WHOLE_ARCHIVE_LINK = 0
|
||||
BIG_STACK = 0
|
||||
BUILD_3DSX = 1
|
||||
BUILD_3DS = 1
|
||||
BUILD_CIA = 1
|
||||
DEBUG = 0
|
||||
GRIFFIN_BUILD = 1
|
||||
WHOLE_ARCHIVE_LINK = 0
|
||||
BUILD_3DSX = 1
|
||||
BUILD_3DS = 1
|
||||
BUILD_CIA = 1
|
||||
|
||||
APP_TITLE = Retroarch 3DS
|
||||
APP_DESCRIPTION = Retroarch 3DS
|
||||
APP_AUTHOR = Team Libretro
|
||||
APP_PRODUCT_CODE = RETROARCH-3DS
|
||||
APP_UNIQUE_ID = 0xBAC00
|
||||
APP_ICON = ctr/default.png
|
||||
APP_BANNER = ctr/libretro_banner.png
|
||||
APP_AUDIO = ctr/silent.wav
|
||||
APP_RSF = ctr/tools/template.rsf
|
||||
APP_SYSTEM_MODE = 64MB
|
||||
APP_SYSTEM_MODE_EXT = 124MB
|
||||
|
||||
|
||||
ifeq ($(BIG_STACK),1)
|
||||
CTR_STACK_SIZE = 0x400000
|
||||
else
|
||||
CTR_STACK_SIZE = 0x100000
|
||||
endif
|
||||
CTR_LINEAR_HEAP_SIZE = 0x600000
|
||||
CTR_MAX_HEAP_SIZE = 0x6000000
|
||||
APP_TITLE = Retroarch 3DS
|
||||
APP_DESCRIPTION = Retroarch 3DS
|
||||
APP_AUTHOR = Team Libretro
|
||||
APP_PRODUCT_CODE = RETROARCH-3DS
|
||||
APP_UNIQUE_ID = 0xBAC00
|
||||
APP_ICON = ctr/default.png
|
||||
APP_BANNER = ctr/libretro_banner.png
|
||||
APP_AUDIO = ctr/silent.wav
|
||||
APP_RSF = ctr/tools/template.rsf
|
||||
APP_SYSTEM_MODE = 64MB
|
||||
APP_SYSTEM_MODE_EXT = 124MB
|
||||
|
||||
include ctr/Makefile.cores
|
||||
|
||||
CONFIG_OBJECT = ctr/ctr_config_$(CTR_STACK_SIZE)_$(CTR_LINEAR_HEAP_SIZE)_$(CTR_MAX_HEAP_SIZE).o
|
||||
|
||||
OBJS :=
|
||||
OBJS += gfx/drivers/ctr_sprite.o
|
||||
OBJS += $(CONFIG_OBJECT)
|
||||
OBJS += ctr/stack_adjust.o
|
||||
OBJS += ctr/ctr_system.o
|
||||
OBJS += ctr/ctr_memory.o
|
||||
OBJS += ctr/ctr_linear.o
|
||||
|
||||
ifeq ($(GRIFFIN_BUILD), 1)
|
||||
OBJS += griffin/griffin.o
|
||||
else
|
||||
@ -270,6 +262,7 @@ ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -marm -mfpu=vfp
|
||||
|
||||
CFLAGS += -mword-relocations \
|
||||
-fomit-frame-pointer -ffast-math \
|
||||
-Werror=implicit-function-declaration \
|
||||
$(ARCH)
|
||||
|
||||
#CFLAGS += -Wall
|
||||
@ -286,19 +279,6 @@ ifeq ($(WHOLE_ARCHIVE_LINK), 1)
|
||||
WHOLE_END := -Wl,--no-whole-archive
|
||||
endif
|
||||
|
||||
ifneq ($(CTR_STACK_SIZE),)
|
||||
CFLAGS += -DCTR_STACK_SIZE=$(CTR_STACK_SIZE)
|
||||
endif
|
||||
|
||||
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
|
||||
@ -365,11 +345,6 @@ else
|
||||
BANNERTOOL = ctr/tools/bannertool.exe
|
||||
endif
|
||||
|
||||
|
||||
$(CONFIG_OBJECT): ctr/ctr_config.c
|
||||
rm -f ctr/ctr_config_*.o
|
||||
$(CC) -c -o $@ $< $(CFLAGS) $(INCDIRS)
|
||||
|
||||
%.o: %.shader
|
||||
python $(AEMSTRO)/aemstro_as.py $< $(notdir $<).shbin
|
||||
$(DEVKITARM)/bin/bin2s $(notdir $<).shbin | $(PREFIX)as -o $@
|
||||
@ -425,6 +400,7 @@ clean:
|
||||
rm -f $(TARGET).elf
|
||||
rm -f $(TARGET).3ds
|
||||
rm -f $(TARGET).cia
|
||||
rm -f $(TARGET).smdh
|
||||
rm -f $(TARGET).bnr
|
||||
rm -f $(TARGET).icn
|
||||
rm -f *_shader_shbin.h
|
||||
|
@ -9,9 +9,6 @@ ifeq ($(LIBRETRO), gambatte)
|
||||
APP_ICON = ctr/gambatte.png
|
||||
#APP_BANNER = ctr/libretro_banner.png
|
||||
#APP_AUDIO = ctr/silent.wav
|
||||
#APP_SYSTEM_MODE = 64MB
|
||||
#APP_SYSTEM_MODE_EXT = Legacy
|
||||
#CTR_LINEAR_HEAP_SIZE = 0x600000
|
||||
|
||||
else ifeq ($(LIBRETRO), gpsp)
|
||||
APP_TITLE = gpSP Libretro
|
||||
@ -22,9 +19,6 @@ else ifeq ($(LIBRETRO), gpsp)
|
||||
APP_ICON = ctr/gpsp.png
|
||||
#APP_BANNER = ctr/libretro_banner.png
|
||||
#APP_AUDIO = ctr/silent.wav
|
||||
#APP_SYSTEM_MODE = 64MB
|
||||
#APP_SYSTEM_MODE_EXT = Legacy
|
||||
#CTR_LINEAR_HEAP_SIZE = 0x600000
|
||||
|
||||
else ifeq ($(LIBRETRO), fceumm)
|
||||
APP_TITLE = FCeumm Libretro
|
||||
@ -35,9 +29,6 @@ else ifeq ($(LIBRETRO), fceumm)
|
||||
APP_ICON = ctr/fceumm.png
|
||||
#APP_BANNER = ctr/libretro_banner.png
|
||||
#APP_AUDIO = ctr/silent.wav
|
||||
#APP_SYSTEM_MODE = 64MB
|
||||
#APP_SYSTEM_MODE_EXT = Legacy
|
||||
#CTR_LINEAR_HEAP_SIZE = 0x600000
|
||||
|
||||
else ifeq ($(LIBRETRO), nestopia)
|
||||
APP_TITLE = Nestopia Libretro
|
||||
@ -48,9 +39,6 @@ else ifeq ($(LIBRETRO), nestopia)
|
||||
APP_ICON = ctr/nestopia.png
|
||||
#APP_BANNER = ctr/libretro_banner.png
|
||||
#APP_AUDIO = ctr/silent.wav
|
||||
#APP_SYSTEM_MODE = 64MB
|
||||
#APP_SYSTEM_MODE_EXT = Legacy
|
||||
CTR_LINEAR_HEAP_SIZE = 0xE00000
|
||||
|
||||
else ifeq ($(LIBRETRO), nxengine)
|
||||
APP_TITLE = NXengine Libretro
|
||||
@ -61,9 +49,6 @@ else ifeq ($(LIBRETRO), nxengine)
|
||||
APP_ICON = ctr/nxengine.png
|
||||
#APP_BANNER = ctr/libretro_banner.png
|
||||
#APP_AUDIO = ctr/silent.wav
|
||||
#APP_SYSTEM_MODE = 64MB
|
||||
#APP_SYSTEM_MODE_EXT = Legacy
|
||||
#CTR_LINEAR_HEAP_SIZE = 0x600000
|
||||
|
||||
else ifeq ($(LIBRETRO), genesis_plus_gx)
|
||||
APP_TITLE = Genesis Plus GX Libretro
|
||||
@ -74,9 +59,6 @@ else ifeq ($(LIBRETRO), genesis_plus_gx)
|
||||
APP_ICON = ctr/genesis_plus_gx.png
|
||||
#APP_BANNER = ctr/libretro_banner.png
|
||||
#APP_AUDIO = ctr/silent.wav
|
||||
#APP_SYSTEM_MODE = 64MB
|
||||
#APP_SYSTEM_MODE_EXT = Legacy
|
||||
CTR_LINEAR_HEAP_SIZE = 0xE00000
|
||||
|
||||
else ifeq ($(LIBRETRO), catsfc)
|
||||
APP_TITLE = CATSFC Libretro
|
||||
@ -87,9 +69,6 @@ else ifeq ($(LIBRETRO), catsfc)
|
||||
APP_ICON = ctr/catsfc.png
|
||||
#APP_BANNER = ctr/libretro_banner.png
|
||||
#APP_AUDIO = ctr/silent.wav
|
||||
#APP_SYSTEM_MODE = 64MB
|
||||
#APP_SYSTEM_MODE_EXT = Legacy
|
||||
#CTR_LINEAR_HEAP_SIZE = 0x600000
|
||||
|
||||
else ifeq ($(LIBRETRO), mednafen_wswan)
|
||||
APP_TITLE = Mednafen wswan Libretro
|
||||
@ -100,9 +79,6 @@ else ifeq ($(LIBRETRO), mednafen_wswan)
|
||||
APP_ICON = ctr/mednafen_wswan.png
|
||||
#APP_BANNER = ctr/libretro_banner.png
|
||||
#APP_AUDIO = ctr/silent.wav
|
||||
#APP_SYSTEM_MODE = 64MB
|
||||
#APP_SYSTEM_MODE_EXT = Legacy
|
||||
CTR_LINEAR_HEAP_SIZE = 0xE00000
|
||||
|
||||
else ifeq ($(LIBRETRO), mednafen_vb)
|
||||
APP_TITLE = Mednafen VB Libretro
|
||||
@ -113,9 +89,6 @@ else ifeq ($(LIBRETRO), mednafen_vb)
|
||||
APP_ICON = ctr/mednafen_vb.png
|
||||
#APP_BANNER = ctr/libretro_banner.png
|
||||
#APP_AUDIO = ctr/silent.wav
|
||||
#APP_SYSTEM_MODE = 64MB
|
||||
#APP_SYSTEM_MODE_EXT = Legacy
|
||||
CTR_LINEAR_HEAP_SIZE = 0xE00000
|
||||
|
||||
else ifeq ($(LIBRETRO), mednafen_ngp)
|
||||
APP_TITLE = Mednafen NGP Libretro
|
||||
@ -126,9 +99,6 @@ else ifeq ($(LIBRETRO), mednafen_ngp)
|
||||
APP_ICON = ctr/mednafen_ngp.png
|
||||
#APP_BANNER = ctr/libretro_banner.png
|
||||
#APP_AUDIO = ctr/silent.wav
|
||||
#APP_SYSTEM_MODE = 64MB
|
||||
#APP_SYSTEM_MODE_EXT = Legacy
|
||||
CTR_LINEAR_HEAP_SIZE = 0xE00000
|
||||
|
||||
else ifeq ($(LIBRETRO), 2048)
|
||||
APP_TITLE = 2048 Libretro
|
||||
@ -139,9 +109,6 @@ else ifeq ($(LIBRETRO), 2048)
|
||||
APP_ICON = ctr/2048.png
|
||||
#APP_BANNER = ctr/libretro_banner.png
|
||||
#APP_AUDIO = ctr/silent.wav
|
||||
#APP_SYSTEM_MODE = 64MB
|
||||
#APP_SYSTEM_MODE_EXT = Legacy
|
||||
CTR_LINEAR_HEAP_SIZE = 0xE00000
|
||||
|
||||
else ifeq ($(LIBRETRO), picodrive)
|
||||
APP_TITLE = Picodrive Libretro
|
||||
@ -152,9 +119,6 @@ else ifeq ($(LIBRETRO), picodrive)
|
||||
APP_ICON = ctr/picodrive.png
|
||||
#APP_BANNER = ctr/libretro_banner.png
|
||||
#APP_AUDIO = ctr/silent.wav
|
||||
#APP_SYSTEM_MODE = 64MB
|
||||
#APP_SYSTEM_MODE_EXT = Legacy
|
||||
#CTR_LINEAR_HEAP_SIZE = 0x600000
|
||||
|
||||
else ifeq ($(LIBRETRO), snes9x_next)
|
||||
APP_TITLE = Snes9x Next Libretro
|
||||
@ -165,9 +129,6 @@ else ifeq ($(LIBRETRO), snes9x_next)
|
||||
APP_ICON = ctr/snes9x_next.png
|
||||
#APP_BANNER = ctr/libretro_banner.png
|
||||
#APP_AUDIO = ctr/silent.wav
|
||||
#APP_SYSTEM_MODE = 64MB
|
||||
#APP_SYSTEM_MODE_EXT = Legacy
|
||||
#CTR_LINEAR_HEAP_SIZE = 0x600000
|
||||
|
||||
else ifeq ($(LIBRETRO), mgba)
|
||||
APP_TITLE = mGBA Libretro
|
||||
@ -178,9 +139,6 @@ else ifeq ($(LIBRETRO), mgba)
|
||||
APP_ICON = ctr/mgba.png
|
||||
#APP_BANNER = ctr/libretro_banner.png
|
||||
#APP_AUDIO = ctr/silent.wav
|
||||
#APP_SYSTEM_MODE = 64MB
|
||||
#APP_SYSTEM_MODE_EXT = Legacy
|
||||
#CTR_LINEAR_HEAP_SIZE = 0x600000
|
||||
|
||||
else ifeq ($(LIBRETRO), quicknes)
|
||||
APP_TITLE = QuickNES Libretro
|
||||
@ -191,9 +149,6 @@ else ifeq ($(LIBRETRO), quicknes)
|
||||
APP_ICON = ctr/quicknes.png
|
||||
#APP_BANNER = ctr/libretro_banner.png
|
||||
#APP_AUDIO = ctr/silent.wav
|
||||
#APP_SYSTEM_MODE = 64MB
|
||||
#APP_SYSTEM_MODE_EXT = Legacy
|
||||
#CTR_LINEAR_HEAP_SIZE = 0x600000
|
||||
|
||||
else ifeq ($(LIBRETRO), fb_alpha_neo)
|
||||
APP_TITLE = Neo Geo (FB Alpha)
|
||||
@ -205,9 +160,6 @@ else ifeq ($(LIBRETRO), fb_alpha_neo)
|
||||
#APP_BANNER = ctr/libretro_banner.png
|
||||
#APP_AUDIO = ctr/silent.wav
|
||||
APP_SYSTEM_MODE = 80MB
|
||||
#APP_SYSTEM_MODE_EXT = Legacy
|
||||
CTR_LINEAR_HEAP_SIZE = 0x3A0000
|
||||
CTR_MAX_HEAP_SIZE = 0xC00000
|
||||
|
||||
else ifeq ($(LIBRETRO), fb_alpha_cps1)
|
||||
APP_TITLE = Final Burn Alpha - CPS-1
|
||||
@ -218,9 +170,6 @@ else ifeq ($(LIBRETRO), fb_alpha_cps1)
|
||||
APP_ICON = ctr/fb_alpha_cps1.png
|
||||
#APP_BANNER = ctr/libretro_banner.png
|
||||
#APP_AUDIO = ctr/silent.wav
|
||||
#APP_SYSTEM_MODE = 64MB
|
||||
#APP_SYSTEM_MODE_EXT = Legacy
|
||||
#CTR_LINEAR_HEAP_SIZE = 0x600000
|
||||
|
||||
else ifeq ($(LIBRETRO), fb_alpha_cps2)
|
||||
APP_TITLE = Final Burn Alpha - CPS-2
|
||||
@ -232,8 +181,6 @@ else ifeq ($(LIBRETRO), fb_alpha_cps2)
|
||||
#APP_BANNER = ctr/libretro_banner.png
|
||||
#APP_AUDIO = ctr/silent.wav
|
||||
APP_SYSTEM_MODE = 80MB
|
||||
#APP_SYSTEM_MODE_EXT = Legacy
|
||||
#CTR_LINEAR_HEAP_SIZE = 0x600000
|
||||
|
||||
else ifeq ($(LIBRETRO), catsfc_plus)
|
||||
APP_TITLE = CATSFC Plus Libretro
|
||||
@ -244,9 +191,6 @@ else ifeq ($(LIBRETRO), catsfc_plus)
|
||||
APP_ICON = ctr/catsfc_plus.png
|
||||
#APP_BANNER = ctr/libretro_banner.png
|
||||
#APP_AUDIO = ctr/silent.wav
|
||||
#APP_SYSTEM_MODE = 64MB
|
||||
#APP_SYSTEM_MODE_EXT = Legacy
|
||||
#CTR_LINEAR_HEAP_SIZE = 0x600000
|
||||
|
||||
else ifeq ($(LIBRETRO), mednafen_pce_fast)
|
||||
APP_TITLE = Mednafen/Beetle PCE FAST
|
||||
@ -257,9 +201,6 @@ else ifeq ($(LIBRETRO), mednafen_pce_fast)
|
||||
APP_ICON = ctr/mednafen_pce_fast.png
|
||||
#APP_BANNER = ctr/libretro_banner.png
|
||||
#APP_AUDIO = ctr/silent.wav
|
||||
#APP_SYSTEM_MODE = 64MB
|
||||
#APP_SYSTEM_MODE_EXT = Legacy
|
||||
#CTR_LINEAR_HEAP_SIZE = 0x600000
|
||||
|
||||
else ifeq ($(LIBRETRO), pcsx_rearmed)
|
||||
APP_TITLE = PCSX ReARMed
|
||||
@ -270,9 +211,6 @@ else ifeq ($(LIBRETRO), pcsx_rearmed)
|
||||
APP_ICON = ctr/pcsx_rearmed.png
|
||||
#APP_BANNER = ctr/libretro_banner.png
|
||||
#APP_AUDIO = ctr/silent.wav
|
||||
#APP_SYSTEM_MODE = 64MB
|
||||
#APP_SYSTEM_MODE_EXT = Legacy
|
||||
CTR_LINEAR_HEAP_SIZE = 0xE00000
|
||||
|
||||
else ifeq ($(LIBRETRO), fmsx)
|
||||
APP_TITLE = fMSX
|
||||
@ -283,8 +221,5 @@ else ifeq ($(LIBRETRO), fmsx)
|
||||
APP_ICON = ctr/fmsx.png
|
||||
#APP_BANNER = ctr/libretro_banner.png
|
||||
#APP_AUDIO = ctr/silent.wav
|
||||
#APP_SYSTEM_MODE = 64MB
|
||||
#APP_SYSTEM_MODE_EXT = Legacy
|
||||
CTR_LINEAR_HEAP_SIZE = 0x1000000
|
||||
|
||||
endif
|
||||
|
@ -1,18 +0,0 @@
|
||||
|
||||
|
||||
#ifndef CTR_STACK_SIZE
|
||||
#define CTR_STACK_SIZE 0x100000
|
||||
#endif
|
||||
|
||||
#ifndef CTR_LINEAR_HEAP_SIZE
|
||||
#define CTR_LINEAR_HEAP_SIZE 0x600000
|
||||
#endif
|
||||
|
||||
#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 + CTR_STACK_SIZE;
|
23
ctr/ctr_debug.h
Normal file
23
ctr/ctr_debug.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef _CTR_DEBUG_H__
|
||||
#define _CTR_DEBUG_H__
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void wait_for_input(void);
|
||||
void dump_result_value(Result val);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define DEBUG_HOLD() do{printf("%s@%s:%d.\n",__FUNCTION__, __FILE__, __LINE__);fflush(stdout);wait_for_input();}while(0)
|
||||
#define DEBUG_STR(X) printf( "%s: %s\n", #X, (char*)(X))
|
||||
#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))
|
||||
#define DEBUG_ERROR(X) do{if(X)dump_result_value(X)}while(0)
|
||||
#define PRINTFPOS(X,Y) "\x1b["#X";"#Y"H"
|
||||
#define PRINTFPOS_STR(X,Y) "\x1b["X";"Y"H"
|
||||
|
||||
#endif //_CTR_DEBUG_H__
|
273
ctr/ctr_linear.cpp
Normal file
273
ctr/ctr_linear.cpp
Normal file
@ -0,0 +1,273 @@
|
||||
/* from https://github.com/smealum/ctrulib
|
||||
* modified to allow reducing __linear_heap_size at runtime */
|
||||
|
||||
|
||||
#include <3ds.h>
|
||||
#include <stdlib.h>
|
||||
#include <3ds/util/rbtree.h>
|
||||
#include "ctr_debug.h"
|
||||
|
||||
struct MemChunk
|
||||
{
|
||||
u8* addr;
|
||||
u32 size;
|
||||
};
|
||||
|
||||
struct MemBlock
|
||||
{
|
||||
MemBlock *prev, *next;
|
||||
u8* base;
|
||||
u32 size;
|
||||
|
||||
static MemBlock* Create(u8* base, u32 size)
|
||||
{
|
||||
auto b = (MemBlock*)malloc(sizeof(MemBlock));
|
||||
if (!b) return nullptr;
|
||||
b->prev = nullptr;
|
||||
b->next = nullptr;
|
||||
b->base = base;
|
||||
b->size = size;
|
||||
return b;
|
||||
}
|
||||
};
|
||||
|
||||
struct MemPool
|
||||
{
|
||||
MemBlock *first, *last;
|
||||
|
||||
bool Ready() { return first != nullptr; }
|
||||
|
||||
void AddBlock(MemBlock* blk)
|
||||
{
|
||||
blk->prev = last;
|
||||
if (last) last->next = blk;
|
||||
if (!first) first = blk;
|
||||
last = blk;
|
||||
}
|
||||
|
||||
void DelBlock(MemBlock* b)
|
||||
{
|
||||
auto prev = b->prev, &pNext = prev ? prev->next : first;
|
||||
auto next = b->next, &nPrev = next ? next->prev : last;
|
||||
pNext = next;
|
||||
nPrev = prev;
|
||||
free(b);
|
||||
}
|
||||
|
||||
void InsertBefore(MemBlock* b, MemBlock* p)
|
||||
{
|
||||
auto prev = b->prev, &pNext = prev ? prev->next : first;
|
||||
b->prev = p;
|
||||
p->next = b;
|
||||
p->prev = prev;
|
||||
pNext = p;
|
||||
}
|
||||
|
||||
void InsertAfter(MemBlock* b, MemBlock* n)
|
||||
{
|
||||
auto next = b->next, &nPrev = next ? next->prev : last;
|
||||
b->next = n;
|
||||
n->prev = b;
|
||||
n->next = next;
|
||||
nPrev = n;
|
||||
}
|
||||
|
||||
//void CoalesceLeft(MemBlock* b);
|
||||
void CoalesceRight(MemBlock* b);
|
||||
|
||||
bool Allocate(MemChunk& chunk, u32 size, int align);
|
||||
void Deallocate(const MemChunk& chunk);
|
||||
|
||||
void Destroy()
|
||||
{
|
||||
MemBlock* next = nullptr;
|
||||
for (auto b = first; b; b = next)
|
||||
{
|
||||
next = b->next;
|
||||
free(b);
|
||||
}
|
||||
first = nullptr;
|
||||
last = nullptr;
|
||||
}
|
||||
|
||||
//void Dump(const char* title);
|
||||
u32 GetFreeSpace();
|
||||
};
|
||||
|
||||
static rbtree_t sAddrMap;
|
||||
|
||||
struct addrMapNode
|
||||
{
|
||||
rbtree_node node;
|
||||
MemChunk chunk;
|
||||
};
|
||||
|
||||
#define getAddrMapNode(x) rbtree_item((x), addrMapNode, node)
|
||||
|
||||
static int addrMapNodeComparator(const rbtree_node_t* _lhs, const rbtree_node_t* _rhs)
|
||||
{
|
||||
auto lhs = getAddrMapNode(_lhs)->chunk.addr;
|
||||
auto rhs = getAddrMapNode(_rhs)->chunk.addr;
|
||||
if (lhs < rhs)
|
||||
return -1;
|
||||
if (lhs > rhs)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void addrMapNodeDestructor(rbtree_node_t* a)
|
||||
{
|
||||
free(getAddrMapNode(a));
|
||||
}
|
||||
|
||||
static addrMapNode* getNode(void* addr)
|
||||
{
|
||||
addrMapNode n;
|
||||
n.chunk.addr = (u8*)addr;
|
||||
auto p = rbtree_find(&sAddrMap, &n.node);
|
||||
return p ? getAddrMapNode(p) : nullptr;
|
||||
}
|
||||
|
||||
static addrMapNode* newNode(const MemChunk& chunk)
|
||||
{
|
||||
auto p = (addrMapNode*)malloc(sizeof(addrMapNode));
|
||||
if (!p) return nullptr;
|
||||
p->chunk = chunk;
|
||||
return p;
|
||||
}
|
||||
|
||||
static void delNode(addrMapNode* node)
|
||||
{
|
||||
rbtree_remove(&sAddrMap, &node->node, addrMapNodeDestructor);
|
||||
}
|
||||
|
||||
extern u32 __linear_heap, __linear_heap_size;
|
||||
|
||||
static MemPool sLinearPool;
|
||||
static u32 sLinearPool_maxaddr;
|
||||
|
||||
static bool linearInit()
|
||||
{
|
||||
auto blk = MemBlock::Create((u8*)__linear_heap, __linear_heap_size);
|
||||
if (blk)
|
||||
{
|
||||
sLinearPool.AddBlock(blk);
|
||||
sLinearPool_maxaddr = __linear_heap;
|
||||
rbtree_init(&sAddrMap, addrMapNodeComparator);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void* linearMemAlign(size_t size, size_t alignment)
|
||||
{
|
||||
// Enforce minimum alignment
|
||||
if (alignment < 16)
|
||||
alignment = 16;
|
||||
|
||||
// Convert alignment to shift amount
|
||||
int shift;
|
||||
for (shift = 4; shift < 32; shift ++)
|
||||
{
|
||||
if ((1U<<shift) == alignment)
|
||||
break;
|
||||
}
|
||||
if (shift == 32) // Invalid alignment
|
||||
return nullptr;
|
||||
|
||||
// Initialize the pool if it is not ready
|
||||
if (!sLinearPool.Ready() && !linearInit())
|
||||
return nullptr;
|
||||
|
||||
// Allocate the chunk
|
||||
MemChunk chunk;
|
||||
if (!sLinearPool.Allocate(chunk, size, shift))
|
||||
return nullptr;
|
||||
|
||||
auto node = newNode(chunk);
|
||||
if (!node)
|
||||
{
|
||||
sLinearPool.Deallocate(chunk);
|
||||
return nullptr;
|
||||
}
|
||||
if (rbtree_insert(&sAddrMap, &node->node));
|
||||
|
||||
if (sLinearPool_maxaddr < (u32)sLinearPool.last->base)
|
||||
sLinearPool_maxaddr = (u32)sLinearPool.last->base;
|
||||
|
||||
return chunk.addr;
|
||||
}
|
||||
|
||||
void* linearAlloc(size_t size)
|
||||
{
|
||||
// extern PrintConsole* currentConsole;
|
||||
// if(currentConsole->consoleInitialised)
|
||||
// {
|
||||
// printf("linearAlloc : 0x%08X\n", size);
|
||||
// DEBUG_HOLD();
|
||||
// }
|
||||
return linearMemAlign(size, 0x80);
|
||||
}
|
||||
|
||||
void* linearRealloc(void* mem, size_t size)
|
||||
{
|
||||
// TODO
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void linearFree(void* mem)
|
||||
{
|
||||
auto node = getNode(mem);
|
||||
if (!node) return;
|
||||
|
||||
// Free the chunk
|
||||
sLinearPool.Deallocate(node->chunk);
|
||||
|
||||
// Free the node
|
||||
delNode(node);
|
||||
}
|
||||
|
||||
u32 linearSpaceFree()
|
||||
{
|
||||
return sLinearPool.GetFreeSpace();
|
||||
}
|
||||
|
||||
extern "C" u32 ctr_get_linear_free(void)
|
||||
{
|
||||
if(sLinearPool.last->base + sLinearPool.last->size != (u8*)__linear_heap + __linear_heap_size)
|
||||
return 0;
|
||||
return sLinearPool.last->size;
|
||||
}
|
||||
|
||||
extern "C" u32 ctr_get_linear_unused(void)
|
||||
{
|
||||
return __linear_heap + __linear_heap_size - sLinearPool_maxaddr;
|
||||
}
|
||||
|
||||
|
||||
extern "C" void ctr_linear_free_pages(u32 pages)
|
||||
{
|
||||
if(sLinearPool.last->base + sLinearPool.last->size != (u8*)__linear_heap + __linear_heap_size)
|
||||
return;
|
||||
|
||||
u32 size = pages << 12;
|
||||
if(size > sLinearPool.last->size)
|
||||
return;
|
||||
|
||||
sLinearPool.last->size -= size;
|
||||
__linear_heap_size -= size;
|
||||
u32 tmp;
|
||||
svcControlMemory(&tmp, __linear_heap + __linear_heap_size, 0x0, size,
|
||||
MEMOP_FREE, (MemPerm)(MEMPERM_READ | MEMPERM_WRITE));
|
||||
|
||||
// printf("l:0x%08X-->0x%08X(-0x%08X) \n", sLinearPool.last->size + size, sLinearPool.last->size, size);
|
||||
// DEBUG_HOLD();
|
||||
}
|
||||
|
||||
extern "C" void ctr_linear_get_stats(void)
|
||||
{
|
||||
printf("last:\n");
|
||||
printf("0x%08X --> 0x%08X (0x%08X) \n", sLinearPool.last->base,
|
||||
sLinearPool.last->base + sLinearPool.last->size, sLinearPool.last->size);
|
||||
printf("free: 0x%08X unused: 0x%08X \n", ctr_get_linear_unused(), ctr_get_linear_free());
|
||||
}
|
151
ctr/ctr_memory.c
Normal file
151
ctr/ctr_memory.c
Normal file
@ -0,0 +1,151 @@
|
||||
#include <3ds.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "ctr_debug.h"
|
||||
|
||||
//void* malloc(size_t nbytes)
|
||||
//{
|
||||
// void* ret = _malloc_r (_REENT, nbytes);
|
||||
// return ret;
|
||||
//}
|
||||
|
||||
//void free (void* aptr)
|
||||
//{
|
||||
// _free_r (_REENT, aptr);
|
||||
//}
|
||||
|
||||
extern u32 __heapBase;
|
||||
extern u32 __heap_size;
|
||||
extern u32 __stack_bottom;
|
||||
extern u32 __stack_size_extra;
|
||||
extern u32 __stacksize__;
|
||||
|
||||
u32 ctr_get_linear_free(void);
|
||||
u32 ctr_get_linear_unused(void);
|
||||
|
||||
u32 ctr_get_stack_free(void)
|
||||
{
|
||||
extern u32 __stack_bottom;
|
||||
|
||||
uint32_t* stack_bottom_current = (u32*)__stack_bottom;
|
||||
while(*stack_bottom_current++ == 0xFCFCFCFC);
|
||||
stack_bottom_current--;
|
||||
|
||||
return ((u32)stack_bottom_current - __stack_bottom);
|
||||
}
|
||||
|
||||
|
||||
u32 ctr_get_stack_usage(void)
|
||||
{
|
||||
extern u32 __stacksize__;
|
||||
u32 stack_free = ctr_get_stack_free();
|
||||
|
||||
return __stacksize__ > stack_free? __stacksize__ - stack_free: 0;
|
||||
}
|
||||
|
||||
void ctr_linear_free_pages(u32 pages);
|
||||
|
||||
void ctr_free_pages(u32 pages)
|
||||
{
|
||||
if(!pages)
|
||||
return;
|
||||
|
||||
u32 linear_free_pages = ctr_get_linear_free() >> 12;
|
||||
|
||||
if((ctr_get_linear_unused() >> 12) > pages + 0x100)
|
||||
return ctr_linear_free_pages(pages);
|
||||
|
||||
// if(linear_free_pages > pages + 0x400)
|
||||
// return ctr_linear_free_pages(pages);
|
||||
|
||||
u32 stack_free = ctr_get_stack_free();
|
||||
u32 stack_usage = __stacksize__ > stack_free? __stacksize__ - stack_free: 0;
|
||||
|
||||
stack_free = stack_free > __stack_size_extra ? __stack_size_extra : stack_free;
|
||||
|
||||
u32 stack_free_pages = stack_free >> 12;
|
||||
|
||||
if(linear_free_pages + (stack_free_pages - (stack_usage >> 12)) > pages)
|
||||
{
|
||||
stack_free_pages -= (stack_usage >> 12);
|
||||
stack_free_pages = stack_free_pages > pages ? pages : stack_free_pages;
|
||||
linear_free_pages = pages - stack_free_pages;
|
||||
}
|
||||
else if(linear_free_pages + stack_free_pages > pages)
|
||||
stack_free_pages = pages - linear_free_pages;
|
||||
else
|
||||
return;
|
||||
|
||||
if(linear_free_pages)
|
||||
ctr_linear_free_pages(linear_free_pages);
|
||||
|
||||
if(stack_free_pages)
|
||||
{
|
||||
u32 tmp;
|
||||
svcControlMemory(&tmp, __stack_bottom,
|
||||
0x0,
|
||||
stack_free_pages << 12,
|
||||
MEMOP_FREE, MEMPERM_READ | MEMPERM_WRITE);
|
||||
__stack_bottom += stack_free_pages << 12;
|
||||
__stack_size_extra -= stack_free_pages << 12;
|
||||
__stacksize__ -= stack_free_pages << 12;
|
||||
// printf("s:0x%08X-->0x%08X(-0x%08X) \n", stack_free,
|
||||
// stack_free - (stack_free_pages << 12), stack_free_pages << 12);
|
||||
// DEBUG_HOLD();
|
||||
}
|
||||
}
|
||||
|
||||
u32 ctr_get_free_space(void)
|
||||
{
|
||||
u32 app_memory = *((u32*)0x1FF80040);
|
||||
s64 mem_used;
|
||||
svcGetSystemInfo(&mem_used, 0, 1);
|
||||
return app_memory - (u32)mem_used;
|
||||
}
|
||||
|
||||
void ctr_request_free_pages(u32 pages)
|
||||
{
|
||||
u32 free_pages = ctr_get_free_space() >> 12;
|
||||
if (pages > free_pages)
|
||||
{
|
||||
ctr_free_pages(pages - free_pages);
|
||||
free_pages = ctr_get_free_space() >> 12;
|
||||
}
|
||||
}
|
||||
|
||||
void* _sbrk_r(struct _reent *ptr, ptrdiff_t incr)
|
||||
{
|
||||
static u32 sbrk_top = 0;
|
||||
|
||||
if (!sbrk_top)
|
||||
sbrk_top = __heapBase;
|
||||
|
||||
u32 tmp;
|
||||
|
||||
int diff = ((sbrk_top + incr + 0xFFF) & ~0xFFF)
|
||||
- (__heapBase + __heap_size);
|
||||
|
||||
if (diff > 0)
|
||||
{
|
||||
ctr_request_free_pages(diff >> 12);
|
||||
|
||||
if (svcControlMemory(&tmp, __heapBase + __heap_size,
|
||||
0x0, diff, MEMOP_ALLOC, MEMPERM_READ | MEMPERM_WRITE) < 0)
|
||||
{
|
||||
ptr->_errno = ENOMEM;
|
||||
return (caddr_t) -1;
|
||||
}
|
||||
}
|
||||
|
||||
__heap_size += diff;
|
||||
|
||||
if (diff < 0)
|
||||
svcControlMemory(&tmp, __heapBase + __heap_size,
|
||||
0x0, -diff, MEMOP_FREE, MEMPERM_READ | MEMPERM_WRITE);
|
||||
|
||||
sbrk_top += incr;
|
||||
|
||||
return (caddr_t)(sbrk_top - incr);
|
||||
}
|
238
ctr/ctr_system.c
Normal file
238
ctr/ctr_system.c
Normal file
@ -0,0 +1,238 @@
|
||||
|
||||
#include <3ds.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define CTR_APPMEMALLOC_PTR ((u32*)0x1FF80040)
|
||||
|
||||
u32 __stacksize__ = 0x00400000;
|
||||
u32 __linear_heap_size = 0x01000000;
|
||||
|
||||
u32 __heap_size;
|
||||
u32 __linear_heap;
|
||||
u32 __heapBase;
|
||||
|
||||
extern u32 __linear_heap_size_hbl;
|
||||
extern u32 __heap_size_hbl;
|
||||
|
||||
extern void (*__system_retAddr)(void);
|
||||
|
||||
void __destroy_handle_list(void);
|
||||
void __appExit();
|
||||
void __libc_fini_array(void);
|
||||
|
||||
void __libctru_init(void (*retAddr)(void));
|
||||
void __appInit();
|
||||
void __libc_init_array(void);
|
||||
|
||||
|
||||
u32 __stack_bottom;
|
||||
u32 __stack_size_extra;
|
||||
|
||||
void __system_allocateHeaps() {
|
||||
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);
|
||||
// Set up newlib heap
|
||||
extern char* fake_heap_end;
|
||||
fake_heap_end = 0x13F00000;
|
||||
|
||||
}
|
||||
|
||||
Result __sync_fini(void) __attribute__((weak));
|
||||
|
||||
extern char** __system_argv;
|
||||
void __attribute__((noreturn)) __libctru_exit(int rc)
|
||||
{
|
||||
u32 tmp=0;
|
||||
|
||||
if(__system_argv)
|
||||
free(__system_argv);
|
||||
|
||||
// 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);
|
||||
|
||||
if (__stack_size_extra)
|
||||
svcControlMemory(&tmp, __stack_bottom, 0x0, __stack_size_extra, MEMOP_FREE, 0x0);
|
||||
|
||||
// Close some handles
|
||||
__destroy_handle_list();
|
||||
|
||||
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 <string.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;
|
||||
|
||||
__system_argv = malloc(sizeof(char**)*(__system_argc + 1) + argSize);
|
||||
char* argCopy = (char*)__system_argv + sizeof(char**)*(__system_argc + 1);
|
||||
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
||||
//void initSystem(void (*retAddr)(void))
|
||||
//{
|
||||
// __libctru_init(retAddr);
|
||||
// __appInit();
|
||||
// __libc_init_array();
|
||||
|
||||
//}
|
||||
//void __attribute__((noreturn)) __ctru_exit(int rc)
|
||||
//{
|
||||
// __libc_fini_array();
|
||||
// __appExit();
|
||||
// __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);
|
||||
}
|
||||
|
||||
bool select_pressed = false;
|
||||
|
||||
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);
|
||||
#if 0
|
||||
select_pressed = true;
|
||||
#endif
|
||||
|
||||
svcSleepThread(1000000);
|
||||
}
|
||||
}
|
||||
|
||||
int usleep (useconds_t us)
|
||||
{
|
||||
svcSleepThread((int64_t)us * 1000);
|
||||
}
|
||||
|
||||
long sysconf(int name)
|
||||
{
|
||||
switch(name)
|
||||
{
|
||||
case _SC_NPROCESSORS_ONLN:
|
||||
return 2;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
49
ctr/stack_adjust.s
Normal file
49
ctr/stack_adjust.s
Normal file
@ -0,0 +1,49 @@
|
||||
|
||||
.arm
|
||||
.align 2
|
||||
|
||||
.global initSystem
|
||||
.type initSystem, %function
|
||||
|
||||
initSystem:
|
||||
ldr r2, =saved_stack
|
||||
str sp, [r2]
|
||||
str lr, [r2,#4]
|
||||
|
||||
bics sp, sp, #7
|
||||
|
||||
bl __libctru_init
|
||||
|
||||
bl __appInit
|
||||
bl __libc_init_array
|
||||
|
||||
ldr r2, =saved_stack
|
||||
ldr lr, [r2,#4]
|
||||
bx lr
|
||||
|
||||
|
||||
.global __ctru_exit
|
||||
.type __ctru_exit, %function
|
||||
|
||||
__ctru_exit:
|
||||
bl __libc_fini_array
|
||||
bl __appExit
|
||||
|
||||
|
||||
ldr r2, =saved_stack
|
||||
ldr sp, [r2]
|
||||
b __libctru_exit
|
||||
|
||||
.data
|
||||
.align 2
|
||||
__stacksize__:
|
||||
.word 0x100000
|
||||
.weak __stacksize__
|
||||
|
||||
.bss
|
||||
.align 2
|
||||
saved_stack:
|
||||
.space 8
|
||||
|
||||
|
||||
|
@ -174,7 +174,7 @@ AccessControlInfo:
|
||||
|
||||
SystemControlInfo:
|
||||
RemasterVersion: 2
|
||||
StackSize: 0x40000
|
||||
StackSize: 0x4000
|
||||
# Modules that run services listed above should be included below
|
||||
# Maximum 48 dependencies
|
||||
# If a module is listed that isn't present on the 3DS, the title will get stuck at the logo (3ds waves)
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <boolean.h>
|
||||
|
||||
@ -31,6 +30,8 @@
|
||||
#include "retroarch.h"
|
||||
#include "audio/audio_driver.h"
|
||||
|
||||
#include "ctr/ctr_debug.h"
|
||||
|
||||
#ifdef IS_SALAMANDER
|
||||
#include "../../file_ext.h"
|
||||
#else
|
||||
@ -39,90 +40,6 @@
|
||||
|
||||
const char* elf_path_cst = "sdmc:/retroarch/test.3dsx";
|
||||
|
||||
#ifndef DEBUG_HOLD
|
||||
void wait_for_input(void);
|
||||
void dump_result_value(Result val);
|
||||
#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))
|
||||
#define DEBUG_ERROR(X) do{if(X)dump_result_value(X)}while(0)
|
||||
#define PRINTFPOS(X,Y) "\x1b["#X";"#Y"H"
|
||||
#define PRINTFPOS_STR(X,Y) "\x1b["X";"Y"H"
|
||||
#endif
|
||||
|
||||
#define CTR_APPMEMALLOC_PTR ((u32*)0x1FF80040)
|
||||
|
||||
extern char* fake_heap_start;
|
||||
extern char* fake_heap_end;
|
||||
u32 __linear_heap;
|
||||
u32 __heapBase;
|
||||
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);
|
||||
|
||||
void __destroy_handle_list(void);
|
||||
void __appExit();
|
||||
void __libc_fini_array(void);
|
||||
|
||||
void __system_allocateHeaps() {
|
||||
extern unsigned int __service_ptr;
|
||||
u32 tmp=0;
|
||||
int64_t mem_used;
|
||||
u32 mem_available;
|
||||
u32 app_memory;
|
||||
|
||||
svcGetSystemInfo(&mem_used, 0, 1);
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
// Allocate the linear heap
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
static void frontend_ctr_get_environment_settings(int *argc, char *argv[],
|
||||
void *args, void *params_data)
|
||||
{
|
||||
@ -161,9 +78,15 @@ static void frontend_ctr_get_environment_settings(int *argc, char *argv[],
|
||||
fill_pathname_join(g_defaults.path.config, g_defaults.dir.port,
|
||||
"retroarch.cfg", sizeof(g_defaults.path.config));
|
||||
|
||||
*argc = 0;
|
||||
#if 0
|
||||
int i;
|
||||
DEBUG_VAR(*argc);
|
||||
for (i=0; i < *argc; i++)
|
||||
DEBUG_STR(argv[i]);
|
||||
DEBUG_HOLD();
|
||||
#endif
|
||||
|
||||
*argc=0;
|
||||
*argc = 0;
|
||||
|
||||
#ifndef IS_SALAMANDER
|
||||
#if 0
|
||||
@ -324,190 +247,6 @@ static int frontend_ctr_get_rating(void)
|
||||
return 3;
|
||||
}
|
||||
|
||||
bool select_pressed = false;
|
||||
|
||||
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);
|
||||
}
|
||||
#if 0
|
||||
static void ctr_crawl_memory(uint32_t* total_size, uint32_t size)
|
||||
{
|
||||
void* tmp = malloc(size);
|
||||
if(tmp)
|
||||
*total_size += size;
|
||||
else
|
||||
size >>= 1;
|
||||
|
||||
if (size > 4)
|
||||
ctr_crawl_memory(total_size, size);
|
||||
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
void ctr_get_memory_info(uint32_t* available, uint32_t* max_block)
|
||||
{
|
||||
*available = 0;
|
||||
|
||||
ctr_crawl_memory(available, 1<<27);
|
||||
|
||||
void* tmp;
|
||||
*max_block = 0;
|
||||
int i;
|
||||
for (i=27; i>2; i--)
|
||||
{
|
||||
tmp = malloc(*max_block + (1 << i));
|
||||
if(tmp)
|
||||
{
|
||||
*max_block += 1 << i;
|
||||
free(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
uint32_t malloc_calls = 0;
|
||||
uint32_t min_malloc_addr = 0xFFFFFFFF;
|
||||
uint32_t max_malloc_addr = 0x0;
|
||||
|
||||
void* malloc(size_t nbytes)
|
||||
{
|
||||
void* ret = _malloc_r (_REENT, nbytes);
|
||||
|
||||
if (ret)
|
||||
{
|
||||
if(max_malloc_addr < ((uint32_t)ret + nbytes))
|
||||
max_malloc_addr = ((uint32_t)ret + nbytes);
|
||||
|
||||
if(min_malloc_addr > (uint32_t)ret)
|
||||
min_malloc_addr = (uint32_t)ret;
|
||||
}
|
||||
|
||||
malloc_calls++;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void free (void* aptr)
|
||||
{
|
||||
_free_r (_REENT, aptr);
|
||||
}
|
||||
|
||||
uint32_t sbrk_calls = 0;
|
||||
uint32_t sbrk_max_incr = 0;
|
||||
uint32_t sbrk_total_incr = 0;
|
||||
uint32_t sbrk_heap_start = 0;
|
||||
uint32_t sbrk_heap_end = 0;
|
||||
|
||||
#include "errno.h"
|
||||
extern char *fake_heap_end;
|
||||
extern char *fake_heap_start;
|
||||
|
||||
/* Register name faking - works in collusion with the linker. */
|
||||
register char * stack_ptr asm ("sp");
|
||||
|
||||
void * _sbrk_r (struct _reent *ptr, ptrdiff_t incr) {
|
||||
extern char end asm ("__end__"); /* Defined by the linker. */
|
||||
static char * heap_start;
|
||||
|
||||
char * prev_heap_start;
|
||||
char * heap_end;
|
||||
|
||||
if (heap_start == NULL) {
|
||||
if (fake_heap_start == NULL) {
|
||||
heap_start = &end;
|
||||
} else {
|
||||
heap_start = fake_heap_start;
|
||||
}
|
||||
}
|
||||
|
||||
prev_heap_start = heap_start;
|
||||
|
||||
if (fake_heap_end == NULL) {
|
||||
heap_end = stack_ptr;
|
||||
} else {
|
||||
heap_end = fake_heap_end;
|
||||
}
|
||||
|
||||
if (heap_start + incr > heap_end) {
|
||||
ptr->_errno = ENOMEM;
|
||||
return (caddr_t) -1;
|
||||
}
|
||||
|
||||
heap_start += incr;
|
||||
|
||||
sbrk_calls++;
|
||||
if ((incr > 0) && (sbrk_max_incr < incr))
|
||||
sbrk_max_incr = incr;
|
||||
sbrk_total_incr += incr;
|
||||
sbrk_heap_start = (uint32_t) heap_start;
|
||||
sbrk_heap_end = (uint32_t) heap_end;
|
||||
|
||||
return (caddr_t) prev_heap_start;
|
||||
}
|
||||
#endif
|
||||
|
||||
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);
|
||||
#if 0
|
||||
select_pressed = true;
|
||||
#endif
|
||||
|
||||
retro_sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
int usleep (useconds_t us)
|
||||
{
|
||||
svcSleepThread((int64_t)us * 1000);
|
||||
}
|
||||
|
||||
long sysconf(int name)
|
||||
{
|
||||
switch(name)
|
||||
{
|
||||
case _SC_NPROCESSORS_ONLN:
|
||||
return 2;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
enum frontend_architecture frontend_ctr_get_architecture(void)
|
||||
{
|
||||
return FRONTEND_ARCH_ARM;
|
||||
|
@ -461,30 +461,56 @@ static bool ctr_frame(void* data, const void* frame,
|
||||
frames = 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// extern u32 gpuCmdBufOffset;
|
||||
|
||||
// if(!(frames & 0x3F))
|
||||
// {
|
||||
// u32 available,max_block;
|
||||
// void ctr_get_memory_info(u32* available, u32* max_block);
|
||||
|
||||
// ctr_get_memory_info(&available, &max_block);
|
||||
// printf(PRINTFPOS(28,0)"u:0x%08X f:0x%08X b:0x%08X\n", __heap_size - available, available, max_block);
|
||||
// }
|
||||
//#define CTR_INSPECT_MEMORY_USAGE
|
||||
|
||||
#ifdef CTR_INSPECT_MEMORY_USAGE
|
||||
uint32_t ctr_get_stack_usage(void);
|
||||
void ctr_linear_get_stats(void);
|
||||
extern u32 __linear_heap_size;
|
||||
extern u32 __heap_size;
|
||||
|
||||
extern uint32_t sbrk_calls, sbrk_max_incr, sbrk_total_incr, sbrk_heap_start, sbrk_heap_end;
|
||||
printf(PRINTFPOS(25,0)"c:0x%08X m:0x%08X c:0x%08X\n", sbrk_calls, sbrk_max_incr, sbrk_total_incr);
|
||||
printf(PRINTFPOS(26,0)"s:0x%08X e:0x%08X \n", sbrk_heap_start, sbrk_heap_end);
|
||||
extern uint32_t malloc_calls, min_malloc_addr, max_malloc_addr;
|
||||
printf(PRINTFPOS(27,0)"n:0x%08X l:0x%08X h:0x%08X\n", malloc_calls, min_malloc_addr, max_malloc_addr);
|
||||
printf(PRINTFPOS(28,0)"0x%08X 0x%08X 0x%08X\r", __heap_size, gpuCmdBufOffset, (__linear_heap_size - linearSpaceFree() +0x3FF) & ~0x3FF);
|
||||
#endif
|
||||
// printf(PRINTFPOS(29,0)"fps: %8.4f frames: %i (%X)\r", fps, total_frames++, (__linear_heap_size - linearSpaceFree()));
|
||||
MemInfo mem_info;
|
||||
PageInfo page_info;
|
||||
u32 query_addr = 0x08000000;
|
||||
printf(PRINTFPOS(0,0));
|
||||
while (query_addr < 0x40000000)
|
||||
{
|
||||
svcQueryMemory(&mem_info, &page_info, query_addr);
|
||||
printf("0x%08X --> 0x%08X (0x%08X) \n", mem_info.base_addr, mem_info.base_addr + mem_info.size, mem_info.size);
|
||||
query_addr = mem_info.base_addr + mem_info.size;
|
||||
if(query_addr == 0x1F000000)
|
||||
query_addr = 0x30000000;
|
||||
}
|
||||
// static u32* dummy_pointer;
|
||||
// if(total_frames == 500)
|
||||
// dummy_pointer = malloc(0x2000000);
|
||||
// if(total_frames == 1000)
|
||||
// free(dummy_pointer);
|
||||
|
||||
|
||||
printf("========================================");
|
||||
printf("0x%08X 0x%08X 0x%08X\n", __heap_size, gpuCmdBufOffset, (__linear_heap_size - linearSpaceFree()));
|
||||
printf("fps: %8.4f frames: %i (%X)\n", fps, total_frames++, (__linear_heap_size - linearSpaceFree()));
|
||||
printf("========================================");
|
||||
u32 app_memory = *((u32*)0x1FF80040);
|
||||
u64 mem_used;
|
||||
svcGetSystemInfo(&mem_used, 0, 1);
|
||||
printf("total mem : 0x%08X \n", app_memory);
|
||||
printf("used: 0x%08X free: 0x%08X \n", (u32)mem_used, app_memory - (u32)mem_used);
|
||||
static u32 stack_usage = 0;
|
||||
extern u32 __stack_bottom;
|
||||
if(!(total_frames & 0x3F))
|
||||
stack_usage = ctr_get_stack_usage();
|
||||
printf("stack total:0x%08X used: 0x%08X\n", 0x10000000 - __stack_bottom, stack_usage);
|
||||
|
||||
printf("========================================");
|
||||
ctr_linear_get_stats();
|
||||
printf("========================================");
|
||||
|
||||
#else
|
||||
printf(PRINTFPOS(29,0)"fps: %8.4f frames: %i\r", fps, total_frames++);
|
||||
#endif
|
||||
fflush(stdout);
|
||||
|
||||
rarch_perf_init(&ctrframe_f, "ctrframe_f");
|
||||
|
@ -31,14 +31,6 @@
|
||||
|
||||
#define CTRGU_SIZE(W,H) (((u32)(W)&0xFFFF)|((u32)(H)<<16))
|
||||
|
||||
|
||||
/* from ctrulib/great-refactor */
|
||||
#define GPU_TEVOP_RGB_SRC_G 0x8
|
||||
#define GPU_TEVOP_RGB_SRC_B 0xC
|
||||
#define GPU_TEVOP_RGB_SRC_ALPHA 0x2
|
||||
#define GPU_MULTIPLY_ADD 0x8
|
||||
/*******************************/
|
||||
|
||||
/* DMA flags */
|
||||
#define CTRGU_DMA_VFLIP (1 << 0)
|
||||
#define CTRGU_DMA_L_TO_T (1 << 1)
|
||||
@ -62,6 +54,7 @@
|
||||
#ifndef DEBUG_HOLD
|
||||
void wait_for_input(void);
|
||||
#define PRINTFPOS(X,Y) "\x1b["#X";"#Y"H"
|
||||
#define PRINTF_LINE(X) "\x1b["X";0H"
|
||||
#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))
|
||||
|
Loading…
Reference in New Issue
Block a user