// **************************************************************************
// *				Sporting Clays for the Nintendo 64						*
// *					   (C) 1999 Charles Doty                           	*
// *	 		   Input Source file contains input code					*
// **************************************************************************

#include <ultra64.h>

#include "input.h"

// System timing correct defines
#define NTSC_COEFFICIENT	0.198166
#define PAL_COEFFICIENT		0.196358
#define KONAMI_OFFSETX		140
#define NAMCO_OFFSETX		10
#define NAMCO_OFFSETY		40

#define MOUSESCALEX			3
#define MOUSESCALEY         4
#define MOUSESPEED			2

WORD ASCII[3][2] =
{
	{0x824f, 0x30},	{0x8260, 0x41},	{0x8281, 0x61}
};

WORD SJIS[] =
{
	0x8140,	0x8149,	0x8168,	0x8194,	0x8190,	0x8193,	0x8195,	0x8166,	0x8169,	0x816a,	0x8196,	0x817b,
	0x8143,	0x817c,	0x8144,	0x815e,	0x8146,	0x8147,	0x8171,	0x8181,	0x8172,	0x8148,	0x8197,	0x816d,
	0x818f,	0x816e,	0x814f,	0x8151,	0x8165,	0x816f,	0x8162,	0x8170,	0x8150
};

OSContStatus		Status[NUMCONTROLLERS];	// Controller status
OSContPad			ControllerData[NUMCONTROLLERS];	// Controller values
BOOL				PadUsed 	= FALSE;	// Is pad being used?
DWORD				PadXValue 	= 1;      	// X Value of Pad movement
DWORD				PadYValue 	= 1;      	// Y Value of Pad movement
RECT				MouseLimits;        	// Limits of the mouse movement
long				MouseX;					// Current mouse x position
long				MouseY;					// Current mouse x position
BOOL				Fired = FALSE;			// Was the gun fired

extern OSMesgQueue	InputMessageQ;			// Message queue for controlllers

DWORD InputInitialize()
{
	BYTE	RetVal;

	PadUsed			= TRUE;
    MouseLimits.x   = 0;
    MouseLimits.y   = 0;
    MouseLimits.w   = SCREENWIDTH - 1;
    MouseLimits.h   = SCREENHEIGHT - 1;
	MouseX			= SCREENWIDTH / 2;
	MouseY			= SCREENHEIGHT / 2;

    osContInit(&InputMessageQ, &RetVal, Status);

	return ERR_NOERROR;
}

DWORD ReadInput(InputStruct *Input, DWORD gun)
{
	Input->Buttons	= BUT_NONE;
	Input->Type		= CON_NONE;

	osContStartReadData(&InputMessageQ);
	osWritebackDCacheAll();
	osRecvMesg(&InputMessageQ, NULL, OS_MESG_BLOCK);
	osContGetReadData(ControllerData);

    ReadPad(Input, gun);
    ReadAnalog(Input, gun);

	return ERR_NOERROR;
}

DWORD SetPadMoveValues(DWORD x, DWORD y)
{
	PadXValue = x;
	PadYValue = y;

	return ERR_NOERROR;
}

DWORD ReadPad(InputStruct *Input, DWORD controller)
{
    if ((ControllerData[controller].button & Z_TRIG) != 0 ||
    	(ControllerData[controller].button & CONT_A) != 0 )
	{
		if (FALSE == Fired)
		{
			Input->Type		= CON_PAD;
			Input->Buttons	|= BUT_TRIGGER;

			Fired = TRUE;
		}
	}

	else
	{
		Fired = FALSE;
	}

	if ((ControllerData[controller].button & CONT_START) != 0)
	{
		Input->Type		= CON_PAD;
		Input->Buttons	|= BUT_START;
	}

    if ((ControllerData[controller].button & U_JPAD) != 0)
	{
		Input->Type		= CON_PAD;
		MouseY			-= PadYValue * MOUSESCALEY;
	}

    if ((ControllerData[controller].button & D_JPAD) != 0)
	{
		Input->Type		= CON_PAD;
		MouseY			+= PadYValue * MOUSESCALEY;
	}

    if ((ControllerData[controller].button & L_JPAD) != 0)
	{
		Input->Type		= CON_PAD;
		MouseX			-= PadXValue * MOUSESCALEX;
	}

    if ((ControllerData[controller].button & R_JPAD) != 0)
	{
		Input->Type		= CON_PAD;
		MouseX			+= PadXValue * MOUSESCALEX;
	}

    if (MouseX < MouseLimits.x)
	{
		MouseX = MouseLimits.x;
	}

	else if (MouseX > MouseLimits.w)
	{
		MouseX = MouseLimits.w;
	}

	if (MouseY < MouseLimits.y)
	{
		MouseY = MouseLimits.y;
	}

	else if (MouseY > MouseLimits.h)
	{
		MouseY = MouseLimits.h;
	}

	Input->X	= MouseX / MOUSESCALEX;
	Input->Y	= MouseY / MOUSESCALEY;

	return ERR_NOERROR;
}

