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