marioparty4/src/msm/msmmem.c
2025-01-15 23:40:36 -06:00

132 lines
3 KiB
C

#include "msm/msmmem.h"
typedef struct MSMBlock_s {
struct MSMBlock_s* prev;
struct MSMBlock_s* next;
u32 freeSize;
u32 size;
void* ptr;
char pad[12];
} MSMBLOCK;
typedef struct MSMMem_s {
void *ptr;
u32 size;
MSMBLOCK *head;
MSMBLOCK first;
} MSM_MEM;
static MSM_MEM mem;
void msmMemFree(void* ptr) {
MSMBLOCK* block;
MSMBLOCK* blockPrev;
MSMBLOCK* blockNext;
MSMBLOCK* blockHead;
MSMBLOCK* base;
base = ptr;
block = &base[-1];
blockPrev = block->prev;
blockNext = block->next;
if (mem.ptr > block || ((u32)mem.ptr + (u32)mem.size) <= (u32)block) {
return;
}
if ((blockPrev->next != block) || (block->ptr != ptr) || (blockNext && (blockNext->prev != block))) {
return;
}
blockPrev->size += block->freeSize + block->size;
blockPrev->next = blockNext;
blockHead = mem.head;
if ((blockHead == block) || (blockHead->size < blockPrev->size)) {
mem.head = blockPrev;
}
if (blockNext) {
blockNext->prev = blockPrev;
if (mem.head->size < blockNext->size) {
mem.head = blockNext;
}
}
}
void* msmMemAlloc(u32 size) {
s32 alignOfs;
u32 freeSize;
u32 allocSize;
MSMBLOCK* block;
MSMBLOCK* blockPrev;
MSMBLOCK* blockNext;
allocSize = size + 0x20;
alignOfs = allocSize & 0x1F;
if (alignOfs) {
allocSize += 0x20 - alignOfs;
}
if (mem.head->size >= allocSize) {
blockPrev = mem.head;
} else {
blockPrev = &mem.first;
do {
if (blockPrev->size >= allocSize) break;
blockPrev = blockPrev->next;
} while (blockPrev);
if (!blockPrev) {
return NULL;
}
}
freeSize = blockPrev->freeSize;
if (freeSize != 0) {
freeSize -= 0x20;
}
block = (void*)((u32)blockPrev->ptr + (freeSize));
blockNext = blockPrev->next;
if ((mem.ptr > block) || ((void*)((u32)mem.ptr + (u32)mem.size) <= block)) {
return NULL;
}
block->freeSize = allocSize;
block->size = blockPrev->size - allocSize;
block->ptr = (block + 1);
block->prev = blockPrev;
block->next = blockNext;
mem.head = block;
blockPrev->size = 0;
blockPrev->next = block;
if (blockNext) {
blockNext->prev = block;
if (mem.head->size < blockNext->size) {
mem.head = blockNext;
}
}
return block->ptr;
}
void msmMemInit(void* ptr, u32 size) {
MSMBLOCK* block;
s32 ofs;
ofs = (s32)ptr & 0x1F;
switch (ofs) {
default:
ofs = 0x20 - ofs;
break;
case 0:
ofs = 0;
break;
}
mem.ptr = (void*)((s32)ptr + ofs);
ofs = (s32)ptr + size;
mem.size = ((ofs - (s32)mem.ptr) & ~0x1F);
block = &mem.first;
block->freeSize = 0;
block->size = mem.size;
block->ptr = mem.ptr;
block->prev = NULL;
block->next = NULL;
mem.head = &mem.first;
}