Rice GLES2 (from mupen64plus-ae) plugin. Compile but doesn't works well on the OpenPa...
[mupen64plus-pandora.git] / source / gles2rice / src / RDP_Texture.h
1 /*
2 Copyright (C) 2002 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 // Texture related ucode
21
22 #include <algorithm>
23
24 #include <stdlib.h>
25 #include "Render.h"
26
27 uint32 g_TmemFlag[16];
28 void SetTmemFlag(uint32 tmemAddr, uint32 size);
29 bool IsTmemFlagValid(uint32 tmemAddr);
30 uint32 GetValidTmemInfoIndex(uint32 tmemAddr);
31
32 void EnhanceTexture(TxtrCacheEntry *pEntry);
33 void MirrorTexture(uint32 tileno, TxtrCacheEntry *pEntry);
34 void LoadHiresTexture( TxtrCacheEntry &entry );
35
36
37 extern TMEMLoadMapInfo g_tmemInfo0;             // Info for Tmem=0
38 extern TMEMLoadMapInfo g_tmemInfo1;             // Info for Tmem=0x100
39
40 TmemType g_Tmem;
41
42 /************************************************************************/
43 /*                                                                      */
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};
48
49 inline uint32 Txl2Words(uint32 width, uint32 size)
50 {
51     if( size == TXT_SIZE_4b )
52         return max(1, width/16);
53     else
54         return max(1, width*sizeBytes[size]/8);
55 }
56
57 inline uint32 CalculateImgSize(uint32 width, uint32 height, uint32 size)
58 {
59     //(((width)*(height) + siz##_INCR) >> siz##_SHIFT) -1
60     return (((width)*(height) + sizeIncr[size]) >> sizeShift[size]) -1;
61 }
62
63
64 inline uint32 CalculateDXT(uint32 txl2words)
65 {
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;
69 }
70
71 inline uint32 ReverseDXT(uint32 val, uint32 lrs, uint32 width, uint32 size)
72 {
73     //#define TXL2WORDS(txls, b_txl)    MAX(1, ((txls)*(b_txl)/8))
74     if( val == 0x800 ) return 1;
75     
76     unsigned int low = 2047/val;
77     if( CalculateDXT(low) > val )   low++;
78     unsigned int high = 2047/(val-1);
79
80     if( low == high )   return low;
81
82     for( unsigned int i=low; i<=high; i++ )
83     {
84         if( Txl2Words(width, size) == i )
85             return i;
86     }
87
88     return  (low+high)/2;   //dxt = 2047 / (dxt-1);
89 }
90
91 // The following inline assemble routines are borrowed from glN64, I am too tired to
92 // rewrite these routine by myself.
93 // Rice, 02/24/2004
94
95 inline void UnswapCopy( void *src, void *dest, uint32 numBytes )
96 {
97 #if !defined(__GNUC__) && !defined(NO_ASM)
98     __asm
99     {
100         mov     ecx, 0
101         mov     esi, dword ptr [src]
102         mov     edi, dword ptr [dest]
103
104         mov     ebx, esi
105         and     ebx, 3          // ebx = number of leading bytes
106
107         cmp     ebx, 0
108         jz      StartDWordLoop
109         neg     ebx
110         add     ebx, 4
111
112         cmp     ebx, [numBytes]
113         jle     NotGreater
114         mov     ebx, [numBytes]
115 NotGreater:
116         mov     ecx, ebx
117             xor     esi, 3
118 LeadingLoop:                // Copies leading bytes, in reverse order (un-swaps)
119         mov     al, byte ptr [esi]
120         mov     byte ptr [edi], al
121         sub     esi, 1
122         add     edi, 1
123         loop    LeadingLoop
124         add     esi, 5
125
126 StartDWordLoop:
127         mov     ecx, dword ptr [numBytes]
128         sub     ecx, ebx        // Don't copy what's already been copied
129
130         mov     ebx, ecx
131         and     ebx, 3
132         //      add     ecx, 3          // Round up to nearest dword
133         shr     ecx, 2
134
135         cmp     ecx, 0          // If there's nothing to do, don't do it
136         jle     StartTrailingLoop
137
138         // Copies from source to destination, bswap-ing first
139 DWordLoop:
140         mov     eax, dword ptr [esi]
141         bswap   eax
142         mov     dword ptr [edi], eax
143         add     esi, 4
144         add     edi, 4
145         loop    DWordLoop
146 StartTrailingLoop:
147         cmp     ebx, 0
148         jz      Done
149         mov     ecx, ebx
150         xor     esi, 3
151
152 TrailingLoop:
153         mov     al, byte ptr [esi]
154         mov     byte ptr [edi], al
155         sub     esi, 1
156         add     edi, 1
157         loop    TrailingLoop
158 Done:
159     }
160 #elif defined(__GNUC__) && defined(__x86_64__) && !defined(NO_ASM)
161   asm volatile(" movl       %k1,   %%ebx      \n"
162                " andl        $3,   %%ebx      \n"
163                " cmpl        $0,   %%ebx      \n"
164                " jz          2f               \n"
165                " negl     %%ebx               \n"
166                " addl        $4,   %%ebx      \n"
167                " cmpl       %k2,   %%ebx      \n"
168                " jle         0f               \n"
169                " movl       %k2,   %%ebx      \n"
170                "0:                            \n"
171                " movl     %%ebx,   %%ecx      \n"
172                " xor         $3,      %1      \n"
173                "1:                            \n"
174                " movb      (%1),    %%al      \n"
175                " movb      %%al,    (%0)      \n"
176                " sub         $1,      %1      \n"
177                " add         $1,      %0      \n"
178                " decl     %%ecx               \n"
179                " jne         1b               \n"
180                " add         $5,      %1      \n"
181                "2:                            \n"
182                " movl       %k2,   %%ecx      \n"
183                " subl     %%ebx,   %%ecx      \n"
184                " movl     %%ecx,   %%ebx      \n"
185                " andl       $3,    %%ebx      \n"
186                " shrl       $2,    %%ecx      \n"
187                " cmpl       $0,    %%ecx      \n"
188                " jle        4f                \n"
189                "3:                            \n"
190                " movl     (%1),    %%eax      \n"
191                " bswapl  %%eax                \n"
192                " movl    %%eax,     (%0)      \n"
193                " add        $4,       %1      \n"
194                " add        $4,       %0      \n"
195                " decl    %%ecx                \n"
196                " jne        3b                \n"
197                "4:                            \n"
198                " cmpl       $0,    %%ebx      \n"
199                " jz         6f                \n"
200                " xor        $3,       %1      \n"
201                "5:                            \n"
202                " movb     (%1),     %%al      \n"
203                " movb     %%al,     (%0)      \n"
204                " sub        $1,       %1      \n"
205                " add        $1,       %0      \n"
206                " decl    %%ebx                \n"
207                " jne        5b                \n"
208                "6:                            \n"
209                :"+r"(dest), "+r"(src)
210                :"r"(numBytes)
211                : "memory", "cc", "%rax", "%rbx", "%rcx"
212                );
213
214 #elif !defined(NO_ASM)
215    unsigned int saveEBX;
216    asm volatile ("mov           %%ebx, %2         \n"
217          "mov       $0, %%ecx         \n"
218          "mov       %0, %%esi         \n"
219          "mov       %1, %%edi         \n"
220          
221          "mov       %%esi, %%ebx      \n"
222          "and       $3, %%ebx         \n"           // ebx = number of leading bytes
223          
224          "cmp       $0, %%ebx         \n"
225          "jz            2f                \n" //jz      StartDWordLoop
226          "neg       %%ebx             \n"
227          "add       $4, %%ebx         \n"
228          
229          "cmp       %3, %%ebx         \n"
230          "jle           0f                \n" //jle     NotGreater
231          "mov       %3, %%ebx         \n"
232          "0:                              \n" //NotGreater:
233          "mov       %%ebx, %%ecx      \n"
234          "xor       $3, %%esi         \n"
235          "1:                              \n" //LeadingLoop:                // Copies leading bytes, in reverse order (un-swaps)
236          "mov       (%%esi), %%al     \n"
237          "mov       %%al, (%%edi)     \n"
238          "sub       $1, %%esi         \n"
239          "add       $1, %%edi         \n"
240          "loop          1b                \n" //loop     LeadingLoop
241          "add       $5, %%esi         \n"
242          
243          "2:                              \n" //StartDWordLoop:
244          "mov       %3, %%ecx         \n"
245          "sub       %%ebx, %%ecx      \n"       // Don't copy what's already been copied
246          
247          "mov       %%ecx, %%ebx      \n"
248          "and       $3, %%ebx         \n"
249          //     add     ecx, 3          // Round up to nearest dword
250          "shr       $2, %%ecx         \n"
251          
252          "cmp       $0, %%ecx         \n"           // If there's nothing to do, don't do it
253          "jle           4f                \n" //jle     StartTrailingLoop
254          
255          // Copies from source to destination, bswap-ing first
256          "3:                              \n" //DWordLoop:
257          "mov       (%%esi), %%eax    \n"
258          "bswap %%eax                     \n"
259          "mov       %%eax, (%%edi)    \n"
260          "add       $4, %%esi         \n"
261          "add       $4, %%edi         \n"
262          "loop          3b                \n" //loop    DWordLoop
263          "4:                              \n" //StartTrailingLoop:
264          "cmp       $0, %%ebx         \n"
265          "jz            6f                \n" //jz      Done
266          "mov       %%ebx, %%ecx      \n"
267          "xor       $3, %%esi         \n"
268          
269          "5:                              \n" //TrailingLoop:
270          "mov       (%%esi), %%al     \n"
271          "mov       %%al, (%%edi)     \n"
272          "sub       $1, %%esi         \n"
273          "add       $1, %%edi         \n"
274          "loop          5b                \n" //loop    TrailingLoop
275          "6:                              \n" //Done:
276          "mov           %2, %%ebx         \n"
277          :
278          : "m"(src), "m"(dest), "m"(saveEBX), "m"(numBytes)
279          : "memory", "cc", "%ecx", "%esi", "%edi", "%eax"
280          );
281 #endif
282 }
283
284 inline void DWordInterleave( void *mem, uint32 numDWords )
285 {
286 #if !defined(__GNUC__) && !defined(NO_ASM)
287     __asm {
288         mov     esi, dword ptr [mem]
289         mov     edi, dword ptr [mem]
290         add     edi, 4
291         mov     ecx, dword ptr [numDWords]
292 DWordInterleaveLoop:
293         mov     eax, dword ptr [esi]
294         mov     ebx, dword ptr [edi]
295         mov     dword ptr [esi], ebx
296         mov     dword ptr [edi], eax
297         add     esi, 8
298         add     edi, 8
299         loop    DWordInterleaveLoop
300     }
301 #elif defined(__GNUC__) && defined(__x86_64__) && !defined(NO_ASM)
302   asm volatile("0:                                 \n"
303                " movl     (%0),     %%eax          \n"
304                " movl    8(%0),     %%ebx          \n"
305                " movl    %%eax,     8(%0)          \n"
306                " movl    %%ebx,      (%0)          \n"
307                " add        $8,        %0          \n"
308                " decl      %k1                     \n"
309                " jne        0b                     \n"
310            : "+r"(mem), "+r"(numDWords)
311            :
312            : "memory", "cc", "%rax", "%rbx"
313            );
314 #elif !defined(NO_ASM)
315    unsigned int saveEBX;
316    asm volatile ("mov           %%ebx, %2          \n"
317          "mov       %0, %%esi          \n"
318          "mov       %0, %%edi          \n"
319          "add       $4, %%edi          \n"
320          "mov       %1, %%ecx          \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"
326          "add       $8, %%esi          \n"
327          "add       $8, %%edi          \n"
328          "loop          0b                 \n" //loop   DWordInterleaveLoop
329          "mov           %2, %%ebx          \n"
330          :
331          : "m"(mem), "m"(numDWords), "m"(saveEBX)
332          : "memory", "cc", "%esi", "%edi", "%ecx", "%eax"
333          );
334 #endif
335 }
336
337 inline void QWordInterleave( void *mem, uint32 numDWords )
338 {
339 #if !defined(__GNUC__) && !defined(NO_ASM)
340     __asm
341     {
342         // Interleave the line on the qword
343         mov     esi, dword ptr [mem]
344         mov     edi, dword ptr [mem]
345         add     edi, 8
346         mov     ecx, dword ptr [numDWords]
347         shr     ecx, 1
348 QWordInterleaveLoop:
349         mov     eax, dword ptr [esi]
350         mov     ebx, dword ptr [edi]
351         mov     dword ptr [esi], ebx
352         mov     dword ptr [edi], eax
353         add     esi, 4
354         add     edi, 4
355         mov     eax, dword ptr [esi]
356         mov     ebx, dword ptr [edi]
357         mov     dword ptr [esi], ebx
358         mov     dword ptr [edi], eax
359         add     esi, 12
360         add     edi, 12
361         loop    QWordInterleaveLoop
362     }
363 #elif defined(__GNUC__) && defined(__x86_64__) && !defined(NO_ASM)
364   asm volatile(" shr        $1,       %k1          \n"
365                "0:                                 \n"
366                " mov      (%0),     %%rax          \n"
367                " mov     8(%0),     %%rbx          \n"
368                " mov     %%rax,     8(%0)          \n"
369                " mov     %%rbx,      (%0)          \n"
370                " add       $16,        %0          \n"
371                " decl      %k1                     \n"
372                " jne        0b                     \n"
373            : "+r"(mem), "+r"(numDWords)
374            :
375            : "memory", "cc", "%rax", "%rbx"
376            );
377 #elif !defined(NO_ASM) // GCC assumed
378
379    unsigned int saveEBX;
380    asm volatile("mov            %%ebx, %2          \n"
381         // Interleave the line on the qword
382         "mov        %0, %%esi          \n"
383         "mov        %0, %%edi          \n"
384         "add        $8, %%edi          \n"
385         "mov        %1, %%ecx          \n"
386         "shr        $1, %%ecx          \n"
387         "0:                                \n" //QWordInterleaveLoop:
388         "mov        (%%esi), %%eax     \n"
389         "mov        (%%edi), %%ebx     \n"
390         "mov        %%ebx, (%%esi)     \n"
391         "mov        %%eax, (%%edi)     \n"
392         "add        $4, %%esi          \n"
393         "add        $4, %%edi          \n"
394         "mov        (%%esi), %%eax     \n"
395         "mov        (%%edi), %%ebx     \n"
396         "mov        %%ebx, (%%esi)     \n"
397         "mov        %%eax, (%%edi)     \n"
398         "add        $12, %%esi         \n"
399         "add        $12, %%edi         \n"
400         "loop           0b                 \n" //loop   QWordInterleaveLoop
401         "mov            %2, %%ebx          \n"
402         :
403         : "m"(mem), "m"(numDWords), "m"(saveEBX)
404         : "memory", "cc", "%esi", "%edi", "%ecx", "%eax"
405         );
406 #endif
407 }
408
409 inline uint32 swapdword( uint32 value )
410 {
411 #if defined(__INTEL_COMPILER) && !defined(NO_ASM)
412     __asm
413     {
414         mov     eax, dword ptr [value]
415         bswap   eax
416     }
417 #elif defined(__GNUC__) && defined(__x86_64__) && !defined(NO_ASM)
418   asm volatile(" bswapl %k0                    \n"
419                : "+r"(value)
420                :
421                :
422                );
423   return value;
424 #elif defined(__GNUC__) && defined(__i386__) && !defined(NO_ASM)
425   asm volatile("bswapl %0 \n"
426                : "+r"(value)
427                :
428                :
429                );
430    return value;
431 #else
432   return ((value & 0xff000000) >> 24) |
433          ((value & 0x00ff0000) >>  8) |
434          ((value & 0x0000ff00) <<  8) |
435          ((value & 0x000000ff) << 24);
436 #endif
437 }
438
439 inline uint16 swapword( uint16 value )
440 {
441 #if defined(__INTEL_COMPILER) && !defined(NO_ASM)
442     __asm
443     {
444         mov     ax, word ptr [value]
445         xchg    ah, al
446     }
447 #elif defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__)) && !defined(NO_ASM)
448   asm volatile("xchg  %%al, %%ah    \n"
449                : "+a"(value)
450                :
451                :
452                );
453   return value;
454 #else
455   return ((value & 0xff00) >> 8) |
456          ((value & 0x00ff) << 8);
457 #endif
458 }
459
460
461 void ComputeTileDimension(int mask, int clamp, int mirror, int width, uint32 &widthToCreate, uint32 &widthToLoad)
462 {
463     int maskwidth = mask > 0 ? (1<<mask) : 0;
464     widthToCreate = widthToLoad = width;
465
466     if( mask > 0 )
467     {
468         if( width > maskwidth )
469         {
470             if( clamp == 0 )
471             {
472                 // clamp is not used, so just use the dwTileMaskWidth as the real width
473                 widthToCreate = widthToLoad = maskwidth;
474             }
475             else
476             {
477                 widthToLoad = maskwidth;
478                 //gti.WidthToCreate = dwTileWidth;
479                 // keep the current WidthToCreate, we will do mirror/wrap
480                 // during texture loading, not during rendering
481             }
482         }
483         else if( width < maskwidth )
484         {
485             // dwTileWidth < dwTileMaskWidth
486
487             if( clamp == 0 )
488             {
489                 if( maskwidth%width == 0 )
490                 {
491                     if( (maskwidth/width)%2 == 0 || mirror == 0 )
492                     {
493                         // Do nothing
494                         // gti.WidthToLoad = gti.WidthToCreate = gRDP.tiles[tileno].dwWidth = dwTileWidth
495                     }
496                     else
497                     {
498                         widthToCreate = maskwidth;
499                     }
500                 }
501                 else
502                 {
503                     widthToCreate = maskwidth;
504                     //widthToLoad = maskwidth;
505                 }
506             }
507             else
508             {
509                 widthToCreate = maskwidth;
510                 //widthToLoad = maskwidth;
511             }
512         }
513         else // dwTileWidth == dwTileMaskWidth
514         {
515         }
516
517         // Some hacks, to limit the image size
518         if( mask >= 8 )
519         {
520             if( maskwidth / width >= 2 )
521             {
522                 widthToCreate = width;
523             }
524         }
525     }
526 }
527
528 bool conkerSwapHack=false;
529
530 bool CalculateTileSizes_method_2(int tileno, TMEMLoadMapInfo *info, TxtrInfo &gti)
531 {
532     Tile &tile = gRDP.tiles[tileno];
533     Tile &loadtile = gRDP.tiles[RDP_TXT_LOADTILE];
534
535     uint32 dwPitch;
536
537     // Now Initialize the texture dimension
538     int dwTileWidth;
539     int dwTileHeight;
540     if( info->bSetBy == CMD_LOADTILE )
541     {
542         if( tile.sl >= tile.sh )
543         {
544             dwTileWidth = info->dwWidth;    // From SetTImage
545             dwTileWidth = dwTileWidth << info->dwSize >> tile.dwSize;
546         }
547         else
548         {
549             dwTileWidth= tile.sh - tile.sl + 1;
550         }
551
552         if( tile.tl >= tile.th )
553         {
554             dwTileHeight= info->th - info->tl + 1;
555         }
556         else
557         {
558             dwTileHeight= tile.th - tile.tl + 1;
559         }
560     }
561     else
562     {
563         if( tile.dwMaskS == 0 || tile.bClampS )
564         {
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 )
569             {
570                 DebuggerAppendMsg("Error");
571             }
572         }
573         else
574         {
575             if( tile.dwMaskS < 8 )
576                 dwTileWidth = (1 << tile.dwMaskS );
577             else if( tile.dwLine )
578             {
579                 dwTileWidth = (tile.dwLine<<5)>>tile.dwSize;
580             }
581             else
582             {
583                 if( tile.sl <= tile.sh )
584                 {
585                     dwTileWidth = tile.sh - tile.sl +1;
586                 }
587                 else if( loadtile.sl <= loadtile.sh )
588                 {
589                     dwTileWidth = loadtile.sh - loadtile.sl +1;
590                 }
591                 else
592                 {
593                     dwTileWidth = tile.sh - tile.sl +1;
594                 }
595             }
596         }
597
598         if( tile.dwMaskT == 0 || tile.bClampT )
599         {
600             dwTileHeight= tile.hilite_th - tile.hilite_tl +1;
601             if( dwTileHeight < tile.th - tile.tl +1 )
602                 dwTileHeight = tile.th - tile.tl +1;
603
604             if( dwTileHeight <= 0 )
605             {
606                 DebuggerAppendMsg("Error");
607             }
608         }
609         else
610         {
611             if( tile.dwMaskT < 8 )
612                 dwTileHeight = (1 << tile.dwMaskT );
613             else if( tile.tl <= tile.th )
614             {
615                 dwTileHeight = tile.th - tile.tl +1;
616             }
617             else if( loadtile.tl <= loadtile.th )
618             {
619                 dwTileHeight = loadtile.th - loadtile.tl +1;
620             }
621             else
622             {
623                 dwTileHeight = tile.th - tile.tl +1;
624             }
625         }
626     }
627
628     int dwTileMaskWidth = tile.dwMaskS > 0 ? (1 << tile.dwMaskS ) : 0;
629     int dwTileMaskHeight = tile.dwMaskT > 0 ? (1 << tile.dwMaskT ) : 0;
630
631     if( dwTileWidth < 0 || dwTileHeight < 0)
632     {
633         if( dwTileMaskWidth > 0 )
634             dwTileWidth = dwTileMaskWidth;
635         else if( dwTileWidth < 0 )
636             dwTileWidth = -dwTileWidth;
637
638         if( dwTileMaskHeight > 0 )
639             dwTileHeight = dwTileMaskHeight;
640         else if( dwTileHeight < 0 )
641             dwTileHeight = -dwTileHeight;
642     }
643
644
645
646     if( dwTileWidth-dwTileMaskWidth == 1 && dwTileMaskWidth && dwTileHeight-dwTileMaskHeight == 1 && dwTileMaskHeight )
647     {
648         // Hack for Mario Kart
649         dwTileWidth--;
650         dwTileHeight--;
651     }
652
653     ComputeTileDimension(tile.dwMaskS, tile.bClampS,
654         tile.bMirrorS, dwTileWidth, gti.WidthToCreate, gti.WidthToLoad);
655     tile.dwWidth = gti.WidthToCreate;
656
657     ComputeTileDimension(tile.dwMaskT, tile.bClampT,
658         tile.bMirrorT, dwTileHeight, gti.HeightToCreate, gti.HeightToLoad);
659     tile.dwHeight = gti.HeightToCreate;
660
661 #ifdef DEBUGGER
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);
666 #endif
667
668
669     gti.bSwapped = info->bSwapped;
670
671     if( info->bSetBy == CMD_LOADTILE )
672     {
673         // It was a tile - the pitch is set by LoadTile
674         dwPitch = info->dwWidth<<(info->dwSize-1);
675
676         if( dwPitch == 0 )
677         {
678             dwPitch = 1024;     // Hack for Bust-A-Move
679         }
680     }
681     else    //Set by LoadBlock
682     {
683         // It was a block load - the pitch is determined by the tile size
684         if (info->dxt == 0 || info->dwTmem != tile.dwTMem )
685         {
686             dwPitch = tile.dwLine << 3;
687             gti.bSwapped = TRUE;
688             if( info->dwTmem != tile.dwTMem && info->dxt != 0 && info->dwSize == TXT_SIZE_16b && tile.dwSize == TXT_SIZE_4b )
689                 conkerSwapHack = true;
690         }
691         else
692         {
693             uint32 DXT = info->dxt;
694             if( info->dxt > 1 )
695             {
696                 DXT = ReverseDXT(info->dxt, info->sh, dwTileWidth, tile.dwSize);
697             }
698             dwPitch = DXT << 3;
699         }
700
701         if (tile.dwSize == TXT_SIZE_32b)
702             dwPitch = tile.dwLine << 4;
703     }
704
705     gti.Pitch = tile.dwPitch = dwPitch;
706
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 )
711     {
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 )
715         {
716             gti.WidthToLoad = pitchwidth;
717         }
718     }
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 )
723     {
724         //uint32 pitchwidth = dwPitch<<1>>tile.dwSize;
725         uint32 pitchHeight = (info->dwTotalWords<<1)/dwPitch;
726         if( pitchHeight == (unsigned int)dwTileMaskHeight || gti.HeightToLoad == 1 )
727         {
728             gti.HeightToLoad = pitchHeight;
729         }
730     }
731     if( gti.WidthToCreate < gti.WidthToLoad )   gti.WidthToCreate = gti.WidthToLoad;
732     if( gti.HeightToCreate < gti.HeightToLoad )     gti.HeightToCreate = gti.HeightToLoad;
733
734     if( info->bSetBy == CMD_LOADTILE )
735     {
736         gti.LeftToLoad = (info->sl<<info->dwSize)>>tile.dwSize;
737         gti.TopToLoad = info->tl;
738     }
739     else
740     {
741         gti.LeftToLoad = (info->sl<<info->dwSize)>>tile.dwSize;
742         gti.TopToLoad = (info->tl<<info->dwSize)>>tile.dwSize;
743     }
744
745     uint32 total64BitWordsToLoad = (gti.HeightToLoad*gti.WidthToLoad)>>(4-tile.dwSize);
746     if( total64BitWordsToLoad + tile.dwTMem > 0x200 )
747     {
748         //TRACE0("Warning: texture loading tmem is over range");
749         if( gti.WidthToLoad > gti.HeightToLoad )
750         {
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;
754         }
755         else
756         {
757             tile.dwHeight = gti.HeightToCreate = gti.HeightToLoad = info->dwTotalWords / ((gti.WidthToLoad << tile.dwSize) >> 1);
758         }
759     }
760
761     // Check the info
762     if( (info->dwTotalWords>>2) < total64BitWordsToLoad+tile.dwTMem-info->dwTmem - 4 )
763     {
764         // Hack here
765         if( (options.enableHackForGames == HACK_FOR_ZELDA||options.enableHackForGames == HACK_FOR_ZELDA_MM) && (unsigned int)tileno != gRSP.curTile )
766         {
767             return false;
768         }
769
770         if( total64BitWordsToLoad+tile.dwTMem-info->dwTmem <= 0x200 )
771         {
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));
774         }
775     }
776
777     //Check memory boundary
778     if( gti.Address + gti.HeightToLoad*gti.Pitch >= g_dwRamSize )
779     {
780         WARNING(TRACE0("Warning: texture loading tmem is over range 3"));
781         gti.HeightToCreate = gti.HeightToLoad = tile.dwHeight = (g_dwRamSize-gti.Address)/gti.Pitch;
782     }
783
784     return true;
785 }
786
787 bool CalculateTileSizes_method_1(int tileno, TMEMLoadMapInfo *info, TxtrInfo &gti)
788 {
789     Tile &tile = gRDP.tiles[tileno];
790     //Tile &loadtile = gRDP.tiles[RDP_TXT_LOADTILE];
791
792     // Now Initialize the texture dimension
793     int loadwidth, loadheight;
794
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);
800
801     gti.bSwapped = info->bSwapped;
802
803     if( info->bSetBy == CMD_LOADTILE )
804     {
805         loadwidth = (abs(info->sh - info->sl) + 1) << info->dwSize >> tile.dwSize;
806         loadheight = (abs(info->th - info->tl) + 1) << info->dwSize >> tile.dwSize;
807
808         tile.dwPitch = info->dwWidth << info->dwSize >> 1;
809         if( tile.dwPitch == 0 ) tile.dwPitch = 1024;        // Hack for Bust-A-Move
810
811         gti.LeftToLoad = (info->sl<<info->dwSize)>>tile.dwSize;
812         gti.TopToLoad = info->tl;
813     }
814     else
815     {
816         loadwidth = abs(tile.sh - tile.sl) +1;
817         if( tile.dwMaskS )  
818         {
819             loadwidth = maskwidth;
820         }
821
822         loadheight = abs(tile.th - tile.tl) +1;
823         if( tile.dwMaskT )  
824         {
825             loadheight = maskheight;
826         }
827
828
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 )
833         {
834             tile.dwPitch = tile.dwLine << 3;
835             gti.bSwapped = TRUE;
836             if( info->dwTmem != tile.dwTMem && info->dxt != 0 && info->dwSize == TXT_SIZE_16b && tile.dwSize == TXT_SIZE_4b )
837                 conkerSwapHack = true;
838         }
839         else
840         {
841             uint32 DXT = info->dxt;
842             if( info->dxt > 1 )
843             {
844                 DXT = ReverseDXT(info->dxt, info->sh, loadwidth, tile.dwSize);
845             }
846             tile.dwPitch = DXT << 3;
847         }
848
849         gti.LeftToLoad = (info->sl<<info->dwSize)>>tile.dwSize;
850         gti.TopToLoad = (info->tl<<info->dwSize)>>tile.dwSize;
851     }
852
853     if( options.enableHackForGames == HACK_FOR_MARIO_KART )
854     {
855         if( loadwidth-maskwidth == 1 && tile.dwMaskS )
856         {
857             loadwidth--;
858             if( loadheight%2 )  loadheight--;
859         }
860
861         if( loadheight-maskheight == 1 && tile.dwMaskT )
862         {
863             loadheight--;
864             if(loadwidth%2) loadwidth--;
865         }
866
867         if( loadwidth - ((g_TI.dwWidth<<g_TI.dwSize)>>tile.dwSize) == 1 )
868         {
869             loadwidth--;
870             if( loadheight%2 )  loadheight--;
871         }
872     }
873
874
875     // Limit the texture size
876     if( g_curRomInfo.bUseSmallerTexture )
877     {
878         if( tile.dwMaskS && tile.bClampS )
879         {
880             if( !tile.bMirrorS )
881             {
882                 if( clampwidth/maskwidth >= 2 )
883                 {
884                     clampwidth = maskwidth;
885                     tile.bForceWrapS = true;
886                 }
887                 else if( clampwidth && maskwidth/clampwidth >= 2 )
888                 {
889                     maskwidth = clampwidth;
890                     tile.bForceClampS = true;
891                 }
892             }
893             else
894             {
895                 if( clampwidth/maskwidth == 2 )
896                 {
897                     clampwidth = maskwidth*2;
898                     tile.bForceWrapS = false;
899                 }
900                 else if( clampwidth/maskwidth > 2 )
901                 {
902                     clampwidth = maskwidth*2;
903                     tile.bForceWrapS = true;
904                 }
905             }
906         }
907
908         if( tile.dwMaskT && tile.bClampT )
909         {
910             if( !tile.bMirrorT )
911             {
912                 if( clampheight/maskheight >= 2 )
913                 {
914                     clampheight = maskheight;
915                     tile.bForceWrapT = true;
916                 }
917                 else if( clampheight && maskheight/clampheight >= 2 )
918                 {
919                     maskwidth = clampwidth;
920                     tile.bForceClampT = true;
921                 }
922             }
923             else
924             {
925                 if( clampheight/maskheight == 2 )
926                 {
927                     clampheight = maskheight*2;
928                     tile.bForceWrapT = false;
929                 }
930                 else if( clampheight/maskheight >= 2 )
931                 {
932                     clampheight = maskheight*2;
933                     tile.bForceWrapT = true;
934                 }
935             }
936         }
937     }
938     else
939     {
940         //if( clampwidth > linewidth )  clampwidth = linewidth;
941         if( clampwidth > 512 && clampheight > 512 )
942         {
943             if( clampwidth > maskwidth && maskwidth && clampheight > 256 )  clampwidth = maskwidth;
944             if( clampheight > maskheight && maskheight && clampheight > 256 )   clampheight = maskheight;
945         }
946
947         if( tile.dwMaskS > 8 && tile.dwMaskT > 8 )  
948         {
949             maskwidth = loadwidth;
950             maskheight = loadheight;
951         }
952         else 
953         {
954             if( tile.dwMaskS > 10 )
955                 maskwidth = loadwidth;
956             if( tile.dwMaskT > 10 )
957                 maskheight = loadheight;
958         }
959     }
960
961     gti.Pitch = tile.dwPitch;
962
963     if( tile.dwMaskS == 0 || tile.bClampS )
964     {
965         gti.WidthToLoad = linewidth ? min( linewidth, maskwidth ? min(clampwidth,maskwidth) : clampwidth ) : clampwidth;
966         if( tile.dwMaskS && clampwidth < maskwidth )
967             tile.dwWidth = gti.WidthToCreate = clampwidth;
968         else
969             tile.dwWidth = gti.WidthToCreate = max(clampwidth,maskwidth);
970     }
971     else
972     {
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;
976     }
977
978     if( tile.dwMaskT == 0 || tile.bClampT )
979     {
980         gti.HeightToLoad = maskheight ? min(clampheight,maskheight) : clampheight;
981         if( tile.dwMaskT && clampheight < maskheight )
982             tile.dwHeight = gti.HeightToCreate = clampheight;
983         else
984             tile.dwHeight = gti.HeightToCreate = max(clampheight,maskheight);
985     }
986     else
987     {
988         gti.HeightToLoad = loadheight > 2 ? min(loadheight,maskheight) : maskheight;
989         tile.dwHeight = gti.HeightToCreate = maskheight;
990     }
991
992     if( options.enableHackForGames == HACK_FOR_MARIO_KART )
993     {
994         if( gti.WidthToLoad - ((g_TI.dwWidth<<g_TI.dwSize)>>tile.dwSize) == 1 )
995         {
996             gti.WidthToLoad--;
997             if( gti.HeightToLoad%2 )    gti.HeightToLoad--;
998         }
999     }
1000
1001     // Double check
1002     uint32 total64BitWordsToLoad = (gti.HeightToLoad*gti.WidthToLoad)>>(4-tile.dwSize);
1003     if( total64BitWordsToLoad + tile.dwTMem > 0x200 )
1004     {
1005         //TRACE0("Warning: texture loading tmem is over range");
1006         if( gti.WidthToLoad > gti.HeightToLoad )
1007         {
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;
1011         }
1012         else
1013         {
1014             tile.dwHeight = gti.HeightToCreate = gti.HeightToLoad = info->dwTotalWords / ((gti.WidthToLoad << tile.dwSize) >> 1);
1015         }
1016     }
1017
1018     // Check the info
1019     if( (info->dwTotalWords>>2) < total64BitWordsToLoad+tile.dwTMem-info->dwTmem - 4 )
1020     {
1021         // Hack here
1022         if( (options.enableHackForGames == HACK_FOR_ZELDA||options.enableHackForGames == HACK_FOR_ZELDA_MM) && (unsigned int)tileno != gRSP.curTile )
1023         {
1024             return false;
1025         }
1026
1027         if( total64BitWordsToLoad+tile.dwTMem-info->dwTmem <= 0x200 )
1028         {
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));
1031         }
1032     }
1033
1034     //Check memory boundary
1035     if( gti.Address + gti.HeightToLoad*gti.Pitch >= g_dwRamSize )
1036     {
1037         WARNING(TRACE0("Warning: texture loading tmem is over range 3"));
1038         gti.HeightToCreate = gti.HeightToLoad = tile.dwHeight = (g_dwRamSize-gti.Address)/gti.Pitch;
1039     }
1040
1041     return true;
1042 }
1043
1044 TxtrCacheEntry* LoadTexture(uint32 tileno)
1045 {
1046     //TxtrCacheEntry *pEntry = NULL;
1047     TxtrInfo gti;
1048
1049     Tile &tile = gRDP.tiles[tileno];
1050
1051     // Retrieve the tile loading info
1052     uint32 infoTmemAddr = tile.dwTMem;
1053     TMEMLoadMapInfo *info = &g_tmemLoadAddrMap[infoTmemAddr];
1054     if( !IsTmemFlagValid(infoTmemAddr) )
1055     {
1056         infoTmemAddr =  GetValidTmemInfoIndex(infoTmemAddr);
1057         info = &g_tmemLoadAddrMap[infoTmemAddr];
1058     }
1059
1060     if( info->dwFormat != tile.dwFormat )
1061     {
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 )
1065         {
1066             //TRACE1("Tile %d format is not matching the loaded texture format", tileno);
1067             return NULL;
1068         }
1069     }
1070
1071     gti = tile; // Copy tile info to textureInfo entry
1072
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
1076
1077     gti.PalAddress = (uchar *) (&g_wRDPTlut[0]);
1078     if( !options.bUseFullTMEM && tile.dwSize == TXT_SIZE_4b )
1079         gti.PalAddress += 16  * 2 * tile.dwPalette; 
1080
1081     gti.Address = (info->dwLoadAddress+(tile.dwTMem-infoTmemAddr)*8) & (g_dwRamSize-1) ;
1082     gti.pPhysicalAddress = ((uint8*)g_pRDRAMu32)+gti.Address;
1083     gti.tileNo = tileno;
1084
1085     if( g_curRomInfo.bTxtSizeMethod2 )
1086     {
1087         if( !CalculateTileSizes_method_2(tileno, info, gti) )
1088             return NULL;
1089     }
1090     else
1091     {
1092         if( !CalculateTileSizes_method_1(tileno, info, gti) )
1093             return NULL;
1094     }
1095
1096     LOG_TEXTURE(
1097     {
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);
1102     });
1103
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
1107         )
1108     {
1109         uint32 idx = tileno-gRSP.curTile;
1110         status.LargerTileRealLeft[idx] = gti.LeftToLoad;
1111         gti.LeftToLoad=0;
1112         gti.WidthToLoad = gti.WidthToCreate = ((gti.Pitch<<1)>>gti.Size);
1113         status.UseLargerTile[idx]=true;
1114     }
1115
1116     // Loading the textures by using texture cache manager
1117     return gTextureManager.GetTexture(&gti, true, true, true);  // Load the texture by using texture cache
1118 }
1119
1120 void PrepareTextures()
1121 {
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] )
1125     {
1126         status.UseLargerTile[0]=false;
1127         status.UseLargerTile[1]=false;
1128
1129         int tilenos[2];
1130         if( CRender::g_pRender->IsTexel0Enable() || gRDP.otherMode.cycle_type  == CYCLE_TYPE_COPY )
1131             tilenos[0] = gRSP.curTile;
1132         else
1133             tilenos[0] = -1;
1134
1135         if( gRSP.curTile<7 && CRender::g_pRender->IsTexel1Enable() )
1136             tilenos[1] = gRSP.curTile+1;
1137         else
1138             tilenos[1] = -1;
1139
1140
1141         for( int i=0; i<2; i++ )
1142         {
1143             if( tilenos[i] < 0 )    continue;
1144
1145             if( CRender::g_pRender->m_pColorCombiner->m_pDecodedMux->m_ColorTextureFlag[i] )
1146             {
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);
1149             }
1150             else
1151             {
1152                 TxtrCacheEntry *pEntry = LoadTexture(tilenos[i]);
1153                 if (pEntry && pEntry->pTexture )
1154                 {
1155                     if( pEntry->txtrBufIdx <= 0 )
1156                     {
1157                         if( pEntry->pEnhancedTexture && pEntry->dwEnhancementFlag == TEXTURE_EXTERNAL && !options.bLoadHiResTextures )
1158                         {
1159                             SAFE_DELETE(pEntry->pEnhancedTexture);
1160                         }
1161
1162                         if( pEntry->pEnhancedTexture == NULL )
1163                         {
1164                             MirrorTexture(tilenos[i], pEntry);;
1165                         }
1166
1167                         if( options.bLoadHiResTextures && (pEntry->pEnhancedTexture == NULL || pEntry->dwEnhancementFlag < TEXTURE_EXTERNAL ) )
1168                         {
1169                             LoadHiresTexture(*pEntry);
1170                         }
1171
1172                         if( pEntry->pEnhancedTexture == NULL || (pEntry->dwEnhancementFlag != options.textureEnhancement && pEntry->dwEnhancementFlag < TEXTURE_EXTERNAL ) )
1173                         {
1174                             EnhanceTexture(pEntry);
1175                         }
1176                     }
1177
1178                     CRender::g_pRender->SetCurrentTexture( tilenos[i], 
1179                         (pEntry->pEnhancedTexture)?pEntry->pEnhancedTexture:pEntry->pTexture,
1180                         pEntry->ti.WidthToLoad, pEntry->ti.HeightToLoad, pEntry);
1181                 }
1182                 else
1183                 {
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");
1187                 }
1188
1189             }
1190         }
1191
1192         gRDP.textureIsChanged = false;
1193     }
1194 }
1195
1196 extern uint32 g_TxtLoadBy;;
1197
1198 void DLParser_LoadTLut(Gfx *gfx)
1199 {
1200 gRDP.textureIsChanged = true;
1201
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;
1207
1208 #ifdef DEBUGGER
1209 uint32 dwTLutFmt = (gRDP.otherModeH >> RSP_SETOTHERMODE_SHIFT_TEXTLUT)&0x3;
1210 #endif
1211
1212 uint32 dwCount;
1213 // starting location in the palettes
1214 uint32 dwTMEMOffset = gRDP.tiles[tileno].dwTMem - 256;  
1215 // number to copy
1216 dwCount = ((uint16)((gfx->words.w1) >> 14) & 0x03FF) + 1;
1217 uint32 dwRDRAMOffset = 0;
1218
1219 Tile &tile = gRDP.tiles[tileno];
1220 tile.bForceWrapS = tile.bForceWrapT = tile.bForceClampS = tile.bForceClampT = false;
1221
1222 tile.hilite_sl = tile.sl = uls;
1223 tile.hilite_tl = tile.tl = ult;
1224 tile.sh = lrs;
1225 tile.th = lrt;
1226 tile.bSizeIsValid = true;
1227
1228 tile.lastTileCmd = CMD_LOADTLUT;
1229
1230 #ifdef DEBUGGER
1231 /*
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");
1234 */
1235 #endif
1236
1237 dwCount = (lrs - uls)+1;
1238 dwRDRAMOffset = (uls + ult*g_TI.dwWidth )*2;
1239 uint32 dwPalAddress = g_TI.dwAddr + dwRDRAMOffset;
1240
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];
1245
1246 if( options.bUseFullTMEM )
1247     {
1248     for (uint32 i=0; i<dwCount && i+tile.dwTMem<0x200; i++)
1249         *(uint16*)(&g_Tmem.g_Tmem64bit[tile.dwTMem+i]) = srcPal[i^1];
1250     }
1251
1252 LOG_TEXTURE(
1253 {
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],
1256                  dwTMEMOffset);
1257
1258 DebuggerAppendMsg("    :ULS: 0x%X, ULT:0x%X, LRS: 0x%X, LRT:0x%X\n", uls, ult, lrs,lrt);
1259
1260 if( pauseAtNext && eventToPause == NEXT_LOADTLUT && dwCount == 16 ) 
1261     {
1262     char buf[2000];
1263     strcpy(buf, "Data:\n");
1264     for(uint32 i=0; i<16; i++ )
1265         {
1266         sprintf(buf+strlen(buf), "%04X ", g_wRDPTlut[dwTMEMOffset+i]);
1267         if(i%4 == 3)
1268             sprintf(buf+strlen(buf), "\n");
1269         }
1270     sprintf(buf+strlen(buf), "\n");
1271     TRACE0(buf);
1272     }
1273 });
1274
1275 DEBUGGER_PAUSE_COUNT_N(NEXT_LOADTLUT);
1276
1277 extern bool RevTlutTableNeedUpdate;
1278 RevTlutTableNeedUpdate = true;
1279 g_TxtLoadBy = CMD_LOADTLUT;
1280 }
1281
1282
1283 void DLParser_LoadBlock(Gfx *gfx)
1284 {
1285     gRDP.textureIsChanged = true;
1286
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
1292
1293     Tile &tile = gRDP.tiles[tileno];
1294     tile.bForceWrapS = tile.bForceWrapT = tile.bForceClampS = tile.bForceClampT = false;
1295
1296     uint32 size     = lrs+1;
1297     if( tile.dwSize == TXT_SIZE_32b )   size<<=1;
1298
1299     SetTmemFlag(tile.dwTMem, size>>2);
1300
1301     TMEMLoadMapInfo &info = g_tmemLoadAddrMap[tile.dwTMem];
1302
1303     info.bSwapped = (dxt == 0? TRUE : FALSE);
1304
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;
1310
1311     for( int i=0; i<8; i++ )
1312     {
1313         if( tile.dwTMem == tile.dwTMem )
1314             tile.lastTileCmd = CMD_LOADBLOCK;
1315     }
1316
1317     info.dwLoadAddress = g_TI.dwAddr;
1318     info.bSetBy = CMD_LOADBLOCK;
1319     info.dxt = dxt;
1320     info.dwLine = tile.dwLine;
1321
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;
1327
1328     if( gRDP.tiles[tileno].dwTMem == 0 )
1329     {
1330         if( size >= 1024 )
1331         {
1332             memcpy(&g_tmemInfo0, &info, sizeof(TMEMLoadMapInfo) );
1333             g_tmemInfo0.dwTotalWords = size>>2;
1334         }
1335         
1336         if( size == 2048 )
1337         {
1338             memcpy(&g_tmemInfo1, &info, sizeof(TMEMLoadMapInfo) );
1339             g_tmemInfo1.dwTotalWords = size>>2;
1340         }
1341     }
1342     else if( tile.dwTMem == 0x100 )
1343     {
1344         if( size == 1024 )
1345         {
1346             memcpy(&g_tmemInfo1, &info, sizeof(TMEMLoadMapInfo) );
1347             g_tmemInfo1.dwTotalWords = size>>2;
1348         }
1349     }
1350
1351     g_TxtLoadBy = CMD_LOADBLOCK;
1352
1353
1354     if( options.bUseFullTMEM )
1355     {
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))
1359         {
1360             return;
1361         }
1362         uint64* src = (uint64*)(g_pRDRAMu8+address);
1363         uint64* dest = &g_Tmem.g_Tmem64bit[tile.dwTMem];
1364
1365         if( dxt > 0)
1366         {
1367             void (*Interleave)( void *mem, uint32 numDWords );
1368
1369             uint32 line = (2047 + dxt) / dxt;
1370             uint32 bpl = line << 3;
1371             uint32 height = bytes / bpl;
1372
1373             if (tile.dwSize == TXT_SIZE_32b)
1374                 Interleave = QWordInterleave;
1375             else
1376                 Interleave = DWordInterleave;
1377
1378             for (uint32 y = 0; y < height; y++)
1379             {
1380                 UnswapCopy( src, dest, bpl );
1381                 if (y & 1) Interleave( dest, line );
1382
1383                 src += line;
1384                 dest += line;
1385             }
1386         }
1387         else
1388             UnswapCopy( src, dest, bytes );
1389     }
1390
1391
1392     LOG_UCODE("    Tile:%d (%d,%d - %d) DXT:0x%04x\n", tileno, uls, ult, lrs, dxt);
1393
1394     LOG_TEXTURE(
1395     {
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));
1398     });
1399
1400     DEBUGGER_PAUSE_COUNT_N(NEXT_TEXTURE_CMD);
1401 }
1402
1403 void swap(uint32 &a, uint32 &b)
1404 {
1405     uint32 temp = a;
1406     a = b;
1407     b = temp;
1408 }
1409 void DLParser_LoadTile(Gfx *gfx)
1410 {
1411     gRDP.textureIsChanged = true;
1412
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;
1418
1419     Tile &tile = gRDP.tiles[tileno];
1420     tile.bForceWrapS = tile.bForceWrapT = tile.bForceClampS = tile.bForceClampT = false;
1421
1422     if (lrt < ult) swap(lrt, ult);
1423     if (lrs < uls) swap(lrs, uls);
1424
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;
1430
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;
1436
1437     if (((tile.dwTMem << 3) + line * height) > 4096)  // check destination ending point (TMEM is 4k bytes)
1438         return;
1439
1440     if( options.bUseFullTMEM )
1441     {
1442         void (*Interleave)( void *mem, uint32 numDWords );
1443         uint32 address, y;
1444         uint64 *dest;
1445         uint8 *src;
1446
1447         if( g_TI.bpl == 0 )
1448         {
1449             if( options.enableHackForGames == HACK_FOR_BUST_A_MOVE )
1450             {
1451                 g_TI.bpl = 1024;        // Hack for Bust-A-Move
1452             }
1453             else
1454             {
1455                 TRACE0("Warning: g_TI.bpl = 0" );
1456             }
1457         }
1458
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];
1462
1463         if ((address + height * bpl) > g_dwRamSize) // check source ending point
1464         {
1465             return;
1466         }
1467
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)
1471         {
1472             Interleave = QWordInterleave;
1473         }
1474         else
1475         {
1476             Interleave = DWordInterleave;
1477         }
1478
1479         if( tile.dwLine == 0 )
1480         {
1481             //tile.dwLine = 1;
1482             return;
1483         }
1484
1485         for (y = 0; y < height; y++)
1486         {
1487             UnswapCopy( src, dest, bpl );
1488             if (y & 1) Interleave( dest, line );
1489
1490             src += g_TI.bpl;
1491             dest += line;
1492         }
1493     }
1494
1495
1496     for( int i=0; i<8; i++ )
1497     {
1498         if( gRDP.tiles[i].dwTMem == tile.dwTMem )
1499             gRDP.tiles[i].lastTileCmd = CMD_LOADTILE;
1500     }
1501
1502     uint32 size = line * height;
1503     SetTmemFlag(tile.dwTMem,size );
1504
1505     LOG_TEXTURE(
1506     {
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);
1510     });
1511
1512     
1513     DEBUGGER_PAUSE_COUNT_N(NEXT_TEXTURE_CMD);
1514
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);
1518
1519     TMEMLoadMapInfo &info = g_tmemLoadAddrMap[tile.dwTMem];
1520
1521     info.dwLoadAddress = g_TI.dwAddr;
1522     info.dwFormat = g_TI.dwFormat;
1523     info.dwSize = g_TI.dwSize;
1524     info.dwWidth = g_TI.dwWidth;
1525
1526     info.sl = uls;
1527     info.sh = lrs;
1528     info.tl = ult;
1529     info.th = lrt;
1530     
1531     info.dxt = 0;
1532     info.dwLine = tile.dwLine;
1533     info.dwTmem = tile.dwTMem;
1534     info.dwTotalWords = size<<2;
1535
1536     info.bSetBy = CMD_LOADTILE;
1537     info.bSwapped =FALSE;
1538
1539     g_TxtLoadBy = CMD_LOADTILE;
1540
1541     if( tile.dwTMem == 0 )
1542     {
1543         if( size >= 256 )
1544         {
1545             memcpy(&g_tmemInfo0, &info, sizeof(TMEMLoadMapInfo) );
1546             g_tmemInfo0.dwTotalWords = size;
1547         }
1548
1549         if( size == 512 )
1550         {
1551             memcpy(&g_tmemInfo1, &info, sizeof(TMEMLoadMapInfo) );
1552             g_tmemInfo1.dwTotalWords = size;
1553         }
1554     }
1555     else if( tile.dwTMem == 0x100 )
1556     {
1557         if( size == 256 )
1558         {
1559             memcpy(&g_tmemInfo1, &info, sizeof(TMEMLoadMapInfo) );
1560             g_tmemInfo1.dwTotalWords = size;
1561         }
1562     }
1563 }
1564
1565
1566 const char *pszOnOff[2] = {"Off", "On"};
1567 uint32 lastSetTile;
1568 void DLParser_SetTile(Gfx *gfx)
1569 {
1570     gRDP.textureIsChanged = true;
1571
1572     uint32 tileno       = gfx->settile.tile;
1573     Tile &tile = gRDP.tiles[tileno];
1574     tile.bForceWrapS = tile.bForceWrapT = tile.bForceClampS = tile.bForceClampT = false;
1575
1576     lastSetTile = tileno;
1577
1578     tile.dwFormat   = gfx->settile.fmt;
1579     tile.dwSize     = gfx->settile.siz;
1580     tile.dwLine     = gfx->settile.line;
1581     tile.dwTMem     = gfx->settile.tmem;
1582
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;
1592
1593
1594     tile.fShiftScaleS = 1.0f;
1595     if( tile.dwShiftS )
1596     {
1597         if( tile.dwShiftS > 10 )
1598         {
1599             tile.fShiftScaleS = (float)(1 << (16 - tile.dwShiftS));
1600         }
1601         else
1602         {
1603             tile.fShiftScaleS = (float)1.0f/(1 << tile.dwShiftS);
1604         }
1605     }
1606
1607     tile.fShiftScaleT = 1.0f;
1608     if( tile.dwShiftT )
1609     {
1610         if( tile.dwShiftT > 10 )
1611         {
1612             tile.fShiftScaleT = (float)(1 << (16 - tile.dwShiftT));
1613         }
1614         else
1615         {
1616             tile.fShiftScaleT = (float)1.0f/(1 << tile.dwShiftT);
1617         }
1618     }
1619
1620     // Hack for DK64
1621     /*
1622     if( tile.dwMaskS > 0 && tile.dwMaskT > 0 && tile.dwMaskS < 8 && tile.dwMaskT < 8 )
1623     {
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;
1628     }
1629     */
1630
1631     tile.lastTileCmd = CMD_SETTILE;
1632
1633     LOG_TEXTURE(
1634     {
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);
1644     });
1645
1646     DEBUGGER_PAUSE_COUNT_N(NEXT_TEXTURE_CMD);
1647
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);
1657 }
1658
1659 void DLParser_SetTileSize(Gfx *gfx)
1660 {
1661     gRDP.textureIsChanged = true;
1662
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;
1668
1669     Tile &tile = gRDP.tiles[tileno];
1670     tile.bForceWrapS = tile.bForceWrapT = tile.bForceClampS = tile.bForceClampT = false;
1671
1672     if( options.bUseFullTMEM )
1673     {
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;
1679
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;
1684
1685         tile.lastTileCmd = CMD_SETTILE_SIZE;
1686     }
1687     else
1688     {
1689         if( tile.lastTileCmd != CMD_SETTILE_SIZE )
1690         {
1691             tile.bSizeIsValid = true;
1692             if( sl/4 > sh/4 || tl/4 > th/4 || (sh == 0 && tile.dwShiftS==0 && th == 0 && tile.dwShiftT ==0 ) )
1693             {
1694 #ifdef DEBUGGER
1695                 if( sl != 0 || tl != 0 || sh != 0 || th != 0 )
1696                 {
1697                     if( tile.dwMaskS==0 || tile.dwMaskT==0 )
1698                         TRACE0("Check me, setTileSize is not correct");
1699                 }
1700 #endif
1701                 tile.bSizeIsValid = false;
1702             }
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;
1707
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;
1712
1713             tile.lastTileCmd = CMD_SETTILE_SIZE;
1714         }
1715         else
1716         {
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;
1721
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;
1728
1729             tile.lastTileCmd = CMD_SETTILE_SIZE;
1730         }
1731     }
1732
1733     LOG_TEXTURE(
1734     {
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);
1738     });
1739     DEBUGGER_PAUSE_COUNT_N(NEXT_TEXTURE_CMD);
1740
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);
1744 }
1745
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)
1749 {
1750     gRDP.textureIsChanged = true;
1751
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;
1757
1758 #ifdef DEBUGGER
1759     if( g_TI.dwAddr == 0x00ffffff)
1760     {
1761         TRACE0("Check me here in setTimg");
1762     }
1763
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));
1766
1767     DEBUGGER_PAUSE_COUNT_N(NEXT_TEXTURE_CMD);
1768
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);
1771 #endif
1772 }
1773
1774 void DLParser_TexRect(Gfx *gfx)
1775 {
1776     //Gtexrect *gtextrect = (Gtexrect *)gfx;
1777
1778     if( !status.bCIBufferIsRendered ) g_pFrameBufferManager->ActiveTextureBuffer();
1779
1780     status.primitiveType = PRIM_TEXTRECT;
1781
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);
1789
1790     if( options.enableHackForGames == HACK_FOR_ALL_STAR_BASEBALL || options.enableHackForGames == HACK_FOR_MLB )
1791     {
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) )
1794         {
1795             // Increment PC so that it points to the right place
1796             gDlistStack[gDlistStackPointer].pc += 16;
1797         }
1798         else
1799         {
1800             // Hack for some games, All_Star_Baseball_2000
1801             gDlistStack[gDlistStackPointer].pc += 8;
1802             dwCmd3 = dwCmd2;
1803             //dwCmd2 = dwHalf1;
1804             //dwCmd2 = 0;
1805
1806             // fix me here
1807             dwCmd2 = (((dwHalf1>>12)&0x03FF)<<17) | (((dwHalf1)&0x03FF)<<1);
1808         }   
1809     }
1810     else
1811     {
1812         gDlistStack[gDlistStackPointer].pc += 16;
1813     }
1814
1815
1816     // Hack for Mario Tennis
1817     if( !status.bHandleN64RenderTexture && g_CI.dwAddr == g_ZI.dwAddr )
1818     {
1819         return;
1820     }
1821
1822
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));
1825
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);
1835     
1836
1837     if( (int)dwXL >= gRDP.scissor.right || (int)dwYL >= gRDP.scissor.bottom || (int)dwXH < gRDP.scissor.left || (int)dwYH < gRDP.scissor.top )
1838     {
1839         // Clipping
1840         return;
1841     }
1842
1843     short s16S = *(short*)(&uS);
1844     short s16T = *(short*)(&uT);
1845
1846     short    s16DSDX  = *(short*)(&uDSDX);
1847     short  s16DTDY  = *(short*)(&uDTDY);
1848
1849     uint32 curTile = gRSP.curTile;
1850     ForceMainTextureIndex(tileno);
1851
1852     float fS0 = s16S / 32.0f;
1853     float fT0 = s16T / 32.0f;
1854
1855     float fDSDX = s16DSDX / 1024.0f;
1856     float fDTDY = s16DTDY / 1024.0f;
1857
1858     uint32 cycletype = gRDP.otherMode.cycle_type;
1859
1860     if (cycletype == CYCLE_TYPE_COPY)
1861     {
1862         fDSDX /= 4.0f;  // In copy mode 4 pixels are copied at once.
1863         dwXH++;
1864         dwYH++;
1865     }
1866     else if (cycletype == CYCLE_TYPE_FILL)
1867     {
1868         dwXH++;
1869         dwYH++;
1870     }
1871
1872     if( fDSDX == 0 )    fDSDX = 1;
1873     if( fDTDY == 0 )    fDTDY = 1;
1874
1875     float fS1 = fS0 + (fDSDX * (dwXH - dwXL));
1876     float fT1 = fT0 + (fDTDY * (dwYH - dwYL));
1877
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);
1881     LOG_UCODE("");
1882
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;
1887
1888     if( dwXL==0 && dwYL==0 && dwXH==windowSetting.fViWidth-1 && dwYH==windowSetting.fViHeight-1 &&
1889         t0u0 == 0 && t0v0==0 && t0u1==0 && t0v1==0 )
1890     {
1891         //Using TextRect to clear the screen
1892     }
1893     else
1894     {
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 )
1899         {
1900             if( options.enableHackForGames == HACK_FOR_YOSHI )
1901             {
1902                 // Hack for Yoshi background image
1903                 PrepareTextures();
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");
1909                 });
1910
1911             }
1912             else
1913             {
1914                 if( frameBufferOptions.bUpdateCIInfo )
1915                 {
1916                     PrepareTextures();
1917                     TexRectToFrameBuffer_8b(dwXL, dwYL, dwXH, dwYH, t0u0, t0v0, t0u1, t0v1, tileno);
1918                 }
1919
1920                 if( !status.bDirectWriteIntoRDRAM )
1921                 {
1922                     CRender::g_pRender->TexRect(dwXL, dwYL, dwXH, dwYH, fS0, fT0, fDSDX, fDTDY);
1923
1924                     status.dwNumTrisRendered += 2;
1925                 }
1926             }
1927         }
1928         else
1929         {
1930             CRender::g_pRender->TexRect(dwXL, dwYL, dwXH, dwYH, fS0, fT0, fDSDX, fDTDY);
1931             status.bFrameBufferDrawnByTriangles = true;
1932
1933             status.dwNumTrisRendered += 2;
1934         }
1935     }
1936
1937     if( status.bHandleN64RenderTexture )    g_pRenderTextureInfo->maxUsedHeight = max(g_pRenderTextureInfo->maxUsedHeight,(int)dwYH);
1938
1939     ForceMainTextureIndex(curTile);
1940 }
1941
1942
1943 void DLParser_TexRectFlip(Gfx *gfx)
1944
1945     status.bCIBufferIsRendered = true;
1946     status.primitiveType = PRIM_TEXTRECTFLIP;
1947
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);
1953
1954     // Increment PC so that it points to the right place
1955     gDlistStack[gDlistStackPointer].pc += 16;
1956
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);
1966
1967     uint32 curTile = gRSP.curTile;
1968     ForceMainTextureIndex(tileno);
1969     
1970     float fS0 = (float)dwS / 32.0f;
1971     float fT0 = (float)dwT / 32.0f;
1972
1973     float fDSDX = (float)nDSDX / 1024.0f;
1974     float fDTDY = (float)nDTDY / 1024.0f;
1975
1976     uint32 cycletype = gRDP.otherMode.cycle_type;
1977
1978     if (cycletype == CYCLE_TYPE_COPY)
1979     {
1980         fDSDX /= 4.0f;  // In copy mode 4 pixels are copied at once.
1981         dwXH++;
1982         dwYH++;
1983     }
1984     else if (cycletype == CYCLE_TYPE_FILL)
1985     {
1986         dwXH++;
1987         dwYH++;
1988     }
1989
1990     float fS1 = fS0 + (fDSDX * (dwYH - dwYL));
1991     float fT1 = fT0 + (fDTDY * (dwXH - dwXL));
1992     
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);
1997     LOG_UCODE("");
1998
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;
2003
2004     CRender::g_pRender->TexRectFlip(dwXL, dwYL, dwXH, dwYH, t0u0, t0v0, t0u1, t0v1);
2005     status.dwNumTrisRendered += 2;
2006
2007     if( status.bHandleN64RenderTexture )    g_pRenderTextureInfo->maxUsedHeight = max(g_pRenderTextureInfo->maxUsedHeight,int(dwYL+(dwXH-dwXL)));
2008
2009     ForceMainTextureIndex(curTile);
2010 }
2011
2012 /************************************************************************/
2013 /*                                                                      */
2014 /************************************************************************/
2015 /*
2016  *  TMEM emulation
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.
2021  *
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.
2024  */
2025 typedef struct TmemInfoEntry{
2026     uint32 start;
2027     uint32 length;
2028     uint32 rdramAddr;
2029     TmemInfoEntry* next;
2030 } TmemInfoEntry;
2031
2032 const int tmenMaxEntry=20;
2033 TmemInfoEntry tmenEntryBuffer[20]={{0}};
2034 TmemInfoEntry *g_pTMEMInfo=NULL;
2035 TmemInfoEntry *g_pTMEMFreeList=tmenEntryBuffer;
2036
2037 void TMEM_Init()
2038 {
2039     g_pTMEMInfo=NULL;
2040     g_pTMEMFreeList=tmenEntryBuffer;
2041         int i;
2042     for( i=0; i<tmenMaxEntry; i++ )
2043     {
2044         tmenEntryBuffer[i].start=0;
2045         tmenEntryBuffer[i].length=0;
2046         tmenEntryBuffer[i].rdramAddr=0;
2047         tmenEntryBuffer[i].next = &(tmenEntryBuffer[i+1]);
2048     }
2049     tmenEntryBuffer[i-1].next = NULL;
2050 }
2051
2052 void TMEM_SetBlock(uint32 tmemstart, uint32 length, uint32 rdramaddr)
2053 {
2054     TmemInfoEntry *p=g_pTMEMInfo;
2055
2056     if( p == NULL )
2057     {
2058         // Move an entry from freelist and link it to the header
2059         p = g_pTMEMFreeList;
2060         g_pTMEMFreeList = g_pTMEMFreeList->next;
2061
2062         p->start = tmemstart;
2063         p->length = length;
2064         p->rdramAddr = rdramaddr;
2065         p->next = NULL;
2066     }
2067     else
2068     {
2069         while ( tmemstart > (p->start+p->length) )
2070         {
2071             if( p->next != NULL ) {
2072                 p = p->next;
2073                 continue;
2074             }
2075             else {
2076                 break;
2077             }
2078         }
2079
2080         if ( p->start == tmemstart ) 
2081         {
2082             // need to replace the block of 'p'
2083             // or append a new block depend the block lengths
2084             if( length == p->length )
2085             {
2086                 p->rdramAddr = rdramaddr;
2087                 return;
2088             }
2089             else if( length < p->length )
2090             {
2091                 TmemInfoEntry *newentry = g_pTMEMFreeList;
2092                 g_pTMEMFreeList = g_pTMEMFreeList->next;
2093
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;
2098
2099                 p->length = length;
2100                 p->next = newentry;
2101                 p->rdramAddr = rdramaddr;
2102             }
2103         }
2104         else if( p->start > tmemstart )
2105         {
2106             // p->start > tmemstart, need to insert the new block before 'p'
2107             TmemInfoEntry *newentry = g_pTMEMFreeList;
2108             g_pTMEMFreeList = g_pTMEMFreeList->next;
2109
2110             if( length+tmemstart < p->start+p->length )
2111             {
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;
2116
2117                 p->length = length;
2118                 p->next = newentry;
2119                 p->rdramAddr = rdramaddr;
2120                 p->start = tmemstart;
2121             }
2122             else if( length+tmemstart == p->start+p->length )
2123             {
2124
2125             }
2126         }
2127         else
2128         {
2129         }
2130     }
2131 }
2132
2133 uint32 TMEM_GetRdramAddr(uint32 tmemstart, uint32 length)
2134 {
2135     return 0;
2136 }
2137
2138
2139 /*
2140  *  New implementation of texture loading
2141  */
2142
2143 bool IsTmemFlagValid(uint32 tmemAddr)
2144 {
2145     uint32 index = tmemAddr>>5;
2146     uint32 bitIndex = (tmemAddr&0x1F);
2147     return ((g_TmemFlag[index] & (1<<bitIndex))!=0);
2148 }
2149
2150 uint32 GetValidTmemInfoIndex(uint32 tmemAddr)
2151 {
2152     return 0;
2153     uint32 index = tmemAddr>>5;
2154     uint32 bitIndex = (tmemAddr&0x1F);
2155
2156     if ((g_TmemFlag[index] & (1<<bitIndex))!=0 )    //This address is valid
2157         return tmemAddr;
2158     else
2159     {
2160         for( uint32 x=index+1; x != 0; x-- )
2161         {
2162             uint32 i = x - 1;
2163             if( g_TmemFlag[i] != 0 )
2164             {
2165                 for( uint32 y=0x20; y != 0; y-- )
2166                 {
2167                     uint32 j = y - 1;
2168                     if( (g_TmemFlag[i] & (1<<j)) != 0 )
2169                     {
2170                         return ((i<<5)+j);
2171                     }
2172                 }
2173             }
2174         }
2175         TRACE0("Error, check me");
2176         return 0;
2177     }
2178 }
2179
2180
2181 void SetTmemFlag(uint32 tmemAddr, uint32 size)
2182 {
2183     uint32 index = tmemAddr>>5;
2184     uint32 bitIndex = (tmemAddr&0x1F);
2185
2186 #ifdef DEBUGGER
2187     if( size > 0x200 )
2188     {
2189         DebuggerAppendMsg("Check me: tmemaddr=%X, size=%x", tmemAddr, size);
2190         size = 0x200-tmemAddr;
2191     }
2192 #endif
2193
2194     if( bitIndex == 0 )
2195     {
2196         uint32 i;
2197         for( i=0; i< (size>>5); i++ )
2198         {
2199             g_TmemFlag[index+i] = 0;
2200         }
2201
2202         if( (size&0x1F) != 0 )
2203         {
2204             //ErrorMsg("Check me: tmemaddr=%X, size=%x", tmemAddr, size);
2205             g_TmemFlag[index+i] &= ~((1<<(size&0x1F))-1);
2206         }
2207
2208         g_TmemFlag[index] |= 1;
2209     }
2210     else
2211     {
2212         if( bitIndex + size <= 0x1F )
2213         {
2214             uint32 val = g_TmemFlag[index];
2215             uint32 mask = (1<<(bitIndex))-1;
2216             mask |= ~((1<<(bitIndex + size))-1);
2217             val &= mask;
2218             val |= (1<<bitIndex);
2219             g_TmemFlag[index] = val;
2220         }
2221         else
2222         {
2223             //ErrorMsg("Check me: tmemaddr=%X, size=%x", tmemAddr, size);
2224             uint32 val = g_TmemFlag[index];
2225             uint32 mask = (1<<bitIndex)-1;
2226             val &= mask;
2227             val |= (1<<bitIndex);
2228             g_TmemFlag[index] = val;
2229             index++;
2230             size -= (0x20-bitIndex);
2231
2232             uint32 i;
2233             for( i=0; i< (size>>5); i++ )
2234             {
2235                 g_TmemFlag[index+i] = 0;
2236             }
2237
2238             if( (size&0x1F) != 0 )
2239             {
2240                 //ErrorMsg("Check me: tmemaddr=%X, size=%x", tmemAddr, size);
2241                 g_TmemFlag[index+i] &= ~((1<<(size&0x1F))-1);
2242             }
2243         }
2244     }
2245 }
2246