Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libmupen64plus/mupen64plus-video-rice/src/ConvertImage.cpp
2 views
1
/*
2
Copyright (C) 2003 Rice1964
3
4
This program is free software; you can redistribute it and/or
5
modify it under the terms of the GNU General Public License
6
as published by the Free Software Foundation; either version 2
7
of the License, or (at your option) any later version.
8
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU General Public License for more details.
13
14
You should have received a copy of the GNU General Public License
15
along with this program; if not, write to the Free Software
16
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18
*/
19
20
#include "Config.h"
21
#include "ConvertImage.h"
22
#include "RenderBase.h"
23
24
ConvertFunction 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
};
36
ConvertFunction 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
49
ConvertFunction 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
62
extern bool conkerSwapHack;
63
64
void 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
131
void 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
234
void 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
338
void 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
409
void 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
478
void 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
592
void 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
//*****************************************************************************
657
void 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
//*****************************************************************************
672
void 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
685
void 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
791
void 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
899
void 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
974
void 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
1045
void 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
1149
uint32 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
1171
void 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
1300
void 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
1402
void 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
1471
1472