From 89d07d48227f39e2226f938eaeba7d2caa6e77f2 Mon Sep 17 00:00:00 2001 From: Ash Logan Date: Fri, 28 Jun 2024 18:56:37 +1000 Subject: [PATCH] libretro, add libmappedmemory option for drc this platform requires *freeing* of the drc memory, so add a hook for that, inside an ifdef so we don't have to touch every platform --- Makefile.libretro | 2 + cpu/drc/cmn.c | 3 ++ pico/pico.h | 1 + platform/libretro/libretro.c | 21 ++++++++-- platform/libretro/wiiu/libmemorymapping.c | 50 +++++++++++++++++++++++ platform/libretro/wiiu/libmemorymapping.h | 10 +++++ 6 files changed, 84 insertions(+), 3 deletions(-) create mode 100644 platform/libretro/wiiu/libmemorymapping.c create mode 100644 platform/libretro/wiiu/libmemorymapping.h diff --git a/Makefile.libretro b/Makefile.libretro index 64cff703c..513fd3bfc 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -290,6 +290,8 @@ else ifeq ($(platform), wiiu) CFLAGS += -DGEKKO -DWIIU -DHW_RVL -DHW_WUP -D__wiiu__ -ffunction-sections -fdata-sections -mcpu=750 -meabi -mhard-float STATIC_LINKING = 1 STATIC_LINKING_LINK = 1 + OBJS += platform/libretro/wiiu/libmemorymapping.o + CFLAGS += -isystem $(DEVKITPRO)/wut/include # Nintendo Switch (libtransistor) else ifeq ($(platform), switch) diff --git a/cpu/drc/cmn.c b/cpu/drc/cmn.c index 65ffd0439..01a3bb638 100644 --- a/cpu/drc/cmn.c +++ b/cpu/drc/cmn.c @@ -57,6 +57,9 @@ void drc_cmn_init(void) void drc_cmn_cleanup(void) { +#ifdef HW_WUP + plat_mem_free_for_drc(tcache); +#endif } // vim:shiftwidth=2:expandtab diff --git a/pico/pico.h b/pico/pico.h index 6759f73d6..d9c2fbe6e 100644 --- a/pico/pico.h +++ b/pico/pico.h @@ -38,6 +38,7 @@ extern void plat_munmap(void *ptr, size_t size); // memory for the dynarec; plat_mem_get_for_drc() can just return NULL extern void *plat_mem_get_for_drc(size_t size); +extern void plat_mem_free_for_drc(void *mem); extern int plat_mem_set_exec(void *ptr, size_t size); // this one should handle display mode changes diff --git a/platform/libretro/libretro.c b/platform/libretro/libretro.c index b94254e34..9a9322cd0 100644 --- a/platform/libretro/libretro.c +++ b/platform/libretro/libretro.c @@ -60,6 +60,9 @@ void linearFree(void* mem); static int ctr_svchack_successful = 0; +#elif defined(HW_WUP) +#include "wiiu/libmemorymapping.h" + #elif defined(VITA) #define TARGET_SIZE_2 24 // 2^24 = 16 megabytes @@ -486,9 +489,13 @@ void *plat_mem_get_for_drc(size_t size) #if defined VITA sceKernelGetMemBlockBase(sceBlock, &mem); #elif defined HW_WUP - // For WiiU, a slice of RWX memory left from the exploit is used, see: - // https://github.com/embercold/pcsx_rearmed/commit/af0453223 - mem = (void *)(0x01000000 - size); + // First try Aroma libmappedmemory... + mem = wiiu_alloc_mappedmemory(size, 4096); + if (!mem) + // Then fall back to RWX memory left from the exploit. + // https://github.com/embercold/pcsx_rearmed/commit/af0453223 + // May want to remove this once Aroma libretro is common. + mem = (void *)(0x01000000 - size); #elif defined __PS3__ ps3mapi_process_page_allocate(sysProcessGetPid(), size, PAGE_SIZE_AUTO, 0x2F, 1, page_table); mem = (void *)page_table[0]; @@ -496,6 +503,14 @@ void *plat_mem_get_for_drc(size_t size) return mem; } +#ifdef HW_WUP +void plat_mem_free_for_drc(void *mem) +{ + wiiu_free_mappedmemory(mem); + wiiu_deinit_mappedmemory(); +} +#endif + int plat_mem_set_exec(void *ptr, size_t size) { int ret = -1; diff --git a/platform/libretro/wiiu/libmemorymapping.c b/platform/libretro/wiiu/libmemorymapping.c new file mode 100644 index 000000000..3b7db6de9 --- /dev/null +++ b/platform/libretro/wiiu/libmemorymapping.c @@ -0,0 +1,50 @@ +#include "libmemorymapping.h" + +#include +#include +#include + +// Aroma libmappedmemory - Maschell promises he won't break ABI here +static void* (**MEMAllocFromMappedMemoryEx)(uint32_t size, int32_t alignment); +static void* (**MEMFreeToMappedMemory)(void *ptr); +static OSDynLoad_Module libmappedmemory; + +static bool wiiu_init_libmappedmemory() { + OSDynLoad_Error err; + + // already ran? + if (MEMAllocFromMappedMemoryEx) + return true; + + err = OSDynLoad_Acquire("homebrew_memorymapping", &libmappedmemory); + if (err != OS_DYNLOAD_OK) + return false; + + err = OSDynLoad_FindExport(libmappedmemory, OS_DYNLOAD_EXPORT_DATA, "MEMAllocFromMappedMemoryEx", (void**)&MEMAllocFromMappedMemoryEx); + if (err != OS_DYNLOAD_OK) + return false; + + err = OSDynLoad_FindExport(libmappedmemory, OS_DYNLOAD_EXPORT_DATA, "MEMFreeToMappedMemory", (void**)&MEMFreeToMappedMemory); + if (err != OS_DYNLOAD_OK) + return false; + + return true; +} + +void *wiiu_alloc_mappedmemory(uint32_t size, int32_t alignment) { + if (!wiiu_init_libmappedmemory()) return NULL; + + return (*MEMAllocFromMappedMemoryEx)(size, alignment); +} + +void wiiu_free_mappedmemory(void *mem) { + if (!wiiu_init_libmappedmemory()) return; + + (*MEMFreeToMappedMemory)(mem); +} + +void wiiu_deinit_mappedmemory(void) { + OSDynLoad_Release(libmappedmemory); + MEMAllocFromMappedMemoryEx = NULL; + MEMFreeToMappedMemory = NULL; +} \ No newline at end of file diff --git a/platform/libretro/wiiu/libmemorymapping.h b/platform/libretro/wiiu/libmemorymapping.h new file mode 100644 index 000000000..91562fcf1 --- /dev/null +++ b/platform/libretro/wiiu/libmemorymapping.h @@ -0,0 +1,10 @@ +#ifndef LIBMEMORYMAPPING_H +#define LIBMEMORYMAPPING_H + +#include + +void *wiiu_alloc_mappedmemory(uint32_t size, int32_t alignment); +void wiiu_free_mappedmemory(void *mem); +void wiiu_deinit_mappedmemory(void); + +#endif // LIBMEMORYMAPPING_H