/************************************************************************************
	ISL PSX LIBRARY	(c) 1999 Interactive Studios Ltd.

	islpad.c			Controller pad routines

************************************************************************************/

//#include <stddef.h>
//#include <libetc.h>
//#include "libpad.h"
//#include <stdio.h>
#include "islpad.h"
#include "main.h"
#include "card.h"
#include "fadeout.h"
#include "menu.h"
#include "startup.h"

enum {									// Supported pad types
	PADTYPE_NONE,
	PADTYPE_DIGITAL,
	PADTYPE_ANALOG,
	PADTYPE_DUALSHOCK,
};

typedef struct _PadPacket {
     short			digital;
     unsigned char	rightX;
     unsigned char	rightY;
     unsigned char	leftX;
     unsigned char	leftY;
} PadPacket;

typedef struct _PadDataType2 {
	unsigned char	buffer[2][34];				// HW packet buffers
	int				state[8];					// Port HW state
	unsigned short	digitalPrev[8];				// Previous d-pad reading
	int				newShock[8];
} PadDataType2;

static PadDataType2		padData2;
static unsigned char	MULTITAP_SUPPORT;

PadDataType				padData;
PadDataType *pReadPad = &padData;


static unsigned char	HWalign[6]={0,1,0xFF,0xFF,0xFF,0xFF};
unsigned char			analog[8];
unsigned short			pad[8], debounce[8];
unsigned short			leftx[8], lefty[8];
unsigned short			rightx[8], righty[8];
unsigned short			bothdebounces, bothpads;

/**************************************************************************
	FUNCTION:	padInitialise()
	PURPOSE:	Initialise pads
	PARAMETERS:	multi-tap on/off
	RETURNS:	
**************************************************************************/

void padInitialise(unsigned char multiTap)
{
	int		loop;

	padData.numPads[0]  = 1;
	padData.numPads[1]  = 1;
	padData.analogAccel = 4;	// default acceleration for analog emulation
	//VSync(5);
	for(loop=0; loop<4; loop++)
	{
		padData.digital[loop]		= 0;
		padData.debounce[loop]		= 0;
		padData.analogX[loop]		= 128;
		padData.analogY[loop]		= 128;
		padData.analogX2[loop]		= 128;
		padData.analogY2[loop]		= 128;
		padData.analogXS[loop]		= 0;
		padData.analogYS[loop]		= 0;
		padData.analogX2S[loop]		= 0;
		padData.analogY2S[loop]		= 0;
		padData.shockEnable			= 0;
		padData2.digitalPrev[loop]	= 0;
		padData2.newShock[loop]		= 0;
	}
}


// (deadmult is 4096/(128-deadzone)
#define DEADZONE 50
#define DEADMULT 53

static void padNormalise(int x,int y,short *nx, short *ny)
{
	int ax,ay;
	int	testMag;
	VECTOR	testVec;
	// Not the most effient piece of code but it works a lot better

	x = -(127 - x);
	y = -(127 - y);

	testMag=Magnitude2D(x,y);

	ax = ABS(x);
	ay = ABS(y);

	if (ax < DEADZONE )
		*nx=0;
	else
		*nx = (ax - DEADZONE) * DEADMULT;
			
	if (ay < DEADZONE )
		*ny=0;
	else
		*ny = (ay - DEADZONE) * DEADMULT;

	testVec.vx=*nx;
	testVec.vy=*ny;
	testVec.vz=0;

	MakeUnit(&testVec);

	*nx=(testVec.vx*testMag)/128;
	*ny=(testVec.vy*testMag)/128;

	if(x < 0)
		*nx = -*nx;
	if(y < 0)
		*ny = -*ny;

/*
	int ax,ay;
	x = -(127 - x);
	y = -(127 - y);
	ax = ABS(x);
	ay = ABS(y);

	if(ax < DEADZONE && ay < DEADZONE)
	{
		*nx = 0;
		*ny = 0;
	}
	else if (ax <= ay)
	{
		*ny = (ay - DEADZONE) * DEADMULT;
		*nx = (ax * (int)(*ny)) >>7;
	}
	else
	{
		*nx = (ax - DEADZONE) * DEADMULT;
		*ny = (ay * (int)(*nx)) >>7;
	}
	if(*nx >4096) *nx = 4096;
	if(*ny >4096) *ny = 4096;

	if(x < 0)
		*nx = -*nx;
	if(y < 0)
		*ny = -*ny;
*/
}


