/****************************************************************************
 * RAGE128 Chapter 6 Sample Code                                            *
 *                                                                          *
 * transcal.c - This program demonstrates how to use Rage 128 Type-3        *
 * command packets to do a transparent scale blit of a rectangle from a     *
 * source area to a destination area.                                       *
 *                                                                          *
 * Copyright (c) 1999 ATI Technologies Inc.  All rights reserved.           *
 ****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <i86.h>
#include <conio.h>
#include "..\util\regdef.h"
#include "..\util\defines.h"
#include "..\util\main.h"
#include "..\util\cce.h"

extern DWORD BPPOverride;


/****************************************************************************
 * main                                                                     *
 *  Function: Main loop.                                                    *
 *    Inputs: none                                                          *
 *   Outputs: none                                                          *
 ****************************************************************************/

void main (int argc, char *argv[])
{
    WORD srcx, srcy, dstx, dsty, dstw, dsth, bpp;
    DWORD Buf[20];
    DWORD scalex, scaley, srcoffset;
    int test;
    int i;
    _img_info IMG_DATA;
    DWORD savescale3dcntl;

    printf ("Rage 128 Sample Code, Chapter 6.\n"
        "TRANSCAL.EXE\n\n"
        "This program demonstrates how to use Rage 128 Type-3 command packets\n"
        "to do a transparent scale blit. A source rectangle is blitted to\n"
        "the top left corner of the screen using a regular blit. Then, it is\n"
        "blitted just below the first rectangle using a transparent scale\n"
        "blit. A thin transparent vertical line should appear where the source\n"
        "colour matches the source reference colour of magenta.\n\n"
        "Mode resolution (eg 640 480) and colour depth (15, 16, 32)\n"
        "should be passed as command line arguments.\n"
        "Default resolution and colour depth is 640x480, 8bpp.\n\n"
        "Press any key to continue.\n\n");

    getch ();

    // Inspect arguments for invalid color depth.

    for (i = 1; i < argc; i++)
    {
        if ((strcmp (argv[i], "8") == 0) || (strcmp (argv[i], "24") == 0))
		{
			printf ("\nThis program does not operate at 8 or 24 bpp.");
			printf ("\nProgram terminated.");
			exit (1);
		}
	}

    // Set 32 BPP colour depth.

    BPPOverride = 32;

    // First, run StartUp function to set up the application

    R128_StartUp (argc, argv);

    if (R128_AdapterInfo.xres <= 320)
    {
        R128_ShutDown ();
        printf ("\nThis program requires a resolution of at least 400x300.");
        printf ("\nProgram terminated.");
        exit (1);
    }

    // Clear the screen

    R128_ClearScreen (BLACK);

    // Set up the source data co-ordinates.
    srcx = 0;
    srcy = R128_AdapterInfo.yres;
    srcoffset = (srcx + srcy*R128_AdapterInfo.pitch*8) * R128_AdapterInfo.bytepp;
    bpp = R128_GetBPPValue (R128_AdapterInfo.bpp);

    // Load the source image file into offscreen memory.

    IMG_DATA = Load_Image (TRAJECTORY_RECTANGULAR, bpp, srcx, srcy);

    // Initialize the CCE microengine.

    if (R128_CCEInit (CCE_MODE_192BM) != CCE_SUCCESS)
    {
        R128_ShutDown ();
        printf ("R128_CCEInit failed!!\n");
        exit (1);
    } // if

    // Force bitmap alpha channel to 0 for scale blit.
    R128_WaitForFifo (1);
    savescale3dcntl = regr (SCALE_3D_CNTL);

    i = 0;
    Buf[i++] = CCE_PACKET0 | (SCALE_3D_CNTL >> 2);
    Buf[i++] = savescale3dcntl | (1L << 30);
    test = R128_CCESubmitPackets (Buf, i);

    // First, blit the source rectangle to the top left corner of the
    // screen for comparison.

    i = 0;

    // Set up a rectangle packet and fill the header with packet size
    // Note that packet size is two less than total number of packets sent

    Buf[i++] = CCE_PACKET3_CNTL_BITBLT;

    // N.B. With the current microcode CCE_PACKET3_CNTL_BITBLT_MULTI
    // does exactly the same operation as CCE_PACKET3_CNTL_BITBLT,
    // i.e., the packet parameters are source-x, source-y (1st packet),
    // dest-x, dest-y (2nd packet), and width, height (3rd packet).

    // Compose GUI_CONTROL

    Buf[i++] = CCE_GC_BRUSH_NONE | CCE_GC_SRC_DSTCOLOR | ROP3_SRCCOPY |
               CCE_GC_DP_SRC_RECT | (R128_GetBPPValue (R128_AdapterInfo.bpp) << 8);

    dstx = 0;
    dsty = 0;

    // Fill rectangle data into packet

    Buf[i++] = (srcx << 16) + srcy;
    Buf[i++] = (dstx << 16) + dsty;
    Buf[i++] = (IMG_DATA.width << 16) + IMG_DATA.height;

    Buf[0] |= ((i - 2) << 16);
    test = R128_CCESubmitPackets (Buf, i);

    // Next, source rectangle just below the first rectangle using
    // a transparent scale blit. 

    i = 0;

    // Set up a rectangle packet and fill the header with packet size
    // Note that packet size is two less than total number of packets sent

    Buf[i++] = CCE_PACKET3_CNTL_TRANS_SCALING;

    // Compose GUI_CONTROL

    Buf[i++] = CCE_GC_BRUSH_NONE | CCE_GC_SRC_DSTCOLOR | ROP3_SRCCOPY |
               CCE_GC_DP_SRC_RECT | (bpp << 8);

    dstx = 0;
    dsty = IMG_DATA.height;
    dstw = IMG_DATA.width << 1;
    dsth = IMG_DATA.height;
    scalex = (IMG_DATA.width << 16)/dstw;
    scaley = (IMG_DATA.height << 16)/dsth;

    // Reject scaling factors that are out-of-range.

    if ((scalex < 16) || (scalex >= (1 << 20)) ||
        (scaley < 16) || (scaley >= (1 << 20)))
    {
        goto app_exit;
    } // if

    // Fill rectangle data into packet

    Buf[i++] = 0x01000005;
    Buf[i++] = R128_GetColourCode (LIGHTMAGENTA);
    Buf[i++] = 0x00000000;

    Buf[i++] = 0x00000100;
    Buf[i++] = 0;
    Buf[i++] = 0;
    Buf[i++] = bpp;
    Buf[i++] = srcoffset;
    Buf[i++] = R128_AdapterInfo.pitch;
    Buf[i++] = 0;
    Buf[i++] = scalex;
    Buf[i++] = scaley;
    Buf[i++] = (dstx << 16) + dsty;
    Buf[i++] = (dsth << 16) + dstw;

    Buf[0] |= ((i - 2) << 16);
    test = R128_CCESubmitPackets (Buf, i);

    // Restore SCALE_3D_CNTL

    i = 0;
    Buf[i++] = CCE_PACKET0 | (SCALE_3D_CNTL >> 2);
    Buf[i++] = savescale3dcntl;
    test = R128_CCESubmitPackets (Buf, i);

    getch ();

app_exit:

    // Shut down the microengine.

    R128_CCEEnd (CCE_END_WAIT);
    R128_ShutDown ();

    return;
} // main
