1 #include <stdint.h>
2
3 #include <retro_miscellaneous.h>
4
5 #include "osal_preproc.h"
6 #include "float.h"
7 #include "ConvertImage.h"
8 #include "DeviceBuilder.h"
9 #include "FrameBuffer.h"
10 #include "Render.h"
11 #include "Timing.h"
12
13 #include "../../Graphics/GBI.h"
14 #include "../../Graphics/RDP/gDP_funcs_prot.h"
15 #include "../../Graphics/image_convert.h"
16
17 extern TMEMLoadMapInfo g_tmemLoadAddrMap[0x200]; /* Totally 4KB TMEM */
18 extern TMEMLoadMapInfo g_tmemInfo0; /* Info for Tmem=0 */
19 extern TMEMLoadMapInfo g_tmemInfo1; /* Info for Tmem=0x100 */
20 extern uint32_t g_TmemFlag[16];
21 extern uint32_t g_TxtLoadBy;
22
UnswapCopy(void * src,void * dest,uint32_t numBytes)23 static inline void UnswapCopy( void *src, void *dest, uint32_t numBytes )
24 {
25 // copy leading bytes
26 int leadingBytes = ((uintptr_t)src) & 3;
27 if (leadingBytes != 0)
28 {
29 leadingBytes = 4-leadingBytes;
30 if ((unsigned int)leadingBytes > numBytes)
31 leadingBytes = numBytes;
32 numBytes -= leadingBytes;
33
34 #ifdef MSB_FIRST
35 src = (void *)((uintptr_t)src);
36 #else
37 src = (void *)((uintptr_t)src ^ 3);
38 #endif
39 for (int i = 0; i < leadingBytes; i++)
40 {
41 *(uint8_t *)(dest) = *(uint8_t *)(src);
42 dest = (void *)((uintptr_t)dest+1);
43 src = (void *)((uintptr_t)src -1);
44 }
45 src = (void *)((uintptr_t)src+5);
46 }
47
48 // copy dwords
49 int numDWords = numBytes >> 2;
50 while (numDWords--)
51 {
52 uint32_t dword = *(uint32_t *)src;
53 dword = ((dword<<24)|((dword<<8)&0x00FF0000)|((dword>>8)&0x0000FF00)|(dword>>24));
54 *(uint32_t *)dest = dword;
55 dest = (void *)((uintptr_t)dest+4);
56 src = (void *)((uintptr_t)src +4);
57 }
58
59 // copy trailing bytes
60 int trailingBytes = numBytes & 3;
61 if (trailingBytes)
62 {
63 #ifdef MSB_FIRST
64 src = (void *)((uintptr_t)src);
65 #else
66 src = (void *)((uintptr_t)src ^ 3);
67 #endif
68 for (int i = 0; i < trailingBytes; i++)
69 {
70 *(uint8_t *)(dest) = *(uint8_t *)(src);
71 dest = (void *)((uintptr_t)dest+1);
72 src = (void *)((uintptr_t)src -1);
73 }
74 }
75 }
76
DWordInterleave(void * mem,uint32_t numDWords)77 static inline void DWordInterleave( void *mem, uint32_t numDWords )
78 {
79 int tmp;
80 while( numDWords-- )
81 {
82 tmp = *(int *)((uintptr_t)mem + 0);
83 *(int *)((uintptr_t)mem + 0) = *(int *)((uintptr_t)mem + 4);
84 *(int *)((uintptr_t)mem + 4) = tmp;
85 mem = (void *)((uintptr_t)mem + 8);
86 }
87 }
88
QWordInterleave(void * mem,uint32_t numDWords)89 static inline void QWordInterleave( void *mem, uint32_t numDWords )
90 {
91 numDWords >>= 1; // qwords
92 while( numDWords-- )
93 {
94 int tmp0, tmp1;
95 tmp0 = *(int *)((uintptr_t)mem + 0);
96 tmp1 = *(int *)((uintptr_t)mem + 4);
97 *(int *)((uintptr_t)mem + 0) = *(int *)((uintptr_t)mem + 8);
98 *(int *)((uintptr_t)mem + 8) = tmp0;
99 *(int *)((uintptr_t)mem + 4) = *(int *)((uintptr_t)mem + 12);
100 *(int *)((uintptr_t)mem + 12) = tmp1;
101 mem = (void *)((uintptr_t)mem + 16);
102 }
103 }
104
SetTmemFlag(uint32_t tmemAddr,uint32_t size)105 static void SetTmemFlag(uint32_t tmemAddr, uint32_t size)
106 {
107 uint32_t index = tmemAddr>>5;
108 uint32_t bitIndex = (tmemAddr&0x1F);
109
110 if( bitIndex == 0 )
111 {
112 uint32_t i;
113 for( i=0; i< (size>>5); i++ )
114 {
115 g_TmemFlag[index+i] = 0;
116 }
117
118 if( (size&0x1F) != 0 )
119 {
120 //ErrorMsg("Check me: tmemaddr=%X, size=%x", tmemAddr, size);
121 g_TmemFlag[index+i] &= ~((1<<(size&0x1F))-1);
122 }
123
124 g_TmemFlag[index] |= 1;
125 }
126 else
127 {
128 if( bitIndex + size <= 0x1F )
129 {
130 uint32_t val = g_TmemFlag[index];
131 uint32_t mask = (1<<(bitIndex))-1;
132 mask |= ~((1<<(bitIndex + size))-1);
133 val &= mask;
134 val |= (1<<bitIndex);
135 g_TmemFlag[index] = val;
136 }
137 else
138 {
139 //ErrorMsg("Check me: tmemaddr=%X, size=%x", tmemAddr, size);
140 uint32_t val = g_TmemFlag[index];
141 uint32_t mask = (1<<bitIndex)-1;
142 val &= mask;
143 val |= (1<<bitIndex);
144 g_TmemFlag[index] = val;
145 index++;
146 size -= (0x20-bitIndex);
147
148 uint32_t i;
149 for( i=0; i< (size>>5); i++ )
150 {
151 g_TmemFlag[index+i] = 0;
152 }
153
154 if( (size&0x1F) != 0 )
155 {
156 //ErrorMsg("Check me: tmemaddr=%X, size=%x", tmemAddr, size);
157 g_TmemFlag[index+i] &= ~((1<<(size&0x1F))-1);
158 }
159 }
160 }
161 }
162
ricegDPSetScissor(void * data,uint32_t mode,float ulx,float uly,float lrx,float lry)163 void ricegDPSetScissor(void *data,
164 uint32_t mode, float ulx, float uly, float lrx, float lry )
165 {
166 ScissorType *tempScissor = (ScissorType*)data;
167
168 tempScissor->mode = mode;
169 tempScissor->x0 = ulx;
170 tempScissor->y0 = uly;
171 tempScissor->x1 = lrx;
172 tempScissor->y1 = lry;
173 }
174
ricegDPSetFillColor(uint32_t c)175 void ricegDPSetFillColor(uint32_t c)
176 {
177 DP_Timing(DLParser_SetFillColor);
178 gRDP.fillColor = Convert555ToRGBA(c);
179 }
180
ricegDPSetFogColor(uint32_t r,uint32_t g,uint32_t b,uint32_t a)181 void ricegDPSetFogColor(uint32_t r, uint32_t g, uint32_t b, uint32_t a)
182 {
183 DP_Timing(DLParser_SetFogColor);
184 CRender::g_pRender->SetFogColor(r, g, b, a );
185 }
186
ricegDPFillRect(int32_t ulx,int32_t uly,int32_t lrx,int32_t lry)187 void ricegDPFillRect(int32_t ulx, int32_t uly, int32_t lrx, int32_t lry )
188 {
189 uint8_t *rdram_u8 = (uint8_t*)gfx_info.RDRAM;
190
191 /* Note, in some modes, the right/bottom lines aren't drawn */
192
193 if( gRDP.otherMode.cycle_type >= G_CYC_COPY )
194 {
195 ++lrx;
196 ++lry;
197 }
198
199 //TXTRBUF_DETAIL_DUMP(DebuggerAppendMsg("FillRect: X0=%d, Y0=%d, X1=%d, Y1=%d, Color=0x%08X", ulx, uly, lrx, lry, gRDP.originalFillColor););
200
201 // Skip this
202 if( status.bHandleN64RenderTexture && options.enableHackForGames == HACK_FOR_BANJO_TOOIE )
203 return;
204
205 if (IsUsedAsDI(g_CI.dwAddr))
206 {
207 // Clear the Z Buffer
208 if( ulx != 0 || uly != 0 || windowSetting.uViWidth- lrx > 1 || windowSetting.uViHeight - lry > 1)
209 {
210 if( options.enableHackForGames == HACK_FOR_GOLDEN_EYE )
211 {
212 // GoldenEye is using double zbuffer
213 if( g_CI.dwAddr == g_ZI.dwAddr )
214 {
215 // The zbuffer is the upper screen
216 COORDRECT rect={int(ulx * windowSetting.fMultX),int(uly * windowSetting.fMultY),int(lrx * windowSetting.fMultX),int(lry * windowSetting.fMultY)};
217 CRender::g_pRender->ClearBuffer(false,true,rect); //Check me
218 LOG_UCODE(" Clearing ZBuffer");
219 }
220 else
221 {
222 // The zbuffer is the lower screen
223 int h = (g_CI.dwAddr-g_ZI.dwAddr)/g_CI.dwWidth/2;
224 COORDRECT rect={int(ulx * windowSetting.fMultX),int((uly + h)*windowSetting.fMultY),int(lrx * windowSetting.fMultX),int((lry + h)*windowSetting.fMultY)};
225 CRender::g_pRender->ClearBuffer(false,true,rect); //Check me
226 LOG_UCODE(" Clearing ZBuffer");
227 }
228 }
229 else
230 {
231 COORDRECT rect={int(ulx * windowSetting.fMultX),int(uly * windowSetting.fMultY),int(lrx * windowSetting.fMultX),int(lry * windowSetting.fMultY)};
232 CRender::g_pRender->ClearBuffer(false,true,rect); //Check me
233 LOG_UCODE(" Clearing ZBuffer");
234 }
235 }
236 else
237 {
238 CRender::g_pRender->ClearBuffer(false,true); //Check me
239 LOG_UCODE(" Clearing ZBuffer");
240 }
241
242 if( g_curRomInfo.bEmulateClear )
243 {
244 // Emulating Clear, by write the memory in RDRAM
245 uint16_t color = (uint16_t)gRDP.originalFillColor;
246 uint32_t pitch = g_CI.dwWidth<<1;
247 int64_t base = (int64_t)(rdram_u8 + g_CI.dwAddr);
248
249 for( uint32_t i = uly; i < lry; i++ )
250 {
251 for( uint32_t j= ulx; j < lrx; j++ )
252 *(uint16_t*)((base+pitch*i+j)^2) = color;
253 }
254 }
255 }
256 else if( status.bHandleN64RenderTexture )
257 {
258 if( !status.bCIBufferIsRendered )
259 g_pFrameBufferManager->ActiveTextureBuffer();
260
261 int cond1 = (((int)ulx < status.leftRendered) ? ((int)ulx) : (status.leftRendered));
262 int cond2 = (((int)uly < status.topRendered) ? ((int)uly) : (status.topRendered));
263 int cond3 = ((status.rightRendered > ((int)lrx)) ? ((int)lrx) : (status.rightRendered));
264 int cond4 = ((status.bottomRendered > ((int)lry)) ? ((int)lry) : (status.bottomRendered));
265 int cond5 = ((g_pRenderTextureInfo->maxUsedHeight > ((int)lry)) ? ((int)lry) : (g_pRenderTextureInfo->maxUsedHeight));
266
267 status.leftRendered = status.leftRendered < 0 ? ulx : cond1;
268 status.topRendered = status.topRendered<0 ? uly : cond2;
269 status.rightRendered = status.rightRendered<0 ? lrx : cond3;
270 status.bottomRendered = status.bottomRendered<0 ? lry : cond4;
271
272 g_pRenderTextureInfo->maxUsedHeight = cond5;
273
274 if( status.bDirectWriteIntoRDRAM || ( ulx ==0 && uly == 0 && (lrx == g_pRenderTextureInfo->N64Width || lrx == g_pRenderTextureInfo->N64Width-1 ) ) )
275 {
276 if( g_pRenderTextureInfo->CI_Info.dwSize == G_IM_SIZ_16b )
277 {
278 uint16_t color = (uint16_t)gRDP.originalFillColor;
279 uint32_t pitch = g_pRenderTextureInfo->N64Width<<1;
280 int64_t base = (int64_t)(rdram_u8 + g_pRenderTextureInfo->CI_Info.dwAddr);
281 for( uint32_t i = uly; i < lry; i++ )
282 {
283 for( uint32_t j= ulx; j< lrx; j++ )
284 *(uint16_t*)((base+pitch*i+j)^2) = color;
285 }
286 }
287 else
288 {
289 uint8_t color = (uint8_t)gRDP.originalFillColor;
290 uint32_t pitch = g_pRenderTextureInfo->N64Width;
291 int64_t base = (int64_t) (rdram_u8 + g_pRenderTextureInfo->CI_Info.dwAddr);
292 for( uint32_t i= uly; i< lry; i++ )
293 {
294 for( uint32_t j= ulx; j< lrx; j++ )
295 *(uint8_t*)((base+pitch*i+j)^3) = color;
296 }
297 }
298
299 status.bFrameBufferDrawnByTriangles = false;
300 }
301 else
302 {
303 status.bFrameBufferDrawnByTriangles = true;
304 }
305 status.bFrameBufferDrawnByTriangles = true;
306
307 if( !status.bDirectWriteIntoRDRAM )
308 {
309 status.bFrameBufferIsDrawn = true;
310
311 //if( ulx ==0 && uly ==0 && (lrx == g_pRenderTextureInfo->N64Width || lrx == g_pRenderTextureInfo->N64Width-1 ) && gRDP.fillColor == 0)
312 //{
313 // CRender::g_pRender->ClearBuffer(true,false);
314 //}
315 //else
316 {
317 if( gRDP.otherMode.cycle_type == G_CYC_FILL )
318 {
319 CRender::g_pRender->FillRect(ulx, uly, lrx, lry, gRDP.fillColor);
320 }
321 else
322 {
323 COLOR primColor = GetPrimitiveColor();
324 CRender::g_pRender->FillRect(ulx, uly, lrx, lry, primColor);
325 }
326 }
327 }
328 }
329 else
330 {
331 LOG_UCODE(" Filling Rectangle");
332 if( frameBufferOptions.bSupportRenderTextures || frameBufferOptions.bCheckBackBufs )
333 {
334 int cond1 = (((int)ulx < status.leftRendered) ? ((int)ulx) : (status.leftRendered));
335 int cond2 = (((int)uly < status.topRendered) ? ((int)uly) : (status.topRendered));
336 int cond3 = ((status.rightRendered > ((int)lrx)) ? ((int)lrx) : (status.rightRendered));
337 int cond4 = ((status.bottomRendered > ((int)lry)) ? ((int)lry) : (status.bottomRendered));
338 int cond5 = ((g_pRenderTextureInfo->maxUsedHeight > ((int)lry)) ? ((int)lry) : (g_pRenderTextureInfo->maxUsedHeight));
339
340 if( !status.bCIBufferIsRendered ) g_pFrameBufferManager->ActiveTextureBuffer();
341
342 status.leftRendered = status.leftRendered<0 ? ulx : cond1;
343 status.topRendered = status.topRendered<0 ? uly : cond2;
344 status.rightRendered = status.rightRendered<0 ? lrx : cond3;
345 status.bottomRendered = status.bottomRendered<0 ? lry : cond4;
346 }
347
348 if( gRDP.otherMode.cycle_type == G_CYC_FILL )
349 {
350 if( !status.bHandleN64RenderTexture || g_pRenderTextureInfo->CI_Info.dwSize == G_IM_SIZ_16b )
351 CRender::g_pRender->FillRect(ulx, uly, lrx, lry, gRDP.fillColor);
352 }
353 else
354 {
355 COLOR primColor = GetPrimitiveColor();
356 //if( RGBA_GETALPHA(primColor) != 0 )
357 {
358 CRender::g_pRender->FillRect(ulx, uly, lrx, lry, primColor);
359 }
360 }
361 }
362 }
363
ricegDPSetEnvColor(uint32_t r,uint32_t g,uint32_t b,uint32_t a)364 void ricegDPSetEnvColor(uint32_t r, uint32_t g, uint32_t b, uint32_t a)
365 {
366 gRDP.colorsAreReloaded = true;
367 gRDP.envColor = COLOR_RGBA(r, g, b, a);
368 gRDP.fvEnvColor[0] = r / 255.0f;
369 gRDP.fvEnvColor[1] = g / 255.0f;
370 gRDP.fvEnvColor[2] = b / 255.0f;
371 gRDP.fvEnvColor[3] = a / 255.0f;
372 }
373
ricegDPLoadBlock(uint32_t tileno,uint32_t uls,uint32_t ult,uint32_t lrs,uint32_t dxt)374 void ricegDPLoadBlock( uint32_t tileno, uint32_t uls, uint32_t ult,
375 uint32_t lrs, uint32_t dxt )
376 {
377 TileAdditionalInfo *tileinfo = &gRDP.tilesinfo[tileno];
378 gDPTile *tile = &gDP.tiles[tileno];
379
380 tileinfo->bForceWrapS = tileinfo->bForceWrapT = tileinfo->bForceClampS = tileinfo->bForceClampT = false;
381
382 uint32_t size = lrs+1;
383
384 if( tile->size == G_IM_SIZ_32b )
385 size<<=1;
386
387 SetTmemFlag(tile->tmem, size>>2);
388
389 TMEMLoadMapInfo &info = g_tmemLoadAddrMap[tile->tmem];
390
391 info.bSwapped = (dxt == 0? true : false);
392
393 info.sl = tileinfo->hilite_sl = tile->lrs = uls;
394 info.sh = tileinfo->hilite_sh = tile->uls = lrs;
395 info.tl = tile->lrt = ult;
396 info.th = tile->ult = dxt;
397
398 tileinfo->bSizeIsValid = false;
399
400 for( int i=0; i<8; i++ )
401 {
402 if( gDP.tiles[i].tmem == tile->tmem )
403 tileinfo->lastTileCmd = CMD_LOADBLOCK;
404 }
405
406 info.dwLoadAddress = g_TI.dwAddr;
407 info.bSetBy = CMD_LOADBLOCK;
408 info.dxt = dxt;
409 info.dwLine = tile->line;
410
411 info.dwFormat = g_TI.dwFormat;
412 info.dwSize = g_TI.dwSize;
413 info.dwWidth = g_TI.dwWidth;
414 info.dwTotalWords = size;
415 info.dwTmem = tile->tmem;
416
417 if( gDP.tiles[tileno].tmem == 0 )
418 {
419 if( size >= 1024 )
420 {
421 memcpy(&g_tmemInfo0, &info, sizeof(TMEMLoadMapInfo) );
422 g_tmemInfo0.dwTotalWords = size>>2;
423 }
424
425 if( size == 2048 )
426 {
427 memcpy(&g_tmemInfo1, &info, sizeof(TMEMLoadMapInfo) );
428 g_tmemInfo1.dwTotalWords = size>>2;
429 }
430 }
431 else if( tile->tmem == 0x100 )
432 {
433 if( size == 1024 )
434 {
435 memcpy(&g_tmemInfo1, &info, sizeof(TMEMLoadMapInfo) );
436 g_tmemInfo1.dwTotalWords = size>>2;
437 }
438 }
439
440 g_TxtLoadBy = CMD_LOADBLOCK;
441
442
443 if( options.bUseFullTMEM )
444 {
445 uint8_t *rdram_u8 = (uint8_t*)gfx_info.RDRAM;
446 uint32_t bytes = (lrs + 1) << tile->size >> 1;
447 uint32_t address = g_TI.dwAddr + ult * g_TI.bpl + (uls << g_TI.dwSize >> 1);
448 if ((bytes == 0) || ((address + bytes) > g_dwRamSize) || (((tile->tmem << 3) + bytes) > 4096))
449 {
450 return;
451 }
452 uint64_t* src = (uint64_t*)(rdram_u8 + address);
453 uint64_t* dest = &g_Tmem.g_Tmem64bit[tile->tmem];
454
455 if( dxt > 0)
456 {
457 void (*Interleave)( void *mem, uint32_t numDWords );
458
459 uint32_t line = (2047 + dxt) / dxt;
460 uint32_t bpl = line << 3;
461 uint32_t height = bytes / bpl;
462
463 if (tile->size == G_IM_SIZ_32b)
464 Interleave = QWordInterleave;
465 else
466 Interleave = DWordInterleave;
467
468 for (uint32_t y = 0; y < height; y++)
469 {
470 UnswapCopy( src, dest, bpl );
471 if (y & 1) Interleave( dest, line );
472
473 src += line;
474 dest += line;
475 }
476 }
477 else
478 {
479 UnswapCopy( src, dest, bytes );
480 }
481 }
482 }
483
ricegDPLoadTile(uint32_t tileno,uint32_t uls,uint32_t ult,uint32_t lrs,uint32_t lrt)484 void ricegDPLoadTile(uint32_t tileno, uint32_t uls, uint32_t ult,
485 uint32_t lrs, uint32_t lrt)
486 {
487 TileAdditionalInfo *tileinfo = &gRDP.tilesinfo[tileno];
488 gDPTile *tile = &gDP.tiles[tileno];
489 tileinfo->bForceWrapS = tileinfo->bForceWrapT = tileinfo->bForceClampS = tileinfo->bForceClampT = false;
490
491 if (lrt < ult)
492 swapdword(&lrt, &ult);
493 if (lrs < uls)
494 swapdword(&lrs, &uls);
495
496 tileinfo->hilite_sl = tile->lrs = uls;
497 tileinfo->hilite_tl = tile->lrt = ult;
498 tileinfo->hilite_sh = tile->uls = lrs;
499 tileinfo->hilite_th = tile->ult = lrt;
500 tileinfo->bSizeIsValid = true;
501
502 // compute block height, and bpl of source and destination
503 uint32_t bpl = (lrs - uls + 1) << tile->size >> 1;
504 uint32_t height = lrt - ult + 1;
505 uint32_t line = tile->line;
506 if (tile->size == G_IM_SIZ_32b)
507 line <<= 1;
508
509 if (((tile->tmem << 3) + line * height) > 4096) // check destination ending point (TMEM is 4k bytes)
510 return;
511
512 if( options.bUseFullTMEM )
513 {
514 uint8_t *rdram_u8 = (uint8_t*)gfx_info.RDRAM;
515 void (*Interleave)( void *mem, uint32_t numDWords );
516
517 if( g_TI.bpl == 0 )
518 {
519 if( options.enableHackForGames == HACK_FOR_BUST_A_MOVE )
520 {
521 g_TI.bpl = 1024; // Hack for Bust-A-Move
522 }
523 else
524 {
525 TRACE0("Warning: g_TI.bpl = 0" );
526 }
527 }
528
529 uint32_t address = g_TI.dwAddr + tile->lrt * g_TI.bpl + (tile->lrs << g_TI.dwSize >> 1);
530 uint64_t* src = (uint64_t*)&rdram_u8[address];
531 uint8_t* dest = (uint8_t*)&g_Tmem.g_Tmem64bit[tile->tmem];
532
533 if ((address + height * bpl) > g_dwRamSize) // check source ending point
534 {
535 return;
536 }
537
538 // Line given for 32-bit is half what it seems it should since they split the
539 // high and low words. I'm cheating by putting them together.
540 if (tile->size == G_IM_SIZ_32b)
541 {
542 Interleave = QWordInterleave;
543 }
544 else
545 {
546 Interleave = DWordInterleave;
547 }
548
549 if( tile->line == 0 )
550 {
551 //tile->line = 1;
552 return;
553 }
554
555 for (uint32_t y = 0; y < height; y++)
556 {
557 UnswapCopy( src, dest, bpl );
558 if (y & 1) Interleave( dest, line );
559
560 src += g_TI.bpl;
561 dest += line;
562 }
563 }
564
565
566 for( int i=0; i<8; i++ )
567 {
568 if( gDP.tiles[i].tmem == tile->tmem )
569 gRDP.tilesinfo[i].lastTileCmd = CMD_LOADTILE;
570 }
571
572 uint32_t size = line * height;
573 SetTmemFlag(tile->tmem, size );
574
575 TMEMLoadMapInfo &info = g_tmemLoadAddrMap[tile->tmem];
576
577 info.dwLoadAddress = g_TI.dwAddr;
578 info.dwFormat = g_TI.dwFormat;
579 info.dwSize = g_TI.dwSize;
580 info.dwWidth = g_TI.dwWidth;
581
582 info.sl = uls;
583 info.sh = lrs;
584 info.tl = ult;
585 info.th = lrt;
586
587 info.dxt = 0;
588 info.dwLine = tile->line;
589 info.dwTmem = tile->tmem;
590 info.dwTotalWords = size<<2;
591
592 info.bSetBy = CMD_LOADTILE;
593 info.bSwapped =false;
594
595 g_TxtLoadBy = CMD_LOADTILE;
596
597 if( tile->tmem == 0 )
598 {
599 if( size >= 256 )
600 {
601 memcpy(&g_tmemInfo0, &info, sizeof(TMEMLoadMapInfo) );
602 g_tmemInfo0.dwTotalWords = size;
603 }
604
605 if( size == 512 )
606 {
607 memcpy(&g_tmemInfo1, &info, sizeof(TMEMLoadMapInfo) );
608 g_tmemInfo1.dwTotalWords = size;
609 }
610 }
611 else if( tile->tmem == 0x100 )
612 {
613 if( size == 256 )
614 {
615 memcpy(&g_tmemInfo1, &info, sizeof(TMEMLoadMapInfo) );
616 g_tmemInfo1.dwTotalWords = size;
617 }
618 }
619 }
620
ricegDPLoadTLUT(uint16_t dwCount,uint32_t tileno,uint32_t uls,uint32_t ult,uint32_t lrs,uint32_t lrt)621 void ricegDPLoadTLUT(uint16_t dwCount, uint32_t tileno, uint32_t uls, uint32_t ult, uint32_t lrs, uint32_t lrt)
622 {
623 uint8_t *rdram_u8 = (uint8_t*)gfx_info.RDRAM;
624 /* Starting location in the palettes */
625 uint32_t dwTMEMOffset = gDP.tiles[tileno].tmem - 256;
626 /* Number to copy */
627 uint32_t dwRDRAMOffset = 0;
628
629 TileAdditionalInfo *tileinfo = &gRDP.tilesinfo[tileno];
630 gDPTile *tile = &gDP.tiles[tileno];
631
632 tileinfo->bForceWrapS = tileinfo->bForceWrapT = tileinfo->bForceClampS = tileinfo->bForceClampT = false;
633
634 tileinfo->hilite_sl = tile->lrs = uls;
635 tileinfo->hilite_tl = tile->lrt = ult;
636 tile->uls = lrs;
637 tile->ult = lrt;
638 tileinfo->bSizeIsValid = true;
639
640 tileinfo->lastTileCmd = CMD_LOADTLUT;
641
642 dwCount = (lrs - uls)+1;
643 dwRDRAMOffset = (uls + ult*g_TI.dwWidth )*2;
644 uint32_t dwPalAddress = g_TI.dwAddr + dwRDRAMOffset;
645
646 /* Copy PAL to the PAL memory */
647 uint16_t *srcPal = (uint16_t*)(rdram_u8 + (dwPalAddress& (g_dwRamSize-1)) );
648 for (uint32_t i=0; i<dwCount && i<0x100; i++)
649 g_wRDPTlut[(i+dwTMEMOffset)^1] = srcPal[i^1];
650
651 if( options.bUseFullTMEM )
652 {
653 for (uint32_t i=0; i<dwCount && i+tile->tmem < 0x200; i++)
654 *(uint16_t*)(&g_Tmem.g_Tmem64bit[tile->tmem + i]) = srcPal[i^1];
655 }
656
657 extern bool RevTlutTableNeedUpdate;
658 RevTlutTableNeedUpdate = true;
659 g_TxtLoadBy = CMD_LOADTLUT;
660 }
661