/****************************************************************************
 * RAGE128 Chapter 6 Sample Code                                            *
 *                                                                          *
 * cntx3d.c - Functions to manage the 3D context.                           * 
 *                                                                          *
 * Copyright (c) 1999 ATI Technologies Inc.  All rights reserved.           *
 ****************************************************************************/

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

CONTEXT3D gContext3D = {0};
static CONTEXT3D gsaveContextRegs = {0};
static BOOL gbContextRegistersSaved = FALSE;
DWORD gCommandBuf[CMD_BUF_SIZE] = {0};

static void SaveContextRegisters (void);
static void RestoreContextRegisters (void);

extern void InitBufferList (void); // in memmgr.c
extern void FreeBufferList (void); // in memmgr.c


/****************************************************************************
 * R128_Init3DContext										                *
 *  Function: Initialize the 3D context to a known state and keep a record  * 
 *            in the global gContext3D CONTEXT3D strcture.                  *                                   *
 *    Inputs: none                                                          *
 *   Outputs: none                                                          *
 ****************************************************************************/

void R128_Init3DContext (void)
{
	DWORD i = 0;
	DWORD temp;

	// Save the original state of the context the first time this function
	// is called.

	if (gbContextRegistersSaved == FALSE)
	{
		SaveContextRegisters ();
		gbContextRegistersSaved = TRUE;
	}

	// Get the current bitdepth value.

    temp = R128_GetBPPValue (R128_AdapterInfo.bpp);

	// Set SCALE_3D_CNTL first.

	i = 0;
    gCommandBuf[i++] = CCE_PACKET0 | (SCALE_3D_CNTL >> 2);
	gCommandBuf[i++] = gContext3D.regSCALE_3D_CNTL =
		SCALE_3D_CNTL_SCALE_DITHER_ERR_DIFF	 |
		SCALE_3D_CNTL_TEX_CACHE_SIZE_FULL |
		SCALE_3D_CNTL_DITHER_INIT_RESET |
		SCALE_3D_CNTL_ROUND_EN_OFF |
        SCALE_3D_CNTL_TEX_CACHE_DIS_OFF |
		SCALE_3D_CNTL_SCALE_3D_FN_TMAP_SHADE |
		SCALE_3D_CNTL_SCALE_PIX_REP_BLEND |
		SCALE_3D_CNTL_TEX_CACHE_SPLIT_OFF |
		SCALE_3D_CNTL_APPLE_YUV_MODE_OFF |
		SCALE_3D_CNTL_TEX_CACHE_PAL_MODE_OFF |
		SCALE_3D_CNTL_ALPHA_COMB_FNC_ADD_CLAMP |
		SCALE_3D_CNTL_FOG_TABLE_EN_ON |
		SCALE_3D_CNTL_SIGNED_DST_CLAMP_OFF |
		SCALE_3D_CNTL_ALPHA_BLEND_SRC_ONE |
		SCALE_3D_CNTL_ALPHA_BLEND_DST_ZERO |
		SCALE_3D_CNTL_ALPHA_TEST_OP_ALWAYS |
		SCALE_3D_CNTL_COMPOSITE_SHADOW_CMP_EQUAL |
		SCALE_3D_CNTL_COMPOSITE_SHADOW_EN_OFF |
		SCALE_3D_CNTL_TEX_MAP_AEN_ON |
		SCALE_3D_CNTL_TEX_CACHE_LINE_SIZE_8QW;

	// Submit the packet.
	
    gCommandBuf[0] |= ((i - 2) << 16);
    R128_CCESubmitPackets (gCommandBuf, i);

	// Send the following in a Type-0 packet:

	i = 0;
    gCommandBuf[i++] = CCE_PACKET0 | (DST_PITCH_OFFSET_C >> 2);

	// Set DST_PITCH_OFFSET_C to same value as default.

	gCommandBuf[i++] = gContext3D.regDST_PITCH_OFFSET_C = 
        R128_AdapterInfo.pitch << 21;

	// Set DP_GUI_MASTER_CNTL:

	gCommandBuf[i++] = gContext3D.regDP_GUI_MASTER_CNTL =
		GMC_SRC_PITCH_OFFSET_DEFAULT |
        GMC_DST_PITCH_OFFSET_LEAVE |
        GMC_SRC_CLIP_DEFAULT |
        GMC_DST_CLIP_DEFAULT |
        GMC_BRUSH_SOLIDCOLOR |
        (temp << 8) |
        GMC_SRC_DSTCOLOR |
        GMC_BYTE_ORDER_MSB_TO_LSB |
        GMC_DP_CONVERSION_TEMP_6500 |
        ROP3_SRCCOPY |
        GMC_DP_SRC_RECT |
        GMC_3D_FCN_EN_SET |
        GMC_DST_CLR_CMP_FCN_CLEAR |
        GMC_AUX_CLIP_CLEAR |
        GMC_WRITE_MASK_SET;

	// Set scissor top, left, bottom, right parameters.

	gCommandBuf[i++] = gContext3D.regSC_TOP_LEFT_C = 0x00000000;

	gCommandBuf[i++] = gContext3D.regSC_BOTTOM_RIGHT_C = (0x1FFF << 16) | 
		0x1FFF;

	// Set z buffer default pitch and memory offset.

	gCommandBuf[i++] = gContext3D.regZ_OFFSET_C = 0x00000000;

	gCommandBuf[i++] = gContext3D.regZ_PITCH_C = 
		(DWORD)R128_AdapterInfo.pitch;

	// Set z and stencil buffer default states.

	gCommandBuf[i++] = gContext3D.regZ_STEN_CNTL_C =                                             
		Z_STEN_CNTL_Z_PIX_WIDTH_16 |
		Z_STEN_CNTL_Z_TEST_LESSEQUAL |
		Z_STEN_CNTL_STENCIL_TEST_ALWAYS |
		Z_STEN_CNTL_STENCIL_S_FAIL_OP_KEEP |
		Z_STEN_CNTL_STENCIL_ZPASS_OP_KEEP |
		Z_STEN_CNTL_STENCIL_ZFAIL_OP_KEEP;

	// Set texture states and various enable/disable fields.

	gCommandBuf[i++] = gContext3D.regTEX_CNTL_C =                                   
		TEX_CNTL_Z_EN_OFF |
		TEX_CNTL_Z_MASK_EN |
		TEX_CNTL_STENCIL_EN_OFF |
        TEX_CNTL_TEX_EN_SHADE |
		TEX_CNTL_SECONDARY_TEX_EN_OFF |
		TEX_CNTL_FOG_EN_OFF |
		TEX_CNTL_DITHRE_EN_OFF |
		TEX_CNTL_ALPHA_EN_OFF |
		TEX_CNTL_ALPHA_TEST_EN_OFF |
		TEX_CNTL_SPEC_LIGHT_EN_OFF |
		TEX_CNTL_TEX_CHROMA_KEY_EN_OFF |
		TEX_CNTL_AMASK_EN_OFF |			
		TEX_CNTL_LIGHT_FN_DIS |
		TEX_CNTL_ALPHA_LIGHT_FN_DIS |
        TEX_CNTL_TEX_CACHE_FLUSH_OFF |
		(0xfL << 24);

	// Set miscellaneous 3D states.

	gCommandBuf[i++] = gContext3D.regMISC_3D_STATE_CNTL_REG =                                   
		MISC_3D_STATE_SCALE_3D_FN_TMAP_SHADE |
		MISC_3D_STATE_SCALE_PIX_REP_REPLICATE |
		MISC_3D_STATE_ALPHA_COMB_FNC_ADD_CLAMP |
		MISC_3D_STATE_FOG_TABLE_EN_TABLE_FOG |
		MISC_3D_STATE_ALPHA_BLEND_SRC_ONE |
		MISC_3D_STATE_ALPHA_BLEND_DST_ZERO |
		MISC_3D_STATE_ALPHA_TEST_OP_ALWAYS;

	// Set the texture compare color.

	gCommandBuf[i++] = gContext3D.regTEXTURE_CLR_CMP_CLR_C = 0x00000000;                       

	// Set the texture compare mask.

	gCommandBuf[i++] = gContext3D.regTEXTURE_CLR_CMP_MSK_C = 0xffffffff;

	// Set the default fog color.
	
	gCommandBuf[i++] = gContext3D.regFOG_COLOR_C = 0x00808080;             

	// Set the default states for the primary texture.
	
	gCommandBuf[i++] = gContext3D.regPRIM_TEX_CNTL_C =                                           
		PRIM_TEX_CNTL_PRIM_MIN_BLEND_FN_NEAREST |
		PRIM_TEX_CNTL_PRIM_MAG_BLEND_FN_NEAREST |
		PRIM_TEX_CNTL_MIP_MAP_DIS_ON |
		PRIM_TEX_CNTL_PRIM_TEX_CLAMP_MODE_S_WRAP |
		PRIM_TEX_CNTL_PRIM_TEX_WRAP_S_OFF |
		PRIM_TEX_CNTL_PRIM_TEX_CLAMP_MODE_T_WRAP |
		PRIM_TEX_CNTL_PRIM_TEX_WRAP_T_OFF |
		PRIM_TEX_CNTL_PRIM_TEX_PERSPECTIVE_DIS_OFF;

	// Set the default combine states for the primary texture.
	
	gCommandBuf[i++] = gContext3D.regPRIM_TEXTURE_COMBINE_CNTL_C =
        TEX_COMBINE_CNTL_COMB_FNC_MODULATE |
		TEX_COMBINE_CNTL_COLOR_FACTOR_TEX |
		TEX_COMBINE_CNTL_INPUT_FACTOR_INT_COLOR |
		TEX_COMBINE_CNTL_COMB_FNC_ALPHA_COPY |
		TEX_COMBINE_CNTL_ALPHA_FACTOR_TEX_ALPHA |
		TEX_COMBINE_CNTL_INP_FACTOR_ALPHA_INT_ALPHA;

	// Set the default texture size parameters.

	gCommandBuf[i++] = gContext3D.regTEX_SIZE_PITCH_C = 0x00000000;

	// Set the primary texture and mipmap offsets.
	
	gCommandBuf[i++] = gContext3D.regPRIM_TEX_0_OFFSET_C = 0x00000000;
	gCommandBuf[i++] = gContext3D.regPRIM_TEX_1_OFFSET_C = 0x00000000;
	gCommandBuf[i++] = gContext3D.regPRIM_TEX_2_OFFSET_C = 0x00000000;
	gCommandBuf[i++] = gContext3D.regPRIM_TEX_3_OFFSET_C = 0x00000000;
	gCommandBuf[i++] = gContext3D.regPRIM_TEX_4_OFFSET_C = 0x00000000;
	gCommandBuf[i++] = gContext3D.regPRIM_TEX_5_OFFSET_C = 0x00000000;
	gCommandBuf[i++] = gContext3D.regPRIM_TEX_6_OFFSET_C = 0x00000000;
	gCommandBuf[i++] = gContext3D.regPRIM_TEX_7_OFFSET_C = 0x00000000;
	gCommandBuf[i++] = gContext3D.regPRIM_TEX_8_OFFSET_C = 0x00000000;
	gCommandBuf[i++] = gContext3D.regPRIM_TEX_9_OFFSET_C = 0x00000000;
	gCommandBuf[i++] = gContext3D.regPRIM_TEX_10_OFFSET_C = 0x00000000;
	
	// Set the default secondary texture states.

	gCommandBuf[i++] = gContext3D.regSEC_TEX_CNTL_C =                                   
		SEC_TEX_CNTL_SEC_SRC_SEL_ST_0;

	// Set the default secondary texture combine states.

	gCommandBuf[i++] = gContext3D.regSEC_TEX_COMBINE_CNTL_C =                                  
        TEX_COMBINE_CNTL_COMB_FNC_DIS |
        TEX_COMBINE_CNTL_COLOR_FACTOR_TEX |
        TEX_COMBINE_CNTL_INPUT_FACTOR_PREV_COLOR |
        TEX_COMBINE_CNTL_COMB_FNC_ALPHA_DIS |
        TEX_COMBINE_CNTL_ALPHA_FACTOR_TEX_ALPHA |
        TEX_COMBINE_CNTL_INP_FACTOR_ALPHA_PREV_ALPHA;

	// Set the secondary texture and mipmap offsets.

	gCommandBuf[i++] = gContext3D.regSEC_TEX_0_OFFSET_C = 0x00000000;     
	gCommandBuf[i++] = gContext3D.regSEC_TEX_1_OFFSET_C = 0x00000000;
	gCommandBuf[i++] = gContext3D.regSEC_TEX_2_OFFSET_C = 0x00000000;
	gCommandBuf[i++] = gContext3D.regSEC_TEX_3_OFFSET_C = 0x00000000;
	gCommandBuf[i++] = gContext3D.regSEC_TEX_4_OFFSET_C = 0x00000000;
	gCommandBuf[i++] = gContext3D.regSEC_TEX_5_OFFSET_C = 0x00000000;
	gCommandBuf[i++] = gContext3D.regSEC_TEX_6_OFFSET_C = 0x00000000;
	gCommandBuf[i++] = gContext3D.regSEC_TEX_7_OFFSET_C = 0x00000000;
	gCommandBuf[i++] = gContext3D.regSEC_TEX_8_OFFSET_C = 0x00000000;
	gCommandBuf[i++] = gContext3D.regSEC_TEX_9_OFFSET_C = 0x00000000;
	gCommandBuf[i++] = gContext3D.regSEC_TEX_10_OFFSET_C = 0x00000000;

	// Set the default constant color.

	gCommandBuf[i++] = gContext3D.regCONSTANT_COLOR_C = 0x00ffffff;                    

	// Set the default primary texture border color.

	gCommandBuf[i++] = gContext3D.regPRIM_TEXTURE_BORDER_COLOR_C = 0x00ffffff;
	
	// Set the default secondary texture border color.

	gCommandBuf[i++] = gContext3D.regSEC_TEXTURE_BORDER_COLOR_C = 0x00ffffff;                     
	
	// Set the default stencil reference and masks.

	gCommandBuf[i++] = gContext3D.regSTEN_REF_MASK_C = 0xffff0000;

	// Set the plane 3D mask.
	
	gCommandBuf[i++] = gContext3D.regPLANE_3D_MASK_C = 0xffffffff;

	// Submit the packet.
	
    gCommandBuf[0] |= ((i - 2) << 16);
    R128_CCESubmitPackets (gCommandBuf, i);

	// Send rest in a Type-1 packet.

    gCommandBuf[0] = CCE_PACKET1 | ((PM4_VC_FPU_SETUP >> 2) << 11) |
        (SETUP_CNTL >> 2);

	// Set default primitive states.

	gCommandBuf[1] = gContext3D.regSETUP_CNTL = 
		SETUP_CNTL_DONT_START_TRI_OFF |
		SETUP_CNTL_DONT_START_ANY_OFF |
		SETUP_CNTL_COLOR_FNC_GOURAUD |
		SETUP_CNTL_PRIM_TYPE_SELECT_TRI |
		SETUP_CNTL_TEXTURE_ST_FORMAT_MULT_W |
		SETUP_CNTL_STARTING_VERTEX_SELECT_1 |
		SETUP_CNTL_ENDING_VERTEX_SELECT_3 |
		SETUP_CNTL_SU_POLY_LINE_NOT_LAST |
		SETUP_CNTL_SUB_PIX_AMOUNT_4BITS;

	gCommandBuf[2] = gContext3D.regPM4_VC_FPU_SETUP = 
		PM4_VC_FPU_SETUP_FRONT_DIR_CW |
		PM4_VC_FPU_SETUP_BACKFACE_CULLING_FN_CULL |
		PM4_VC_FPU_SETUP_FRONTFACE_CULLING_FN_REV_SOLID |
		PM4_VC_FPU_SETUP_PM4_COLOR_FCN_GOURAUD |
		PM4_VC_FPU_SETUP_PM4_SUB_PIX_AMOUNT_4BITS |
		PM4_VC_FPU_SETUP_FPU_MODE_3D |
		PM4_VC_FPU_SETUP_TRAP_DISABLE_ON |
		PM4_VC_FPU_SETUP_EDGE_ANTIALIAS_OFF |
		PM4_VC_FPU_SETUP_SUPERSAMPLE_OFF |
		PM4_VC_FPU_SETUP_XFACTOR_2 |
		PM4_VC_FPU_SETUP_YFACTOR_2 |
		PM4_VC_FPU_SETUP_FLAT_SHADE_VERTEX_D3D |
		PM4_VC_FPU_SETUP_FPU_ROUND_EN_OFF |
		PM4_VC_FPU_SETUP_VC_WM_SEL_8DW;

	// Submit the packet.

    R128_CCESubmitPackets (gCommandBuf, 3);

	// Set the default fog table start, end, and density parameters.

	i = 0;
	gCommandBuf[i++] = CCE_PACKET0 | (FOG_3D_TABLE_START >> 2);
	gCommandBuf[i++] = gContext3D.regFOG_3D_TABLE_START = 0x00000000;
	gCommandBuf[i++] = gContext3D.regFOG_3D_TABLE_END = 0xffffffff;
	gCommandBuf[i++] = gContext3D.regFOG_3D_TABLE_DENSITY = 0x00000000;

	// Submit the packet.
	
    gCommandBuf[0] |= ((i - 2) << 16);
    R128_CCESubmitPackets (gCommandBuf, i);

	// Convenient place to init the offscreen memory manager.

	InitBufferList ();
}


