/******************************************************************************
 * mach64 Chapter 4 sample code                                               *
 *                                                                            *
 * This program performs mach64 detection, aperture setting, and mode         *
 * setting.  It then draws a series of points, filled rectangles, lines,      *
 * open rectangles, and filled polygons.  Each stage is transgressed by       *
 * pressing a key on the keyboard.                                            *
 *                                                                            *
 * Copyright (c) 1994-1998 ATI Technologies Inc.  All rights reserved.        *
 ******************************************************************************/

#include <stdio.h>
#include <i86.h>
#include "defines.h"
#include "main.h"

// Prototypes.

int testa (int choice);
int testb (int points);

/******************************************************************************
 * Main Program                                                               *
 *  Function: Demonstrates mach64 Linear Aperture                             *
 *    Inputs: NONE                                                            *
 *   Outputs: NONE                                                            *
 ******************************************************************************/

void main (int argc, char *argv[])
{
    long scrn_ptr;                      // Virtual base address to screen.

    printf ("mach64 Chapter 4 sample code\n"
            "\n"
            "linear.c\n"
            "This program performs mach64 detection, aperture setting, and mode\n"
            "setting.  It then draws a series of points, filled rectangles, lines,\n"
            "open rectangles, and filled polygons.  Each stage is transgressed by\n"
            "pressing a key on the keyboard.\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");

    // Detect mach64.
    if (!init_graphics ())
    {
        printf ("ERROR: Graphics not initialized properly!\n");
        exit (1);
    } // if

    // Fill QUERY_DATA using BIOS calls 08h and 09h.
    if (!long_query ())
    {
        printf ("ERROR: long query failed!\n");
        exit (1);
    } // if

    // Save old video mode.
    get_old_mode ();

    // Short query to get linear address and aperture size.
    if (!short_query_function ())
    {
        printf ("ERROR: short query function failed!\n");
        exit (1);
    }

    // Get virtual address.
    scrn_ptr = phys_to_virt (MODE_INFO.linear_address,
                             MODE_INFO.linear_aperture_size);
    MODE_INFO.virt_seg = scrn_ptr;

    // Process the command line arguments to override default resolution
    // and colour depth settings.
    process_command_line (argc, argv);
    printf ("Spatial X-Resolution: %d\n", GMODE_RES);
    printf ("         Pixel Depth: %d\n\n", GCLR_DEPTH);
    printf (" Press Any Key To Begin\n");
    getch ();

    // Load and set mode.  '2' indicates pitch is same as xres.
    if (!load_and_set_mode (GMODE_RES, GCLR_DEPTH, 2))
    {
        printf ("ERROR: mode setting failed!\n");
        exit (1);
    } // if

    // Enable aperture.
    if (!enable_aperture ())
    {
        printf ("ERROR: enable aperture failed!\n");
        exit (1);
    } // if

    // Sample drawing routines.
    if (!clear_screen ())
    {
        printf ("Could not clear screen\n");
        exit (1);
    } // if
    testa (1);                          // points
    getch ();
    testa (2);                          // filled rectangles
    getch ();
    testa (3);                          // lines
    getch ();
    testa (4);                          // open rectangles
    getch ();
    testb (6);                          // polygons 3 - 6 sides
    getch ();

    // Restore mode.
    set_old_mode ();

    exit (0);                           // No errors.
    
} // main


/******************************************************************************
 * testa                                                                      *
 *  Function: Draws random sized items to the screen until key, using the     *
 *            linear aperture.  Min size is 1 pixel, max size is screen       *
 *            dimensions.                                                     *
 *    Inputs: choice of 4 objects (point, filled rect, line, open rect)       *
 *   Outputs: 0 - if unsuccessful                                             *
 *            1 - if successful                                               *
 ******************************************************************************/

int testa (int choice)
{
    float frnd1, frnd2, frnd3, frnd4, frnd5;
    int n1, n2, n3, n4, n5;
    int count;

    srand ((unsigned) clock ());
    while (!kbhit ())
    {
        // Set up random numbers.
        frnd1 = rand () / 32768.0;
        frnd2 = rand () / 32768.0;
        frnd3 = rand () / 32768.0;
        frnd4 = rand () / 32768.0;
        frnd5 = rand () / 32768.0;
        n1 = (int) (NUM_COLOURS * frnd1);
        n2 = (int) (MODE_INFO.xres * frnd2);
        n3 = (int) (MODE_INFO.yres * frnd3);
        n4 = (int) (MODE_INFO.xres * frnd4);
        n5 = (int) (MODE_INFO.yres * frnd5);
        switch (choice)
        {
            case 1:
                draw_point (n2, n3, n1);
                break;

            case 2:
                draw_frect (n2, n3, n4, n5, n1);
                break;

            case 3:
                draw_line (n2, n3, n4, n5, n1);
                break;

            case 4:
                draw_rect (n2, n3, n4, n5, n1);
                break;

            default:
                return (0);
        } // switch
    } // while

    return (1);

} // testa


/******************************************************************************
 * testb                                                                      *
 *  Function: testb draws polygons with max 'points' sides until key,         *
 *            through the linear aperture.  Min # sides is 3.                 *
 *    Inputs: points - number of points (or sides) of the polygons            *
 *   Outputs: 0 - if unsuccessful                                             *
 *            1 - if successful                                               *
 ******************************************************************************/

int testb (int points)
{
    point pts[20];
    polygon poly;
    int count1, count2;
    float f1, f2, f3, f4;
    int n1, n2, n3, n4;

    srand ((unsigned) clock ());
    while (!kbhit ())
    {
        // Set up random numbers for # points, and colour.
        f1 = rand () / 32768.0;
        f4 = rand () / 32768.0;
        n1 = (int) (NUM_COLOURS * f1);
        n4 = (int) 3+((points-2) * f4);

        // Setup random points in polygon structure.
        for (count2 = 0; count2 < n4; count2++)
        {
            f2 = rand () / 32768.0;
            f3 = rand () / 32768.0;
            n2 = (int) (MODE_INFO.xres * f2);
            n3 = (int) (MODE_INFO.yres * f3);
            pts[count2].x = n2;
            pts[count2].y = n3;
        } // for
        poly.length = n4;
        poly.point_ptr = pts;

        // Draw polygon.
        if (!draw_polygon (&poly, 0, 0, n1))
        {
            return (0);
        } // if
    } // while

    return (1);

} // testb
