Per's removal of the memory heap system. Now MALLOC is just malloc, and not some wrapper around a wrapper that will allocate it from a specific pool.

The MSVC poject will need to be updated I guess, as some files were deleted.


git-svn-id: svn+ssh://svn.gna.org/svn/warzone/trunk@1343 4a71c877-e1ca-e34f-864e-861f7616d084
master
Gerard Krol 2007-04-03 10:33:26 +00:00
parent fe90b5374a
commit 42ed587327
24 changed files with 26 additions and 1740 deletions

View File

@ -10,10 +10,10 @@ BUILT_SOURCES = resource_parser.tab.h strres_parser.tab.h
CLEANFILES = resource_parser.tab.h strres_parser.tab.h
noinst_LIBRARIES = libframework.a
noinst_HEADERS = block.h configfile.h cursors.h cursors16.h debug.h font.h fractions.h frame.h \
frameint.h frameresource.h heap.h input.h listmacs.h mem.h memint.h resly.h \
noinst_HEADERS = configfile.h cursors.h cursors16.h debug.h font.h fractions.h frame.h \
frameint.h frameresource.h heap.h input.h listmacs.h mem.h resly.h \
strres.h strresly.h treap.h treapint.h trig.h types.h
libframework_a_SOURCES = SDL_framerate.c block.c configfile.c debug.c exceptionhandler.c frame.c \
frameresource.c heap.c input.c mem.c resource_lexer.lex.c resource_parser.tab.c \
libframework_a_SOURCES = SDL_framerate.c configfile.c debug.c exceptionhandler.c frame.c \
frameresource.c heap.c input.c resource_lexer.lex.c resource_parser.tab.c \
strres.c strres_lexer.lex.c strres_parser.tab.c treap.c trig.c

View File

@ -1,15 +1,13 @@
MAKERULES=../../makerules
include $(MAKERULES)/configure.mk
SRC=block.c \
configfile.c \
SRC=configfile.c \
debug.c \
exceptionhandler.c \
frame.c \
frameresource.c \
heap.c \
input.c \
mem.c \
resource_parser.tab.c \
resource_lexer.lex.c \
strres.c \

View File

