Wing Commander II
Reconstructed Win32 source (1996)
Toggle main menu visibility
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
9
volatile
short
g_nNearHeapActive
= 0;
/* 0x00493044 */
10
volatile
short
g_nNearHeapMaxDescriptors
= 0x80;
/* 0x00493048 */
11
volatile
int
g_nNearHeapRelocationBytes
= 0;
/* 0x0049304c */
12
#include <float.h>
13
14
/* Function start: 0x4207B0 */
15
short
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
}
32
g_nNearHeapFirstDescriptor
+= 8;
33
return
1;
34
}
35
return
0;
36
}
37
38
/* Function start: 0x420874 */
39
int
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;
47
if
(
g_nNearArenaSize
+
g_1_nNearHeapBase
>
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 */
57
void
PurgeNearHeapBlocks
(
short
flags)
58
{
59
NearHeapBlock
*entry;
60
int
descriptorAddress;
61
62
if
(
g_nNearHeapActive
!= 0) {
63
if
((flags & 0x10) != 0) {
64
g_nNearHeapFirstDescriptor
=
65
g_nNearArenaSize
+
g_1_nNearHeapBase
- 8;
66
entry =
DosNearPtrToFar
(
g_nNearHeapFirstDescriptor
);
67
entry->
address
=
g_1_nNearHeapBase
;
68
entry->
sizeAndFlags
=
g_nNearArenaSize
-
69
g_nNearHeapMaxDescriptors
* 8;
70
}
else
{
71
descriptorAddress =
72
g_nNearArenaSize
+
g_1_nNearHeapBase
- 8;
73
while
(descriptorAddress >=
74
g_nNearHeapFirstDescriptor
) {
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 */
86
unsigned
short
InitializeNearHeap
(
void
)
87
{
88
if
(
g_nNearHeapActive
== 0) {
89
g_nNearArenaSize
= (short)
GetNavRangeSentinel
();
90
g_1_pNearHeapAllocationPtr
= 0;
91
if
(
g_nNearHeapMaxDescriptors
* 8 <
92
g_nNearArenaSize
)
93
g_1_pNearHeapAllocationPtr
=
94
AllocateTaggedMemory
(
g_nNearArenaSize
, 0);
95
if
(
g_1_pNearHeapAllocationPtr
!= 0) {
96
g_nNearHeapActive
++;
97
g_1_nNearHeapBase
=
98
DosFarPtrToNear
(
g_1_pNearHeapAllocationPtr
);
99
if
(*(
short
*)0x00400013 == 0x270) {
100
g_nNearHeapRelocationBytes
=
101
0x9c000 -
g_1_nNearHeapBase
-
102
g_nNearArenaSize
;
103
g_nNearArenaSize
=
104
0x98000 -
g_1_nNearHeapBase
-
105
g_nNearHeapRelocationBytes
;
106
if
(
g_nNearHeapMaxDescriptors
* 8 <
107
g_nNearArenaSize
) {
108
DosMemmove
(
109
DosNearPtrToFar
(
g_nNearArenaSize
+
110
g_1_nNearHeapBase
),
111
DosNearPtrToFar
(
112
0x9c000 -
g_nNearHeapRelocationBytes
),
113
g_nNearHeapRelocationBytes
);
114
}
else
{
115
FreeIfNotNull
(
g_1_pNearHeapAllocationPtr
);
116
g_nNearHeapActive
= 0;
117
}
118
}
119
if
(
g_nNearHeapActive
!= 0)
120
PurgeNearHeapBlocks
(0x10);
121
}
122
}
123
return
g_nNearHeapActive
;
124
}
125
126
/* Function start: 0x420B12 */
127
void
ShutdownNearHeap
(
void
)
128
{
129
if
(
g_nNearHeapRelocationBytes
!= 0) {
130
DosMemmove
(
131
DosNearPtrToFar
(
132
0x9c000 -
g_nNearHeapRelocationBytes
),
133
DosNearPtrToFar
(
134
g_nNearArenaSize
+
135
g_1_nNearHeapBase
),
136
g_nNearHeapRelocationBytes
);
137
}
138
if
(
g_nNearHeapActive
!= 0)
139
FreeIfNotNull
(
g_1_pNearHeapAllocationPtr
);
140
g_nNearHeapActive
= 0;
141
}
142
143
/* Function start: 0x420B88 */
144
void
*
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 =
169
g_1_nNearHeapBase
+
g_nNearArenaSize
- 8;
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) {
175
if
(
g_1_nNearHeapBase
+
g_nNearArenaSize
-
176
g_nNearHeapMaxDescriptors
* 8 >=
177
g_nNearHeapFirstDescriptor
) {
178
lastBlock =
DosNearPtrToFar
(
179
g_1_nNearHeapBase
+
180
g_nNearArenaSize
- 8);
181
if
((lastBlock->
sizeAndFlags
& 0x80000000) == 0 &&
182
lastBlock->
address
+
183
(lastBlock->
sizeAndFlags
& 0xfffff) ==
184
g_nNearHeapFirstDescriptor
&&
185
(
int
)(lastBlock->
sizeAndFlags
& 0xfffff) > 8) {
186
lastBlock->
sizeAndFlags
-= 8;
187
g_nNearHeapMaxDescriptors
++;
188
}
189
}
190
if
(
g_1_nNearHeapBase
+
g_nNearArenaSize
-
191
g_nNearHeapMaxDescriptors
* 8 <
192
g_nNearHeapFirstDescriptor
) {
193
g_nNearHeapFirstDescriptor
-= 8;
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 */
229
void
*
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 <
257
g_1_nNearHeapBase
+
g_nNearArenaSize
) {
258
entry =
DosNearPtrToFar
(descriptorAddress);
259
freeSize = entry->
sizeAndFlags
& 0xfffff;
260
if
((entry->
sizeAndFlags
& 0x80000000) == 0 &&
261
size <= (
int
)freeSize) {
262
if
(size < (
int
)freeSize) {
263
if
(
g_1_nNearHeapBase
+
g_nNearArenaSize
-
264
g_nNearHeapMaxDescriptors
* 8 >=
265
g_nNearHeapFirstDescriptor
) {
266
lastBlock =
DosNearPtrToFar
(
267
g_1_nNearHeapBase
+
268
g_nNearArenaSize
- 8);
269
if
((lastBlock->
sizeAndFlags
& 0x80000000) == 0 &&
270
lastBlock->
address
+
271
(lastBlock->
sizeAndFlags
& 0xfffff) ==
272
g_nNearHeapFirstDescriptor
&&
273
(
int
)(lastBlock->
sizeAndFlags
& 0xfffff) > 8) {
274
lastBlock->
sizeAndFlags
-= 8;
275
g_nNearHeapMaxDescriptors
++;
276
}
277
}
278
if
(
g_1_nNearHeapBase
+
g_nNearArenaSize
-
279
g_nNearHeapMaxDescriptors
* 8 <
280
g_nNearHeapFirstDescriptor
) {
281
g_nNearHeapFirstDescriptor
-= 8;
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. */
319
void
FreeNearHeapBlock
(
void
*pointer)
320
{
321
int
address;
322
NearHeapBlock
*descriptor;
323
int
descriptorAddress;
324
325
address =
DosFarPtrToNear
(pointer);
326
descriptorAddress =
327
g_nNearArenaSize
+
g_1_nNearHeapBase
- 8;
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 */
341
int
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 =
351
g_nNearArenaSize
+
g_1_nNearHeapBase
- 8;
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. */
373
volatile
int
g_nNearArenaSize
;
/* 0x005d3050 */
374
volatile
int
g_1_nNearHeapBase
;
/* 0x005d3054 */
375
int
g_nNearHeapFirstDescriptor
;
/* 0x005d3058 */
376
void
*
volatile
g_1_pNearHeapAllocationPtr
;
/* 0x005d305c */
DosFarPtrToNear
unsigned int DosFarPtrToNear(void *v)
Definition
eventmgr.c:441
ShutdownNearHeap
void ShutdownNearHeap(void)
Definition
nearheap.c:127
DosMemmove
void DosMemmove(void *dst, const void *src, unsigned short n)
InitializeNearHeap
unsigned short InitializeNearHeap(void)
Definition
nearheap.c:86
AllocateNearHeapBlockFromEnd
void * AllocateNearHeapBlockFromEnd(int size, short flags)
Definition
nearheap.c:144
PurgeNearHeapBlocks
void PurgeNearHeapBlocks(short flags)
Definition
nearheap.c:57
ReleaseNearHeapBlock
int ReleaseNearHeapBlock(int descriptorAddress)
Definition
nearheap.c:39
DosNearPtrToFar
void * DosNearPtrToFar(unsigned int v)
Definition
eventmgr.c:447
GetNearHeapBlockSize
int GetNearHeapBlockSize(void *pointer)
Definition
nearheap.c:341
AllocateTaggedMemory
void * AllocateTaggedMemory(unsigned int size, short flags)
Definition
memapi.c:92
MergeAdjacentNearHeapBlocks
short MergeAdjacentNearHeapBlocks(int descriptorAddress)
Definition
nearheap.c:15
FreeNearHeapBlock
void FreeNearHeapBlock(void *pointer)
Definition
nearheap.c:319
FreeIfNotNull
void FreeIfNotNull(void *p)
Definition
eventmgr.c:1955
AllocateNearHeapBlockByFlags
void * AllocateNearHeapBlockByFlags(int size, short flags)
Definition
nearheap.c:229
GetNavRangeSentinel
short GetNavRangeSentinel(void)
Definition
eventmgr.c:1908
game.h
Shared Win32 declarations, types and library interfaces.
g_nNearHeapRelocationBytes
volatile int g_nNearHeapRelocationBytes
Definition
nearheap.c:11
g_1_pNearHeapAllocationPtr
void *volatile g_1_pNearHeapAllocationPtr
Definition
nearheap.c:376
g_nNearHeapFirstDescriptor
int g_nNearHeapFirstDescriptor
Definition
nearheap.c:375
g_1_nNearHeapBase
volatile int g_1_nNearHeapBase
Definition
nearheap.c:374
g_nNearHeapActive
volatile short g_nNearHeapActive
Definition
nearheap.c:9
g_nNearArenaSize
volatile int g_nNearArenaSize
Definition
nearheap.c:373
g_nNearHeapMaxDescriptors
volatile short g_nNearHeapMaxDescriptors
Definition
nearheap.c:10
NearHeapBlock
Definition
game_data.h:327
NearHeapBlock::sizeAndFlags
unsigned int sizeAndFlags
Definition
game_data.h:329
NearHeapBlock::address
int address
Definition
game_data.h:328
src
nearheap.c
Generated by
1.18.0