1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23
24 #include "sword1/memman.h"
25 #include "common/textconsole.h"
26 #include "common/util.h"
27
28 namespace Sword1 {
29
MemMan()30 MemMan::MemMan() {
31 _alloced = 0;
32 _memListFree = _memListFreeEnd = NULL;
33 }
34
~MemMan()35 MemMan::~MemMan() {
36 flush();
37 if (_alloced)
38 warning("deleting MemMan, still %d bytes alloced", _alloced);
39 }
40
alloc(MemHandle * bsMem,uint32 pSize,uint16 pCond)41 void MemMan::alloc(MemHandle *bsMem, uint32 pSize, uint16 pCond) {
42 _alloced += pSize;
43 bsMem->data = (void *)malloc(pSize);
44 if (!bsMem->data)
45 error("MemMan::alloc(): Can't alloc %d bytes of memory.", pSize);
46 bsMem->cond = pCond;
47 bsMem->size = pSize;
48 if (pCond == MEM_CAN_FREE) {
49 warning("%d Bytes alloced as FREEABLE.", pSize); // why should one want to alloc mem if it can be freed?
50 addToFreeList(bsMem);
51 } else if (bsMem->next || bsMem->prev) // it's in our _freeAble list, remove it from there
52 removeFromFreeList(bsMem);
53 checkMemoryUsage();
54 }
55
freeNow(MemHandle * bsMem)56 void MemMan::freeNow(MemHandle *bsMem) {
57 if (bsMem->cond != MEM_FREED) {
58 _alloced -= bsMem->size;
59 removeFromFreeList(bsMem);
60 free(bsMem->data);
61 bsMem->cond = MEM_FREED;
62 }
63 }
64
setCondition(MemHandle * bsMem,uint16 pCond)65 void MemMan::setCondition(MemHandle *bsMem, uint16 pCond) {
66 if ((pCond == MEM_FREED) || (pCond > MEM_DONT_FREE))
67 error("MemMan::setCondition: program tried to set illegal memory condition");
68 if (bsMem->cond != pCond) {
69 bsMem->cond = pCond;
70 if (pCond == MEM_DONT_FREE)
71 removeFromFreeList(bsMem);
72 else if (pCond == MEM_CAN_FREE)
73 addToFreeList(bsMem);
74 }
75 }
76
flush()77 void MemMan::flush() {
78 while (_memListFree) {
79 free(_memListFreeEnd->data);
80 _memListFreeEnd->data = NULL;
81 _memListFreeEnd->cond = MEM_FREED;
82 _alloced -= _memListFreeEnd->size;
83 removeFromFreeList(_memListFreeEnd);
84 }
85 if (_alloced)
86 warning("MemMan::flush: Something's wrong: still %d bytes alloced", _alloced);
87 }
88
checkMemoryUsage()89 void MemMan::checkMemoryUsage() {
90 while ((_alloced > MAX_ALLOC) && _memListFree) {
91 free(_memListFreeEnd->data);
92 _memListFreeEnd->data = NULL;
93 _memListFreeEnd->cond = MEM_FREED;
94 _alloced -= _memListFreeEnd->size;
95 removeFromFreeList(_memListFreeEnd);
96 }
97 }
98
addToFreeList(MemHandle * bsMem)99 void MemMan::addToFreeList(MemHandle *bsMem) {
100 if (bsMem->next || bsMem->prev) {
101 warning("addToFreeList: mem block is already in freeList");
102 return;
103 }
104 bsMem->prev = NULL;
105 bsMem->next = _memListFree;
106 if (bsMem->next)
107 bsMem->next->prev = bsMem;
108 _memListFree = bsMem;
109 if (!_memListFreeEnd)
110 _memListFreeEnd = _memListFree;
111 }
112
removeFromFreeList(MemHandle * bsMem)113 void MemMan::removeFromFreeList(MemHandle *bsMem) {
114 if (_memListFree == bsMem)
115 _memListFree = bsMem->next;
116 if (_memListFreeEnd == bsMem)
117 _memListFreeEnd = bsMem->prev;
118
119 if (bsMem->next)
120 bsMem->next->prev = bsMem->prev;
121 if (bsMem->prev)
122 bsMem->prev->next = bsMem->next;
123 bsMem->next = bsMem->prev = NULL;
124 }
125
initHandle(MemHandle * bsMem)126 void MemMan::initHandle(MemHandle *bsMem) {
127 memset(bsMem, 0, sizeof(MemHandle));
128 }
129
130 } // End of namespace Sword1
131