@ -1,649 +0,0 @@
/*
This file is part of Warzone 2100.
Copyright (C) 1999-2004 Eidos Interactive
Copyright (C) 2005-2007 Warzone Resurrection Project
Warzone 2100 is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Warzone 2100 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Warzone 2100; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* Block.c
*
* Routines to allocate memory from one large block.
* Any memory allocated is only available to reallocated after
* the whole block has been reset.
*
*/
#include <string.h>
/* Allow frame header files to be singly included */
#define FRAME_LIB_INCLUDE
// memory usage printf's
#define DEBUG_GROUP0
#include "types.h"
#include "debug.h"
#include "mem.h"
#include "heap.h"
#include "treap.h"
#include "treapint.h"
#include "memint.h"
#include "listmacs.h"
#include "block.h"
/* What functions to use for the real malloc and free */
#define RMALLOC malloc
#define RFREE free
/* Whether allocated memory is initialised to a value and whether the memory
* is trashed before it is freed.
* This is done automatically by Visual C's memory routines.
*/
#define MEMORY_SET TRUE
// the filename and line number of the last call to the block functions
static const char *pCallFileName;
static SDWORD callLine;
// the list of allocated blocks
static BLOCK_HEAP *psBlockList=NULL;
// initialise the block system
BOOL blkInitialise(void)
{
ASSERT( psBlockList==NULL, "blkInitialise: Blocks already initialised" ); // blkShutDown() needs to be called
LIST_INIT(psBlockList);
return TRUE;
}
// shutdown the block system
void blkShutDown(void)
{
BLOCK_HEAP *psNext;
if (psBlockList)
{
debug( LOG_NEVER, "blkShutDown: blocks still allocated:\n" );
while (psBlockList)
{
psNext = psBlockList->psNext;
blkDestroy(psBlockList);
psBlockList = psNext;
}
}
}
// Note the call position for a blkAlloc or blkFree
void blkCallPos(const char *pFileName, SDWORD line)
{
pCallFileName = pFileName;
callLine = line;
}
// Create a new block heap
BOOL blkCreate(BLOCK_HEAP **ppsHeap, SDWORD init, SDWORD ext)
{
debug( LOG_NEVER, "BLKCREATE CALLED !!!!!!!!!!!!!!!!!!!!!!\n" );
*ppsHeap = (BLOCK_HEAP*)RMALLOC(sizeof(BLOCK_HEAP));
if (!*ppsHeap)
{
debug( LOG_ERROR, "blkCreate: Out of memory" );
abort();
return FALSE;
}
(*ppsHeap)->psBlocks = (BLOCK_HEAP_MEM*)RMALLOC(sizeof(BLOCK_HEAP_MEM));
if (!(*ppsHeap)->psBlocks)
{
debug( LOG_ERROR, "blkCreate: Out of memory" );
abort();
return FALSE;
}
(*ppsHeap)->psBlocks->pMem = (UBYTE*)RMALLOC(init);
if (!(*ppsHeap)->psBlocks->pMem)
{
debug( LOG_ERROR, "blkCreate: Out of memory" );
abort();
return FALSE;
}
(*ppsHeap)->init = init;
(*ppsHeap)->ext = ext;
(*ppsHeap)->psBlocks->size = init;
(*ppsHeap)->psBlocks->pFree = (*ppsHeap)->psBlocks->pMem;
(*ppsHeap)->psBlocks->psNext = NULL;
#ifdef DEBUG_MALLOC
(*ppsHeap)->pFileName = pCallFileName;
(*ppsHeap)->line = callLine;
(*ppsHeap)->psMemTreap = NULL;
(*ppsHeap)->free = FALSE;
(*ppsHeap)->TotalAllocated=0;
#endif
LIST_ADD(psBlockList, *ppsHeap);
return TRUE;
}
// Release a block heap
void blkDestroy(BLOCK_HEAP *psHeap)
{
BLOCK_HEAP_MEM *psCurr, *psNext;
#ifdef DEBUG_MALLOC
if (psHeap->psMemTreap != NULL)
{
debug( LOG_NEVER, "blkDestroy: %s at %d: memory allocated :\n", psHeap->pFileName, psHeap->line );
#ifdef REALLY_DEBUG_MALLOC
memRecReport(psHeap->psMemTreap);
#endif
}
#endif
LIST_REMOVE(psBlockList, psHeap, BLOCK_HEAP);
for(psCurr=psHeap->psBlocks; psCurr; psCurr=psNext)
{
RFREE(psCurr->pMem);
psNext = psCurr->psNext;
RFREE(psCurr);
}
RFREE(psHeap);
}
#ifdef DEBUG_MALLOC
void memMemoryDump(MEM_NODE *Node);
#endif
void blkPrintDetails(BLOCK_HEAP *psHeap)
{
if (psHeap!=NULL)
{
#ifdef DEBUG_MALLOC
UDWORD Left = (UDWORD)((psHeap->psBlocks->pMem)+(psHeap->psBlocks->size)-(psHeap->psBlocks->pFree));
debug( LOG_NEVER, "ptr=%p init=%d ext=%d used=%d (Start=$%p Free=$%p Left=%d)\n", psHeap,psHeap->init, psHeap->ext,psHeap->TotalAllocated, psHeap->psBlocks->pMem, psHeap->psBlocks->pFree, Left );
memMemoryDump(psHeap->psMemTreap);
#else
debug( LOG_NEVER, "ptr=%p init=%d ext=%d\n", psHeap, psHeap->init, psHeap->ext );
#endif
}
else
{
debug( LOG_NEVER, "NULL POINTER IN BLOCK LIST\n" );
}
}
// report on the blocks
void blkReport(void)
{
#ifdef DEBUG
UDWORD BlockNumber=0;
BLOCK_HEAP *psCurHeap;
debug( LOG_NEVER, "\n\nBlock Report. Current Block=%p:\n", memGetBlockHeap() );
psCurHeap=psBlockList;
while (psCurHeap)
{
debug( LOG_NEVER, "Block %d)",BlockNumber++ );
blkPrintDetails(psCurHeap);
psCurHeap = psCurHeap->psNext;
}
debug( LOG_NEVER, "\n\n" );
#endif
}
#if(0) // no longer used - uploaded in small chunks
// This is a special free that checks to see if we can free up the memory
// We can only do this if it is the last allocated memory in the block
//
// This can be used for scratch memory ... Critical on the Playstation where memory is so tight
//
// - e.g. The sound data must be stored as one 400k file. This must be loaded into scratch memory
// we clearly do not have 400k of spare memory around.
//
//
// Returns true or false
//
BOOL blkSpecialFree(BLOCK_HEAP *psHeap, void *Ptr)
{
BLOCK_HEAP_MEM *psCurr;
UDWORD RequestedFreeMem=(UDWORD)Ptr;
for(psCurr = psHeap->psBlocks; psCurr; psCurr = psCurr->psNext)
{
if ((UDWORD)psCurr->pLastAllocated == RequestedFreeMem)
{
#ifdef DEBUG_MALLOC
UDWORD BlockSize=((UDWORD)psCurr->pFree)-RequestedFreeMem;
debug( LOG_NEVER, "FREED %d block bytes\n", BlockSize ); // del me now !
psHeap->TotalAllocated-=BlockSize;
#endif
psCurr->pFree = psCurr->pLastAllocated;
psCurr->pLastAllocated=0; // remove pointer so that it cant be allocated again
return(TRUE); // able to return mem
}
}
return(FALSE); // unable to free mem
}
#endif
// Allocate some memory from a block heap
void *blkAlloc(BLOCK_HEAP *psHeap, SDWORD size)
{
void *pAlloc;
BLOCK_HEAP_MEM *psCurr, *psNew;
#ifdef DEBUG_MALLOC
SDWORD allocSize;
MEM_NODE *psNode;
#endif
// Round up to nearest 4 bytes ( 32 bit align ).. Neaded for Playstation.. PD.
size = (size + 3) & 0xfffffffc;
// can't allocate 0 bytes
if (size <= 0)
{
ASSERT( FALSE, "blkAlloc: cannot allocate 0 bytes" );
return NULL;
}
#ifdef DEBUG_MALLOC
// see if free has been called for this block
if (psHeap->free)
{
debug( LOG_NEVER, "Block Heap: %s at %d: Alloc after free:\n free %s at %d\n alloc %s at %d\n", psHeap->pFileName, psHeap->line, psHeap->pFreeFile, psHeap->freeLine, pCallFileName, callLine );
psHeap->free = FALSE;
}
// increase the size of the block to allow for the treap entry and overwrite blocks
allocSize = size;
size += sizeof(MEM_NODE) + 2 * SAFETY_ZONE_SIZE;
psHeap->TotalAllocated+=allocSize;
#endif
// find a block with a large enough segment free
pAlloc = NULL;
for(psCurr = psHeap->psBlocks; psCurr; psCurr = psCurr->psNext)
{
if (psCurr->pFree + size <= psCurr->pMem + psCurr->size)
{
pAlloc = psCurr->pFree;
psCurr->pFree += size;
break;
}
}
// if there wasn't a block try to allocate a new one
if ((psCurr == NULL) && (psHeap->ext != 0))
{
psNew = (BLOCK_HEAP_MEM*)RMALLOC(sizeof(BLOCK_HEAP_MEM));
if (!psNew)
{
ASSERT( FALSE, "blkAlloc: warning out of memory" );
// Out of memory
return NULL;
}
if (size < psHeap->ext)
{
psNew->pMem = (UBYTE*)RMALLOC(psHeap->ext);
psNew->size = psHeap->ext;
}
else
{
psNew->pMem = (UBYTE*)RMALLOC(size);
psNew->size = size;
}
if (!psNew->pMem)
{
// Out of memory
RFREE(psNew);
ASSERT( FALSE, "blkAlloc: warning out of memory" );
return NULL;
}
psNew->psNext = NULL;
psNew->pFree = psNew->pMem + size;
pAlloc = psNew->pMem;
// Add the block to the end of the list
for(psCurr=psHeap->psBlocks; psCurr->psNext != NULL; psCurr = psCurr->psNext)
;
psCurr->psNext = psNew;
}
#ifdef DEBUG_MALLOC
if (!pAlloc)
{
// failed to allocate the memory
ASSERT( FALSE, "Warning: malloc returning NULL - [%s - %d] %d bytes",pCallFileName,callLine, size );
return NULL;
}
// add the allocated memory into the treap
psNode = (MEM_NODE *)pAlloc;
psNode->pFile = pCallFileName;
psNode->line = callLine;
psNode->size = allocSize;
/* Store the new entry in the memory treap */
psNode->priority = (UDWORD)rand();
psNode->key = (void*)psNode;
psNode->pObj = psNode;
psNode->psLeft = NULL;
psNode->psRight = NULL;
treapAddNode((TREAP_NODE **)&psHeap->psMemTreap, (TREAP_NODE *)psNode, memBlockCmp);
/* Now initialise the memory - try to catch unitialised variables */
memset((UBYTE *)(psNode) + sizeof(MEM_NODE),
SAFETY_ZONE_BYTE, SAFETY_ZONE_SIZE);
memset((UBYTE *)(psNode) + sizeof(MEM_NODE) + SAFETY_ZONE_SIZE + allocSize,
SAFETY_ZONE_BYTE, SAFETY_ZONE_SIZE);
#if MEMORY_SET
/* The PC initialises malloc'ed memory already, no need to do it again */
memset((UBYTE *)(psNode) + sizeof(MEM_NODE) + SAFETY_ZONE_SIZE,
INITIALISE_BYTE, allocSize);
#endif
// offset the return value by the header size
pAlloc = ((UBYTE *)(pAlloc) + sizeof(MEM_NODE) + SAFETY_ZONE_SIZE);
#endif
psCurr->pLastAllocated=(UBYTE*)pAlloc;
///* - error trapping an out-of-mem allocation !!!
//NoMemChk:
return pAlloc;
}
//*/
// return a chunk of memory to the block
// this only does anything whith DEBUG_BLOCK defined
void blkFree(BLOCK_HEAP *psHeap, void *pMemToFree)
{
#ifdef DEBUG_MALLOC
MEM_NODE sNode, *psDeleted;
SDWORD i, InvalidBottom, InvalidTop;
UBYTE *pMemBase;
#if MEMORY_SET
SDWORD Size;
#endif
// note the call to free
psHeap->free = TRUE;
psHeap->pFreeFile = pCallFileName;
psHeap->freeLine = callLine;
// Create a dummy node for the search
// This is only looked at by memBlockCmp so only need to set the object and size
sNode.pObj = ((UBYTE *)pMemToFree) - sizeof(MEM_NODE) - SAFETY_ZONE_SIZE;
sNode.size = 1;
/* Get the node for the memory block */
psDeleted = (MEM_NODE *)treapDelRec((TREAP_NODE **)&psHeap->psMemTreap,
(void*)&sNode, memBlockCmp);
ASSERT( psDeleted != NULL,
"Invalid pointer passed to mem_Free by:\n"
"File: %s\nLine: %d\n\n"
"Attempt to free already freed pointer?",
pCallFileName, callLine );
if (psDeleted)
{
/* The pointer is valid, check the buffer zones */
pMemBase = (UBYTE *)(pMemToFree) - SAFETY_ZONE_SIZE;
InvalidBottom = InvalidTop = 0;
for(i=0; i<SAFETY_ZONE_SIZE; i++)
{
if (pMemBase[i] != SAFETY_ZONE_BYTE)
{
InvalidBottom++;
}
if (pMemBase[i + psDeleted->size + SAFETY_ZONE_SIZE] != SAFETY_ZONE_BYTE)
{
InvalidTop++;
}
}
// this breaks debug... ***** look into why...
// ASSERT( !InvalidBottom && !InvalidTop,
// "Safety zone on memory overwritten.\n"
// "%d Invalid bytes (of %d) found below memory buffer.\n"
// "%d Invalid bytes (of %d) found above memory buffer.\n\n"
// "Memory allocated by:\nFile: %s\nLine: %d\n"
// "Memory freed by:\nFile: %s\nLine: %d\n",
// InvalidBottom, SAFETY_ZONE_SIZE, InvalidTop, SAFETY_ZONE_SIZE,
// psDeleted->pFile, psDeleted->line,
// pCallFileName, callLine );
/* Trash the memory before it is freed */
#if MEMORY_SET
Size = psDeleted->size;
memset(pMemToFree, FREE_BYTE, Size);
#endif
}
#else
// non debug free !
// psHeap = psHeap;
// pMemToFree = pMemToFree;
#endif
{
// BOOL bRes;
#if(1)
//DBPRINTF(("UNABLE TO FREE MEMORY\n"));
#else
bRes=blkSpecialFree(psHeap, pMemToFree); // Free it up if we can ! - we can only free the last entry
#ifdef DEBUG
if (bRes==TRUE)
{
debug( LOG_NEVER, "blkFree called - memory successfully released\n" );
}
else
{
// debug( LOG_NEVER, "blkFree called - memory NOT released\n" );
}
#endif
#endif
}
}
// Reset a block heap
void blkReset(BLOCK_HEAP *psHeap)
{
BLOCK_HEAP_MEM *psCurr;
#ifdef DEBUG_GROUP0
SDWORD block=0, alloc=0;
#endif
#ifdef DEBUG_MALLOC
if (psHeap->psMemTreap != NULL)
{
debug( LOG_NEVER, "blkReset: %s at %d: memory allocated :\n", psHeap->pFileName, psHeap->line );
#ifdef REALLY_DEBUG_MALLOC
memRecReport(psHeap->psMemTreap);
#endif
}
psHeap->psMemTreap = NULL;
psHeap->free = FALSE;
psHeap->TotalAllocated=0;
debug( LOG_NEVER, "blkReset: %s at %d: memory usage:\n", psHeap->pFileName, psHeap->line );
#else
debug( LOG_NEVER, "blkReset: memory usage:\n" );
#endif
psCurr = psHeap->psBlocks;
while(psCurr)
{
#ifdef DEBUG_GROUP0
alloc += psCurr->pFree - psCurr->pMem;
block += psCurr->size;
#endif
#if defined(DEBUG_MALLOC) && MEMORY_SET
memset(psCurr->pMem, FREE_BYTE, psCurr->size);
#endif
psCurr->pFree = psCurr->pMem;
psCurr = psCurr->psNext;
}
debug( LOG_NEVER, " Blocks allocated %dk, Memory allocated %dk\n", block/1024, alloc/1024 );
}
// Find which block a pointer is from if any
BLOCK_HEAP *blkFind(void *pPtr)
{
BLOCK_HEAP *psHeap;
BLOCK_HEAP_MEM *psMem;
for(psHeap=psBlockList; psHeap; psHeap=psHeap->psNext)
{
for(psMem=psHeap->psBlocks; psMem; psMem=psMem->psNext)
{
if ((UBYTE *)pPtr >= psMem->pMem &&
(UBYTE *)pPtr < psMem->pMem + psMem->size)
{
return psHeap;
}
}
}
return NULL;
}
// check if a pointer is valid in a block
BOOL blkPointerValid(BLOCK_HEAP *psHeap, void *pData, SDWORD size)
{
#ifdef DEBUG_MALLOC
MEM_NODE sNode;
void *Tmp;
ASSERT( size, "blkPointerValid: cannot check a pointer with zero size" );
if (pData == NULL)
{
return FALSE;
}
// Create a dummy node for the search
// This is only looked at by memBlockCmp so only need to set the object and size
sNode.pObj = ((UBYTE *)pData) - sizeof(MEM_NODE) - SAFETY_ZONE_SIZE;
sNode.size = size;
// See if the block is in the treap
Tmp = treapFindRec((TREAP_NODE *)psHeap->psMemTreap, (void*)&sNode, memBlockCmp);
if (Tmp != NULL)
// if (treapFindRec((TREAP_NODE *)psHeap->psMemTreap, (void*)&sNode, memBlockCmp))
{
return TRUE;
}
return FALSE;
#else
psHeap = psHeap;
pData = pData;
size = size;
return TRUE;
#endif
}
// check if a pointer is valid in any currently allocated block
BOOL blkPointerValidAll(void *pData, SDWORD size)
{
#ifdef DEBUG_MALLOC
BLOCK_HEAP *psCurr;
for(psCurr=psBlockList; psCurr; psCurr=psCurr->psNext)
{
if (blkPointerValid(psCurr, pData, size))
{
return TRUE;
}
}
return FALSE;
#else
pData = pData;
size = size;
return TRUE;
#endif
}
BLOCK_HEAP *psSuspendedHeap=NULL;
// suspend the current block ... all allocations pass though to system memory allocation
// if a block is already suspended then an assertion will occur.
void blockSuspendUsage(void)
{
ASSERT( psSuspendedHeap==NULL, "a memory block is already suspended" );
psSuspendedHeap = memGetBlockHeap();
memSetBlockHeap(NULL);
}
// restore the current block - if there is one
void blockUnsuspendUsage(void)
{
memSetBlockHeap(psSuspendedHeap);
psSuspendedHeap=NULL;
}

