1645 lines
40 KiB
C
1645 lines
40 KiB
C
//****************************************************************************
|
|
//
|
|
// File: joycal.c
|
|
// Content: Joystick calibration dialog
|
|
// History:
|
|
// Date By Reason
|
|
// ==== == ======
|
|
// 11-dec-94 craige split out of joycpl.c; some tweaks
|
|
// 15-dec-94 craige allow N joysticks
|
|
// 17-dec-94 craige new UI as requested by ChrisB
|
|
// 18-dec-94 craige process UV
|
|
// 05-jan-95 craige new centering confirmation messages
|
|
// 04-mar-95 craige bug 10761 - separate strings for pluralization
|
|
// bug 12036 - now works when "Back" clicked off of
|
|
// custom 4-axis with POV hat
|
|
//
|
|
// Copyright (c) Microsoft Corporation 1994-1995
|
|
//
|
|
//****************************************************************************
|
|
|
|
#include "joycpl.h"
|
|
|
|
/*
|
|
* This has the look and feel of a wizard, but isn't This leads to the
|
|
* obvious...
|
|
*
|
|
* Q: Why isn't this a "real" wizard?
|
|
*
|
|
* A: - it doesn't have multiple pages, it has a single page. the user
|
|
* sees different joystick items activate and de-activate on the dialog
|
|
* as he/she calibrates each axis. fussing with multiple sheets for each
|
|
* axis would be confusing and unnecessary.
|
|
*/
|
|
|
|
/*
|
|
* calibration states
|
|
*/
|
|
typedef enum {
|
|
JCS_INIT=-1,
|
|
JCS_XY_CENTER1,
|
|
JCS_XY_MOVE,
|
|
JCS_XY_CENTER2,
|
|
JCS_Z_MOVE,
|
|
JCS_Z_PLACEHOLDER,
|
|
JCS_R_MOVE,
|
|
JCS_R_PLACEHOLDER,
|
|
JCS_U_MOVE,
|
|
JCS_U_PLACEHOLDER,
|
|
JCS_V_MOVE,
|
|
JCS_V_PLACEHOLDER,
|
|
JCS_POV_MOVEUP,
|
|
JCS_POV_MOVERIGHT,
|
|
JCS_POV_MOVEDOWN,
|
|
JCS_POV_MOVELEFT,
|
|
JCS_FINI
|
|
} cal_states;
|
|
|
|
typedef enum {
|
|
JC_XY=0,
|
|
JC_Z,
|
|
JC_POV_UP,
|
|
JC_POV_RIGHT,
|
|
JC_POV_DOWN,
|
|
JC_POV_LEFT,
|
|
JC_R,
|
|
JC_U,
|
|
JC_V,
|
|
JC_FINI
|
|
} cal_wins;
|
|
|
|
/*
|
|
* variables used in calibration
|
|
*/
|
|
typedef struct {
|
|
LPGLOBALVARS pgv;
|
|
cal_states cState;
|
|
BOOL bHasTimer;
|
|
BOOL bUseTimer;
|
|
HINSTANCE hinst;
|
|
JOYINFOEX ji;
|
|
JOYRANGE jr;
|
|
DWORD pov[JOY_POV_NUMDIRS];
|
|
int iAxisCount;
|
|
BOOL bPOVdone;
|
|
} CALVARS, *LPCALVARS;
|
|
|
|
#define JOY_CALIB_FLAGS JOY_RETURNX | JOY_RETURNY | JOY_RETURNZ | \
|
|
JOY_RETURNR | JOY_RETURNU | JOY_RETURNV | \
|
|
JOY_RETURNBUTTONS | JOY_RETURNRAWDATA
|
|
|
|
/*
|
|
* setDefaultButton - make a button the default window
|
|
*/
|
|
static void setDefaultButton( HWND hwnd, HWND hwdb )
|
|
{
|
|
DWORD style;
|
|
int i;
|
|
HWND hwb;
|
|
int idList[] = { IDC_JOYCALBACK,
|
|
IDC_JOYCALNEXT,
|
|
IDC_JOYPICKPOV,
|
|
IDC_JOYCALDONE,
|
|
IDC_JOYTEST };
|
|
/*
|
|
* turn off the current default push button
|
|
*/
|
|
for( i=0;i<sizeof( idList )/sizeof( idList[0] );i++ ) {
|
|
hwb = GetDlgItem( hwnd, idList[i] );
|
|
style = GetWindowLong( hwb, GWL_STYLE );
|
|
if( style & BS_DEFPUSHBUTTON ) {
|
|
style &= ~BS_DEFPUSHBUTTON;
|
|
style |= BS_PUSHBUTTON;
|
|
SetWindowLong( hwb, GWL_STYLE, style );
|
|
}
|
|
}
|
|
|
|
/*
|
|
* make the specified button the default
|
|
*/
|
|
style = GetWindowLong( hwdb, GWL_STYLE );
|
|
style &= ~(BS_PUSHBUTTON|BS_DEFPUSHBUTTON);
|
|
style |= BS_DEFPUSHBUTTON;
|
|
SetWindowLong( hwdb, GWL_STYLE, style );
|
|
|
|
} /* setDefaultButton */
|
|
|
|
/*
|
|
* setLabel
|
|
*
|
|
* set the label for an axis based on current calibration state
|
|
*/
|
|
static void setLabel(
|
|
LPGLOBALVARS pgv,
|
|
HWND hwnd,
|
|
UINT id,
|
|
LPJOYREGHWCONFIG pcfg,
|
|
DWORD bit )
|
|
{
|
|
char str[MAX_STR];
|
|
char calstr[MAX_STR];
|
|
int type;
|
|
HINSTANCE hinst;
|
|
HWND hwtext;
|
|
|
|
hinst = GetWindowInstance( hwnd );
|
|
|
|
/*
|
|
* get text for this axis label...
|
|
*/
|
|
if( pcfg->dwUsageSettings & JOY_US_ISOEM ) {
|
|
type = pcfg->dwType - JOY_HW_LASTENTRY;
|
|
if( type < 0 || type >= pgv->pjd->oemCount ) {
|
|
type = -1;
|
|
}
|
|
} else {
|
|
type = -1;
|
|
}
|
|
switch( id ) {
|
|
case IDC_JOYLIST1_LABEL:
|
|
if( (type == -1) || (pgv->pjd->oemList[type].xy_label[0] == 0) ) {
|
|
if( !LoadString( hinst, IDS_XYAXIS_LABEL, str, sizeof( str ) ) ) {
|
|
return;
|
|
}
|
|
} else {
|
|
strcpy( str, pgv->pjd->oemList[type].xy_label );
|
|
}
|
|
break;
|
|
case IDC_JOYLIST2_LABEL:
|
|
if( (type == -1) || (pgv->pjd->oemList[type].z_label[0] == 0 ) ) {
|
|
if( !LoadString( hinst, IDS_ZAXIS_LABEL, str, sizeof( str ) ) ) {
|
|
return;
|
|
}
|
|
} else {
|
|
strcpy( str, pgv->pjd->oemList[type].z_label );
|
|
}
|
|
break;
|
|
case IDC_JOYLIST3_LABEL:
|
|
if( (type == -1) || (pgv->pjd->oemList[type].r_label[0] == 0) ) {
|
|
if( !LoadString( hinst, IDS_RAXIS_LABEL, str, sizeof( str ) ) ) {
|
|
return;
|
|
}
|
|
} else {
|
|
strcpy( str, pgv->pjd->oemList[type].r_label );
|
|
}
|
|
break;
|
|
case IDC_JOYLIST4_LABEL:
|
|
if( (type == -1) || (pgv->pjd->oemList[type].u_label[0] == 0) ) {
|
|
if( !LoadString( hinst, IDS_UAXIS_LABEL, str, sizeof( str ) ) ) {
|
|
return;
|
|
}
|
|
} else {
|
|
strcpy( str, pgv->pjd->oemList[type].u_label );
|
|
}
|
|
break;
|
|
case IDC_JOYLIST5_LABEL:
|
|
if( (type == -1) || (pgv->pjd->oemList[type].v_label[0] == 0) ) {
|
|
if( !LoadString( hinst, IDS_VAXIS_LABEL, str, sizeof( str ) ) ) {
|
|
return;
|
|
}
|
|
} else {
|
|
strcpy( str, pgv->pjd->oemList[type].v_label );
|
|
}
|
|
break;
|
|
case IDC_JOYPOV_LABEL:
|
|
if( (type == -1) || (pgv->pjd->oemList[type].pov_label[0] == 0) ) {
|
|
if( !LoadString( hinst, IDS_POVAXIS_LABEL, str, sizeof( str ) ) ) {
|
|
return;
|
|
}
|
|
} else {
|
|
strcpy( str, pgv->pjd->oemList[type].pov_label );
|
|
}
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* tack on the calibration indicator if needed
|
|
*/
|
|
if( pcfg->hwv.dwCalFlags & bit ) {
|
|
if( !LoadString( hinst, IDS_JOYCALINDICATOR,
|
|
calstr, sizeof( calstr ) ) ) {
|
|
return;
|
|
}
|
|
if( strlen( str ) + strlen( calstr ) + 1 >= sizeof( str ) ) {
|
|
return;
|
|
}
|
|
strcat( str, " " );
|
|
strcat( str, calstr );
|
|
}
|
|
hwtext = GetDlgItem( hwnd, id );
|
|
if( hwtext != NULL ) {
|
|
SetWindowText( hwtext, str );
|
|
}
|
|
|
|
} /* setLabel */
|
|
|
|
/*
|
|
* enableCalWindows - enable or disable specific calibration windows
|
|
*/
|
|
static void enableCalWindows(
|
|
LPGLOBALVARS pgv,
|
|
LPJOYREGHWCONFIG pcfg,
|
|
HWND hwnd,
|
|
cal_wins id )
|
|
{
|
|
BOOL on;
|
|
HWND hwlb;
|
|
HWND hwb;
|
|
// HWND hwcb;
|
|
int iid;
|
|
|
|
/*
|
|
* set up the buttons
|
|
*/
|
|
hwb = GetDlgItem( hwnd,IDC_JOYCALDONE );
|
|
if( id == JC_FINI ) {
|
|
ShowWindow( GetDlgItem( hwnd, IDC_JOYCALNEXT ), SW_HIDE );
|
|
ShowWindow( GetDlgItem( hwnd, IDC_JOYTEST ), SW_NORMAL );
|
|
EnableWindow( hwb, TRUE );
|
|
ShowWindow( hwb, SW_NORMAL );
|
|
SetFocus( hwb );
|
|
setDefaultButton( hwnd, hwb );
|
|
} else {
|
|
ShowWindow( GetDlgItem( hwnd, IDC_JOYCALNEXT ), SW_NORMAL );
|
|
ShowWindow( GetDlgItem( hwnd, IDC_JOYTEST ), SW_HIDE );
|
|
EnableWindow( hwb, FALSE );
|
|
ShowWindow( hwb, SW_HIDE );
|
|
}
|
|
|
|
/*
|
|
* set up the labels with the (done) after it...
|
|
*/
|
|
setLabel( pgv, hwnd, IDC_JOYLIST1_LABEL, pcfg, JOY_ISCAL_XY );
|
|
|
|
if( pcfg->hws.dwFlags & JOY_HWS_HASZ ) {
|
|
setLabel( pgv, hwnd, IDC_JOYLIST2_LABEL, pcfg, JOY_ISCAL_Z );
|
|
}
|
|
|
|
if( (pcfg->hws.dwFlags & JOY_HWS_HASR) || (pcfg->dwUsageSettings & JOY_US_HASRUDDER)) {
|
|
setLabel( pgv, hwnd, IDC_JOYLIST3_LABEL, pcfg, JOY_ISCAL_R );
|
|
}
|
|
|
|
if( pcfg->hws.dwFlags & JOY_HWS_HASPOV ) {
|
|
setLabel( pgv, hwnd, IDC_JOYPOV_LABEL, pcfg, JOY_ISCAL_POV );
|
|
}
|
|
|
|
if( pcfg->hws.dwFlags & JOY_HWS_HASU ) {
|
|
setLabel( pgv, hwnd, IDC_JOYLIST4_LABEL, pcfg, JOY_ISCAL_U );
|
|
}
|
|
|
|
if( pcfg->hws.dwFlags & JOY_HWS_HASV ) {
|
|
setLabel( pgv, hwnd, IDC_JOYLIST5_LABEL, pcfg, JOY_ISCAL_V );
|
|
}
|
|
|
|
|
|
/*
|
|
* set up the XY window
|
|
*/
|
|
on = FALSE;
|
|
if( id == JC_XY ) {
|
|
on = TRUE;
|
|
}
|
|
hwlb = GetDlgItem( hwnd, IDC_JOYLIST1 );
|
|
if( !on ) {
|
|
InvalidateRect( hwlb, NULL, TRUE );
|
|
}
|
|
EnableWindow( hwlb, on );
|
|
EnableWindow( GetDlgItem( hwnd, IDC_JOYLIST1_LABEL ), on );
|
|
|
|
/*
|
|
* set up the Z window
|
|
*/
|
|
on = FALSE;
|
|
if( id == JC_Z ) {
|
|
on = TRUE;
|
|
}
|
|
hwlb = GetDlgItem( hwnd, IDC_JOYLIST2 );
|
|
if( !on ) {
|
|
InvalidateRect( hwlb, NULL, TRUE );
|
|
}
|
|
EnableWindow( hwlb, on );
|
|
EnableWindow( GetDlgItem( hwnd, IDC_JOYLIST2_LABEL ), on );
|
|
|
|
/*
|
|
* set up the R window
|
|
*/
|
|
on = FALSE;
|
|
if( id == JC_R ) {
|
|
on = TRUE;
|
|
}
|
|
hwlb = GetDlgItem( hwnd, IDC_JOYLIST3 );
|
|
if( !on ) {
|
|
InvalidateRect( hwlb, NULL, TRUE );
|
|
}
|
|
EnableWindow( hwlb, on );
|
|
EnableWindow( GetDlgItem( hwnd, IDC_JOYLIST3_LABEL ), on );
|
|
|
|
/*
|
|
* set up the U window
|
|
*/
|
|
on = FALSE;
|
|
if( id == JC_U ) {
|
|
on = TRUE;
|
|
}
|
|
hwlb = GetDlgItem( hwnd, IDC_JOYLIST4 );
|
|
if( hwlb != NULL ) {
|
|
if( !on ) {
|
|
InvalidateRect( hwlb, NULL, TRUE );
|
|
}
|
|
EnableWindow( hwlb, on );
|
|
EnableWindow( GetDlgItem( hwnd, IDC_JOYLIST4_LABEL ), on );
|
|
}
|
|
|
|
/*
|
|
* set up the V window
|
|
*/
|
|
on = FALSE;
|
|
if( id == JC_V ) {
|
|
on = TRUE;
|
|
}
|
|
hwlb = GetDlgItem( hwnd, IDC_JOYLIST5 );
|
|
if( hwlb != NULL ) {
|
|
if( !on ) {
|
|
InvalidateRect( hwlb, NULL, TRUE );
|
|
}
|
|
EnableWindow( hwlb, on );
|
|
EnableWindow( GetDlgItem( hwnd, IDC_JOYLIST5_LABEL ), on );
|
|
}
|
|
|
|
/*
|
|
* set up the POV icon
|
|
*/
|
|
on = FALSE;
|
|
if( id >= JC_POV_UP && id <= JC_POV_LEFT ) {
|
|
on = TRUE;
|
|
}
|
|
EnableWindow( GetDlgItem( hwnd, IDC_JOYPOV_LABEL ), on );
|
|
hwb = GetDlgItem( hwnd, IDC_JOYPICKPOV );
|
|
EnableWindow( hwb, on );
|
|
if( on ) {
|
|
ShowWindow( hwb, SW_NORMAL );
|
|
SetFocus( hwb );
|
|
setDefaultButton( hwnd, hwb );
|
|
switch( id ) {
|
|
case JC_POV_UP:
|
|
iid = IDI_JOYPOV_UP;
|
|
break;
|
|
case JC_POV_RIGHT:
|
|
iid = IDI_JOYPOV_RIGHT;
|
|
break;
|
|
case JC_POV_LEFT:
|
|
iid = IDI_JOYPOV_LEFT;
|
|
break;
|
|
case JC_POV_DOWN:
|
|
iid = IDI_JOYPOV_DOWN;
|
|
break;
|
|
}
|
|
} else {
|
|
ShowWindow( hwb, SW_HIDE );
|
|
UpdateWindow( hwb );
|
|
iid = IDI_JOYPOV_GRAYED;
|
|
}
|
|
ChangeIcon( hwnd, iid, IDC_JOYPOV );
|
|
|
|
} /* enableCalWindows */
|
|
|
|
|
|
/*
|
|
* getJoyName - get the name of a joystick
|
|
*/
|
|
static int getJoyName( LPJOYREGHWCONFIG pcfg, BOOL plural )
|
|
{
|
|
int str2id;
|
|
|
|
if( pcfg->hws.dwFlags & JOY_HWS_ISYOKE ) {
|
|
if( plural ) {
|
|
str2id = IDS_JOYCAL_YOKES;
|
|
} else {
|
|
str2id = IDS_JOYCAL_YOKE;
|
|
}
|
|
} else if( pcfg->hws.dwFlags & JOY_HWS_ISCARCTRL ) {
|
|
if( plural ) {
|
|
str2id = IDS_JOYCAL_CARS;
|
|
} else {
|
|
str2id = IDS_JOYCAL_CAR;
|
|
}
|
|
} else if( pcfg->hws.dwFlags & JOY_HWS_ISGAMEPAD ) {
|
|
if( plural ) {
|
|
str2id = IDS_JOYCAL_GAMEPADS;
|
|
} else {
|
|
str2id = IDS_JOYCAL_GAMEPAD;
|
|
}
|
|
} else {
|
|
if( plural ) {
|
|
str2id = IDS_JOY2S;
|
|
} else {
|
|
str2id = IDS_JOY2;
|
|
}
|
|
}
|
|
return str2id;
|
|
|
|
} /* getJoyName */
|
|
|
|
/*
|
|
* joyCalStateChange - calibration state change
|
|
*/
|
|
static BOOL joyCalStateChange( LPCALVARS pcv, HWND hwnd, BOOL back )
|
|
{
|
|
HINSTANCE hinst;
|
|
HWND hwtext;
|
|
int strid;
|
|
int stridx;
|
|
int str2id;
|
|
int str3id;
|
|
int str4id;
|
|
char str[2*MAX_STR];
|
|
char buff[2*MAX_STR];
|
|
char str2[64];
|
|
char str3[64];
|
|
char str4[64];
|
|
BOOL done;
|
|
LPJOYREGHWCONFIG pcfg;
|
|
BOOL rc;
|
|
int type;
|
|
LPGLOBALVARS pgv;
|
|
BOOL isdone;
|
|
|
|
/*
|
|
* move to the next state: get the appropriate string
|
|
* to display, and enable the correct controls
|
|
*/
|
|
pgv = pcv->pgv;
|
|
rc = TRUE;
|
|
done = FALSE;
|
|
pcfg = &pgv->joyHWCurr;
|
|
str2id = -1;
|
|
str3id = -1;
|
|
str4id = -1;
|
|
pcv->cState++;
|
|
EnableWindow( GetDlgItem( hwnd, IDC_JOYCALBACK ), back );
|
|
while( !done ) {
|
|
done = TRUE;
|
|
switch( pcv->cState ) {
|
|
case JCS_XY_CENTER1:
|
|
/*
|
|
* init. range variables
|
|
*/
|
|
pcv->jr.jpMin.dwX = (DWORD) -1;
|
|
pcv->jr.jpMin.dwY = (DWORD) -1;
|
|
pcv->jr.jpMin.dwZ = (DWORD) -1;
|
|
pcv->jr.jpMin.dwR = (DWORD) -1;
|
|
pcv->jr.jpMin.dwU = (DWORD) -1;
|
|
pcv->jr.jpMin.dwV = (DWORD) -1;
|
|
pcv->jr.jpMax.dwX = 0;
|
|
pcv->jr.jpMax.dwY = 0;
|
|
pcv->jr.jpMax.dwZ = 0;
|
|
pcv->jr.jpMax.dwR = 0;
|
|
pcv->jr.jpMax.dwU = 0;
|
|
pcv->jr.jpMax.dwV = 0;
|
|
|
|
/*
|
|
* set strings to display
|
|
*/
|
|
stridx = CALSTR1;
|
|
if( pcfg->hws.dwFlags & JOY_HWS_ISYOKE ) {
|
|
strid = IDS_JOYCALXY_CENTERYOKE;
|
|
} else if( pcfg->hws.dwFlags & JOY_HWS_ISCARCTRL ) {
|
|
strid = IDS_JOYCALXY_CENTERCAR;
|
|
} else if( pcfg->hws.dwFlags & JOY_HWS_ISGAMEPAD ) {
|
|
strid = IDS_JOYCALXY_CENTERGAMEPAD;
|
|
} else {
|
|
strid = IDS_JOYCALXY_CENTER;
|
|
}
|
|
enableCalWindows( pgv, pcfg, hwnd, JC_XY );
|
|
break;
|
|
case JCS_XY_MOVE:
|
|
stridx = CALSTR2;
|
|
if( pcfg->hws.dwFlags & JOY_HWS_ISYOKE ) {
|
|
strid = IDS_JOYCALXY_MOVEYOKE;
|
|
} else if( pcfg->hws.dwFlags & JOY_HWS_ISCARCTRL ) {
|
|
strid = IDS_JOYCALXY_MOVECAR;
|
|
} else if( pcfg->hws.dwFlags & JOY_HWS_ISGAMEPAD ) {
|
|
strid = IDS_JOYCALXY_MOVEGAMEPAD;
|
|
} else {
|
|
strid = IDS_JOYCALXY_MOVE;
|
|
}
|
|
break;
|
|
case JCS_XY_CENTER2:
|
|
stridx = CALSTR3;
|
|
if( pcfg->hws.dwFlags & JOY_HWS_ISYOKE ) {
|
|
strid = IDS_JOYCALXY_CENTERYOKE2;
|
|
} else if( pcfg->hws.dwFlags & JOY_HWS_ISCARCTRL ) {
|
|
strid = IDS_JOYCALXY_CENTERCAR2;
|
|
} else if( pcfg->hws.dwFlags & JOY_HWS_ISGAMEPAD ) {
|
|
strid = IDS_JOYCALXY_CENTERGAMEPAD2;
|
|
} else {
|
|
strid = IDS_JOYCALXY_CENTER2;
|
|
}
|
|
break;
|
|
case JCS_Z_MOVE:
|
|
stridx = CALSTR4;
|
|
if( !(pcfg->hws.dwFlags & JOY_HWS_HASZ) ) {
|
|
pcv->cState = JCS_R_MOVE;
|
|
done = FALSE;
|
|
} else {
|
|
enableCalWindows( pgv, pcfg, hwnd, JC_Z );
|
|
strid = IDS_JOYCALZ_MOVE;
|
|
str2id = getJoyName( pcfg, TRUE );
|
|
}
|
|
break;
|
|
case JCS_Z_PLACEHOLDER:
|
|
pcv->cState = JCS_R_MOVE;
|
|
done = FALSE;
|
|
break;
|
|
case JCS_R_MOVE:
|
|
stridx = CALSTR5;
|
|
if( !(pcfg->hws.dwFlags & JOY_HWS_HASR) && !(pcfg->dwUsageSettings & JOY_US_HASRUDDER) ) {
|
|
pcv->cState = JCS_U_MOVE;
|
|
done = FALSE;
|
|
} else {
|
|
enableCalWindows( pgv, pcfg, hwnd, JC_R );
|
|
strid = IDS_JOYCALRUDDER_MOVE;
|
|
str2id = getJoyName( pcfg, TRUE );
|
|
}
|
|
break;
|
|
case JCS_R_PLACEHOLDER:
|
|
pcv->cState = JCS_U_MOVE;
|
|
done = FALSE;
|
|
break;
|
|
case JCS_U_MOVE:
|
|
stridx = CALSTR6;
|
|
if( !(pcfg->hws.dwFlags & JOY_HWS_HASU) ) {
|
|
pcv->cState = JCS_V_MOVE;
|
|
done = FALSE;
|
|
} else {
|
|
enableCalWindows( pgv, pcfg, hwnd, JC_U );
|
|
strid = IDS_JOYCALU_MOVE;
|
|
str2id = getJoyName( pcfg, TRUE );
|
|
}
|
|
break;
|
|
case JCS_U_PLACEHOLDER:
|
|
pcv->cState = JCS_V_MOVE;
|
|
done = FALSE;
|
|
break;
|
|
case JCS_V_MOVE:
|
|
stridx = CALSTR7;
|
|
if( !(pcfg->hws.dwFlags & JOY_HWS_HASV) ) {
|
|
pcv->cState = JCS_POV_MOVEUP;
|
|
done = FALSE;
|
|
} else {
|
|
enableCalWindows( pgv, pcfg, hwnd, JC_V );
|
|
strid = IDS_JOYCALV_MOVE;
|
|
str2id = getJoyName( pcfg, TRUE );
|
|
}
|
|
break;
|
|
case JCS_V_PLACEHOLDER:
|
|
pcv->cState = JCS_POV_MOVEUP;
|
|
done = FALSE;
|
|
break;
|
|
case JCS_POV_MOVEUP:
|
|
stridx = CALSTR8;
|
|
if( !(pcfg->hws.dwFlags & JOY_HWS_HASPOV)) {
|
|
pcv->cState = JCS_FINI;
|
|
done = FALSE;
|
|
} else {
|
|
enableCalWindows( pgv, pcfg, hwnd, JC_POV_UP );
|
|
strid = IDS_JOYCALPOV_MOVE;
|
|
str2id = IDS_JOYCAL_UP;
|
|
str3id = getJoyName( pcfg, TRUE );
|
|
str4id = IDS_JOYCAL_UP;
|
|
}
|
|
break;
|
|
case JCS_POV_MOVERIGHT:
|
|
stridx = CALSTR9;
|
|
enableCalWindows( pgv, pcfg, hwnd, JC_POV_RIGHT );
|
|
strid = IDS_JOYCALPOV_MOVE;
|
|
str2id = IDS_JOYCAL_RIGHT;
|
|
str3id = getJoyName( pcfg, TRUE );
|
|
str4id = IDS_JOYCAL_RIGHT;
|
|
break;
|
|
case JCS_POV_MOVEDOWN:
|
|
stridx = CALSTR10;
|
|
enableCalWindows( pgv, pcfg, hwnd, JC_POV_DOWN );
|
|
strid = IDS_JOYCALPOV_MOVE;
|
|
str2id = IDS_JOYCAL_DOWN;
|
|
str3id = getJoyName( pcfg, TRUE );
|
|
str4id = IDS_JOYCAL_DOWN;
|
|
break;
|
|
case JCS_POV_MOVELEFT:
|
|
stridx = CALSTR11;
|
|
enableCalWindows( pgv, pcfg, hwnd, JC_POV_LEFT );
|
|
strid = IDS_JOYCALPOV_MOVE;
|
|
str2id = IDS_JOYCAL_LEFT;
|
|
str3id = getJoyName( pcfg, TRUE );
|
|
str4id = IDS_JOYCAL_LEFT;
|
|
break;
|
|
case JCS_FINI:
|
|
/*
|
|
* see if everything that needs to be calibrated
|
|
* was actually calibrated
|
|
*/
|
|
if( !(pcfg->hwv.dwCalFlags & JOY_ISCAL_XY) ) {
|
|
isdone = FALSE;
|
|
} else if( (pcfg->hws.dwFlags & JOY_HWS_HASZ) &&
|
|
!(pcfg->hwv.dwCalFlags & JOY_ISCAL_Z) ) {
|
|
isdone = FALSE;
|
|
} else if( ((pcfg->hws.dwFlags & JOY_HWS_HASR) ||
|
|
(pcfg->dwUsageSettings & JOY_US_HASRUDDER)) &&
|
|
!(pcfg->hwv.dwCalFlags & JOY_ISCAL_R) ) {
|
|
isdone = FALSE;
|
|
} else if( (pcfg->hws.dwFlags & JOY_HWS_HASPOV) &&
|
|
!(pcfg->hwv.dwCalFlags & JOY_ISCAL_POV) ) {
|
|
isdone = FALSE;
|
|
} else if( (pcfg->hws.dwFlags & JOY_HWS_HASU) &&
|
|
!(pcfg->hwv.dwCalFlags & JOY_ISCAL_U) ) {
|
|
isdone = FALSE;
|
|
} else if( (pcfg->hws.dwFlags & JOY_HWS_HASV) &&
|
|
!(pcfg->hwv.dwCalFlags & JOY_ISCAL_V) ) {
|
|
isdone = FALSE;
|
|
} else {
|
|
isdone = TRUE;
|
|
}
|
|
if( isdone ) {
|
|
strid = IDS_JOYCAL_DONE;
|
|
} else {
|
|
strid = IDS_JOYCAL_NOTDONE;
|
|
}
|
|
str2id = getJoyName( pcfg, FALSE );
|
|
str3id = getJoyName( pcfg, TRUE );
|
|
stridx = CALSTR12;
|
|
enableCalWindows( pgv, pcfg, hwnd, JC_FINI );
|
|
rc = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* see if there is any OEM text specified
|
|
*/
|
|
hinst = GetWindowInstance( hwnd );
|
|
hwtext = GetDlgItem( hwnd, IDC_JOYCALMSG );
|
|
if( pcfg->dwUsageSettings & JOY_US_ISOEM ) {
|
|
LPJOYDATA pjd;
|
|
pjd = pgv->pjd;
|
|
type = pcfg->dwType - JOY_HW_LASTENTRY;
|
|
if( pjd->oemList[type].cal_strs[ stridx ][0] != 0 ) {
|
|
SetWindowText( hwtext, pjd->oemList[type].cal_strs[ stridx] );
|
|
return rc;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* no OEM text, use the defaults
|
|
*/
|
|
if( LoadString( hinst, strid, str, sizeof( str ) ) ) {
|
|
if( str2id != -1 ) {
|
|
if( LoadString( hinst, str2id, str2, sizeof( str2 ) ) ) {
|
|
if( str3id != -1 ) {
|
|
if( LoadString( hinst, str3id, str3, sizeof( str3 ) ) ) {
|
|
if( str4id != -1 ) {
|
|
if( LoadString( hinst, str4id, str4, sizeof( str4 ) ) ) {
|
|
// wsprintf( buff, str, str2, str3, str4 );
|
|
LPSTR lpargs[] = {str2, str3, str4};
|
|
|
|
FormatMessage(FORMAT_MESSAGE_FROM_STRING |
|
|
FORMAT_MESSAGE_ARGUMENT_ARRAY,
|
|
(LPSTR) str,
|
|
0, 0,
|
|
buff,
|
|
sizeof(buff),
|
|
(va_list *)lpargs);
|
|
SetWindowText( hwtext, buff );
|
|
}
|
|
} else {
|
|
wsprintf( buff, str, str2, str3 );
|
|
SetWindowText( hwtext, buff );
|
|
}
|
|
}
|
|
} else {
|
|
wsprintf( buff, str, str2, str2 );
|
|
SetWindowText( hwtext, buff );
|
|
}
|
|
}
|
|
} else {
|
|
SetWindowText( hwtext, str );
|
|
}
|
|
}
|
|
|
|
return rc;
|
|
|
|
} /* joyCalStateChange */
|
|
|
|
/*
|
|
* joyCalStateSkip - skip the current state, move to the next one
|
|
*/
|
|
static void joyCalStateSkip( LPCALVARS pcv, HWND hwnd )
|
|
{
|
|
|
|
/*
|
|
* if we're calibrating XY, skip to Z
|
|
*/
|
|
if( pcv->cState <= JCS_XY_CENTER2 ) {
|
|
pcv->cState = JCS_XY_CENTER2;
|
|
/*
|
|
* if we're calibrating Z, skip to R
|
|
*/
|
|
} else if( pcv->cState < JCS_Z_PLACEHOLDER ) {
|
|
pcv->cState = JCS_Z_PLACEHOLDER;
|
|
/*
|
|
* if we're calibrating R, skip to U
|
|
*/
|
|
} else if( pcv->cState < JCS_R_PLACEHOLDER ) {
|
|
pcv->cState = JCS_R_PLACEHOLDER;
|
|
/*
|
|
* if we're calibrating U, skip to V
|
|
*/
|
|
} else if( pcv->cState < JCS_U_PLACEHOLDER ) {
|
|
pcv->cState = JCS_U_PLACEHOLDER;
|
|
/*
|
|
* if we're calibrating V, skip to POV
|
|
*/
|
|
} else if( pcv->cState < JCS_V_PLACEHOLDER ) {
|
|
pcv->cState = JCS_V_PLACEHOLDER;
|
|
/*
|
|
* we must be calibration POV, skip to the end
|
|
*/
|
|
} else {
|
|
pcv->cState = JCS_POV_MOVELEFT;
|
|
}
|
|
|
|
/*
|
|
* state changed, reset to the new one
|
|
*/
|
|
CauseRedraw( &pcv->ji, FALSE );
|
|
joyCalStateChange( pcv, hwnd, TRUE );
|
|
|
|
} /* joyCalStateSkip */
|
|
|
|
/*
|
|
* resetCustomPOVFlags - set POV flags based on original values for custom joystick
|
|
*/
|
|
static void resetCustomPOVFlags( LPGLOBALVARS pgv, LPJOYREGHWCONFIG pcfg )
|
|
{
|
|
if( pcfg->dwType == JOY_HW_CUSTOM ) {
|
|
pcfg->hws.dwFlags &= ~(JOY_HWS_POVISPOLL|JOY_HWS_POVISBUTTONCOMBOS);
|
|
if( pgv->bOrigPOVIsPoll ) {
|
|
pcfg->hws.dwFlags |= JOY_HWS_POVISPOLL;
|
|
}
|
|
if( pgv->bOrigPOVIsButtonCombos ) {
|
|
pcfg->hws.dwFlags |= JOY_HWS_POVISBUTTONCOMBOS;
|
|
}
|
|
}
|
|
|
|
} /* resetCustomPOVFlags */
|
|
|
|
|
|
/*
|
|
* joyCalStateBack - move back to start the previous state
|
|
*/
|
|
static void joyCalStateBack( LPCALVARS pcv, HWND hwnd )
|
|
{
|
|
BOOL back;
|
|
LPJOYREGHWCONFIG pcfg;
|
|
LPGLOBALVARS pgv;
|
|
|
|
pgv = pcv->pgv;
|
|
back = TRUE;
|
|
pcfg = &pgv->joyHWCurr;
|
|
/*
|
|
* at the end, backup
|
|
*/
|
|
if( pcv->cState == JCS_FINI ) {
|
|
/*
|
|
* if there is POV, back up to it
|
|
*/
|
|
if( pcfg->hws.dwFlags & JOY_HWS_HASPOV ) {
|
|
pcv->cState = JCS_V_PLACEHOLDER;
|
|
resetCustomPOVFlags( pgv, pcfg );
|
|
/*
|
|
* if there is V, back up to it
|
|
*/
|
|
} else if( pcfg->hws.dwFlags & JOY_HWS_HASV ) {
|
|
pcv->cState = JCS_U_PLACEHOLDER;
|
|
/*
|
|
* if there is U, back up to it
|
|
*/
|
|
} else if( pcfg->hws.dwFlags & JOY_HWS_HASU ) {
|
|
pcv->cState = JCS_R_PLACEHOLDER;
|
|
/*
|
|
* if there is R, back up to it
|
|
*/
|
|
} else if( (pcfg->hws.dwFlags & JOY_HWS_HASR) ||
|
|
(pcfg->dwUsageSettings & JOY_US_HASRUDDER) ) {
|
|
pcv->cState = JCS_Z_PLACEHOLDER;
|
|
/*
|
|
* if there is Z, back up to it
|
|
*/
|
|
} else if( pcfg->hws.dwFlags & JOY_HWS_HASZ ) {
|
|
pcv->cState = JCS_XY_CENTER2;
|
|
/*
|
|
* no where else to go, back up to XY
|
|
*/
|
|
} else {
|
|
pcv->cState = JCS_INIT;
|
|
back = FALSE;
|
|
}
|
|
/*
|
|
* doing POV, so restart it
|
|
*/
|
|
} else if( pcv->cState > JCS_POV_MOVEUP ) {
|
|
pcv->cState = JCS_V_PLACEHOLDER;
|
|
// pcfg->hws.dwFlags &= ~(JOY_HWS_POVISPOLL|JOY_HWS_POVISBUTTONCOMBOS);
|
|
resetCustomPOVFlags( pgv, pcfg );
|
|
/*
|
|
* just starting POV, back up
|
|
*/
|
|
} else if( pcv->cState == JCS_POV_MOVEUP ) {
|
|
/*
|
|
* if there is V, back up to it
|
|
*/
|
|
if( pcfg->hws.dwFlags & JOY_HWS_HASV ) {
|
|
pcv->cState = JCS_U_PLACEHOLDER;
|
|
/*
|
|
* if there is U, back up to it
|
|
*/
|
|
} else if( pcfg->hws.dwFlags & JOY_HWS_HASU ) {
|
|
pcv->cState = JCS_R_PLACEHOLDER;
|
|
/*
|
|
* if there is R, back up to it
|
|
*/
|
|
} else if( (pcfg->hws.dwFlags & JOY_HWS_HASR) ||
|
|
(pcfg->dwUsageSettings & JOY_US_HASRUDDER) ) {
|
|
pcv->cState = JCS_Z_PLACEHOLDER;
|
|
/*
|
|
* if there is Z, back up to it
|
|
*/
|
|
} else if( pcfg->hws.dwFlags & JOY_HWS_HASZ ) {
|
|
pcv->cState = JCS_XY_CENTER2;
|
|
/*
|
|
* no where else to go, back up to XY
|
|
*/
|
|
} else {
|
|
pcv->cState = JCS_INIT;
|
|
back = FALSE;
|
|
}
|
|
/*
|
|
* doing V, backup
|
|
*/
|
|
} else if( pcv->cState == JCS_V_MOVE ) {
|
|
/*
|
|
* if there is U, back up to it
|
|
*/
|
|
if( pcfg->hws.dwFlags & JOY_HWS_HASU ) {
|
|
pcv->cState = JCS_R_PLACEHOLDER;
|
|
/*
|
|
* if there is R, back up to it
|
|
*/
|
|
} else if( (pcfg->hws.dwFlags & JOY_HWS_HASR) ||
|
|
(pcfg->dwUsageSettings & JOY_US_HASRUDDER) ) {
|
|
pcv->cState = JCS_Z_PLACEHOLDER;
|
|
/*
|
|
* if there is Z, back up to it
|
|
*/
|
|
} else if( pcfg->hws.dwFlags & JOY_HWS_HASZ ) {
|
|
pcv->cState = JCS_XY_CENTER2;
|
|
/*
|
|
* no where else to go, back up to XY
|
|
*/
|
|
} else {
|
|
pcv->cState = JCS_INIT;
|
|
back = FALSE;
|
|
}
|
|
/*
|
|
* doing U, backup
|
|
*/
|
|
} else if( pcv->cState == JCS_U_MOVE ) {
|
|
/*
|
|
* if there is R, back up to it
|
|
*/
|
|
if( (pcfg->hws.dwFlags & JOY_HWS_HASR) ||
|
|
(pcfg->dwUsageSettings & JOY_US_HASRUDDER) ) {
|
|
pcv->cState = JCS_Z_PLACEHOLDER;
|
|
/*
|
|
* if there is Z, back up to it
|
|
*/
|
|
} else if( pcfg->hws.dwFlags & JOY_HWS_HASZ ) {
|
|
pcv->cState = JCS_XY_CENTER2;
|
|
/*
|
|
* no where else to go, back up to XY
|
|
*/
|
|
} else {
|
|
pcv->cState = JCS_INIT;
|
|
back = FALSE;
|
|
}
|
|
/*
|
|
* doing R, backup
|
|
*/
|
|
} else if( pcv->cState == JCS_R_MOVE ) {
|
|
/*
|
|
* if there is Z, back up to it
|
|
*/
|
|
if( pcfg->hws.dwFlags & JOY_HWS_HASZ ) {
|
|
pcv->cState = JCS_XY_CENTER2;
|
|
/*
|
|
* no where else to go, back up to XY
|
|
*/
|
|
} else {
|
|
pcv->cState = JCS_INIT;
|
|
back = FALSE;
|
|
}
|
|
/*
|
|
* if we're doing Z or in the middle of XY, backup to XY
|
|
*/
|
|
} else {
|
|
pcv->cState = JCS_INIT;
|
|
back = FALSE;
|
|
}
|
|
|
|
/*
|
|
* state changed, reset to the new one
|
|
*/
|
|
CauseRedraw( &pcv->ji, FALSE );
|
|
joyCalStateChange( pcv, hwnd, back );
|
|
|
|
} /* joyCalStateBack */
|
|
|
|
/*
|
|
* macro to get new max/min data for an axis
|
|
*/
|
|
#define NEWMINMAX( a ) \
|
|
if( pji->dw##a##pos > pcv->jr.jpMax.dw##a ) { \
|
|
pcv->jr.jpMax.dw##a = pji->dw##a##pos; \
|
|
} \
|
|
if( pji->dw##a##pos < pcv->jr.jpMin.dw##a ) { \
|
|
pcv->jr.jpMin.dw##a = pji->dw##a##pos; \
|
|
} \
|
|
|
|
/*
|
|
* macro to do continuous calibration--changes jpi->dw*pos based on current
|
|
* position and latest minimum/maximum values
|
|
*/
|
|
#define CAL_MIN 50 // Pretend it's centered unless HW range is >= CAL_MIN
|
|
|
|
#define SIMULATECALIBRATION(_pcv,_pji,_AXIS_) \
|
|
{ \
|
|
NEWMINMAX(_AXIS_); \
|
|
_pji->dw##_AXIS_##pos -= _pcv->jr.jpMin.dw##_AXIS_; \
|
|
if (_pcv->jr.jpMax.dw##_AXIS_ - _pcv->jr.jpMin.dw##_AXIS_ < CAL_MIN) { \
|
|
_pji->dw##_AXIS_##pos = (RANGE_MAX -RANGE_MIN)/2; \
|
|
} else if ( RANGE_MAX == RANGE_MIN ) { \
|
|
_pji->dw##_AXIS_##pos = (RANGE_MAX -RANGE_MIN)/2; \
|
|
} else { \
|
|
_pji->dw##_AXIS_##pos *= (RANGE_MAX-RANGE_MIN); \
|
|
_pji->dw##_AXIS_##pos /= ( _pcv->jr.jpMax.dw##_AXIS_ - \
|
|
_pcv->jr.jpMin.dw##_AXIS_ ); \
|
|
} \
|
|
_pji->dw##_AXIS_##pos += RANGE_MIN; \
|
|
}
|
|
|
|
/*
|
|
* joyCollectCalInfo - record calibration info
|
|
*/
|
|
static BOOL joyCollectCalInfo( LPCALVARS pcv, HWND hwnd, LPJOYINFOEX pji )
|
|
{
|
|
LPGLOBALVARS pgv;
|
|
LPJOYREGHWCONFIG pcfg;
|
|
|
|
pgv = pcv->pgv;
|
|
switch( pcv->cState ) {
|
|
/*
|
|
* remember XY center
|
|
*/
|
|
case JCS_XY_CENTER1:
|
|
case JCS_XY_CENTER2:
|
|
{
|
|
JOYINFOEX jiex = *pji;
|
|
SIMULATECALIBRATION( pcv, pji, X );
|
|
SIMULATECALIBRATION( pcv, pji, Y );
|
|
DoJoyMove( pgv, hwnd, pji, &pcv->ji, JOYMOVE_DRAWXY );
|
|
*pji = jiex;
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* remember max/min XY values
|
|
*/
|
|
case JCS_XY_MOVE:
|
|
{
|
|
JOYINFOEX jiex = *pji;
|
|
SIMULATECALIBRATION( pcv, pji, X );
|
|
SIMULATECALIBRATION( pcv, pji, Y );
|
|
DoJoyMove( pgv, hwnd, pji, &pcv->ji, JOYMOVE_DRAWXY );
|
|
*pji = jiex;
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* remember max/min Z value
|
|
*/
|
|
case JCS_Z_MOVE:
|
|
{
|
|
JOYINFOEX jiex = *pji;
|
|
SIMULATECALIBRATION( pcv, pji, Z );
|
|
DoJoyMove( pgv, hwnd, pji, &pcv->ji, JOYMOVE_DRAWZ );
|
|
*pji = jiex;
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* remember max/min R value
|
|
*/
|
|
case JCS_R_MOVE:
|
|
{
|
|
JOYINFOEX jiex = *pji;
|
|
SIMULATECALIBRATION( pcv, pji, R );
|
|
DoJoyMove( pgv, hwnd, pji, &pcv->ji, JOYMOVE_DRAWR );
|
|
*pji = jiex;
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* remember max/min U value
|
|
*/
|
|
case JCS_U_MOVE:
|
|
{
|
|
JOYINFOEX jiex = *pji;
|
|
SIMULATECALIBRATION( pcv, pji, U );
|
|
DoJoyMove( pgv, hwnd, pji, &pcv->ji, JOYMOVE_DRAWU );
|
|
*pji = jiex;
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* remember max/min V value
|
|
*/
|
|
case JCS_V_MOVE:
|
|
{
|
|
JOYINFOEX jiex = *pji;
|
|
SIMULATECALIBRATION( pcv, pji, V );
|
|
DoJoyMove( pgv, hwnd, pji, &pcv->ji, JOYMOVE_DRAWV );
|
|
*pji = jiex;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* if a button was pressed, move to the next state
|
|
*/
|
|
if( ((pcv->ji.dwButtons & ALL_BUTTONS) != (pji->dwButtons & ALL_BUTTONS)) &&
|
|
((pji->dwButtons & JOY_BUTTON1) ||
|
|
(pji->dwButtons & JOY_BUTTON2) ||
|
|
(pji->dwButtons & JOY_BUTTON3) ||
|
|
(pji->dwButtons & JOY_BUTTON4) ) ) {
|
|
/*
|
|
* check and see if we are leaving one calibration to the next;
|
|
* if yes, take time to stop and remember what the user just did
|
|
*/
|
|
pcfg = &pgv->joyHWCurr;
|
|
switch( pcv->cState ) {
|
|
case JCS_XY_CENTER1:
|
|
pcv->jr.jpCenter.dwX = pji->dwXpos;
|
|
pcv->jr.jpCenter.dwY = pji->dwYpos;
|
|
DPF( "Center 1: %d,%d\r\n", pji->dwXpos, pji->dwYpos );
|
|
break;
|
|
|
|
case JCS_XY_CENTER2:
|
|
DPF( "Center 2: %d,%d\r\n", pji->dwXpos, pji->dwYpos );
|
|
pcv->jr.jpCenter.dwX += pji->dwXpos;
|
|
pcv->jr.jpCenter.dwY += pji->dwYpos;
|
|
pcv->jr.jpCenter.dwX /= 2;
|
|
pcv->jr.jpCenter.dwY /= 2;
|
|
DPF( "Center Avg: %d,%d\r\n", pcv->jr.jpCenter.dwX, pcv->jr.jpCenter.dwY );
|
|
pcfg->hwv.jrvHardware.jpMin.dwX = pcv->jr.jpMin.dwX;
|
|
pcfg->hwv.jrvHardware.jpMin.dwY = pcv->jr.jpMin.dwY;
|
|
pcfg->hwv.jrvHardware.jpMax.dwX = pcv->jr.jpMax.dwX;
|
|
pcfg->hwv.jrvHardware.jpMax.dwY = pcv->jr.jpMax.dwY;
|
|
pcfg->hwv.jrvHardware.jpCenter.dwX = pcv->jr.jpCenter.dwX;
|
|
pcfg->hwv.jrvHardware.jpCenter.dwY = pcv->jr.jpCenter.dwY;
|
|
pcfg->hwv.dwCalFlags |= JOY_ISCAL_XY;
|
|
break;
|
|
case JCS_Z_MOVE:
|
|
pcfg->hwv.jrvHardware.jpMin.dwZ = pcv->jr.jpMin.dwZ;
|
|
pcfg->hwv.jrvHardware.jpMax.dwZ = pcv->jr.jpMax.dwZ;
|
|
pcfg->hwv.dwCalFlags |= JOY_ISCAL_Z;
|
|
break;
|
|
case JCS_R_MOVE:
|
|
pcfg->hwv.jrvHardware.jpMin.dwR = pcv->jr.jpMin.dwR;
|
|
pcfg->hwv.jrvHardware.jpMax.dwR = pcv->jr.jpMax.dwR;
|
|
pcfg->hwv.dwCalFlags |= JOY_ISCAL_R;
|
|
break;
|
|
case JCS_U_MOVE:
|
|
pcfg->hwv.jrvHardware.jpMin.dwU = pcv->jr.jpMin.dwU;
|
|
pcfg->hwv.jrvHardware.jpMax.dwU = pcv->jr.jpMax.dwU;
|
|
pcfg->hwv.dwCalFlags |= JOY_ISCAL_U;
|
|
break;
|
|
case JCS_V_MOVE:
|
|
pcfg->hwv.jrvHardware.jpMin.dwV = pcv->jr.jpMin.dwV;
|
|
pcfg->hwv.jrvHardware.jpMax.dwV = pcv->jr.jpMax.dwV;
|
|
pcfg->hwv.dwCalFlags |= JOY_ISCAL_V;
|
|
break;
|
|
}
|
|
pcv->ji.dwButtons = pji->dwButtons;
|
|
return joyCalStateChange( pcv, hwnd, TRUE );
|
|
}
|
|
pcv->ji.dwButtons = pji->dwButtons;
|
|
return TRUE;
|
|
|
|
} /* joyCollectCalInfo */
|
|
|
|
/*
|
|
* joyCalibrateInitDialog - init the calibration dialog
|
|
*/
|
|
static BOOL joyCalibrateInitDialog( HWND hwnd, LPARAM lParam )
|
|
{
|
|
LPJOYREGHWCONFIG pcfg;
|
|
LPCALVARS pcv;
|
|
LPGLOBALVARS pgv;
|
|
|
|
/*
|
|
* set up calibration variables
|
|
*/
|
|
pcv = DoAlloc( sizeof( CALVARS ) );
|
|
SetWindowLong( hwnd, DWL_USER, (LONG) pcv );
|
|
if( pcv == NULL ) {
|
|
return FALSE;
|
|
}
|
|
pgv = (LPGLOBALVARS) lParam;
|
|
pcv->pgv = pgv;
|
|
|
|
/*
|
|
* init state info
|
|
*/
|
|
pcv->cState = JCS_INIT;
|
|
|
|
/*
|
|
* set dialog text based on OEM strings
|
|
*/
|
|
SetOEMText( pgv, hwnd, FALSE );
|
|
|
|
/*
|
|
* customize dialog based on Z axis, R axis, and POV hat
|
|
*/
|
|
pcfg = &pgv->joyHWCurr;
|
|
pcv->iAxisCount = 2;
|
|
if( pcfg->hws.dwFlags & JOY_HWS_HASZ ) {
|
|
pcv->iAxisCount++;
|
|
}
|
|
if( (pcfg->hws.dwFlags & JOY_HWS_HASR) || (pcfg->dwUsageSettings & JOY_US_HASRUDDER) ) {
|
|
pcv->iAxisCount++;
|
|
}
|
|
if( (pcfg->hws.dwFlags & JOY_HWS_HASPOV) &&
|
|
(pcfg->hws.dwFlags & JOY_HWS_POVISPOLL) ) {
|
|
pcv->iAxisCount++;
|
|
}
|
|
if( pcfg->hws.dwFlags & JOY_HWS_HASU ) {
|
|
pcv->iAxisCount++;
|
|
}
|
|
if( pcfg->hws.dwFlags & JOY_HWS_HASV ) {
|
|
pcv->iAxisCount++;
|
|
}
|
|
ShowControls( pcfg, hwnd );
|
|
|
|
/*
|
|
* if all axes are used and we have POV then it MUST be buttons
|
|
*/
|
|
if( pcfg->hws.dwFlags & JOY_HWS_HASPOV ) {
|
|
if( pgv->dwMaxAxes == 4 && pcv->iAxisCount == 4 ) {
|
|
pcfg->hws.dwFlags |= JOY_HWS_POVISBUTTONCOMBOS;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* other misc setup
|
|
*/
|
|
pcv->bPOVdone = FALSE;
|
|
pcv->bHasTimer = SetTimer( hwnd, TIMER_ID, JOYPOLLTIME, NULL );
|
|
pcv->bUseTimer = TRUE;
|
|
if( !pcv->bHasTimer ) {
|
|
DPF( "No timer for joystick calibration!\r\n" );
|
|
return FALSE;
|
|
}
|
|
if( !joyCalStateChange( pcv, hwnd, FALSE ) ) {
|
|
DPF( "Could not initialize joystick calibration\r\n" );
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
} /* joyCalibrateInitDialog */
|
|
|
|
/*
|
|
* setJIFlagsForPOV - get joyinfo flags to allow a raw POV poll
|
|
*/
|
|
static void setJIFlagsForPOV( LPCALVARS pcv, LPJOYREGHWCONFIG pcfg, DWORD *pflags )
|
|
{
|
|
/*
|
|
* for polled POV, we need to specifiy JOY_CAL_READ(3|4) to make
|
|
* the driver give us position values back instead of trying to
|
|
* give us a POV value back
|
|
*/
|
|
if( pcfg->hws.dwFlags & JOY_HWS_HASPOV ) {
|
|
if( pcfg->hws.dwFlags & JOY_HWS_POVISPOLL ) {
|
|
if( pcv->iAxisCount == 6 ) {
|
|
(*pflags) |= JOY_CAL_READ6;
|
|
} else if( pcv->iAxisCount == 5 ) {
|
|
(*pflags) |= JOY_CAL_READ5;
|
|
} else if( pcv->iAxisCount == 4 ) {
|
|
(*pflags) |= JOY_CAL_READ4;
|
|
} else if( pcv->iAxisCount == 3 ) {
|
|
(*pflags) |= JOY_CAL_READ3;
|
|
}
|
|
/*
|
|
* if we don't have a 3rd or 4th axis on this joystick, try reading
|
|
* another axis anyway to see if the POV hat is on it
|
|
*/
|
|
} else if( !(pcfg->hws.dwFlags & (JOY_HWS_POVISPOLL|JOY_HWS_POVISBUTTONCOMBOS)) ) {
|
|
if( pcv->iAxisCount == 5 ) {
|
|
(*pflags) |= JOY_CAL_READ6;
|
|
} else if( pcv->iAxisCount == 4 ) {
|
|
(*pflags) |= JOY_CAL_READ5;
|
|
} else if( pcv->iAxisCount == 3 ) {
|
|
(*pflags) |= JOY_CAL_READ4;
|
|
} else if( pcv->iAxisCount == 2 ) {
|
|
(*pflags) |= JOY_CAL_READ3;
|
|
}
|
|
}
|
|
}
|
|
|
|
} /* setJIFlagsForPOV */
|
|
|
|
/*
|
|
* tryPOV - try for a POV access
|
|
*/
|
|
static BOOL tryPOV( LPCALVARS pcv, HWND hwnd )
|
|
{
|
|
int rc;
|
|
BOOL ispoll;
|
|
BOOL isb;
|
|
BOOL nowaypoll;
|
|
JOYINFOEX ji;
|
|
DWORD val;
|
|
LPJOYREGHWCONFIG pcfg;
|
|
LPGLOBALVARS pgv;
|
|
int i;
|
|
|
|
pgv = pcv->pgv;
|
|
|
|
/*
|
|
* reject call if not in a POV state
|
|
*/
|
|
if( !(pcv->cState == JCS_POV_MOVEUP ||
|
|
pcv->cState == JCS_POV_MOVEDOWN ||
|
|
pcv->cState == JCS_POV_MOVELEFT ||
|
|
pcv->cState == JCS_POV_MOVERIGHT) ) {
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* take a snapshot of the current joystick state
|
|
*/
|
|
pcfg = &pgv->joyHWCurr;
|
|
nowaypoll = FALSE;
|
|
ji.dwSize = sizeof( ji );
|
|
while( 1 ) {
|
|
/*
|
|
* get joystick info
|
|
*/
|
|
ji.dwFlags = JOY_CALIB_FLAGS;
|
|
setJIFlagsForPOV( pcv, pcfg, &ji.dwFlags );
|
|
rc = joyGetPosEx( pgv->iJoyId, &ji );
|
|
if( rc == JOYERR_NOERROR ) {
|
|
break;
|
|
}
|
|
if( !(pcfg->hws.dwFlags & JOY_HWS_POVISPOLL) &&
|
|
(ji.dwFlags & (JOY_CAL_READ3|JOY_CAL_READ4|JOY_CAL_READ5|JOY_CAL_READ6)) ) {
|
|
/*
|
|
* try again, but don't ask for extra axis
|
|
*/
|
|
ji.dwFlags &= ~(JOY_CAL_READ6 | JOY_CAL_READ5 | JOY_CAL_READ4 | JOY_CAL_READ3);
|
|
rc = joyGetPosEx( pgv->iJoyId, &ji );
|
|
if( rc == JOYERR_NOERROR ) {
|
|
nowaypoll = TRUE; // pov can't possibly be polled
|
|
break;
|
|
} else {
|
|
if( !JoyError( hwnd ) ) {
|
|
return FALSE;
|
|
}
|
|
return TRUE; // have to wait for next "Select POV" to retry
|
|
}
|
|
} else {
|
|
if( !JoyError( hwnd ) ) {
|
|
return FALSE;
|
|
}
|
|
return TRUE; // have to wait for next "Select POV" to retry
|
|
}
|
|
}
|
|
|
|
/*
|
|
* here is where we determine if POV is polled or is button combos.
|
|
*
|
|
* See if we already know the answer (bits in joyHWCurr):
|
|
* if yes:
|
|
* we're done.
|
|
* if no:
|
|
* We see if there are currently multiple buttons down.
|
|
* if yes:
|
|
* POV is assumed to be button combos.
|
|
* if no:
|
|
* POV is assumed to be done with polling
|
|
*/
|
|
ispoll = FALSE;
|
|
isb = FALSE;
|
|
if( pcfg->hws.dwFlags & JOY_HWS_POVISPOLL ) {
|
|
ispoll = TRUE;
|
|
} else if( pcfg->hws.dwFlags & JOY_HWS_POVISBUTTONCOMBOS ) {
|
|
isb = TRUE;
|
|
}
|
|
if( !isb && !ispoll ) {
|
|
/*
|
|
* the type is indeterminate, so we identify it
|
|
*/
|
|
if( nowaypoll ||
|
|
((ji.dwButtons != 0) && (ji.dwButtons != JOY_BUTTON1) &&
|
|
(ji.dwButtons != JOY_BUTTON2) && (ji.dwButtons != JOY_BUTTON3) &&
|
|
(ji.dwButtons != JOY_BUTTON4)) ) {
|
|
isb = TRUE;
|
|
pcfg->hws.dwFlags |= JOY_HWS_POVISBUTTONCOMBOS;
|
|
} else {
|
|
/*
|
|
* we always assume J2 Y for a polling POV if unspecified
|
|
*/
|
|
ispoll = TRUE;
|
|
pcfg->hws.dwFlags |= JOY_HWS_POVISPOLL;
|
|
}
|
|
/*
|
|
* the driver needs to notified that we've made this decision
|
|
*/
|
|
RegSaveCurrentJoyHW( pgv );
|
|
RegistryUpdated( pgv );
|
|
}
|
|
|
|
/*
|
|
* record the data value for this POV reading
|
|
*/
|
|
if( isb ) {
|
|
val = ji.dwButtons;
|
|
} else {
|
|
if( !(pcfg->hws.dwFlags & JOY_HWS_HASZ) ) {
|
|
val = ji.dwZpos;
|
|
} else {
|
|
val = ji.dwRpos;
|
|
}
|
|
}
|
|
switch( pcv->cState ) {
|
|
case JCS_POV_MOVEUP:
|
|
pcv->pov[JOY_POVVAL_FORWARD] = val;
|
|
break;
|
|
case JCS_POV_MOVERIGHT:
|
|
pcv->pov[JOY_POVVAL_RIGHT] = val;
|
|
break;
|
|
case JCS_POV_MOVEDOWN:
|
|
pcv->pov[JOY_POVVAL_BACKWARD] = val;
|
|
break;
|
|
case JCS_POV_MOVELEFT:
|
|
pcv->pov[JOY_POVVAL_LEFT] = val;
|
|
/*
|
|
* since this was the last POV thing to calibrate, we need
|
|
* to save the calibration info
|
|
*/
|
|
for( i=0;i<JOY_POV_NUMDIRS;i++ ) {
|
|
pcfg->hwv.dwPOVValues[i] = pcv->pov[i];
|
|
}
|
|
pcfg->hwv.dwCalFlags |= JOY_ISCAL_POV;
|
|
pcv->bPOVdone = TRUE;
|
|
break;
|
|
}
|
|
return joyCalStateChange( pcv, hwnd, TRUE );
|
|
|
|
} /* tryPOV */
|
|
|
|
/*
|
|
* FixCustomPOVType - fix custom POV type info if POV wasn't calibrated;
|
|
* called by test dlg to update config
|
|
*/
|
|
void FixCustomPOVType( LPCALVARS pcv )
|
|
{
|
|
if( !pcv->bPOVdone ) {
|
|
resetCustomPOVFlags( pcv->pgv, &pcv->pgv->joyHWCurr );
|
|
}
|
|
|
|
} /* FixCustomPOVType */
|
|
|
|
/*
|
|
* CalibrateProc - calibrate a joystick
|
|
*/
|
|
BOOL CALLBACK CalibrateProc( HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
BOOL rc;
|
|
|
|
switch( umsg ) {
|
|
case WM_TIMER:
|
|
{
|
|
LPCALVARS pcv;
|
|
|
|
pcv = (LPCALVARS) GetWindowLong( hwnd, DWL_USER );
|
|
if( pcv->bUseTimer ) {
|
|
JOYINFOEX ji;
|
|
MMRESULT rc;
|
|
LPJOYREGHWCONFIG pcfg;
|
|
LPGLOBALVARS pgv;
|
|
|
|
pgv = pcv->pgv;
|
|
pcv->bUseTimer = FALSE;
|
|
ji.dwSize = sizeof( ji );
|
|
while( 1 ) {
|
|
/*
|
|
* get current joystick info
|
|
*/
|
|
ji.dwFlags = JOY_CALIB_FLAGS;
|
|
pcfg = &pgv->joyHWCurr;
|
|
setJIFlagsForPOV( pcv, pcfg, &ji.dwFlags );
|
|
rc = joyGetPosEx( pgv->iJoyId, &ji );
|
|
if( rc == JOYERR_NOERROR ) {
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* didn't work, try without extra POV axis
|
|
*/
|
|
if( !(pcfg->hws.dwFlags & JOY_HWS_POVISPOLL) &&
|
|
(ji.dwFlags & (JOY_CAL_READ3|JOY_CAL_READ4|JOY_CAL_READ5|JOY_CAL_READ6)) ) {
|
|
ji.dwFlags &= ~(JOY_CAL_READ6 | JOY_CAL_READ5 | JOY_CAL_READ4 | JOY_CAL_READ3);
|
|
rc = joyGetPosEx( pgv->iJoyId, &ji );
|
|
if( rc == JOYERR_NOERROR ) {
|
|
break;
|
|
}
|
|
}
|
|
if( !JoyError( hwnd ) ) {
|
|
/*
|
|
* return now if cancel selected; don't turn back
|
|
* on the timer
|
|
*/
|
|
return FALSE;
|
|
}
|
|
continue;
|
|
}
|
|
if( rc == JOYERR_NOERROR ) {
|
|
joyCollectCalInfo( pcv, hwnd, &ji );
|
|
}
|
|
/*
|
|
* If we've started POV calibration, we need to look at the
|
|
* keyboard and ignore joystick, so don't turn the timer
|
|
* back on if we've started the POV calibration
|
|
*/
|
|
if( pcv->cState < JCS_POV_MOVEUP ) {
|
|
pcv->bUseTimer = TRUE;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case WM_DESTROY:
|
|
{
|
|
LPCALVARS pcv;
|
|
pcv = (LPCALVARS) GetWindowLong( hwnd, DWL_USER );
|
|
DoFree( pcv );
|
|
break;
|
|
}
|
|
|
|
case WM_INITDIALOG:
|
|
{
|
|
LPCALVARS pcv;
|
|
|
|
rc = joyCalibrateInitDialog( hwnd, lParam );
|
|
if( !rc ) {
|
|
pcv = (LPCALVARS) GetWindowLong( hwnd, DWL_USER );
|
|
if( pcv != NULL && pcv->bHasTimer ) {
|
|
KillTimer( hwnd, TIMER_ID );
|
|
pcv->bHasTimer = FALSE;
|
|
}
|
|
EndDialog( hwnd, 0 );
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
case WM_PAINT:
|
|
{
|
|
LPCALVARS pcv;
|
|
pcv = (LPCALVARS) GetWindowLong( hwnd, DWL_USER );
|
|
CauseRedraw( &pcv->ji, FALSE );
|
|
return FALSE;
|
|
}
|
|
|
|
case WM_COMMAND:
|
|
{
|
|
int id;
|
|
LPCALVARS pcv;
|
|
|
|
pcv = (LPCALVARS) GetWindowLong( hwnd, DWL_USER );
|
|
id = GET_WM_COMMAND_ID(wParam, lParam);
|
|
switch( id ) {
|
|
case IDC_JOYTEST:
|
|
{
|
|
BOOL timeon;
|
|
|
|
timeon = pcv->bUseTimer;
|
|
pcv->bUseTimer = FALSE;
|
|
DoTest( pcv->pgv, hwnd, FixCustomPOVType, pcv );
|
|
pcv->bUseTimer = timeon;
|
|
break;
|
|
}
|
|
case IDCANCEL:
|
|
// fall through
|
|
case IDC_JOYCALDONE:
|
|
if( pcv->bHasTimer ) {
|
|
KillTimer( hwnd, TIMER_ID );
|
|
pcv->bHasTimer = FALSE;
|
|
}
|
|
{
|
|
LPJOYREGHWCONFIG pcfg;
|
|
pcfg = &pcv->pgv->joyHWCurr;
|
|
}
|
|
EndDialog( hwnd, (id == IDC_JOYCALDONE) );
|
|
break;
|
|
case IDC_JOYPICKPOV:
|
|
if( !tryPOV( pcv, hwnd ) ) {
|
|
HWND hwb;
|
|
hwb = GetDlgItem( hwnd, IDC_JOYPICKPOV );
|
|
ShowWindow( hwb, SW_HIDE );
|
|
EnableWindow( hwb, FALSE );
|
|
}
|
|
break;
|
|
|
|
case IDC_JOYCALNEXT:
|
|
pcv->bUseTimer = TRUE;
|
|
joyCalStateSkip( pcv, hwnd );
|
|
break;
|
|
|
|
case IDC_JOYCALBACK:
|
|
pcv->bUseTimer = TRUE;
|
|
joyCalStateBack( pcv, hwnd );
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return FALSE;
|
|
|
|
} /* CalibrateProc */
|
|
|
|
/*
|
|
* DoCalibrate - do the calibration dialog
|
|
*/
|
|
void DoCalibrate( LPGLOBALVARS pgv, HWND hwnd )
|
|
{
|
|
JOYREGHWCONFIG save_joycfg;
|
|
int rc;
|
|
int id;
|
|
|
|
/*
|
|
* save the current config, and then add the rudder if it is present
|
|
*/
|
|
save_joycfg = pgv->joyHWCurr;
|
|
|
|
/*
|
|
* if this is a custom joystick, then don't assume anything
|
|
* about how the POV is set up
|
|
*/
|
|
if( pgv->joyHWCurr.dwType == JOY_HW_CUSTOM ) {
|
|
pgv->bOrigPOVIsPoll = (pgv->joyHWCurr.hws.dwFlags & JOY_HWS_POVISPOLL);
|
|
pgv->bOrigPOVIsButtonCombos = (pgv->joyHWCurr.hws.dwFlags & JOY_HWS_POVISBUTTONCOMBOS);
|
|
pgv->joyHWCurr.hws.dwFlags &= ~(JOY_HWS_POVISPOLL|JOY_HWS_POVISBUTTONCOMBOS);
|
|
}
|
|
|
|
/*
|
|
* update the registry with our new joystick info
|
|
*/
|
|
RegSaveCurrentJoyHW( pgv );
|
|
RegistryUpdated( pgv );
|
|
|
|
if( pgv->joyHWCurr.hws.dwFlags & (JOY_HWS_HASU|JOY_HWS_HASV) ) {
|
|
id = IDD_JOYCALIBRATE1;
|
|
} else {
|
|
id = IDD_JOYCALIBRATE;
|
|
}
|
|
rc = DialogBoxParam((HINSTANCE)GetWindowLong( hwnd, GWL_HINSTANCE ),
|
|
MAKEINTRESOURCE( id ), hwnd, CalibrateProc, (LONG) pgv );
|
|
|
|
/*
|
|
* update the registry with the new info or the old info
|
|
*/
|
|
if( rc ) {
|
|
PropSheet_Changed( GetParent(hwnd), hwnd );
|
|
} else {
|
|
pgv->joyHWCurr = save_joycfg;
|
|
}
|
|
RegSaveCurrentJoyHW( pgv );
|
|
RegistryUpdated( pgv );
|
|
|
|
} /* DoCalibrate */
|