/****************************************************************************\
*                                                                           *
* tpNinjaR.c-   TrueMotion player video hardware/system specific interface  *
*                                                                           *
*       TruePlay2 v 7.0.0                                                   *
*       Copyright (c) 1994-98, The Duck Corp. All rights reserved.          * 
*                                                                           *
*       Created:    8/5/98                                                  *
*                                                                           *
\***************************************************************************/
#include "tpApi.h"

#include "shinobi.h"
#include "sg_gd.h"

/* Ripple Stuff  8-5-98 */
#define NUM_GRID			75
/*
#define NUM_ROW_GRID		(NUM_GRID * 2)-2
#define NUM_GRID_VERTICES	(NUM_GRID*NUM_GRID)
*/
#define GRID_WIDTH			2.0f
/*
#define NUM_GRID_INDICES	((NUM_GRID-1)*(NUM_GRID-1)*2*3)
*/

NJS_TEXTURE_VTX	stripGrid[NUM_GRID][NUM_GRID*2]; /* Basic Stripped grid */

NJS_TEXTURE_VTX	xStripGrid[NUM_GRID*3]; /* Basic Changed Stripped grid */


#define SIN_WAVE	1
#define DRIP		2
int rippleMode;


NJS_TEXTURE_VTX	poly[4];
extern Uint32 counter;

int counted,total,total2;

#define NUM 4


static void SetupRippleGridAndIndices(MovieHandle movie,int w, int h) {
	int i, j;
	int col = 0;
	float fw = (float) w;
	float fh = (float) h;

	for( i=0; i<NUM_GRID-1; i++ )
	{
		for( col=0,j=0; j<NUM_GRID; j++,col +=2 )
		{
			float x = ((float)j)*GRID_WIDTH/(((float)NUM_GRID)-1.f) - GRID_WIDTH/2.f;
			float y = ((float)i)*GRID_WIDTH/(((float)NUM_GRID)-1.f) - GRID_WIDTH/2.f;
			float yPrime = ((float)(i+1))*GRID_WIDTH/(((float)NUM_GRID)-1.f) - GRID_WIDTH/2.f;

			float u = ( (((float)j) / ((float)NUM_GRID-1)) * fw ) /1024.f;
			float v = ( (((float)i) / ((float)NUM_GRID-1)) * fh ) /512.f;
			float vPrime = ( (((float)(i+1)) / ((float)NUM_GRID-1)) * fh ) /512.f;
				
			/*
			x = (x * 320.0f) + 320.0f;
			y = (y * 240.0f) + 240.0f;
			yPrime = (yPrime * 240.0f) + 240.0f;
			*/
			stripGrid[i][col].x = x;
			stripGrid[i][col].y = y;
			stripGrid[i][col].z = 0.4f;
			stripGrid[i][col].col = 0xFFFFFFFF;

			stripGrid[i][col].x *= 640.f / 1.5f;
			stripGrid[i][col].y *= 480.f / 1.5f;
			stripGrid[i][col].x += 640.f / 1.25f;
			stripGrid[i][col].y += 480.f / 1.25f;
			
			/*calculate the u&v texture coordinates for this vertex*/
			/* first calculate u from 0.0<->1.0 then from 0.0<->640.f then from 0.0<->(640.f/1024.f) */
			/* first calculate v from 0.0<->1.0 then from 0.0<->480.f then from 0.0<->(480.f/512.f) */
			stripGrid[i][col].u = u;
			stripGrid[i][col].v = v;

			stripGrid[i][col+1].x = x;
			stripGrid[i][col+1].y = yPrime;
			stripGrid[i][col+1].z = 0.4f;
			stripGrid[i][col+1].col = 0xFFFFFFFF;

			stripGrid[i][col+1].u = u;
			stripGrid[i][col+1].v = vPrime;

			stripGrid[i][col+1].x *= 640.f / 1.5f;
			stripGrid[i][col+1].y *= 480.f / 1.5f;
			stripGrid[i][col+1].x += 640.f / 1.25f;
			stripGrid[i][col+1].y += 480.f / 1.25f;
		}
	}
	
	for(j=0; j<NUM_GRID*3; j++){
		xStripGrid[j].col = 0xFFFFFFFF;
	}

	rippleMode = SIN_WAVE;
}