View File

@ -1,160 +0,0 @@
/*
This file is part of Warzone 2100.
Copyright (C) 1999-2004 Eidos Interactive
Copyright (C) 2005-2007 Warzone Resurrection Project
Warzone 2100 is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Warzone 2100 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Warzone 2100; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*! \file block.h
* \brief Routines to allocate memory from one large block.
*
* Any memory allocated is only available to be reallocated after
* the whole block has been reset.
*/
#ifndef _block_h
#define _block_h
#include "mem.h"
#include "memint.h"
/**********************************************************************************/
/* type definitions */
typedef struct _block_heap_mem
{
SDWORD size; // size of block
UBYTE *pFree; // pointer to the start of the free memory section
UBYTE *pMem; // pointer to the base of the memory block
UBYTE *pLastAllocated; // The start of the last allocated block (so that it can be freed by blkSpecialFree
struct _block_heap_mem *psNext;
} BLOCK_HEAP_MEM;
typedef struct _block_heap
{
SDWORD init, ext; // initial and extension block sizes
BLOCK_HEAP_MEM *psBlocks;
#ifdef DEBUG_MALLOC
const char *pFileName;
SDWORD line;
MEM_NODE *psMemTreap; // treap of the memory blocks
BOOL free; // whether free has been called for this block
const char *pFreeFile; // where the last free was called from
SDWORD freeLine;
UDWORD TotalAllocated; // Total amount of bytes used in the block (sum of all alloc's)
#endif
struct _block_heap *psNext;
} BLOCK_HEAP;
/**********************************************************************************/
/* function prototypes */
// initialise the block system
extern BOOL blkInitialise(void);
// shutdown the block system
extern void blkShutDown(void);
// Create a new block heap
extern BOOL blkCreate(BLOCK_HEAP **ppsHeap, SDWORD init, SDWORD ext);
// Release a block heap
extern void blkDestroy(BLOCK_HEAP *psHeap);
// Allocate some memory from a block heap
extern void *blkAlloc(BLOCK_HEAP *psHeap, SDWORD size);
// return a chunk of memory to the block
// this only does anything whith DEBUG_BLOCK defined
extern void blkFree(BLOCK_HEAP *psHeap, void *pMemToFree);
// Reset a block heap
extern void blkReset(BLOCK_HEAP *psHeap);
// Find which block a pointer is from if any
extern BLOCK_HEAP *blkFind(void *pPtr);
// check if a pointer is valid in a block
extern BOOL blkPointerValid(BLOCK_HEAP *psHeap, void *pData, SDWORD size);
// check if a pointer is valid in any currently allocated block
extern BOOL blkPointerValidAll(void *pData, SDWORD size);
// Note the call position for a blkAlloc or blkFree
extern void blkCallPos(const char *pFileName, SDWORD line);
void blkPrintDetails(BLOCK_HEAP *psHeap);
void blkReport(void);
BOOL blkSpecialFree(BLOCK_HEAP *psHeap, void *Ptr);
void blockSuspendUsage(void);
void blockUnsuspendUsage(void);
/**********************************************************************************/
/* macro definitions */
#ifdef DEBUG_MALLOC
#define BLOCK_CREATE(ppsHeap, init, ext) \
(blkCallPos(__FILE__, __LINE__), \
blkCreate((ppsHeap), (init), (ext)))
#define BLOCK_DESTROY(psHeap) \
blkCallPos(__FILE__, __LINE__); \
blkDestroy(psHeap)
#define BLOCK_ALLOC(psHeap, size) \
(blkCallPos(__FILE__, __LINE__), \
blkAlloc(psHeap, size))
#define BLOCK_FREE(psHeap, pMemToFree) \
blkCallPos(__FILE__, __LINE__); \
blkFree(psHeap, pMemToFree)
#define BLOCK_RESET(psHeap) \
blkCallPos(__FILE__, __LINE__); \
blkReset(psHeap)
#define BLOCK_PTRVALID(psHeap, pData, size) \
blkPointerValid(psHeap, pData, size)
#else
#define BLOCK_CREATE(ppsHeap, init, ext) \
blkCreate((ppsHeap), (init), (ext))
#define BLOCK_DESTROY(psHeap) \
blkDestroy(psHeap)
#define BLOCK_ALLOC(psHeap, size) \
blkAlloc(psHeap, size)
#define BLOCK_FREE(psHeap, pMemToFree) \
blkFree(psHeap, pMemToFree)
#define BLOCK_RESET(psHeap) \
blkReset(psHeap)
#define BLOCK_PTRVALID(psHeap, pData, size) \
(TRUE)
#endif
#endif

View File

