/******************************************************************************

		WAVE RACE 64

		File		: enmachine.c
		Description	: endo's move mini-machine program
		Date		: 1996
		Author		: T.Endo

******************************************************************************/

#include "ot_header.h"
#include "ot_sub.h"
#include "ot_newton.h"
#include "ot_sea.h"

#include "endefine.h"
#include "enmachine.h"
#include "enmain.h"
#include "enbuoy.h"
#include "endraw.h"
#include "encrsedit.h"
#include "enchkcrs.h"
#include "enmath.h"

/******************************************************************************
	defines
******************************************************************************/

#define MACHINE_SPEED	2

/******************************************************************************
	external variables
******************************************************************************/

#include "endata/edit/texext.h"

/******************************************************************************
	variables
******************************************************************************/

/*---------------------------------------------------------------------------*/
static int	machine_initx[] = { -15, -10,  -5,   0,  5, 10 };
static int	machine_initz[] = {  -5,   0,   5,  10, 15, 20 };

/*---------------------------------------------------------------------------*/
static Gfx	*pgfx, *pengfx;

/*---------------------------------------------------------------------------*/
static int	machine_color[][3] = {
	{  64,   0,   0 },
	{   0,   0, 192 },
	{   0,  64,   0 },
	{  64,  64,   0 },
	{   0,  64,  64 },
	{  64,   0,  64 },
};

/******************************************************************************
	init machine
******************************************************************************/
void InitMachine(void)
{
	int	i;

	for (i = 0; i < nofmachine; i++) {
		machine[i].px = buoy[ngoalbuoy].ox + (-24 + machine_initx[i]) / crsscale_c;
		machine[i].py = 0.F;
		machine[i].pz = buoy[ngoalbuoy].oz + (8  + machine_initz[i]) / crsscale_c;
		machine[i].vx = machine[i].vy = machine[i].vz = 0.F;
	}
	nplmachine = 0;
}

/******************************************************************************
	move machine sub
******************************************************************************/
static void MoveOneMachine(int num)
{
	int		fthrough;
	Machine		*pmachine;
	enCont		*pcont;

/*	return;	*/

	if (num == nplmachine)
		pcont = &cont[0];
#if 0
	else if (num == 1)
		pcont = &cont[1];
#endif
	else return;

	pmachine = &machine[num];

#if 1
	pmachine->px +=  pcont->ax * 2 / crsscale_c;		
	pmachine->pz += -pcont->ay * 2 / crsscale_c;		

	if (pcont->lev & CONT_RIGHT)	pmachine->px += MACHINE_SPEED / crsscale_c;
	if (pcont->lev & CONT_LEFT)	pmachine->px -= MACHINE_SPEED / crsscale_c;
	if (pcont->lev & CONT_DOWN)	pmachine->pz += MACHINE_SPEED / crsscale_c;
	if (pcont->lev & CONT_UP)	pmachine->pz -= MACHINE_SPEED / crsscale_c;
#else
	pmachine->vx += (float)pcont->x / 64 / crsscale_c;
	pmachine->vz += -(float)pcont->y / 64 / crsscale_c;

	pmachine->px += pmachine->vx / crsscale_c;
	pmachine->pz += pmachine->vz / crsscale_c;
#endif

	fthrough = 0;
	if (pmachine->px < -SCREEN_CH / crsscale_c) {
		pmachine->px += SCREEN_WD / crsscale_c;
		fthrough = 1;
	}
	else if (pmachine->px >= SCREEN_CH / crsscale_c) {
		pmachine->px -= SCREEN_WD / crsscale_c;
		fthrough = 1;
	}
	if (pmachine->pz < -SCREEN_CV / crsscale_c) {
		pmachine->pz += SCREEN_HT / crsscale_c;
		fthrough = 1;
	}
	else if (pmachine->pz >= SCREEN_CV / crsscale_c) {
		pmachine->pz -= SCREEN_HT / crsscale_c;
		fthrough = 1;
	}
	if (fthrough)
		chkcrs[num].fbback = 0;
		
#if 0
	if (num == nplmachine)
		printf("pp: %8.2f%8.2f\n", pmachine->px, pmachine->pz);
#endif

}

/******************************************************************************
	move machine main
******************************************************************************/
void DoMachine(void)
{
	int	i;
	
	for (i = 0; i < nofmachine; i++)
			MoveOneMachine(i);
/* debug */
	if (cont[0].trg & CONT_R)
		nplmachine = ++nplmachine % nofmachine;

}


