/*FILE HEADER**************************************************************
 *
 *  File name		: $Id$
 *  RCS Revision Number	: $Revision: 1.1 $
 *  Last Modified	: $Date: 94/10/28 09:23:34 $
 *  CSCI name		: Real-Time Graphics System - Applications Interface
 *  CSC name		: All functions
 *  Notes:
 *	This file contains the set of functions which can be used by
 *	application programs to drive a DY 4 Graphics Controller Card
 *	equipped with Real-Time Graphics System - Command Processor
 *	firmware.
 *  History		:
 *	1994 Feb 25	Jeff Sanderson
 *	    Release Rev -.
 *
 *
 * NOTE: For an explanation of the following functions, please refer to:
 *
 *        SVME/DMV-770 RTGS Software Users Manual, DY4 Doc.# 804030
 *
 *END FILE HEADER*********************************************************/


#include "dy4std.h"        /* Headers which define the FFW environment   */
#include "es.h"            /* on the host card, and give access to the   */
#include "css.h"           /* services of the host FFW                   */

#include "rtgs_ai.h"       /* RTGS AI header                             */
#include "strings.h"       /* command name and error code strings        */


/*- Local function prototypes -------------------------------------------*/

void Put_cmd( register uint32 *command, register int n );


/*- Global variables ----------------------------------------------------*/

uint32  W_gcc_base_addr;   /* The base address of the GCC.               */
fifo_t  *W_fifo_base;      /* ptr to current fifo                        */
static  uint32   cmd[8];   /* A common array for storing command streams */


/*HEADER*******************************************************************
 *
 *  CSU name	: Utility Functions
 *  Description	:
 *	These functions provide a functional interface to modifying
 *	addresses and registers on the GCC.
 *
 *END*********************************************************************/

/*-----------------------------------------------------------------------*/
/* set the base of the current fifo_t struct used to access the RTGS-CP  */
/*-----------------------------------------------------------------------*/

void Set_current_fifo( fifo_t *fifo )
{
    if( fifo == DEFAULT_FIFO )
    {
	W_fifo_base = DEFAULT_FIFO_ADDR;
    }
    else
    {
	W_fifo_base = fifo;
    }
}

/*-----------------------------------------------------------------------*/
/* set the base of the current SVME-770 being commanded                  */
/*-----------------------------------------------------------------------*/

void Set_gcc_base_address( int addr )
{
    W_gcc_base_addr = ( uint32 )( addr );
    Set_current_fifo( DEFAULT_FIFO_ADDR );
}

/*-----------------------------------------------------------------------*/
/* Take the SVME-770 out of BI-mode(r)                                   */
/*-----------------------------------------------------------------------*/

void Take_gcc_out_of_bi_mode( void )
{
    uint32 tmp;

    /* Take the GCC out of Bus Isolation Mode */

    BI_MODE = 0;

    /* Initialize the pointer to the FIFO */

    Set_current_fifo( DEFAULT_FIFO );
 
    /* Rev 1 SMP34020 chips need a read to initialize */
    /* the VMEbus interface */

    tmp = FIFO_HEAD_PTR;
}

/*-----------------------------------------------------------------------*/
/* Get the error code, clear the reg, and return the code                */
/*-----------------------------------------------------------------------*/

uint32 Get_error_code( void )
{
    uint32 error_code;

    error_code = ERROR_REG;
    ERROR_REG = 0;

    return( error_code );
}

/*-----------------------------------------------------------------------*/
/* Syncronize the host execution to the GCC's ( use raise int if you dont*/
/* want to poll over the VME)                                            */
/*-----------------------------------------------------------------------*/

void Gcc_sync( void )
{

    cmd[ 0 ] = 0x00100000;

    Put_cmd( cmd, 1 );

    while( FIFO_TAIL_PTR != FIFO_HEAD_PTR )
    {
        /* do nothing */
    }
}

/*------------------------------------------------------------------------*/
/* NOTE: Due to the byte swapping between little and big endian modes,    */
/* three copy routines are needed, based on the element size being copied */
/* It is also difficult to take care of trailing bytes. For this reason   */
/* all copies are done in multiples of long words. You will also note that*/
/* the Gcc_malloc command has been altered to pad out mallocs to be       */
/* multiples of long words. This should prevent overruns of malloc'd      */
/* buffers.                                                               */
/*------------------------------------------------------------------------*/

void Copy_data_to_gcc( char *src, char *dst, int size )
{
    register int32   i;
    register uint32  *src32;
    register uint32  *dst32;

    /* Copy the pointers. */

    src32 = ( uint32 * )( src );
    dst32 = ( uint32 * )( dst );

    /* Copy as much as possible 32 bits at a time. */

    for( i = 0 ; i < ( size / 4 ) ; i++ )
    {
	*dst32++ = *src32++;
    }

    /* Copy any remaining bytes one at a time. */

    i = size - (( size / 4 ) * 4 );
    if( i )
    {
        *dst32 = *src32;
    }
}

/*-----------------------------------------------------------------------*/

