/******************************************************************************
 * mach64 Chapter 6 sample code                                               *
 *                                                                            *
 * tblit.c - This program demonstrates transparent bitblits.                  *
 * A pattern of rectangles is displayed on the screen.  Then a small          *
 * pattern is displayed in the top left corner to act as the source of        *
 * bitblit.  This source is blitted using a colour compare, first equal       *
 * to LIGHT BLUE, then not equal to LIGHT BLUE.  In the fist case, the        *
 * areas of the source pattern that is equal to light blue is transparent.    *
 * In the second case, the areas of the source pattern that is not equal      *
 * to light blue is transparent.                                              *
 *                                                                            *
 * Copyright (c) 1994-1998 ATI Technologies Inc.  All rights reserved.        *
 ******************************************************************************/

#include <stdio.h>
#include <i86.h>
#include "..\util\atim64.h"
#include "..\util\defines.h"
#include "..\util\main.h"

/******************************************************************************
 * Main Program to demonstrate transparent bitblits                           *
 *  Function: A small rectangular pattern is blitted to the screen a few      *
 *            times, but the colour compare is set to equal to LIGHT BLUE     *
 *            and not equal to LIGHT BLUE.  This results in transparent       *
 *            bitblits.                                                       *
 *    Inputs: Arguments for mode spatial and colour resolution                *
 *   Outputs: NONE                                                            *
 ******************************************************************************/

void main (int argc, char *argv[])
{
    int width;                          // Width of drawing area.
    int height;                         // Height of drawing area.
    int i;                              // Counter for rows of rectangles.
    int j;                              // Counter for columns of rectangles.
    int n;                              // # rectangles in x and y direction.

    printf ("mach64 Chapter 6 sample code\n"
            "\n"
            "tblit.c\n"
            "This program demonstrates transparent bitblits.\n"
            "A pattern of rectangles is displayed on the screen.  Then a small\n"
            "pattern is displayed in the top left corner to act as the source of\n"
            "bitblit.  This source is blitted using a colour compare, first equal\n"
            "to LIGHT BLUE, then not equal to LIGHT BLUE.  In the fist case, the\n"
            "areas of the source pattern that is equal to light blue is transparent.\n"
            "In the second case, the areas of the source pattern that is not equal\n"
            "to light blue is transparent.\n"
            "\n"
            "Spatial resolution (640, 800, 1024, 1280, 1600) and Colour Depth\n"
            "(8, 15, 16, 24, 32) should be passed as arguments.\n"
            "Default setting is 640x480 spatial resolution and 8bpp pixel depth.\n");

    // Batch command to detect the mach64, perform a hardware query, Save old
    // mode information, process mode info arguments, load and set mode, enable
    // aperture, set up palettes, initialize engine to known state, and reset
    // all engine queues.
    start (argc, argv);

    // Check for 24 bpp mode - Lines are not supported in 24 bpp modes.
    if (MODE_INFO.bpp == 24)
    {
        // Disable accelerator mode and switch back to VGA text mode.

        finish ();

        printf ("Transparent Bitblits are not supported in 24 bpp modes.\n");
        exit (1);
    } // if

    // Set up values.
    width = 640;                        // Less than or equal to xres.
    height = 480;                       // Less than or equal to yres.
    n = 4;                              // > 0 ,<= min (width, height)

    clear_screen (0, 0, MODE_INFO.xres, MODE_INFO.yres);

    for (i = 0; i < n; i++)
    {
        for (j = 0; j < n; j++)
        {
            wait_for_fifo (1);
            regw (DP_FRGD_CLR, get_colour_code ((n*i+j)%NUM_COLOURS));
            draw_rectangle (((MODE_INFO.xres - width)/2) + (j*width/n),
                            ((MODE_INFO.yres - height)/2) + (i*height/n),
                            width/n, height/n);
        } // for
    } // for
    
    // Wait for carriage return
    getch ();

    // Draw the source to be blited.
    wait_for_fifo (1);
    regw (DP_FRGD_CLR, get_colour_code(WHITE));
    draw_rectangle ((MODE_INFO.xres - width)/2,
                    (MODE_INFO.yres - height)/2,
                    width / 8,
                    height / 6);
    wait_for_fifo (1);
    regw (DP_FRGD_CLR, get_colour_code (LIGHTRED));
    draw_rectangle (((MODE_INFO.xres - width)/2) + (width / 64),
                    ((MODE_INFO.yres - height)/2) + (height / 48),
                    (width / 8) - (2 * (width / 64)),
                    (height / 6) - (2 * (height / 48)));
    wait_for_fifo (1);
    regw (DP_FRGD_CLR, get_colour_code (LIGHTBLUE));
    draw_rectangle (((MODE_INFO.xres - width)/2) + (width / 32),
                    ((MODE_INFO.yres - height)/2) + (height / 24),
                    (width / 8) - (2 * (width / 32)),
                    (height / 6) - (2 * (height / 24)));

    // Wait for a carriage return.
    getch ();

    // Set colour compare registers to source compare:
    //
    // In this example, the LIGHTBLUE center of the source rectangle
    // is selected as being the source colour to ignore when bliting.
    // The resultant blit will contain all the source data except pixels
    // having the same colour as the compare colour (LIGHTBLUE). Note that
    // the compare source is SOURCE. Also, the compare colour and the colour
    // pixel being compared are both ANDed with the colour compare mask.
    wait_for_fifo (3);
    regw (CLR_CMP_CNTL, COMPARE_SOURCE | COMPARE_EQUAL);
    regw (CLR_CMP_CLR, get_colour_code (LIGHTBLUE));
    regw (CLR_CMP_MASK, 0xFFFFFFFF);

    // Draw several transparent blits at different locations.

    // Set src type for blit.
    wait_for_fifo (1);
    regw (DP_SRC, FRGD_SRC_BLIT);

    for (i = 0; i < 6; i++)
    {
        blit ((MODE_INFO.xres - width)/2,
              (MODE_INFO.yres - height)/2,
              ((MODE_INFO.xres - width)/2 + width / 8) + (i * (width / 8)),
              ((MODE_INFO.yres - height)/2) + (i * (height / 6)),
              width / 8, height / 6);
    } // for

    // By changing the compare function from COMPARE_EQUAL to
    // COMPARE_NOT_EQUAL, the resultant blit will contain ONLY the source
    // data having the same colour as the compare colour (LIGHTBLUE).
    wait_for_fifo (1);
    regw (CLR_CMP_CNTL, COMPARE_SOURCE | COMPARE_NOT_EQUAL);

    // Draw several transparent blits at different locations.
    for (i = 0; i < 6; i++)
    {
        blit ((MODE_INFO.xres - width)/2,
              (MODE_INFO.yres - height)/2,
              ((MODE_INFO.xres - width)/2 + 2 * width / 8) + (i * (width / 8)),
              ((MODE_INFO.yres - height)/2) + (i * (height / 6)),
              width / 8, height / 6);
    } // for

    // Wait for a carriage return.
    getch ();

    // Batch command to restore old mode.
    finish ();

    exit (0);                           // No errors.

} // main
