/****************************************************************************
 * RAGE128 Chapter 6 Sample Code                                            *
 *                                                                          *
 * smalltxt.c - This program demonstrates how to use Rage 128 command       *
 * packets to draw small text.                                              * 
 *                                                                          *
 * 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"

// The creation of the packed bitmaps for the characters is done as follows:
// Using the letter 'a' below as an example, first the bitmap for the letter
// is drawn in a character grid.  For 'a', we use a 7x6 grid:
//
//                 * * * * *                           1 1 1 1 1 0 0
//                         * *                         0 0 0 0 1 1 0
//      'a'   =      * * * * *     when written out    0 1 1 1 1 1 0
//                 * *     * *     in binary form ->   1 1 0 0 1 1 0
//                 * *     * *                         1 1 0 0 1 1 0
//                   * * * * * *                       0 1 1 1 1 1 1
//
// Scanning the binary representation from left to right, top to bottom will
// produce the 42 bit sequence: 111110000001100111110110011011001100111111.
// Breaking up this sequence into byte-sized values produces:
// 11111000 00011001 11110110 01101100 11001111 11000000 where the six '0's at
// the end are padding to fill out the remaining byte.
// In hexadecimal, the above byte sequence is: F8 19 F6 6C CF C0.
// Finally, pack the above bytes into Intel-ordered DWORD groups adding zero
// bytes to pad out the last DWORD to get: 6CF619F8 0000C0CF

DWORD Raster_ATI[6] = { 0xFF01FF01, 0xEEC1FF41, 0xE311E701,
                        0xE6CFED9D, 0xA073E0E7, 0x00008010 };
DWORD Raster_R[3] = { 0xC6C3C6FC, 0xC3C3C6FC, 0x0000C3C3 };
DWORD Raster_a[2] = { 0x6CF619F8, 0x0000C0CF };
DWORD Raster_g[2] = { 0x79F33C7F, 0x0078B387 };
DWORD Raster_e[2] = { 0xC1FE3C7B, 0x000000E0 };
DWORD Raster_1[2] = { 0x300CC331, 0xF0330CC3 };
DWORD Raster_2[3] = { 0x30188F7D, 0xC16018C7, 0x000000FC };
DWORD Raster_8[3] = { 0x66C3663C, 0xC3C3663C, 0x00003C66 };

typedef struct tagSmallGlyph {
    BYTE dx, dy, w, h;
    int num_dwords;
    DWORD *raster;
} SmallGlyph;

SmallGlyph text[] = { {  0, 10, 17, 10, 6, Raster_ATI },
                      { 24, 10,  8, 10, 3, Raster_R },
                      { 10,  6,  7,  6, 2, Raster_a },
                      {  9,  6,  6,  9, 2, Raster_g },
                      {  8,  6,  6,  6, 2, Raster_e },
                      { 13, 10,  6, 10, 2, Raster_1 },
                      {  8, 10,  7, 10, 3, Raster_2 },
                      {  9, 10,  8, 10, 3, Raster_8 } };


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

void main (int argc, char *argv[])
{
    DWORD Buf[50];
    DWORD x, y;
    int test;
    int i, j, k;

    printf ("Rage 128 Sample Code, Chapter 6.\n"
        "SMALLTXT.EXE\n\n"
        "This program will demonstrate using Type-3 packets with the CCE\n"
        "microengine of the Rage 128.\n\n"
        "Mode resolution (eg 640 480) and colour depth (8, 15, 16, 24, 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 ();

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

    R128_StartUp (argc, argv);

    // Clear the screen

    R128_ClearScreen (BLACK);

    // Initialize the CCE microengine.

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

    while (!kbhit ())
    {
        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_SMALLTEXT;

        // Compose GUI_CONTROL

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

        Buf[i++] = R128_GetColourCode (rand () % NUM_COLOURS);

        x = (rand () % (R128_AdapterInfo.xres - 90));
        y = (rand () % (R128_AdapterInfo.yres - 10)) + 10;

        // Fill rectangle data into packet

        Buf[i++] = x + (y << 16);

        for (j = 0; j < (sizeof (text) / sizeof (SmallGlyph)); j += 1)
        {
            Buf[i++] = text[j].dx + (text[j].dy << 8) +
                       (text[j].w << 16) + (text[j].h << 24);
            for (k = 0; k < text[j].num_dwords; k += 1)
            {
                Buf[i++] = text[j].raster[k];
            } // for
        } // for

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

        // Slow things down a little so that the text can be read.

        R128_Delay (1);
    } // while

    getch ();

    // Shut down the microengine.

    R128_CCEEnd (CCE_END_WAIT);
    R128_ShutDown ();

    return;
} // main
