/******************************************************************************
    Joy.c : Definition of structures and Macros
    PC Version
    Author : M. TRABUCATO
    Last update : 28.04.98
******************************************************************************/
 
/**************************************************************
   Initialization of the Game port.
**************************************************************/
short INO_fn_wInitGamePort(short wHistorySize)
{
    short wNbJoystick;
 
    if ( JoyLib_tdstGp.m_wGameportOk == 1 )
        return (0);
 
    wNbJoystick = fn_wJoyGetMaxJoystickCount();
    if ( wNbJoystick == 0 )
    {
        /* There is no gameport */
        ulJoystickErrorCode = C_ErrNoJoystickDriver;
        return (C_wJoyError);
    }
 
    memset(&JoyLib_tdstGp,0,sizeof(tdstGamePort));
    memset(JoyLib_tdstJC,0,sizeof(tdstJoystickCaps*)*16);
    memset(JoyLib_tdstJS,0,sizeof(tdstJoystickStatus*)*16);
 
    JoyLib_tdstGp.m_wHistorySize = wHistorySize;
    JoyLib_tdstGp.m_wNbMaxiJoystick = wNbJoystick;
 
    JoyLib_tdstGp.m_wNbJoystick = 0;
    JoyLib_tdstGp.m_wGameportOk = 1;
    JoyLib_tdstGp.m_uwActiveFlag = 0;
 
    /* Demo mode initialization: mode normal and 0 record frame */
    JoyLib_pstDemoRecordBuffer = NULL;
    JoyLib_wMode = C_wJoyNormalMode;
    DemoRecordJoystick = C_wJoystick1;
 
    return(0);
}
 
/*****************************************************************
  Joystick query function
*****************************************************************/
 
