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

	input.c

    PSP input control functions

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

#include "psp.h"


/***************************************************************************
	Private variables
 ***************************************************************************/

static int pad;
static u8 pressed_check[12];
static u8 pressed_count[12];
static u8 pressed_delay[12];


/*--------------------------------------------------------
	Initialize pad
 -------------------------------------------------------*/

void pad_init(void)
{
	sceCtrlSetSamplingCycle(0);
	sceCtrlSetSamplingMode(1);

	pad = 0;
	memset(pressed_check, 0, sizeof(pressed_check));
}


/*--------------------------------------------------------
	Poll pad
 -------------------------------------------------------*/

int poll_gamepad(void)
{
	SceCtrlData paddata;

	sceCtrlPeekBufferPositive(&paddata, 1);

	if (paddata.Ly >= 0xD0) paddata.Buttons |= PSP_CTRL_DOWN;  // DOWN
	if (paddata.Ly <= 0x30) paddata.Buttons |= PSP_CTRL_UP;    // UP
	if (paddata.Lx <= 0x30) paddata.Buttons |= PSP_CTRL_LEFT;  // LEFT
	if (paddata.Lx >= 0xD0) paddata.Buttons |= PSP_CTRL_RIGHT; // RIGHT

	return paddata.Buttons;
}


/*--------------------------------------------------------
	Update pad status
 -------------------------------------------------------*/

void pad_update(void)
{
	pad = poll_gamepad();
}


/*--------------------------------------------------------
	Get button status
 -------------------------------------------------------*/

int pad_pressed(u32 code)
{
	return (pad & code) != 0;
}


/*--------------------------------------------------------
	Check any buttons are pressed
 -------------------------------------------------------*/

int pad_pressed_any(u32 disable_code)
{
	return (pad & (PSP_CTRL_ANY ^ disable_code)) != 0;
}


/*--------------------------------------------------------
	Get button status with delay
 -------------------------------------------------------*/

int pad_pressed_memory(u32 code)
{
	int internal_code, pressed;

	switch (code)
	{
	case PSP_CTRL_UP:		internal_code =  0; break;
	case PSP_CTRL_DOWN:		internal_code =  1; break;
	case PSP_CTRL_LEFT:		internal_code =  2; break;
	case PSP_CTRL_RIGHT:	internal_code =  3; break;
	case PSP_CTRL_CIRCLE:	internal_code =  4; break;
	case PSP_CTRL_CROSS:	internal_code =  5; break;
	case PSP_CTRL_SQUARE:	internal_code =  6; break;
	case PSP_CTRL_TRIANGLE:	internal_code =  7; break;
	case PSP_CTRL_START:	internal_code =  8; break;
	case PSP_CTRL_SELECT:	internal_code =  9; break;
	case PSP_CTRL_LTRIGGER:	internal_code = 10; break;
	case PSP_CTRL_RTRIGGER:	internal_code = 11; break;
	default: return 0;
	};

	pressed = pad_pressed(code);

	if (pressed)
	{
		if (!pressed_check[internal_code])
		{
			pressed_check[internal_code] = 1;
			pressed_count[internal_code] = 0;
			pressed_delay[internal_code] = 9;
		}
		else if (++pressed_count[internal_code] > pressed_delay[internal_code])
		{
			pressed_count[internal_code] = 0;
			pressed_delay[internal_code] = 3;
		}
		else
			pressed = 0;
	}
	else
		pressed_check[internal_code] = 0;

	return pressed;
}


/*--------------------------------------------------------
	Wait clear pad status
 -------------------------------------------------------*/

void pad_wait_clear(void)
{
	while (poll_gamepad()) if (!bLoop) break;

	pad = 0;
	memset(pressed_check, 0, sizeof(pressed_check));
}


/*--------------------------------------------------------
	Wait press any buttons
 -------------------------------------------------------*/

void pad_wait_press(int msec)
{
	if (msec == -1)
	{
		pad_wait_clear();

		while (1)
		{
			if (poll_gamepad()) break;
			if (!bLoop) break;
		}
	}
	else
	{
		TICKER curr = ticker();
		TICKER target, prev;

		target = curr + msec * (TICKS_PER_SEC / 1000);

		pad_wait_clear();

		while (curr - target < 0)
		{
			prev = curr;
			curr = ticker();

			if (poll_gamepad()) break;
			if (prev > curr) break;
			if (!bLoop) break;
		}
	}
}
