TINSEL: Remove DWM_FIXED and add new MemoryAllocFixed() function

svn-id: r45401
This commit is contained in:
Max Horn 2009-10-26 10:41:11 +00:00
parent 9065dca09a
commit bbe0b81aff
4 changed files with 95 additions and 104 deletions

View File

@ -5526,7 +5526,7 @@ void RegisterIcons(void *cptr, int num) {
if (TinselV0) {
// In Tinsel 0, the INV_OBJECT structure doesn't have an attributes field, so we
// need to 'unpack' the source structures into the standard Tinsel v1/v2 format
invObjects = (INV_OBJECT *)MemoryAlloc(DWM_FIXED, numObjects * sizeof(INV_OBJECT));
invObjects = (INV_OBJECT *)MemoryAllocFixed(numObjects * sizeof(INV_OBJECT));
byte *srcP = (byte *)cptr;
INV_OBJECT *destP = (INV_OBJECT *)invObjects;
@ -5535,9 +5535,11 @@ void RegisterIcons(void *cptr, int num) {
destP->attribute = 0;
}
} else if (TinselV2) {
if (invFilms == NULL)
if (invFilms == NULL) {
// First time - allocate memory
invFilms = (SCNHANDLE *)MemoryAlloc(DWM_FIXED | DWM_ZEROINIT, numObjects * sizeof(SCNHANDLE));
invFilms = (SCNHANDLE *)MemoryAllocFixed(numObjects * sizeof(SCNHANDLE));
memset(invFilms, 0, numObjects * sizeof(SCNHANDLE));
}
if (invFilms == NULL)
error(NO_MEM, "inventory scripts");

View File

@ -48,9 +48,10 @@ bool bLockedScene = 0;
//----------------- LOCAL DEFINES --------------------
struct MEMHANDLE {
char szName[12]; ///< 00 - file name of graphics file
int32 filesize; ///< 12 - file size and flags
MEM_NODE *pNode; ///< 16 - memory node for the graphics
char szName[12]; ///< file name of graphics file
int32 filesize; ///< file size and flags
MEM_NODE *_node; ///< memory node for the graphics
uint8 *_ptr; ///< start of data for fixed blocks (i.e., preloaded data)
uint32 flags2;
};
@ -127,7 +128,8 @@ void SetupHandleTable(void) {
handleTable[i].filesize = f.readUint32LE();
// The pointer should always be NULL. We don't
// need to read that from the file.
handleTable[i].pNode = NULL;
handleTable[i]._node = NULL;
handleTable[i]._ptr = NULL;
f.seek(4, SEEK_CUR);
// For Discworld 2, read in the flags2 field
handleTable[i].flags2 = t2Flag ? f.readUint32LE() : 0;
@ -151,30 +153,30 @@ void SetupHandleTable(void) {
for (i = 0, pH = handleTable; i < numHandles; i++, pH++) {
if (pH->filesize & fPreload) {
// allocate a fixed memory node for permanent files
pH->pNode = MemoryAlloc(DWM_FIXED, sizeof(MEM_NODE) + (pH->filesize & FSIZE_MASK));
pH->_ptr = (uint8 *)MemoryAllocFixed((pH->filesize & FSIZE_MASK));
pH->_node = NULL;
// make sure memory allocated
assert(pH->pNode);
// Initialise the MEM_NODE structure
memset(pH->pNode, 0, sizeof(MEM_NODE));
assert(pH->_ptr);
// load the data
LoadFile(pH, true);
}
#ifdef BODGE
else if ((pH->filesize & FSIZE_MASK) == 8) {
pH->pNode = NULL;
pH->_node = NULL;
pH->_ptr = NULL;
}
#endif
else {
// allocate a discarded memory node for other files
pH->pNode = MemoryAlloc(
pH->_node = MemoryAlloc(
DWM_MOVEABLE | DWM_DISCARDABLE | DWM_NOALLOC,
pH->filesize & FSIZE_MASK);
pH->_ptr = NULL;
// make sure memory allocated
assert(pH->pNode);
assert(pH->_node || pH->_ptr);
}
}
}
@ -213,7 +215,7 @@ void LoadCDGraphData(MEMHANDLE *pH) {
assert(!(pH->filesize & fPreload));
// discardable - lock the memory
addr = (byte *)MemoryLock(pH->pNode);
addr = (byte *)MemoryLock(pH->_node);
// make sure address is valid
assert(addr);
@ -230,7 +232,7 @@ void LoadCDGraphData(MEMHANDLE *pH) {
}
// discardable - unlock the memory
MemoryUnlock(pH->pNode);
MemoryUnlock(pH->_node);
// set the loaded flag
pH->filesize |= fLoaded;
@ -256,8 +258,8 @@ void LoadExtraGraphData(SCNHANDLE start, SCNHANDLE next) {
OpenCDGraphFile();
if ((handleTable + cdPlayHandle)->pNode->pBaseAddr != NULL)
MemoryDiscard((handleTable + cdPlayHandle)->pNode); // Free it
if ((handleTable + cdPlayHandle)->_node->pBaseAddr != NULL)
MemoryDiscard((handleTable + cdPlayHandle)->_node); // Free it
// It must always be the same
assert(cdPlayHandle == (start >> SCNHANDLE_SHIFT));
@ -301,19 +303,19 @@ void LoadFile(MEMHANDLE *pH, bool bWarn) {
if (pH->filesize & fPreload)
// preload - no need to lock the memory
addr = (uint8 *)pH->pNode + sizeof(MEM_NODE);
addr = pH->_ptr;
else {
// discardable - lock the memory
addr = (uint8 *)MemoryLock(pH->pNode);
addr = (uint8 *)MemoryLock(pH->_node);
}
#ifdef DEBUG
if (addr == NULL) {
if (pH->filesize & fPreload)
// preload - no need to lock the memory
addr = (uint8 *)pH->pNode;
addr = pH->_ptr;
else {
// discardable - lock the memory
addr = (uint8 *)MemoryLock(pH->pNode);
addr = (uint8 *)MemoryLock(pH->_node);
}
}
#endif
@ -328,7 +330,7 @@ void LoadFile(MEMHANDLE *pH, bool bWarn) {
if ((pH->filesize & fPreload) == 0) {
// discardable - unlock the memory
MemoryUnlock(pH->pNode);
MemoryUnlock(pH->_node);
}
// set the loaded flag
@ -362,50 +364,52 @@ byte *LockMem(SCNHANDLE offset) {
pH = handleTable + handle;
if (pH->filesize & fPreload) {
#if 0
if (TinselV2)
// update the LRU time (new in this file)
pH->pNode->lruTime = DwGetCurrentTime();
#endif
// permanent files are already loaded
return (uint8 *)pH->pNode + sizeof(MEM_NODE) + (offset & OFFSETMASK);
return pH->_ptr + (offset & OFFSETMASK);
} else if (handle == cdPlayHandle) {
// Must be in currently loaded/loadable range
if (offset < cdBaseHandle || offset >= cdTopHandle)
error("Overlapping (in time) CD-plays");
if (pH->pNode->pBaseAddr && (pH->filesize & fLoaded))
if (pH->_node->pBaseAddr && (pH->filesize & fLoaded))
// already allocated and loaded
return pH->pNode->pBaseAddr + ((offset - cdBaseHandle) & OFFSETMASK);
return pH->_node->pBaseAddr + ((offset - cdBaseHandle) & OFFSETMASK);
if (pH->pNode->pBaseAddr == NULL)
if (pH->_node->pBaseAddr == NULL)
// must have been discarded - reallocate the memory
MemoryReAlloc(pH->pNode, cdTopHandle-cdBaseHandle,
MemoryReAlloc(pH->_node, cdTopHandle-cdBaseHandle,
DWM_MOVEABLE | DWM_DISCARDABLE);
if (pH->pNode->pBaseAddr == NULL)
if (pH->_node->pBaseAddr == NULL)
error("Out of memory");
LoadCDGraphData(pH);
// make sure address is valid
assert(pH->pNode->pBaseAddr);
assert(pH->_node->pBaseAddr);
// update the LRU time (new in this file)
pH->pNode->lruTime = DwGetCurrentTime();
pH->_node->lruTime = DwGetCurrentTime();
return pH->pNode->pBaseAddr + ((offset - cdBaseHandle) & OFFSETMASK);
return pH->_node->pBaseAddr + ((offset - cdBaseHandle) & OFFSETMASK);
} else {
if (pH->pNode->pBaseAddr && (pH->filesize & fLoaded))
if (pH->_node->pBaseAddr && (pH->filesize & fLoaded))
// already allocated and loaded
return pH->pNode->pBaseAddr + (offset & OFFSETMASK);
return pH->_node->pBaseAddr + (offset & OFFSETMASK);
if (pH->pNode->pBaseAddr == NULL)
if (pH->_node->pBaseAddr == NULL)
// must have been discarded - reallocate the memory
MemoryReAlloc(pH->pNode, pH->filesize & FSIZE_MASK,
MemoryReAlloc(pH->_node, pH->filesize & FSIZE_MASK,
DWM_MOVEABLE | DWM_DISCARDABLE);
if (pH->pNode->pBaseAddr == NULL)
if (pH->_node->pBaseAddr == NULL)
error("Out of memory");
if (TinselV2) {
@ -415,9 +419,9 @@ byte *LockMem(SCNHANDLE offset) {
LoadFile(pH, true);
// make sure address is valid
assert(pH->pNode->pBaseAddr);
assert(pH->_node->pBaseAddr);
return pH->pNode->pBaseAddr + (offset & OFFSETMASK);
return pH->_node->pBaseAddr + (offset & OFFSETMASK);
}
}
@ -447,7 +451,7 @@ void LockScene(SCNHANDLE offset) {
// WORKAROUND: The original didn't include the DWM_LOCKED flag. It's being
// included because the method is 'LockScene' so it's presumed that the
// point of this was that the scene's memory block be locked
MemoryReAlloc(pH->pNode, pH->filesize & FSIZE_MASK, DWM_MOVEABLE | DWM_LOCKED);
MemoryReAlloc(pH->_node, pH->filesize & FSIZE_MASK, DWM_MOVEABLE | DWM_LOCKED);
#ifdef DEBUG
bLockedScene = true;
#endif
@ -470,7 +474,7 @@ void UnlockScene(SCNHANDLE offset) {
if ((pH->filesize & fPreload) == 0) {
// change the flags for the node
MemoryReAlloc(pH->pNode, pH->filesize & FSIZE_MASK, DWM_MOVEABLE | DWM_DISCARDABLE);
MemoryReAlloc(pH->_node, pH->filesize & FSIZE_MASK, DWM_MOVEABLE | DWM_DISCARDABLE);
#ifdef DEBUG
bLockedScene = false;
#endif
@ -510,7 +514,8 @@ void TouchMem(SCNHANDLE offset) {
pH = handleTable + handle;
// update the LRU time whether its loaded or not!
pH->pNode->lruTime = DwGetCurrentTime();
if (pH->_node)
pH->_node->lruTime = DwGetCurrentTime();
}
}

View File

@ -279,11 +279,6 @@ MEM_NODE *MemoryAlloc(int flags, long size) {
MEM_NODE *pNode;
bool bCompacted = true; // set when heap has been compacted
// compact the heap if we are allocating fixed memory
if (flags & DWM_FIXED) {
HeapCompact(MAX_INT, false);
}
#ifdef SCUMM_NEED_ALIGNMENT
const int alignPadding = sizeof(void*) - 1;
size = (size + alignPadding) & ~alignPadding; //round up to nearest multiple of sizeof(void*), this ensures the addresses that are returned are alignment-safe.
@ -307,12 +302,8 @@ MEM_NODE *MemoryAlloc(int flags, long size) {
if (flags & DWM_ZEROINIT)
memset(pNode->pBaseAddr, 0, size);
if (flags & DWM_FIXED)
// lock the memory
return (MEM_NODE *)MemoryLock(pNode);
else
// just return the node
return pNode;
// return the node
return pNode;
} else {
// allocate a node for the remainder of the free block
MEM_NODE *pTemp = AllocMemNode();
@ -326,34 +317,19 @@ MEM_NODE *MemoryAlloc(int flags, long size) {
// set size of node
pNode->size = size;
if (flags & DWM_FIXED) {
// place the free node after pNode
pTemp->pBaseAddr = pNode->pBaseAddr + size;
pTemp->pNext = pNode->pNext;
pTemp->pPrev = pNode;
pNode->pNext->pPrev = pTemp;
pNode->pNext = pTemp;
// place the free node before pNode
pTemp->pBaseAddr = pNode->pBaseAddr;
pNode->pBaseAddr += freeSize;
pTemp->pNext = pNode;
pTemp->pPrev = pNode->pPrev;
pNode->pPrev->pNext = pTemp;
pNode->pPrev = pTemp;
// check for zeroing the block
if (flags & DWM_ZEROINIT)
memset(pNode->pBaseAddr, 0, size);
// check for zeroing the block
if (flags & DWM_ZEROINIT)
memset(pNode->pBaseAddr, 0, size);
return (MEM_NODE *)MemoryLock(pNode);
} else {
// place the free node before pNode
pTemp->pBaseAddr = pNode->pBaseAddr;
pNode->pBaseAddr += freeSize;
pTemp->pNext = pNode;
pTemp->pPrev = pNode->pPrev;
pNode->pPrev->pNext = pTemp;
pNode->pPrev = pTemp;
// check for zeroing the block
if (flags & DWM_ZEROINIT)
memset(pNode->pBaseAddr, 0, size);
return pNode;
}
return pNode;
}
}
}
@ -383,6 +359,21 @@ MEM_NODE *MemoryAlloc(int flags, long size) {
return NULL;
}
void *MemoryAllocFixed(long size) {
// Allocate a fixed block of data. For now, we simply malloc it!
// TODO: We really should keep a list of the allocated pointers,
// so that we can discard them later on, when the engine quits.
#ifdef SCUMM_NEED_ALIGNMENT
const int alignPadding = sizeof(void*) - 1;
size = (size + alignPadding) & ~alignPadding; //round up to nearest multiple of sizeof(void*), this ensures the addresses that are returned are alignment-safe.
#endif
return malloc(size);
}
/**
* Discards the specified memory object.
* @param pMemNode Node of the memory object
@ -512,14 +503,8 @@ MEM_NODE *MemoryReAlloc(MEM_NODE *pMemNode, long size, int flags) {
assert(pMemNode >= mnodeList && pMemNode <= mnodeList + NUM_MNODES - 1);
// validate the flags
// cannot be fixed and moveable
assert((flags & (DWM_FIXED | DWM_MOVEABLE)) != (DWM_FIXED | DWM_MOVEABLE));
// cannot be fixed and discardable
assert((flags & (DWM_FIXED | DWM_DISCARDABLE)) != (DWM_FIXED | DWM_DISCARDABLE));
// must be fixed or moveable
assert(flags & (DWM_FIXED | DWM_MOVEABLE));
// must be moveable
assert(flags & DWM_MOVEABLE);
// align the size to machine boundary requirements
size = (size + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
@ -541,7 +526,7 @@ MEM_NODE *MemoryReAlloc(MEM_NODE *pMemNode, long size, int flags) {
pMemNode->pPrev->pNext = pMemNode->pNext;
// allocate a new node
pNew = MemoryAlloc((flags & ~DWM_FIXED) | DWM_MOVEABLE, size);
pNew = MemoryAlloc(flags | DWM_MOVEABLE, size);
// make sure memory allocated
assert(pNew != NULL);
@ -560,12 +545,8 @@ MEM_NODE *MemoryReAlloc(MEM_NODE *pMemNode, long size, int flags) {
FreeMemNode(pNew);
}
if (flags & DWM_FIXED)
// lock the memory
return (MEM_NODE *)MemoryLock(pMemNode);
else
// just return the node
return pMemNode;
// return the node
return pMemNode;
}
/**

View File

@ -43,14 +43,13 @@ struct MEM_NODE {
};
// allocation flags for the MemoryAlloc function
#define DWM_FIXED 0x0001 // allocates fixed memory
#define DWM_MOVEABLE 0x0002 // allocates movable memory
#define DWM_DISCARDABLE 0x0004 // allocates discardable memory
#define DWM_NOALLOC 0x0008 // when used with discardable memory - allocates a discarded block
#define DWM_NOCOMPACT 0x0010 // does not discard memory to satisfy the allocation request
#define DWM_ZEROINIT 0x0020 // initialises memory contents to zero
#define DWM_SOUND 0x0040 // allocate from the sound pool
#define DWM_GRAPHIC 0x0080 // allocate from the graphics pool
#define DWM_MOVEABLE 0x0002 ///< allocates movable memory
#define DWM_DISCARDABLE 0x0004 ///< allocates discardable memory
#define DWM_NOALLOC 0x0008 ///< when used with discardable memory - allocates a discarded block
#define DWM_NOCOMPACT 0x0010 ///< does not discard memory to satisfy the allocation request
#define DWM_ZEROINIT 0x0020 ///< initialises memory contents to zero
#define DWM_SOUND 0x0040 ///< allocate from the sound pool
#define DWM_GRAPHIC 0x0080 ///< allocate from the graphics pool
// return value from the MemoryFlags function
#define DWM_DISCARDED 0x0100 // the objects memory block has been discarded
@ -70,10 +69,14 @@ void MemoryInit(void); // initialises the memory manager
void MemoryStats(void); // Shows the maximum number of mnodes used at once
#endif
MEM_NODE *MemoryAlloc( // allocates the specified number of bytes from the heap
// allocates a non-fixed block with the specified number of bytes from the heap
MEM_NODE *MemoryAlloc(
int flags, // allocation attributes
long size); // number of bytes to allocate
// allocates a fixed block with the specified number of bytes
void *MemoryAllocFixed(long size);
void MemoryDiscard( // discards the specified memory object
MEM_NODE *pMemNode); // node of the memory object