diff --git a/libctru/include/3ds.h b/libctru/include/3ds.h index d128d25..7373406 100644 --- a/libctru/include/3ds.h +++ b/libctru/include/3ds.h @@ -9,6 +9,7 @@ extern "C" { #include <3ds/svc.h> #include <3ds/srv.h> #include <3ds/linear.h> +#include <3ds/vram.h> #include <3ds/os.h> #include <3ds/gfx.h> #include <3ds/console.h> diff --git a/libctru/include/3ds/vram.h b/libctru/include/3ds/vram.h new file mode 100644 index 0000000..9743410 --- /dev/null +++ b/libctru/include/3ds/vram.h @@ -0,0 +1,8 @@ +#pragma once + +// Functions for allocating/deallocating VRAM +void* vramAlloc(size_t size); // returns a 16-byte aligned address +void* vramMemAlign(size_t size, size_t alignment); +void* vramRealloc(void* mem, size_t size); // not implemented yet +void vramFree(void* mem); +u32 vramSpaceFree(); // get free VRAM space in bytes diff --git a/libctru/source/allocator/addrmap.h b/libctru/source/allocator/addrmap.h new file mode 100644 index 0000000..11e8183 --- /dev/null +++ b/libctru/source/allocator/addrmap.h @@ -0,0 +1,48 @@ +#pragma once + +static rbtree_t sAddrMap; + +struct addrMapNode +{ + rbtree_node node; + MemChunk chunk; +}; + +#define getAddrMapNode(x) rbtree_item((x), addrMapNode, node) + +static int addrMapNodeComparator(const rbtree_node_t* _lhs, const rbtree_node_t* _rhs) +{ + auto lhs = getAddrMapNode(_lhs)->chunk.addr; + auto rhs = getAddrMapNode(_rhs)->chunk.addr; + if (lhs < rhs) + return -1; + if (lhs > rhs) + return 1; + return 0; +} + +static void addrMapNodeDestructor(rbtree_node_t* a) +{ + free(getAddrMapNode(a)); +} + +static addrMapNode* getNode(void* addr) +{ + addrMapNode n; + n.chunk.addr = (u8*)addr; + auto p = rbtree_find(&sAddrMap, &n.node); + return p ? getAddrMapNode(p) : nullptr; +} + +static addrMapNode* newNode(const MemChunk& chunk) +{ + auto p = (addrMapNode*)malloc(sizeof(addrMapNode)); + if (!p) return nullptr; + p->chunk = chunk; + return p; +} + +static void delNode(addrMapNode* node) +{ + rbtree_remove(&sAddrMap, &node->node, addrMapNodeDestructor); +} diff --git a/libctru/source/allocator/linear.cpp b/libctru/source/allocator/linear.cpp index 0d7819b..0ad052c 100644 --- a/libctru/source/allocator/linear.cpp +++ b/libctru/source/allocator/linear.cpp @@ -6,56 +6,11 @@ extern "C" } #include "mem_pool.h" +#include "addrmap.h" extern u32 __linear_heap, __linear_heap_size; static MemPool sLinearPool; -static rbtree_t sAddrMap; - -struct addrMapNode -{ - rbtree_node node; - MemChunk chunk; -}; - -#define getAddrMapNode(x) rbtree_item((x), addrMapNode, node) - -static int addrMapNodeComparator(const rbtree_node_t* _lhs, const rbtree_node_t* _rhs) -{ - auto lhs = getAddrMapNode(_lhs)->chunk.addr; - auto rhs = getAddrMapNode(_rhs)->chunk.addr; - if (lhs < rhs) - return -1; - if (lhs > rhs) - return 1; - return 0; -} - -static void addrMapNodeDestructor(rbtree_node_t* a) -{ - free(getAddrMapNode(a)); -} - -static addrMapNode* getNode(void* addr) -{ - addrMapNode n; - n.chunk.addr = (u8*)addr; - auto p = rbtree_find(&sAddrMap, &n.node); - return p ? getAddrMapNode(p) : nullptr; -} - -static addrMapNode* newNode(const MemChunk& chunk) -{ - auto p = (addrMapNode*)malloc(sizeof(addrMapNode)); - if (!p) return nullptr; - p->chunk = chunk; - return p; -} - -static void delNode(addrMapNode* node) -{ - rbtree_remove(&sAddrMap, &node->node, addrMapNodeDestructor); -} static bool linearInit() { diff --git a/libctru/source/allocator/vram.cpp b/libctru/source/allocator/vram.cpp new file mode 100644 index 0000000..4918729 --- /dev/null +++ b/libctru/source/allocator/vram.cpp @@ -0,0 +1,86 @@ +extern "C" +{ + #include <3ds/types.h> + #include <3ds/vram.h> + #include <3ds/util/rbtree.h> +} + +#include "mem_pool.h" +#include "addrmap.h" + +static MemPool sVramPool; + +static bool vramInit() +{ + auto blk = MemBlock::Create((u8*)0x1F000000, 0x00600000); + if (blk) + { + sVramPool.AddBlock(blk); + rbtree_init(&sAddrMap, addrMapNodeComparator); + return true; + } + return false; +} + +void* vramMemAlign(size_t size, size_t alignment) +{ + // Enforce minimum alignment + if (alignment < 16) + alignment = 16; + + // Convert alignment to shift amount + int shift; + for (shift = 4; shift < 32; shift ++) + { + if ((1U<node)); + return chunk.addr; +} + +void* vramAlloc(size_t size) +{ + return vramMemAlign(size, 16); +} + +void* vramRealloc(void* mem, size_t size) +{ + // TODO + return NULL; +} + +void vramFree(void* mem) +{ + auto node = getNode(mem); + if (!node) return; + + // Free the chunk + sVramPool.Deallocate(node->chunk); + + // Free the node + delNode(node); +} + +u32 vramSpaceFree() +{ + return sVramPool.GetFreeSpace(); +}