#include "3dc.h" #include "module.h" #include "stratdef.h" #include "sfx.h" #define UseLocalAssert Yes #include "ourasert.h" /* globals for export */ int NumActiveBlocks; DISPLAYBLOCK *ActiveBlockList[maxobjects]; /* Object Block Lists et al */ static int NumFreeBlocks; static DISPLAYBLOCK *FreeBlockList[maxobjects]; static DISPLAYBLOCK **FreeBlockListPtr = &FreeBlockList[maxobjects-1]; static DISPLAYBLOCK FreeBlockData[maxobjects]; static DISPLAYBLOCK **ActiveBlockListPtr = &ActiveBlockList[0]; /* Texture Animation Block Extensions */ static int NumFreeTxAnimBlocks; static TXACTRLBLK *FreeTxAnimBlockList[maxTxAnimblocks]; static TXACTRLBLK **FreeTxAnimBlockListPtr = &FreeTxAnimBlockList[maxTxAnimblocks-1]; static TXACTRLBLK FreeTxAnimBlockData[maxTxAnimblocks]; /* Light Block Extensions */ static int NumFreeLightBlocks; static LIGHTBLOCK *FreeLightBlockList[maxlightblocks]; static LIGHTBLOCK **FreeLightBlockListPtr = &FreeLightBlockList[maxlightblocks-1]; static LIGHTBLOCK FreeLightBlockData[maxlightblocks]; /* To create the free block list, pointers to "FreeBlockData[]" must be copied to "FreeBlockList[]". Also: "NumFreeBlocks" must be updated as "FreeBlockList[]" is created. "NumActiveBlocks" must be initialised to zero. */ void InitialiseObjectBlocks(void) { DISPLAYBLOCK *FreeBlkPtr = &FreeBlockData[0]; NumActiveBlocks = 0; FreeBlockListPtr = &FreeBlockList[maxobjects-1]; ActiveBlockListPtr = &ActiveBlockList[0]; for(NumFreeBlocks = 0; NumFreeBlocksObVDBPtr); /* Checks for null */ if(dblockptr->ObNumLights) { for(light = dblockptr->ObNumLights - 1; light != -1; light--) DeleteLightBlock(dblockptr->ObLights[light], dblockptr); } /* If no SB, deallocate any Texture Animation Blocks */ if(dblockptr->ObStrategyBlock == 0) { if(dblockptr->ObTxAnimCtrlBlks) { taptr = dblockptr->ObTxAnimCtrlBlks; while(taptr) { DeallocateTxAnimBlock(taptr); taptr = taptr->tac_next; } } } /* Deallocate the Lazy Morphed Points Array Pointer */ #if (SupportMorphing && LazyEvaluationForMorphing) if(dblockptr->ObMorphedPts) { DeallocateMem(dblockptr->ObMorphedPts); dblockptr->ObMorphedPts = 0; } #endif /* KJL 16:52:43 06/01/98 - dealloc sfx block if one exists */ if(dblockptr->SfxPtr) { DeallocateSfxBlock(dblockptr->SfxPtr); } DeallocateObjectBlock(dblockptr); /* Back to Free List */ /* If this is the current landscape, clear the pointer */ return 0; } } } return -1; } /* Support Functions for Texture Animation Blocks */ void InitialiseTxAnimBlocks(void) { TXACTRLBLK *FreeBlkPtr = &FreeTxAnimBlockData[0]; FreeTxAnimBlockListPtr = &FreeTxAnimBlockList[maxTxAnimblocks-1]; for(NumFreeTxAnimBlocks=0; NumFreeTxAnimBlocks < maxTxAnimblocks; NumFreeTxAnimBlocks++) { FreeTxAnimBlockList[NumFreeTxAnimBlocks] = FreeBlkPtr; FreeBlkPtr++; } } /* Allocate a Texture Animation Block */ TXACTRLBLK* AllocateTxAnimBlock(void) { TXACTRLBLK *FreeBlkPtr = 0; /* Default to null ptr */ int *sptr; int i; if(NumFreeTxAnimBlocks) { FreeBlkPtr = *FreeTxAnimBlockListPtr--; NumFreeTxAnimBlocks--; /* One less free block */ /* Clear the block */ sptr = (int *)FreeBlkPtr; for(i = sizeof(TXACTRLBLK)/4; i!=0; i--) *sptr++ = 0; } return FreeBlkPtr; } /* Deallocate a Texture Animation Block */ void DeallocateTxAnimBlock(TXACTRLBLK *TxAnimblockptr) { FreeTxAnimBlockListPtr++; *FreeTxAnimBlockListPtr = TxAnimblockptr; NumFreeTxAnimBlocks++; /* One more free block */ } /* Add a Texture Animation Block to a Display Block */ void AddTxAnimBlock(DISPLAYBLOCK *dptr, TXACTRLBLK *taptr) { TXACTRLBLK *taptr_tmp; if(dptr->ObTxAnimCtrlBlks) { taptr_tmp = dptr->ObTxAnimCtrlBlks; while(taptr_tmp->tac_next) taptr_tmp = taptr_tmp->tac_next; taptr_tmp->tac_next = taptr; } else dptr->ObTxAnimCtrlBlks = taptr; } /* Support functions for Light Blocks */ void InitialiseLightBlocks(void) { LIGHTBLOCK *FreeBlkPtr = &FreeLightBlockData[0]; FreeLightBlockListPtr = &FreeLightBlockList[maxlightblocks-1]; for(NumFreeLightBlocks=0; NumFreeLightBlocks < maxlightblocks; NumFreeLightBlocks++) { FreeLightBlockList[NumFreeLightBlocks] = FreeBlkPtr; FreeBlkPtr++; } } LIGHTBLOCK* AllocateLightBlock(void) { LIGHTBLOCK *FreeBlkPtr = 0; /* Default to null ptr */ int *lptr; int i; if(NumFreeLightBlocks) { FreeBlkPtr = *FreeLightBlockListPtr--; NumFreeLightBlocks--; /* One less free block */ /* Clear the block */ lptr = (int *)FreeBlkPtr; for(i = sizeof(LIGHTBLOCK)/4; i!=0; i--) *lptr++ = 0; } return(FreeBlkPtr); } void DeallocateLightBlock(LIGHTBLOCK *lptr) { /* Not all lights come from the free light list */ if(lptr->LightFlags & LFlag_WasNotAllocated) return; /* Make sure that this light IS from the free light list */ GLOBALASSERT( (lptr >= FreeLightBlockData) && (lptr < &FreeLightBlockData[maxlightblocks]) ); /* Ok to return the light */ FreeLightBlockListPtr++; *FreeLightBlockListPtr = lptr; NumFreeLightBlocks++; /* One more free block */ } /* See if there are any free slots in the dptr light block array. If there are, allocate a light block, place it in the list and return the pointer to the caller. A late addition is the passing of a light block (from somewhere, it does not matter where). This light block is then added rather than one being allocated from the free light block list. */ LIGHTBLOCK* AddLightBlock(DISPLAYBLOCK *dptr, LIGHTBLOCK *lptr_to_add) { LIGHTBLOCK **larrayptr; LIGHTBLOCK **freelarrayptr; LIGHTBLOCK *lptr = 0; int i, lfree; /* Are there any free slots? */ lfree = No; larrayptr = &dptr->ObLights[0]; freelarrayptr = NULL; for(i = MaxObjectLights; i!=0 && lfree == No; i--) { if(*larrayptr == 0) { freelarrayptr = larrayptr; lfree = Yes; } larrayptr++; } if(lfree) { if(lptr_to_add) { lptr = lptr_to_add; } else { lptr = AllocateLightBlock(); } if(lptr) { *freelarrayptr = lptr; dptr->ObNumLights++; } } return lptr; } /* To delete a light block, copy the end block to the new free slot and reduce the count by one. Make sure the end block array entry is cleared. */ void DeleteLightBlock(LIGHTBLOCK *lptr, DISPLAYBLOCK *dptr) { int i, larrayi; DeallocateLightBlock(lptr); /* What is lptr's array index? */ larrayi = -1; /* null value */ for(i = 0; i < dptr->ObNumLights; i++) if(dptr->ObLights[i] == lptr) larrayi = i; /* Proceed only if lptr has been found in the array */ if(larrayi != -1) { /* Copy the end block to that of lptr */ dptr->ObLights[larrayi] = dptr->ObLights[dptr->ObNumLights - 1]; /* Clear the end block array entry */ dptr->ObLights[dptr->ObNumLights - 1] = 0; /* One less light in the dptr list */ dptr->ObNumLights--; } } /* When running the parallel strategies, display and light block deallocation must only be done at the end of the frame, AFTER processor synchronisation and BEFORE the shadow copy. */ int DisplayAndLightBlockDeallocation(void) { DISPLAYBLOCK **activeblocksptr; DISPLAYBLOCK *dptr; int i, j; LIGHTBLOCK *lptr; if(NumActiveBlocks) { activeblocksptr = &ActiveBlockList[NumActiveBlocks - 1]; for(i = NumActiveBlocks; i!=0; i--) { dptr = *activeblocksptr--; /* Deallocate Object? */ if(dptr->ObFlags2 & ObFlag2_Deallocate) { DestroyActiveObject(dptr); } /* Deallocate any Lights? */ else { if(dptr->ObNumLights) { for(j = dptr->ObNumLights - 1; j > -1; j--) { lptr = dptr->ObLights[j]; if(lptr->LightFlags & LFlag_Deallocate) { DeleteLightBlock(dptr->ObLights[j], dptr); } } } } } } return 0; }