summaryrefslogtreecommitdiff
path: root/src/SDK/OS/OSAlloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/SDK/OS/OSAlloc.c')
-rw-r--r--src/SDK/OS/OSAlloc.c186
1 files changed, 186 insertions, 0 deletions
diff --git a/src/SDK/OS/OSAlloc.c b/src/SDK/OS/OSAlloc.c
index 090233e..a60f3c0 100644
--- a/src/SDK/OS/OSAlloc.c
+++ b/src/SDK/OS/OSAlloc.c
@@ -1,6 +1,48 @@
#include "types.h"
#include "OS/OSAlloc.h"
+// TODO: move to header
+typedef enum {
+ OS_ARENA_MAIN = 0,
+ OS_ARENA_MAIN_SUBPRIV = 1,
+ OS_ARENA_MAINEX = 2,
+ OS_ARENA_ITCM = 3,
+ OS_ARENA_DTCM = 4,
+ OS_ARENA_SHARED = 5,
+ OS_ARENA_WRAM_MAIN = 6,
+ OS_ARENA_WRAM_SUB = 7,
+ OS_ARENA_WRAM_SUBPRIV = 8,
+ OS_ARENA_MAX = 9
+} OSArenaId;
+
+#define OSi_ROUND(n, a) (((u32) (n) + (a) - 1) & ~((a) - 1))
+
+// NOTE: there is just one HeapInfo pointer in PBR, not an array
+// void* OSiHeapInfo[OS_ARENA_MAX];
+
+inline Cell* DLAddFront(Cell* list, Cell* cell)
+{
+ cell->next = list;
+ cell->prev = NULL;
+
+ if (list != NULL)
+ list->prev = cell;
+ return cell;
+}
+
+inline Cell* DLExtract(Cell* list, Cell* cell)
+{
+ if (cell->next) {
+ cell->next->prev = cell->prev;
+ }
+ if (cell->prev == NULL) {
+ list = cell->next;
+ } else {
+ cell->prev->next = cell->next;
+ }
+ return list;
+}
+
Cell *DLInsert(Cell *original, Cell *inserted)
{
Cell *prevCell = NULL;
@@ -47,3 +89,147 @@ Cell *DLInsert(Cell *original, Cell *inserted)
return inserted;
}
+
+#if 0 // not found in DOL
+static u32 gUnk8063fa6c; // aligned arenaEnd, 680
+
+// returned by OSInitAlloc, "base address of the new arena,"
+// pointer to the beginning of the real data after the heap array header, 684
+static void *gUnk8063fa70;
+
+// Table of heaps
+static int gUnk8063fa74; // maxHeaps param of OSInitAlloc, 688
+
+volatile OSHeapHandle __OSCurrHeap = -1;
+
+void *OSInitAlloc(void *arenaStart, void *arenaEnd, int maxHeaps)
+{
+ HeapArray = (HeapDesc *)arenaStart;
+ gUnk8063fa74 = maxHeaps;
+ for (int i = 0; i < gUnk8063fa74; i++) {
+ HeapArray[i].heapSize = -1; // -1 indicates this heap is unused
+ HeapArray[i].start = NULL;
+ HeapArray[i].freeList = NULL;
+ }
+ gUnk8063fa6c = (u32)arenaEnd & ~0x1f;
+ __OSCurrHeap = -1;
+ gUnk8063fa70 = (void *)(((u32)&HeapArray[maxHeaps] + 0x1f) & ~0x1f);
+ return gUnk8063fa70;
+}
+
+OSHeapHandle OSCreateHeap(void *start, void *end)
+{
+ start = (void *)((u32)start + 0x1f & ~0x1f);
+ end = (void *)((u32)end & ~0x1f);
+ for (int i = 0; i < gUnk8063fa74; i++) {
+ if (HeapArray[i].heapSize < 0) {
+ HeapArray[i].heapSize = end - start;
+ ((Cell *)start)->prev = NULL;
+ ((Cell *)start)->next = NULL;
+ ((Cell *)start)->size = HeapArray[i].heapSize;
+ HeapArray[i].start = (Cell *)start;
+ HeapArray[i].freeList = NULL;
+ return i;
+ }
+ }
+ return -1;
+}
+
+#endif
+
+// arenaStart param of OSInitAlloc, points to array of
+// maxHeap HeapDescs, 68c
+extern HeapDesc *HeapArray;
+
+#define HEADERSIZE OSi_ROUND(sizeof(Cell), 32)
+#define MINOBJSIZE (HEADERSIZE+32)
+
+void* OSAllocFromHeap(/*OSArenaId id,*/ OSHeapHandle heap, u32 size) {
+ // OSHeapInfo* heapInfo;
+ HeapDesc* hd;
+ Cell* cell;
+ Cell* newCell;
+ long leftoverSize;
+
+ /*
+ OSIntrMode enabled = OS_DisableInterrupts();
+ heapInfo = OSiHeapInfo[id];
+ if (!heapInfo) {
+ (void)OS_RestoreInterrupts(enabled);
+ return NULL;
+ }
+
+ if (heap < 0) {
+ heap = heapInfo->currentHeap;
+ }
+ */
+
+ //hd = &heapInfo->heapArray[heap];
+ hd = &HeapArray[heap];
+
+ size += HEADERSIZE;
+ size = OSi_ROUND(size, 32);
+
+ for (cell = hd->free; cell != NULL; cell = cell->next) {
+ if ((long)size <= cell->size) {
+ break;
+ }
+ }
+
+ if (cell == NULL) {
+ //(void)OS_RestoreInterrupts(enabled);
+ return NULL;
+ }
+
+ leftoverSize = cell->size - (long)size;
+ if (leftoverSize < MINOBJSIZE) {
+ hd->free = DLExtract(hd->free, cell);
+ } else {
+ cell->size = (long)size;
+
+ newCell = (Cell *) ((char *)cell + size);
+ newCell->size = leftoverSize;
+
+ newCell->prev = cell->prev;
+ newCell->next = cell->next;
+
+ if (newCell->next != NULL) {
+ newCell->next->prev = newCell;
+ }
+
+ if (newCell->prev != NULL) {
+ newCell->prev->next = newCell;
+ } else {
+ hd->free = newCell;
+ }
+ }
+
+ hd->allocated = DLAddFront(hd->allocated, cell);
+
+ //(void)OS_RestoreInterrupts(enabled);
+ return (void *)((char *)cell + HEADERSIZE);
+}
+
+void OSFreeToHeap(/*OSArenaId id,*/ OSHeapHandle heap, void* ptr) {
+ OSHeapInfo *heapInfo;
+ HeapDesc *hd;
+ Cell *cell;
+
+ /*
+ OSIntrMode enabled = OS_DisableInterrupts();
+ heapInfo = OSiHeapInfo[id];
+
+ if (heap < 0) {
+ heap = heapInfo->currentHeap;
+ }
+ */
+
+ cell = (Cell *) ((char *)ptr - HEADERSIZE);
+ //hd = &heapInfo->heapArray[heap];
+ hd = &HeapArray[heap];
+
+ hd->allocated = DLExtract(hd->allocated, cell);
+ hd->free = DLInsert(hd->free, cell);
+
+ //(void)OS_RestoreInterrupts(enabled);
+}