1 | /********************************************************************** <BR>
|
---|
2 | This file is part of Crack dot Com's free source code release of
|
---|
3 | Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
|
---|
4 | information about compiling & licensing issues visit this URL</a>
|
---|
5 | <PRE> If that doesn't help, contact Jonathan Clark at
|
---|
6 | golgotha_source@usa.net (Subject should have "GOLG" in it)
|
---|
7 | ***********************************************************************/
|
---|
8 |
|
---|
9 | //WARNING: this code is really nauseating.
|
---|
10 | #include "tex_cache.hh"
|
---|
11 | #include "mip_average.hh"
|
---|
12 | #include "status/status.hh"
|
---|
13 | #include "file/file.hh"
|
---|
14 | #include "error/error.hh"
|
---|
15 | #include "r1_res.hh"
|
---|
16 |
|
---|
17 | void do_single_file(i4_file_class *dst_file,
|
---|
18 | w32 id,
|
---|
19 | sw32 max_texture_dimention,
|
---|
20 | w32 network_file_date,
|
---|
21 | tex_cache_entry_t *t);
|
---|
22 |
|
---|
23 | struct file_status_sort_struct
|
---|
24 | {
|
---|
25 | w32 id;
|
---|
26 | w32 file_status_index;
|
---|
27 | };
|
---|
28 |
|
---|
29 | int file_status_struct_compare(const file_status_sort_struct *a, const file_status_sort_struct *b)
|
---|
30 | {
|
---|
31 | if (a->id<b->id)
|
---|
32 | return -1;
|
---|
33 | else if (a->id>b->id)
|
---|
34 | return 1;
|
---|
35 | else return 0;
|
---|
36 | }
|
---|
37 |
|
---|
38 |
|
---|
39 | void tex_cache_entry_t::write(i4_file_class *f)
|
---|
40 | {
|
---|
41 | if (!f)
|
---|
42 | {
|
---|
43 | i4_warning("tex_cache_entry_t::write() NULL file");
|
---|
44 | return;
|
---|
45 | }
|
---|
46 |
|
---|
47 | f->write_32(id);
|
---|
48 | f->write_32(lowmipoffset);
|
---|
49 | f->write_32(average_color);
|
---|
50 | f->write_32(last_modified);
|
---|
51 |
|
---|
52 | f->write_16(base_width);
|
---|
53 | f->write_16(base_height);
|
---|
54 |
|
---|
55 | f->write_8(flags);
|
---|
56 | f->write_8(num_mip_levels);
|
---|
57 | }
|
---|
58 |
|
---|
59 | void tex_cache_entry_t::read(i4_file_class *f)
|
---|
60 | {
|
---|
61 | if (!f)
|
---|
62 | {
|
---|
63 | i4_warning("tex_cache_entry_t::read() NULL file");
|
---|
64 | return;
|
---|
65 | }
|
---|
66 |
|
---|
67 | id = f->read_32();
|
---|
68 | lowmipoffset = f->read_32();
|
---|
69 | average_color = f->read_32();
|
---|
70 | last_modified = f->read_32();
|
---|
71 |
|
---|
72 | base_width = f->read_16();
|
---|
73 | base_height = f->read_16();
|
---|
74 |
|
---|
75 | flags = f->read_8();
|
---|
76 | num_mip_levels = f->read_8();
|
---|
77 | }
|
---|
78 |
|
---|
79 |
|
---|
80 |
|
---|
81 | void tex_cache_header_t::write(i4_file_class *f)
|
---|
82 | {
|
---|
83 | if (!f)
|
---|
84 | {
|
---|
85 | i4_warning("tex_cache_header_t::write() NULL file");
|
---|
86 | return;
|
---|
87 | }
|
---|
88 |
|
---|
89 | regular_format.write(f);
|
---|
90 | chroma_format.write(f);
|
---|
91 | alpha_format.write(f);
|
---|
92 |
|
---|
93 | f->write_32(max_mip_dimention);
|
---|
94 | f->write_32(num_entries);
|
---|
95 | }
|
---|
96 |
|
---|
97 | void tex_cache_header_t::read(i4_file_class *f)
|
---|
98 | {
|
---|
99 | if (!f)
|
---|
100 | {
|
---|
101 | i4_warning("tex_cache_header_t::read() NULL file");
|
---|
102 | return;
|
---|
103 | }
|
---|
104 |
|
---|
105 | if (f->size() < tex_cache_header_disk_size())
|
---|
106 | {
|
---|
107 | i4_warning("texture cache file corrupt");
|
---|
108 | regular_format.default_format();
|
---|
109 | chroma_format.default_format();
|
---|
110 | alpha_format.default_format();
|
---|
111 | max_mip_dimention = 0;
|
---|
112 | num_entries = 0;
|
---|
113 | entries = 0;
|
---|
114 | return;
|
---|
115 | }
|
---|
116 |
|
---|
117 | //seek to the end and read the last dword
|
---|
118 |
|
---|
119 | f->seek(f->size()-4);
|
---|
120 | sw32 expected_size = f->read_32();
|
---|
121 |
|
---|
122 | if (expected_size != f->size())
|
---|
123 | {
|
---|
124 | i4_warning("texture cache file corrupt");
|
---|
125 | entries = 0;
|
---|
126 | num_entries = 0;
|
---|
127 | return;
|
---|
128 | }
|
---|
129 |
|
---|
130 | //seek back to the beginning and start reading the file
|
---|
131 | f->seek(0);
|
---|
132 |
|
---|
133 | regular_format.read(f);
|
---|
134 | chroma_format.read(f);
|
---|
135 | alpha_format.read(f);
|
---|
136 |
|
---|
137 | max_mip_dimention = f->read_32();
|
---|
138 | num_entries = f->read_32();
|
---|
139 |
|
---|
140 | w32 entry_lump_size = tex_cache_entry_disk_size() * num_entries;
|
---|
141 |
|
---|
142 | //read in the entries
|
---|
143 |
|
---|
144 | if (entry_lump_size)
|
---|
145 | {
|
---|
146 | entries = (tex_cache_entry_t *)i4_malloc(sizeof(tex_cache_entry_t) * num_entries,"tex_cache_entries");
|
---|
147 | f->seek(f->size() - 4 - entry_lump_size);
|
---|
148 | }
|
---|
149 | else
|
---|
150 | {
|
---|
151 | num_entries = 0;
|
---|
152 | entries = 0;
|
---|
153 | }
|
---|
154 |
|
---|
155 | sw32 i;
|
---|
156 |
|
---|
157 | for (i=0; i<num_entries; i++)
|
---|
158 | {
|
---|
159 | entries[i].read(f);
|
---|
160 | }
|
---|
161 | }
|
---|
162 |
|
---|
163 |
|
---|
164 | i4_bool r1_texture_manager_class::update_cache_file(i4_array<w32> &update_ids,
|
---|
165 | const i4_const_str &network_dir,
|
---|
166 | const i4_const_str &local_dir)
|
---|
167 | {
|
---|
168 | sw32 i,j,k;
|
---|
169 |
|
---|
170 | i4_array<w32> network_file_ids(128,128);
|
---|
171 | i4_array<tex_cache_entry_t> new_cache_entries(128,128);
|
---|
172 |
|
---|
173 | i4_status_class *stat=i4_create_status(r1_gets("checking_times"), I4_STATUS_UNKNOWN_TOTAL);
|
---|
174 |
|
---|
175 |
|
---|
176 | i4_directory_struct ds;
|
---|
177 | i4_get_directory(network_dir, ds, i4_T, stat);
|
---|
178 |
|
---|
179 | delete stat;
|
---|
180 |
|
---|
181 | for (i=0; i<ds.tfiles; i++)
|
---|
182 | network_file_ids.add(r1_get_file_id(*ds.files[i]));
|
---|
183 |
|
---|
184 | i4_file_class *old_cache_file = i4_open(r1_get_cache_file(), I4_READ | I4_NO_BUFFER);
|
---|
185 |
|
---|
186 | w32 csize = old_cache_file->size();
|
---|
187 |
|
---|
188 | void *old_cache_file_data = i4_malloc(csize,"old cache file data");
|
---|
189 | old_cache_file->read(old_cache_file_data,csize);
|
---|
190 |
|
---|
191 | delete old_cache_file;
|
---|
192 |
|
---|
193 | old_cache_file = new i4_ram_file_class(old_cache_file_data,csize);
|
---|
194 |
|
---|
195 | tex_cache_header_t old_cache_header;
|
---|
196 |
|
---|
197 | old_cache_header.read(old_cache_file);
|
---|
198 |
|
---|
199 | w32 total_cache_entries = old_cache_header.num_entries;
|
---|
200 | w32 old_cache_header_num_entries = old_cache_header.num_entries;
|
---|
201 |
|
---|
202 | for (i=0; i < update_ids.size();)
|
---|
203 | {
|
---|
204 | tex_cache_entry_t *t = find_id_in_tex_cache(old_cache_header.entries,old_cache_header.num_entries,update_ids[i]);
|
---|
205 |
|
---|
206 | if (t)
|
---|
207 | {
|
---|
208 | update_ids.remove(i); //pull this out of the list
|
---|
209 | t->flags |= R1_MIP_EXTRA_FLAG;
|
---|
210 | }
|
---|
211 | else
|
---|
212 | {
|
---|
213 | //new textures going into the cache file
|
---|
214 | total_cache_entries++;
|
---|
215 | i++;
|
---|
216 | }
|
---|
217 | }
|
---|
218 |
|
---|
219 | i4_file_class *new_cache_file = i4_open(r1_get_cache_file(), I4_WRITE | I4_NO_BUFFER);
|
---|
220 |
|
---|
221 | old_cache_header.num_entries = total_cache_entries;
|
---|
222 | old_cache_header.write(new_cache_file);
|
---|
223 |
|
---|
224 | r1_setup_decompression(®ular_format,&chroma_format,&alpha_format,R1_CHROMA_COLOR,square_textures);
|
---|
225 |
|
---|
226 | update_ids.sort(w32_compare);
|
---|
227 |
|
---|
228 | j = 0;
|
---|
229 | i = 0;
|
---|
230 |
|
---|
231 | i4_bool i_done = i4_F;
|
---|
232 | i4_bool j_done = i4_F;
|
---|
233 |
|
---|
234 | stat = i4_create_status(r1_gets("updating_texture_cache"));
|
---|
235 |
|
---|
236 | while (1)
|
---|
237 | {
|
---|
238 | if (j>=update_ids.size()) j_done = i4_T;
|
---|
239 |
|
---|
240 | if (i>=old_cache_header_num_entries) i_done = i4_T;
|
---|
241 |
|
---|
242 | if (i_done && j_done) break;
|
---|
243 |
|
---|
244 | w32 file_offs = new_cache_file->tell();
|
---|
245 |
|
---|
246 | if ((j_done && !i_done) || (!i_done && old_cache_header.entries[i].id < update_ids[j]))
|
---|
247 | {
|
---|
248 | tex_cache_entry_t *t = &old_cache_header.entries[i];
|
---|
249 |
|
---|
250 | if (!(t->flags & R1_MIP_EXTRA_FLAG))
|
---|
251 | {
|
---|
252 | if (t->lowmipoffset != 0xFFFFFFFF)
|
---|
253 | {
|
---|
254 | old_cache_file->seek(t->lowmipoffset);
|
---|
255 |
|
---|
256 | sw32 entry_size = sizeof(sw32) * 2 +
|
---|
257 | t->base_width / (1<<(t->num_mip_levels-1)) *
|
---|
258 | t->base_height / (1<<(t->num_mip_levels-1)) * 2;
|
---|
259 |
|
---|
260 | t->lowmipoffset = file_offs;
|
---|
261 |
|
---|
262 | w8 copy_buffer[2048];
|
---|
263 | while (entry_size)
|
---|
264 | {
|
---|
265 | sw32 copy_size = (entry_size < 2048) ? (entry_size) : (2048);
|
---|
266 |
|
---|
267 | old_cache_file->read(copy_buffer, copy_size);
|
---|
268 | new_cache_file->write(copy_buffer,copy_size);
|
---|
269 |
|
---|
270 | entry_size -= copy_size;
|
---|
271 | }
|
---|
272 | }
|
---|
273 | }
|
---|
274 | else
|
---|
275 | {
|
---|
276 | t->flags &= (~R1_MIP_EXTRA_FLAG);
|
---|
277 |
|
---|
278 | w32 file_date=0xFFFFFFFF;
|
---|
279 |
|
---|
280 | //have to update this texture
|
---|
281 | for (k=0; k<network_file_ids.size(); k++)
|
---|
282 | {
|
---|
283 | if (t->id==network_file_ids[k])
|
---|
284 | {
|
---|
285 | file_date = ds.file_status[k].last_modified;
|
---|
286 | break;
|
---|
287 | }
|
---|
288 | }
|
---|
289 |
|
---|
290 | //dont want files in the cache w/different mip levels.
|
---|
291 | do_single_file(new_cache_file,
|
---|
292 | t->id,
|
---|
293 | old_cache_header.max_mip_dimention,
|
---|
294 | file_date,
|
---|
295 | t);
|
---|
296 | }
|
---|
297 |
|
---|
298 | new_cache_entries.add(*t);
|
---|
299 |
|
---|
300 | i++;
|
---|
301 | }
|
---|
302 | else
|
---|
303 | if ((i_done && !j_done) || (!j_done && update_ids[j] < old_cache_header.entries[i].id))
|
---|
304 | {
|
---|
305 | //have to add this id
|
---|
306 | w32 new_id = update_ids[j];
|
---|
307 |
|
---|
308 | w32 file_date=0xFFFFFFFF;
|
---|
309 |
|
---|
310 | //have to update this texture
|
---|
311 | for (k=0; k<network_file_ids.size(); k++)
|
---|
312 | {
|
---|
313 | if (new_id==network_file_ids[k])
|
---|
314 | {
|
---|
315 | file_date = ds.file_status[k].last_modified;
|
---|
316 | break;
|
---|
317 | }
|
---|
318 | }
|
---|
319 |
|
---|
320 | tex_cache_entry_t new_entry;
|
---|
321 |
|
---|
322 | do_single_file(new_cache_file,
|
---|
323 | new_id,
|
---|
324 | old_cache_header.max_mip_dimention,
|
---|
325 | file_date,
|
---|
326 | &new_entry);
|
---|
327 |
|
---|
328 | new_cache_entries.add(new_entry);
|
---|
329 | j++;
|
---|
330 | }
|
---|
331 |
|
---|
332 | if (stat)
|
---|
333 | stat->update((new_cache_entries.size()+1) / (float)total_cache_entries);
|
---|
334 | }
|
---|
335 |
|
---|
336 | if (stat)
|
---|
337 | delete stat;
|
---|
338 |
|
---|
339 |
|
---|
340 | if (old_cache_header.entries)
|
---|
341 | i4_free(old_cache_header.entries);
|
---|
342 |
|
---|
343 | i4_free(old_cache_file_data);
|
---|
344 | delete old_cache_file;
|
---|
345 |
|
---|
346 | r1_end_decompression();
|
---|
347 |
|
---|
348 | if (total_cache_entries != new_cache_entries.size())
|
---|
349 | {
|
---|
350 | i4_warning("error updating the texture cache file");
|
---|
351 | }
|
---|
352 |
|
---|
353 | for (i=0;i<new_cache_entries.size();i++)
|
---|
354 | {
|
---|
355 | new_cache_entries[i].write(new_cache_file);
|
---|
356 | }
|
---|
357 |
|
---|
358 | sw32 cache_size = new_cache_file->tell() + 4;
|
---|
359 |
|
---|
360 | new_cache_file->write_32(cache_size);
|
---|
361 |
|
---|
362 | delete new_cache_file;
|
---|
363 |
|
---|
364 | return i4_T;
|
---|
365 | }
|
---|
366 |
|
---|
367 | i4_bool r1_texture_manager_class::build_cache_file(i4_array<w32> &texture_file_ids,
|
---|
368 | const i4_const_str &network_dir,
|
---|
369 | const i4_const_str &local_dir)
|
---|
370 | {
|
---|
371 | //creates a tex_cache.dat "directory" w/lowest mip levels and mipheader_t info (tex_cache_entry_t, actually)
|
---|
372 | //decompresses others to local .gtx files
|
---|
373 |
|
---|
374 | i4_array<w32> network_file_ids(128,128);
|
---|
375 |
|
---|
376 | sw32 i,j;
|
---|
377 |
|
---|
378 |
|
---|
379 | r1_setup_decompression(®ular_format,&chroma_format,&alpha_format,R1_CHROMA_COLOR,square_textures);
|
---|
380 |
|
---|
381 | i4_file_class *dst_file = i4_open(r1_get_cache_file(),I4_WRITE | I4_NO_BUFFER);
|
---|
382 |
|
---|
383 | tex_cache_header_t tex_cache_header;
|
---|
384 |
|
---|
385 | memcpy(&tex_cache_header.regular_format,®ular_format,sizeof(i4_pixel_format));
|
---|
386 | memcpy(&tex_cache_header.chroma_format ,&chroma_format, sizeof(i4_pixel_format));
|
---|
387 | memcpy(&tex_cache_header.alpha_format ,&alpha_format, sizeof(i4_pixel_format));
|
---|
388 |
|
---|
389 | tex_cache_header.max_mip_dimention = max_texture_dimention;
|
---|
390 | tex_cache_header.num_entries = texture_file_ids.size();
|
---|
391 |
|
---|
392 | tex_cache_header.write(dst_file);
|
---|
393 |
|
---|
394 | tex_cache_entry_t *tex_cache_entries = 0;
|
---|
395 |
|
---|
396 | if (texture_file_ids.size())
|
---|
397 | {
|
---|
398 | tex_cache_entries = (tex_cache_entry_t *)
|
---|
399 | i4_malloc(sizeof(tex_cache_entry_t) * texture_file_ids.size(),"tex_cache_entries");
|
---|
400 | }
|
---|
401 |
|
---|
402 | //the entries will go at the end of the file. to get to the start of the entry list,
|
---|
403 | //seek to: filesize()-(num_entries*sizeof(tex_cache_entry_t))
|
---|
404 |
|
---|
405 |
|
---|
406 |
|
---|
407 |
|
---|
408 | i4_status_class *stat=i4_create_status(r1_gets("checking_times"), I4_STATUS_UNKNOWN_TOTAL);
|
---|
409 |
|
---|
410 | i4_directory_struct ds;
|
---|
411 | i4_get_directory(network_dir, ds, i4_T, stat);
|
---|
412 | delete stat;
|
---|
413 |
|
---|
414 | for (i=0; i<ds.tfiles; i++)
|
---|
415 | network_file_ids.add(r1_get_file_id(*ds.files[i]));
|
---|
416 |
|
---|
417 | stat = i4_create_status(r1_gets("building_texture_cache"));
|
---|
418 |
|
---|
419 | if (network_file_ids.size() != ds.tfiles)
|
---|
420 | i4_error("something bad happened building the texture cache file");
|
---|
421 |
|
---|
422 | for (i=0; i<texture_file_ids.size(); i++)
|
---|
423 | {
|
---|
424 | w32 id = texture_file_ids[i];
|
---|
425 |
|
---|
426 | w32 file_date = 0xFFFFFFFF;
|
---|
427 |
|
---|
428 | for (j=0; j<network_file_ids.size(); j++)
|
---|
429 | {
|
---|
430 | if (id==network_file_ids[j])
|
---|
431 | {
|
---|
432 | file_date = ds.file_status[j].last_modified;
|
---|
433 | break;
|
---|
434 | }
|
---|
435 | }
|
---|
436 |
|
---|
437 | //we need to decompress (for now, just copy)
|
---|
438 | //the network (or cd image) texture to our hard drive
|
---|
439 | do_single_file(dst_file,
|
---|
440 | id,
|
---|
441 | max_texture_dimention,
|
---|
442 | file_date,
|
---|
443 | &tex_cache_entries[i]);
|
---|
444 |
|
---|
445 |
|
---|
446 | if (stat)
|
---|
447 | stat->update((float)(i+1) / (float)texture_file_ids.size());
|
---|
448 | }
|
---|
449 |
|
---|
450 | if (stat)
|
---|
451 | delete stat;
|
---|
452 |
|
---|
453 |
|
---|
454 | if (tex_cache_entries)
|
---|
455 | {
|
---|
456 | for (i=0; i<tex_cache_header.num_entries; i++)
|
---|
457 | {
|
---|
458 | tex_cache_entries[i].write(dst_file);
|
---|
459 | }
|
---|
460 | i4_free(tex_cache_entries);
|
---|
461 | }
|
---|
462 |
|
---|
463 | sw32 cache_size = dst_file->tell() + 4;
|
---|
464 |
|
---|
465 | dst_file->write_32(cache_size);
|
---|
466 |
|
---|
467 | delete dst_file;
|
---|
468 |
|
---|
469 | r1_end_decompression();
|
---|
470 |
|
---|
471 |
|
---|
472 |
|
---|
473 | return i4_T;
|
---|
474 | }
|
---|
475 |
|
---|
476 |
|
---|
477 |
|
---|
478 | void do_single_file(i4_file_class *dst_file,
|
---|
479 | w32 id,
|
---|
480 | sw32 max_texture_dimention,
|
---|
481 | w32 network_file_date,
|
---|
482 | tex_cache_entry_t *t)
|
---|
483 | {
|
---|
484 |
|
---|
485 | i4_str *local_fname = r1_texture_id_to_filename(id, r1_get_decompressed_dir());
|
---|
486 | i4_str *network_fname = r1_texture_id_to_filename(id, r1_get_compressed_dir());
|
---|
487 |
|
---|
488 | char local_tex_file[256];
|
---|
489 | i4_os_string(*local_fname,local_tex_file,256);
|
---|
490 | delete local_fname;
|
---|
491 |
|
---|
492 | char network_tex_file[256];
|
---|
493 | i4_os_string(*network_fname,network_tex_file,256);
|
---|
494 | delete network_fname;
|
---|
495 |
|
---|
496 | i4_bool loaded = i4_F;
|
---|
497 |
|
---|
498 | w32 file_offs = dst_file->tell();
|
---|
499 |
|
---|
500 | //open the mip file from the network to get information on the mip levels
|
---|
501 | mipheader_t mipheader;
|
---|
502 |
|
---|
503 | i4_file_class *src_file = i4_open(i4_const_str(network_tex_file),I4_READ | I4_NO_BUFFER);
|
---|
504 | if (!src_file)
|
---|
505 | i4_warning("Couldn't open compressed texture: %s.", network_tex_file);
|
---|
506 |
|
---|
507 | void *file_buf = 0;
|
---|
508 | w32 file_size;
|
---|
509 |
|
---|
510 | if (src_file)
|
---|
511 | {
|
---|
512 | file_size = src_file->size();
|
---|
513 | file_buf = i4_malloc(file_size,"file buffer");
|
---|
514 |
|
---|
515 | src_file->read(file_buf,file_size);
|
---|
516 | delete src_file;
|
---|
517 |
|
---|
518 | src_file = new i4_ram_file_class(file_buf,file_size);
|
---|
519 | }
|
---|
520 |
|
---|
521 | if (src_file)
|
---|
522 | {
|
---|
523 | mipheader.read(src_file);
|
---|
524 |
|
---|
525 | loaded = r1_decompress_to_local_mip(src_file,
|
---|
526 | dst_file,
|
---|
527 | network_tex_file,
|
---|
528 | local_tex_file,
|
---|
529 | &mipheader,
|
---|
530 | max_texture_dimention);
|
---|
531 |
|
---|
532 | if (file_buf)
|
---|
533 | i4_free(file_buf);
|
---|
534 |
|
---|
535 | delete src_file;
|
---|
536 | }
|
---|
537 |
|
---|
538 | if (loaded)
|
---|
539 | {
|
---|
540 | t->id = id;
|
---|
541 | t->lowmipoffset = file_offs;
|
---|
542 | t->last_modified = network_file_date;
|
---|
543 | t->average_color = mipheader.average_color;
|
---|
544 | t->base_width = mipheader.base_width;
|
---|
545 | t->base_height = mipheader.base_height;
|
---|
546 | t->flags = mipheader.flags;
|
---|
547 | t->num_mip_levels = mipheader.num_mip_levels;
|
---|
548 | }
|
---|
549 | else
|
---|
550 | {
|
---|
551 | i4_warning("Failed to decompress %s. Try updating textures w/the maxtool.",network_tex_file);
|
---|
552 |
|
---|
553 | //be sure to set lowmipoffset to 0xFFFFFFFF and last_modified to 0 since the load failed
|
---|
554 | t->id = id;
|
---|
555 | t->lowmipoffset = 0xFFFFFFFF;
|
---|
556 | t->last_modified = 0;
|
---|
557 | t->average_color = 0;
|
---|
558 | t->base_width = 0;
|
---|
559 | t->base_height = 0;
|
---|
560 | t->flags = 0;
|
---|
561 | t->num_mip_levels = 0;
|
---|
562 | }
|
---|
563 | }
|
---|
564 |
|
---|
565 |
|
---|
566 | void r1_texture_manager_class::keep_cache_current(i4_array<w32> *file_ids)
|
---|
567 | {
|
---|
568 | tex_cache_header_t tex_cache_header;
|
---|
569 |
|
---|
570 | i4_file_class *cache_file = i4_open(r1_get_cache_file(),I4_READ | I4_NO_BUFFER);
|
---|
571 |
|
---|
572 | //does the cache file exist?
|
---|
573 | if (!cache_file)
|
---|
574 | {
|
---|
575 | //need to build a cache file
|
---|
576 | if (file_ids && file_ids->size())
|
---|
577 | build_cache_file(*file_ids, r1_get_compressed_dir(), r1_get_decompressed_dir());
|
---|
578 | }
|
---|
579 | else
|
---|
580 | {
|
---|
581 | //cache file exists, make sure its in the proper format
|
---|
582 | //if anything doesnt match, gotta rebuild
|
---|
583 | tex_cache_header.read(cache_file);
|
---|
584 |
|
---|
585 | if (
|
---|
586 | !palettes_are_same(&tex_cache_header.regular_format,®ular_format) ||
|
---|
587 | !palettes_are_same(&tex_cache_header.chroma_format,&chroma_format) ||
|
---|
588 | !palettes_are_same(&tex_cache_header.alpha_format,&alpha_format) ||
|
---|
589 | (tex_cache_header.max_mip_dimention < max_texture_dimention)
|
---|
590 | )
|
---|
591 | {
|
---|
592 | //close the old cache file
|
---|
593 | if (tex_cache_header.entries)
|
---|
594 | i4_free(tex_cache_header.entries);
|
---|
595 |
|
---|
596 | delete cache_file;
|
---|
597 | cache_file = 0;
|
---|
598 |
|
---|
599 | //build a new one
|
---|
600 | if (file_ids && file_ids->size())
|
---|
601 | build_cache_file(*file_ids,
|
---|
602 | r1_get_compressed_dir(),
|
---|
603 | r1_get_decompressed_dir());
|
---|
604 |
|
---|
605 | }
|
---|
606 | else
|
---|
607 | if (file_ids && file_ids->size())
|
---|
608 | {
|
---|
609 | //cache file was there (and in a compatible format) but we need to make sure it is up to date
|
---|
610 |
|
---|
611 | //yes. get directory information from the source compressed texture directory
|
---|
612 | i4_directory_struct ds;
|
---|
613 | i4_get_directory(r1_get_compressed_dir(), ds, i4_T);
|
---|
614 |
|
---|
615 | i4_array<file_status_sort_struct> sorted_status_indices(128,128);
|
---|
616 |
|
---|
617 | sw32 i;
|
---|
618 |
|
---|
619 | for (i=0; i<ds.tfiles; i++)
|
---|
620 | {
|
---|
621 | file_status_sort_struct s;
|
---|
622 | s.id = r1_get_file_id(*(ds.files[i]));
|
---|
623 | s.file_status_index = i;
|
---|
624 |
|
---|
625 | sorted_status_indices.add(s);
|
---|
626 | }
|
---|
627 |
|
---|
628 | sorted_status_indices.sort(file_status_struct_compare);
|
---|
629 |
|
---|
630 | i4_array<w32> ids_needing_update(128,128);
|
---|
631 |
|
---|
632 | //determine which textures need to be updated,
|
---|
633 | //and also determine if there are any NEW ones
|
---|
634 | //that need to be added to the cache
|
---|
635 |
|
---|
636 | for (i=0; i<file_ids->size(); i++)
|
---|
637 | {
|
---|
638 | w32 id = (*file_ids)[i];//r1_get_file_id(*ds.files[i]);
|
---|
639 |
|
---|
640 | tex_cache_entry_t *t = find_id_in_tex_cache(tex_cache_header.entries,
|
---|
641 | tex_cache_header.num_entries,id);
|
---|
642 |
|
---|
643 | if (!t || (t->lowmipoffset==0xFFFFFFFF))
|
---|
644 | {
|
---|
645 | if (t && t->lowmipoffset==0xFFFFFFFF)
|
---|
646 | {
|
---|
647 | //its not in the cache right now because the file didnt exist before
|
---|
648 | //if it exists now, add it to the update list. if not, well dont even try
|
---|
649 | //(this avoids creating an "update textures" wait everytime if a bunch of texture files
|
---|
650 | // just dont exist)
|
---|
651 | file_status_sort_struct s;
|
---|
652 | s.id = id;
|
---|
653 |
|
---|
654 | sw32 location = sorted_status_indices.binary_search(&s,file_status_struct_compare);
|
---|
655 | if (location != -1)
|
---|
656 | {
|
---|
657 | //yeah, its in the directory, add it to the update list
|
---|
658 | ids_needing_update.add(id);
|
---|
659 | }
|
---|
660 | }
|
---|
661 | else
|
---|
662 | {
|
---|
663 | //its not in the cache. add it
|
---|
664 | ids_needing_update.add(id);
|
---|
665 | }
|
---|
666 | }
|
---|
667 | else
|
---|
668 | {
|
---|
669 | //it is in the cache. make sure its current. if the file does not exist, dont
|
---|
670 | //add it
|
---|
671 |
|
---|
672 | file_status_sort_struct s;
|
---|
673 | s.id = id;
|
---|
674 |
|
---|
675 | if (id==0x0f6dbf86)
|
---|
676 | {
|
---|
677 | int a;
|
---|
678 | a=0;
|
---|
679 | }
|
---|
680 |
|
---|
681 | sw32 location = sorted_status_indices.binary_search(&s,file_status_struct_compare);
|
---|
682 |
|
---|
683 | //it exists in the directory. if the directory file is more recent than ours, update it.
|
---|
684 | //if it doesnt exist, well then obviously dont update it.
|
---|
685 | if (location != -1)
|
---|
686 | {
|
---|
687 | if (ds.file_status[sorted_status_indices[location].file_status_index].last_modified > t->last_modified)
|
---|
688 | {
|
---|
689 | //must update this texture
|
---|
690 | ids_needing_update.add(id);
|
---|
691 | }
|
---|
692 | }
|
---|
693 | }
|
---|
694 | }
|
---|
695 |
|
---|
696 |
|
---|
697 | if (tex_cache_header.entries)
|
---|
698 | i4_free(tex_cache_header.entries);
|
---|
699 |
|
---|
700 | delete cache_file;
|
---|
701 | cache_file = 0;
|
---|
702 |
|
---|
703 | //does anything need updating?
|
---|
704 | if (ids_needing_update.size())
|
---|
705 | {
|
---|
706 | //yes. delete this old data and re-read it after we've updated the cache file
|
---|
707 | update_cache_file(ids_needing_update,
|
---|
708 | r1_get_compressed_dir(),
|
---|
709 | r1_get_decompressed_dir());
|
---|
710 | }
|
---|
711 | }
|
---|
712 | else
|
---|
713 | {
|
---|
714 | if (tex_cache_header.entries)
|
---|
715 | i4_free(tex_cache_header.entries);
|
---|
716 |
|
---|
717 | delete cache_file;
|
---|
718 | cache_file = 0;
|
---|
719 | }
|
---|
720 | }
|
---|
721 |
|
---|
722 | if (cache_file)
|
---|
723 | {
|
---|
724 | i4_warning("unhandled case: keep_cache_current");
|
---|
725 | }
|
---|
726 | }
|
---|