@ -405,12 +405,6 @@ void frameShutDown(void)
// Shutdown the resource stuff
resShutDown();
// shutdown the block memory heap
blkShutDown();
/* Shutdown the memory system */
memShutDown();
}
/***************************************************************************

View File

@ -34,7 +34,6 @@
#include "heap.h"
#include "treap.h"
#include "block.h"
#include "fractions.h"
#include "trig.h"

View File

@ -117,12 +117,10 @@ void resSetBaseDir(char *pResDir)
/* Parse the res file */
BOOL resLoad(const char *pResFile, SDWORD blockID,
char *pLoadBuffer, SDWORD bufferSize,
BLOCK_HEAP *psMemHeap)
char *pLoadBuffer, SDWORD bufferSize)
{
char *pBuffer;
UDWORD size;
BLOCK_HEAP *psOldHeap;
strcpy(aCurrResDir, aResDir);
@ -135,19 +133,12 @@ BOOL resLoad(const char *pResFile, SDWORD blockID,
debug(LOG_WZ, "resLoad: loading %s", pResFile);
// make sure the WRF doesn't get loaded into a block heap
psOldHeap = memGetBlockHeap();
memSetBlockHeap(NULL);
// Load the RES file; allocate memory for a wrf, and load it
if (!loadFile(pResFile, &pBuffer, &size)) {
debug(LOG_ERROR, "resLoad: failed to load %s", pResFile);
return FALSE;
}
// now set the memory system to use the block heap
memSetBlockHeap(psMemHeap);
// and parse it
resSetInputBuffer(pBuffer, size);
if (res_parse() != 0) {
@ -155,9 +146,6 @@ BOOL resLoad(const char *pResFile, SDWORD blockID,
return FALSE;
}
// reset the memory system
memSetBlockHeap(psOldHeap);
FREE(pBuffer);
return TRUE;
@ -357,16 +345,12 @@ static BOOL RetreiveResourceFile(char *ResourceName, RESOURCEFILE **NewResource)
return(TRUE);
}
blockSuspendUsage();
// This is needed for files that do not fit in the WDG cache ... (VAB file for example)
if (!loadFile(ResourceName, &pBuffer, &size))
{
return FALSE;
}
blockUnsuspendUsage();
ResData->type=RESFILETYPE_LOADED;
ResData->size=size;
ResData->pBuffer=pBuffer;

View File

@ -97,8 +97,7 @@ extern void resSetBaseDir(char *pResDir);
/* Parse the res file */
struct _block_heap;
BOOL resLoad(const char *pResFile, SDWORD blockID,
char *pLoadBuffer, SDWORD bufferSize,
struct _block_heap *psMemHeap);
char *pLoadBuffer, SDWORD bufferSize);
/* Release all the resources currently loaded and the resource load functions */
extern void resReleaseAll(void);

View File

@ -37,7 +37,6 @@
#include "heap.h"
#include "treap.h"
#include "treapint.h"
#include "block.h"
// Control whether a heap usage report is printed out when a heap is destroyed
#define HEAP_USAGE_REPORT FALSE
@ -185,7 +184,6 @@ BOOL heapCreate(OBJ_HEAP **ppsHeap, UDWORD size, UDWORD init, UDWORD ext)
(*ppsHeap)->initAlloc = init;
(*ppsHeap)->extAlloc = ext;
(*ppsHeap)->psExt = NULL;
(*ppsHeap)->psBlkHeap = memGetBlockHeap();
#if DEBUG_HEAP
(*ppsHeap)->maxUsage = 0;
(*ppsHeap)->currUsage = 0;
@ -251,7 +249,6 @@ BOOL heapAlloc(OBJ_HEAP *psHeap, void **ppObject)
UDWORD i;
FREE_OBJECT *psCurr = NULL;
UBYTE *pBase;
BLOCK_HEAP *psCurrBlk;
#if DEBUG_HEAP
HEAP_OBJHDR *psHdr;
FREE_OBJECT *psFree;
@ -273,10 +270,6 @@ BOOL heapAlloc(OBJ_HEAP *psHeap, void **ppObject)
return FALSE;
}
/* No objects left - need to add a heap extension */
psCurrBlk = memGetBlockHeap();
memSetBlockHeap(psHeap->psBlkHeap);
#ifdef REALLY_DEBUG_HEAP
debug(LOG_MEMORY, "heapAlloc: Heap %s, line %d extended. Max use: %d\n", psHeap->pFile, psHeap->line, psHeap->maxUsage);
#endif
@ -296,7 +289,6 @@ BOOL heapAlloc(OBJ_HEAP *psHeap, void **ppObject)
FREE(psNew);
return FALSE;
}
memSetBlockHeap(psCurrBlk);
#if DEBUG_HEAP
/* Initialise the memory to check for overwrites */

View File

@ -63,8 +63,6 @@ typedef struct _obj_heap
UDWORD initAlloc; // The initial number of objects allocated
UDWORD extAlloc; // The number of objects to allocate after the initial
// allocation is used up
struct _block_heap *psBlkHeap; // which block heap (if any) this object heap was allocated from
FREE_OBJECT *psFree; // The currently free objects
UBYTE *pMemory; // The main memory heap

View File

