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