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