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 // Still to be swapped:
27 ConvertFunction gConvertFunctions_16_FullTMEM[ 8 ][ 4 ] =
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 } // ?
39 ConvertFunction gConvertFunctions_16[ 8 ][ 4 ] =
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 } // ?
52 ConvertFunction gConvertTlutFunctions_16[ 8 ][ 4 ] =
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 } // ?
65 extern bool conkerSwapHack;
67 void ConvertRGBA16_16(CTexture *pTexture, const TxtrInfo &tinfo)
73 // Copy of the base pointer
74 uint16 * pSrc = (uint16*)(tinfo.pPhysicalAddress);
75 uint8 * pByteSrc = (uint8 *)pSrc;
77 if (!pTexture->StartUpdate(&dInfo))
82 for (y = 0; y < tinfo.HeightToLoad; y++)
89 // dwDst points to start of destination row
90 uint16 * wDst = (uint16 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);
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);
96 for (x = 0; x < tinfo.WidthToLoad; x++)
98 uint16 w = *(uint16 *)&pByteSrc[dwWordOffset ^ nFiddle];
100 wDst[x] = Convert555ToR4G4B4A4(w);
102 // Increment word offset to point to the next two pixels
109 for (y = 0; y < tinfo.HeightToLoad; y++)
111 // dwDst points to start of destination row
112 uint16 * wDst = (uint16 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);
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);
118 for (x = 0; x < tinfo.WidthToLoad; x++)
120 uint16 w = *(uint16 *)&pByteSrc[dwWordOffset ^ 0x2];
122 wDst[x] = Convert555ToR4G4B4A4(w);
124 // Increment word offset to point to the next two pixels
130 pTexture->EndUpdate(&dInfo);
131 pTexture->SetOthersVariables();
134 void ConvertRGBA32_16(CTexture *pTexture, const TxtrInfo &tinfo)
137 uint32 * pSrc = (uint32*)(tinfo.pPhysicalAddress);
138 if (!pTexture->StartUpdate(&dInfo))
141 if( options.bUseFullTMEM )
143 Tile &tile = gRDP.tiles[tinfo.tileNo];
146 if( tinfo.tileNo >= 0 )
148 pWordSrc = (uint32*)&g_Tmem.g_Tmem64bit[tile.dwTMem];
150 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
152 uint16 * dwDst = (uint16 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);
154 uint32 nFiddle = ( y&1 )? 0x2 : 0;
155 int idx = tile.dwLine*4*y;
157 for (uint32 x = 0; x < tinfo.WidthToLoad; x++, idx++)
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));
170 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
174 uint16 *pDst = (uint16*)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
175 uint8 *pS = (uint8 *)pSrc + (y+tinfo.TopToLoad) * tinfo.Pitch + (tinfo.LeftToLoad*4);
177 for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
180 *pDst++ = R4G4B4A4_MAKE((pS[3]>>4), // Red
183 (pS[0]>>4)); // Alpha
189 uint16 *pDst = (uint16*)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
190 uint8 *pS = (uint8 *)pSrc + (y+tinfo.TopToLoad) * tinfo.Pitch + (tinfo.LeftToLoad*4);
194 for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
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
208 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
210 uint16 *pDst = (uint16*)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
211 uint8 *pS = (uint8 *)pSrc + (y+tinfo.TopToLoad) * tinfo.Pitch + (tinfo.LeftToLoad*4);
213 for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
215 *pDst++ = R4G4B4A4_MAKE((pS[3]>>4), // Red
218 (pS[0]>>4)); // Alpha
225 pTexture->EndUpdate(&dInfo);
226 pTexture->SetOthersVariables();
230 // E.g. Dear Mario text
232 void ConvertIA4_16(CTexture *pTexture, const TxtrInfo &tinfo)
237 uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);
238 if (!pTexture->StartUpdate(&dInfo))
243 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
245 uint16 *pDst = (uint16*)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
247 // For odd lines, swap words too
254 // This may not work if X is not even?
255 uint32 dwByteOffset = (y+tinfo.TopToLoad) * tinfo.Pitch + (tinfo.LeftToLoad/2);
257 // Do two pixels at a time
258 for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)
260 uint8 b = pSrc[dwByteOffset ^ nFiddle];
263 *pDst++ = R4G4B4A4_MAKE(ThreeToFour[(b & 0xE0) >> 5],
264 ThreeToFour[(b & 0xE0) >> 5],
265 ThreeToFour[(b & 0xE0) >> 5],
266 OneToFour[(b & 0x10) >> 4]);
269 *pDst++ = R4G4B4A4_MAKE(ThreeToFour[(b & 0x0E) >> 1],
270 ThreeToFour[(b & 0x0E) >> 1],
271 ThreeToFour[(b & 0x0E) >> 1],
272 OneToFour[(b & 0x01)] );
280 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
282 uint16 *pDst = (uint16*)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
284 // This may not work if X is not even?
285 uint32 dwByteOffset = (y+tinfo.TopToLoad) * tinfo.Pitch + (tinfo.LeftToLoad/2);
287 // Do two pixels at a time
288 for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)
290 uint8 b = pSrc[dwByteOffset ^ 0x3];
293 *pDst++ = R4G4B4A4_MAKE(ThreeToFour[(b & 0xE0) >> 5],
294 ThreeToFour[(b & 0xE0) >> 5],
295 ThreeToFour[(b & 0xE0) >> 5],
296 OneToFour[(b & 0x10) >> 4]);
299 *pDst++ = R4G4B4A4_MAKE(ThreeToFour[(b & 0x0E) >> 1],
300 ThreeToFour[(b & 0x0E) >> 1],
301 ThreeToFour[(b & 0x0E) >> 1],
302 OneToFour[(b & 0x01)] );
309 pTexture->EndUpdate(&dInfo);
310 pTexture->SetOthersVariables();
313 // E.g Mario's head textures
314 void ConvertIA8_16(CTexture *pTexture, const TxtrInfo &tinfo)
319 uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);
320 if (!pTexture->StartUpdate(&dInfo))
325 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
327 // For odd lines, swap words too
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;
338 for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
340 uint8 b = pSrc[dwByteOffset ^ nFiddle];
342 *pDst++ = R4G4B4A4_MAKE( ((b&0xf0)>>4),((b&0xf0)>>4),((b&0xf0)>>4),(b&0x0f));
350 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
352 uint16 *pDst = (uint16*)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
354 // Points to current byte
355 uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;
357 for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
359 uint8 b = pSrc[dwByteOffset ^ 0x3];
361 *pDst++ = R4G4B4A4_MAKE(((b&0xf0)>>4),((b&0xf0)>>4),((b&0xf0)>>4),(b&0x0f));
368 pTexture->EndUpdate(&dInfo);
369 pTexture->SetOthersVariables();
373 // E.g. camera's clouds, shadows
374 void ConvertIA16_16(CTexture *pTexture, const TxtrInfo &tinfo)
378 uint16 * pSrc = (uint16*)(tinfo.pPhysicalAddress);
379 uint8 * pByteSrc = (uint8 *)pSrc;
381 if (!pTexture->StartUpdate(&dInfo))
384 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
386 uint16 *pDst = (uint16*)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
388 // Points to current word
389 uint32 dwWordOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad * 2);
391 for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
393 uint16 w = *(uint16 *)&pByteSrc[dwWordOffset^0x2];
395 uint8 i = (uint8)(w >> 12);
396 uint8 a = (uint8)(w & 0xFF);
398 *pDst++ = R4G4B4A4_MAKE(i, i, i, (a>>4));
404 pTexture->EndUpdate(&dInfo);
405 pTexture->SetOthersVariables();
411 void ConvertI4_16(CTexture *pTexture, const TxtrInfo &tinfo)
416 uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);
417 if (!pTexture->StartUpdate(&dInfo))
422 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
424 uint16 *pDst = (uint16*)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
426 // Might not work with non-even starting X
427 uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);
429 // For odd lines, swap words too
430 if( !conkerSwapHack || (y&4) == 0 )
445 for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)
447 uint8 b = pSrc[dwByteOffset ^ nFiddle];
450 //*pDst++ = R4G4B4A4_MAKE(b>>4, b>>4, b>>4, b>>4);
451 *pDst++ = FourToSixteen[(b & 0xF0)>>4];
453 //*pDst++ = R4G4B4A4_MAKE(b & 0x0f, b & 0x0f, b & 0x0f, b & 0x0f);
454 *pDst++ = FourToSixteen[b & 0x0f];
462 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
464 uint8 *pDst = (uint8 *)dInfo.lpSurface + y * dInfo.lPitch;
466 // Might not work with non-even starting X
467 uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);
469 for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)
471 uint8 b = pSrc[dwByteOffset ^ 0x3];
474 //*pDst++ = R4G4B4A4_MAKE(b>>4, b>>4, b>>4, b>>4);
475 *pDst++ = FourToEight[(b & 0xF0)>>4];
478 //*pDst++ = R4G4B4A4_MAKE(b & 0x0f, b & 0x0f, b & 0x0f, b & 0x0f);
479 *pDst++ = FourToEight[b & 0x0f];
486 pTexture->EndUpdate(&dInfo);
487 pTexture->SetOthersVariables();
491 void ConvertI8_16(CTexture *pTexture, const TxtrInfo &tinfo)
496 long long pSrc = (long long) (tinfo.pPhysicalAddress);
497 if (!pTexture->StartUpdate(&dInfo))
502 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
509 uint16 *pDst = (uint16*)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
511 uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;
513 for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
515 uint8 b = *(uint8*)((pSrc+dwByteOffset)^nFiddle);
517 *pDst++ = R4G4B4A4_MAKE(b>>4,
528 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
530 uint16 *pDst = (uint16*)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
532 uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;
534 for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
536 uint8 b = *(uint8*)((pSrc+dwByteOffset)^0x3);
538 *pDst++ = R4G4B4A4_MAKE(b>>4,
548 pTexture->EndUpdate(&dInfo);
549 pTexture->SetOthersVariables();
554 // Used by Starfox intro
555 void ConvertCI4_RGBA16_16(CTexture *pTexture, const TxtrInfo &tinfo)
560 uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);
561 uint16 * pPal = (uint16 *)tinfo.PalAddress;
562 if (!pTexture->StartUpdate(&dInfo))
568 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
576 uint16 * pDst = (uint16 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
578 uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);
580 for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)
582 uint8 b = pSrc[dwByteOffset ^ nFiddle];
584 uint8 bhi = (b&0xf0)>>4;
585 uint8 blo = (b&0x0f);
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!
598 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
600 uint16 * pDst = (uint16 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
602 uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);
604 for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)
606 uint8 b = pSrc[dwByteOffset ^ 0x3];
608 uint8 bhi = (b&0xf0)>>4;
609 uint8 blo = (b&0x0f);
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!
620 pTexture->EndUpdate(&dInfo);
621 pTexture->SetOthersVariables();
624 //*****************************************************************************
625 // Convert CI4 images. We need to switch on the palette type
626 //*****************************************************************************
627 void ConvertCI4_16( CTexture * p_texture, const TxtrInfo & tinfo )
629 if ( tinfo.TLutFmt == TLUT_FMT_RGBA16 )
631 ConvertCI4_RGBA16_16( p_texture, tinfo );
633 else if ( tinfo.TLutFmt == TLUT_FMT_IA16 )
635 ConvertCI4_IA16_16( p_texture, tinfo );
639 //*****************************************************************************
640 // Convert CI8 images. We need to switch on the palette type
641 //*****************************************************************************
642 void ConvertCI8_16( CTexture * p_texture, const TxtrInfo & tinfo )
644 if ( tinfo.TLutFmt == TLUT_FMT_RGBA16 )
646 ConvertCI8_RGBA16_16( p_texture, tinfo );
648 else if ( tinfo.TLutFmt == TLUT_FMT_IA16 )
650 ConvertCI8_IA16_16( p_texture, tinfo );
654 // Used by Starfox intro
655 void ConvertCI4_IA16_16(CTexture *pTexture, const TxtrInfo &tinfo)
660 uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);
661 uint16 * pPal = (uint16 *)tinfo.PalAddress;
662 if (!pTexture->StartUpdate(&dInfo))
667 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
674 uint16 * pDst = (uint16 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
676 uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);
678 for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)
680 uint8 b = pSrc[dwByteOffset ^ nFiddle];
682 uint8 bhi = (b&0xf0)>>4;
683 uint8 blo = (b&0x0f);
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!
694 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
696 uint16 * pDst = (uint16 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
698 uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);
700 for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2)
702 uint8 b = pSrc[dwByteOffset ^ 0x3];
704 uint8 bhi = (b&0xf0)>>4;
705 uint8 blo = (b&0x0f);
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!
716 pTexture->EndUpdate(&dInfo);
717 pTexture->SetOthersVariables();
721 // Used by MarioKart for Cars etc
722 void ConvertCI8_RGBA16_16(CTexture *pTexture, const TxtrInfo &tinfo)
727 uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);
728 uint16 * pPal = (uint16 *)tinfo.PalAddress;
729 if (!pTexture->StartUpdate(&dInfo))
734 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
741 uint16 *pDst = (uint16 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
743 uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;
745 for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
747 uint8 b = pSrc[dwByteOffset ^ nFiddle];
749 *pDst++ = Convert555ToR4G4B4A4(pPal[b^1]); // Remember palette is in different endian order!
757 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
759 uint16 *pDst = (uint16 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
761 uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;
763 for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
765 uint8 b = pSrc[dwByteOffset ^ 0x3];
767 *pDst++ = Convert555ToR4G4B4A4(pPal[b^1]); // Remember palette is in different endian order!
774 pTexture->EndUpdate(&dInfo);
775 pTexture->SetOthersVariables();
779 // Used by MarioKart for Cars etc
780 void ConvertCI8_IA16_16(CTexture *pTexture, const TxtrInfo &tinfo)
785 uint8 * pSrc = (uint8*)(tinfo.pPhysicalAddress);
786 uint16 * pPal = (uint16 *)tinfo.PalAddress;
787 if (!pTexture->StartUpdate(&dInfo))
792 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
799 uint16 *pDst = (uint16 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
801 uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;
803 for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
805 uint8 b = pSrc[dwByteOffset ^ nFiddle];
807 *pDst++ = ConvertIA16ToR4G4B4A4(pPal[b^1]); // Remember palette is in different endian order!
815 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
817 uint16 *pDst = (uint16 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
819 uint32 dwByteOffset = ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;
821 for (uint32 x = 0; x < tinfo.WidthToLoad; x++)
823 uint8 b = pSrc[dwByteOffset ^ 0x3];
825 *pDst++ = ConvertIA16ToR4G4B4A4(pPal[b^1]); // Remember palette is in different endian order!
832 pTexture->EndUpdate(&dInfo);
833 pTexture->SetOthersVariables();
837 void ConvertYUV_16(CTexture *pTexture, const TxtrInfo &tinfo)
840 if (!pTexture->StartUpdate(&dInfo))
846 if( options.bUseFullTMEM )
848 Tile &tile = gRDP.tiles[tinfo.tileNo];
851 if( tinfo.tileNo >= 0 )
852 pSrc = (uint16*)&g_Tmem.g_Tmem64bit[tile.dwTMem];
854 pSrc = (uint16*)(tinfo.pPhysicalAddress);
856 uint8 * pByteSrc = (uint8 *)pSrc;
857 for (y = 0; y < tinfo.HeightToLoad; y++)
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);
863 for (x = 0; x < tinfo.WidthToLoad/2; x++)
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];
870 wDst[x*2+0] = ConvertYUV16ToR4G4B4(y0,u0,v0);
871 wDst[x*2+1] = ConvertYUV16ToR4G4B4(y1,u0,v0);
879 // Copy of the base pointer
880 uint16 * pSrc = (uint16*)(tinfo.pPhysicalAddress);
881 uint8 * pByteSrc = (uint8 *)pSrc;
886 for (y = 0; y < tinfo.HeightToLoad; y++)
893 // dwDst points to start of destination row
894 uint16 * wDst = (uint16 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);
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);
900 for (x = 0; x < tinfo.WidthToLoad/2; x++)
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];
907 wDst[x*2+0] = ConvertYUV16ToR4G4B4(y0,u0,v0);
908 wDst[x*2+1] = ConvertYUV16ToR4G4B4(y1,u0,v0);
916 for (y = 0; y < tinfo.HeightToLoad; y++)
918 // dwDst points to start of destination row
919 uint16 * wDst = (uint16 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);
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);
925 for (x = 0; x < tinfo.WidthToLoad/2; x++)
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];
932 wDst[x*2+0] = ConvertYUV16ToR4G4B4(y0,u0,v0);
933 wDst[x*2+1] = ConvertYUV16ToR4G4B4(y1,u0,v0);
941 pTexture->EndUpdate(&dInfo);
942 pTexture->SetOthersVariables();
945 uint16 ConvertYUV16ToR4G4B4(int Y, int U, int V)
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);
958 // Used by Starfox intro
959 void Convert4b_16(CTexture *pTexture, const TxtrInfo &tinfo)
963 if (!pTexture->StartUpdate(&dInfo))
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);
970 Tile &tile = gRDP.tiles[tinfo.tileNo];
972 uint8 *pByteSrc = tinfo.tileNo >= 0 ? (uint8*)&g_Tmem.g_Tmem64bit[tile.dwTMem] : (uint8*)(tinfo.pPhysicalAddress);
974 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
976 uint16 * pDst = (uint16 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
979 if( tinfo.tileNo < 0 )
995 nFiddle = ( y&1 )? 0x4 : 0;
998 int idx = tinfo.tileNo>=0 ? tile.dwLine*8*y : ((y+tinfo.TopToLoad) * tinfo.Pitch) + (tinfo.LeftToLoad / 2);
1000 for (uint32 x = 0; x < tinfo.WidthToLoad; x+=2, idx++)
1002 uint8 b = pByteSrc[idx^nFiddle];
1003 uint8 bhi = (b&0xf0)>>4;
1004 uint8 blo = (b&0x0f);
1006 if( gRDP.otherMode.text_tlut>=2 || ( tinfo.Format != TXT_FMT_IA && tinfo.Format != TXT_FMT_I) )
1008 if( tinfo.TLutFmt == TLUT_FMT_IA16 )
1010 if( tinfo.tileNo>=0 )
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)]);
1017 pDst[0] = ConvertIA16ToR4G4B4A4(pPal[bhi^1]);
1018 pDst[1] = ConvertIA16ToR4G4B4A4(pPal[blo^1]);
1023 if( tinfo.tileNo>=0 )
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)]);
1030 pDst[0] = Convert555ToR4G4B4A4(pPal[bhi^1]);
1031 pDst[1] = Convert555ToR4G4B4A4(pPal[blo^1]);
1035 else if( tinfo.Format == TXT_FMT_IA )
1037 pDst[0] = ConvertIA4ToR4G4B4A4(b>>4);
1038 pDst[1] = ConvertIA4ToR4G4B4A4(b&0xF);
1040 else //if( tinfo.Format == TXT_FMT_I )
1042 pDst[0] = ConvertI4ToR4G4B4A4(b>>4);
1043 pDst[1] = ConvertI4ToR4G4B4A4(b&0xF);
1055 pTexture->EndUpdate(&dInfo);
1056 pTexture->SetOthersVariables();
1059 void Convert8b_16(CTexture *pTexture, const TxtrInfo &tinfo)
1062 if (!pTexture->StartUpdate(&dInfo))
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);
1070 Tile &tile = gRDP.tiles[tinfo.tileNo];
1073 if( tinfo.tileNo >= 0 )
1074 pByteSrc = (uint8*)&g_Tmem.g_Tmem64bit[tile.dwTMem];
1076 pByteSrc = (uint8*)(tinfo.pPhysicalAddress);
1079 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
1081 uint16 * pDst = (uint16 *)((uint8 *)dInfo.lpSurface + y * dInfo.lPitch);
1084 if( tinfo.tileNo < 0 )
1100 nFiddle = ( y&1 )? 0x4 : 0;
1103 int idx = tinfo.tileNo>=0? tile.dwLine*8*y : ((y+tinfo.TopToLoad) * tinfo.Pitch) + tinfo.LeftToLoad;
1105 for (uint32 x = 0; x < tinfo.WidthToLoad; x++, idx++)
1107 uint8 b = pByteSrc[idx^nFiddle];
1109 if( gRDP.otherMode.text_tlut>=2 || ( tinfo.Format != TXT_FMT_IA && tinfo.Format != TXT_FMT_I) )
1111 if( tinfo.TLutFmt == TLUT_FMT_IA16 )
1113 if( tinfo.tileNo>=0 )
1114 *pDst = ConvertIA16ToR4G4B4A4(g_Tmem.g_Tmem16bit[0x400+(b<<2)]);
1116 *pDst = ConvertIA16ToR4G4B4A4(pPal[b^1]);
1120 if( tinfo.tileNo>=0 )
1121 *pDst = Convert555ToR4G4B4A4(g_Tmem.g_Tmem16bit[0x400+(b<<2)]);
1123 *pDst = Convert555ToR4G4B4A4(pPal[b^1]);
1126 else if( tinfo.Format == TXT_FMT_IA )
1128 *pDst = R4G4B4A4_MAKE( ((b&0xf0)>>4),((b&0xf0)>>4),((b&0xf0)>>4),(b&0x0f));
1130 else //if( tinfo.Format == TXT_FMT_I )
1132 *pDst = R4G4B4A4_MAKE(b>>4, b>>4, b>>4, b>>4);
1137 *pDst |= 0xFF000000;
1143 pTexture->EndUpdate(&dInfo);
1144 pTexture->SetOthersVariables();
1148 void Convert16b_16(CTexture *pTexture, const TxtrInfo &tinfo)
1151 if (!pTexture->StartUpdate(&dInfo))
1154 Tile &tile = gRDP.tiles[tinfo.tileNo];
1157 if( tinfo.tileNo >= 0 )
1158 pWordSrc = (uint16*)&g_Tmem.g_Tmem64bit[tile.dwTMem];
1160 pWordSrc = (uint16*)(tinfo.pPhysicalAddress);
1163 for (uint32 y = 0; y < tinfo.HeightToLoad; y++)
1165 uint16 * dwDst = (uint16 *)((uint8 *)dInfo.lpSurface + y*dInfo.lPitch);
1168 if( tinfo.tileNo < 0 )
1184 nFiddle = ( y&1 )? 0x2 : 0;
1187 int idx = tinfo.tileNo>=0? tile.dwLine*4*y : (((y+tinfo.TopToLoad) * tinfo.Pitch)>>1) + tinfo.LeftToLoad;
1189 for (uint32 x = 0; x < tinfo.WidthToLoad; x++, idx++)
1191 uint16 w = pWordSrc[idx^nFiddle];
1192 uint16 w2 = tinfo.tileNo>=0? ((w>>8)|(w<<8)) : w;
1194 if( tinfo.Format == TXT_FMT_RGBA )
1196 dwDst[x] = Convert555ToR4G4B4A4(w2);
1198 else if( tinfo.Format == TXT_FMT_YUV )
1201 else if( tinfo.Format >= TXT_FMT_IA )
1203 uint8 i = (uint8)(w2 >> 12);
1204 uint8 a = (uint8)(w2 & 0xFF);
1205 dwDst[x] = R4G4B4A4_MAKE(i, i, i, (a>>4));
1210 pTexture->EndUpdate(&dInfo);
1211 pTexture->SetOthersVariables();