/**
 * TrueReality - N64/rdp.c
 * Copyright (C) 1998 by Niki W. Waibel
 *
 * This program is free software; you can redistribute it and/
 * or modify it under the terms of the GNU General Public Li-
 * cence as published by the Free Software Foundation; either
 * version 2 of the Licence, or any later version.
 *
 * This program is distributed in the hope that it will be use-
 * ful, but WITHOUT ANY WARRANTY; without even the implied war-
 * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public Licence for more details.
 *
 * You should have received a copy of the GNU General Public
 * Licence along with this program; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
 * USA.
 *
 * Information about me (the author):
 *   Niki W. Waibel, Reichenau 20, 6890 Lustenau, Austria - EUROPE
 *   niki.waibel@gmx.net
**/





#include <stdio.h>
#include <stdarg.h>

#include <config.h>
#include <parser_extern.h>
#include <memory_extern.h>
#include <type_sizes.h>

#ifdef DEBUG
        #include <debug.h>
#endif

#include "../output/display/display.h"

#include "rdp.h"
#include "mnemonic.h"
#include "registers.h"




/* BWG */
struct rdp_tile_descriptor
{
    /* SETTILESIZE */
        HWORD   s; /* Upper Left Texture X-Coordinate (12 bits) */
        HWORD   t; /* Upper Left Texture Y-Coordinate (12 bits) */
        HWORD   S; /* Lower Right Texture X-Coordinate (12 bits) */
        HWORD   T; /* Lower Right Texture Y-Coordinate (12 bits) */

    /* SETTILE */
        BYTE    format;
        BYTE    size;
        int     line;
        int     tmem;
        BYTE    palette;
        BIT     clampt;
        BIT     mirrort;
        BYTE    maskt;
        BYTE    shiftt;
        BIT     clamps;
        BIT     mirrors;
        BYTE    masks;
        BYTE    shifts;
};
/* end BWG */




/**/

static WORD  cmd0, cmd1;
static WORD  start, stop, curr;
static WORD  rdp_fillcolor;
static WORD  rdp_primcolor;
static WORD  rdp_envcolor;
static WORD  rdp_fogcolor;
static WORD  rdp_blendcolor;

/* This is the frame buffer location to draw into */
/* Used by rdp_setcolorimage() */
static BYTE  rdp_colorimg_fmt;          /* Frame Format (3 bits) */
static BYTE  rdp_colorimg_size;         /* Bits per pixel (2 bits) */
static HWORD rdp_colorimg_width;        /* width of frame in pixels (12 bits) */
static WORD  rdp_colorimg_rdram;        /* RDRAM pointer to Image (32 bits) */

/* This is the frame buffer location to draw into */
/* Used by rdp_settextureimage() */
static BYTE  rdp_textureimg_fmt;        /* see above */
static BYTE  rdp_textureimg_size;
static HWORD rdp_textureimg_width;
static WORD  rdp_textureimg_rdram;

/* This is the location of an 8 bit TLUT */
/* Used by rdp_loadtlut() */
static BYTE  rdp_tlut_8_fmt;   /* TLUT Format (3 bits) */
static BYTE  rdp_tlut_8_size;  /* Bits per pixel (2 bits) */
static WORD  rdp_tlut_8_rdram; /* RDRAM pointer to TLUT (32 bits) */

/* This is the location of an 4 bit TLUT */
/* Used by rdp_loadtlut() */
static BYTE  rdp_tlut_4_fmt[16];   /* TLUT Format (3 bits) */
static BYTE  rdp_tlut_4_size[16];  /* Bits per pixel (2 bits) */
static WORD  rdp_tlut_4_rdram[16]; /* RDRAM pointer to TLUT (32 bits) */

/* These are the tile descriptors */
static struct rdp_tile_descriptor rdp_td[8];



/* rdp instructions */

