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 #ifndef SCUMM_RESOURCE_H
24 #define SCUMM_RESOURCE_H
25 
26 #include "common/array.h"
27 #include "scumm/scumm.h"	// for ResType
28 
29 namespace Scumm {
30 
31 enum {
32 	OF_OWNER_MASK = 0x0F,
33 	OF_STATE_MASK = 0xF0,
34 
35 	OF_STATE_SHL = 4
36 };
37 
38 class ResourceIterator {
39 	uint32 _size;
40 	uint32 _pos;
41 	const byte *_ptr;
42 	bool _smallHeader;
43 public:
44 	ResourceIterator(const byte *searchin, bool smallHeader);
45 	const byte *findNext(uint32 tag);
46 };
47 
48 enum {
49 	RES_INVALID_OFFSET = 0xFFFFFFFF
50 };
51 
52 class ScummEngine;
53 
54 /**
55  * The mode of a resource type indicates whether the resource can be restored
56  * from the game data files or not.
57  * This affects for example whether the resource is stored in savestates.
58  *
59  * Note that we treat sound resources somewhat differently: On the one hand,
60  * these behave mostly like a kStaticResTypeMode res type. However, when we
61  * create a savestate, we do save *some* information about them: Namely, which
62  * sound resources are loaded in memory at the time the save is made. And when
63  * loading, we invoke ensureResourceLoaded() for each sound resource that was
64  * marked in this way.
65  */
66 enum ResTypeMode {
67 	kDynamicResTypeMode = 0,	///< Resource is generated during runtime and may change
68 	kStaticResTypeMode = 1,		///< Resource comes from data files, does not change
69 	kSoundResTypeMode = 2		///< Resource comes from data files, but may change
70 };
71 
72 /**
73  * The 'resource manager' class. Currently doesn't really deserve to be called
74  * a 'class', at least until somebody gets around to OOfying this more.
75  */
76 class ResourceManager {
77 	//friend class ScummDebugger;
78 	//friend class ScummEngine;
79 protected:
80 	ScummEngine *_vm;
81 
82 public:
83 	class Resource {
84 	public:
85 		/**
86 		 * Pointer to the data contained in this resource
87 		 */
88 		byte *_address;
89 
90 		/**
91 		 * Size of this resource, i.e. of the data contained in it.
92 		 */
93 		uint32 _size;
94 
95 	protected:
96 		/**
97 		 * The uppermost bit indicates whether the resources is locked.
98 		 * The lower 7 bits contain a counter. This counter measures roughly
99 		 * how old the resource is; it starts out with a count of 1 and can go
100 		 * as high as 127. When memory falls low resp. when the engine decides
101 		 * that it should throw out some unused stuff, then it begins by
102 		 * removing the resources with the highest counter (excluding locked
103 		 * resources and resources that are known to be in use).
104 		 */
105 		byte _flags;
106 
107 		/**
108 		 * The status of the resource. Currently only one bit is used, which
109 		 * indicates whether the resource is modified.
110 		 */
111 		byte _status;
112 
113 	public:
114 		/**
115 		 * The id of the room (resp. the disk) the resource is contained in.
116 		 */
117 		byte _roomno;
118 
119 		/**
120 		 * The offset (in bytes) where the data for this resources can be found
121 		 * in the game data file(s), relative to the start of the room the
122 		 * resource is contained in.
123 		 *
124 		 * A value of RES_INVALID_OFFSET indicates a resources that is not contained
125 		 * in the game data files.
126 		 */
127 		uint32 _roomoffs;
128 
129 	public:
130 		Resource();
131 		~Resource();
132 
133 		void nuke();
134 
135 		inline void setResourceCounter(byte counter);
136 		inline byte getResourceCounter() const;
137 
138 		void lock();
139 		void unlock();
140 		bool isLocked() const;
141 
142 		// HE specific
143 		void setModified();
144 		bool isModified() const;
145 		void setOffHeap();
146 		void setOnHeap();
147 		bool isOffHeap() const;
148 	};
149 
150 	/**
151 	 * This struct represents a resource type and all resource of that type.
152 	 */
153 	class ResTypeData : public Common::Array<Resource> {
154 	friend class ResourceManager;
155 	public:
156 		/**
157 		 * The mode of this res type.
158 		 */
159 		ResTypeMode _mode;
160 
161 		/**
162 		 * The 4-byte tag or chunk type associated to this resource type, if any.
163 		 * Only applies to resources that are loaded from the game data files.
164 		 * This value is only used for debugging purposes.
165 		 */
166 		uint32 _tag;
167 
168 	public:
169 		ResTypeData();
170 		~ResTypeData();
171 	};
172 	ResTypeData _types[rtLast + 1];
173 
174 protected:
175 	uint32 _allocatedSize;
176 	uint32 _maxHeapThreshold, _minHeapThreshold;
177 	byte _expireCounter;
178 
179 public:
180 	ResourceManager(ScummEngine *vm);
181 	~ResourceManager();
182 
183 	void setHeapThreshold(int min, int max);
184 
185 	void allocResTypeData(ResType type, uint32 tag, int num, ResTypeMode mode);
186 	void freeResources();
187 
188 	byte *createResource(ResType type, ResId idx, uint32 size);
189 	void nukeResource(ResType type, ResId idx);
190 
191 //	inline Resource &getRes(ResType type, ResId idx) { return _types[type][idx]; }
192 //	inline const Resource &getRes(ResType type, ResId idx) const { return _types[type][idx]; }
193 
194 	bool isResourceLoaded(ResType type, ResId idx) const;
195 
196 	void lock(ResType type, ResId idx);
197 	void unlock(ResType type, ResId idx);
198 	bool isLocked(ResType type, ResId idx) const;
199 
200 	// HE Specific
201 	void setModified(ResType type, ResId idx);
202 	bool isModified(ResType type, ResId idx) const;
203 	void setOffHeap(ResType type, ResId idx);
204 	void setOnHeap(ResType type, ResId idx);
205 
206 	/**
207 	 * This method increments the _expireCounter, and if it overflows (which happens
208 	 * after at most 256 calls), it calls increaseResourceCounter.
209 	 * It is invoked in the engine's main loop ScummEngine::scummLoop().
210 	 */
211 	void increaseExpireCounter();
212 
213 	/**
214 	 * Update the specified resource's counter.
215 	 */
216 	void setResourceCounter(ResType type, ResId idx, byte counter);
217 
218 	/**
219 	 * Increment the counter of all unlocked loaded resources.
220 	 * The maximal count is 255.
221 	 * This is called by increaseExpireCounter and expireResources,
222 	 * but also by ScummEngine::startScene.
223 	 */
224 	void increaseResourceCounters();
225 
226 	void resourceStats();
227 
228 //protected:
229 	bool validateResource(const char *str, ResType type, ResId idx) const;
230 protected:
231 	void expireResources(uint32 size);
232 };
233 
234 } // End of namespace Scumm
235 
236 #endif
237