/****************************************************************************
 * RAGE128 Chapter 6 Sample Code                                            *
 *                                                                          *
 * zbuf.c - This program demonstrates how to set z buffering 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\zbuffer.h"
#include "..\util\util3d.h"

char gErrMsg [64] = {0};

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


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

void main (int argc, char *argv[])
{
	int i, exitcode = 0;
    TLVERTEX2 rect[4];
	TLVERTEX2 tri[3];
	PRIMDATA rectstrip, tristrip;
	ECMP ecmp;
	DWORD ZClear;

    printf ("Rage 128 Sample Code, Chapter 6.\n"
        "ZBUF.EXE\n\n"
        "This program demonstrates how to set z buffer 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. During program execution,\n"
        "press any key to cycle through z buffer compare modes.\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 (DARKBLUE);

    // 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 ();

	// Create the z buffer.

    ATTEMPT (R128_CreateZStencilBuffer (ZSTENFORMAT_Z32),
		"create z buffer failed!!")

	// Set Z buffer mode to test and write mode.

	ATTEMPT (R128_SetZBufferState (ZBUFFERSTATE_MODE, (DWORD) ZMODE_TESTWRITE),
		"set z buffer mode failed!!")

	// Set z clear value.

	ZClear = 0x80000000; // 0.5f

	// Set rect parameters.

	rect[0].x = R128_AdapterInfo.xres * 0.1f;
	rect[0].y = R128_AdapterInfo.yres * 0.2f;
	rect[0].z = 0.5f;
	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.2f;
	rect[1].z = 0.5f;
	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.1f;
	rect[2].y = R128_AdapterInfo.yres * 0.8f;
	rect[2].z = 0.5f;
	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.8f;
	rect[3].z = 0.5f;
	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;

	// Set triangle parameters

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

	tri[1].x = R128_AdapterInfo.xres * 0.8f;
	tri[1].y = R128_AdapterInfo.yres * 0.5f;
	tri[1].z = 0.9f;
	tri[1].rhw = 1.0f;
	tri[1].diffuse = 0x0000ff00;
	tri[1].specular = 0x00000000;
	tri[1].s2 = tri[1].s1 = 1.0f;
	tri[1].t2 = tri[1].t1 = 0.5f;

	tri[2].x = R128_AdapterInfo.xres * 0.4f;
	tri[2].y = R128_AdapterInfo.yres * 0.7f;
	tri[2].z = 0.1f;
	tri[2].rhw = 1.0f;
	tri[2].diffuse = 0x0000ff00;
	tri[2].specular = 0x00000000;
	tri[2].s2 = tri[2].s1 = 0.0f;
	tri[2].t2 = tri[2].t1 = 0.0f;

	tristrip.numverts = 3;
	tristrip.verts = tri;

	// Loop through all the z compare functions

	for (ecmp = CMP_NEVER; ecmp <= CMP_ALWAYS; ecmp++)
	{
		// Set the z compare function.

		ATTEMPT (R128_SetZBufferState (ZBUFFERSTATE_CMP, (DWORD)ecmp),
			"set z buffer cmp fnc failed!!")

		// Clear the zbuffer

        ATTEMPT (R128_ClearZBuffer (ZClear),
			"R128_ClearZBuffer failed!!")

		// Clear the screen.

        R128_CCEClearScreen (0x000000ff);

		// Draw the rectangle.  

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

		// Draw the triangle.

		ATTEMPT (R128_DrawTriangleStrip (&tristrip),
			"R128_DrawTriangleStrip for tri failed!!")

		// Wait for key press to exit.

		getch ();
	} // for

exit_app:

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

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

	// print error message if any.

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

	exit (exitcode);
} // main