static void rdp_fixme();
static void rdp_spnoop();
static void rdp_matrix();
static void rdp_movemem();
static void rdp_vertex();
static void rdp_displaylist();
static void rdp_sprite2d();
static void rdp_noop();
static void rdp_texrect();
static void rdp_texrectflip();
static void rdp_loadsync();
static void rdp_pipesync();
static void rdp_tilesync();
static void rdp_fullsync();
static void rdp_setkeygb();
static void rdp_setkeyr();
static void rdp_setconvert();
static void rdp_setscissor();
static void rdp_setprimdepth();
static void rdp_setothermode();
static void rdp_loadtlut();
static void rdp_settilesize();
static void rdp_loadblock();
static void rdp_loadtile();
static void rdp_settile();
static void rdp_fillrect();
static void rdp_setfillcolor();
static void rdp_setfogcolor();
static void rdp_setblendcolor();
static void rdp_setprimcolor();
static void rdp_setenvcolor();
static void rdp_setcombine();
static void rdp_settextureimage();
static void rdp_setdepthimage();
static void rdp_setcolorimage();
static void rdp_trifill();
static void rdp_trishade();
static void rdp_tritxtr();
static void rdp_trishadetxtr();
static void rdp_trifillz();
static void rdp_trishadez();
static void rdp_tritxtrz();
static void rdp_trishadetxtrz();




/* rdp instruction function pointer */

static rdp_instr instruction[256] =
{
        rdp_spnoop,             rdp_matrix,             rdp_fixme,              rdp_movemem,
        rdp_vertex,             rdp_fixme,              rdp_displaylist,        rdp_fixme,
        rdp_fixme,              rdp_sprite2d,           rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_noop,               rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_trifill,            rdp_trishade,           rdp_tritxtr,            rdp_trishadetxtr,
        rdp_trifillz,           rdp_trishadez,          rdp_tritxtrz,           rdp_trishadetxtrz,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_fixme,              rdp_fixme,              rdp_fixme,              rdp_fixme,
        rdp_texrect,            rdp_texrectflip,        rdp_loadsync,           rdp_pipesync,
        rdp_tilesync,           rdp_fullsync,           rdp_setkeygb,           rdp_setkeyr,
        rdp_setconvert,         rdp_setscissor,         rdp_setprimdepth,       rdp_setothermode,
        rdp_loadtlut,           rdp_fixme,              rdp_settilesize,        rdp_loadblock,
        rdp_loadtile,           rdp_settile,            rdp_fillrect,           rdp_setfillcolor,
        rdp_setfogcolor,        rdp_setblendcolor,      rdp_setprimcolor,       rdp_setenvcolor,
        rdp_setcombine,         rdp_settextureimage,    rdp_setdepthimage,      rdp_setcolorimage
};





/* define macros - to speed up things and to make things looking nice */



#ifdef DEBUG
        #define PRINT_RDP_NOT_IMPLEMENTED(name)                                                 \
                printf(ST_FG_BRO "$%02lx %s - NOT IMPLEMENTED\n" ST_FG_DEF, cmd0>>24, name);    \
                fflush(stdout);

        #define PRINT_RDP_WARNING(text)                                         \
                if(prefs.debug & DBG_RDP)                                       \
                {                                                               \
                        printf(ST_FG_BRO "RDP WARNING: %s\n" ST_FG_DEF, text);  \
                        fflush(stdout);                                         \
                }

        #define PRINT_RDP_INFO(name)                                    \
                if(prefs.debug & DBG_RDP)                               \
                {                                                       \
                        printf("$%02lx %s", cmd0>>24, name);            \
                        fflush(stdout);                                 \
                }

        void    PRINT_RDP_MNEMONIC(char *fmt, ...)
        {
                va_list ap;

                if(prefs.debug & DBG_RDP)                                       \
                {                                                               \
                        va_start(ap, fmt);
                        vprintf(fmt, ap);
                        va_end(ap);
                }
        }

#else
        #define PRINT_RDP_NOT_IMPLEMENTED(name)
        #define PRINT_RDP_WARNING(text)
        #define PRINT_RDP_INFO(name)
        void    PRINT_RDP_MNEMONIC(char *fmt, ...)
        {
        }
#endif










/* */

void rdp_go()
{
        /* we should do a fork() here - but!!! how could we stay portable? */

        start = curr = ((WORD *)mem.dpc_reg)[0] & 0xfff;
        stop  =        ((WORD *)mem.dpc_reg)[1] & 0xfff;

#ifdef DEBUG
        if(prefs.debug & DBG_RDP)
                printf("start: $%lx; stop: $%lx;\n", start, stop);
#endif



        ((WORD *)mem.dpc_reg)[2] = curr;

/* comment this for my version (niki w. waibel) - uncomment for BWG's version.
#define BWG
*/

#ifdef BWG
        while(curr != stop)
        {
#endif
#ifndef BWG
        if(start == stop)
                return;
        curr = stop - 8;
#endif
#ifdef DEBUG
                if(prefs.debug & DBG_RDP)
                        printf("RDP: [$%lx]: ", curr);
#endif

                cmd0 = ((WORD *)mem.sp_dmem)[(curr>>2)+0];
                cmd1 = ((WORD *)mem.sp_dmem)[(curr>>2)+1];

                instruction[cmd0>>24]();

                ((WORD *)mem.dpc_reg)[2] = (curr += 8);

                //getchar();

#ifdef BWG
        } /* while(curr != stop) */
#endif

} /* void rsp_go() */