static void padHandlePort(int pad)
{
	if(per[pad]->info->type==PDD_DEVTYPE_CONTROLLER)
	{
		padData.present[pad]=1;
		padData.analog[pad]=1;
	}
	else
	{
		padData.present[pad]=0;
		padData.analog[pad]=0;
	}
}

void padHandleInput()
{
	padHandler();
}

void padHandleShock()
{
}

/**************************************************************************
	FUNCTION:	padHandler()
	PURPOSE:	Handle pad reading/connection etc.
	PARAMETERS:	
	RETURNS:	
**************************************************************************/

int firstPad = -1;
int padPort[4] = {PDD_PORT_A0,PDD_PORT_B0,PDD_PORT_C0,PDD_PORT_D0};
int cheat = 0;
int noControllerInputTime = 0;
extern int noRestart;
extern int demoVideo;
void padHandler()
{
	int		pad;
	int		loop,px,py;
	static  UBYTE delock[4]={0,0,0,0};
	static	UBYTE delock2[2][4] = {0,0,0,0,0,0,0,0};

	long buttonListDC[11] = {PDD_DGT_KL, PDD_DGT_KR, PDD_DGT_KU, PDD_DGT_KD, PDD_DGT_TY,  PDD_DGT_TB, PDD_DGT_TA, PDD_DGT_TX, PDD_DGT_TL, PDD_DGT_TR, PDD_DGT_ST};
	long buttonListPS[11] = {PAD_L1,     PAD_R1,     PAD_SELECT, 0,          PAD_TRIANGLE,PAD_CIRCLE, PAD_CROSS,  PAD_SQUARE, PAD_L2,     PAD_R2,     PAD_START};


	pdExecPeripheralServer();

	if((!levinfo) || (cycle_routine == selectVMUCycle) || (cycle_routine == startupCycle) || (cycle_routine == menuCycle) || (pauseOn) || (levinfo->level_number == LEVNUMBER_A1_FOWLER) || (levinfo->level_number == LEVNUMBER_A2_FOWLER) || (levinfo->level_number == LEVNUMBER_A4_FOWLER))
	{
		buttonListPS[0] = PAD_LEFT;
		buttonListPS[1] = PAD_RIGHT;
		buttonListPS[2] = PAD_UP;
		buttonListPS[3] = PAD_DOWN;
	}


	for(pad=0;pad<4;pad++)
	{
		per[pad] = pdGetPeripheral(padPort[pad]);
		padHandlePort(pad);

#if PALMODE==1
		padData.debounce[pad] = 0;
		padData.digital[pad] = 0;
		if((firstPad == -1) && (padData.present[pad]))
		{
			if(per[pad]->press & PDD_DGT_KL)
				padData.debounce[0] |= PAD_LEFT;
			if(per[pad]->press & PDD_DGT_KR)
				padData.debounce[0] |= PAD_RIGHT;
			if(per[pad]->press & PDD_DGT_TA)
				padData.debounce[0] |= PAD_CROSS;


			if(per[pad]->x1 > 80 && delock2[0][pad] == 0)
			{
				padData.debounce[0] |= PAD_RIGHT;
				delock2[0][pad]=1;
			}
			else if(per[pad]->x1 < 50)
				delock2[0][pad]=0;

			if(per[pad]->x1 < -80 && delock2[1][pad] == 0)
			{
				padData.debounce[0] |= PAD_LEFT;
				delock2[1][pad] = 1;
			}
			else if(per[pad]->x1 > -50)

				delock2[1][pad] = 0;



			if(per[pad]->press & PDD_DGT_ST)
			{
				if((titleScreen) && (hzQuit) && (!demoVideo))
					firstPad = pad;
				else
				{
					padData.debounce[0] |= PAD_START;
					if((per[pad]->on & (PDD_DGT_TA + PDD_DGT_TB + PDD_DGT_TX + PDD_DGT_TY)) == PDD_DGT_TA + PDD_DGT_TB + PDD_DGT_TX + PDD_DGT_TY)
//					if((per[pad]->on & (PDD_DGT_TA)) == PDD_DGT_TA)
						padData.digital[0] = PAD_START + PAD_CROSS + PAD_CIRCLE + PAD_SQUARE + PAD_TRIANGLE;
				}
			}
		}
#else

		if((firstPad == -1) && (padData.present[pad]))
			firstPad = pad;
#endif
	}


	if(firstPad == -1)
	{
		return;
	}
#ifdef DEBUG
	if(padData.present[firstPad] == 0)
	{
		if(cheat == 1)
		{
			noRestart = YES;
			pauseEndQuitGame();
			noRestart = NO;
			levflowCheatToEngine();
			cheat = 0;
		}
		return;
	}
#endif
	//for(pad=0;pad<4;pad++)

//////////////////////
//////////////////////THIS IS THE CODE FOR THE 2ND PAD DEBUG STUFF
//////////////////////
#ifdef DEBUG
		pad=3;

		padData.debounce[pad+1] = 0;
		padData.digital[pad+1] = 0;
		for(loop=0;loop<11;loop++)//number of buttons
		{
			if(per[pad]->press & buttonListDC[loop])
				padData.debounce[pad+1] |= buttonListPS[loop];
			if(per[pad]->on & buttonListDC[loop])
				padData.digital[pad+1] |= buttonListPS[loop];
		}

		padData.analogX2[0] = padData.analogX2S[0] = per[pad]->x1+128;
		padData.analogY2[0] = padData.analogY2S[0] = per[pad]->y1+128;
		
		padNormalise(padData.analogX2[0], padData.analogY2[0], &padData.analogX2S[0], &padData.analogY2S[0]);
#endif
//////////////////////
//////////////////////FEEL FREE TO DELETE NEAR THE END
//////////////////////


  	pad=0;
	{
		//if(!padData.present[pad])continue;

		padData.debounce[pad] = 0;
		padData.digital[pad] = 0;
		for(loop=0;loop<11;loop++)//number of buttons
		{
			if(per[firstPad]->press & buttonListDC[loop])
				padData.debounce[pad] |= buttonListPS[loop];
			if(per[firstPad]->on & buttonListDC[loop])
				padData.digital[pad] |= buttonListPS[loop];
		}

		if(per[firstPad]->x1 >= 50 && delock[0] == 0)
		{
			padData.debounce[pad] |= PAD_RIGHT;delock[0]=1;
		}
		else if(per[firstPad]->x1 < 50)
			delock[0]=0;

		if(per[firstPad]->x1 <= -50 && delock[1] == 0)
		{
			padData.debounce[pad] |= PAD_LEFT;
			delock[1] = 1;
		}
		else if(per[firstPad]->x1 > -50)
			delock[1] = 0;

		if(per[firstPad]->y1 >= 50 && delock[2]==0)
		{
			padData.debounce[pad] |= PAD_DOWN;
			delock[2] = 1;
		}
		else if(per[firstPad]->y1 < 50)
			delock[2] = 0;

		if(per[firstPad]->y1 <= -50 && delock[3] == 0)
		{
			padData.debounce[pad] |= PAD_UP;
			delock[3] = 1;
		}
		else if(per[firstPad]->y1 > -50)
			delock[3] = 0;
	 
		//make the analog a little more 'powerful'
		px = (per[firstPad]->x1+128)*1.5;
		if(px<-128)px=-128; 
		if(px> 128)px= 128;
		py = (per[firstPad]->y1+128)*1.5; 
		if(py<-128)py=-128; 
		if(py> 128)py= 128;

		padData.analogX[pad] = padData.analogXS[pad] = per[firstPad]->x1+128;
		padData.analogY[pad] = padData.analogYS[pad] = per[firstPad]->y1+128;
		
		padNormalise(padData.analogX[pad], padData.analogY[pad], &padData.analogXS[pad], &padData.analogYS[pad]);
	}

	if((padData.digital[0]) || (padData.debounce[0]))
	{
		noControllerInputTime = 0;
		if(keepFade)
		{
			keepFade = 0;
			ScreenFade(100,255,5);
		}
	}
	else
		noControllerInputTime++;
}

