From ded38f88aafb41bd3db574f2ec9f101b9bdba355 Mon Sep 17 00:00:00 2001 From: Sergey Lipskiy Date: Sun, 24 Mar 2024 18:19:13 +0700 Subject: [PATCH] Add "Use strong CRC for texture dump" option. (#2820) * [GLideNHQ] Add checksum64strong(...) function for strong checksum calculation. * Add "Use strong CRC for texture dump" option. When this option is on, textures dumped with alternative strong CRC. Dumps with strong CRC are stored in "strong_crc" subfolder of dump folder. Hires texture load is changed: if HD texture with RiceCRC is not found, the plugin tries to load HD texture with alternative strong CRC. --- src/Config.cpp | 5 ++ src/Config.h | 2 + src/GLideNHQ/TxFilter.cpp | 14 ++- src/GLideNHQ/TxFilter.h | 4 +- src/GLideNHQ/TxFilterExport.cpp | 20 ++++- src/GLideNHQ/TxFilterExport.h | 8 +- src/GLideNHQ/TxUtil.cpp | 137 ++++++++++++++++++++++++----- src/GLideNHQ/TxUtil.h | 10 ++- src/GLideNUI/ConfigDialog.cpp | 4 + src/GLideNUI/Settings.cpp | 3 + src/GLideNUI/configDialog.ui | 10 +++ src/TextureFilterHandler.cpp | 2 + src/Textures.cpp | 53 ++++++++--- src/Textures.h | 2 +- src/VI.cpp | 9 ++ src/mupenplus/Config_mupenplus.cpp | 7 ++ 16 files changed, 246 insertions(+), 44 deletions(-) diff --git a/src/Config.cpp b/src/Config.cpp index c4e971625..8a2463f45 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -103,6 +103,7 @@ void Config::resetToDefaults() textureFilter.txCacheCompression = 1; textureFilter.txSaveCache = 1; textureFilter.txDump = 0; + textureFilter.txStrongCRC = 0; textureFilter.txEnhancedTextureFileStorage = 0; textureFilter.txHiresTextureFileStorage = 0; @@ -207,6 +208,8 @@ const char* Config::hotkeyIniName(u32 _idx) return "hkForceGammaCorrection"; case Config::HotKey::hkInaccurateTexCords: return "hkInaccurateTexCords"; + case Config::HotKey::hkStrongCRC: + return "hkStrongCRC"; } return nullptr; } @@ -245,6 +248,8 @@ const char* Config::enabledHotkeyIniName(u32 _idx) return "hkForceGammaCorrectionEnabled"; case Config::HotKey::hkInaccurateTexCords: return "hkInaccurateTexCordsEnabled"; + case Config::HotKey::hkStrongCRC: + return "hkStrongCRCEnabled"; } return nullptr; } diff --git a/src/Config.h b/src/Config.h index 07ffa138a..053a27622 100644 --- a/src/Config.h +++ b/src/Config.h @@ -177,6 +177,7 @@ struct Config u32 txCacheCompression; // Zip textures cache u32 txSaveCache; // Save texture cache to hard disk u32 txDump; // Dump textures + u32 txStrongCRC; // Dump textures with alternative (strong) CRC u32 txEnhancedTextureFileStorage; // Use file storage instead of memory cache for enhanced textures. u32 txHiresTextureFileStorage; // Use file storage instead of memory cache for hires textures. @@ -239,6 +240,7 @@ struct Config hkOsdRenderingResolution, hkForceGammaCorrection, hkInaccurateTexCords, + hkStrongCRC, hkTotal }; diff --git a/src/GLideNHQ/TxFilter.cpp b/src/GLideNHQ/TxFilter.cpp index 231b41864..fe5b774e6 100644 --- a/src/GLideNHQ/TxFilter.cpp +++ b/src/GLideNHQ/TxFilter.cpp @@ -580,8 +580,18 @@ TxFilter::checksum64(uint8 *src, int width, int height, int size, int rowStride, return 0; } +uint64 +TxFilter::checksum64strong(uint8 *src, int width, int height, int size, int rowStride, uint8 *palette) +{ + if (_options & (HIRESTEXTURES_MASK | DUMP_TEX)) + return TxUtil::checksum64strong(src, width, height, size, rowStride, palette); + + return 0; +} + boolean -TxFilter::dmptx(uint8 *src, int width, int height, int rowStridePixel, ColorFormat gfmt, N64FormatSize n64FmtSz, Checksum r_crc64) +TxFilter::dmptx(uint8 *src, int width, int height, int rowStridePixel, + ColorFormat gfmt, N64FormatSize n64FmtSz, Checksum r_crc64, boolean isStrongCrc) { assert(gfmt != graphics::colorFormat::RGBA); if (!_initialized) @@ -609,7 +619,7 @@ TxFilter::dmptx(uint8 *src, int width, int height, int rowStridePixel, ColorForm tmpbuf.assign(_dumpPath); tmpbuf.append(wst("/")); tmpbuf.append(_ident); - tmpbuf.append(wst("/GLideNHQ")); + isStrongCrc ? tmpbuf.append(wst("/GLideNHQ_strong_crc")) : tmpbuf.append(wst("/GLideNHQ")); if (!osal_path_existsW(tmpbuf.c_str()) && osal_mkdirp(tmpbuf.c_str()) != 0) return 0; diff --git a/src/GLideNHQ/TxFilter.h b/src/GLideNHQ/TxFilter.h index 2c4af8e4e..75d0aa4b3 100644 --- a/src/GLideNHQ/TxFilter.h +++ b/src/GLideNHQ/TxFilter.h @@ -78,7 +78,9 @@ class TxFilter 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, N64FormatSize n64FmtSz, Checksum r_crc64); + uint64 checksum64strong(uint8 *src, int width, int height, int size, int rowStride, uint8 *palette); + boolean dmptx(uint8 *src, int width, int height, int rowStridePixel, + ColorFormat gfmt, N64FormatSize n64FmtSz, Checksum r_crc64, boolean isStrongCrc); boolean reloadhirestex(); void dumpcache(); }; diff --git a/src/GLideNHQ/TxFilterExport.cpp b/src/GLideNHQ/TxFilterExport.cpp index 335276b06..dc892e858 100644 --- a/src/GLideNHQ/TxFilterExport.cpp +++ b/src/GLideNHQ/TxFilterExport.cpp @@ -84,15 +84,33 @@ txfilter_checksum(uint8 *src, int width, int height, int size, int rowStride, ui return 0; } +TAPI uint64 TAPIENTRY +txfilter_checksum_strong(uint8 *src, int width, int height, int size, int rowStride, uint8 *palette) +{ + if (txFilter) + return txFilter->checksum64strong(src, width, height, size, rowStride, palette); + + return 0; +} + TAPI boolean TAPIENTRY 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)), n64FmtSz, r_crc64); + return txFilter->dmptx(src, width, height, rowStridePixel, ColorFormat(u32(gfmt)), n64FmtSz, r_crc64, FALSE); return 0; } +TAPI boolean TAPIENTRY +txfilter_dmptx_strong(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)), n64FmtSz, r_crc64, TRUE); + + return 0; +} + TAPI boolean TAPIENTRY txfilter_reloadhirestex() { diff --git a/src/GLideNHQ/TxFilterExport.h b/src/GLideNHQ/TxFilterExport.h index eaf655a8b..9633d04ed 100644 --- a/src/GLideNHQ/TxFilterExport.h +++ b/src/GLideNHQ/TxFilterExport.h @@ -92,7 +92,7 @@ typedef unsigned char boolean; #define GZ_HIRESTEXCACHE 0x00800000 #define DUMP_TEXCACHE 0x01000000 #define DUMP_HIRESTEXCACHE 0x02000000 -#define UNDEFINED_0 0x04000000 +#define DUMP_STRONG_CRC 0x04000000 #define UNDEFINED_1 0x08000000 #define FORCE16BPP_HIRESTEX 0x10000000 #define FORCE16BPP_TEX 0x20000000 @@ -225,9 +225,15 @@ txfilter_hirestex(uint64 g64crc, Checksum r_crc64, uint16 *palette, N64FormatSiz TAPI uint64 TAPIENTRY txfilter_checksum(uint8 *src, int width, int height, int size, int rowStride, uint8 *palette); +TAPI uint64 TAPIENTRY +txfilter_checksum_strong(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, N64FormatSize n64FmtSz, Checksum r_crc64); +TAPI boolean TAPIENTRY +txfilter_dmptx_strong(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/TxUtil.cpp b/src/GLideNHQ/TxUtil.cpp index 0a12b0a9a..57a132fda 100644 --- a/src/GLideNHQ/TxUtil.cpp +++ b/src/GLideNHQ/TxUtil.cpp @@ -38,21 +38,22 @@ #include #endif +#define XXH_INLINE_ALL +#include "xxHash/xxhash.h" + /* * Utilities ******************************************************************************/ +static uint32 Uint64ToUint32(uint64_t t) +{ + return static_cast((t & 0xFFFFFFFF) ^ (t >> 32)); +} + uint32 TxUtil::checksumTx(uint8 *src, int width, int height, ColorFormat format) { int dataSize = sizeofTx(width, height, format); - - /* for now we use adler32 if something else is better - * we can simply swtich later - */ - /* return (dataSize ? Adler32(src, dataSize, 1) : 0); */ - - /* zlib crc32 */ - return (dataSize ? crc32(crc32(0L, Z_NULL, 0), src, dataSize) : 0); + return Uint64ToUint32(XXH3_64bits(src, dataSize)); } int @@ -77,18 +78,6 @@ TxUtil::sizeofTx(int width, int height, ColorFormat format) return dataSize; } -uint32 -TxUtil::checksum(uint8 *src, int width, int height, int size, int rowStride) -{ - /* Rice CRC32 for now. We can switch this to Jabo MD5 or - * any other custom checksum. - * TODO: use *_HIRESTEXTURE option. */ - - if (!src) return 0; - - return RiceCRC32(src, width, height, size, rowStride); -} - uint64 TxUtil::checksum64(uint8 *src, int width, int height, int size, int rowStride, uint8 *palette) { @@ -126,6 +115,43 @@ TxUtil::checksum64(uint8 *src, int width, int height, int size, int rowStride, u return crc64Ret; } +uint64 +TxUtil::checksum64strong(uint8 *src, int width, int height, int size, int rowStride, uint8 *palette) +{ + /* XXH3_64bits for strong 32bit texture hash. */ + /* Returned value is 64bits: hi=palette crc32 low=texture crc32 */ + + if (!src) + return 0; + + uint64 crc64Ret = 0; + + if (palette) { + uint32 crc32 = 0, cimax = 0; + switch (size & 0xff) { + case 1: + if (StrongCRC32_CI8(src, width, height, rowStride, &crc32, &cimax)) { + crc64Ret = StrongCRC32(palette, cimax + 1, 1, 2, 512); + crc64Ret <<= 32; + crc64Ret |= crc32; + } + break; + case 0: + if (StrongCRC32_CI4(src, width, height, rowStride, &crc32, &cimax)) { + crc64Ret = StrongCRC32(palette, cimax + 1, 1, 2, 32); + crc64Ret <<= 32; + crc64Ret |= crc32; + } + } + } + + if (!crc64Ret) { + crc64Ret = StrongCRC32(src, width, height, size, rowStride); + } + + return crc64Ret; +} + /* Rice CRC32 for hires texture packs */ /* NOTE: The following is used in Glide64 to calculate the CRC32 * for Rice hires texture packs. @@ -484,6 +510,77 @@ TxUtil::RiceCRC32_CI8(const uint8* src, int width, int height, int rowStride, return 1; } +uint32 +TxUtil::StrongCRC32(const uint8* src, int width, int height, int size, int rowStride) +{ + /* NOTE: bytesPerLine must be equal or larger than 4 */ + const uint32 bytesPerLine = width << size >> 1; + + u64 crc = UINT64_MAX; + std::vector buf(static_cast(height) * std::max(bytesPerLine, static_cast(rowStride))); + uint8* pData = buf.data(); + try { + for (int y = 0; y < height; ++y) { + if (bytesPerLine < 4) { + // bytesPerLine must be >= 4, but if it less than 4, reproduce RiceCRC behavior, + // that is read bytes before provided source address. + memcpy(pData, src - 4 + bytesPerLine, 4); + pData += 4; + } + else { + memcpy(pData, src, bytesPerLine); + pData += bytesPerLine; + } + src += rowStride; + } + crc = XXH3_64bits(buf.data(), static_cast(pData - buf.data())); + } + catch (...) { + DBG_INFO(80, wst("Error: StrongCRC32 exception!\n")); + } + + return Uint64ToUint32(crc); +} + +boolean +TxUtil::StrongCRC32_CI4(const uint8* src, int width, int height, int rowStride, + uint32* crc32, uint32* cimax) +{ + /* NOTE: bytes_per_width must be equal or larger than 4 */ + + /* 4bit CI */ + try { + uint32 crc32Ret = StrongCRC32(src, width, height, 0, rowStride); + uint32 cimaxRet = CalculateMaxCI4b(src, width, height, rowStride); + *crc32 = crc32Ret; + *cimax = cimaxRet; + return 1; + } catch(...) { + DBG_INFO(80, wst("Error: RiceCRC32 exception!\n")); + } + return 0; +} + +boolean +TxUtil::StrongCRC32_CI8(const uint8* src, int width, int height, int rowStride, + uint32* crc32, uint32* cimax) +{ + /* NOTE: bytes_per_width must be equal or larger than 4 */ + + /* 8bit CI */ + try { + uint32 crc32Ret = StrongCRC32(src, width, height, 1, rowStride); + uint32 cimaxRet = CalculateMaxCI8b(src, width, height, rowStride); + *crc32 = crc32Ret; + *cimax = cimaxRet; + return 1; + } + catch (...) { + DBG_INFO(80, wst("Error: RiceCRC32 exception!\n")); + } + return 0; +} + uint32 TxUtil::getNumberofProcessors() { uint32 numcore = std::thread::hardware_concurrency(); diff --git a/src/GLideNHQ/TxUtil.h b/src/GLideNHQ/TxUtil.h index 26b6a0589..1c0b2e61c 100644 --- a/src/GLideNHQ/TxUtil.h +++ b/src/GLideNHQ/TxUtil.h @@ -43,14 +43,16 @@ class TxUtil uint32* crc32, uint32* cimax); static boolean RiceCRC32_CI8(const uint8* src, int width, int height, int rowStride, uint32* crc32, uint32* cimax); + static uint32 StrongCRC32(const uint8* src, int width, int height, int size, int rowStride); + static boolean StrongCRC32_CI4(const uint8* src, int width, int height, int rowStride, + uint32* crc32, uint32* cimax); + static boolean StrongCRC32_CI8(const uint8* src, int width, int height, int rowStride, + uint32* crc32, uint32* cimax); public: static int sizeofTx(int width, int height, ColorFormat format); static uint32 checksumTx(uint8 *data, int width, int height, ColorFormat format); -#if 0 /* unused */ - static uint32 chkAlpha(uint32* src, int width, int height); -#endif - static uint32 checksum(uint8 *src, int width, int height, int size, int rowStride); static uint64 checksum64(uint8 *src, int width, int height, int size, int rowStride, uint8 *palette); + static uint64 checksum64strong(uint8 *src, int width, int height, int size, int rowStride, uint8 *palette); static uint32 getNumberofProcessors(); }; diff --git a/src/GLideNUI/ConfigDialog.cpp b/src/GLideNUI/ConfigDialog.cpp index d9dc88053..e00cee456 100644 --- a/src/GLideNUI/ConfigDialog.cpp +++ b/src/GLideNUI/ConfigDialog.cpp @@ -105,6 +105,8 @@ QString ConfigDialog::_hotkeyDescription(quint32 _idx) const return tr("Toggle force gamma correction"); case Config::HotKey::hkInaccurateTexCords: return tr("Toggle inaccurate texture coordinates"); + case Config::HotKey::hkStrongCRC: + return tr("Toggle strong CRC for textures dump"); } return tr("Unknown hotkey"); } @@ -373,6 +375,7 @@ void ConfigDialog::_init(bool reInit, bool blockCustomSettings) ui->texturePackGroupBox->setChecked(config.textureFilter.txHiresEnable != 0); ui->alphaChannelCheckBox->setChecked(config.textureFilter.txHiresFullAlphaChannel != 0); ui->alternativeCRCCheckBox->setChecked(config.textureFilter.txHresAltCRC != 0); + ui->strongCRCCheckBox->setChecked(config.textureFilter.txStrongCRC != 0); ui->force16bppCheckBox->setChecked(config.textureFilter.txForce16bpp != 0); ui->compressCacheCheckBox->setChecked(config.textureFilter.txCacheCompression != 0); ui->saveTextureCacheCheckBox->setChecked(config.textureFilter.txSaveCache != 0); @@ -689,6 +692,7 @@ void ConfigDialog::accept(bool justSave) { config.textureFilter.txHiresEnable = ui->texturePackGroupBox->isChecked() ? 1 : 0; config.textureFilter.txHiresFullAlphaChannel = ui->alphaChannelCheckBox->isChecked() ? 1 : 0; config.textureFilter.txHresAltCRC = ui->alternativeCRCCheckBox->isChecked() ? 1 : 0; + config.textureFilter.txStrongCRC = ui->strongCRCCheckBox->isChecked() ? 1 : 0; config.textureFilter.txCacheCompression = ui->compressCacheCheckBox->isChecked() ? 1 : 0; config.textureFilter.txForce16bpp = ui->force16bppCheckBox->isChecked() ? 1 : 0; diff --git a/src/GLideNUI/Settings.cpp b/src/GLideNUI/Settings.cpp index c32e0472c..be7a9a1ba 100644 --- a/src/GLideNUI/Settings.cpp +++ b/src/GLideNUI/Settings.cpp @@ -103,6 +103,7 @@ void _loadSettings(QSettings & settings) config.textureFilter.txHiresEnable = settings.value("txHiresEnable", config.textureFilter.txHiresEnable).toInt(); config.textureFilter.txHiresFullAlphaChannel = settings.value("txHiresFullAlphaChannel", config.textureFilter.txHiresFullAlphaChannel).toInt(); config.textureFilter.txHresAltCRC = settings.value("txHresAltCRC", config.textureFilter.txHresAltCRC).toInt(); + config.textureFilter.txStrongCRC = settings.value("txStrongCRC", config.textureFilter.txStrongCRC).toInt(); config.textureFilter.txForce16bpp = settings.value("txForce16bpp", config.textureFilter.txForce16bpp).toInt(); config.textureFilter.txCacheCompression = settings.value("txCacheCompression", config.textureFilter.txCacheCompression).toInt(); config.textureFilter.txSaveCache = settings.value("txSaveCache", config.textureFilter.txSaveCache).toInt(); @@ -252,6 +253,7 @@ void _writeSettingsToFile(const QString & filename) settings.setValue("txHiresEnable", config.textureFilter.txHiresEnable); settings.setValue("txHiresFullAlphaChannel", config.textureFilter.txHiresFullAlphaChannel); settings.setValue("txHresAltCRC", config.textureFilter.txHresAltCRC); + settings.setValue("txStrongCRC", config.textureFilter.txStrongCRC); settings.setValue("txForce16bpp", config.textureFilter.txForce16bpp); settings.setValue("txCacheCompression", config.textureFilter.txCacheCompression); settings.setValue("txSaveCache", config.textureFilter.txSaveCache); @@ -550,6 +552,7 @@ void saveCustomRomSettings(const QString & _strIniFolder, const QString & _strSh WriteCustomSetting(textureFilter, txHiresEnable); WriteCustomSetting(textureFilter, txHiresFullAlphaChannel); WriteCustomSetting(textureFilter, txHresAltCRC); + WriteCustomSetting(textureFilter, txStrongCRC); WriteCustomSetting(textureFilter, txForce16bpp); WriteCustomSetting(textureFilter, txCacheCompression); WriteCustomSetting(textureFilter, txSaveCache); diff --git a/src/GLideNUI/configDialog.ui b/src/GLideNUI/configDialog.ui index 7f8f8ad1a..c66745048 100644 --- a/src/GLideNUI/configDialog.ui +++ b/src/GLideNUI/configDialog.ui @@ -2678,6 +2678,16 @@ + + + + <html><head/><body><p>This option enables alternative, strong CRC method instead of RiceCRC for texture dump. If you find some textures not dumped, try checking this option.</p><p>[Recommended: <span style=" font-style:italic;">Mostly unchecked, unless RiceCRC fails</span>]</p></body></html> + + + Strong CRC calculation (when RiceCRC fails) + + + diff --git a/src/TextureFilterHandler.cpp b/src/TextureFilterHandler.cpp index 5233b85fd..aa864df68 100644 --- a/src/TextureFilterHandler.cpp +++ b/src/TextureFilterHandler.cpp @@ -57,6 +57,8 @@ u32 TextureFilterHandler::_getConfigOptions() const options |= LET_TEXARTISTS_FLY; if (config.hotkeys.enabledKeys[Config::HotKey::hkTexDump] != 0 || config.textureFilter.txDump) options |= DUMP_TEX; + if (config.textureFilter.txStrongCRC) + options |= DUMP_STRONG_CRC; if (config.textureFilter.txDeposterize) options |= DEPOSTERIZE; if (config.textureFilter.txEnhancedTextureFileStorage) diff --git a/src/Textures.cpp b/src/Textures.cpp index f340c9e24..4d4c91a9b 100644 --- a/src/Textures.cpp +++ b/src/Textures.cpp @@ -1151,7 +1151,7 @@ void TextureCache::_loadBackground(CachedTexture *pTexture) free(pDest); } -bool TextureCache::_loadHiresTexture(u32 _tile, CachedTexture *_pTexture, u64 & _ricecrc) +bool TextureCache::_loadHiresTexture(u32 _tile, CachedTexture *_pTexture, u64 & _ricecrc, u64 & _strongcrc) { if (config.textureFilter.txHiresEnable == 0 || !TFH.isInited()) return false; @@ -1221,10 +1221,18 @@ bool TextureCache::_loadHiresTexture(u32 _tile, CachedTexture *_pTexture, u64 & } _ricecrc = txfilter_checksum(addr, width, height, _pTexture->size, bpl, paladdr); + if (config.textureFilter.txStrongCRC) + _strongcrc = txfilter_checksum_strong(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, N64FormatSize(_pTexture->format, _pTexture->size), &ghqTexInfo) && - ghqTexInfo.width != 0 && ghqTexInfo.height != 0) { + auto hirestexFound = txfilter_hirestex(_pTexture->crc, _ricecrc, palette, N64FormatSize(_pTexture->format, _pTexture->size), &ghqTexInfo); + if (!hirestexFound) { + // Texture with RiceCRC was not found. Try alternative CRC. + if (_strongcrc == 0U) + _strongcrc = txfilter_checksum_strong(addr, width, height, _pTexture->size, bpl, paladdr); + hirestexFound = txfilter_hirestex(_pTexture->crc, _strongcrc, palette, N64FormatSize(_pTexture->format, _pTexture->size), &ghqTexInfo); + } + if (hirestexFound && ghqTexInfo.width != 0 && ghqTexInfo.height != 0) { ghqTexInfo.format = gfxContext.convertInternalTextureFormat(ghqTexInfo.format); Context::InitTextureParams params; params.handle = _pTexture->name; @@ -1390,7 +1398,8 @@ void doubleTexture(T* pTex, u32 width, u32 height) void TextureCache::_loadFast(u32 _tile, CachedTexture *_pTexture) { u64 ricecrc = 0; - if (_loadHiresTexture(_tile, _pTexture, ricecrc)) + u64 strongcrc = 0; + if (_loadHiresTexture(_tile, _pTexture, ricecrc, strongcrc)) return; s32 mipLevel = 0; @@ -1490,10 +1499,15 @@ void TextureCache::_loadFast(u32 _tile, CachedTexture *_pTexture) config.textureFilter.txHiresEnable != 0 && config.hotkeys.enabledKeys[Config::HotKey::hkTexDump] != 0) || config.textureFilter.txDump) { - txfilter_dmptx((u8*)m_tempTextureHolder.data(), tmptex.width, tmptex.height, - tmptex.width, (u16)u32(glInternalFormat), - N64FormatSize(_pTexture->format, _pTexture->size), - ricecrc); + config.textureFilter.txStrongCRC ? + txfilter_dmptx_strong((u8*)m_tempTextureHolder.data(), tmptex.width, tmptex.height, + tmptex.width, (u16)u32(glInternalFormat), + N64FormatSize(_pTexture->format, _pTexture->size), + strongcrc) : + txfilter_dmptx((u8*)m_tempTextureHolder.data(), tmptex.width, tmptex.height, + tmptex.width, (u16)u32(glInternalFormat), + N64FormatSize(_pTexture->format, _pTexture->size), + ricecrc); } bool bLoaded = false; @@ -1591,7 +1605,8 @@ void TextureCache::_loadFast(u32 _tile, CachedTexture *_pTexture) void TextureCache::_loadAccurate(u32 _tile, CachedTexture *_pTexture) { u64 ricecrc = 0; - if (_loadHiresTexture(_tile, _pTexture, ricecrc)) + u64 strongcrc = 0; + if (_loadHiresTexture(_tile, _pTexture, ricecrc, strongcrc)) return; bool force32bitFormat = false; @@ -1666,10 +1681,15 @@ void TextureCache::_loadAccurate(u32 _tile, CachedTexture *_pTexture) config.textureFilter.txHiresEnable != 0 && config.hotkeys.enabledKeys[Config::HotKey::hkTexDump] != 0) || config.textureFilter.txDump) { - txfilter_dmptx((u8*)(m_tempTextureHolder.data() + texDataOffset), tmptex.width, tmptex.height, - tmptex.width, (u16)u32(glInternalFormat), - N64FormatSize(_pTexture->format, _pTexture->size), - ricecrc); + config.textureFilter.txStrongCRC ? + txfilter_dmptx_strong((u8*)(m_tempTextureHolder.data() + texDataOffset), tmptex.width, tmptex.height, + tmptex.width, (u16)u32(glInternalFormat), + N64FormatSize(_pTexture->format, _pTexture->size), + strongcrc) : + txfilter_dmptx((u8*)(m_tempTextureHolder.data() + texDataOffset), tmptex.width, tmptex.height, + tmptex.width, (u16)u32(glInternalFormat), + N64FormatSize(_pTexture->format, _pTexture->size), + ricecrc); } texDataOffset += tmptex.width * tmptex.height; @@ -1725,7 +1745,12 @@ void TextureCache::_loadAccurate(u32 _tile, CachedTexture *_pTexture) config.textureFilter.txHiresEnable != 0 && config.hotkeys.enabledKeys[Config::HotKey::hkTexDump] != 0) || config.textureFilter.txDump) { - txfilter_dmptx((u8*)m_tempTextureHolder.data(), tmptex.width, tmptex.height, + config.textureFilter.txStrongCRC ? + txfilter_dmptx_strong((u8*)m_tempTextureHolder.data(), tmptex.width, tmptex.height, + tmptex.width, (u16)u32(glInternalFormat), + N64FormatSize(_pTexture->format, _pTexture->size), + strongcrc) : + txfilter_dmptx((u8*)m_tempTextureHolder.data(), tmptex.width, tmptex.height, tmptex.width, (u16)u32(glInternalFormat), N64FormatSize(_pTexture->format, _pTexture->size), ricecrc); diff --git a/src/Textures.h b/src/Textures.h index 0fb985231..fb84d6e5f 100644 --- a/src/Textures.h +++ b/src/Textures.h @@ -90,7 +90,7 @@ struct TextureCache CachedTexture * _addTexture(u64 _crc64); void _loadFast(u32 _tile, CachedTexture *_pTexture); void _loadAccurate(u32 _tile, CachedTexture *_pTexture); - bool _loadHiresTexture(u32 _tile, CachedTexture *_pTexture, u64 & _ricecrc); + bool _loadHiresTexture(u32 _tile, CachedTexture *_pTexture, u64 & _ricecrc, u64 & _strongcrc); void _loadBackground(CachedTexture *pTexture); bool _loadHiresBackground(CachedTexture *_pTexture, u64 & _ricecrc); void _loadDepthTexture(CachedTexture * _pTexture, u16* _pDest); diff --git a/src/VI.cpp b/src/VI.cpp index ed8099043..fafa695d7 100644 --- a/src/VI.cpp +++ b/src/VI.cpp @@ -15,6 +15,7 @@ #include "DebugDump.h" #include "osal_keys.h" #include "DisplayWindow.h" +#include "TextureFilterHandler.h" #include "GLideNHQ/TxFilterExport.h" #include @@ -131,6 +132,14 @@ static void checkHotkeys() /* Turn on texture dump */ if (osal_is_key_pressed(config.hotkeys.enabledKeys[Config::hkTexDump], 0x0001)) textureCache().toggleDumpTex(); + + if (osal_is_key_pressed(config.hotkeys.enabledKeys[Config::hkStrongCRC], 0x0001)) { + if (config.textureFilter.txStrongCRC == 0) + dwnd().getDrawer().showMessage("Enable strong CRC for textures dump\n", Milliseconds(750)); + else + dwnd().getDrawer().showMessage("Disable strong CRC for textures dump\n", Milliseconds(750)); + config.textureFilter.txStrongCRC = !config.textureFilter.txStrongCRC; + } } if (osal_is_key_pressed(config.hotkeys.enabledKeys[Config::hkTexCoordBounds], 0x0001)) { diff --git a/src/mupenplus/Config_mupenplus.cpp b/src/mupenplus/Config_mupenplus.cpp index 73598ccd7..2d9315d62 100644 --- a/src/mupenplus/Config_mupenplus.cpp +++ b/src/mupenplus/Config_mupenplus.cpp @@ -53,6 +53,8 @@ const char* _hotkeyDescription(u32 _idx) return "Hotkey: toggle force gamma correction"; case Config::HotKey::hkInaccurateTexCords: return "Hotkey: toggle inaccurate texture coordinates"; + case Config::HotKey::hkStrongCRC: + return "Hotkey: toggle strong CRC for textures dump"; } return "Unknown hotkey"; } @@ -257,6 +259,8 @@ bool Config_SetDefault() assert(res == M64ERR_SUCCESS); res = ConfigSetDefaultBool(g_configVideoGliden64, "txDump", config.textureFilter.txDump, "Dump textures"); assert(res == M64ERR_SUCCESS); + res = ConfigSetDefaultBool(g_configVideoGliden64, "txStrongCRC", config.textureFilter.txStrongCRC, "Use strong CRC for texture dump."); + assert(res == M64ERR_SUCCESS); res = ConfigSetDefaultBool(g_configVideoGliden64, "txEnhancedTextureFileStorage", config.textureFilter.txEnhancedTextureFileStorage, "Use file storage instead of memory cache for enhanced textures."); assert(res == M64ERR_SUCCESS); res = ConfigSetDefaultBool(g_configVideoGliden64, "txHiresTextureFileStorage", config.textureFilter.txHiresTextureFileStorage, "Use file storage instead of memory cache for HD textures."); @@ -473,6 +477,8 @@ void Config_LoadCustomConfig() if (result == M64ERR_SUCCESS) config.textureFilter.txSaveCache = atoi(value); result = ConfigExternalGetParameter(fileHandle, sectionName, "textureFilter\\txDump", value, sizeof(value)); if (result == M64ERR_SUCCESS) config.textureFilter.txDump = atoi(value); + result = ConfigExternalGetParameter(fileHandle, sectionName, "textureFilter\\txStrongCRC", value, sizeof(value)); + if (result == M64ERR_SUCCESS) config.textureFilter.txStrongCRC = atoi(value); result = ConfigExternalGetParameter(fileHandle, sectionName, "textureFilter\\txEnhancedTextureFileStorage", value, sizeof(value)); if (result == M64ERR_SUCCESS) config.textureFilter.txEnhancedTextureFileStorage = atoi(value); result = ConfigExternalGetParameter(fileHandle, sectionName, "textureFilter\\txHiresTextureFileStorage", value, sizeof(value)); @@ -569,6 +575,7 @@ void Config_LoadConfig() config.textureFilter.txCacheCompression = ConfigGetParamBool(g_configVideoGliden64, "txCacheCompression"); config.textureFilter.txSaveCache = ConfigGetParamBool(g_configVideoGliden64, "txSaveCache"); config.textureFilter.txDump = ConfigGetParamBool(g_configVideoGliden64, "txDump"); + config.textureFilter.txStrongCRC = ConfigGetParamBool(g_configVideoGliden64, "txStrongCRC"); config.textureFilter.txEnhancedTextureFileStorage = ConfigGetParamBool(g_configVideoGliden64, "txEnhancedTextureFileStorage"); config.textureFilter.txHiresTextureFileStorage = ConfigGetParamBool(g_configVideoGliden64, "txHiresTextureFileStorage"); config.textureFilter.txNoTextureFileStorage = ConfigGetParamBool(g_configVideoGliden64, "txNoTextureFileStorage");