diff --git a/Source/Core/VideoCommon/Src/TextureDecoder.cpp b/Source/Core/VideoCommon/Src/TextureDecoder.cpp index 1cf39c17ea..606c1223d3 100644 --- a/Source/Core/VideoCommon/Src/TextureDecoder.cpp +++ b/Source/Core/VideoCommon/Src/TextureDecoder.cpp @@ -88,26 +88,63 @@ int TexDecoder_GetTextureSizeInBytes(int width, int height, int format) return (width * height * TexDecoder_GetTexelSizeInNibbles(format)) / 2; } -u64 TexDecoder_GetFullHash(const u8 *key, int len, u64 seed) +u32 TexDecoder_GetFullHash32(const u8 *src, int len, u32 seed) +{ + const u32 m = 0x5bd1e995; + const int r = 24; + + u32 h = seed ^ len; + + const u32 * data = (const u32 *)src; + int Flen = len / 4; + + while(len) + { + u32 k = data[0]; + k *= m; + k ^= k >> r; + //k *= m; + //h *= m; + h ^= k; + + data++; + len --; + } + + switch(len) + { + case 3: h ^= data[2] << 16; + case 2: h ^= data[1] << 8; + case 1: h ^= data[0]; + h *= m; + }; + h ^= h >> 13; + h *= m; + h ^= h >> 15; + return h; +} + +#ifdef _M_X64 +u64 TexDecoder_GetFullHash(const u8 *src, int len, u64 seed) { const u64 m = 0xc6a4a7935bd1e995; const int r = 47; u64 h = seed ^ (len * m); - const u64 * data = (const u64 *)key; + const u64 * data = (const u64 *)src; const u64 * end = data + (len/8); - + while(data != end) { - u64 k = *data++; - + u64 k = data[0]; + data++; k *= m; k ^= k >> r; - k *= m; + //k *= m; h ^= k; - h *= m; + //h *= m; } const u8 * data2 = (const u8*)data; @@ -131,6 +168,70 @@ u64 TexDecoder_GetFullHash(const u8 *key, int len, u64 seed) return h; } +#else +u64 TexDecoder_GetFullHash(const u8 *src, int len, u64 seed) +{ + const u32 m = 0x5bd1e995; + const int r = 24; + + u32 h1 = seed ^ len; + u32 h2 = 0; + + const u32 * data = (const u32 *)src; + + while(len >= 8) + { + u32 k1 = *data++; + k1 *= m; + k1 ^= k1 >> r; + //k1 *= m; + //h1 *= m; + h1 ^= k1; + len -= 4; + + u32 k2 = *data++; + k2 *= m; + k2 ^= k2 >> r; + //k2 *= m; + //h2 *= m; + h2 ^= k2; + len -= 4; + } + + if(len >= 4) + { + u32 k1 = *data++; + k1 *= m; + k1 ^= k1 >> r; + //k1 *= m; + //h1 *= m; + h1 ^= k1; + len -= 4; + } + + switch(len) + { + case 3: h2 ^= ((u8*)data)[2] << 16; + case 2: h2 ^= ((u8*)data)[1] << 8; + case 1: h2 ^= ((u8*)data)[0]; + h2 *= m; + }; + + h1 ^= h2 >> 18; h1 *= m; + h2 ^= h1 >> 22; h2 *= m; + h1 ^= h2 >> 17; h1 *= m; + h2 ^= h1 >> 19; h2 *= m; + + u64 h = h1; + + h = (h << 32) | h2; + + return h; +} + + +#endif + u64 TexDecoder_GetFastHash(const u8 *src, int len, u64 seed) { u64 hash = seed ? seed : 0x1337c0debeefbabe; diff --git a/Source/Core/VideoCommon/Src/TextureDecoder.h b/Source/Core/VideoCommon/Src/TextureDecoder.h index 187401a5a9..cc5a17851f 100644 --- a/Source/Core/VideoCommon/Src/TextureDecoder.h +++ b/Source/Core/VideoCommon/Src/TextureDecoder.h @@ -91,6 +91,7 @@ void TexDecoder_DecodeTexel(u8 *dst, const u8 *src, int s, int t, int imageWidth u64 TexDecoder_GetFullHash(const u8 *src, int len, u64 seed = 0); u64 TexDecoder_GetFastHash(const u8 *src, int len, u64 seed = 0); +u32 TexDecoder_GetFullHash32(const u8 *src, int len, u32 seed = 0); void TexDecoder_SetTexFmtOverlayOptions(bool enable, bool center); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp index 1cc4d0832a..c76cf409ce 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp @@ -167,10 +167,13 @@ TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width, // visible or invisible. Thus, unless we want to recreate the textures for every drawn character, // we must make sure that texture with different tluts get different IDs. texHash = TexDecoder_GetFullHash(ptr,TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, tex_format)); - u64 tlutHash = TexDecoder_GetFullHash(&texMem[tlutaddr], TexDecoder_GetPaletteSize(tex_format)); - texHash ^= tlutHash; + u32 tlutHash = TexDecoder_GetFullHash32(&texMem[tlutaddr], TexDecoder_GetPaletteSize(tex_format)); + //texHash ^= tlutHash; //this line was the problem, as the hash changes with the tlut hash + //the textures where alway recreated if (g_ActiveConfig.bSafeTextureCache) - texID = texID ^ ((u32)(tlutHash & 0xFFFFFFFF)) ^ ((u32)((tlutHash >> 32) & 0xFFFFFFFF)); + { + texID = texID ^ tlutHash; + } } else { diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.cpp b/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.cpp index 4aac7e1d6d..49d418f4e5 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.cpp @@ -275,10 +275,10 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width // visible or invisible. Thus, unless we want to recreate the textures for every drawn character, // we must make sure that texture with different tluts get different IDs. texHash = TexDecoder_GetFullHash(ptr,TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, tex_format)); - u64 tlutHash = TexDecoder_GetFullHash(&texMem[tlutaddr], TexDecoder_GetPaletteSize(tex_format)); - texHash ^= tlutHash; + u32 tlutHash = TexDecoder_GetFullHash32(&texMem[tlutaddr], TexDecoder_GetPaletteSize(tex_format)); + //texHash ^= tlutHash; if (g_ActiveConfig.bSafeTextureCache) - texID = texID ^ ((u32)(tlutHash & 0xFFFFFFFF)) ^ ((u32)((tlutHash >> 32) & 0xFFFFFFFF)); + texID = texID ^ tlutHash; //DebugLog("addr: %08x | texID: %08x | texHash: %08x", address, texID, hash_value); } else