98e75f2d |
1 | /* |
2 | * Texture Filtering |
3 | * Version: 1.0 |
4 | * |
5 | * Copyright (C) 2007 Hiroshi Morii All Rights Reserved. |
6 | * Email koolsmoky(at)users.sourceforge.net |
7 | * Web http://www.3dfxzone.it/koolsmoky |
8 | * |
9 | * this is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License as published by |
11 | * the Free Software Foundation; either version 2, or (at your option) |
12 | * any later version. |
13 | * |
14 | * this is distributed in the hope that it will be useful, |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | * GNU General Public License for more details. |
18 | * |
19 | * You should have received a copy of the GNU General Public License |
20 | * along with GNU Make; see the file COPYING. If not, write to |
21 | * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. |
22 | */ |
23 | |
24 | #ifdef __MSC__ |
25 | #pragma warning(disable: 4786) |
26 | #endif |
27 | |
28 | #include <boost/filesystem.hpp> |
29 | #include <zlib.h> |
30 | #include "TxCache.h" |
31 | #include "TxDbg.h" |
32 | #include "../Glide64/m64p.h" |
33 | #include "../Glide64/Gfx_1.3.h" |
34 | |
35 | TxCache::~TxCache() |
36 | { |
37 | /* free memory, clean up, etc */ |
38 | clear(); |
39 | |
40 | delete _txUtil; |
41 | } |
42 | |
43 | TxCache::TxCache(int options, int cachesize, const wchar_t *datapath, |
44 | const wchar_t *cachepath, const wchar_t *ident, |
45 | dispInfoFuncExt callback) |
46 | { |
47 | _txUtil = new TxUtil(); |
48 | |
49 | _options = options; |
50 | _cacheSize = cachesize; |
51 | _callback = callback; |
52 | _totalSize = 0; |
53 | |
54 | /* save path name */ |
55 | if (datapath) |
56 | _datapath.assign(datapath); |
57 | if (cachepath) |
58 | _cachepath.assign(cachepath); |
59 | |
60 | /* save ROM name */ |
61 | if (ident) |
62 | _ident.assign(ident); |
63 | |
64 | /* zlib memory buffers to (de)compress hires textures */ |
65 | if (_options & (GZ_TEXCACHE|GZ_HIRESTEXCACHE)) { |
66 | _gzdest0 = TxMemBuf::getInstance()->get(0); |
67 | _gzdest1 = TxMemBuf::getInstance()->get(1); |
68 | _gzdestLen = (TxMemBuf::getInstance()->size_of(0) < TxMemBuf::getInstance()->size_of(1)) ? |
69 | TxMemBuf::getInstance()->size_of(0) : TxMemBuf::getInstance()->size_of(1); |
70 | |
71 | if (!_gzdest0 || !_gzdest1 || !_gzdestLen) { |
72 | _options &= ~(GZ_TEXCACHE|GZ_HIRESTEXCACHE); |
73 | _gzdest0 = NULL; |
74 | _gzdest1 = NULL; |
75 | _gzdestLen = 0; |
76 | } |
77 | } |
78 | } |
79 | |
80 | boolean |
81 | TxCache::add(uint64 checksum, GHQTexInfo *info, int dataSize) |
82 | { |
83 | /* NOTE: dataSize must be provided if info->data is zlib compressed. */ |
84 | |
85 | if (!checksum || !info->data) return 0; |
86 | |
87 | uint8 *dest = info->data; |
88 | uint16 format = info->format; |
89 | |
90 | if (!dataSize) { |
91 | dataSize = _txUtil->sizeofTx(info->width, info->height, info->format); |
92 | |
93 | if (!dataSize) return 0; |
94 | |
95 | if (_options & (GZ_TEXCACHE|GZ_HIRESTEXCACHE)) { |
96 | /* zlib compress it. compression level:1 (best speed) */ |
97 | uLongf destLen = _gzdestLen; |
98 | dest = (dest == _gzdest0) ? _gzdest1 : _gzdest0; |
99 | if (compress2(dest, &destLen, info->data, dataSize, 1) != Z_OK) { |
100 | dest = info->data; |
101 | DBG_INFO(80, L"Error: zlib compression failed!\n"); |
102 | } else { |
103 | DBG_INFO(80, L"zlib compressed: %.02fkb->%.02fkb\n", (float)dataSize/1000, (float)destLen/1000); |
104 | dataSize = destLen; |
105 | format |= GR_TEXFMT_GZ; |
106 | } |
107 | } |
108 | } |
109 | |
110 | /* if cache size exceeds limit, remove old cache */ |
111 | if (_cacheSize > 0) { |
112 | _totalSize += dataSize; |
113 | if ((_totalSize > _cacheSize) && !_cachelist.empty()) { |
114 | /* _cachelist is arranged so that frequently used textures are in the back */ |
115 | std::list<uint64>::iterator itList = _cachelist.begin(); |
116 | while (itList != _cachelist.end()) { |
117 | /* find it in _cache */ |
118 | std::map<uint64, TXCACHE*>::iterator itMap = _cache.find(*itList); |
119 | if (itMap != _cache.end()) { |
120 | /* yep we have it. remove it. */ |
121 | _totalSize -= (*itMap).second->size; |
122 | free((*itMap).second->info.data); |
123 | delete (*itMap).second; |
124 | _cache.erase(itMap); |
125 | } |
126 | itList++; |
127 | |
128 | /* check if memory cache has enough space */ |
129 | if (_totalSize <= _cacheSize) |
130 | break; |
131 | } |
132 | /* remove from _cachelist */ |
133 | _cachelist.erase(_cachelist.begin(), itList); |
134 | |
135 | DBG_INFO(80, L"+++++++++\n"); |
136 | } |
137 | _totalSize -= dataSize; |
138 | } |
139 | |
140 | /* cache it */ |
141 | uint8 *tmpdata = (uint8*)malloc(dataSize); |
142 | if (tmpdata) { |
143 | TXCACHE *txCache = new TXCACHE; |
144 | if (txCache) { |
145 | /* we can directly write as we filter, but for now we get away |
146 | * with doing memcpy after all the filtering is done. |
147 | */ |
148 | memcpy(tmpdata, dest, dataSize); |
149 | |
150 | /* copy it */ |
151 | memcpy(&txCache->info, info, sizeof(GHQTexInfo)); |
152 | txCache->info.data = tmpdata; |
153 | txCache->info.format = format; |
154 | txCache->size = dataSize; |
155 | |
156 | /* add to cache */ |
157 | if (_cacheSize > 0) { |
158 | _cachelist.push_back(checksum); |
159 | txCache->it = --(_cachelist.end()); |
160 | } |
161 | /* _cache[checksum] = txCache; */ |
162 | _cache.insert(std::map<uint64, TXCACHE*>::value_type(checksum, txCache)); |
163 | |
164 | #ifdef DEBUG |
165 | DBG_INFO(80, L"[%5d] added!! crc:%08X %08X %d x %d gfmt:%x total:%.02fmb\n", |
166 | _cache.size(), (uint32)(checksum >> 32), (uint32)(checksum & 0xffffffff), |
167 | info->width, info->height, info->format, (float)_totalSize/1000000); |
168 | |
169 | DBG_INFO(80, L"smalllodlog2:%d largelodlog2:%d aspectratiolog2:%d\n", |
170 | txCache->info.smallLodLog2, txCache->info.largeLodLog2, txCache->info.aspectRatioLog2); |
171 | |
172 | if (info->tiles) { |
173 | DBG_INFO(80, L"tiles:%d un-tiled size:%d x %d\n", info->tiles, info->untiled_width, info->untiled_height); |
174 | } |
175 | |
176 | if (_cacheSize > 0) { |
177 | DBG_INFO(80, L"cache max config:%.02fmb\n", (float)_cacheSize/1000000); |
178 | |
179 | if (_cache.size() != _cachelist.size()) { |
180 | DBG_INFO(80, L"Error: cache/cachelist mismatch! (%d/%d)\n", _cache.size(), _cachelist.size()); |
181 | } |
182 | } |
183 | #endif |
184 | |
185 | /* total cache size */ |
186 | _totalSize += dataSize; |
187 | |
188 | return 1; |
189 | } |
190 | free(tmpdata); |
191 | } |
192 | |
193 | return 0; |
194 | } |
195 | |
196 | boolean |
197 | TxCache::get(uint64 checksum, GHQTexInfo *info) |
198 | { |
199 | if (!checksum || _cache.empty()) return 0; |
200 | |
201 | /* find a match in cache */ |
202 | std::map<uint64, TXCACHE*>::iterator itMap = _cache.find(checksum); |
203 | if (itMap != _cache.end()) { |
204 | /* yep, we've got it. */ |
205 | memcpy(info, &(((*itMap).second)->info), sizeof(GHQTexInfo)); |
206 | |
207 | /* push it to the back of the list */ |
208 | if (_cacheSize > 0) { |
209 | _cachelist.erase(((*itMap).second)->it); |
210 | _cachelist.push_back(checksum); |
211 | ((*itMap).second)->it = --(_cachelist.end()); |
212 | } |
213 | |
214 | /* zlib decompress it */ |
215 | if (info->format & GR_TEXFMT_GZ) { |
216 | uLongf destLen = _gzdestLen; |
217 | uint8 *dest = (_gzdest0 == info->data) ? _gzdest1 : _gzdest0; |
218 | if (uncompress(dest, &destLen, info->data, ((*itMap).second)->size) != Z_OK) { |
219 | DBG_INFO(80, L"Error: zlib decompression failed!\n"); |
220 | return 0; |
221 | } |
222 | info->data = dest; |
223 | info->format &= ~GR_TEXFMT_GZ; |
224 | DBG_INFO(80, L"zlib decompressed: %.02fkb->%.02fkb\n", (float)(((*itMap).second)->size)/1000, (float)destLen/1000); |
225 | } |
226 | |
227 | return 1; |
228 | } |
229 | |
230 | return 0; |
231 | } |
232 | |
233 | boolean |
234 | TxCache::save(const wchar_t *path, const wchar_t *filename, int config) |
235 | { |
236 | if (!_cache.empty()) { |
237 | /* dump cache to disk */ |
238 | char cbuf[MAX_PATH]; |
239 | |
240 | boost::filesystem::wpath cachepath(path); |
241 | boost::filesystem::create_directory(cachepath); |
242 | |
243 | /* Ugly hack to enable fopen/gzopen in Win9x */ |
244 | #ifdef BOOST_WINDOWS_API |
245 | wchar_t curpath[MAX_PATH]; |
246 | GETCWD(MAX_PATH, curpath); |
247 | CHDIR(cachepath.wstring().c_str()); |
248 | #else |
249 | char curpath[MAX_PATH]; |
250 | wcstombs(cbuf, cachepath.wstring().c_str(), MAX_PATH); |
251 | if (GETCWD(MAX_PATH, curpath) == NULL) |
252 | ERRLOG("Error while retrieving working directory!"); |
253 | if (CHDIR(cbuf) != 0) |
254 | ERRLOG("Error while changing current directory to '%s'!", cbuf); |
255 | #endif |
256 | |
257 | wcstombs(cbuf, filename, MAX_PATH); |
258 | |
259 | gzFile gzfp = gzopen(cbuf, "wb1"); |
260 | DBG_INFO(80, L"gzfp:%x file:%ls\n", gzfp, filename); |
261 | if (gzfp) { |
262 | /* write header to determine config match */ |
263 | gzwrite(gzfp, &config, 4); |
264 | |
265 | std::map<uint64, TXCACHE*>::iterator itMap = _cache.begin(); |
266 | while (itMap != _cache.end()) { |
267 | uint8 *dest = (*itMap).second->info.data; |
268 | uint32 destLen = (*itMap).second->size; |
269 | uint16 format = (*itMap).second->info.format; |
270 | |
271 | /* to keep things simple, we save the texture data in a zlib uncompressed state. */ |
272 | /* sigh... for those who cannot wait the extra few seconds. changed to keep |
273 | * texture data in a zlib compressed state. if the GZ_TEXCACHE or GZ_HIRESTEXCACHE |
274 | * option is toggled, the cache will need to be rebuilt. |
275 | */ |
276 | /*if (format & GR_TEXFMT_GZ) { |
277 | dest = _gzdest0; |
278 | destLen = _gzdestLen; |
279 | if (dest && destLen) { |
280 | if (uncompress(dest, &destLen, (*itMap).second->info.data, (*itMap).second->size) != Z_OK) { |
281 | dest = NULL; |
282 | destLen = 0; |
283 | } |
284 | format &= ~GR_TEXFMT_GZ; |
285 | } |
286 | }*/ |
287 | |
288 | if (dest && destLen) { |
289 | /* texture checksum */ |
290 | gzwrite(gzfp, &((*itMap).first), 8); |
291 | |
292 | /* other texture info */ |
293 | gzwrite(gzfp, &((*itMap).second->info.width), 4); |
294 | gzwrite(gzfp, &((*itMap).second->info.height), 4); |
295 | gzwrite(gzfp, &format, 2); |
296 | |
297 | gzwrite(gzfp, &((*itMap).second->info.smallLodLog2), 4); |
298 | gzwrite(gzfp, &((*itMap).second->info.largeLodLog2), 4); |
299 | gzwrite(gzfp, &((*itMap).second->info.aspectRatioLog2), 4); |
300 | |
301 | gzwrite(gzfp, &((*itMap).second->info.tiles), 4); |
302 | gzwrite(gzfp, &((*itMap).second->info.untiled_width), 4); |
303 | gzwrite(gzfp, &((*itMap).second->info.untiled_height), 4); |
304 | |
305 | gzwrite(gzfp, &((*itMap).second->info.is_hires_tex), 1); |
306 | |
307 | gzwrite(gzfp, &destLen, 4); |
308 | gzwrite(gzfp, dest, destLen); |
309 | } |
310 | |
311 | itMap++; |
312 | |
313 | /* not ready yet */ |
314 | /*if (_callback) |
315 | (*_callback)(L"Total textures saved to HDD: %d\n", std::distance(itMap, _cache.begin()));*/ |
316 | } |
317 | gzclose(gzfp); |
318 | } |
319 | |
320 | if (CHDIR(curpath) != 0) |
321 | ERRLOG("Error while changing current directory back to original path of '%s'!", curpath); |
322 | } |
323 | |
324 | return _cache.empty(); |
325 | } |
326 | |
327 | boolean |
328 | TxCache::load(const wchar_t *path, const wchar_t *filename, int config) |
329 | { |
330 | /* find it on disk */ |
331 | char cbuf[MAX_PATH]; |
332 | |
333 | boost::filesystem::wpath cachepath(path); |
334 | |
335 | #ifdef BOOST_WINDOWS_API |
336 | wchar_t curpath[MAX_PATH]; |
337 | GETCWD(MAX_PATH, curpath); |
338 | CHDIR(cachepath.wstring().c_str()); |
339 | #else |
340 | char curpath[MAX_PATH]; |
341 | wcstombs(cbuf, cachepath.wstring().c_str(), MAX_PATH); |
342 | if (GETCWD(MAX_PATH, curpath) == NULL) |
343 | ERRLOG("Error while retrieving working directory!"); |
344 | if (CHDIR(cbuf) != 0) |
345 | ERRLOG("Error while changing current directory to '%s'!", cbuf); |
346 | #endif |
347 | |
348 | wcstombs(cbuf, filename, MAX_PATH); |
349 | |
350 | gzFile gzfp = gzopen(cbuf, "rb"); |
351 | DBG_INFO(80, L"gzfp:%x file:%ls\n", gzfp, filename); |
352 | if (gzfp) { |
353 | /* yep, we have it. load it into memory cache. */ |
354 | int dataSize; |
355 | uint64 checksum; |
356 | GHQTexInfo tmpInfo; |
357 | int tmpconfig; |
358 | /* read header to determine config match */ |
359 | gzread(gzfp, &tmpconfig, 4); |
360 | |
361 | if (tmpconfig == config) { |
362 | do { |
363 | memset(&tmpInfo, 0, sizeof(GHQTexInfo)); |
364 | |
365 | gzread(gzfp, &checksum, 8); |
366 | |
367 | gzread(gzfp, &tmpInfo.width, 4); |
368 | gzread(gzfp, &tmpInfo.height, 4); |
369 | gzread(gzfp, &tmpInfo.format, 2); |
370 | |
371 | gzread(gzfp, &tmpInfo.smallLodLog2, 4); |
372 | gzread(gzfp, &tmpInfo.largeLodLog2, 4); |
373 | gzread(gzfp, &tmpInfo.aspectRatioLog2, 4); |
374 | |
375 | gzread(gzfp, &tmpInfo.tiles, 4); |
376 | gzread(gzfp, &tmpInfo.untiled_width, 4); |
377 | gzread(gzfp, &tmpInfo.untiled_height, 4); |
378 | |
379 | gzread(gzfp, &tmpInfo.is_hires_tex, 1); |
380 | |
381 | gzread(gzfp, &dataSize, 4); |
382 | |
383 | tmpInfo.data = (uint8*)malloc(dataSize); |
384 | if (tmpInfo.data) { |
385 | gzread(gzfp, tmpInfo.data, dataSize); |
386 | |
387 | /* add to memory cache */ |
388 | add(checksum, &tmpInfo, (tmpInfo.format & GR_TEXFMT_GZ) ? dataSize : 0); |
389 | |
390 | free(tmpInfo.data); |
391 | } else { |
392 | gzseek(gzfp, dataSize, SEEK_CUR); |
393 | } |
394 | |
395 | /* skip in between to prevent the loop from being tied down to vsync */ |
396 | if (_callback && (!(_cache.size() % 100) || gzeof(gzfp))) |
397 | (*_callback)(L"[%d] total mem:%.02fmb - %ls\n", _cache.size(), (float)_totalSize/1000000, filename); |
398 | |
399 | } while (!gzeof(gzfp)); |
400 | gzclose(gzfp); |
401 | } else { |
402 | if ((tmpconfig & HIRESTEXTURES_MASK) != (config & HIRESTEXTURES_MASK)) { |
403 | const char *conf_str; |
404 | if ((tmpconfig & HIRESTEXTURES_MASK) == NO_HIRESTEXTURES) |
405 | conf_str = "0"; |
406 | else if ((tmpconfig & HIRESTEXTURES_MASK) == RICE_HIRESTEXTURES) |
407 | conf_str = "1"; |
408 | else |
409 | conf_str = "set to an unsupported format"; |
410 | |
411 | WriteLog(M64MSG_WARNING, "Ignored texture cache due to incompatible setting: ghq_hirs must be %s", conf_str); |
412 | } |
413 | if ((tmpconfig & COMPRESS_HIRESTEX) != (config & COMPRESS_HIRESTEX)) |
414 | WriteLog(M64MSG_WARNING, "Ignored texture cache due to incompatible setting: ghq_hirs_cmpr must be %s", (tmpconfig & COMPRESS_HIRESTEX) ? "True" : "False"); |
415 | if ((tmpconfig & COMPRESSION_MASK) != (config & COMPRESSION_MASK) && (tmpconfig & COMPRESS_HIRESTEX)) { |
416 | const char *conf_str; |
417 | if ((tmpconfig & COMPRESSION_MASK) == FXT1_COMPRESSION) |
418 | conf_str = "1"; |
419 | else if ((tmpconfig & COMPRESSION_MASK) == S3TC_COMPRESSION) |
420 | conf_str = "0"; |
421 | else |
422 | conf_str = "set to an unsupported format"; |
423 | |
424 | WriteLog(M64MSG_WARNING, "Ignored texture cache due to incompatible setting: ghq_cmpr must be %s", conf_str); |
425 | } |
426 | if ((tmpconfig & TILE_HIRESTEX) != (config & TILE_HIRESTEX)) |
427 | WriteLog(M64MSG_WARNING, "Ignored texture cache due to incompatible setting: ghq_hirs_tile must be %s", (tmpconfig & TILE_HIRESTEX) ? "True" : "False"); |
428 | if ((tmpconfig & FORCE16BPP_HIRESTEX) != (config & FORCE16BPP_HIRESTEX)) |
429 | WriteLog(M64MSG_WARNING, "Ignored texture cache due to incompatible setting: ghq_hirs_f16bpp must be %s", (tmpconfig & FORCE16BPP_HIRESTEX) ? "True" : "False"); |
430 | if ((tmpconfig & GZ_HIRESTEXCACHE) != (config & GZ_HIRESTEXCACHE)) |
431 | WriteLog(M64MSG_WARNING, "ghq_hirs_gz must be %s", (tmpconfig & GZ_HIRESTEXCACHE) ? "True" : "False"); |
432 | if ((tmpconfig & LET_TEXARTISTS_FLY) != (config & LET_TEXARTISTS_FLY)) |
433 | WriteLog(M64MSG_WARNING, "Ignored texture cache due to incompatible setting: ghq_hirs_let_texartists_fly must be %s", (tmpconfig & LET_TEXARTISTS_FLY) ? "True" : "False"); |
434 | |
435 | if ((tmpconfig & FILTER_MASK) != (config & FILTER_MASK)) { |
436 | const char *conf_str; |
437 | if ((tmpconfig & FILTER_MASK) == NO_FILTER) |
438 | conf_str = "0"; |
439 | else if ((tmpconfig & FILTER_MASK) == SMOOTH_FILTER_1) |
440 | conf_str = "1"; |
441 | else if ((tmpconfig & FILTER_MASK) == SMOOTH_FILTER_2) |
442 | conf_str = "2"; |
443 | else if ((tmpconfig & FILTER_MASK) == SMOOTH_FILTER_3) |
444 | conf_str = "3"; |
445 | else if ((tmpconfig & FILTER_MASK) == SMOOTH_FILTER_4) |
446 | conf_str = "4"; |
447 | else if ((tmpconfig & FILTER_MASK) == SHARP_FILTER_1) |
448 | conf_str = "5"; |
449 | else if ((tmpconfig & FILTER_MASK) == SHARP_FILTER_2) |
450 | conf_str = "6"; |
451 | else |
452 | conf_str = "set to an unsupported format"; |
453 | WriteLog(M64MSG_WARNING, "Ignored texture cache due to incompatible setting: ghq_fltr must be %s", conf_str); |
454 | } |
455 | |
456 | if ((tmpconfig & ENHANCEMENT_MASK) != (config & ENHANCEMENT_MASK)) { |
457 | const char *conf_str; |
458 | if ((tmpconfig & ENHANCEMENT_MASK) == NO_ENHANCEMENT) |
459 | conf_str = "0"; |
460 | else if ((tmpconfig & ENHANCEMENT_MASK) == X2_ENHANCEMENT) |
461 | conf_str = "2"; |
462 | else if ((tmpconfig & ENHANCEMENT_MASK) == X2SAI_ENHANCEMENT) |
463 | conf_str = "3"; |
464 | else if ((tmpconfig & ENHANCEMENT_MASK) == HQ2X_ENHANCEMENT) |
465 | conf_str = "4"; |
466 | else if ((tmpconfig & ENHANCEMENT_MASK) == HQ2XS_ENHANCEMENT) |
467 | conf_str = "5"; |
468 | else if ((tmpconfig & ENHANCEMENT_MASK) == LQ2X_ENHANCEMENT) |
469 | conf_str = "6"; |
470 | else if ((tmpconfig & ENHANCEMENT_MASK) == LQ2XS_ENHANCEMENT) |
471 | conf_str = "7"; |
472 | else if ((tmpconfig & ENHANCEMENT_MASK) == HQ4X_ENHANCEMENT) |
473 | conf_str = "8"; |
474 | else |
475 | conf_str = "set to an unsupported format"; |
476 | WriteLog(M64MSG_WARNING, "Ignored texture cache due to incompatible setting: ghq_enht must be %s", conf_str); |
477 | } |
478 | |
479 | if ((tmpconfig & COMPRESS_TEX) != (config & COMPRESS_TEX)) |
480 | WriteLog(M64MSG_WARNING, "Ignored texture cache due to incompatible setting: ghq_enht_cmpr must be %s", (tmpconfig & COMPRESS_TEX) ? "True" : "False"); |
481 | if ((tmpconfig & FORCE16BPP_TEX) != (config & FORCE16BPP_TEX)) |
482 | WriteLog(M64MSG_WARNING, "Ignored texture cache due to incompatible setting: ghq_enht_f16bpp must be %s", (tmpconfig & FORCE16BPP_TEX) ? "True" : "False"); |
483 | if ((tmpconfig & GZ_TEXCACHE) != (config & GZ_TEXCACHE)) |
484 | WriteLog(M64MSG_WARNING, "Ignored texture cache due to incompatible setting: ghq_enht_gz must be %s", (tmpconfig & GZ_TEXCACHE) ? "True" : "False"); |
485 | } |
486 | } |
487 | |
488 | if (CHDIR(curpath) != 0) |
489 | ERRLOG("Error while changing current directory back to original path of '%s'!", curpath); |
490 | |
491 | return !_cache.empty(); |
492 | } |
493 | |
494 | boolean |
495 | TxCache::del(uint64 checksum) |
496 | { |
497 | if (!checksum || _cache.empty()) return 0; |
498 | |
499 | std::map<uint64, TXCACHE*>::iterator itMap = _cache.find(checksum); |
500 | if (itMap != _cache.end()) { |
501 | |
502 | /* for texture cache (not hi-res cache) */ |
503 | if (!_cachelist.empty()) _cachelist.erase(((*itMap).second)->it); |
504 | |
505 | /* remove from cache */ |
506 | free((*itMap).second->info.data); |
507 | _totalSize -= (*itMap).second->size; |
508 | delete (*itMap).second; |
509 | _cache.erase(itMap); |
510 | |
511 | DBG_INFO(80, L"removed from cache: checksum = %08X %08X\n", (uint32)(checksum & 0xffffffff), (uint32)(checksum >> 32)); |
512 | |
513 | return 1; |
514 | } |
515 | |
516 | return 0; |
517 | } |
518 | |
519 | boolean |
520 | TxCache::is_cached(uint64 checksum) |
521 | { |
522 | std::map<uint64, TXCACHE*>::iterator itMap = _cache.find(checksum); |
523 | if (itMap != _cache.end()) return 1; |
524 | |
525 | return 0; |
526 | } |
527 | |
528 | void |
529 | TxCache::clear() |
530 | { |
531 | if (!_cache.empty()) { |
532 | std::map<uint64, TXCACHE*>::iterator itMap = _cache.begin(); |
533 | while (itMap != _cache.end()) { |
534 | free((*itMap).second->info.data); |
535 | delete (*itMap).second; |
536 | itMap++; |
537 | } |
538 | _cache.clear(); |
539 | } |
540 | |
541 | if (!_cachelist.empty()) _cachelist.clear(); |
542 | |
543 | _totalSize = 0; |
544 | } |