@ -1,529 +0,0 @@
/*
This file is part of Warzone 2100.
Copyright (C) 1999-2004 Eidos Interactive
Copyright (C) 2005-2007 Warzone Resurrection Project
Warzone 2100 is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Warzone 2100 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Warzone 2100; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* mem.c
*
* Replacements for malloc and free to track memory usage.
*
* Also allows pointer validity checking.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
/* Allow frame header files to be singly included */
#define FRAME_LIB_INCLUDE
#include "types.h"
#include "debug.h"
#include "mem.h"
#include "heap.h"
#include "treap.h"
#include "treapint.h"
#include "memint.h"
#include "block.h"
#include <assert.h>
/* Whether allocated memory is initialised to a value and whether the memory
* is trashed before it is freed.
* This is done automatically by Visual C's memory routines.
*/
// No piece of code should ever depend upon memory being initialized (RAII: Resource Acquisition Is Initialization)
// Therefore I humbly comment this line out, which might very well result in
// buggy code becoming even buggier (just search this file for the next
// instance of MEMORY_SET). -- Giel
//#define MEMORY_SET TRUE
/* Number of bytes after which memory amounts are displayed in Kb */
#define SHOW_KB_LIMIT (0x400)
/* What functions to use for the real malloc and free */
#define RMALLOC malloc
#define RFREE free
/* The root of the memory treap */
static MEM_NODE *psMemRoot = NULL;
/* The current block heap to use instead of MALLOC */
static BLOCK_HEAP *psCurrBlockHeap;
/* Initialise the memory system */
BOOL memInitialise(void)
{
if (psMemRoot != NULL)
{
debug(LOG_MEMORY, "memInitialise: *** WARNING *** : memory still allocated??");
}
psMemRoot = NULL;
psCurrBlockHeap = NULL;
return TRUE;
}
/* Release the memory treap */
static void memTreapDestroy(TREAP_NODE *psRoot)
{
if (psRoot)
{
// Destroy the sub trees
memTreapDestroy(psRoot->psLeft);
memTreapDestroy(psRoot->psRight);
// Free the root
RFREE(psRoot);
}
}
/* Shutdown the memory system */
void memShutDown(void)
{
// Report any memory still allocated
#ifdef REALLY_DEBUG_MALLOC
memMemoryReport();
#endif
// Free up the allocated memory
memTreapDestroy((TREAP_NODE *)psMemRoot);
}
/* Set a block heap to use for all memory allocation rather than standard malloc/free */
void memSetBlockHeap(BLOCK_HEAP *psHeap)
{
psCurrBlockHeap = psHeap;
}
/* Get the current block heap */
BLOCK_HEAP *memGetBlockHeap(void)
{
return psCurrBlockHeap;
}
/* compare two memory blocks
* NOTE: key1 is always the block passed into the treap code
* and therefore not necessarily to be trusted
*/
SDWORD memBlockCmp(void *key1, void *key2)
{
UBYTE *start1, *start2, *end1, *end2;
// Calculate the edges of the memory blocks
start1 = (UBYTE *)((char *)(((MEM_NODE *)key1)->pObj) + sizeof(MEM_NODE) + SAFETY_ZONE_SIZE);
start2 = (UBYTE *)((char *)(((MEM_NODE *)key2)->pObj) + sizeof(MEM_NODE) + SAFETY_ZONE_SIZE);
end1 = start1 + ((MEM_NODE *)key1)->size;
end2 = start2 + ((MEM_NODE *)key2)->size;
// see if one block is inside another
if ((start1 >= start2 && end1 <= end2))// || // block 1 inside block 2
// (start2 >= start1 && end2 <= end1)) // block 2 inside block 1
{
return 0;
}
else if (start1 < start2)
{
// less than
return -1;
}
// greater than
return 1;
}
#ifdef DEBUG_MALLOC
/* Replacement for malloc that records where the memory was requested.
* All allocated memory is initialised to INITIALISE_BYTE
* A buffer is also allocated at the top and bottom of the memory to check for
* overwrites.
*/
void *memMalloc(const char *pFileName, SDWORD LineNumber, size_t Size)
{
void *pMemBase;
MEM_NODE *psNode;
ASSERT( (pFileName != NULL), "No filename passed to mem_Malloc" );
ASSERT( Size != 0, "Cannot allocate 0 bytes of memory." );
if (psCurrBlockHeap != NULL)
{
// use a block heap rather than normal malloc
blkCallPos(pFileName, LineNumber);
return blkAlloc(psCurrBlockHeap, Size);
}
pMemBase = RMALLOC( Size + sizeof(MEM_NODE) + 2 * SAFETY_ZONE_SIZE );
if (!pMemBase)
{
ASSERT( FALSE, "Warning: malloc returning NULL - [%s - %d]",pFileName,LineNumber );
debug( LOG_NEVER, "[%s - %d] %zu bytes\n", pFileName, LineNumber, Size );
return NULL;
}
/* Got the main bit of memory - set up the node entry */
// This part of code adds information about which file requested
// on what line what amount of memory.
psNode = (MEM_NODE *)pMemBase;
psNode->pFile = (char *)RMALLOC( strlen(pFileName)+1 );
if (!psNode->pFile)
{
RFREE(pMemBase);
debug( LOG_NEVER, "Warning: malloc returning NULL" );
return NULL;
}
strcpy((char *)psNode->pFile, pFileName);
psNode->line = LineNumber;
psNode->size = Size;
/* Store the new entry in the memory treap */
psNode->priority = (UDWORD)rand();
psNode->key = (void*)psNode;
psNode->pObj = psNode;
psNode->psLeft = NULL;
psNode->psRight = NULL;
treapAddNode((TREAP_NODE **)&psMemRoot, (TREAP_NODE *)psNode, memBlockCmp);
/* Now initialise the memory - try to catch unitialised variables */
// Fill up the safety zone left of (or before) and right of (or after)
// the requested memory page, with SAFETY_ZONE_BYTE to be able to
// catch writing out of bounds.
memset((UBYTE *)(pMemBase) + sizeof(MEM_NODE), // Left or before the requested memchunk
SAFETY_ZONE_BYTE, SAFETY_ZONE_SIZE);
memset((UBYTE *)(pMemBase) + sizeof(MEM_NODE) + SAFETY_ZONE_SIZE + Size, // Right or after chunck
SAFETY_ZONE_BYTE, SAFETY_ZONE_SIZE);
#ifdef MEMORY_SET
// Initialize memory before returning its address (WRONG!!! The code that requests mem should ensure initialization)
memset((UBYTE *)(pMemBase) + sizeof(MEM_NODE) + SAFETY_ZONE_SIZE,
INITIALISE_BYTE, Size);
#endif
return ((UBYTE *)(pMemBase) + sizeof(MEM_NODE) + SAFETY_ZONE_SIZE);
}
#endif
#ifndef DEBUG_MALLOC
/* Replacement for malloc for release builds. */
void *memMallocRelease(size_t Size)
{
if (psCurrBlockHeap != NULL)
{
// use a block heap rather than normal malloc
return blkAlloc(psCurrBlockHeap, Size);
}
return RMALLOC(Size);
}
#endif
#ifdef DEBUG_MALLOC
/* Replacement for free
*
* Checks whether the pointer is valid before freeing it.
* If the pointer is invalid, it asserts.
* The buffer zones around the allocated memory are also checked for
* overwrites.
* All memory is reset to FREE_BYTE before freeing to avoid using
* freed memory.
*/
void memFree(const char *pFileName, SDWORD LineNumber, void *pMemToFree)
{
MEM_NODE sNode, *psDeleted;
UWORD i, InvalidBottom, InvalidTop;
UBYTE *pMemBase;
BLOCK_HEAP *psBlock;
ASSERT( (pFileName != NULL), "No filename passed to memFree" );
ASSERT( (pMemToFree != NULL), "Attempt to free NULL pointer, called by:\n"
"File: %s\nLine: %d\n", pFileName, LineNumber );
if (pMemToFree == NULL) return;
// see if the pointer was allocated in a block
psBlock = blkFind(pMemToFree);
if (psBlock != NULL)
{
// use a block heap rather than normal free
blkCallPos(pFileName, LineNumber);
blkFree(psBlock, pMemToFree);
return;
}
// Create a dummy node for the search
// This is only looked at by memBlockCmp so only need to set the object and size
sNode.pObj = ((UBYTE *)pMemToFree) - sizeof(MEM_NODE) - SAFETY_ZONE_SIZE;
sNode.size = 1;
/* Get the node for the memory block */
psDeleted = (MEM_NODE *)treapDelRec((TREAP_NODE **)&psMemRoot,
(void*)&sNode, memBlockCmp);
ASSERT( psDeleted != NULL,
"Invalid pointer passed to memFree by:\n"
"File: %s\nLine: %d\n\n"
"Attempt to free already freed pointer?",
pFileName, LineNumber );
if (psDeleted)
{
/* The pointer is valid, check the buffer zones */
pMemBase = (UBYTE *)(pMemToFree) - SAFETY_ZONE_SIZE;
InvalidBottom = InvalidTop = 0;
// Check wether out of bound writes have occured since memMalloc()
for(i=0; i<SAFETY_ZONE_SIZE; i++)
{
if (pMemBase[i] != SAFETY_ZONE_BYTE)
{
InvalidBottom++;
}
if (pMemBase[i + psDeleted->size + SAFETY_ZONE_SIZE] != SAFETY_ZONE_BYTE)
{
InvalidTop++;
}
}
ASSERT( !InvalidBottom && !InvalidTop,
"Safety zone on memory overwritten.\n"
"%d Invalid bytes (of %d) found below memory buffer.\n"
"%d Invalid bytes (of %d) found above memory buffer.\n\n"
"Memory allocated by:\nFile: %s\nLine: %d\n"
"Memory freed by:\nFile: %s\nLine: %d\n",
InvalidBottom, SAFETY_ZONE_SIZE, InvalidTop, SAFETY_ZONE_SIZE,
psDeleted->pFile, psDeleted->line,
pFileName, LineNumber );
/* Now free the memory */
RFREE((char *)psDeleted->pFile);
RFREE(psDeleted);
}
}
#endif
#ifndef DEBUG_MALLOC
/* Replacement for Free for release builds */
void memFreeRelease(void *pMemToFree)
{
// see if the pointer was allocated in a block
BLOCK_HEAP* psBlock = blkFind(pMemToFree);
if (psBlock != NULL)
{
// use a block heap rather than normal free
blkFree(psBlock, pMemToFree);
return;
}
RFREE(pMemToFree);
}
#endif
/* Checks whether the memory buffer pointed to by pPtr of size Size
* is contained in any of the memory blocks allocated.
*/
BOOL memPointerValid(void *pPtr, size_t size)
{
MEM_NODE sNode;
ASSERT( size, "memPointerValid: cannot check a pointer with zero size" );
if (pPtr == NULL)
{
return FALSE;
}
// Create a dummy node for the search
// This is only looked at by memBlockCmp so only need to set the object and size
sNode.pObj = ((UBYTE *)pPtr) - sizeof(MEM_NODE) - SAFETY_ZONE_SIZE;
sNode.size = size;
// See if the block is in the treap
if (treapFindRec((TREAP_NODE *)psMemRoot, (void*)&sNode, memBlockCmp))
{
return TRUE;
}
// check the block heaps as well (if the code is there)
#ifdef DEBUG_MALLOC
return blkPointerValidAll(pPtr, size);
#else
return FALSE;
#endif
}
#ifdef REALLY_DEBUG_MALLOC
/* Recursive function to print out the list of memory blocks */
SDWORD memRecReport(MEM_NODE *psRoot)
{
if (psRoot)
{
if (psRoot->size < SHOW_KB_LIMIT)
{
debug(LOG_MEMORY, "memRecReport for %s line %d: \t%d bytes",
psRoot->pFile, psRoot->line, psRoot->size);
}
else
{
debug(LOG_MEMORY, "memRecReport for %s line %d: \t%d kilobytes",
psRoot->pFile, psRoot->line, (int) psRoot->size / 1024);
}
return memRecReport((MEM_NODE *)psRoot->psLeft) +
memRecReport((MEM_NODE *)psRoot->psRight) +
psRoot->size;
}
return 0;
}
#endif
#ifdef DEBUG_MALLOC
#define MAXMODULES (32)
typedef struct
{
char pFile[128];
int Count;
int Total;
} MEMMOD;
static MEMMOD MemModuleInfo[MAXMODULES];
static UDWORD MemTotalEntries;
static UDWORD MemTotalModules;
static UDWORD MemTotalAllocated;
#endif
#ifdef DEBUG_MALLOC
/* Recursive function to total up the amount of mem allocated */
static void memSummary(MEM_NODE *psRoot)
{
// bsort
if (psRoot)
{
int i;
BOOL FoundModule;
MemTotalEntries++;
MemTotalAllocated+=psRoot->size;
FoundModule=FALSE;
for (i=0;i<(SDWORD)MemTotalModules;i++)
{
if (strcmp(psRoot->pFile,MemModuleInfo[i].pFile)==0)
{
MemModuleInfo[i].Count++;
MemModuleInfo[i].Total+=psRoot->size;
FoundModule=TRUE;
}
}
if (FoundModule==FALSE)
{
if (MemTotalModules <MAXMODULES)
{
strcpy(MemModuleInfo[MemTotalModules].pFile,psRoot->pFile);
MemModuleInfo[MemTotalModules].Count=1;
MemModuleInfo[MemTotalModules].Total=psRoot->size;
MemTotalModules++;
}
}
memSummary((MEM_NODE *)psRoot->psLeft);
memSummary((MEM_NODE *)psRoot->psRight);
}
return ;
}
#endif
void memMemoryDump(MEM_NODE *Node)
{
#ifdef DEBUG_MALLOC
int i;
MemTotalEntries=0;
MemTotalModules=0;
MemTotalAllocated=0;
memSummary(Node);
debug(LOG_MEMORY, "Memory Summary: %d bytes allocated in %d handy size chunks", MemTotalAllocated, MemTotalEntries);
for (i=0;i<(SDWORD)MemTotalModules;i++)
{
debug(LOG_MEMORY, "memMemoryDump: %d) [%s] %d allocations totalling %d bytes",
i, MemModuleInfo[i].pFile, MemModuleInfo[i].Count, MemModuleInfo[i].Total);
}
#endif
}
#ifdef REALLY_DEBUG_MALLOC
/* Report on currently allocated memory.
*/
void memMemoryReport(void)
{
SDWORD TotMem;
if (!psMemRoot)
{
debug(LOG_MEMORY, "memMemoryReport: No memory allocated");
}
else
{
TotMem = memRecReport(psMemRoot);
if (TotMem < SHOW_KB_LIMIT)
{
debug(LOG_MEMORY, "memMemoryReport: Total memory allocated is %d bytes", TotMem);
}
else
{
debug(LOG_MEMORY, "memMemoryReport: Total memory allocated is %d kilobytes", (int) TotMem / 1024);
}
}
}
#endif
/* Display the memory treap */
void memDisplayTreap(void)
{
#ifdef DEBUG_MALLOC
debug(LOG_MEMORY, "Memory Allocation Treap:");
treapDisplayRec((TREAP_NODE *)psMemRoot, 0);
#endif
}

