mirror of
https://github.com/pret/pokediamond.git
synced 2026-08-07 03:04:19 -05:00
257 lines
5.1 KiB
C
257 lines
5.1 KiB
C
//
|
|
// Created by mart on 4/23/20.
|
|
//
|
|
|
|
#include "os_alloc.h"
|
|
#include "consts.h"
|
|
#include "os_system.h"
|
|
|
|
extern Cell* DLInsert(Cell* list, Cell* cell);
|
|
extern Cell* DLAddFront(Cell* list, Cell* cell);
|
|
|
|
void* OSiHeapInfo[OS_ARENA_MAX] = {
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
};
|
|
|
|
#ifdef MATCH_ASM
|
|
asm static Cell* DLExtract(Cell* list, Cell* cell)
|
|
{
|
|
ldr r3, [r1, #0x4]
|
|
cmp r3, #0x0
|
|
ldrne r2, [r1, #0x0]
|
|
strne r2, [r3, #0x0]
|
|
ldr r2, [r1, #0x0]
|
|
cmp r2, #0x0
|
|
ldreq r0, [r1, #0x4]
|
|
ldrne r1, [r1, #0x4]
|
|
strne r1, [r2, #0x4]
|
|
bx lr
|
|
}
|
|
#else
|
|
static Cell* DLExtract(Cell* list, Cell* cell)
|
|
{
|
|
if (cell->next) {
|
|
cell->prev = cell->next->prev;
|
|
}
|
|
if (cell->prev) {
|
|
cell->prev->next = cell->next;
|
|
return list;
|
|
}
|
|
else {
|
|
return cell->next;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#define HEADERSIZE OSi_ROUND(sizeof(Cell), 32)
|
|
#define MINOBJSIZE (HEADERSIZE+32)
|
|
|
|
#ifdef MATCH_ASM
|
|
asm void OS_FreeToHeap(OSArenaId id, OSHeapHandle heap, void* ptr) {
|
|
stmdb sp!, {r4-r7, lr}
|
|
sub sp,sp,#0x4
|
|
mov r7,r0
|
|
mov r5,r1
|
|
mov r4,r2
|
|
bl OS_DisableInterrupts
|
|
ldr r1,=OSiHeapInfo
|
|
mov r6,r0
|
|
ldr r0,[r1,r7,lsl #0x2]
|
|
cmp r5,#0x0
|
|
ldrlt r5,[r0,#0x0]
|
|
ldr r1,[r0,#0x10]
|
|
mov r0,#0xc
|
|
mla r7,r5,r0,r1
|
|
sub r4,r4,#0x20
|
|
ldr r0,[r7,#0x8]
|
|
mov r1,r4
|
|
bl DLExtract
|
|
str r0,[r7,#0x8]
|
|
ldr r0,[r7,#0x4]
|
|
mov r1,r4
|
|
bl DLInsert
|
|
str r0,[r7,#0x4]
|
|
mov r0,r6
|
|
bl OS_RestoreInterrupts
|
|
add sp,sp,#0x4
|
|
ldmia sp!,{ r4-r7, lr }
|
|
bx lr
|
|
}
|
|
#else
|
|
void OS_FreeToHeap(OSArenaId id, OSHeapHandle heap, void* ptr) {
|
|
OSHeapInfo *heapInfo;
|
|
HeapDesc *hd;
|
|
Cell *cell;
|
|
|
|
OSIntrMode enabled = OS_DisableInterrupts();
|
|
heapInfo = OSiHeapInfo[id];
|
|
|
|
if (heap < 0) {
|
|
heap = heapInfo->currentHeap;
|
|
}
|
|
|
|
cell = (Cell *) ((char *)ptr - HEADERSIZE);
|
|
hd = &heapInfo->heapArray[heap];
|
|
|
|
hd->allocated = DLExtract(hd->allocated, cell);
|
|
hd->free = DLInsert(hd->free, cell);
|
|
|
|
OS_RestoreInterrupts(enabled);
|
|
}
|
|
#endif
|
|
|
|
#ifdef MATCH_ASM
|
|
asm void* OS_AllocFromHeap(OSArenaId id, OSHeapHandle heap, u32 size) {
|
|
stmdb sp!, {r4-r7,lr}
|
|
sub sp, sp, #0x4
|
|
mov r6, r0
|
|
mov r5, r1
|
|
mov r7, r2
|
|
bl OS_DisableInterrupts
|
|
ldr r1, =OSiHeapInfo
|
|
mov r4, r0
|
|
ldr r1, [r1, r6, lsl #0x2]
|
|
cmp r1, #0x0
|
|
bne _020CC7AC
|
|
bl OS_RestoreInterrupts
|
|
add sp, sp, #0x4
|
|
mov r0, #0x0
|
|
ldmia sp!, {r4-r7,lr}
|
|
bx lr
|
|
_020CC7AC:
|
|
cmp r5, #0x0
|
|
ldrlt r5, [r1, #0x0]
|
|
ldr r1, [r1, #0x10]
|
|
mov r0, #0xc
|
|
mla r6, r5, r0, r1
|
|
ldr r0, [r6, #0x4]
|
|
add r1, r7, #0x20
|
|
add r1, r1, #0x1f
|
|
mov r5, r0
|
|
cmp r0, #0x0
|
|
bic r7, r1, #0x1f
|
|
beq _020CC7F4
|
|
_020CC7DC:
|
|
ldr r1, [r5, #0x8]
|
|
cmp r7, r1
|
|
ble _020CC7F4
|
|
ldr r5, [r5, #0x4]
|
|
cmp r5, #0x0
|
|
bne _020CC7DC
|
|
_020CC7F4:
|
|
cmp r5, #0x0
|
|
bne _020CC814
|
|
mov r0, r4
|
|
bl OS_RestoreInterrupts
|
|
add sp, sp, #0x4
|
|
mov r0, #0x0
|
|
ldmia sp!, {r4-r7,lr}
|
|
bx lr
|
|
_020CC814:
|
|
ldr r1, [r5, #0x8]
|
|
sub r1, r1, r7
|
|
cmp r1, #0x40
|
|
bhs _020CC834
|
|
mov r1, r5
|
|
bl DLExtract
|
|
str r0, [r6, #0x4]
|
|
b _020CC86C
|
|
_020CC834:
|
|
str r7, [r5, #0x8]
|
|
add r2, r5, r7
|
|
str r1, [r2, #0x8]
|
|
ldr r0, [r5, #0x0]
|
|
str r0, [r5, r7]
|
|
ldr r0, [r5, #0x4]
|
|
str r0, [r2, #0x4]
|
|
ldr r0, [r2, #0x4]
|
|
cmp r0, #0x0
|
|
strne r2, [r0, #0x0]
|
|
ldr r0, [r2, #0x0]
|
|
cmp r0, #0x0
|
|
strne r2, [r0, #0x4]
|
|
streq r2, [r6, #0x4]
|
|
_020CC86C:
|
|
ldr r0, [r6, #0x8]
|
|
mov r1, r5
|
|
bl DLAddFront
|
|
str r0, [r6, #0x8]
|
|
mov r0, r4
|
|
bl OS_RestoreInterrupts
|
|
add r0, r5, #0x20
|
|
add sp, sp, #0x4
|
|
ldmia sp!, {r4-r7,lr}
|
|
bx lr
|
|
}
|
|
#else
|
|
void* OS_AllocFromHeap(OSArenaId id, OSHeapHandle heap, u32 size) {
|
|
OSHeapInfo* heapInfo;
|
|
HeapDesc* hd;
|
|
Cell* cell;
|
|
Cell* newCell;
|
|
long leftoverSize;
|
|
|
|
OSIntrMode enabled = OS_DisableInterrupts();
|
|
heapInfo = OSiHeapInfo[id];
|
|
if (!heapInfo) {
|
|
OS_RestoreInterrupts(enabled);
|
|
return NULL;
|
|
}
|
|
|
|
if (heap < 0) {
|
|
heap = heapInfo->currentHeap;
|
|
}
|
|
|
|
hd = &heapInfo->heapArray[heap];
|
|
|
|
size += HEADERSIZE;
|
|
size = OSi_ROUND(size, 32);
|
|
|
|
for (cell = hd->free; cell != NULL; cell = cell->next) {
|
|
if ((long)size <= cell->size) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (cell == NULL) {
|
|
OS_RestoreInterrupts(enabled);
|
|
return NULL;
|
|
}
|
|
|
|
leftoverSize = cell->size - (long)size;
|
|
if (leftoverSize < MINOBJSIZE) {
|
|
hd->free = DLExtract(hd->free, cell);
|
|
} else {
|
|
cell->size = (long)size;
|
|
|
|
newCell = (Cell *) ((char *)cell + size);
|
|
newCell->size = leftoverSize;
|
|
|
|
newCell->prev = cell->prev;
|
|
newCell->next = cell->next;
|
|
|
|
if (newCell->next != NULL) {
|
|
newCell->next->prev = newCell;
|
|
}
|
|
|
|
if (newCell->prev != NULL) {
|
|
newCell->prev->next = newCell;
|
|
} else {
|
|
hd->free = newCell;
|
|
}
|
|
}
|
|
|
|
hd->allocated = DLAddFront(hd->allocated, cell);
|
|
|
|
OS_RestoreInterrupts(enabled);
|
|
return (void *)((char *)cell + HEADERSIZE);
|
|
}
|
|
#endif |