void rdp_dis()
{

} /* void rdp_dis() */





void rdp_reset()
{

} /* void rsp_reset() */










/******************************************************************************\
*                                                                              *
*   RDP (Reality Display Processor)                                            *
*                                                                              *
\******************************************************************************/



static void rdp_fixme()
{
        PRINT_RDP_NOT_IMPLEMENTED("FIXME")

        CPU_HALT

} /* static void rdp_fixme() */





static void rdp_spnoop()
{
        PRINT_RDP_INFO("SPNOOP\n")

} /* static void rdp_spnoop() */





static void rdp_matrix()
{
        PRINT_RDP_NOT_IMPLEMENTED("MATRIX")

        CPU_HALT

} /* static void rdp_matrix() */





static void rdp_movemem()
{
        PRINT_RDP_NOT_IMPLEMENTED("MOVEMEM")

        CPU_HALT

} /* static void rdp_movemem() */





static void rdp_vertex()
{
        PRINT_RDP_NOT_IMPLEMENTED("VERTEX")

        CPU_HALT

} /* static void rdp_vertex() */





static void rdp_displaylist()
{
        PRINT_RDP_NOT_IMPLEMENTED("DISPLAYLIST")

        CPU_HALT

} /* static void rdp_displaylist() */





static void rdp_sprite2d()
{
        PRINT_RDP_NOT_IMPLEMENTED("SPRITE2D")

        CPU_HALT

} /* static void rdp_sprite2d() */





static void rdp_noop()
{
        PRINT_RDP_INFO("NOOP\n")

} /* static void rdp_noop() */





static void rdp_texrect()
{
        WORD    cmd2 = ((WORD *)mem.sp_dmem)[(curr>>2)+2];
        WORD    cmd3 = ((WORD *)mem.sp_dmem)[(curr>>2)+3];



        PRINT_RDP_INFO("TEXRECT ")
        PRINT_RDP_MNEMONIC("xh=%lu; yh=%lu; tile=%lu; xl=%lu; yl=%lu; s=%lu; t=%lu; dsdx=%lu; dtdy=%lu\n",
               (cmd0 & 0x00fff000) >> 14,
               (cmd0 & 0x00000fff) >> 2,
               (cmd1 & 0x07000000) >> 24,
               (cmd1 & 0x00fff000) >> 14,
               (cmd1 & 0x00000fff) >> 2,
               (cmd2 & 0xffff0000) >> 16,
               (cmd2 & 0x0000ffff),
               (cmd3 & 0xffff0000) >> 16,
               (cmd3 & 0x0000ffff));
        PRINT_RDP_WARNING("ignored")
        fflush(stdout);

#ifdef DISPLAY
        if(prefs.display != NO_DISPLAY)
                DrawVisualFillRect((cmd1 & 0x00ffc000) >> 14, (cmd1 & 0x00000ffc) >> 2,
                                   (cmd0 & 0x00ffc000) >> 14, (cmd0 & 0x00000ffc) >> 2,
                                   rdp_primcolor);
#endif

  /* BWG */
  /* This shouldn't be just a fill, its supposed to draw a textured rectangle 
     from any of the 10 possible Image formats/Sizes 
     into current display (16 or 8 bit) */


} /* static void rdp_texrect() */





static void rdp_texrectflip()
{
        PRINT_RDP_NOT_IMPLEMENTED("TEXRECTFLIP")

        CPU_HALT

} /* static void rdp_texrectflip() */





static void rdp_loadsync()
{
        PRINT_RDP_INFO("LOADSYNC\n")
        PRINT_RDP_WARNING("ignored")
        fflush(stdout);

} /* static void rdp_loadsync() */





static void rdp_pipesync()
{
        PRINT_RDP_INFO("PIPESYNC\n")
        PRINT_RDP_WARNING("ignored")
        fflush(stdout);

} /* static void rdp_pipesync() */





