diff options
Diffstat (limited to 'Source/Core/VideoCommon/TextureDecoder_Generic.cpp')
| -rw-r--r-- | Source/Core/VideoCommon/TextureDecoder_Generic.cpp | 536 |
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; + } + } } |
