Rice GLES2 (from mupen64plus-ae) plugin. Compile but doesn't works well on the OpenPa...
[mupen64plus-pandora.git] / source / gles2rice / src / ConvertImage.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 ConvertFunction     gConvertFunctions_FullTMEM[ 8 ][ 4 ] = 
25 {
26     // 4bpp             8bpp            16bpp               32bpp
27     {  Convert4b,       Convert8b,      Convert16b,         ConvertRGBA32 },        // RGBA
28     {  NULL,            NULL,           ConvertYUV,         NULL },                 // YUV
29     {  Convert4b,       Convert8b,      NULL,               NULL },                 // CI
30     {  Convert4b,       Convert8b,      Convert16b,         NULL },                 // IA
31     {  Convert4b,       Convert8b,      Convert16b,         NULL },                 // I
32     {  NULL,            NULL,           NULL,               NULL },                 // ?
33     {  NULL,            NULL,           NULL,               NULL },                 // ?
34     {  NULL,            NULL,           NULL,               NULL }                  // ?
35 };
36 ConvertFunction     gConvertFunctions[ 8 ][ 4 ] = 
37 {
38     // 4bpp             8bpp            16bpp               32bpp
39     {  ConvertCI4,      ConvertCI8,     ConvertRGBA16,      ConvertRGBA32 },        // RGBA
40     {  NULL,            NULL,           ConvertYUV,         NULL },                 // YUV
41     {  ConvertCI4,      ConvertCI8,     NULL,               NULL },                 // CI
42     {  ConvertIA4,      ConvertIA8,     ConvertIA16,        NULL },                 // IA
43     {  ConvertI4,       ConvertI8,      ConvertIA16,        NULL },                 // I
44     {  NULL,            NULL,           NULL,               NULL },                 // ?
45     {  NULL,            NULL,           NULL,               NULL },                 // ?
46     {  NULL,            NULL,           NULL,               NULL }                  // ?
47 };
48
49 ConvertFunction     gConvertTlutFunctions[ 8 ][ 4 ] = 
50 {
51     // 4bpp             8bpp            16bpp               32bpp
52     {  ConvertCI4,      ConvertCI8,     ConvertRGBA16,      ConvertRGBA32 },        // RGBA
53     {  NULL,            NULL,           ConvertYUV,         NULL },                 // YUV
54     {  ConvertCI4,      ConvertCI8,     NULL,               NULL },                 // CI
55     {  ConvertCI4,      ConvertCI8,     ConvertIA16,        NULL },                 // IA
56     {  ConvertCI4,      ConvertCI8,     ConvertIA16,        NULL },                 // I
57     {  NULL,            NULL,           NULL,               NULL },                 // ?
58     {  NULL,            NULL,           NULL,               NULL },                 // ?
59     {  NULL,            NULL,           NULL,               NULL }                  // ?
60 };
61
62 extern bool conkerSwapHack;
63
64 void ConvertRGBA16(CTexture *pTexture, const TxtrInfo &tinfo)
65 {
66     DrawInfo dInfo;
67
68     // Copy of the base pointer
69     uint16 * pSrc = (uint16*)(tinfo.pPhysicalAddress);
70
71     uint8 * pByteSrc = (uint8 *)pSrc;
72     if (!pTexture->StartUpdate(&dInfo))
73         return;
74
75     uint32 nFiddle;
76
77     if (tinfo.bSwapped)
78     {
79         for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
80         {
81             if ((y&1) == 0)
82                 nFiddle = 0x2;
83             else
84                 nFiddle = 0x2 | 0x4;
85
86             // dwDst points to start of destination row
87             uint32 * dwDst = (uint32 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);
88
89             // DWordOffset points to the current dword we're looking at
90             // (process 2 pixels at a time). May be a problem if we don't start on even pixel
91             uint32 dwWordOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad * 2);
92
93             for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
94             {
95                 uint16 w = *(uint16 *)&pByteSrc[dwWordOffset ^ nFiddle];
96
97                 dwDst[x] = Convert555ToRGBA(w);
98                 
99                 // Increment word offset to point to the next two pixels
100                 dwWordOffset += 2;
101             }
102         }
103     }
104     else
105     {
106         for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
107         {
108             // dwDst points to start of destination row
109             uint32 * dwDst = (uint32 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);
110
111             // DWordOffset points to the current dword we're looking at
112             // (process 2 pixels at a time). May be a problem if we don't start on even pixel
113             uint32 dwWordOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad * 2);
114
115             for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
116             {
117                 uint16 w = *(uint16 *)&pByteSrc[dwWordOffset ^ 0x2];
118
119                 dwDst[x] = Convert555ToRGBA(w);
120                 
121                 // Increment word offset to point to the next two pixels
122                 dwWordOffset += 2;
123             }
124         }
125     }
126
127     pTexture->EndUpdate(&dInfo);
128     pTexture->SetOthersVariables();
129 }
130
131 void ConvertRGBA32(CTexture *pTexture, const TxtrInfo &tinfo)
132 {
133     DrawInfo dInfo;
134     if (!pTexture->StartUpdate(&dInfo))
135         return;
136
137     uint32 * pSrc = (uint32*)(tinfo.pPhysicalAddress);
138
139     if( options.bUseFullTMEM )
140     {
141         Tile &tile = gRDP.tiles[tinfo.tileNo];
142
143         uint32 *pWordSrc;
144         if( tinfo.tileNo >= 0 )
145         {
146             pWordSrc = (uint32*)&g_Tmem.g_Tmem64bit[tile.dwTMem];
147
148             for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
149             {
150                 uint32 * dwDst = (uint32 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);
151
152                 uint32 nFiddle = ( y&1 )? 0x2 : 0;
153                 int idx = tile.dwLine*4*y;
154
155                 for (uint32 x = 0; x < tinfo.WidthToLoad; x++, idx++)
156                 {
157                     uint32 w = pWordSrc[idx^nFiddle];
158                     uint8* psw = (uint8*)&w;
159                     uint8* pdw = (uint8*)&dwDst[x];
160                     pdw[0] = psw[2];    // Blue
161                     pdw[1] = psw[1];    // Green
162                     pdw[2] = psw[0];    // Red
163                     pdw[3] = psw[3];    // Alpha
164                 }
165             }
166         }
167     }
168     else
169     {
170         if (tinfo.bSwapped)
171         {
172             for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
173             {
174                 if ((y%2) == 0)
175                 {
176                     uint8 *pDst = (uint8 *)dInfo.lpSurface + y * dInfo.lPitch;
177                     uint8 *pS = (uint8 *)pSrc + (y+tinfo.TopToLoad) * tinfo.Pitch + (tinfo.LeftToLoad*4);
178
179                     for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
180                     {
181                         pDst[0] = pS[1];    // Blue
182                         pDst[1] = pS[2];    // Green
183                         pDst[2] = pS[3];    // Red
184                         pDst[3] = pS[0];    // Alpha
185                         pS+=4;
186                         pDst+=4;
187                     }
188                 }
189                 else
190                 {
191                     uint32 *pDst = (uint32 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
192                     uint8 *pS = (uint8 *)pSrc;
193                     int n;
194
195                     n = (y+tinfo.TopToLoad) * tinfo.Pitch + (tinfo.LeftToLoad*4);
196                     for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
197                     {
198                         *pDst++ = COLOR_RGBA(pS[(n+3)^0x8],
199                             pS[(n+2)^0x8],
200                             pS[(n+1)^0x8],
201                             pS[(n+0)^0x8]);
202
203                         n += 4;
204                     }
205                 }
206             }
207         }
208         else
209         {
210             for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
211             {
212                 uint8 *pDst = (uint8 *)dInfo.lpSurface + y * dInfo.lPitch;
213                 uint8 *pS = (uint8 *)pSrc + (y+tinfo.TopToLoad) * tinfo.Pitch + (tinfo.LeftToLoad*4);
214
215                 for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
216                 {
217                     pDst[0] = pS[1];    // Blue
218                     pDst[1] = pS[2];    // Green
219                     pDst[2] = pS[3];    // Red
220                     pDst[3] = pS[0];    // Alpha
221                     pS+=4;
222                     pDst+=4;
223                 }
224             }
225         }
226     }
227
228     pTexture->EndUpdate(&dInfo);
229     pTexture->SetOthersVariables();
230 }
231
232 // E.g. Dear Mario text
233 // Copy, Score etc
234 void ConvertIA4(CTexture *pTexture, const TxtrInfo &tinfo)
235 {
236     DrawInfo dInfo;
237     uint32 nFiddle;
238
239     uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);
240
241 #ifdef DEBUGGER
242     if (((long long)pSrc) % 4) TRACE0("Texture src addr is not aligned to 4 bytes, check me");
243 #endif
244
245     if (!pTexture->StartUpdate(&dInfo))
246         return;
247
248     if (tinfo.bSwapped)
249     {
250         for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
251         {
252             uint8 *pDst = (uint8 *)dInfo.lpSurface + y * dInfo.lPitch;
253
254             // For odd lines, swap words too
255             if ((y%2) == 0)
256                 nFiddle = 0x3;
257             else
258                 nFiddle = 0x7;
259
260
261             // This may not work if X is not even?
262             uint32 dwByteOffset = (y+tinfo.TopToLoad) * tinfo.Pitch + (tinfo.LeftToLoad/2);
263
264             if (tinfo.WidthToLoad == 1)
265             {
266                 // corner case
267                 uint8 b = pSrc[dwByteOffset ^ nFiddle];
268                 *pDst++ = ThreeToEight[(b & 0xE0) >> 5];
269                 *pDst++ = ThreeToEight[(b & 0xE0) >> 5];
270                 *pDst++ = ThreeToEight[(b & 0xE0) >> 5];
271                 *pDst++ = OneToEight[(b & 0x10) >> 4];  
272             }
273             else for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)
274             {
275                 // Do two pixels at a time
276                 uint8 b = pSrc[dwByteOffset ^ nFiddle];
277
278                 // Even
279                 *pDst++ = ThreeToEight[(b & 0xE0) >> 5];
280                 *pDst++ = ThreeToEight[(b & 0xE0) >> 5];
281                 *pDst++ = ThreeToEight[(b & 0xE0) >> 5];
282                 *pDst++ = OneToEight[(b & 0x10) >> 4];  
283                 // Odd
284                 *pDst++ = ThreeToEight[(b & 0x0E) >> 1];
285                 *pDst++ = ThreeToEight[(b & 0x0E) >> 1];
286                 *pDst++ = ThreeToEight[(b & 0x0E) >> 1];
287                 *pDst++ = OneToEight[(b & 0x01)     ];
288
289                 dwByteOffset++;
290             }
291         }
292     }
293     else
294     {
295         for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
296         {
297             uint8 *pDst = (uint8 *)dInfo.lpSurface + (y * dInfo.lPitch);
298
299             // This may not work if X is not even?
300             uint32 dwByteOffset = (y+tinfo.TopToLoad) * tinfo.Pitch + (tinfo.LeftToLoad/2);
301
302             if (tinfo.WidthToLoad == 1)
303             {
304                 // corner case
305                 uint8 b = pSrc[dwByteOffset ^ 0x3];
306                 *pDst++ = ThreeToEight[(b & 0xE0) >> 5];
307                 *pDst++ = ThreeToEight[(b & 0xE0) >> 5];
308                 *pDst++ = ThreeToEight[(b & 0xE0) >> 5];
309                 *pDst++ = OneToEight[(b & 0x10) >> 4];  
310             }
311             else for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)
312             {
313                 // Do two pixels at a time
314                 uint8 b = pSrc[dwByteOffset ^ 0x3];
315
316                 // Even
317                 *pDst++ = ThreeToEight[(b & 0xE0) >> 5];
318                 *pDst++ = ThreeToEight[(b & 0xE0) >> 5];
319                 *pDst++ = ThreeToEight[(b & 0xE0) >> 5];
320                 *pDst++ = OneToEight[(b & 0x10) >> 4];  
321                 // Odd
322                 *pDst++ = ThreeToEight[(b & 0x0E) >> 1];
323                 *pDst++ = ThreeToEight[(b & 0x0E) >> 1];
324                 *pDst++ = ThreeToEight[(b & 0x0E) >> 1];
325                 *pDst++ = OneToEight[(b & 0x01)     ];
326
327                 dwByteOffset++;
328             }
329         }
330     }
331
332     pTexture->EndUpdate(&dInfo);
333     pTexture->SetOthersVariables();
334
335 }
336
337 // E.g Mario's head textures
338 void ConvertIA8(CTexture *pTexture, const TxtrInfo &tinfo)
339 {
340     DrawInfo dInfo;
341     uint32 nFiddle;
342
343     uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);
344
345 #ifdef DEBUGGER
346     if (((long long)pSrc) % 4) TRACE0("Texture src addr is not aligned to 4 bytes, check me");
347 #endif
348
349     if (!pTexture->StartUpdate(&dInfo))
350         return;
351
352     if (tinfo.bSwapped)
353     {
354         for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
355         {
356             // For odd lines, swap words too
357             if ((y%2) == 0)
358                 nFiddle = 0x3;
359             else
360                 nFiddle = 0x7;
361
362             uint8 *pDst = (uint8 *)dInfo.lpSurface + y * dInfo.lPitch;
363             // Points to current byte
364             uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;
365
366             for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
367             {
368                 uint8 b = pSrc[dwByteOffset ^ nFiddle];
369                 uint8 I = FourToEight[(b & 0xf0)>>4];
370
371                 *pDst++ = I;
372                 *pDst++ = I;
373                 *pDst++ = I;
374                 *pDst++ = FourToEight[(b & 0x0f)   ];
375
376                 dwByteOffset++;
377             }
378         }
379     }
380     else
381     {
382         register const uint8* FourToEightArray = &FourToEight[0];
383         for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
384         {
385             uint8 *pDst = (uint8 *)dInfo.lpSurface + y * dInfo.lPitch;
386
387             // Points to current byte
388             uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;
389
390             for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
391             {
392                 register uint8 b = pSrc[(dwByteOffset++) ^ 0x3];
393                 uint8 I = *(FourToEightArray+(b>>4));
394
395                 *pDst++ = I;
396                 *pDst++ = I;
397                 *pDst++ = I;
398                 *pDst++ = *(FourToEightArray+(b&0xF));
399             }
400         }
401     }   
402     
403     pTexture->EndUpdate(&dInfo);
404     pTexture->SetOthersVariables();
405
406 }
407
408 // E.g. camera's clouds, shadows
409 void ConvertIA16(CTexture *pTexture, const TxtrInfo &tinfo)
410 {
411     DrawInfo dInfo;
412     uint32 nFiddle;
413
414     uint16 * pSrc = (uint16*)(tinfo.pPhysicalAddress);
415     uint8 * pByteSrc = (uint8 *)pSrc;
416
417     if (!pTexture->StartUpdate(&dInfo))
418         return;
419
420     if (tinfo.bSwapped)
421     {
422         for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
423         {
424             uint8 *pDst = (uint8 *)dInfo.lpSurface + y * dInfo.lPitch;
425
426             if ((y%2) == 0)
427                 nFiddle = 0x2;
428             else
429                 nFiddle = 0x4 | 0x2;
430
431             // Points to current word
432             uint32 dwWordOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad * 2);
433
434             for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
435             {
436                 uint16 w = *(uint16 *)&pByteSrc[dwWordOffset^nFiddle];
437
438                 *pDst++ = (uint8)(w >> 8);
439                 *pDst++ = (uint8)(w >> 8);
440                 *pDst++ = (uint8)(w >> 8);
441                 *pDst++ = (uint8)(w & 0xFF);
442
443                 dwWordOffset += 2;
444             }
445         }
446     }
447     else
448     {
449         for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
450         {
451             uint8 *pDst = (uint8 *)dInfo.lpSurface + y * dInfo.lPitch;
452
453             // Points to current word
454             uint32 dwWordOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad * 2);
455
456             for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
457             {
458                 uint16 w = *(uint16 *)&pByteSrc[dwWordOffset^0x2];
459
460                 *pDst++ = (uint8)(w >> 8);
461                 *pDst++ = (uint8)(w >> 8);
462                 *pDst++ = (uint8)(w >> 8);
463                 *pDst++ = (uint8)(w & 0xFF);
464
465                 dwWordOffset += 2;
466             }
467         }       
468     }
469
470
471     pTexture->EndUpdate(&dInfo);
472     pTexture->SetOthersVariables();
473 }
474
475
476
477 // Used by MarioKart
478 void ConvertI4(CTexture *pTexture, const TxtrInfo &tinfo)
479 {
480     DrawInfo dInfo;
481     uint32 nFiddle;
482
483     uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);
484
485 #ifdef DEBUGGER
486     if (((long long) pSrc) % 4) TRACE0("Texture src addr is not aligned to 4 bytes, check me");
487 #endif
488
489     if (!pTexture->StartUpdate(&dInfo))
490         return;
491
492     if (tinfo.bSwapped)
493     {
494         for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
495         {
496             uint8 *pDst = (uint8 *)dInfo.lpSurface + y * dInfo.lPitch;
497
498             // Might not work with non-even starting X
499             uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);
500
501             // For odd lines, swap words too
502             if( !conkerSwapHack || (y&4) == 0 )
503             {
504                 if ((y%2) == 0)
505                     nFiddle = 0x3;
506                 else
507                     nFiddle = 0x7;
508             }
509             else
510             {
511                 if ((y%2) == 1)
512                     nFiddle = 0x3;
513                 else
514                     nFiddle = 0x7;
515             }
516
517             if (tinfo.WidthToLoad == 1)
518             {
519                 // corner case
520                 uint8 b = pSrc[dwByteOffset ^ nFiddle];
521                 *pDst++ = FourToEight[(b & 0xF0)>>4];
522                 *pDst++ = FourToEight[(b & 0xF0)>>4];
523                 *pDst++ = FourToEight[(b & 0xF0)>>4];
524                 *pDst++ = FourToEight[(b & 0xF0)>>4];   
525             }
526             else for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)
527             {
528                 // two pixels at a time
529                 uint8 b = pSrc[dwByteOffset ^ nFiddle];
530
531                 // Even
532                 *pDst++ = FourToEight[(b & 0xF0)>>4];   // Other implementations seem to or in (b&0xF0)>>4
533                 *pDst++ = FourToEight[(b & 0xF0)>>4]; // why?
534                 *pDst++ = FourToEight[(b & 0xF0)>>4];
535                 *pDst++ = FourToEight[(b & 0xF0)>>4];   
536                 // Odd
537                 *pDst++ = FourToEight[(b & 0x0F)];
538                 *pDst++ = FourToEight[(b & 0x0F)];
539                 *pDst++ = FourToEight[(b & 0x0F)];
540                 *pDst++ = FourToEight[(b & 0x0F)];
541
542                 dwByteOffset++;
543             }
544         }
545
546         conkerSwapHack = false;
547     }
548     else
549     {
550         for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
551         {
552             uint8 *pDst = (uint8 *)dInfo.lpSurface + y * dInfo.lPitch;
553
554             // Might not work with non-even starting X
555             uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);
556
557             if (tinfo.WidthToLoad == 1)
558             {
559                 // corner case
560                 uint8 b = pSrc[dwByteOffset ^ 0x3];
561                 *pDst++ = FourToEight[(b & 0xF0)>>4];
562                 *pDst++ = FourToEight[(b & 0xF0)>>4];
563                 *pDst++ = FourToEight[(b & 0xF0)>>4];
564                 *pDst++ = FourToEight[(b & 0xF0)>>4];   
565             }
566             else for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)
567             {
568                 // two pixels at a time
569                 uint8 b = pSrc[dwByteOffset ^ 0x3];
570
571                 // Even
572                 *pDst++ = FourToEight[(b & 0xF0)>>4];   // Other implementations seem to or in (b&0xF0)>>4
573                 *pDst++ = FourToEight[(b & 0xF0)>>4]; // why?
574                 *pDst++ = FourToEight[(b & 0xF0)>>4];
575                 *pDst++ = FourToEight[(b & 0xF0)>>4];   
576                 // Odd
577                 *pDst++ = FourToEight[(b & 0x0F)];
578                 *pDst++ = FourToEight[(b & 0x0F)];
579                 *pDst++ = FourToEight[(b & 0x0F)];
580                 *pDst++ = FourToEight[(b & 0x0F)];
581
582                 dwByteOffset++;
583             }
584         }
585     }
586
587     pTexture->EndUpdate(&dInfo);
588     pTexture->SetOthersVariables();
589 }
590
591 // Used by MarioKart
592 void ConvertI8(CTexture *pTexture, const TxtrInfo &tinfo)
593 {
594     DrawInfo dInfo;
595     uint32 nFiddle;
596
597     long long pSrc = (long long) tinfo.pPhysicalAddress;
598     if (!pTexture->StartUpdate(&dInfo))
599         return;
600
601     if (tinfo.bSwapped)
602     {
603         for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
604         {
605             if ((y%2) == 0)
606                 nFiddle = 0x3;
607             else
608                 nFiddle = 0x7;
609
610             uint8 *pDst = (uint8 *)dInfo.lpSurface + y * dInfo.lPitch;
611
612             uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;
613
614             for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
615             {
616                 uint8 b = *(uint8*)((pSrc+dwByteOffset)^nFiddle);
617
618                 *pDst++ = b;
619                 *pDst++ = b;
620                 *pDst++ = b;
621                 *pDst++ = b;        // Alpha not 255?
622
623                 dwByteOffset++;
624             }
625         }
626     }
627     else
628     {
629         for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
630         {
631             uint8 *pDst = (uint8 *)dInfo.lpSurface + y * dInfo.lPitch;
632
633             uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;
634
635             for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
636             {
637                 uint8 b = *(uint8*)((pSrc+dwByteOffset)^0x3);
638
639                 *pDst++ = b;
640                 *pDst++ = b;
641                 *pDst++ = b;
642                 *pDst++ = b;        // Alpha not 255?
643
644                 dwByteOffset++;
645             }
646         }
647     }
648
649     pTexture->EndUpdate(&dInfo);
650     pTexture->SetOthersVariables();
651
652 }
653
654 //*****************************************************************************
655 // Convert CI4 images. We need to switch on the palette type
656 //*****************************************************************************
657 void ConvertCI4( CTexture * p_texture, const TxtrInfo & tinfo )
658 {
659     if ( tinfo.TLutFmt == TLUT_FMT_RGBA16 )
660     {
661         ConvertCI4_RGBA16( p_texture, tinfo );  
662     }
663     else if ( tinfo.TLutFmt == TLUT_FMT_IA16 )
664     {
665         ConvertCI4_IA16( p_texture, tinfo );                    
666     }
667 }
668
669 //*****************************************************************************
670 // Convert CI8 images. We need to switch on the palette type
671 //*****************************************************************************
672 void ConvertCI8( CTexture * p_texture, const TxtrInfo & tinfo )
673 {
674     if ( tinfo.TLutFmt == TLUT_FMT_RGBA16 )
675     {
676         ConvertCI8_RGBA16( p_texture, tinfo );  
677     }
678     else if ( tinfo.TLutFmt == TLUT_FMT_IA16 )
679     {
680         ConvertCI8_IA16( p_texture, tinfo );                    
681     }
682 }
683
684 // Used by Starfox intro
685 void ConvertCI4_RGBA16(CTexture *pTexture, const TxtrInfo &tinfo)
686 {
687     DrawInfo dInfo;
688     uint32 nFiddle;
689
690     uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);
691     uint16 * pPal = (uint16 *)tinfo.PalAddress;
692     bool bIgnoreAlpha = (tinfo.TLutFmt==TLUT_FMT_NONE);
693     
694     if (!pTexture->StartUpdate(&dInfo))
695         return;
696
697     if (tinfo.bSwapped)
698     {
699         for (uint32 y = 0; y <  tinfo.HeightToLoad; y++)
700         {
701             if ((y%2) == 0)
702                 nFiddle = 0x3;
703             else
704                 nFiddle = 0x7;
705
706             uint32 * pDst = (uint32 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
707
708             uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch);
709
710             if (tinfo.WidthToLoad == 1)
711             {
712                 // corner case
713                 uint8 b = pSrc[dwByteOffset ^ nFiddle];
714                 uint8 bhi = (b&0xf0)>>4;
715                 *pDst = Convert555ToRGBA(pPal[bhi^1]);    // Remember palette is in different endian order!
716                 if( bIgnoreAlpha )
717                 {
718                     *pDst |= 0xFF000000;
719                 }
720             }
721             else for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)
722             {
723                 // two at a time
724                 uint8 b = pSrc[dwByteOffset ^ nFiddle];
725
726                 uint8 bhi = (b&0xf0)>>4;
727                 uint8 blo = (b&0x0f);
728
729                 pDst[0] = Convert555ToRGBA(pPal[bhi^1]);    // Remember palette is in different endian order!
730                 pDst[1] = Convert555ToRGBA(pPal[blo^1]);    // Remember palette is in different endian order!
731
732                 if( bIgnoreAlpha )
733                 {
734                     pDst[0] |= 0xFF000000;
735                     pDst[1] |= 0xFF000000;
736                 }
737
738                 pDst+=2;
739
740                 dwByteOffset++;
741             }
742         }
743     }
744     else
745     {
746         for (uint32 y = 0; y <  tinfo.HeightToLoad; y++)
747         {
748             uint32 * pDst = (uint32 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
749
750             uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);
751
752             if (tinfo.WidthToLoad == 1)
753             {
754                 // corner case
755                 uint8 b = pSrc[dwByteOffset ^ 0x3];
756                 uint8 bhi = (b&0xf0)>>4;
757                 *pDst = Convert555ToRGBA(pPal[bhi^1]);    // Remember palette is in different endian order!
758                 if( bIgnoreAlpha )
759                 {
760                     *pDst |= 0xFF000000;
761                 }
762             }
763             else for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)
764             {
765                 // two at a time
766                 uint8 b = pSrc[dwByteOffset ^ 0x3];
767
768                 uint8 bhi = (b&0xf0)>>4;
769                 uint8 blo = (b&0x0f);
770
771                 pDst[0] = Convert555ToRGBA(pPal[bhi^1]);    // Remember palette is in different endian order!
772                 pDst[1] = Convert555ToRGBA(pPal[blo^1]);    // Remember palette is in different endian order!
773                 
774                 if( bIgnoreAlpha )
775                 {
776                     pDst[0] |= 0xFF000000;
777                     pDst[1] |= 0xFF000000;
778                 }
779
780                 pDst+=2;
781
782                 dwByteOffset++;
783             }
784         }
785     }
786     pTexture->EndUpdate(&dInfo);
787     pTexture->SetOthersVariables();
788 }
789
790 // Used by Starfox intro
791 void ConvertCI4_IA16(CTexture *pTexture, const TxtrInfo &tinfo)
792 {
793     DrawInfo dInfo;
794     uint32 nFiddle;
795
796     uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);
797
798 #ifdef DEBUGGER
799     if (((long long) pSrc) % 4) TRACE0("Texture src addr is not aligned to 4 bytes, check me");
800 #endif
801
802     uint16 * pPal = (uint16 *)tinfo.PalAddress;
803     bool bIgnoreAlpha = (tinfo.TLutFmt==TLUT_FMT_UNKNOWN);
804
805     if (!pTexture->StartUpdate(&dInfo))
806         return;
807
808     if (tinfo.bSwapped)
809     {
810         for (uint32 y = 0; y <  tinfo.HeightToLoad; y++)
811         {
812             if ((y%2) == 0)
813                 nFiddle = 0x3;
814             else
815                 nFiddle = 0x7;
816
817             uint32 * pDst = (uint32 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
818
819             uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);
820
821             if (tinfo.WidthToLoad == 1)
822             {
823                 // corner case
824                 uint8 b = pSrc[dwByteOffset ^ nFiddle];
825                 uint8 bhi = (b&0xf0)>>4;
826                 *pDst = ConvertIA16ToRGBA(pPal[bhi^1]);   // Remember palette is in different endian order!
827                 if( bIgnoreAlpha )
828                     *pDst |= 0xFF000000;
829             }
830             else for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)
831             {
832                 // two at a time
833                 uint8 b = pSrc[dwByteOffset ^ nFiddle];
834
835                 uint8 bhi = (b&0xf0)>>4;
836                 uint8 blo = (b&0x0f);
837
838                 pDst[0] = ConvertIA16ToRGBA(pPal[bhi^1]);   // Remember palette is in different endian order!
839                 pDst[1] = ConvertIA16ToRGBA(pPal[blo^1]);   // Remember palette is in different endian order!
840                 
841                 if( bIgnoreAlpha )
842                 {
843                     pDst[0] |= 0xFF000000;
844                     pDst[1] |= 0xFF000000;
845                 }
846
847                 pDst+=2;
848
849                 dwByteOffset++;
850             }
851         }
852     }
853     else
854     {
855         for (uint32 y = 0; y <  tinfo.HeightToLoad; y++)
856         {
857             uint32 * pDst = (uint32 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
858
859             uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);
860
861             if (tinfo.WidthToLoad == 1)
862             {
863                 // corner case
864                 uint8 b = pSrc[dwByteOffset ^ 0x3];
865                 uint8 bhi = (b&0xf0)>>4;
866                 *pDst = ConvertIA16ToRGBA(pPal[bhi^1]);   // Remember palette is in different endian order!
867                 if( bIgnoreAlpha )
868                     *pDst |= 0xFF000000;
869             }
870             else for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)
871             {
872                 // two pixels at a time
873                 uint8 b = pSrc[dwByteOffset ^ 0x3];
874
875                 uint8 bhi = (b&0xf0)>>4;
876                 uint8 blo = (b&0x0f);
877
878                 pDst[0] = ConvertIA16ToRGBA(pPal[bhi^1]);   // Remember palette is in different endian order!
879                 pDst[1] = ConvertIA16ToRGBA(pPal[blo^1]);   // Remember palette is in different endian order!
880                 
881                 if( bIgnoreAlpha )
882                 {
883                     pDst[0] |= 0xFF000000;
884                     pDst[1] |= 0xFF000000;
885                 }
886
887                 pDst+=2;
888
889                 dwByteOffset++;
890             }
891         }
892     }
893     pTexture->EndUpdate(&dInfo);
894     pTexture->SetOthersVariables();
895 }
896
897
898 // Used by MarioKart for Cars etc
899 void ConvertCI8_RGBA16(CTexture *pTexture, const TxtrInfo &tinfo)
900 {
901     DrawInfo dInfo;
902     uint32 nFiddle;
903
904     uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);
905
906 #ifdef DEBUGGER
907     if (((long long) pSrc) % 4) TRACE0("Texture src addr is not aligned to 4 bytes, check me");
908 #endif
909
910     uint16 * pPal = (uint16 *)tinfo.PalAddress;
911     bool bIgnoreAlpha = (tinfo.TLutFmt==TLUT_FMT_NONE);
912
913     if (!pTexture->StartUpdate(&dInfo))
914         return;
915     
916     if (tinfo.bSwapped)
917     {
918         for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
919         {
920             if ((y%2) == 0)
921                 nFiddle = 0x3;
922             else
923                 nFiddle = 0x7;
924
925             uint32 *pDst = (uint32 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
926
927             uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;
928             
929             for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
930             {
931                 uint8 b = pSrc[dwByteOffset ^ nFiddle];
932
933                 *pDst++ = Convert555ToRGBA(pPal[b^1]);  // Remember palette is in different endian order!
934                 
935                 if( bIgnoreAlpha )
936                 {
937                     *(pDst-1) |= 0xFF000000;
938                 }
939
940                 dwByteOffset++;
941             }
942         }
943     }
944     else
945     {
946         for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
947         {
948             uint32 *pDst = (uint32 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
949
950             int dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;
951             
952             for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
953             {
954                 uint8 b = pSrc[dwByteOffset ^ 0x3];
955
956                 *pDst++ = Convert555ToRGBA(pPal[b^1]);  // Remember palette is in different endian order!
957                 if( bIgnoreAlpha )
958                 {
959                     *(pDst-1) |= 0xFF000000;
960                 }
961
962                 dwByteOffset++;
963             }
964         }
965     }
966
967     pTexture->EndUpdate(&dInfo);
968     pTexture->SetOthersVariables();
969
970 }
971
972
973 // Used by MarioKart for Cars etc
974 void ConvertCI8_IA16(CTexture *pTexture, const TxtrInfo &tinfo)
975 {
976     DrawInfo dInfo;
977     uint32 nFiddle;
978
979     uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);
980
981 #ifdef DEBUGGER
982     if (((long long) pSrc) % 4) TRACE0("Texture src addr is not aligned to 4 bytes, check me");
983 #endif
984
985     uint16 * pPal = (uint16 *)tinfo.PalAddress;
986     bool bIgnoreAlpha = (tinfo.TLutFmt==TLUT_FMT_UNKNOWN);
987
988     if (!pTexture->StartUpdate(&dInfo))
989         return;
990
991     if (tinfo.bSwapped)
992     {
993         for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
994         {
995             if ((y%2) == 0)
996                 nFiddle = 0x3;
997             else
998                 nFiddle = 0x7;
999
1000             uint32 *pDst = (uint32 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
1001
1002             uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;
1003             
1004             for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
1005             {
1006                 uint8 b = pSrc[dwByteOffset ^ nFiddle];
1007
1008                 *pDst++ = ConvertIA16ToRGBA(pPal[b^1]); // Remember palette is in different endian order!
1009                 if( bIgnoreAlpha )
1010                 {
1011                     *(pDst-1) |= 0xFF000000;
1012                 }
1013
1014                 dwByteOffset++;
1015             }
1016         }
1017     }
1018     else
1019     {
1020         for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
1021         {
1022             uint32 *pDst = (uint32 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
1023
1024             uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;
1025             
1026             for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
1027             {
1028                 uint8 b = pSrc[dwByteOffset ^ 0x3];
1029
1030                 *pDst++ = ConvertIA16ToRGBA(pPal[b^1]); // Remember palette is in different endian order!
1031                 if( bIgnoreAlpha )
1032                 {
1033                     *(pDst-1) |= 0xFF000000;
1034                 }
1035
1036                 dwByteOffset++;
1037             }
1038         }
1039     }
1040
1041     pTexture->EndUpdate(&dInfo);
1042     pTexture->SetOthersVariables();
1043 }
1044
1045 void ConvertYUV(CTexture *pTexture, const TxtrInfo &tinfo)
1046 {
1047     DrawInfo dInfo;
1048     if (!pTexture->StartUpdate(&dInfo))
1049         return;
1050
1051     uint32 x, y;
1052     uint32 nFiddle;
1053
1054     if( options.bUseFullTMEM )
1055     {
1056         Tile &tile = gRDP.tiles[tinfo.tileNo];
1057
1058         uint16 * pSrc;
1059         if( tinfo.tileNo >= 0 )
1060             pSrc = (uint16*)&g_Tmem.g_Tmem64bit[tile.dwTMem];
1061         else
1062             pSrc = (uint16*)(tinfo.pPhysicalAddress);
1063
1064         uint8 * pByteSrc = (uint8 *)pSrc;
1065         for (y = 0; y < tinfo.HeightToLoad; y++)
1066         {
1067             nFiddle = ( y&1 )? 0x4 : 0;
1068             int dwWordOffset = tinfo.tileNo>=0? tile.dwLine*8*y : ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad * 2);
1069             uint32 * dwDst = (uint32 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);
1070
1071             for (x = 0; x < tinfo.WidthToLoad/2; x++)
1072             {
1073                 int y0 = *(uint8*)&pByteSrc[(dwWordOffset+1)^nFiddle];
1074                 int y1 = *(uint8*)&pByteSrc[(dwWordOffset+3)^nFiddle];
1075                 int u0 = *(uint8*)&pByteSrc[(dwWordOffset  )^nFiddle];
1076                 int v0 = *(uint8*)&pByteSrc[(dwWordOffset+2)^nFiddle];
1077
1078                 dwDst[x*2+0] = ConvertYUV16ToR8G8B8(y0,u0,v0);
1079                 dwDst[x*2+1] = ConvertYUV16ToR8G8B8(y1,u0,v0);
1080
1081                 dwWordOffset += 4;
1082             }
1083         }
1084     }
1085     else
1086     {
1087         uint16 * pSrc = (uint16*)(tinfo.pPhysicalAddress);
1088         uint8 * pByteSrc = (uint8 *)pSrc;
1089
1090         if (tinfo.bSwapped)
1091         {
1092             for (y = 0; y < tinfo.HeightToLoad; y++)
1093             {
1094                 if ((y&1) == 0)
1095                     nFiddle = 0x3;
1096                 else
1097                     nFiddle = 0x7;
1098
1099                 // dwDst points to start of destination row
1100                 uint32 * dwDst = (uint32 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);
1101
1102                 // DWordOffset points to the current dword we're looking at
1103                 // (process 2 pixels at a time). May be a problem if we don't start on even pixel
1104                 uint32 dwWordOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad * 2);
1105
1106                 for (x = 0; x < tinfo.WidthToLoad/2; x++)
1107                 {
1108                     int y0 = *(uint8*)&pByteSrc[(dwWordOffset+2)^nFiddle];
1109                     int v0 = *(uint8*)&pByteSrc[(dwWordOffset+1)^nFiddle];
1110                     int y1 = *(uint8*)&pByteSrc[(dwWordOffset  )^nFiddle];
1111                     int u0 = *(uint8*)&pByteSrc[(dwWordOffset+3)^nFiddle];
1112
1113                     dwDst[x*2+0] = ConvertYUV16ToR8G8B8(y0,u0,v0);
1114                     dwDst[x*2+1] = ConvertYUV16ToR8G8B8(y1,u0,v0);
1115
1116                     dwWordOffset += 4;
1117                 }
1118             }
1119         }
1120         else
1121         {
1122             for (y = 0; y < tinfo.HeightToLoad; y++)
1123             {
1124                 // dwDst points to start of destination row
1125                 uint32 * dwDst = (uint32 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);
1126                 uint32 dwByteOffset = y * 32;
1127
1128                 for (x = 0; x < tinfo.WidthToLoad/2; x++)
1129                 {
1130                     int y0 = *(uint8*)&pByteSrc[(dwByteOffset+2)];
1131                     int v0 = *(uint8*)&pByteSrc[(dwByteOffset+1)];
1132                     int y1 = *(uint8*)&pByteSrc[(dwByteOffset  )];
1133                     int u0 = *(uint8*)&pByteSrc[(dwByteOffset+3)];
1134
1135                     dwDst[x*2+0] = ConvertYUV16ToR8G8B8(y0,u0,v0);
1136                     dwDst[x*2+1] = ConvertYUV16ToR8G8B8(y1,u0,v0);
1137
1138                     // Increment word offset to point to the next two pixels
1139                     dwByteOffset += 4;
1140                 }
1141             }
1142         }
1143     }
1144
1145     pTexture->EndUpdate(&dInfo);
1146     pTexture->SetOthersVariables();
1147 }
1148
1149 uint32 ConvertYUV16ToR8G8B8(int Y, int U, int V)
1150 {
1151     /*
1152     int R = int(g_convc0 *(Y-16) + g_convc1 * V);
1153     int G = int(g_convc0 *(Y-16) + g_convc2 * U - g_convc3 * V);
1154     int B = int(g_convc0 *(Y-16) + g_convc4 * U);
1155     */
1156
1157     Y += 80;
1158     int R = int(Y + (1.370705f * (V-128)));
1159     int G = int(Y - (0.698001f * (V-128)) - (0.337633f * (U-128)));
1160     int B = int(Y + (1.732446f * (U-128)));
1161
1162     R = R < 0 ? 0 : (R>255 ? 255 : R);
1163     G = G < 0 ? 0 : (G>255 ? 255 : G);
1164     B = B < 0 ? 0 : (B>255 ? 255 : B);
1165
1166     return COLOR_RGBA(R, G, B, 0xFF);
1167 }
1168
1169
1170 // Used by Starfox intro
1171 void Convert4b(CTexture *pTexture, const TxtrInfo &tinfo)
1172 {
1173     DrawInfo dInfo;
1174
1175     if (!pTexture->StartUpdate(&dInfo)) 
1176         return;
1177
1178     uint16 * pPal = (uint16 *)tinfo.PalAddress;
1179     bool bIgnoreAlpha = (tinfo.TLutFmt==TLUT_FMT_UNKNOWN);
1180     if( tinfo.Format <= TXT_FMT_CI ) bIgnoreAlpha = (tinfo.TLutFmt==TLUT_FMT_NONE);
1181
1182     Tile &tile = gRDP.tiles[tinfo.tileNo];
1183
1184     uint8 *pByteSrc = tinfo.tileNo >= 0 ? (uint8*)&g_Tmem.g_Tmem64bit[tile.dwTMem] : (uint8*)(tinfo.pPhysicalAddress);
1185
1186     for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
1187     {
1188         uint32 nFiddle;
1189         if( tinfo.tileNo < 0 )  
1190         {
1191             if (tinfo.bSwapped)
1192             {
1193                 if ((y%2) == 0)
1194                     nFiddle = 0x3;
1195                 else
1196                     nFiddle = 0x7;
1197             }
1198             else
1199             {
1200                 nFiddle = 3;
1201             }
1202         }
1203         else
1204         {
1205             nFiddle = ( y&1 )? 0x4 : 0;
1206         }
1207
1208         uint32 * pDst = (uint32 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
1209         int idx = tinfo.tileNo>=0 ? tile.dwLine*8*y : ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);
1210
1211         if (tinfo.WidthToLoad == 1)
1212         {
1213             // corner case
1214             uint8 b = pByteSrc[idx^nFiddle];
1215             uint8 bhi = (b&0xf0)>>4;
1216             if( gRDP.otherMode.text_tlut>=2 || ( tinfo.Format != TXT_FMT_IA && tinfo.Format != TXT_FMT_I) )
1217             {
1218                 if( tinfo.TLutFmt == TLUT_FMT_IA16 )
1219                 {
1220                     if( tinfo.tileNo>=0 )
1221                         *pDst = ConvertIA16ToRGBA(g_Tmem.g_Tmem16bit[0x400+tinfo.Palette*0x40+(bhi<<2)]);
1222                     else
1223                         *pDst = ConvertIA16ToRGBA(pPal[bhi^1]);
1224                 }
1225                 else
1226                 {
1227                     if( tinfo.tileNo>=0 )
1228                         *pDst = Convert555ToRGBA(g_Tmem.g_Tmem16bit[0x400+tinfo.Palette*0x40+(bhi<<2)]);
1229                     else
1230                         *pDst = Convert555ToRGBA(pPal[bhi^1]);
1231                 }
1232             }
1233             else if( tinfo.Format == TXT_FMT_IA )
1234                 *pDst = ConvertIA4ToRGBA(b>>4);
1235             else    // if( tinfo.Format == TXT_FMT_I )
1236                 *pDst = ConvertI4ToRGBA(b>>4);
1237             if( bIgnoreAlpha )
1238                 *pDst |= 0xFF000000;
1239         }
1240         else for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2, idx++)
1241         {
1242             // two pixels at a time
1243             uint8 b = pByteSrc[idx^nFiddle];
1244             uint8 bhi = (b&0xf0)>>4;
1245             uint8 blo = (b&0x0f);
1246
1247             if( gRDP.otherMode.text_tlut>=2 || ( tinfo.Format != TXT_FMT_IA && tinfo.Format != TXT_FMT_I) )
1248             {
1249                 if( tinfo.TLutFmt == TLUT_FMT_IA16 )
1250                 {
1251                     if( tinfo.tileNo>=0 )
1252                     {
1253                         pDst[0] = ConvertIA16ToRGBA(g_Tmem.g_Tmem16bit[0x400+tinfo.Palette*0x40+(bhi<<2)]);
1254                         pDst[1] = ConvertIA16ToRGBA(g_Tmem.g_Tmem16bit[0x400+tinfo.Palette*0x40+(blo<<2)]);
1255                     }
1256                     else
1257                     {
1258                         pDst[0] = ConvertIA16ToRGBA(pPal[bhi^1]);
1259                         pDst[1] = ConvertIA16ToRGBA(pPal[blo^1]);
1260                     }
1261                 }
1262                 else
1263                 {
1264                     if( tinfo.tileNo>=0 )
1265                     {
1266                         pDst[0] = Convert555ToRGBA(g_Tmem.g_Tmem16bit[0x400+tinfo.Palette*0x40+(bhi<<2)]);
1267                         pDst[1] = Convert555ToRGBA(g_Tmem.g_Tmem16bit[0x400+tinfo.Palette*0x40+(blo<<2)]);
1268                     }
1269                     else
1270                     {
1271                         pDst[0] = Convert555ToRGBA(pPal[bhi^1]);
1272                         pDst[1] = Convert555ToRGBA(pPal[blo^1]);
1273                     }
1274                 }
1275             }
1276             else if( tinfo.Format == TXT_FMT_IA )
1277             {
1278                 pDst[0] = ConvertIA4ToRGBA(b>>4);
1279                 pDst[1] = ConvertIA4ToRGBA(b&0xF);
1280             }
1281             else    // if( tinfo.Format == TXT_FMT_I )
1282             {
1283                 pDst[0] = ConvertI4ToRGBA(b>>4);
1284                 pDst[1] = ConvertI4ToRGBA(b&0xF);
1285             }
1286
1287             if( bIgnoreAlpha )
1288             {
1289                 pDst[0] |= 0xFF000000;
1290                 pDst[1] |= 0xFF000000;
1291             }
1292             pDst+=2;
1293         }
1294     }
1295
1296     pTexture->EndUpdate(&dInfo);
1297     pTexture->SetOthersVariables();
1298 }
1299
1300 void Convert8b(CTexture *pTexture, const TxtrInfo &tinfo)
1301 {
1302     DrawInfo dInfo;
1303     if (!pTexture->StartUpdate(&dInfo)) 
1304         return;
1305
1306     uint16 * pPal = (uint16 *)tinfo.PalAddress;
1307     bool bIgnoreAlpha = (tinfo.TLutFmt==TLUT_FMT_UNKNOWN);
1308     if( tinfo.Format <= TXT_FMT_CI ) bIgnoreAlpha = (tinfo.TLutFmt==TLUT_FMT_NONE);
1309
1310     Tile &tile = gRDP.tiles[tinfo.tileNo];
1311
1312     uint8 *pByteSrc;
1313     if( tinfo.tileNo >= 0 )
1314     {
1315         pByteSrc = (uint8*)&g_Tmem.g_Tmem64bit[tile.dwTMem];
1316     }
1317     else
1318     {
1319         pByteSrc = (uint8*)(tinfo.pPhysicalAddress);
1320     }
1321
1322
1323     for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
1324     {
1325         uint32 * pDst = (uint32 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
1326
1327         uint32 nFiddle;
1328         if( tinfo.tileNo < 0 )  
1329         {
1330             if (tinfo.bSwapped)
1331             {
1332                 if ((y%2) == 0)
1333                     nFiddle = 0x3;
1334                 else
1335                     nFiddle = 0x7;
1336             }
1337             else
1338             {
1339                 nFiddle = 3;
1340             }
1341         }
1342         else
1343         {
1344             nFiddle = ( y&1 )? 0x4 : 0;
1345         }
1346
1347
1348         int idx = tinfo.tileNo>=0? tile.dwLine*8*y : ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;
1349
1350         for (uint32 x = 0; x < tinfo.WidthToLoad; x++, idx++)
1351         {
1352             uint8 b = pByteSrc[idx^nFiddle];
1353
1354             if( gRDP.otherMode.text_tlut>=2 || ( tinfo.Format != TXT_FMT_IA && tinfo.Format != TXT_FMT_I) )
1355             {
1356                 if( tinfo.TLutFmt == TLUT_FMT_IA16 )
1357                 {
1358                     if( tinfo.tileNo>=0 )
1359                         *pDst = ConvertIA16ToRGBA(g_Tmem.g_Tmem16bit[0x400+(b<<2)]);
1360                     else
1361                         *pDst = ConvertIA16ToRGBA(pPal[b^1]);
1362                 }
1363                 else
1364                 {
1365                     if( tinfo.tileNo>=0 )
1366                         *pDst = Convert555ToRGBA(g_Tmem.g_Tmem16bit[0x400+(b<<2)]);
1367                     else
1368                         *pDst = Convert555ToRGBA(pPal[b^1]);
1369                 }
1370             }
1371             else if( tinfo.Format == TXT_FMT_IA )
1372             {
1373                 uint8 I = FourToEight[(b & 0xf0)>>4];
1374                 uint8 * pByteDst = (uint8*)pDst;
1375                 pByteDst[0] = I;
1376                 pByteDst[1] = I;
1377                 pByteDst[2] = I;
1378                 pByteDst[3] = FourToEight[(b & 0x0f)   ];
1379             }
1380             else    // if( tinfo.Format == TXT_FMT_I )
1381             {
1382                 uint8 * pByteDst = (uint8*)pDst;
1383                 pByteDst[0] = b;
1384                 pByteDst[1] = b;
1385                 pByteDst[2] = b;
1386                 pByteDst[3] = b;
1387             }
1388
1389             if( bIgnoreAlpha )
1390             {
1391                 *pDst |= 0xFF000000;
1392             }
1393             pDst++;
1394         }
1395     }
1396
1397     pTexture->EndUpdate(&dInfo);
1398     pTexture->SetOthersVariables();
1399 }
1400
1401
1402 void Convert16b(CTexture *pTexture, const TxtrInfo &tinfo)
1403 {
1404     DrawInfo dInfo;
1405     if (!pTexture->StartUpdate(&dInfo)) 
1406         return;
1407
1408     Tile &tile = gRDP.tiles[tinfo.tileNo];
1409
1410     uint16 *pWordSrc;
1411     if( tinfo.tileNo >= 0 )
1412         pWordSrc = (uint16*)&g_Tmem.g_Tmem64bit[tile.dwTMem];
1413     else
1414         pWordSrc = (uint16*)(tinfo.pPhysicalAddress);
1415
1416
1417     for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
1418     {
1419         uint32 * dwDst = (uint32 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);
1420
1421         uint32 nFiddle;
1422         if( tinfo.tileNo < 0 )  
1423         {
1424             if (tinfo.bSwapped)
1425             {
1426                 if ((y&1) == 0)
1427                     nFiddle = 0x1;
1428                 else
1429                     nFiddle = 0x3;
1430             }
1431             else
1432             {
1433                 nFiddle = 0x1;
1434             }
1435         }
1436         else
1437         {
1438             nFiddle = ( y&1 )? 0x2 : 0;
1439         }
1440
1441
1442         int idx = tinfo.tileNo>=0? tile.dwLine*4*y : (((y+tinfo.TopToLoad) * tinfo.Pitch)>>1) + tinfo.LeftToLoad;
1443
1444         for (uint32 x = 0; x < tinfo.WidthToLoad; x++, idx++)
1445         {
1446             uint16 w = pWordSrc[idx^nFiddle];
1447             uint16 w2 = tinfo.tileNo>=0? ((w>>8)|(w<<8)) : w;
1448
1449             if( tinfo.Format == TXT_FMT_RGBA )
1450             {
1451                 dwDst[x] = Convert555ToRGBA(w2);
1452             }
1453             else if( tinfo.Format == TXT_FMT_YUV )
1454             {
1455             }
1456             else if( tinfo.Format >= TXT_FMT_IA )
1457             {
1458                 uint8 * pByteDst = (uint8*)&dwDst[x];
1459                 *pByteDst++ = (uint8)(w2 >> 8);
1460                 *pByteDst++ = (uint8)(w2 >> 8);
1461                 *pByteDst++ = (uint8)(w2 >> 8);
1462                 *pByteDst++ = (uint8)(w2 & 0xFF);
1463             }
1464         }
1465     }
1466
1467     pTexture->EndUpdate(&dInfo);
1468     pTexture->SetOthersVariables();
1469 }
1470