/*----------------------------------------------------------------------------- Name : liBlendBufferPrepare Description : Prepare a buffer, in the appropriate image size, for blending. Inputs : image - image we are preparing to blend. newTeamColor0,1 - out parameters for the team color effect buffer. Outputs : Allocates and clears out a buffer in the same size as the image. Return : This new buffer ----------------------------------------------------------------------------*/ color *liBlendBufferPrepare(layerimage *image, ubyte **newTeamColor0, ubyte **newTeamColor1) { color *newBuffer; newBuffer = memAlloc(image->width * image->height * sizeof(color), "RGBA blend buffer", 0); //allocate the buffer memClearDword(newBuffer, colRGBA(0, 0, 0, 255), image->width * image->height); //clear to opaque black if (newTeamColor0 != NULL) { *newTeamColor0 = memAlloc(image->width * image->height, //allocate team color buffer "TeamColor0EffectBuffer", 0); *newTeamColor1 = memAlloc(image->width * image->height, //allocate team color buffer "TeamColor1EffectBuffer", 0); memset(*newTeamColor0, 0, image->width * image->height);//clear the memory memset(*newTeamColor1, 0, image->width * image->height);//in both buffers } return(newBuffer); //return the buffer }
/*----------------------------------------------------------------------------- Name : memReset Description : Reset the memory module and optionally clear all memory. Inputs : void Outputs : Global heap set up and (optionally) cleared. Return : OKAY on success. ----------------------------------------------------------------------------*/ sdword memReset(void) { memInitCheck(); #if MEM_CLEAR_MEM memClearDword(memPool, MEM_ClearSetting, memPoolLength / sizeof(udword)); #endif //set pointer to first free memory cookie memFirst = memFirstFree = (memcookie *)memPool; //set pointer to end of pool memLast = (memcookie *)(memPool + memRoundDown(memPoolLength)); //init first free cookie memFirstFree->flags = MBF_VerifyValue; memFirstFree->blocksNext = memBlocksCompute(memFirstFree, memLast) - 1; memFirstFree->blocksPrevious = -1; memNameSet(memFirstFree, MEM_NameHeap); memLast->blocksPrevious = memBlocksCompute(memFirstFree, memLast) - 1; memLast->flags = MBF_VerifyValue; #if MEM_MODULE_TEST { ubyte *a, *b, *c, *d, *e, *f; a = memAlloc(10, "TEST_A", 0); b = memAlloc(100, "TEST_B", 0); c = memAlloc(1, "TEST_C", 0); d = memAlloc(64, "TEST_D", 0); e = memAlloc(10000, "TEST_E", 0); f = memAlloc(10, "TEST_F", 0); memFree(b); memFree(c); memFree(d); memFree(f); memDefragment(); } #endif // MEM_MODULE_TEST return(OKAY); }
/*----------------------------------------------------------------------------- Name : memFree Description : Frees a block of memory Inputs : pointer - pointer to memory to be freed Outputs : Return : OKAY (generates a fatal error on bogus pointers) ----------------------------------------------------------------------------*/ sdword memFree(void *pointer) { memcookie *cookie, *nextCookie, *previousCookie; memcookie *stillNextCookie;//, *stillPreviousCookie; memInitCheck(); dbgAssert(pointer != NULL); cookie = (memcookie *)pointer; cookie--; //get pointer to cookie structure memCookieVerify(cookie); //make sure cookie is valid #if MEM_ERROR_CHECKING dbgAssert(cookie->blocksNext > 0); //ensure non-zero size dbgAssert((ubyte *)cookie + sizeof(memcookie) + memBlocksToBytes(cookie->blocksNext) <= (ubyte *)memLast); #endif #if MEM_VERBOSE_LEVEL >= 2 dbgMessagef("\nmemFree: freed %d bytes of '%s' from 0x%x", memBlocksToBytes(cookie->blocksNext), cookie->name, cookie); #endif bitClear(cookie->flags, MBF_AllocatedNext); //say it's not active memNameSet(cookie, MEM_HeapFree); //clear name of cookie if (memFirstFree > cookie) //make sure first free is the actual first free { memFirstFree = cookie; } #if MEM_CLEAR_MEM_ON_FREE memClearDword(pointer, MEM_ClearSetting, memBlocksToBytes(cookie->blocksNext) / 4); #endif #if MEM_DEFRAGMENT_FREE //attempt to combine with adjacent free block nextCookie = (memcookie *)((ubyte *)cookie + //next cookie sizeof(memcookie) + memBlocksToBytes(cookie->blocksNext)); if (nextCookie < memLast) //if not end of heap { memCookieVerify(nextCookie); //make sure cookie is valid if (!bitTest(nextCookie->flags, MBF_AllocatedNext)) //if next block also free { #if MEM_VERBOSE_LEVEL >= 3 dbgMessagef("\nmemFree: combined blocks 0x%x(%d) and 0x%x(%d) into one.", cookie, memBlocksToBytes(cookie->blocksNext), nextCookie, memBlocksToBytes(nextCookie->blocksNext)); #endif //combine sizes if (nextCookie < memLast) //update blocks previous of block past next block { stillNextCookie = nextCookie + nextCookie->blocksNext + 1; memCookieVerify(stillNextCookie); cookie->blocksNext += nextCookie->blocksNext + MEM_BlocksPerCookie; stillNextCookie->blocksPrevious = cookie->blocksNext; } #if MEM_CLEAR_MEM //clear lost cookie memClearDword(nextCookie, MEM_ClearSetting, sizeof(memcookie) / sizeof(udword)); #endif } } //attempt to combine with previous cookie if both free if (cookie->blocksPrevious != -1) { //if there is a previous block previousCookie = (memcookie *)((ubyte *)cookie - //get previous block sizeof(memcookie) - memBlocksToBytes(cookie->blocksPrevious)); dbgAssert(previousCookie >= memFirst); memCookieVerify(previousCookie); if (!bitTest(previousCookie->flags, MBF_AllocatedNext)) //if previous block also free { #if MEM_VERBOSE_LEVEL >= 3 dbgMessagef("\nmemFree: combined blocks 0x%x(%d) and 0x%x(%d) into one.", previousCookie, memBlocksToBytes(previousCookie->blocksNext), cookie, memBlocksToBytes(cookie->blocksNext)); #endif //combine sizes nextCookie = cookie + cookie->blocksNext + 1; memCookieVerify(nextCookie); nextCookie->blocksPrevious += cookie->blocksPrevious + 1; previousCookie->blocksNext = nextCookie->blocksPrevious; #if MEM_CLEAR_MEM //clear lost cookie memClearDword(cookie, MEM_ClearSetting, sizeof(memcookie) / sizeof(udword)); #endif } } #endif //MEM_DEFRAGMENT_FREE return(OKAY); }
void *memAllocFunctionA(sdword length, udword flags) #endif { ubyte *newPointer = NULL; memcookie *cookie, *newCookie, *nextCookie; memInitCheck(); length = memRoundUp(length); //round length up to block size dbgAssert(length > 0 && length < memPoolLength); //veify size is reasonable #if MEM_VERBOSE_LEVEL >= 2 dbgMessagef("\nmemAllocAttempt: allocating %d bytes for '%s'", length, name); #endif cookie = memFirstFree; //start at beginning of free list while (cookie < memLast) { //walk through entire list memCookieVerify(cookie); //make sure cookie is valid if (!bitTest(cookie->flags, MBF_AllocatedNext)) //if this block free { if (memBlocksToBytes(cookie->blocksNext) >= length)//if block bigger or equal { if (memBlocksToBytes(cookie->blocksNext) > length)//if block bigger size { nextCookie = (memcookie *)((ubyte *)cookie +//next cookie sizeof(memcookie) + memBlocksToBytes(cookie->blocksNext)); memCookieVerify(nextCookie); //make sure next cookie valid dbgAssert(nextCookie->blocksPrevious == nextCookie - cookie - 1); nextCookie->blocksPrevious -= //next cookie has fewer length / MEM_BlockSize + 1; //bytes previous to it newCookie = (memcookie *)((ubyte *)cookie + sizeof(memcookie) + length); newCookie->flags = MBF_VerifyValue; //init the new cookie newCookie->blocksNext = cookie->blocksNext - length / MEM_BlockSize - memBytesToBlocks(sizeof(memcookie)); newCookie->blocksPrevious = length / MEM_BlockSize; memNameSet(newCookie, MEM_HeapFree); //set the name of new cookie #if MEM_VERBOSE_LEVEL >= 3 dbgMessagef("\nmemAllocAttempt: found free block of size %d at 0x%x, made new cookie at 0x%x of size %d", memBlocksToBytes(cookie->blocksNext), cookie, newCookie, memBlocksToBytes(newCookie->blocksNext)); #endif cookie->blocksNext = length / MEM_BlockSize;//set new block size } else { #if MEM_VERBOSE_LEVEL >= 3 dbgMessagef("\nmemAllocAttempt: found free same-size block at 0x%x", cookie); #endif } memNameSet(cookie, name); //set new name bitSet(cookie->flags, MBF_AllocatedNext); //say it's allocated newPointer = (ubyte *)(cookie + 1); //set return pointer if (cookie == memFirstFree) //if allocating first free block { //find next free cookie while (bitTest(memFirstFree->flags, MBF_AllocatedNext)) { memCookieVerify(memFirstFree); //verify this cookie nextCookie = (memcookie *)((ubyte *)memFirstFree +//next cookie sizeof(memcookie) + memBlocksToBytes(memFirstFree->blocksNext)); if (nextCookie >= memLast) //if cookie pointed past end of heap { goto noMoreFree; //no more free structures } memFirstFree = nextCookie; } memNameSet(memFirstFree, MEM_NameHeapFirst); noMoreFree:; } break; } #if MEM_VERBOSE_LEVEL >= 4 dbgMessagef("\nmemAllocAttempt: skipping free block of size %d at 0x%x - too small", memBlocksToBytes(cookie->blocksNext), cookie); #endif } else { #if MEM_VERBOSE_LEVEL >= 4 dbgMessagef("\nmemAllocAttempt: skipping block of size %d at 0x%x - already allocated", memBlocksToBytes(cookie->blocksNext), cookie); #endif } dbgAssert(memBlocksToBytes(cookie->blocksNext) >= 0 && memBlocksToBytes(cookie->blocksNext) < memPoolLength); cookie = (memcookie *)((ubyte *)cookie + //next cookie sizeof(memcookie) + memBlocksToBytes(cookie->blocksNext)); } if (newPointer == NULL) { #if MEM_VERBOSE_LEVEL >= 1 dbgMessagef("\nmemAllocAttempt: failed to find block of length %d", length); #endif } else { #if MEM_CLEAR_MEM //clear the new block memClearDword(newPointer, MEM_ClearSetting, length / sizeof(udword)); #endif } return(newPointer); }