diff --git a/src/GLideNHQ/TxCache.cpp b/src/GLideNHQ/TxCache.cpp index 892887c2..449dc6a1 100644 --- a/src/GLideNHQ/TxCache.cpp +++ b/src/GLideNHQ/TxCache.cpp @@ -37,17 +37,19 @@ #include "TxCache.h" #include "TxDbg.h" +#define TXCACHE_FORMAT_VERSION UNDEFINED_1 + class TxCacheImpl { public: virtual ~TxCacheImpl() = default; virtual bool add(Checksum checksum, GHQTexInfo *info, int dataSize = 0) = 0; - virtual bool get(Checksum checksum, GHQTexInfo *info) = 0; + virtual bool get(Checksum checksum, N64FormatSize n64FmtSz, GHQTexInfo *info) = 0; virtual bool save(const wchar_t *path, const wchar_t *filename, const int config) = 0; virtual bool load(const wchar_t *path, const wchar_t *filename, const int config, bool force) = 0; virtual bool del(Checksum checksum) = 0; - virtual bool isCached(Checksum checksum) = 0; + virtual bool isCached(Checksum checksum, N64FormatSize n64FmtSz) const = 0; virtual void clear() = 0; virtual bool empty() const = 0; virtual uint32 getOptions() const = 0; @@ -68,12 +70,12 @@ public: ~TxMemoryCache(); bool add(Checksum checksum, GHQTexInfo *info, int dataSize = 0) override; - bool get(Checksum checksum, GHQTexInfo *info) override; + bool get(Checksum checksum, N64FormatSize n64FmtSz, GHQTexInfo *info) override; bool save(const wchar_t *path, const wchar_t *filename, const int config) override; bool load(const wchar_t *path, const wchar_t *filename, const int config, bool force) override; bool del(Checksum checksum) override; - bool isCached(Checksum checksum) override; + bool isCached(Checksum checksum, N64FormatSize n64FmtSz) const override; void clear() override; bool empty() const override { return _cache.empty(); } @@ -95,12 +97,15 @@ private: uint64 _cacheLimit; uint64 _totalSize; - std::map _cache; + using Cache = std::multimap; + Cache _cache; + Cache::const_iterator find(Checksum checksum, N64FormatSize n64FmtSz) const; std::list _cachelist; uint8 *_gzdest0 = nullptr; uint8 *_gzdest1 = nullptr; uint32 _gzdestLen = 0; + bool _isOldVersion = false; }; TxMemoryCache::TxMemoryCache(uint32 options, @@ -133,11 +138,11 @@ TxMemoryCache::~TxMemoryCache() clear(); } -bool TxMemoryCache::add(Checksum checksum, GHQTexInfo *info, int dataSize) +bool TxMemoryCache::add(Checksum checksum, GHQTexInfo* info, int dataSize) { /* NOTE: dataSize must be provided if info->data is zlib compressed. */ - if (!checksum || !info->data || _cache.find(checksum) != _cache.end()) + if (!checksum || !info->data || find(checksum, info->n64_format_size) != _cache.end()) return false; uint8 *dest = info->data; @@ -206,7 +211,7 @@ bool TxMemoryCache::add(Checksum checksum, GHQTexInfo *info, int dataSize) memcpy(tmpdata, dest, dataSize); /* copy it */ - memcpy(&txCache->info, info, sizeof(GHQTexInfo)); + txCache->info = *info; txCache->info.data = tmpdata; txCache->info.format = format; txCache->size = dataSize; @@ -221,7 +226,7 @@ bool TxMemoryCache::add(Checksum checksum, GHQTexInfo *info, int dataSize) #ifdef DEBUG DBG_INFO(80, wst("[%5d] added!! crc:%08X %08X %d x %d gfmt:%x total:%.02fmb\n"), - _cache.size(), checksum._hi, checksum._low, + _cache.size(), checksum._palette, checksum._texture, info->width, info->height, info->format & 0xffff, (double)_totalSize / 1000000); if (_cacheLimit != 0) { @@ -239,41 +244,53 @@ bool TxMemoryCache::add(Checksum checksum, GHQTexInfo *info, int dataSize) return true; } -bool TxMemoryCache::get(Checksum checksum, GHQTexInfo *info) +TxMemoryCache::Cache::const_iterator TxMemoryCache::find(Checksum checksum, N64FormatSize n64FmtSz) const +{ + if (_isOldVersion) + return _cache.find(checksum); + + auto range = _cache.equal_range(checksum); + for (auto it = range.first; it != range.second; ++it) { + if (it->second->info.n64_format_size.formatsize() == n64FmtSz.formatsize()) + return it; + } + return _cache.cend(); +} + +bool TxMemoryCache::get(Checksum checksum, N64FormatSize n64FmtSz, GHQTexInfo *info) { if (!checksum || _cache.empty()) return false; /* find a match in cache */ - auto itMap = _cache.find(checksum); - if (itMap != _cache.end()) { - /* yep, we've got it. */ - memcpy(info, &(((*itMap).second)->info), sizeof(GHQTexInfo)); + auto itMap = find(checksum, n64FmtSz); + if (itMap == _cache.end()) + return false; - /* push it to the back of the list */ - if (_cacheLimit != 0) { - _cachelist.erase(((*itMap).second)->it); - _cachelist.push_back(checksum); - ((*itMap).second)->it = --(_cachelist.end()); - } + /* yep, we've got it. */ + *info = ((*itMap).second)->info; - /* zlib decompress it */ - if (info->format & GL_TEXFMT_GZ) { - uLongf destLen = _gzdestLen; - uint8 *dest = (_gzdest0 == info->data) ? _gzdest1 : _gzdest0; - if (uncompress(dest, &destLen, info->data, ((*itMap).second)->size) != Z_OK) { - DBG_INFO(80, wst("Error: zlib decompression failed!\n")); - return false; - } - info->data = dest; - info->format &= ~GL_TEXFMT_GZ; - DBG_INFO(80, wst("zlib decompressed: %.02fkb->%.02fkb\n"), (float)(((*itMap).second)->size) / 1000, (float)destLen / 1000); - } - - return true; + /* push it to the back of the list */ + if (_cacheLimit != 0) { + _cachelist.erase(((*itMap).second)->it); + _cachelist.push_back(checksum); + ((*itMap).second)->it = --(_cachelist.end()); } - return false; + /* zlib decompress it */ + if (info->format & GL_TEXFMT_GZ) { + uLongf destLen = _gzdestLen; + uint8 *dest = (_gzdest0 == info->data) ? _gzdest1 : _gzdest0; + if (uncompress(dest, &destLen, info->data, ((*itMap).second)->size) != Z_OK) { + DBG_INFO(80, wst("Error: zlib decompression failed!\n")); + return false; + } + info->data = dest; + info->format &= ~GL_TEXFMT_GZ; + DBG_INFO(80, wst("zlib decompressed: %.02fkb->%.02fkb\n"), (float)(((*itMap).second)->size) / 1000, (float)destLen / 1000); + } + + return true; } bool TxMemoryCache::save(const wchar_t *path, const wchar_t *filename, int config) @@ -302,6 +319,10 @@ bool TxMemoryCache::save(const wchar_t *path, const wchar_t *filename, int confi gzFile gzfp = gzopen(cbuf, "wb1"); DBG_INFO(80, wst("gzfp:%x file:%ls\n"), gzfp, filename); if (gzfp) { + /* write current version */ + int version = TXCACHE_FORMAT_VERSION; + gzwrite(gzfp, &version, 4); + /* write header to determine config match */ gzwrite(gzfp, &config, 4); @@ -340,6 +361,7 @@ bool TxMemoryCache::save(const wchar_t *path, const wchar_t *filename, int confi gzwrite(gzfp, &((*itMap).second->info.texture_format), 2); gzwrite(gzfp, &((*itMap).second->info.pixel_type), 2); gzwrite(gzfp, &((*itMap).second->info.is_hires_tex), 1); + gzwrite(gzfp, &((*itMap).second->info.n64_format_size._formatsize), 2); gzwrite(gzfp, &destLen, 4); gzwrite(gzfp, dest, destLen); @@ -382,9 +404,19 @@ bool TxMemoryCache::load(const wchar_t *path, const wchar_t *filename, int confi /* yep, we have it. load it into memory cache. */ int dataSize; uint64 checksum; - int tmpconfig; - /* read header to determine config match */ - gzread(gzfp, &tmpconfig, 4); + + int version = 0; + int tmpconfig = 0; + /* read version */ + gzread(gzfp, &version, 4); + if (version == TXCACHE_FORMAT_VERSION) { + _isOldVersion = false; + /* read header to determine config match */ + gzread(gzfp, &tmpconfig, 4); + } else { + _isOldVersion = true; + tmpconfig = version; + } if (tmpconfig == config || force) { do { @@ -398,6 +430,8 @@ bool TxMemoryCache::load(const wchar_t *path, const wchar_t *filename, int confi gzread(gzfp, &tmpInfo.texture_format, 2); gzread(gzfp, &tmpInfo.pixel_type, 2); gzread(gzfp, &tmpInfo.is_hires_tex, 1); + if (!_isOldVersion) + gzread(gzfp, &tmpInfo.n64_format_size._formatsize, 2); gzread(gzfp, &dataSize, 4); @@ -445,7 +479,7 @@ bool TxMemoryCache::del(Checksum checksum) delete (*itMap).second; _cache.erase(itMap); - DBG_INFO(80, wst("removed from cache: checksum = %08X %08X\n"), checksum._low, checksum._hi); + DBG_INFO(80, wst("removed from cache: checksum = %08X %08X\n"), checksum._palette, checksum._texture); return true; } @@ -453,9 +487,9 @@ bool TxMemoryCache::del(Checksum checksum) return false; } -bool TxMemoryCache::isCached(Checksum checksum) +bool TxMemoryCache::isCached(Checksum checksum, N64FormatSize n64FmtSz) const { - return _cache.find(checksum) != _cache.end(); + return find(checksum, n64FmtSz) != _cache.cend(); } void TxMemoryCache::clear() @@ -485,12 +519,12 @@ public: ~TxFileStorage() = default; bool add(Checksum checksum, GHQTexInfo *info, int dataSize = 0) override; - bool get(Checksum checksum, GHQTexInfo *info) override; + bool get(Checksum checksum, N64FormatSize n64FmtSz, GHQTexInfo *info) override; bool save(const wchar_t *path, const wchar_t *filename, const int config) override; bool load(const wchar_t *path, const wchar_t *filename, const int config, bool force) override; bool del(Checksum checksum) override { return false; } - bool isCached(Checksum checksum) override; + bool isCached(Checksum checksum, N64FormatSize n64FmtSz) const override; void clear() override; bool empty() const override { return _storage.empty(); } @@ -513,8 +547,19 @@ private: dispInfoFuncExt _callback; uint64 _totalSize = 0; - using StorageMap = std::unordered_map; + union StorageOffset + { + StorageOffset() : _data(0U) {} + StorageOffset(int64 data) : _data(data) {} + struct { + int64 _offset : 48; + int64 _formatsize : 16; + }; + int64 _data; + }; + using StorageMap = std::unordered_multimap; StorageMap _storage; + StorageMap::const_iterator find(Checksum checksum, N64FormatSize n64FmtSz) const; uint8 *_gzdest0 = nullptr; uint8 *_gzdest1 = nullptr; @@ -524,12 +569,15 @@ private: std::ofstream _outfile; int64 _storagePos = 0; bool _dirty = false; + bool _isOldVersion = false; static const int _fakeConfig; static const int64 _initialPos; + static const int64 _initialPosOld; }; const int TxFileStorage::_fakeConfig = -1; -const int64 TxFileStorage::_initialPos = sizeof(int64) + sizeof(int); +const int64 TxFileStorage::_initialPos = sizeof(int64) + sizeof(int) + sizeof(int); // offset + version + config +const int64 TxFileStorage::_initialPosOld = sizeof(int64) + sizeof(int); // offset + config TxFileStorage::TxFileStorage(uint32 options, const wchar_t *cachePath, @@ -594,6 +642,8 @@ bool TxFileStorage::open(bool forRead) if (!_outfile.good()) return false; + const int version = TXCACHE_FORMAT_VERSION; + FWRITE(version); FWRITE(_fakeConfig); _storagePos = _initialPos; FWRITE(_storagePos); @@ -616,6 +666,8 @@ void TxFileStorage::clear() _outfile.close(); _outfile.open(_fullPath, std::ofstream::out | std::ofstream::binary | std::ofstream::trunc); + const int version = TXCACHE_FORMAT_VERSION; + FWRITE(version); FWRITE(_fakeConfig); _storagePos = _initialPos; FWRITE(_storagePos); @@ -632,6 +684,7 @@ bool TxFileStorage::writeData(uint32 dataSize, const GHQTexInfo & info) FWRITE(info.texture_format); FWRITE(info.pixel_type); FWRITE(info.is_hires_tex); + FWRITE(info.n64_format_size._formatsize); FWRITE(dataSize); _outfile.write((char*)info.data, dataSize); return _outfile.good(); @@ -645,6 +698,8 @@ bool TxFileStorage::readData(GHQTexInfo & info) FREAD(info.texture_format); FREAD(info.pixel_type); FREAD(info.is_hires_tex); + if (!_isOldVersion) + FREAD(info.n64_format_size._formatsize); uint32 dataSize = 0U; FREAD(dataSize); @@ -679,7 +734,7 @@ bool TxFileStorage::add(Checksum checksum, GHQTexInfo *info, int dataSize) { /* NOTE: dataSize must be provided if info->data is zlib compressed. */ - if (!checksum || !info->data || _storage.find(checksum) != _storage.end()) + if (!checksum || !info->data || isCached(checksum, info->n64_format_size)) return false; if (_infile.is_open() || !_outfile.is_open()) @@ -724,8 +779,12 @@ bool TxFileStorage::add(Checksum checksum, GHQTexInfo *info, int dataSize) _outfile.seekp(_storagePos, std::ofstream::beg); assert(_storagePos == _outfile.tellp()); + assert(_storagePos < 0xFFFFFFFFFFFFFF); - _storage.insert(StorageMap::value_type(checksum._checksum, _storagePos)); + StorageOffset offset; + offset._formatsize = info->n64_format_size.formatsize(); + offset._offset = _storagePos; + _storage.insert(StorageMap::value_type(checksum._checksum, offset)); if (!writeData(dataSize, infoToWrite)) return false; _storagePos = _outfile.tellp(); @@ -733,7 +792,7 @@ bool TxFileStorage::add(Checksum checksum, GHQTexInfo *info, int dataSize) #ifdef DEBUG DBG_INFO(80, wst("[%5d] added!! crc:%08X %08X %d x %d gfmt:%x total:%.02fmb\n"), - _storage.size(), checksum._hi, checksum._low, + _storage.size(), checksum._palette, checksum._texture, info->width, info->height, info->format & 0xffff, (double)(_totalSize / 1024) / 1024.0); #endif @@ -743,13 +802,26 @@ bool TxFileStorage::add(Checksum checksum, GHQTexInfo *info, int dataSize) return true; } -bool TxFileStorage::get(Checksum checksum, GHQTexInfo *info) +TxFileStorage::StorageMap::const_iterator TxFileStorage::find(Checksum checksum, N64FormatSize n64FmtSz) const +{ + if (_isOldVersion) + return _storage.find(checksum); + + auto range = _storage.equal_range(checksum); + for (auto it = range.first; it != range.second; ++it) { + if (static_cast(it->second._formatsize) == n64FmtSz.formatsize()) + return it; + } + return _storage.cend(); +} + +bool TxFileStorage::get(Checksum checksum, N64FormatSize n64FmtSz, GHQTexInfo *info) { if (!checksum || _storage.empty()) return false; /* find a match in storage */ - auto itMap = _storage.find(checksum); + auto itMap = find(checksum, n64FmtSz); if (itMap == _storage.end()) return false; @@ -757,7 +829,7 @@ bool TxFileStorage::get(Checksum checksum, GHQTexInfo *info) if (!open(true)) return false; - _infile.seekg(itMap->second, std::ifstream::beg); + _infile.seekg(itMap->second._offset, std::ifstream::beg); return readData(*info); } @@ -782,6 +854,8 @@ bool TxFileStorage::save(const wchar_t *path, const wchar_t *filename, int confi _outfile.seekp(0L, std::ofstream::beg); + int version = TXCACHE_FORMAT_VERSION; + FWRITE(version); FWRITE(config); FWRITE(_storagePos); _outfile.seekp(_storagePos, std::ofstream::beg); @@ -791,7 +865,7 @@ bool TxFileStorage::save(const wchar_t *path, const wchar_t *filename, int confi (*_callback)(wst("Saving texture storage...\n")); for (auto& item : _storage) { FWRITE(item.first); - FWRITE(item.second); + FWRITE(item.second._data); } _outfile.close(); if (_callback) @@ -813,19 +887,38 @@ bool TxFileStorage::load(const wchar_t *path, const wchar_t *filename, int confi if (!open(true)) return false; + int version = 0; int tmpconfig = 0; - /* read header to determine config match */ + /* read version */ _infile.seekg(0L, std::ifstream::beg); - FREAD(tmpconfig); - FREAD(_storagePos); - if (tmpconfig == _fakeConfig) { - if (_storagePos != _initialPos) + FREAD(version); + if (version == TXCACHE_FORMAT_VERSION) { + _isOldVersion = false; + /* read header to determine config match */ + FREAD(tmpconfig); + FREAD(_storagePos); + if (tmpconfig == _fakeConfig) { + if (_storagePos != _initialPos) + return false; + } else if (tmpconfig != config && !force) return false; - } else if (tmpconfig != config && !force) - return false; - if (_storagePos <= sizeof(config) + sizeof(_storagePos)) - return false; + if (_storagePos <= _initialPos) + return false; + } else { + _isOldVersion = true; + tmpconfig = version; + FREAD(_storagePos); + if (tmpconfig == _fakeConfig) { + if (_storagePos != _initialPosOld) + return false; + } else if (tmpconfig != config && !force) + return false; + + if (_storagePos <= _initialPosOld) + return false; + } + _infile.seekg(_storagePos, std::ifstream::beg); int storageSize = 0; @@ -849,9 +942,9 @@ bool TxFileStorage::load(const wchar_t *path, const wchar_t *filename, int confi return !_storage.empty(); } -bool TxFileStorage::isCached(Checksum checksum) +bool TxFileStorage::isCached(Checksum checksum, N64FormatSize n64FmtSz) const { - return _storage.find(checksum) != _storage.end(); + return find(checksum, n64FmtSz) != _storage.cend(); } /************************** TxCache *************************************/ @@ -886,9 +979,9 @@ bool TxCache::add(Checksum checksum, GHQTexInfo *info, int dataSize) return _pImpl->add(checksum, info, dataSize); } -bool TxCache::get(Checksum checksum, GHQTexInfo *info) +bool TxCache::get(Checksum checksum, N64FormatSize n64FmtSz, GHQTexInfo *info) { - return _pImpl->get(checksum, info); + return _pImpl->get(checksum, n64FmtSz, info); } uint64 TxCache::size() const @@ -921,9 +1014,9 @@ bool TxCache::del(Checksum checksum) return _pImpl->del(checksum); } -bool TxCache::isCached(Checksum checksum) +bool TxCache::isCached(Checksum checksum, N64FormatSize n64FmtSz) const { - return _pImpl->isCached(checksum); + return _pImpl->isCached(checksum, n64FmtSz); } void TxCache::clear() diff --git a/src/GLideNHQ/TxCache.h b/src/GLideNHQ/TxCache.h index af06a954..5596e12f 100644 --- a/src/GLideNHQ/TxCache.h +++ b/src/GLideNHQ/TxCache.h @@ -31,27 +31,6 @@ #include "TxInternal.h" #include "TxUtil.h" -struct Checksum -{ - union - { - uint64 _checksum; /* checksum hi:palette low:texture */ - struct - { - uint32 _low; - uint32 _hi; - }; - }; - - Checksum(uint64 checksum) : _checksum(checksum) {} - operator bool() { - return _checksum != 0; - } - operator uint64() { - return _checksum; - } -}; - class TxCacheImpl; class TxCache @@ -66,8 +45,8 @@ protected: bool save(); bool load(bool force); - bool del(Checksum checksum); /* checksum hi:palette low:texture */ - bool isCached(Checksum checksum); /* checksum hi:palette low:texture */ + bool del(Checksum checksum); + bool isCached(Checksum checksum, N64FormatSize n64FmtSz) const; void clear(); uint64 size() const; // number of elements uint64 totalSize() const; // size of elements in bytes @@ -82,7 +61,7 @@ public: virtual ~TxCache(); TxCache(uint32 options, uint64 cacheLimit, const wchar_t *cachePath, const wchar_t *ident, dispInfoFuncExt callback); bool add(Checksum checksum, GHQTexInfo *info, int dataSize = 0); - bool get(Checksum checksum, GHQTexInfo *info); + bool get(Checksum checksum, N64FormatSize n64FmtSz, GHQTexInfo *info); bool empty() const; }; diff --git a/src/GLideNHQ/TxFilter.cpp b/src/GLideNHQ/TxFilter.cpp index f7deabb1..3aec25e3 100644 --- a/src/GLideNHQ/TxFilter.cpp +++ b/src/GLideNHQ/TxFilter.cpp @@ -164,7 +164,7 @@ TxFilter::TxFilter(int maxwidth, } boolean -TxFilter::filter(uint8 *src, int srcwidth, int srcheight, ColorFormat srcformat, uint64 g64crc, GHQTexInfo *info) +TxFilter::filter(uint8 *src, int srcwidth, int srcheight, ColorFormat srcformat, uint64 g64crc, N64FormatSize n64FmtSz, GHQTexInfo *info) { uint8 *texture = src; uint8 *tmptex = _tex1; @@ -186,7 +186,7 @@ TxFilter::filter(uint8 *src, int srcwidth, int srcheight, ColorFormat srcformat, /* check if we have it in cache */ if ((g64crc & 0xffffffff00000000) == 0 && /* we reach here only when there is no hires texture for this crc */ - _txTexCache->get(g64crc, info)) { + _txTexCache->get(g64crc, n64FmtSz, info)) { DBG_INFO(80, wst("cache hit: %d x %d gfmt:%x\n"), info->width, info->height, info->format); return 1; /* yep, we've got it */ } @@ -451,6 +451,7 @@ TxFilter::filter(uint8 *src, int srcwidth, int srcheight, ColorFormat srcformat, info->width = srcwidth; info->height = srcheight; info->is_hires_tex = 0; + info->n64_format_size = n64FmtSz; setTextureFormat(destformat, info); /* cache the texture. */ @@ -463,7 +464,7 @@ TxFilter::filter(uint8 *src, int srcwidth, int srcheight, ColorFormat srcformat, } boolean -TxFilter::hirestex(uint64 g64crc, uint64 r_crc64, uint16 *palette, GHQTexInfo *info) +TxFilter::hirestex(uint64 g64crc, Checksum r_crc64, uint16 *palette, N64FormatSize n64FmtSz, GHQTexInfo *info) { /* NOTE: Rice CRC32 sometimes return the same value for different textures. * As a workaround, Glide64 CRC32 is used for the key for NON-hires @@ -476,13 +477,13 @@ TxFilter::hirestex(uint64 g64crc, uint64 r_crc64, uint16 *palette, GHQTexInfo *i */ DBG_INFO(80, wst("hirestex: r_crc64:%08X %08X, g64crc:%08X %08X\n"), - (uint32)(r_crc64 >> 32), (uint32)(r_crc64 & 0xffffffff), + r_crc64._palette, r_crc64._texture, (uint32)(g64crc >> 32), (uint32)(g64crc & 0xffffffff)); #if HIRES_TEXTURE /* check if we have it in hires memory cache. */ if ((_options & HIRESTEXTURES_MASK) && r_crc64) { - if (_txHiResLoader->get(r_crc64, info)) { + if (_txHiResLoader->get(r_crc64, n64FmtSz, info)) { DBG_INFO(80, wst("hires hit: %d x %d gfmt:%x\n"), info->width, info->height, info->format); /* TODO: Enable emulation for special N64 combiner modes. There are few ways @@ -509,11 +510,11 @@ TxFilter::hirestex(uint64 g64crc, uint64 r_crc64, uint16 *palette, GHQTexInfo *i return 1; /* yep, got it */ } - if (_txHiResLoader->get((r_crc64 >> 32), info) || - _txHiResLoader->get((r_crc64 & 0xffffffff), info)) { + if (_txHiResLoader->get(r_crc64._palette, n64FmtSz, info) || + _txHiResLoader->get(r_crc64._texture, n64FmtSz, info)) { DBG_INFO(80, wst("hires hit: %d x %d gfmt:%x\n"), info->width, info->height, info->format); - /* for true CI textures, we use the passed in palette to convert to + /* for true CI textures, we use the passed in palette to convert to * ARGB1555 and add it to memory cache. * * NOTE: we do this AFTER all other texture cache searches because @@ -543,6 +544,7 @@ TxFilter::hirestex(uint64 g64crc, uint64 r_crc64, uint16 *palette, GHQTexInfo *i info->width = width; info->height = height; info->is_hires_tex = 1; + info->n64_format_size = n64FmtSz; setTextureFormat(format, info); /* XXX: add to hires texture cache!!! */ @@ -558,7 +560,7 @@ TxFilter::hirestex(uint64 g64crc, uint64 r_crc64, uint16 *palette, GHQTexInfo *i /* check if we have it in memory cache */ if (_cacheSize && g64crc) { - if (_txTexCache->get(g64crc, info)) { + if (_txTexCache->get(g64crc, n64FmtSz, info)) { DBG_INFO(80, wst("cache hit: %d x %d gfmt:%x\n"), info->width, info->height, info->format); return 1; /* yep, we've got it */ } @@ -579,7 +581,7 @@ TxFilter::checksum64(uint8 *src, int width, int height, int size, int rowStride, } boolean -TxFilter::dmptx(uint8 *src, int width, int height, int rowStridePixel, ColorFormat gfmt, uint16 n64fmt, uint64 r_crc64) +TxFilter::dmptx(uint8 *src, int width, int height, int rowStridePixel, ColorFormat gfmt, N64FormatSize n64FmtSz, Checksum r_crc64) { assert(gfmt != graphics::colorFormat::RGBA); if (!_initialized) @@ -588,9 +590,9 @@ TxFilter::dmptx(uint8 *src, int width, int height, int rowStridePixel, ColorForm if (!(_options & DUMP_TEX)) return 0; - DBG_INFO(80, wst("gfmt = %02x n64fmt = %02x\n"), u32(gfmt), n64fmt); + DBG_INFO(80, wst("gfmt = %02x n64fmt = %02x\n"), u32(gfmt), n64FmtSz._format); DBG_INFO(80, wst("hirestex: r_crc64:%08X %08X\n"), - (uint32)(r_crc64 >> 32), (uint32)(r_crc64 & 0xffffffff)); + r_crc64._palette, r_crc64._texture); if (gfmt != graphics::internalcolorFormat::RGBA8) { if (!_txQuantize->quantize(src, _tex1, rowStridePixel, height, gfmt, graphics::internalcolorFormat::RGBA8)) @@ -611,13 +613,13 @@ TxFilter::dmptx(uint8 *src, int width, int height, int rowStridePixel, ColorForm if (!osal_path_existsW(tmpbuf.c_str()) && osal_mkdirp(tmpbuf.c_str()) != 0) return 0; - if ((n64fmt >> 8) == 0x2) { + if (n64FmtSz._format == 0x2) { wchar_t wbuf[256]; - tx_swprintf(wbuf, 256, wst("/%ls#%08X#%01X#%01X#%08X_ciByRGBA.png"), _ident.c_str(), (uint32)(r_crc64 & 0xffffffff), (n64fmt >> 8), (n64fmt & 0xf), (uint32)(r_crc64 >> 32)); + tx_swprintf(wbuf, 256, wst("/%ls#%08X#%01X#%01X#%08X_ciByRGBA.png"), _ident.c_str(), r_crc64._texture, n64FmtSz._format, n64FmtSz._size, r_crc64._palette); tmpbuf.append(wbuf); } else { wchar_t wbuf[256]; - tx_swprintf(wbuf, 256, wst("/%ls#%08X#%01X#%01X_all.png"), _ident.c_str(), (uint32)(r_crc64 & 0xffffffff), (n64fmt >> 8), (n64fmt & 0xf)); + tx_swprintf(wbuf, 256, wst("/%ls#%08X#%01X#%01X_all.png"), _ident.c_str(), r_crc64._texture, n64FmtSz._format, n64FmtSz._size); tmpbuf.append(wbuf); } diff --git a/src/GLideNHQ/TxFilter.h b/src/GLideNHQ/TxFilter.h index a331c697..2c4af8e4 100644 --- a/src/GLideNHQ/TxFilter.h +++ b/src/GLideNHQ/TxFilter.h @@ -70,13 +70,15 @@ public: int srcheight, ColorFormat srcformat, uint64 g64crc, /* glide64 crc, 64bit for future use */ + N64FormatSize n64FmtSz, GHQTexInfo *info); boolean hirestex(uint64 g64crc, /* glide64 crc, 64bit for future use */ - uint64 r_crc64, /* checksum hi:palette low:texture */ + Checksum r_crc64, uint16 *palette, + N64FormatSize n64FmtSz, GHQTexInfo *info); uint64 checksum64(uint8 *src, int width, int height, int size, int rowStride, uint8 *palette); - boolean dmptx(uint8 *src, int width, int height, int rowStridePixel, ColorFormat gfmt, uint16 n64fmt, uint64 r_crc64); + boolean dmptx(uint8 *src, int width, int height, int rowStridePixel, ColorFormat gfmt, N64FormatSize n64FmtSz, Checksum r_crc64); boolean reloadhirestex(); void dumpcache(); }; diff --git a/src/GLideNHQ/TxFilterExport.cpp b/src/GLideNHQ/TxFilterExport.cpp index 93c81925..335276b0 100644 --- a/src/GLideNHQ/TxFilterExport.cpp +++ b/src/GLideNHQ/TxFilterExport.cpp @@ -57,20 +57,20 @@ txfilter_shutdown(void) TAPI boolean TAPIENTRY txfilter_filter(uint8 *src, int srcwidth, int srcheight, uint16 srcformat, - uint64 g64crc, GHQTexInfo *info) + uint64 g64crc, N64FormatSize n64FmtSz, GHQTexInfo *info) { if (txFilter) return txFilter->filter(src, srcwidth, srcheight, ColorFormat(u32(srcformat)), - g64crc, info); + g64crc, n64FmtSz, info); return 0; } TAPI boolean TAPIENTRY -txfilter_hirestex(uint64 g64crc, uint64 r_crc64, uint16 *palette, GHQTexInfo *info) +txfilter_hirestex(uint64 g64crc, Checksum r_crc64, uint16 *palette, N64FormatSize n64FmtSz, GHQTexInfo *info) { if (txFilter) - return txFilter->hirestex(g64crc, r_crc64, palette, info); + return txFilter->hirestex(g64crc, r_crc64, palette, n64FmtSz, info); return 0; } @@ -85,10 +85,10 @@ txfilter_checksum(uint8 *src, int width, int height, int size, int rowStride, ui } TAPI boolean TAPIENTRY -txfilter_dmptx(uint8 *src, int width, int height, int rowStridePixel, uint16 gfmt, uint16 n64fmt, uint64 r_crc64) +txfilter_dmptx(uint8 *src, int width, int height, int rowStridePixel, uint16 gfmt, N64FormatSize n64FmtSz, Checksum r_crc64) { if (txFilter) - return txFilter->dmptx(src, width, height, rowStridePixel, ColorFormat(u32(gfmt)), n64fmt, r_crc64); + return txFilter->dmptx(src, width, height, rowStridePixel, ColorFormat(u32(gfmt)), n64FmtSz, r_crc64); return 0; } diff --git a/src/GLideNHQ/TxFilterExport.h b/src/GLideNHQ/TxFilterExport.h index bd87a468..e4f4f0ca 100644 --- a/src/GLideNHQ/TxFilterExport.h +++ b/src/GLideNHQ/TxFilterExport.h @@ -45,6 +45,9 @@ #define CHDIR(a) chdir(a) #endif +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef unsigned int uint32; #ifdef __MSC__ typedef __int64 int64; typedef unsigned __int64 uint64; @@ -100,21 +103,77 @@ typedef unsigned char boolean; #define GZ_HIRESTEXCACHE 0x00800000 #define DUMP_TEXCACHE 0x01000000 #define DUMP_HIRESTEXCACHE 0x02000000 -#define TILE_HIRESTEX 0x04000000 -#define UNDEFINED_0 0x08000000 +#define UNDEFINED_0 0x04000000 +#define UNDEFINED_1 0x08000000 #define FORCE16BPP_HIRESTEX 0x10000000 #define FORCE16BPP_TEX 0x20000000 #define LET_TEXARTISTS_FLY 0x40000000 /* a little freedom for texture artists */ #define DUMP_TEX 0x80000000 -struct GHQTexInfo { - unsigned char *data = nullptr; - int width = 0; - int height = 0; - unsigned int format = 0; - unsigned short texture_format = 0; - unsigned short pixel_type = 0; - unsigned char is_hires_tex = 0; +struct Checksum +{ + union + { + uint64 _checksum; /* checksum hi:palette low:texture */ + struct + { + uint32 _texture; + uint32 _palette; + }; + }; + + Checksum(uint64 checksum) : _checksum(checksum) {} + Checksum(uint32 texture, uint32 palette) : _texture(texture), _palette(palette) {} + + operator bool() const { + return _checksum != 0; + } + + operator uint64() const { + return _checksum; + } +}; + +struct N64FormatSize +{ + union + { + uint16 _formatsize; + struct + { + uint8 _format; + uint8 _size; + }; + }; + + N64FormatSize(uint16 n64format, uint16 n64size) : + _format(static_cast(n64format)), + _size(static_cast(n64size)) + {} + + uint16 formatsize() const + { + return _formatsize; + } + + bool operator==(const N64FormatSize& _other) const + { + return _other._formatsize == _formatsize; + } +}; + +struct GHQTexInfo +{ + GHQTexInfo() {} + ~GHQTexInfo() {} + unsigned char *data{ nullptr }; + unsigned int width{ 0u }; + unsigned int height{ 0u }; + unsigned int format{ 0u }; + unsigned short texture_format{ 0u }; + unsigned short pixel_type{ 0u }; + unsigned char is_hires_tex{ 0u }; + N64FormatSize n64_format_size{ 0u, 0u }; }; /* Callback to display hires texture info. @@ -155,10 +214,6 @@ typedef void (*dispInfoFuncExt)(const wchar_t *format, ...); #endif #endif // OS_WINDOWS -typedef unsigned char uint8; -typedef unsigned short uint16; -typedef unsigned int uint32; - #ifdef __cplusplus extern "C"{ #endif @@ -173,16 +228,16 @@ txfilter_shutdown(void); TAPI boolean TAPIENTRY txfilter_filter(uint8 *src, int srcwidth, int srcheight, uint16 srcformat, - uint64 g64crc, GHQTexInfo *info); + uint64 g64crc, N64FormatSize n64FmtSz, GHQTexInfo *info); TAPI boolean TAPIENTRY -txfilter_hirestex(uint64 g64crc, uint64 r_crc64, uint16 *palette, GHQTexInfo *info); +txfilter_hirestex(uint64 g64crc, Checksum r_crc64, uint16 *palette, N64FormatSize n64FmtSz, GHQTexInfo *info); TAPI uint64 TAPIENTRY txfilter_checksum(uint8 *src, int width, int height, int size, int rowStride, uint8 *palette); TAPI boolean TAPIENTRY -txfilter_dmptx(uint8 *src, int width, int height, int rowStridePixel, uint16 gfmt, uint16 n64fmt, uint64 r_crc64); +txfilter_dmptx(uint8 *src, int width, int height, int rowStridePixel, uint16 gfmt, N64FormatSize n64FmtSz, Checksum r_crc64); TAPI boolean TAPIENTRY txfilter_reloadhirestex(); diff --git a/src/GLideNHQ/TxHiResCache.cpp b/src/GLideNHQ/TxHiResCache.cpp index e7c63bd3..d6ad5a7d 100644 --- a/src/GLideNHQ/TxHiResCache.cpp +++ b/src/GLideNHQ/TxHiResCache.cpp @@ -97,7 +97,6 @@ int TxHiResCache::_getConfig() const { return getOptions() & (HIRESTEXTURES_MASK | - TILE_HIRESTEX | FORCE16BPP_HIRESTEX | GZ_HIRESTEXCACHE | FILE_HIRESTEXCACHE | @@ -251,7 +250,7 @@ TxHiResCache::LoadResult TxHiResCache::_loadHiResTextures(const wchar_t * dir_pa chksum64 <<= 32; chksum64 |= (uint64)chksum; } - if (isCached(chksum64)) { + if (isCached(chksum64, N64FormatSize(fmt, siz))) { #if !DEBUG INFO(80, wst("-----\n")); INFO(80, wst("file: %s\n"), fname); @@ -281,6 +280,7 @@ TxHiResCache::LoadResult TxHiResCache::_loadHiResTextures(const wchar_t * dir_pa tmpInfo.width = width; tmpInfo.height = height; tmpInfo.is_hires_tex = 1; + tmpInfo.n64_format_size = N64FormatSize(fmt, siz); setTextureFormat(format, &tmpInfo); /* remove redundant in cache */ @@ -325,7 +325,7 @@ bool TxHiResCache::add(Checksum checksum, GHQTexInfo *info, int dataSize) return TxCache::add(checksum, info, dataSize); } -bool TxHiResCache::get(Checksum checksum, GHQTexInfo *info) +bool TxHiResCache::get(Checksum checksum, N64FormatSize n64FmtSz, GHQTexInfo *info) { - return TxCache::get(checksum, info); + return TxCache::get(checksum, n64FmtSz, info); } diff --git a/src/GLideNHQ/TxHiResCache.h b/src/GLideNHQ/TxHiResCache.h index 41b884ee..43ebf596 100644 --- a/src/GLideNHQ/TxHiResCache.h +++ b/src/GLideNHQ/TxHiResCache.h @@ -60,7 +60,7 @@ public: dispInfoFuncExt callback); bool empty() const override; bool add(Checksum checksum, GHQTexInfo *info, int dataSize = 0) override; - bool get(Checksum checksum, GHQTexInfo *info) override; + bool get(Checksum checksum, N64FormatSize n64FmtSz, GHQTexInfo *info) override; bool reload() override; void dump() override; }; diff --git a/src/GLideNHQ/TxHiResLoader.cpp b/src/GLideNHQ/TxHiResLoader.cpp index 3949830e..e3ad732a 100644 --- a/src/GLideNHQ/TxHiResLoader.cpp +++ b/src/GLideNHQ/TxHiResLoader.cpp @@ -571,4 +571,3 @@ uint8_t* TxHiResLoader::loadFileInfoTex(char* fname, return tex; } - diff --git a/src/GLideNHQ/TxHiResLoader.h b/src/GLideNHQ/TxHiResLoader.h index 98c72f19..60d70572 100644 --- a/src/GLideNHQ/TxHiResLoader.h +++ b/src/GLideNHQ/TxHiResLoader.h @@ -23,7 +23,7 @@ class TxHiResLoader protected: uint32_t checkFileName(char* ident, char* fname, uint32_t* pChksum, uint32_t* pPalchksum, uint32_t* pFmt, uint32_t* pSiz); uint8_t* loadFileInfoTex(char* fname, int siz, int* pWidth, int* pHeight, uint32_t fmt, ColorFormat* pFormat); - + std::unique_ptr _txImage; std::unique_ptr _txQuantize; std::unique_ptr _txReSample; @@ -42,7 +42,7 @@ public: virtual bool empty() const = 0; virtual bool add(Checksum checksum, GHQTexInfo *info, int dataSize = 0) = 0; - virtual bool get(Checksum checksum, GHQTexInfo *info) = 0; + virtual bool get(Checksum checksum, N64FormatSize n64FmtSz, GHQTexInfo *info) = 0; virtual bool reload() = 0; virtual void dump() = 0; }; diff --git a/src/GLideNHQ/TxHiResNoCache.cpp b/src/GLideNHQ/TxHiResNoCache.cpp index 353e6163..701c49da 100644 --- a/src/GLideNHQ/TxHiResNoCache.cpp +++ b/src/GLideNHQ/TxHiResNoCache.cpp @@ -49,30 +49,44 @@ bool TxHiResNoCache::empty() const return _filesIndex.empty(); } -bool TxHiResNoCache::get(Checksum checksum, GHQTexInfo *info) +TxHiResNoCache::FileIndexMap::const_iterator TxHiResNoCache::findFile(Checksum checksum, N64FormatSize n64FmtSz) const { - if (!checksum) { - return false; + auto range = _filesIndex.equal_range(checksum); + for (auto it = range.first; it != range.second; ++it) { + if (N64FormatSize(it->second.fmt, it->second.siz).formatsize() == n64FmtSz.formatsize()) + return it; } + return _filesIndex.end(); +} +bool TxHiResNoCache::get(Checksum checksum, N64FormatSize n64FmtSz, GHQTexInfo *info) +{ + if (!checksum) + return false; -#ifdef DEBUG - uint32 chksum = checksum._checksum & 0xffffffff; - uint32 palchksum = checksum._checksum >> 32; -#endif + uint32 chksum = checksum._texture; + uint32 palchksum = checksum._palette; /* loop over each file from the index and try to match it with checksum */ - auto indexEntry = _filesIndex.find(checksum); - if (indexEntry == _filesIndex.end()) { + auto indexEntry = findFile(checksum, n64FmtSz); + if (indexEntry == _filesIndex.cend()) { DBG_INFO(80, wst("TxNoCache::get: chksum:%08X %08X not found\n"), chksum, palchksum); return false; } - fileIndexEntry_t& entry = indexEntry->second; + auto entry = indexEntry->second; /* make sure to not load the same texture twice */ - auto loadedTexMap = _loadedTex.find(checksum); - if (loadedTexMap != _loadedTex.end()) { + auto findTex = [n64FmtSz, this](Checksum checksum) + { + auto range = _loadedTex.equal_range(checksum); + for (auto it = range.first; it != range.second; ++it) { + if (it->second.n64_format_size == n64FmtSz) + return it; + } + return _loadedTex.end(); + }; + if (auto loadedTexMap = findTex(checksum); loadedTexMap != _loadedTex.end()) { DBG_INFO(80, wst("TxNoCache::get: cached chksum:%08X %08X found\n"), chksum, palchksum); *info = loadedTexMap->second; return true; @@ -113,6 +127,7 @@ bool TxHiResNoCache::get(Checksum checksum, GHQTexInfo *info) info->width = width; info->height = height; info->is_hires_tex = 1; + info->n64_format_size = n64FmtSz; setTextureFormat(format, info); /* add to loaded textures */ @@ -180,9 +195,8 @@ bool TxHiResNoCache::_createFileIndexInDir(tx_wstring directory, bool update) uint64 chksum64 = 0; uint32 chksum = 0, palchksum = 0, length = 0; - fileIndexEntry_t entry; + FileIndexEntry entry; entry.fmt = entry.siz = 0; - bool ret = false; wcstombs(entry.fname, foundfilename, MAX_PATH); @@ -205,14 +219,14 @@ bool TxHiResNoCache::_createFileIndexInDir(tx_wstring directory, bool update) } /* try to add entry to file index */ - ret = _filesIndex.insert(std::map::value_type(chksum64, entry)).second; - if (!ret) { + if (findFile(chksum64, N64FormatSize(entry.fmt, entry.siz)) != _filesIndex.cend()) { /* technically we should probably fail here, * however HTS & HTC both don't fail when there are duplicates, * so to maintain backwards compatability, we won't either */ DBG_INFO(80, wst("TxNoCache::_createFileIndexInDir: failed to add cksum:%08X %08X file:%ls\n"), chksum, palchksum, texturefilename.c_str()); } else { + _filesIndex.insert(std::map::value_type(chksum64, entry)); DBG_INFO(80, wst("TxNoCache::_createFileIndexInDir: added cksum:%08X %08X file:%ls\n"), chksum, palchksum, texturefilename.c_str()); } diff --git a/src/GLideNHQ/TxHiResNoCache.h b/src/GLideNHQ/TxHiResNoCache.h index 8baeabd4..15fb61f0 100644 --- a/src/GLideNHQ/TxHiResNoCache.h +++ b/src/GLideNHQ/TxHiResNoCache.h @@ -10,7 +10,7 @@ class TxHiResNoCache : public TxHiResLoader bool _createFileIndexInDir(tx_wstring directory, bool update); void _clear(); - struct fileIndexEntry_t + struct FileIndexEntry { char fname[MAX_PATH]; tx_wstring directory; @@ -21,8 +21,10 @@ class TxHiResNoCache : public TxHiResLoader tx_wstring _fullTexPath; tx_wstring _ident; char _identc[MAX_PATH]; - std::map _filesIndex; - std::map _loadedTex; + using FileIndexMap = std::multimap; + FileIndexMap _filesIndex; + FileIndexMap::const_iterator findFile(Checksum checksum, N64FormatSize n64FmtSz) const; + std::multimap _loadedTex; dispInfoFuncExt _callback; public: ~TxHiResNoCache(); @@ -37,7 +39,7 @@ class TxHiResNoCache : public TxHiResLoader dispInfoFuncExt callback); bool empty() const override; bool add(Checksum checksum, GHQTexInfo *info, int dataSize = 0) override { return false; } - bool get(Checksum checksum, GHQTexInfo *info) override; + bool get(Checksum checksum, N64FormatSize n64FmtSz, GHQTexInfo *info) override; bool reload() override; void dump() override { }; }; diff --git a/src/GLideNHQ/TxTexCache.cpp b/src/GLideNHQ/TxTexCache.cpp index a8255ead..27234348 100644 --- a/src/GLideNHQ/TxTexCache.cpp +++ b/src/GLideNHQ/TxTexCache.cpp @@ -53,7 +53,7 @@ TxTexCache::TxTexCache(int options, int cachesize, const wchar_t *cachePath, con } } -bool TxTexCache::add(uint64 checksum, GHQTexInfo *info) +bool TxTexCache::add(Checksum checksum, GHQTexInfo *info) { const bool res = TxCache::add(checksum, info); if (res) diff --git a/src/GLideNHQ/TxTexCache.h b/src/GLideNHQ/TxTexCache.h index 4a4a9e3b..edda93d4 100644 --- a/src/GLideNHQ/TxTexCache.h +++ b/src/GLideNHQ/TxTexCache.h @@ -37,7 +37,7 @@ private: public: ~TxTexCache(); TxTexCache(int options, int cachesize, const wchar_t *cachePath, const wchar_t *ident, dispInfoFuncExt callback); - bool add(uint64 checksum /* checksum hi:palette low:texture */, GHQTexInfo *info); + bool add(Checksum checksum, GHQTexInfo *info); void dump(); }; diff --git a/src/Textures.cpp b/src/Textures.cpp index ac037755..04a47bca 100644 --- a/src/Textures.cpp +++ b/src/Textures.cpp @@ -994,11 +994,10 @@ bool TextureCache::_loadHiresBackground(CachedTexture *_pTexture, u64 & _ricecrc } _ricecrc = txfilter_checksum(addr, tile_width, - tile_height, (unsigned short)(gSP.bgImage.format << 8 | gSP.bgImage.size), - bpl, paladdr); + tile_height, gSP.bgImage.size, bpl, paladdr); GHQTexInfo ghqTexInfo; // TODO: fix problem with zero texture dimensions on GLideNHQ side. - if (txfilter_hirestex(_pTexture->crc, _ricecrc, palette, &ghqTexInfo) && + if (txfilter_hirestex(_pTexture->crc, _ricecrc, palette, N64FormatSize(_pTexture->format, _pTexture->size), &ghqTexInfo) && ghqTexInfo.width != 0 && ghqTexInfo.height != 0) { ghqTexInfo.format = gfxContext.convertInternalTextureFormat(ghqTexInfo.format); Context::InitTextureParams params; @@ -1096,7 +1095,7 @@ void TextureCache::_loadBackground(CachedTexture *pTexture) config.hotkeys.enabledKeys[Config::HotKey::hkTexDump] != 0) { txfilter_dmptx((u8*)pDest, pTexture->width, pTexture->height, pTexture->width, (u16)u32(glInternalFormat), - (unsigned short)(pTexture->format << 8 | pTexture->size), + N64FormatSize(pTexture->format, pTexture->size), ricecrc); } @@ -1106,7 +1105,7 @@ void TextureCache::_loadBackground(CachedTexture *pTexture) TFH.isInited()) { GHQTexInfo ghqTexInfo; if (txfilter_filter((u8*)pDest, pTexture->width, pTexture->height, - (u16)u32(glInternalFormat), (uint64)pTexture->crc, &ghqTexInfo) != 0 && + (u16)u32(glInternalFormat), pTexture->crc, N64FormatSize(pTexture->format, pTexture->size), &ghqTexInfo) != 0 && ghqTexInfo.data != nullptr) { if (ghqTexInfo.width % 2 != 0 && @@ -1220,10 +1219,10 @@ bool TextureCache::_loadHiresTexture(u32 _tile, CachedTexture *_pTexture, u64 & // palette = (rdp.pal_8 + (gSP.textureTile[_t]->palette << 4)); } - _ricecrc = txfilter_checksum(addr, width, height, (unsigned short)(_pTexture->format << 8 | _pTexture->size), bpl, paladdr); + _ricecrc = txfilter_checksum(addr, width, height, _pTexture->size, bpl, paladdr); GHQTexInfo ghqTexInfo; // TODO: fix problem with zero texture dimensions on GLideNHQ side. - if (txfilter_hirestex(_pTexture->crc, _ricecrc, palette, &ghqTexInfo) && + if (txfilter_hirestex(_pTexture->crc, _ricecrc, palette, N64FormatSize(_pTexture->format, _pTexture->size), &ghqTexInfo) && ghqTexInfo.width != 0 && ghqTexInfo.height != 0) { ghqTexInfo.format = gfxContext.convertInternalTextureFormat(ghqTexInfo.format); Context::InitTextureParams params; @@ -1491,7 +1490,7 @@ void TextureCache::_loadFast(u32 _tile, CachedTexture *_pTexture) config.hotkeys.enabledKeys[Config::HotKey::hkTexDump] != 0) { txfilter_dmptx((u8*)m_tempTextureHolder.data(), tmptex.width, tmptex.height, tmptex.width, (u16)u32(glInternalFormat), - (unsigned short)(_pTexture->format << 8 | _pTexture->size), + N64FormatSize(_pTexture->format, _pTexture->size), ricecrc); } @@ -1518,6 +1517,7 @@ void TextureCache::_loadFast(u32 _tile, CachedTexture *_pTexture) GHQTexInfo ghqTexInfo; if (txfilter_filter((u8*)m_tempTextureHolder.data(), tmptex.width, tmptex.height, (u16)u32(glInternalFormat), (uint64)_pTexture->crc, + N64FormatSize(_pTexture->format, _pTexture->size), &ghqTexInfo) != 0 && ghqTexInfo.data != nullptr) { if (ghqTexInfo.width % 2 != 0 && ghqTexInfo.format != u32(internalcolorFormat::RGBA8) && @@ -1665,7 +1665,7 @@ void TextureCache::_loadAccurate(u32 _tile, CachedTexture *_pTexture) config.hotkeys.enabledKeys[Config::HotKey::hkTexDump] != 0) { txfilter_dmptx((u8*)(m_tempTextureHolder.data() + texDataOffset), tmptex.width, tmptex.height, tmptex.width, (u16)u32(glInternalFormat), - (unsigned short)(_pTexture->format << 8 | _pTexture->size), + N64FormatSize(_pTexture->format, _pTexture->size), ricecrc); } @@ -1723,7 +1723,7 @@ void TextureCache::_loadAccurate(u32 _tile, CachedTexture *_pTexture) config.hotkeys.enabledKeys[Config::HotKey::hkTexDump] != 0) { txfilter_dmptx((u8*)m_tempTextureHolder.data(), tmptex.width, tmptex.height, tmptex.width, (u16)u32(glInternalFormat), - (unsigned short)(_pTexture->format << 8 | _pTexture->size), + N64FormatSize(_pTexture->format, _pTexture->size), ricecrc); } @@ -1750,6 +1750,7 @@ void TextureCache::_loadAccurate(u32 _tile, CachedTexture *_pTexture) GHQTexInfo ghqTexInfo; if (txfilter_filter((u8*)m_tempTextureHolder.data(), tmptex.width, tmptex.height, (u16)u32(glInternalFormat), (uint64)_pTexture->crc, + N64FormatSize(_pTexture->format, _pTexture->size), &ghqTexInfo) != 0 && ghqTexInfo.data != nullptr) { if (ghqTexInfo.width % 2 != 0 && ghqTexInfo.format != u32(internalcolorFormat::RGBA8) &&