/****************************************************************************
 * RAGE128 Chapter 6 Sample Code                                            *
 *                                                                          *
 * tabfog.c - This program demonstrates how to set table fog states using   *
 * CCE command packets.                                                     *
 *                                                                          *
 * Copyright (c) 1999 ATI Technologies Inc.  All rights reserved.           *
 ****************************************************************************/


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

char gErrMsg [64] = {0};

extern DWORD BPPOverride; // Override default 8bpp mode in Chap 3 lib.

void SetupFogTable (char* fogtable);


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

void main (int argc, char *argv[])
{
	int i, exitcode = 0;
    TLVERTEX2 rect[4];
	PRIMDATA rectstrip;
    char* fogtable = NULL;


    printf ("Rage 128 Sample Code, Chapter 6.\n"
        "TABFOG.EXE\n\n"
        "This program demonstrates how to set table fog states using Rage 128\n"
        "CCE command packets.\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, 32bpp.\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);
		}
	}

    // Override default 8bpp mode in Chap 3 lib.

    BPPOverride = 32;

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

    R128_StartUp (argc, argv);

    // Clear the screen.

    R128_ClearScreen (DARKGREEN);

    // Initialize the CCE microengine.

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

	// Set the default 3D context.

    R128_Init3DContext ();

	// Set rect parameters.

	rect[0].x = R128_AdapterInfo.xres * 0.3f;
	rect[0].y = R128_AdapterInfo.yres * 0.2f;
    rect[0].z = 0.1f;
	rect[0].rhw = 1.0f;
	rect[0].diffuse = 0x00ff0000;
    rect[0].specular = 0x00000000;
	rect[0].s2 = rect[0].s1 = 0.0f;
	rect[0].t2 = rect[0].t1 = 1.0f;

	rect[1].x = R128_AdapterInfo.xres * 0.7f;
	rect[1].y = R128_AdapterInfo.yres * 0.4f;
    rect[1].z = 0.9f;
	rect[1].rhw = 1.0f;
	rect[1].diffuse = 0x00ff0000;
    rect[1].specular = 0x00000000;
	rect[1].s2 = rect[1].s1 = 1.0f;
	rect[1].t2 = rect[1].t1 = 1.0f;

	rect[2].x = R128_AdapterInfo.xres * 0.3f;
	rect[2].y = R128_AdapterInfo.yres * 0.8f;
    rect[2].z = 0.1f;
	rect[2].rhw = 1.0f;
	rect[2].diffuse = 0x00ff0000;
    rect[2].specular = 0x00000000;
	rect[2].s2 = rect[2].s1 = 0.0f;
	rect[2].t2 = rect[2].t1 = 0.0f;

	rect[3].x = R128_AdapterInfo.xres * 0.7f;
	rect[3].y = R128_AdapterInfo.yres * 0.6f;
    rect[3].z = 0.9f;
	rect[3].rhw = 1.0f;
	rect[3].diffuse = 0x00ff0000;
    rect[3].specular = 0x00000000;
	rect[3].s2 = rect[3].s1 = 1.0f;
	rect[3].t2 = rect[3].t1 = 0.0f;

	rectstrip.numverts = 4;
	rectstrip.verts = rect;

    // Allocate a buffer for the fog table.

    fogtable = malloc (256 * sizeof(char));

    if (fogtable == NULL)
    {
        sprintf (gErrMsg, "fogtable malloc failed!!");
		exitcode = 1;
		goto exit_app;
	}

    // Set the table fog entries.

    SetupFogTable (fogtable);

    ATTEMPT (R128_SetFogState (FOGSTATE_ENABLE, TRUE), 
		"fog enable failed!!")

    // Enable fog.

    ATTEMPT (R128_SetFogState (FOGSTATE_MODE, FOGMODE_TABLE), 
		"set fog mode failed!!")

    // Set the fog color.

    ATTEMPT (R128_SetFogState (FOGSTATE_COLOR, 0x00008f00), 
		"set fog color failed!!")

    // Set the fog table.

    ATTEMPT (R128_SetFogState (FOGSTATE_TABLE, (DWORD)fogtable), 
        "set fog table failed!!")

    // Set the fog start z value.

    ATTEMPT (R128_SetFogState (FOGSTATE_START, 0x00000000), 
        "set fog start failed!!")

    // Set the fog end z value.

    ATTEMPT (R128_SetFogState (FOGSTATE_END, 0xffffffff), 
        "set fog end failed!!")

    // Draw the quadrangle.

	ATTEMPT (R128_DrawTriangleStrip (&rectstrip), 
		"R128_DrawTriangleStrip for rect failed!!")

	// Wait for key press to exit.

	getch ();

exit_app:

	// Close 3D context, shut down micro-engine and restore original mode.

	R128_Close3DContext ();
    R128_CCEEnd (CCE_END_WAIT);
    R128_ShutDown ();

	// Free the fog table.

	if (fogtable)
		free (fogtable);

	// print error message if any.

	if (exitcode == 1)
		printf ("%s\n", gErrMsg);

	exit (exitcode);
} // main


/****************************************************************************
 * SetupFogTable                                                            *
 *  Function: Draw a single gouraud shaded triangle.                        *
 *    Inputs: fogtable - 256 entry table of fog values.                     *
 *   Outputs: none                                                          *
 ****************************************************************************/

void SetupFogTable (char* fogtable)
{
    int i;

    // Set a simple linear fog table.

    for (i=0; i < 256; i++)
    {
        fogtable[i] = 255 - i;
    }
}
