From eb9a98bcf968b1500ca5ceee4a18b8c57741d176 Mon Sep 17 00:00:00 2001 From: DiscostewSM Date: Mon, 6 Feb 2017 11:52:57 -0800 Subject: [PATCH 1/2] Assignable VRAM bank allocations This change integrates being able to allocate to a specific VRAM bank into the existing implementation. --- libctru/include/3ds/allocator/vram.h | 36 ++++++++++- libctru/source/allocator/vram.cpp | 90 +++++++++++++++++++++++----- 2 files changed, 109 insertions(+), 17 deletions(-) diff --git a/libctru/include/3ds/allocator/vram.h b/libctru/include/3ds/allocator/vram.h index 4355b2f..ed1fd28 100644 --- a/libctru/include/3ds/allocator/vram.h +++ b/libctru/include/3ds/allocator/vram.h @@ -4,6 +4,21 @@ */ #pragma once +typedef enum +{ + VRAM_A = 0x00; + VRAM_B = 0x01; + VRAM_AB = 0x02; +} VRAM_ALLOCATOR; + +/** + * @brief Allocates a 0x80-byte aligned buffer to a specific VRAM bank. + * @param bank The bank to which the buffer will reside. + * @param size Size of the buffer to allocate. + * @return The allocated buffer. + */ +void* vramBankAlloc(VRAM_ALLOCATOR bank, size_t size); + /** * @brief Allocates a 0x80-byte aligned buffer. * @param size Size of the buffer to allocate. @@ -11,6 +26,15 @@ */ void* vramAlloc(size_t size); +/** + * @brief Allocates a buffer aligned to the given size in a specific bank. + * @param bank The bank to which the buffer will reside + * @param size Size of the buffer to allocate. + * @param alignment Alignment to use. + * @return The allocated buffer. + */ +void* vramBankMemAlign(VRAM_ALLOCATOR bank, size_t size, size_t alignment); + /** * @brief Allocates a buffer aligned to the given size. * @param size Size of the buffer to allocate. @@ -35,7 +59,13 @@ void* vramRealloc(void* mem, size_t size); void vramFree(void* mem); /** - * @brief Gets the current VRAM free space. - * @return The current VRAM free space. + * @brief Gets the current VRAM bank free space. + * @return The current VRAM bank free space. */ -u32 vramSpaceFree(void); +u32 vramBankSpaceFree(VRAM_ALLOCATOR bank); + +/** + * @brief Gets the current overall VRAM free space. + * @return The current overall VRAM free space. + */ +u32 vramSpaceFree(void); \ No newline at end of file diff --git a/libctru/source/allocator/vram.cpp b/libctru/source/allocator/vram.cpp index 4161d7c..c92202e 100644 --- a/libctru/source/allocator/vram.cpp +++ b/libctru/source/allocator/vram.cpp @@ -8,21 +8,28 @@ extern "C" #include "mem_pool.h" #include "addrmap.h" -static MemPool sVramPool; +static MemPool sVramPoolA; +static MemPool sVramPoolB; static bool vramInit() { - auto blk = MemBlock::Create((u8*)0x1F000000, 0x00600000); - if (blk) + auto blkA = MemBlock::Create((u8*)0x1F000000, 0x00300000); + if (blkA) { - sVramPool.AddBlock(blk); - rbtree_init(&sAddrMap, addrMapNodeComparator); - return true; + auto blkB = MemBlock::Create((u8*)0x1F300000, 0x00300000); + if(blkB) + { + sVramPoolA.AddBlock(blkA); + sVramPoolB.Addblock(blkB); + rbtree_init(&sAddrMap, addrMapNodeComparator); + return true; + } + free(blkA); } return false; } -void* vramMemAlign(size_t size, size_t alignment) +void* vramBankMemAlign(VRAM_ALLOCATOR bank, size_t size, size_t alignment) { // Enforce minimum alignment if (alignment < 16) @@ -39,27 +46,65 @@ void* vramMemAlign(size_t size, size_t alignment) return nullptr; // Initialize the pool if it is not ready - if (!sVramPool.Ready() && !vramInit()) + if (!sVramPoolA.Ready() && !sVramPoolB.Ready() && !vramInit()) return nullptr; // Allocate the chunk MemChunk chunk; - if (!sVramPool.Allocate(chunk, size, shift)) - return nullptr; + int bankSet; + if(bank != VRAM_B) + { + // Attempt Bank A (for both cases) + if(!sVramPoolA.Allocate(chunk, size, shift)) + { + if(bank == VRAM_A) + return nullptr; + else + { + // Attempt Bank B + if(!sVramPoolB.Allocate(chunk, size, shift)) + return nullptr; + bankSet = 1; + } + } + else + bankset = 0; + } + else + { + // Attempt Bank B only + if(!sVramPoolB.Allocate(chunk, size, shift)) + return nullptr; + bankSet = 1; + } auto node = newNode(chunk); if (!node) { - sVramPool.Deallocate(chunk); + if(bankSet) + sVramPoolB.Deallocate(chunk); + else + sVramPoolA.Deallocate(chunk); return nullptr; } + if (rbtree_insert(&sAddrMap, &node->node)); return chunk.addr; } +void* vramMemAlign(size_t size, size_t alignment) +{ + return vramBankMemAlign(VRMA_AB, size, alignment); +} + +void* vramBankAlloc(VRAM_ALLOCATOR bank, size_t size) +{ + return vramBankMemAlign(bank, size, 0x80); +} + void* vramAlloc(size_t size) { - return vramMemAlign(size, 0x80); + return vramBankMemAlign(VRAM_AB, size, 0x80); } void* vramRealloc(void* mem, size_t size) @@ -74,13 +119,30 @@ void vramFree(void* mem) if (!node) return; // Free the chunk - sVramPool.Deallocate(node->chunk); + if((u32)mem < 0x1F300000) + sVramPoolA.Deallocate(node->chunk); + else + sVramPoolB.Deallocate(node->chunk); // Free the node delNode(node); } +u32 vramBankSpaceFree(VRAM_ALLOCATOR bank); +{ + if(bank != VRAM_B) + { + u32 space = sVramPoolA.GetFreeSpace(); + if(bank == VRAM_A) + return space; + else + return space + sVramPoolB.GetFreeSpace(); + } + else + return sVramPoolB.GetFreeSpace(); +} + u32 vramSpaceFree() { - return sVramPool.GetFreeSpace(); + return sVramPoolA.GetFreeSpace() + sVramPoolB.GetFreeSpace(); } From 7c4769e5add2c629b0104591ef2c3c03de4b07cc Mon Sep 17 00:00:00 2001 From: DiscostewSM Date: Mon, 6 Feb 2017 12:16:01 -0800 Subject: [PATCH 2/2] Fix some coding mistakes --- libctru/include/3ds/allocator/vram.h | 6 +++--- libctru/source/allocator/vram.cpp | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/libctru/include/3ds/allocator/vram.h b/libctru/include/3ds/allocator/vram.h index ed1fd28..e3940c8 100644 --- a/libctru/include/3ds/allocator/vram.h +++ b/libctru/include/3ds/allocator/vram.h @@ -6,9 +6,9 @@ typedef enum { - VRAM_A = 0x00; - VRAM_B = 0x01; - VRAM_AB = 0x02; + VRAM_A = 0x00, + VRAM_B = 0x01, + VRAM_AB = 0x02 } VRAM_ALLOCATOR; /** diff --git a/libctru/source/allocator/vram.cpp b/libctru/source/allocator/vram.cpp index c92202e..d4811e9 100644 --- a/libctru/source/allocator/vram.cpp +++ b/libctru/source/allocator/vram.cpp @@ -20,7 +20,7 @@ static bool vramInit() if(blkB) { sVramPoolA.AddBlock(blkA); - sVramPoolB.Addblock(blkB); + sVramPoolB.AddBlock(blkB); rbtree_init(&sAddrMap, addrMapNodeComparator); return true; } @@ -68,7 +68,7 @@ void* vramBankMemAlign(VRAM_ALLOCATOR bank, size_t size, size_t alignment) } } else - bankset = 0; + bankSet = 0; } else { @@ -94,7 +94,7 @@ void* vramBankMemAlign(VRAM_ALLOCATOR bank, size_t size, size_t alignment) void* vramMemAlign(size_t size, size_t alignment) { - return vramBankMemAlign(VRMA_AB, size, alignment); + return vramBankMemAlign(VRAM_AB, size, alignment); } void* vramBankAlloc(VRAM_ALLOCATOR bank, size_t size) @@ -128,7 +128,7 @@ void vramFree(void* mem) delNode(node); } -u32 vramBankSpaceFree(VRAM_ALLOCATOR bank); +u32 vramBankSpaceFree(VRAM_ALLOCATOR bank) { if(bank != VRAM_B) {