Wing Commander
Reconstructed Win32 source (1996)
Loading...
Searching...
No Matches
nearheap.c
Go to the documentation of this file.
1/**
2 * @file
3 * @ingroup data
4 * @brief Near-heap descriptor allocation and compaction carried over from DOS.
5 *
6 * Address range 40e890-40efdf.
7 */
8#include <process.h>
9#include "wc1.h"
10
11/* Linker commons defined here; LINK orders them by identifier hash. */
12int nNearHeapSize; /* 0x005a811c */
13int nNearHeapBase; /* 0x005a8120 */
15void *pCurrentNearHeapAlloc; /* 0x005a8128 */
16short nNavMapMaximumPositionX; /* 0x005a812c */
17short nNavigationMapMinimumCoordX; /* 0x005a812e */
18unsigned short awMapNavObjectiveLabelIndex[16]; /* 0x005a8130 */
19short nNavMapMaximumPosY; /* 0x005a8150 */
20short nNavMapCentreX; /* 0x005a8152 */
21short nNavigationMapMinimumPositionY; /* 0x005a8154 */
23
24/* Function start: 0x40E890 */
25unsigned short MergeAdjacentNearHeapBlocks(int descriptorAddress)
26{
27 NearHeapBlock *block;
28
29 block = DosNearPtrToFar(descriptorAddress);
30 if ((block->sizeAndFlags & 0x80000000) == 0 &&
31 (block[1].sizeAndFlags & 0x80000000) == 0 &&
32 block->address + (block->sizeAndFlags & 0xfffff) ==
33 block[1].address) {
34 block[1].address = block->address;
35 block[1].sizeAndFlags += block->sizeAndFlags & 0xfffff;
36 while (descriptorAddress > nCurrentNearHeapFirstDescriptor) {
37 descriptorAddress -= 8;
38 block = DosNearPtrToFar(descriptorAddress);
39 block[1].address = block->address;
40 block[1].sizeAndFlags = block->sizeAndFlags;
41 }
43 return 1;
44 }
45 return 0;
46}
47
48/* Function start: 0x40E900 */
49int ReleaseNearHeapBlock(int descriptorAddress)
50{
51 NearHeapBlock *block;
52
53 block = DosNearPtrToFar(descriptorAddress);
54 block->sizeAndFlags &= 0x7fffffff;
55 if (descriptorAddress + 8 <
57 MergeAdjacentNearHeapBlocks(descriptorAddress) != 0)
58 descriptorAddress += 8;
59 if (descriptorAddress > nCurrentNearHeapFirstDescriptor)
60 MergeAdjacentNearHeapBlocks(descriptorAddress - 8);
61 return descriptorAddress;
62}
63
64static short nNearHeapActive = 0; /* 0x004688c0 */
65short nNearHeapMaxDescriptors = 0x80; /* 0x004688c4 */
66static unsigned int nNearHeapRelocationBytes = 0; /* 0x004688c8 */
67
68/* Function start: 0x40E950 */
69void PurgeNearHeapBlocks(unsigned short flags)
70{
71 NearHeapBlock *block;
72 int descriptorAddress;
73
74 if (nNearHeapActive != 0) {
75 if ((flags & 0x10) != 0) {
78 block->address = nNearHeapBase;
79 block->sizeAndFlags =
81 return;
82 }
83 descriptorAddress = nNearHeapBase +
84 nNearHeapSize - 8;
85 for (; descriptorAddress >= nCurrentNearHeapFirstDescriptor;
86 descriptorAddress -= 8) {
87 block = DosNearPtrToFar(descriptorAddress);
88 if ((block->sizeAndFlags & 0x40000000) == 0)
89 descriptorAddress = ReleaseNearHeapBlock(descriptorAddress);
90 }
91 }
92}
93
94/* Function start: 0x40E9E0 */
95unsigned short InitializeNearHeap(void)
96{
97 if (nNearHeapActive == 0) {
103 if (pCurrentNearHeapAlloc != 0) {
107 if (*(unsigned short *)0x00400013 == 0x270) {
109 0x9c000 - nNearHeapSize - nNearHeapBase;
114 DosMemcpy(
119 0x9c000 -
122 } else {
124 nNearHeapActive = 0;
125 }
126 }
127 if (nNearHeapActive != 0)
129 }
130 }
131 return nNearHeapActive;
132}
133
134/* Function start: 0x40EB10 */
135/* Nothing in the shipped executable calls this. It undoes
136 InitializeNearHeap: copies the relocated bytes back below 0x9C000 and
137 frees the heap's allocation. */
139{
140 int relocationBytes;
141
142 relocationBytes = nNearHeapRelocationBytes;
143 if (relocationBytes != 0)
144 DosMemcpy(DosNearPtrToFar(0x9c000 - relocationBytes),
146 relocationBytes);
147 if (nNearHeapActive != 0)
149 nNearHeapActive = 0;
150}
151
152/* Function start: 0x40EB70 */
153void *AllocateNearHeapBlockFromEnd(int size, unsigned short flags)
154{
155 int descriptorAddress;
156 int shiftAddress;
157 int blockSize;
158 NearHeapBlock *block;
159 NearHeapBlock *lastBlock;
160 int allocationAddress;
161 unsigned int allocationFlags;
162 unsigned short alignment;
163
164 if (size <= 0)
165 return 0;
166 allocationFlags = 0x80000000;
167 alignment = flags & 3;
168 if (alignment == 1) {
169 allocationFlags = 0x90000000;
170 size++;
171 } else if (alignment == 2) {
172 allocationFlags = 0xa0000000;
173 size += 0xf;
174 }
175 if ((flags & 0x10) != 0)
176 allocationFlags |= 0x40000000;
177
178 allocationAddress = 0;
179 descriptorAddress =
181 for (; descriptorAddress >= nCurrentNearHeapFirstDescriptor;
182 descriptorAddress -= 8) {
183 block = DosNearPtrToFar(descriptorAddress);
184 blockSize = block->sizeAndFlags & 0xfffff;
185 if ((block->sizeAndFlags & 0x80000000) != 0)
186 continue;
187 if (blockSize < size)
188 continue;
189 if (blockSize > size) {
190 if (nNearHeapBase -
194 lastBlock = DosNearPtrToFar(
196 nNearHeapSize - 8);
197 if ((lastBlock->sizeAndFlags & 0x80000000) == 0) {
198 blockSize = lastBlock->sizeAndFlags & 0xfffff;
199 if (lastBlock->address + blockSize ==
201 blockSize > 8) {
202 lastBlock->sizeAndFlags -= 8;
204 }
205 }
206 }
207
208 if (nNearHeapBase -
212 continue;
213
215 shiftAddress = nCurrentNearHeapFirstDescriptor;
216 for (; descriptorAddress > shiftAddress; shiftAddress += 8) {
217 block = DosNearPtrToFar(shiftAddress);
218 block->address = block[1].address;
219 block->sizeAndFlags = block[1].sizeAndFlags;
220 }
221 descriptorAddress -= 8;
222 block = DosNearPtrToFar(descriptorAddress);
223 blockSize = block->sizeAndFlags - size;
224 block->sizeAndFlags = blockSize;
225 block[1].address += blockSize & 0xffffff;
226 blockSize = allocationFlags + size;
227 block[1].sizeAndFlags = blockSize;
228 allocationAddress = block[1].address;
229 break;
230 }
231 block->sizeAndFlags |= allocationFlags;
232 allocationAddress = block->address;
233 break;
234 }
235
236 if (allocationAddress != 0) {
237 if (alignment == 1)
238 allocationAddress = (allocationAddress + 1) & 0xfffffffe;
239 else if (alignment == 2)
240 allocationAddress = (allocationAddress + 0xf) & 0xfffffff0;
241 }
242 return DosNearPtrToFar(allocationAddress);
243}
244
245/* Function start: 0x40ED30 */
246void *AllocateNearHeapBlockByFlags(int size, unsigned short flags)
247{
248 int blockSize;
249 int descriptorAddress;
250 int shiftAddress;
251 NearHeapBlock *block;
252 int allocationAddress;
253 unsigned int sizeAndFlags;
254 unsigned int allocationFlags;
255 unsigned short alignment;
256
257 if ((flags & 0x20) != 0)
258 return AllocateNearHeapBlockFromEnd(size, flags);
259 if (size <= 0)
260 return 0;
261 allocationFlags = 0x80000000;
262 alignment = flags & 3;
263 if (alignment == 1) {
264 allocationFlags = 0x90000000;
265 size++;
266 } else if (alignment == 2) {
267 allocationFlags = 0xa0000000;
268 size += 0xf;
269 }
270 if ((flags & 0x10) != 0)
271 allocationFlags |= 0x40000000;
272
273 allocationAddress = 0;
274 descriptorAddress = nCurrentNearHeapFirstDescriptor;
275 for (; descriptorAddress <
277 descriptorAddress += 8) {
278 block = DosNearPtrToFar(descriptorAddress);
279 sizeAndFlags = block->sizeAndFlags;
280 blockSize = sizeAndFlags & 0xfffff;
281 if ((sizeAndFlags & 0x80000000) != 0)
282 continue;
283 if (blockSize < size)
284 continue;
285 if (blockSize > size) {
286 if (nNearHeapBase -
290 block = DosNearPtrToFar(
292 nNearHeapSize - 8);
293 if ((block->sizeAndFlags & 0x80000000) == 0) {
294 blockSize = block->sizeAndFlags & 0xfffff;
295 if (block->address + blockSize ==
297 blockSize > 8) {
298 block->sizeAndFlags -= 8;
300 }
301 }
302 }
303
304 if (nNearHeapBase -
308 continue;
309
311 shiftAddress = nCurrentNearHeapFirstDescriptor;
312 for (; descriptorAddress > shiftAddress; shiftAddress += 8) {
313 block = DosNearPtrToFar(shiftAddress);
314 block->address = block[1].address;
315 block->sizeAndFlags = block[1].sizeAndFlags;
316 }
317 descriptorAddress -= 8;
318 block = DosNearPtrToFar(descriptorAddress);
319 block->sizeAndFlags = allocationFlags + size;
320 block[1].address += size;
321 block[1].sizeAndFlags -= size;
322 allocationAddress = block->address;
323 break;
324 }
325 block->sizeAndFlags |= allocationFlags;
326 allocationAddress = block->address;
327 break;
328 }
329
330 if (allocationAddress != 0) {
331 if (alignment == 1)
332 allocationAddress = (allocationAddress + 1) & 0xfffffffe;
333 else if (alignment == 2)
334 allocationAddress = (allocationAddress + 0xf) & 0xfffffff0;
335 }
336 return DosNearPtrToFar(allocationAddress);
337}
338
339/* Function start: 0x40EF00 */
340/* Nothing in the shipped executable calls this. Releases the near heap
341 block that contains the given pointer. */
342void FreeNearHeapBlock(void *pointer)
343{
344 int descriptorAddress;
345 NearHeapBlock *block;
346 int address;
347 int blockAddress;
348
349 address = DosFarPtrToNear(pointer);
350 descriptorAddress =
352 for (; descriptorAddress >= nCurrentNearHeapFirstDescriptor;
353 descriptorAddress -= 8) {
354 block = DosNearPtrToFar(descriptorAddress);
355 blockAddress = block->address;
356 if (blockAddress <= address &&
357 blockAddress + (block->sizeAndFlags & 0xfffff) >
358 address) {
359 ReleaseNearHeapBlock(descriptorAddress);
360 break;
361 }
362 }
363}
364
365/* Function start: 0x40EF60 */
366/* Nothing in the shipped executable calls this. Returns the usable size of
367 the near heap block that contains the given pointer, or 0. */
368int GetNearHeapBlockSize(void *pointer)
369{
370 NearHeapBlock *block;
371 int descriptorAddress;
372 int size;
373 int address;
374
375 size = 0;
376 address = DosFarPtrToNear(pointer);
377 descriptorAddress =
379 for (; descriptorAddress >= nCurrentNearHeapFirstDescriptor;
380 descriptorAddress -= 8) {
381 block = DosNearPtrToFar(descriptorAddress);
382 if (address >= block->address &&
383 block->address + (block->sizeAndFlags & 0xfffff) >
384 address) {
385 size = block->sizeAndFlags & 0xfffff;
386 if ((block->sizeAndFlags & 0x10000000) != 0)
387 size--;
388 else if ((block->sizeAndFlags & 0x20000000) != 0)
389 size -= 0xf;
390 break;
391 }
392 }
393 return size;
394}
TextContext stCurrentNavMapTxtCtx
Definition nearheap.c:22
short nNavMapMaximumPosY
Definition nearheap.c:19
unsigned short awMapNavObjectiveLabelIndex[16]
Definition nearheap.c:18
int nCurrentNearHeapFirstDescriptor
Definition nearheap.c:14
int nNearHeapBase
Definition nearheap.c:13
short nNavMapMaximumPositionX
Definition nearheap.c:16
int nNearHeapSize
Definition nearheap.c:12
void * pCurrentNearHeapAlloc
Definition nearheap.c:15
short nNavigationMapMinimumCoordX
Definition nearheap.c:17
short nNearHeapMaxDescriptors
Definition nearheap.c:65
short nNavMapCentreX
Definition nearheap.c:20
short nNavigationMapMinimumPositionY
Definition nearheap.c:21
void ShutdownNearHeap(void)
Definition nearheap.c:138
static short nNearHeapActive
Definition nearheap.c:64
int GetNearHeapBlockSize(void *pointer)
Definition nearheap.c:368
static unsigned int nNearHeapRelocationBytes
Definition nearheap.c:66
void FreeNearHeapBlock(void *pointer)
Definition nearheap.c:342
int sizeAndFlags
Definition wcdata.h:332
Umbrella header for the game core.
void * AllocateTaggedMemory(int size, unsigned short flags)
Definition ending.c:31
void *__stdcall DosNearPtrToFar(unsigned int v)
Definition strdos.c:31
unsigned short MergeAdjacentNearHeapBlocks(int descriptorAddress)
Definition nearheap.c:25
unsigned short InitializeNearHeap(void)
Definition nearheap.c:95
unsigned int __stdcall DosFarPtrToNear(void *v)
Definition strdos.c:25
void PurgeNearHeapBlocks(unsigned short flags)
Definition nearheap.c:69
void __stdcall DosMemcpy(void *dst, const void *src, unsigned short n)
int ReleaseNearHeapBlock(int descriptorAddress)
Definition nearheap.c:49
void * AllocateNearHeapBlockByFlags(int size, unsigned short flags)
Definition nearheap.c:246
unsigned short GetNavRangeSentinel(void)
Definition eventmgr.c:1102
void * AllocateNearHeapBlockFromEnd(int size, unsigned short flags)
Definition nearheap.c:153
void FreeIfNotNull(void *p)
Definition eventmgr.c:1147