void Copy_string_to_gcc( char *src, char *dst, int size )
{
    register uint32  *src32;
    register uint32  *dst32;
    register int32   i;

    union bs {
        uint32 lw;
        uint8 b[4];
    } tmp1, tmp2;

    /* Copy the pointers. */

    src32 = ( uint32 * )( src );
    dst32 = ( uint32 * )( dst );

    /* Copy as much as possible 32 bits at a time. */

    for( i = 0 ; i <= ( size / 4 ) ; i++ )
    {
        tmp1.lw     = *src32++;
        tmp2.b[ 0 ] = tmp1.b[ 3 ];
        tmp2.b[ 1 ] = tmp1.b[ 2 ];
        tmp2.b[ 2 ] = tmp1.b[ 1 ];
        tmp2.b[ 3 ] = tmp1.b[ 0 ];
	*dst32++    = tmp2.lw;
    }

    i = size - (( size / 4 ) * 4 );

    if( i )
    {
        tmp1.lw     = *src32++;
        tmp2.b[ 0 ] = tmp1.b[ 3 ];
        tmp2.b[ 1 ] = tmp1.b[ 2 ];
        tmp2.b[ 2 ] = tmp1.b[ 1 ];
        tmp2.b[ 3 ] = tmp1.b[ 0 ];
	*dst32++    = tmp2.lw;
    }
}

/*-----------------------------------------------------------------------*/

void Copy_bitmap_to_gcc( char *src, char *dst, int size )
{
    register uint32  *src32;
    register uint32  *dst32;
    register int32   tmp1;
    register int32   tmp2;
    register int32   i;
    register int32   j;

    /* Copy the pointers. */

    src32 = ( uint32 * )( src );
    dst32 = ( uint32 * )( dst );

    /* Copy as much as possible 32 bits at a time. */

    for( i = 0 ; i <= ( size / 4 ) ; i++ )
    {
	tmp1 = *src32++;

        for( j = 0, tmp2 = 0 ; j < 32 ; j++ )
        {
            tmp2 |= ((( tmp1 >> 31 - j ) & 1 ) << j );
        }

	*dst32++ = tmp2;
    }

    i = size - (( size / 4 ) * 4 );

    if( i )
    {
	tmp1 = *src32++;

        for( j = 0, tmp2 = 0 ; j < 32 ; j++ )
        {
            tmp2 |= ((( tmp1 >> 31 - j ) & 1 ) << j );
        }

	*dst32++ = tmp2;
    }
}

/*-----------------------------------------------------------------------*/
/* Set the current cursor position. This is only read by the RTGS-CP     */
/* during vertical retrace ( every 1/60th sec. )                         */
/*-----------------------------------------------------------------------*/

void Move_cursor( int x, int y )
{
    CURSOR_LOCATION_REG = ((( uint16 )( y ) << 16 ) + ( uint16 )( x ));
}



/*HEADER*******************************************************************
 *
 *  CSU name	: Workstation Functions
 *  Description	:
 *	The Workstation functions set graphics modes and characteristics
 *	of the GCC.
 *
 *	Each function simply formats the parameters into an array,
 *	which is written to the GCC FIFO by Put_cmd().
 *
 *END*********************************************************************/

/*-----------------------------------------------------------------------*/

void Initialize_graphics( void )
{
    cmd[ 0 ] = ( 0x0000 << 16 );

    Put_cmd( cmd, 1 );
}

/*-----------------------------------------------------------------------*/

void Initialize_video( int video_index )
{
    cmd[ 0 ] = (( 0x0001 << 16 ) + ( uint16 )( video_index ));

    Put_cmd( cmd, 1 );
}

/*-----------------------------------------------------------------------*/

void Custom_initialize_video( video_params_t *video_params )
{
    cmd[ 0 ] = ( 0x0002 << 16 );
    cmd[ 1 ] = GSP_ADDR( video_params );

    Put_cmd( cmd, 2 );
}

/*-----------------------------------------------------------------------*/

void Run_diagnostics( void )
{
    cmd[ 0 ] = ( 0x0003 << 16 );

    Put_cmd( cmd, 1 );
}

/*-----------------------------------------------------------------------*/

char *Gcc_malloc( int size, int mem_addr )
{
    register uint32 temp;


    /* round up to the next long word size */
    if( size & 0x3 )
    {
        size &= 0xFFFFFFFC;
        size += 4;
    }

    W_malloc_flag = 0;

    cmd[ 0 ] = ( 0x0004 << 16 );
    cmd[ 1 ] = ( uint32 )( size );

    if( mem_addr != 0 )
    {
	cmd[2] = GSP_ADDR( mem_addr );
    }
    else
    {
	cmd[2] = 0;
    }

    Put_cmd( cmd, 3 );

    if( W_vector_mask & CONDITION_MALLOC )
    {
        while( W_malloc_flag == 0 );
    }
    else
    {
	Gcc_sync();
    }
    
    temp = MEM_ADDR_REG;

    if( temp == 0 )
    {
        return(( char * )( temp ));
    }
    else
    {
        return(( char * )( VME_ADDR( temp  )));
    }
}

/*-----------------------------------------------------------------------*/

