2 Copyright (C) 2002 Rice1964
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.
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.
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.
20 // Texture related ucode
27 uint32 g_TmemFlag[16];
28 void SetTmemFlag(uint32 tmemAddr, uint32 size);
29 bool IsTmemFlagValid(uint32 tmemAddr);
30 uint32 GetValidTmemInfoIndex(uint32 tmemAddr);
32 void EnhanceTexture(TxtrCacheEntry *pEntry);
33 void MirrorTexture(uint32 tileno, TxtrCacheEntry *pEntry);
34 void LoadHiresTexture( TxtrCacheEntry &entry );
37 extern TMEMLoadMapInfo g_tmemInfo0; // Info for Tmem=0
38 extern TMEMLoadMapInfo g_tmemInfo1; // Info for Tmem=0x100
42 /************************************************************************/
44 /************************************************************************/
45 uint32 sizeShift[4] = {2,1,0,0};
46 uint32 sizeIncr[4] = {3,1,0,0};
47 uint32 sizeBytes[4] = {0,1,2,4};
49 inline uint32 Txl2Words(uint32 width, uint32 size)
51 if( size == TXT_SIZE_4b )
52 return max(1, width/16);
54 return max(1, width*sizeBytes[size]/8);
57 inline uint32 CalculateImgSize(uint32 width, uint32 height, uint32 size)
59 //(((width)*(height) + siz##_INCR) >> siz##_SHIFT) -1
60 return (((width)*(height) + sizeIncr[size]) >> sizeShift[size]) -1;
64 inline uint32 CalculateDXT(uint32 txl2words)
66 //#define CALC_DXT(width, b_txl) ((2048 + TXL2WORDS(width, b_txl) - 1) / TXL2WORDS(width, b_txl))
67 if( txl2words == 0 ) return 1;
68 else return (2048+txl2words-1)/txl2words;
71 inline uint32 ReverseDXT(uint32 val, uint32 lrs, uint32 width, uint32 size)
73 //#define TXL2WORDS(txls, b_txl) MAX(1, ((txls)*(b_txl)/8))
74 if( val == 0x800 ) return 1;
76 unsigned int low = 2047/val;
77 if( CalculateDXT(low) > val ) low++;
78 unsigned int high = 2047/(val-1);
80 if( low == high ) return low;
82 for( unsigned int i=low; i<=high; i++ )
84 if( Txl2Words(width, size) == i )
88 return (low+high)/2; //dxt = 2047 / (dxt-1);
91 // The following inline assemble routines are borrowed from glN64, I am too tired to
92 // rewrite these routine by myself.
95 inline void UnswapCopy( void *src, void *dest, uint32 numBytes )
97 #if !defined(__GNUC__) && !defined(NO_ASM)
101 mov esi, dword ptr [src]
102 mov edi, dword ptr [dest]
105 and ebx, 3 // ebx = number of leading bytes
118 LeadingLoop: // Copies leading bytes, in reverse order (un-swaps)
119 mov al, byte ptr [esi]
120 mov byte ptr [edi], al
127 mov ecx, dword ptr [numBytes]
128 sub ecx, ebx // Don't copy what's already been copied
132 // add ecx, 3 // Round up to nearest dword
135 cmp ecx, 0 // If there's nothing to do, don't do it
136 jle StartTrailingLoop
138 // Copies from source to destination, bswap-ing first
140 mov eax, dword ptr [esi]
142 mov dword ptr [edi], eax
153 mov al, byte ptr [esi]
154 mov byte ptr [edi], al
160 #elif defined(__GNUC__) && defined(__x86_64__) && !defined(NO_ASM)
161 asm volatile(" movl %k1, %%ebx \n"
167 " cmpl %k2, %%ebx \n"
169 " movl %k2, %%ebx \n"
171 " movl %%ebx, %%ecx \n"
174 " movb (%1), %%al \n"
175 " movb %%al, (%0) \n"
182 " movl %k2, %%ecx \n"
183 " subl %%ebx, %%ecx \n"
184 " movl %%ecx, %%ebx \n"
190 " movl (%1), %%eax \n"
192 " movl %%eax, (%0) \n"
202 " movb (%1), %%al \n"
203 " movb %%al, (%0) \n"
209 :"+r"(dest), "+r"(src)
211 : "memory", "cc", "%rax", "%rbx", "%rcx"
214 #elif !defined(NO_ASM)
215 unsigned int saveEBX;
216 asm volatile ("mov %%ebx, %2 \n"
221 "mov %%esi, %%ebx \n"
222 "and $3, %%ebx \n" // ebx = number of leading bytes
225 "jz 2f \n" //jz StartDWordLoop
230 "jle 0f \n" //jle NotGreater
232 "0: \n" //NotGreater:
233 "mov %%ebx, %%ecx \n"
235 "1: \n" //LeadingLoop: // Copies leading bytes, in reverse order (un-swaps)
236 "mov (%%esi), %%al \n"
237 "mov %%al, (%%edi) \n"
240 "loop 1b \n" //loop LeadingLoop
243 "2: \n" //StartDWordLoop:
245 "sub %%ebx, %%ecx \n" // Don't copy what's already been copied
247 "mov %%ecx, %%ebx \n"
249 // add ecx, 3 // Round up to nearest dword
252 "cmp $0, %%ecx \n" // If there's nothing to do, don't do it
253 "jle 4f \n" //jle StartTrailingLoop
255 // Copies from source to destination, bswap-ing first
257 "mov (%%esi), %%eax \n"
259 "mov %%eax, (%%edi) \n"
262 "loop 3b \n" //loop DWordLoop
263 "4: \n" //StartTrailingLoop:
266 "mov %%ebx, %%ecx \n"
269 "5: \n" //TrailingLoop:
270 "mov (%%esi), %%al \n"
271 "mov %%al, (%%edi) \n"
274 "loop 5b \n" //loop TrailingLoop
278 : "m"(src), "m"(dest), "m"(saveEBX), "m"(numBytes)
279 : "memory", "cc", "%ecx", "%esi", "%edi", "%eax"
284 inline void DWordInterleave( void *mem, uint32 numDWords )
286 #if !defined(__GNUC__) && !defined(NO_ASM)
288 mov esi, dword ptr [mem]
289 mov edi, dword ptr [mem]
291 mov ecx, dword ptr [numDWords]
293 mov eax, dword ptr [esi]
294 mov ebx, dword ptr [edi]
295 mov dword ptr [esi], ebx
296 mov dword ptr [edi], eax
299 loop DWordInterleaveLoop
301 #elif defined(__GNUC__) && defined(__x86_64__) && !defined(NO_ASM)
303 " movl (%0), %%eax \n"
304 " movl 8(%0), %%ebx \n"
305 " movl %%eax, 8(%0) \n"
306 " movl %%ebx, (%0) \n"
310 : "+r"(mem), "+r"(numDWords)
312 : "memory", "cc", "%rax", "%rbx"
314 #elif !defined(NO_ASM)
315 unsigned int saveEBX;
316 asm volatile ("mov %%ebx, %2 \n"
321 "0: \n" //DWordInterleaveLoop:
322 "mov (%%esi), %%eax \n"
323 "mov (%%edi), %%ebx \n"
324 "mov %%ebx, (%%esi) \n"
325 "mov %%eax, (%%edi) \n"
328 "loop 0b \n" //loop DWordInterleaveLoop
331 : "m"(mem), "m"(numDWords), "m"(saveEBX)
332 : "memory", "cc", "%esi", "%edi", "%ecx", "%eax"
337 inline void QWordInterleave( void *mem, uint32 numDWords )
339 #if !defined(__GNUC__) && !defined(NO_ASM)
342 // Interleave the line on the qword
343 mov esi, dword ptr [mem]
344 mov edi, dword ptr [mem]
346 mov ecx, dword ptr [numDWords]
349 mov eax, dword ptr [esi]
350 mov ebx, dword ptr [edi]
351 mov dword ptr [esi], ebx
352 mov dword ptr [edi], eax
355 mov eax, dword ptr [esi]
356 mov ebx, dword ptr [edi]
357 mov dword ptr [esi], ebx
358 mov dword ptr [edi], eax
361 loop QWordInterleaveLoop
363 #elif defined(__GNUC__) && defined(__x86_64__) && !defined(NO_ASM)
364 asm volatile(" shr $1, %k1 \n"
366 " mov (%0), %%rax \n"
367 " mov 8(%0), %%rbx \n"
368 " mov %%rax, 8(%0) \n"
369 " mov %%rbx, (%0) \n"
373 : "+r"(mem), "+r"(numDWords)
375 : "memory", "cc", "%rax", "%rbx"
377 #elif !defined(NO_ASM) // GCC assumed
379 unsigned int saveEBX;
380 asm volatile("mov %%ebx, %2 \n"
381 // Interleave the line on the qword
387 "0: \n" //QWordInterleaveLoop:
388 "mov (%%esi), %%eax \n"
389 "mov (%%edi), %%ebx \n"
390 "mov %%ebx, (%%esi) \n"
391 "mov %%eax, (%%edi) \n"
394 "mov (%%esi), %%eax \n"
395 "mov (%%edi), %%ebx \n"
396 "mov %%ebx, (%%esi) \n"
397 "mov %%eax, (%%edi) \n"
400 "loop 0b \n" //loop QWordInterleaveLoop
403 : "m"(mem), "m"(numDWords), "m"(saveEBX)
404 : "memory", "cc", "%esi", "%edi", "%ecx", "%eax"
409 inline uint32 swapdword( uint32 value )
411 #if defined(__INTEL_COMPILER) && !defined(NO_ASM)
414 mov eax, dword ptr [value]
417 #elif defined(__GNUC__) && defined(__x86_64__) && !defined(NO_ASM)
418 asm volatile(" bswapl %k0 \n"
424 #elif defined(__GNUC__) && defined(__i386__) && !defined(NO_ASM)
425 asm volatile("bswapl %0 \n"
432 return ((value & 0xff000000) >> 24) |
433 ((value & 0x00ff0000) >> 8) |
434 ((value & 0x0000ff00) << 8) |
435 ((value & 0x000000ff) << 24);
439 inline uint16 swapword( uint16 value )
441 #if defined(__INTEL_COMPILER) && !defined(NO_ASM)
444 mov ax, word ptr [value]
447 #elif defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__)) && !defined(NO_ASM)
448 asm volatile("xchg %%al, %%ah \n"
455 return ((value & 0xff00) >> 8) |
456 ((value & 0x00ff) << 8);
461 void ComputeTileDimension(int mask, int clamp, int mirror, int width, uint32 &widthToCreate, uint32 &widthToLoad)
463 int maskwidth = mask > 0 ? (1<<mask) : 0;
464 widthToCreate = widthToLoad = width;
468 if( width > maskwidth )
472 // clamp is not used, so just use the dwTileMaskWidth as the real width
473 widthToCreate = widthToLoad = maskwidth;
477 widthToLoad = maskwidth;
478 //gti.WidthToCreate = dwTileWidth;
479 // keep the current WidthToCreate, we will do mirror/wrap
480 // during texture loading, not during rendering
483 else if( width < maskwidth )
485 // dwTileWidth < dwTileMaskWidth
489 if( maskwidth%width == 0 )
491 if( (maskwidth/width)%2 == 0 || mirror == 0 )
494 // gti.WidthToLoad = gti.WidthToCreate = gRDP.tiles[tileno].dwWidth = dwTileWidth
498 widthToCreate = maskwidth;
503 widthToCreate = maskwidth;
504 //widthToLoad = maskwidth;
509 widthToCreate = maskwidth;
510 //widthToLoad = maskwidth;
513 else // dwTileWidth == dwTileMaskWidth
517 // Some hacks, to limit the image size
520 if( maskwidth / width >= 2 )
522 widthToCreate = width;
528 bool conkerSwapHack=false;
530 bool CalculateTileSizes_method_2(int tileno, TMEMLoadMapInfo *info, TxtrInfo >i)
532 Tile &tile = gRDP.tiles[tileno];
533 Tile &loadtile = gRDP.tiles[RDP_TXT_LOADTILE];
537 // Now Initialize the texture dimension
540 if( info->bSetBy == CMD_LOADTILE )
542 if( tile.sl >= tile.sh )
544 dwTileWidth = info->dwWidth; // From SetTImage
545 dwTileWidth = dwTileWidth << info->dwSize >> tile.dwSize;
549 dwTileWidth= tile.sh - tile.sl + 1;
552 if( tile.tl >= tile.th )
554 dwTileHeight= info->th - info->tl + 1;
558 dwTileHeight= tile.th - tile.tl + 1;
563 if( tile.dwMaskS == 0 || tile.bClampS )
565 dwTileWidth = tile.hilite_sh - tile.hilite_sl +1;
566 if( dwTileWidth < tile.sh - tile.sl +1 )
567 dwTileWidth = tile.sh - tile.sl +1;
568 if( dwTileWidth <= 0 )
570 DebuggerAppendMsg("Error");
575 if( tile.dwMaskS < 8 )
576 dwTileWidth = (1 << tile.dwMaskS );
577 else if( tile.dwLine )
579 dwTileWidth = (tile.dwLine<<5)>>tile.dwSize;
583 if( tile.sl <= tile.sh )
585 dwTileWidth = tile.sh - tile.sl +1;
587 else if( loadtile.sl <= loadtile.sh )
589 dwTileWidth = loadtile.sh - loadtile.sl +1;
593 dwTileWidth = tile.sh - tile.sl +1;
598 if( tile.dwMaskT == 0 || tile.bClampT )
600 dwTileHeight= tile.hilite_th - tile.hilite_tl +1;
601 if( dwTileHeight < tile.th - tile.tl +1 )
602 dwTileHeight = tile.th - tile.tl +1;
604 if( dwTileHeight <= 0 )
606 DebuggerAppendMsg("Error");
611 if( tile.dwMaskT < 8 )
612 dwTileHeight = (1 << tile.dwMaskT );
613 else if( tile.tl <= tile.th )
615 dwTileHeight = tile.th - tile.tl +1;
617 else if( loadtile.tl <= loadtile.th )
619 dwTileHeight = loadtile.th - loadtile.tl +1;
623 dwTileHeight = tile.th - tile.tl +1;
628 int dwTileMaskWidth = tile.dwMaskS > 0 ? (1 << tile.dwMaskS ) : 0;
629 int dwTileMaskHeight = tile.dwMaskT > 0 ? (1 << tile.dwMaskT ) : 0;
631 if( dwTileWidth < 0 || dwTileHeight < 0)
633 if( dwTileMaskWidth > 0 )
634 dwTileWidth = dwTileMaskWidth;
635 else if( dwTileWidth < 0 )
636 dwTileWidth = -dwTileWidth;
638 if( dwTileMaskHeight > 0 )
639 dwTileHeight = dwTileMaskHeight;
640 else if( dwTileHeight < 0 )
641 dwTileHeight = -dwTileHeight;
646 if( dwTileWidth-dwTileMaskWidth == 1 && dwTileMaskWidth && dwTileHeight-dwTileMaskHeight == 1 && dwTileMaskHeight )
648 // Hack for Mario Kart
653 ComputeTileDimension(tile.dwMaskS, tile.bClampS,
654 tile.bMirrorS, dwTileWidth, gti.WidthToCreate, gti.WidthToLoad);
655 tile.dwWidth = gti.WidthToCreate;
657 ComputeTileDimension(tile.dwMaskT, tile.bClampT,
658 tile.bMirrorT, dwTileHeight, gti.HeightToCreate, gti.HeightToLoad);
659 tile.dwHeight = gti.HeightToCreate;
662 if( gti.WidthToCreate < gti.WidthToLoad )
663 TRACE2("Check me, width to create = %d, width to load = %d", gti.WidthToCreate, gti.WidthToLoad);
664 if( gti.HeightToCreate < gti.HeightToLoad )
665 TRACE2("Check me, height to create = %d, height to load = %d", gti.HeightToCreate, gti.HeightToLoad);
669 gti.bSwapped = info->bSwapped;
671 if( info->bSetBy == CMD_LOADTILE )
673 // It was a tile - the pitch is set by LoadTile
674 dwPitch = info->dwWidth<<(info->dwSize-1);
678 dwPitch = 1024; // Hack for Bust-A-Move
681 else //Set by LoadBlock
683 // It was a block load - the pitch is determined by the tile size
684 if (info->dxt == 0 || info->dwTmem != tile.dwTMem )
686 dwPitch = tile.dwLine << 3;
688 if( info->dwTmem != tile.dwTMem && info->dxt != 0 && info->dwSize == TXT_SIZE_16b && tile.dwSize == TXT_SIZE_4b )
689 conkerSwapHack = true;
693 uint32 DXT = info->dxt;
696 DXT = ReverseDXT(info->dxt, info->sh, dwTileWidth, tile.dwSize);
701 if (tile.dwSize == TXT_SIZE_32b)
702 dwPitch = tile.dwLine << 4;
705 gti.Pitch = tile.dwPitch = dwPitch;
707 if( (gti.WidthToLoad < gti.WidthToCreate || tile.bSizeIsValid == false) && tile.dwMaskS > 0 && gti.WidthToLoad != (unsigned int)dwTileMaskWidth &&
708 info->bSetBy == CMD_LOADBLOCK )
709 //if( (gti.WidthToLoad < gti.WidthToCreate ) && tile.dwMaskS > 0 && gti.WidthToLoad != dwTileMaskWidth &&
710 // info->bSetBy == CMD_LOADBLOCK )
712 // We have got the pitch now, recheck the width_to_load
713 uint32 pitchwidth = dwPitch<<1>>tile.dwSize;
714 if( pitchwidth == (unsigned int)dwTileMaskWidth )
716 gti.WidthToLoad = pitchwidth;
719 if( (gti.HeightToLoad < gti.HeightToCreate || tile.bSizeIsValid == false) && tile.dwMaskT > 0 && gti.HeightToLoad != (unsigned int)dwTileMaskHeight &&
720 info->bSetBy == CMD_LOADBLOCK )
721 //if( (gti.HeightToLoad < gti.HeightToCreate ) && tile.dwMaskT > 0 && gti.HeightToLoad != dwTileMaskHeight &&
722 // info->bSetBy == CMD_LOADBLOCK )
724 //uint32 pitchwidth = dwPitch<<1>>tile.dwSize;
725 uint32 pitchHeight = (info->dwTotalWords<<1)/dwPitch;
726 if( pitchHeight == (unsigned int)dwTileMaskHeight || gti.HeightToLoad == 1 )
728 gti.HeightToLoad = pitchHeight;
731 if( gti.WidthToCreate < gti.WidthToLoad ) gti.WidthToCreate = gti.WidthToLoad;
732 if( gti.HeightToCreate < gti.HeightToLoad ) gti.HeightToCreate = gti.HeightToLoad;
734 if( info->bSetBy == CMD_LOADTILE )
736 gti.LeftToLoad = (info->sl<<info->dwSize)>>tile.dwSize;
737 gti.TopToLoad = info->tl;
741 gti.LeftToLoad = (info->sl<<info->dwSize)>>tile.dwSize;
742 gti.TopToLoad = (info->tl<<info->dwSize)>>tile.dwSize;
745 uint32 total64BitWordsToLoad = (gti.HeightToLoad*gti.WidthToLoad)>>(4-tile.dwSize);
746 if( total64BitWordsToLoad + tile.dwTMem > 0x200 )
748 //TRACE0("Warning: texture loading tmem is over range");
749 if( gti.WidthToLoad > gti.HeightToLoad )
751 uint32 newheight = (dwPitch << 1 )>> tile.dwSize;
752 tile.dwWidth = gti.WidthToLoad = gti.WidthToCreate = min(newheight, (gti.WidthToLoad&0xFFFFFFFE));
753 tile.dwHeight = gti.HeightToCreate = gti.HeightToLoad = ((0x200 - tile.dwTMem) << (4-tile.dwSize)) / gti.WidthToLoad;
757 tile.dwHeight = gti.HeightToCreate = gti.HeightToLoad = info->dwTotalWords / ((gti.WidthToLoad << tile.dwSize) >> 1);
762 if( (info->dwTotalWords>>2) < total64BitWordsToLoad+tile.dwTMem-info->dwTmem - 4 )
765 if( (options.enableHackForGames == HACK_FOR_ZELDA||options.enableHackForGames == HACK_FOR_ZELDA_MM) && (unsigned int)tileno != gRSP.curTile )
770 if( total64BitWordsToLoad+tile.dwTMem-info->dwTmem <= 0x200 )
772 LOG_TEXTURE(TRACE4("Fix me, info is not covering this Tmem address,Info start: 0x%x, total=0x%x, Tmem start: 0x%x, total=0x%x",
773 info->dwTmem,info->dwTotalWords>>2, tile.dwTMem, total64BitWordsToLoad));
777 //Check memory boundary
778 if( gti.Address + gti.HeightToLoad*gti.Pitch >= g_dwRamSize )
780 WARNING(TRACE0("Warning: texture loading tmem is over range 3"));
781 gti.HeightToCreate = gti.HeightToLoad = tile.dwHeight = (g_dwRamSize-gti.Address)/gti.Pitch;
787 bool CalculateTileSizes_method_1(int tileno, TMEMLoadMapInfo *info, TxtrInfo >i)
789 Tile &tile = gRDP.tiles[tileno];
790 //Tile &loadtile = gRDP.tiles[RDP_TXT_LOADTILE];
792 // Now Initialize the texture dimension
793 int loadwidth, loadheight;
795 int maskwidth = tile.dwMaskS ? (1 << tile.dwMaskS ) : 0;
796 int maskheight = tile.dwMaskT ? (1 << tile.dwMaskT ) : 0;
797 int clampwidth = abs(tile.hilite_sh - tile.hilite_sl) +1;
798 int clampheight = abs(tile.hilite_th - tile.hilite_tl) +1;
799 int linewidth = tile.dwLine << (5 - tile.dwSize);
801 gti.bSwapped = info->bSwapped;
803 if( info->bSetBy == CMD_LOADTILE )
805 loadwidth = (abs(info->sh - info->sl) + 1) << info->dwSize >> tile.dwSize;
806 loadheight = (abs(info->th - info->tl) + 1) << info->dwSize >> tile.dwSize;
808 tile.dwPitch = info->dwWidth << info->dwSize >> 1;
809 if( tile.dwPitch == 0 ) tile.dwPitch = 1024; // Hack for Bust-A-Move
811 gti.LeftToLoad = (info->sl<<info->dwSize)>>tile.dwSize;
812 gti.TopToLoad = info->tl;
816 loadwidth = abs(tile.sh - tile.sl) +1;
819 loadwidth = maskwidth;
822 loadheight = abs(tile.th - tile.tl) +1;
825 loadheight = maskheight;
829 // It was a block load - the pitch is determined by the tile size
830 if (tile.dwSize == TXT_SIZE_32b)
831 tile.dwPitch = tile.dwLine << 4;
832 else if (info->dxt == 0 )
834 tile.dwPitch = tile.dwLine << 3;
836 if( info->dwTmem != tile.dwTMem && info->dxt != 0 && info->dwSize == TXT_SIZE_16b && tile.dwSize == TXT_SIZE_4b )
837 conkerSwapHack = true;
841 uint32 DXT = info->dxt;
844 DXT = ReverseDXT(info->dxt, info->sh, loadwidth, tile.dwSize);
846 tile.dwPitch = DXT << 3;
849 gti.LeftToLoad = (info->sl<<info->dwSize)>>tile.dwSize;
850 gti.TopToLoad = (info->tl<<info->dwSize)>>tile.dwSize;
853 if( options.enableHackForGames == HACK_FOR_MARIO_KART )
855 if( loadwidth-maskwidth == 1 && tile.dwMaskS )
858 if( loadheight%2 ) loadheight--;
861 if( loadheight-maskheight == 1 && tile.dwMaskT )
864 if(loadwidth%2) loadwidth--;
867 if( loadwidth - ((g_TI.dwWidth<<g_TI.dwSize)>>tile.dwSize) == 1 )
870 if( loadheight%2 ) loadheight--;
875 // Limit the texture size
876 if( g_curRomInfo.bUseSmallerTexture )
878 if( tile.dwMaskS && tile.bClampS )
882 if( clampwidth/maskwidth >= 2 )
884 clampwidth = maskwidth;
885 tile.bForceWrapS = true;
887 else if( clampwidth && maskwidth/clampwidth >= 2 )
889 maskwidth = clampwidth;
890 tile.bForceClampS = true;
895 if( clampwidth/maskwidth == 2 )
897 clampwidth = maskwidth*2;
898 tile.bForceWrapS = false;
900 else if( clampwidth/maskwidth > 2 )
902 clampwidth = maskwidth*2;
903 tile.bForceWrapS = true;
908 if( tile.dwMaskT && tile.bClampT )
912 if( clampheight/maskheight >= 2 )
914 clampheight = maskheight;
915 tile.bForceWrapT = true;
917 else if( clampheight && maskheight/clampheight >= 2 )
919 maskwidth = clampwidth;
920 tile.bForceClampT = true;
925 if( clampheight/maskheight == 2 )
927 clampheight = maskheight*2;
928 tile.bForceWrapT = false;
930 else if( clampheight/maskheight >= 2 )
932 clampheight = maskheight*2;
933 tile.bForceWrapT = true;
940 //if( clampwidth > linewidth ) clampwidth = linewidth;
941 if( clampwidth > 512 && clampheight > 512 )
943 if( clampwidth > maskwidth && maskwidth && clampheight > 256 ) clampwidth = maskwidth;
944 if( clampheight > maskheight && maskheight && clampheight > 256 ) clampheight = maskheight;
947 if( tile.dwMaskS > 8 && tile.dwMaskT > 8 )
949 maskwidth = loadwidth;
950 maskheight = loadheight;
954 if( tile.dwMaskS > 10 )
955 maskwidth = loadwidth;
956 if( tile.dwMaskT > 10 )
957 maskheight = loadheight;
961 gti.Pitch = tile.dwPitch;
963 if( tile.dwMaskS == 0 || tile.bClampS )
965 gti.WidthToLoad = linewidth ? min( linewidth, maskwidth ? min(clampwidth,maskwidth) : clampwidth ) : clampwidth;
966 if( tile.dwMaskS && clampwidth < maskwidth )
967 tile.dwWidth = gti.WidthToCreate = clampwidth;
969 tile.dwWidth = gti.WidthToCreate = max(clampwidth,maskwidth);
973 gti.WidthToLoad = loadwidth > 2 ? min(loadwidth,maskwidth) : maskwidth;
974 if( linewidth ) gti.WidthToLoad = min( linewidth, (int)gti.WidthToLoad );
975 tile.dwWidth = gti.WidthToCreate = maskwidth;
978 if( tile.dwMaskT == 0 || tile.bClampT )
980 gti.HeightToLoad = maskheight ? min(clampheight,maskheight) : clampheight;
981 if( tile.dwMaskT && clampheight < maskheight )
982 tile.dwHeight = gti.HeightToCreate = clampheight;
984 tile.dwHeight = gti.HeightToCreate = max(clampheight,maskheight);
988 gti.HeightToLoad = loadheight > 2 ? min(loadheight,maskheight) : maskheight;
989 tile.dwHeight = gti.HeightToCreate = maskheight;
992 if( options.enableHackForGames == HACK_FOR_MARIO_KART )
994 if( gti.WidthToLoad - ((g_TI.dwWidth<<g_TI.dwSize)>>tile.dwSize) == 1 )
997 if( gti.HeightToLoad%2 ) gti.HeightToLoad--;
1002 uint32 total64BitWordsToLoad = (gti.HeightToLoad*gti.WidthToLoad)>>(4-tile.dwSize);
1003 if( total64BitWordsToLoad + tile.dwTMem > 0x200 )
1005 //TRACE0("Warning: texture loading tmem is over range");
1006 if( gti.WidthToLoad > gti.HeightToLoad )
1008 uint32 newheight = (tile.dwPitch << 1 )>> tile.dwSize;
1009 tile.dwWidth = gti.WidthToLoad = gti.WidthToCreate = min(newheight, (gti.WidthToLoad&0xFFFFFFFE));
1010 tile.dwHeight = gti.HeightToCreate = gti.HeightToLoad = ((0x200 - tile.dwTMem) << (4-tile.dwSize)) / gti.WidthToLoad;
1014 tile.dwHeight = gti.HeightToCreate = gti.HeightToLoad = info->dwTotalWords / ((gti.WidthToLoad << tile.dwSize) >> 1);
1019 if( (info->dwTotalWords>>2) < total64BitWordsToLoad+tile.dwTMem-info->dwTmem - 4 )
1022 if( (options.enableHackForGames == HACK_FOR_ZELDA||options.enableHackForGames == HACK_FOR_ZELDA_MM) && (unsigned int)tileno != gRSP.curTile )
1027 if( total64BitWordsToLoad+tile.dwTMem-info->dwTmem <= 0x200 )
1029 LOG_TEXTURE(TRACE4("Fix me, info is not covering this Tmem address,Info start: 0x%x, total=0x%x, Tmem start: 0x%x, total=0x%x",
1030 info->dwTmem,info->dwTotalWords>>2, tile.dwTMem, total64BitWordsToLoad));
1034 //Check memory boundary
1035 if( gti.Address + gti.HeightToLoad*gti.Pitch >= g_dwRamSize )
1037 WARNING(TRACE0("Warning: texture loading tmem is over range 3"));
1038 gti.HeightToCreate = gti.HeightToLoad = tile.dwHeight = (g_dwRamSize-gti.Address)/gti.Pitch;
1044 TxtrCacheEntry* LoadTexture(uint32 tileno)
1046 //TxtrCacheEntry *pEntry = NULL;
1049 Tile &tile = gRDP.tiles[tileno];
1051 // Retrieve the tile loading info
1052 uint32 infoTmemAddr = tile.dwTMem;
1053 TMEMLoadMapInfo *info = &g_tmemLoadAddrMap[infoTmemAddr];
1054 if( !IsTmemFlagValid(infoTmemAddr) )
1056 infoTmemAddr = GetValidTmemInfoIndex(infoTmemAddr);
1057 info = &g_tmemLoadAddrMap[infoTmemAddr];
1060 if( info->dwFormat != tile.dwFormat )
1062 // Check the tile format, hack for Zelda's road
1063 if( tileno != gRSP.curTile && tile.dwTMem == gRDP.tiles[gRSP.curTile].dwTMem &&
1064 tile.dwFormat != gRDP.tiles[gRSP.curTile].dwFormat )
1066 //TRACE1("Tile %d format is not matching the loaded texture format", tileno);
1071 gti = tile; // Copy tile info to textureInfo entry
1073 gti.TLutFmt = gRDP.otherMode.text_tlut <<RSP_SETOTHERMODE_SHIFT_TEXTLUT;
1074 if (gti.Format == TXT_FMT_CI && gti.TLutFmt == TLUT_FMT_NONE )
1075 gti.TLutFmt = TLUT_FMT_RGBA16; // Force RGBA
1077 gti.PalAddress = (uchar *) (&g_wRDPTlut[0]);
1078 if( !options.bUseFullTMEM && tile.dwSize == TXT_SIZE_4b )
1079 gti.PalAddress += 16 * 2 * tile.dwPalette;
1081 gti.Address = (info->dwLoadAddress+(tile.dwTMem-infoTmemAddr)*8) & (g_dwRamSize-1) ;
1082 gti.pPhysicalAddress = ((uint8*)g_pRDRAMu32)+gti.Address;
1083 gti.tileNo = tileno;
1085 if( g_curRomInfo.bTxtSizeMethod2 )
1087 if( !CalculateTileSizes_method_2(tileno, info, gti) )
1092 if( !CalculateTileSizes_method_1(tileno, info, gti) )
1098 TRACE0("Loading texture:\n");
1099 DebuggerAppendMsg("Left: %d, Top: %d, Width: %d, Height: %d, Size to Load (%d, %d)",
1100 gti.LeftToLoad, gti.TopToLoad, gti.WidthToCreate, gti.HeightToCreate, gti.WidthToLoad, gti.HeightToLoad);
1101 DebuggerAppendMsg("Pitch: %d, Addr: 0x%08x", gti.Pitch, gti.Address);
1104 // Option for faster loading tiles
1105 if( g_curRomInfo.bFastLoadTile && info->bSetBy == CMD_LOADTILE && ((gti.Pitch<<1)>>gti.Size) <= 0x400
1106 //&& ((gti.Pitch<<1)>>gti.Size) > 128 && status.primitiveType == PRIM_TEXTRECT
1109 uint32 idx = tileno-gRSP.curTile;
1110 status.LargerTileRealLeft[idx] = gti.LeftToLoad;
1112 gti.WidthToLoad = gti.WidthToCreate = ((gti.Pitch<<1)>>gti.Size);
1113 status.UseLargerTile[idx]=true;
1116 // Loading the textures by using texture cache manager
1117 return gTextureManager.GetTexture(>i, true, true, true); // Load the texture by using texture cache
1120 void PrepareTextures()
1122 if( gRDP.textureIsChanged || !currentRomOptions.bFastTexCRC ||
1123 CRender::g_pRender->m_pColorCombiner->m_pDecodedMux->m_ColorTextureFlag[0] ||
1124 CRender::g_pRender->m_pColorCombiner->m_pDecodedMux->m_ColorTextureFlag[1] )
1126 status.UseLargerTile[0]=false;
1127 status.UseLargerTile[1]=false;
1130 if( CRender::g_pRender->IsTexel0Enable() || gRDP.otherMode.cycle_type == CYCLE_TYPE_COPY )
1131 tilenos[0] = gRSP.curTile;
1135 if( gRSP.curTile<7 && CRender::g_pRender->IsTexel1Enable() )
1136 tilenos[1] = gRSP.curTile+1;
1141 for( int i=0; i<2; i++ )
1143 if( tilenos[i] < 0 ) continue;
1145 if( CRender::g_pRender->m_pColorCombiner->m_pDecodedMux->m_ColorTextureFlag[i] )
1147 TxtrCacheEntry *pEntry = gTextureManager.GetConstantColorTexture(CRender::g_pRender->m_pColorCombiner->m_pDecodedMux->m_ColorTextureFlag[i]);
1148 CRender::g_pRender->SetCurrentTexture( tilenos[i], pEntry->pTexture, 4, 4, pEntry);
1152 TxtrCacheEntry *pEntry = LoadTexture(tilenos[i]);
1153 if (pEntry && pEntry->pTexture )
1155 if( pEntry->txtrBufIdx <= 0 )
1157 if( pEntry->pEnhancedTexture && pEntry->dwEnhancementFlag == TEXTURE_EXTERNAL && !options.bLoadHiResTextures )
1159 SAFE_DELETE(pEntry->pEnhancedTexture);
1162 if( pEntry->pEnhancedTexture == NULL )
1164 MirrorTexture(tilenos[i], pEntry);;
1167 if( options.bLoadHiResTextures && (pEntry->pEnhancedTexture == NULL || pEntry->dwEnhancementFlag < TEXTURE_EXTERNAL ) )
1169 LoadHiresTexture(*pEntry);
1172 if( pEntry->pEnhancedTexture == NULL || (pEntry->dwEnhancementFlag != options.textureEnhancement && pEntry->dwEnhancementFlag < TEXTURE_EXTERNAL ) )
1174 EnhanceTexture(pEntry);
1178 CRender::g_pRender->SetCurrentTexture( tilenos[i],
1179 (pEntry->pEnhancedTexture)?pEntry->pEnhancedTexture:pEntry->pTexture,
1180 pEntry->ti.WidthToLoad, pEntry->ti.HeightToLoad, pEntry);
1184 pEntry = gTextureManager.GetBlackTexture();
1185 CRender::g_pRender->SetCurrentTexture( tilenos[i], pEntry->pTexture, 4, 4, pEntry);
1186 _VIDEO_DisplayTemporaryMessage("Fail to load texture, use black to replace");
1192 gRDP.textureIsChanged = false;
1196 extern uint32 g_TxtLoadBy;;
1198 void DLParser_LoadTLut(Gfx *gfx)
1200 gRDP.textureIsChanged = true;
1202 uint32 tileno = gfx->loadtile.tile;
1203 uint32 uls = gfx->loadtile.sl/4;
1204 uint32 ult = gfx->loadtile.tl/4;
1205 uint32 lrs = gfx->loadtile.sh/4;
1206 uint32 lrt = gfx->loadtile.th/4;
1209 uint32 dwTLutFmt = (gRDP.otherModeH >> RSP_SETOTHERMODE_SHIFT_TEXTLUT)&0x3;
1213 // starting location in the palettes
1214 uint32 dwTMEMOffset = gRDP.tiles[tileno].dwTMem - 256;
1216 dwCount = ((uint16)((gfx->words.w1) >> 14) & 0x03FF) + 1;
1217 uint32 dwRDRAMOffset = 0;
1219 Tile &tile = gRDP.tiles[tileno];
1220 tile.bForceWrapS = tile.bForceWrapT = tile.bForceClampS = tile.bForceClampT = false;
1222 tile.hilite_sl = tile.sl = uls;
1223 tile.hilite_tl = tile.tl = ult;
1226 tile.bSizeIsValid = true;
1228 tile.lastTileCmd = CMD_LOADTLUT;
1232 if((((gfx->words.w0)>>12)&0x3) != 0 || (((gfx->words.w0))&0x3) != 0 || (((gfx->words.w1)>>12)&0x3) != 0 || (((gfx->words.w1))&0x3) != 0)
1233 TRACE0("Load tlut, sl,tl,sh,th are not integers");
1237 dwCount = (lrs - uls)+1;
1238 dwRDRAMOffset = (uls + ult*g_TI.dwWidth )*2;
1239 uint32 dwPalAddress = g_TI.dwAddr + dwRDRAMOffset;
1241 //Copy PAL to the PAL memory
1242 uint16 *srcPal = (uint16*)(g_pRDRAMu8 + (dwPalAddress& (g_dwRamSize-1)) );
1243 for (uint32 i=0; i<dwCount && i<0x100; i++)
1244 g_wRDPTlut[(i+dwTMEMOffset)^1] = srcPal[i^1];
1246 if( options.bUseFullTMEM )
1248 for (uint32 i=0; i<dwCount && i+tile.dwTMem<0x200; i++)
1249 *(uint16*)(&g_Tmem.g_Tmem64bit[tile.dwTMem+i]) = srcPal[i^1];
1254 DebuggerAppendMsg("LoadTLut Tile: %d Start: 0x%X+0x%X, Count: 0x%X\nFmt is %s, TMEM=0x%X\n",
1255 tileno, g_TI.dwAddr, dwRDRAMOffset, dwCount,textluttype[dwTLutFmt],
1258 DebuggerAppendMsg(" :ULS: 0x%X, ULT:0x%X, LRS: 0x%X, LRT:0x%X\n", uls, ult, lrs,lrt);
1260 if( pauseAtNext && eventToPause == NEXT_LOADTLUT && dwCount == 16 )
1263 strcpy(buf, "Data:\n");
1264 for(uint32 i=0; i<16; i++ )
1266 sprintf(buf+strlen(buf), "%04X ", g_wRDPTlut[dwTMEMOffset+i]);
1268 sprintf(buf+strlen(buf), "\n");
1270 sprintf(buf+strlen(buf), "\n");
1275 DEBUGGER_PAUSE_COUNT_N(NEXT_LOADTLUT);
1277 extern bool RevTlutTableNeedUpdate;
1278 RevTlutTableNeedUpdate = true;
1279 g_TxtLoadBy = CMD_LOADTLUT;
1283 void DLParser_LoadBlock(Gfx *gfx)
1285 gRDP.textureIsChanged = true;
1287 uint32 tileno = gfx->loadtile.tile;
1288 uint32 uls = gfx->loadtile.sl;
1289 uint32 ult = gfx->loadtile.tl;
1290 uint32 lrs = gfx->loadtile.sh;
1291 uint32 dxt = gfx->loadtile.th; // 1.11 fixed point
1293 Tile &tile = gRDP.tiles[tileno];
1294 tile.bForceWrapS = tile.bForceWrapT = tile.bForceClampS = tile.bForceClampT = false;
1296 uint32 size = lrs+1;
1297 if( tile.dwSize == TXT_SIZE_32b ) size<<=1;
1299 SetTmemFlag(tile.dwTMem, size>>2);
1301 TMEMLoadMapInfo &info = g_tmemLoadAddrMap[tile.dwTMem];
1303 info.bSwapped = (dxt == 0? TRUE : FALSE);
1305 info.sl = tile.hilite_sl = tile.sl = uls;
1306 info.sh = tile.hilite_sh = tile.sh = lrs;
1307 info.tl = tile.tl = ult;
1308 info.th = tile.th = dxt;
1309 tile.bSizeIsValid = false;
1311 for( int i=0; i<8; i++ )
1313 if( tile.dwTMem == tile.dwTMem )
1314 tile.lastTileCmd = CMD_LOADBLOCK;
1317 info.dwLoadAddress = g_TI.dwAddr;
1318 info.bSetBy = CMD_LOADBLOCK;
1320 info.dwLine = tile.dwLine;
1322 info.dwFormat = g_TI.dwFormat;
1323 info.dwSize = g_TI.dwSize;
1324 info.dwWidth = g_TI.dwWidth;
1325 info.dwTotalWords = size;
1326 info.dwTmem = tile.dwTMem;
1328 if( gRDP.tiles[tileno].dwTMem == 0 )
1332 memcpy(&g_tmemInfo0, &info, sizeof(TMEMLoadMapInfo) );
1333 g_tmemInfo0.dwTotalWords = size>>2;
1338 memcpy(&g_tmemInfo1, &info, sizeof(TMEMLoadMapInfo) );
1339 g_tmemInfo1.dwTotalWords = size>>2;
1342 else if( tile.dwTMem == 0x100 )
1346 memcpy(&g_tmemInfo1, &info, sizeof(TMEMLoadMapInfo) );
1347 g_tmemInfo1.dwTotalWords = size>>2;
1351 g_TxtLoadBy = CMD_LOADBLOCK;
1354 if( options.bUseFullTMEM )
1356 uint32 bytes = (lrs + 1) << tile.dwSize >> 1;
1357 uint32 address = g_TI.dwAddr + ult * g_TI.bpl + (uls << g_TI.dwSize >> 1);
1358 if ((bytes == 0) || ((address + bytes) > g_dwRamSize) || (((tile.dwTMem << 3) + bytes) > 4096))
1362 uint64* src = (uint64*)(g_pRDRAMu8+address);
1363 uint64* dest = &g_Tmem.g_Tmem64bit[tile.dwTMem];
1367 void (*Interleave)( void *mem, uint32 numDWords );
1369 uint32 line = (2047 + dxt) / dxt;
1370 uint32 bpl = line << 3;
1371 uint32 height = bytes / bpl;
1373 if (tile.dwSize == TXT_SIZE_32b)
1374 Interleave = QWordInterleave;
1376 Interleave = DWordInterleave;
1378 for (uint32 y = 0; y < height; y++)
1380 UnswapCopy( src, dest, bpl );
1381 if (y & 1) Interleave( dest, line );
1388 UnswapCopy( src, dest, bytes );
1392 LOG_UCODE(" Tile:%d (%d,%d - %d) DXT:0x%04x\n", tileno, uls, ult, lrs, dxt);
1396 DebuggerAppendMsg("LoadBlock:%d (%d,%d,%d) DXT:0x%04x(%X)\n",
1397 tileno, uls, ult, (((gfx->words.w1)>>12)&0x0FFF), dxt, ((gfx->words.w1)&0x0FFF));
1400 DEBUGGER_PAUSE_COUNT_N(NEXT_TEXTURE_CMD);
1403 void swap(uint32 &a, uint32 &b)
1409 void DLParser_LoadTile(Gfx *gfx)
1411 gRDP.textureIsChanged = true;
1413 uint32 tileno = gfx->loadtile.tile;
1414 uint32 uls = gfx->loadtile.sl/4;
1415 uint32 ult = gfx->loadtile.tl/4;
1416 uint32 lrs = gfx->loadtile.sh/4;
1417 uint32 lrt = gfx->loadtile.th/4;
1419 Tile &tile = gRDP.tiles[tileno];
1420 tile.bForceWrapS = tile.bForceWrapT = tile.bForceClampS = tile.bForceClampT = false;
1422 if (lrt < ult) swap(lrt, ult);
1423 if (lrs < uls) swap(lrs, uls);
1425 tile.hilite_sl = tile.sl = uls;
1426 tile.hilite_tl = tile.tl = ult;
1427 tile.hilite_sh = tile.sh = lrs;
1428 tile.hilite_th = tile.th = lrt;
1429 tile.bSizeIsValid = true;
1431 // compute block height, and bpl of source and destination
1432 uint32 bpl = (lrs - uls + 1) << tile.dwSize >> 1;
1433 uint32 height = lrt - ult + 1;
1434 uint32 line = tile.dwLine;
1435 if (tile.dwSize == TXT_SIZE_32b) line <<= 1;
1437 if (((tile.dwTMem << 3) + line * height) > 4096) // check destination ending point (TMEM is 4k bytes)
1440 if( options.bUseFullTMEM )
1442 void (*Interleave)( void *mem, uint32 numDWords );
1449 if( options.enableHackForGames == HACK_FOR_BUST_A_MOVE )
1451 g_TI.bpl = 1024; // Hack for Bust-A-Move
1455 TRACE0("Warning: g_TI.bpl = 0" );
1459 address = g_TI.dwAddr + tile.tl * g_TI.bpl + (tile.sl << g_TI.dwSize >> 1);
1460 src = &g_pRDRAMu8[address];
1461 dest = &g_Tmem.g_Tmem64bit[tile.dwTMem];
1463 if ((address + height * bpl) > g_dwRamSize) // check source ending point
1468 // Line given for 32-bit is half what it seems it should since they split the
1469 // high and low words. I'm cheating by putting them together.
1470 if (tile.dwSize == TXT_SIZE_32b)
1472 Interleave = QWordInterleave;
1476 Interleave = DWordInterleave;
1479 if( tile.dwLine == 0 )
1485 for (y = 0; y < height; y++)
1487 UnswapCopy( src, dest, bpl );
1488 if (y & 1) Interleave( dest, line );
1496 for( int i=0; i<8; i++ )
1498 if( gRDP.tiles[i].dwTMem == tile.dwTMem )
1499 gRDP.tiles[i].lastTileCmd = CMD_LOADTILE;
1502 uint32 size = line * height;
1503 SetTmemFlag(tile.dwTMem,size );
1507 DebuggerAppendMsg("LoadTile:%d (%d,%d) -> (%d,%d) [%d x %d]\n",
1508 tileno, uls, ult, lrs, lrt,
1509 (lrs - uls)+1, (lrt - ult)+1);
1513 DEBUGGER_PAUSE_COUNT_N(NEXT_TEXTURE_CMD);
1515 LOG_UCODE(" Tile:%d (%d,%d) -> (%d,%d) [%d x %d]",
1516 tileno, uls, ult, lrs, lrt,
1517 (lrs - uls)+1, (lrt - ult)+1);
1519 TMEMLoadMapInfo &info = g_tmemLoadAddrMap[tile.dwTMem];
1521 info.dwLoadAddress = g_TI.dwAddr;
1522 info.dwFormat = g_TI.dwFormat;
1523 info.dwSize = g_TI.dwSize;
1524 info.dwWidth = g_TI.dwWidth;
1532 info.dwLine = tile.dwLine;
1533 info.dwTmem = tile.dwTMem;
1534 info.dwTotalWords = size<<2;
1536 info.bSetBy = CMD_LOADTILE;
1537 info.bSwapped =FALSE;
1539 g_TxtLoadBy = CMD_LOADTILE;
1541 if( tile.dwTMem == 0 )
1545 memcpy(&g_tmemInfo0, &info, sizeof(TMEMLoadMapInfo) );
1546 g_tmemInfo0.dwTotalWords = size;
1551 memcpy(&g_tmemInfo1, &info, sizeof(TMEMLoadMapInfo) );
1552 g_tmemInfo1.dwTotalWords = size;
1555 else if( tile.dwTMem == 0x100 )
1559 memcpy(&g_tmemInfo1, &info, sizeof(TMEMLoadMapInfo) );
1560 g_tmemInfo1.dwTotalWords = size;
1566 const char *pszOnOff[2] = {"Off", "On"};
1568 void DLParser_SetTile(Gfx *gfx)
1570 gRDP.textureIsChanged = true;
1572 uint32 tileno = gfx->settile.tile;
1573 Tile &tile = gRDP.tiles[tileno];
1574 tile.bForceWrapS = tile.bForceWrapT = tile.bForceClampS = tile.bForceClampT = false;
1576 lastSetTile = tileno;
1578 tile.dwFormat = gfx->settile.fmt;
1579 tile.dwSize = gfx->settile.siz;
1580 tile.dwLine = gfx->settile.line;
1581 tile.dwTMem = gfx->settile.tmem;
1583 tile.dwPalette = gfx->settile.palette;
1584 tile.bClampT = gfx->settile.ct;
1585 tile.bMirrorT = gfx->settile.mt;
1586 tile.dwMaskT = gfx->settile.maskt;
1587 tile.dwShiftT = gfx->settile.shiftt;
1588 tile.bClampS = gfx->settile.cs;
1589 tile.bMirrorS = gfx->settile.ms;
1590 tile.dwMaskS = gfx->settile.masks;
1591 tile.dwShiftS = gfx->settile.shifts;
1594 tile.fShiftScaleS = 1.0f;
1597 if( tile.dwShiftS > 10 )
1599 tile.fShiftScaleS = (float)(1 << (16 - tile.dwShiftS));
1603 tile.fShiftScaleS = (float)1.0f/(1 << tile.dwShiftS);
1607 tile.fShiftScaleT = 1.0f;
1610 if( tile.dwShiftT > 10 )
1612 tile.fShiftScaleT = (float)(1 << (16 - tile.dwShiftT));
1616 tile.fShiftScaleT = (float)1.0f/(1 << tile.dwShiftT);
1622 if( tile.dwMaskS > 0 && tile.dwMaskT > 0 && tile.dwMaskS < 8 && tile.dwMaskT < 8 )
1624 tile.sh = tile.sl + (1<<tile.dwMaskS);
1625 tile.th = tile.tl + (1<<tile.dwMaskT);
1626 tile.hilite_sl = tile.sl;
1627 tile.hilite_tl = tile.tl;
1631 tile.lastTileCmd = CMD_SETTILE;
1635 DebuggerAppendMsg("SetTile:%d Fmt: %s/%s Line:%d TMem:0x%04x Palette:%d\n",
1636 tileno, pszImgFormat[tile.dwFormat], pszImgSize[tile.dwSize],
1637 tile.dwLine, tile.dwTMem, tile.dwPalette);
1638 DebuggerAppendMsg(" S: Clamp: %s Mirror:%s Mask:0x%x Shift:0x%x\n",
1639 pszOnOff[tile.bClampS],pszOnOff[tile.bMirrorS],
1640 tile.dwMaskS, tile.dwShiftS);
1641 DebuggerAppendMsg(" T: Clamp: %s Mirror:%s Mask:0x%x Shift:0x%x\n",
1642 pszOnOff[tile.bClampT],pszOnOff[tile.bMirrorT],
1643 tile.dwMaskT, tile.dwShiftT);
1646 DEBUGGER_PAUSE_COUNT_N(NEXT_TEXTURE_CMD);
1648 LOG_UCODE(" Tile:%d Fmt: %s/%s Line:%d TMem:0x%04x Palette:%d",
1649 tileno, pszImgFormat[tile.dwFormat], pszImgSize[tile.dwSize],
1650 tile.dwLine, tile.dwTMem, tile.dwPalette);
1651 LOG_UCODE(" S: Clamp: %s Mirror:%s Mask:0x%x Shift:0x%x",
1652 pszOnOff[tile.bClampS],pszOnOff[tile.bMirrorS],
1653 tile.dwMaskS, tile.dwShiftS);
1654 LOG_UCODE(" T: Clamp: %s Mirror:%s Mask:0x%x Shift:0x%x",
1655 pszOnOff[tile.bClampT],pszOnOff[tile.bMirrorT],
1656 tile.dwMaskT, tile.dwShiftT);
1659 void DLParser_SetTileSize(Gfx *gfx)
1661 gRDP.textureIsChanged = true;
1663 uint32 tileno = gfx->loadtile.tile;
1664 int sl = gfx->loadtile.sl;
1665 int tl = gfx->loadtile.tl;
1666 int sh = gfx->loadtile.sh;
1667 int th = gfx->loadtile.th;
1669 Tile &tile = gRDP.tiles[tileno];
1670 tile.bForceWrapS = tile.bForceWrapT = tile.bForceClampS = tile.bForceClampT = false;
1672 if( options.bUseFullTMEM )
1674 tile.bSizeIsValid = true;
1675 tile.hilite_sl = tile.sl = sl / 4;
1676 tile.hilite_tl = tile.tl = tl / 4;
1677 tile.hilite_sh = tile.sh = sh / 4;
1678 tile.hilite_th = tile.th = th / 4;
1680 tile.fhilite_sl = tile.fsl = sl / 4.0f;
1681 tile.fhilite_tl = tile.ftl = tl / 4.0f;
1682 tile.fhilite_sh = tile.fsh = sh / 4.0f;
1683 tile.fhilite_th = tile.fth = th / 4.0f;
1685 tile.lastTileCmd = CMD_SETTILE_SIZE;
1689 if( tile.lastTileCmd != CMD_SETTILE_SIZE )
1691 tile.bSizeIsValid = true;
1692 if( sl/4 > sh/4 || tl/4 > th/4 || (sh == 0 && tile.dwShiftS==0 && th == 0 && tile.dwShiftT ==0 ) )
1695 if( sl != 0 || tl != 0 || sh != 0 || th != 0 )
1697 if( tile.dwMaskS==0 || tile.dwMaskT==0 )
1698 TRACE0("Check me, setTileSize is not correct");
1701 tile.bSizeIsValid = false;
1703 tile.hilite_sl = tile.sl = sl / 4;
1704 tile.hilite_tl = tile.tl = tl / 4;
1705 tile.hilite_sh = tile.sh = sh / 4;
1706 tile.hilite_th = tile.th = th / 4;
1708 tile.fhilite_sl = tile.fsl = sl / 4.0f;
1709 tile.fhilite_tl = tile.ftl = tl / 4.0f;
1710 tile.fhilite_sh = tile.fsh = sh / 4.0f;
1711 tile.fhilite_th = tile.fth = th / 4.0f;
1713 tile.lastTileCmd = CMD_SETTILE_SIZE;
1717 tile.fhilite_sh = tile.fsh;
1718 tile.fhilite_th = tile.fth;
1719 tile.fhilite_sl = tile.fsl = (sl>0x7ff ? (sl-0xfff) : sl)/4.0f;
1720 tile.fhilite_tl = tile.ftl = (tl>0x7ff ? (tl-0xfff) : tl)/4.0f;
1722 tile.hilite_sl = sl>0x7ff ? (sl-0xfff) : sl;
1723 tile.hilite_tl = tl>0x7ff ? (tl-0xfff) : tl;
1724 tile.hilite_sl /= 4;
1725 tile.hilite_tl /= 4;
1726 tile.hilite_sh = sh/4;
1727 tile.hilite_th = th/4;
1729 tile.lastTileCmd = CMD_SETTILE_SIZE;
1735 DebuggerAppendMsg("SetTileSize:%d (%d/4,%d/4) -> (%d/4,%d/4) [%d x %d]\n",
1736 tileno, sl, tl, sh, th,
1737 ((sh/4) - (sl/4)) + 1, ((th/4) - (tl/4)) + 1);
1739 DEBUGGER_PAUSE_COUNT_N(NEXT_TEXTURE_CMD);
1741 LOG_UCODE(" Tile:%d (%d,%d) -> (%d,%d) [%d x %d]",
1742 tileno, sl/4, tl/4, sh/4, th/4,
1743 ((sh/4) - (sl/4)) + 1, ((th/4) - (tl/4)) + 1);
1746 extern const char *pszImgFormat[8];// = {"RGBA", "YUV", "CI", "IA", "I", "?1", "?2", "?3"};
1747 extern const char *pszImgSize[4];// = {"4", "8", "16", "32"};
1748 void DLParser_SetTImg(Gfx *gfx)
1750 gRDP.textureIsChanged = true;
1752 g_TI.dwFormat = gfx->setimg.fmt;
1753 g_TI.dwSize = gfx->setimg.siz;
1754 g_TI.dwWidth = gfx->setimg.width + 1;
1755 g_TI.dwAddr = RSPSegmentAddr((gfx->setimg.addr));
1756 g_TI.bpl = g_TI.dwWidth << g_TI.dwSize >> 1;
1759 if( g_TI.dwAddr == 0x00ffffff)
1761 TRACE0("Check me here in setTimg");
1764 LOG_TEXTURE(TRACE4("SetTImage: 0x%08x Fmt: %s/%s Width in Pixel: %d\n", g_TI.dwAddr,
1765 pszImgFormat[g_TI.dwFormat], pszImgSize[g_TI.dwSize], g_TI.dwWidth));
1767 DEBUGGER_PAUSE_COUNT_N(NEXT_TEXTURE_CMD);
1769 LOG_UCODE("Image: 0x%08x Fmt: %s/%s Width in Pixel: %d", g_TI.dwAddr,
1770 pszImgFormat[g_TI.dwFormat], pszImgSize[g_TI.dwSize], g_TI.dwWidth);
1774 void DLParser_TexRect(Gfx *gfx)
1776 //Gtexrect *gtextrect = (Gtexrect *)gfx;
1778 if( !status.bCIBufferIsRendered ) g_pFrameBufferManager->ActiveTextureBuffer();
1780 status.primitiveType = PRIM_TEXTRECT;
1782 // This command used 128bits, and not 64 bits. This means that we have to look one
1783 // Command ahead in the buffer, and update the PC.
1784 uint32 dwPC = gDlistStack[gDlistStackPointer].pc; // This points to the next instruction
1785 uint32 dwCmd2 = *(uint32 *)(g_pRDRAMu8 + dwPC+4);
1786 uint32 dwCmd3 = *(uint32 *)(g_pRDRAMu8 + dwPC+4+8);
1787 uint32 dwHalf1 = *(uint32 *)(g_pRDRAMu8 + dwPC);
1788 uint32 dwHalf2 = *(uint32 *)(g_pRDRAMu8 + dwPC+8);
1790 if( options.enableHackForGames == HACK_FOR_ALL_STAR_BASEBALL || options.enableHackForGames == HACK_FOR_MLB )
1792 if( ((dwHalf1>>24) == 0xb4 || (dwHalf1>>24) == 0xb3 || (dwHalf1>>24) == 0xb2 || (dwHalf1>>24) == 0xe1) &&
1793 ((dwHalf2>>24) == 0xb4 || (dwHalf2>>24) == 0xb3 || (dwHalf2>>24) == 0xb2 || (dwHalf2>>24) == 0xf1) )
1795 // Increment PC so that it points to the right place
1796 gDlistStack[gDlistStackPointer].pc += 16;
1800 // Hack for some games, All_Star_Baseball_2000
1801 gDlistStack[gDlistStackPointer].pc += 8;
1807 dwCmd2 = (((dwHalf1>>12)&0x03FF)<<17) | (((dwHalf1)&0x03FF)<<1);
1812 gDlistStack[gDlistStackPointer].pc += 16;
1816 // Hack for Mario Tennis
1817 if( !status.bHandleN64RenderTexture && g_CI.dwAddr == g_ZI.dwAddr )
1823 LOG_UCODE("0x%08x: %08x %08x", dwPC, *(uint32 *)(g_pRDRAMu8 + dwPC+0), *(uint32 *)(g_pRDRAMu8 + dwPC+4));
1824 LOG_UCODE("0x%08x: %08x %08x", dwPC+8, *(uint32 *)(g_pRDRAMu8 + dwPC+8), *(uint32 *)(g_pRDRAMu8 + dwPC+8+4));
1826 uint32 dwXH = (((gfx->words.w0)>>12)&0x0FFF)/4;
1827 uint32 dwYH = (((gfx->words.w0) )&0x0FFF)/4;
1828 uint32 tileno = ((gfx->words.w1)>>24)&0x07;
1829 uint32 dwXL = (((gfx->words.w1)>>12)&0x0FFF)/4;
1830 uint32 dwYL = (((gfx->words.w1) )&0x0FFF)/4;
1831 uint16 uS = (uint16)( dwCmd2>>16)&0xFFFF;
1832 uint16 uT = (uint16)( dwCmd2 )&0xFFFF;
1833 uint16 uDSDX = (uint16)(( dwCmd3>>16)&0xFFFF);
1834 uint16 uDTDY = (uint16)(( dwCmd3 )&0xFFFF);
1837 if( (int)dwXL >= gRDP.scissor.right || (int)dwYL >= gRDP.scissor.bottom || (int)dwXH < gRDP.scissor.left || (int)dwYH < gRDP.scissor.top )
1843 short s16S = *(short*)(&uS);
1844 short s16T = *(short*)(&uT);
1846 short s16DSDX = *(short*)(&uDSDX);
1847 short s16DTDY = *(short*)(&uDTDY);
1849 uint32 curTile = gRSP.curTile;
1850 ForceMainTextureIndex(tileno);
1852 float fS0 = s16S / 32.0f;
1853 float fT0 = s16T / 32.0f;
1855 float fDSDX = s16DSDX / 1024.0f;
1856 float fDTDY = s16DTDY / 1024.0f;
1858 uint32 cycletype = gRDP.otherMode.cycle_type;
1860 if (cycletype == CYCLE_TYPE_COPY)
1862 fDSDX /= 4.0f; // In copy mode 4 pixels are copied at once.
1866 else if (cycletype == CYCLE_TYPE_FILL)
1872 if( fDSDX == 0 ) fDSDX = 1;
1873 if( fDTDY == 0 ) fDTDY = 1;
1875 float fS1 = fS0 + (fDSDX * (dwXH - dwXL));
1876 float fT1 = fT0 + (fDTDY * (dwYH - dwYL));
1878 LOG_UCODE(" Tile:%d Screen(%d,%d) -> (%d,%d)", tileno, dwXL, dwYL, dwXH, dwYH);
1879 LOG_UCODE(" Tex:(%#5f,%#5f) -> (%#5f,%#5f) (DSDX:%#5f DTDY:%#5f)",
1880 fS0, fT0, fS1, fT1, fDSDX, fDTDY);
1883 float t0u0 = (fS0-gRDP.tiles[tileno].hilite_sl) * gRDP.tiles[tileno].fShiftScaleS;
1884 float t0v0 = (fT0-gRDP.tiles[tileno].hilite_tl) * gRDP.tiles[tileno].fShiftScaleT;
1885 float t0u1 = t0u0 + (fDSDX * (dwXH - dwXL))*gRDP.tiles[tileno].fShiftScaleS;
1886 float t0v1 = t0v0 + (fDTDY * (dwYH - dwYL))*gRDP.tiles[tileno].fShiftScaleT;
1888 if( dwXL==0 && dwYL==0 && dwXH==windowSetting.fViWidth-1 && dwYH==windowSetting.fViHeight-1 &&
1889 t0u0 == 0 && t0v0==0 && t0u1==0 && t0v1==0 )
1891 //Using TextRect to clear the screen
1895 if( status.bHandleN64RenderTexture && //status.bDirectWriteIntoRDRAM &&
1896 g_pRenderTextureInfo->CI_Info.dwFormat == gRDP.tiles[tileno].dwFormat &&
1897 g_pRenderTextureInfo->CI_Info.dwSize == gRDP.tiles[tileno].dwSize &&
1898 gRDP.tiles[tileno].dwFormat == TXT_FMT_CI && gRDP.tiles[tileno].dwSize == TXT_SIZE_8b )
1900 if( options.enableHackForGames == HACK_FOR_YOSHI )
1902 // Hack for Yoshi background image
1904 TexRectToFrameBuffer_8b(dwXL, dwYL, dwXH, dwYH, t0u0, t0v0, t0u1, t0v1, tileno);
1905 DEBUGGER_PAUSE_AT_COND_AND_DUMP_COUNT_N((eventToPause == NEXT_FLUSH_TRI || eventToPause == NEXT_TEXTRECT), {
1906 DebuggerAppendMsg("TexRect: tile=%d, X0=%d, Y0=%d, X1=%d, Y1=%d,\nfS0=%f, fT0=%f, ScaleS=%f, ScaleT=%f\n",
1907 gRSP.curTile, dwXL, dwYL, dwXH, dwYH, fS0, fT0, fDSDX, fDTDY);
1908 DebuggerAppendMsg("Pause after TexRect for Yoshi\n");
1914 if( frameBufferOptions.bUpdateCIInfo )
1917 TexRectToFrameBuffer_8b(dwXL, dwYL, dwXH, dwYH, t0u0, t0v0, t0u1, t0v1, tileno);
1920 if( !status.bDirectWriteIntoRDRAM )
1922 CRender::g_pRender->TexRect(dwXL, dwYL, dwXH, dwYH, fS0, fT0, fDSDX, fDTDY);
1924 status.dwNumTrisRendered += 2;
1930 CRender::g_pRender->TexRect(dwXL, dwYL, dwXH, dwYH, fS0, fT0, fDSDX, fDTDY);
1931 status.bFrameBufferDrawnByTriangles = true;
1933 status.dwNumTrisRendered += 2;
1937 if( status.bHandleN64RenderTexture ) g_pRenderTextureInfo->maxUsedHeight = max(g_pRenderTextureInfo->maxUsedHeight,(int)dwYH);
1939 ForceMainTextureIndex(curTile);
1943 void DLParser_TexRectFlip(Gfx *gfx)
1945 status.bCIBufferIsRendered = true;
1946 status.primitiveType = PRIM_TEXTRECTFLIP;
1948 // This command used 128bits, and not 64 bits. This means that we have to look one
1949 // Command ahead in the buffer, and update the PC.
1950 uint32 dwPC = gDlistStack[gDlistStackPointer].pc; // This points to the next instruction
1951 uint32 dwCmd2 = *(uint32 *)(g_pRDRAMu8 + dwPC+4);
1952 uint32 dwCmd3 = *(uint32 *)(g_pRDRAMu8 + dwPC+4+8);
1954 // Increment PC so that it points to the right place
1955 gDlistStack[gDlistStackPointer].pc += 16;
1957 uint32 dwXH = (((gfx->words.w0)>>12)&0x0FFF)/4;
1958 uint32 dwYH = (((gfx->words.w0) )&0x0FFF)/4;
1959 uint32 tileno = ((gfx->words.w1)>>24)&0x07;
1960 uint32 dwXL = (((gfx->words.w1)>>12)&0x0FFF)/4;
1961 uint32 dwYL = (((gfx->words.w1) )&0x0FFF)/4;
1962 uint32 dwS = ( dwCmd2>>16)&0xFFFF;
1963 uint32 dwT = ( dwCmd2 )&0xFFFF;
1964 int nDSDX = (int)(short)(( dwCmd3>>16)&0xFFFF);
1965 int nDTDY = (int)(short)(( dwCmd3 )&0xFFFF);
1967 uint32 curTile = gRSP.curTile;
1968 ForceMainTextureIndex(tileno);
1970 float fS0 = (float)dwS / 32.0f;
1971 float fT0 = (float)dwT / 32.0f;
1973 float fDSDX = (float)nDSDX / 1024.0f;
1974 float fDTDY = (float)nDTDY / 1024.0f;
1976 uint32 cycletype = gRDP.otherMode.cycle_type;
1978 if (cycletype == CYCLE_TYPE_COPY)
1980 fDSDX /= 4.0f; // In copy mode 4 pixels are copied at once.
1984 else if (cycletype == CYCLE_TYPE_FILL)
1990 float fS1 = fS0 + (fDSDX * (dwYH - dwYL));
1991 float fT1 = fT0 + (fDTDY * (dwXH - dwXL));
1993 LOG_UCODE(" Tile:%d (%d,%d) -> (%d,%d)",
1994 tileno, dwXL, dwYL, dwXH, dwYH);
1995 LOG_UCODE(" Tex:(%#5f,%#5f) -> (%#5f,%#5f) (DSDX:%#5f DTDY:%#5f)",
1996 fS0, fT0, fS1, fT1, fDSDX, fDTDY);
1999 float t0u0 = (fS0) * gRDP.tiles[tileno].fShiftScaleS-gRDP.tiles[tileno].sl;
2000 float t0v0 = (fT0) * gRDP.tiles[tileno].fShiftScaleT-gRDP.tiles[tileno].tl;
2001 float t0u1 = t0u0 + (fDSDX * (dwYH - dwYL))*gRDP.tiles[tileno].fShiftScaleS;
2002 float t0v1 = t0v0 + (fDTDY * (dwXH - dwXL))*gRDP.tiles[tileno].fShiftScaleT;
2004 CRender::g_pRender->TexRectFlip(dwXL, dwYL, dwXH, dwYH, t0u0, t0v0, t0u1, t0v1);
2005 status.dwNumTrisRendered += 2;
2007 if( status.bHandleN64RenderTexture ) g_pRenderTextureInfo->maxUsedHeight = max(g_pRenderTextureInfo->maxUsedHeight,int(dwYL+(dwXH-dwXL)));
2009 ForceMainTextureIndex(curTile);
2012 /************************************************************************/
2014 /************************************************************************/
2017 * There are 0x200's 64bits entry in TMEM
2018 * Usually, textures are loaded into TMEM at 0x0, and TLUT is loaded at 0x100
2019 * of course, the whole TMEM can be used by textures if TLUT is not used, and TLUT
2020 * can be at other address of TMEM.
2022 * We don't want to emulate TMEM by creating a block of memory for TMEM and load
2023 * everything into the block of memory, this will be slow.
2025 typedef struct TmemInfoEntry{
2029 TmemInfoEntry* next;
2032 const int tmenMaxEntry=20;
2033 TmemInfoEntry tmenEntryBuffer[20]={{0}};
2034 TmemInfoEntry *g_pTMEMInfo=NULL;
2035 TmemInfoEntry *g_pTMEMFreeList=tmenEntryBuffer;
2040 g_pTMEMFreeList=tmenEntryBuffer;
2042 for( i=0; i<tmenMaxEntry; i++ )
2044 tmenEntryBuffer[i].start=0;
2045 tmenEntryBuffer[i].length=0;
2046 tmenEntryBuffer[i].rdramAddr=0;
2047 tmenEntryBuffer[i].next = &(tmenEntryBuffer[i+1]);
2049 tmenEntryBuffer[i-1].next = NULL;
2052 void TMEM_SetBlock(uint32 tmemstart, uint32 length, uint32 rdramaddr)
2054 TmemInfoEntry *p=g_pTMEMInfo;
2058 // Move an entry from freelist and link it to the header
2059 p = g_pTMEMFreeList;
2060 g_pTMEMFreeList = g_pTMEMFreeList->next;
2062 p->start = tmemstart;
2064 p->rdramAddr = rdramaddr;
2069 while ( tmemstart > (p->start+p->length) )
2071 if( p->next != NULL ) {
2080 if ( p->start == tmemstart )
2082 // need to replace the block of 'p'
2083 // or append a new block depend the block lengths
2084 if( length == p->length )
2086 p->rdramAddr = rdramaddr;
2089 else if( length < p->length )
2091 TmemInfoEntry *newentry = g_pTMEMFreeList;
2092 g_pTMEMFreeList = g_pTMEMFreeList->next;
2094 newentry->length = p->length - length;
2095 newentry->next = p->next;
2096 newentry->rdramAddr = p->rdramAddr + p->length;
2097 newentry->start = p->start + p->length;
2101 p->rdramAddr = rdramaddr;
2104 else if( p->start > tmemstart )
2106 // p->start > tmemstart, need to insert the new block before 'p'
2107 TmemInfoEntry *newentry = g_pTMEMFreeList;
2108 g_pTMEMFreeList = g_pTMEMFreeList->next;
2110 if( length+tmemstart < p->start+p->length )
2112 newentry->length = p->length - length;
2113 newentry->next = p->next;
2114 newentry->rdramAddr = p->rdramAddr + p->length;
2115 newentry->start = p->start + p->length;
2119 p->rdramAddr = rdramaddr;
2120 p->start = tmemstart;
2122 else if( length+tmemstart == p->start+p->length )
2133 uint32 TMEM_GetRdramAddr(uint32 tmemstart, uint32 length)
2140 * New implementation of texture loading
2143 bool IsTmemFlagValid(uint32 tmemAddr)
2145 uint32 index = tmemAddr>>5;
2146 uint32 bitIndex = (tmemAddr&0x1F);
2147 return ((g_TmemFlag[index] & (1<<bitIndex))!=0);
2150 uint32 GetValidTmemInfoIndex(uint32 tmemAddr)
2153 uint32 index = tmemAddr>>5;
2154 uint32 bitIndex = (tmemAddr&0x1F);
2156 if ((g_TmemFlag[index] & (1<<bitIndex))!=0 ) //This address is valid
2160 for( uint32 x=index+1; x != 0; x-- )
2163 if( g_TmemFlag[i] != 0 )
2165 for( uint32 y=0x20; y != 0; y-- )
2168 if( (g_TmemFlag[i] & (1<<j)) != 0 )
2175 TRACE0("Error, check me");
2181 void SetTmemFlag(uint32 tmemAddr, uint32 size)
2183 uint32 index = tmemAddr>>5;
2184 uint32 bitIndex = (tmemAddr&0x1F);
2189 DebuggerAppendMsg("Check me: tmemaddr=%X, size=%x", tmemAddr, size);
2190 size = 0x200-tmemAddr;
2197 for( i=0; i< (size>>5); i++ )
2199 g_TmemFlag[index+i] = 0;
2202 if( (size&0x1F) != 0 )
2204 //ErrorMsg("Check me: tmemaddr=%X, size=%x", tmemAddr, size);
2205 g_TmemFlag[index+i] &= ~((1<<(size&0x1F))-1);
2208 g_TmemFlag[index] |= 1;
2212 if( bitIndex + size <= 0x1F )
2214 uint32 val = g_TmemFlag[index];
2215 uint32 mask = (1<<(bitIndex))-1;
2216 mask |= ~((1<<(bitIndex + size))-1);
2218 val |= (1<<bitIndex);
2219 g_TmemFlag[index] = val;
2223 //ErrorMsg("Check me: tmemaddr=%X, size=%x", tmemAddr, size);
2224 uint32 val = g_TmemFlag[index];
2225 uint32 mask = (1<<bitIndex)-1;
2227 val |= (1<<bitIndex);
2228 g_TmemFlag[index] = val;
2230 size -= (0x20-bitIndex);
2233 for( i=0; i< (size>>5); i++ )
2235 g_TmemFlag[index+i] = 0;
2238 if( (size&0x1F) != 0 )
2240 //ErrorMsg("Check me: tmemaddr=%X, size=%x", tmemAddr, size);
2241 g_TmemFlag[index+i] &= ~((1<<(size&0x1F))-1);