/****************************************************************************
 * R128_Close3DContext						                                *
 *  Function: 3D context clean-up: restore original context.                *
 *    Inputs: none                                                          *
 *   Outputs: none                                                          *
 ****************************************************************************/

void R128_Close3DContext (void)
{
    // Flush ring buffer.

    R128_Flush ();

	if (gbContextRegistersSaved)
	{
		RestoreContextRegisters ();
		gbContextRegistersSaved = FALSE;
	}

    // Free the offscreen memory manager buffer list.

    FreeBufferList ();
}


/****************************************************************************
 * SaveContextRegisters                                                     *
 *  Function: Save original state of 3D context.                            *
 *    Inputs: none                                                          *
 *   Outputs: none                                                          *
 ****************************************************************************/

static void SaveContextRegisters (void)
{
	// Read original state of registers and save in a global CONTEXT3D struct.

    R128_WaitForFifo (16);
	gsaveContextRegs.regSCALE_3D_CNTL = regr (SCALE_3D_CNTL);
	gsaveContextRegs.regDST_PITCH_OFFSET_C = regr (DST_PITCH_OFFSET_C);
	gsaveContextRegs.regDP_GUI_MASTER_CNTL = regr (DP_GUI_MASTER_CNTL);
	gsaveContextRegs.regSC_TOP_LEFT_C = regr (SC_TOP_LEFT_C);
	gsaveContextRegs.regSC_BOTTOM_RIGHT_C = regr (SC_BOTTOM_RIGHT_C); 
	gsaveContextRegs.regZ_OFFSET_C = regr (Z_OFFSET_C); 
	gsaveContextRegs.regZ_PITCH_C = regr (Z_PITCH_C); 
	gsaveContextRegs.regZ_STEN_CNTL_C = regr (Z_STEN_CNTL_C);                                             
	gsaveContextRegs.regTEX_CNTL_C = regr (TEX_CNTL_C);                                   
	gsaveContextRegs.regMISC_3D_STATE_CNTL_REG = 
		regr (MISC_3D_STATE_CNTL_REG);
	gsaveContextRegs.regTEXTURE_CLR_CMP_CLR_C = regr (TEXTURE_CLR_CMP_CLR_C); 
	gsaveContextRegs.regTEXTURE_CLR_CMP_MSK_C = regr (TEXTURE_CLR_CMP_MSK_C); 
	gsaveContextRegs.regFOG_COLOR_C = regr (FOG_COLOR_C); 
	gsaveContextRegs.regPRIM_TEX_CNTL_C = regr (PRIM_TEX_CNTL_C);
	gsaveContextRegs.regPRIM_TEXTURE_COMBINE_CNTL_C = 
		regr (PRIM_TEXTURE_COMBINE_CNTL_C);   
	gsaveContextRegs.regTEX_SIZE_PITCH_C = regr (TEX_SIZE_PITCH_C);

	R128_WaitForFifo (16);
	gsaveContextRegs.regPRIM_TEX_0_OFFSET_C = regr (PRIM_TEX_0_OFFSET_C); 
	gsaveContextRegs.regPRIM_TEX_1_OFFSET_C = regr (PRIM_TEX_1_OFFSET_C); 
    gsaveContextRegs.regPRIM_TEX_2_OFFSET_C = regr (PRIM_TEX_2_OFFSET_C); 
	gsaveContextRegs.regPRIM_TEX_3_OFFSET_C = regr (PRIM_TEX_3_OFFSET_C); 
	gsaveContextRegs.regPRIM_TEX_4_OFFSET_C = regr (PRIM_TEX_4_OFFSET_C); 
	gsaveContextRegs.regPRIM_TEX_5_OFFSET_C = regr (PRIM_TEX_5_OFFSET_C);             
	gsaveContextRegs.regPRIM_TEX_6_OFFSET_C = regr (PRIM_TEX_6_OFFSET_C);
	gsaveContextRegs.regPRIM_TEX_7_OFFSET_C = regr (PRIM_TEX_7_OFFSET_C);
	gsaveContextRegs.regPRIM_TEX_8_OFFSET_C = regr (PRIM_TEX_8_OFFSET_C);
	gsaveContextRegs.regPRIM_TEX_9_OFFSET_C = regr (PRIM_TEX_9_OFFSET_C);
	gsaveContextRegs.regPRIM_TEX_10_OFFSET_C = regr (PRIM_TEX_10_OFFSET_C); 
	gsaveContextRegs.regSEC_TEX_CNTL_C = regr (SEC_TEX_CNTL_C);
	gsaveContextRegs.regSEC_TEX_COMBINE_CNTL_C = 
		regr (SEC_TEX_COMBINE_CNTL_C);
	gsaveContextRegs.regSEC_TEX_0_OFFSET_C = regr (SEC_TEX_0_OFFSET_C); 
	gsaveContextRegs.regSEC_TEX_1_OFFSET_C = regr (SEC_TEX_1_OFFSET_C); 
	gsaveContextRegs.regSEC_TEX_2_OFFSET_C = regr (SEC_TEX_2_OFFSET_C);

	R128_WaitForFifo (16);
	gsaveContextRegs.regSEC_TEX_3_OFFSET_C = regr (SEC_TEX_3_OFFSET_C);
	gsaveContextRegs.regSEC_TEX_4_OFFSET_C = regr (SEC_TEX_4_OFFSET_C);
	gsaveContextRegs.regSEC_TEX_5_OFFSET_C = regr (SEC_TEX_5_OFFSET_C);
	gsaveContextRegs.regSEC_TEX_6_OFFSET_C = regr (SEC_TEX_6_OFFSET_C);
	gsaveContextRegs.regSEC_TEX_7_OFFSET_C = regr (SEC_TEX_7_OFFSET_C);
	gsaveContextRegs.regSEC_TEX_8_OFFSET_C = regr (SEC_TEX_8_OFFSET_C); 
	gsaveContextRegs.regSEC_TEX_9_OFFSET_C = regr (SEC_TEX_9_OFFSET_C);
	gsaveContextRegs.regSEC_TEX_10_OFFSET_C = regr (SEC_TEX_10_OFFSET_C); 
	gsaveContextRegs.regCONSTANT_COLOR_C = regr (CONSTANT_COLOR_C); 
	gsaveContextRegs.regPRIM_TEXTURE_BORDER_COLOR_C = 
		regr (PRIM_TEXTURE_BORDER_COLOR_C); 
	gsaveContextRegs.regSEC_TEXTURE_BORDER_COLOR_C = 
		regr (SEC_TEXTURE_BORDER_COLOR_C); 
    gsaveContextRegs.regSTEN_REF_MASK_C = regr (STEN_REF_MASK_C); 
	gsaveContextRegs.regPLANE_3D_MASK_C = regr (PLANE_3D_MASK_C); 
	gsaveContextRegs.regSETUP_CNTL = regr (SETUP_CNTL); 
	gsaveContextRegs.regPM4_VC_FPU_SETUP = regr (PM4_VC_FPU_SETUP); 
	gsaveContextRegs.regFOG_3D_TABLE_START = regr (FOG_3D_TABLE_START);

    R128_WaitForFifo (2);
	gsaveContextRegs.regFOG_3D_TABLE_END = regr (FOG_3D_TABLE_END);
	gsaveContextRegs.regFOG_3D_TABLE_DENSITY = regr (FOG_3D_TABLE_DENSITY);

}


