2 Copyright (C) 2003 Rice1964
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.
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.
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.
21 #include "ConvertImage.h"
22 #include "RenderBase.h"
24 ConvertFunction gConvertFunctions_FullTMEM[ 8 ][ 4 ] =
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 } // ?
36 ConvertFunction gConvertFunctions[ 8 ][ 4 ] =
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 } // ?
49 ConvertFunction gConvertTlutFunctions[ 8 ][ 4 ] =
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 } // ?
62 extern bool conkerSwapHack;
64 void ConvertRGBA16(CTexture *pTexture, const TxtrInfo &tinfo)
68 // Copy of the base pointer
69 uint16 * pSrc = (uint16*)(tinfo.pPhysicalAddress);
71 uint8 * pByteSrc = (uint8 *)pSrc;
72 if (!pTexture->StartUpdate(&dInfo))
79 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
86 // dwDst points to start of destination row
87 uint32 * dwDst = (uint32 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);
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);
93 for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
95 uint16 w = *(uint16 *)&pByteSrc[dwWordOffset ^ nFiddle];
97 dwDst[x] = Convert555ToRGBA(w);
99 // Increment word offset to point to the next two pixels
106 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
108 // dwDst points to start of destination row
109 uint32 * dwDst = (uint32 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);
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);
115 for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
117 uint16 w = *(uint16 *)&pByteSrc[dwWordOffset ^ 0x2];
119 dwDst[x] = Convert555ToRGBA(w);
121 // Increment word offset to point to the next two pixels
127 pTexture->EndUpdate(&dInfo);
128 pTexture->SetOthersVariables();
131 void ConvertRGBA32(CTexture *pTexture, const TxtrInfo &tinfo)
134 if (!pTexture->StartUpdate(&dInfo))
137 uint32 * pSrc = (uint32*)(tinfo.pPhysicalAddress);
139 if( options.bUseFullTMEM )
141 Tile &tile = gRDP.tiles[tinfo.tileNo];
144 if( tinfo.tileNo >= 0 )
146 pWordSrc = (uint32*)&g_Tmem.g_Tmem64bit[tile.dwTMem];
148 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
150 uint32 * dwDst = (uint32 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);
152 uint32 nFiddle = ( y&1 )? 0x2 : 0;
153 int idx = tile.dwLine*4*y;
155 for (uint32 x = 0; x < tinfo.WidthToLoad; x++, idx++)
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
172 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
176 uint8 *pDst = (uint8 *)dInfo.lpSurface + y * dInfo.lPitch;
177 uint8 *pS = (uint8 *)pSrc + (y+tinfo.TopToLoad) * tinfo.Pitch + (tinfo.LeftToLoad*4);
179 for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
181 pDst[0] = pS[1]; // Blue
182 pDst[1] = pS[2]; // Green
183 pDst[2] = pS[3]; // Red
184 pDst[3] = pS[0]; // Alpha
191 uint32 *pDst = (uint32 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
192 uint8 *pS = (uint8 *)pSrc;
195 n = (y+tinfo.TopToLoad) * tinfo.Pitch + (tinfo.LeftToLoad*4);
196 for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
198 *pDst++ = COLOR_RGBA(pS[(n+3)^0x8],
210 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
212 uint8 *pDst = (uint8 *)dInfo.lpSurface + y * dInfo.lPitch;
213 uint8 *pS = (uint8 *)pSrc + (y+tinfo.TopToLoad) * tinfo.Pitch + (tinfo.LeftToLoad*4);
215 for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
217 pDst[0] = pS[1]; // Blue
218 pDst[1] = pS[2]; // Green
219 pDst[2] = pS[3]; // Red
220 pDst[3] = pS[0]; // Alpha
228 pTexture->EndUpdate(&dInfo);
229 pTexture->SetOthersVariables();
232 // E.g. Dear Mario text
234 void ConvertIA4(CTexture *pTexture, const TxtrInfo &tinfo)
239 uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);
242 if (((long long)pSrc) % 4) TRACE0("Texture src addr is not aligned to 4 bytes, check me");
245 if (!pTexture->StartUpdate(&dInfo))
250 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
252 uint8 *pDst = (uint8 *)dInfo.lpSurface + y * dInfo.lPitch;
254 // For odd lines, swap words too
261 // This may not work if X is not even?
262 uint32 dwByteOffset = (y+tinfo.TopToLoad) * tinfo.Pitch + (tinfo.LeftToLoad/2);
264 if (tinfo.WidthToLoad == 1)
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];
273 else for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)
275 // Do two pixels at a time
276 uint8 b = pSrc[dwByteOffset ^ nFiddle];
279 *pDst++ = ThreeToEight[(b & 0xE0) >> 5];
280 *pDst++ = ThreeToEight[(b & 0xE0) >> 5];
281 *pDst++ = ThreeToEight[(b & 0xE0) >> 5];
282 *pDst++ = OneToEight[(b & 0x10) >> 4];
284 *pDst++ = ThreeToEight[(b & 0x0E) >> 1];
285 *pDst++ = ThreeToEight[(b & 0x0E) >> 1];
286 *pDst++ = ThreeToEight[(b & 0x0E) >> 1];
287 *pDst++ = OneToEight[(b & 0x01) ];
295 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
297 uint8 *pDst = (uint8 *)dInfo.lpSurface + (y * dInfo.lPitch);
299 // This may not work if X is not even?
300 uint32 dwByteOffset = (y+tinfo.TopToLoad) * tinfo.Pitch + (tinfo.LeftToLoad/2);
302 if (tinfo.WidthToLoad == 1)
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];
311 else for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)
313 // Do two pixels at a time
314 uint8 b = pSrc[dwByteOffset ^ 0x3];
317 *pDst++ = ThreeToEight[(b & 0xE0) >> 5];
318 *pDst++ = ThreeToEight[(b & 0xE0) >> 5];
319 *pDst++ = ThreeToEight[(b & 0xE0) >> 5];
320 *pDst++ = OneToEight[(b & 0x10) >> 4];
322 *pDst++ = ThreeToEight[(b & 0x0E) >> 1];
323 *pDst++ = ThreeToEight[(b & 0x0E) >> 1];
324 *pDst++ = ThreeToEight[(b & 0x0E) >> 1];
325 *pDst++ = OneToEight[(b & 0x01) ];
332 pTexture->EndUpdate(&dInfo);
333 pTexture->SetOthersVariables();
337 // E.g Mario's head textures
338 void ConvertIA8(CTexture *pTexture, const TxtrInfo &tinfo)
343 uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);
346 if (((long long)pSrc) % 4) TRACE0("Texture src addr is not aligned to 4 bytes, check me");
349 if (!pTexture->StartUpdate(&dInfo))
354 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
356 // For odd lines, swap words too
362 uint8 *pDst = (uint8 *)dInfo.lpSurface + y * dInfo.lPitch;
363 // Points to current byte
364 uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;
366 for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
368 uint8 b = pSrc[dwByteOffset ^ nFiddle];
369 uint8 I = FourToEight[(b & 0xf0)>>4];
374 *pDst++ = FourToEight[(b & 0x0f) ];
382 register const uint8* FourToEightArray = &FourToEight[0];
383 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
385 uint8 *pDst = (uint8 *)dInfo.lpSurface + y * dInfo.lPitch;
387 // Points to current byte
388 uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;
390 for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
392 register uint8 b = pSrc[(dwByteOffset++) ^ 0x3];
393 uint8 I = *(FourToEightArray+(b>>4));
398 *pDst++ = *(FourToEightArray+(b&0xF));
403 pTexture->EndUpdate(&dInfo);
404 pTexture->SetOthersVariables();
408 // E.g. camera's clouds, shadows
409 void ConvertIA16(CTexture *pTexture, const TxtrInfo &tinfo)
414 uint16 * pSrc = (uint16*)(tinfo.pPhysicalAddress);
415 uint8 * pByteSrc = (uint8 *)pSrc;
417 if (!pTexture->StartUpdate(&dInfo))
422 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
424 uint8 *pDst = (uint8 *)dInfo.lpSurface + y * dInfo.lPitch;
431 // Points to current word
432 uint32 dwWordOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad * 2);
434 for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
436 uint16 w = *(uint16 *)&pByteSrc[dwWordOffset^nFiddle];
438 *pDst++ = (uint8)(w >> 8);
439 *pDst++ = (uint8)(w >> 8);
440 *pDst++ = (uint8)(w >> 8);
441 *pDst++ = (uint8)(w & 0xFF);
449 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
451 uint8 *pDst = (uint8 *)dInfo.lpSurface + y * dInfo.lPitch;
453 // Points to current word
454 uint32 dwWordOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad * 2);
456 for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
458 uint16 w = *(uint16 *)&pByteSrc[dwWordOffset^0x2];
460 *pDst++ = (uint8)(w >> 8);
461 *pDst++ = (uint8)(w >> 8);
462 *pDst++ = (uint8)(w >> 8);
463 *pDst++ = (uint8)(w & 0xFF);
471 pTexture->EndUpdate(&dInfo);
472 pTexture->SetOthersVariables();
478 void ConvertI4(CTexture *pTexture, const TxtrInfo &tinfo)
483 uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);
486 if (((long long) pSrc) % 4) TRACE0("Texture src addr is not aligned to 4 bytes, check me");
489 if (!pTexture->StartUpdate(&dInfo))
494 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
496 uint8 *pDst = (uint8 *)dInfo.lpSurface + y * dInfo.lPitch;
498 // Might not work with non-even starting X
499 uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);
501 // For odd lines, swap words too
502 if( !conkerSwapHack || (y&4) == 0 )
517 if (tinfo.WidthToLoad == 1)
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];
526 else for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)
528 // two pixels at a time
529 uint8 b = pSrc[dwByteOffset ^ nFiddle];
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];
537 *pDst++ = FourToEight[(b & 0x0F)];
538 *pDst++ = FourToEight[(b & 0x0F)];
539 *pDst++ = FourToEight[(b & 0x0F)];
540 *pDst++ = FourToEight[(b & 0x0F)];
546 conkerSwapHack = false;
550 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
552 uint8 *pDst = (uint8 *)dInfo.lpSurface + y * dInfo.lPitch;
554 // Might not work with non-even starting X
555 uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);
557 if (tinfo.WidthToLoad == 1)
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];
566 else for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)
568 // two pixels at a time
569 uint8 b = pSrc[dwByteOffset ^ 0x3];
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];
577 *pDst++ = FourToEight[(b & 0x0F)];
578 *pDst++ = FourToEight[(b & 0x0F)];
579 *pDst++ = FourToEight[(b & 0x0F)];
580 *pDst++ = FourToEight[(b & 0x0F)];
587 pTexture->EndUpdate(&dInfo);
588 pTexture->SetOthersVariables();
592 void ConvertI8(CTexture *pTexture, const TxtrInfo &tinfo)
597 long long pSrc = (long long) tinfo.pPhysicalAddress;
598 if (!pTexture->StartUpdate(&dInfo))
603 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
610 uint8 *pDst = (uint8 *)dInfo.lpSurface + y * dInfo.lPitch;
612 uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;
614 for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
616 uint8 b = *(uint8*)((pSrc+dwByteOffset)^nFiddle);
621 *pDst++ = b; // Alpha not 255?
629 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
631 uint8 *pDst = (uint8 *)dInfo.lpSurface + y * dInfo.lPitch;
633 uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;
635 for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
637 uint8 b = *(uint8*)((pSrc+dwByteOffset)^0x3);
642 *pDst++ = b; // Alpha not 255?
649 pTexture->EndUpdate(&dInfo);
650 pTexture->SetOthersVariables();
654 //*****************************************************************************
655 // Convert CI4 images. We need to switch on the palette type
656 //*****************************************************************************
657 void ConvertCI4( CTexture * p_texture, const TxtrInfo & tinfo )
659 if ( tinfo.TLutFmt == TLUT_FMT_RGBA16 )
661 ConvertCI4_RGBA16( p_texture, tinfo );
663 else if ( tinfo.TLutFmt == TLUT_FMT_IA16 )
665 ConvertCI4_IA16( p_texture, tinfo );
669 //*****************************************************************************
670 // Convert CI8 images. We need to switch on the palette type
671 //*****************************************************************************
672 void ConvertCI8( CTexture * p_texture, const TxtrInfo & tinfo )
674 if ( tinfo.TLutFmt == TLUT_FMT_RGBA16 )
676 ConvertCI8_RGBA16( p_texture, tinfo );
678 else if ( tinfo.TLutFmt == TLUT_FMT_IA16 )
680 ConvertCI8_IA16( p_texture, tinfo );
684 // Used by Starfox intro
685 void ConvertCI4_RGBA16(CTexture *pTexture, const TxtrInfo &tinfo)
690 uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);
691 uint16 * pPal = (uint16 *)tinfo.PalAddress;
692 bool bIgnoreAlpha = (tinfo.TLutFmt==TLUT_FMT_NONE);
694 if (!pTexture->StartUpdate(&dInfo))
699 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
706 uint32 * pDst = (uint32 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
708 uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch);
710 if (tinfo.WidthToLoad == 1)
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!
721 else for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)
724 uint8 b = pSrc[dwByteOffset ^ nFiddle];
726 uint8 bhi = (b&0xf0)>>4;
727 uint8 blo = (b&0x0f);
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!
734 pDst[0] |= 0xFF000000;
735 pDst[1] |= 0xFF000000;
746 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
748 uint32 * pDst = (uint32 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
750 uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);
752 if (tinfo.WidthToLoad == 1)
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!
763 else for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)
766 uint8 b = pSrc[dwByteOffset ^ 0x3];
768 uint8 bhi = (b&0xf0)>>4;
769 uint8 blo = (b&0x0f);
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!
776 pDst[0] |= 0xFF000000;
777 pDst[1] |= 0xFF000000;
786 pTexture->EndUpdate(&dInfo);
787 pTexture->SetOthersVariables();
790 // Used by Starfox intro
791 void ConvertCI4_IA16(CTexture *pTexture, const TxtrInfo &tinfo)
796 uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);
799 if (((long long) pSrc) % 4) TRACE0("Texture src addr is not aligned to 4 bytes, check me");
802 uint16 * pPal = (uint16 *)tinfo.PalAddress;
803 bool bIgnoreAlpha = (tinfo.TLutFmt==TLUT_FMT_UNKNOWN);
805 if (!pTexture->StartUpdate(&dInfo))
810 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
817 uint32 * pDst = (uint32 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
819 uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);
821 if (tinfo.WidthToLoad == 1)
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!
830 else for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)
833 uint8 b = pSrc[dwByteOffset ^ nFiddle];
835 uint8 bhi = (b&0xf0)>>4;
836 uint8 blo = (b&0x0f);
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!
843 pDst[0] |= 0xFF000000;
844 pDst[1] |= 0xFF000000;
855 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
857 uint32 * pDst = (uint32 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
859 uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);
861 if (tinfo.WidthToLoad == 1)
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!
870 else for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)
872 // two pixels at a time
873 uint8 b = pSrc[dwByteOffset ^ 0x3];
875 uint8 bhi = (b&0xf0)>>4;
876 uint8 blo = (b&0x0f);
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!
883 pDst[0] |= 0xFF000000;
884 pDst[1] |= 0xFF000000;
893 pTexture->EndUpdate(&dInfo);
894 pTexture->SetOthersVariables();
898 // Used by MarioKart for Cars etc
899 void ConvertCI8_RGBA16(CTexture *pTexture, const TxtrInfo &tinfo)
904 uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);
907 if (((long long) pSrc) % 4) TRACE0("Texture src addr is not aligned to 4 bytes, check me");
910 uint16 * pPal = (uint16 *)tinfo.PalAddress;
911 bool bIgnoreAlpha = (tinfo.TLutFmt==TLUT_FMT_NONE);
913 if (!pTexture->StartUpdate(&dInfo))
918 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
925 uint32 *pDst = (uint32 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
927 uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;
929 for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
931 uint8 b = pSrc[dwByteOffset ^ nFiddle];
933 *pDst++ = Convert555ToRGBA(pPal[b^1]); // Remember palette is in different endian order!
937 *(pDst-1) |= 0xFF000000;
946 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
948 uint32 *pDst = (uint32 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
950 int dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;
952 for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
954 uint8 b = pSrc[dwByteOffset ^ 0x3];
956 *pDst++ = Convert555ToRGBA(pPal[b^1]); // Remember palette is in different endian order!
959 *(pDst-1) |= 0xFF000000;
967 pTexture->EndUpdate(&dInfo);
968 pTexture->SetOthersVariables();
973 // Used by MarioKart for Cars etc
974 void ConvertCI8_IA16(CTexture *pTexture, const TxtrInfo &tinfo)
979 uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);
982 if (((long long) pSrc) % 4) TRACE0("Texture src addr is not aligned to 4 bytes, check me");
985 uint16 * pPal = (uint16 *)tinfo.PalAddress;
986 bool bIgnoreAlpha = (tinfo.TLutFmt==TLUT_FMT_UNKNOWN);
988 if (!pTexture->StartUpdate(&dInfo))
993 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
1000 uint32 *pDst = (uint32 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
1002 uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;
1004 for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
1006 uint8 b = pSrc[dwByteOffset ^ nFiddle];
1008 *pDst++ = ConvertIA16ToRGBA(pPal[b^1]); // Remember palette is in different endian order!
1011 *(pDst-1) |= 0xFF000000;
1020 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
1022 uint32 *pDst = (uint32 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
1024 uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;
1026 for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
1028 uint8 b = pSrc[dwByteOffset ^ 0x3];
1030 *pDst++ = ConvertIA16ToRGBA(pPal[b^1]); // Remember palette is in different endian order!
1033 *(pDst-1) |= 0xFF000000;
1041 pTexture->EndUpdate(&dInfo);
1042 pTexture->SetOthersVariables();
1045 void ConvertYUV(CTexture *pTexture, const TxtrInfo &tinfo)
1048 if (!pTexture->StartUpdate(&dInfo))
1054 if( options.bUseFullTMEM )
1056 Tile &tile = gRDP.tiles[tinfo.tileNo];
1059 if( tinfo.tileNo >= 0 )
1060 pSrc = (uint16*)&g_Tmem.g_Tmem64bit[tile.dwTMem];
1062 pSrc = (uint16*)(tinfo.pPhysicalAddress);
1064 uint8 * pByteSrc = (uint8 *)pSrc;
1065 for (y = 0; y < tinfo.HeightToLoad; y++)
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);
1071 for (x = 0; x < tinfo.WidthToLoad/2; x++)
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];
1078 dwDst[x*2+0] = ConvertYUV16ToR8G8B8(y0,u0,v0);
1079 dwDst[x*2+1] = ConvertYUV16ToR8G8B8(y1,u0,v0);
1087 uint16 * pSrc = (uint16*)(tinfo.pPhysicalAddress);
1088 uint8 * pByteSrc = (uint8 *)pSrc;
1092 for (y = 0; y < tinfo.HeightToLoad; y++)
1099 // dwDst points to start of destination row
1100 uint32 * dwDst = (uint32 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);
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);
1106 for (x = 0; x < tinfo.WidthToLoad/2; x++)
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];
1113 dwDst[x*2+0] = ConvertYUV16ToR8G8B8(y0,u0,v0);
1114 dwDst[x*2+1] = ConvertYUV16ToR8G8B8(y1,u0,v0);
1122 for (y = 0; y < tinfo.HeightToLoad; y++)
1124 // dwDst points to start of destination row
1125 uint32 * dwDst = (uint32 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);
1126 uint32 dwByteOffset = y * 32;
1128 for (x = 0; x < tinfo.WidthToLoad/2; x++)
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)];
1135 dwDst[x*2+0] = ConvertYUV16ToR8G8B8(y0,u0,v0);
1136 dwDst[x*2+1] = ConvertYUV16ToR8G8B8(y1,u0,v0);
1138 // Increment word offset to point to the next two pixels
1145 pTexture->EndUpdate(&dInfo);
1146 pTexture->SetOthersVariables();
1149 uint32 ConvertYUV16ToR8G8B8(int Y, int U, int V)
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);
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)));
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);
1166 return COLOR_RGBA(R, G, B, 0xFF);
1170 // Used by Starfox intro
1171 void Convert4b(CTexture *pTexture, const TxtrInfo &tinfo)
1175 if (!pTexture->StartUpdate(&dInfo))
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);
1182 Tile &tile = gRDP.tiles[tinfo.tileNo];
1184 uint8 *pByteSrc = tinfo.tileNo >= 0 ? (uint8*)&g_Tmem.g_Tmem64bit[tile.dwTMem] : (uint8*)(tinfo.pPhysicalAddress);
1186 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
1189 if( tinfo.tileNo < 0 )
1205 nFiddle = ( y&1 )? 0x4 : 0;
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);
1211 if (tinfo.WidthToLoad == 1)
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) )
1218 if( tinfo.TLutFmt == TLUT_FMT_IA16 )
1220 if( tinfo.tileNo>=0 )
1221 *pDst = ConvertIA16ToRGBA(g_Tmem.g_Tmem16bit[0x400+tinfo.Palette*0x40+(bhi<<2)]);
1223 *pDst = ConvertIA16ToRGBA(pPal[bhi^1]);
1227 if( tinfo.tileNo>=0 )
1228 *pDst = Convert555ToRGBA(g_Tmem.g_Tmem16bit[0x400+tinfo.Palette*0x40+(bhi<<2)]);
1230 *pDst = Convert555ToRGBA(pPal[bhi^1]);
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);
1238 *pDst |= 0xFF000000;
1240 else for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2, idx++)
1242 // two pixels at a time
1243 uint8 b = pByteSrc[idx^nFiddle];
1244 uint8 bhi = (b&0xf0)>>4;
1245 uint8 blo = (b&0x0f);
1247 if( gRDP.otherMode.text_tlut>=2 || ( tinfo.Format != TXT_FMT_IA && tinfo.Format != TXT_FMT_I) )
1249 if( tinfo.TLutFmt == TLUT_FMT_IA16 )
1251 if( tinfo.tileNo>=0 )
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)]);
1258 pDst[0] = ConvertIA16ToRGBA(pPal[bhi^1]);
1259 pDst[1] = ConvertIA16ToRGBA(pPal[blo^1]);
1264 if( tinfo.tileNo>=0 )
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)]);
1271 pDst[0] = Convert555ToRGBA(pPal[bhi^1]);
1272 pDst[1] = Convert555ToRGBA(pPal[blo^1]);
1276 else if( tinfo.Format == TXT_FMT_IA )
1278 pDst[0] = ConvertIA4ToRGBA(b>>4);
1279 pDst[1] = ConvertIA4ToRGBA(b&0xF);
1281 else // if( tinfo.Format == TXT_FMT_I )
1283 pDst[0] = ConvertI4ToRGBA(b>>4);
1284 pDst[1] = ConvertI4ToRGBA(b&0xF);
1289 pDst[0] |= 0xFF000000;
1290 pDst[1] |= 0xFF000000;
1296 pTexture->EndUpdate(&dInfo);
1297 pTexture->SetOthersVariables();
1300 void Convert8b(CTexture *pTexture, const TxtrInfo &tinfo)
1303 if (!pTexture->StartUpdate(&dInfo))
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);
1310 Tile &tile = gRDP.tiles[tinfo.tileNo];
1313 if( tinfo.tileNo >= 0 )
1315 pByteSrc = (uint8*)&g_Tmem.g_Tmem64bit[tile.dwTMem];
1319 pByteSrc = (uint8*)(tinfo.pPhysicalAddress);
1323 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
1325 uint32 * pDst = (uint32 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
1328 if( tinfo.tileNo < 0 )
1344 nFiddle = ( y&1 )? 0x4 : 0;
1348 int idx = tinfo.tileNo>=0? tile.dwLine*8*y : ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;
1350 for (uint32 x = 0; x < tinfo.WidthToLoad; x++, idx++)
1352 uint8 b = pByteSrc[idx^nFiddle];
1354 if( gRDP.otherMode.text_tlut>=2 || ( tinfo.Format != TXT_FMT_IA && tinfo.Format != TXT_FMT_I) )
1356 if( tinfo.TLutFmt == TLUT_FMT_IA16 )
1358 if( tinfo.tileNo>=0 )
1359 *pDst = ConvertIA16ToRGBA(g_Tmem.g_Tmem16bit[0x400+(b<<2)]);
1361 *pDst = ConvertIA16ToRGBA(pPal[b^1]);
1365 if( tinfo.tileNo>=0 )
1366 *pDst = Convert555ToRGBA(g_Tmem.g_Tmem16bit[0x400+(b<<2)]);
1368 *pDst = Convert555ToRGBA(pPal[b^1]);
1371 else if( tinfo.Format == TXT_FMT_IA )
1373 uint8 I = FourToEight[(b & 0xf0)>>4];
1374 uint8 * pByteDst = (uint8*)pDst;
1378 pByteDst[3] = FourToEight[(b & 0x0f) ];
1380 else // if( tinfo.Format == TXT_FMT_I )
1382 uint8 * pByteDst = (uint8*)pDst;
1391 *pDst |= 0xFF000000;
1397 pTexture->EndUpdate(&dInfo);
1398 pTexture->SetOthersVariables();
1402 void Convert16b(CTexture *pTexture, const TxtrInfo &tinfo)
1405 if (!pTexture->StartUpdate(&dInfo))
1408 Tile &tile = gRDP.tiles[tinfo.tileNo];
1411 if( tinfo.tileNo >= 0 )
1412 pWordSrc = (uint16*)&g_Tmem.g_Tmem64bit[tile.dwTMem];
1414 pWordSrc = (uint16*)(tinfo.pPhysicalAddress);
1417 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
1419 uint32 * dwDst = (uint32 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);
1422 if( tinfo.tileNo < 0 )
1438 nFiddle = ( y&1 )? 0x2 : 0;
1442 int idx = tinfo.tileNo>=0? tile.dwLine*4*y : (((y+tinfo.TopToLoad) * tinfo.Pitch)>>1) + tinfo.LeftToLoad;
1444 for (uint32 x = 0; x < tinfo.WidthToLoad; x++, idx++)
1446 uint16 w = pWordSrc[idx^nFiddle];
1447 uint16 w2 = tinfo.tileNo>=0? ((w>>8)|(w<<8)) : w;
1449 if( tinfo.Format == TXT_FMT_RGBA )
1451 dwDst[x] = Convert555ToRGBA(w2);
1453 else if( tinfo.Format == TXT_FMT_YUV )
1456 else if( tinfo.Format >= TXT_FMT_IA )
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);
1467 pTexture->EndUpdate(&dInfo);
1468 pTexture->SetOthersVariables();