From 06901ef22a33b0b5444300251730b994ffc2e02d Mon Sep 17 00:00:00 2001 From: PixelyIon Date: Thu, 2 Jun 2022 19:48:55 +0530 Subject: [PATCH] Fix BC7 output swizzling from BGRA to RGBA BC7 CPU decoding had the red and blue channels swapped around as it outputted a BGRA image after decoding while we expected an RGBA image to be produced. This should fix the colors of certain textures in titles such as Cuphead or Sonic Forces. --- .../cpp/skyline/gpu/texture/bc_decoder.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/app/src/main/cpp/skyline/gpu/texture/bc_decoder.cpp b/app/src/main/cpp/skyline/gpu/texture/bc_decoder.cpp index 5dc9e887..f43d00f9 100644 --- a/app/src/main/cpp/skyline/gpu/texture/bc_decoder.cpp +++ b/app/src/main/cpp/skyline/gpu/texture/bc_decoder.cpp @@ -42,9 +42,9 @@ namespace { } for (int j = 0; j < BlockHeight && (y + j) < dstH; j++) { - int dstOffset = j * dstPitch; - int idxOffset = j * BlockHeight; - for (int i = 0; i < BlockWidth && (x + i) < dstW; i++, idxOffset++, dstOffset += dstBpp) { + size_t dstOffset = j * dstPitch; + size_t idxOffset = j * BlockHeight; + for (size_t i = 0; i < BlockWidth && (x + i) < dstW; i++, idxOffset++, dstOffset += dstBpp) { *reinterpret_cast(dst + dstOffset) = c[getIdx(idxOffset)].pack8888(); } } @@ -107,8 +107,8 @@ namespace { int c[4]; }; - unsigned int getIdx(int i) const { - int offset = i << 1; // 2 bytes per index + size_t getIdx(int i) const { + size_t offset = i << 1; // 2 bytes per index return (idx & (0x3 << offset)) >> offset; } @@ -1392,22 +1392,23 @@ namespace { } Color output; - output.rgb.r = interpolate(subset[0].rgb.r, subset[1].rgb.r, colorIdx); + // Note: We flip r and b channels past this point as the texture storage is BGR while the output is RGB + output.rgb.r = interpolate(subset[0].rgb.b, subset[1].rgb.b, colorIdx); output.rgb.g = interpolate(subset[0].rgb.g, subset[1].rgb.g, colorIdx); - output.rgb.b = interpolate(subset[0].rgb.b, subset[1].rgb.b, colorIdx); + output.rgb.b = interpolate(subset[0].rgb.r, subset[1].rgb.r, colorIdx); output.a = interpolate(subset[0].a, subset[1].a, alphaIdx); switch (Get(mode.Rotation())) { default: break; case 1: - std::swap(output.a, output.rgb.r); + std::swap(output.a, output.rgb.b); break; case 2: std::swap(output.a, output.rgb.g); break; case 3: - std::swap(output.a, output.rgb.b); + std::swap(output.a, output.rgb.r); break; }