mirror of
https://github.com/pret/pmd-red.git
synced 2026-03-26 12:05:17 -05:00
603 lines
14 KiB
C
603 lines
14 KiB
C
#include "global.h"
|
|
#include "globaldata.h"
|
|
#include "memory.h"
|
|
#include "cpu.h"
|
|
#include "debug.h"
|
|
|
|
#define HEAP_SIZE 0x24000
|
|
|
|
// size: 0x8
|
|
struct HeapSettings
|
|
{
|
|
/* 0x0 */ u8 *start;
|
|
/* 0x4 */ u32 size;
|
|
};
|
|
|
|
// size: 0xC
|
|
struct HeapMemoryBlock
|
|
{
|
|
/* 0x0 */ u8 *start;
|
|
/* 0x4 */ s32 size;
|
|
/* 0x8 */ s32 allocatedSize;
|
|
};
|
|
|
|
// size: 0x8
|
|
struct HeapMemoryBlock2
|
|
{
|
|
/* 0x0 */ struct HeapFreeListElement *start;
|
|
/* 0x4 */ s32 size;
|
|
};
|
|
|
|
// size: 0x10
|
|
struct HeapFreeListElement
|
|
{
|
|
/* 0x0 */ u32 unk_atb;
|
|
/* 0x4 */ u32 atb;
|
|
/* 0x8 */ u32 grp;
|
|
/* 0xC */ struct HeapMemoryBlock block;
|
|
};
|
|
|
|
// size: 0x1C
|
|
struct HeapDescriptor
|
|
{
|
|
u32 unk0;
|
|
/* 0x4 */ struct HeapDescriptor *parentHeap;
|
|
/* 0x8 */ struct HeapFreeListElement *freeList;
|
|
/* 0xC */ s32 freeCount;
|
|
/* 0x10 */ s32 freeListLength;
|
|
/* 0x14 */ u8 *start;
|
|
/* 0x18 */ u32 size;
|
|
};
|
|
|
|
// size: 0x8
|
|
struct unkMemoryStruct
|
|
{
|
|
struct HeapDescriptor *unk0;
|
|
u32 end;
|
|
};
|
|
|
|
static EWRAM_DATA struct HeapDescriptor *sHeapDescriptorList[8] = {0};
|
|
static EWRAM_DATA s32 sHeapCount = {0};
|
|
UNUSED static EWRAM_DATA u32 sUnused1 = 0;
|
|
static EWRAM_DATA struct HeapDescriptor sMainHeapDescriptor = {0};
|
|
UNUSED static EWRAM_DATA u32 sUnused2 = 0;
|
|
static EWRAM_DATA struct HeapFreeListElement sMainHeapFreeList[32] = {0};
|
|
static EWRAM_DATA u8 sMainHeap[HEAP_SIZE] = {0};
|
|
|
|
static void DoFree(struct HeapDescriptor *, void *);
|
|
static void DoInitHeap(struct HeapDescriptor *, struct HeapSettings *, struct HeapFreeListElement *, u32);
|
|
static void InitSubHeap(struct HeapDescriptor *, struct HeapMemoryBlock2 *, u32);
|
|
static struct HeapDescriptor *DoCreateSubHeap(struct unkMemoryStruct *a, u32 b);
|
|
static void *DoAlloc(struct HeapDescriptor *heap, s32 size, u32 a2);
|
|
static void InitHeapInternal(void);
|
|
|
|
ALIGNED(4) static const char sFileNameText[] = "../system/memory_locate.c";
|
|
|
|
void InitHeap(void)
|
|
{
|
|
InitHeapInternal();
|
|
}
|
|
|
|
void MemoryClear8(void *dest, s32 size)
|
|
{
|
|
u8 *cur = dest;
|
|
|
|
while (size > 0) {
|
|
size -= 1;
|
|
*cur++ = 0;
|
|
}
|
|
}
|
|
|
|
void MemoryClear16(u16 *dest, s32 size)
|
|
{
|
|
while (size > 0) {
|
|
size -= 2;
|
|
*dest++ = 0;
|
|
}
|
|
}
|
|
|
|
UNUSED static void MemoryClear32(u32 *dest, s32 size)
|
|
{
|
|
CpuClear(dest, size);
|
|
}
|
|
|
|
void MemoryFill8(void *dest, u8 value, s32 size)
|
|
{
|
|
u8 *cur = dest;
|
|
|
|
while (size > 0) {
|
|
size -= 1;
|
|
*cur++ = value;
|
|
}
|
|
}
|
|
|
|
void MemoryFill16(u16 *dest, u16 value, s32 size)
|
|
{
|
|
while (size > 0) {
|
|
size -= 2;
|
|
*dest++ = value;
|
|
}
|
|
}
|
|
|
|
UNUSED static void MemoryFill32(u32 *dest, u32 value, s32 size)
|
|
{
|
|
while (size > 0) {
|
|
size -= 4;
|
|
*dest++ = value;
|
|
}
|
|
}
|
|
|
|
void MemoryCopy8(void *dest, void *src, s32 size)
|
|
{
|
|
u8 *dCur = dest;
|
|
u8 *sCur = src;
|
|
|
|
while (size > 0) {
|
|
size -= 1;
|
|
*dCur++ = *sCur++;
|
|
}
|
|
}
|
|
|
|
UNUSED static void MemoryCopy16(u16 *dest, u16 *src, s32 size)
|
|
{
|
|
while (size > 0) {
|
|
size -= 2;
|
|
*dest++ = *src++;
|
|
}
|
|
}
|
|
|
|
void MemoryCopy32(u32 *dest, u32 *src, s32 size)
|
|
{
|
|
while (size > 0) {
|
|
size -= 4;
|
|
*dest++ = *src++;
|
|
}
|
|
}
|
|
|
|
static void InitHeapInternal(void)
|
|
{
|
|
struct HeapSettings settings;
|
|
|
|
settings.start = sMainHeap;
|
|
settings.size = HEAP_SIZE;
|
|
sHeapCount = 0;
|
|
DoInitHeap(&sMainHeapDescriptor, &settings, sMainHeapFreeList, sizeof(sMainHeapFreeList) / sizeof(struct HeapFreeListElement));
|
|
}
|
|
|
|
static void DoInitHeap(struct HeapDescriptor *descriptor, struct HeapSettings *settings, struct HeapFreeListElement *freeList, u32 freeListLength)
|
|
{
|
|
u32 aligned_size;
|
|
|
|
aligned_size = settings->size & ~(3);
|
|
|
|
sHeapDescriptorList[sHeapCount++] = descriptor;
|
|
|
|
descriptor->start = settings->start;
|
|
descriptor->size = aligned_size;
|
|
descriptor->unk0 = 2;
|
|
descriptor->parentHeap = NULL;
|
|
descriptor->freeList = freeList;
|
|
descriptor->freeCount = 1;
|
|
descriptor->freeListLength = freeListLength;
|
|
|
|
freeList->unk_atb = 0;
|
|
freeList->atb = 0;
|
|
freeList->block.start = descriptor->start;
|
|
freeList->block.size = aligned_size;
|
|
freeList->block.allocatedSize = 0;
|
|
freeList->grp = 0;
|
|
}
|
|
|
|
static void InitSubHeap(struct HeapDescriptor *parentHeap, struct HeapMemoryBlock2 *block, u32 freeListMax)
|
|
{
|
|
u32 freeListSize;
|
|
u32 aligned_size;
|
|
u32 alignment;
|
|
struct HeapFreeListElement *freeList;
|
|
struct HeapSettings settings;
|
|
|
|
freeListSize = freeListMax * 3;
|
|
alignment = ~3;
|
|
freeListSize *= 8;
|
|
aligned_size = (block->size - freeListSize) & alignment;
|
|
freeList = (struct HeapFreeListElement *)block->start;
|
|
settings.start = &((u8 *)block->start)[freeListSize];
|
|
settings.size = aligned_size;
|
|
DoInitHeap(parentHeap, &settings, freeList, freeListMax);
|
|
}
|
|
|
|
static u32 xxx_memory_attr_related(u32 r0)
|
|
{
|
|
u32 temp;
|
|
u32 return_var;
|
|
|
|
if (r0 == 0)
|
|
return 0;
|
|
|
|
if (r0 & 8)
|
|
return 4;
|
|
|
|
temp = r0 & 7; // Doesn't match with switch statement
|
|
if (temp == 7)
|
|
return_var = 1;
|
|
else if (temp == 1)
|
|
return_var = 2;
|
|
else if (temp == 3)
|
|
return_var = 3;
|
|
else
|
|
return_var = 5;
|
|
|
|
return return_var;
|
|
}
|
|
|
|
static s32 MemorySearchFromFront(struct HeapDescriptor *heap, s32 atb, s32 size)
|
|
{
|
|
s32 i;
|
|
struct HeapFreeListElement *curr;
|
|
|
|
if (atb & 4) {
|
|
i = 0;
|
|
curr = &heap->freeList[0];
|
|
|
|
for (; i < heap->freeCount; i++, curr++) {
|
|
if (!(curr->atb & 1)) {
|
|
if (curr->block.size >= size)
|
|
return i;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (; i < heap->freeCount; i++, curr++) {
|
|
if (!(curr->atb & 1)) {
|
|
if (curr->block.size >= size)
|
|
return i;
|
|
}
|
|
}
|
|
|
|
}
|
|
else {
|
|
s32 ret = -1;
|
|
s32 sizeMax = HEAP_SIZE + 1;
|
|
i = 0;
|
|
curr = &heap->freeList[0];
|
|
|
|
for (; i < heap->freeCount; i++, curr++) {
|
|
if (!(curr->atb & 1) && curr->block.size >= size && curr->block.size < sizeMax) {
|
|
ret = i;
|
|
sizeMax = curr->block.size;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
static s32 MemorySearchFromBack(struct HeapDescriptor *heap, s32 atb, s32 size)
|
|
{
|
|
s32 i;
|
|
struct HeapFreeListElement *curr;
|
|
|
|
if (atb & 4) {
|
|
i = heap->freeCount - 1;
|
|
curr = &heap->freeList[i];
|
|
|
|
for (; i >= 0; i--, curr--) {
|
|
if (!(curr->atb & 1)) {
|
|
if (curr->block.size >= size)
|
|
return i;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (; i >= 0; i--, curr--) {
|
|
if (!(curr->atb & 1)) {
|
|
if (curr->block.size >= size)
|
|
return i;
|
|
}
|
|
}
|
|
|
|
}
|
|
else {
|
|
s32 ret = -1;
|
|
s32 sizeMax = HEAP_SIZE + 1;
|
|
i = heap->freeCount - 1;
|
|
curr = &heap->freeList[i];
|
|
|
|
for (; i >= 0; i--, curr--) {
|
|
if (!(curr->atb & 1) && curr->block.size >= size && curr->block.size < sizeMax) {
|
|
ret = i;
|
|
sizeMax = curr->block.size;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
ALIGNED(4) static const char sText_LocateSetFront[] = "_LocateSetFront";
|
|
static const DebugLocation sLocateSetFrontDebugLocation =
|
|
{
|
|
.file = sFileNameText,
|
|
.line = 581,
|
|
.func = sText_LocateSetFront
|
|
};
|
|
|
|
static struct HeapFreeListElement * _LocateSetFront(struct HeapDescriptor *heap, s32 index, s32 atb, s32 size, s32 group)
|
|
{
|
|
s32 i;
|
|
struct HeapFreeListElement *curr;
|
|
struct HeapFreeListElement *block;
|
|
s32 sizeAligned;
|
|
|
|
sizeAligned = size + 3;
|
|
sizeAligned &= ~(3);
|
|
curr = &heap->freeList[index];
|
|
if (curr->block.size > sizeAligned) {
|
|
i = heap->freeCount;
|
|
block = &heap->freeList[heap->freeCount];
|
|
for (; i > index; i--, block--) {
|
|
block[0] = block[-1];
|
|
}
|
|
|
|
heap->freeCount++;
|
|
if (heap->freeCount > heap->freeListLength) {
|
|
FatalError(&sLocateSetFrontDebugLocation, "Memory Locate sprit max over [%3d/%3d]", heap->freeCount, heap->freeListLength);
|
|
}
|
|
|
|
block = &heap->freeList[index + 1];
|
|
block->block.start += sizeAligned;
|
|
block->block.size -= sizeAligned;
|
|
|
|
curr->block.size = sizeAligned;
|
|
curr->block.allocatedSize = size;
|
|
}
|
|
|
|
curr->unk_atb = xxx_memory_attr_related(atb);
|
|
curr->atb = atb;
|
|
curr->grp = group;
|
|
return curr;
|
|
}
|
|
|
|
ALIGNED(4) static const char sText_LocateSetBack[] = "_LocateSetBack";
|
|
static const DebugLocation sLocateSetBackDebugLocation =
|
|
{
|
|
.file = sFileNameText,
|
|
.line = 673,
|
|
.func = sText_LocateSetBack
|
|
};
|
|
|
|
static struct HeapFreeListElement * _LocateSetBack(struct HeapDescriptor *heap, s32 index, s32 atb, s32 size, s32 group)
|
|
{
|
|
s32 i;
|
|
struct HeapFreeListElement *curr;
|
|
struct HeapFreeListElement *block;
|
|
s32 sizeAligned;
|
|
u8 *newBlockStart;
|
|
|
|
sizeAligned = size + 3;
|
|
sizeAligned &= ~(3);
|
|
curr = &heap->freeList[index];
|
|
if (curr->block.size > sizeAligned) {
|
|
i = heap->freeCount;
|
|
block = &heap->freeList[heap->freeCount];
|
|
for (; i > index; i--, block--) {
|
|
block[0] = block[-1];
|
|
}
|
|
|
|
heap->freeCount++;
|
|
if (heap->freeCount > heap->freeListLength) {
|
|
FatalError(&sLocateSetBackDebugLocation, "Memory Locate sprit max over [%3d/%3d]", heap->freeCount, heap->freeListLength);
|
|
}
|
|
|
|
curr->block.size -= sizeAligned;
|
|
newBlockStart = curr->block.size + curr->block.start;
|
|
|
|
curr++;
|
|
curr->block.start = newBlockStart;
|
|
curr->block.size = sizeAligned;
|
|
curr->block.allocatedSize = size;
|
|
}
|
|
|
|
curr->unk_atb = xxx_memory_attr_related(atb);
|
|
curr->atb = atb;
|
|
curr->grp = group;
|
|
return curr;
|
|
}
|
|
|
|
ALIGNED(4) static const char sText_LocateSet[] = "_LocateSet";
|
|
static const DebugLocation sLocateSetDebugLocation =
|
|
{
|
|
.file = sFileNameText,
|
|
.line = 812,
|
|
.func = sText_LocateSet
|
|
};
|
|
|
|
static void * _LocateSet(struct HeapDescriptor *heap, s32 size, s32 group)
|
|
{
|
|
s32 index;
|
|
struct HeapFreeListElement * foundSet;
|
|
s32 atb;
|
|
|
|
if (heap == NULL) {
|
|
heap = &sMainHeapDescriptor;
|
|
}
|
|
|
|
// Set some sort flag/attr?
|
|
atb = group >> 8 | 1;
|
|
|
|
// Reset it?
|
|
group = group & 0xff;
|
|
|
|
if ((atb & 2) != 0) {
|
|
index = MemorySearchFromFront(heap,atb,size);
|
|
if (index < 0) goto error;
|
|
foundSet = _LocateSetFront(heap,index,atb,size,group);
|
|
return foundSet->block.start;
|
|
}
|
|
else {
|
|
index = MemorySearchFromBack(heap,atb,size);
|
|
if (index < 0) goto error;
|
|
foundSet = _LocateSetBack(heap,index,atb,size,group);
|
|
return foundSet->block.start;
|
|
}
|
|
|
|
error:
|
|
FatalError(&sLocateSetDebugLocation,
|
|
"Memroy LocateSet [%p] buffer %8x size can't locate\n atb %02x grp %3d ", // Spelling error is intentional
|
|
heap,size,atb,group);
|
|
}
|
|
|
|
void *MemoryAlloc(s32 size, s32 group)
|
|
{
|
|
return DoAlloc(&sMainHeapDescriptor, size, group);
|
|
}
|
|
|
|
void MemoryFree(void *a)
|
|
{
|
|
DoFree(&sMainHeapDescriptor, a);
|
|
}
|
|
|
|
ALIGNED(4) static const char sText_MemoryLocate_LocalCreate[] = "MemoryLocate_LocalCreate";
|
|
|
|
UNUSED static struct HeapDescriptor *MemoryLocate_LocalCreate(struct HeapDescriptor *parentHeap,u32 size,u32 param_3,u32 group)
|
|
{
|
|
int index;
|
|
struct HeapFreeListElement *foundSet;
|
|
struct HeapDescriptor *iVar3;
|
|
struct unkMemoryStruct local_1c;
|
|
|
|
if (parentHeap == NULL) {
|
|
parentHeap = &sMainHeapDescriptor;
|
|
}
|
|
|
|
index = MemorySearchFromBack(parentHeap,9,size);
|
|
if (index < 0) {
|
|
static const DebugLocation debugInfo = {
|
|
.file = sFileNameText,
|
|
.line = 1109,
|
|
.func = sText_MemoryLocate_LocalCreate
|
|
};
|
|
FatalError(&debugInfo,"Memroy LocalCreate buffer %08x size can't locate",size); // Spelling error is intentional
|
|
}
|
|
|
|
foundSet = _LocateSetBack(parentHeap,index,9,size,group);
|
|
local_1c.unk0 = (void *) foundSet->block.start;
|
|
local_1c.end = foundSet->block.size;
|
|
|
|
iVar3 = DoCreateSubHeap(&local_1c,param_3);
|
|
iVar3->parentHeap = parentHeap;
|
|
return iVar3;
|
|
}
|
|
|
|
static struct HeapDescriptor *DoCreateSubHeap(struct unkMemoryStruct *a, u32 b)
|
|
{
|
|
struct HeapMemoryBlock2 s2;
|
|
struct HeapDescriptor *a1;
|
|
|
|
a1 = a->unk0;
|
|
s2.start = (struct HeapFreeListElement *)((u8*)a1 + sizeof(struct HeapDescriptor));
|
|
s2.size = a->end - sizeof(struct HeapDescriptor);
|
|
InitSubHeap(a1, &s2, b);
|
|
return a1;
|
|
}
|
|
|
|
UNUSED static void xxx_unused_memory_free(struct HeapDescriptor *a1)
|
|
{
|
|
bool8 b;
|
|
s32 i;
|
|
bool8 temp;
|
|
|
|
if (a1 == NULL)
|
|
return;
|
|
|
|
b = FALSE;
|
|
if (a1->freeCount == 1 && a1->freeList->atb == 0)
|
|
b = TRUE;
|
|
|
|
if (b) {
|
|
temp = FALSE;
|
|
i = 0;
|
|
for (; i < sHeapCount; i++) {
|
|
if (sHeapDescriptorList[i] == a1) {
|
|
sHeapCount--;
|
|
for (; i < sHeapCount; i++) {
|
|
sHeapDescriptorList[i] = sHeapDescriptorList[i + 1];
|
|
}
|
|
temp = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if (temp && a1->parentHeap != NULL)
|
|
DoFree(a1->parentHeap, a1);
|
|
}
|
|
}
|
|
|
|
static void *DoAlloc(struct HeapDescriptor *heap, s32 size, u32 a2)
|
|
{
|
|
return _LocateSet(heap, size, a2 | 0x100);
|
|
}
|
|
|
|
static void DoFree(struct HeapDescriptor *heapDescriptior, void *ptrToFree)
|
|
{
|
|
struct HeapFreeListElement *curr;
|
|
struct HeapFreeListElement *next;
|
|
struct HeapFreeListElement *prev;
|
|
s32 i;
|
|
|
|
if (heapDescriptior == NULL)
|
|
heapDescriptior = &sMainHeapDescriptor;
|
|
|
|
if (ptrToFree == NULL)
|
|
return;
|
|
|
|
i = 0;
|
|
curr = &heapDescriptior->freeList[0];
|
|
for (; i < heapDescriptior->freeCount; i++, curr++) {
|
|
if (curr->block.start == (u8 *)ptrToFree) {
|
|
curr->unk_atb = 0;
|
|
curr->atb = 0;
|
|
curr->block.allocatedSize = 0;
|
|
curr->grp = 0;
|
|
|
|
if (i < heapDescriptior->freeCount - 1) {
|
|
s32 j;
|
|
|
|
next = curr + 1;
|
|
if (next->atb == 0) {
|
|
curr->block.size += next->block.size;
|
|
heapDescriptior->freeCount--;
|
|
for (j = i + 1; j < heapDescriptior->freeCount; j++, next++)
|
|
next[0] = next[1];
|
|
}
|
|
}
|
|
|
|
if (i >= 1) {
|
|
s32 j;
|
|
prev = curr - 1;
|
|
if (prev->atb == 0) {
|
|
prev->block.size += curr->block.size;
|
|
heapDescriptior->freeCount--;
|
|
prev = curr;
|
|
for (j = i; j < heapDescriptior->freeCount; j++, prev++)
|
|
prev[0] = prev[1];
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
UNUSED static void nullsub_141(void)
|
|
{
|
|
|
|
}
|
|
|
|
UNUSED static void nullsub_142(void)
|
|
{
|
|
|
|
} |