Joystick v1.0, Windows, 6 axes, 32 button, POV, deadzones
Posted: Tue Sep 27, 2011 9:34 am
Code: Select all
;Joystick Include v1.0 (c) Roger Hågensen, EmSai 2011.
;zlib license, http://en.wikipedia.org/wiki/Zlib_license
;Warning!
;structures and fields marked ;Internal are just that, they are used by the joystick functions() or the OS API.
;structures or fields marked as ;Readable can be read but must not be written to directly.
;structures or fields marked as ;Writable can be written to but must not be read from directly.
;structures or fields marked ;Readable/Writable can be read and/or written to directly.
Structure JOYSTICK_INFO_CAPS ;Internal
wPeriodMin.l
wPeriodMax.l
wNumButtons.l
wNumAxes.l
wXmin.l
wXmax.l
wYmin.l
wYmax.l
wZmin.l
wZmax.l
wRmin.l
wRmax.l
wUmin.l
wUmax.l
wVmin.l
wVmax.l
wPOV.l
wMid.w
wPid.w
name.s
EndStructure
Structure JOYSTICK_INFO_DEADZONE ;Internal/Debugging
c.f ;Readable
e.f ;Readable
EndStructure
Structure JOYSTICK_INFO
x.f ;Readable
y.f ;Readable
z.f ;Readable
r.f ;Readable
u.f ;Readable
v.f ;Readable
pov.f ;Readable
button.f[32] ;Readable
;The following fields may or may not be changed in the future.
deadzonex.JOYSTICK_INFO_DEADZONE ;Internal
deadzoney.JOYSTICK_INFO_DEADZONE ;Internal
deadzonez.JOYSTICK_INFO_DEADZONE ;Internal
deadzoner.JOYSTICK_INFO_DEADZONE ;Internal
deadzoneu.JOYSTICK_INFO_DEADZONE ;Internal
deadzonev.JOYSTICK_INFO_DEADZONE ;Internal
;The following fields are internal only, and may change at any time.
id.i ;Internal
jic.JOYSTICK_INFO_CAPS ;Internal
pji.JOYINFOEX ;Internal
EndStructure
Procedure.i Joystick_Alloc(joystick.i)
Protected *jsi.JOYSTICK_INFO,pji.JOYINFOEX,pjc.JOYCAPS,error,text$,hkey.i,regtype.l,regsize.l
pji\dwSize=SizeOf(JOYINFOEX)
pji\dwFlags=#JOY_RETURNALL|#JOY_RETURNPOVCTS
If joyGetPosEx_(joystick,pji)=#JOYERR_NOERROR
error=joyGetDevCaps_(joystick,pjc,SizeOf(JOYCAPS))
If error=#JOYERR_NOERROR
*jsi=AllocateMemory(SizeOf(JOYSTICK_INFO))
If *jsi
*jsi\id=joystick
*jsi\jic\name="Joystick/Gamepad "+Str(joystick+1)
text$="System\CurrentControlSet\Control\MediaProperties\PrivateProperties\Joystick\OEM\VID_"+RSet(Hex(pjc\wMid,#PB_Word),4,"0")+"&PID_"+RSet(Hex(pjc\wPid,#PB_Word),4,"0")
If RegOpenKeyEx_(#HKEY_CURRENT_USER,text$,#Null,#KEY_QUERY_VALUE,@hkey)=#ERROR_SUCCESS
If RegQueryValueEx_(hkey,"OEMName",#Null,#Null,#Null,@regsize)=#ERROR_SUCCESS
text$=Space(regsize+1)
If RegQueryValueEx_(hkey,"OEMName",#Null,@regtype,@text$,@regsize)=#ERROR_SUCCESS
If regtype=#REG_SZ
*jsi\jic\name=Left(text$,255)
EndIf
EndIf
EndIf
RegCloseKey_(hkey)
EndIf
*jsi\jic\wMid=pjc\wMid
*jsi\jic\wPid=pjc\wPid
*jsi\jic\wPeriodMin=pjc\wPeriodMin
*jsi\jic\wPeriodMax=pjc\wPeriodMax
*jsi\jic\wNumButtons=pjc\wNumButtons
*jsi\jic\wNumAxes=pjc\wNumAxes
*jsi\jic\wXmin=pjc\wXmin
*jsi\jic\wXmax=pjc\wXmax
*jsi\jic\wYmin=pjc\wYmin
*jsi\jic\wYmax=pjc\wYmax
If (pjc\wCaps&#JOYCAPS_HASPOV)
*jsi\jic\wPOV=#True
EndIf
If (pjc\wCaps&#JOYCAPS_HASZ)
*jsi\jic\wZmin=pjc\wZmin
*jsi\jic\wZmax=pjc\wZmax
EndIf
If (pjc\wCaps&#JOYCAPS_HASR)
*jsi\jic\wRmin=pjc\wRmin
*jsi\jic\wRmax=pjc\wRmax
EndIf
If (pjc\wCaps&#JOYCAPS_HASU)
*jsi\jic\wUmin=pjc\wUmin
*jsi\jic\wUmax=pjc\wUmax
EndIf
If (pjc\wCaps&#JOYCAPS_HASV)
*jsi\jic\wVmin=pjc\wVmin
*jsi\jic\wVmax=pjc\wVmax
EndIf
*jsi\pji\dwSize=SizeOf(JOYINFOEX)
*jsi\pji\dwFlags=#JOY_RETURNALL|#JOY_RETURNPOVCTS
EndIf
EndIf
EndIf
ProcedureReturn *jsi
EndProcedure
Procedure.i Joystick_Free(*jsi.JOYSTICK_INFO)
If *jsi
FreeMemory(*jsi)
EndIf
ProcedureReturn #Null
EndProcedure
Procedure.i Joystick_Update(*jsi.JOYSTICK_INFO)
Protected result.i,value.l,min.l,max.l,n.i,i.i
If *jsi
If JoyGetPosEx_(*jsi\id,*jsi\pji)=#JOYERR_NOERROR
min=*jsi\jic\wXmin
max=*jsi\jic\wXmax
value=*jsi\pji\dwXpos
If value<=min
value=0
ElseIf value>=max
value=65535
EndIf
;Note! Centered is actually 32767 while it ideally should be 32767.5, which is why this adjustment is needed.
If value<32768
value-32767
Else
value-32768
EndIf
*jsi\x=value/32767.0
If *jsi\deadzonex\c Or *jsi\deadzonex\e
If Abs(*jsi\x)<*jsi\deadzonex\c
*jsi\x=0.0
ElseIf *jsi\x>(1.0-*jsi\deadzonex\e)
*jsi\x=1.0
ElseIf *jsi\x<(-1.0+*jsi\deadzonex\e)
*jsi\x=-1.0
EndIf
EndIf
min=*jsi\jic\wYmin
max=*jsi\jic\wYmax
value=*jsi\pji\dwYpos
If value<=min
value=0
ElseIf value>=max
value=65535
EndIf
If value<32768
value-32767
Else
value-32768
EndIf
*jsi\y=value/32767.0
If *jsi\deadzoney\c Or *jsi\deadzoney\e
If Abs(*jsi\y)<*jsi\deadzoney\c
*jsi\y=0.0
ElseIf *jsi\y>(1.0-*jsi\deadzoney\e)
*jsi\y=1.0
ElseIf *jsi\y<(-1.0+*jsi\deadzoney\e)
*jsi\y=-1.0
EndIf
EndIf
min=*jsi\jic\wZmin
max=*jsi\jic\wZmax
If min|max
value=*jsi\pji\dwZpos
If value<=min
value=0
ElseIf value>=max
value=65535
EndIf
If value<32768
value-32767
Else
value-32768
EndIf
*jsi\z=value/32767.0
If *jsi\deadzonez\c Or *jsi\deadzonez\e
If Abs(*jsi\z)<*jsi\deadzonez\c
*jsi\z=0.0
ElseIf *jsi\z>(1.0-*jsi\deadzonez\e)
*jsi\z=1.0
ElseIf *jsi\z<(-1.0+*jsi\deadzonez\e)
*jsi\z=-1.0
EndIf
EndIf
EndIf
min=*jsi\jic\wRmin
max=*jsi\jic\wRmax
If min|max
value=*jsi\pji\dwRpos
If value<=min
value=0
ElseIf value>=max
value=65535
EndIf
If value<32768
value-32767
Else
value-32768
EndIf
*jsi\r=value/32767.0
If *jsi\deadzoner\c Or *jsi\deadzoner\e
If Abs(*jsi\r)<*jsi\deadzoner\c
*jsi\r=0.0
ElseIf *jsi\r>(1.0-*jsi\deadzoner\e)
*jsi\r=1.0
ElseIf *jsi\r<(-1.0+*jsi\deadzoner\e)
*jsi\r=-1.0
EndIf
EndIf
EndIf
min=*jsi\jic\wUmin
max=*jsi\jic\wUmax
If min|max
value=*jsi\pji\dwUpos
If value<=min
value=0
ElseIf value>=max
value=65535
EndIf
If value<32768
value-32767
Else
value-32768
EndIf
*jsi\u=value/32767.0
If *jsi\deadzoneu\c Or *jsi\deadzoneu\e
If Abs(*jsi\u)<*jsi\deadzoneu\c
*jsi\u=0.0
ElseIf *jsi\u>(1.0-*jsi\deadzoneu\e)
*jsi\u=1.0
ElseIf *jsi\u<(-1.0+*jsi\deadzoneu\e)
*jsi\u=-1.0
EndIf
EndIf
EndIf
min=*jsi\jic\wVmin
max=*jsi\jic\wVmax
If min|max
value=*jsi\pji\dwVpos
If value<=min
value=0
ElseIf value>=max
value=65535
EndIf
If value<32768
value-32767
Else
value-32768
EndIf
*jsi\v=value/32767.0
If *jsi\deadzonev\c Or *jsi\deadzonev\e
If Abs(*jsi\v)<*jsi\deadzonev\c
*jsi\v=0.0
ElseIf *jsi\v>(1.0-*jsi\deadzonev\e)
*jsi\v=1.0
ElseIf *jsi\v<(-1.0+*jsi\deadzonev\e)
*jsi\v=-1.0
EndIf
EndIf
EndIf
If *jsi\jic\wPOV
value=*jsi\pji\dwPOV
If value=0
value=36000
ElseIf value<1 Or value>35999
value=0
EndIf
*jsi\pov=value/36000.0
;no deadzone as this is a digital input rather than analog
EndIf
n=*jsi\jic\wNumButtons-1
For i=0 To n
If *jsi\pji\dwButtons&(1<<i)
*jsi\button[i]=1.0
Else
*jsi\button[i]=0.0
EndIf
;no deadzone as this is a digital input rather than analog
Next
result=#True
Else
*jsi\pov=0.0
*jsi\x=0.0
*jsi\y=0.0
*jsi\z=0.0
*jsi\r=0.0
*jsi\u=0.0
*jsi\v=0.0
n=*jsi\jic\wNumButtons-1
For i=0 To n
*jsi\button[i]=0.0
Next
EndIf
EndIf
ProcedureReturn result
EndProcedure
Procedure.i Joystick_Count()
Protected result.i,pji.JOYINFOEX,i.i
pji\dwSize=SizeOf(JOYINFOEX)
While joyGetPosEx_(i,pji)=#JOYERR_NOERROR
i+1
result+1
Wend
ProcedureReturn result
EndProcedure
Procedure.s Joystick_OEMName(*jsi.JOYSTICK_INFO)
Protected result.s
If *jsi
result=*jsi\jic\name
EndIf
ProcedureReturn result
EndProcedure
Procedure.i Joystick_OEMID(*jsi.JOYSTICK_INFO)
Protected result.i
If *jsi
result=(*jsi\jic\wMid<<16)|*jsi\jic\wPid
EndIf
ProcedureReturn result
EndProcedure
Procedure.i Joystick_ButtonCount(*jsi.JOYSTICK_INFO)
Protected result.i
If *jsi
result=*jsi\jic\wNumButtons
EndIf
ProcedureReturn result
EndProcedure
Procedure.i Joystick_AxesCount(*jsi.JOYSTICK_INFO)
Protected result.i
If *jsi
result=*jsi\jic\wNumAxes
EndIf
ProcedureReturn result
EndProcedure
Procedure.i Joystick_HasPOV(*jsi.JOYSTICK_INFO)
Protected result.i
If *jsi
result=*jsi\jic\wPOV
EndIf
ProcedureReturn result
EndProcedure
Procedure.i Joystick_HasZ(*jsi.JOYSTICK_INFO)
Protected result.i
If *jsi
If *jsi\jic\wZmin|*jsi\jic\wZmax
result=#True
EndIf
EndIf
ProcedureReturn result
EndProcedure
Procedure.i Joystick_HasR(*jsi.JOYSTICK_INFO)
Protected result.i
If *jsi
If *jsi\jic\wRmin|*jsi\jic\wRmax
result=#True
EndIf
EndIf
ProcedureReturn result
EndProcedure
Procedure.i Joystick_HasU(*jsi.JOYSTICK_INFO)
Protected result.i
If *jsi
If *jsi\jic\wUmin|*jsi\jic\wUmax
result=#True
EndIf
EndIf
ProcedureReturn result
EndProcedure
Procedure.i Joystick_HasV(*jsi.JOYSTICK_INFO)
Protected result.i
If *jsi
If *jsi\jic\wVmin|*jsi\jic\wVmax
result=#True
EndIf
EndIf
ProcedureReturn result
EndProcedure
#JOYSTICK_DEADZONE_ALL=0
#JOYSTICK_DEADZONE_X=1
#JOYSTICK_DEADZONE_Y=2
#JOYSTICK_DEADZONE_Z=3
#JOYSTICK_DEADZONE_R=4
#JOYSTICK_DEADZONE_U=5
#JOYSTICK_DEADZONE_V=6
Procedure.i Joystick_Deadzone(*jsi.JOYSTICK_INFO,deadzone_c.f,deadzone_e.f,axis.i)
Protected result.i
If *jsi
deadzone_c=Abs(deadzone_c)
If deadzone_c>0.5
deadzone_c=0.5
EndIf
deadzone_e=Abs(deadzone_e)
If deadzone_e>0.5
deadzone_e=0.5
EndIf
If axis=#JOYSTICK_DEADZONE_ALL
*jsi\deadzonex\c=deadzone_c
*jsi\deadzonex\e=deadzone_e
*jsi\deadzoney\c=deadzone_c
*jsi\deadzoney\e=deadzone_e
*jsi\deadzonez\c=deadzone_c
*jsi\deadzonez\e=deadzone_e
*jsi\deadzoner\c=deadzone_c
*jsi\deadzoner\e=deadzone_e
*jsi\deadzoneu\c=deadzone_c
*jsi\deadzoneu\e=deadzone_e
*jsi\deadzonev\c=deadzone_c
*jsi\deadzonev\e=deadzone_e
ElseIf axis=#JOYSTICK_DEADZONE_X
*jsi\deadzonex\c=deadzone_c
*jsi\deadzonex\e=deadzone_e
ElseIf axis=#JOYSTICK_DEADZONE_Y
*jsi\deadzoney\c=deadzone_c
*jsi\deadzoney\e=deadzone_e
ElseIf axis=#JOYSTICK_DEADZONE_Z
*jsi\deadzonez\c=deadzone_c
*jsi\deadzonez\e=deadzone_e
ElseIf axis=#JOYSTICK_DEADZONE_R
*jsi\deadzoner\c=deadzone_c
*jsi\deadzoner\e=deadzone_e
ElseIf axis=#JOYSTICK_DEADZONE_U
*jsi\deadzoneu\c=deadzone_c
*jsi\deadzoneu\e=deadzone_e
ElseIf axis=#JOYSTICK_DEADZONE_V
*jsi\deadzonev\c=deadzone_c
*jsi\deadzonev\e=deadzone_e
EndIf
result=#True
EndIf
ProcedureReturn result
EndProcedure
Procedure.i Joystick_GetDeadzone(*jsi.JOYSTICK_INFO,axis.i)
Protected result.i
If *jsi
If axis=#JOYSTICK_DEADZONE_X
result=*jsi\deadzonex
ElseIf axis=#JOYSTICK_DEADZONE_Y
result=*jsi\deadzoney
ElseIf axis=#JOYSTICK_DEADZONE_Z
result=*jsi\deadzonez
ElseIf axis=#JOYSTICK_DEADZONE_R
result=*jsi\deadzoner
ElseIf axis=#JOYSTICK_DEADZONE_U
result=*jsi\deadzoneu
ElseIf axis=#JOYSTICK_DEADZONE_V
result=*jsi\deadzonev
EndIf
EndIf
ProcedureReturn result
EndProcedure