/******************************************************************
  short  fn_wJoyReadJoystick(): read all connected joystick.
******************************************************************/
short INO_fn_wReadJoystick(short wReadMode)
{
    u_short     i,j;
    short       wResult;
 
    JoyLib_tdstGp.m_ulTimeCount++;
 
    /* Check if the gameport is Ok */
    INO_fn_wUpdateGamePort();
 
    if ( JoyLib_tdstGp.m_wGameportOk == 0 )
    {
        ulJoystickErrorCode = C_ErrDriverNotInitialized;
        return (C_wJoyError);
    }
 
    for ( i = 0 ; i < JoyLib_tdstGp.m_wNbMaxiJoystick ; i++)
    {
        if ( (JoyLib_tdstGp.m_uwActiveFlag & (1 << i)) != 0 )
        {
            /* If the joystick isn't connected and the function mode is C_wJoyReadConnected */
            /* skip this joystick */
            if ( (wReadMode == C_wJoyReadConnected) && (JoyLib_tdstJC[i]->m_uwType == C_wJoyNone) )
                break;
 
            wResult = fn_wJoyGetJoystickState(i, JoyLib_tdstJS[i], JoyLib_tdstJC[i] );
            if ( wResult == C_wJoyError )
                JoyLib_tdstJC[i]->m_uwType = C_wJoyNone;
 
            /* If we are currently in play demo mode */
            /* Any button press stop the demo playing mode */
            if ( JoyLib_wMode == C_wJoyDemoPlayingMode )
            {
                if ( (JoyLib_tdstJS[i]->m_ulButton != 0) || (JoyLib_ulDemoRecordCurrent >= JoyLib_ulDemoRecordCount) )
                    INO_fn_wStopJoystickDemo();
                else
                {
                    if ( i == DemoRecordJoystick )
                    {
                        tdstJoystickAxisValues* p_stTmp ,* p_stTmp2;
                        JoyLib_tdstJS[i]->m_ulButton     = JoyLib_pstDemoRecordBuffer[JoyLib_ulDemoRecordCurrent].m_ulButton;
                        JoyLib_tdstJS[i]->m_ulDirection  = JoyLib_pstDemoRecordBuffer[JoyLib_ulDemoRecordCurrent].m_ulDirection;
                        p_stTmp = &(JoyLib_tdstJS[i]->m_stAxisValues);
                        p_stTmp2 = &(JoyLib_pstDemoRecordBuffer[JoyLib_ulDemoRecordCurrent].m_stAxisValues);
                        M_JoyCopyAxisValues(p_stTmp, p_stTmp2);
                        /*
                        JoyLib_tdstJS[i]->m_stAxisValues.m_uwXValue = JoyLib_pstDemoRecordBuffer[JoyLib_ulDemoRecordCurrent].m_ulXValue;
                        JoyLib_tdstJS[i]->m_stAxisValues.m_uwYValue = JoyLib_pstDemoRecordBuffer[JoyLib_ulDemoRecordCurrent].m_ulYValue;
                        JoyLib_tdstJS[i]->m_stAxisValues.m_uwZValue = JoyLib_pstDemoRecordBuffer[JoyLib_ulDemoRecordCurrent].m_ulZValue;
                        JoyLib_tdstJS[i]->m_stAxisValues.m_uwRValue = JoyLib_pstDemoRecordBuffer[JoyLib_ulDemoRecordCurrent].m_ulRValue;
                        JoyLib_tdstJS[i]->m_stAxisValues.m_uwUValue = JoyLib_pstDemoRecordBuffer[JoyLib_ulDemoRecordCurrent].m_ulUValue;
                        JoyLib_tdstJS[i]->m_stAxisValues.m_uwVValue = JoyLib_pstDemoRecordBuffer[JoyLib_ulDemoRecordCurrent].m_ulVValue;
                        */
                        JoyLib_ulDemoRecordCurrent++;
                    }
                }
            }
 
            /* In normal mode or record mode, analyse joystick*/
            /* Check the activate directions */
            else if ( wResult != C_wJoyError )
                fn_vJoyUpdateDirection(i, JoyLib_tdstJS[i], JoyLib_tdstJC[i] );
 
            /* If we are currently in Record demo mode */
            if ( JoyLib_wMode == C_wJoyDemoRecordingMode )
            {
                if ( ((JoyLib_tdstJS[i]->m_ulExitRecordingModeButton & JoyLib_tdstJS[i]->m_ulButton) != 0)
                    || (JoyLib_ulDemoRecordCount >= JoyLib_ulDemoMaxStep) )
                    INO_fn_wStopRecordingJoystick();
                else
                {
                    if ( i == DemoRecordJoystick )
                    {
                        JoyLib_pstDemoRecordBuffer[JoyLib_ulDemoRecordCount].m_ulButton = JoyLib_tdstJS[i]->m_ulButton;
                        JoyLib_pstDemoRecordBuffer[JoyLib_ulDemoRecordCount].m_ulDirection = JoyLib_tdstJS[i]->m_ulDirection;
                        M_JoyCopyAxisValues(
                                            &(JoyLib_pstDemoRecordBuffer[JoyLib_ulDemoRecordCount].m_stAxisValues),
                                            &(JoyLib_tdstJS[i]->m_stAxisValues)
                                           );
                        /*
                        JoyLib_pstDemoRecordBuffer[JoyLib_ulDemoRecordCount].m_ulXValue = JoyLib_tdstJS[i]->m_stAxisValues.m_uwXValue;
                        JoyLib_pstDemoRecordBuffer[JoyLib_ulDemoRecordCount].m_ulYValue = JoyLib_tdstJS[i]->m_stAxisValues.m_uwYValue;
                        JoyLib_pstDemoRecordBuffer[JoyLib_ulDemoRecordCount].m_ulZValue = JoyLib_tdstJS[i]->m_stAxisValues.m_uwZValue;
                        JoyLib_pstDemoRecordBuffer[JoyLib_ulDemoRecordCount].m_ulRValue = JoyLib_tdstJS[i]->m_stAxisValues.m_uwRValue;
                        JoyLib_pstDemoRecordBuffer[JoyLib_ulDemoRecordCount].m_ulUValue = JoyLib_tdstJS[i]->m_stAxisValues.m_uwUValue;
                        JoyLib_pstDemoRecordBuffer[JoyLib_ulDemoRecordCount].m_ulVValue = JoyLib_tdstJS[i]->m_stAxisValues.m_uwVValue;
                        */
                        JoyLib_ulDemoRecordCount++;
                    }
                }
            }
 
            /* Update the historic */
            if ( wResult != C_wJoyError )
            {
                if ( JoyLib_tdstJS[i]->m_uwValidRecordNumber == 0 )
                {
                    JoyLib_tdstH[i][0].m_ulDirection = JoyLib_tdstJS[i]->m_ulDirection;
                    JoyLib_tdstH[i][0].m_ulButton = JoyLib_tdstJS[i]->m_ulButton;
                    M_JoyCopyAxisValues(
                                        &(JoyLib_tdstH[i][0].m_stAxisValues),
                                        &(JoyLib_tdstJS[i]->m_stAxisValues)
                                       );
                    /*
                    JoyLib_tdstH[i][0].m_ulXValue = JoyLib_tdstJS[i]->m_stAxisValues.m_uwXValue;
                    JoyLib_tdstH[i][0].m_ulYValue = JoyLib_tdstJS[i]->m_stAxisValues.m_uwYValue;
                    JoyLib_tdstH[i][0].m_ulZValue = JoyLib_tdstJS[i]->m_stAxisValues.m_uwZValue;
                    JoyLib_tdstH[i][0].m_ulRValue = JoyLib_tdstJS[i]->m_stAxisValues.m_uwRValue;
                    JoyLib_tdstH[i][0].m_ulUValue = JoyLib_tdstJS[i]->m_stAxisValues.m_uwUValue;
                    JoyLib_tdstH[i][0].m_ulVValue = JoyLib_tdstJS[i]->m_stAxisValues.m_uwVValue;
                    */
                    /*JoyLib_tdstH[i][0].m_ulTimeCount = JoyLib_tdstGp.m_ulTimeCount;*/
                    JoyLib_tdstJS[i]->m_ulLastTimeCount = JoyLib_tdstGp.m_ulTimeCount;
                    JoyLib_tdstJS[i]->m_uwValidRecordNumber = 1;
                }
                else
                {
                    j = JoyLib_tdstJS[i]->m_uwHistoryHead;
                    /*    if ( (JoyLib_tdstH[i][j].m_ulDirection != JoyLib_tdstJS[i]->m_ulDirection) ||
                    (JoyLib_tdstH[i][j].m_ulButton    != JoyLib_tdstJS[i]->m_ulButton) )
                    {
                    */
                    j++;
                    if ( j > JoyLib_tdstGp.m_wHistorySize-1 ) j = 0;
                    JoyLib_tdstH[i][j].m_ulDirection = JoyLib_tdstJS[i]->m_ulDirection;
                    JoyLib_tdstH[i][j].m_ulButton = JoyLib_tdstJS[i]->m_ulButton;
                    M_JoyCopyAxisValues(
                                        &(JoyLib_tdstH[i][j].m_stAxisValues),
                                        &(JoyLib_tdstJS[i]->m_stAxisValues)
                                       );
                    /*
                    JoyLib_tdstH[i][j].m_ulXValue = JoyLib_tdstJS[i]->m_stAxisValues.m_uwXValue;
                    JoyLib_tdstH[i][j].m_ulYValue = JoyLib_tdstJS[i]->m_stAxisValues.m_uwYValue;
                    JoyLib_tdstH[i][j].m_ulZValue = JoyLib_tdstJS[i]->m_stAxisValues.m_uwZValue;
                    JoyLib_tdstH[i][j].m_ulRValue = JoyLib_tdstJS[i]->m_stAxisValues.m_uwRValue;
                    JoyLib_tdstH[i][j].m_ulUValue = JoyLib_tdstJS[i]->m_stAxisValues.m_uwUValue;
                    JoyLib_tdstH[i][j].m_ulVValue = JoyLib_tdstJS[i]->m_stAxisValues.m_uwVValue;
                    */
                    /*JoyLib_tdstH[i][j].m_ulTimeCount = JoyLib_tdstGp.m_ulTimeCount;*/
                    JoyLib_tdstJS[i]->m_ulLastTimeCount = JoyLib_tdstGp.m_ulTimeCount;
                    JoyLib_tdstJS[i]->m_uwHistoryHead = j;
                    if ( JoyLib_tdstJS[i]->m_uwValidRecordNumber != JoyLib_tdstGp.m_wHistorySize )
                        JoyLib_tdstJS[i]->m_uwValidRecordNumber++;
                }
            }
        }
    }
    return (0);
}
 
 
/**************************************************************
**************************************************************/
 
