MF_API void MFHeap_Free(void *pMem) { MFCALLSTACK; if(!pMem) { MFDebug_Warn(3, "Attemptd to Free 'NULL' pointer."); return; } MFThread_LockMutex(gAllocMutex); MFAllocHeader *pHeader = GetAllocHeader(pMem); MFDebug_Assert(MFHeap_ValidateMemory(pMem), MFStr("Memory corruption detected!!\n%s(" MFFMT_SIZE_T ")", pHeader->pFile, pHeader->line)); MFHeap *pHeap = pHeader->pHeap; #if !defined(_RETAIL) size_t extra; size_t allocBytes = GetAllocSize(pHeader->size, extra); pHeap->totalAllocated -= allocBytes; pHeap->totalWaste -= extra; --pHeap->allocCount; // MFDebug_Log(2, MFStr("Free: %p, %d bytes - %s:(%d)", pMem, pHeader->size, pHeader->pFile, (int)pHeader->line)); #endif MFCopyMemory((char*)pMem + pHeader->size, "freefreefreefree", MFHeap_MungwallBytes); #if defined(USE_PRE_MUNGWALL) MFCopyMemory((char*)pMem - MFHeap_MungwallBytes, "eerfeerfeerfeerf", MFHeap_MungwallBytes); #endif MFMemSet(pMem, 0xFE, pHeader->size); pHeap->pCallbacks->pFree((char*)pMem - pHeader->alignment, pHeap->pHeapData); #if defined(_USE_TRACKING_HASH_TABLE) FreeAlloc(pMem); #endif MFThread_ReleaseMutex(gAllocMutex); }
MF_API bool MFHeap_ValidateHeap() { #if defined(_USE_TRACKING_HASH_TABLE) MFThread_LockMutex(gAllocMutex); for(int i=0; i<MFHeap_AllocTableLength; ++i) { MFHeap_AllocItem *pI = gpAllocTable[i]; while(pI) { if(!MFHeap_ValidateMemory(pI->pMemory)) MFDebug_Assert(false, "Corrupt memory allocation!"); pI = pI->pNext; } } MFThread_ReleaseMutex(gAllocMutex); #endif return true; }
MF_API bool MFHeap_ValidateHeap() { #if defined(_USE_ALLOC_TRACKER) MFThread_LockMutex(gAllocMutex); if(gPoolInitialised) { int numAllocated = gAllocList.GetNumAllocated(); for(int a=0; a<numAllocated; ++a) { void *pMem = *(void**)gAllocList.GetItem(a); if(!MFHeap_ValidateMemory(pMem)) { MFDebug_Assert(false, "Corrupt memory allocation!"); return false; } } } MFThread_ReleaseMutex(gAllocMutex); #endif return true; }
MF_API void *MFHeap_ReallocInternal(void *pMem, size_t bytes) { MFCALLSTACK; if(pMem) { MFAllocHeader *pHeader = &((MFAllocHeader*)pMem)[-1]; MFDebug_Assert(MFHeap_ValidateMemory(pMem), MFStr("Memory corruption detected!!\n%s(%d)", pHeader->pFile, pHeader->line)); void *pNew = MFHeap_AllocInternal(bytes, pHeader->pHeap); MFDebug_Assert(pNew, "Failed to allocate memory!"); if(!pNew) return NULL; MFCopyMemory(pNew, pMem, MFMin(bytes, (size_t)pHeader->size)); MFHeap_Free(pMem); return pNew; } else { return MFHeap_AllocInternal(bytes, NULL); } }
MF_API void MFCollision_BuildField(MFCollisionItem *pField) { MFCollisionField *pFieldData = (MFCollisionField*)pField->pTemplate; int numItems = pFieldData->itemList.GetLength(); if(numItems <= 0) { MFDebug_Warn(4, "EmptyField can not be generated."); return; } // find the min and max range of the objects MFVector fieldMin = MakeVector(10e+30f), fieldMax = MakeVector(-10e+30f); MFCollisionItem **ppI = pFieldData->itemList.Begin(); while(*ppI) { MFCollisionItem *pI = *ppI; MFCollisionTemplate *pT = pI->pTemplate; MFVector tMin = ApplyMatrixH(pT->boundingVolume.min, pI->worldPos); MFVector tMax = ApplyMatrixH(pT->boundingVolume.max, pI->worldPos); fieldMin = MFMin(fieldMin, tMin); fieldMax = MFMax(fieldMax, tMax); ppI++; } pFieldData->fieldMin = fieldMin; pFieldData->fieldMax = fieldMin; MFVector numCells; MFVector fieldRange = fieldMax - fieldMin; numCells.Rcp3(pFieldData->cellSize); numCells.Mul3(fieldRange, numCells); pFieldData->width = (int)MFCeil(numCells.x); pFieldData->height = (int)MFCeil(numCells.y); pFieldData->depth = (int)MFCeil(numCells.z); // this is TOTALLY broken!! .. if a big object lies in many cell's, it could easilly overflow the array. int totalCells = pFieldData->width * pFieldData->height * pFieldData->depth; int numPointers = totalCells * 2 + numItems * 16; MFCollisionItem **ppItems = (MFCollisionItem**)MFHeap_Alloc(sizeof(MFCollisionItem*) * numPointers); pFieldData->pppItems = (MFCollisionItem***)ppItems; ppItems += totalCells; for(int z=0; z<pFieldData->depth; z++) { for(int y=0; y<pFieldData->height; y++) { for(int x=0; x<pFieldData->width; x++) { pFieldData->pppItems[z*pFieldData->height*pFieldData->width + y*pFieldData->width + x] = ppItems; MFVector thisCell = fieldMin + pFieldData->cellSize * MakeVector((float)x, (float)y, (float)z); MFVector thisCellEnd = thisCell + pFieldData->cellSize; MFCollisionItem **ppI = pFieldData->itemList.Begin(); while(*ppI) { MFCollisionItem *pI = *ppI; MFCollisionTemplate *pT = pI->pTemplate; // if this item fits in this cell, insert it into this cells list. MFVector tMin = ApplyMatrixH(pT->boundingVolume.min, pI->worldPos); MFVector tMax = ApplyMatrixH(pT->boundingVolume.max, pI->worldPos); // test of bounding boxes overlap if(MFCollision_TestAABB(tMin, tMax, thisCell, thisCellEnd)) { *ppItems = pI; ++ppItems; } ppI++; } *ppItems = NULL; ++ppItems; } } } MFHeap_ValidateMemory(pFieldData->pppItems); }
MF_API void MFHeap_Free(void *pMem) { MFCALLSTACK; if(!pMem) { MFDebug_Warn(3, "Attemptd to Free 'NULL' pointer."); return; } MFAllocHeader *pHeader = &((MFAllocHeader*)pMem)[-1]; MFDebug_Assert(MFHeap_ValidateMemory(pMem), MFStr("Memory corruption detected!!\n%s(%d)", pHeader->pFile, pHeader->line)); MFThread_LockMutex(gAllocMutex); MFHeap *pHeap = pHeader->pHeap; if(pHeap->heapType != MFHT_Debug) { #if defined(_USE_TRACKING_HASH_TABLE) int hash = MFUtil_HashPointer(pMem) % MFHeap_AllocTableLength; MFHeap_AllocItem *pT = gpAllocTable[hash]; if(pT) { if(pT->pMemory == pMem) { gpAllocTable[hash] = pT->pNext; gAllocHeaderPool.Free(pT); } else { while(pT->pNext && pT->pNext->pMemory != pMem) pT = pT->pNext; if(pT->pNext) { MFHeap_AllocItem *pTN = pT->pNext; pT->pNext = pTN->pNext; gAllocHeaderPool.Free(pTN); } } } #endif #if defined(_USE_ALLOC_TRACKER) if(gPoolInitialised) { int numAllocs = gAllocList.GetNumAllocated(); for(int a=0; a<numAllocs; ++a) { void **ppAlloc = (void**)gAllocList.GetItem(a); if(*ppAlloc == pMem) { gAllocList.Free(ppAlloc); break; } } } #endif } #if !defined(_RETAIL) int pad = 0; while(pad < (int)sizeof(MFAllocHeader)) pad += heapAlignment; size_t extra = pad + sizeof(MFAllocHeader) + MFHeap_MungwallBytes; pHeap->totalAllocated -= pHeader->size + extra; pHeap->totalWaste -= extra; --pHeap->allocCount; // MFDebug_Log(2, MFStr("Free: %08X, %d bytes - %s:(%d)", pMem, pHeader->size, pHeader->pFile, (int)pHeader->line)); #endif MFHeap *pAllocHeap = pHeader->pHeap; MFCopyMemory((char*)pMem + pHeader->size, "freefreefreefree", MFHeap_MungwallBytes); MFCopyMemory((char*)pMem - 8, "freefreefreefree", MFHeap_MungwallBytes); MFMemSet(pMem, 0xFE, pHeader->size); pAllocHeap->pCallbacks->pFree((char*)pMem - pHeader->alignment, pAllocHeap->pHeapData); MFThread_ReleaseMutex(gAllocMutex); }