#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>
--- /dev/null
+#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
--- /dev/null
+#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);
+}
}
#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()
{
--- /dev/null
+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<<shift) == alignment)
+ break;
+ }
+ if (shift == 32) // Invalid alignment
+ return nullptr;
+
+ // Initialize the pool if it is not ready
+ if (!sVramPool.Ready() && !vramInit())
+ return nullptr;
+
+ // Allocate the chunk
+ MemChunk chunk;
+ if (!sVramPool.Allocate(chunk, size, shift))
+ return nullptr;
+
+ auto node = newNode(chunk);
+ if (!node)
+ {
+ sVramPool.Deallocate(chunk);
+ return nullptr;
+ }
+ if (rbtree_insert(&sAddrMap, &node->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();
+}