void Gcc_free( char *mem_addr )
{
    cmd[ 0 ] = ( 0x0005 << 16 );
    cmd[ 1 ] = ( uint32 )( GSP_ADDR( mem_addr ));

    Put_cmd( cmd, 2 );
}

/*-----------------------------------------------------------------------*/

void Raise_interrupt( void )
{
    /* Clear the flag, indicating that the */
    /* interrupt hasn't happened yet.      */

    W_interrupt_flag = 0;

    cmd[ 0 ] = ( 0x0006 << 16 );

    Put_cmd( cmd, 1 );

    /* Wait until the interrupt happens.   */

    while( W_interrupt_flag == 0 ) 
    {
        /* do nothing */
    }
}

/*-----------------------------------------------------------------------*/

void Install_font( int font_index )
{
    cmd[0] = (( 0x0007 << 16 ) + ( uint16 )( font_index ));

    Put_cmd( cmd, 1 );
}

/*-----------------------------------------------------------------------*/

void Load_text_font( int index, font_t *text_font )
{
    cmd[ 0 ] = (( 0x0008 << 16 ) + ( uint16 )( index ));
    cmd[ 1 ] = ( uint32 )( GSP_ADDR( text_font ));

    Put_cmd( cmd, 2 );
}

/*-----------------------------------------------------------------------*/

void Define_text_symbol( int index, char *str )
{
    cmd[ 0 ] = (( 0x0009 << 16 ) + ( uint16 )( index ));
    cmd[ 1 ] = ( uint32 )( GSP_ADDR( str ));

    Put_cmd( cmd, 2 );
}

/*-----------------------------------------------------------------------*/

void Clear_screen( int colour, int first_line, int last_line )
{
    cmd[ 0 ] = (( 0x000a << 16 ) + ( uint16 )( colour ));
    cmd[ 1 ] = ((( uint16 )( first_line ) << 16 ) + ( uint16 )( last_line ));

    Put_cmd( cmd, 2 );
}

/*-----------------------------------------------------------------------*/

void Set_clipping_mode( int mode )
{
    cmd[ 0 ] = (( 0x000b << 16 ) + ( uint16 )( mode ));

    Put_cmd( cmd, 1 );
}

/*-----------------------------------------------------------------------*/

void Set_clip_rectangle( int x1, int y1, int x2, int y2 )
{
    cmd[ 0 ] = ( 0x000c << 16 );
    cmd[ 1 ] = ( uint32 )((( uint16 )( y1 ) << 16 ) + ( uint16 )( x1 ));
    cmd[ 2 ] = ( uint32 )((( uint16 )( y2 ) << 16 ) + ( uint16 )( x2 ));

    Put_cmd( cmd, 3 );
}

/*-----------------------------------------------------------------------*/

void Set_plane_mask( int plane_mask )
{
    cmd[ 0 ] = (( 0x000d << 16 ) + ( uint16 )( plane_mask ));

    Put_cmd( cmd, 1 );
}

/*-----------------------------------------------------------------------*/

void Set_colour_representation( int lut, int colour_index, 
                                int red, int green, int blue )
{
    cmd[ 0 ] = (( 0x000e << 16 ) + ( uint32 )( colour_index & 0xFF));
    cmd[ 1 ] = ( (( uint32 )( lut   & 0xFF ) << 24 )
               + (( uint32 )( red   & 0xFF ) << 16 ) 
               + (( uint32 )( green & 0xFF ) <<  8 ) 
               + (( uint32 )( blue  & 0xFF )       ));

    Put_cmd( cmd, 2 );
}

/*-----------------------------------------------------------------------*/

void Set_scale_and_offset( fixed scale_x, fixed scale_y, 
                           int pt_x, int pt_y, int t_x, int t_y)
{
    cmd[ 0 ] = ( 0x000f << 16 );
    cmd[ 1 ] = ( uint32 )( scale_x );
    cmd[ 2 ] = ( uint32 )( scale_y );
    cmd[ 3 ] = ( uint32 )((( uint16 )( pt_y ) << 16 ) + ( uint16 )( pt_x ));
    cmd[ 4 ] = ( uint32 )((( uint16 )(  t_y ) << 16 ) + ( uint16 )(  t_x ));

    Put_cmd( cmd, 5 );
}

/*-----------------------------------------------------------------------*/

void Delay( int ticks )
{
    cmd[ 0 ] = (( 0x0010 << 16 ) + ( uint16 )( ticks ));

    Put_cmd( cmd, 1 );
}

/*-----------------------------------------------------------------------*/

void Set_interrupt_mode( int vector, int level, int mask )
{

    VECTOR_REGISTER = ( uint8 )( vector );

    level &= 0x07;
    level |= 0x10;

    INT_LEVEL_REG  = ( uint8 )( level );

    cmd[ 0 ] = ( 0x0011 << 16 );
    cmd[ 1 ] =  ( uint32 )( mask );

    Put_cmd( cmd, 2 );
}

/*-----------------------------------------------------------------------*/

