ScummVM API documentation
res_man.h
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 * Additional copyright for this file:
8 * Copyright (C) 1999-2000 Revolution Software Ltd.
9 * This code is based on source code created by Revolution Software,
10 * used with permission.
11 *
12 * This program is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation, either version 3 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 *
25 */
26
27#ifndef ICB_RES_MAN_H
28#define ICB_RES_MAN_H
29
30#include "engines/icb/p4.h"
31#include "engines/icb/common/px_array.h"
32#include "engines/icb/common/px_string.h"
33#include "engines/icb/common/px_common.h"
34#include "engines/icb/common/px_clu_api.h"
35
36namespace Common {
37class Mutex;
38}
39
40namespace ICB {
41
42// Horrible forward declaration, this really should be a macro, but that makes
43// debugging a real bitch
44// The actual body is contained in res_man_psx.h & res_man_pc.h
45// as the PC & PSX have different ways of determining if the files are identical
46// i.e. PC uses strcmp, PSX uses compare the hash values
47inline int32 SameUrl(const char *urla, const uint32 urla_hash, const uint32 clustera_hash, const char *urlb, const uint32 urlb_hash, const uint32 clusterb_hash);
48
49} // End of namespace ICB (To avoid nesting during includes)
50
51#include "engines/icb/res_man_pc.h"
52
53namespace ICB {
54
55// Generic stuff
56
57extern uint32 MAX_MEM_BLOCKS;
58
59#define MEM_null 0
60#define MEM_free 1
61#define MEM_in_use 2
62
63#define RM_LOADNOW 0 // load file right now
64#define RM_ASYNCLOAD 1 // async load file
65
66#define MAKE_TOTAL_HASH(c, f) (2 * c + f)
67
68typedef struct {
69 uint32 url_hash; // hash value of the url name
70 uint32 cluster_hash; // hash value of the cluster the url beint32s to
71 uint8 *ad;
72 uint32 size;
73 uint32 protect;
74 uint32 total_hash; // 2*cluster_hash+url_hash;
75 int16 parent; // who is before us
76 int16 child; // who is after us
77 uint16 age;
78 uint8 state;
79 uint8 pad1;
80} mem;
81
82// MUST BE PADDED TO 8 BYTES!!!!
83typedef struct {
84 uint32 total_hash;
85 int32 search;
87
88// Put the res_man params in a structure to prevent passing lots of the same arguments
89// from function to function
90typedef struct RMParams {
91 uint32 url_hash;
92 const char *cluster;
93 uint32 cluster_hash;
94 uint32 mode;
95 int32 len;
96 int32 seekpos;
97 int32 zipped;
98 int32 search;
99 int32 compressed; // No zero if the resource is compressed
101 uint8 not_ready_yet; // are not ready yet
102} RMParams;
103
104class res_man {
105 uint32 total_pool; // fixed initial memory pool
106 uint32 total_free_memory;
107 uint8 *memory_base;
108 uint32 total_blocks; // total memory blocks in use - 1 more than number_files_open as we have the end free block to be eaten into
109 uint32 number_files_open;
110 uint32 max_mem_blocks;
111
112 mem *mem_list; // mem_list[MAX_MEM_BLOCKS];
113
114 mem_offset *mem_offset_list;
115 int32 num_mem_offsets;
116
117 uint16 current_time_frame; // inc's each time Res_open is called and is given to resource as its age cannot be allowed to start at 0!
118
119public:
120 int32 amount_of_defrags;
121
122 res_man();
123 res_man(uint32 memory_tot);
124 res_man(uint8 *base, uint32 size);
125 void Construct(uint8 *base, uint32 size, mem *memList, mem_offset *memOffsets, uint32 nMemBlocks);
126 ~res_man();
127
128 void AddMemOffset(uint32 total_hash, int32 search); // adds to mem list, clearing out if nesesary
129 inline int32 FindMemSearch(uint32 total_hash); // returns a search file for given total_hash, generates and adds if not in
130 inline int32 FindMemOffset(uint32 total_hash); // returns index into offsets table
131
132public:
133 void Reset(); // trash all resources
134
135 // So that other parts of the game can use this memory
136 inline uint8 *Get_memory_base();
137 inline uint32 Get_memory_size();
138
139 void Set_auto_timeframe_advance();
140 void Set_to_no_defrag();
141
142 int16 find_oldest_file();
143 void Garbage_removal();
144
145 // load whole cluster (if size is specified then load that amount of data, otherwise just load
146 // the cluster header first...
147 void Res_open_cluster(const char *cluster_url, uint32 &cluster_hash, int32 size = -1);
148
149 void Res_open_mini_cluster(const char *cluster_url, uint32 &cluster_hash, const char *fake_cluster_url, uint32 &fake_cluster_hash);
150
151 // If hash or cluster_hash == NULL_HASH then the hash of url/cluster_url
152 // is computed and stored in hash/cluster_hash
153 uint8 *Res_open(const char *url, uint32 &url_hash, const char *cluster_url, uint32 &cluster_hash,
154 int32 compressed = 0, // non zero if the resource is compressed
155 int32 *ret_len = NULL);
156 // new function to just allocate some memory for use
157 // by code which wants temporary memory but not files
158 // e.g. stream player, image decompressor
159 uint8 *Res_alloc(uint32 url_hash, const char *cluster, uint32 cluster_hash, uint32 length);
160 // If hash or cluster_hash == NULL_HASH then the hash of url/cluster_url
161 void Res_purge(const char *url, uint32 url_hash, const char *cluster, uint32 cluster_hash, uint32 fatal = 1);
162 void Res_purge_all();
163 uint32 Fetch_size(const char *url, uint32 url_hash, const char *cluster_url, uint32 cluster_hash);
164
165 void Advance_time_stamp();
166 uint32 Check_file_size(const char *url, uint32 url_hash, const char *cluster_url, uint32 cluster_hash);
167 bool8 Test_file(const char *url);
168 bool8 Test_file(const char *url, uint32 url_hash, const char *cluster_url, uint32 cluster_hash);
169
170 uint32 Fetch_files_open();
171 uint32 Fetch_total_pool_size();
172 uint32 Fetch_free_memory();
173 uint32 Fetch_mem_used();
174 mem *Fetch_mem_list();
175 uint32 Fetch_max_mem_blocks();
176
177 uint32 Fetch_old_memory(int32 number_of_cycles);
178
179 // For testing purposes wanted to call Defrag from console
180 // so made it public function
181 void Defrag();
182
183 // To aid debugging messages
184 inline void Id(int32 newId);
185 inline int32 Id();
186
187private:
188 inline void MakeHash(const char *s, uint32 &h);
189 inline int32 CheckHash(const char *s, const uint32 h, uint32 &h2);
190
191 const char *OpenFile(int32 &cluster_search, RMParams *params);
192
193 // the old linear ones
194 int16 OldFindFile(uint32 url_hash, uint32 cluster_hash, uint32 total_hash);
195
196 // new binary ones
197 int16 FindFile(uint32 url_hash, uint32 cluster_hash, uint32 total_hash);
198
199 int16 FindFile(RMParams *params);
200 void FindFileCluster(int32 &url_search, int32 &cluster_search, RMParams *params);
201
202 HEADER_NORMAL *GetFileHeader(int32 &cluster_search, RMParams *params);
203
204 inline int32 SameFile(mem *current_mem_block, const char *url, const uint32 url_hash, const uint32 cluster_hash);
205
206 void ReadFile(const char *new_url, RMParams *params);
207 uint32 FindMemBlock(uint32 adj_len, RMParams *params);
208 uint8 *AllocMemory(uint32 &memory_tot);
209
210 void Initialise(uint32 memory_tot);
211
212 uint8 *Internal_open(RMParams *params, int32 *ret_len = NULL);
213
214 uint8 *LoadFile(int32 &cluster_search, RMParams *params);
215
216 int16 Find_space(uint32 len);
217 uint16 Fetch_spawn(uint16 parent);
218
219 bool8 auto_time_advance; // if true then time stamp is automatically imcremented as a file is opened
220 bool8 no_defrag; // this manager is a static one so resources cannot be purged, shuffled or aged out
221 uint8 id; // used for debugging messages to say which res_man you are
222
223 uint8 padding1;
224};
225
226// binary search the mem_offset table return -1 if not found
227inline int32 res_man::FindMemOffset(uint32 hash) {
228 int32 top, bottom;
229 int32 i;
230 uint32 current;
231
232 if (!num_mem_offsets)
233 return -1;
234
235 top = num_mem_offsets - 1;
236 i = top >> 1;
237 bottom = 0;
238
239 for (;;) {
240 current = mem_offset_list[i].total_hash;
241 if (hash == current)
242 return i;
243 else if (top == bottom)
244 return -1;
245 else if (hash > current) {
246 bottom = i + 1;
247 i = (top + bottom) >> 1;
248 } else {
249 top = i;
250 i = (top + bottom) >> 1;
251 }
252 }
253}
254
255inline int32 res_man::FindMemSearch(uint32 total_hash) { // returns a search file for given total_hash, generates and adds if not in
256 int32 i = FindMemOffset(total_hash);
257 if (i == -1)
258 return -1;
259 else
260 return mem_offset_list[i].search;
261}
262
263inline uint8 *res_man::Get_memory_base() {
264 return memory_base;
265}
266
267inline uint32 res_man::Get_memory_size() {
268 return total_pool;
269}
270
271inline void res_man::Set_auto_timeframe_advance() {
272 auto_time_advance = TRUE8; // timeframe will be advanced with each res-open
273}
274
275inline void res_man::Set_to_no_defrag() {
276 no_defrag = TRUE8; // stop ageing out, etc
277}
278
279inline uint32 res_man::Fetch_total_pool_size() {
280 return (total_pool);
281}
282
283inline uint32 res_man::Fetch_free_memory() {
284 return (total_free_memory);
285}
286
287inline uint32 res_man::Fetch_files_open() {
288 return (number_files_open);
289}
290
291inline mem *res_man::Fetch_mem_list() { return mem_list; }
292
293inline uint32 res_man::Fetch_max_mem_blocks() { return max_mem_blocks; }
294
295inline uint32 res_man::Fetch_mem_used() {
296 return (total_pool - total_free_memory);
297}
298
299inline int32 res_man::SameFile(mem *current_mem_block, const char *url, const uint32 url_hash, const uint32 cluster_hash) {
300 return SameUrl(url, url_hash, cluster_hash, NULL, current_mem_block->url_hash, current_mem_block->cluster_hash);
301}
302
303inline void res_man::MakeHash(const char *s, uint32 &h) {
304 // if hash value is not set then make it
305 if (h == NULL_HASH)
306 h = EngineHashString(s);
307}
308
309inline int32 res_man::CheckHash(const char *s, const uint32 h, uint32 &h2) {
310 if (!s)
311 return 1;
312 h2 = EngineHashString(s);
313 if (h2 != h)
314 return 0;
315 return 1;
316}
317
318// To aid debugging messages
319inline void res_man::Id(int32 newId) { id = (uint8)newId; }
320
321inline int32 res_man::Id() { return (int32)id; }
322
323extern uint32 memory_available; // set by memory_stats
324
325void Memory_stats();
326void Print_console_clusters();
327
328} // End of namespace ICB
329
330#endif // #ifndef RES_MAN_H
Definition: stream.h:745
Definition: res_man.h:104
Definition: algorithm.h:29
Definition: px_clu_api.h:76
Definition: res_man.h:90
Definition: res_man.h:83
Definition: res_man.h:68