pmd-red/src/memory.c
2024-12-02 12:00:19 +01:00

552 lines
13 KiB
C

#include "global.h"
#include "cpu.h"
#include "memory.h"
EWRAM_DATA struct HeapDescriptor *gHeapDescriptorList[8] = {0}; // 2000E88
EWRAM_DATA s32 gHeapCount = {0}; // 2000EA8
UNUSED static EWRAM_DATA u32 sUnused1 = {0}; // 2000EAC
EWRAM_DATA struct HeapDescriptor gMainHeapDescriptor = {0}; // 2000EB0
UNUSED static EWRAM_DATA u32 sUnused2 = {0}; // 2000ECC
extern struct HeapFreeListElement gMainHeapFreeList[32]; // 2000ED0 (CAPACITY OR STRUCT SIZE IS WRONG)
extern u8 gMainHeap[HEAP_SIZE]; // 20011D0
void InitHeapInternal(void);
void InitHeap(void)
{
InitHeapInternal();
}
void MemoryClear8(u8 *dest, s32 size)
{
while (size > 0)
{
size -= 1;
*dest++ = 0;
}
}
void MemoryClear16(u16 *dest, s32 size)
{
while (size > 0)
{
size -= 2;
*dest++ = 0;
}
}
void MemoryClear32(u32 *dest, s32 size)
{
CpuClear(dest, size);
}
void MemoryFill8(u8 *dest, u8 value, s32 size)
{
while (size > 0)
{
size -= 1;
*dest++ = value;
}
}
void MemoryFill16(u16 *dest, u16 value, s32 size)
{
while (size > 0)
{
size -= 2;
*dest++ = value;
}
}
void MemoryFill32(u32 *dest, u32 value, s32 size)
{
while (size > 0)
{
size -= 4;
*dest++ = value;
}
}
void MemoryCopy8(u8 *dest, u8 *src, s32 size)
{
while (size > 0)
{
size -= 1;
*dest++ = *src++;
}
}
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++;
}
}
void InitHeapInternal(void)
{
struct HeapSettings settings;
settings.start = gMainHeap;
settings.size = HEAP_SIZE;
gHeapCount = 0;
DoInitHeap(&gMainHeapDescriptor, &settings, gMainHeapFreeList, sizeof(gMainHeapFreeList) / sizeof(struct HeapFreeListElement));
}
void DoInitHeap(struct HeapDescriptor *descriptor, struct HeapSettings *settings, struct HeapFreeListElement *freeList, u32 freeListLength)
{
u32 aligned_size;
aligned_size = settings->size & 0xFFFFFFFC;
gHeapDescriptorList[gHeapCount++] = 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;
}
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);
}
u32 xxx_memory_attr_related(u32 r0)
{
u32 temp;
u32 return_var;
if(r0 == 0)
{
return 0;
}
if((r0 & 8) != 0)
{
return 4;
}
temp = r0 & 7;
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;
}
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;
}
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;
}
// Todo: fix fatal error and struct unkMemoryStruct2 *
void FatalError(const void *, const char *, ...) __attribute__((noreturn));
extern const char *const gUnknown_80B7EB8;
extern const char *const gUnknown_80B7EFC;
extern const char gUnknown_80B7EC4[];
struct unkMemoryStruct2 * _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) {
// ../system/memory_locate.c
// Memory Locate sprit max over [%3d/%3d]
FatalError(&gUnknown_80B7EB8, gUnknown_80B7EC4, 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 (void*) curr;
}
struct unkMemoryStruct2 * _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) {
// ../system/memory_locate.c
// Memory Locate sprit max over [%3d/%3d]
FatalError(&gUnknown_80B7EFC, gUnknown_80B7EC4, 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 (void*) curr;
}
extern u32 gUnknown_80B7F14;
extern u32 gUnknown_80B7F88;
extern const char gLocateSetErrorMessage[];
extern struct HeapDescriptor gMainHeapDescriptor;
extern const char gLocalCreateErrorMessage[];
extern s32 MemorySearchFromBack(struct HeapDescriptor *heap, s32, s32);
extern s32 MemorySearchFromFront(struct HeapDescriptor *heap, s32, s32);
void DoFree(struct HeapDescriptor *, void *);
void *DoAlloc(struct HeapDescriptor *, s32, u32);
struct HeapDescriptor* _LocateSet(struct HeapDescriptor *heap, s32 size, s32 group)
{
s32 index;
struct unkMemoryStruct2 * uVar2;
s32 atb;
if (heap == NULL) {
heap = &gMainHeapDescriptor;
}
// 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;
uVar2 = _LocateSetFront(heap,index,atb,size,group);
return uVar2->unkC;
}
else {
index = MemorySearchFromBack(heap,atb,size);
if (index < 0) goto error;
uVar2 = _LocateSetBack(heap,index,atb,size,group);
return uVar2->unkC;
}
error:
// LocateSet [%p] buffer %8x size can't locate
// atb %02x grp %3d
FatalError(&gUnknown_80B7F14,
gLocateSetErrorMessage,
heap,size,atb,group);
}
void *MemoryAlloc(s32 size, s32 group)
{
DoAlloc(&gMainHeapDescriptor, size, group);
}
void MemoryFree(void *a)
{
DoFree(&gMainHeapDescriptor, a);
}
struct HeapDescriptor *MemoryLocate_LocalCreate(struct HeapDescriptor *parentHeap,u32 size,u32 param_3,u32 group)
{
int index;
struct unkMemoryStruct2 *iVar2;
struct HeapDescriptor *iVar3;
struct unkMemoryStruct local_1c;
if (parentHeap == NULL) {
parentHeap = &gMainHeapDescriptor;
}
index = MemorySearchFromBack(parentHeap,9,size);
if (index < 0)
// Memroy LocalCreate buffer %08x size can't locate
FatalError(&gUnknown_80B7F88,gLocalCreateErrorMessage,size);
iVar2 = _LocateSetBack(parentHeap,index,9,size,group);
local_1c.unk0 = iVar2->unkC;
local_1c.end = iVar2->end;
iVar3 = DoCreateSubHeap(&local_1c,param_3);
iVar3->parentHeap = parentHeap;
return iVar3;
}
struct HeapDescriptor *DoCreateSubHeap(struct unkMemoryStruct *a, u32 b)
{
struct HeapMemoryBlock2 s2;
struct HeapDescriptor *a1;
u32 end;
a1 = a->unk0;
s2.start = (struct HeapFreeListElement *)((u8*)a1 + sizeof(struct HeapDescriptor));
end = a->end;
s2.size = end - sizeof(struct HeapDescriptor);
InitSubHeap(a1, &s2, b);
return a1;
}
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 < gHeapCount; i++) {
if (gHeapDescriptorList[i] == a1) {
gHeapCount--;
for (; i < gHeapCount; i++) {
gHeapDescriptorList[i] = gHeapDescriptorList[i + 1];
}
temp = TRUE;
break;
}
}
if (temp && a1->parentHeap != NULL)
DoFree(a1->parentHeap, a1);
}
}
void *DoAlloc(struct HeapDescriptor *heap, s32 size, u32 a2)
{
return _LocateSet(heap, size, a2 | 0x100);
}
void DoFree(struct HeapDescriptor *heapDescriptior, void *ptrToFree)
{
struct HeapFreeListElement *curr;
struct HeapFreeListElement *next;
struct HeapFreeListElement *prev;
s32 i;
if (heapDescriptior == NULL)
heapDescriptior = &gMainHeapDescriptor;
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;
}
}
}
void nullsub_141(void)
{
}
void nullsub_142(void)
{
}