diff --git a/Core/Compatibility.cpp b/Core/Compatibility.cpp index 7493edf7d6..5f26b33db5 100644 --- a/Core/Compatibility.cpp +++ b/Core/Compatibility.cpp @@ -51,6 +51,7 @@ void Compatibility::CheckSettings(IniFile &iniFile, const std::string &gameID) { CheckSetting(iniFile, gameID, "ClearToRAM", &flags_.ClearToRAM); CheckSetting(iniFile, gameID, "Force04154000Download", &flags_.Force04154000Download); CheckSetting(iniFile, gameID, "DrawSyncEatCycles", &flags_.DrawSyncEatCycles); + CheckSetting(iniFile, gameID, "FakeMipmapChange", &flags_.FakeMipmapChange); } void Compatibility::CheckSetting(IniFile &iniFile, const std::string &gameID, const char *option, bool *flag) { diff --git a/Core/Compatibility.h b/Core/Compatibility.h index 991b824d73..449c01e3f3 100644 --- a/Core/Compatibility.h +++ b/Core/Compatibility.h @@ -51,6 +51,7 @@ struct CompatFlags { bool ClearToRAM; bool Force04154000Download; bool DrawSyncEatCycles; + bool FakeMipmapChange; }; class IniFile; diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index 56ea4f3fb1..bf56a55114 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -23,6 +23,7 @@ #include "Common/CommonTypes.h" #include "Common/MemoryUtil.h" #include "Core/TextureReplacer.h" +#include "Core/System.h" #include "GPU/Common/GPUDebugInterface.h" #include "GPU/Common/TextureDecoder.h" @@ -102,6 +103,10 @@ public: return cache.size(); } + bool IsFakeMipmapChange() { + return PSP_CoreParameter().compat.flags().FakeMipmapChange && gstate.getTexLevelMode() == GE_TEXLEVEL_MODE_CONST; + } + // Wow this is starting to grow big. Soon need to start looking at resizing it. // Must stay a POD. struct TexCacheEntry { diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index b7e7a44dd7..c7e7e438ea 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -605,7 +605,7 @@ void TextureCacheDX9::SetTexture(bool force) { } u8 level = 0; - if (gstate.getTexLevelMode() == GE_TEXLEVEL_MODE_CONST) + if (IsFakeMipmapChange()) level = (gstate.texlevel >> 20) & 0xF; u32 texaddr = gstate.getTextureAddress(level); if (!Memory::IsValidAddress(texaddr)) { @@ -1014,7 +1014,7 @@ void TextureCacheDX9::BuildTexture(TexCacheEntry *const entry, bool replaceImage maxLevel = 0; } - if (gstate.getTexLevelMode() == GE_TEXLEVEL_MODE_CONST) { + if (IsFakeMipmapChange()) { u8 level = (gstate.texlevel >> 20) & 0xF; LoadTextureLevel(*entry, replaced, level, maxLevel, replaceImages, scaleFactor, dstFmt); } else @@ -1102,7 +1102,7 @@ void TextureCacheDX9::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &re int h = gstate.getTextureHeight(level); LPDIRECT3DTEXTURE9 &texture = DxTex(&entry); - if ((level == 0 || gstate.getTexLevelMode() == GE_TEXLEVEL_MODE_CONST) && (!replaceImages || texture == nullptr)) { + if ((level == 0 || IsFakeMipmapChange()) && (!replaceImages || texture == nullptr)) { // Create texture D3DPOOL pool = D3DPOOL_MANAGED; int usage = 0; @@ -1123,7 +1123,7 @@ void TextureCacheDX9::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &re } } HRESULT hr; - if (gstate.getTexLevelMode() == GE_TEXLEVEL_MODE_CONST) + if (IsFakeMipmapChange()) hr = pD3Ddevice->CreateTexture(tw, th, 1, usage, tfmt, pool, &texture, NULL); else hr = pD3Ddevice->CreateTexture(tw, th, levels, usage, tfmt, pool, &texture, NULL); @@ -1135,7 +1135,7 @@ void TextureCacheDX9::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &re } D3DLOCKED_RECT rect; - if (gstate.getTexLevelMode() == GE_TEXLEVEL_MODE_CONST) + if (IsFakeMipmapChange()) texture->LockRect(0, &rect, NULL, 0); else texture->LockRect(level, &rect, NULL, 0); @@ -1205,7 +1205,7 @@ void TextureCacheDX9::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &re } } - if (gstate.getTexLevelMode() == GE_TEXLEVEL_MODE_CONST) + if (IsFakeMipmapChange()) texture->UnlockRect(0); else texture->UnlockRect(level); diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index c9a6122dd2..40a634c7f6 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -687,7 +687,7 @@ void TextureCacheGLES::SetTexture(bool force) { } u8 level = 0; - if (gstate.getTexLevelMode() == GE_TEXLEVEL_MODE_CONST) + if (IsFakeMipmapChange()) level = (gstate.texlevel >> 20) & 0xF; u32 texaddr = gstate.getTextureAddress(level); if (!Memory::IsValidAddress(texaddr)) { @@ -1058,7 +1058,7 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry, bool replaceImag // be as good quality as the game's own (might even be better in some cases though). // Always load base level texture here - if (gstate.getTexLevelMode() == GE_TEXLEVEL_MODE_CONST) { + if (IsFakeMipmapChange()) { u8 level = (gstate.texlevel >> 20) & 0xF; LoadTextureLevel(*entry, replaced, level, replaceImages, scaleFactor, dstFmt); } else @@ -1278,7 +1278,7 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, w, h, components2, dstFmt, pixelData); } else { PROFILE_THIS_SCOPE("loadtex"); - if (gstate.getTexLevelMode() == GE_TEXLEVEL_MODE_CONST) + if (IsFakeMipmapChange()) glTexImage2D(GL_TEXTURE_2D, 0, components, w, h, 0, components2, dstFmt, pixelData); else glTexImage2D(GL_TEXTURE_2D, level, components, w, h, 0, components2, dstFmt, pixelData); diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index aedad28a57..4eb9d162c0 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -624,7 +624,7 @@ void TextureCacheVulkan::SetTexture() { #endif u8 level = 0; - if (gstate.getTexLevelMode() == GE_TEXLEVEL_MODE_CONST) + if (IsFakeMipmapChange()) level = (gstate.texlevel >> 20) & 0xF; u32 texaddr = gstate.getTextureAddress(level); if (!Memory::IsValidAddress(texaddr)) { @@ -1086,7 +1086,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry, VulkanPushBuff if (entry->vkTex) { u8 level = (gstate.texlevel >> 20) & 0xF; - bool fakeMipmap = gstate.getTexLevelMode() == GE_TEXLEVEL_MODE_CONST && level > 0; + bool fakeMipmap = IsFakeMipmapChange() && level > 0; // Upload the texture data. for (int i = 0; i <= maxLevel; i++) { int mipWidth = gstate.getTextureWidth(i) * scaleFactor; diff --git a/assets/compat.ini b/assets/compat.ini index 7ea055b3d5..00adc21e42 100644 --- a/assets/compat.ini +++ b/assets/compat.ini @@ -152,4 +152,13 @@ ULJS00145 = true ULKS46183 = true ULJS00260 = true ULJS19041 = true -NPJH50843 = true \ No newline at end of file +NPJH50843 = true + +[FakeMipmapChange] +# This hacks separates each mipmap to independent textures to display wrong-size mipmaps. +# For example this requires games like Tactics Ogre(Japanese) to display multi bytes fonts stored in mipmaps. +# See issue #5350. +# Tactics Ogre(Japanese) +ULJM05753 = true +NPJH50348 = true +ULJM06009 = true