diff options
Diffstat (limited to 'engines')
-rw-r--r-- | engines/tinsel/dialogs.cpp | 13 | ||||
-rw-r--r-- | engines/tinsel/handle.cpp | 36 | ||||
-rw-r--r-- | engines/tinsel/heapmem.cpp | 59 | ||||
-rw-r--r-- | engines/tinsel/heapmem.h | 5 | ||||
-rw-r--r-- | engines/tinsel/tinsel.cpp | 2 |
5 files changed, 67 insertions, 48 deletions
diff --git a/engines/tinsel/dialogs.cpp b/engines/tinsel/dialogs.cpp index c5686378c5..1b318e69c2 100644 --- a/engines/tinsel/dialogs.cpp +++ b/engines/tinsel/dialogs.cpp @@ -5526,7 +5526,10 @@ 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 *)MemoryAllocFixed(numObjects * sizeof(INV_OBJECT)); + MEM_NODE *node = MemoryAllocFixed(numObjects * sizeof(INV_OBJECT)); + assert(node); + invObjects = (INV_OBJECT *)MemoryDeref(node); + assert(invObjects); byte *srcP = (byte *)cptr; INV_OBJECT *destP = (INV_OBJECT *)invObjects; @@ -5537,12 +5540,14 @@ void RegisterIcons(void *cptr, int num) { } else if (TinselV2) { if (invFilms == NULL) { // First time - allocate memory - invFilms = (SCNHANDLE *)MemoryAllocFixed(numObjects * sizeof(SCNHANDLE)); + MEM_NODE *node = MemoryAllocFixed(numObjects * sizeof(SCNHANDLE)); + assert(node); + invFilms = (SCNHANDLE *)MemoryDeref(node); + if (invFilms == NULL) + error(NO_MEM, "inventory scripts"); memset(invFilms, 0, numObjects * sizeof(SCNHANDLE)); } - if (invFilms == NULL) - error(NO_MEM, "inventory scripts"); // Add defined permanent conversation icons // and store all the films separately diff --git a/engines/tinsel/handle.cpp b/engines/tinsel/handle.cpp index 04b4b2fc60..b7e81dc4ca 100644 --- a/engines/tinsel/handle.cpp +++ b/engines/tinsel/handle.cpp @@ -51,7 +51,6 @@ struct MEMHANDLE { 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; }; @@ -129,7 +128,6 @@ void SetupHandleTable(void) { // The pointer should always be NULL. We don't // need to read that from the file. 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; @@ -153,11 +151,10 @@ 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->_ptr = (uint8 *)MemoryAllocFixed((pH->filesize & FSIZE_MASK)); - pH->_node = NULL; + pH->_node = MemoryAllocFixed((pH->filesize & FSIZE_MASK)); // make sure memory allocated - assert(pH->_ptr); + assert(pH->_node); // load the data LoadFile(pH); @@ -165,16 +162,14 @@ void SetupHandleTable(void) { #ifdef BODGE else if ((pH->filesize & FSIZE_MASK) == 8) { pH->_node = NULL; - pH->_ptr = NULL; } #endif else { // allocate a discarded memory node for other files pH->_node = MemoryNoAlloc(); - pH->_ptr = NULL; // make sure memory allocated - assert(pH->_node || pH->_ptr); + assert(pH->_node); } } } @@ -297,13 +292,8 @@ void LoadFile(MEMHANDLE *pH) { int bytes; uint8 *addr; - if (pH->filesize & fPreload) - // preload - no need to lock the memory - addr = pH->_ptr; - else { - // discardable - lock the memory - addr = (uint8 *)MemoryLock(pH->_node); - } + // lock the memory + addr = (uint8 *)MemoryLock(pH->_node); // make sure address is valid assert(addr); @@ -313,10 +303,8 @@ void LoadFile(MEMHANDLE *pH) { // close the file f.close(); - if ((pH->filesize & fPreload) == 0) { - // discardable - unlock the memory - MemoryUnlock(pH->_node); - } + // discardable - unlock the memory + MemoryUnlock(pH->_node); // set the loaded flag pH->filesize |= fLoaded; @@ -347,8 +335,7 @@ byte *LockMem(SCNHANDLE offset) { pH = handleTable + handle; if (pH->filesize & fPreload) { - // permanent files are already loaded - return pH->_ptr + (offset & OFFSETMASK); + // permanent files are already loaded, nothing to be done } else if (handle == cdPlayHandle) { // Must be in currently loaded/loadable range if (offset < cdBaseHandle || offset >= cdTopHandle) @@ -365,8 +352,7 @@ byte *LockMem(SCNHANDLE offset) { MemoryTouch(pH->_node); } - return MemoryDeref(pH->_node) + ((offset - cdBaseHandle) & OFFSETMASK); - + offset -= cdBaseHandle; } else { // may have been discarded, make sure memory is allocated MemoryReAlloc(pH->_node, pH->filesize & FSIZE_MASK); @@ -382,9 +368,9 @@ byte *LockMem(SCNHANDLE offset) { // make sure address is valid assert(pH->filesize & fLoaded); } - - return MemoryDeref(pH->_node) + (offset & OFFSETMASK); } + + return MemoryDeref(pH->_node) + (offset & OFFSETMASK); } /** diff --git a/engines/tinsel/heapmem.cpp b/engines/tinsel/heapmem.cpp index 5f32888f6e..31a8b97377 100644 --- a/engines/tinsel/heapmem.cpp +++ b/engines/tinsel/heapmem.cpp @@ -69,6 +69,9 @@ static int numNodes; static int maxNodes; #endif +// list of all fixed memory nodes +MEM_NODE s_fixedMnodesList[5]; + // the mnode heap sentinel static MEM_NODE heapSentinel; @@ -79,7 +82,7 @@ static MEM_NODE *AllocMemNode(void); /** * Initialises the memory manager. */ -void MemoryInit(void) { +void MemoryInit() { MEM_NODE *pNode; #ifdef DEBUG @@ -98,6 +101,9 @@ void MemoryInit(void) { // null the last mnode mnodeList[NUM_MNODES - 1].pNext = NULL; + // clear list of fixed memory nodes + memset(s_fixedMnodesList, 0, sizeof(s_fixedMnodesList)); + // allocates a big chunk of memory uint32 size = MemoryPoolSize[0]; if (TinselVersion == TINSEL_V1) size = MemoryPoolSize[1]; @@ -128,9 +134,27 @@ void MemoryInit(void) { // flag sentinel as locked heapSentinel.flags = DWM_LOCKED | DWM_SENTINEL; + + // store the start of the master data block in the sentinel + heapSentinel.pBaseAddr = mem; } /** + * Deinitialises the memory manager. + */ +void MemoryDeinit() { + MEM_NODE *pNode = s_fixedMnodesList; + for (int i = 0; i < ARRAYSIZE(s_fixedMnodesList); ++i, ++pNode) { + free(pNode->pBaseAddr); + pNode->pBaseAddr = 0; + } + + // free memory used for the memory pool + free(heapSentinel.pBaseAddr); +} + + +/** * Allocate a mnode from the free list. */ static MEM_NODE *AllocMemNode(void) { @@ -362,18 +386,31 @@ MEM_NODE *MemoryNoAlloc() { /** * Allocate a fixed block of data. - * @note For now, we simply malloc it! - * @todo We really should keep a list of the allocated pointers, + * @todo We really should keep track of the allocated pointers, * so that we can discard them later on, when the engine quits. */ -void *MemoryAllocFixed(long size) { +MEM_NODE *MemoryAllocFixed(long size) { #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); + // Search for a free entry in s_fixedMnodesList + MEM_NODE *pNode = s_fixedMnodesList; + for (int i = 0; i < ARRAYSIZE(s_fixedMnodesList); ++i, ++pNode) { + if (!pNode->pBaseAddr) { + pNode->pNext = 0; + pNode->pPrev = 0; + pNode->pBaseAddr = (byte *)malloc(size); + pNode->size = size; + pNode->lruTime = DwGetCurrentTime(); + pNode->flags = DWM_USED; + return pNode; + } + } + + return 0; } @@ -429,9 +466,6 @@ void MemoryDiscard(MEM_NODE *pMemNode) { * @param pMemNode Node of the memory object */ void *MemoryLock(MEM_NODE *pMemNode) { - // validate mnode pointer - assert(pMemNode >= mnodeList && pMemNode <= mnodeList + NUM_MNODES - 1); - // make sure memory object is not already locked assert((pMemNode->flags & DWM_LOCKED) == 0); @@ -497,9 +531,6 @@ void MemoryReAlloc(MEM_NODE *pMemNode, long size) { * @param pMemNode Node of the memory object */ void MemoryUnlock(MEM_NODE *pMemNode) { - // validate mnode pointer - assert(pMemNode >= mnodeList && pMemNode <= mnodeList + NUM_MNODES - 1); - // make sure memory object is already locked assert(pMemNode->flags & DWM_LOCKED); @@ -515,17 +546,11 @@ void MemoryUnlock(MEM_NODE *pMemNode) { * @param pMemNode Node of the memory object */ void MemoryTouch(MEM_NODE *pMemNode) { - // validate mnode pointer - assert(pMemNode >= mnodeList && pMemNode <= mnodeList + NUM_MNODES - 1); - // update the LRU time pMemNode->lruTime = DwGetCurrentTime(); } uint8 *MemoryDeref(MEM_NODE *pMemNode) { - // validate mnode pointer - assert(pMemNode >= mnodeList && pMemNode <= mnodeList + NUM_MNODES - 1); - return pMemNode->pBaseAddr; } diff --git a/engines/tinsel/heapmem.h b/engines/tinsel/heapmem.h index 86c7c456c0..5fa84dca4f 100644 --- a/engines/tinsel/heapmem.h +++ b/engines/tinsel/heapmem.h @@ -38,13 +38,14 @@ struct MEM_NODE; |* Memory Function Prototypes *| \*----------------------------------------------------------------------*/ -void MemoryInit(void); // initialises the memory manager +void MemoryInit(); // initialises the memory manager +void MemoryDeinit(); // deinitialises the memory manager // reserves a memory node for a movable & discardable block MEM_NODE *MemoryNoAlloc(); // allocates a fixed block with the specified number of bytes -void *MemoryAllocFixed(long size); +MEM_NODE *MemoryAllocFixed(long size); void MemoryDiscard( // discards the specified memory object MEM_NODE *pMemNode); // node of the memory object diff --git a/engines/tinsel/tinsel.cpp b/engines/tinsel/tinsel.cpp index 320eb495d5..6b71b0c245 100644 --- a/engines/tinsel/tinsel.cpp +++ b/engines/tinsel/tinsel.cpp @@ -893,6 +893,8 @@ TinselEngine::~TinselEngine() { FreeGlobalProcesses(); FreeGlobals(); delete _scheduler; + + MemoryDeinit(); } void TinselEngine::syncSoundSettings() { |