| 
									
										
										
										
											2015-05-24 06:55:12 +02:00
										 |  |  | // Copyright 2008 Dolphin Emulator Project
 | 
					
						
							| 
									
										
										
										
											2015-05-18 01:08:10 +02:00
										 |  |  | // Licensed under GPLv2+
 | 
					
						
							| 
									
										
										
										
											2014-05-02 22:47:04 -04:00
										 |  |  | // Refer to the license.txt file included.
 | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-02 22:47:04 -04:00
										 |  |  | #include <algorithm>
 | 
					
						
							| 
									
										
										
										
											2010-07-31 14:40:01 +00:00
										 |  |  | #include <cmath>
 | 
					
						
							| 
									
										
										
										
											2011-03-07 20:23:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | #include "Common/CPUDetect.h"
 | 
					
						
							| 
									
										
										
										
											2016-01-17 16:54:31 -05:00
										 |  |  | #include "Common/CommonTypes.h"
 | 
					
						
							| 
									
										
										
										
											2017-03-03 14:43:52 -05:00
										 |  |  | #include "Common/Swap.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-19 02:27:20 +01:00
										 |  |  | #include "VideoCommon/LookUpTables.h"
 | 
					
						
							|  |  |  | #include "VideoCommon/TextureDecoder.h"
 | 
					
						
							| 
									
										
										
										
											2017-01-14 11:29:05 +11:00
										 |  |  | #include "VideoCommon/TextureDecoder_Util.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-19 02:27:20 +01:00
										 |  |  | //#include "VideoCommon/VideoCommon.h" // to get debug logs
 | 
					
						
							|  |  |  | #include "VideoCommon/VideoConfig.h"
 | 
					
						
							| 
									
										
										
										
											2010-07-31 14:40:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-07 11:30:39 +09:00
										 |  |  | // GameCube/Wii texture decoder
 | 
					
						
							| 
									
										
										
										
											2009-09-02 21:00:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-07 11:30:39 +09:00
										 |  |  | // Decodes all known GameCube/Wii texture formats.
 | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | // by ector
 | 
					
						
							| 
									
										
										
										
											2009-09-02 21:00:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-10 16:22:44 -04:00
										 |  |  | static inline u32 DecodePixel_IA8(u16 val) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   int a = val & 0xFF; | 
					
						
							|  |  |  |   int i = val >> 8; | 
					
						
							|  |  |  |   return i | (i << 8) | (i << 16) | (a << 24); | 
					
						
							| 
									
										
										
										
											2014-08-10 16:22:44 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline u32 DecodePixel_RGB565(u16 val) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   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); | 
					
						
							| 
									
										
										
										
											2014-08-10 16:22:44 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline u32 DecodePixel_RGB5A3(u16 val) | 
					
						
							| 
									
										
										
										
											2010-06-19 13:31:40 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   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); | 
					
						
							| 
									
										
										
										
											2010-06-19 13:31:40 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-30 12:45:55 -07:00
										 |  |  | static inline u32 DecodePixel_Paletted(u16 pixel, TLUTFormat tlutfmt) | 
					
						
							| 
									
										
										
										
											2010-06-19 13:31:40 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   switch (tlutfmt) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2017-07-30 12:45:55 -07:00
										 |  |  |   case TLUTFormat::IA8: | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |     return DecodePixel_IA8(pixel); | 
					
						
							| 
									
										
										
										
											2017-07-30 12:45:55 -07:00
										 |  |  |   case TLUTFormat::RGB565: | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |     return DecodePixel_RGB565(Common::swap16(pixel)); | 
					
						
							| 
									
										
										
										
											2017-07-30 12:45:55 -07:00
										 |  |  |   case TLUTFormat::RGB5A3: | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |     return DecodePixel_RGB5A3(Common::swap16(pixel)); | 
					
						
							|  |  |  |   default: | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2010-06-19 13:31:40 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-30 12:45:55 -07:00
										 |  |  | static inline void DecodeBytes_C4(u32* dst, const u8* src, const u8* tlut_, TLUTFormat tlutfmt) | 
					
						
							| 
									
										
										
										
											2010-06-19 13:31:40 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   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); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2010-06-19 13:31:40 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-30 12:45:55 -07:00
										 |  |  | static inline void DecodeBytes_C8(u32* dst, const u8* src, const u8* tlut_, TLUTFormat tlutfmt) | 
					
						
							| 
									
										
										
										
											2013-10-29 01:23:17 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   const u16* tlut = (u16*)tlut_; | 
					
						
							|  |  |  |   for (int x = 0; x < 8; x++) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     u8 val = src[x]; | 
					
						
							|  |  |  |     *dst++ = DecodePixel_Paletted(tlut[val], tlutfmt); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2010-06-19 13:31:40 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-30 12:45:55 -07:00
										 |  |  | static inline void DecodeBytes_C14X2(u32* dst, const u16* src, const u8* tlut_, TLUTFormat tlutfmt) | 
					
						
							| 
									
										
										
										
											2010-06-19 13:31:40 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   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); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2010-06-19 13:31:40 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | static inline void DecodeBytes_IA4(u32* dst, const u8* src) | 
					
						
							| 
									
										
										
										
											2010-06-19 13:31:40 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   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; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2010-06-19 13:31:40 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | static inline void DecodeBytes_RGB5A3(u32* dst, const u16* src) | 
					
						
							| 
									
										
										
										
											2010-06-19 13:31:40 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-12-30 19:17:08 +00:00
										 |  |  | #if 0
 | 
					
						
							| 
									
										
										
										
											2011-01-01 03:52:32 +00:00
										 |  |  | 	for (int x = 0; x < 4; x++) | 
					
						
							| 
									
										
										
										
											2014-08-10 16:22:44 -04:00
										 |  |  | 		dst[x] = DecodePixel_RGB5A3(Common::swap16(src[x])); | 
					
						
							| 
									
										
										
										
											2010-12-30 19:17:08 +00:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   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])); | 
					
						
							| 
									
										
										
										
											2010-12-30 19:17:08 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-06-19 13:31:40 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | static inline void DecodeBytes_RGBA8(u32* dst, const u16* src, const u16* src2) | 
					
						
							| 
									
										
										
										
											2010-06-19 13:31:40 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-12-30 19:17:08 +00:00
										 |  |  | #if 0
 | 
					
						
							| 
									
										
										
										
											2014-08-30 16:51:27 -04:00
										 |  |  | 	for (int x = 0; x < 4; x++) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2013-03-19 21:51:12 -04:00
										 |  |  | 		dst[x] =  ((src[x] & 0xFF) << 24) | ((src[x] & 0xFF00)>>8)  | (src2[x] << 8); | 
					
						
							| 
									
										
										
										
											2010-12-30 19:17:08 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   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); | 
					
						
							| 
									
										
										
										
											2010-12-30 19:17:08 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-06-19 13:31:40 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | static void DecodeDXTBlock(u32* dst, const DXTBlock* src, int pitch) | 
					
						
							| 
									
										
										
										
											2010-06-19 13:31:40 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   // 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) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2017-01-14 01:41:44 +11:00
										 |  |  |     colors[2] = | 
					
						
							|  |  |  |         MakeRGBA(DXTBlend(red2, red1), DXTBlend(green2, green1), DXTBlend(blue2, blue1), 255); | 
					
						
							|  |  |  |     colors[3] = | 
					
						
							|  |  |  |         MakeRGBA(DXTBlend(red1, red2), DXTBlend(green1, green2), DXTBlend(blue1, blue2), 255); | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2016-12-11 21:54:21 +10:00
										 |  |  |     // color[3] is the same as color[2] (average of both colors), but transparent.
 | 
					
						
							|  |  |  |     // This differs from DXT1 where color[3] is transparent black.
 | 
					
						
							| 
									
										
										
										
											2017-01-14 01:41:44 +11:00
										 |  |  |     colors[2] = MakeRGBA((red1 + red2) / 2, (green1 + green2) / 2, (blue1 + blue2) / 2, 255); | 
					
						
							|  |  |  |     colors[3] = MakeRGBA((red1 + red2) / 2, (green1 + green2) / 2, (blue1 + blue2) / 2, 0); | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2011-01-01 03:52:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   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; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2010-06-19 13:31:40 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-06 16:41:20 +00:00
										 |  |  | // JSD 01/06/11:
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | // 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
 | 
					
						
							| 
									
										
										
										
											2011-01-06 16:41:20 +00:00
										 |  |  | // 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.
 | 
					
						
							| 
									
										
										
										
											2009-12-07 18:48:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-30 12:45:55 -07:00
										 |  |  | void _TexDecoder_DecodeImpl(u32* dst, const u8* src, int width, int height, TextureFormat texformat, | 
					
						
							|  |  |  |                             const u8* tlut, TLUTFormat tlutfmt) | 
					
						
							| 
									
										
										
										
											2010-06-19 13:31:40 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   const int Wsteps4 = (width + 3) / 4; | 
					
						
							|  |  |  |   const int Wsteps8 = (width + 7) / 8; | 
					
						
							| 
									
										
										
										
											2011-03-21 05:46:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   switch (texformat) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2017-07-30 12:45:55 -07:00
										 |  |  |   case TextureFormat::C4: | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |     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; | 
					
						
							| 
									
										
										
										
											2017-07-30 12:45:55 -07:00
										 |  |  |   case TextureFormat::I4: | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   { | 
					
						
							|  |  |  |     // 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; | 
					
						
							| 
									
										
										
										
											2017-07-30 12:45:55 -07:00
										 |  |  |   case TextureFormat::I8:  // speed critical
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   { | 
					
						
							|  |  |  |     // 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; | 
					
						
							| 
									
										
										
										
											2011-01-01 03:52:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |           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; | 
					
						
							| 
									
										
										
										
											2017-07-30 12:45:55 -07:00
										 |  |  |   case TextureFormat::C8: | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |     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; | 
					
						
							| 
									
										
										
										
											2017-07-30 12:45:55 -07:00
										 |  |  |   case TextureFormat::IA4: | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   { | 
					
						
							|  |  |  |     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; | 
					
						
							| 
									
										
										
										
											2017-07-30 12:45:55 -07:00
										 |  |  |   case TextureFormat::IA8: | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   { | 
					
						
							|  |  |  |     // 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; | 
					
						
							| 
									
										
										
										
											2017-07-30 12:45:55 -07:00
										 |  |  |   case TextureFormat::C14X2: | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |     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; | 
					
						
							| 
									
										
										
										
											2017-07-30 12:45:55 -07:00
										 |  |  |   case TextureFormat::RGB565: | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   { | 
					
						
							|  |  |  |     // 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; | 
					
						
							| 
									
										
										
										
											2017-07-30 12:45:55 -07:00
										 |  |  |   case TextureFormat::RGB5A3: | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   { | 
					
						
							|  |  |  |     // 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; | 
					
						
							| 
									
										
										
										
											2017-07-30 12:45:55 -07:00
										 |  |  |   case TextureFormat::RGBA8:  // speed critical
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   { | 
					
						
							|  |  |  |     // 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; | 
					
						
							| 
									
										
										
										
											2017-07-30 12:45:55 -07:00
										 |  |  |   case TextureFormat::CMPR:  // speed critical
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |     // 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; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2009-12-07 18:48:31 +00:00
										 |  |  | } |