void Create_fifo( fifo_t *fifo )
{
    cmd[ 0 ] = ( 0x0012 << 16 );
    cmd[ 1 ] =  ( uint32 )( GSP_ADDR( fifo ));

    Put_cmd( cmd, 2 );
}

/*-----------------------------------------------------------------------*/

void Release_fifo( void )
{
    cmd[ 0 ] = ( 0x0013 << 16 );

    Put_cmd( cmd, 1 );
}

/*-----------------------------------------------------------------------*/

void Set_phase_alignment( int offset )
{
    cmd[ 0 ] = (( 0x0014 << 16 ) + ( uint16 )( offset ));

    Put_cmd( cmd, 1 );
}

/*-----------------------------------------------------------------------*/

void Save_video_mode( void )
{
    cmd[ 0 ] = ( 0x0015 << 16 );

    Put_cmd( cmd, 1 );
}

/*-----------------------------------------------------------------------*/

void Get_video_mode( video_params_t *params )
{
    cmd[ 0 ] = ( 0x0016 << 16 );
    cmd[ 1 ] = ( uint32 )( GSP_ADDR( params ));

    Put_cmd( cmd, 2 );
}

/*-----------------------------------------------------------------------*/

void Move_video_vertical( int increment )
{
    cmd[ 0 ] = (( 0x0018 << 16 ) + ( uint16 )( increment ));

    Put_cmd( cmd, 1 );
}

/*-----------------------------------------------------------------------*/

void Move_video_horizontal( int increment )
{
    cmd[ 0 ] = (( 0x0019 << 16 ) + ( uint16 )( increment ));

    Put_cmd( cmd, 1 );
}

/*-----------------------------------------------------------------------*/

void Set_screen_offset( int x, int y )
{
    cmd[ 0 ] = ( 0x001a << 16 );
    cmd[ 1 ] = ( uint32 )((( uint16 )( y ) << 16 ) + ( uint16 )( x ));

    Put_cmd( cmd, 2 );
}

/*-----------------------------------------------------------------------*/

void Move_screen( int *display_buf_start, int *draw_buf_start )
{
    cmd[ 0 ] = ( 0x001b << 16 );
    cmd[ 1 ] = ( uint32 )( GSP_ADDR( display_buf_start ));
    cmd[ 2 ] = ( uint32 )( GSP_ADDR( draw_buf_start ));

    Put_cmd( cmd, 3 );
}

/*-----------------------------------------------------------------------*/

void Reset_seeprom( void )
{
    cmd[ 0 ] = ( 0x001c << 16 );

    Put_cmd( cmd, 1 );
}

/*-----------------------------------------------------------------------*/


/*HEADER*******************************************************************
 *
 *  CSU name	: Drawing Functions
 *  Description	:
 *	The Drawing Functions perform the graphics drawing.
 *
 *	Each function simply formats the parameters into an array,
 *	which is written to the GCC FIFO by Put_cmd().
 *
 *END*********************************************************************/

/*-----------------------------------------------------------------------*/

void Draw_line( int x1, int y1, int x2, int y2 )
{
    cmd[ 0 ] = ( 0x0020 << 16 );
    cmd[ 1 ] = ((( uint16 )( y1 ) << 16 ) + ( uint16 )( x1 ));
    cmd[ 2 ] = ((( uint16 )( y2 ) << 16 ) + ( uint16 )( x2 ));

    Put_cmd( cmd, 3 );
}

/*-----------------------------------------------------------------------*/

void Draw_polyline( int n, point_t *pts)
{
    cmd[ 0 ] = (( 0x0021 << 16 ) + ( uint16 )( n ));
    cmd[ 1 ] = ( uint32 )( GSP_ADDR( pts ));

    Put_cmd( cmd, 2 );
}

/*-----------------------------------------------------------------------*/

void Draw_ellipse( int x, int y, int r_x, int r_y )
{
    cmd[ 0 ] = ( 0x0022 << 16 );
    cmd[ 1 ] = ((( uint16 )( y   ) << 16 ) + ( uint16 )( x   ));
    cmd[ 2 ] = ((( uint16 )( r_y ) << 16 ) + ( uint16 )( r_x ));

    Put_cmd( cmd, 3 );
}

/*-----------------------------------------------------------------------*/

void Draw_elliptical_arc( int x, int y, int r_x, int r_y, 
                          int theta_1, int theta_2 )
{
    cmd[ 0 ] = ( 0x0023 << 16 );
    cmd[ 1 ] = ((( uint16 )( y       ) << 16 ) + ( uint16 )( x       ));
    cmd[ 2 ] = ((( uint16 )( r_y     ) << 16 ) + ( uint16 )( r_x     ));
    cmd[ 3 ] = ((( uint16 )( theta_1 ) << 16 ) + ( uint16 )( theta_2 ));

    Put_cmd( cmd, 4 );
}

/*-----------------------------------------------------------------------*/

void Draw_text( int x, int y, char *str )
{
    cmd[ 0 ] = ( 0x0024 << 16 );
    cmd[ 1 ] = ((( uint16 )( y ) << 16 ) + ( uint16 )( x ));
    cmd[ 2 ] = ( uint32 )( GSP_ADDR( str ));

    Put_cmd( cmd, 3 );
}

