From 9fe9493701a0ae86adc3f56d6d1cd318a5875d70 Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Sat, 3 Oct 2015 16:33:48 -0700 Subject: [PATCH] Dynamically allocate shared memory. --- libctru/include/3ds/mappable.h | 6 +++ libctru/include/3ds/services/csnd.h | 1 - libctru/include/3ds/services/hid.h | 4 +- libctru/include/3ds/services/irrst.h | 4 +- libctru/source/allocator/mappable.cpp | 61 +++++++++++++++++++++++++++ libctru/source/gfx.c | 9 +++- libctru/source/services/csnd.c | 33 ++++++++++++--- libctru/source/services/hid.c | 28 +++++++++--- libctru/source/services/irrst.c | 25 +++++++++-- libctru/source/system/appInit.c | 2 +- 10 files changed, 149 insertions(+), 24 deletions(-) create mode 100644 libctru/include/3ds/mappable.h create mode 100644 libctru/source/allocator/mappable.cpp diff --git a/libctru/include/3ds/mappable.h b/libctru/include/3ds/mappable.h new file mode 100644 index 0000000..5df8c5e --- /dev/null +++ b/libctru/include/3ds/mappable.h @@ -0,0 +1,6 @@ +#pragma once + +// Functions for allocating/deallocating mappable memory +void* mappableAlloc(size_t size); // returns a page-aligned address +void mappableFree(void* mem); +u32 mappableSpaceFree(); // get free mappable space in bytes diff --git a/libctru/include/3ds/services/csnd.h b/libctru/include/3ds/services/csnd.h index e3258a0..16ad2be 100644 --- a/libctru/include/3ds/services/csnd.h +++ b/libctru/include/3ds/services/csnd.h @@ -2,7 +2,6 @@ #include <3ds/types.h> #define CSND_NUM_CHANNELS 32 -#define CSND_SHAREDMEM_DEFAULT 0x10004000 #define CSND_TIMER(n) (0x3FEC3FC / ((u32)(n))) diff --git a/libctru/include/3ds/services/hid.h b/libctru/include/3ds/services/hid.h index 87a99cf..dafc009 100644 --- a/libctru/include/3ds/services/hid.h +++ b/libctru/include/3ds/services/hid.h @@ -2,8 +2,6 @@ //See also: http://3dbrew.org/wiki/HID_Services http://3dbrew.org/wiki/HID_Shared_Memory -#define HID_SHAREDMEM_DEFAULT (0x10000000) - typedef enum { KEY_A = BIT(0), @@ -75,7 +73,7 @@ typedef enum extern Handle hidMemHandle; extern vu32* hidSharedMem; -Result hidInit(u32* sharedMem); +Result hidInit(); void hidExit(); void hidScanInput(); diff --git a/libctru/include/3ds/services/irrst.h b/libctru/include/3ds/services/irrst.h index 2390eb4..cf2085e 100644 --- a/libctru/include/3ds/services/irrst.h +++ b/libctru/include/3ds/services/irrst.h @@ -4,12 +4,10 @@ #include "3ds/services/hid.h" // for circlePosition definition -#define IRRST_SHAREDMEM_DEFAULT (0x1000A000) - extern Handle irrstMemHandle; extern vu32* irrstSharedMem; -Result irrstInit(u32* sharedMem); +Result irrstInit(); void irrstExit(); void irrstScanInput(); diff --git a/libctru/source/allocator/mappable.cpp b/libctru/source/allocator/mappable.cpp new file mode 100644 index 0000000..f0c7ba5 --- /dev/null +++ b/libctru/source/allocator/mappable.cpp @@ -0,0 +1,61 @@ +extern "C" +{ + #include <3ds/types.h> + #include <3ds/mappable.h> + #include <3ds/util/rbtree.h> +} + +#include "mem_pool.h" +#include "addrmap.h" + +static MemPool sMappablePool; + +static bool mappableInit() +{ + auto blk = MemBlock::Create((u8*)0x10000000, 0x04000000); + if (blk) + { + sMappablePool.AddBlock(blk); + rbtree_init(&sAddrMap, addrMapNodeComparator); + return true; + } + return false; +} + +void* mappableAlloc(size_t size) +{ + // Initialize the pool if it is not ready + if (!sMappablePool.Ready() && !mappableInit()) + return nullptr; + + // Allocate the chunk + MemChunk chunk; + if (!sMappablePool.Allocate(chunk, size, 12)) + return nullptr; + + auto node = newNode(chunk); + if (!node) + { + sMappablePool.Deallocate(chunk); + return nullptr; + } + if (rbtree_insert(&sAddrMap, &node->node)); + return chunk.addr; +} + +void mappableFree(void* mem) +{ + auto node = getNode(mem); + if (!node) return; + + // Free the chunk + sMappablePool.Deallocate(node->chunk); + + // Free the node + delNode(node); +} + +u32 mappableSpaceFree() +{ + return sMappablePool.GetFreeSpace(); +} diff --git a/libctru/source/gfx.c b/libctru/source/gfx.c index 0688804..f0b68a3 100644 --- a/libctru/source/gfx.c +++ b/libctru/source/gfx.c @@ -5,6 +5,7 @@ #include <3ds/gfx.h> #include <3ds/svc.h> #include <3ds/linear.h> +#include <3ds/mappable.h> #include <3ds/vram.h> GSP_FramebufferInfo topFramebufferInfo, bottomFramebufferInfo; @@ -116,7 +117,7 @@ void gfxInit(GSP_FramebufferFormats topFormat, GSP_FramebufferFormats bottomForm gspInit(); - gfxSharedMemory=(u8*)0x10002000; + gfxSharedMemory=(u8*)mappableAlloc(0x1000); GSPGPU_AcquireRight(NULL, 0x0); @@ -191,6 +192,12 @@ void gfxExit() GSPGPU_UnregisterInterruptRelayQueue(NULL); svcCloseHandle(gspSharedMemHandle); + if(gfxSharedMemory != NULL) + { + mappableFree(gfxSharedMemory); + gfxSharedMemory = NULL; + } + svcCloseHandle(gspEvent); GSPGPU_ReleaseRight(NULL); diff --git a/libctru/source/services/csnd.c b/libctru/source/services/csnd.c index d034237..2832062 100644 --- a/libctru/source/services/csnd.c +++ b/libctru/source/services/csnd.c @@ -3,6 +3,7 @@ #include <3ds/types.h> #include <3ds/svc.h> #include <3ds/srv.h> +#include <3ds/mappable.h> #include <3ds/os.h> #include <3ds/services/csnd.h> @@ -118,7 +119,6 @@ Result CSND_Reset(void) Result csndInit(void) { Result ret=0; - csndSharedMem = (vu32*)CSND_SHAREDMEM_DEFAULT; // TODO: proper error handling! @@ -133,17 +133,33 @@ Result csndInit(void) csndSharedMemSize = csndOffsets[3] + 0x3C; // Total size of the CSND shared memory ret = CSND_Initialize(); - if (ret != 0) return ret; + if (ret != 0) goto cleanup1; + + csndSharedMem = (vu32*)mappableAlloc(csndSharedMemSize); + if(!csndSharedMem) + { + ret = -1; + goto cleanup1; + } ret = svcMapMemoryBlock(csndSharedMemBlock, (u32)csndSharedMem, 3, 0x10000000); - if (ret != 0) return ret; + if (ret != 0) goto cleanup2; memset((void*)csndSharedMem, 0, csndSharedMemSize); ret = CSND_AcquireSoundChannels(&csndChannels); - if (ret != 0) return ret; + if (!ret) return 0; - return 0; +cleanup2: + svcCloseHandle(csndSharedMemBlock); + if(csndSharedMem != NULL) + { + mappableFree((void*) csndSharedMem); + csndSharedMem = NULL; + } +cleanup1: + svcCloseHandle(csndHandle); + return ret; } Result csndExit(void) @@ -161,6 +177,13 @@ Result csndExit(void) ret = CSND_Shutdown(); svcCloseHandle(csndHandle); + + if(csndSharedMem != NULL) + { + mappableFree((void*) csndSharedMem); + csndSharedMem = NULL; + } + return ret; } diff --git a/libctru/source/services/hid.c b/libctru/source/services/hid.c index 7eeb29d..1be6050 100644 --- a/libctru/source/services/hid.c +++ b/libctru/source/services/hid.c @@ -6,6 +6,7 @@ #include <3ds/types.h> #include <3ds/svc.h> #include <3ds/srv.h> +#include <3ds/mappable.h> #include <3ds/services/apt.h> #include <3ds/services/hid.h> #include <3ds/services/irrst.h> @@ -25,30 +26,34 @@ static angularRate gRate; static bool hidInitialised; -Result hidInit(u32* sharedMem) +Result hidInit() { u8 val=0; Result ret=0; if(hidInitialised) return ret; - if(!sharedMem)sharedMem=(u32*)HID_SHAREDMEM_DEFAULT; - // Request service. if((ret=srvGetServiceHandle(&hidHandle, "hid:USER")) && (ret=srvGetServiceHandle(&hidHandle, "hid:SPVR")))return ret; // Get sharedmem handle. if((ret=HIDUSER_GetHandles(&hidMemHandle, &hidEvents[HIDEVENT_PAD0], &hidEvents[HIDEVENT_PAD1], &hidEvents[HIDEVENT_Accel], &hidEvents[HIDEVENT_Gyro], &hidEvents[HIDEVENT_DebugPad]))) goto cleanup1; - // Map HID shared memory at addr "sharedMem". - hidSharedMem=sharedMem; + // Map HID shared memory. + hidSharedMem=(vu32*)mappableAlloc(0x2b0); + if(!hidSharedMem) + { + ret = -1; + goto cleanup1; + } + if((ret=svcMapMemoryBlock(hidMemHandle, (u32)hidSharedMem, MEMPERM_READ, 0x10000000)))goto cleanup2; APT_CheckNew3DS(NULL, &val); if(val) { - ret = irrstInit(NULL); + ret = irrstInit(); } // Reset internal state. @@ -58,6 +63,11 @@ Result hidInit(u32* sharedMem) cleanup2: svcCloseHandle(hidMemHandle); + if(hidSharedMem != NULL) + { + mappableFree((void*) hidSharedMem); + hidSharedMem = NULL; + } cleanup1: svcCloseHandle(hidHandle); return ret; @@ -80,6 +90,12 @@ void hidExit() { irrstExit(); } + + if(hidSharedMem != NULL) + { + mappableFree((void*) hidSharedMem); + hidSharedMem = NULL; + } hidInitialised = false; } diff --git a/libctru/source/services/irrst.c b/libctru/source/services/irrst.c index 14abbcb..083d2a6 100644 --- a/libctru/source/services/irrst.c +++ b/libctru/source/services/irrst.c @@ -6,6 +6,7 @@ #include <3ds/types.h> #include <3ds/svc.h> #include <3ds/srv.h> +#include <3ds/mappable.h> #include <3ds/services/irrst.h> // used to determine whether or not we should do IRRST_Initialize @@ -21,11 +22,10 @@ static u32 kHeld; static circlePosition csPos; static bool irrstUsed = false; -Result irrstInit(u32* sharedMem) +Result irrstInit() { if(irrstUsed)return 0; - if(!sharedMem)sharedMem=(u32*)IRRST_SHAREDMEM_DEFAULT; Result ret=0; // Request service. @@ -37,8 +37,14 @@ Result irrstInit(u32* sharedMem) // Initialize ir:rst if(__get_handle_from_list("ir:rst")==0)ret=IRRST_Initialize(10, 0); - // Map ir:rst shared memory at addr "sharedMem". - irrstSharedMem=sharedMem; + // Map ir:rst shared memory. + irrstSharedMem=(vu32*)mappableAlloc(0x98); + if(!irrstSharedMem) + { + ret = -1; + goto cleanup1; + } + if((ret=svcMapMemoryBlock(irrstMemHandle, (u32)irrstSharedMem, MEMPERM_READ, 0x10000000)))goto cleanup2; // Reset internal state. @@ -48,6 +54,11 @@ Result irrstInit(u32* sharedMem) cleanup2: svcCloseHandle(irrstMemHandle); + if(irrstSharedMem != NULL) + { + mappableFree((void*) irrstSharedMem); + irrstSharedMem = NULL; + } cleanup1: svcCloseHandle(irrstHandle); return ret; @@ -64,6 +75,12 @@ void irrstExit() if(__get_handle_from_list("ir:rst")==0) IRRST_Shutdown(); svcCloseHandle(irrstMemHandle); svcCloseHandle(irrstHandle); + + if(irrstSharedMem != NULL) + { + mappableFree((void*) irrstSharedMem); + irrstSharedMem = NULL; + } } void irrstWaitForEvent(bool nextEvent) diff --git a/libctru/source/system/appInit.c b/libctru/source/system/appInit.c index ac90ae6..c3213e0 100644 --- a/libctru/source/system/appInit.c +++ b/libctru/source/system/appInit.c @@ -10,7 +10,7 @@ void __attribute__((weak)) __appInit() { // Initialize services srvInit(); aptInit(); - hidInit(NULL); + hidInit(); fsInit(); sdmcInit();