/****************************************************************************
 * Rage 128 Chapter 4 sample code                                           *
 *                                                                          *
 * meblit.c - This program uses the Rage 128 engine to perform a monochrome *
 * expansion blt using data supplied by the host registers                  *
 *                                                                          *
 * Copyright (c) 1999 ATI Technologies Inc.  All rights reserved.           *
 ****************************************************************************/
#include <stdio.h>
#include <i86.h>
#include <conio.h>
#include <stdlib.h>
#include "..\util\regdef.h"
#include "..\util\defines.h"
#include "..\util\main.h"

void MEBltThruHostData (DWORD * , WORD , blt_data * );

/****************************************************************************
 * Main Program to demonstrate a monochrome expanded blt                    *
 *  Function: Repeatedly blts an 'a' onto the screen.  The monochrome data  *
 *            is supplied to the engine by the HOST_DATAx registers.        *
 *    Inputs: Arguments for mode spatial and colour resolution              *
 *   Outputs: NONE                                                          *
 ****************************************************************************/
void main (int argc, char *argv[])
{
    WORD colour;
    DWORD bitmap[15];
    blt_data *slappy = NULL;

    bitmap[0]  = 0x0003FFFF;            // 00000000000000111111111111111111
    bitmap[1]  = 0x000C0006;            // 00000000000011000000000000000110
    bitmap[2]  = 0xF0300018;            // 11110000001100000000000000011000
    bitmap[3]  = 0x38C3F860;            // 00111000110000111111100001100000
    bitmap[4]  = 0x3318398E;            // 00110011000110000011100110000111
    bitmap[5]  = 0x0C780630;            // 00001100011110000000011000110000
    bitmap[6]  = 0x319F18FC;            // 00110001100111110001100011111100
    bitmap[7]  = 0xC60F630F;            // 11000110000011110110001100001111
    bitmap[8]  = 0x3E0D8C06;            // 00110111000011011000110000000110
    bitmap[9]  = 0xC7E6FFFB;            // 11000111111001101111111111111011
    bitmap[10] = 0xFFF8000D;            // 11111111111110000000000000001101
    bitmap[11] = 0x0000001F;            // 00000000000000000000000000011111
    bitmap[12] = 0x00000000;            // 00000000000000000000000000000000

    R128_StartUp (argc, argv);

    R128_ClearScreen (LIGHTRED);
    slappy->h = 21; // height of the mono bitmap
    slappy->w = 17; // width of the mono bitmap
    getch ();

    while (!kbhit ())
    {
        slappy->x = rand()%(R128_AdapterInfo.xres-slappy->w);
        slappy->y = rand()%(R128_AdapterInfo.yres-slappy->h);
        colour = rand ()%16;
        slappy->frgd = colour;
        colour ^= 0xF;
        slappy->bkgd = colour;
        MEBltThruHostData (&bitmap, 13, slappy);
    }

    // Time to shut down...
    getch ();

    R128_ShutDown ();

    exit (0);

} // main

/****************************************************************************
 * MEBltThruHostData (DWORD *pSrc, WORD NumDWORDS, blt_data *pdata)         *
 *  Function: performs a mono expanded blt, using data from the HOST_DATAx  *
 *            registers.                                                    *
 *    Inputs: DWORD *pSrc - data that will be loaded through the host data  *
 *                          registers.                                      *
 *            WORD NumDWORDS - number of DWORDs to sent thru the host port  *
 *            blt_data *pdata - pointer to the blt_data structure that      *
 *                              contains data on the position and size of   *
 *                              the expanded blt.                           *
 *   Outputs: NONE.                                                         *
 ****************************************************************************/
void MEBltThruHostData (DWORD *pSrc, WORD NumDWORDS, blt_data * pData)
{
    int loop;
    DWORD temp;


    // First write GUI_MASTER_CNTL.
    temp = R128_GetBPPValue (R128_AdapterInfo.bpp);

    R128_WaitForFifo (5);
    regw (DP_GUI_MASTER_CNTL,
                (0 << 0) |      // Use mmDEFAULT_OFFSET and mmDEFAULT_PITCH for SRC
                (0 << 1) |      // Use mmDEFAULT_OFFSET and mmDEFAULT_PITCH for DST
                (0 << 2) |      // Use mmDEFAULT_SC_BOTTOM_RIGHT
                (1 << 3) |      // Use mmSC_TOP_LEFT and mmSC_BOTTOM_RIGHT for DST
                (0xC << 4) |    // NO_BRUSH needed.
                (temp << 8) |   // Set DST_DATATYPE to current bpp
                (0 << 12) |     // Expand to foreground and background.
                (1 << 14) |     // Consume monochrome data from LSbit to MSbit
                (0 << 15) |     // Set Conversion temp to 6500k
                (0xCC << 16) |  // Set ROP3 to SRC_COPY
                (3 << 24) |     // Source Data is from HOSTDATA registers.
                (0 << 27) |     // Clear 3D_SCALE_CNTL (Disable 3D engine)
                (1 << 28) |     // Clear CLR_CMP_CNTL (Disable Color Compare)
                (1 << 29) |     // Clear AUX_SC_CNTL (Disable Auxilary Scissors)
                (1 << 30) |     // Set DP_WRITE_MASK to 0xFFFFFFFF
                (0 << 31)       // No BRUSH_X_Y required.
    );

    // Set the colors to expand the data to.
    temp = R128_GetColourCode (pData->frgd);
    regw (DP_SRC_FRGD_CLR, temp);
    // use the complimentary colour for the background.
    temp = R128_GetColourCode (pData->bkgd);
    regw (DP_SRC_BKGD_CLR, temp);

    // Setup the destination trajectory.
    regw (DST_X_Y, ((pData->x << 16) | pData->y ) );
    regw (DST_WIDTH_HEIGHT, ((pData->w << 16) | pData->h) );

    // Write the data out to the HostData registers.  We write the number of DWords
    // less the last one, which we must write out to HOST_DATA_LAST to tell the GUI
    // engine that the HOSTDATA operation is complete.

    for (loop = 0; loop < NumDWORDS-1; loop++ )
    {
        R128_WaitForFifo (1);
        regw (HOST_DATA0, *pSrc );
        pSrc += 1;
    }

    // Write out the final piece of data.
    R128_WaitForFifo (1);
    regw (HOST_DATA_LAST, *pSrc );
} // R128_MEBltThruHostData ()...