View File

@ -25,82 +25,9 @@
#define _mem_h
#include <stdlib.h>
#include "types.h"
#include "debug.h"
/* DEBUG_MALLOC == TRUE uses debugging malloc and free
DEBUG_MALLOC == FALSE uses normal malloc and free */
#ifdef DEBUG
#define DEBUG_MALLOC TRUE
#define DEBUG_HEAP TRUE
/* Uncomment below for even more debug spam */
#undef REALLY_DEBUG_HEAP
#undef REALLY_DEBUG_MALLOC
#else
#undef DEBUG_MALLOC
#undef DEBUG_HEAP
#define MALLOC(size) malloc(size)
#define FREE(ptr) do { free(ptr); ptr = NULL; } while(0)
#define PTRVALID(ptr, size) (ptr != NULL)
#endif
/* Function Prototypes */
/* Initialise the memory system */
BOOL memInitialise(void);
/* Shutdown the memory system */
void memShutDown(void);
/* Set a block heap to use for all memory allocation rather than standard malloc/free */
struct _block_heap;
void memSetBlockHeap(struct _block_heap *psHeap);
/* Get the current block heap */
struct _block_heap *memGetBlockHeap(void);
/* malloc and free replacements */
#ifdef DEBUG_MALLOC
void *memMalloc(const char *pFileName, SDWORD LineNumber, size_t Size);
void memFree(const char *pFileName, SDWORD LineNumber, void *pMemToFree);
#define MALLOC(size) memMalloc(__FILE__, __LINE__, size)
#define FREE(ptr) do { memFree(__FILE__, __LINE__, ptr); ptr = NULL; } while(0)
#else // !DEBUG_MALLOC
void *memMallocRelease(size_t Size);
void memFreeRelease(void *pMemToFree);
#define MALLOC(size) memMallocRelease(size)
#define FREE(ptr) do { memFreeRelease(ptr); ptr = NULL; } while(0)
#endif // DEBUG_MALLOC
/* Check a pointer refers to a valid block of memory */
BOOL memPointerValid(void *pPtr, size_t Size);
#ifdef REALLY_DEBUG_MALLOC
/* Report on currently allocated memory */
void memMemoryReport(void);
/* Recursive function to print out the list of memory blocks */
extern SDWORD memRecReport(MEM_NODE *psRoot);
#endif
/* Display the memory treap */
void memDisplayTreap(void);
#ifdef DEBUG_MALLOC
#ifndef NO_PTRVALID
#define PTRVALID(ptr, size) memPointerValid(ptr, size)
#else
#define PTRVALID(ptr, size) (((ptr)==NULL)?FALSE:TRUE)
#endif
#else // !DEBUG_MALLOC
#define PTRVALID(ptr, size) (TRUE)
#endif // DEBUG_MALLOC
#endif // _mem_h_

View File

@ -1,49 +0,0 @@
/*
This file is part of Warzone 2100.
Copyright (C) 1999-2004 Eidos Interactive
Copyright (C) 2005-2007 Warzone Resurrection Project
Warzone 2100 is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Warzone 2100 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Warzone 2100; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*! \file memint.h
* \brief Internal framework definitions for the memory system.
*/
#ifndef _memint_h
#define _memint_h
/* The size of saftey buffer to leave before and after any malloc'ed memory.
Can use this to check writing over end of buffers */
#define SAFETY_ZONE_SIZE (32)
/* The character used to initialise malloc'ed memory, or to trash memory before
freeing it */
#define SAFETY_ZONE_BYTE (0xac)
#define INITIALISE_BYTE (0xcd)
#define FREE_BYTE (0xdd)
// memory block header for the treap code
typedef struct _mem_node
{
TREAP_NODE_BASE; // The treap data to store the node
TREAP_NODE_DEBUG; // The debug info for the node (file, line).
UDWORD size; // The memory block size
} MEM_NODE;
/* compare two memory blocks */
extern SDWORD memBlockCmp(void *key1, void *key2);
#endif

View File

@ -130,10 +130,10 @@ animObj_HashFreeElementFunc( void * psElement )
{
#ifdef DEBUG
ANIM_OBJECT *psObj = (ANIM_OBJECT *) psElement;
#endif
ASSERT( PTRVALID(psObj, sizeof(ANIM_OBJECT)),
"animObj_HashFreeElementFunc: object pointer invalid\n" );
#endif
}
/***************************************************************************/

View File

@ -60,9 +60,6 @@ static STACK_CHUNK *psCurrChunk=NULL;
/* The current free entry on the current stack chunk */
static UDWORD currEntry=0;
/* The block heap the stack was created in */
static BLOCK_HEAP *psStackBlock;
/* Get rid of the top value without returning it */
static inline BOOL stackRemoveTop(void);
@ -77,8 +74,6 @@ BOOL stackEmpty(void)
/* Allocate a new chunk for the stack */
static BOOL stackNewChunk(UDWORD size)
{
BLOCK_HEAP *psHeap;
/* see if a chunk has already been allocated */
if (psCurrChunk->psNext != NULL)
{
@ -87,9 +82,6 @@ static BOOL stackNewChunk(UDWORD size)
}
else
{
psHeap = memGetBlockHeap();
memSetBlockHeap(psStackBlock);
/* Allocate a new chunk */
psCurrChunk->psNext = (STACK_CHUNK *)MALLOC(sizeof(STACK_CHUNK));
if (!psCurrChunk->psNext)
@ -112,8 +104,6 @@ static BOOL stackNewChunk(UDWORD size)
/* initialize pointers
note: 0 means type == VAL_BOOL */
memset(psCurrChunk->psNext->aVals, 0, sizeof(INTERP_VAL) * size);
memSetBlockHeap(psHeap);
}
return TRUE;
@ -983,8 +973,6 @@ BOOL castTop(INTERP_TYPE neededType)
/* Initialise the stack */
BOOL stackInitialise(void)
{
psStackBlock = memGetBlockHeap();
psStackBase = (STACK_CHUNK *)MALLOC(sizeof(STACK_CHUNK));
if (psStackBase == NULL)
{

View File

@ -1084,16 +1084,11 @@ static void dataStrResRelease(void *pData)
static BOOL dataScriptLoad(char *pBuffer, UDWORD size, void **ppData)
{
SCRIPT_CODE *psProg=NULL;
BLOCK_HEAP *psHeap;
BOOL printHack = FALSE;
calcCheatHash(pBuffer,size,CHEAT_SCRIPT);
debug(LOG_WZ, "COMPILING SCRIPT ...%s",GetLastResourceFilename());
// make sure the memory system uses normal malloc for a compile
psHeap = memGetBlockHeap();
memSetBlockHeap(NULL);
scr_lineno = 1;
if (!scriptCompile(pBuffer, size, &psProg, SCRIPTTYPE)) // see script.h
@ -1101,7 +1096,6 @@ static BOOL dataScriptLoad(char *pBuffer, UDWORD size, void **ppData)
debug(LOG_ERROR, "Script %s did not compile", GetLastResourceFilename());
return FALSE;
}
memSetBlockHeap(psHeap);
if (printHack)
{

View File

@ -618,22 +618,22 @@ BOOL runMultiPlayerMenu(void)
{
initLoadingScreen( TRUE );
/* if (!resLoad("wrf/forcedit.wrf", 500,
DisplayBuffer, displayBufferSize,
psGameHeap)) //need the object heaps to have been set up before loading
DisplayBuffer, displayBufferSize))
//need the object heaps to have been set up before loading
{
return FALSE;
}
*/
if (!resLoad("wrf/piestats.wrf", 501,
DisplayBuffer, displayBufferSize,
psGameHeap)) //need the object heaps to have been set up before loading
DisplayBuffer, displayBufferSize))
//need the object heaps to have been set up before loading
{
return FALSE;
}
if (!resLoad("wrf/forcedit2.wrf", 502,
DisplayBuffer, displayBufferSize,
psGameHeap)) //need the object heaps to have been set up before loading
DisplayBuffer, displayBufferSize))
//need the object heaps to have been set up before loading
{
return FALSE;
}

View File

@ -1783,12 +1783,9 @@ BOOL loadGame(char *pGameToLoad, BOOL keepObjects, BOOL freeMem, BOOL UserSaveGa
}
if(bMultiPlayer)
{
blockSuspendUsage();
loadMultiStats(saveGameData.sPName,&playerStats); // stats stuff
setMultiStats(NetPlay.dpidPlayer,playerStats,FALSE);
setMultiStats(NetPlay.dpidPlayer,playerStats,TRUE);
blockUnsuspendUsage();
}
}
@ -1929,7 +1926,6 @@ BOOL loadGame(char *pGameToLoad, BOOL keepObjects, BOOL freeMem, BOOL UserSaveGa
if (saveGameOnMission && UserSaveGame)
{
LOADBARCALLBACK(); // loadingScreenCallback();
memSetBlockHeap(psMapHeap);//should be set
//the scroll limits for the mission map have already been written
if (saveGameVersion >= VERSION_29)
@ -1975,9 +1971,6 @@ BOOL loadGame(char *pGameToLoad, BOOL keepObjects, BOOL freeMem, BOOL UserSaveGa
}
}
//set mission heap
memSetBlockHeap(psMissionHeap);
// reload the objects that were in the mission list
//except droids these are always loaded directly to the mission.apsDroidList
/*
@ -2868,14 +2861,10 @@ error:
BOOL saveGame(char *aFileName, SDWORD saveType)
{
UDWORD fileExtension;
BLOCK_HEAP *psHeap;
DROID *psDroid, *psNext;
debug(LOG_WZ, "saveGame: %s", aFileName);
psHeap = memGetBlockHeap();
memSetBlockHeap(NULL);
fileExtension = strlen(aFileName) - 3;
gameTimeStop();
@ -3195,15 +3184,11 @@ BOOL saveGame(char *aFileName, SDWORD saveType)
swapMissionPointers();
}
memSetBlockHeap(psHeap);
/* Start the game clock */
gameTimeStart();
return TRUE;
error:
memSetBlockHeap(psHeap);
/* Start the game clock */
gameTimeStart();
@ -4058,11 +4043,9 @@ BOOL gameLoadV(char *pFileData, UDWORD filesize, UDWORD version)
}
if(bMultiPlayer)
{
blockSuspendUsage();
loadMultiStats(psSaveGame->sPName,&playerStats); // stats stuff
setMultiStats(NetPlay.dpidPlayer,playerStats,FALSE);
setMultiStats(NetPlay.dpidPlayer,playerStats,TRUE);
blockUnsuspendUsage();
}
}