/******************************************************************************
	draw course
******************************************************************************/
static void DrawCourse(void)
{
	int	i, ix, iz, sx, sz;
	ushort	*ptex;

	gSPClearGeometryMode(pengfx++, G_GEOM_ALL);
	gSPSetGeometryMode(pengfx++, G_SHADE);
	gSPTexture(pengfx++, 0x8000, 0x8000, 0, G_TX_RENDERTILE, G_ON);
	gDPPipeSync(pengfx++);
	gDPSetTexturePersp(pengfx++, G_TP_NONE);
	gDPSetCombineMode(pengfx++, G_CC_DECALRGBA, G_CC_DECALRGBA);
	gDPSetRenderMode(pengfx++,  G_RM_TEX_EDGE, G_RM_TEX_EDGE2);
	gDPSetAlphaCompare(pengfx++, G_AC_NONE);

	for (i = 0; i < nofbuoy; i++) {
		if (buoy[i].user >= BUOY_USER_EN)
			continue;
	
		switch (buoy[i].type) {
			case BUOY_KD_RIGHT:
				ptex = tx_edbuoy_red;
				sx = sz = 8;
				break;
			case BUOY_KD_LEFT:
				ptex = tx_edbuoy_ylw;
				sx = sz = 8;
				break;
			case BUOY_KD_CHECK:
				ptex = tx_chkgate;
				sx = sz = 16;
				break;
			case BUOY_KD_GOAL:
				ptex = tx_goalgate;
				sx = sz = 16;
				break;
			default:
				ptex = tx_arrow;
				sx = sz = 8;
				break;
		}
		ix = buoy[i].ox * crsscale_c - sx / 2 + SCREEN_CH;
		iz = buoy[i].oz * crsscale_c - sz / 2 + SCREEN_CV;

		gDPPipeSync(pengfx++);
		gDPLoadTextureBlock(pengfx++, ptex, G_IM_FMT_RGBA, G_IM_SIZ_16b, 16, 16, 0,
			G_TX_NOMIRROR, G_TX_NOMIRROR,
			G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
		gSPScisTextureRectangle(pengfx++,
			ix << 2, iz << 2, ix + sx << 2, iz + sz << 2, G_TX_RENDERTILE,
			0 << 5, 0 << 5, 1024 * 16 / sx, 1024 * 16 / sz);
	}

}
	
/******************************************************************************
	draw machine, arrow
******************************************************************************/
static void DrawMachine(void)
{
	int	i, j, ix, iz, sx, sz, ex, ez, fsize;
	static int	calpha = 125, valpha = 10;

/*---------------------------------------------------------------------------*/
/* machine */
#define G_CC_TEST2	TEXEL0, ENVIRONMENT, TEXEL0_ALPHA, ENVIRONMENT,  0, 0, 0, 1

	gSPClearGeometryMode(pengfx++, G_GEOM_ALL);
	gSPSetGeometryMode(pengfx++, G_SHADE);
	gSPTexture(pengfx++, 0x8000, 0x8000, 0, G_TX_RENDERTILE, G_ON);
	gDPPipeSync(pengfx++);
	gDPSetTexturePersp(pengfx++, G_TP_NONE);
	gDPSetCombineMode(pengfx++, G_CC_TEST2, G_CC_TEST2);
	gDPSetRenderMode(pengfx++,  G_RM_TEX_EDGE, G_RM_TEX_EDGE2);
	gDPSetAlphaCompare(pengfx++, G_AC_NONE);

	gDPLoadTextureBlock(pengfx++, tx_player, G_IM_FMT_RGBA, G_IM_SIZ_16b, 16, 16, 0,
		G_TX_NOMIRROR, G_TX_NOMIRROR,
		G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
	for (i = nofmachine - 1; i >= 0; i--) {
		if (i != nplmachine) {
			sx = machine[i].px * crsscale_c - 4 + SCREEN_CH;
			sz = machine[i].pz * crsscale_c - 4 + SCREEN_CV;
			ex = sx + 8;
			ez = sz + 8;
			fsize = 2;
		}
		else {
			sx = machine[i].px * crsscale_c - 8 + SCREEN_CH;
			sz = machine[i].pz * crsscale_c - 8 + SCREEN_CV;
			ex = sx + 16;
			ez = sz + 16;
			fsize = 1;
		}
		gDPPipeSync(pengfx++);
		gDPSetEnvColor(pengfx++,  machine_color[i][0], machine_color[i][1], machine_color[i][2],  255);
		if (sx >= 0 && sx <= SCREEN_WD - 1 &&
			sz >= 0 && sz <= SCREEN_HT - 1)
			gSPTextureRectangle(pengfx++,
				sx << 2, sz << 2, ex << 2, ez << 2, G_TX_RENDERTILE,
				(0 << 5), (0 << 5), (fsize << 10), (fsize << 10));
	}

/*---------------------------------------------------------------------------*/
/* arrow */
#define G_CC_TEST3	ENVIRONMENT, 0, TEXEL0, 0,  0, 0, 0, TEXEL0
#define G_CC_TEST4	ENVIRONMENT, 0, TEXEL0, 0,  ENVIRONMENT, 0, TEXEL0, 0

	calpha += valpha;
	if (calpha == 125 || calpha == 255) valpha = -valpha;

	if (1 || (centest & 15)) {
		gDPPipeSync(pengfx++);
		gDPSetCombineMode(pengfx++, G_CC_TEST4, G_CC_TEST4);
		gDPSetRenderMode(pengfx++,  G_RM_XLU_SURF, G_RM_XLU_SURF2);

		gDPLoadTextureBlock(pengfx++, tx_arrow, G_IM_FMT_RGBA, G_IM_SIZ_16b, 16, 16, 0,
			G_TX_NOMIRROR, G_TX_NOMIRROR,
			G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
/*		for (i = nofmachine - 1; i >= 0; i--) {	*/
		for (j = 0; j < nofmachine; j++) {
			i = (j + centest / 8) % nofmachine;
		
			ix = buoy[chkcrs[i].ibnext].ox * crsscale_c -  8 + SCREEN_CH;
			iz = buoy[chkcrs[i].ibnext].oz * crsscale_c - 20 + SCREEN_CV;
			gDPPipeSync(pengfx++);
			gDPSetEnvColor(pengfx++,  machine_color[i][0], machine_color[i][1], machine_color[i][2],  calpha);
			gSPTextureRectangle(pengfx++,
				ix << 2, iz << 2, ix + 16 << 2, iz + 16 << 2, G_TX_RENDERTILE,
				(0 << 5), (0 << 5), (1 << 10), (1 << 10));
		}
	}
}

/******************************************************************************
	draw parameter
******************************************************************************/
static void DrawParameter(void)
{
	int	i, ix, iz;

/*---------------------------------------------------------------------------*/
/* init RCP */
	gSPClearGeometryMode(pengfx++, G_GEOM_ALL);
	gSPSetGeometryMode(pengfx++, G_SHADE);
	gSPTexture(pengfx++, 0x8000, 0x8000, 0, G_TX_RENDERTILE, G_ON);
	gDPPipeSync(pengfx++);
	gDPSetTexturePersp(pengfx++, G_TP_NONE);
	gDPSetCombineMode(pengfx++, G_CC_TEST2, G_CC_TEST2);
	gDPSetRenderMode(pengfx++,  G_RM_TEX_EDGE, G_RM_TEX_EDGE2);
	gDPSetAlphaCompare(pengfx++, G_AC_NONE);

/*---------------------------------------------------------------------------*/
/* draw */
	gDPLoadTextureBlock(pengfx++, tx_letter, G_IM_FMT_RGBA, G_IM_SIZ_16b, 64, 32, 0,
		G_TX_NOMIRROR, G_TX_NOMIRROR,
		G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
	for (i = nofmachine - 1; i >= 0; i--) {
		gDPPipeSync(pengfx++);
		gDPSetEnvColor(pengfx++,  machine_color[i][0], machine_color[i][1], machine_color[i][2],  255);

		/*---------------------------------------------------------------------------*/
		/* lap */
		ix = 32 + i * 12;
		iz = 24;
		gSPTextureRectangle(pengfx++,
			ix << 2, iz << 2, ix + 11 << 2, iz + 15 << 2, G_TX_RENDERTILE,
			chkcrs[i].lap * 6 << 5, 0 << 5, 1 << 9, 1 << 9);

		/*---------------------------------------------------------------------------*/
		/* rank */
		ix = 240 + i * 12;
/*		ix = 240 + chkcrs[i].rank * 12;	*/
		iz = 24;
		gSPTextureRectangle(pengfx++,
			ix << 2, iz << 2, ix + 11 << 2, iz + 15 << 2, G_TX_RENDERTILE,
			(chkcrs[i].rank + 1) * 6 << 5, 0 << 5, 1 << 9, 1 << 9);
#if 1
		/*---------------------------------------------------------------------------*/
		/* irank */
		ix = 32 + i * 6;
		iz = 24 + 16;
		gSPTextureRectangle(pengfx++,
			ix << 2, iz << 2, ix + 6 << 2, iz + 8 << 2, G_TX_RENDERTILE,
			chkcrs[i].irank * 6 << 5, 0 << 5, 1 << 10, 1 << 10);
#endif
#if 1
		/*---------------------------------------------------------------------------*/
		/* miss sum */
		ix = 270 + i * 6;
		iz = 24 + 16;
		gSPTextureRectangle(pengfx++,
			ix << 2, iz << 2, ix + 6 << 2, iz + 8 << 2, G_TX_RENDERTILE,
			(chkcrs[i].miss_sum % 10) * 6 << 5, 0 << 5, 1 << 10, 1 << 10);
#endif
	}
}


/******************************************************************************
	draw test game
******************************************************************************/

void DrawTestGame(Gfx **ppgfx)
{
	int	i, j, imtx;
	float	ortho_l, ortho_r, ortho_b, ortho_t; 
	u16	perspNorm;
	char	buf[64];
	ushort	*ptex;
	
	static float 	theta = 0;
	static int	lookx = 0, looky = 0;

/*---------------------------------------------------------------------------*/
/* calculate */
	centest++;
/*	printf("ct: %8d\n", centest);	*/


#if 0
	if (cont[0].lev & CONT_L) {
		if (cont[0].lev & CONT_RIGHT)   lookx += 2;
		if (cont[0].lev & CONT_LEFT)	lookx -= 2;
		if (cont[0].lev & CONT_UP)	looky += 2;
		if (cont[0].lev & CONT_DOWN)	looky -= 2;
		printf("lk: %8d%8d\n", lookx, looky);
	}
#endif


/*---------------------------------------------------------------------------*/
/* initialize */

	pengfx = peditdynamic->glist;

/*	gSPDisplayList(pengfx++, dl_rspinit);	*/
/*	gSPDisplayList(pengfx++, dl_rdpinit);	*/
	
/*	ClearZBuffer(&pengfx);		*/
/*	ClearFrameBuffer(&pengfx);	*/
/*	GradationBG(&pengfx, 0, 0, 0,  0, 0, 64);	*/
	GradationBG(&pengfx, 0, 0, 0,  0, 64, 0);

/*---------------------------------------------------------------------------*/
/* set projection matrix */

	ortho_l = -(float)SCREEN_WD / 2.0F;
	ortho_r =  (float)SCREEN_WD / 2.0F;
	ortho_b = -(float)SCREEN_HT / 2.0F;
	ortho_t =  (float)SCREEN_HT / 2.0F;
	guOrtho(&peditdynamic->mtx_ortho,
		ortho_l, ortho_r, ortho_b, ortho_t,
		-10000.0F, 10000.0F, 1.0F);


	gSPMatrix(pengfx++, &peditdynamic->mtx_ortho, G_MTX_PROJECTION|G_MTX_LOAD|G_MTX_NOPUSH);
 
/*---------------------------------------------------------------------------*/
/* set view matrix */

/*---------------------------------------------------------------------------*/
/* models */

	imtx = 0;

	egRotate(&peditdynamic->mtx_model[imtx],  theta,  0, 0, 1);
	gSPMatrix(pengfx++, &peditdynamic->mtx_model[imtx++], G_MTX_MODELVIEW|G_MTX_LOAD|G_MTX_NOPUSH);
	
/*	gSPDisplayList(pengfx++, dl_onetri);	*/


/*	theta += 1;	*/
	
	
/*---------------------------------------------------------------------------*/
/* main */

	DrawCourse();	
	DrawMachine();	
	DrawParameter();


/*---------------------------------------------------------------------------*/
/* others */

#if 0
	/* visual coverage */
	gDPPipeSync(pengfx++);
	gDPSetBlendColor(pengfx++, 255, 255, 255, 2555);
	gDPSetPrimDepth(pengfx++, 0xffff, 0xffff);
	gDPSetDepthSource(pengfx++, G_ZS_PRIM);
	gDPSetRenderMode(pengfx++, G_RM_VISCVG, G_RM_VISCVG2);
	gDPFillRectangle(pengfx++, 0, 0, SCREEN_WD - 1, SCREEN_HT - 1);
#endif

/*---------------------------------------------------------------------------*/
/* draw end */

	gSPEndDisplayList(pengfx++);

/*---------------------------------------------------------------------------*/
/* set segment & call endo's dlist */

	pgfx = *ppgfx;
	gSPDisplayList(pgfx++, peditdynamic->glist);
	*ppgfx = pgfx;
}

/******************************************************************************
	main
******************************************************************************/
void TestGameMain(Gfx **ppgfx)
{
	DoMachine();
	ChkCourse();
	DrawTestGame(ppgfx);
}


/******************************************************************************
-------------------------------------------------------------------------------
				end of file
-------------------------------------------------------------------------------
******************************************************************************/
