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