Digimon World 3 decomp
The European version, SLES_039.36
Loading...
Searching...
No Matches
heap.c
Go to the documentation of this file.
1#include "engine/game.h"
2
3/* Frees a heap block, merging it with the free blocks around it */
4void freeMem(void *ptr) {
5 MemBlock *block = (MemBlock *)ptr - 1; /* the header just before the data */
6 MemBlock *prev;
7 MemBlock *next;
8
9 if (ptr != NULL) {
10 prev = block->prev;
11 next = block->next;
12 block->tag = MEM_FREE;
13 if (next->tag == MEM_FREE) {
14 block->next = next->next;
15 next->next->prev = block;
16 }
17 if (prev->tag == MEM_FREE) {
18 prev->next = block->next;
19 block->next->prev = prev;
20 }
21 }
22}
23
24/* HEAP.nop: empty, and nothing calls it */
25void heapNop(void) {
26}
27
28/* Frees every heap block with tag `tag` */
29void freeMemByTag(s32 tag) {
30 MemBlock *block;
31
32 for (block = HEAP.first; block->tag != MEM_END; block = block->next) {
33 if (block->tag == tag) {
34 freeMem(block + 1);
35 }
36 }
37}
38
39/* Makes the heap one free block from HEAP_START, followed by the end marker */
40void initHeap(void) {
42 MemBlock *last;
43
45 last = HEAP_END - 1;
48 HEAP.size = (u8 *)HEAP_END - (u8 *)start;
49 start->prev = start;
50 start->next = last;
51 start->tag = MEM_FREE;
52 last->prev = start;
53 last->tag = MEM_END;
54 last->next = HEAP.end;
55}
56
57/* Clears `size` bytes, a word at a time when size is a multiple of 4 */
58void zeroMem(void *dst, s32 size) {
59 s32 i;
60
61 if (size & 3) {
62 u8 *p = dst;
63
64 for (i = 0; i < size; i++) {
65 *p++ = 0;
66 }
67 } else {
68 s32 *p = dst;
69
70 size >>= 2;
71 for (i = 0; i < size; i++) {
72 *p++ = 0;
73 }
74 }
75}
76
77/* Sets `count` bytes to `value` */
78void fillMem(s8 *dst, s8 value, s32 count) {
79 s32 i;
80
81 for (i = 0; i < count; i++) {
82 *dst++ = value;
83 }
84}
85
86/* First fit from the start of the heap */
87void *tryAllocMem(u32 size, s32 tag) {
88 MemBlock *b;
89 MemBlock *new;
90 u32 avail;
91 u32 splitSize;
92
93 size = (size + 3) >> 2 << 2;
94 splitSize = size + 20;
95 for (b = HEAP.first; b->tag != MEM_END; b = b->next) {
96 if (b->tag == MEM_FREE) {
97 avail = (u8 *)b->next - (u8 *)b - sizeof(MemBlock);
98 if (avail >= size) {
99 if (avail > splitSize) {
100 new = (MemBlock *)((u8 *)b + size + sizeof(MemBlock));
101 new->prev = b;
102 new->next = b->next;
103 new->tag = MEM_FREE;
104 b->next->prev = new;
105 b->next = new;
106 }
107 b->tag = tag;
108 return b + 1;
109 }
110 }
111 }
112 return NULL;
113}
114
115/* First fit from the end of the heap */
116void *tryAllocMemHigh(u32 size, s32 tag) {
117 MemBlock *b;
118 MemBlock *prev;
119 MemBlock *new;
120 u32 avail;
121
122 size = ((size + 3) >> 2 << 2) + sizeof(MemBlock);
123 for (b = HEAP.end - 1; HEAP.first != b; b = b->prev) {
124 prev = b->prev;
125 if (prev->tag == MEM_FREE) {
126 avail = (u8 *)b - (u8 *)prev;
127 if (size == avail) {
128 new = prev;
129 new->tag = tag;
130 return new + 1;
131 }
132 if (size < avail) {
133 new = (MemBlock *)((u8 *)b - size);
134 new->prev = prev;
135 new->next = b;
136 new->tag = tag;
137 b->prev->next = new;
138 b->prev = new;
139 return new + 1;
140 }
141 }
142 }
143 return NULL;
144}
145
146/* Evicts cached files until the allocation fits */
147void *allocMem(s32 size, s32 tag) {
148 void *ptr;
149
150 while ((ptr = tryAllocMem(size, tag)) == NULL) {
152 }
153 return ptr;
154}
155
156/* The block is returned in v0, left there by tryAllocMemHigh */
157void allocMemHigh(s32 size, s32 tag) {
158 while (tryAllocMemHigh(size, tag) == 0) {
160 }
161}
162
163/* allocMem, cleared */
164void *allocMemZeroed(s32 size, s32 tag) {
165 void *ret = allocMem(size, tag);
166
167 zeroMem(ret, size);
168 return ret;
169}
170
171/* Keeps a block alive across mode changes, or hands it back to the mode */
172void lockMem(void *ptr, s32 lock) {
173 MemBlock *block = (MemBlock *)ptr - 1; /* the header just before the data */
174
175 if (lock) {
176 block->tag = MEM_LOCKED;
177 } else {
178 block->tag = MEM_MODE;
179 }
180}
181
182/* The functions that return what a call left in v0 (allocMemHigh, findTask) and the ones that take
183 other types are cast to what the tables give their callers */
185 0,
186 NULL,
187 NULL,
188 initHeap,
189 freeMem,
191 allocMem,
192 (void *(*)(s32, s32))allocMemHigh,
194 zeroMem,
195 (void (*)(void *, s32, s32))fillMem,
196 lockMem,
197 heapNop,
198};
#define NULL
Definition common.h:17
signed int s32
Definition common.h:11
unsigned int u32
Definition common.h:12
signed char s8
Definition common.h:7
unsigned char u8
Definition common.h:8
FileCache FILE_CACHE
The file cache.
Definition file_cache.c:7
void freeMemByTag(s32 tag)
Frees every heap block with tag tag
Definition heap.c:29
void * allocMemZeroed(s32 size, s32 tag)
allocMem, cleared
Definition heap.c:164
void freeMem(void *ptr)
Frees a heap block, merging it with the free blocks around it.
Definition heap.c:4
void lockMem(void *ptr, s32 lock)
Keeps a block alive across mode changes, or hands it back to the mode.
Definition heap.c:172
void * tryAllocMem(u32 size, s32 tag)
First fit from the start of the heap.
Definition heap.c:87
void initHeap(void)
Makes the heap one free block from HEAP_START, followed by the end marker.
Definition heap.c:40
void allocMemHigh(s32 size, s32 tag)
The block is returned in v0, left there by tryAllocMemHigh.
Definition heap.c:157
void fillMem(s8 *dst, s8 value, s32 count)
Sets count bytes to value
Definition heap.c:78
void * allocMem(s32 size, s32 tag)
Evicts cached files until the allocation fits.
Definition heap.c:147
void * tryAllocMemHigh(u32 size, s32 tag)
First fit from the end of the heap.
Definition heap.c:116
void heapNop(void)
HEAP.nop: empty, and nothing calls it.
Definition heap.c:25
Heap HEAP
The functions that return what a call left in v0 (allocMemHigh, findTask) and the ones that take othe...
Definition heap.c:184
void zeroMem(void *dst, s32 size)
Clears size bytes, a word at a time when size is a multiple of 4.
Definition heap.c:58
#define MEM_FREE
MemBlock.tag.
Definition heap.h:15
#define HEAP_END
The heap: a doubly linked list of blocks from HEAP_START to HEAP_END.
Definition heap.h:12
#define MEM_END
the marker that ends the list
Definition heap.h:16
#define MEM_LOCKED
kept across mode changes (lockMem)
Definition heap.h:19
#define MEM_MODE
the current mode's: freed by main whenever the mode task ends
Definition heap.h:17
MemBlock * HEAP_START
The first of the executable's small data (.sdata), where $gp points.
Definition heap_start.c:10
Task * start(void)
The mode's entry point (MODE_ENTRY_POINTS): starts its root task (update_scene.inc....
Definition start.inc.c:3
void(* evictOldest)(void)
Definition file.h:89
The heap (HEAP)
Definition heap.h:22
struct MemBlock * end
Definition heap.h:25
s32 size
Definition heap.h:23
struct MemBlock * first
Definition heap.h:24
Header of a heap block; the data follows it.
Definition heap.h:40
struct MemBlock * prev
Definition heap.h:41
struct MemBlock * next
Definition heap.h:42
s32 tag
MEM_*.
Definition heap.h:43