/************************************************************************************
	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"

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;
	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:	
**************************************************************************/

void padHandler()
{
	int		pad;
	int		loop;
	static  UBYTE delock[4]={0,0,0,0};

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


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

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

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

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

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

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

		if(per[pad]->y1 <-80 && delock[3]==0){padData.debounce[pad] |= PAD_UP;delock[3]=1;}
		else
			if(per[pad]->y1 >-50)delock[3]=0;
	 
		padData.analogX[pad] = padData.analogXS[pad] = per[pad]->x1+128;
		padData.analogY[pad] = padData.analogYS[pad] = per[pad]->y1+128;
		
		padNormalise(padData.analogX[pad], padData.analogY[pad], &padData.analogXS[pad], &padData.analogYS[pad]);
	}

	pdExecPeripheralServer();
}