static void rdp_tilesync()
{
        PRINT_RDP_INFO("TILESYNC\n")
        PRINT_RDP_WARNING("ignored")
        fflush(stdout);

} /* static void rdp_tilesync() */





static void rdp_fullsync()
{
        PRINT_RDP_INFO("FULLSYNC\n")
        PRINT_RDP_WARNING("does DP interrupt - don't know if correct")

        reg.do_or_check_sthg = RS4300I_DO_DP_INTERRUPT;

} /* static void rdp_fullsync() */





static void rdp_setkeygb()
{
        PRINT_RDP_NOT_IMPLEMENTED("SETKEYGB")

        CPU_HALT

} /* static void rdp_setkeygb() */





static void rdp_setkeyr()
{
        PRINT_RDP_NOT_IMPLEMENTED("SETKEYR")

        CPU_HALT

} /* static void rdp_setkeyr() */





static void rdp_setconvert()
{
        PRINT_RDP_NOT_IMPLEMENTED("SETCONVERT")

        CPU_HALT

} /* static void rdp_setconvert() */





static void rdp_setscissor()
{
        static char     *interlace_modes[] = { "no", "?", "even", "odd" };



        PRINT_RDP_INFO("SETSCISSOR ")
        PRINT_RDP_MNEMONIC("x=%lu; y=%lu; interlace_mode=%s; width=%lu; height=%lu\n",
               (cmd0 & 0x00fff000) >> 14,
               (cmd0 & 0x00000fff) >> 2,
               interlace_modes[(cmd1 & 0x03000000) >> 24],
               (cmd1 & 0x00fff000) >> 14,
               (cmd1 & 0x00000fff) >> 2);
        PRINT_RDP_WARNING("interlace mode is ignored")
        fflush(stdout);

#ifdef DISPLAY
        if(prefs.display != NO_DISPLAY)
                SetVisualClipRect((cmd0 & 0x00fff000) >> 14, (cmd0 & 0x00000fff) >> 2,
                                  (cmd1 & 0x00fff000) >> 14, (cmd1 & 0x00000fff) >> 2);
#endif

/* BWG */
/* You are mostly correct here, but this comes back to my origional gripe..
   I followed this function for the X11 handler...  You use X's scissor,
   that isnt correct.  You have to do scissors on all RDP commands to the frame
   buffer in RDRAM.  Eventually the vertical retrace causes this to make it to 
   the screen. */
/* Conclusion, you affect X-Window, not RDRAM frame buffer..
   It is a problem. */

} /* static void rdp_setscissor() */





static void rdp_setprimdepth()
{
        PRINT_RDP_NOT_IMPLEMENTED("SETPRIMDEPTH")

        CPU_HALT

} /* static void rdp_setprimdepth() */





static void rdp_setothermode()
{
        PRINT_RDP_INFO("SETOTHERMODE\n")
        PRINT_RDP_WARNING("this should clear/init SETOTHERMODE_[HL] - is not done")
        fflush(stdout);

} /* static void rdp_setothermode() */





static void rdp_loadtlut()
{
        PRINT_RDP_INFO("LOADTLUT ")

/* BWG */
        if( (cmd1 & 0x00ffc000) >> 14 == 255)  /* if 8 bit LUT */
        {
            /* Should change TLUT_8 to TLUT_4[*] slower but more accurate 
               It would only be a problem if either:
               1) a program loaded 4 bit LUTS then drew as though an 8 bit LUT was loaded
               2) a program loaded 8 bit LUT then drew as though 4 bit LUTS were loaded */
                
                rdp_tlut_8_fmt   = rdp_textureimg_fmt;
                rdp_tlut_8_size  = rdp_textureimg_size;
                rdp_tlut_8_rdram = rdp_textureimg_rdram;
  
                PRINT_RDP_MNEMONIC("tile=%lu, count=255\n", (cmd1 & 0x07000000) >> 24);
        }
        else  /* count = 15 and tile->palette is meaningfull */
        {
            /* only do this operation 1 time */
            /* (fix me with a structure pointer BWG)  
               to prevent repettitve [CURR_TILE]'s */
          
                int CURR_TILE = (cmd1 & 0x07000000) >> 24;

                rdp_tlut_4_fmt[rdp_td[CURR_TILE].palette]   = rdp_textureimg_fmt; 
                rdp_tlut_4_size[rdp_td[CURR_TILE].palette]  = rdp_textureimg_size;
                rdp_tlut_4_rdram[rdp_td[CURR_TILE].palette] = rdp_textureimg_rdram;

                PRINT_RDP_MNEMONIC("tile=%u, count=%ld\n", 
                       CURR_TILE,
                       (cmd1 & 0x00ffc000) >> 14);

        }
        fflush(stdout);


} /* static void rdp_loadtlut() */





