1
2 #include "3dc.h"
3 #include "module.h"
4
5 #include "stratdef.h"
6 #include "sfx.h"
7
8 #define UseLocalAssert Yes
9 #include "ourasert.h"
10
11
12 /* globals for export */
13
14 int NumActiveBlocks;
15 DISPLAYBLOCK *ActiveBlockList[maxobjects];
16
17
18
19
20 /*
21 Object Block Lists et al
22 */
23
24 static int NumFreeBlocks;
25 static DISPLAYBLOCK *FreeBlockList[maxobjects];
26 static DISPLAYBLOCK **FreeBlockListPtr = &FreeBlockList[maxobjects-1];
27 static DISPLAYBLOCK FreeBlockData[maxobjects];
28 static DISPLAYBLOCK **ActiveBlockListPtr = &ActiveBlockList[0];
29
30
31 /*
32 Texture Animation Block Extensions
33 */
34
35 static int NumFreeTxAnimBlocks;
36 static TXACTRLBLK *FreeTxAnimBlockList[maxTxAnimblocks];
37 static TXACTRLBLK **FreeTxAnimBlockListPtr = &FreeTxAnimBlockList[maxTxAnimblocks-1];
38 static TXACTRLBLK FreeTxAnimBlockData[maxTxAnimblocks];
39
40
41
42 /*
43 Light Block Extensions
44 */
45
46 static int NumFreeLightBlocks;
47 static LIGHTBLOCK *FreeLightBlockList[maxlightblocks];
48 static LIGHTBLOCK **FreeLightBlockListPtr = &FreeLightBlockList[maxlightblocks-1];
49 static LIGHTBLOCK FreeLightBlockData[maxlightblocks];
50
51
52
53 /*
54
55 To create the free block list, pointers to "FreeBlockData[]" must be copied
56 to "FreeBlockList[]".
57
58 Also:
59
60 "NumFreeBlocks" must be updated as "FreeBlockList[]" is created.
61 "NumActiveBlocks" must be initialised to zero.
62
63 */
InitialiseObjectBlocks(void)64 void InitialiseObjectBlocks(void)
65 {
66
67 DISPLAYBLOCK *FreeBlkPtr = &FreeBlockData[0];
68
69 NumActiveBlocks = 0;
70
71 FreeBlockListPtr = &FreeBlockList[maxobjects-1];
72 ActiveBlockListPtr = &ActiveBlockList[0];
73
74 for(NumFreeBlocks = 0; NumFreeBlocks<maxobjects; NumFreeBlocks++) {
75
76 FreeBlockList[NumFreeBlocks] = FreeBlkPtr;
77
78 FreeBlkPtr++;
79
80 }
81 }
82
83
84 /*
85
86 "AllocateObjectBlock()" is identical to the routine "GetBlock"
87
88 */
89
AllocateObjectBlock(void)90 DISPLAYBLOCK* AllocateObjectBlock(void)
91 {
92
93 DISPLAYBLOCK *FreeBlkPtr = 0; /* Default to null ptr */
94 int *sptr;
95 int i;
96
97
98 if(NumFreeBlocks) {
99
100 FreeBlkPtr = *FreeBlockListPtr--;
101
102 NumFreeBlocks--; /* One less free block */
103
104 /* Clear the block */
105
106 sptr = (int *)FreeBlkPtr;
107 for(i = sizeof(DISPLAYBLOCK)/4; i!=0; i--)
108 *sptr++ = 0;
109 }
110
111 return(FreeBlkPtr);
112 }
113
114
115 /*
116
117 "DeallocateObjectBlock()" is identical to the routine "ReturnBlock"
118
119 */
120
DeallocateObjectBlock(DISPLAYBLOCK * dblockptr)121 void DeallocateObjectBlock(DISPLAYBLOCK *dblockptr)
122 {
123 /* Deallocate the Display Block */
124
125 FreeBlockListPtr++;
126 *FreeBlockListPtr = dblockptr;
127
128 NumFreeBlocks++; /* One more free block */
129 }
130
131
132 /*
133 "CreateActiveObject()" calls "AllocateObjectBlock()". An active object is
134 passed into the view and strategy routines unless flagged otherwise
135
136 WARNING!
137
138 An active object must ALWAYS be deallocated by "DestroyActiveObject()".
139 */
140
CreateActiveObject(void)141 DISPLAYBLOCK* CreateActiveObject(void)
142 {
143
144 DISPLAYBLOCK *dblockptr;
145
146
147 dblockptr = AllocateObjectBlock();
148
149 if(dblockptr) {
150
151 *ActiveBlockListPtr++ = dblockptr;
152
153 NumActiveBlocks++;
154
155
156 }
157
158 return dblockptr;
159 }
160
161
162 /*
163
164 DestroyActiveObject()
165
166 Remove the block from "ActiveBlockList".
167 Use the array model because it's clearer.
168
169 This function returns 0 if successful, -1 if not
170
171 */
172
173
DestroyActiveObject(DISPLAYBLOCK * dblockptr)174 int DestroyActiveObject(DISPLAYBLOCK *dblockptr)
175 {
176 int i, light;
177 TXACTRLBLK *taptr;
178
179 /* If the block ptr is OK, search the Active Blocks List */
180 if(dblockptr) {
181
182 for(i = 0; i < NumActiveBlocks; i++) {
183
184 if(ActiveBlockList[i] == dblockptr) {
185
186 ActiveBlockList[i] = ActiveBlockList[NumActiveBlocks-1];
187 NumActiveBlocks--;
188 ActiveBlockListPtr--;
189
190 DestroyActiveVDB(dblockptr->ObVDBPtr); /* Checks for null */
191
192 if(dblockptr->ObNumLights) {
193 for(light = dblockptr->ObNumLights - 1; light != -1; light--)
194 DeleteLightBlock(dblockptr->ObLights[light], dblockptr);
195 }
196
197 /* If no SB, deallocate any Texture Animation Blocks */
198
199 if(dblockptr->ObStrategyBlock == 0) {
200
201 if(dblockptr->ObTxAnimCtrlBlks) {
202
203 taptr = dblockptr->ObTxAnimCtrlBlks;
204
205 while(taptr) {
206
207 DeallocateTxAnimBlock(taptr);
208
209 taptr = taptr->tac_next;
210
211 }
212
213 }
214
215 }
216
217
218 /* Deallocate the Lazy Morphed Points Array Pointer */
219
220 #if (SupportMorphing && LazyEvaluationForMorphing)
221 if(dblockptr->ObMorphedPts) {
222 DeallocateMem(dblockptr->ObMorphedPts);
223 dblockptr->ObMorphedPts = 0;
224 }
225 #endif
226
227 /* KJL 16:52:43 06/01/98 - dealloc sfx block if one exists */
228 if(dblockptr->SfxPtr)
229 {
230 DeallocateSfxBlock(dblockptr->SfxPtr);
231 }
232
233 DeallocateObjectBlock(dblockptr); /* Back to Free List */
234
235 /* If this is the current landscape, clear the pointer */
236
237 return 0;
238 }
239 }
240 }
241
242 return -1;
243 }
244
245
246
247
248 /*
249
250 Support Functions for Texture Animation Blocks
251
252 */
253
InitialiseTxAnimBlocks(void)254 void InitialiseTxAnimBlocks(void)
255
256 {
257
258 TXACTRLBLK *FreeBlkPtr = &FreeTxAnimBlockData[0];
259
260
261 FreeTxAnimBlockListPtr = &FreeTxAnimBlockList[maxTxAnimblocks-1];
262
263 for(NumFreeTxAnimBlocks=0; NumFreeTxAnimBlocks < maxTxAnimblocks; NumFreeTxAnimBlocks++) {
264
265 FreeTxAnimBlockList[NumFreeTxAnimBlocks] = FreeBlkPtr;
266
267 FreeBlkPtr++;
268
269 }
270
271 }
272
273
274 /*
275
276 Allocate a Texture Animation Block
277
278 */
279
AllocateTxAnimBlock(void)280 TXACTRLBLK* AllocateTxAnimBlock(void)
281
282 {
283
284 TXACTRLBLK *FreeBlkPtr = 0; /* Default to null ptr */
285 int *sptr;
286 int i;
287
288
289 if(NumFreeTxAnimBlocks) {
290
291 FreeBlkPtr = *FreeTxAnimBlockListPtr--;
292
293 NumFreeTxAnimBlocks--; /* One less free block */
294
295 /* Clear the block */
296
297 sptr = (int *)FreeBlkPtr;
298 for(i = sizeof(TXACTRLBLK)/4; i!=0; i--)
299 *sptr++ = 0;
300
301 }
302
303 return FreeBlkPtr;
304
305 }
306
307
308 /*
309
310 Deallocate a Texture Animation Block
311
312 */
313
DeallocateTxAnimBlock(TXACTRLBLK * TxAnimblockptr)314 void DeallocateTxAnimBlock(TXACTRLBLK *TxAnimblockptr)
315
316 {
317
318 FreeTxAnimBlockListPtr++;
319
320 *FreeTxAnimBlockListPtr = TxAnimblockptr;
321
322 NumFreeTxAnimBlocks++; /* One more free block */
323
324 }
325
326
327 /*
328
329 Add a Texture Animation Block to a Display Block
330
331 */
332
AddTxAnimBlock(DISPLAYBLOCK * dptr,TXACTRLBLK * taptr)333 void AddTxAnimBlock(DISPLAYBLOCK *dptr, TXACTRLBLK *taptr)
334
335 {
336
337 TXACTRLBLK *taptr_tmp;
338
339
340 if(dptr->ObTxAnimCtrlBlks) {
341
342 taptr_tmp = dptr->ObTxAnimCtrlBlks;
343
344 while(taptr_tmp->tac_next)
345 taptr_tmp = taptr_tmp->tac_next;
346
347 taptr_tmp->tac_next = taptr;
348
349 }
350
351 else dptr->ObTxAnimCtrlBlks = taptr;
352
353 }
354
355
356
357
358
359 /*
360
361 Support functions for Light Blocks
362
363 */
364
InitialiseLightBlocks(void)365 void InitialiseLightBlocks(void)
366
367 {
368
369 LIGHTBLOCK *FreeBlkPtr = &FreeLightBlockData[0];
370
371
372 FreeLightBlockListPtr = &FreeLightBlockList[maxlightblocks-1];
373
374 for(NumFreeLightBlocks=0; NumFreeLightBlocks < maxlightblocks; NumFreeLightBlocks++) {
375
376 FreeLightBlockList[NumFreeLightBlocks] = FreeBlkPtr;
377
378 FreeBlkPtr++;
379
380 }
381
382 }
383
384
AllocateLightBlock(void)385 LIGHTBLOCK* AllocateLightBlock(void)
386
387 {
388
389 LIGHTBLOCK *FreeBlkPtr = 0; /* Default to null ptr */
390 int *lptr;
391 int i;
392
393
394 if(NumFreeLightBlocks) {
395
396 FreeBlkPtr = *FreeLightBlockListPtr--;
397
398 NumFreeLightBlocks--; /* One less free block */
399
400 /* Clear the block */
401
402 lptr = (int *)FreeBlkPtr;
403 for(i = sizeof(LIGHTBLOCK)/4; i!=0; i--)
404 *lptr++ = 0;
405
406 }
407
408 return(FreeBlkPtr);
409
410 }
411
412
DeallocateLightBlock(LIGHTBLOCK * lptr)413 void DeallocateLightBlock(LIGHTBLOCK *lptr)
414
415 {
416
417 /* Not all lights come from the free light list */
418
419 if(lptr->LightFlags & LFlag_WasNotAllocated) return;
420
421
422 /* Make sure that this light IS from the free light list */
423
424 GLOBALASSERT(
425 (lptr >= FreeLightBlockData) &&
426 (lptr < &FreeLightBlockData[maxlightblocks])
427 );
428
429
430 /* Ok to return the light */
431
432 FreeLightBlockListPtr++;
433
434 *FreeLightBlockListPtr = lptr;
435
436 NumFreeLightBlocks++; /* One more free block */
437
438 }
439
440
441 /*
442
443 See if there are any free slots in the dptr light block array.
444 If there are, allocate a light block, place it in the list and return
445 the pointer to the caller.
446
447 A late addition is the passing of a light block (from somewhere, it does
448 not matter where). This light block is then added rather than one being
449 allocated from the free light block list.
450
451 */
452
AddLightBlock(DISPLAYBLOCK * dptr,LIGHTBLOCK * lptr_to_add)453 LIGHTBLOCK* AddLightBlock(DISPLAYBLOCK *dptr, LIGHTBLOCK *lptr_to_add)
454
455 {
456
457 LIGHTBLOCK **larrayptr;
458 LIGHTBLOCK **freelarrayptr;
459 LIGHTBLOCK *lptr = 0;
460 int i, lfree;
461
462
463 /* Are there any free slots? */
464
465 lfree = No;
466
467 larrayptr = &dptr->ObLights[0];
468 freelarrayptr = NULL;
469
470 for(i = MaxObjectLights; i!=0 && lfree == No; i--) {
471
472 if(*larrayptr == 0) {
473
474 freelarrayptr = larrayptr;
475 lfree = Yes;
476
477 }
478
479 larrayptr++;
480
481 }
482
483 if(lfree) {
484
485 if(lptr_to_add) {
486
487 lptr = lptr_to_add;
488
489 }
490
491 else {
492
493 lptr = AllocateLightBlock();
494
495 }
496
497 if(lptr)
498 {
499 *freelarrayptr = lptr;
500 dptr->ObNumLights++;
501 }
502
503 }
504
505 return lptr;
506
507 }
508
509
510 /*
511
512 To delete a light block, copy the end block to the new free slot and
513 reduce the count by one. Make sure the end block array entry is cleared.
514
515 */
516
DeleteLightBlock(LIGHTBLOCK * lptr,DISPLAYBLOCK * dptr)517 void DeleteLightBlock(LIGHTBLOCK *lptr, DISPLAYBLOCK *dptr)
518 {
519
520 int i, larrayi;
521
522 DeallocateLightBlock(lptr);
523
524 /* What is lptr's array index? */
525
526 larrayi = -1; /* null value */
527
528 for(i = 0; i < dptr->ObNumLights; i++)
529 if(dptr->ObLights[i] == lptr) larrayi = i;
530
531
532
533 /* Proceed only if lptr has been found in the array */
534
535 if(larrayi != -1) {
536
537 /* Copy the end block to that of lptr */
538
539 dptr->ObLights[larrayi] = dptr->ObLights[dptr->ObNumLights - 1];
540
541 /* Clear the end block array entry */
542
543 dptr->ObLights[dptr->ObNumLights - 1] = 0;
544
545 /* One less light in the dptr list */
546
547 dptr->ObNumLights--;
548
549 }
550 }
551
552
553
554
555 /*
556
557 When running the parallel strategies, display and light block deallocation
558 must only be done at the end of the frame, AFTER processor synchronisation
559 and BEFORE the shadow copy.
560
561 */
562
DisplayAndLightBlockDeallocation(void)563 int DisplayAndLightBlockDeallocation(void)
564 {
565
566 DISPLAYBLOCK **activeblocksptr;
567 DISPLAYBLOCK *dptr;
568 int i, j;
569 LIGHTBLOCK *lptr;
570
571 if(NumActiveBlocks) {
572
573 activeblocksptr = &ActiveBlockList[NumActiveBlocks - 1];
574
575 for(i = NumActiveBlocks; i!=0; i--) {
576
577 dptr = *activeblocksptr--;
578
579 /* Deallocate Object? */
580
581 if(dptr->ObFlags2 & ObFlag2_Deallocate) {
582
583 DestroyActiveObject(dptr);
584
585 }
586
587
588 /* Deallocate any Lights? */
589
590 else {
591
592 if(dptr->ObNumLights) {
593
594 for(j = dptr->ObNumLights - 1; j > -1; j--) {
595
596 lptr = dptr->ObLights[j];
597
598 if(lptr->LightFlags & LFlag_Deallocate) {
599
600 DeleteLightBlock(dptr->ObLights[j], dptr);
601
602 }
603
604 }
605
606 }
607
608 }
609
610 }
611
612 }
613 return 0;
614 }
615