Wing Commander II
Reconstructed Win32 source (1996)
Loading...
Searching...
No Matches
nearheap.c
Go to the documentation of this file.
1/*
2 * Near heap allocator.
3 *
4 * Retail object 0x4207B0-0x42120F (link order; see docs/ORDER.md).
5 */
6#define NEARHEAP_C
7#include "game.h"
8
9volatile short g_nNearHeapActive = 0; /* 0x00493044 */
10volatile short g_nNearHeapMaxDescriptors = 0x80; /* 0x00493048 */
11volatile int g_nNearHeapRelocationBytes = 0; /* 0x0049304c */
12#include <float.h>
13
14/* Function start: 0x4207B0 */
15short MergeAdjacentNearHeapBlocks(int descriptorAddress)
16{
17 NearHeapBlock *block;
18
19 block = DosNearPtrToFar(descriptorAddress);
20 if ((block->sizeAndFlags & 0x80000000) == 0 &&
21 (block[1].sizeAndFlags & 0x80000000) == 0 &&
22 block->address + (block->sizeAndFlags & 0xfffff) ==
23 block[1].address) {
24 block[1].address = block->address;
25 block[1].sizeAndFlags += block->sizeAndFlags & 0xfffff;
26 while (descriptorAddress > g_nNearHeapFirstDescriptor) {
27 descriptorAddress -= 8;
28 block = DosNearPtrToFar(descriptorAddress);
29 block[1].address = block->address;
30 block[1].sizeAndFlags = block->sizeAndFlags;
31 }
33 return 1;
34 }
35 return 0;
36}
37
38/* Function start: 0x420874 */
39int ReleaseNearHeapBlock(int descriptorAddress)
40{
41 NearHeapBlock *block;
42
43 block = DosNearPtrToFar(descriptorAddress);
44 /* The signed read is what keeps the mask out of the descriptor
45 * word: the compiler folds the unsigned form into `and [mem]`. */
46 block->sizeAndFlags = (int)block->sizeAndFlags & 0x7fffffff;
48 descriptorAddress + 8 &&
49 MergeAdjacentNearHeapBlocks(descriptorAddress) != 0)
50 descriptorAddress += 8;
51 if (descriptorAddress > g_nNearHeapFirstDescriptor)
52 MergeAdjacentNearHeapBlocks(descriptorAddress - 8);
53 return descriptorAddress;
54}
55
56/* Function start: 0x4208FC */
57void PurgeNearHeapBlocks(short flags)
58{
59 NearHeapBlock *entry;
60 int descriptorAddress;
61
62 if (g_nNearHeapActive != 0) {
63 if ((flags & 0x10) != 0) {
70 } else {
71 descriptorAddress =
73 while (descriptorAddress >=
75 entry = DosNearPtrToFar(descriptorAddress);
76 if ((entry->sizeAndFlags & 0x40000000) == 0)
77 descriptorAddress =
78 ReleaseNearHeapBlock(descriptorAddress);
79 descriptorAddress -= 8;
80 }
81 }
82 }
83}
84
85/* Function start: 0x4209C2 */
125
126/* Function start: 0x420B12 */
142
143/* Function start: 0x420B88 */
144void *AllocateNearHeapBlockFromEnd(int size, short flags)
145{
146 unsigned int newFlags;
147 int freeSize;
148 NearHeapBlock *entry;
149 NearHeapBlock *lastBlock;
150 int descriptorAddress;
151 int moveAddress;
152 int found;
153
154 if (size <= 0)
155 return 0;
156 newFlags = 0x80000000;
157 if ((flags & 3) == 1) {
158 newFlags |= 0x10000000;
159 size++;
160 } else if ((flags & 3) == 2) {
161 newFlags |= 0x20000000;
162 size += 0xf;
163 }
164 if ((flags & 0x10) != 0)
165 newFlags |= 0x40000000;
166
167 found = 0;
168 descriptorAddress =
170 while (descriptorAddress >= g_nNearHeapFirstDescriptor) {
171 entry = DosNearPtrToFar(descriptorAddress);
172 freeSize = entry->sizeAndFlags & 0xfffff;
173 if ((entry->sizeAndFlags & 0x80000000) == 0 && freeSize >= size) {
174 if (freeSize > size) {
178 lastBlock = DosNearPtrToFar(
180 g_nNearArenaSize - 8);
181 if ((lastBlock->sizeAndFlags & 0x80000000) == 0 &&
182 lastBlock->address +
183 (lastBlock->sizeAndFlags & 0xfffff) ==
185 (int)(lastBlock->sizeAndFlags & 0xfffff) > 8) {
186 lastBlock->sizeAndFlags -= 8;
188 }
189 }
194 moveAddress = g_nNearHeapFirstDescriptor;
195 while (moveAddress < descriptorAddress) {
196 lastBlock = DosNearPtrToFar(moveAddress);
197 lastBlock->address = lastBlock[1].address;
198 lastBlock->sizeAndFlags = lastBlock[1].sizeAndFlags;
199 moveAddress += 8;
200 }
201 descriptorAddress -= 8;
202 entry = DosNearPtrToFar(descriptorAddress);
203 entry->sizeAndFlags -= size;
204 entry[1].address +=
205 (int)(entry->sizeAndFlags & 0xffffff);
206 entry[1].sizeAndFlags = newFlags + size;
207 found = entry[1].address;
208 break;
209 }
210 } else {
211 entry->sizeAndFlags |= newFlags;
212 found = entry->address;
213 break;
214 }
215 }
216 descriptorAddress -= 8;
217 }
218
219 if (found != 0) {
220 if ((flags & 3) == 1)
221 found = (found + 1) & 0xfffffffe;
222 else if ((flags & 3) == 2)
223 found = (found + 0xf) & 0xfffffff0;
224 }
225 return DosNearPtrToFar(found);
226}
227
228/* Function start: 0x420E16 */
229void *AllocateNearHeapBlockByFlags(int size, short flags)
230{
231 NearHeapBlock *entry;
232 NearHeapBlock *lastBlock;
233 int descriptorAddress;
234 int moveAddress;
235 int found;
236 unsigned int freeSize;
237 unsigned int newFlags;
238
239 if ((flags & 0x20) != 0)
240 return AllocateNearHeapBlockFromEnd(size, flags);
241 if (size <= 0)
242 return 0;
243 newFlags = 0x80000000;
244 if ((flags & 3) == 1) {
245 newFlags |= 0x10000000;
246 size++;
247 } else if ((flags & 3) == 2) {
248 newFlags |= 0x20000000;
249 size += 0xf;
250 }
251 if ((flags & 0x10) != 0)
252 newFlags |= 0x40000000;
253
254 found = 0;
255 descriptorAddress = g_nNearHeapFirstDescriptor;
256 while (descriptorAddress <
258 entry = DosNearPtrToFar(descriptorAddress);
259 freeSize = entry->sizeAndFlags & 0xfffff;
260 if ((entry->sizeAndFlags & 0x80000000) == 0 &&
261 size <= (int)freeSize) {
262 if (size < (int)freeSize) {
266 lastBlock = DosNearPtrToFar(
268 g_nNearArenaSize - 8);
269 if ((lastBlock->sizeAndFlags & 0x80000000) == 0 &&
270 lastBlock->address +
271 (lastBlock->sizeAndFlags & 0xfffff) ==
273 (int)(lastBlock->sizeAndFlags & 0xfffff) > 8) {
274 lastBlock->sizeAndFlags -= 8;
276 }
277 }
282 moveAddress = g_nNearHeapFirstDescriptor;
283 while (moveAddress < descriptorAddress) {
284 lastBlock = DosNearPtrToFar(moveAddress);
285 lastBlock->address = lastBlock[1].address;
286 lastBlock->sizeAndFlags = lastBlock[1].sizeAndFlags;
287 moveAddress += 8;
288 }
289 descriptorAddress -= 8;
290 entry = DosNearPtrToFar(descriptorAddress);
291 entry->sizeAndFlags = size + newFlags;
292 entry[1].address += size;
293 entry[1].sizeAndFlags -= size;
294 found = entry->address;
295 break;
296 }
297 } else {
298 entry->sizeAndFlags |= newFlags;
299 found = entry->address;
300 break;
301 }
302 }
303 descriptorAddress += 8;
304 }
305
306 if (found != 0) {
307 if ((flags & 3) == 1)
308 found = (found + 1) & 0xfffffffe;
309 else if ((flags & 3) == 2)
310 found = (found + 0xf) & 0xfffffff0;
311 }
312 return DosNearPtrToFar(found);
313}
314
315/* Function start: 0x4210B8 */
316/* Nothing in the shipped executable calls this. Releases the near-heap
317 * block whose extent contains pointer, searching the descriptors from the
318 * top of the heap down. */
319void FreeNearHeapBlock(void *pointer)
320{
321 int address;
322 NearHeapBlock *descriptor;
323 int descriptorAddress;
324
325 address = DosFarPtrToNear(pointer);
326 descriptorAddress =
328 while (descriptorAddress >= g_nNearHeapFirstDescriptor) {
329 descriptor = DosNearPtrToFar(descriptorAddress);
330 if (descriptor->address <= address &&
331 (int)(descriptor->sizeAndFlags & 0xfffff) +
332 descriptor->address > address) {
333 ReleaseNearHeapBlock(descriptorAddress);
334 break;
335 }
336 descriptorAddress -= 8;
337 }
338}
339
340/* Function start: 0x421144 */
341int GetNearHeapBlockSize(void *pointer)
342{
343 int descriptorAddress;
344 int address;
345 int size;
346 NearHeapBlock *descriptor;
347
348 size = 0;
349 address = DosFarPtrToNear(pointer);
350 descriptorAddress =
352 while (g_nNearHeapFirstDescriptor <= descriptorAddress) {
353 descriptor = DosNearPtrToFar(descriptorAddress);
354 if (descriptor->address <= address &&
355 descriptor->address +
356 (int)(descriptor->sizeAndFlags & 0xfffff) >
357 address) {
358 size = descriptor->sizeAndFlags & 0xfffff;
359 /* Each tag flag reserves bytes the caller cannot use. */
360 if ((descriptor->sizeAndFlags & 0x10000000) != 0)
361 size--;
362 else if ((descriptor->sizeAndFlags & 0x20000000) != 0)
363 size -= 15;
364 break;
365 }
366 descriptorAddress -= 8;
367 }
368 return size;
369}
370
371/* Linker commons defined here. LINK lays a unit's commons out by the
372 * identifiers' hash keys, so these spellings follow the original addresses. */
373volatile int g_nNearArenaSize; /* 0x005d3050 */
374volatile int g_1_nNearHeapBase; /* 0x005d3054 */
375int g_nNearHeapFirstDescriptor; /* 0x005d3058 */
376void * volatile g_1_pNearHeapAllocationPtr; /* 0x005d305c */
unsigned int DosFarPtrToNear(void *v)
Definition eventmgr.c:441
void ShutdownNearHeap(void)
Definition nearheap.c:127
void DosMemmove(void *dst, const void *src, unsigned short n)
unsigned short InitializeNearHeap(void)
Definition nearheap.c:86
void * AllocateNearHeapBlockFromEnd(int size, short flags)
Definition nearheap.c:144
void PurgeNearHeapBlocks(short flags)
Definition nearheap.c:57
int ReleaseNearHeapBlock(int descriptorAddress)
Definition nearheap.c:39
void * DosNearPtrToFar(unsigned int v)
Definition eventmgr.c:447
int GetNearHeapBlockSize(void *pointer)
Definition nearheap.c:341
void * AllocateTaggedMemory(unsigned int size, short flags)
Definition memapi.c:92
short MergeAdjacentNearHeapBlocks(int descriptorAddress)
Definition nearheap.c:15
void FreeNearHeapBlock(void *pointer)
Definition nearheap.c:319
void FreeIfNotNull(void *p)
Definition eventmgr.c:1955
void * AllocateNearHeapBlockByFlags(int size, short flags)
Definition nearheap.c:229
short GetNavRangeSentinel(void)
Definition eventmgr.c:1908
Shared Win32 declarations, types and library interfaces.
volatile int g_nNearHeapRelocationBytes
Definition nearheap.c:11
void *volatile g_1_pNearHeapAllocationPtr
Definition nearheap.c:376
int g_nNearHeapFirstDescriptor
Definition nearheap.c:375
volatile int g_1_nNearHeapBase
Definition nearheap.c:374
volatile short g_nNearHeapActive
Definition nearheap.c:9
volatile int g_nNearArenaSize
Definition nearheap.c:373
volatile short g_nNearHeapMaxDescriptors
Definition nearheap.c:10
unsigned int sizeAndFlags
Definition game_data.h:329