/*-----------------------------------------------------------------------*/

void Draw_text_symbol( int x, int y, int index )
{
    cmd[ 0 ] = (( 0x0025 << 16 ) + ( uint16 )( index ));
    cmd[ 1 ] = ((( uint16 )( y ) << 16 ) + (uint16)( x ));

    Put_cmd( cmd, 2 );
}

/*-----------------------------------------------------------------------*/

void Draw_polymarker( int n, point_t *pts )
{
    cmd[ 0 ] = (( 0x0026 << 16 ) + ( uint16 )( n ));
    cmd[ 1 ] = ( uint32 )( GSP_ADDR( pts ));

    Put_cmd( cmd, 2 );
}

/*-----------------------------------------------------------------------*/

void Draw_filled_rectangle( int x1, int y1, int x2, int y2 )
{
    cmd[ 0 ] = ( 0x0027 << 16 );
    cmd[ 1 ] = ((( uint16 )( y1 ) << 16 ) + ( uint16 )( x1 ));
    cmd[ 2 ] = ((( uint16 )( y2 ) << 16 ) + ( uint16 )( x2 ));

    Put_cmd( cmd, 3 );
}

/*-----------------------------------------------------------------------*/

void Draw_filled_polygon( int n, point_t *pts )
{
    cmd[ 0 ] = (( 0x0028 << 16 ) + ( uint16 )( n ));
    cmd[ 1 ] = ( uint32 )( GSP_ADDR( pts ));

    Put_cmd( cmd, 2 );
}

/*-----------------------------------------------------------------------*/

void Draw_filled_convex_polygon( int n, point_t *pts )
{
    cmd[ 0 ] = (( 0x0029 << 16 ) + ( uint16 )( n ));
    cmd[ 1 ] = ( uint32 )( GSP_ADDR( pts ));

    Put_cmd( cmd, 2 );
}

/*-----------------------------------------------------------------------*/

void Draw_filled_ellipse( int x, int y, int r_x, int r_y )
{
    cmd[ 0 ] = ( 0x002a << 16 );
    cmd[ 1 ] = ((( uint16 )( y   ) << 16 ) + ( uint16 )( x   ));
    cmd[ 2 ] = ((( uint16 )( r_y ) << 16 ) + ( uint16 )( r_x ));

    Put_cmd( cmd, 3 );
}

/*-----------------------------------------------------------------------*/

void Bitblt_bit_expand( int *bitmap, int x, int y, int w, int h, 
                        int src_pitch)
{
    cmd[ 0 ] = (( 0x002b << 16 ) + ( uint16 )( src_pitch ));
    cmd[ 1 ] = ( uint32 )( GSP_ADDR( bitmap ));
    cmd[ 2 ] = ((( uint16 )( y ) << 16 ) + ( uint16 )( x ));
    cmd[ 3 ] = ((( uint16 )( h ) << 16 ) + ( uint16 )( w ));

    Put_cmd( cmd, 4 );
}

/*-----------------------------------------------------------------------*/

void Bitblt_linear_to_xy( int *pixmap, int x, int y, int w, int h, 
                          int src_pitch)
{
    cmd[ 0 ] = (( 0x002c << 16 ) + ( uint16 )( src_pitch ));
    cmd[ 1 ] = ( uint32 )( GSP_ADDR( pixmap ));
    cmd[ 2 ] = ((( uint16 )( y ) << 16 ) + ( uint16 )( x ));
    cmd[ 3 ] = ((( uint16 )( h ) << 16 ) + ( uint16 )( w ));

    Put_cmd( cmd, 4 );
}

/*-----------------------------------------------------------------------*/

void Bitblt_xy_to_xy( int x1, int y1, int x2, int y2, int w, int h)
{
    cmd[ 0 ] = ( 0x002d << 16 );
    cmd[ 1 ] = ((( uint16 )( y1 ) << 16 ) + ( uint16 )( x1 ));
    cmd[ 2 ] = ((( uint16 )( y2 ) << 16 ) + ( uint16 )( x2 ));
    cmd[ 3 ] = ((( uint16 )( h  ) << 16 ) + ( uint16 )( w  ));

    Put_cmd( cmd, 4 );
}

/*-----------------------------------------------------------------------*/

void Bitblt_xy_to_linear( int x, int y, int *pixmap, int w, int h, 
                          int dest_pitch )
{
    cmd[ 0 ] = (( 0x002e << 16 ) + ( uint16 )( dest_pitch ));
    cmd[ 1 ] = ((( uint16 )( y ) << 16 ) + ( uint16 )( x ));
    cmd[ 2 ] = ( uint32 )( GSP_ADDR( pixmap ));
    cmd[ 3 ] = ((( uint16 )( h ) << 16 ) + ( uint16 )( w ));

    Put_cmd( cmd, 4 );
}

/*-----------------------------------------------------------------------*/

