summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon/TextureDecoder_Generic.cpp
diff options
context:
space:
mode:
authorPierre Bourdon <delroth@gmail.com>2016-06-24 10:43:46 +0200
committerPierre Bourdon <delroth@gmail.com>2016-06-24 10:43:46 +0200
commit3570c7f03a2aa90aa634f96c0af1969af610f14d (patch)
tree4252e03c0e853ba7cffe022937698c854ad0eaa9 /Source/Core/VideoCommon/TextureDecoder_Generic.cpp
parent2115e8a4a6814e32107b5205ff5c95bbd3c6e99c (diff)
Reformat all the things. Have fun with merge conflicts.
Diffstat (limited to 'Source/Core/VideoCommon/TextureDecoder_Generic.cpp')
-rw-r--r--Source/Core/VideoCommon/TextureDecoder_Generic.cpp536
1 files changed, 274 insertions, 262 deletions
diff --git a/Source/Core/VideoCommon/TextureDecoder_Generic.cpp b/Source/Core/VideoCommon/TextureDecoder_Generic.cpp
index d5d9280b87..fe0f53c845 100644
--- a/Source/Core/VideoCommon/TextureDecoder_Generic.cpp
+++ b/Source/Core/VideoCommon/TextureDecoder_Generic.cpp
@@ -5,9 +5,9 @@
#include <algorithm>
#include <cmath>
+#include "Common/CPUDetect.h"
#include "Common/CommonFuncs.h"
#include "Common/CommonTypes.h"
-#include "Common/CPUDetect.h"
#include "VideoCommon/LookUpTables.h"
#include "VideoCommon/TextureDecoder.h"
//#include "VideoCommon/VideoCommon.h" // to get debug logs
@@ -20,112 +20,112 @@
static inline u32 DecodePixel_IA8(u16 val)
{
- int a = val & 0xFF;
- int i = val >> 8;
- return i | (i<<8) | (i<<16) | (a<<24);
+ int a = val & 0xFF;
+ int i = val >> 8;
+ return i | (i << 8) | (i << 16) | (a << 24);
}
static inline u32 DecodePixel_RGB565(u16 val)
{
- int r,g,b,a;
- r=Convert5To8((val>>11) & 0x1f);
- g=Convert6To8((val>>5 ) & 0x3f);
- b=Convert5To8((val ) & 0x1f);
- a=0xFF;
- return r | (g<<8) | (b << 16) | (a << 24);
+ int r, g, b, a;
+ r = Convert5To8((val >> 11) & 0x1f);
+ g = Convert6To8((val >> 5) & 0x3f);
+ b = Convert5To8((val)&0x1f);
+ a = 0xFF;
+ return r | (g << 8) | (b << 16) | (a << 24);
}
static inline u32 DecodePixel_RGB5A3(u16 val)
{
- int r,g,b,a;
- if ((val&0x8000))
- {
- r=Convert5To8((val>>10) & 0x1f);
- g=Convert5To8((val>>5 ) & 0x1f);
- b=Convert5To8((val ) & 0x1f);
- a=0xFF;
- }
- else
- {
- a=Convert3To8((val>>12) & 0x7);
- r=Convert4To8((val>>8 ) & 0xf);
- g=Convert4To8((val>>4 ) & 0xf);
- b=Convert4To8((val ) & 0xf);
- }
- return r | (g<<8) | (b << 16) | (a << 24);
+ int r, g, b, a;
+ if ((val & 0x8000))
+ {
+ r = Convert5To8((val >> 10) & 0x1f);
+ g = Convert5To8((val >> 5) & 0x1f);
+ b = Convert5To8((val)&0x1f);
+ a = 0xFF;
+ }
+ else
+ {
+ a = Convert3To8((val >> 12) & 0x7);
+ r = Convert4To8((val >> 8) & 0xf);
+ g = Convert4To8((val >> 4) & 0xf);
+ b = Convert4To8((val)&0xf);
+ }
+ return r | (g << 8) | (b << 16) | (a << 24);
}
static inline u32 DecodePixel_Paletted(u16 pixel, TlutFormat tlutfmt)
{
- switch (tlutfmt)
- {
- case GX_TL_IA8:
- return DecodePixel_IA8(pixel);
- case GX_TL_RGB565:
- return DecodePixel_RGB565(Common::swap16(pixel));
- case GX_TL_RGB5A3:
- return DecodePixel_RGB5A3(Common::swap16(pixel));
- default:
- return 0;
- }
+ switch (tlutfmt)
+ {
+ case GX_TL_IA8:
+ return DecodePixel_IA8(pixel);
+ case GX_TL_RGB565:
+ return DecodePixel_RGB565(Common::swap16(pixel));
+ case GX_TL_RGB5A3:
+ return DecodePixel_RGB5A3(Common::swap16(pixel));
+ default:
+ return 0;
+ }
}
-static inline void DecodeBytes_C4(u32 *dst, const u8 *src, const u8* tlut_, TlutFormat tlutfmt)
+static inline void DecodeBytes_C4(u32* dst, const u8* src, const u8* tlut_, TlutFormat tlutfmt)
{
- const u16* tlut = (u16*) tlut_;
- for (int x = 0; x < 4; x++)
- {
- u8 val = src[x];
- *dst++ = DecodePixel_Paletted(tlut[val >> 4], tlutfmt);
- *dst++ = DecodePixel_Paletted(tlut[val & 0xF], tlutfmt);
- }
+ const u16* tlut = (u16*)tlut_;
+ for (int x = 0; x < 4; x++)
+ {
+ u8 val = src[x];
+ *dst++ = DecodePixel_Paletted(tlut[val >> 4], tlutfmt);
+ *dst++ = DecodePixel_Paletted(tlut[val & 0xF], tlutfmt);
+ }
}
-static inline void DecodeBytes_C8(u32 *dst, const u8 *src, const u8* tlut_, TlutFormat tlutfmt)
+static inline void DecodeBytes_C8(u32* dst, const u8* src, const u8* tlut_, TlutFormat tlutfmt)
{
- const u16* tlut = (u16*) tlut_;
- for (int x = 0; x < 8; x++)
- {
- u8 val = src[x];
- *dst++ = DecodePixel_Paletted(tlut[val], tlutfmt);
- }
+ const u16* tlut = (u16*)tlut_;
+ for (int x = 0; x < 8; x++)
+ {
+ u8 val = src[x];
+ *dst++ = DecodePixel_Paletted(tlut[val], tlutfmt);
+ }
}
-static inline void DecodeBytes_C14X2(u32 *dst, const u16 *src, const u8* tlut_, TlutFormat tlutfmt)
+static inline void DecodeBytes_C14X2(u32* dst, const u16* src, const u8* tlut_, TlutFormat tlutfmt)
{
- const u16* tlut = (u16*) tlut_;
- for (int x = 0; x < 4; x++)
- {
- u16 val = Common::swap16(src[x]);
- *dst++ = DecodePixel_Paletted(tlut[(val & 0x3FFF)], tlutfmt);
- }
+ const u16* tlut = (u16*)tlut_;
+ for (int x = 0; x < 4; x++)
+ {
+ u16 val = Common::swap16(src[x]);
+ *dst++ = DecodePixel_Paletted(tlut[(val & 0x3FFF)], tlutfmt);
+ }
}
-static inline void DecodeBytes_IA4(u32 *dst, const u8 *src)
+static inline void DecodeBytes_IA4(u32* dst, const u8* src)
{
- for (int x = 0; x < 8; x++)
- {
- const u8 val = src[x];
- u8 a = Convert4To8(val >> 4);
- u8 l = Convert4To8(val & 0xF);
- dst[x] = (a << 24) | l << 16 | l << 8 | l;
- }
+ for (int x = 0; x < 8; x++)
+ {
+ const u8 val = src[x];
+ u8 a = Convert4To8(val >> 4);
+ u8 l = Convert4To8(val & 0xF);
+ dst[x] = (a << 24) | l << 16 | l << 8 | l;
+ }
}
-static inline void DecodeBytes_RGB5A3(u32 *dst, const u16 *src)
+static inline void DecodeBytes_RGB5A3(u32* dst, const u16* src)
{
#if 0
for (int x = 0; x < 4; x++)
dst[x] = DecodePixel_RGB5A3(Common::swap16(src[x]));
#else
- dst[0] = DecodePixel_RGB5A3(Common::swap16(src[0]));
- dst[1] = DecodePixel_RGB5A3(Common::swap16(src[1]));
- dst[2] = DecodePixel_RGB5A3(Common::swap16(src[2]));
- dst[3] = DecodePixel_RGB5A3(Common::swap16(src[3]));
+ dst[0] = DecodePixel_RGB5A3(Common::swap16(src[0]));
+ dst[1] = DecodePixel_RGB5A3(Common::swap16(src[1]));
+ dst[2] = DecodePixel_RGB5A3(Common::swap16(src[2]));
+ dst[3] = DecodePixel_RGB5A3(Common::swap16(src[3]));
#endif
}
-static inline void DecodeBytes_RGBA8(u32 *dst, const u16 *src, const u16 * src2)
+static inline void DecodeBytes_RGBA8(u32* dst, const u16* src, const u16* src2)
{
#if 0
for (int x = 0; x < 4; x++)
@@ -133,216 +133,228 @@ static inline void DecodeBytes_RGBA8(u32 *dst, const u16 *src, const u16 * src2)
dst[x] = ((src[x] & 0xFF) << 24) | ((src[x] & 0xFF00)>>8) | (src2[x] << 8);
}
#else
- dst[0] = ((src[0] & 0xFF) << 24) | ((src[0] & 0xFF00)>>8) | (src2[0] << 8);
- dst[1] = ((src[1] & 0xFF) << 24) | ((src[1] & 0xFF00)>>8) | (src2[1] << 8);
- dst[2] = ((src[2] & 0xFF) << 24) | ((src[2] & 0xFF00)>>8) | (src2[2] << 8);
- dst[3] = ((src[3] & 0xFF) << 24) | ((src[3] & 0xFF00)>>8) | (src2[3] << 8);
+ dst[0] = ((src[0] & 0xFF) << 24) | ((src[0] & 0xFF00) >> 8) | (src2[0] << 8);
+ dst[1] = ((src[1] & 0xFF) << 24) | ((src[1] & 0xFF00) >> 8) | (src2[1] << 8);
+ dst[2] = ((src[2] & 0xFF) << 24) | ((src[2] & 0xFF00) >> 8) | (src2[2] << 8);
+ dst[3] = ((src[3] & 0xFF) << 24) | ((src[3] & 0xFF00) >> 8) | (src2[3] << 8);
#endif
}
struct DXTBlock
{
- u16 color1;
- u16 color2;
- u8 lines[4];
+ u16 color1;
+ u16 color2;
+ u8 lines[4];
};
static inline u32 MakeRGBA(int r, int g, int b, int a)
{
- return (a<<24)|(b<<16)|(g<<8)|r;
+ return (a << 24) | (b << 16) | (g << 8) | r;
}
-static void DecodeDXTBlock(u32 *dst, const DXTBlock *src, int pitch)
+static void DecodeDXTBlock(u32* dst, const DXTBlock* src, int pitch)
{
- // S3TC Decoder (Note: GCN decodes differently from PC so we can't use native support)
- // Needs more speed.
- u16 c1 = Common::swap16(src->color1);
- u16 c2 = Common::swap16(src->color2);
- int blue1 = Convert5To8(c1 & 0x1F);
- int blue2 = Convert5To8(c2 & 0x1F);
- int green1 = Convert6To8((c1 >> 5) & 0x3F);
- int green2 = Convert6To8((c2 >> 5) & 0x3F);
- int red1 = Convert5To8((c1 >> 11) & 0x1F);
- int red2 = Convert5To8((c2 >> 11) & 0x1F);
- int colors[4];
- colors[0] = MakeRGBA(red1, green1, blue1, 255);
- colors[1] = MakeRGBA(red2, green2, blue2, 255);
- if (c1 > c2)
- {
- int blue3 = ((blue2 - blue1) >> 1) - ((blue2 - blue1) >> 3);
- int green3 = ((green2 - green1) >> 1) - ((green2 - green1) >> 3);
- int red3 = ((red2 - red1) >> 1) - ((red2 - red1) >> 3);
- colors[2] = MakeRGBA(red1 + red3, green1 + green3, blue1 + blue3, 255);
- colors[3] = MakeRGBA(red2 - red3, green2 - green3, blue2 - blue3, 255);
- }
- else
- {
- colors[2] = MakeRGBA((red1 + red2 + 1) / 2, // Average
- (green1 + green2 + 1) / 2,
- (blue1 + blue2 + 1) / 2, 255);
- colors[3] = MakeRGBA(red2, green2, blue2, 0); // Color2 but transparent
- }
+ // S3TC Decoder (Note: GCN decodes differently from PC so we can't use native support)
+ // Needs more speed.
+ u16 c1 = Common::swap16(src->color1);
+ u16 c2 = Common::swap16(src->color2);
+ int blue1 = Convert5To8(c1 & 0x1F);
+ int blue2 = Convert5To8(c2 & 0x1F);
+ int green1 = Convert6To8((c1 >> 5) & 0x3F);
+ int green2 = Convert6To8((c2 >> 5) & 0x3F);
+ int red1 = Convert5To8((c1 >> 11) & 0x1F);
+ int red2 = Convert5To8((c2 >> 11) & 0x1F);
+ int colors[4];
+ colors[0] = MakeRGBA(red1, green1, blue1, 255);
+ colors[1] = MakeRGBA(red2, green2, blue2, 255);
+ if (c1 > c2)
+ {
+ int blue3 = ((blue2 - blue1) >> 1) - ((blue2 - blue1) >> 3);
+ int green3 = ((green2 - green1) >> 1) - ((green2 - green1) >> 3);
+ int red3 = ((red2 - red1) >> 1) - ((red2 - red1) >> 3);
+ colors[2] = MakeRGBA(red1 + red3, green1 + green3, blue1 + blue3, 255);
+ colors[3] = MakeRGBA(red2 - red3, green2 - green3, blue2 - blue3, 255);
+ }
+ else
+ {
+ colors[2] = MakeRGBA((red1 + red2 + 1) / 2, // Average
+ (green1 + green2 + 1) / 2, (blue1 + blue2 + 1) / 2, 255);
+ colors[3] = MakeRGBA(red2, green2, blue2, 0); // Color2 but transparent
+ }
- for (int y = 0; y < 4; y++)
- {
- int val = src->lines[y];
- for (int x = 0; x < 4; x++)
- {
- dst[x] = colors[(val >> 6) & 3];
- val <<= 2;
- }
- dst += pitch;
- }
+ for (int y = 0; y < 4; y++)
+ {
+ int val = src->lines[y];
+ for (int x = 0; x < 4; x++)
+ {
+ dst[x] = colors[(val >> 6) & 3];
+ val <<= 2;
+ }
+ dst += pitch;
+ }
}
// JSD 01/06/11:
-// TODO: we really should ensure BOTH the source and destination addresses are aligned to 16-byte boundaries to
-// squeeze out a little more performance. _mm_loadu_si128/_mm_storeu_si128 is slower than _mm_load_si128/_mm_store_si128
-// because they work on unaligned addresses. The processor is free to make the assumption that addresses are multiples
+// TODO: we really should ensure BOTH the source and destination addresses are aligned to 16-byte
+// boundaries to
+// squeeze out a little more performance. _mm_loadu_si128/_mm_storeu_si128 is slower than
+// _mm_load_si128/_mm_store_si128
+// because they work on unaligned addresses. The processor is free to make the assumption that
+// addresses are multiples
// of 16 in the aligned case.
// TODO: complete SSE2 optimization of less often used texture formats.
// TODO: refactor algorithms using _mm_loadl_epi64 unaligned loads to prefer 128-bit aligned loads.
-void _TexDecoder_DecodeImpl(u32 * dst, const u8 * src, int width, int height, int texformat, const u8* tlut, TlutFormat tlutfmt)
+void _TexDecoder_DecodeImpl(u32* dst, const u8* src, int width, int height, int texformat,
+ const u8* tlut, TlutFormat tlutfmt)
{
- const int Wsteps4 = (width + 3) / 4;
- const int Wsteps8 = (width + 7) / 8;
+ const int Wsteps4 = (width + 3) / 4;
+ const int Wsteps8 = (width + 7) / 8;
- switch (texformat)
- {
- case GX_TF_C4:
- for (int y = 0; y < height; y += 8)
- for (int x = 0, yStep = (y / 8) * Wsteps8; x < width; x += 8,yStep++)
- for (int iy = 0, xStep = 8 * yStep; iy < 8; iy++,xStep++)
- DecodeBytes_C4(dst + (y + iy) * width + x, src + 4 * xStep, tlut, tlutfmt);
- break;
- case GX_TF_I4:
- {
- // Reference C implementation:
- for (int y = 0; y < height; y += 8)
- for (int x = 0; x < width; x += 8)
- for (int iy = 0; iy < 8; iy++, src += 4)
- for (int ix = 0; ix < 4; ix++)
- {
- int val = src[ix];
- u8 i1 = Convert4To8(val >> 4);
- u8 i2 = Convert4To8(val & 0xF);
- memset(dst+(y + iy) * width + x + ix * 2 , i1,4);
- memset(dst+(y + iy) * width + x + ix * 2 + 1 , i2,4);
- }
- }
- break;
- case GX_TF_I8: // speed critical
- {
- // Reference C implementation
- for (int y = 0; y < height; y += 4)
- for (int x = 0; x < width; x += 8)
- for (int iy = 0; iy < 4; ++iy, src += 8)
- {
- u32 * newdst = dst + (y + iy)*width+x;
- const u8 * newsrc = src;
- u8 srcval;
+ switch (texformat)
+ {
+ case GX_TF_C4:
+ for (int y = 0; y < height; y += 8)
+ for (int x = 0, yStep = (y / 8) * Wsteps8; x < width; x += 8, yStep++)
+ for (int iy = 0, xStep = 8 * yStep; iy < 8; iy++, xStep++)
+ DecodeBytes_C4(dst + (y + iy) * width + x, src + 4 * xStep, tlut, tlutfmt);
+ break;
+ case GX_TF_I4:
+ {
+ // Reference C implementation:
+ for (int y = 0; y < height; y += 8)
+ for (int x = 0; x < width; x += 8)
+ for (int iy = 0; iy < 8; iy++, src += 4)
+ for (int ix = 0; ix < 4; ix++)
+ {
+ int val = src[ix];
+ u8 i1 = Convert4To8(val >> 4);
+ u8 i2 = Convert4To8(val & 0xF);
+ memset(dst + (y + iy) * width + x + ix * 2, i1, 4);
+ memset(dst + (y + iy) * width + x + ix * 2 + 1, i2, 4);
+ }
+ }
+ break;
+ case GX_TF_I8: // speed critical
+ {
+ // Reference C implementation
+ for (int y = 0; y < height; y += 4)
+ for (int x = 0; x < width; x += 8)
+ for (int iy = 0; iy < 4; ++iy, src += 8)
+ {
+ u32* newdst = dst + (y + iy) * width + x;
+ const u8* newsrc = src;
+ u8 srcval;
- srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
- srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
- srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
- srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
- srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
- srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
- srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
- srcval = newsrc[0]; newdst[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
- }
- }
- break;
- case GX_TF_C8:
- for (int y = 0; y < height; y += 4)
- for (int x = 0, yStep = (y / 4) * Wsteps8; x < width; x += 8, yStep++)
- for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++)
- DecodeBytes_C8((u32*)dst + (y + iy) * width + x, src + 8 * xStep, tlut, tlutfmt);
- break;
- case GX_TF_IA4:
- {
- for (int y = 0; y < height; y += 4)
- for (int x = 0, yStep = (y / 4) * Wsteps8; x < width; x += 8, yStep++)
- for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++)
- DecodeBytes_IA4(dst + (y + iy) * width + x, src + 8 * xStep);
- }
- break;
- case GX_TF_IA8:
- {
- // Reference C implementation:
- for (int y = 0; y < height; y += 4)
- for (int x = 0; x < width; x += 4)
- for (int iy = 0; iy < 4; iy++, src += 8)
- {
- u32 *ptr = dst + (y + iy) * width + x;
- u16 *s = (u16 *)src;
- ptr[0] = DecodePixel_IA8(s[0]);
- ptr[1] = DecodePixel_IA8(s[1]);
- ptr[2] = DecodePixel_IA8(s[2]);
- ptr[3] = DecodePixel_IA8(s[3]);
- }
- }
- break;
- case GX_TF_C14X2:
- for (int y = 0; y < height; y += 4)
- for (int x = 0, yStep = (y / 4) * Wsteps4; x < width; x += 4, yStep++)
- for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++)
- DecodeBytes_C14X2(dst + (y + iy) * width + x, (u16*)(src + 8 * xStep), tlut, tlutfmt);
- break;
- case GX_TF_RGB565:
- {
- // Reference C implementation.
- for (int y = 0; y < height; y += 4)
- for (int x = 0; x < width; x += 4)
- for (int iy = 0; iy < 4; iy++, src += 8)
- {
- u32 *ptr = dst + (y + iy) * width + x;
- u16 *s = (u16 *)src;
- for (int j = 0; j < 4; j++)
- *ptr++ = DecodePixel_RGB565(Common::swap16(*s++));
- }
- }
- break;
- case GX_TF_RGB5A3:
- {
- // Reference C implementation:
- for (int y = 0; y < height; y += 4)
- for (int x = 0; x < width; x += 4)
- for (int iy = 0; iy < 4; iy++, src += 8)
- DecodeBytes_RGB5A3(dst+(y+iy)*width+x, (u16*)src);
- }
- break;
- case GX_TF_RGBA8: // speed critical
- {
- // Reference C implementation.
- for (int y = 0; y < height; y += 4)
- for (int x = 0; x < width; x += 4)
- {
- for (int iy = 0; iy < 4; iy++)
- DecodeBytes_RGBA8(dst + (y+iy)*width + x, (u16*)src + 4 * iy, (u16*)src + 4 * iy + 16);
- src += 64;
- }
- }
- break;
- case GX_TF_CMPR: // speed critical
- // The metroid games use this format almost exclusively.
- {
- for (int y = 0; y < height; y += 8)
- {
- for (int x = 0; x < width; x += 8)
- {
- DecodeDXTBlock((u32*)dst + y * width + x, (DXTBlock*)src, width);
- src += sizeof(DXTBlock);
- DecodeDXTBlock((u32*)dst + y * width + x + 4, (DXTBlock*)src, width);
- src += sizeof(DXTBlock);
- DecodeDXTBlock((u32*)dst + (y + 4) * width + x, (DXTBlock*)src, width);
- src += sizeof(DXTBlock);
- DecodeDXTBlock((u32*)dst + (y + 4) * width + x + 4, (DXTBlock*)src, width);
- src += sizeof(DXTBlock);
- }
- }
- break;
- }
- }
+ srcval = (newsrc++)[0];
+ (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
+ srcval = (newsrc++)[0];
+ (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
+ srcval = (newsrc++)[0];
+ (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
+ srcval = (newsrc++)[0];
+ (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
+ srcval = (newsrc++)[0];
+ (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
+ srcval = (newsrc++)[0];
+ (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
+ srcval = (newsrc++)[0];
+ (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
+ srcval = newsrc[0];
+ newdst[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
+ }
+ }
+ break;
+ case GX_TF_C8:
+ for (int y = 0; y < height; y += 4)
+ for (int x = 0, yStep = (y / 4) * Wsteps8; x < width; x += 8, yStep++)
+ for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++)
+ DecodeBytes_C8((u32*)dst + (y + iy) * width + x, src + 8 * xStep, tlut, tlutfmt);
+ break;
+ case GX_TF_IA4:
+ {
+ for (int y = 0; y < height; y += 4)
+ for (int x = 0, yStep = (y / 4) * Wsteps8; x < width; x += 8, yStep++)
+ for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++)
+ DecodeBytes_IA4(dst + (y + iy) * width + x, src + 8 * xStep);
+ }
+ break;
+ case GX_TF_IA8:
+ {
+ // Reference C implementation:
+ for (int y = 0; y < height; y += 4)
+ for (int x = 0; x < width; x += 4)
+ for (int iy = 0; iy < 4; iy++, src += 8)
+ {
+ u32* ptr = dst + (y + iy) * width + x;
+ u16* s = (u16*)src;
+ ptr[0] = DecodePixel_IA8(s[0]);
+ ptr[1] = DecodePixel_IA8(s[1]);
+ ptr[2] = DecodePixel_IA8(s[2]);
+ ptr[3] = DecodePixel_IA8(s[3]);
+ }
+ }
+ break;
+ case GX_TF_C14X2:
+ for (int y = 0; y < height; y += 4)
+ for (int x = 0, yStep = (y / 4) * Wsteps4; x < width; x += 4, yStep++)
+ for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++)
+ DecodeBytes_C14X2(dst + (y + iy) * width + x, (u16*)(src + 8 * xStep), tlut, tlutfmt);
+ break;
+ case GX_TF_RGB565:
+ {
+ // Reference C implementation.
+ for (int y = 0; y < height; y += 4)
+ for (int x = 0; x < width; x += 4)
+ for (int iy = 0; iy < 4; iy++, src += 8)
+ {
+ u32* ptr = dst + (y + iy) * width + x;
+ u16* s = (u16*)src;
+ for (int j = 0; j < 4; j++)
+ *ptr++ = DecodePixel_RGB565(Common::swap16(*s++));
+ }
+ }
+ break;
+ case GX_TF_RGB5A3:
+ {
+ // Reference C implementation:
+ for (int y = 0; y < height; y += 4)
+ for (int x = 0; x < width; x += 4)
+ for (int iy = 0; iy < 4; iy++, src += 8)
+ DecodeBytes_RGB5A3(dst + (y + iy) * width + x, (u16*)src);
+ }
+ break;
+ case GX_TF_RGBA8: // speed critical
+ {
+ // Reference C implementation.
+ for (int y = 0; y < height; y += 4)
+ for (int x = 0; x < width; x += 4)
+ {
+ for (int iy = 0; iy < 4; iy++)
+ DecodeBytes_RGBA8(dst + (y + iy) * width + x, (u16*)src + 4 * iy,
+ (u16*)src + 4 * iy + 16);
+ src += 64;
+ }
+ }
+ break;
+ case GX_TF_CMPR: // speed critical
+ // The metroid games use this format almost exclusively.
+ {
+ for (int y = 0; y < height; y += 8)
+ {
+ for (int x = 0; x < width; x += 8)
+ {
+ DecodeDXTBlock((u32*)dst + y * width + x, (DXTBlock*)src, width);
+ src += sizeof(DXTBlock);
+ DecodeDXTBlock((u32*)dst + y * width + x + 4, (DXTBlock*)src, width);
+ src += sizeof(DXTBlock);
+ DecodeDXTBlock((u32*)dst + (y + 4) * width + x, (DXTBlock*)src, width);
+ src += sizeof(DXTBlock);
+ DecodeDXTBlock((u32*)dst + (y + 4) * width + x + 4, (DXTBlock*)src, width);
+ src += sizeof(DXTBlock);
+ }
+ }
+ break;
+ }
+ }
}