292f9317 |
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 | |