void Bitblt_linear_to_linear( int *src, int src_pitch,
                              int *dst, int dst_pitch,
                              int w,    int h )
{
    cmd[ 0 ] = ( 0x002f << 16 );
    cmd[ 1 ] = ((( uint16 )( dst_pitch ) << 16 ) + ( uint16 )( src_pitch ));
    cmd[ 2 ] = ( uint32 )( GSP_ADDR( src ));
    cmd[ 3 ] = ( uint32 )( GSP_ADDR( dst ));
    cmd[ 4 ] = ((( uint16 )( h ) << 16 ) + ( uint16 )( w ));

    Put_cmd( cmd, 5 );
}

/*-----------------------------------------------------------------------*/

/*HEADER*******************************************************************
 *
 *  CSU name	: Pixel Manipulation Functions
 *  Description	:
 *	The Pixel Manipulation Functions get and put individual pixels.
 *
 *	Each function simply formats the parameters into an array,
 *	which is written to the GCC FIFO by Put_cmd().
 *
 *END*********************************************************************/

/*-----------------------------------------------------------------------*/

void Get_pixel( int x, int y, int *pixel_value )
{
    cmd[ 0 ] = ( 0x0030 << 16 );
    cmd[ 1 ] = ((( uint16 )( y ) << 16 ) + ( uint16 )( x ));
    cmd[ 2 ] = ( uint32 )( GSP_ADDR( pixel_value ));

    Put_cmd( cmd, 3 );
}

/*-----------------------------------------------------------------------*/

void Put_pixel( int x, int y, int pixel_value )
{
    cmd[ 0 ] = (( 0x0031 << 16 ) + ( uint16 )( pixel_value ));
    cmd[ 1 ] = ((( uint16 )(  y ) << 16 ) + ( uint16 )( x ));

    Put_cmd( cmd, 2 );
}

/*-----------------------------------------------------------------------*/


/*HEADER*******************************************************************
 *
 *  CSU name	: Attribute Functions
 *  Description	:
 *	The Attribute Functions set attributes for the Drawing Functions.
 *
 *	Each function simply formats the parameters into an array,
 *	which is written to the GCC FIFO by Put_cmd().
 *
 *END*********************************************************************/

/*-----------------------------------------------------------------------*/

void Set_foreground_colour( int colour_index )
{
    cmd[ 0 ] = (( 0x0040 << 16 ) + ( uint16 )( colour_index ));

    Put_cmd( cmd, 1 );
}

/*-----------------------------------------------------------------------*/

void Set_background_colour( int colour_index )
{
    cmd[ 0 ] = (( 0x0041 << 16 ) + ( uint16 )( colour_index ));

    Put_cmd( cmd, 1 );
}

/*-----------------------------------------------------------------------*/

void Set_transparency_mode( int mode )
{
    cmd[ 0 ] = (( 0x0042 << 16 ) + ( uint16 )( mode ));

    Put_cmd( cmd, 1 );
}

/*-----------------------------------------------------------------------*/

void Set_pixel_processing_operation( int ppop )
{
    cmd[ 0 ] = (( 0x0043 << 16 ) + ( uint16 )( ppop ));

    Put_cmd( cmd, 1 );
}

/*-----------------------------------------------------------------------*/

void Set_line_style( int line_style_mask )
{
    cmd[ 0 ] = ( 0x0044 << 16 );
    cmd[ 1 ] = ( uint32 )( line_style_mask );

    Put_cmd( cmd, 2 );
}

/*-----------------------------------------------------------------------*/

void Set_line_width( int width )
{
    cmd[ 0 ] = (( 0x0045 << 16 ) + ( uint16 )( width ));

    Put_cmd( cmd, 1 );
}

/*-----------------------------------------------------------------------*/

void Set_keying_mode( int mode )
{
    cmd[ 0 ] = (( 0x0046 << 16 ) + ( uint16 )( mode ));

    Put_cmd( cmd, 1 );
}

/*-----------------------------------------------------------------------*/

void Set_text_font( int font_index )
{
    cmd[ 0 ] = (( 0x0047 << 16 ) + ( uint16 )( font_index ));

    Put_cmd( cmd, 1 );
}

/*-----------------------------------------------------------------------*/

void Set_text_spacing( int spacing )
{
    cmd[ 0 ] = ( 0x0048 << 16 ) + ( uint16 )( spacing );

    Put_cmd( cmd, 1 );
}

/*-----------------------------------------------------------------------*/

void Set_marker_type( int marker_type )
{
    cmd[ 0 ] = (( 0x0049 << 16 ) + ( uint16 )( marker_type ));

    Put_cmd (cmd, 1);
}

/*-----------------------------------------------------------------------*/

void Set_marker_size( int marker_size )
{
    cmd[ 0 ] = (( 0x004a << 16 ) + ( uint16 )( marker_size ));

    Put_cmd( cmd, 1 );
}

/*-----------------------------------------------------------------------*/

void Set_environment( environment_t *env )
{
    cmd[ 0 ] = ( 0x004b << 16 );
    cmd[ 1 ] = ( uint32 )( GSP_ADDR( env ));

    Put_cmd( cmd, 2 );
}

/*-----------------------------------------------------------------------*/

