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