static void rdp_settilesize()
{
        PRINT_RDP_INFO("SETTILESIZE ")
        PRINT_RDP_MNEMONIC("uls=%lu; ult=%lu; tile=%lu; lrs=%lu; lrs=%lu\n",
               (cmd0 & 0x00fff000) >> 12,
                cmd0 & 0x00000fff,
               (cmd1 & 0x07000000) >> 24,
               (cmd1 & 0x00fff000) >> 12,
                cmd1 & 0x00000fff);
        PRINT_RDP_WARNING("ignored")
        fflush(stdout);

} /* static void rdp_settilesize() */





static void rdp_loadblock()
{
        PRINT_RDP_INFO("LOADBLOCK ")
        PRINT_RDP_MNEMONIC("uls=%lu; ult=%lu; tile=%lu; lrs=%lu; dxt=%lu\n",
               (cmd0 & 0x00fff000) >> 12,
                cmd0 & 0x00000fff,
               (cmd1 & 0x07000000) >> 24,
               (cmd1 & 0x00fff000) >> 12,
                cmd1 & 0x00000fff);
        PRINT_RDP_WARNING("ignored")
        fflush(stdout);

} /* static void rdp_loadblock() */





static void rdp_loadtile()
{
        PRINT_RDP_INFO("LOADTILE ")
        PRINT_RDP_MNEMONIC("uls=%lu, ult=%lu, tile=%lu; lrs=%lu, lrt=%lu\n", 
               (cmd0 & 0x00fff000) >> 12, 
               (cmd0 & 0x00000fff),
               (cmd1 & 0x07000000) >> 24,
               (cmd1 & 0x00fff000) >> 12, 
               (cmd1 & 0x00000fff) );
        PRINT_RDP_WARNING("ignored")
        fflush(stdout);

/* BWG */
        /* We are going to try and ignore this command. */
        /* This command moves memory from RDRAM into TMEM. */
        /* We are going to try and aviod this because it is an extra memcpy */
        /* This will get us into trouble only when the uls,ult,lrs,lrt of
           the LOADTILE are different from the uls,ult,lrs,lrt of the SETTILESIZE
           that occurs just before TEXRECT */

} /* static void rdp_loadtile() */





static void rdp_settile()
{
        static char *format[]   = { "RGBA", "YUV", "CI", "IA", "I", "?", "?", "?" };
        static char *size[]     = { "4bit", "8bit", "16bit", "32bit" };
        static char *cm[]       = { "NOMIRROR/WARP", "MIRROR", "CLAMP", "(MIRROR&CLAMP)?" };



/* BWG */
        /* only do this operation 1 time */
        /* (fix me with a structure pointer BWG)  
           to prevent repettitve [CURR_TILE]'s */

        int CURR_TILE = (cmd1 & 0x07000000) >> 24;
        
        rdp_td[CURR_TILE].format  = (cmd0 & 0x00e00000) >> 21;
        rdp_td[CURR_TILE].size    = (cmd0 & 0x00180000) >> 19;

        /* The following is << 3, because line represents 64 bit entries. */
        /* 2 lines = 128 bits..  128 bits / 16 bits per pixel = 8 pixels. */
        /* It will be easier for us to use number of pixels rather than lines */

        rdp_td[CURR_TILE].line    = ((cmd0 & 0x0003fe00) >> 9) << 3;
        rdp_td[CURR_TILE].tmem    = (cmd0 & 0x000001ff) ;
        rdp_td[CURR_TILE].palette = (cmd1 & 0x00f00000) >> 20;
        rdp_td[CURR_TILE].clampt  = (cmd1 & 0x00080000) >> 19;
        rdp_td[CURR_TILE].mirrort = (cmd1 & 0x00040000) >> 18;
        rdp_td[CURR_TILE].maskt   = (cmd1 & 0x0003c000) >> 14;
        rdp_td[CURR_TILE].shiftt  = (cmd1 & 0x00003c00) >> 10;
        rdp_td[CURR_TILE].clamps  = (cmd1 & 0x00000200) >> 9;
        rdp_td[CURR_TILE].mirrors = (cmd1 & 0x00000100) >> 8;
        rdp_td[CURR_TILE].masks   = (cmd1 & 0x000000f0) >> 4;
        rdp_td[CURR_TILE].shifts  = (cmd1 & 0x0000000f) ;
/* end BWG */


        PRINT_RDP_INFO("SETTILE ")
        PRINT_RDP_MNEMONIC("format=%s; size=%s; line=%lu; tmem=%lu; tile=%lu; palette=$%lx; "
               "cmt=%s; maskt=%lu; shiftt=%lu; cms=%s; masks=%lu; shifts=%lu\n",
               format[rdp_td[CURR_TILE].format],
               size[rdp_td[CURR_TILE].size],
               rdp_td[CURR_TILE].line,
               rdp_td[CURR_TILE].tmem,
               CURR_TILE,
               rdp_td[CURR_TILE].palette,
               cm[rdp_td[CURR_TILE].clampt + rdp_td[CURR_TILE].mirrort],
               rdp_td[CURR_TILE].maskt,
               rdp_td[CURR_TILE].shiftt,
               cm[rdp_td[CURR_TILE].clamps + rdp_td[CURR_TILE].mirrors],
               rdp_td[CURR_TILE].masks,
               rdp_td[CURR_TILE].shifts);

} /* static void rdp_settile() */