void Get_environment( environment_t *env )
{
    cmd[ 0 ] = ( 0x004c << 16 );
    cmd[ 1 ] = ( uint32 )( GSP_ADDR( env ));

    Put_cmd( cmd, 2 );
}

/*-----------------------------------------------------------------------*/

/*HEADER*******************************************************************
 *
 *  CSU name	: Cursor Functions
 *  Description	:
 *	The Cursor Functions define and manipulate the software cursors.
 *
 *	Each function simply formats the parameters into an array,
 *	which is written to the GCC FIFO by Put_cmd().
 *
 *END*********************************************************************/

/*-----------------------------------------------------------------------*/

void Define_cursor( int cursor_type, cursor_def_t *cursor_def )
{
    cmd[ 0 ] = (( 0x0050 << 16 ) + ( uint16 )( cursor_type ));
    cmd[ 1 ] = ( uint32 )( GSP_ADDR( cursor_def ));

    Put_cmd( cmd, 2 );
}

/*-----------------------------------------------------------------------*/

void Set_cursor_mode( int mode )
{
    cmd[ 0 ] = (( 0x0051 << 16 ) + ( uint16 )( mode ));

    Put_cmd( cmd, 1 );
}

/*-----------------------------------------------------------------------*/

void Set_rubberband_mode( int mode, int type )
{
    cmd[ 0 ] = (( 0x0052 << 16 ) + (( uint8 )( mode ) << 8 ) 
               + ( uint8 )( type ));

    Put_cmd( cmd, 1 );
}

/*-----------------------------------------------------------------------*/


/*HEADER*******************************************************************
 *
 *  CSU name	: Inquiry Functions
 *  Description	:
 *	The Inquiry Functions return values from the GCC.
 *
 *	Each function simply formats the parameters into an array,
 *	which is written to the GCC FIFO by Put_cmd().
 *
 *END*********************************************************************/

/*-----------------------------------------------------------------------*/

void Inquire_text_extent( char *string, point_t *size )
{
    cmd[ 0 ] = ( 0x0060 << 16 );
    cmd[ 1 ] = ( uint32 )( GSP_ADDR( string ));
    cmd[ 2 ] = ( uint32 )( GSP_ADDR( size   ));

    Put_cmd( cmd, 3 );
}

/*-----------------------------------------------------------------------*/

void Inquire_pixel_size( int *pixel_size )
{
    cmd[ 0 ] = ( 0x0061 << 16 );
    cmd[ 1 ] = ( uint32 )( GSP_ADDR( pixel_size ));

    Put_cmd( cmd, 2 );
}

/*-----------------------------------------------------------------------*/

void Compare_point_to_cliprect( int x, int y, int *outcodes )
{
    cmd[ 0 ] = ( 0x0062 << 16 );
    cmd[ 1 ] = ( uint32 )((( uint16 )( y ) << 16 ) + ( uint16 )( x ));
    cmd[ 2 ] = ( uint32 )( GSP_ADDR( outcodes ));

    Put_cmd( cmd, 3 );
}

/*-----------------------------------------------------------------------*/

void Get_pixel_address( int x, int y, int *address )
{
    cmd[ 0 ] = ( 0x0063 << 16 );
    cmd[ 1 ] = ((( uint16 )( y ) << 16 ) + ( uint16 )( x ));
    cmd[ 2 ] = ( uint32 )( GSP_ADDR( address ));

    Put_cmd( cmd, 3 );
}

/*-----------------------------------------------------------------------*/


/*HEADER*******************************************************************
 *
 *  CSU name	: Command List Functions
 *  Description	:
 *	The Command List Functions 
 *
 *	Each function simply formats the parameters into an array,
 *	which is written to the GCC FIFO by Put_cmd().
 *
 *END*********************************************************************/

/*-----------------------------------------------------------------------*/

void Open_command_list( int list_number )
{
    cmd[ 0 ] = (( 0x0070 << 16 ) + ( uint16 )( list_number ));

    Put_cmd( cmd, 1 );
}

/*-----------------------------------------------------------------------*/

void Close_command_list( void )
{
    cmd[ 0 ] = ( 0x0071 << 16 );

    Put_cmd( cmd, 1 );
}

/*-----------------------------------------------------------------------*/

void Run_command_list( int list_number )
{
    cmd[ 0 ] = (( 0x0072 << 16 ) + ( uint16 )( list_number ));

    Put_cmd( cmd, 1 );
}

/*-----------------------------------------------------------------------*/

void Delete_command_list( int list_number )
{
    cmd[ 0 ] = (( 0x0073 << 16 ) + ( uint16 )( list_number ));

    Put_cmd( cmd, 1 );
}

/*-----------------------------------------------------------------------*/


/*HEADER*******************************************************************
 *
 *  CSU name	: Double Buffering Functions
 *  Description	:
 *	The Double Buffering Functions manipulate frame buffers.
 *
 *	Each function simply formats the parameters into an array,
 *	which is written to the GCC FIFO by Put_cmd().
 *
 *END*********************************************************************/

/*-----------------------------------------------------------------------*/