/**************************************************************
  Return the current position of the joystick along the specified axis
  The return value is a double contained between -1.0 to 1.0.
**************************************************************/
short INO_fn_wGetJoystickCurrentPosition(short wJoystickNum, short wAxis, double *pdfPosition)
{
    double  dfPosition, dfMiddle, dfRange;
 
    if ( JoyLib_tdstGp.m_wGameportOk == 0 )
    {
        ulJoystickErrorCode = C_ErrDriverNotInitialized;
        return (C_wJoyError);
    }
    if ( (wJoystickNum < C_wJoystick1) || (wJoystickNum > C_wJoystick16) )
    {
        ulJoystickErrorCode = C_ErrBadJoystick;
        return (C_wJoyError);
    }
    if ( (JoyLib_tdstGp.m_uwActiveFlag & (1 << wJoystickNum)) == 0 )
    {
        ulJoystickErrorCode = C_ErrJoystickNotActive;
        return (C_wJoyError);
    }
 
    switch (wAxis)
    {
    case C_ulJoyX:
        dfPosition = (double)M_JoyX(JoyLib_tdstJS[wJoystickNum]);
        dfRange = (double)(M_JoyXMax(JoyLib_tdstJC[wJoystickNum]) - M_JoyXMin(JoyLib_tdstJC[wJoystickNum])) / 2.0;
        dfMiddle = (double)(M_JoyXMax(JoyLib_tdstJC[wJoystickNum]) + M_JoyXMin(JoyLib_tdstJC[wJoystickNum])) / 2.0;
        break;
    case C_ulJoyY:
        dfPosition = (double)M_JoyY(JoyLib_tdstJS[wJoystickNum]);
        dfRange = (double)(M_JoyYMax(JoyLib_tdstJC[wJoystickNum]) - M_JoyYMin(JoyLib_tdstJC[wJoystickNum])) / 2.0;
        dfMiddle = (double)(M_JoyYMax(JoyLib_tdstJC[wJoystickNum]) + M_JoyYMin(JoyLib_tdstJC[wJoystickNum])) / 2.0;
        break;
    case C_ulJoyZ:
        dfPosition = (double)M_JoyZ(JoyLib_tdstJS[wJoystickNum]);
        dfRange = (double)(M_JoyZMax(JoyLib_tdstJC[wJoystickNum]) - M_JoyZMin(JoyLib_tdstJC[wJoystickNum])) / 2.0;
        dfMiddle = (double)(M_JoyZMax(JoyLib_tdstJC[wJoystickNum]) + M_JoyZMin(JoyLib_tdstJC[wJoystickNum])) / 2.0;
        break;
    case C_ulJoyR:
        dfPosition = (double)M_JoyR(JoyLib_tdstJS[wJoystickNum]);
        dfRange = (double)(M_JoyRMax(JoyLib_tdstJC[wJoystickNum]) - M_JoyRMin(JoyLib_tdstJC[wJoystickNum])) / 2.0;
        dfMiddle = (double)(M_JoyRMax(JoyLib_tdstJC[wJoystickNum]) + M_JoyRMin(JoyLib_tdstJC[wJoystickNum])) / 2.0;
        break;
    case C_ulJoyU:
        dfPosition = (double)M_JoyU(JoyLib_tdstJS[wJoystickNum]);
        dfRange = (double)(M_JoyUMax(JoyLib_tdstJC[wJoystickNum]) - M_JoyUMin(JoyLib_tdstJC[wJoystickNum])) / 2.0;
        dfMiddle = (double)(M_JoyUMax(JoyLib_tdstJC[wJoystickNum]) + M_JoyUMin(JoyLib_tdstJC[wJoystickNum])) / 2.0;
        break;
    case C_ulJoyV:
        dfPosition = (double)M_JoyV(JoyLib_tdstJS[wJoystickNum]);
        dfRange = (double)(M_JoyVMax(JoyLib_tdstJC[wJoystickNum]) - M_JoyVMin(JoyLib_tdstJC[wJoystickNum])) / 2.0;
        dfMiddle = (double)(M_JoyVMax(JoyLib_tdstJC[wJoystickNum]) + M_JoyVMin(JoyLib_tdstJC[wJoystickNum])) / 2.0;
        break;
    default:
        return (C_wJoyError);
    }
 
    dfPosition -= dfMiddle;
    *pdfPosition = dfPosition / dfRange;
 
    return (0);
}
 