/*****************************************************************************
 * RestoreContextRegisters                                                   *
 *  Function: Restore original 3D context.                                   *
 *    Inputs: none                                                           *
 *   Outputs: none                                                           *
 *****************************************************************************/

static void RestoreContextRegisters (void)
{
	int size;
	int i = 0;

	// Restore SCALE_3D_CNTL.

    gCommandBuf[i++] = CCE_PACKET0 | (SCALE_3D_CNTL >> 2);
	gCommandBuf[i++] = gsaveContextRegs.regSCALE_3D_CNTL;

	// Submit the packet.
	
    gCommandBuf[0] |= ((i - 2) << 16);
    R128_CCESubmitPackets (gCommandBuf, i);

	// Copy regDST_PITCH_OFFSET_C to regPLANE_3D_MASK_C
	// fields into command buffer and send as Type-0 packet.

	// Compute size of packet.

	size = (DWORD)(&(gsaveContextRegs.regSETUP_CNTL)) - 
		(DWORD)(&(gsaveContextRegs.regDST_PITCH_OFFSET_C));

    gCommandBuf[0] = CCE_PACKET0 | (DST_PITCH_OFFSET_C >> 2);
    memcpy (&(gCommandBuf[1]), &(gsaveContextRegs.regDST_PITCH_OFFSET_C),
        size);

	// Submit packet.

    gCommandBuf[0] |= ((size - 2) << 16);
    R128_CCESubmitPackets (gCommandBuf, size);

	// Send regSETUP_CNTL and regPM4_VC_FPU_SETUP in a Type-1
	// packet.

	
    gCommandBuf[0] = CCE_PACKET1 | ((PM4_VC_FPU_SETUP >> 2) << 11) |
        (SETUP_CNTL >> 2);
	gCommandBuf[1] = gsaveContextRegs.regSETUP_CNTL;
	gCommandBuf[2] = gsaveContextRegs.regPM4_VC_FPU_SETUP; 

	// Submit packet.

    R128_CCESubmitPackets (gCommandBuf, 3);

	// Restore the fog table start, end, and density parameters.

	i = 0;
	gCommandBuf[i++] = CCE_PACKET0 | (FOG_3D_TABLE_START >> 2);
	gCommandBuf[i++] = gsaveContextRegs.regFOG_3D_TABLE_START;
	gCommandBuf[i++] = gsaveContextRegs.regFOG_3D_TABLE_END;
	gCommandBuf[i++] = gsaveContextRegs.regFOG_3D_TABLE_DENSITY;

	// Submit the packet.
	
    gCommandBuf[0] |= ((i - 2) << 16);
    R128_CCESubmitPackets (gCommandBuf, i);

}


