From 0c73267625a4acebfbea8b4ef048c51ee96155d3 Mon Sep 17 00:00:00 2001 From: aliaspider Date: Wed, 30 Sep 2015 23:43:20 +0100 Subject: [PATCH] (ctr/3ds) optimize build, add support for 32x/svp dynamic recompilers. --- Makefile.libretro | 36 +++--- platform/libretro/3ds/3ds_utils.c | 78 ++++++++++++ platform/libretro/3ds/3ds_utils.h | 18 +++ platform/libretro/libretro.c | 198 ++++++++++++++++++++++++++++-- 4 files changed, 303 insertions(+), 27 deletions(-) create mode 100644 platform/libretro/3ds/3ds_utils.c create mode 100644 platform/libretro/3ds/3ds_utils.h diff --git a/Makefile.libretro b/Makefile.libretro index dc9bd66a..e6766fd9 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -193,27 +193,31 @@ else ifeq ($(platform), ctr) CXX = $(DEVKITARM)/bin/arm-none-eabi-g++$(EXE_EXT) AR = $(DEVKITARM)/bin/arm-none-eabi-ar$(EXE_EXT) CFLAGS += -DARM11 -D_3DS - CFLAGS += -march=armv6k -mtune=mpcore -mfloat-abi=hard + CFLAGS += -march=armv6k -mtune=mpcore -mfloat-abi=hard -marm -mfpu=vfp CFLAGS += -Wall -mword-relocations CFLAGS += -fomit-frame-pointer -ffast-math - CFLAGS += -D_3DS - PLATFORM_DEFINES := -D_3DS STATIC_LINKING = 1 NO_MMAP = 1 DONT_COMPILE_IN_ZLIB = 1 - - asm_memory = 0 - asm_render = 0 - asm_ym2612 = 0 - asm_misc = 0 - asm_cdpico = 0 - asm_cdmemory = 0 - asm_mix = 0 - use_cyclone = 0 - use_fame = 1 - use_drz80 = 0 - use_cz80 = 1 - + ARCH = arm + ARM_ASM = 1 + + asm_memory = 1 + asm_render = 1 + asm_ym2612 = 1 + asm_misc = 1 + asm_cdpico = 1 + asm_cdmemory = 1 + asm_mix = 1 + + use_cyclone = 1 + use_fame = 0 + use_drz80 = 1 + use_cz80 = 0 + use_sh2drc = 1 + use_svpdrc = 1 + + OBJS +=platform/libretro/3ds/3ds_utils.o # Vita else ifeq ($(platform), vita) diff --git a/platform/libretro/3ds/3ds_utils.c b/platform/libretro/3ds/3ds_utils.c new file mode 100644 index 00000000..e0f76ca2 --- /dev/null +++ b/platform/libretro/3ds/3ds_utils.c @@ -0,0 +1,78 @@ + +#include "3ds_utils.h" + +typedef int (*ctr_callback_type)(void); + +int srvGetServiceHandle(unsigned int* out, const char* name); +int svcCloseHandle(unsigned int handle); +int svcBackdoor(ctr_callback_type); + + +static void ctr_enable_all_svc_kernel(void) +{ + __asm__ volatile("cpsid aif"); + + unsigned int* svc_access_control = *(*(unsigned int***)0xFFFF9000 + 0x22) - 0x6; + + svc_access_control[0]=0xFFFFFFFE; + svc_access_control[1]=0xFFFFFFFF; + svc_access_control[2]=0xFFFFFFFF; + svc_access_control[3]=0x3FFFFFFF; +} + + +static void ctr_invalidate_ICache_kernel(void) +{ + __asm__ volatile( + "cpsid aif\n\t" + "mov r0, #0\n\t" + "mcr p15, 0, r0, c7, c5, 0\n\t"); +} + +static void ctr_flush_DCache_kernel(void) +{ + __asm__ volatile( + "cpsid aif\n\t" + "mov r0, #0\n\t" + "mcr p15, 0, r0, c7, c10, 0\n\t"); + +} + + +static void ctr_enable_all_svc(void) +{ + svcBackdoor((ctr_callback_type)ctr_enable_all_svc_kernel); +} + +void ctr_invalidate_ICache(void) +{ +// __asm__ volatile("svc 0x2E\n\t"); + svcBackdoor((ctr_callback_type)ctr_invalidate_ICache_kernel); + +} + +void ctr_flush_DCache(void) +{ +// __asm__ volatile("svc 0x4B\n\t"); + svcBackdoor((ctr_callback_type)ctr_flush_DCache_kernel); +} + + +void ctr_flush_invalidate_cache(void) +{ + ctr_flush_DCache(); + ctr_invalidate_ICache(); +} + +int ctr_svchack_init(void) +{ + extern unsigned int __service_ptr; + + if(__service_ptr) + return 0; + + /* CFW */ + ctr_enable_all_svc(); + return 1; +} + diff --git a/platform/libretro/3ds/3ds_utils.h b/platform/libretro/3ds/3ds_utils.h new file mode 100644 index 00000000..5aa452f6 --- /dev/null +++ b/platform/libretro/3ds/3ds_utils.h @@ -0,0 +1,18 @@ +#ifndef _3DS_UTILS_H +#define _3DS_UTILS_H + +void ctr_invalidate_ICache(void); +void ctr_flush_DCache(void); + +void ctr_flush_invalidate_cache(void); + +int ctr_svchack_init(void); + + + +#include +#define DEBUG_HOLD() do{printf("%s@%s:%d.\n",__FUNCTION__, __FILE__, __LINE__);fflush(stdout);wait_for_input();}while(0) + +void wait_for_input(void); + +#endif // _3DS_UTILS_H diff --git a/platform/libretro/libretro.c b/platform/libretro/libretro.c index 10af6637..8bd6363f 100644 --- a/platform/libretro/libretro.c +++ b/platform/libretro/libretro.c @@ -24,6 +24,19 @@ #include #endif +#ifdef _3DS +#include "3ds/3ds_utils.h" +#define MEMOP_PROT 6 +int svcDuplicateHandle(unsigned int* out, unsigned int original); +int svcCloseHandle(unsigned int handle); +int svcControlProcessMemory(unsigned int process, void* addr0, void* addr1, + unsigned int size, unsigned int type, unsigned int perm); +#define MEMOP_MAP 4 +#define MEMOP_UNMAP 5 + +static int ctr_svchack_successful = 0; +#endif + #include #include #include "../common/input_pico.h" @@ -67,8 +80,10 @@ void cache_flush_d_inval_i(void *start, void *end) size_t len = (char *)end - (char *)start; sys_dcache_flush(start, len); sys_icache_invalidate(start, len); +#elif defined(_3DS) + ctr_flush_invalidate_cache(); #else - __clear_cache(start, end); + __clear_cache(start, end); #endif #endif } @@ -190,7 +205,7 @@ void munmap(void *base_addr, size_t len) int mprotect(void *addr, size_t len, int prot) { - /* stub - not really needed at this point since this codepath has no dynarecs */ + /* stub - not really needed at this point since this codepath has no dynarecs */ return 0; } @@ -200,6 +215,134 @@ int mprotect(void *addr, size_t len, int prot) #define MAP_ANONYMOUS MAP_ANON #endif +#ifdef _3DS +typedef struct +{ + unsigned int requested_map; + void* buffer; +}pico_mmap_t; + +pico_mmap_t pico_mmaps[] = { + {0x02000000, 0}, + {0x06000000, 0}, + {NULL, 0} +}; + +void *plat_mmap(unsigned long addr, size_t size, int need_exec, int is_fixed) +{ + (void)is_fixed; + + if (ctr_svchack_successful) + { + pico_mmap_t* pico_mmap; + + for (pico_mmap = pico_mmaps; pico_mmap->requested_map; pico_mmap++) + { + if ((pico_mmap->requested_map == addr)) + { + unsigned int ptr_aligned, tmp; + unsigned int currentHandle; + unsigned int perm = 0b011; + + if (need_exec) + perm = 0b111; + + size = (size + 0xFFF) & ~0xFFF; + pico_mmap->buffer = malloc(size + 0x1000); + ptr_aligned = (((unsigned int)pico_mmap->buffer) + 0xFFF) & ~0xFFF; + + svcDuplicateHandle(¤tHandle, 0xFFFF8001); + + if(svcControlProcessMemory(currentHandle, pico_mmap->requested_map, ptr_aligned, size, MEMOP_MAP, perm) < 0) + { + if (log_cb) + log_cb(RETRO_LOG_ERROR, "could not map memory @0x%08X\n", pico_mmap->requested_map); + exit(1); + } + + svcCloseHandle(currentHandle); + return (void*)pico_mmap->requested_map; + } + } + } + + return malloc(size); +} + +void *plat_mremap(void *ptr, size_t oldsize, size_t newsize) +{ + if (ctr_svchack_successful) + { + pico_mmap_t* pico_mmap; + + for (pico_mmap = pico_mmaps; pico_mmap->requested_map; pico_mmap++) + { + if ((pico_mmap->requested_map == (unsigned int)ptr)) + { + unsigned int ptr_aligned; + unsigned int currentHandle; + void* tmp; + + oldsize = (oldsize + 0xFFF) & ~0xFFF; + newsize = (newsize + 0xFFF) & ~0xFFF; + ptr_aligned = (((unsigned int)pico_mmap->buffer) + 0xFFF) & ~0xFFF; + + svcDuplicateHandle(¤tHandle, 0xFFFF8001); + + svcControlProcessMemory(currentHandle, pico_mmap->requested_map, ptr_aligned, oldsize, MEMOP_UNMAP, 0b011); + + tmp = realloc(pico_mmap->buffer, newsize + 0x1000); + if(!tmp) + return NULL; + + pico_mmap->buffer = tmp; + ptr_aligned = (((unsigned int)pico_mmap->buffer) + 0xFFF) & ~0xFFF; + + svcControlProcessMemory(currentHandle, pico_mmap->requested_map, ptr_aligned, newsize, MEMOP_MAP, 0x3); + + svcCloseHandle(currentHandle); + + return ptr; + } + } + } + + return realloc(ptr, newsize); + +} +void plat_munmap(void *ptr, size_t size) +{ + if (ctr_svchack_successful) + { + pico_mmap_t* pico_mmap; + + for (pico_mmap = pico_mmaps; pico_mmap->requested_map; pico_mmap++) + { + if ((pico_mmap->requested_map == (unsigned int)ptr)) + { + unsigned int ptr_aligned; + unsigned int currentHandle; + + size = (size + 0xFFF) & ~0xFFF; + ptr_aligned = (((unsigned int)pico_mmap->buffer) + 0xFFF) & ~0xFFF; + + svcDuplicateHandle(¤tHandle, 0xFFFF8001); + + svcControlProcessMemory(currentHandle, (void*)pico_mmap->requested_map, (void*)ptr_aligned, size, MEMOP_UNMAP, 0b011); + + svcCloseHandle(currentHandle); + + free(pico_mmap->buffer); + pico_mmap->buffer = NULL; + return; + } + } + } + + free(ptr); +} + +#else void *plat_mmap(unsigned long addr, size_t size, int need_exec, int is_fixed) { int flags = MAP_PRIVATE | MAP_ANONYMOUS; @@ -265,6 +408,7 @@ void plat_munmap(void *ptr, size_t size) if (ptr != NULL) munmap(ptr, size); } +#endif int plat_mem_set_exec(void *ptr, size_t size) { @@ -272,6 +416,26 @@ int plat_mem_set_exec(void *ptr, size_t size) int ret = VirtualProtect(ptr,size,PAGE_EXECUTE_READWRITE,0); if (ret == 0 && log_cb) log_cb(RETRO_LOG_ERROR, "mprotect(%p, %zd) failed: %d\n", ptr, size, 0); +#elif defined(_3DS) + int ret = -1; + if (ctr_svchack_successful) + { + unsigned int currentHandle; + svcDuplicateHandle(¤tHandle, 0xFFFF8001); + ret = svcControlProcessMemory(currentHandle, ptr, 0x0, + size, MEMOP_PROT, 0b111); + svcCloseHandle(currentHandle); + ctr_flush_invalidate_cache(); + + } + else + { + if (log_cb) + log_cb(RETRO_LOG_ERROR, "plat_mem_set_exec called with no svcControlProcessMemory access\n"); + exit(1); + } + + #else int ret = mprotect(ptr, size, PROT_READ | PROT_WRITE | PROT_EXEC); if (ret != 0 && log_cb) @@ -302,7 +466,8 @@ void lprintf(const char *fmt, ...) vsprintf(buffer, fmt, ap); /* TODO - add 'level' param for warning/error messages? */ if (log_cb) - log_cb(RETRO_LOG_INFO, "%s\n", fmt); + log_cb(RETRO_LOG_INFO, "%s\n", fmt, ap); + va_end(ap); } /* libretro */ @@ -1001,6 +1166,10 @@ static void update_variables(void) PicoOpt &= ~POPT_EN_DRC; } #endif +#ifdef _3DS + if(!ctr_svchack_successful) + PicoOpt &= ~POPT_EN_DRC; +#endif } void retro_run(void) @@ -1011,7 +1180,7 @@ void retro_run(void) if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated) update_variables(); - input_poll_cb(); + input_poll_cb(); PicoPad[0] = PicoPad[1] = 0; for (pad = 0; pad < 2; pad++) @@ -1047,29 +1216,36 @@ void retro_init(void) environ_cb(RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE, &disk_control); +#ifdef _3DS + ctr_svchack_successful = ctr_svchack_init(); +#endif + PicoOpt = POPT_EN_STEREO|POPT_EN_FM|POPT_EN_PSG|POPT_EN_Z80 | POPT_EN_MCD_PCM|POPT_EN_MCD_CDDA|POPT_EN_MCD_GFX | POPT_EN_32X|POPT_EN_PWM | POPT_ACC_SPRITES|POPT_DIS_32C_BORDER; #ifdef __arm__ - PicoOpt |= POPT_EN_DRC; +#ifdef _3DS + if (ctr_svchack_successful) +#endif + PicoOpt |= POPT_EN_DRC; #endif PsndRate = 44100; PicoAutoRgnOrder = 0x184; // US, EU, JP vout_width = 320; - vout_height = 240; - vout_buf = malloc(VOUT_MAX_WIDTH * VOUT_MAX_HEIGHT * 2); + vout_height = 240; + vout_buf = malloc(VOUT_MAX_WIDTH * VOUT_MAX_HEIGHT * 2); - PicoInit(); - PicoDrawSetOutFormat(PDF_RGB555, 0); - PicoDrawSetOutBuf(vout_buf, vout_width * 2); + PicoInit(); + PicoDrawSetOutFormat(PDF_RGB555, 0); + PicoDrawSetOutBuf(vout_buf, vout_width * 2); //PicoMessage = plat_status_msg_busy_next; PicoMCDopenTray = disk_tray_open; PicoMCDcloseTray = disk_tray_close; - update_variables(); + update_variables(); } void retro_deinit(void) -- 2.39.5