├── .gitignore ├── README.md ├── example.ahk └── VJoy_lib.ahk /.gitignore: -------------------------------------------------------------------------------- 1 | *.ini 2 | *.exe 3 | *.zip 4 | *.lnk 5 | *.scc 6 | *.png 7 | *.tmp.* -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | AHK-vJoy-Library 2 | ================ 3 | 4 | A library for AutoHotkey to enable controlling a vJoy virtual Joystick. 5 | 6 | For Shaul's vJoy - http://vjoystick.sourceforge.net 7 | 8 | Compatible with x64 and x86 - even x86 compiled scripts running on an x64 OS... 9 | 10 | Based on code by Axlar - http://www.autohotkey.com/board/topic/87690- 11 | 12 | 13 | 14 | 15 | Requirements 16 | ============ 17 | AutoHotkey obviously, but scripts can be compiled to remove this requirement. 18 | 19 | vJoy installed. 20 | 21 | Detects if vJoy installed by checking registry key. 22 | 23 | Locates correct (x86 /x64) vJoyInterface.dll from Registry key. 24 | 25 | Warns user if no DLL found / all failed to load, and optionally launches browser window to vJoy site. 26 | -------------------------------------------------------------------------------- /example.ahk: -------------------------------------------------------------------------------- 1 | #SingleInstance, force 2 | #include vjoy_lib.ahk 3 | 4 | ; Set the vjoy id of the stick to control 5 | vjoy_id := 1 6 | 7 | ; Init the vJoy stick 8 | vjoy_init(vjoy_id) 9 | 10 | ; Check X axis exists on stick 11 | if (!VJoy_GetAxisExist_X(vjoy_id)){ 12 | msgbox Please enable the X axis of vjoy ID %vjoy_id% using the vJoy config utility. 13 | } 14 | 15 | ; Find out how many buttons we have access to 16 | max_buttons := VJoy_GetVJDButtonNumber(vjoy_id) 17 | 18 | ; HOTKEYS === 19 | ; Pulse a random Button 20 | F11:: 21 | ; Decide which button to press 22 | Random, btn, 1, max_buttons 23 | 24 | ; Press the button 25 | VJoy_SetBtn(1, vjoy_id, btn) 26 | 27 | ; Wait a while 28 | Sleep 500 29 | 30 | ; Release the button 31 | VJoy_SetBtn(0, vjoy_id, btn) 32 | Return 33 | 34 | 35 | ; Move the x axis by a random amount 36 | F12:: 37 | ; Pick a number between 0 and 32767 and store it in val 38 | Random, val, 0, 32767 39 | 40 | ; Set axis value 41 | VJoy_SetAxis(val, vjoy_id, HID_USAGE_X) 42 | return 43 | 44 | 45 | -------------------------------------------------------------------------------- /VJoy_lib.ahk: -------------------------------------------------------------------------------- 1 | ; VJoy_lib.ahk 2 | ; Original code by Axlar - http://www.autohotkey.com/board/topic/87690- 3 | ; modded by evilC: 4 | ; VJoy_SetAxis fix (Bad ternary operator) 5 | ; Reworking of VJoy_LoadLibrary 6 | 7 | VJD_MAXDEV := 16 8 | 9 | ; ported from VjdStat in vjoyinterface.h 10 | VJD_STAT_OWN := 0 ; The vJoy Device is owned by this application. 11 | VJD_STAT_FREE := 1 ; The vJoy Device is NOT owned by any application (including this one). 12 | VJD_STAT_BUSY := 2 ; The vJoy Device is owned by another application. It cannot be acquired by this application. 13 | VJD_STAT_MISS := 3 ; The vJoy Device is missing. It either does not exist or the driver is down. 14 | VJD_STAT_UNKN := 4 ; Unknown 15 | 16 | ; HID Descriptor definitions(ported from public.h 17 | HID_USAGE_X := 0x30 18 | HID_USAGE_Y := 0x31 19 | HID_USAGE_Z := 0x32 20 | HID_USAGE_RX:= 0x33 21 | HID_USAGE_RY:= 0x34 22 | HID_USAGE_RZ:= 0x35 23 | HID_USAGE_SL0:= 0x36 24 | HID_USAGE_SL1:= 0x37 25 | 26 | VJDev := Object() 27 | 28 | ; Load lib from already load or current/system directory 29 | VJoy_LoadLibrary() { 30 | Global hVJDLL 31 | 32 | if (hVJDLL) { 33 | return hVJDLL 34 | } 35 | ; Find vJoy install folder by looking for registry key. 36 | vJoyFolder := RegRead64("HKEY_LOCAL_MACHINE", "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{8E31F76F-74C3-47F1-9550-E041EEDC5FBB}_is1", "InstallLocation") 37 | if (!vJoyFolder){ 38 | msgbox 4, ERROR, % "ERROR: Could not find the vJoy Registry Key.`n`nvJoy does not appear to be installed.`nPlease ensure you have installed vJoy from`n`nhttp://vjoystick.sourceforge.net.`n`nDo you wish to open a browser window to the site now?" 39 | IfMsgBox, Yes 40 | Run http://vjoystick.sourceforge.net 41 | ExitApp 42 | } 43 | 44 | ; Try to find location of correct DLL. 45 | ; vJoy versions prior to 2.0.4 241214 lack these registry keys - if key not found, advise update. 46 | if (A_PtrSize == 8){ 47 | ; 64-Bit AHK 48 | DllFolder := RegRead64("HKEY_LOCAL_MACHINE", "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{8E31F76F-74C3-47F1-9550-E041EEDC5FBB}_is1", "DllX64Location") 49 | } else { 50 | ; 32-Bit AHK 51 | DllFolder := RegRead64("HKEY_LOCAL_MACHINE", "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{8E31F76F-74C3-47F1-9550-E041EEDC5FBB}_is1", "DllX86Location") 52 | } 53 | 54 | if (!DllFolder){ 55 | ; Could not find registry entry. Advise vJoy update. 56 | msgbox, 4, ERROR, % "A vJoy install was found in " vJoyFolder ", but it appears to be an old version.`nPlease update vJoy to the latest version from `n`nhttp://vjoystick.sourceforge.net.`n`nDo you wish to open a browser window to the site now?" 57 | IfMsgBox, Yes 58 | Run http://vjoystick.sourceforge.net 59 | ExitApp 60 | } 61 | 62 | DllFolder .= "\" 63 | 64 | DllFile := "vJoyInterface.dll" 65 | 66 | x86 := "x86\" 67 | x64 := "x64\" 68 | 69 | ErrorReport := "Trying to locate correct " DllFile "...`nLooking in " DllFolder " ... " 70 | if (FileExist(DllFolder DllFile)){ 71 | ErrorReport .= "FOUND. Loading... " 72 | ; Try loading DLL from x64 folder 73 | hVJDLL := DLLCall("LoadLibrary", "Str", DllFolder DllFile) 74 | if (hVJDLL) { 75 | ErrorReport .= "OK.`n" 76 | } else { 77 | ErrorReport .= "FAILED.`n" 78 | } 79 | } else { 80 | ErrorReport .= "NOT FOUND.`n" 81 | } 82 | if (!hVJDLL) { 83 | MsgBox % "Failed to load interface DLL.`n`n" ErrorReport 84 | return 0 85 | } 86 | return hVJDLL 87 | } 88 | 89 | GetFileVersion(pszFilePath) { 90 | dwSize := DLLCall("Version\GetFileVersionInfoSize", "Str", pszFilePath) 91 | if (!dwSize) { 92 | return 93 | } 94 | VarSetCapacity(pvData, dwSize) 95 | if (!DLLCall("Version\GetFileVersionInfo", "Str", pszFilePath 96 | , "Int", 0, "Int", dwSize, "Ptr", &pvData)) { 97 | return 98 | } 99 | ; Get British product version string 100 | if (!DLLCall("Version\VerQueryValue", "UInt", &pvData, "Str" 101 | , "\\StringFileInfo\\040904b0\\ProductVersion", "UIntP" 102 | , lpTranslate, "UInt", 0)) { 103 | return 104 | } 105 | return StrGet(lpTranslate) 106 | } 107 | 108 | Class VJoyDev { 109 | __New(dev_id) { 110 | 111 | Global NoticeDone, hVJDLL, VJD_STAT_OWN, VJD_STAT_FREE, VJD_STAT_BUSY, VJD_STAT_MISS, VJD_STAT_UNKN,HID_USAGE_X,HID_USAGE_Y,HID_USAGE_Z,HID_USAGE_RX,HID_USAGE_RY,HID_USAGE_RZ,HID_USAGE_SL0,HID_USAGE_SL1 112 | 113 | if (!hVJDLL) { 114 | hVJDLL := VJoy_LoadLibrary() 115 | } 116 | if (!hVJDLL) { 117 | if (!NoticeDone) { 118 | NoticeDone := True 119 | MsgBox, [VJoy Constructer] LoadLibrary vJoyInterface.dll failed! 120 | } 121 | return 122 | } 123 | 124 | this.DeviceEnabled := DllCall("vJoyInterface.dll\vJoyEnabled") 125 | if (ErrorLevel = 4) { 126 | MsgBox, Error! VJoy library "vJoyInterface.dll" is not found!`nErrorLevel:%ErrorLevel% 127 | return 128 | } 129 | if (!this.DeviceEnabled) { 130 | ;MsgBox, Error! VJoy interface is not installed!`nErrorLevel:%ErrorLevel% 131 | return 132 | } 133 | 134 | DeviceStatus := DllCall("vJoyInterface\GetVJDStatus", "UInt", dev_id) 135 | if (DeviceStatus = VJD_STAT_OWN) { 136 | stat_str = VJD_STAT_OWN 137 | ;ToolTip, vJoy Device %dev_id% is already owned by this feeder 138 | } else if (DeviceStatus = VJD_STAT_FREE) { 139 | ;ToolTip, vJoy Device %dev_id% is free 140 | stat_str = VJD_STAT_FREE 141 | } else if (DeviceStatus = VJD_STAT_BUSY) { 142 | ;MsgBox vJoy Device %dev_id% is already owned by another feeder`nCannot continue`n 143 | stat_str = VJD_STAT_BUSY 144 | return 145 | } else if (DeviceStatus = VJD_STAT_MISS) { 146 | ;MsgBox vJoy Device %dev_id% is not installed or disabled`nCannot continue`n 147 | stat_str = VJD_STAT_MISS 148 | return 149 | } else { 150 | stat_str = VJD_STAT_UNKN 151 | MsgBox vJoy Device %dev_id% general error`nCannot continue`n 152 | return 153 | } 154 | ;ToolTip 155 | 156 | ; Get the number of buttons and POV Hat switchessupported by this vJoy device 157 | this.ContPovNumber := DllCall("vJoyInterface\GetVJDContPovNumber", "UInt", dev_id) 158 | this.ContPov := Object() 159 | Loop, % this.ContPovNumber ; insert dummy 160 | this.ContPov.Insert(A_Index, 0) 161 | 162 | this.DiscPovNumber := DllCall("vJoyInterface\GetVJDDiscPovNumber", "UInt", dev_id) 163 | this.DiscPov := Object() 164 | Loop, % this.DiscPovNumber ; insert dummy 165 | this.DiscPov.Insert(A_Index, 0) 166 | 167 | this.NumberOfButtons := DllCall("vJoyInterface\GetVJDButtonNumber", "Int", dev_id) 168 | this.Btn := Object() 169 | Loop, % this.NumberOfButtons ; insert dummy 170 | this.Btn.Insert(A_Index, 0) 171 | 172 | this.AxisExist_X := DllCall("vJoyInterface\GetVJDAxisExist", "Int", dev_id, "Int", HID_USAGE_X ) 173 | this.AxisExist_Y := DllCall("vJoyInterface\GetVJDAxisExist", "Int", dev_id, "Int", HID_USAGE_Y ) 174 | this.AxisExist_Z := DllCall("vJoyInterface\GetVJDAxisExist", "Int", dev_id, "Int", HID_USAGE_Z ) 175 | this.AxisExist_RX := DllCall("vJoyInterface\GetVJDAxisExist", "Int", dev_id, "Int", HID_USAGE_RX ) 176 | this.AxisExist_RY := DllCall("vJoyInterface\GetVJDAxisExist", "Int", dev_id, "Int", HID_USAGE_RY ) 177 | this.AxisExist_RZ := DllCall("vJoyInterface\GetVJDAxisExist", "Int", dev_id, "Int", HID_USAGE_RZ ) 178 | this.AxisExist_SL0 := DllCall("vJoyInterface\GetVJDAxisExist", "Int", dev_id, "Int", HID_USAGE_SL0) 179 | this.AxisExist_SL1 := DllCall("vJoyInterface\GetVJDAxisExist", "Int", dev_id, "Int", HID_USAGE_SL1) 180 | 181 | if (DllCall("vJoyInterface\GetVJDAxisMax", "Int", dev_id, "Int", HID_USAGE_X, "IntP", nResult)) { 182 | this.AxisMax_X := nResult 183 | } 184 | if (DllCall("vJoyInterface\GetVJDAxisMax", "Int", dev_id, "Int", HID_USAGE_Y, "IntP", nResult)) { 185 | this.AxisMax_Y := nResult 186 | } 187 | if (DllCall("vJoyInterface\GetVJDAxisMax", "Int", dev_id, "Int", HID_USAGE_Z, "IntP", nResult)) { 188 | this.AxisMax_Z := nResult 189 | } 190 | if (DllCall("vJoyInterface\GetVJDAxisMax", "Int", dev_id, "Int", HID_USAGE_RX, "IntP", nResult)) { 191 | this.AxisMax_RX := nResult 192 | } 193 | if (DllCall("vJoyInterface\GetVJDAxisMax", "Int", dev_id, "Int", HID_USAGE_RY, "IntP", nResult)) { 194 | this.AxisMax_RY := nResult 195 | } 196 | if (DllCall("vJoyInterface\GetVJDAxisMax", "Int", dev_id, "Int", HID_USAGE_RZ, "IntP", nResult)) { 197 | this.AxisMax_RZ := nResult 198 | } 199 | if (DllCall("vJoyInterface\GetVJDAxisMax", "Int", dev_id, "Int", HID_USAGE_SL0, "IntP", nResult)) { 200 | this.Slider0_Max := nResult 201 | } 202 | if (DllCall("vJoyInterface\GetVJDAxisMax", "Int", dev_id, "Int", HID_USAGE_SL1, "IntP", nResult)) { 203 | this.Slider1_Max := nResult 204 | } 205 | 206 | ; Acquire the target device 207 | if (DeviceStatus = VJD_STAT_FREE) { 208 | ac_jvd := DllCall("vJoyInterface\AcquireVJD", "UInt", dev_id) 209 | if (!ac_jvd) { 210 | MsgBox, Dev:%dev_id% aquire fail ErrorLevel: %ErrorLevel% 211 | } 212 | } 213 | 214 | if (DeviceStatus = VJD_STAT_OWN) { 215 | MsgBox % "Failed to acquire vJoy device number: " dev_id "`n(Other process owned device)" 216 | return 217 | } else if (DeviceStatus = VJD_STAT_FREE and !ac_jvd ) { 218 | MsgBox % "Failed to acquire vJoy device number: " dev_id "`nAcquired: " ac_jvd 219 | return 220 | } else { 221 | ;ToolTip, % "Acquired: vJoy device number: " dev_id 222 | } 223 | ;ToolTip 224 | 225 | this.DeviceID := dev_id 226 | this.DeviceStatus := DeviceStatus 227 | this.Reset() 228 | this.DeviceReady := True 229 | 230 | return this 231 | } 232 | 233 | __Delete() { 234 | this.Relinquish() 235 | } 236 | 237 | SetAxis(axis_val, usage) { 238 | res := DllCall("vJoyInterface\SetAxis", "Int", axis_val, "UInt", this.DeviceID, "UInt", usage) 239 | if (!res) { 240 | MsgBox, SetAxis(%axis_val%`,%usage%) Error!`nErrorLevel:%ErrorLevel% 241 | } 242 | return res 243 | } 244 | 245 | SetAxis_X(axis_val) { 246 | Global HID_USAGE_X 247 | new_val := parse_rel_val(axis_val, this.Axis_X, this.AxisMax_X) 248 | res := this.SetAxis(new_val, HID_USAGE_X) 249 | if (res) { 250 | this.Axis_X := new_val 251 | } 252 | return res 253 | } 254 | SetAxis_Y(axis_val) { 255 | Global HID_USAGE_Y 256 | new_val := parse_rel_val(axis_val, this.Axis_Y, this.AxisMax_Y) 257 | res := this.SetAxis(new_val, HID_USAGE_Y) 258 | if (res) { 259 | this.Axis_Y := new_val 260 | } 261 | return res 262 | } 263 | SetAxis_Z(axis_val) { 264 | Global HID_USAGE_Z 265 | new_val := parse_rel_val(axis_val, this.Axis_Z, this.AxisMax_Z) 266 | res := this.SetAxis(new_val, HID_USAGE_Z) 267 | if (res) { 268 | this.Axis_Z := new_val 269 | } 270 | return res 271 | } 272 | SetAxis_RX(axis_val) { 273 | Global HID_USAGE_RX 274 | new_val := parse_rel_val(axis_val, this.Axis_RX, this.AxisMax_RX) 275 | res := this.SetAxis(new_val, HID_USAGE_RX) 276 | if (res) { 277 | this.Axis_RX := new_val 278 | } 279 | return res 280 | } 281 | SetAxis_RY(axis_val) { 282 | Global HID_USAGE_RY 283 | new_val := parse_rel_val(axis_val, this.Axis_RY, this.AxisMax_RY) 284 | res := this.SetAxis(new_val, HID_USAGE_RY) 285 | if (res) { 286 | this.Axis_RY := new_val 287 | } 288 | return res 289 | } 290 | SetAxis_RZ(axis_val) { 291 | Global HID_USAGE_RZ 292 | new_val := parse_rel_val(axis_val, this.Axis_RZ, this.AxisMax_RZ) 293 | res := this.SetAxis(new_val, HID_USAGE_RZ) 294 | if (res) { 295 | this.Axis_RZ := new_val 296 | } 297 | return res 298 | } 299 | SetAxis_SL0(axis_val) { 300 | Global HID_USAGE_SL0 301 | new_val := parse_rel_val(axis_val, this.Axis_SL0, this.AxisMax_SL0) 302 | res := this.SetAxis(new_val, HID_USAGE_SL0) 303 | if (res) { 304 | this.Slider0 := new_val 305 | } 306 | return res 307 | } 308 | SetAxis_SL1(axis_val) { 309 | Global HID_USAGE_SL1 310 | new_val := parse_rel_val(axis_val, this.Axis_SL1, this.AxisMax_SL1) 311 | res := this.SetAxis(new_val, HID_USAGE_SL1) 312 | if (res) { 313 | this.Slider1 := new_val 314 | } 315 | return res 316 | } 317 | 318 | GetBtn(bid) { 319 | if (bid < 1 or bid > this.NumberOfButtons) { 320 | return 0 321 | } 322 | return this.Btn[bid] 323 | } 324 | 325 | SetBtn(sw, btn_id) { 326 | if (btn_id < 1 or btn_id > this.NumberOfButtons) { 327 | MsgBox, SetBtn: range check error! 328 | return 0 329 | } 330 | res := DllCall("vJoyInterface\SetBtn", "Int", sw, "UInt", this.DeviceID, "UChar", btn_id) 331 | if (res) { 332 | this.Btn[btn_id] := sw 333 | } 334 | return res 335 | } 336 | 337 | SetDiscPov(Value, nPov) { 338 | _res := DllCall("vJoyInterface\SetDiscPov", "Int", Value, "UInt", this.DeviceID, "UChar", nPov) 339 | if (!_res) { 340 | MsgBox, SetDiscPov err: %ErrorLevel% 341 | } else { 342 | this.DiscPov[nPov] := Value 343 | } 344 | return _res 345 | } 346 | 347 | SetContPov(Value, nPov) { 348 | _res := DllCall("vJoyInterface\SetContPov", "Int", Value, "UInt", this.DeviceID, "UChar", nPov) 349 | if (!_res) { 350 | MsgBox, SetContPov err: %ErrorLevel% 351 | } else { 352 | this.ContPov[nPov] := Value 353 | } 354 | return _res 355 | } 356 | 357 | Reset() { 358 | ; Reset local state values 359 | this.Axis_X := 0 360 | this.Axis_Y := 0 361 | this.Axis_Z := 0 362 | this.Axis_RX := 0 363 | this.Axis_RY := 0 364 | this.Axis_RZ := 0 365 | this.Slider0 := 0 366 | this.Slider1 := 0 367 | 368 | for i in this.ContPov 369 | this.ContPov[i] := 0 370 | for i in this.DiscPov 371 | this.DiscPov[i] := 0 372 | for i in this.Btn 373 | this.Btn[i] := 0 374 | return DllCall("vJoyInterface\ResetVJD", "UInt", this.DeviceID) 375 | } 376 | 377 | Relinquish() { 378 | return DllCall("vJoyInterface\RelinquishVJD", "UInt", this.DeviceID) 379 | } 380 | } 381 | 382 | VJoy_init(id := 1) { 383 | Global VJDev, VJD_MAXDEV 384 | if (id < 1 || id > VJD_MAXDEV) { 385 | MsgBox, [%A_ThisFunc%] Device %id% is invalid. Please specify 1-%VJD_MAXDEV%. 386 | return 387 | } 388 | VJDev[id] := new VJoyDev(id) 389 | return VJDev[id] 390 | } 391 | 392 | 393 | VJoy_DeviceErr(id) { 394 | Global VJD_MAXDEV, VJDev 395 | if (id < 1 or id > VJD_MAXDEV) { 396 | MsgBox, [%A_ThisFunc%] Device %id% is invalid. Please specify 1-%VJD_MAXDEV%. 397 | return True 398 | } 399 | if (!VJDev[id].DeviceReady) { 400 | MsgBox, [%A_ThisFunc%] Device %id% is not ready. 401 | return True 402 | } 403 | return False 404 | } 405 | VJoy_Ready(id) { 406 | Global VJD_MAXDEV, VJDev 407 | if (id < 1 || id > VJD_MAXDEV) { 408 | return False 409 | } 410 | return VJDev[id].DeviceReady 411 | } 412 | 413 | VJoy_ResetVJD(id) { 414 | Global VJDev 415 | if (VJoy_DeviceErr(id)) 416 | return False 417 | return VJDev[id].Reset() 418 | } 419 | 420 | VJoy_ResetAll() { 421 | return DllCall("vJoyInterface\ResetAll") 422 | } 423 | 424 | ; Release device 425 | VJoy_RelinquishVJD(id) { 426 | Global VJDev 427 | if (VJoy_DeviceErr(id)) 428 | return False 429 | return VJDev[id].Relinquish() 430 | } 431 | 432 | ; Acquire device - added by evilC 433 | VJoy_AcquireVJD(id) { 434 | Global VJDev 435 | if (VJoy_DeviceErr(id)) 436 | return False 437 | return DllCall("vJoyInterface\AcquireVJD", "UInt", id) 438 | } 439 | 440 | ; destructor 441 | VJoy_Close() { 442 | Global VJDev 443 | 444 | VJoy_ResetAll() 445 | 446 | for idx, dev in VJDev 447 | dev.delete 448 | if (hVJDLL) { 449 | DLLCall("FreeLibraly", "Ptr", hVJDLL) 450 | hVJDLL:= 451 | } 452 | } 453 | 454 | VJoy_GetContPovNumber(id) { 455 | Global VJDev 456 | if (VJoy_DeviceErr(id)) 457 | return False 458 | return VJDev[id].ContPovNumber 459 | } 460 | 461 | VJoy_GetDiscPovNumber(id) { 462 | Global VJDev 463 | if (VJoy_DeviceErr(id)) 464 | return False 465 | return VJDev[id].DiscPovNumber 466 | } 467 | 468 | VJoy_GetVJDButtonNumber(id) { 469 | Global VJDev 470 | if (VJoy_DeviceErr(id)) 471 | return False 472 | return VJDev[id].NumberOfButtons 473 | } 474 | 475 | VJoy_GetAxisExist_X(id) { 476 | Global VJDev 477 | if (VJoy_DeviceErr(id)) 478 | return False 479 | return VJDev[id].AxisExist_X 480 | } 481 | VJoy_GetAxisExist_Y(id) { 482 | Global VJDev 483 | if (VJoy_DeviceErr(id)) 484 | return False 485 | return VJDev[id].AxisExist_Y 486 | } 487 | VJoy_GetAxisExist_Z(id) { 488 | Global VJDev 489 | if (VJoy_DeviceErr(id)) 490 | return False 491 | return VJDev[id].AxisExist_Z 492 | } 493 | VJoy_GetAxisExist_RX(id) { 494 | Global VJDev 495 | if (VJoy_DeviceErr(id)) 496 | return False 497 | return VJDev[id].AxisExist_RX 498 | } 499 | VJoy_GetAxisExist_RY(id) { 500 | Global VJDev 501 | if (VJoy_DeviceErr(id)) 502 | return False 503 | return VJDev[id].AxisExist_RY 504 | } 505 | VJoy_GetAxisExist_RZ(id) { 506 | Global VJDev 507 | if (VJoy_DeviceErr(id)) 508 | return False 509 | return VJDev[id].AxisExist_RZ 510 | } 511 | VJoy_GetAxisExist_SL0(id) { 512 | Global VJDev 513 | if (VJoy_DeviceErr(id)) 514 | return False 515 | return VJDev[id].AxisExist_SL0 516 | } 517 | VJoy_GetAxisExist_SL1(id) { 518 | Global VJDev 519 | if (VJoy_DeviceErr(id)) 520 | return False 521 | return VJDev[id].AxisExist_SL1 522 | } 523 | 524 | 525 | VJoy_GetAxisMax_X(id) { 526 | Global VJDev 527 | if (VJoy_DeviceErr(id)) 528 | return False 529 | return VJDev[id].AxisMax_X 530 | } 531 | VJoy_GetAxisMax_Y(id) { 532 | Global VJDev 533 | if (VJoy_DeviceErr(id)) 534 | return False 535 | return VJDev[id].AxisMax_Y 536 | } 537 | VJoy_GetAxisMax_Z(id) { 538 | Global VJDev 539 | if (VJoy_DeviceErr(id)) 540 | return False 541 | return VJDev[id].AxisMax_Z 542 | } 543 | VJoy_GetAxisMax_RX(id) { 544 | Global VJDev 545 | if (VJoy_DeviceErr(id)) 546 | return False 547 | return VJDev[id].AxisMax_RX 548 | } 549 | VJoy_GetAxisMax_RY(id) { 550 | Global VJDev 551 | if (VJoy_DeviceErr(id)) 552 | return False 553 | return VJDev[id].AxisMax_RY 554 | } 555 | VJoy_GetAxisMax_RZ(id) { 556 | Global VJDev 557 | if (VJoy_DeviceErr(id)) 558 | return False 559 | return VJDev[id].AxisMax_RZ 560 | } 561 | VJoy_GetAxisMax_SL0(id) { 562 | Global VJDev 563 | if (VJoy_DeviceErr(id)) 564 | return False 565 | return VJDev[id].Slider0_Max 566 | } 567 | VJoy_GetAxisMax_SL1(id) { 568 | Global VJDev 569 | if (VJoy_DeviceErr(id)) 570 | return False 571 | return VJDev[id].Slider1_Max 572 | } 573 | 574 | ; for compatibility 575 | VJoy_GetVJDAxisMax(id, usage) { 576 | 577 | Global VJDev, HID_USAGE_X,HID_USAGE_Y,HID_USAGE_Z,HID_USAGE_RX,HID_USAGE_RY,HID_USAGE_RZ,HID_USAGE_SL0,HID_USAGE_SL1 578 | if (VJoy_DeviceErr(id)) 579 | return False 580 | 581 | return (usage = HID_USAGE_X) ? VJDev[id].AxisMax_X : 582 | (usage = HID_USAGE_Y) ? VJDev[id].AxisMax_Y : 583 | (usage = HID_USAGE_Z) ? VJDev[id].AxisMax_Z : 584 | (usage = HID_USAGE_RX) ? VJDev[id].AxisMax_RX : 585 | (usage = HID_USAGE_RY) ? VJDev[id].AxisMax_RY : 586 | (usage = HID_USAGE_RZ) ? VJDev[id].AxisMax_RZ : 587 | (usage = HID_USAGE_SL0) ? VJDev[id].AxisMax_Y : 588 | VJDev[id].AxisMax_SL1 589 | } 590 | 591 | VJoy_GetVJDAxisExist(id, usage) { 592 | 593 | Global VJDev, HID_USAGE_X,HID_USAGE_Y,HID_USAGE_Z,HID_USAGE_RX,HID_USAGE_RY,HID_USAGE_RZ,HID_USAGE_SL0,HID_USAGE_SL1 594 | if (VJoy_DeviceErr(id)) 595 | return False 596 | 597 | return (usage = HID_USAGE_X) ? VJDev[id].AxisExist_X : 598 | (usage = HID_USAGE_Y) ? VJDev[id].AxisExist_Y : 599 | (usage = HID_USAGE_Z) ? VJDev[id].AxisExist_Z : 600 | (usage = HID_USAGE_RX) ? VJDev[id].AxisExist_RX : 601 | (usage = HID_USAGE_RY) ? VJDev[id].AxisExist_RY : 602 | (usage = HID_USAGE_RZ) ? VJDev[id].AxisExist_RZ : 603 | (usage = HID_USAGE_SL0) ? VJDev[id].AxisExist_Y : 604 | VJDev[id].AxisExist_SL1 605 | } 606 | 607 | VJoy_GetBtn(id, btn_id) { 608 | Global VJDev 609 | if (VJoy_DeviceErr(id)) 610 | return False 611 | return VJDev[id].GetBtn(btn_id) 612 | } 613 | 614 | VJoy_SetBtn(sw, id, btn_id) { 615 | Global VJDev 616 | if (!VJDev[id].DeviceReady){ 617 | return False 618 | } 619 | if (VJoy_DeviceErr(id)) 620 | return False 621 | res := VJDev[id].SetBtn(sw, btn_id) 622 | if (!res) { 623 | MsgBox, SetBtn(%sw%, %id%, %btn_id%) err: %ErrorLevel%`nnLastError: %A_LastError% 624 | } 625 | return res 626 | } 627 | 628 | VJoy_GetAxis_X(id) { 629 | Global VJDev 630 | if (VJoy_DeviceErr(id)) 631 | return False 632 | return VJDev[id].Axis_X 633 | } 634 | VJoy_GetAxis_Y(id) { 635 | Global VJDev 636 | if (VJoy_DeviceErr(id)) 637 | return False 638 | return VJDev[id].Axis_Y 639 | } 640 | VJoy_GetAxis_Z(id) { 641 | Global VJDev 642 | if (VJoy_DeviceErr(id)) 643 | return False 644 | return VJDev[id].Axis_Z 645 | } 646 | VJoy_GetAxis_RX(id) { 647 | Global VJDev 648 | if (VJoy_DeviceErr(id)) 649 | return False 650 | return VJDev[id].Axis_RX 651 | } 652 | VJoy_GetAxis_RY(id) { 653 | Global VJDev 654 | if (VJoy_DeviceErr(id)) 655 | return False 656 | return VJDev[id].Axis_RY 657 | } 658 | VJoy_GetAxis_RZ(id) { 659 | Global VJDev 660 | if (VJoy_DeviceErr(id)) 661 | return False 662 | return VJDev[id].Axis_RZ 663 | } 664 | VJoy_GetAxis_SL0(id) { 665 | Global VJDev 666 | if (VJoy_DeviceErr(id)) 667 | return False 668 | return VJDev[id].Slider0 669 | } 670 | VJoy_GetAxis_SL1(id) { 671 | Global VJDev 672 | if (VJoy_DeviceErr(id)) 673 | return False 674 | return VJDev[id].Slider1 675 | } 676 | 677 | VJoy_SetAxis_X(axis_val, id) { 678 | Global VJDev 679 | if (VJoy_DeviceErr(id)) 680 | return False 681 | return VJDev[id].SetAxis_X(axis_val) 682 | } 683 | VJoy_SetAxis_Y(axis_val, id) { 684 | Global VJDev 685 | if (VJoy_DeviceErr(id)) 686 | return False 687 | return VJDev[id].SetAxis_Y(axis_val) 688 | } 689 | VJoy_SetAxis_Z(axis_val, id) { 690 | Global VJDev 691 | if (VJoy_DeviceErr(id)) 692 | return False 693 | return VJDev[id].SetAxis_Z(axis_val) 694 | } 695 | VJoy_SetAxis_RX(axis_val, id) { 696 | Global VJDev 697 | if (VJoy_DeviceErr(id)) 698 | return False 699 | return VJDev[id].SetAxis_RX(axis_val) 700 | } 701 | VJoy_SetAxis_RY(axis_val, id) { 702 | Global VJDev 703 | if (VJoy_DeviceErr(id)) 704 | return False 705 | return VJDev[id].SetAxis_RY(axis_val) 706 | } 707 | VJoy_SetAxis_RZ(axis_val, id) { 708 | Global VJDev 709 | if (VJoy_DeviceErr(id)) 710 | return False 711 | return VJDev[id].SetAxis_RZ(axis_val) 712 | } 713 | VJoy_SetAxis_SL0(axis_val, id) { 714 | Global VJDev 715 | if (VJoy_DeviceErr(id)) 716 | return False 717 | return VJDev[id].SetAxis_SL0(axis_val) 718 | } 719 | VJoy_SetAxis_SL1(axis_val, id) { 720 | Global VJDev 721 | if (VJoy_DeviceErr(id)) 722 | return False 723 | return VJDev[id].SetAxis_SL1(axis_val) 724 | } 725 | 726 | ; for compatibility 727 | VJoy_SetAxis(axis_val, id, usage) { 728 | Global VJDev, HID_USAGE_X,HID_USAGE_Y,HID_USAGE_Z,HID_USAGE_RX,HID_USAGE_RY,HID_USAGE_RZ,HID_USAGE_SL0,HID_USAGE_SL1 729 | if (!VJDev[id].DeviceReady){ 730 | return False 731 | } 732 | if (VJoy_DeviceErr(id)) 733 | return False 734 | 735 | if (usage == HID_USAGE_X){ 736 | return VJDev[id].SetAxis_X(axis_val) 737 | } else if (usage == HID_USAGE_Y){ 738 | return VJDev[id].SetAxis_Y(axis_val) 739 | } else if (usage == HID_USAGE_Z){ 740 | return VJDev[id].SetAxis_Z(axis_val) 741 | } else if (usage == HID_USAGE_RX){ 742 | return VJDev[id].SetAxis_RX(axis_val) 743 | } else if (usage == HID_USAGE_RY){ 744 | return VJDev[id].SetAxis_RY(axis_val) 745 | } else if (usage == HID_USAGE_RZ){ 746 | return VJDev[id].SetAxis_RZ(axis_val) 747 | } else if (usage == HID_USAGE_SL0){ 748 | return VJDev[id].SetAxis_SL0(axis_val) 749 | } else if (usage == HID_USAGE_SL1){ 750 | return VJDev[id].SetAxis_SL1(axis_val) 751 | } else { 752 | MsgBox, Unknown Axis: %usage% 753 | } 754 | } 755 | 756 | VJoy_GetDiscPov(id, nPov) { 757 | Global VJDev 758 | if (VJoy_DeviceErr(id)) 759 | return False 760 | return VJDev[id].DiscPov[nPov] 761 | } 762 | VJoy_SetDiscPov(Value, id, nPov) { 763 | Global VJDev 764 | if (VJoy_DeviceErr(id)) 765 | return False 766 | return VJDev[id].SetDiscPov(Value, nPov) 767 | } 768 | 769 | VJoy_GetContPov(id, nPov) { 770 | Global VJDev 771 | if (VJoy_DeviceErr(id)) 772 | return False 773 | return VJDev[id].ContPov[nPov] 774 | } 775 | VJoy_SetContPov(Value, id, nPov) { 776 | Global VJDev 777 | if (VJoy_DeviceErr(id)) 778 | return False 779 | return VJDev[id].SetContPov(Value, nPov) 780 | } 781 | 782 | ; for debug: dump value of structure 783 | VJoy_Dump(id) { 784 | Global VJDev 785 | if (VJoy_DeviceErr(id)) 786 | return False 787 | 788 | num := VJoy_GetVJDButtonNumber(id) 789 | for idx, btn in VJDev[id].Btn 790 | { 791 | if (idx<10) 792 | buf1 .= "_" 793 | buf1 .= idx . "|" 794 | buf2 .= "_" . btn . "|" 795 | } 796 | str_btn = Button(%num%):`n %buf1%`n %buf2%`n 797 | 798 | if (VJoy_GetAxisMax_X(id)) { 799 | str_btn .= "Axis_X: " . VJoy_GetAxis_X(id) . "`n" 800 | } 801 | if (VJoy_GetAxisMax_Y(id)) { 802 | str_btn .= "Axis_Y: " . VJoy_GetAxis_Y(id) . "`n" 803 | } 804 | if (VJoy_GetAxisMax_Z(id)) { 805 | str_btn .= "Axis_Z: " . VJoy_GetAxis_Z(id) . "`n" 806 | } 807 | if (VJoy_GetAxisMax_RX(id)) { 808 | str_btn .= "Axis_RX: " . VJoy_GetAxis_RX(id) . "`n" 809 | } 810 | if (VJoy_GetAxisMax_RY(id)) { 811 | str_btn .= "Axis_RY: " . VJoy_GetAxis_RY(id) . "`n" 812 | } 813 | if (VJoy_GetAxisMax_RZ(id)) { 814 | str_btn .= "Axis_RZ: " . VJoy_GetAxis_RZ(id) . "`n" 815 | } 816 | if (VJoy_GetAxisMax_SL0(id)) { 817 | str_btn .= "Axis_SL0: " . VJoy_GetAxis_SL0(id) . "`n" 818 | } 819 | if (VJoy_GetAxisMax_SL1(id)) { 820 | str_btn .= "Axis_SL1: " . VJoy_GetAxis_SL1(id) . "`n" 821 | } 822 | 823 | num := VJoy_GetContPovNumber(id) 824 | if (num) { 825 | for idx, btn in VJDev[id].ContPov 826 | { 827 | Loop, % (StrLen(btn) - 1) 828 | buf3 .= "_" 829 | buf3 .= idx . "|" 830 | buf4 .= btn . "|" 831 | } 832 | str_cont = ContPov(%num%):`n %buf3%`n %buf4%`n 833 | } else { 834 | str_cont = No Continuous Button.`n 835 | } 836 | str_btn .= str_cont 837 | 838 | num := VJoy_GetDiscPovNumber(id) 839 | if (num) { 840 | for idx, btn in VJDev[id].DiscPov 841 | { 842 | Loop, % (StrLen(btn) - 1) 843 | buf5 .= "_" 844 | buf5 .= idx . "|" 845 | buf6 .= btn . "|" 846 | } 847 | str_Disc = DiscPov(%num%):`n %buf5%`n %buf6%`n 848 | } else { 849 | str_Disc = No Discrete Button.`n 850 | } 851 | str_btn .= str_Disc 852 | ToolTip, %str_btn% 853 | } 854 | 855 | parse_rel_val(invar, curval, max) { 856 | if (InStr(invar, "+")) { 857 | StringReplace, _buffer, invar, + 858 | res := curval + _buffer 859 | if (res > max) 860 | return max 861 | return res 862 | } else if (InStr(invar, "-")) { 863 | StringReplace, _buffer, invar, - 864 | res := curval - _buffer 865 | if (res < 0) 866 | return 0 867 | return res 868 | } 869 | return invar 870 | } 871 | 872 | ; x64 compatible registry read from http://www.autohotkey.com/board/topic/36290-regread64-and-regwrite64-no-redirect-to-wow6432node/ 873 | RegRead64(sRootKey, sKeyName, sValueName = "", DataMaxSize=1024) { 874 | HKEY_CLASSES_ROOT := 0x80000000 ; http://msdn.microsoft.com/en-us/library/aa393286.aspx 875 | HKEY_CURRENT_USER := 0x80000001 876 | HKEY_LOCAL_MACHINE := 0x80000002 877 | HKEY_USERS := 0x80000003 878 | HKEY_CURRENT_CONFIG := 0x80000005 879 | HKEY_DYN_DATA := 0x80000006 880 | HKCR := HKEY_CLASSES_ROOT 881 | HKCU := HKEY_CURRENT_USER 882 | HKLM := HKEY_LOCAL_MACHINE 883 | HKU := HKEY_USERS 884 | HKCC := HKEY_CURRENT_CONFIG 885 | 886 | REG_NONE := 0 ; http://msdn.microsoft.com/en-us/library/ms724884.aspx 887 | REG_SZ := 1 888 | REG_EXPAND_SZ := 2 889 | REG_BINARY := 3 890 | REG_DWORD := 4 891 | REG_DWORD_BIG_ENDIAN := 5 892 | REG_LINK := 6 893 | REG_MULTI_SZ := 7 894 | REG_RESOURCE_LIST := 8 895 | 896 | KEY_QUERY_VALUE := 0x0001 ; http://msdn.microsoft.com/en-us/library/ms724878.aspx 897 | KEY_WOW64_64KEY := 0x0100 ; http://msdn.microsoft.com/en-gb/library/aa384129.aspx (do not redirect to Wow6432Node on 64-bit machines) 898 | KEY_SET_VALUE := 0x0002 899 | KEY_WRITE := 0x20006 900 | ENC := A_IsUnicode?"W":"A" 901 | hKey := "", sValueType := "" 902 | 903 | myhKey := %sRootKey% ; pick out value (0x8000000x) from list of HKEY_xx vars 904 | IfEqual,myhKey,, { ; Error - Invalid root key 905 | ErrorLevel := 3 906 | return "" 907 | } 908 | RegAccessRight := KEY_QUERY_VALUE + KEY_WOW64_64KEY 909 | ;VarSetCapacity(sValueType, 4) 910 | DllCall("Advapi32.dll\RegOpenKeyEx" ENC, "uint", myhKey, "str", sKeyName, "uint", 0, "uint", RegAccessRight, "uint*", hKey) ; open key 911 | DllCall("Advapi32.dll\RegQueryValueEx" ENC, "uint", hKey, "str", sValueName, "uint", 0, "uint*", sValueType, "uint", 0, "uint", 0) ; get value type 912 | If (sValueType == REG_SZ or sValueType == REG_EXPAND_SZ) { 913 | VarSetCapacity(sValue, vValueSize:=DataMaxSize) 914 | DllCall("Advapi32.dll\RegQueryValueEx" ENC, "uint", hKey, "str", sValueName, "uint", 0, "uint", 0, "str", sValue, "uint*", vValueSize) ; get string or string-exp 915 | } Else If (sValueType == REG_DWORD) { 916 | VarSetCapacity(sValue, vValueSize:=4) 917 | DllCall("Advapi32.dll\RegQueryValueEx" ENC, "uint", hKey, "str", sValueName, "uint", 0, "uint", 0, "uint*", sValue, "uint*", vValueSize) ; get dword 918 | } Else If (sValueType == REG_MULTI_SZ) { 919 | VarSetCapacity(sTmp, vValueSize:=DataMaxSize) 920 | DllCall("Advapi32.dll\RegQueryValueEx" ENC, "uint", hKey, "str", sValueName, "uint", 0, "uint", 0, "str", sTmp, "uint*", vValueSize) ; get string-mult 921 | sValue := ExtractData(&sTmp) "`n" 922 | Loop { 923 | If (errorLevel+2 >= &sTmp + vValueSize) 924 | Break 925 | sValue := sValue ExtractData( errorLevel+1 ) "`n" 926 | } 927 | } Else If (sValueType == REG_BINARY) { 928 | VarSetCapacity(sTmp, vValueSize:=DataMaxSize) 929 | DllCall("Advapi32.dll\RegQueryValueEx" ENC, "uint", hKey, "str", sValueName, "uint", 0, "uint", 0, "str", sTmp, "uint*", vValueSize) ; get binary 930 | sValue := "" 931 | SetFormat, integer, h 932 | Loop %vValueSize% { 933 | hex := SubStr(Asc(SubStr(sTmp,A_Index,1)),3) 934 | StringUpper, hex, hex 935 | sValue := sValue hex 936 | } 937 | SetFormat, integer, d 938 | } Else { ; value does not exist or unsupported value type 939 | DllCall("Advapi32.dll\RegCloseKey", "uint", hKey) 940 | ErrorLevel := 1 941 | return "" 942 | } 943 | DllCall("Advapi32.dll\RegCloseKey", "uint", hKey) 944 | return sValue 945 | } 946 | 947 | ExtractData(pointer) { ; http://www.autohotkey.com/forum/viewtopic.php?p=91578#91578 SKAN 948 | Loop { 949 | errorLevel := ( pointer+(A_Index-1) ) 950 | Asc := *( errorLevel ) 951 | IfEqual, Asc, 0, Break ; Break if NULL Character 952 | String := String . Chr(Asc) 953 | } 954 | Return String 955 | } 956 | --------------------------------------------------------------------------------