/******************************************************************************
 * mach64 Chapter 6 sample code                                               *
 *                                                                            *
 * gpblit.c - This program uses the mach64 engine to perform a general        *
 * pattern bitblit.  (source trajectory 4 - General Pattern)                  *
 *                                                                            *
 * 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 a simple general pattern bitblits              *
 *  Function: Draws a general pattern (concentric coloured rectangles)        *
 *            in the top left corner of the screen.  This pattern is used     *
 *            to fill a blit area which is larger than the source.            *
 *    Inputs: Arguments for mode spatial and colour resolution                *
 *   Outputs: NONE                                                            *
 ******************************************************************************/

void main (int argc, char *argv[])
{
    int width;                          // Width of work area.
    int height;                         // Height of work area.
    int srcx;                           // Top left x co-ord of source pattern.
    int srcy;                           // Top left y co-ord of source pattern.
    int srcwidth;                       // Width of source pattern.
    int srcheight;                      // Height of source pattern.
    int dstx;                           // Top left x co-ord of dest area.
    int dsty;                           // Top left y co-ord of dest area.
    int dstwidth;                       // Width of destination area.
    int dstheight;                      // Height of destination area.
    unsigned long rotation;             // Used for 24bpp rotation.

    printf ("mach64 Chapter 6 sample code\n"
            "\n"
            "gpblit.c\n"
            "This program demonstrates a general pattern bitblits.  First it draws\n"
            "a general pattern (concentric coloured rectangles) in the top left\n"
            "corner of the screen.  This pattern is used to fill a blit area which\n"
            "is larger than the source.\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);

    // Setup dimensions of source and destination.
    width = 640;
    height = 480;

    // Main source rectangle (source pattern).
    srcx = width / 32;
    srcy = height / 64;
    srcwidth = width / 16;
    srcheight = height / 12;

    // Destination rectangle.
    dstx = width / 8;
    dsty = height / 16;
    dstwidth = MODE_INFO.xres / 4;
    dstheight = MODE_INFO.yres / 3;

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

    // Draw some filled rectangles to act as a source.
    wait_for_fifo (1);
    regw (DP_FRGD_CLR, get_colour_code (WHITE));
    draw_rectangle (srcx, srcy, srcwidth, srcheight);

    wait_for_fifo (1);
    regw (DP_FRGD_CLR, get_colour_code (LIGHTBLUE));
    draw_rectangle (srcx + (width / 160), srcy + (height / 120),
                    srcwidth - (2 * (width / 160)),
                    srcheight - (2 * (height / 120)));

    wait_for_fifo (1);
    regw (DP_FRGD_CLR, get_colour_code (LIGHTGREEN));
    draw_rectangle (srcx + (2 * (width / 160)), srcy + (2 * (height / 120)),
                    srcwidth - (4 * (width / 160)),
                    srcheight - (4 * (height / 120)));

    wait_for_fifo (1);
    regw (DP_FRGD_CLR, get_colour_code (LIGHTRED));
    draw_rectangle (srcx + (3 * (width / 160)), srcy + (3 * (height / 120)),
                    srcwidth - (6 * (width / 160)),
                    srcheight - (6 * (height / 120)));

    // Wait for a carriage return (show screen before operation).
    getch ();

    // Perform a general pattern blit:
    //    The source data is at (srcx, srcy) and has a size of
    //    (srcwidth, srcheight). The destination blit will be drawn at
    //    (dstx, dsty) with a size of (dstwidth, dstheight). The general
    //    pattern blit allows the source to wrap in the X & Y directions
    //    while continuing to draw to the destination.

    // Setup for colour blit:
    //    The monochrome path controls which source channel is used to read
    //    the source data. If the monochrome path is "1", the foreground
    //    channel is selected as the source; if the monochrome path is "0",
    //    the background channel is selected. In this case, the monochrome
    //    path will be set to "1".
    wait_for_fifo (11);
    regw (DP_SRC, MONO_SRC_ONE | FRGD_SRC_BLIT);

    // Use general pattern for source:
    //    This implies that the destination rectangle can be a different
    //    size than the source rectangle - in this example, the destination
    //    rectangle is larger.
    regw (SRC_CNTL, SRC_PATTERN_ENABLE);

    // Set source start coordinate and rectangle size.

    // Adjust source trajectory starting x value and width for 24 bpp mode.
    if (MODE_INFO.bpp == 24)
    {
        srcx = srcx * 3;
        srcwidth = srcwidth * 3;
    } // if

    regw (SRC_X, srcx);
    regw (SRC_Y, srcy);
    regw (SRC_HEIGHT1, srcheight);
    regw (SRC_WIDTH1, srcwidth);

    // Set draw direction bits and adjust for 24 bpp mode if required.
    if (MODE_INFO.bpp == 24)
    {
        // Get the dstx parameter 24bpp rotation before adjusting it.

        rotation = (unsigned long)(((dstx * 3) / 4) % 6);

        // Adjust horizontal parameters for 24 bpp.

        dstx = dstx * 3;
        dstwidth = dstwidth * 3;

        // Setup 24 bpp alignment.

        regw (DST_CNTL, DST_24_ROTATION_ENABLE | DST_Y_TOP_TO_BOTTOM |
                        DST_X_LEFT_TO_RIGHT | (rotation << 8));
    }
    else
    {
        regw (DST_CNTL, DST_Y_TOP_TO_BOTTOM | DST_X_LEFT_TO_RIGHT);
    } // if

    // Set destination start coordinate and rectangle size.
    regw (DST_X, dstx);
    regw (DST_Y, dsty);
    regw (DST_HEIGHT, dstheight);
    regw (DST_WIDTH, dstwidth);         // This write initiates the operation.

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

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

    exit (0);                           // No errors.

} // main