static void rdp_fillrect()
{
        PRINT_RDP_INFO("FILLRECT ")

/* BWG */ /* Fixed lrx->lry typo */
        PRINT_RDP_MNEMONIC("ulx=%lu; uly=%lu; lrx=%lu; lry=%lu\n",
               (cmd0 & 0x00ffc000) >> 14,
               (cmd0 & 0x00000ffc) >> 2,
               (cmd1 & 0x00ffc000) >> 14,
               (cmd1 & 0x00000ffc) >> 2);
        PRINT_RDP_WARNING("modes are ignored")
        fflush(stdout);

#ifdef DISPLAY
        if(prefs.display != NO_DISPLAY)
                DrawVisualFillRect((cmd1 & 0x00ffc000) >> 14, (cmd1 & 0x00000ffc) >> 2,
                                   (cmd0 & 0x00ffc000) >> 14, (cmd0 & 0x00000ffc) >> 2,
                                   rdp_fillcolor);
#endif

/* BWG */
/* You are mostly correct here, but this comes back to my origional gripe..
   I followed this function for the X11 handler...  You cleared the view port,
   that isnt correct.  You have to clear the frame buffer in RDRAM.  Eventually
   the vertical retrace causes this to make it to the screen. */
/* Conclusion, you affect X-Window, not RDRAM frame buffer..  It is a problem. */

} /* static void rdp_fillrect() */





static void rdp_setfillcolor()
{
        PRINT_RDP_INFO("SETFILLCOLOR ")
        PRINT_RDP_MNEMONIC("color=$%08lx\n", cmd1);
        fflush(stdout);

        rdp_fillcolor = cmd1;

} /* static void rdp_setfillcolor() */





static void rdp_setfogcolor()
{
        PRINT_RDP_INFO("SETFOGCOLOR ")
        PRINT_RDP_MNEMONIC("color=$%08lx\n", cmd1);
        fflush(stdout);

        rdp_fogcolor = cmd1;

} /* static void rdp_setfogcolor() */





static void rdp_setblendcolor()
{
        PRINT_RDP_INFO("SETBLENDCOLOR ")
        PRINT_RDP_MNEMONIC("color=$%08lx\n", cmd1);
        fflush(stdout);

        rdp_blendcolor = cmd1;

} /* static void rdp_setblendcolor() */





static void rdp_setprimcolor()
{
        PRINT_RDP_INFO("SETPRIMCOLOR ")
        PRINT_RDP_MNEMONIC("color=$%08lx\n", cmd1);
        fflush(stdout);

        rdp_primcolor = cmd1;

} /* static void rdp_setprimcolor() */





static void rdp_setenvcolor()
{
        PRINT_RDP_INFO("SETENVCOLOR ")
        PRINT_RDP_MNEMONIC("color=$%08lx\n", cmd1);
        fflush(stdout);

        rdp_envcolor = cmd1;

} /* static void rdp_setenvcolor() */





