From bbe0b81aff36cc188d598ba3d66cc2521e14c0f2 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 26 Oct 2009 10:41:11 +0000 Subject: TINSEL: Remove DWM_FIXED and add new MemoryAllocFixed() function svn-id: r45401 --- engines/tinsel/dialogs.cpp | 8 +++-- engines/tinsel/handle.cpp | 85 ++++++++++++++++++++++--------------------- engines/tinsel/heapmem.cpp | 89 ++++++++++++++++++---------------------------- engines/tinsel/heapmem.h | 21 ++++++----- 4 files changed, 97 insertions(+), 106 deletions(-) diff --git a/engines/tinsel/dialogs.cpp b/engines/tinsel/dialogs.cpp index 36f7017c99..c5686378c5 100644 --- a/engines/tinsel/dialogs.cpp +++ b/engines/tinsel/dialogs.cpp @@ -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"); diff --git a/engines/tinsel/handle.cpp b/engines/tinsel/handle.cpp index cdccf9027f..b1d4e608df 100644 --- a/engines/tinsel/handle.cpp +++ b/engines/tinsel/handle.cpp @@ -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(); } } diff --git a/engines/tinsel/heapmem.cpp b/engines/tinsel/heapmem.cpp index 8a5d351381..b358b945e0 100644 --- a/engines/tinsel/heapmem.cpp +++ b/engines/tinsel/heapmem.cpp @@ -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; - - // 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; - } + // 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; } } } @@ -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; } /** diff --git a/engines/tinsel/heapmem.h b/engines/tinsel/heapmem.h index 358c5f77b5..2bea20f231 100644 --- a/engines/tinsel/heapmem.h +++ b/engines/tinsel/heapmem.h @@ -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 -- cgit v1.2.3