/****************************************************************************
 * DumpContextAndRegisters                                                  *
 *  Function: Write state of 3D context into file CONTEXT.TXT.              *
 *    Inputs: none                                                          *
 *   Outputs: none                                                          *
 ****************************************************************************/

void DumpContextAndRegisters (void)
{
	FILE* fp;

	fp = fopen ("context.txt", "w");
	if (!fp) return;

    R128_WaitForFifo (16);
	fprintf (fp, "%08x %08x\n", gContext3D.regSCALE_3D_CNTL, 
		regr (SCALE_3D_CNTL));
	fprintf (fp, "%08x %08x\n", gContext3D.regDST_PITCH_OFFSET_C, 
		regr (DST_PITCH_OFFSET_C));
	fprintf (fp, "%08x %08x\n", gContext3D.regDP_GUI_MASTER_CNTL, 
		regr (DP_GUI_MASTER_CNTL));
	fprintf (fp, "%08x %08x\n", gContext3D.regSC_TOP_LEFT_C, 
		regr (SC_TOP_LEFT_C));
	fprintf (fp, "%08x %08x\n", gContext3D.regSC_BOTTOM_RIGHT_C, 
		regr (SC_BOTTOM_RIGHT_C)); 
	fprintf (fp, "%08x %08x\n", gContext3D.regZ_OFFSET_C, 
		regr (Z_OFFSET_C)); 
	fprintf (fp, "%08x %08x\n", gContext3D.regZ_PITCH_C, 
		regr (Z_PITCH_C)); 
	fprintf (fp, "%08x %08x\n", gContext3D.regZ_STEN_CNTL_C, 
		regr (Z_STEN_CNTL_C));
	fprintf (fp, "%08x %08x\n", gContext3D.regTEX_CNTL_C, 
		regr (TEX_CNTL_C));
	fprintf (fp, "%08x %08x\n", gContext3D.regMISC_3D_STATE_CNTL_REG, 
		regr (MISC_3D_STATE_CNTL_REG));
	fprintf (fp, "%08x %08x\n", gContext3D.regTEXTURE_CLR_CMP_CLR_C, 
		regr (TEXTURE_CLR_CMP_CLR_C)); 
	fprintf (fp, "%08x %08x\n", gContext3D.regTEXTURE_CLR_CMP_MSK_C, 
		regr (TEXTURE_CLR_CMP_MSK_C));
	fprintf (fp, "%08x %08x\n", gContext3D.regFOG_COLOR_C, 
		regr (FOG_COLOR_C)); 
	fprintf (fp, "%08x %08x\n", gContext3D.regPRIM_TEX_CNTL_C, 
		regr (PRIM_TEX_CNTL_C));
	fprintf (fp, "%08x %08x\n", gContext3D.regPRIM_TEXTURE_COMBINE_CNTL_C, 
		regr (PRIM_TEXTURE_COMBINE_CNTL_C));
	fprintf (fp, "%08x %08x\n", gContext3D.regTEX_SIZE_PITCH_C, 
		regr (TEX_SIZE_PITCH_C));


	R128_WaitForFifo (16);

	fprintf (fp, "%08x %08x\n", gContext3D.regPRIM_TEX_0_OFFSET_C, 
		regr (PRIM_TEX_0_OFFSET_C));
	fprintf (fp, "%08x %08x\n", gContext3D.regPRIM_TEX_1_OFFSET_C, 
		regr (PRIM_TEX_1_OFFSET_C));
	fprintf (fp, "%08x %08x\n", gContext3D.regPRIM_TEX_2_OFFSET_C, 
		regr (PRIM_TEX_2_OFFSET_C));
	fprintf (fp, "%08x %08x\n", gContext3D.regPRIM_TEX_3_OFFSET_C, 
		regr (PRIM_TEX_3_OFFSET_C));
	fprintf (fp, "%08x %08x\n", gContext3D.regPRIM_TEX_4_OFFSET_C, 
		regr (PRIM_TEX_4_OFFSET_C));
	fprintf (fp, "%08x %08x\n", gContext3D.regPRIM_TEX_5_OFFSET_C, 
		regr (PRIM_TEX_5_OFFSET_C));
	fprintf (fp, "%08x %08x\n", gContext3D.regPRIM_TEX_6_OFFSET_C, 
		regr (PRIM_TEX_6_OFFSET_C));
	fprintf (fp, "%08x %08x\n", gContext3D.regPRIM_TEX_7_OFFSET_C, 
		regr (PRIM_TEX_7_OFFSET_C));
	fprintf (fp, "%08x %08x\n", gContext3D.regPRIM_TEX_8_OFFSET_C, 
		regr (PRIM_TEX_8_OFFSET_C));
	fprintf (fp, "%08x %08x\n", gContext3D.regPRIM_TEX_9_OFFSET_C, 
		regr (PRIM_TEX_9_OFFSET_C));
	fprintf (fp, "%08x %08x\n", gContext3D.regPRIM_TEX_10_OFFSET_C, 
		regr (PRIM_TEX_10_OFFSET_C)); 
	fprintf (fp, "%08x %08x\n", gContext3D.regSEC_TEX_CNTL_C, 
		regr (SEC_TEX_CNTL_C));
	fprintf (fp, "%08x %08x\n", gContext3D.regSEC_TEX_COMBINE_CNTL_C, 
		regr (SEC_TEX_COMBINE_CNTL_C));
	fprintf (fp, "%08x %08x\n", gContext3D.regSEC_TEX_0_OFFSET_C, 
		regr (SEC_TEX_0_OFFSET_C)); 
	fprintf (fp, "%08x %08x\n", gContext3D.regSEC_TEX_1_OFFSET_C, 
		regr (SEC_TEX_1_OFFSET_C)); 
	fprintf (fp, "%08x %08x\n", gContext3D.regSEC_TEX_2_OFFSET_C, 
		regr (SEC_TEX_2_OFFSET_C));


    R128_WaitForFifo (16);
	fprintf (fp, "%08x %08x\n", gContext3D.regSEC_TEX_3_OFFSET_C, 
		regr (SEC_TEX_3_OFFSET_C));
	fprintf (fp, "%08x %08x\n", gContext3D.regSEC_TEX_4_OFFSET_C, 
		regr (SEC_TEX_4_OFFSET_C));
	fprintf (fp, "%08x %08x\n", gContext3D.regSEC_TEX_5_OFFSET_C, 
		regr (SEC_TEX_5_OFFSET_C));
	fprintf (fp, "%08x %08x\n", gContext3D.regSEC_TEX_6_OFFSET_C, 
		regr (SEC_TEX_6_OFFSET_C));
	fprintf (fp, "%08x %08x\n", gContext3D.regSEC_TEX_7_OFFSET_C, 
		regr (SEC_TEX_7_OFFSET_C));
	fprintf (fp, "%08x %08x\n", gContext3D.regSEC_TEX_8_OFFSET_C, 
		regr (SEC_TEX_8_OFFSET_C)); 
	fprintf (fp, "%08x %08x\n", gContext3D.regSEC_TEX_9_OFFSET_C, 
		regr (SEC_TEX_9_OFFSET_C));
	fprintf (fp, "%08x %08x\n", gContext3D.regSEC_TEX_10_OFFSET_C, 
		regr (SEC_TEX_10_OFFSET_C)); 
	fprintf (fp, "%08x %08x\n", gContext3D.regCONSTANT_COLOR_C, 
		regr (CONSTANT_COLOR_C)); 
	fprintf (fp, "%08x %08x\n", gContext3D.regPRIM_TEXTURE_BORDER_COLOR_C, 
		regr (PRIM_TEXTURE_BORDER_COLOR_C)); 
	fprintf (fp, "%08x %08x\n", gContext3D.regSEC_TEXTURE_BORDER_COLOR_C, 
		regr (SEC_TEXTURE_BORDER_COLOR_C)); 
	fprintf (fp, "%08x %08x\n", gContext3D.regSTEN_REF_MASK_C, 
		regr (STEN_REF_MASK_C)); 
	fprintf (fp, "%08x %08x\n", gContext3D.regPLANE_3D_MASK_C, 
		regr (PLANE_3D_MASK_C)); 
	fprintf (fp, "%08x %08x\n", gContext3D.regSETUP_CNTL, 
		regr (SETUP_CNTL)); 
	fprintf (fp, "%08x %08x\n", gContext3D.regPM4_VC_FPU_SETUP, 
		regr (PM4_VC_FPU_SETUP));
    fprintf (fp, "%08x %08x\n", gContext3D.regFOG_3D_TABLE_START, 
        regr (FOG_3D_TABLE_START));

    R128_WaitForFifo (2);
    fprintf (fp, "%08x %08x\n", gContext3D.regFOG_3D_TABLE_END, 
        regr (FOG_3D_TABLE_END));
    fprintf (fp, "%08x %08x\n", gContext3D.regFOG_3D_TABLE_DENSITY, 
        regr (FOG_3D_TABLE_DENSITY));

	fclose (fp);
}