void Set_frame_buffering( int drawing_buffer, int visible_buffer )
{
    cmd[ 0 ] = (( 0x0080 << 16 ) + 1 );   /* the 1 is required */
    cmd[ 1 ] = ((( uint16 )( drawing_buffer ) << 16 ) 
               + ( uint16 )( visible_buffer ));

    Put_cmd( cmd, 2 );
}

/*-----------------------------------------------------------------------*/

void Flip_buffers( int clear_buffer_flag, int colour )
{
    cmd[ 0 ] = (( 0x0081 << 16 ) + (( uint8 )( clear_buffer_flag ) << 8 ) 
               + ( uint8 )( colour ));

    Put_cmd( cmd, 1 );
}

/*-----------------------------------------------------------------------*/


/*HEADER*******************************************************************
 *
 *  CSU name	: Downloadable Functions
 *  Description	:
 *	The Downloadable Functions allow for downloading and installing
 *	new functions as commands.
 *
 *	Each function simply formats the parameters into an array,
 *	which is written to the GCC FIFO by Put_cmd().
 *
 *END*********************************************************************/

/*-----------------------------------------------------------------------*/

void Define_new_function( int command_code, int entry_point,
			  int num_parameters )
{
    cmd[ 0 ] = (( 0x0090 << 16 ) + ( uint16 )( command_code ));
    cmd[ 1 ] = ( uint32 )( GSP_ADDR( entry_point ));
    cmd[ 2 ] = ( uint32 )( ( num_parameters << 16 ));

    Put_cmd( cmd, 3 );
}

/*-----------------------------------------------------------------------*/


/*HEADER*******************************************************************
 *
 * The rotate command is an undocumented function, thet was beyond the 
 * scope of the current project. I left it in because several people may 
 * find it useful.
 * The function rotates by an arbitrary angle a source bitmap to a 
 * destination bitmap ( usualy the screen ). 
 * The center of the destination buffer maps to the center of the source 
 * buffer. The source buffer must be large enough that the longest half
 * diagonal of the destination does not fall off the edge of the source
 * buffer.
 * The structure rotate_params must reside on the 770. 
 * 
 * struct {
 *	long output_address;	bit address of upper left corner
 *	long output_pitch;	diff in bits between 2 vert adjacent pixels
 *	long output_width;	width of dest in pixels
 *	long output_height;	height of dest in pixels
 *	long input_address;	bit address of upper left corner 
 *	long input_pitch;	diff in bits between 2 vert adjacent pixels
 *	long input_height;	height of src in pixels
 *	fixed sin_theta;	signed 16-frac_bit fixed point ( 0xnnnn.nnnn )
 *	fixed cos_theta;	signed 16-frac_bit fixed point ( 0xnnnn.nnnn )
 * }rotate_params;
 *
 * In a lab test it took ~1.2 seconds to rotate a 1024x768x8 image
 *END*********************************************************************/

/*-----------------------------------------------------------------------*/

void Rotate( rotate_params *params )
{
    cmd[ 0 ] = ( 0x00FF << 16 );
    cmd[ 1 ] = GSP_ADDR( params );

    Put_cmd( cmd, 2 );
}

/*-----------------------------------------------------------------------*/


/*HEADER*******************************************************************
 *
 *  CSU name	 : Put_cmd
 *  Description	 :
 *	Put_cmd() puts the n words in the command buffer and writes
 *	them to the FIFO.
 *
 *END*********************************************************************/

/*-----------------------------------------------------------------------*/

void Put_cmd( register uint32 *command, register int n )
{
    register int32   i;
    register uint32  head_ptr;
    register uint32  tail_ptr;
    register int32   avail;


    /* Get the current FIFO head pointer. */
    head_ptr = FIFO_HEAD_PTR;

    /* Wait for enough room in the command FIFO. */
    avail = 0;
    while( n > avail )
    {
	tail_ptr = FIFO_TAIL_PTR;
	if( tail_ptr > head_ptr )
        {
	    avail = ((( tail_ptr - head_ptr ) / 0x20 ) - 1 );
        }
	else
        {
	    avail = ((( FIFO_SIZE + tail_ptr - head_ptr ) / 0x20 ) - 1 );
        }
    }

    /* Put the command in the FIFO. */
    for( i = 0 ; i < n ; i++ )
    {
	/* Move to the next location. */
	head_ptr += 0x20;

	/* If the top of the circular queue is reached, go to the base. */
	if( head_ptr > FIFO_END_ADDR )
        {
	    head_ptr = FIFO_BASE_ADDR;
        }

	/* Put the command entry at the current FIFO location. */
	*(( uint32 * )VME_ADDR( head_ptr )) = command[ i ];
    }

    /* Update the pointer to the head of the FIFO. */
    FIFO_HEAD_PTR = head_ptr;

#undef DEBUG
#ifdef DEBUG
    if(( avail = Get_error_code() ) != 0 ) {
        Printf( "%s, %s\n",
               gcc_command_strings[ (( avail >> 16 ) & 0xFFFF ) ],
               gcc_error_strings[ ( avail & 0xFFFF ) ] );
	Key_wait();
    }
#endif
}
/* END OF FILE ************************************************************/

