Rice GLES2 (from mupen64plus-ae) plugin. Compile but doesn't works well on the OpenPa...
[mupen64plus-pandora.git] / source / gles2rice / src / ConvertImage16.cpp
1 /*
2 Copyright (C) 2003 Rice1964
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17
18 */
19
20 #include "Config.h"
21 #include "ConvertImage.h"
22 #include "RenderBase.h"
23
24 // Still to be swapped:
25 // IA16
26
27 ConvertFunction     gConvertFunctions_16_FullTMEM[ 8 ][ 4 ] = 
28 {
29     // 4bpp             8bpp            16bpp               32bpp
30     {  Convert4b_16,    Convert8b_16,   Convert16b_16,      ConvertRGBA32_16 },     // RGBA
31     {  NULL,            NULL,           ConvertYUV_16,      NULL },                 // YUV
32     {  Convert4b_16,    Convert8b_16,   NULL,               NULL },                 // CI
33     {  Convert4b_16,    Convert8b_16,   Convert16b_16,      NULL },                 // IA
34     {  Convert4b_16,    Convert8b_16,   Convert16b_16,      NULL },                 // I
35     {  NULL,            NULL,           NULL,               NULL },                 // ?
36     {  NULL,            NULL,           NULL,               NULL },                 // ?
37     {  NULL,            NULL,           NULL,               NULL }                  // ?
38 };
39 ConvertFunction     gConvertFunctions_16[ 8 ][ 4 ] = 
40 {
41     // 4bpp             8bpp            16bpp               32bpp
42     {  ConvertCI4_16,   ConvertCI8_16,  ConvertRGBA16_16,   ConvertRGBA32_16 },     // RGBA
43     {  NULL,            NULL,           ConvertYUV_16,      NULL },                 // YUV
44     {  ConvertCI4_16,   ConvertCI8_16,  NULL,               NULL },                 // CI
45     {  ConvertIA4_16,   ConvertIA8_16,  ConvertIA16_16,     NULL },                 // IA
46     {  ConvertI4_16,    ConvertI8_16,   ConvertRGBA16_16,   NULL },                 // I
47     {  NULL,            NULL,           NULL,               NULL },                 // ?
48     {  NULL,            NULL,           NULL,               NULL },                 // ?
49     {  NULL,            NULL,           NULL,               NULL }                  // ?
50 };
51
52 ConvertFunction     gConvertTlutFunctions_16[ 8 ][ 4 ] = 
53 {
54     // 4bpp             8bpp            16bpp               32bpp
55     {  ConvertCI4_16,   ConvertCI8_16,  ConvertRGBA16_16,   ConvertRGBA32_16 },     // RGBA
56     {  NULL,            NULL,           ConvertYUV_16,      NULL },                 // YUV
57     {  ConvertCI4_16,   ConvertCI8_16,  NULL,               NULL },                 // CI
58     {  ConvertCI4_16,   ConvertCI8_16,  ConvertIA16_16,     NULL },                 // IA
59     {  ConvertCI4_16,   ConvertCI8_16,  ConvertRGBA16_16,   NULL },                 // I
60     {  NULL,            NULL,           NULL,               NULL },                 // ?
61     {  NULL,            NULL,           NULL,               NULL },                 // ?
62     {  NULL,            NULL,           NULL,               NULL }                  // ?
63 };
64
65 extern bool conkerSwapHack;
66
67 void ConvertRGBA16_16(CTexture *pTexture, const TxtrInfo &tinfo)
68 {
69     DrawInfo dInfo;
70     uint32 x, y;
71     uint32 nFiddle;
72
73     // Copy of the base pointer
74     uint16 * pSrc = (uint16*)(tinfo.pPhysicalAddress);
75     uint8 * pByteSrc = (uint8 *)pSrc;
76
77     if (!pTexture->StartUpdate(&dInfo))
78         return;
79
80     if (tinfo.bSwapped)
81     {
82         for (y = 0; y < tinfo.HeightToLoad; y++)
83         {
84             if ((y%2) == 0)
85                 nFiddle = 0x2;
86             else
87                 nFiddle = 0x2 | 0x4;
88
89             // dwDst points to start of destination row
90             uint16 * wDst = (uint16 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);
91
92             // DWordOffset points to the current dword we're looking at
93             // (process 2 pixels at a time). May be a problem if we don't start on even pixel
94             uint32 dwWordOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad * 2);
95
96             for (x = 0; x < tinfo.WidthToLoad; x++)
97             {
98                 uint16 w = *(uint16 *)&pByteSrc[dwWordOffset ^ nFiddle];
99
100                 wDst[x] = Convert555ToR4G4B4A4(w);
101                 
102                 // Increment word offset to point to the next two pixels
103                 dwWordOffset += 2;
104             }
105         }
106     }
107     else
108     {
109         for (y = 0; y < tinfo.HeightToLoad; y++)
110         {
111             // dwDst points to start of destination row
112             uint16 * wDst = (uint16 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);
113
114             // DWordOffset points to the current dword we're looking at
115             // (process 2 pixels at a time). May be a problem if we don't start on even pixel
116             uint32 dwWordOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad * 2);
117
118             for (x = 0; x < tinfo.WidthToLoad; x++)
119             {
120                 uint16 w = *(uint16 *)&pByteSrc[dwWordOffset ^ 0x2];
121
122                 wDst[x] = Convert555ToR4G4B4A4(w);
123                 
124                 // Increment word offset to point to the next two pixels
125                 dwWordOffset += 2;
126             }
127         }
128     }
129
130     pTexture->EndUpdate(&dInfo);
131     pTexture->SetOthersVariables();
132 }
133
134 void ConvertRGBA32_16(CTexture *pTexture, const TxtrInfo &tinfo)
135 {
136     DrawInfo dInfo;
137     uint32 * pSrc = (uint32*)(tinfo.pPhysicalAddress);
138     if (!pTexture->StartUpdate(&dInfo))
139         return;
140
141     if( options.bUseFullTMEM )
142     {
143         Tile &tile = gRDP.tiles[tinfo.tileNo];
144
145         uint32 *pWordSrc;
146         if( tinfo.tileNo >= 0 )
147         {
148             pWordSrc = (uint32*)&g_Tmem.g_Tmem64bit[tile.dwTMem];
149
150             for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
151             {
152                 uint16 * dwDst = (uint16 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);
153
154                 uint32 nFiddle = ( y&1 )? 0x2 : 0;
155                 int idx = tile.dwLine*4*y;
156
157                 for (uint32 x = 0; x < tinfo.WidthToLoad; x++, idx++)
158                 {
159                     uint32 w = pWordSrc[idx^nFiddle];
160                     uint8* psw = (uint8*)&w;
161                     dwDst[x] = R4G4B4A4_MAKE( (psw[0]>>4), (psw[1]>>4), (psw[2]>>4), (psw[3]>>4));
162                 }
163             }
164         }
165     }
166     else
167     {
168         if (tinfo.bSwapped)
169         {
170             for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
171             {
172                 if ((y%2) == 0)
173                 {
174                     uint16 *pDst = (uint16*)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
175                     uint8 *pS = (uint8 *)pSrc + (y+tinfo.TopToLoad) * tinfo.Pitch + (tinfo.LeftToLoad*4);
176
177                     for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
178                     {
179
180                         *pDst++ = R4G4B4A4_MAKE((pS[3]>>4),  // Red
181                                                 (pS[2]>>4),  // Green
182                                                 (pS[1]>>4),  // Blue
183                                                 (pS[0]>>4)); // Alpha
184                         pS+=4;
185                     }
186                 }
187                 else
188                 {
189                     uint16 *pDst = (uint16*)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
190                     uint8 *pS = (uint8 *)pSrc + (y+tinfo.TopToLoad) * tinfo.Pitch + (tinfo.LeftToLoad*4);
191                     int n;
192
193                     n = 0;
194                     for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
195                     {
196                         *pDst++ = R4G4B4A4_MAKE((pS[(n^0x8) + 3]>>4),   // Red
197                                                 (pS[(n^0x8) + 2]>>4),   // Green
198                                                 (pS[(n^0x8) + 1]>>4),   // Blue
199                                                 (pS[(n^0x8) + 0]>>4));  // Alpha
200
201                         n += 4;
202                     }
203                 }
204             }
205         }
206         else
207         {
208             for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
209             {
210                 uint16 *pDst = (uint16*)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
211                 uint8 *pS = (uint8 *)pSrc + (y+tinfo.TopToLoad) * tinfo.Pitch + (tinfo.LeftToLoad*4);
212
213                 for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
214                 {
215                     *pDst++ = R4G4B4A4_MAKE((pS[3]>>4),     // Red
216                                             (pS[2]>>4),     // Green
217                                             (pS[1]>>4),     // Blue
218                                             (pS[0]>>4));    // Alpha
219                     pS+=4;
220                 }
221             }
222         }
223     }
224
225     pTexture->EndUpdate(&dInfo);
226     pTexture->SetOthersVariables();
227
228 }
229
230 // E.g. Dear Mario text
231 // Copy, Score etc
232 void ConvertIA4_16(CTexture *pTexture, const TxtrInfo &tinfo)
233 {
234     DrawInfo dInfo;
235     uint32 nFiddle;
236
237     uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);
238     if (!pTexture->StartUpdate(&dInfo))
239         return;
240
241     if (tinfo.bSwapped)
242     {
243         for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
244         {
245             uint16 *pDst = (uint16*)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
246
247             // For odd lines, swap words too
248             if ((y%2) == 0)
249                 nFiddle = 0x3;
250             else
251                 nFiddle = 0x7;
252
253
254             // This may not work if X is not even?
255             uint32 dwByteOffset = (y+tinfo.TopToLoad) * tinfo.Pitch + (tinfo.LeftToLoad/2);
256
257             // Do two pixels at a time
258             for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)
259             {
260                 uint8 b = pSrc[dwByteOffset ^ nFiddle];
261
262                 // Even
263                 *pDst++ = R4G4B4A4_MAKE(ThreeToFour[(b & 0xE0) >> 5],
264                                         ThreeToFour[(b & 0xE0) >> 5],
265                                         ThreeToFour[(b & 0xE0) >> 5],
266                                         OneToFour[(b & 0x10) >> 4]);
267     
268                 // Odd
269                 *pDst++ = R4G4B4A4_MAKE(ThreeToFour[(b & 0x0E) >> 1],
270                                         ThreeToFour[(b & 0x0E) >> 1],
271                                         ThreeToFour[(b & 0x0E) >> 1],
272                                         OneToFour[(b & 0x01)]     );
273
274                 dwByteOffset++;
275             }
276         }
277     }
278     else
279     {
280         for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
281         {
282             uint16 *pDst = (uint16*)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
283
284             // This may not work if X is not even?
285             uint32 dwByteOffset = (y+tinfo.TopToLoad) * tinfo.Pitch + (tinfo.LeftToLoad/2);
286
287             // Do two pixels at a time
288             for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)
289             {
290                 uint8 b = pSrc[dwByteOffset ^ 0x3];
291
292                 // Even
293                 *pDst++ = R4G4B4A4_MAKE(ThreeToFour[(b & 0xE0) >> 5],
294                                         ThreeToFour[(b & 0xE0) >> 5],
295                                         ThreeToFour[(b & 0xE0) >> 5],
296                                         OneToFour[(b & 0x10) >> 4]);
297     
298                 // Odd
299                 *pDst++ = R4G4B4A4_MAKE(ThreeToFour[(b & 0x0E) >> 1],
300                                         ThreeToFour[(b & 0x0E) >> 1],
301                                         ThreeToFour[(b & 0x0E) >> 1],
302                                         OneToFour[(b & 0x01)]     );
303
304                 dwByteOffset++;
305             }
306         }
307     }
308     
309     pTexture->EndUpdate(&dInfo);
310     pTexture->SetOthersVariables();
311 }
312
313 // E.g Mario's head textures
314 void ConvertIA8_16(CTexture *pTexture, const TxtrInfo &tinfo)
315 {
316     DrawInfo dInfo;
317     uint32 nFiddle;
318
319     uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);
320     if (!pTexture->StartUpdate(&dInfo))
321         return;
322
323     if (tinfo.bSwapped)
324     {
325         for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
326         {
327             // For odd lines, swap words too
328             if ((y%2) == 0)
329                 nFiddle = 0x3;
330             else
331                 nFiddle = 0x7;
332
333
334             uint16 *pDst = (uint16 *)((uint8*)dInfo.lpSurface + y * dInfo.lPitch);
335             // Points to current byte
336             uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;
337
338             for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
339             {
340                 uint8 b = pSrc[dwByteOffset ^ nFiddle];
341
342                 *pDst++ = R4G4B4A4_MAKE( ((b&0xf0)>>4),((b&0xf0)>>4),((b&0xf0)>>4),(b&0x0f));
343
344                 dwByteOffset++;
345             }
346         }
347     }
348     else
349     {
350         for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
351         {
352             uint16 *pDst = (uint16*)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
353
354             // Points to current byte
355             uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;
356
357             for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
358             {
359                 uint8 b = pSrc[dwByteOffset ^ 0x3];
360
361                 *pDst++ = R4G4B4A4_MAKE(((b&0xf0)>>4),((b&0xf0)>>4),((b&0xf0)>>4),(b&0x0f));
362
363                 dwByteOffset++;
364             }
365         }
366     }
367     
368     pTexture->EndUpdate(&dInfo);
369     pTexture->SetOthersVariables();
370
371 }
372
373 // E.g. camera's clouds, shadows
374 void ConvertIA16_16(CTexture *pTexture, const TxtrInfo &tinfo)
375 {
376     DrawInfo dInfo;
377
378     uint16 * pSrc = (uint16*)(tinfo.pPhysicalAddress);
379     uint8 * pByteSrc = (uint8 *)pSrc;
380
381     if (!pTexture->StartUpdate(&dInfo))
382         return;
383         
384     for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
385     {
386         uint16 *pDst = (uint16*)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
387
388         // Points to current word
389         uint32 dwWordOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad * 2);
390
391         for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
392         {
393             uint16 w = *(uint16 *)&pByteSrc[dwWordOffset^0x2];
394
395             uint8 i = (uint8)(w >> 12);
396             uint8 a = (uint8)(w & 0xFF);
397
398             *pDst++ = R4G4B4A4_MAKE(i, i, i, (a>>4));
399
400             dwWordOffset += 2;
401         }
402     }
403
404     pTexture->EndUpdate(&dInfo);
405     pTexture->SetOthersVariables();
406 }
407
408
409
410 // Used by MarioKart 
411 void ConvertI4_16(CTexture *pTexture, const TxtrInfo &tinfo)
412 {
413     DrawInfo dInfo;
414     uint32 nFiddle;
415
416     uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);
417     if (!pTexture->StartUpdate(&dInfo))
418         return;
419
420     if (tinfo.bSwapped)
421     {
422         for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
423         {
424             uint16 *pDst = (uint16*)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
425
426             // Might not work with non-even starting X
427             uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);
428
429             // For odd lines, swap words too
430             if( !conkerSwapHack || (y&4) == 0 )
431             {
432                 if ((y%2) == 0)
433                     nFiddle = 0x3;
434                 else
435                     nFiddle = 0x7;
436             }
437             else
438             {
439                 if ((y%2) == 1)
440                     nFiddle = 0x3;
441                 else
442                     nFiddle = 0x7;
443             }
444
445             for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)
446             {
447                 uint8 b = pSrc[dwByteOffset ^ nFiddle];
448
449                 // Even
450                 //*pDst++ = R4G4B4A4_MAKE(b>>4, b>>4, b>>4, b>>4);
451                 *pDst++ = FourToSixteen[(b & 0xF0)>>4];
452                 // Odd
453                 //*pDst++ = R4G4B4A4_MAKE(b & 0x0f, b & 0x0f, b & 0x0f, b & 0x0f);
454                 *pDst++ = FourToSixteen[b & 0x0f];
455
456                 dwByteOffset++;
457             }
458         }
459     }
460     else
461     {
462         for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
463         {
464             uint8 *pDst = (uint8 *)dInfo.lpSurface + y * dInfo.lPitch;
465
466             // Might not work with non-even starting X
467             uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);
468
469             for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)
470             {
471                 uint8 b = pSrc[dwByteOffset ^ 0x3];
472
473                 // Even
474                 //*pDst++ = R4G4B4A4_MAKE(b>>4, b>>4, b>>4, b>>4);
475                 *pDst++ = FourToEight[(b & 0xF0)>>4];
476
477                 // Odd
478                 //*pDst++ = R4G4B4A4_MAKE(b & 0x0f, b & 0x0f, b & 0x0f, b & 0x0f);
479                 *pDst++ = FourToEight[b & 0x0f];
480
481                 dwByteOffset++;
482             }
483         }
484     }
485     
486     pTexture->EndUpdate(&dInfo);
487     pTexture->SetOthersVariables();
488 }
489
490 // Used by MarioKart
491 void ConvertI8_16(CTexture *pTexture, const TxtrInfo &tinfo)
492 {
493     DrawInfo dInfo;
494     uint32 nFiddle;
495
496     long long pSrc = (long long) (tinfo.pPhysicalAddress);
497     if (!pTexture->StartUpdate(&dInfo))
498         return;
499
500     if (tinfo.bSwapped)
501     {
502         for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
503         {
504             if ((y%2) == 0)
505                 nFiddle = 0x3;
506             else
507                 nFiddle = 0x7;
508
509             uint16 *pDst = (uint16*)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
510
511             uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;
512
513             for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
514             {
515                 uint8 b = *(uint8*)((pSrc+dwByteOffset)^nFiddle);
516
517                 *pDst++ = R4G4B4A4_MAKE(b>>4,
518                                         b>>4,
519                                         b>>4,
520                                         b>>4);
521
522                 dwByteOffset++;
523             }
524         }
525     }
526     else
527     {
528         for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
529         {
530             uint16 *pDst = (uint16*)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
531
532             uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;
533
534             for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
535             {
536                 uint8 b = *(uint8*)((pSrc+dwByteOffset)^0x3);
537
538                 *pDst++ = R4G4B4A4_MAKE(b>>4,
539                                         b>>4,
540                                         b>>4,
541                                         b>>4);
542
543                 dwByteOffset++;
544             }
545         }
546
547     }
548     pTexture->EndUpdate(&dInfo);
549     pTexture->SetOthersVariables();
550
551 }
552
553
554 // Used by Starfox intro
555 void ConvertCI4_RGBA16_16(CTexture *pTexture, const TxtrInfo &tinfo)
556 {
557     DrawInfo dInfo;
558     uint32 nFiddle;
559
560     uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);
561     uint16 * pPal = (uint16 *)tinfo.PalAddress;
562     if (!pTexture->StartUpdate(&dInfo))
563         return;
564
565     if (tinfo.bSwapped)
566     {
567
568         for (uint32 y = 0; y <  tinfo.HeightToLoad; y++)
569         {
570             if ((y%2) == 0)
571                 nFiddle = 0x3;
572             else
573                 nFiddle = 0x7;
574
575
576             uint16 * pDst = (uint16 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
577
578             uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);
579
580             for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)
581             {
582                 uint8 b = pSrc[dwByteOffset ^ nFiddle];
583
584                 uint8 bhi = (b&0xf0)>>4;
585                 uint8 blo = (b&0x0f);
586
587                 pDst[0] = Convert555ToR4G4B4A4(pPal[bhi^1]);    // Remember palette is in different endian order!
588                 pDst[1] = Convert555ToR4G4B4A4(pPal[blo^1]);    // Remember palette is in different endian order!
589                 pDst+=2;
590
591                 dwByteOffset++;
592             }
593         }   
594         
595     }
596     else
597     {
598         for (uint32 y = 0; y <  tinfo.HeightToLoad; y++)
599         {
600             uint16 * pDst = (uint16 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
601
602             uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);
603
604             for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)
605             {
606                 uint8 b = pSrc[dwByteOffset ^ 0x3];
607
608                 uint8 bhi = (b&0xf0)>>4;
609                 uint8 blo = (b&0x0f);
610
611                 pDst[0] = Convert555ToR4G4B4A4(pPal[bhi^1]);    // Remember palette is in different endian order!
612                 pDst[1] = Convert555ToR4G4B4A4(pPal[blo^1]);    // Remember palette is in different endian order!
613                 pDst+=2;
614
615                 dwByteOffset++;
616             }
617         }
618     }
619
620     pTexture->EndUpdate(&dInfo);
621     pTexture->SetOthersVariables();
622 }
623
624 //*****************************************************************************
625 // Convert CI4 images. We need to switch on the palette type
626 //*****************************************************************************
627 void ConvertCI4_16( CTexture * p_texture, const TxtrInfo & tinfo )
628 {
629     if ( tinfo.TLutFmt == TLUT_FMT_RGBA16 )
630     {
631         ConvertCI4_RGBA16_16( p_texture, tinfo );   
632     }
633     else if ( tinfo.TLutFmt == TLUT_FMT_IA16 )
634     {
635         ConvertCI4_IA16_16( p_texture, tinfo );                 
636     }
637 }
638
639 //*****************************************************************************
640 // Convert CI8 images. We need to switch on the palette type
641 //*****************************************************************************
642 void ConvertCI8_16( CTexture * p_texture, const TxtrInfo & tinfo )
643 {
644     if ( tinfo.TLutFmt == TLUT_FMT_RGBA16 )
645     {
646         ConvertCI8_RGBA16_16( p_texture, tinfo );   
647     }
648     else if ( tinfo.TLutFmt == TLUT_FMT_IA16 )
649     {
650         ConvertCI8_IA16_16( p_texture, tinfo );                 
651     }
652 }
653
654 // Used by Starfox intro
655 void ConvertCI4_IA16_16(CTexture *pTexture, const TxtrInfo &tinfo)
656 {
657     DrawInfo dInfo;
658     uint32 nFiddle;
659
660     uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);
661     uint16 * pPal = (uint16 *)tinfo.PalAddress;
662     if (!pTexture->StartUpdate(&dInfo))
663         return;
664
665     if (tinfo.bSwapped)
666     {
667         for (uint32 y = 0; y <  tinfo.HeightToLoad; y++)
668         {
669             if ((y%2) == 0)
670                 nFiddle = 0x3;
671             else
672                 nFiddle = 0x7;
673
674             uint16 * pDst = (uint16 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
675
676             uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);
677
678             for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)
679             {
680                 uint8 b = pSrc[dwByteOffset ^ nFiddle];
681
682                 uint8 bhi = (b&0xf0)>>4;
683                 uint8 blo = (b&0x0f);
684
685                 pDst[0] = ConvertIA16ToR4G4B4A4(pPal[bhi^1]);   // Remember palette is in different endian order!
686                 pDst[1] = ConvertIA16ToR4G4B4A4(pPal[blo^1]);   // Remember palette is in different endian order!
687                 pDst += 2;
688                 dwByteOffset++;
689             }
690         }
691     }
692     else
693     {
694         for (uint32 y = 0; y <  tinfo.HeightToLoad; y++)
695         {
696             uint16 * pDst = (uint16 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
697
698             uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);
699
700             for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)
701             {
702                 uint8 b = pSrc[dwByteOffset ^ 0x3];
703
704                 uint8 bhi = (b&0xf0)>>4;
705                 uint8 blo = (b&0x0f);
706
707                 pDst[0] = ConvertIA16ToR4G4B4A4(pPal[bhi^1]);   // Remember palette is in different endian order!
708                 pDst[1] = ConvertIA16ToR4G4B4A4(pPal[blo^1]);   // Remember palette is in different endian order!
709                 pDst+=2;
710
711                 dwByteOffset++;
712             }
713         }
714     }
715
716     pTexture->EndUpdate(&dInfo);
717     pTexture->SetOthersVariables();
718 }
719
720
721 // Used by MarioKart for Cars etc
722 void ConvertCI8_RGBA16_16(CTexture *pTexture, const TxtrInfo &tinfo)
723 {
724     DrawInfo dInfo;
725     uint32 nFiddle;
726
727     uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);
728     uint16 * pPal = (uint16 *)tinfo.PalAddress;
729     if (!pTexture->StartUpdate(&dInfo))
730         return;
731
732     if (tinfo.bSwapped)
733     {
734         for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
735         {
736             if ((y%2) == 0)
737                 nFiddle = 0x3;
738             else
739                 nFiddle = 0x7;
740
741             uint16 *pDst = (uint16 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
742
743             uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;
744             
745             for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
746             {
747                 uint8 b = pSrc[dwByteOffset ^ nFiddle];
748
749                 *pDst++ = Convert555ToR4G4B4A4(pPal[b^1]);  // Remember palette is in different endian order!
750
751                 dwByteOffset++;
752             }
753         }
754     }
755     else
756     {
757         for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
758         {
759             uint16 *pDst = (uint16 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
760
761             uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;
762             
763             for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
764             {
765                 uint8 b = pSrc[dwByteOffset ^ 0x3];
766
767                 *pDst++ = Convert555ToR4G4B4A4(pPal[b^1]);  // Remember palette is in different endian order!
768
769                 dwByteOffset++;
770             }
771         }
772     }
773
774     pTexture->EndUpdate(&dInfo);
775     pTexture->SetOthersVariables();
776 }
777
778
779 // Used by MarioKart for Cars etc
780 void ConvertCI8_IA16_16(CTexture *pTexture, const TxtrInfo &tinfo)
781 {
782     DrawInfo dInfo;
783     uint32 nFiddle;
784
785     uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);
786     uint16 * pPal = (uint16 *)tinfo.PalAddress;
787     if (!pTexture->StartUpdate(&dInfo))
788         return;
789
790     if (tinfo.bSwapped)
791     {
792         for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
793         {
794             if ((y%2) == 0)
795                 nFiddle = 0x3;
796             else
797                 nFiddle = 0x7;
798
799             uint16 *pDst = (uint16 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
800
801             uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;
802             
803             for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
804             {
805                 uint8 b = pSrc[dwByteOffset ^ nFiddle];
806
807                 *pDst++ = ConvertIA16ToR4G4B4A4(pPal[b^1]); // Remember palette is in different endian order!
808
809                 dwByteOffset++;
810             }
811         }
812     }
813     else
814     {
815         for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
816         {
817             uint16 *pDst = (uint16 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
818
819             uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;
820             
821             for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
822             {
823                 uint8 b = pSrc[dwByteOffset ^ 0x3];
824
825                 *pDst++ = ConvertIA16ToR4G4B4A4(pPal[b^1]); // Remember palette is in different endian order!
826
827                 dwByteOffset++;
828             }
829         }
830     }
831
832     pTexture->EndUpdate(&dInfo);
833     pTexture->SetOthersVariables();
834 }
835
836
837 void ConvertYUV_16(CTexture *pTexture, const TxtrInfo &tinfo)
838 {
839     DrawInfo dInfo;
840     if (!pTexture->StartUpdate(&dInfo))
841         return;
842
843     uint32 x, y;
844     uint32 nFiddle;
845
846     if( options.bUseFullTMEM )
847     {
848         Tile &tile = gRDP.tiles[tinfo.tileNo];
849
850         uint16 * pSrc;
851         if( tinfo.tileNo >= 0 )
852             pSrc = (uint16*)&g_Tmem.g_Tmem64bit[tile.dwTMem];
853         else
854             pSrc = (uint16*)(tinfo.pPhysicalAddress);
855
856         uint8 * pByteSrc = (uint8 *)pSrc;
857         for (y = 0; y < tinfo.HeightToLoad; y++)
858         {
859             nFiddle = ( y&1 )? 0x4 : 0;
860             int dwWordOffset = tinfo.tileNo>=0? tile.dwLine*8*y : ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad * 2);
861             uint16 * wDst = (uint16 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);
862
863             for (x = 0; x < tinfo.WidthToLoad/2; x++)
864             {
865                 int y0 = *(uint8*)&pByteSrc[(dwWordOffset+1)^nFiddle];
866                 int y1 = *(uint8*)&pByteSrc[(dwWordOffset+3)^nFiddle];
867                 int u0 = *(uint8*)&pByteSrc[(dwWordOffset  )^nFiddle];
868                 int v0 = *(uint8*)&pByteSrc[(dwWordOffset+2)^nFiddle];
869
870                 wDst[x*2+0] = ConvertYUV16ToR4G4B4(y0,u0,v0);
871                 wDst[x*2+1] = ConvertYUV16ToR4G4B4(y1,u0,v0);
872
873                 dwWordOffset += 4;
874             }
875         }
876     }
877     else
878     {
879         // Copy of the base pointer
880         uint16 * pSrc = (uint16*)(tinfo.pPhysicalAddress);
881         uint8 * pByteSrc = (uint8 *)pSrc;
882
883
884         if (tinfo.bSwapped)
885         {
886             for (y = 0; y < tinfo.HeightToLoad; y++)
887             {
888                 if ((y%2) == 0)
889                     nFiddle = 0x2;
890                 else
891                     nFiddle = 0x2 | 0x4;
892
893                 // dwDst points to start of destination row
894                 uint16 * wDst = (uint16 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);
895
896                 // DWordOffset points to the current dword we're looking at
897                 // (process 2 pixels at a time). May be a problem if we don't start on even pixel
898                 uint32 dwWordOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad * 2);
899
900                 for (x = 0; x < tinfo.WidthToLoad/2; x++)
901                 {
902                     uint32 y0 = *(uint8*)&pByteSrc[(dwWordOffset+1)^nFiddle];
903                     uint32 y1 = *(uint8*)&pByteSrc[(dwWordOffset+3)^nFiddle];
904                     uint32 u0 = *(uint8*)&pByteSrc[(dwWordOffset  )^nFiddle];
905                     uint32 v0 = *(uint8*)&pByteSrc[(dwWordOffset+2)^nFiddle];
906
907                     wDst[x*2+0] = ConvertYUV16ToR4G4B4(y0,u0,v0);
908                     wDst[x*2+1] = ConvertYUV16ToR4G4B4(y1,u0,v0);
909
910                     dwWordOffset += 4;
911                 }
912             }
913         }
914         else
915         {
916             for (y = 0; y < tinfo.HeightToLoad; y++)
917             {
918                 // dwDst points to start of destination row
919                 uint16 * wDst = (uint16 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);
920
921                 // DWordOffset points to the current dword we're looking at
922                 // (process 2 pixels at a time). May be a problem if we don't start on even pixel
923                 uint32 dwWordOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad * 2);
924
925                 for (x = 0; x < tinfo.WidthToLoad/2; x++)
926                 {
927                     uint32 y0 = *(uint8*)&pByteSrc[(dwWordOffset+1)^3];
928                     uint32 y1 = *(uint8*)&pByteSrc[(dwWordOffset+3)^3];
929                     uint32 u0 = *(uint8*)&pByteSrc[(dwWordOffset  )^3];
930                     uint32 v0 = *(uint8*)&pByteSrc[(dwWordOffset+2)^3];
931
932                     wDst[x*2+0] = ConvertYUV16ToR4G4B4(y0,u0,v0);
933                     wDst[x*2+1] = ConvertYUV16ToR4G4B4(y1,u0,v0);
934
935                     dwWordOffset += 4;
936                 }
937             }
938         }
939     }
940
941     pTexture->EndUpdate(&dInfo);
942     pTexture->SetOthersVariables();
943 }
944
945 uint16 ConvertYUV16ToR4G4B4(int Y, int U, int V)
946 {
947     uint32 A=1;
948     uint32 R1 = Y + g_convk0 * V;
949     uint32 G1 = Y + g_convk1 * U + g_convk2 * V;
950     uint32 B1 = Y + g_convk3 * U;
951     uint32 R = (R1 - g_convk4) * g_convk5 + R1;
952     uint32 G = (G1 - g_convk4) * g_convk5 + G1;
953     uint32 B = (B1 - g_convk4) * g_convk5 + B1;
954     return (uint16)R4G4B4A4_MAKE((R>>4), (G>>4), (B>>4), 0xF*A);
955 }
956
957
958 // Used by Starfox intro
959 void Convert4b_16(CTexture *pTexture, const TxtrInfo &tinfo)
960 {
961     DrawInfo dInfo;
962
963     if (!pTexture->StartUpdate(&dInfo)) 
964         return;
965
966     uint16 * pPal = (uint16 *)tinfo.PalAddress;
967     bool bIgnoreAlpha = (tinfo.TLutFmt==TLUT_FMT_UNKNOWN);
968     if( tinfo.Format <= TXT_FMT_CI ) bIgnoreAlpha = (tinfo.TLutFmt==TLUT_FMT_NONE);
969
970     Tile &tile = gRDP.tiles[tinfo.tileNo];
971
972     uint8 *pByteSrc = tinfo.tileNo >= 0 ? (uint8*)&g_Tmem.g_Tmem64bit[tile.dwTMem] : (uint8*)(tinfo.pPhysicalAddress);
973
974     for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
975     {
976         uint16 * pDst = (uint16 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
977
978         uint32 nFiddle;
979         if( tinfo.tileNo < 0 )  
980         {
981             if (tinfo.bSwapped)
982             {
983                 if ((y%2) == 0)
984                     nFiddle = 0x3;
985                 else
986                     nFiddle = 0x7;
987             }
988             else
989             {
990                 nFiddle = 3;
991             }
992         }
993         else
994         {
995             nFiddle = ( y&1 )? 0x4 : 0;
996         }
997
998         int idx = tinfo.tileNo>=0 ? tile.dwLine*8*y : ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);
999
1000         for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2, idx++)
1001         {
1002             uint8 b = pByteSrc[idx^nFiddle];
1003             uint8 bhi = (b&0xf0)>>4;
1004             uint8 blo = (b&0x0f);
1005
1006             if( gRDP.otherMode.text_tlut>=2 || ( tinfo.Format != TXT_FMT_IA && tinfo.Format != TXT_FMT_I) )
1007             {
1008                 if( tinfo.TLutFmt == TLUT_FMT_IA16 )
1009                 {
1010                     if( tinfo.tileNo>=0 )
1011                     {
1012                         pDst[0] = ConvertIA16ToR4G4B4A4(g_Tmem.g_Tmem16bit[0x400+tinfo.Palette*0x40+(bhi<<2)]);
1013                         pDst[1] = ConvertIA16ToR4G4B4A4(g_Tmem.g_Tmem16bit[0x400+tinfo.Palette*0x40+(blo<<2)]);
1014                     }
1015                     else
1016                     {
1017                         pDst[0] = ConvertIA16ToR4G4B4A4(pPal[bhi^1]);
1018                         pDst[1] = ConvertIA16ToR4G4B4A4(pPal[blo^1]);
1019                     }
1020                 }
1021                 else
1022                 {
1023                     if( tinfo.tileNo>=0 )
1024                     {
1025                         pDst[0] = Convert555ToR4G4B4A4(g_Tmem.g_Tmem16bit[0x400+tinfo.Palette*0x40+(bhi<<2)]);
1026                         pDst[1] = Convert555ToR4G4B4A4(g_Tmem.g_Tmem16bit[0x400+tinfo.Palette*0x40+(blo<<2)]);
1027                     }
1028                     else
1029                     {
1030                         pDst[0] = Convert555ToR4G4B4A4(pPal[bhi^1]);
1031                         pDst[1] = Convert555ToR4G4B4A4(pPal[blo^1]);
1032                     }
1033                 }
1034             }
1035             else if( tinfo.Format == TXT_FMT_IA )
1036             {
1037                 pDst[0] = ConvertIA4ToR4G4B4A4(b>>4);
1038                 pDst[1] = ConvertIA4ToR4G4B4A4(b&0xF);
1039             }
1040             else //if( tinfo.Format == TXT_FMT_I )
1041             {
1042                 pDst[0] = ConvertI4ToR4G4B4A4(b>>4);
1043                 pDst[1] = ConvertI4ToR4G4B4A4(b&0xF);
1044             }
1045
1046             if( bIgnoreAlpha )
1047             {
1048                 pDst[0] |= 0xF000;
1049                 pDst[1] |= 0xF000;
1050             }
1051             pDst+=2;
1052         }
1053     }
1054
1055     pTexture->EndUpdate(&dInfo);
1056     pTexture->SetOthersVariables();
1057 }
1058
1059 void Convert8b_16(CTexture *pTexture, const TxtrInfo &tinfo)
1060 {
1061     DrawInfo dInfo;
1062     if (!pTexture->StartUpdate(&dInfo)) 
1063         return;
1064
1065
1066     uint16 * pPal = (uint16 *)tinfo.PalAddress;
1067     bool bIgnoreAlpha = (tinfo.TLutFmt==TLUT_FMT_UNKNOWN);
1068     if( tinfo.Format <= TXT_FMT_CI ) bIgnoreAlpha = (tinfo.TLutFmt==TLUT_FMT_NONE);
1069
1070     Tile &tile = gRDP.tiles[tinfo.tileNo];
1071
1072     uint8 *pByteSrc;
1073     if( tinfo.tileNo >= 0 )
1074         pByteSrc = (uint8*)&g_Tmem.g_Tmem64bit[tile.dwTMem];
1075     else
1076         pByteSrc = (uint8*)(tinfo.pPhysicalAddress);
1077
1078
1079     for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
1080     {
1081         uint16 * pDst = (uint16 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
1082
1083         uint32 nFiddle;
1084         if( tinfo.tileNo < 0 )  
1085         {
1086             if (tinfo.bSwapped)
1087             {
1088                 if ((y%2) == 0)
1089                     nFiddle = 0x3;
1090                 else
1091                     nFiddle = 0x7;
1092             }
1093             else
1094             {
1095                 nFiddle = 3;
1096             }
1097         }
1098         else
1099         {
1100             nFiddle = ( y&1 )? 0x4 : 0;
1101         }
1102
1103         int idx = tinfo.tileNo>=0? tile.dwLine*8*y : ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;
1104
1105         for (uint32 x = 0; x < tinfo.WidthToLoad; x++, idx++)
1106         {
1107             uint8 b = pByteSrc[idx^nFiddle];
1108
1109             if( gRDP.otherMode.text_tlut>=2 || ( tinfo.Format != TXT_FMT_IA && tinfo.Format != TXT_FMT_I) )
1110             {
1111                 if( tinfo.TLutFmt == TLUT_FMT_IA16 )
1112                 {
1113                     if( tinfo.tileNo>=0 )
1114                         *pDst = ConvertIA16ToR4G4B4A4(g_Tmem.g_Tmem16bit[0x400+(b<<2)]);
1115                     else
1116                         *pDst = ConvertIA16ToR4G4B4A4(pPal[b^1]);
1117                 }
1118                 else
1119                 {
1120                     if( tinfo.tileNo>=0 )
1121                         *pDst = Convert555ToR4G4B4A4(g_Tmem.g_Tmem16bit[0x400+(b<<2)]);
1122                     else
1123                         *pDst = Convert555ToR4G4B4A4(pPal[b^1]);
1124                 }
1125             }
1126             else if( tinfo.Format == TXT_FMT_IA )
1127             {
1128                 *pDst = R4G4B4A4_MAKE( ((b&0xf0)>>4),((b&0xf0)>>4),((b&0xf0)>>4),(b&0x0f));
1129             }
1130             else //if( tinfo.Format == TXT_FMT_I )
1131             {
1132                 *pDst = R4G4B4A4_MAKE(b>>4, b>>4, b>>4, b>>4);
1133             }
1134
1135             if( bIgnoreAlpha )
1136             {
1137                 *pDst |= 0xFF000000;
1138             }
1139             pDst++;
1140         }
1141     }
1142
1143     pTexture->EndUpdate(&dInfo);
1144     pTexture->SetOthersVariables();
1145 }
1146
1147
1148 void Convert16b_16(CTexture *pTexture, const TxtrInfo &tinfo)
1149 {
1150     DrawInfo dInfo;
1151     if (!pTexture->StartUpdate(&dInfo)) 
1152         return;
1153
1154     Tile &tile = gRDP.tiles[tinfo.tileNo];
1155
1156     uint16 *pWordSrc;
1157     if( tinfo.tileNo >= 0 )
1158         pWordSrc = (uint16*)&g_Tmem.g_Tmem64bit[tile.dwTMem];
1159     else
1160         pWordSrc = (uint16*)(tinfo.pPhysicalAddress);
1161
1162
1163     for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
1164     {
1165         uint16 * dwDst = (uint16 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);
1166
1167         uint32 nFiddle;
1168         if( tinfo.tileNo < 0 )  
1169         {
1170             if (tinfo.bSwapped)
1171             {
1172                 if ((y&1) == 0)
1173                     nFiddle = 0x1;
1174                 else
1175                     nFiddle = 0x3;
1176             }
1177             else
1178             {
1179                 nFiddle = 0x1;
1180             }
1181         }
1182         else
1183         {
1184             nFiddle = ( y&1 )? 0x2 : 0;
1185         }
1186
1187         int idx = tinfo.tileNo>=0? tile.dwLine*4*y : (((y+tinfo.TopToLoad) * tinfo.Pitch)>>1) + tinfo.LeftToLoad;
1188
1189         for (uint32 x = 0; x < tinfo.WidthToLoad; x++, idx++)
1190         {
1191             uint16 w = pWordSrc[idx^nFiddle];
1192             uint16 w2 = tinfo.tileNo>=0? ((w>>8)|(w<<8)) : w;
1193
1194             if( tinfo.Format == TXT_FMT_RGBA )
1195             {
1196                 dwDst[x] = Convert555ToR4G4B4A4(w2);
1197             }
1198             else if( tinfo.Format == TXT_FMT_YUV )
1199             {
1200             }
1201             else if( tinfo.Format >= TXT_FMT_IA )
1202             {
1203                 uint8 i = (uint8)(w2 >> 12);
1204                 uint8 a = (uint8)(w2 & 0xFF);
1205                 dwDst[x] = R4G4B4A4_MAKE(i, i, i, (a>>4));
1206             }
1207         }
1208     }
1209
1210     pTexture->EndUpdate(&dInfo);
1211     pTexture->SetOthersVariables();
1212 }
1213