static void rdp_setcombine()
{
        PRINT_RDP_INFO("SETCOMBINE ")
        PRINT_RDP_MNEMONIC("mode0=$%06lx; mode1=$%08lx\n",
               (cmd0 & 0x00ffffff),
               (cmd1 & 0xffffffff));
        PRINT_RDP_WARNING("ignored")
        fflush(stdout);

} /* static void rdp_setcombine() */





static void rdp_settextureimage()
{
        static char *format[]   = { "RGBA", "YUV", "CI", "IA", "I", "?", "?", "?" };
        static char *size[]     = { "4bit", "8bit", "16bit", "32bit" };


/* BWG */
        rdp_textureimg_fmt = (cmd0 & 0x00e00000) >> 21;
        rdp_textureimg_size   = (cmd0 & 0x00180000) >> 19;
        rdp_textureimg_width  = 1 + (cmd0 & 0x00000fff);
        rdp_textureimg_rdram  = cmd1;

        PRINT_RDP_INFO("SETTEXTUREIMAGE ")
        PRINT_RDP_MNEMONIC("format=%s; size=%s; width=%lu; addr=$%lx\n",
               format[rdp_textureimg_fmt],
               size[rdp_textureimg_size],
               (long) rdp_textureimg_width,
               rdp_textureimg_rdram);
        PRINT_RDP_WARNING("ignored")
        fflush(stdout);

} /* static void rdp_settextureimage() */





static void rdp_setdepthimage()
{
        PRINT_RDP_INFO("SETDEPTHIMAGE ")
        PRINT_RDP_MNEMONIC("addr=$%lx\n", cmd1);
        PRINT_RDP_WARNING("ignored")
        fflush(stdout);

} /* static void rdp_setdepthimage() */





static void rdp_setcolorimage()
{
        static char *format[]   = { "RGBA", "YUV", "CI", "IA", "I", "?", "?", "?" };
        static char *size[]     = { "4bit", "8bit", "16bit", "32bit" };



/* BWG */
        rdp_colorimg_fmt =  (cmd0 & 0x00e00000) >> 21;
        rdp_colorimg_size   =  (cmd0 & 0x00180000) >> 19;
        rdp_colorimg_width  =  1 + (cmd0 & 0x00000fff);
        rdp_colorimg_rdram  = cmd1;

        PRINT_RDP_INFO("SETCOLORIMAGE ")
        PRINT_RDP_MNEMONIC("format=%s; size=%s; width=%lu; addr=$%lx\n",
               format[rdp_colorimg_fmt],
               size[rdp_colorimg_size],
               (long) rdp_colorimg_width,
               rdp_colorimg_rdram);
        PRINT_RDP_WARNING("ignored")
        fflush(stdout);

} /* static void rdp_setcolorimage() */





static void rdp_trifill()
{
        PRINT_RDP_NOT_IMPLEMENTED("TRIFILL")

        CPU_HALT

} /* static void rdp_trifill() */





static void rdp_trishade()
{
        PRINT_RDP_NOT_IMPLEMENTED("TRISHADE")

        CPU_HALT

} /* static void rdp_trishade() */





static void rdp_tritxtr()
{
        PRINT_RDP_NOT_IMPLEMENTED("TRITXTR")

        CPU_HALT

} /* static void rdp_tritxtr() */





static void rdp_trishadetxtr()
{
        PRINT_RDP_NOT_IMPLEMENTED("TRISHADETXTR")

        CPU_HALT

} /* static void rdp_trishadetxtr() */





static void rdp_trifillz()
{
        PRINT_RDP_NOT_IMPLEMENTED("TRIFILLZ")

        CPU_HALT

} /* static void rdp_trifillz() */





static void rdp_trishadez()
{
        PRINT_RDP_NOT_IMPLEMENTED("TRISHADEZ")

        CPU_HALT

} /* static void rdp_trishadez() */





static void rdp_tritxtrz()
{
        PRINT_RDP_NOT_IMPLEMENTED("TRITXTRZ")

        CPU_HALT

} /* static void rdp_tritxtrz() */





static void rdp_trishadetxtrz()
{
        PRINT_RDP_NOT_IMPLEMENTED("TRISHADETXTRZ")

        CPU_HALT

} /* static void rdp_trishadetxtrz() */





