/*****************************************************************************
 *                                                                           *
 * Module : JOYSTICK.C                                                       *
 *                                                                           *
 * Gestion du Joystick 0                                                     *
 *                                                                           *
 *****************************************************************************/


#include  <exec/types.h>         
#include  <dos/dostags.h>
#include  <devices/gameport.h>   
#include  <devices/inputevent.h> 
#include  <proto/exec.h>
#include  <proto/dos.h>

#include  "joystick.h"
#include  "main.h"


#define RIGHTGAMEPORT 1 
#define LEFTGAMEPORT  0 


static ULONG termSig;

static struct Task * parentTask;


static void __asm TermCode( register __d0 ULONG return_code )
{
    Signal( parentTask, 1L << termSig );
}


/*
// Boucle de scanning du joystick.
*/
static void WaitJoy( struct IOStdReq   * JoyIoMsg
                   , struct MsgPort    * JoyMsgPort
                   , struct InputEvent * JoyIEvent
                   )
{
    struct GamePortTrigger gpt;
    int Joy = 0x3F;

    gpt.gpt_Keys = GPTF_DOWNKEYS | GPTF_UPKEYS;
    gpt.gpt_Timeout = 5;       /* Timeout d'1/10 de seconde */
    gpt.gpt_XDelta = 1;
    gpt.gpt_YDelta = 1;
    JoyIoMsg->io_Command = GPD_SETTRIGGER;
    JoyIoMsg->io_Length = sizeof( gpt );
    JoyIoMsg->io_Data = (APTR) &gpt;
    DoIO( ( struct IORequest * )JoyIoMsg );
    if ( ! JoyIoMsg->io_Error );
        {
        JoyIoMsg->io_Command = GPD_READEVENT;  
        JoyIoMsg->io_Length = sizeof( struct InputEvent );
        JoyIoMsg->io_Data = ( APTR )JoyIEvent;
        JoyIoMsg->io_Flags = 0;

        while( finProc != ETAT_FIN )
            {
            SendIO( ( struct IORequest * )JoyIoMsg );
            WaitPort( JoyMsgPort );
            if ( GetMsg( JoyMsgPort ) )
                {
                if ( JoyIEvent->ie_X == 1 )
                    Joy &= 0xF7;
                else
                    Joy |= 0x08;

                if ( JoyIEvent->ie_X == -1 )
                    Joy &= 0xFB;
                else
                    Joy |= 0x04;

                if ( JoyIEvent->ie_Y == 1 )
                    Joy &= 0xFD;
                else
                    Joy |= 0x02;

                if ( JoyIEvent->ie_Y == -1 )
                    Joy &= 0xFE;
                else
                    Joy |= 0x01;

                if ( ( JoyIEvent->ie_Code & 0x7F ) == IECODE_LBUTTON )
                    {
                    if ( ! ( JoyIEvent->ie_Code & IECODE_UP_PREFIX ) )
                        Joy &= 0xEF;
                    else
                        Joy |= 0x10;
                    }

                if ( ( JoyIEvent->ie_Code & 0x7F ) == IECODE_RBUTTON )
                    {
                    if ( ! ( JoyIEvent->ie_Code & IECODE_UP_PREFIX ) )
                        Joy &= 0xDF;
                    else
                        Joy |= 0x20;
                    }

                EtatLigneClav[ 9 ] = ( EtatLigneClav[ 9 ] & 0xC0 ) | Joy;
                }
            }
        }
}


/*
// Ouverture gameport.device, appel de la fonction de
// scanning du joystick
*/
void GestionJoy( void )
{
    struct IOStdReq * JoyIoMsg;    
    struct MsgPort  * JoyMsgPort; 
    struct InputEvent JoyIEvent;
    BYTE type;

    if ( ( JoyMsgPort = CreatePort( 0, 0 ) ) != NULL )
        {
        if ( ( JoyIoMsg = CreateStdIO( JoyMsgPort ) ) != NULL )
            {
            if ( ! OpenDevice( "gameport.device"
                             , RIGHTGAMEPORT
                             , ( struct IORequest * )JoyIoMsg
                             , 0xFFFF 
                             )
               )
                {
                JoyIoMsg->io_Command = GPD_ASKCTYPE;
                JoyIoMsg->io_Length = 1;
                JoyIoMsg->io_Data = ( APTR )&type;  
                DoIO( ( struct IORequest * )JoyIoMsg );  
                if ( type != GPCT_ABSJOYSTICK )
                    {
                    type = GPCT_ABSJOYSTICK;
                    JoyIoMsg->io_Command = GPD_SETCTYPE;
                    JoyIoMsg->io_Length = 1;
                    JoyIoMsg->io_Data = ( APTR )&type;  
                    DoIO( ( struct IORequest * )JoyIoMsg );  
                    if ( ! JoyIoMsg->io_Error );
                        WaitJoy( JoyIoMsg, JoyMsgPort, &JoyIEvent );
                
                    type = GPCT_NOCONTROLLER;
                    JoyIoMsg->io_Command = GPD_SETCTYPE;
                    JoyIoMsg->io_Length = 1;
                    JoyIoMsg->io_Data = ( APTR )&type;  
                    DoIO( ( struct IORequest * )JoyIoMsg );  
                    CloseDevice( ( struct IORequest * )JoyIoMsg );
                    }
                else
                    AfficheErreur( "Le port joystick est déjà utilisé." );
                }
            DeleteStdIO( JoyIoMsg );
            }
        DeletePort( JoyMsgPort );
        }
}    


/*
// Création d'un process avec la fonction GestionJoy()
*/
BOOL StartJoy( struct Task * parent
             , STRPTR name
             , LONG priority
             , ULONG stacksize 
             )
{
    BOOL result = FALSE;

    parentTask = parent;

    if ( ( termSig = AllocSignal( -1 ) ) != -1 )
        {
        if ( CreateNewProcTags( NP_Name,      name
                              , NP_Priority,  priority
                              , NP_StackSize, stacksize
                              , NP_Entry,     GestionJoy
                              , NP_ExitCode,  TermCode
                              , TAG_END 
                              ) != NULL 
           ) 
            result = TRUE;
        else 
            FreeSignal( termSig );
        }
    return( result );
}


/*
// Fonction de terminaison du process "Joystick"
*/
void WaitEndJoy( void )
{
    Wait( 1L << termSig );
    FreeSignal( termSig );
}