/**************************************************************
  Return the current position of the joystick along the specified axis
  The return value is a double contained between -1.0 to 1.0.
**************************************************************/
#ifndef _FIRE_DEADCODE_U64_
short INO_fn_wGetJoystickPreviousPosition(short wJoystickNum, short wAxis, short wHistoryNum, double *pdfPosition)
{
    long   iIndex;
    double dfPosition,dfRange,dfMiddle;
 
    if ( JoyLib_tdstGp.m_wGameportOk == 0 )
    {
        ulJoystickErrorCode = C_ErrDriverNotInitialized;
        return (C_wJoyError);
    }
    if ( (wJoystickNum < C_wJoystick1) || (wJoystickNum > C_wJoystick16) )
    {
        ulJoystickErrorCode = C_ErrBadJoystick;
        return (C_wJoyError);
    }
    if ( (JoyLib_tdstGp.m_uwActiveFlag & (1 << wJoystickNum)) == 0 )
    {
        ulJoystickErrorCode = C_ErrJoystickNotActive;
        return (C_wJoyError);
    }
    if ( wHistoryNum > JoyLib_tdstJS[wJoystickNum]->m_uwValidRecordNumber )
    {
        ulJoystickErrorCode = C_ErrJoyHistoricOverflow;
        return (C_wJoyError);
    }
 
    iIndex = JoyLib_tdstJS[wJoystickNum]->m_uwHistoryHead - wHistoryNum;
    switch (wAxis)
    {
    case C_ulJoyX:
        dfPosition = (double)M_JoyX(&(JoyLib_tdstH[wJoystickNum][iIndex]));
        dfRange = (double)(M_JoyXMax(JoyLib_tdstJC[wJoystickNum]) - M_JoyXMin(JoyLib_tdstJC[wJoystickNum])) / 2.0;
        dfMiddle = (double)(M_JoyXMax(JoyLib_tdstJC[wJoystickNum]) + M_JoyXMin(JoyLib_tdstJC[wJoystickNum])) / 2.0;
        break;
    case C_ulJoyY:
        dfPosition = (double)M_JoyY(&(JoyLib_tdstH[wJoystickNum][iIndex]));
        dfRange = (double)(M_JoyYMax(JoyLib_tdstJC[wJoystickNum]) - M_JoyYMin(JoyLib_tdstJC[wJoystickNum])) / 2.0;
        dfMiddle = (double)(M_JoyYMax(JoyLib_tdstJC[wJoystickNum]) + M_JoyYMin(JoyLib_tdstJC[wJoystickNum])) / 2.0;
        break;
    case C_ulJoyZ:
        dfPosition = (long)M_JoyZ(&(JoyLib_tdstH[wJoystickNum][iIndex]));
        dfRange = (double)(M_JoyZMax(JoyLib_tdstJC[wJoystickNum]) - M_JoyZMin(JoyLib_tdstJC[wJoystickNum])) / 2.0;
        dfMiddle = (double)(M_JoyZMax(JoyLib_tdstJC[wJoystickNum]) + M_JoyZMin(JoyLib_tdstJC[wJoystickNum])) / 2.0;
        break;
    case C_ulJoyR:
        dfPosition = (double)M_JoyR(&(JoyLib_tdstH[wJoystickNum][iIndex]));
        dfRange = (double)(M_JoyRMax(JoyLib_tdstJC[wJoystickNum]) - M_JoyRMin(JoyLib_tdstJC[wJoystickNum])) / 2.0;
        dfMiddle = (double)(M_JoyRMax(JoyLib_tdstJC[wJoystickNum]) + M_JoyRMin(JoyLib_tdstJC[wJoystickNum])) / 2.0;
        break;
    case C_ulJoyU:
        dfPosition = (double)M_JoyU(&(JoyLib_tdstH[wJoystickNum][iIndex]));
        dfRange = (double)(M_JoyUMax(JoyLib_tdstJC[wJoystickNum]) - M_JoyUMin(JoyLib_tdstJC[wJoystickNum])) / 2.0;
        dfMiddle = (double)(M_JoyUMax(JoyLib_tdstJC[wJoystickNum]) + M_JoyUMin(JoyLib_tdstJC[wJoystickNum])) / 2.0;
        break;
    case C_ulJoyV:
        dfPosition = (double)M_JoyV(&(JoyLib_tdstH[wJoystickNum][iIndex]));
        dfRange = (double)(M_JoyVMax(JoyLib_tdstJC[wJoystickNum]) - M_JoyVMin(JoyLib_tdstJC[wJoystickNum])) / 2.0;
        dfMiddle = (double)(M_JoyVMax(JoyLib_tdstJC[wJoystickNum]) + M_JoyVMin(JoyLib_tdstJC[wJoystickNum])) / 2.0;
        break;
    default:
        return (C_wJoyError);
    }
 
    dfPosition -= dfMiddle;
    *pdfPosition = dfPosition / dfRange;
 
    return (0);
}
#endif /* _FIRE_DEADCODE_U64_ */
 