View File

@ -108,31 +108,6 @@ extern char * global_mods[];
extern char * campaign_mods[];
extern char * multiplay_mods[];
// the sizes for the game block heap
#define GAMEBLOCK_INIT (2*1024*1024)
#define GAMEBLOCK_EXT (1024*1024)
// the sizes for the campaign map block heap
#define MAPBLOCK_INIT (1024*1024)
#define MAPBLOCK_EXT (32*1024)
// the sizes for the mission block heap
#define MISSIONBLOCK_INIT (2*1024*1024)
#define MISSIONBLOCK_EXT (512*1024)
// the block heap for the game data
BLOCK_HEAP *psGameHeap;
// the block heap for the campaign map
BLOCK_HEAP *psMapHeap;
// the block heap for the pre WRF data
BLOCK_HEAP *psMissionHeap;
// the block id for the game data
#define GAME_BLOCKID 100
// Ascii to font image id lookup table for frontend font.
//
@ -1031,24 +1006,6 @@ BOOL systemInitialise(void)
return FALSE;
}
// create a block heap for the game data
if (!BLOCK_CREATE(&psGameHeap, GAMEBLOCK_INIT, GAMEBLOCK_EXT))
{
return FALSE;
}
// create a block heap for the campaign map
if (!BLOCK_CREATE(&psMapHeap, MAPBLOCK_INIT, MAPBLOCK_EXT))
{
return FALSE;
}
// create a block heap for the pre WRF data
if (!BLOCK_CREATE(&psMissionHeap, MISSIONBLOCK_INIT, MISSIONBLOCK_EXT))
{
return FALSE;
}
#ifdef ARROWS
arrowInit();
#endif
@ -1084,12 +1041,6 @@ BOOL systemShutdown(void)
free( data_dirs );
*/
// release the block heaps
BLOCK_DESTROY(psGameHeap);
BLOCK_DESTROY(psMapHeap);
BLOCK_DESTROY(psMissionHeap);
if (!bDisableLobby && !multiShutdown()) // ajl. init net stuff
{
return FALSE;
@ -1161,9 +1112,6 @@ BOOL frontendInitialise(const char *ResourceFile)
{
debug(LOG_MAIN, "Initialising frontend : %s", ResourceFile);
// allocate memory from the pre data heap
memSetBlockHeap(psGameHeap);
if(!InitialiseGlobals()) // Initialise all globals and statics everywhere.
{
return FALSE;
@ -1202,10 +1150,9 @@ BOOL frontendInitialise(const char *ResourceFile)
}
debug(LOG_MAIN, "frontEndInitialise: loading resource file .....");
if (!resLoad(ResourceFile, 0,
DisplayBuffer, displayBufferSize,
psGameHeap)) //need the object heaps to have been set up before loading in the save game
if (!resLoad(ResourceFile, 0, DisplayBuffer, displayBufferSize))
{
//need the object heaps to have been set up before loading in the save game
return FALSE;
}
@ -1244,8 +1191,6 @@ BOOL frontendInitialise(const char *ResourceFile)
SetFormAudioIDs(-1,ID_SOUND_WINDOWCLOSE); // disable the open noise since distorted in 3dfx builds.
memSetBlockHeap(NULL);
initMiscVars();
gameTimeInit();
@ -1304,19 +1249,12 @@ BOOL frontendShutdown(void)
*/
pie_TexShutDown();
// reset the block heap
BLOCK_RESET(psGameHeap);
return TRUE;
}
/******************************************************************************/
/* Initialisation before data is loaded */
@ -1324,9 +1262,6 @@ BOOL frontendShutdown(void)
BOOL stageOneInitialise(void)
{
BLOCK_HEAP *psHeap;
debug(LOG_MAIN, "stageOneInitalise");
// Initialise all globals and statics everwhere.
@ -1367,17 +1302,12 @@ BOOL stageOneInitialise(void)
return FALSE;
}
// debug mode only so use normal MALLOC
psHeap = memGetBlockHeap();
memSetBlockHeap(NULL);
#ifdef DISP2D
if (!disp2DInitialise())
{
return FALSE;
}
#endif
memSetBlockHeap(psHeap);
if ( !anim_Init( anim_GetShapeFunc ) )
{

View File

@ -66,15 +66,6 @@ BOOL rebuildSearchPath( searchPathMode mode, BOOL force );
BOOL buildMapList(void);
// the block heap for the game data
extern BLOCK_HEAP *psGameHeap;
// the block heap for the campaign map
extern BLOCK_HEAP *psMapHeap;
// the block heap for the pre WRF data
extern BLOCK_HEAP *psMissionHeap;
extern IMAGEFILE *FrontImages;
#endif // _init_h

View File

@ -500,10 +500,7 @@ KEY_MAPPING *keyAddMapping(KEY_STATUS status,KEY_CODE metaCode, KEY_CODE subCode
void (*pKeyMapFunc)(void), const char *name)
{
KEY_MAPPING *newMapping;
BLOCK_HEAP *psHeap;
psHeap = memGetBlockHeap();
memSetBlockHeap(NULL);
/* Get some memory for our binding */
newMapping = (KEY_MAPPING*)MALLOC(sizeof(KEY_MAPPING));
@ -513,8 +510,6 @@ BLOCK_HEAP *psHeap;
newMapping->pName = (char*)MALLOC(strlen(name)+1);
ASSERT( newMapping->pName != NULL, "Couldn't allocate the memory for the string in a mapping" );
memSetBlockHeap(psHeap);
/* Copy over the name */
strcpy(newMapping->pName,name);

View File

@ -466,18 +466,11 @@ BOOL levReleaseMissionData(void)
return FALSE;
}
if ((psCurrLevel->type == LDS_COMPLETE ||
psCurrLevel->type >= MULTI_TYPE_START) && psCurrLevel->game == -1)
{
BLOCK_RESET(psMissionHeap);
}
// free up the old data
for(i=LEVEL_MAXFILES-1; i >= 0; i--)
{
if (i == psCurrLevel->game)
{
BLOCK_RESET(psMissionHeap);
if (psCurrLevel->psBaseData == NULL)
{
if (!stageTwoShutDown())
@ -492,10 +485,6 @@ BOOL levReleaseMissionData(void)
resReleaseBlockData(i + CURRENT_DATAID);
}
}
if (psCurrLevel->type == LDS_BETWEEN)
{
BLOCK_RESET(psMissionHeap);
}
}
return TRUE;
}
@ -539,8 +528,6 @@ BOOL levReleaseAll(void)
{
return FALSE;
}
BLOCK_RESET(psGameHeap);
}
psCurrLevel=NULL;
@ -563,20 +550,14 @@ static BOOL levLoadSingleWRF(char *pName)
{
return FALSE;
}
BLOCK_RESET(psGameHeap);
memSetBlockHeap(psGameHeap);
// load the data
debug(LOG_WZ, "levLoadSingleWRF: Loading %s ...", pName);
if (!resLoad(pName, 0,
DisplayBuffer, displayBufferSize,
psGameHeap))
if (!resLoad(pName, 0, DisplayBuffer, displayBufferSize))
{
return FALSE;
}
BLOCK_RESET(psMissionHeap);
memSetBlockHeap(psMissionHeap);
if (!stageThreeInitialise())
{
return FALSE;
@ -620,11 +601,7 @@ BOOL levLoadBaseData(char *pName)
// clear all the old data
levReleaseAll();
// basic game data is loaded in the game heap
memSetBlockHeap(psGameHeap);
// initialise
BLOCK_RESET(psGameHeap);
if (!stageOneInitialise())
{
return FALSE;
@ -639,8 +616,7 @@ BOOL levLoadBaseData(char *pName)
// load the data
debug(LOG_WZ, "levLoadBaseData: Loading %s", psBaseData->apDataFiles[i]);
if (!resLoad(psBaseData->apDataFiles[i], i,
DisplayBuffer, displayBufferSize,
psGameHeap))
DisplayBuffer, displayBufferSize))
{
return FALSE;
}
@ -663,7 +639,6 @@ BOOL levLoadData(char *pName, char *pSaveName, SDWORD saveType)
{
LEVEL_DATASET *psNewLevel, *psBaseData, *psChangeLevel;
SDWORD i;
BLOCK_HEAP *psCurrHeap;
BOOL bCamChangeSaveGame;
debug(LOG_WZ, "Loading level %s", pName);
@ -767,16 +742,10 @@ BOOL levLoadData(char *pName, char *pSaveName, SDWORD saveType)
}
// basic game data is loaded in the game heap
debug( LOG_NEVER, "levLoadData: Setting game heap\n" );
memSetBlockHeap(psGameHeap);
// initialise if necessary
if (psNewLevel->type == LDS_COMPLETE || //psNewLevel->type >= MULTI_TYPE_START ||
psBaseData != NULL)
{
debug( LOG_NEVER, "levLoadData: reset game heap\n" );
BLOCK_RESET(psGameHeap);
if (!stageOneInitialise())
{
return FALSE;
@ -794,8 +763,7 @@ BOOL levLoadData(char *pName, char *pSaveName, SDWORD saveType)
// load the data
debug(LOG_WZ, "levLoadData: Loading %s ...", psBaseData->apDataFiles[i]);
if (!resLoad(psBaseData->apDataFiles[i], i,
DisplayBuffer, displayBufferSize,
psGameHeap))
DisplayBuffer, displayBufferSize))
{
return FALSE;
}
@ -824,10 +792,6 @@ BOOL levLoadData(char *pName, char *pSaveName, SDWORD saveType)
}
}
debug( LOG_NEVER, "levLoadData: setting map heap\n" );
BLOCK_RESET(psMapHeap);
memSetBlockHeap(psMapHeap);
//set the mission type before the saveGame data is loaded
if (saveType == GTYPE_SAVE_MIDMISSION)
{
@ -862,10 +826,6 @@ BOOL levLoadData(char *pName, char *pSaveName, SDWORD saveType)
return FALSE;
}
}
debug( LOG_NEVER, "levLoadData: setting mission heap\n" );
BLOCK_RESET(psMissionHeap);
memSetBlockHeap(psMissionHeap);
}
//we need to load up the save game data here for a camchange
@ -882,10 +842,6 @@ BOOL levLoadData(char *pName, char *pSaveName, SDWORD saveType)
}
}
debug( LOG_NEVER, "levLoadData: setting map heap\n" );
BLOCK_RESET(psMapHeap);
memSetBlockHeap(psMapHeap);
debug( LOG_NEVER, "levLoadData: loading savegame: %s\n", pSaveName );
if (!loadGame(pSaveName, FALSE, TRUE,TRUE))
{
@ -902,14 +858,12 @@ BOOL levLoadData(char *pName, char *pSaveName, SDWORD saveType)
//psChangeLevel = NULL;
//stageTwoShutDown??
//block_reset??
}
}
// load the new data
debug( LOG_NEVER, "levLoadData: loading mission dataset: %s\n", psNewLevel->pName );
psCurrHeap = memGetBlockHeap();
for(i=0; i<LEVEL_MAXFILES; i++)
{
if (psNewLevel->game == i)
@ -923,35 +877,11 @@ BOOL levLoadData(char *pName, char *pSaveName, SDWORD saveType)
{
return FALSE;
}
debug( LOG_NEVER, "levLoadData: setting map heap\n" );
BLOCK_RESET(psMapHeap);
memSetBlockHeap(psMapHeap);
psCurrHeap = psMapHeap;
}
// missions with a seperate map have to use the mission heap now
if ((psNewLevel->type == LDS_MKEEP
||psNewLevel->type == LDS_MCLEAR
||psNewLevel->type == LDS_MKEEP_LIMBO
) &&
pSaveName == NULL)
{
debug( LOG_NEVER, "levLoadData: setting mission heap\n" );
BLOCK_RESET(psMissionHeap);
memSetBlockHeap(psMissionHeap);
psCurrHeap = psMissionHeap;
}
// load a savegame if there is one - but not if already done so
if (pSaveName != NULL && !bCamChangeSaveGame)
{
// make sure the map gets loaded into the right heap
debug( LOG_NEVER, "levLoadData: setting map heap\n" );
BLOCK_RESET(psMapHeap);
memSetBlockHeap(psMapHeap);
psCurrHeap = psMapHeap;
//set the mission type before the saveGame data is loaded
if (saveType == GTYPE_SAVE_MIDMISSION)
{
@ -1078,23 +1008,13 @@ BOOL levLoadData(char *pName, char *pSaveName, SDWORD saveType)
return FALSE;
}
}
// set the mission heap now if it isn't already being used
if (memGetBlockHeap() != psMissionHeap)
{
debug( LOG_NEVER, "levLoadData: setting mission heap\n" );
BLOCK_RESET(psMissionHeap);
memSetBlockHeap(psMissionHeap);
}
psCurrHeap = psMissionHeap;
}
else if (psNewLevel->apDataFiles[i])
{
// load the data
debug(LOG_WZ, "levLoadData: Loading %s", psNewLevel->apDataFiles[i]);
if (!resLoad(psNewLevel->apDataFiles[i], i + CURRENT_DATAID,
DisplayBuffer, displayBufferSize,
psCurrHeap))
DisplayBuffer, displayBufferSize))
{
return FALSE;
}
@ -1103,16 +1023,6 @@ BOOL levLoadData(char *pName, char *pSaveName, SDWORD saveType)
dataClearSaveFlag();
// set the mission heap now if it isn't already being used
if (memGetBlockHeap() != psMissionHeap)
{
debug( LOG_NEVER, "levLoadData: setting mission heap\n" );
BLOCK_RESET(psMissionHeap);
memSetBlockHeap(psMissionHeap);
psCurrHeap = psMissionHeap;
}
//if (pSaveName != NULL && saveType == GTYPE_SAVE_MIDMISSION)
if (pSaveName != NULL)
{

View File

@ -452,11 +452,6 @@ init://jump here from the end if re_initialising
debug(LOG_MAIN, "reinitializing");
if (!blkInitialise())
{
return FALSE;
}
bDisableLobby = FALSE;
loadConfig();

View File

@ -124,16 +124,12 @@ BOOL startLimitScreen(void)
{
initLoadingScreen( TRUE );//changed by jeremy mar8
if (!resLoad("wrf/piestats.wrf", 501,
DisplayBuffer, displayBufferSize,
psGameHeap))//need the object heaps to have been set up before loading
if (!resLoad("wrf/piestats.wrf", 501, DisplayBuffer, displayBufferSize))
{
return FALSE;
}
if (!resLoad("wrf/forcedit2.wrf", 502,
DisplayBuffer, displayBufferSize,
psGameHeap))//need the object heaps to have been set up before loading
if (!resLoad("wrf/forcedit2.wrf", 502, DisplayBuffer, displayBufferSize))
{
return FALSE;
}