(ctr/3ds) optimize build, add support for 32x/svp dynamic recompilers.
authoraliaspider <aliaspider@gmail.com>
Wed, 30 Sep 2015 22:43:20 +0000 (23:43 +0100)
committeraliaspider <aliaspider@gmail.com>
Wed, 30 Sep 2015 22:43:20 +0000 (23:43 +0100)
Makefile.libretro
platform/libretro/3ds/3ds_utils.c [new file with mode: 0644]
platform/libretro/3ds/3ds_utils.h [new file with mode: 0644]
platform/libretro/libretro.c

index dc9bd66..e6766fd 100644 (file)
@@ -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 (file)
index 0000000..e0f76ca
--- /dev/null
@@ -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 (file)
index 0000000..5aa452f
--- /dev/null
@@ -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 <stdio.h>
+#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
index 10af663..8bd6363 100644 (file)
 #include <libkern/OSCacheControl.h>
 #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 <pico/pico_int.h>
 #include <pico/state.h>
 #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(&currentHandle, 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(&currentHandle, 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(&currentHandle, 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(&currentHandle, 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)