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 
36 namespace Common {
37 class Mutex;
38 }
39 
40 namespace 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
47 inline 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 
53 namespace ICB {
54 
55 // Generic stuff
56 
57 extern 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 
68 typedef 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!!!!
83 typedef struct {
84  uint32 total_hash;
85  int32 search;
86 } mem_offset;
87 
88 // Put the res_man params in a structure to prevent passing lots of the same arguments
89 // from function to function
90 typedef 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 
104 class 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 
119 public:
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 
132 public:
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 
187 private:
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
227 inline 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 
255 inline 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 
263 inline uint8 *res_man::Get_memory_base() {
264  return memory_base;
265 }
266 
267 inline uint32 res_man::Get_memory_size() {
268  return total_pool;
269 }
270 
271 inline void res_man::Set_auto_timeframe_advance() {
272  auto_time_advance = TRUE8; // timeframe will be advanced with each res-open
273 }
274 
275 inline void res_man::Set_to_no_defrag() {
276  no_defrag = TRUE8; // stop ageing out, etc
277 }
278 
279 inline uint32 res_man::Fetch_total_pool_size() {
280  return (total_pool);
281 }
282 
283 inline uint32 res_man::Fetch_free_memory() {
284  return (total_free_memory);
285 }
286 
287 inline uint32 res_man::Fetch_files_open() {
288  return (number_files_open);
289 }
290 
291 inline mem *res_man::Fetch_mem_list() { return mem_list; }
292 
293 inline uint32 res_man::Fetch_max_mem_blocks() { return max_mem_blocks; }
294 
295 inline uint32 res_man::Fetch_mem_used() {
296  return (total_pool - total_free_memory);
297 }
298 
299 inline 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 
303 inline 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 
309 inline 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
319 inline void res_man::Id(int32 newId) { id = (uint8)newId; }
320 
321 inline int32 res_man::Id() { return (int32)id; }
322 
323 extern uint32 memory_available; // set by memory_stats
324 
325 void Memory_stats();
326 void Print_console_clusters();
327 
328 } // End of namespace ICB
329 
330 #endif // #ifndef RES_MAN_H
Definition: res_man.h:68
Definition: actor.h:32
Definition: stream.h:745
Definition: algorithm.h:29
Definition: res_man.h:104
Definition: res_man.h:83
Definition: res_man.h:90
Definition: px_clu_api.h:76