static int DrawRipple()
{
	int i, j;
	int col = 0;
	static float freq = 16.0f;
	static float amp = 0.15f;

	{
		/* the controller is used to control the frequency of the wave */

		const PDS_PERIPHERALINFO* info;
		const PDS_PERIPHERAL* per;

		per = pdGetPeripheral(PDD_PORT_A0);

		if (!(per->info->type & PDD_DEVTYPE_CONTROLLER)) {
			freq = 16.0f;
			amp = 0.15f;
		}

		if (per->press & NJD_DGT_KR) freq += 1.0f;
		if (per->press & NJD_DGT_KL) freq -= 1.0f;
		if (freq < 0.0f) freq = 0.0f;
		if (freq > 64.0f) freq = 64.0f;

		if (per->press & NJD_DGT_KU) amp += .03f;
		if (per->press & NJD_DGT_KD) amp -= .03f;

		if (amp < -0.3f) amp = -0.3f;
		if (amp > 0.3f) amp = 0.3f;

	}

	{
		static float n = 0.0f;
		int xx, yy;
		int i, j;
		int col = 0;
		int xCor = ((NUM_GRID/2) * -1);
		int yCor = ((NUM_GRID/2) * -1);
		float radius;

		/* calculate the first "row" of vertices */

		for( i=0,col=0,j=0; j<NUM_GRID; j++,col +=2 ){
			xx = (j+xCor)*(j+xCor);				
			yy = (i+yCor)*(i+yCor);

			radius = (float)njSqrt(xx+yy);

			xStripGrid[col].z = ((float)njSin(NJM_DEG_ANG(radius + n)*freq) * amp);
			xStripGrid[col].z += 0.30f;

			xStripGrid[col].x = stripGrid[i][col].x / ( xStripGrid[col].z + 1.5f );
			xStripGrid[col].y = stripGrid[i][col].y / ( xStripGrid[col].z + 1.5f );

			xStripGrid[col].u = stripGrid[i][col].u;
			xStripGrid[col].v = stripGrid[i][col].v;
		}

		/* now, after we calculate a "row" of vertices, 
			we can then draw the polygon strip "above" it
		*/

		for( i=0; i<NUM_GRID-1; i++ )
		{
			for( col=i,j=0; j<NUM_GRID; j++,col +=2 )
			{
				xx = (j+xCor)*(j+xCor);				
				yy = (i+1+yCor)*(i+1+yCor);

				radius = (float)njSqrt(xx+yy);

				xStripGrid[col+1].z = ((float)njSin(NJM_DEG_ANG(radius + n)*freq) * amp);
				xStripGrid[col+1].z += 0.30f;

				xStripGrid[col+1].x = stripGrid[i][(j*2)+1].x / ( xStripGrid[col+1].z + 1.5f );
				xStripGrid[col+1].y = stripGrid[i][(j*2)+1].y / ( xStripGrid[col+1].z + 1.5f );

				xStripGrid[col+1].u = stripGrid[i][(j*2)+1].u;
				xStripGrid[col+1].v = stripGrid[i][(j*2)+1].v;

			}
			/* draw the polygon strip */
			njDrawTexture( &xStripGrid[i], NUM_GRID*2, 0,FALSE);
		}

		/* now change the angle to cause the wave movement */

		n += 0.45f;

		if (n > 360.f)	
			n = 0.f;
	}	
	return 0;
}

static PLAYER_STATUS_CODE tp_beforeDecompress(MovieHandle movie)
{
	/* no predecompression step necessary */
	return TP_OK;
}
/* how we really decompress a frame*/
static PLAYER_STATUS_CODE tp_afterDecompress(MovieHandle movie)
{
	int x, y, w, h;

	DXL_GetXImageXYWH(movie->xImage, &x, &y, &w, &h);
	{
		unsigned long entry;

		for(entry = 0; entry < 512; entry++){
		  *((volatile unsigned long *)(0xF4000000 | (entry << 5))) = 0x00000000; 
		  /* OC address array write */
		}
	}

	/* 
		since the internal format of the xImage matches the 
		UYVY format of the texture, the application transfers it 
		directly to the powerVR
	*/
	njReLoadTexturePartNumG(0,
		(signed char *)DXL_GetXImageFrameBuffer(movie->xImage),
		0,
		w*h*2
		);

	/* draw the new texture and wait for VSync */
	DrawRipple();
	njWaitVSync();

	return TP_OK;
}


static PLAYER_STATUS_CODE tp_centerScreen(MovieHandle movie) {

	int x, y, w, h;

	DXL_GetXImageXYWH(movie->xImage, &x, &y, &w, &h);

	/* this sets the geometry for the textured polygon */

	poly[0].z = poly[1].z = 
		poly[2].z = poly[3].z = 0.48;
	
	poly[0].col = poly[1].col = 
		poly[2].col = poly[3].col =  0xFFFFFFFF;

	poly[0].x = poly[1].x = 000;
	poly[0].y = poly[2].y = 000;
	poly[0].u = poly[1].u = 0;
	poly[0].v = poly[2].v = 0;

	/* 
		the height and width of the frame are scaled 
		to the width of the screen (640) 
	*/
	poly[1].y = poly[3].y = (h*640)/w;
	poly[2].x = poly[3].x = (w*640)/w;

	/*
		we're using a stride texture, adjust the v and u
		to reflect the true width of the frame
		and set sender width to the real width
	*/
	poly[1].v = poly[3].v = (float)h/512.f;
	poly[2].u = poly[3].u = (float)w/1024.f;
	
	njSetRenderWidth(w);

	/* 
		for frames smaller than 640x480, enable filtering 
		otherwise enable point sampling
	*/

	if ((w < 640) || (h < 480))
		njTextureFilterMode( NJD_TEXTUREFILTER_TRILINEAR );
	else{
		njTextureFilterMode( NJD_TEXTUREFILTER_POINT_SAMPLE );
	}

	SetupRippleGridAndIndices(movie,w,h);

	return TP_OK;
}

static PLAYER_STATUS_CODE tp_restoreDisplay(MovieHandle movie) 
{
	return TP_OK;
}

PLAYER_STATUS_CODE tp_setupDisplay(MovieHandle movie)
{

	movie->beforeDecompress = tp_beforeDecompress;
	movie->afterDecompress = tp_afterDecompress;
	movie->restoreDisplay = tp_restoreDisplay;
	movie->centerScreen = tp_centerScreen;

	return TP_OK;
}

