TxTexCache::~TxTexCache() { #if DUMP_CACHE if (_options & DUMP_TEXCACHE) { /* dump cache to disk */ std::wstring filename = _ident + L"_MEMORYCACHE.dat"; boost::filesystem::wpath cachepath(_path); cachepath /= boost::filesystem::wpath(L"cache"); int config = _options & (FILTER_MASK|ENHANCEMENT_MASK|COMPRESS_TEX|COMPRESSION_MASK|FORCE16BPP_TEX|GZ_TEXCACHE); TxCache::save(cachepath.string().c_str(), filename.c_str(), config); } #endif }
TxTexCache::~TxTexCache() { #if DUMP_CACHE if (_options & DUMP_TEXCACHE) { /* dump cache to disk */ std::wstring filename = _ident + L"_MEMORYCACHE.dat"; CPath cachepath(stdstr().FromUTF16(_path.c_str()).c_str(),""); cachepath.AppendDirectory("cache"); int config = _options & (FILTER_MASK|ENHANCEMENT_MASK|COMPRESS_TEX|COMPRESSION_MASK|FORCE16BPP_TEX|GZ_TEXCACHE); TxCache::save(stdstr((std::string &)cachepath).ToUTF16().c_str(), filename.c_str(), config); } #endif }
TxTexCache::TxTexCache(int options, int cachesize, const wchar_t *path, const wchar_t *ident, dispInfoFuncExt callback ) : TxCache((options & ~GZ_HIRESTEXCACHE), cachesize, path, ident, callback) { /* assert local options */ if (_path.empty() || _ident.empty() || !_cacheSize) _options &= ~DUMP_TEXCACHE; #if DUMP_CACHE if (_options & DUMP_TEXCACHE) { /* find it on disk */ std::wstring filename = _ident + L"_MEMORYCACHE.dat"; CPath cachepath(stdstr().FromUTF16(_path.c_str()),""); cachepath.AppendDirectory("cache"); int config = _options & (FILTER_MASK|ENHANCEMENT_MASK|COMPRESS_TEX|COMPRESSION_MASK|FORCE16BPP_TEX|GZ_TEXCACHE); TxCache::load(stdstr((std::string &)cachepath).ToUTF16().c_str(), filename.c_str(), config); } #endif }
TxTexCache::TxTexCache(int options, int cachesize, const wchar_t *path, const wchar_t *ident, dispInfoFuncExt callback ) : TxCache((options & ~GZ_HIRESTEXCACHE), cachesize, path, ident, callback) { /* assert local options */ if (_path.empty() || _ident.empty() || !_cacheSize) _options &= ~DUMP_TEXCACHE; #if DUMP_CACHE if (_options & DUMP_TEXCACHE) { /* find it on disk */ std::wstring filename = _ident + L"_MEMORYCACHE.dat"; boost::filesystem::wpath cachepath(_path); cachepath /= boost::filesystem::wpath(L"cache"); int config = _options & (FILTER_MASK|ENHANCEMENT_MASK|COMPRESS_TEX|COMPRESSION_MASK|FORCE16BPP_TEX|GZ_TEXCACHE); TxCache::load(cachepath.string().c_str(), filename.c_str(), config); } #endif }
boolean TxCache::load(const wchar_t *path, const wchar_t *filename, int config) { /* find it on disk */ char cbuf[MAX_PATH]; boost::filesystem::wpath cachepath(path); #ifdef BOOST_WINDOWS_API wchar_t curpath[MAX_PATH]; GETCWD(MAX_PATH, curpath); CHDIR(cachepath.wstring().c_str()); #else char curpath[MAX_PATH]; wcstombs(cbuf, cachepath.wstring().c_str(), MAX_PATH); GETCWD(MAX_PATH, curpath); CHDIR(cbuf); #endif wcstombs(cbuf, filename, MAX_PATH); gzFile gzfp = gzopen(cbuf, "rb"); DBG_INFO(80, L"gzfp:%x file:%ls\n", gzfp, filename); if (gzfp) { /* yep, we have it. load it into memory cache. */ int dataSize; uint64 checksum; GHQTexInfo tmpInfo; int tmpconfig; /* read header to determine config match */ gzread(gzfp, &tmpconfig, 4); if (tmpconfig == config) { do { memset(&tmpInfo, 0, sizeof(GHQTexInfo)); gzread(gzfp, &checksum, 8); gzread(gzfp, &tmpInfo.width, 4); gzread(gzfp, &tmpInfo.height, 4); gzread(gzfp, &tmpInfo.format, 2); gzread(gzfp, &tmpInfo.smallLodLog2, 4); gzread(gzfp, &tmpInfo.largeLodLog2, 4); gzread(gzfp, &tmpInfo.aspectRatioLog2, 4); gzread(gzfp, &tmpInfo.tiles, 4); gzread(gzfp, &tmpInfo.untiled_width, 4); gzread(gzfp, &tmpInfo.untiled_height, 4); gzread(gzfp, &tmpInfo.is_hires_tex, 1); gzread(gzfp, &dataSize, 4); tmpInfo.data = (uint8*)malloc(dataSize); if (tmpInfo.data) { gzread(gzfp, tmpInfo.data, dataSize); /* add to memory cache */ add(checksum, &tmpInfo, (tmpInfo.format & GR_TEXFMT_GZ) ? dataSize : 0); free(tmpInfo.data); } else { gzseek(gzfp, dataSize, SEEK_CUR); } /* skip in between to prevent the loop from being tied down to vsync */ if (_callback && (!(_cache.size() % 100) || gzeof(gzfp))) (*_callback)(L"[%d] total mem:%.02fmb - %ls\n", _cache.size(), (float)_totalSize/1000000, filename); } while (!gzeof(gzfp)); gzclose(gzfp); } else { if ((tmpconfig & HIRESTEXTURES_MASK) != (config & HIRESTEXTURES_MASK)) { const char *conf_str; if ((tmpconfig & HIRESTEXTURES_MASK) == NO_HIRESTEXTURES) conf_str = "0"; else if ((tmpconfig & HIRESTEXTURES_MASK) == RICE_HIRESTEXTURES) conf_str = "1"; else conf_str = "set to an unsupported format"; WriteLog(M64MSG_WARNING, "Ignored texture cache due to incompatible setting: ghq_hirs must be %s", conf_str); } if ((tmpconfig & COMPRESS_HIRESTEX) != (config & COMPRESS_HIRESTEX)) WriteLog(M64MSG_WARNING, "Ignored texture cache due to incompatible setting: ghq_hirs_cmpr must be %s", (tmpconfig & COMPRESS_HIRESTEX) ? "True" : "False"); if ((tmpconfig & COMPRESSION_MASK) != (config & COMPRESSION_MASK) && (tmpconfig & COMPRESS_HIRESTEX)) { const char *conf_str; if ((tmpconfig & COMPRESSION_MASK) == FXT1_COMPRESSION) conf_str = "1"; else if ((tmpconfig & COMPRESSION_MASK) == S3TC_COMPRESSION) conf_str = "0"; else conf_str = "set to an unsupported format"; WriteLog(M64MSG_WARNING, "Ignored texture cache due to incompatible setting: ghq_cmpr must be %s", conf_str); } if ((tmpconfig & TILE_HIRESTEX) != (config & TILE_HIRESTEX)) WriteLog(M64MSG_WARNING, "Ignored texture cache due to incompatible setting: ghq_hirs_tile must be %s", (tmpconfig & TILE_HIRESTEX) ? "True" : "False"); if ((tmpconfig & FORCE16BPP_HIRESTEX) != (config & FORCE16BPP_HIRESTEX)) WriteLog(M64MSG_WARNING, "Ignored texture cache due to incompatible setting: ghq_hirs_f16bpp must be %s", (tmpconfig & FORCE16BPP_HIRESTEX) ? "True" : "False"); if ((tmpconfig & GZ_HIRESTEXCACHE) != (config & GZ_HIRESTEXCACHE)) WriteLog(M64MSG_WARNING, "ghq_hirs_gz must be %s", (tmpconfig & GZ_HIRESTEXCACHE) ? "True" : "False"); if ((tmpconfig & LET_TEXARTISTS_FLY) != (config & LET_TEXARTISTS_FLY)) WriteLog(M64MSG_WARNING, "Ignored texture cache due to incompatible setting: ghq_hirs_let_texartists_fly must be %s", (tmpconfig & LET_TEXARTISTS_FLY) ? "True" : "False"); if ((tmpconfig & FILTER_MASK) != (config & FILTER_MASK)) { const char *conf_str; if ((tmpconfig & FILTER_MASK) == NO_FILTER) conf_str = "0"; else if ((tmpconfig & FILTER_MASK) == SMOOTH_FILTER_1) conf_str = "1"; else if ((tmpconfig & FILTER_MASK) == SMOOTH_FILTER_2) conf_str = "2"; else if ((tmpconfig & FILTER_MASK) == SMOOTH_FILTER_3) conf_str = "3"; else if ((tmpconfig & FILTER_MASK) == SMOOTH_FILTER_4) conf_str = "4"; else if ((tmpconfig & FILTER_MASK) == SHARP_FILTER_1) conf_str = "5"; else if ((tmpconfig & FILTER_MASK) == SHARP_FILTER_2) conf_str = "6"; else conf_str = "set to an unsupported format"; WriteLog(M64MSG_WARNING, "Ignored texture cache due to incompatible setting: ghq_fltr must be %s", conf_str); } if ((tmpconfig & ENHANCEMENT_MASK) != (config & ENHANCEMENT_MASK)) { const char *conf_str; if ((tmpconfig & ENHANCEMENT_MASK) == NO_ENHANCEMENT) conf_str = "0"; else if ((tmpconfig & ENHANCEMENT_MASK) == X2_ENHANCEMENT) conf_str = "2"; else if ((tmpconfig & ENHANCEMENT_MASK) == X2SAI_ENHANCEMENT) conf_str = "3"; else if ((tmpconfig & ENHANCEMENT_MASK) == HQ2X_ENHANCEMENT) conf_str = "4"; else if ((tmpconfig & ENHANCEMENT_MASK) == HQ2XS_ENHANCEMENT) conf_str = "5"; else if ((tmpconfig & ENHANCEMENT_MASK) == LQ2X_ENHANCEMENT) conf_str = "6"; else if ((tmpconfig & ENHANCEMENT_MASK) == LQ2XS_ENHANCEMENT) conf_str = "7"; else if ((tmpconfig & ENHANCEMENT_MASK) == HQ4X_ENHANCEMENT) conf_str = "8"; else conf_str = "set to an unsupported format"; WriteLog(M64MSG_WARNING, "Ignored texture cache due to incompatible setting: ghq_enht must be %s", conf_str); } if ((tmpconfig & COMPRESS_TEX) != (config & COMPRESS_TEX)) WriteLog(M64MSG_WARNING, "Ignored texture cache due to incompatible setting: ghq_enht_cmpr must be %s", (tmpconfig & COMPRESS_TEX) ? "True" : "False"); if ((tmpconfig & FORCE16BPP_TEX) != (config & FORCE16BPP_TEX)) WriteLog(M64MSG_WARNING, "Ignored texture cache due to incompatible setting: ghq_enht_f16bpp must be %s", (tmpconfig & FORCE16BPP_TEX) ? "True" : "False"); if ((tmpconfig & GZ_TEXCACHE) != (config & GZ_TEXCACHE)) WriteLog(M64MSG_WARNING, "Ignored texture cache due to incompatible setting: ghq_enht_gz must be %s", (tmpconfig & GZ_TEXCACHE) ? "True" : "False"); } } CHDIR(curpath); return !_cache.empty(); }
boolean TxCache::save(const wchar_t *path, const wchar_t *filename, int config) { if (!_cache.empty()) { /* dump cache to disk */ char cbuf[MAX_PATH]; boost::filesystem::wpath cachepath(path); boost::filesystem::create_directory(cachepath); /* Ugly hack to enable fopen/gzopen in Win9x */ #ifdef BOOST_WINDOWS_API wchar_t curpath[MAX_PATH]; GETCWD(MAX_PATH, curpath); CHDIR(cachepath.wstring().c_str()); #else char curpath[MAX_PATH]; wcstombs(cbuf, cachepath.wstring().c_str(), MAX_PATH); GETCWD(MAX_PATH, curpath); CHDIR(cbuf); #endif wcstombs(cbuf, filename, MAX_PATH); gzFile gzfp = gzopen(cbuf, "wb1"); DBG_INFO(80, L"gzfp:%x file:%ls\n", gzfp, filename); if (gzfp) { /* write header to determine config match */ gzwrite(gzfp, &config, 4); std::map<uint64, TXCACHE*>::iterator itMap = _cache.begin(); while (itMap != _cache.end()) { uint8 *dest = (*itMap).second->info.data; uint32 destLen = (*itMap).second->size; uint16 format = (*itMap).second->info.format; /* to keep things simple, we save the texture data in a zlib uncompressed state. */ /* sigh... for those who cannot wait the extra few seconds. changed to keep * texture data in a zlib compressed state. if the GZ_TEXCACHE or GZ_HIRESTEXCACHE * option is toggled, the cache will need to be rebuilt. */ /*if (format & GR_TEXFMT_GZ) { dest = _gzdest0; destLen = _gzdestLen; if (dest && destLen) { if (uncompress(dest, &destLen, (*itMap).second->info.data, (*itMap).second->size) != Z_OK) { dest = NULL; destLen = 0; } format &= ~GR_TEXFMT_GZ; } }*/ if (dest && destLen) { /* texture checksum */ gzwrite(gzfp, &((*itMap).first), 8); /* other texture info */ gzwrite(gzfp, &((*itMap).second->info.width), 4); gzwrite(gzfp, &((*itMap).second->info.height), 4); gzwrite(gzfp, &format, 2); gzwrite(gzfp, &((*itMap).second->info.smallLodLog2), 4); gzwrite(gzfp, &((*itMap).second->info.largeLodLog2), 4); gzwrite(gzfp, &((*itMap).second->info.aspectRatioLog2), 4); gzwrite(gzfp, &((*itMap).second->info.tiles), 4); gzwrite(gzfp, &((*itMap).second->info.untiled_width), 4); gzwrite(gzfp, &((*itMap).second->info.untiled_height), 4); gzwrite(gzfp, &((*itMap).second->info.is_hires_tex), 1); gzwrite(gzfp, &destLen, 4); gzwrite(gzfp, dest, destLen); } itMap++; /* not ready yet */ /*if (_callback) (*_callback)(L"Total textures saved to HDD: %d\n", std::distance(itMap, _cache.begin()));*/ } gzclose(gzfp); } CHDIR(curpath); } return _cache.empty(); }