// Burner Input module
#include "fba.h"

// 1 if current input is on (i.e. emu in foreground)
static int bCinpOkay = 0;

int CinpState(int nCode)
{
	// Return off, if current input is turned off
	if (bCinpOkay == 0) {
		return 0;
	}
	
	// Read from Direct Input
	return DinpState(nCode);
}

// Read the axis of a joystick
int CinpAxis(int i, int nAxis)
{
	// Return off, if current input is turned off
	if (bCinpOkay == 0) {
		return 0;
	}
	
	// Read from Direct Input
	return DinpAxis(i, nAxis);
}

int InputMake(bool bCopy)
{
	bCinpOkay = 0;

	DinpStart();								// Poll joysticks etc

	bCinpOkay = 1;

	struct GameInp* pgi;
	unsigned int i;

	for (i = 0, pgi = GameInp; i < nGameInpCount; i++, pgi++) {
		if (pgi->pVal == NULL) {
			continue;
		}

		switch (pgi->nInput) {
			case 0:									// Undefined
				pgi->nVal = 0;
				break;
			case 1:									// Constant value
				pgi->nVal = pgi->nConst;
				break;
			case 2:	{								// Digital input
				int s = CinpState(pgi->nCode);
				if (pgi->nType == 1) {
					// Set analog controls to full
					if (s) {
						pgi->nVal = 0xFF;
					} else {
						pgi->nVal = 0x01;
					}
				} else {
					// Binary controls
					if (s) {
						pgi->nVal = 1;
					} else {
						pgi->nVal = 0;
					}
				}

				break;
			}
			case 3:	{								// Joystick axis
				int nJoy = CinpAxis(pgi->nJoy, pgi->nAxis);
				nJoy >>= 9;
				nJoy += 0x80;

				// Clip axis to 8 bits
				if (nJoy < 0x01) {
					nJoy = 0x01;
				}
				if (nJoy > 0xFF) {
					nJoy = 0xFF;
				}
				pgi->nVal = (unsigned char)nJoy;

				break;
			}
			case 4:	{								// Joystick axis Lo
				int nJoy = CinpAxis(pgi->nJoy, pgi->nAxis);
				if (nJoy < 127) {
					nJoy = -nJoy;
					nJoy >>= 8;

					if (nJoy < 0x00) {
						nJoy = 0x00;
					}
					if (nJoy > 0xFF) {
						nJoy = 0xFF;
					}

					pgi->nVal = (unsigned char)nJoy;
				} else {
					pgi->nVal = 0x00;
				}

				break;
			}
			case 5:	{								// Joystick axis Hi
				int nJoy = CinpAxis(pgi->nJoy, pgi->nAxis);
				if (nJoy > 127) {
					nJoy >>= 8;

					if (nJoy < 0x00) {
						nJoy = 0x00;
					}
					if (nJoy > 0xFF) {
						nJoy = 0xFF;
					}

					pgi->nVal = (unsigned char)nJoy;
				} else {
					pgi->nVal = 0x00;
				}

				break;
			}
			case 6:									// Keyboard slider
			case 7:									// Joystick slider
				pgi->nVal = (unsigned char)(pgi->nSliderValue >> 8);
				break;
		}

		if (pgi->pVal && bCopy) {
			*(pgi->pVal) = pgi->nVal;
		}
	}

	return 0;
}

// Do one frames worth of keyboard input sliders
int InputTick()
{
	unsigned int i;
	struct GameInp *pgi;

	for (i = 0, pgi = GameInp; i < nGameInpCount; i++, pgi++) {
		int nAdd = 0;
		if (pgi->nInput != 6 && pgi->nInput != 7) {					// not a slider
			continue;
		}

		if (pgi->nInput == 6) {
			// Get states of the two keys
			if (CinpState(pgi->nSlider[0]))	{
				nAdd -= 0x100;
			}
			if (CinpState(pgi->nSlider[1]))	{
				nAdd += 0x100;
			}
		}

		if (pgi->nInput == 7) {
			// Get state of the axis
			nAdd = CinpAxis(pgi->nJoy, pgi->nAxis);
			nAdd /= 0x100;
		}
		
		// nAdd is now -0x100 to +0x100

		// Change to slider speed
		nAdd *= pgi->nSliderSpeed;
		nAdd /= 0x100;

		if (pgi->nSliderCenter) {									// Attact to center
			int v = pgi->nSliderValue - 0x8000;
			v *= (pgi->nSliderCenter - 1);
			v /= pgi->nSliderCenter;
			v += 0x8000;
			pgi->nSliderValue = v;
		}

		pgi->nSliderValue += nAdd;
		// Limit slider
		if (pgi->nSliderValue < 0x0100) {
			pgi->nSliderValue = 0x0100;
		}
		if (pgi->nSliderValue > 0xFF00) {
			pgi->nSliderValue = 0xFF00;
		}
	}
	return 0;
}

int InputInit()
{
	return 0;
}

int InputExit()
{
	return 0;
}
