summaryrefslogtreecommitdiff
path: root/arm9/lib
diff options
context:
space:
mode:
Diffstat (limited to 'arm9/lib')
-rw-r--r--arm9/lib/libnns/include/NNS_FND_heapcommon.h75
-rw-r--r--arm9/lib/libnns/include/NNS_FND_list.h15
-rw-r--r--arm9/lib/libnns/src/NNS_FND_allocator.c32
-rw-r--r--arm9/lib/libnns/src/NNS_FND_expheap.c204
-rw-r--r--arm9/lib/libnns/src/NNS_FND_heapcommon.c55
-rw-r--r--arm9/lib/libnns/src/NNS_FND_list.c128
6 files changed, 509 insertions, 0 deletions
diff --git a/arm9/lib/libnns/include/NNS_FND_heapcommon.h b/arm9/lib/libnns/include/NNS_FND_heapcommon.h
index e6fab69c..77473efe 100644
--- a/arm9/lib/libnns/include/NNS_FND_heapcommon.h
+++ b/arm9/lib/libnns/include/NNS_FND_heapcommon.h
@@ -2,11 +2,26 @@
#define GUARD_NNS_FND_HEAPCOMMON_H
#include "NNS_FND_list.h"
+#include "MI_memory.h"
#define NNS_FND_HEAP_DEFAULT_ALIGNMENT 4
+#define NNS_FndGetFillValForHeap(type) (0)
+
typedef struct NNSiFndHeapHead NNSiFndHeapHead;
+typedef s32 NNSiIntPtr;
+typedef u32 NNSiUIntPtr;
+
+#define NNSi_FndGetBitValue(data, st, bits) (((data) >>(st)) & ((1 <<(bits)) -1))
+#define NNSi_FndSetBitValue(data, st, bits, val) do { \
+ u32 maskBits = (u32)((1 << (bits)) - 1); \
+ u32 newVal = (val) & maskBits; \
+ (void)(maskBits <<= st); \
+ (data) &= ~maskBits; \
+ (data) |= newVal << (st); \
+} while (FALSE);
+
struct NNSiFndHeapHead
{
u32 signature;
@@ -23,4 +38,64 @@ struct NNSiFndHeapHead
typedef NNSiFndHeapHead* NNSFndHeapHandle; // Type to represent heap handle
+static inline NNSiUIntPtr NNSiGetUIntPtr(const void* ptr)
+{
+ return (NNSiUIntPtr)ptr;
+}
+
+static inline u32 GetOffsetFromPtr(const void* start, const void* end)
+{
+ return NNSiGetUIntPtr(end) - NNSiGetUIntPtr(start);
+}
+
+static inline void* AddU32ToPtr(void* ptr, u32 val)
+{
+ return (void*)( NNSiGetUIntPtr(ptr) + val );
+}
+
+static inline const void* AddU32ToCPtr(const void* ptr, u32 val)
+{
+ return (const void*)( NNSiGetUIntPtr(ptr) + val );
+}
+
+static inline void* SubU32ToPtr(void* ptr, u32 val)
+{
+ return (void*)(NNSiGetUIntPtr(ptr) - val);
+}
+
+static inline const void* SubU32ToCPtr(const void* ptr, u32 val)
+{
+ return (const void*)(NNSiGetUIntPtr(ptr) - val);
+}
+
+static inline int ComparePtr(const void* a, const void* b)
+{
+ const u8* wa = a;
+ const u8* wb = b;
+
+ return wa - wb;
+}
+
+
+static inline u16 GetOptForHeap(const NNSiFndHeapHead* pHeapHd)
+{
+ return (u16)NNSi_FndGetBitValue(pHeapHd->attribute, 0, 8);
+}
+
+static inline void SetOptForHeap(
+ NNSiFndHeapHead* pHeapHd,
+ u16 optFlag
+ )
+{
+ NNSi_FndSetBitValue(pHeapHd->attribute, 0, 8, optFlag);
+}
+
+static inline void FillAllocMemory(NNSiFndHeapHead* pHeapHd, void* address, u32 size)
+{
+ if (GetOptForHeap(pHeapHd) & 1)
+ MI_CpuFill32(address, NNS_FndGetFillValForHeap(0), size);
+}
+
+void NNSi_FndInitHeapHead(NNSiFndHeapHead *pHead, u32 signature, void* heapStart, void* heapEnd, u16 optionFlag);
+
#endif //GUARD_NNS_FND_HEAPCOMMON_H
diff --git a/arm9/lib/libnns/include/NNS_FND_list.h b/arm9/lib/libnns/include/NNS_FND_list.h
index 5fec2fdf..4bba7882 100644
--- a/arm9/lib/libnns/include/NNS_FND_list.h
+++ b/arm9/lib/libnns/include/NNS_FND_list.h
@@ -17,4 +17,19 @@ typedef struct
} NNSFndList;
+void NNS_FndInitList(
+ NNSFndList *pList,
+ s32 alignment
+);
+
+void NNS_FndAppendListObject(
+ NNSFndList *pList,
+ void* object
+);
+
+void NNS_FndRemoveListObject(
+ NNSFndList *pList,
+ void* object
+);
+
#endif //GUARD_NNS_FND_LIST_H
diff --git a/arm9/lib/libnns/src/NNS_FND_allocator.c b/arm9/lib/libnns/src/NNS_FND_allocator.c
new file mode 100644
index 00000000..31d0eb70
--- /dev/null
+++ b/arm9/lib/libnns/src/NNS_FND_allocator.c
@@ -0,0 +1,32 @@
+#include "nitro.h"
+#include "NNS_FND_allocator.h"
+#include "NNS_FND_expheap.h"
+
+void *AllocatorAllocForExpHeap(NNSFndAllocator * pAllocator, u32 size)
+{
+ return NNS_FndAllocFromExpHeapEx(pAllocator->pHeap, size, pAllocator->heapParam1);
+}
+
+void AllocatorFreeForExpHeap(NNSFndAllocator * pAllocator, void *memBlock)
+{
+ NNS_FndFreeToExpHeap(pAllocator->pHeap, memBlock);
+}
+
+void *NNS_FndAllocFromAllocator(NNSFndAllocator * pAllocator, u32 size)
+{
+ return pAllocator->pFunc->pfAlloc(pAllocator, size);
+}
+
+void NNS_FndFreeToAllocator(NNSFndAllocator * pAllocator, void *memBlock)
+{
+ pAllocator->pFunc->pfFree(pAllocator, memBlock);
+}
+
+void NNS_FndInitAllocatorForExpHeap(NNSFndAllocator * pAllocator, NNSFndHeapHandle pHeap, int alignment)
+{
+ static const NNSFndAllocatorFunc pFunc = {AllocatorAllocForExpHeap, AllocatorFreeForExpHeap};
+ pAllocator->pFunc = &pFunc;
+ pAllocator->pHeap = pHeap;
+ pAllocator->heapParam1 = alignment;
+ pAllocator->heapParam2 = 0;
+}
diff --git a/arm9/lib/libnns/src/NNS_FND_expheap.c b/arm9/lib/libnns/src/NNS_FND_expheap.c
new file mode 100644
index 00000000..f5a74dc4
--- /dev/null
+++ b/arm9/lib/libnns/src/NNS_FND_expheap.c
@@ -0,0 +1,204 @@
+#include "global.h"
+#include "NNS_FND_expheap.h"
+
+typedef struct NNSiMemRegion {
+ void* start;
+ void* end;
+} NNSiMemRegion;
+
+static inline u16 GetAlignmentForMBlock(NNSiFndExpHeapMBlockHead* block)
+{
+ return NNSi_FndGetBitValue(block->attribute, 8, 7);
+}
+
+static inline void SetAllocDirForMBlock(NNSiFndExpHeapMBlockHead* pEHMBHead, u16 direction)
+{
+ NNSi_FndSetBitValue(pEHMBHead->attribute, 15, 1, direction);
+}
+
+static inline void SetAlignmentForMBlock(NNSiFndExpHeapMBlockHead* pEHMBHead, u16 alignment)
+{
+ NNSi_FndSetBitValue(pEHMBHead->attribute, 8, 7, alignment);
+}
+
+static inline void SetGroupIDForMBlock(NNSiFndExpHeapMBlockHead* pEHMBHead, u16 groupID)
+{
+ NNSi_FndSetBitValue(pEHMBHead->attribute, 0, 8, groupID);
+}
+
+static inline void* GetMemPtrForMBlock(NNSiFndExpHeapMBlockHead* block)
+{
+ return AddU32ToPtr(block, sizeof(NNSiFndExpHeapMBlockHead));
+}
+
+static inline void* GetMBlockEndAddr(NNSiFndExpHeapMBlockHead* block)
+{
+ return AddU32ToPtr(GetMemPtrForMBlock(block), block->blockSize);
+}
+
+static inline void SetAllocMode(NNSiFndExpHeapHead* pExHeapHd, u16 mode)
+{
+ NNSi_FndSetBitValue(pExHeapHd->feature, 0, 1, mode);
+}
+
+static inline NNSiFndExpHeapHead* GetExpHeapHeadPtrFromHeapHead(NNSiFndHeapHead* pHHead)
+{
+ return AddU32ToPtr(pHHead, sizeof(NNSiFndHeapHead));
+}
+
+static inline NNSiFndHeapHead* GetHeapHeadPtrFromExpHeapHead(NNSiFndExpHeapHead* pEHHead)
+{
+ return SubU32ToPtr(pEHHead, sizeof(NNSiFndHeapHead));
+}
+
+void GetRegionOfMBlock(NNSiMemRegion* region, NNSiFndExpHeapMBlockHead* block)
+{
+ region->start = SubU32ToPtr(block, GetAlignmentForMBlock(block));
+ region->end = GetMBlockEndAddr(block);
+}
+
+NNSiFndExpHeapMBlockHead* RemoveMBlock(NNSiFndExpMBlockList* list, NNSiFndExpHeapMBlockHead* block)
+{
+ NNSiFndExpHeapMBlockHead* const prev = block->pMBHeadPrev;
+ NNSiFndExpHeapMBlockHead* const next = block->pMBHeadNext;
+
+ if (prev != NULL)
+ {
+ prev->pMBHeadNext = next;
+ }
+ else
+ {
+ list->head = next;
+ }
+
+ if (next != NULL)
+ {
+ next->pMBHeadPrev = prev;
+ }
+ else
+ {
+ list->tail = prev;
+ }
+
+ return prev;
+}
+
+NNSiFndExpHeapMBlockHead* InsertMBlock(NNSiFndExpMBlockList* list, NNSiFndExpHeapMBlockHead* target, NNSiFndExpHeapMBlockHead* prev)
+{
+ NNSiFndExpHeapMBlockHead* next;
+ target->pMBHeadPrev = prev;
+ if (prev != NULL)
+ {
+ next = prev->pMBHeadNext;
+ prev->pMBHeadNext = target;
+ }
+ else
+ {
+ next = list->head;
+ list->head = target;
+ }
+ target->pMBHeadNext = next;
+ if (next != NULL)
+ {
+ next->pMBHeadPrev = target;
+ }
+ else
+ {
+ list->tail = target;
+ }
+
+ return target;
+}
+
+NNSiFndExpHeapMBlockHead* InitMBlock(const NNSiMemRegion* pRegion, u16 signature)
+{
+ NNSiFndExpHeapMBlockHead* block = pRegion->start;
+ block->signature = signature;
+ block->attribute = 0;
+ block->blockSize = GetOffsetFromPtr(GetMemPtrForMBlock(block), pRegion->end);
+ block->pMBHeadPrev = NULL;
+ block->pMBHeadNext = NULL;
+ return block;
+}
+
+static inline NNSiFndExpHeapMBlockHead* InitFreeMBlock(const NNSiMemRegion* region)
+{
+ return InitMBlock(region, 0x4652);
+}
+
+NNSiFndHeapHead* InitExpHeap(void* startAddress, void* endAddress, u16 optFlag)
+{
+ NNSiFndHeapHead* pHeapHd = (NNSiFndHeapHead*)startAddress;
+ NNSiFndExpHeapHead* pExpHeapHd = GetExpHeapHeadPtrFromHeapHead(pHeapHd);
+ NNSi_FndInitHeapHead(pHeapHd, 0x45585048, AddU32ToPtr(pExpHeapHd, sizeof(NNSiFndExpHeapHead)), endAddress, optFlag);
+ pExpHeapHd->groupID = 0;
+ pExpHeapHd->feature = 0;
+ SetAllocMode(pExpHeapHd, 0);
+
+ NNSiFndExpHeapMBlockHead* pMBHead;
+ NNSiMemRegion region;
+
+ region.start = pHeapHd->heapStart;
+ region.end = pHeapHd->heapEnd;
+ pMBHead = InitFreeMBlock(&region);
+
+ pExpHeapHd->mbFreeList.head = pMBHead;
+ pExpHeapHd->mbFreeList.tail = pMBHead;
+ pExpHeapHd->mbUsedList.head = NULL;
+ pExpHeapHd->mbUsedList.tail = NULL;
+
+ return pHeapHd;
+}
+
+static inline void AppendMBlock(NNSiFndExpMBlockList* list, NNSiFndExpHeapMBlockHead* block)
+{
+ (void) InsertMBlock(list, block, list->tail);
+}
+
+void* AllocUsedBlockFromFreeBlock(NNSiFndExpHeapHead* pEHHead, NNSiFndExpHeapMBlockHead* pMBHeadFree, void* mblock, u32 size, u16 direction)
+{
+ NNSiMemRegion freeRgnT;
+ NNSiMemRegion freeRgnB;
+ NNSiFndExpHeapMBlockHead* pMBHeadFreePrev;
+
+ GetRegionOfMBlock(&freeRgnT, pMBHeadFree);
+
+ freeRgnB.end = freeRgnT.end;
+ freeRgnB.start = AddU32ToPtr(mblock, size);
+ freeRgnT.end = SubU32ToPtr(mblock, sizeof(NNSiFndExpHeapMBlockHead));
+
+ pMBHeadFreePrev = RemoveMBlock(&pEHHead->mbFreeList, pMBHeadFree);
+
+ if (GetOffsetFromPtr(freeRgnT.start, freeRgnT.end) < sizeof(NNSiFndExpHeapMBlockHead))
+ {
+ freeRgnT.end = freeRgnT.start;
+ }
+ else
+ {
+ pMBHeadFreePrev = InsertMBlock(&pEHHead->mbFreeList, InitFreeMBlock(&freeRgnT), pMBHeadFreePrev);
+ }
+ if (GetOffsetFromPtr(freeRgnB.start, freeRgnB.end) < sizeof(NNSiFndExpHeapMBlockHead))
+ {
+ freeRgnB.start= freeRgnB.end;
+ }
+ else
+ {
+ (void)InsertMBlock(&pEHHead->mbFreeList, InitFreeMBlock(&freeRgnB), pMBHeadFreePrev);
+ }
+
+ FillAllocMemory(GetHeapHeadPtrFromExpHeapHead(pEHHead), freeRgnT.end, GetOffsetFromPtr(freeRgnT.end, freeRgnB.start));
+
+ NNSiFndExpHeapMBlockHead* pMBHeadNewUsed;
+ NNSiMemRegion region;
+
+ region.start = SubU32ToPtr(mblock, sizeof(NNSiFndExpHeapMBlockHead));
+ region.end = freeRgnB.start;
+
+ pMBHeadNewUsed = InitMBlock(&region, 0x5544);
+ SetAllocDirForMBlock(pMBHeadNewUsed, direction);
+ SetAlignmentForMBlock(pMBHeadNewUsed, (u16)GetOffsetFromPtr(freeRgnT.end, pMBHeadNewUsed));
+ SetGroupIDForMBlock(pMBHeadNewUsed, pEHHead->groupID);
+ AppendMBlock(&pEHHead->mbUsedList, pMBHeadNewUsed);
+
+ return mblock;
+}
diff --git a/arm9/lib/libnns/src/NNS_FND_heapcommon.c b/arm9/lib/libnns/src/NNS_FND_heapcommon.c
new file mode 100644
index 00000000..07b8e9cf
--- /dev/null
+++ b/arm9/lib/libnns/src/NNS_FND_heapcommon.c
@@ -0,0 +1,55 @@
+#include "nitro.h"
+#include "NNS_FND_heapcommon.h"
+#include "NNS_FND_list.h"
+
+BOOL sRootListInitialized;
+NNSFndList sRootList;
+
+void *NNS_FndGetNextListObject(NNSFndList *, void *);
+
+static NNSiFndHeapHead* FindContainHeap(NNSFndList * pList, const void * memBlock)
+{
+ NNSiFndHeapHead * pHead = NULL;
+
+ while ((pHead = NNS_FndGetNextListObject(pList, pHead)) != NULL)
+ {
+ if (pHead->heapStart <= memBlock && memBlock < pHead->heapEnd)
+ {
+ NNSiFndHeapHead * ret = FindContainHeap(&pHead->childList, memBlock);
+ if (ret == NULL)
+ ret = pHead;
+ return ret;
+ }
+ }
+ return NULL;
+}
+
+static NNSFndList* FindListContainHeap(const void * memBlock)
+{
+ NNSFndList* ret = &sRootList;
+ NNSiFndHeapHead* pHead = FindContainHeap(&sRootList, memBlock);
+ if (pHead != NULL)
+ ret = &pHead->childList;
+ return ret;
+}
+
+void NNSi_FndInitHeapHead(NNSiFndHeapHead *pHead, u32 signature, void* heapStart, void* heapEnd, u16 optionFlag)
+{
+ pHead->signature = signature;
+ pHead->heapStart = heapStart;
+ pHead->heapEnd = heapEnd;
+ pHead->attribute = 0;
+ SetOptForHeap(pHead, optionFlag);
+ NNS_FndInitList(&pHead->childList, 4);
+ if (!sRootListInitialized)
+ {
+ NNS_FndInitList(&sRootList, 4);
+ sRootListInitialized = TRUE;
+ }
+ NNS_FndAppendListObject(FindListContainHeap(pHead), pHead);
+}
+
+void NNSi_FndFinalizeHeap(NNSiFndHeapHead *pHead)
+{
+ NNS_FndRemoveListObject(FindListContainHeap(pHead), pHead);
+}
diff --git a/arm9/lib/libnns/src/NNS_FND_list.c b/arm9/lib/libnns/src/NNS_FND_list.c
new file mode 100644
index 00000000..d4dd7620
--- /dev/null
+++ b/arm9/lib/libnns/src/NNS_FND_list.c
@@ -0,0 +1,128 @@
+#include "nitro.h"
+#include "NNS_FND_list.h"
+
+#define OBJ_TO_LINK(list, obj) ((NNSFndLink*)((void*)(obj) + (list)->offset))
+
+void NNS_FndInitList(NNSFndList* list, s32 alignment)
+{
+ list->headObject = NULL;
+ list->tailObject = NULL;
+ list->numObjects = 0;
+ list->offset = (u16)alignment;
+}
+
+static void SetFirstObject(NNSFndList* list, void* object)
+{
+ NNSFndLink* tail = OBJ_TO_LINK(list, object);
+ tail->nextObject = NULL;
+ tail->prevObject = NULL;
+ list->headObject = object;
+ list->tailObject = object;
+ list->numObjects++;
+}
+
+void NNS_FndAppendListObject(NNSFndList* list, void* object)
+{
+ if (list->headObject == NULL)
+ {
+ SetFirstObject(list, object);
+ }
+ else
+ {
+ NNSFndLink *tail = OBJ_TO_LINK(list, object);
+ tail->prevObject = list->tailObject;
+ tail->nextObject = NULL;
+ OBJ_TO_LINK(list, list->tailObject)->nextObject = object;
+ list->tailObject = object;
+ list->numObjects++;
+ }
+}
+
+void NNS_FndPrependListObject(NNSFndList* list, void* object)
+{
+ if (list->headObject == NULL)
+ {
+ SetFirstObject(list, object);
+ }
+ else
+ {
+ NNSFndLink *tail = OBJ_TO_LINK(list, object);
+ tail->prevObject = NULL;
+ tail->nextObject = list->headObject;
+ OBJ_TO_LINK(list, list->headObject)->prevObject = object;
+ list->headObject = object;
+ list->numObjects++;
+ }
+}
+
+void NNS_FndInsertListObject(NNSFndList* list, void* where, void* object)
+{
+ if (where == NULL)
+ {
+ NNS_FndAppendListObject(list, object);
+ }
+
+ else if (where == list->headObject)
+ {
+ NNS_FndPrependListObject(list, object);
+ }
+ else
+ {
+ NNSFndLink* tail = OBJ_TO_LINK(list, object);
+ void* prevObject = OBJ_TO_LINK(list, where)->prevObject;
+ NNSFndLink* head = OBJ_TO_LINK(list, prevObject);
+ tail->prevObject = prevObject;
+ tail->nextObject = where;
+ head->nextObject = object;
+ OBJ_TO_LINK(list, where)->prevObject = object;
+ list->numObjects++;
+ }
+}
+
+void NNS_FndRemoveListObject(NNSFndList* list, void* object)
+{
+ NNSFndLink* node = OBJ_TO_LINK(list, object);
+ if (node->prevObject == NULL)
+ {
+ list->headObject = node->nextObject;
+ }
+ else
+ {
+ OBJ_TO_LINK(list, node->prevObject)->nextObject = node->nextObject;
+ }
+ if (node->nextObject == NULL)
+ {
+ list->tailObject = node->prevObject;
+ }
+ else
+ {
+ OBJ_TO_LINK(list, node->nextObject)->prevObject = node->prevObject;
+ }
+ node->prevObject = NULL;
+ node->nextObject = NULL;
+ list->numObjects--;
+}
+
+void * NNS_FndGetNextListObject(NNSFndList* list, void* object)
+{
+ if (object == NULL)
+ {
+ return list->headObject;
+ }
+ else
+ {
+ return OBJ_TO_LINK(list, object)->nextObject;
+ }
+}
+
+void * NNS_FndGetPrevListObject(NNSFndList* list, void* object)
+{
+ if (object == NULL)
+ {
+ return list->tailObject;
+ }
+ else
+ {
+ return OBJ_TO_LINK(list, object)->prevObject;
+ }
+}