132 lines
3 KiB
C
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;
|
|
}
|