diff --git a/plugins/GSdx/GSCrc.cpp b/plugins/GSdx/GSCrc.cpp index b4ab18d286..f737194879 100644 --- a/plugins/GSdx/GSCrc.cpp +++ b/plugins/GSdx/GSCrc.cpp @@ -534,6 +534,7 @@ bool IsCrcExcluded(string exclusionList, uint32 crc) CRC::Game CRC::Lookup(uint32 crc) { + printf("GSdx Lookup CRC:%X\n", crc); if(m_map.empty()) { string exclusions = theApp.GetConfig( "CrcHacksExclusions", "" ); @@ -549,7 +550,7 @@ CRC::Game CRC::Lookup(uint32 crc) , m_games[i].crc, m_games[i].title, m_games[i].region, m_map[m_games[i].crc]->title, m_map[m_games[i].crc]->region); crcDups++; } - + m_map[m_games[i].crc] = &m_games[i]; } //else diff --git a/plugins/GSdx/GSDeviceOGL.cpp b/plugins/GSdx/GSDeviceOGL.cpp index ca241aa74d..2a2d5bec25 100644 --- a/plugins/GSdx/GSDeviceOGL.cpp +++ b/plugins/GSdx/GSDeviceOGL.cpp @@ -767,7 +767,8 @@ GLuint GSDeviceOGL::CompilePS(PSSelector sel) + format("#define PS_DFMT %d\n", sel.dfmt) + format("#define PS_DEPTH_FMT %d\n", sel.depth_fmt) + format("#define PS_CHANNEL_FETCH %d\n", sel.channel) - + format("#define PS_URBAN_CHAOS_HACK %d\n", sel.urban_chaos_hack) + + format("#define PS_URBAN_CHAOS_HLE %d\n", sel.urban_chaos_hle) + + format("#define PS_TALES_OF_ABYSS_HLE %d\n", sel.tales_of_abyss_hle) + format("#define PS_AEM %d\n", sel.aem) + format("#define PS_TFX %d\n", sel.tfx) + format("#define PS_TCC %d\n", sel.tcc) diff --git a/plugins/GSdx/GSDeviceOGL.h b/plugins/GSdx/GSDeviceOGL.h index d56ff8a3ba..8b83075f2f 100644 --- a/plugins/GSdx/GSDeviceOGL.h +++ b/plugins/GSdx/GSDeviceOGL.h @@ -289,9 +289,10 @@ class GSDeviceOGL final : public GSDevice // Hack uint32 tcoffsethack:1; - uint32 urban_chaos_hack:1; + uint32 urban_chaos_hle:1; + uint32 tales_of_abyss_hle:1; - uint32 _free2:15; + uint32 _free2:14; }; uint64 key; diff --git a/plugins/GSdx/GSHwHack.cpp b/plugins/GSdx/GSHwHack.cpp index 42870564e9..04c5129ce8 100644 --- a/plugins/GSdx/GSHwHack.cpp +++ b/plugins/GSdx/GSHwHack.cpp @@ -295,31 +295,6 @@ bool GSC_AceCombat4(const GSFrameInfo& fi, int& skip) return true; } -bool GSC_Tekken5(const GSFrameInfo& fi, int& skip) -{ - if(skip == 0) - { - if(fi.TME && (fi.FBP == 0x02d60 || fi.FBP == 0x02d80 || fi.FBP == 0x02ea0 || fi.FBP == 0x03620) && fi.FPSM == fi.TPSM && fi.TBP0 == 0x00000 && fi.TPSM == PSM_PSMCT32) - { - skip = 95; - } - else if(fi.TME && (fi.FBP == 0x02bc0 || fi.FBP == 0x02be0 || fi.FBP == 0x02d00) && fi.FPSM == fi.TPSM && fi.TBP0 == 0x00000 && fi.TPSM == PSM_PSMCT32) - { - skip = 2; - } - else if(fi.TME) - { - if( (fi.TPSM == PSM_PSMZ32 || fi.TPSM == PSM_PSMZ24 || fi.TPSM == PSM_PSMZ16 || fi.TPSM == PSM_PSMZ16S) || - (GSUtil::HasSharedBits(fi.FBP, fi.FPSM, fi.TBP0, fi.TPSM)) ) - { - skip = 24; - } - } - } - - return true; -} - bool GSC_IkkiTousen(const GSFrameInfo& fi, int& skip) { if(skip == 0) @@ -354,30 +329,6 @@ bool GSC_Onimusha3(const GSFrameInfo& fi, int& skip) return true; } -bool GSC_TalesOfAbyss(const GSFrameInfo& fi, int& skip) -{ - if(skip == 0) - { - if(fi.TME && (fi.FBP == 0x00000 || fi.FBP == 0x00e00) && fi.TBP0 == 0x01c00 && fi.TPSM == PSM_PSMT8) // copies the z buffer to the alpha channel of the fb - { - skip = 1000; - } - else if(fi.TME && (fi.FBP == 0x00000 || fi.FBP == 0x00e00) && (fi.TBP0 == 0x03560 || fi.TBP0 == 0x038e0) && fi.TPSM == PSM_PSMCT32) - { - skip = 1; - } - } - else - { - if(fi.TME && fi.TPSM != PSM_PSMT8) - { - skip = 0; - } - } - - return true; -} - bool GSC_Genji(const GSFrameInfo& fi, int& skip) { if( !skip && fi.TME && (fi.FBP == 0x700 || fi.FBP == 0x0) && fi.TBP0 == 0x1500 && fi.TPSM ) @@ -1358,6 +1309,56 @@ bool GSC_SteambotChronicles(const GSFrameInfo& fi, int& skip) //////////////////////////////////////////////////////////////////////////////// // Correctly emulated on OpenGL but can be used as potential speed hack //////////////////////////////////////////////////////////////////////////////// + +bool GSC_TalesOfAbyss(const GSFrameInfo& fi, int& skip) +{ + if(skip == 0) + { + if(fi.TME && (fi.FBP == 0x00000 || fi.FBP == 0x00e00) && fi.TBP0 == 0x01c00 && fi.TPSM == PSM_PSMT8) // copies the z buffer to the alpha channel of the fb + { + skip = 1000; + } + else if(fi.TME && (fi.FBP == 0x00000 || fi.FBP == 0x00e00) && (fi.TBP0 == 0x03560 || fi.TBP0 == 0x038e0) && fi.TPSM == PSM_PSMCT32) + { + skip = 1; + } + } + else + { + if(fi.TME && fi.TPSM != PSM_PSMT8) + { + skip = 0; + } + } + + return true; +} + +bool GSC_Tekken5(const GSFrameInfo& fi, int& skip) +{ + if(skip == 0) + { + if(fi.TME && (fi.FBP == 0x02d60 || fi.FBP == 0x02d80 || fi.FBP == 0x02ea0 || fi.FBP == 0x03620) && fi.FPSM == fi.TPSM && fi.TBP0 == 0x00000 && fi.TPSM == PSM_PSMCT32) + { + skip = 95; + } + else if(fi.TME && (fi.FBP == 0x02bc0 || fi.FBP == 0x02be0 || fi.FBP == 0x02d00) && fi.FPSM == fi.TPSM && fi.TBP0 == 0x00000 && fi.TPSM == PSM_PSMCT32) + { + skip = 2; + } + else if(fi.TME) + { + if( (fi.TPSM == PSM_PSMZ32 || fi.TPSM == PSM_PSMZ24 || fi.TPSM == PSM_PSMZ16 || fi.TPSM == PSM_PSMZ16S) || + (GSUtil::HasSharedBits(fi.FBP, fi.FPSM, fi.TBP0, fi.TPSM)) ) + { + skip = 24; + } + } + } + + return true; +} + bool GSC_DeathByDegreesTekkenNinaWilliams(const GSFrameInfo& fi, int& skip) { if(skip == 0) @@ -2491,10 +2492,8 @@ void GSState::SetupCrcHack() lut[CRC::Spartan] = GSC_Spartan; lut[CRC::StarWarsForceUnleashed] = GSC_StarWarsForceUnleashed; lut[CRC::SteambotChronicles] = GSC_SteambotChronicles; - lut[CRC::TalesOfAbyss] = GSC_TalesOfAbyss; lut[CRC::TalesOfLegendia] = GSC_TalesOfLegendia; lut[CRC::TalesofSymphonia] = GSC_TalesofSymphonia; - lut[CRC::Tekken5] = GSC_Tekken5; lut[CRC::TimeSplitters2] = GSC_TimeSplitters2; lut[CRC::TombRaiderAnniversary] = GSC_TombRaider; lut[CRC::TombRaiderLegend] = GSC_TombRaiderLegend; @@ -2567,15 +2566,18 @@ void GSState::SetupCrcHack() // Channel Effect lut[CRC::DeathByDegreesTekkenNinaWilliams] = GSC_DeathByDegreesTekkenNinaWilliams; - lut[CRC::GT3] = GSC_GT3; - lut[CRC::GT4] = GSC_GT4; - lut[CRC::GTConcept] = GSC_GTConcept; lut[CRC::JamesBondEverythingOrNothing] = GSC_JamesBondEverythingOrNothing; lut[CRC::MetalGearSolid3] = GSC_MetalGearSolid3; // + accurate blending lut[CRC::SkyGunner] = GSC_SkyGunner; lut[CRC::StarWarsBattlefront2] = GSC_StarWarsBattlefront2; lut[CRC::StarWarsBattlefront] = GSC_StarWarsBattlefront; + // Dedicated shader for channel effect lut[CRC::TouristTrophy] = GSC_TouristTrophy; + lut[CRC::GT3] = GSC_GT3; + lut[CRC::GT4] = GSC_GT4; + lut[CRC::GTConcept] = GSC_GTConcept; + lut[CRC::TalesOfAbyss] = GSC_TalesOfAbyss; + lut[CRC::Tekken5] = GSC_Tekken5; } m_gsc = lut[m_game.title]; diff --git a/plugins/GSdx/GSRendererOGL.cpp b/plugins/GSdx/GSRendererOGL.cpp index e0f55d2200..57f837582d 100644 --- a/plugins/GSdx/GSRendererOGL.cpp +++ b/plugins/GSdx/GSRendererOGL.cpp @@ -673,7 +673,41 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour // // First let's check we really have a channel shuffle effect if (m_channel_shuffle) { - if (m_context->CLAMP.WMS == 3 && ((m_context->CLAMP.MAXU & 0x8) == 8)) { + if (m_game.title == CRC::GT4 || m_game.title == CRC::GT3 || m_game.title == CRC::GTConcept || m_game.title == CRC::TouristTrophy) { + GL_INS("Gran Turismo RGB Channel"); + ps_sel.channel = 7; + m_context->TEX0.TFX = TFX_DECAL; + rt = tex->m_from_target; + } else if (m_game.title == CRC::Tekken5) { + GL_INS("Tekken5 RGB Channel"); + ps_sel.channel = 7; + m_context->FRAME.FBMSK = 0xFF000000; + // 12 pages: 2 calls by channel, 3 channels, 1 blit + // Minus current draw call + m_skip = 12 * (3 + 3 + 1) - 1; + rt = tex->m_from_target; + } else if ((tex->m_texture->GetType() == GSTexture::DepthStencil) && !(tex->m_32_bits_fmt)) { + // So far 2 games hit this code path. Urban Chaos and Tales of Abyss + // UC: will copy depth to green channel + // ToA: will copy depth to alpha channel + if ((m_context->FRAME.FBMSK & 0xFF0000) == 0xFF0000) { + // Green channel is masked + GL_INS("Tales Of Abyss Crazyness (MSB 16b depth to Alpha)"); + ps_sel.tales_of_abyss_hle = 1; + } else { + GL_INS("Urban Chaos Crazyness (Green extraction)"); + ps_sel.urban_chaos_hle = 1; + } + } else if (m_index.tail <= 64 && m_context->CLAMP.WMT == 3) { + // Blood will tell. I think it is channel effect too but again + // implemented in a different way. I don't want to add more CRC stuff. So + // let's disable channel when the signature is different + // + // Note: Tales Of Abyss and Tekken5 could hit this path too. Those games are + // handled above. + GL_INS("maybe not a channel!"); + m_channel_shuffle = false; + } else if (m_context->CLAMP.WMS == 3 && ((m_context->CLAMP.MAXU & 0x8) == 8)) { // Read either blue or Alpha. Let's go for Blue ;) // MGS3/Kill Zone GL_INS("Blue channel"); @@ -683,9 +717,6 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour // Pop GL_INS("Red channel"); ps_sel.channel = 1; - } else if ((tex->m_texture->GetType() == GSTexture::DepthStencil) && !(tex->m_32_bits_fmt)) { - GL_INS("Urban Chaos Crazyness"); - ps_sel.urban_chaos_hack = 1; } else { GL_INS("channel not supported"); m_channel_shuffle = false; diff --git a/plugins/GSdx/res/glsl/tfx_fs.glsl b/plugins/GSdx/res/glsl/tfx_fs.glsl index c6bb84933c..22e4fdb71e 100644 --- a/plugins/GSdx/res/glsl/tfx_fs.glsl +++ b/plugins/GSdx/res/glsl/tfx_fs.glsl @@ -235,7 +235,14 @@ vec4 sample_depth(vec2 st) ivec2 uv = ivec2(uv_f); vec4 t; -#if PS_URBAN_CHAOS_HACK == 1 +#if PS_TALES_OF_ABYSS_HLE == 1 + // Warning: UV can't be used in channel effect + int depth = fetch_raw_depth(); + + // Convert msb based on the palette + t = texelFetch(PaletteSampler, ivec2((depth >> 8) & 0xFF, 0), 0) * 255.0f; + +#elif PS_URBAN_CHAOS_HLE == 1 // Depth buffer is read as a RGB5A1 texture. The game try to extract the green channel. // So it will do a first channel trick to extract lsb, value is right-shifted. // Then a new channel trick to extract msb which will shifted to the left. @@ -246,7 +253,7 @@ vec4 sample_depth(vec2 st) int depth = fetch_raw_depth(); // Convert lsb based on the palette - t = texelFetch(PaletteSampler, ivec2((depth & 0xFF), 0), 0); + t = texelFetch(PaletteSampler, ivec2((depth & 0xFF), 0), 0) * 255.0f; // Msb is easier float green = float((depth >> 8) & 0xFF) * 36.0f; @@ -331,6 +338,13 @@ vec4 fetch_alpha() return sample_p(rt.a) * 255.0f; } +vec4 fetch_rgb() +{ + vec4 rt = fetch_raw_color(); + vec4 c = vec4(sample_p(rt.r).r, sample_p(rt.g).g, sample_p(rt.b).b, 1.0f); + return c * 255.0f; +} + ////////////////////////////////////////////////////////////////////// vec4 sample_color(vec2 st) @@ -500,6 +514,8 @@ vec4 ps_color() vec4 T = fetch_blue(); #elif PS_CHANNEL_FETCH == 4 vec4 T = fetch_alpha(); +#elif PS_CHANNEL_FETCH == 7 + vec4 T = fetch_rgb(); #elif PS_DEPTH_FMT > 0 // Integral coordinate vec4 T = sample_depth(PSin.t_int.zw); diff --git a/plugins/GSdx/res/glsl_source.h b/plugins/GSdx/res/glsl_source.h index 9466f6f2a1..7225be1046 100644 --- a/plugins/GSdx/res/glsl_source.h +++ b/plugins/GSdx/res/glsl_source.h @@ -1079,7 +1079,14 @@ static const char* const tfx_fs_all_glsl = " ivec2 uv = ivec2(uv_f);\n" "\n" " vec4 t;\n" - "#if PS_URBAN_CHAOS_HACK == 1\n" + "#if PS_TALES_OF_ABYSS_HLE == 1\n" + " // Warning: UV can't be used in channel effect\n" + " int depth = fetch_raw_depth();\n" + "\n" + " // Convert msb based on the palette\n" + " t = texelFetch(PaletteSampler, ivec2((depth >> 8) & 0xFF, 0), 0) * 255.0f;\n" + "\n" + "#elif PS_URBAN_CHAOS_HLE == 1\n" " // Depth buffer is read as a RGB5A1 texture. The game try to extract the green channel.\n" " // So it will do a first channel trick to extract lsb, value is right-shifted.\n" " // Then a new channel trick to extract msb which will shifted to the left.\n" @@ -1090,7 +1097,7 @@ static const char* const tfx_fs_all_glsl = " int depth = fetch_raw_depth();\n" "\n" " // Convert lsb based on the palette\n" - " t = texelFetch(PaletteSampler, ivec2((depth & 0xFF), 0), 0);\n" + " t = texelFetch(PaletteSampler, ivec2((depth & 0xFF), 0), 0) * 255.0f;\n" "\n" " // Msb is easier\n" " float green = float((depth >> 8) & 0xFF) * 36.0f;\n" @@ -1175,6 +1182,13 @@ static const char* const tfx_fs_all_glsl = " return sample_p(rt.a) * 255.0f;\n" "}\n" "\n" + "vec4 fetch_rgb()\n" + "{\n" + " vec4 rt = fetch_raw_color();\n" + " vec4 c = vec4(sample_p(rt.r).r, sample_p(rt.g).g, sample_p(rt.b).b, 1.0f);\n" + " return c * 255.0f;\n" + "}\n" + "\n" "//////////////////////////////////////////////////////////////////////\n" "\n" "vec4 sample_color(vec2 st)\n" @@ -1344,6 +1358,8 @@ static const char* const tfx_fs_all_glsl = " vec4 T = fetch_blue();\n" "#elif PS_CHANNEL_FETCH == 4\n" " vec4 T = fetch_alpha();\n" + "#elif PS_CHANNEL_FETCH == 7\n" + " vec4 T = fetch_rgb();\n" "#elif PS_DEPTH_FMT > 0\n" " // Integral coordinate\n" " vec4 T = sample_depth(PSin.t_int.zw);\n"