DWORD ReadAnalog(InputStruct *Input, DWORD controller)
{
	ControllerData[controller].stick_x /= 10;
	ControllerData[controller].stick_y /= 10;

    if (ControllerData[controller].stick_x != 0)
	{
		Input->Type		= CON_PAD;
		MouseX			+= ControllerData[controller].stick_x * MOUSESCALEY;

	    if (MouseX < MouseLimits.x)
		{
			MouseX = MouseLimits.x;
		}

		else if (MouseX > MouseLimits.w)
		{
			MouseX = MouseLimits.w;
		}

		Input->X	= MouseX / MOUSESCALEX;
	}

    if (ControllerData[controller].stick_y != 0)
	{

		Input->Type		= CON_PAD;
		MouseY			-= ControllerData[controller].stick_y * MOUSESCALEY;

		if (MouseY < MouseLimits.y)
		{
			MouseY = MouseLimits.y;
		}

		else if (MouseY > MouseLimits.h)
		{
			MouseY = MouseLimits.h;
		}

		Input->Y	= MouseY / MOUSESCALEY;
	}

	return ERR_NOERROR;
}

DWORD SetMouseLimits(long x1, long y1, long x2, long y2)
{
    MouseLimits.x	= x1 * MOUSESCALEX;
    MouseLimits.y	= y1 * MOUSESCALEY;
    MouseLimits.w	= x2 * MOUSESCALEX;
    MouseLimits.h	= y2 * MOUSESCALEY;

	return ERR_NOERROR;
}

DWORD SetInputMousePosition(long x, long y)
{
	MouseX			= x * MOUSESCALEX;
	MouseY			= y * MOUSESCALEY;

	return ERR_NOERROR;
}

DWORD Convert2SJIS(BYTE *string, BYTE *dest)
{
	int		loop;
	int 	sjis_code;
	int 	ascii_code;
	BYTE 	stmp;
	BYTE 	stmp2;
	BYTE 	*dest2;

	dest2 = dest;

	for (loop = 0; loop < 32; loop++)
	{
		*dest2++ = 0x81;
		*dest2++ = 0x40;
	}

	while (*string != 0)
	{
		stmp2 		= 0;
		ascii_code 	= *string++;

		if ((ascii_code >= 0x20) && (ascii_code <= 0x2f))
		{
			stmp2 = 1;
		}

		else if ((ascii_code >= 0x30) && (ascii_code <= 0x39))
		{
			stmp = 0;
		}

		else if ((ascii_code >= 0x3a) && (ascii_code <= 0x40))
		{
			stmp2 = 11;
		}

		else if ((ascii_code >= 0x41) && (ascii_code <= 0x5a))
		{
			stmp = 1;
		}

		else if ((ascii_code >= 0x5b) && (ascii_code <= 0x60))
		{
			stmp2 = 37;
		}

		else if ((ascii_code >= 0x61) && (ascii_code <= 0x7a))
		{
			stmp = 2;
		}

		else if ((ascii_code >= 0x7b) && (ascii_code <= 0x7e))
		{
			stmp2 = 63;
		}

		else
		{
#ifdef DEBUG
			printf("Bad ASCII code 0x%x to Convert2SJIS.\n", ascii_code);
#endif

			return ERR_BADPARAMS;
		}

		if (stmp2 != 0)
		{
			sjis_code = SJIS[ascii_code - 0x20 - (stmp2 - 1)];
		}

		else
		{
			sjis_code = ASCII[stmp][0] + ascii_code - ASCII[stmp][1];
     	}

		*dest++ = (sjis_code & 0xff00) >> 8;
		*dest++ = (sjis_code & 0xff);
	}

	return ERR_NOERROR;
}
