diff --git a/Source/Core/VideoCommon/TextureDecoder.h b/Source/Core/VideoCommon/TextureDecoder.h index 2a270eacd1..a1313afab1 100644 --- a/Source/Core/VideoCommon/TextureDecoder.h +++ b/Source/Core/VideoCommon/TextureDecoder.h @@ -116,6 +116,7 @@ void TexDecoder_DecodeTexel(u8* dst, const u8* src, int s, int t, int imageWidth TextureFormat texformat, const u8* tlut, TLUTFormat tlutfmt); void TexDecoder_DecodeTexelRGBA8FromTmem(u8* dst, const u8* src_ar, const u8* src_gb, int s, int t, int imageWidth); +void TexDecoder_DecodeXFB(u8* dst, const u8* src, u32 width, u32 height, u32 stride); void TexDecoder_SetTexFmtOverlayOptions(bool enable, bool center); diff --git a/Source/Core/VideoCommon/TextureDecoder_Common.cpp b/Source/Core/VideoCommon/TextureDecoder_Common.cpp index 2e84e3d282..5fbe34a098 100644 --- a/Source/Core/VideoCommon/TextureDecoder_Common.cpp +++ b/Source/Core/VideoCommon/TextureDecoder_Common.cpp @@ -751,3 +751,41 @@ void TexDecoder_DecodeRGBA8FromTmem(u8* dst, const u8* src_ar, const u8* src_gb, } } } + +void TexDecoder_DecodeXFB(u8* dst, const u8* src, u32 width, u32 height, u32 stride) +{ + const u8* src_ptr = src; + u8* dst_ptr = dst; + + for (u32 y = 0; y < height; y++) + { + const u8* row_ptr = src_ptr; + for (u32 x = 0; x < width; x += 2) + { + // We do this one color sample (aka 2 RGB pixels) at a time + int Y1 = int(*(row_ptr++)) - 16; + int U = int(*(row_ptr++)) - 128; + int Y2 = int(*(row_ptr++)) - 16; + int V = int(*(row_ptr++)) - 128; + + // We do the inverse BT.601 conversion for YCbCr to RGB + // http://www.equasys.de/colorconversion.html#YCbCr-RGBColorFormatConversion + u8 R1 = static_cast(MathUtil::Clamp(int(1.164f * Y1 + 1.596f * V), 0, 255)); + u8 G1 = static_cast(MathUtil::Clamp(int(1.164f * Y1 - 0.392f * U - 0.813f * V), 0, 255)); + u8 B1 = static_cast(MathUtil::Clamp(int(1.164f * Y1 + 2.017f * U), 0, 255)); + + u8 R2 = static_cast(MathUtil::Clamp(int(1.164f * Y2 + 1.596f * V), 0, 255)); + u8 G2 = static_cast(MathUtil::Clamp(int(1.164f * Y2 - 0.392f * U - 0.813f * V), 0, 255)); + u8 B2 = static_cast(MathUtil::Clamp(int(1.164f * Y2 + 2.017f * U), 0, 255)); + + u32 rgba = 0xff000000 | B1 << 16 | G1 << 8 | R1; + std::memcpy(dst_ptr, &rgba, sizeof(rgba)); + dst_ptr += sizeof(rgba); + rgba = 0xff000000 | B2 << 16 | G2 << 8 | R2; + std::memcpy(dst_ptr, &rgba, sizeof(rgba)); + dst_ptr += sizeof(rgba); + } + + src_ptr += stride; + } +} diff --git a/Source/Core/VideoCommon/TextureDecoder_Generic.cpp b/Source/Core/VideoCommon/TextureDecoder_Generic.cpp index ec74c21db4..4a2b516e7c 100644 --- a/Source/Core/VideoCommon/TextureDecoder_Generic.cpp +++ b/Source/Core/VideoCommon/TextureDecoder_Generic.cpp @@ -346,5 +346,8 @@ void _TexDecoder_DecodeImpl(u32* dst, const u8* src, int width, int height, Text } break; } + case TextureFormat::XFB: + TexDecoder_DecodeXFB(reinterpret_cast(dst), src, width, height, width * 2); + break; } } diff --git a/Source/Core/VideoCommon/TextureDecoder_x64.cpp b/Source/Core/VideoCommon/TextureDecoder_x64.cpp index 8a55bb5a53..7d41dbee53 100644 --- a/Source/Core/VideoCommon/TextureDecoder_x64.cpp +++ b/Source/Core/VideoCommon/TextureDecoder_x64.cpp @@ -1488,37 +1488,8 @@ void _TexDecoder_DecodeImpl(u32* dst, const u8* src, int width, int height, Text break; case TextureFormat::XFB: - { - for (int y = 0; y < height; y += 1) - { - for (int x = 0; x < width; x += 2) - { - size_t offset = static_cast((y * width + x) * 2); - - // We do this one color sample (aka 2 RGB pixles) at a time - int Y1 = int(src[offset]) - 16; - int U = int(src[offset + 1]) - 128; - int Y2 = int(src[offset + 2]) - 16; - int V = int(src[offset + 3]) - 128; - - // We do the inverse BT.601 conversion for YCbCr to RGB - // http://www.equasys.de/colorconversion.html#YCbCr-RGBColorFormatConversion - u8 R1 = static_cast(MathUtil::Clamp(int(1.164f * Y1 + 1.596f * V), 0, 255)); - u8 G1 = - static_cast(MathUtil::Clamp(int(1.164f * Y1 - 0.392f * U - 0.813f * V), 0, 255)); - u8 B1 = static_cast(MathUtil::Clamp(int(1.164f * Y1 + 2.017f * U), 0, 255)); - - u8 R2 = static_cast(MathUtil::Clamp(int(1.164f * Y2 + 1.596f * V), 0, 255)); - u8 G2 = - static_cast(MathUtil::Clamp(int(1.164f * Y2 - 0.392f * U - 0.813f * V), 0, 255)); - u8 B2 = static_cast(MathUtil::Clamp(int(1.164f * Y2 + 2.017f * U), 0, 255)); - - dst[y * width + x] = 0xff000000 | B1 << 16 | G1 << 8 | R1; - dst[y * width + x + 1] = 0xff000000 | B2 << 16 | G2 << 8 | R2; - } - } - } - break; + TexDecoder_DecodeXFB(reinterpret_cast(dst), src, width, height, width * 2); + break; default: PanicAlert("Invalid Texture Format (0x%X)! (_TexDecoder_DecodeImpl)",