/***************************************************************************/
/*  Description: CPA Joystick.lib. Implementation of the privates          */
/*                                 for the Windows version                 */
/*  Author: F. Jentey                                                      */
/*  Last Update: 05/03/97                                                  */
/***************************************************************************/
 
 
#include <stdio.h>
 
#include "../Specif/JoyWin.h"
#include "INO/Joystick.h"
 
 
#define  SEUIL    50
 
 
 
 
/*
    fn_wJoyGetMaxJoystickCount: return the number of joystick gameport can support
                                return 0 if there is no gameport.
*/
short fn_wJoyGetMaxJoystickCount()
{
    return (joyGetNumDevs());
}
 
 
/*
    Fill the p_stJoyCaps with the capabilities of the specified joystick
    Return an error if unable to get these information.
    It usually happens when the joystick isn't configurated in the control panel,
    but could also appear with some joystcik if the joystick isn't connected.
*/
short fn_wJoyGetJoystickCaps( short wJoystickNum, tdstJoystickCaps* p_stJoyCaps )
{
    MMRESULT    err;
    JOYCAPS     JoyCaps;
 
    err = joyGetDevCaps(wJoystickNum, &JoyCaps, sizeof(JOYCAPS));
    switch ( err )
    {
        case JOYERR_NOERROR:
             break;
        case MMSYSERR_INVALPARAM:
        case MMSYSERR_NODRIVER:
        default:
             return (C_wJoyError);
             break;
    }
 
 
    p_stJoyCaps->m_uwMid  = JoyCaps.wMid;
    p_stJoyCaps->m_uwPid  = JoyCaps.wPid;
    
 
	/* CHRISTOPHE PAD NT 4 RAYMAN II MODIFICATIONS {*/
	#ifdef _PAD_NT
		p_stJoyCaps->m_uwNbButton = 6;
	#else
		p_stJoyCaps->m_uwNbButton = JoyCaps.wNumButtons;
	#endif _PAD_NT
	/* } END CHRISTOPHE PAD NT 4 RAYMAN II MODIFICATIONS*/
 
    p_stJoyCaps->m_stAxisCaps.m_uwXmin  = JoyCaps.wXmin;
    p_stJoyCaps->m_stAxisCaps.m_uwXmax  = JoyCaps.wXmax;
    p_stJoyCaps->m_stAxisCaps.m_uwXdown = (JoyCaps.wXmin + JoyCaps.wXmax)/2
                                        - ((JoyCaps.wXmax - JoyCaps.wXmin)*SEUIL)/200;
    p_stJoyCaps->m_stAxisCaps.m_uwXup   = (JoyCaps.wXmin + JoyCaps.wXmax)/2
                                        + ((JoyCaps.wXmax - JoyCaps.wXmin)*SEUIL)/200;
    p_stJoyCaps->m_stAxisCaps.m_uwYmin  = JoyCaps.wYmin;
    p_stJoyCaps->m_stAxisCaps.m_uwYmax  = JoyCaps.wYmax;
    p_stJoyCaps->m_stAxisCaps.m_uwYdown = (JoyCaps.wYmin + JoyCaps.wYmax)/2
                                        + ((JoyCaps.wYmax - JoyCaps.wYmin)*SEUIL)/200;
    p_stJoyCaps->m_stAxisCaps.m_uwYup   = (JoyCaps.wYmin + JoyCaps.wYmax)/2
                                        - ((JoyCaps.wYmax - JoyCaps.wYmin)*SEUIL)/200;
    p_stJoyCaps->m_uwNbAxe = JoyCaps.wNumAxes;
    
    if ( JoyCaps.wNumAxes > 2 )
    {
        if ( JoyCaps.wCaps & JOYCAPS_HASZ != 0)
        {
            p_stJoyCaps->m_uwNbAxe++;
            p_stJoyCaps->m_ulCapsFlag |= C_ulJoyZ;
            p_stJoyCaps->m_stAxisCaps.m_uwZmin = JoyCaps.wZmin;
            p_stJoyCaps->m_stAxisCaps.m_uwZmax = JoyCaps.wZmax;
            p_stJoyCaps->m_stAxisCaps.m_uwZdown = (JoyCaps.wZmin + JoyCaps.wZmax)/2
                                                - ((JoyCaps.wZmax - JoyCaps.wZmin)*SEUIL)/200;
            p_stJoyCaps->m_stAxisCaps.m_uwZup   = (JoyCaps.wZmin + JoyCaps.wZmax)/2
                                                + ((JoyCaps.wZmax - JoyCaps.wZmin)*SEUIL)/200;
        }   
 
 
		
		/* CHRISTOPHE MODIFICATIONS 02/05/98 { */
		#ifdef _PAD_NT
			/* TEST THE RUDDER AXIS*/
			if ( JoyCaps.wCaps & JOYCAPS_HASR != 0)
			{
				p_stJoyCaps->m_uwNbAxe++;
				p_stJoyCaps->m_ulCapsFlag |= C_ulJoyR;
				p_stJoyCaps->m_stAxisCaps.m_uwRmin = JoyCaps.wRmin;
				p_stJoyCaps->m_stAxisCaps.m_uwRmax = JoyCaps.wRmax;
				p_stJoyCaps->m_stAxisCaps.m_uwRdown = (JoyCaps.wRmin + JoyCaps.wRmax)/2
													- ((JoyCaps.wRmax - JoyCaps.wRmin)*SEUIL)/200;
				p_stJoyCaps->m_stAxisCaps.m_uwRup   = (JoyCaps.wRmin + JoyCaps.wRmax)/2
													+ ((JoyCaps.wRmax - JoyCaps.wRmin)*SEUIL)/200;
			}   
		#endif _PAD_NT        
		/* } END CHRISTOPHE MODIFICATIONS 02/05/98 */
 
        /* TO DO : test the other axis */
    }
 
    /* Useless
    joySetThreshold(wJoystickNum, 4000); 
    */
 
    return (0);
}
 
 
/*
    Fill the p_stJoyState with the state of the specified joystick
    Return an error if unable to get these information.
    It usually happens when the joystick isn't configurated in the control panel,
    but could also appear with some joystick if the joystick isn't connected.
*/
short fn_wJoyGetJoystickState(
                              short wJoystickNum,
                              tdstJoystickStatus* p_stJoyState,
                              tdstJoystickCaps* p_stJoyCaps
                             )
{
    MMRESULT    err;
    JOYINFOEX   jie;
 
    memset(&jie,0,sizeof(jie));
    jie.dwSize = sizeof(jie);
 
	/* CHRISTOPHE MODIFICATIONS PAD NT 4 RAYMAN II }*/
	#ifdef _PAD_NT
		jie.dwFlags = JOY_RETURNX | JOY_RETURNY | JOY_RETURNZ | JOY_RETURNR |JOY_RETURNBUTTONS; 
	#else
	    jie.dwFlags = JOY_RETURNX | JOY_RETURNY | JOY_RETURNBUTTONS; 
	#endif _PAD_NT
	/* { END CHRISTOPHE MODIFICATION PAD NT 4 RAYMAN II*/
 
 
    if ( (p_stJoyCaps->m_ulCapsFlag & C_ulJoyZ) != 0 )
        jie.dwFlags |= JOY_RETURNZ;
    if ( (p_stJoyCaps->m_ulCapsFlag & C_ulJoyR) != 0 )
        jie.dwFlags |= JOY_RETURNR;
    if ( (p_stJoyCaps->m_ulCapsFlag & C_ulJoyU) != 0 )
        jie.dwFlags |= JOY_RETURNU;
    if ( (p_stJoyCaps->m_ulCapsFlag & C_ulJoyV) != 0 )
        jie.dwFlags |= JOY_RETURNV;
    /* TO DO: add support of the other capabilities (pov) */
 
    /* Read joystich state */
    err = joyGetPosEx(wJoystickNum, &jie);
 
    /* Check if plugged */
    switch ( err )
    {
    case JOYERR_NOERROR:
        break;
    case JOYERR_UNPLUGGED:
        /* The specified joystick is not connected to the computer. */
    case MMSYSERR_BADDEVICEID:
        /* The specified joystick identifier is invalid. */
    case MMSYSERR_INVALPARAM:
        /* An invalid parameter was passed. */
    case MMSYSERR_NODRIVER:
        /* The joystick driver is not present. */
    default:
        return (C_wJoyError);
        break;
    }
 
 
    /* Copy button info */
    p_stJoyState->m_ulButton = jie.dwButtons;
 
    /* Read X and Y informations */
    p_stJoyState->m_stAxisValues.m_uwXValue = (u_short)jie.dwXpos;
    p_stJoyState->m_stAxisValues.m_uwYValue = (u_short)jie.dwYpos;
 
	/* CHRISTOPHE PAD NT MODIFICATIONS 4 RAYMAN II {*/
    /* Read Z information */
/*    if ( p_stJoyCaps->m_ulCapsFlag & C_ulJoyZ != 0 )*/
/*        p_stJoyState->m_stAxisValues.m_uwZValue = (u_short)jie.dwZpos;*/
 
	#ifdef _PAD_NT
		if ( (p_stJoyCaps->m_ulCapsFlag & C_ulJoyZ) != 0 )
		{
			p_stJoyState->m_stAxisValues.m_uwZValue = (u_short)jie.dwZpos;
 
			if( p_stJoyState->m_stAxisValues.m_uwZValue < (0xffff/2) )
			{
				p_stJoyState->m_ulButton |= 16;
			}
		}
	#endif _PAD_NT
 
    /* Read R information */
/*    if ( p_stJoyCaps->m_ulCapsFlag & C_ulJoyR != 0 )*/
/*        p_stJoyState->m_stAxisValues.m_uwRValue = (u_short)jie.dwRpos;*/
 
	#ifdef _PAD_NT
		if ( (p_stJoyCaps->m_ulCapsFlag & C_ulJoyR) != 0 )
		{
			p_stJoyState->m_stAxisValues.m_uwRValue = (u_short)jie.dwRpos;
 
			if( p_stJoyState->m_stAxisValues.m_uwRValue < (0xffff/2) )
			{
				p_stJoyState->m_ulButton |= 32;				 
			}
		}
	#endif _PAD_NT
 
  
    /* Read U information */
/*    if ( p_stJoyCaps->m_ulCapsFlag & C_ulJoyU != 0 )*/
/*        p_stJoyState->m_stAxisValues.m_uwUValue = (u_short)jie.dwUpos;*/
 
    /* Read U information */
    if ( (p_stJoyCaps->m_ulCapsFlag & C_ulJoyU) != 0 )
        p_stJoyState->m_stAxisValues.m_uwUValue = (u_short)jie.dwUpos;
    
    /* Read V information */
    if ( (p_stJoyCaps->m_ulCapsFlag & C_ulJoyV) != 0 )
        p_stJoyState->m_stAxisValues.m_uwVValue = (u_short)jie.dwVpos;
 
    /* Read V information */
/*    if ( p_stJoyCaps->m_ulCapsFlag & C_ulJoyV != 0 )*/
/*        p_stJoyState->m_stAxisValues.m_uwVValue = (u_short)jie.dwVpos;*/
    
    /* Copy button info */
/*    p_stJoyState->m_ulButton = jie.dwButtons;*/
 
	/* } END CHRISTOPHE MODIFICATIONS PAD NT 4 RAYMAN II*/
    return (0);
}
 
 
void fn_vJoyUpdateDirection(
                            short wJoystickNum,
                            tdstJoystickStatus* p_stJoyState,
                            tdstJoystickCaps* p_stJoyCaps
                           )
{
    p_stJoyState->m_ulDirection = 0;
    
    /* Update X direction */
    if ( p_stJoyState->m_stAxisValues.m_uwXValue < p_stJoyCaps->m_stAxisCaps.m_uwXdown )
        p_stJoyState->m_ulDirection |= C_ulJoyLeft;
    else
        if ( p_stJoyState->m_stAxisValues.m_uwXValue > p_stJoyCaps->m_stAxisCaps.m_uwXup )
            p_stJoyState->m_ulDirection |= C_ulJoyRight;
    
    /* Update Y direction */
    if ( p_stJoyState->m_stAxisValues.m_uwYValue > p_stJoyCaps->m_stAxisCaps.m_uwYdown )
        p_stJoyState->m_ulDirection |= C_ulJoyDown;
    else
        if ( p_stJoyState->m_stAxisValues.m_uwYValue < p_stJoyCaps->m_stAxisCaps.m_uwYup )
            p_stJoyState->m_ulDirection |= C_ulJoyUp;
    
	#ifndef _PAD_NT
		/* Update Z direction */
		if ( (p_stJoyCaps->m_ulCapsFlag & C_ulJoyZ) != 0 )
		{
			if ( p_stJoyState->m_stAxisValues.m_uwZValue < p_stJoyCaps->m_stAxisCaps.m_uwZdown )
				p_stJoyState->m_ulDirection |= C_ulJoyZDown;
			else
				if ( p_stJoyState->m_stAxisValues.m_uwZValue > p_stJoyCaps->m_stAxisCaps.m_uwZup )
					p_stJoyState->m_ulDirection |= C_ulJoyZUp;
		}
	#endif _PAD_NT
 
/*
    if ( p_stJoyCaps->m_ulCapsFlag & C_ulJoyZ != 0 )
    {
        if ( p_stJoyState->m_stAxisValues.m_uwZValue < p_stJoyCaps->m_stAxisCaps.m_uwZdown )
            p_stJoyState->m_ulDirection |= C_ulJoyZDown;
        else
            if ( p_stJoyState->m_stAxisValues.m_uwZValue > p_stJoyCaps->m_stAxisCaps.m_uwZup )
                p_stJoyState->m_ulDirection |= C_ulJoyZUp;
    }
*/
}
 
 
/*
    Return C_wJoyTrue if the specified joystick is conected else C_wJoyFalse
    Return C_wJoyError if an error occured
*/
short fn_wJoyCheckConnection( short wJoystickNum )
{
    MMRESULT    err;
    JOYINFOEX   jie;
 
    memset(&jie,0,sizeof(jie));
    jie.dwSize = sizeof(jie);
    err = joyGetPosEx(wJoystickNum,&jie);
 
    if ( (err != JOYERR_NOERROR) && (err != JOYERR_UNPLUGGED) )
        return (C_wJoyError);
    else
    {
        if ( err != JOYERR_NOERROR )
          return (C_wJoyFalse);
        else
            return (C_wJoyTrue);
    }
}
 
 
/*
    Return the productName in pszName
*/
short fn_wJoyGetOEMProductName( short wJoystickNum, char *pszName )
{
    JOYCAPS JoyCaps;
    TCHAR   szKey[256];
    TCHAR   szValue[256];
    TCHAR   szOEMKey[256];
    HKEY    hKey;
    DWORD   dwcb;
    LONG    lr;
 
 
    joyGetDevCaps(wJoystickNum,&JoyCaps,sizeof(JOYCAPS));
    wJoystickNum++;
 
    sprintf(szKey,"%s\\%s\\%s",REGSTR_PATH_JOYCONFIG,JoyCaps.szRegKey,REGSTR_KEY_JOYCURR);
    lr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPTSTR)&szKey,0,KEY_ALL_ACCESS,&hKey);
    if (lr != ERROR_SUCCESS )
        return (C_wJoyError);
 
    dwcb = sizeof(szOEMKey);
    sprintf(szValue, "Joystick%d%s", wJoystickNum, REGSTR_VAL_JOYOEMNAME);
    lr = RegQueryValueEx(hKey, szValue,0 ,0 ,(LPBYTE) &szOEMKey, (LPDWORD) &dwcb);
    RegCloseKey(hKey);
    if (lr != ERROR_SUCCESS )
    {
        *pszName = 0;
        return (C_wJoyError);
    }
 
    sprintf(szKey,"%s\\%s",REGSTR_PATH_JOYOEM,szOEMKey);
    lr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey,0,KEY_ALL_ACCESS,&hKey);
    if (lr != ERROR_SUCCESS )
        return (C_wJoyError);
 
    dwcb = sizeof(szValue);
    lr = RegQueryValueEx(hKey, REGSTR_VAL_JOYOEMNAME,0 ,0 ,(LPBYTE) pszName, (LPDWORD) &dwcb);
    RegCloseKey(hKey);
    if (lr != ERROR_SUCCESS )
        return (C_wJoyError);
    else
        return (0);
}
