├── .gitignore ├── CvJI ├── CvGenInterface.ahk ├── CvJoyInterface.ahk ├── MouseDelta.ahk └── SelfDeletingTimer.ahk ├── Layouts_1.8 ├── Wii U GamePad - vJoy Device_Custom.ccc └── Wii U Pro Controller - vJoy Device_Custom.ccc ├── README.md ├── SavedKeyLists.ini ├── ScpVBus ├── ScpVBus.inf ├── ScpVBus.sys ├── WdfCoinstaller01009.dll ├── devcon.exe ├── scpvbus.cat └── v1.7.1.2 │ ├── x64 │ ├── ScpVBus.inf │ ├── ScpVBus.sys │ ├── WdfCoinstaller01009.dll │ ├── devcon.exe │ └── scpvbus.cat │ └── x86 │ ├── ScpVBus.inf │ ├── ScpVBus.sys │ ├── WdfCoinstaller01009.dll │ ├── devcon.exe │ └── scpvbus.cat ├── controllerProfiles ├── vJoyDevice_GamePad.txt ├── vJoyDevice_Pro.txt ├── vXBox_GamePad.txt └── vXBox_Pro.txt ├── mouse2joystick_Custom_CEMU.ahk └── settings.ini /.gitignore: -------------------------------------------------------------------------------- 1 | mouse2joystick_Custom_CEMU.ico 2 | mouse2joystick_Custom_CEMU.ahk.ini 3 | *.exe 4 | *.zip 5 | 6 | !devcon.exe 7 | !WdfCoinstaller01009.dll -------------------------------------------------------------------------------- /CvJI/CvGenInterface.ahk: -------------------------------------------------------------------------------- 1 |  2 | Class CvGenInterface { 3 | DebugMode := 0 4 | SingleStickMode := 1 ; If set to 1, helper classes will automatically relinquish existing vjoy device on attempting to acquire one not connected. 5 | ResetOnAcquire := 1 ; Resets Devices to vjoy norms on Acquire via helper classes. 6 | ResetOnRelinquish := 1 ; Resets Devices to vjoy norms on Relinquish via helper classes. 7 | LibraryLoaded := 0 ; Did the Library Load OK when the class Instantiated? 8 | 9 | LoadLibraryLog := "" ; If Not, holds log of why it failed. 10 | hModule := 0 ; handle to DLL 11 | Devices := [] ; Array for Helper Classes of Devices 12 | xDevices := [] ; Array for Helper Classes of vXbox Devices 13 | 14 | VJD_MAXDEV := 16 ; Max Number of Devices vJoy Supports 15 | VXB_MAXDEV := 4 ; Max Number of Devices vXbox Supports 16 | 17 | ; ported from VjdStat in vjoyinterface.h 18 | VJD_STAT_OWN := 0 ; The vJoy Device is owned by this application. 19 | VJD_STAT_FREE := 1 ; The vJoy Device is NOT owned by any application (including this one). 20 | VJD_STAT_BUSY := 2 ; The vJoy Device is owned by another application. It cannot be acquired by this application. 21 | VJD_STAT_MISS := 3 ; The vJoy Device is missing. It either does not exist or the driver is down. 22 | VJD_STAT_UNKN := 4 ; Unknown 23 | 24 | ; HID Descriptor definitions(ported from public.h) 25 | HID_USAGE_X := 0x30 26 | HID_USAGE_Y := 0x31 27 | HID_USAGE_Z := 0x32 28 | HID_USAGE_RX:= 0x33 29 | HID_USAGE_RY:= 0x34 30 | HID_USAGE_RZ:= 0x35 31 | HID_USAGE_SL0:= 0x36 32 | HID_USAGE_SL1:= 0x37 33 | 34 | ; Handy lookups to axis HID_USAGE values 35 | AxisIndex := [0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37] ; Index (Axis Number) to HID Descriptor 36 | AxisAssoc := {x:0x30, y:0x31, z:0x32, rx:0x33, ry:0x34, rz: 0x35, sl1:0x36, sl2:0x37} ; Name (eg "x", "y", "z", "sl1") to HID Descriptor 37 | AxisNames := ["X","Y","Z","RX","RY","RZ","SL0","SL1"] 38 | 39 | static DllName := "vGenInterface" 40 | 41 | ; ===== Constructors / Destructors 42 | __New(){ 43 | ; Build Device array 44 | Loop % this.VJD_MAXDEV { 45 | this.Devices[A_Index] := new this.CvJoyDevice(A_Index, this) 46 | } 47 | 48 | Loop % this.VXB_MAXDEV { 49 | this.xDevices[A_Index] := new this.CvXBoxDevice(A_Index, this) 50 | } 51 | 52 | ; Try and Load the DLL 53 | this.LoadLibrary() 54 | return this 55 | } 56 | 57 | __Delete(){ 58 | ; Relinquish Devices 59 | Loop % this.VJD_MAXDEV { 60 | this.Devices[A_Index].Relinquish() 61 | } 62 | 63 | Loop % this.VXB_MAXDEV { 64 | this.xDevices[A_Index].Relinquish() 65 | } 66 | 67 | ; Unload DLL 68 | if (this.hModule){ 69 | DllCall("FreeLibrary", "Ptr", this.hModule) 70 | } 71 | } 72 | 73 | ; ===== Helper Functions 74 | ; Converts vJoy range (0->32768 to a range like an AHK input 0->100) 75 | PercentTovJoy(percent){ 76 | return percent * 327.68 77 | } 78 | 79 | vJoyToPercent(vJoy){ 80 | return vJoy / 327.68 81 | } 82 | 83 | ; ===== DLL loading / vJoy Install detection 84 | 85 | ; Load the vJoyInterface DLL. 86 | LoadLibrary() { 87 | ;Global hModule 88 | 89 | if (this.LibraryLoaded) { 90 | this.LoadLibraryLog .= "Library already loaded. Aborting...`n" 91 | return 1 92 | } 93 | 94 | this.LoadLibraryLog := "" 95 | 96 | ; Check if vJoy is installed. Even with the DLL, if vJoy is not installed it will not work... 97 | ; Find vJoy install folder by looking for registry key. 98 | if (A_Is64bitOS && A_PtrSize != 8){ 99 | SetRegView 64 100 | } 101 | RegRead vJoyFolder, HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{8E31F76F-74C3-47F1-9550-E041EEDC5FBB}_is1, InstallLocation 102 | 103 | if (!vJoyFolder){ 104 | this.LoadLibraryLog .= "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." 105 | return 0 106 | } 107 | 108 | ; Try to find location of correct DLL. 109 | ; vJoy versions prior to 2.0.4 241214 lack these registry keys - if key not found, advise update. 110 | if (A_PtrSize == 8){ 111 | ; 64-Bit AHK 112 | DllKey := "DllX64Location" 113 | SecondFolder := vJoyFolder . "x64" 114 | } else { 115 | ; 32-Bit AHK 116 | DllKey := "DllX86Location" 117 | SecondFolder := vJoyFolder . "x86" 118 | } 119 | RegRead DllFolder, HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{8E31F76F-74C3-47F1-9550-E041EEDC5FBB}_is1, % DllKey 120 | 121 | if (!DllFolder){ 122 | ; Could not find registry entry. Advise vJoy update. 123 | this.LoadLibraryLog .= "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." 124 | DllFolder := SecondFolder 125 | } 126 | 127 | DllFolder .= "\" 128 | 129 | ; All good so far, try and load the DLL 130 | DllFile := "vGenInterface.dll" 131 | this.LoadLibraryLog := "vJoy Install Detected. Trying to load " DllFile "...`n" 132 | CheckLocations := [DllFolder DllFile] 133 | 134 | hModule := 0 135 | Loop % CheckLocations.Maxindex() { 136 | this.LoadLibraryLog .= "Checking " CheckLocations[A_Index] "... " 137 | if (FileExist(CheckLocations[A_Index])){ 138 | this.LoadLibraryLog .= "FOUND.`nTrying to load.. " 139 | hModule := DLLCall("LoadLibrary", "Str", CheckLocations[A_Index]) 140 | if (hModule){ 141 | this.hModule := hModule 142 | this.LoadLibraryLog .= "OK.`n" 143 | this.LoadLibraryLog .= "Checking driver enabled... " 144 | en := DllCall(DllFile "\vJoyEnabled", "Cdecl") 145 | if (en){ 146 | this.LibraryLoaded := 1 147 | this.LoadLibraryLog .= "OK.`n" 148 | ver := DllCall(DllFile "\GetvJoyVersion", "Cdecl") 149 | this.LoadLibraryLog .= "Loaded vJoy DLL version " ver "`n" 150 | vb := this.IsVBusExist() 151 | if (vb){ 152 | this.LoadLibraryLog .= "SCPVBus is installed`n" 153 | } else { 154 | this.LoadLibraryLog .= "SCPVBus is not installed (Non fatal)`n" 155 | } 156 | this.SetScpVBusState(vb) 157 | this._SetInitState(hModule) 158 | return 1 159 | } else { 160 | this.LoadLibraryLog .= "FAILED.`n" 161 | } 162 | } else { 163 | this.LoadLibraryLog .= "FAILED.`n" 164 | } 165 | } else { 166 | this.LoadLibraryLog .= "NOT FOUND.`n" 167 | } 168 | } 169 | this.LoadLibraryLog .= "`nFailed to load valid " DllFile "`n" 170 | this.LibraryLoaded := 0 171 | return 0 172 | } 173 | 174 | ; ===== vJoy Interface DLL call wrappers 175 | ; In the order detailed in the vJoy SDK's Interface Function Reference 176 | ; http://sourceforge.net/projects/vjoystick/files/ 177 | 178 | ; === General driver data 179 | 180 | IsVBusExist(){ 181 | ret := DllCall(this.DllName "\isVBusExist", "Cdecl") 182 | return (ret == 0) 183 | } 184 | 185 | vJoyEnabled(){ 186 | return DllCall(this.DllName "\vJoyEnabled") 187 | } 188 | 189 | GetvJoyVersion(){ 190 | return DllCall(this.DllName "\GetvJoyVersion") 191 | } 192 | 193 | GetvJoyProductString(){ 194 | return DllCall(this.DllName "\GetvJoyProductString") 195 | } 196 | 197 | GetvJoyManufacturerString(){ 198 | return DllCall(this.DllName "\GetvJoyManufacturerString") 199 | } 200 | 201 | GetvJoySerialNumberString(){ 202 | return DllCall(this.DllName "\GetvJoySerialNumberString") 203 | } 204 | 205 | ; === Write access to vJoy Device 206 | GetVJDStatus(rID){ 207 | return DllCall(this.DllName "\GetVJDStatus", "UInt", rID) 208 | } 209 | 210 | ; Handle setting IsOwned property outside helper class, to allow mixing 211 | AcquireVJD(rID){ 212 | this.Devices[rID].IsOwned := DllCall(this.DllName "\AcquireVJD", "UInt", rID) 213 | return this.Devices[rID].IsOwned 214 | } 215 | 216 | ; Handle setting IsOwned property outside helper class, to allow mixing 217 | AcquireDev(rID){ 218 | ;VarSetCapacity(dev, A_PtrSize) 219 | useType := 1 220 | this.xDevices[rID].IsOwned := !DllCall(this.DllName "\AcquireDev", "UInt", rID, "UInt", useType, "Ptr*", dev, "Cdecl") 221 | this.xDevices[rID].xID := dev 222 | return this.Devices[rID].IsOwned 223 | } 224 | 225 | RelinquishVJD(rID){ 226 | DllCall(this.DllName "\RelinquishVJD", "UInt", rID) 227 | this.Devices[rID].IsOwned := 0 228 | return this.Devices[rID].IsOwned 229 | } 230 | 231 | RelinquishDev(rID){ 232 | DllCall(this.DllName "\RelinquishDev", "Ptr", this.xDevices[rID].xID) 233 | this.xDevices[rID].IsOwned := 0 234 | return this.xDevices[rID].IsOwned 235 | } 236 | 237 | ; Not sure if this one is good. What is a "PVOID"? 238 | UpdateVJD(rID, pData){ 239 | return DllCall(this.DllName "\UpdateVJD", "UInt", rID, "PVOID", pData) 240 | } 241 | 242 | ; === vJoy Device properties 243 | 244 | GetVJDButtonNumber(rID){ 245 | return DllCall(this.DllName "\GetVJDButtonNumber", "UInt", rID) 246 | } 247 | 248 | GetVJDDiscPovNumber(rID){ 249 | return DllCall(this.DllName "\GetVJDDiscPovNumber", "UInt", rID) 250 | } 251 | 252 | GetVJDContPovNumber(rID){ 253 | return DllCall(this.DllName "\GetVJDContPovNumber", "UInt", rID) 254 | } 255 | 256 | GetVJDAxisExist(rID, Axis){ 257 | return DllCall(this.DllName "\GetVJDAxisExist", "UInt", rID, "Uint", Axis) 258 | } 259 | 260 | ResetVJD(rID){ 261 | return DllCall(this.DllName "\ResetVJD", "UInt", rID) 262 | } 263 | 264 | ResetController(rID){ 265 | return DllCall(this.DllName "\ResetController", "UInt", rID) 266 | } 267 | 268 | ResetAll(){ 269 | return DllCall(this.DllName "\ResetAll") 270 | } 271 | 272 | ResetButtons(rID){ 273 | return DllCall(this.DllName "\ResetButtons", "UInt", rID) 274 | } 275 | 276 | ResetPovs(rID){ 277 | return DllCall(this.DllName "\ResetPovs", "UInt", rID) 278 | } 279 | 280 | SetAxis(Value, rID, Axis){ 281 | return DllCall(this.DllName "\SetAxis", "Int", Value, "UInt", rID, "UInt", Axis) 282 | } 283 | 284 | SetDevAxis(Value, rID, Axis){ 285 | return DllCall(this.DllName "\SetDevAxis", "Ptr", this.xDevices[rID].xID, "UInt", Axis, "Float", Value, "Cdecl") 286 | } 287 | 288 | SetBtn(Value, rID, nBtn){ 289 | return DllCall(this.DllName "\SetBtn", "Int", Value, "UInt", rID, "UInt", nBtn) 290 | } 291 | 292 | SetDevPov(Value, rID, nPov){ 293 | return DllCall(this.DllName "\SetDevPov", "Ptr", this.xDevices[rID].xID, "UInt", nPov, "Float", Value, "Cdecl") 294 | } 295 | 296 | SetDevBtn(Value, rID, nBtn){ 297 | return DllCall(this.DllName "\SetDevButton", "Ptr", this.xDevices[rID].xID, "UInt", nBtn, "Uint", Value, "Cdecl") 298 | } 299 | 300 | GetDevHandle(rID){ 301 | DllCall(this.DllName "\GetDevHandle", "Uint", rID, "UInt", 1, "Ptr*", dev, "Cdecl") 302 | return dev 303 | } 304 | 305 | SetDiscPov(Value, rID, nPov){ 306 | return DllCall(this.DllName "\SetDiscPov", "Int", Value, "UInt", rID, "UChar", nPov) 307 | } 308 | 309 | SetContPov(Value, rID, nPOV){ 310 | return DllCall(this.DllName "\SetContPov", "Int", Value, "UInt", rID, "UChar", nPov) 311 | } 312 | 313 | PlugIn(rID) { 314 | return DllCall(this.DllName "\PlugIn", "UInt", rID) 315 | } 316 | 317 | PlugInNext() { 318 | DllCall(this.DllName "\PlugInNext", "Ptr*", slot) 319 | return slot 320 | } 321 | 322 | UnPlug(rID) { 323 | return DllCall(this.DllName "\UnPlug", "UInt", rID) 324 | } 325 | 326 | UnPlugAll() { 327 | ret := "" 328 | Loop 4 { 329 | IF this.isControllerPluggedIn(A_Index) 330 | ret .= "|" . DllCall(this.DllName "\UnPlugForce", "UInt", A_Index) 331 | } 332 | Return ret 333 | } 334 | 335 | isControllerPluggedIn(rID) { 336 | DLLCall(this.DllName "\isControllerPluggedIn", "UInt", rID, "Ptr*", Exist) 337 | Return Exist 338 | } 339 | 340 | isControllerOwned(rID) { 341 | DLLCall(this.DllName "\isControllerOwned", "UInt", rID, "Ptr*", Owned) 342 | Return Owned 343 | } 344 | 345 | GetLedNumber(rID) { 346 | DLLCall(this.DllName "\GetLedNumber", "UInt", rID, "Ptr*", pLed) 347 | Return pLed 348 | } 349 | 350 | 351 | ;;;;;;;;;================== 352 | ; ===== Device helper subclass. 353 | Class CvJoyDevice { 354 | IsOwned := 0 355 | 356 | GetStatus(){ 357 | return this.Interface.GetVJDStatus(this.DeviceID) 358 | } 359 | 360 | ; Converts Status to human readable form 361 | GetStatusName(){ 362 | DeviceStatus := this.GetStatus() 363 | if (DeviceStatus = this.Interface.VJD_STAT_OWN) { 364 | return "OWN" 365 | } else if (DeviceStatus = this.Interface.VJD_STAT_FREE) { 366 | return "FREE" 367 | } else if (DeviceStatus = this.Interface.VJD_STAT_BUSY) { 368 | return "BUSY" 369 | } else if (DeviceStatus = this.Interface.VJD_STAT_MISS) { 370 | return "MISS" 371 | } else { 372 | return "???" 373 | } 374 | } 375 | 376 | ; Acquire the device 377 | Acquire(){ 378 | if (this.IsOwned){ 379 | return 1 380 | } 381 | if (this.Interface.SingleStickMode){ 382 | Loop % this.Interface.Devices.MaxIndex() { 383 | if (A_Index == this.DeviceID){ 384 | Continue 385 | } 386 | if (this.Interface.Devices[A_Index].IsOwned){ 387 | this.Interface.Devices[A_Index].Relinquish() 388 | break 389 | } 390 | } 391 | } 392 | ret := this.Interface.AcquireVJD(this.DeviceID) 393 | if (ret && this.Interface.ResetOnAcquire){ 394 | ; Reset the Device so it centers 395 | this.Interface.ResetVJD(this.DeviceID) 396 | } else { 397 | if (this.Interface.DebugMode) { 398 | OutputDebug, % "Error in " A_ThisFunc "`nDeviceID = " this.DeviceID ", ErrorLevel: " ErrorLevel ", Device Status: " this.GetStatusName() 399 | } 400 | } 401 | return ret 402 | } 403 | 404 | ; Relinquish the device, resetting it if Owned 405 | Relinquish(){ 406 | if (this.IsOwned && this.Interface.ResetOnRelinquish){ 407 | this.Interface.ResetVJD(this.DeviceID) 408 | } 409 | return this.Interface.RelinquishVJD(this.DeviceID) 410 | } 411 | 412 | Reset(){ 413 | this.Interface.ResetVJD(this.DeviceID) 414 | } 415 | 416 | ResetButtons(){ 417 | this.Interface.ResetButtons(this.DeviceID) 418 | } 419 | 420 | ResetPovs(){ 421 | this.Interface.ResetButtons(this.DeviceID) 422 | } 423 | 424 | ; Does the device exist or not? 425 | IsEnabled(){ 426 | state := this.GetStatus() 427 | return state != this.Interface.VJD_STAT_MISS && state != this.Interface.VJD_STAT_UNKN 428 | } 429 | 430 | ; Is it possible to take control of the device? 431 | IsAvailable(){ 432 | state := this.GetStatus() 433 | return state == this.Interface.VJD_STAT_FREE || state == this.Interface.VJD_STAT_OWN 434 | } 435 | 436 | ; Set Axis by Index number. 437 | ; eg x = 1, y = 2, z = 3, rx = 4 438 | SetAxisByIndex(axis_val, index){ 439 | if (!this.Acquire()){ 440 | return 0 441 | } 442 | return this.Interface.SetAxis(axis_val, this.DeviceID, this.Interface.AxisIndex[index]) 443 | } 444 | 445 | ; Set Axis by Name 446 | ; eg "x", "y", "z", "rx" 447 | SetAxisByName(axis_val, name){ 448 | if (!this.Acquire()){ 449 | return 0 450 | } 451 | return this.Interface.SetAxis(axis_val, this.DeviceID, this.Interface.AxisAssoc[name]) 452 | } 453 | 454 | SetBtn(btn_val, btn){ 455 | if (!this.Acquire()){ 456 | return 0 457 | } 458 | return this.Interface.SetBtn(btn_val, this.DeviceID, btn) 459 | } 460 | 461 | SetDiscPov(pov_val, pov){ 462 | if (!this.Acquire()){ 463 | return 0 464 | } 465 | return this.Interface.SetDiscPov(pov_val, this.DeviceID, pov) 466 | } 467 | 468 | SetContPov(pov_val, pov){ 469 | if (!this.Acquire()){ 470 | return 0 471 | } 472 | return this.Interface.SetContPov(pov_val, this.DeviceID, pov) 473 | } 474 | 475 | ; Constructor 476 | __New(id, parent){ 477 | this.DeviceID := id 478 | this.Interface := parent 479 | } 480 | 481 | ; Destructor 482 | __Delete(){ 483 | this.Relinquish() 484 | } 485 | } 486 | 487 | 488 | ;;;;;;;;;================== 489 | Class CvXBoxDevice { 490 | IsOwned := 0 491 | xID := "" 492 | 493 | GetStatus(){ 494 | return this.Interface.GetVJDStatus(this.DeviceID) 495 | } 496 | 497 | ; Converts Status to human readable form 498 | GetStatusName(){ 499 | DeviceStatus := this.GetStatus() 500 | if (DeviceStatus = this.Interface.VJD_STAT_OWN) { 501 | return "OWN" 502 | } else if (DeviceStatus = this.Interface.VJD_STAT_FREE) { 503 | return "FREE" 504 | } else if (DeviceStatus = this.Interface.VJD_STAT_BUSY) { 505 | return "BUSY" 506 | } else if (DeviceStatus = this.Interface.VJD_STAT_MISS) { 507 | return "MISS" 508 | } else { 509 | return "???" 510 | } 511 | } 512 | 513 | PlugIn() { 514 | return this.Interface.PlugInNext() 515 | } 516 | 517 | unPlug() { 518 | this.IsOwned := 0 519 | return this.Interface.UnPlug(this.DeviceID) 520 | } 521 | 522 | GetLEDNumber() { 523 | return this.Interface.GetLedNumber(this.DeviceID) 524 | } 525 | 526 | 527 | ; Acquire the device 528 | Acquire(){ 529 | if (this.IsOwned){ 530 | return 1 531 | } 532 | if (this.Interface.SingleStickMode){ 533 | Loop % this.Interface.xDevices.MaxIndex() { 534 | if (A_Index == this.DeviceID){ 535 | Continue 536 | } 537 | if (this.Interface.xDevices[A_Index].IsOwned){ 538 | this.Interface.xDevices[A_Index].Relinquish() 539 | break 540 | } 541 | } 542 | } 543 | ret := this.Interface.AcquireDev(this.DeviceID) 544 | if (ret && this.Interface.ResetOnAcquire){ 545 | ; Reset the Device so it centers 546 | this.Interface.ResetController(this.DeviceID) 547 | } else { 548 | if (this.Interface.DebugMode) { 549 | OutputDebug, % "Error in " A_ThisFunc "`nDeviceID = " this.DeviceID ", ErrorLevel: " ErrorLevel ", Device Status: " this.GetStatusName() 550 | } 551 | } 552 | return ret 553 | } 554 | 555 | ; Relinquish the device, resetting it if Owned 556 | Relinquish(){ 557 | if (this.IsOwned && this.Interface.ResetOnRelinquish){ 558 | this.Interface.ResetController(this.DeviceID) 559 | } 560 | return this.Interface.RelinquishDev(this.DeviceID) 561 | } 562 | 563 | Reset(){ 564 | this.Interface.ResetController(this.DeviceID) 565 | } 566 | 567 | ResetButtons(){ 568 | this.Interface.ResetController(this.DeviceID) 569 | } 570 | 571 | ResetPovs(){ 572 | this.Interface.ResetController(this.DeviceID) 573 | } 574 | 575 | ; Does the device exist or not? 576 | IsEnabled(){ 577 | state := this.GetStatus() 578 | return state != this.Interface.VJD_STAT_MISS && state != this.Interface.VJD_STAT_UNKN 579 | } 580 | 581 | ; Is it possible to take control of the device? 582 | IsAvailable(){ 583 | state := this.GetStatus() 584 | return state == this.Interface.VJD_STAT_FREE || state == this.Interface.VJD_STAT_OWN 585 | } 586 | 587 | IsControllerOwned(){ 588 | return this.Interface.isControllerOwned(this.DeviceID) 589 | } 590 | 591 | ; Set Axis by Index number. 592 | ; eg x = 1, y = 2, z = 3, rx = 4 593 | SetAxisByIndex(axis_val, index){ 594 | if (!this.Acquire()){ 595 | return 0 596 | } 597 | return this.Interface.SetDevAxis(axis_val, this.DeviceID, index) 598 | } 599 | 600 | 601 | ; Set Axis by Name 602 | ; eg "x", "y", "z", "rx" 603 | SetAxisByName(axis_val, name){ 604 | if (!this.Acquire()){ 605 | return 0 606 | } 607 | return this.Interface.SetDevAxis(axis_val, this.DeviceID, this.Interface.AxisAssoc[name]) 608 | } 609 | 610 | SetPOV(POV_dir) { 611 | if (!this.Acquire()){ 612 | return 0 613 | } 614 | return this.Interface.SetDevPov( POV_dir,this.DeviceID, 1) 615 | } 616 | 617 | SetBtn(btn_val, btn){ 618 | if (!this.Acquire()){ 619 | return 0 620 | } 621 | return this.Interface.SetDevBtn(btn_val, this.DeviceID, btn) 622 | } 623 | 624 | SetDiscPov(pov_val, pov){ 625 | if (!this.Acquire()){ 626 | return 0 627 | } 628 | return this.Interface.SetDiscPov(pov_val, this.DeviceID, pov) 629 | } 630 | 631 | SetContPov(pov_val, pov){ 632 | if (!this.Acquire()){ 633 | return 0 634 | } 635 | return this.Interface.SetContPov(pov_val, this.DeviceID, pov) 636 | } 637 | 638 | ; Constructor 639 | __New(id, parent){ 640 | this.DeviceID := id 641 | this.Interface := parent 642 | } 643 | 644 | ; Destructor 645 | __Delete(){ 646 | this.Relinquish() 647 | } 648 | } 649 | 650 | } 651 | -------------------------------------------------------------------------------- /CvJI/CvJoyInterface.ahk: -------------------------------------------------------------------------------- 1 |  2 | Class CvJoyInterface { 3 | DebugMode := 0 4 | SingleStickMode := 1 ; If set to 1, helper classes will automatically relinquish existing vjoy device on attempting to acquire one not connected. 5 | ResetOnAcquire := 1 ; Resets Devices to vjoy norms on Acquire via helper classes. 6 | ResetOnRelinquish := 1 ; Resets Devices to vjoy norms on Relinquish via helper classes. 7 | LibraryLoaded := 0 ; Did the Library Load OK when the class Instantiated? 8 | LoadLibraryLog := "" ; If Not, holds log of why it failed. 9 | hModule := 0 ; handle to DLL 10 | Devices := [] ; Array for Helper Classes of Devices 11 | 12 | VJD_MAXDEV := 16 ; Max Number of Devices vJoy Supports 13 | 14 | ; ported from VjdStat in vjoyinterface.h 15 | VJD_STAT_OWN := 0 ; The vJoy Device is owned by this application. 16 | VJD_STAT_FREE := 1 ; The vJoy Device is NOT owned by any application (including this one). 17 | VJD_STAT_BUSY := 2 ; The vJoy Device is owned by another application. It cannot be acquired by this application. 18 | VJD_STAT_MISS := 3 ; The vJoy Device is missing. It either does not exist or the driver is down. 19 | VJD_STAT_UNKN := 4 ; Unknown 20 | 21 | ; HID Descriptor definitions(ported from public.h) 22 | HID_USAGE_X := 0x30 23 | HID_USAGE_Y := 0x31 24 | HID_USAGE_Z := 0x32 25 | HID_USAGE_RX:= 0x33 26 | HID_USAGE_RY:= 0x34 27 | HID_USAGE_RZ:= 0x35 28 | HID_USAGE_SL0:= 0x36 29 | HID_USAGE_SL1:= 0x37 30 | 31 | ; Handy lookups to axis HID_USAGE values 32 | AxisIndex := [0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37] ; Index (Axis Number) to HID Descriptor 33 | AxisAssoc := {x:0x30, y:0x31, z:0x32, rx:0x33, ry:0x34, rz: 0x35, sl1:0x36, sl2:0x37} ; Name (eg "x", "y", "z", "sl1") to HID Descriptor 34 | AxisNames := ["X","Y","Z","RX","RY","RZ","SL0","SL1"] 35 | 36 | ; ===== Device helper subclass. 37 | Class CvJoyDevice { 38 | IsOwned := 0 39 | 40 | GetStatus(){ 41 | return this.Interface.GetVJDStatus(this.DeviceID) 42 | } 43 | 44 | ; Converts Status to human readable form 45 | GetStatusName(){ 46 | DeviceStatus := this.GetStatus() 47 | if (DeviceStatus = this.Interface.VJD_STAT_OWN) { 48 | return "OWN" 49 | } else if (DeviceStatus = this.Interface.VJD_STAT_FREE) { 50 | return "FREE" 51 | } else if (DeviceStatus = this.Interface.VJD_STAT_BUSY) { 52 | return "BUSY" 53 | } else if (DeviceStatus = this.Interface.VJD_STAT_MISS) { 54 | return "MISS" 55 | } else { 56 | return "???" 57 | } 58 | } 59 | 60 | ; Acquire the device 61 | Acquire(){ 62 | if (this.IsOwned){ 63 | return 1 64 | } 65 | if (this.Interface.SingleStickMode){ 66 | Loop % this.Interface.Devices.MaxIndex() { 67 | if (A_Index == this.DeviceID){ 68 | Continue 69 | } 70 | if (this.Interface.Devices[A_Index].IsOwned){ 71 | this.Interface.Devices[A_Index].Relinquish() 72 | break 73 | } 74 | } 75 | } 76 | ret := this.Interface.AcquireVJD(this.DeviceID) 77 | if (ret && this.Interface.ResetOnAcquire){ 78 | ; Reset the Device so it centers 79 | this.Interface.ResetVJD(this.DeviceID) 80 | } else { 81 | if (this.Interface.DebugMode) { 82 | OutputDebug, % "Error in " A_ThisFunc "`nDeviceID = " this.DeviceID ", ErrorLevel: " ErrorLevel ", Device Status: " this.GetStatusName() 83 | } 84 | } 85 | return ret 86 | } 87 | 88 | ; Relinquish the device, resetting it if Owned 89 | Relinquish(){ 90 | if (this.IsOwned && this.Interface.ResetOnRelinquish){ 91 | this.Interface.ResetVJD(this.DeviceID) 92 | } 93 | return this.Interface.RelinquishVJD(this.DeviceID) 94 | } 95 | 96 | Reset(){ 97 | this.Interface.ResetVJD(this.DeviceID) 98 | } 99 | 100 | ResetButtons(){ 101 | this.Interface.ResetButtons(this.DeviceID) 102 | } 103 | 104 | ResetPovs(){ 105 | this.Interface.ResetButtons(this.DeviceID) 106 | } 107 | 108 | ; Does the device exist or not? 109 | IsEnabled(){ 110 | state := this.GetStatus() 111 | return state != this.Interface.VJD_STAT_MISS && state != this.Interface.VJD_STAT_UNKN 112 | } 113 | 114 | ; Is it possible to take control of the device? 115 | IsAvailable(){ 116 | state := this.GetStatus() 117 | return state == this.Interface.VJD_STAT_FREE || state == this.Interface.VJD_STAT_OWN 118 | } 119 | 120 | ; Set Axis by Index number. 121 | ; eg x = 1, y = 2, z = 3, rx = 4 122 | SetAxisByIndex(axis_val, index){ 123 | if (!this.Acquire()){ 124 | return 0 125 | } 126 | return this.Interface.SetAxis(axis_val, this.DeviceID, this.Interface.AxisIndex[index]) 127 | } 128 | 129 | ; Set Axis by Name 130 | ; eg "x", "y", "z", "rx" 131 | SetAxisByName(axis_val, name){ 132 | if (!this.Acquire()){ 133 | return 0 134 | } 135 | return this.Interface.SetAxis(axis_val, this.DeviceID, this.Interface.AxisAssoc[name]) 136 | } 137 | 138 | SetBtn(btn_val, btn){ 139 | if (!this.Acquire()){ 140 | return 0 141 | } 142 | return this.Interface.SetBtn(btn_val, this.DeviceID, btn) 143 | } 144 | 145 | SetDiscPov(pov_val, pov){ 146 | if (!this.Acquire()){ 147 | return 0 148 | } 149 | return this.Interface.SetDiscPov(pov_val, this.DeviceID, pov) 150 | } 151 | 152 | SetContPov(pov_val, pov){ 153 | if (!this.Acquire()){ 154 | return 0 155 | } 156 | return this.Interface.SetContPov(pov_val, this.DeviceID, pov) 157 | } 158 | 159 | ; Constructor 160 | __New(id, parent){ 161 | this.DeviceID := id 162 | this.Interface := parent 163 | } 164 | 165 | ; Destructor 166 | __Delete(){ 167 | this.Relinquish() 168 | } 169 | } 170 | 171 | ; ===== Constructors / Destructors 172 | __New(){ 173 | ; Build Device array 174 | Loop % this.VJD_MAXDEV { 175 | this.Devices[A_Index] := new this.CvJoyDevice(A_Index, this) 176 | } 177 | 178 | ; Try and Load the DLL 179 | this.LoadLibrary() 180 | return this 181 | } 182 | 183 | __Delete(){ 184 | ; Relinquish Devices 185 | Loop % this.VJD_MAXDEV { 186 | this.Devices[A_Index].Relinquish() 187 | } 188 | 189 | ; Unload DLL 190 | if (this.hModule){ 191 | DllCall("FreeLibrary", "Ptr", this.hModule) 192 | } 193 | } 194 | 195 | ; ===== Helper Functions 196 | ; Converts vJoy range (0->32768 to a range like an AHK input 0->100) 197 | PercentTovJoy(percent){ 198 | return percent * 327.68 199 | } 200 | 201 | vJoyToPercent(vJoy){ 202 | return vJoy / 327.68 203 | } 204 | 205 | ; ===== DLL loading / vJoy Install detection 206 | 207 | ; Load the vJoyInterface DLL. 208 | LoadLibrary() { 209 | ;Global hModule 210 | 211 | if (this.LibraryLoaded) { 212 | this.LoadLibraryLog .= "Library already loaded. Aborting...`n" 213 | return 1 214 | } 215 | 216 | this.LoadLibraryLog := "" 217 | 218 | ; Check if vJoy is installed. Even with the DLL, if vJoy is not installed it will not work... 219 | ; Find vJoy install folder by looking for registry key. 220 | if (A_Is64bitOS && A_PtrSize != 8){ 221 | SetRegView 64 222 | } 223 | RegRead vJoyFolder, HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{8E31F76F-74C3-47F1-9550-E041EEDC5FBB}_is1, InstallLocation 224 | 225 | if (!vJoyFolder){ 226 | this.LoadLibraryLog .= "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." 227 | return 0 228 | } 229 | 230 | ; Try to find location of correct DLL. 231 | ; vJoy versions prior to 2.0.4 241214 lack these registry keys - if key not found, advise update. 232 | if (A_PtrSize == 8){ 233 | ; 64-Bit AHK 234 | DllKey := "DllX64Location" 235 | SecondFolder := vJoyFolder . "x64" 236 | } else { 237 | ; 32-Bit AHK 238 | DllKey := "DllX86Location" 239 | SecondFolder := vJoyFolder . "x86" 240 | } 241 | RegRead DllFolder, HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{8E31F76F-74C3-47F1-9550-E041EEDC5FBB}_is1, % DllKey 242 | 243 | if (!DllFolder){ 244 | ; Could not find registry entry. Advise vJoy update. 245 | this.LoadLibraryLog .= "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." 246 | DllFolder := SecondFolder 247 | } 248 | 249 | DllFolder .= "\" 250 | 251 | ; All good so far, try and load the DLL 252 | DllFile := "vJoyInterface.dll" 253 | this.LoadLibraryLog := "vJoy Install Detected. Trying to load " DllFile "...`n" 254 | CheckLocations := [DllFolder DllFile] 255 | 256 | hModule := 0 257 | Loop % CheckLocations.Maxindex() { 258 | this.LoadLibraryLog .= "Checking " CheckLocations[A_Index] "... " 259 | if (FileExist(CheckLocations[A_Index])){ 260 | this.LoadLibraryLog .= "FOUND.`nTrying to load.. " 261 | hModule := DLLCall("LoadLibrary", "Str", CheckLocations[A_Index]) 262 | if (hModule){ 263 | this.hModule := hModule 264 | this.LoadLibraryLog .= "OK.`n" 265 | this.LoadLibraryLog .= "Checking driver enabled... " 266 | if (this.vJoyEnabled()){ 267 | this.LibraryLoaded := 1 268 | this.LoadLibraryLog .= "OK.`n" 269 | this.LoadLibraryLog .= "Loaded vJoy DLL version " this.GetvJoyVersion() "`n" 270 | if (this.DebugMode){ 271 | OutputDebug, % this.LoadLibraryLog 272 | } 273 | return 1 274 | } else { 275 | this.LoadLibraryLog .= "FAILED.`n" 276 | } 277 | } else { 278 | this.LoadLibraryLog .= "FAILED.`n" 279 | } 280 | } else { 281 | this.LoadLibraryLog .= "NOT FOUND.`n" 282 | } 283 | } 284 | this.LoadLibraryLog .= "`nFailed to load valid " DllFile "`n" 285 | this.LibraryLoaded := 0 286 | return 0 287 | } 288 | 289 | ; ===== vJoy Interface DLL call wrappers 290 | ; In the order detailed in the vJoy SDK's Interface Function Reference 291 | ; http://sourceforge.net/projects/vjoystick/files/ 292 | 293 | ; === General driver data 294 | vJoyEnabled(){ 295 | return DllCall("vJoyInterface\vJoyEnabled") 296 | } 297 | 298 | GetvJoyVersion(){ 299 | return DllCall("vJoyInterface\GetvJoyVersion") 300 | } 301 | 302 | GetvJoyProductString(){ 303 | return DllCall("vJoyInterface\GetvJoyProductString") 304 | } 305 | 306 | GetvJoyManufacturerString(){ 307 | return DllCall("vJoyInterface\GetvJoyManufacturerString") 308 | } 309 | 310 | GetvJoySerialNumberString(){ 311 | return DllCall("vJoyInterface\GetvJoySerialNumberString") 312 | } 313 | 314 | ; === Write access to vJoy Device 315 | GetVJDStatus(rID){ 316 | return DllCall("vJoyInterface\GetVJDStatus", "UInt", rID) 317 | } 318 | 319 | ; Handle setting IsOwned property outside helper class, to allow mixing 320 | AcquireVJD(rID){ 321 | this.Devices[rID].IsOwned := DllCall("vJoyInterface\AcquireVJD", "UInt", rID) 322 | return this.Devices[rID].IsOwned 323 | } 324 | 325 | RelinquishVJD(rID){ 326 | DllCall("vJoyInterface\RelinquishVJD", "UInt", rID) 327 | this.Devices[rID].IsOwned := 0 328 | return this.Devices[rID].IsOwned 329 | } 330 | 331 | ; Not sure if this one is good. What is a "PVOID"? 332 | UpdateVJD(rID, pData){ 333 | return DllCall("vJoyInterface\UpdateVJD", "UInt", rID, "PVOID", pData) 334 | } 335 | 336 | ; === vJoy Device properties 337 | 338 | GetVJDButtonNumber(rID){ 339 | return DllCall("vJoyInterface\GetVJDButtonNumber", "UInt", rID) 340 | } 341 | 342 | GetVJDDiscPovNumber(rID){ 343 | return DllCall("vJoyInterface\GetVJDDiscPovNumber", "UInt", rID) 344 | } 345 | 346 | GetVJDContPovNumber(rID){ 347 | return DllCall("vJoyInterface\GetVJDContPovNumber", "UInt", rID) 348 | } 349 | 350 | GetVJDAxisExist(rID, Axis){ 351 | return DllCall("vJoyInterface\GetVJDAxisExist", "UInt", rID, "Uint", Axis) 352 | } 353 | 354 | ResetVJD(rID){ 355 | return DllCall("vJoyInterface\ResetVJD", "UInt", rID) 356 | } 357 | 358 | ResetAll(){ 359 | return DllCall("vJoyInterface\ResetAll") 360 | } 361 | 362 | ResetButtons(rID){ 363 | return DllCall("vJoyInterface\ResetButtons", "UInt", rID) 364 | } 365 | 366 | ResetPovs(rID){ 367 | return DllCall("vJoyInterface\ResetPovs", "UInt", rID) 368 | } 369 | 370 | SetAxis(Value, rID, Axis){ 371 | return DllCall("vJoyInterface\SetAxis", "Int", Value, "UInt", rID, "UInt", Axis) 372 | } 373 | 374 | SetBtn(Value, rID, nBtn){ 375 | return DllCall("vJoyInterface\SetBtn", "Int", Value, "UInt", rID, "UInt", nBtn) 376 | } 377 | 378 | SetDiscPov(Value, rID, nPov){ 379 | return DllCall("vJoyInterface\SetDiscPov", "Int", Value, "UInt", rID, "UChar", nPov) 380 | } 381 | 382 | SetContPov(Value, rID, nPOV){ 383 | return DllCall("vJoyInterface\SetContPov", "Int", Value, "UInt", rID, "UChar", nPov) 384 | } 385 | 386 | } 387 | -------------------------------------------------------------------------------- /CvJI/MouseDelta.ahk: -------------------------------------------------------------------------------- 1 | ; Instantiate this class and pass it a func name or a Function Object 2 | ; The specified function will be called with the delta move for the X and Y axes 3 | ; Normally, there is no windows message "mouse stopped", so one is simulated. 4 | ; After 10ms of no mouse movement, the callback is called with 0 for X and Y 5 | Class MouseDelta { 6 | State := 0 7 | __New(callback){ 8 | this.TimeoutFn := this.TimeoutFunc.Bind(this) 9 | this.MouseMovedFn := this.MouseMoved.Bind(this) 10 | 11 | this.Callback := callback 12 | } 13 | 14 | Start(){ 15 | static DevSize := 8 + A_PtrSize, RIDEV_INPUTSINK := 0x00000100 16 | ; Register mouse for WM_INPUT messages. 17 | VarSetCapacity(RAWINPUTDEVICE, DevSize) 18 | NumPut(1, RAWINPUTDEVICE, 0, "UShort") 19 | NumPut(2, RAWINPUTDEVICE, 2, "UShort") 20 | NumPut(RIDEV_INPUTSINK, RAWINPUTDEVICE, 4, "Uint") 21 | ; WM_INPUT needs a hwnd to route to, so get the hwnd of the AHK Gui. 22 | ; It doesn't matter if the GUI is showing, it still exists 23 | Gui +hwndhwnd 24 | NumPut(hwnd, RAWINPUTDEVICE, 8, "Uint") 25 | 26 | this.RAWINPUTDEVICE := RAWINPUTDEVICE 27 | DllCall("RegisterRawInputDevices", "Ptr", &RAWINPUTDEVICE, "UInt", 1, "UInt", DevSize ) 28 | OnMessage(0x00FF, this.MouseMovedFn) 29 | this.State := 1 30 | return this ; allow chaining 31 | } 32 | 33 | Stop(){ 34 | static RIDEV_REMOVE := 0x00000001 35 | static DevSize := 8 + A_PtrSize 36 | OnMessage(0x00FF, this.MouseMovedFn, 0) 37 | RAWINPUTDEVICE := this.RAWINPUTDEVICE 38 | NumPut(RIDEV_REMOVE, RAWINPUTDEVICE, 4, "Uint") 39 | DllCall("RegisterRawInputDevices", "Ptr", &RAWINPUTDEVICE, "UInt", 1, "UInt", DevSize ) 40 | this.State := 0 41 | return this ; allow chaining 42 | } 43 | 44 | SetState(state){ 45 | if (state && !this.State) 46 | this.Start() 47 | else if (!state && this.State) 48 | this.Stop() 49 | return this ; allow chaining 50 | } 51 | 52 | Delete(){ 53 | this.Stop() 54 | ;~ this.TimeoutFn := "" 55 | this.MouseMovedFn := "" 56 | } 57 | 58 | ; Called when the mouse moved. 59 | ; Messages tend to contain small (+/- 1) movements, and happen frequently (~20ms) 60 | MouseMoved(wParam, lParam){ 61 | ;Critical 62 | ; RawInput statics 63 | static DeviceSize := 2 * A_PtrSize, iSize := 0, sz := 0, pcbSize:=8+2*A_PtrSize, offsets := {x: (20+A_PtrSize*2), y: (24+A_PtrSize*2)}, uRawInput 64 | 65 | static axes := {x: 1, y: 2} 66 | 67 | ; Get hDevice from RAWINPUTHEADER to identify which mouse this data came from 68 | VarSetCapacity(header, pcbSize, 0) 69 | If (!DllCall("GetRawInputData", "UPtr", lParam, "uint", 0x10000005, "UPtr", &header, "Uint*", pcbSize, "Uint", pcbSize) or ErrorLevel) 70 | Return 0 71 | ThisMouse := NumGet(header, 8, "UPtr") 72 | 73 | ; Find size of rawinput data - only needs to be run the first time. 74 | if (!iSize){ 75 | r := DllCall("GetRawInputData", "UInt", lParam, "UInt", 0x10000003, "Ptr", 0, "UInt*", iSize, "UInt", 8 + (A_PtrSize * 2)) 76 | VarSetCapacity(uRawInput, iSize) 77 | } 78 | sz := iSize ; param gets overwritten with # of bytes output, so preserve iSize 79 | ; Get RawInput data 80 | r := DllCall("GetRawInputData", "UInt", lParam, "UInt", 0x10000003, "Ptr", &uRawInput, "UInt*", sz, "UInt", 8 + (A_PtrSize * 2)) 81 | 82 | x := 0, y := 0 ; Ensure we always report a number for an axis. Needed? 83 | x := NumGet(&uRawInput, offsets.x, "Int") 84 | y := NumGet(&uRawInput, offsets.y, "Int") 85 | 86 | this.Callback.(ThisMouse, x, y) 87 | 88 | ; There is no message for "Stopped", so simulate one 89 | fn := this.TimeoutFn 90 | SetTimer, % fn, -33 91 | } 92 | 93 | TimeoutFunc(){ 94 | this.Callback.("RESET", 0, 0) 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /CvJI/SelfDeletingTimer.ahk: -------------------------------------------------------------------------------- 1 | ;https://autohotkey.com/boards/viewtopic.php?t=13010 2 | 3 | class SelfDeletingTimer { 4 | __New(period, fn, prms*) { 5 | this.fn := IsObject(fn) ? fn : Func(fn) 6 | this.prms := prms 7 | SetTimer % this, % period 8 | } 9 | Call() { 10 | this.fn.Call(this.prms*) 11 | SetTimer % this, Delete 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Layouts_1.8/Wii U GamePad - vJoy Device_Custom.ccc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CemuUser8/mouse2joystick_custom_CEMU/c7cfdb830929ac46c24e89b112e3fcfbb18ae1d3/Layouts_1.8/Wii U GamePad - vJoy Device_Custom.ccc -------------------------------------------------------------------------------- /Layouts_1.8/Wii U Pro Controller - vJoy Device_Custom.ccc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CemuUser8/mouse2joystick_custom_CEMU/c7cfdb830929ac46c24e89b112e3fcfbb18ae1d3/Layouts_1.8/Wii U Pro Controller - vJoy Device_Custom.ccc -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Not Being Maintained 2 | 3 | # Script last updated on May 20, 2020. 4 | Version 0.4.1.4 5 | 6 | * Added ability to map the mouse wheel to keys in the keylist helper 7 | * Wheel keys can't be used to hold down buttons, since wheels don't send an UP keystroke like all the other keys. 8 | * Added a Save button to the settings, so you can save and apply your settings without closing the window. This should make it easier to tweak and play with settings while testing. 9 | * Added ability to adjust the walking speed, no longer set to 50%. [Keybinds work on the fly as you are moving.](https://imgur.com/25brjqd) 10 | * You can change the speed by setting and pressing the `+` and `-` keybinds 11 | * I believe I have finally fixed the controller profiles for the Wii U Pro Controller for both vJoy and vXbox. 12 | 13 |   14 | 15 | Older Changes: 16 | * Completely re-wrote settings code 17 | * Allows me to more easily manage adding and/or changing the settings for the script 18 | * [Added ability to save keylists](https://i.imgur.com/E6Bualc.png), in pretty much the exact way CEMU lets you manage Controller Profiles 19 | * From this version on **64bit is required**, this shouldn't' be an issue since CEMU already has that requirement. 20 | * Updated included ScpVBus, as the version I had was outdated, and probably 32bit. 21 | 22 | I highly recommend deleting your `settings.ini` file when upgrading to this version. Things have moved, and one section changed names ever so slightly. The way this works shouldn't cause any actual issues, but still the file will be cleaner if you: make note your settings -> delete the file -> re-input your changes. 23 | 24 | 25 |   26 | 27 | [Updated Video - April 5, 2018] [BSoD Gaming made a video](https://www.youtube.com/watch?v=bOJy67OJfZI) that shows how to set this up. It is incomplete, but for the most part it shows the initial process very well. It doesn't get into details about anything, and while it recommends using the alternate mouse movement detection **be aware that this is still experimental** and already implemented slightly different from the version used in the video. Also, changing your mouse sensitivity will only really have an effect with this experimental mode, not really on the normal mode. Along the same lines, the sensitivity he has in the settings are invalid (negative values make no sense with how it is implemented and might even cause issues), but again since he is using the alternate method they have zero effect on the program. 28 | 29 | *** 30 | # Initial Setup (Updated to include vXBox images) 31 | *** 32 | 1. Install the latest [vJoy](https://sourceforge.net/projects/vjoystick/files/latest/download) 33 | 2. Run the [vJoy Configuration](http://i.imgur.com/vvHW0yz.png) (Not necessary if you only plan on using vXBox) 34 | * Set it up so it has **at least 18 Buttons**, I set mine to 32. 35 | 3. [Download controller profiles](https://bitbucket.org/CemuUser8/files/downloads/controllerProfiles.zip) for CEMU > 1.9.0      *(Also included in GitHub release zip)* 36 | * Extract these text files into your [CEMU controllerProfiles folder](https://i.imgur.com/Mf5L6km.png) 37 | 4. Then open CEMU and goto the [input settings](http://i.imgur.com/N5Nibtq.png) 38 | * Choose the type of controller you want to use, [either 'Wii U Pro Controller' or 'Wii U GamePad'](http://i.imgur.com/sfKWlgu.png) 39 | * If using standard vJoy Device 40 | * Choose [DirectInput for the Controller API](http://i.imgur.com/KKCLqs8.png) 41 | * Make sure to [choose the device as `vJoy Device` and confirm it says connected](http://i.imgur.com/Zx9pTmK.png) 42 | * If using vXBox Device 43 | * **Run the script FIRST and [choose 'Use vXBox Device'](https://i.imgur.com/s2TnMep.png) on the General Page of settings** 44 | * If this is the first time you will be prompted to Install ScpVBus, choose yes, then yes again on the security prompt to run `DevCon` 45 | * Script will reload and if the message box doesn't show up again you should be ready to use vXBox. 46 | * Choose [XInput for the Controller API](https://i.imgur.com/2sPQM3e.png) 47 | * Make sure to [choose a controller and confirm it says connected](https://i.imgur.com/syOuO0f.png) (May need to press refresh for Controller to show up) 48 | * If it doesn't say connected try [switching the vXBox device number in the script settings](https://i.imgur.com/3MC3B9L.png) one of them WILL say connected in CEMU (this seems to be a CEMU quirk as other applications don't care which vXBox device is selected it will always grab the active one) 49 | * *Not sure if necessary but [Press Calibrate](http://i.imgur.com/3E6UrZX.png)* 50 | * Choose the [appropriate Profile](https://i.imgur.com/zMdtNwy.png) for the type of controller you are setting up. 51 | * [Click Load](http://i.imgur.com/PQFlfr1.png) 52 | 53 |   54 | 55 | * For vJoy devices -- The input setup should look [like this](http://i.imgur.com/SvBR4BN.png) 56 | 57 | * For vXBox devices -- The input setup should look [like this](https://i.imgur.com/ZAVpvMa.png) 58 | * *Note: feel free to manually remap the blow mic and showscreen buttons here, as the vXBox controller doesn't have enough buttons for them to be included.* 59 | 60 | ### If it doesn't look like this, you are going to have a problem 61 | 62 | *** 63 | # Using the Script and changing the key mapping 64 | *** 65 | 1. Visit the [GitHub release page](https://github.com/CemuUser8/mouse2joystick_custom_CEMU/releases) and download the latest release (0.4.1.4 currently) 66 | 2. Launch the script: 67 | * Double click the `.ahk` file if you have AutoHotKey installed. 68 | * Run the exe if you don't. 69 | 3. IF you don't want to customize anything you are ready to use the Script. 70 | * Press `F1` to toggle the controller ( CEMU and Script must be running ) 71 | 72 | **Mapping your keys** 73 | 74 | * Open the script settings by right clicking on the [controller icon in your system tray](http://i.imgur.com/fPBWOsU.png) (Bottom Right) and choose 'settings' 75 | * Goto the [Mouse2Joystick->Keys](http://i.imgur.com/eMMnEGj.png) page: 76 | * You can set the [KeyList](http://i.imgur.com/JSJ1KsH.png) here 77 | * This is a comma separated list of [AHK valid keys](https://autohotkey.com/docs/KeyList.htm) in order of vJoy Buttons 78 | * The first key is mapped to `Button 0` and so on. 79 | * Manually setting the list has an advantage in that you can add more than one key to the same button (New as of 0.2.0.3) 80 | * This is accomplished by adding the keys together using the `|` symbol. 81 | * i.e. you'll notice `Xbutton1|e,` is what I have set for `A` -- allowing `Mouse4` and `e` to both work. 82 | * I recommend setting up the keys with the Helper as below, then adding in any desired secondary keys manually. 83 | * [KeyList Helper](http://i.imgur.com/VF2vwfE.png) 84 | * This is an [interface that closely matches CEMU input layout](http://i.imgur.com/ewQL8ff.png), which will make it easy to create your KeyList. 85 | * You just need to click each box and then press the key you would like to use 86 | * Can be mouse buttons 87 | * AutoCycle will go through each key one by one allowing you to quickly set the keys 88 | * When you click save you will see the KeyList string update itself with any changes you've made. 89 | * If you'd like to add secondary keys now is a great time to do it. 90 | 91 | Note: you can still keep KeyList strings for different games saved to a text file locally, and just paste it in (like it used to have to be done) 92 | 93 | *** 94 | 95 | **Other Settings Overview** 96 | 97 | * Open the script settings by right clicking on the [controller icon in your system tray](http://i.imgur.com/fPBWOsU.png) (Bottom Right) and choose 'settings' 98 | * On the [General](http://i.imgur.com/hmMxz21.png) page: 99 | * Input Destination 100 | * If you changed the name of your cemu executable enter it here 101 | * Activate Executable 102 | * Choose to have the script automatically activate cemu when controller is toggled on 103 | * vJoy Device 104 | * Choose which vJoy device to control, if you have more than one set up. 105 | * On the [General->Setup](http://i.imgur.com/ROm9GO4.png) page: 106 | * Sensitivity 107 | * Controls how far the mouse needs to move to tilt the stick 108 | * Lower values are more sensitive, I recommend 30-100 109 | * Non-Linear Sensitivity 110 | * Lower values cause the sensitivity to be raised near the center 111 | * Deadzone 112 | * Can be set very close to 0, I recommend setting to the smallest possible value where your camera doesn't wander. 113 | * Mouse Check Frequency 114 | * This is how often the mouse position is checked and reset back to the center. 115 | * On the [General->Hotkeys](http://i.imgur.com/fkbmOvP.png) page: 116 | * Quit Application 117 | * A Master Hotkey to quit out of the script immediately 118 | * Toggle the controller on/off 119 | * Set the key to choose the Toggle for the controller (Default F1) 120 | * On the [Mouse2Joystick->Axes](http://i.imgur.com/EEiTuJM.png) page: 121 | * Invert Axis, is self explanatory 122 | * Apparently I initally mapped my y-axis as inverted, so 'Yes' here means 'No' (Sorry) 123 | * On the [Mouse2Joystick->Keys](http://i.imgur.com/eMMnEGj.png) page: 124 | * This is the Most important page as it is where you change your assigned keys 125 | * **Covered in more detail above** 126 | * On the [KeyboardMovement->Keys](http://i.imgur.com/okKlFwE.png) page: 127 | * Keyboard Movement 128 | * Set your movement keys here. 129 | * Extra Keyboard Keys 130 | * Set your Toggle Walk, ZL Lock, Gyro keys here 131 | * On the [Extra Settings](http://i.imgur.com/FvFEeVQ.png) page: 132 | * Enable BotW MouseWheel Weapon Change Feature 133 | * Choose yes if you would like to be able to use the mouse wheel to change weapons in BotW 134 | * Should be off for all other games obviously 135 | * Enable ZL Lock Key Feature 136 | * Also for BotW, will allow you use a separate key to toggle ZL On, until pressed again. 137 | * Pressing the regularily assigned ZL key will always toggle from current state 138 | * Cursor 139 | * Choose if you would like cursor hidden 140 | * Sometimes useful for troubleshooting to make it visible again. 141 | 142 | 143 | *** 144 | # Script Downloads 145 | *** 146 | **[GitHub Releases](https://github.com/CemuUser8/mouse2joystick_custom_CEMU/releases) will be the best place to find the latest version of the script** 147 | 148 | 149 | **[Alternate Direct Download](https://bitbucket.org/CemuUser8/files/downloads/mouse2joystick_Custom_CEMU.zip)** 150 | 151 | *** 152 | # Extra Reminders 153 | *** 154 | 155 | * **Changing your keys within CEMU isn't recommended as it is tedious and finicky. The script allows you to easily change which key is assigned to which vJoy button. Then the button assignment in CEMU doesn't matter at all as long as each key has something.** 156 | 157 | 158 | 159 | * **Note that the in-game camera settings affect the camera speed the most, so try changing there if camera speed is your only issue.** 160 | 161 | * **If you run CEMU as an admin, then you need to run the script as an admin as well.** 162 | 163 | *** 164 | ***Please feel free to comment here for help, or send me a PM.*** 165 | 166 |   167 | 168 |   169 | 170 | ## Instructions for rpcs3 (or any non CEMU XInput use): 171 | 172 | * Install the [latest version of vJoy](https://sourceforge.net/projects/vjoystick/files/latest/download) 173 | * Run the downloaded program (or AutoHotkey script if you download the source) 174 | * Open the program settings by on the [controller icon in your system tray](http://i.imgur.com/fPBWOsU.png) (Bottom Right) and choose 'settings' 175 | * [Choose to use vXBox.](https://i.imgur.com/s2TnMep.png) AND [Choose "No" under the "Activate Executable" Section](https://i.imgur.com/vlB7qXm.png) - Press "Ok" to reload the script with the option enabled. 176 | * If the first time, a prompt will come up asking to install ScpVBus, Press Yes, then on the security prompt to run DevCon Press Yes again. 177 | * The script will reload and connect a virtual XBox controller, drivers may be installed automatically on Windows10, or you will need them pre-installed on Windows7. 178 | * To remap your keys Open the settings and goto the[ "Mouse2Joystick -> Keys"](http://i.imgur.com/eMMnEGj.png) section. 179 | * Press the [KeyList Helper Button](http://i.imgur.com/VF2vwfE.png) 180 | * You can map your [keys on this screen](https://i.imgur.com/IhTR03m.png), read the ReadMe for how to add a second key to the same button 181 | * Set your movement keys on the ["KeyboardMovement -> Keys"](http://i.imgur.com/okKlFwE.png) settings screen. (Clear the Toggle ZL Lock and Toggle Gyro keys by clicking them and pressing `Backspace` - they aren't needed in rpcs3) 182 | * In rpcs3, set your controller to use XInput 183 | * When you want to use the controller Press "F1" (default but customizable) to toggle using the virtual Controller. 184 | 185 | That should be it, your mouse should now control the Right Analog stick, and your movement keys the Left. 186 | 187 | I will be honest I have not done this myself, I have just helped someone else do it and they said it works perfectly just needed a quick guide on how to set it up for this. 188 | *** 189 | -------------------------------------------------------------------------------- /SavedKeyLists.ini: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CemuUser8/mouse2joystick_custom_CEMU/c7cfdb830929ac46c24e89b112e3fcfbb18ae1d3/SavedKeyLists.ini -------------------------------------------------------------------------------- /ScpVBus/ScpVBus.inf: -------------------------------------------------------------------------------- 1 | ; 2 | ; ScpVBus.inf 3 | ; 4 | 5 | [Version] 6 | Signature="$WINDOWS NT$" 7 | Class=System 8 | ClassGuid={4D36E97D-E325-11CE-BFC1-08002BE10318} 9 | Provider=%ManufacturerName% 10 | CatalogFile=ScpVBus.cat 11 | DriverVer=09/27/2016,9.11.9.337 12 | 13 | [DestinationDirs] 14 | DefaultDestDir = 12 15 | 16 | ; ================= Class section ===================== 17 | 18 | [SourceDisksNames] 19 | 1 = %DiskName%,,,"" 20 | 21 | [SourceDisksFiles] 22 | ScpVBus.sys = 1,, 23 | 24 | ;***************************************** 25 | ; Install Section 26 | ;***************************************** 27 | 28 | [Manufacturer] 29 | %ManufacturerName%=SCProductions,NTamd64 30 | 31 | [SCProductions.NTamd64] 32 | %ScpVBus.DeviceDesc%=ScpVBus_Device, Root\ScpVBus 33 | 34 | [ScpVBus_Device.NT] 35 | CopyFiles=Drivers_Dir 36 | 37 | [Drivers_Dir] 38 | ScpVBus.sys 39 | 40 | ;-------------- Service installation 41 | [ScpVBus_Device.NT.Services] 42 | AddService = ScpVBus,%SPSVCINST_ASSOCSERVICE%, ScpVBus_Service_Inst 43 | 44 | ; -------------- ScpVBus driver install sections 45 | [ScpVBus_Service_Inst] 46 | DisplayName = %ScpVBus.SVCDESC% 47 | ServiceType = 1 ; SERVICE_KERNEL_DRIVER 48 | StartType = 3 ; SERVICE_DEMAND_START 49 | ErrorControl = 1 ; SERVICE_ERROR_NORMAL 50 | ServiceBinary = %12%\ScpVBus.sys 51 | 52 | ; 53 | ;--- ScpVBus_Device Coinstaller installation ------ 54 | ; 55 | 56 | [DestinationDirs] 57 | ScpVBus_Device_CoInstaller_CopyFiles = 11 58 | 59 | [ScpVBus_Device.NT.CoInstallers] 60 | AddReg=ScpVBus_Device_CoInstaller_AddReg 61 | CopyFiles=ScpVBus_Device_CoInstaller_CopyFiles 62 | 63 | [ScpVBus_Device_CoInstaller_AddReg] 64 | HKR,,CoInstallers32,0x00010000, "WdfCoInstaller01009.dll,WdfCoInstaller" 65 | 66 | [ScpVBus_Device_CoInstaller_CopyFiles] 67 | WdfCoInstaller01009.dll 68 | 69 | [SourceDisksFiles] 70 | WdfCoInstaller01009.dll=1 ; make sure the number matches with SourceDisksNames 71 | 72 | [ScpVBus_Device.NT.Wdf] 73 | KmdfService = ScpVBus, ScpVBus_wdfsect 74 | [ScpVBus_wdfsect] 75 | KmdfLibraryVersion = 1.9 76 | 77 | [Strings] 78 | SPSVCINST_ASSOCSERVICE= 0x00000002 79 | ManufacturerName="Nefarius Software Solutions" 80 | DiskName = "Scp Virtual Bus Installation Media" 81 | ScpVBus.DeviceDesc = "Scp Virtual Bus Driver" 82 | ScpVBus.SVCDESC = "Scp Virtual Bus Driver" 83 | -------------------------------------------------------------------------------- /ScpVBus/ScpVBus.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CemuUser8/mouse2joystick_custom_CEMU/c7cfdb830929ac46c24e89b112e3fcfbb18ae1d3/ScpVBus/ScpVBus.sys -------------------------------------------------------------------------------- /ScpVBus/WdfCoinstaller01009.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CemuUser8/mouse2joystick_custom_CEMU/c7cfdb830929ac46c24e89b112e3fcfbb18ae1d3/ScpVBus/WdfCoinstaller01009.dll -------------------------------------------------------------------------------- /ScpVBus/devcon.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CemuUser8/mouse2joystick_custom_CEMU/c7cfdb830929ac46c24e89b112e3fcfbb18ae1d3/ScpVBus/devcon.exe -------------------------------------------------------------------------------- /ScpVBus/scpvbus.cat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CemuUser8/mouse2joystick_custom_CEMU/c7cfdb830929ac46c24e89b112e3fcfbb18ae1d3/ScpVBus/scpvbus.cat -------------------------------------------------------------------------------- /ScpVBus/v1.7.1.2/x64/ScpVBus.inf: -------------------------------------------------------------------------------- 1 | ; 2 | ; ScpVBus.inf 3 | ; 4 | 5 | [Version] 6 | Signature="$WINDOWS NT$" 7 | Class=System 8 | ClassGuid={4D36E97D-E325-11CE-BFC1-08002BE10318} 9 | Provider=%ManufacturerName% 10 | CatalogFile=ScpVBus.cat 11 | DriverVer=09/27/2016,9.11.9.337 12 | 13 | [DestinationDirs] 14 | DefaultDestDir = 12 15 | 16 | ; ================= Class section ===================== 17 | 18 | [SourceDisksNames] 19 | 1 = %DiskName%,,,"" 20 | 21 | [SourceDisksFiles] 22 | ScpVBus.sys = 1,, 23 | 24 | ;***************************************** 25 | ; Install Section 26 | ;***************************************** 27 | 28 | [Manufacturer] 29 | %ManufacturerName%=SCProductions,NTamd64 30 | 31 | [SCProductions.NTamd64] 32 | %ScpVBus.DeviceDesc%=ScpVBus_Device, Root\ScpVBus 33 | 34 | [ScpVBus_Device.NT] 35 | CopyFiles=Drivers_Dir 36 | 37 | [Drivers_Dir] 38 | ScpVBus.sys 39 | 40 | ;-------------- Service installation 41 | [ScpVBus_Device.NT.Services] 42 | AddService = ScpVBus,%SPSVCINST_ASSOCSERVICE%, ScpVBus_Service_Inst 43 | 44 | ; -------------- ScpVBus driver install sections 45 | [ScpVBus_Service_Inst] 46 | DisplayName = %ScpVBus.SVCDESC% 47 | ServiceType = 1 ; SERVICE_KERNEL_DRIVER 48 | StartType = 3 ; SERVICE_DEMAND_START 49 | ErrorControl = 1 ; SERVICE_ERROR_NORMAL 50 | ServiceBinary = %12%\ScpVBus.sys 51 | 52 | ; 53 | ;--- ScpVBus_Device Coinstaller installation ------ 54 | ; 55 | 56 | [DestinationDirs] 57 | ScpVBus_Device_CoInstaller_CopyFiles = 11 58 | 59 | [ScpVBus_Device.NT.CoInstallers] 60 | AddReg=ScpVBus_Device_CoInstaller_AddReg 61 | CopyFiles=ScpVBus_Device_CoInstaller_CopyFiles 62 | 63 | [ScpVBus_Device_CoInstaller_AddReg] 64 | HKR,,CoInstallers32,0x00010000, "WdfCoInstaller01009.dll,WdfCoInstaller" 65 | 66 | [ScpVBus_Device_CoInstaller_CopyFiles] 67 | WdfCoInstaller01009.dll 68 | 69 | [SourceDisksFiles] 70 | WdfCoInstaller01009.dll=1 ; make sure the number matches with SourceDisksNames 71 | 72 | [ScpVBus_Device.NT.Wdf] 73 | KmdfService = ScpVBus, ScpVBus_wdfsect 74 | [ScpVBus_wdfsect] 75 | KmdfLibraryVersion = 1.9 76 | 77 | [Strings] 78 | SPSVCINST_ASSOCSERVICE= 0x00000002 79 | ManufacturerName="Nefarius Software Solutions" 80 | DiskName = "Scp Virtual Bus Installation Media" 81 | ScpVBus.DeviceDesc = "Scp Virtual Bus Driver" 82 | ScpVBus.SVCDESC = "Scp Virtual Bus Driver" 83 | -------------------------------------------------------------------------------- /ScpVBus/v1.7.1.2/x64/ScpVBus.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CemuUser8/mouse2joystick_custom_CEMU/c7cfdb830929ac46c24e89b112e3fcfbb18ae1d3/ScpVBus/v1.7.1.2/x64/ScpVBus.sys -------------------------------------------------------------------------------- /ScpVBus/v1.7.1.2/x64/WdfCoinstaller01009.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CemuUser8/mouse2joystick_custom_CEMU/c7cfdb830929ac46c24e89b112e3fcfbb18ae1d3/ScpVBus/v1.7.1.2/x64/WdfCoinstaller01009.dll -------------------------------------------------------------------------------- /ScpVBus/v1.7.1.2/x64/devcon.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CemuUser8/mouse2joystick_custom_CEMU/c7cfdb830929ac46c24e89b112e3fcfbb18ae1d3/ScpVBus/v1.7.1.2/x64/devcon.exe -------------------------------------------------------------------------------- /ScpVBus/v1.7.1.2/x64/scpvbus.cat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CemuUser8/mouse2joystick_custom_CEMU/c7cfdb830929ac46c24e89b112e3fcfbb18ae1d3/ScpVBus/v1.7.1.2/x64/scpvbus.cat -------------------------------------------------------------------------------- /ScpVBus/v1.7.1.2/x86/ScpVBus.inf: -------------------------------------------------------------------------------- 1 | ; 2 | ; ScpVBus.inf 3 | ; 4 | 5 | [Version] 6 | Signature="$WINDOWS NT$" 7 | Class=System 8 | ClassGuid={4D36E97D-E325-11CE-BFC1-08002BE10318} 9 | Provider=%ManufacturerName% 10 | CatalogFile=ScpVBus.cat 11 | DriverVer=09/27/2016,9.11.25.89 12 | 13 | [DestinationDirs] 14 | DefaultDestDir = 12 15 | 16 | ; ================= Class section ===================== 17 | 18 | [SourceDisksNames] 19 | 1 = %DiskName%,,,"" 20 | 21 | [SourceDisksFiles] 22 | ScpVBus.sys = 1,, 23 | 24 | ;***************************************** 25 | ; Install Section 26 | ;***************************************** 27 | 28 | [Manufacturer] 29 | %ManufacturerName%=SCProductions,NTx86 30 | 31 | [SCProductions.NTx86] 32 | %ScpVBus.DeviceDesc%=ScpVBus_Device, Root\ScpVBus 33 | 34 | [ScpVBus_Device.NT] 35 | CopyFiles=Drivers_Dir 36 | 37 | [Drivers_Dir] 38 | ScpVBus.sys 39 | 40 | ;-------------- Service installation 41 | [ScpVBus_Device.NT.Services] 42 | AddService = ScpVBus,%SPSVCINST_ASSOCSERVICE%, ScpVBus_Service_Inst 43 | 44 | ; -------------- ScpVBus driver install sections 45 | [ScpVBus_Service_Inst] 46 | DisplayName = %ScpVBus.SVCDESC% 47 | ServiceType = 1 ; SERVICE_KERNEL_DRIVER 48 | StartType = 3 ; SERVICE_DEMAND_START 49 | ErrorControl = 1 ; SERVICE_ERROR_NORMAL 50 | ServiceBinary = %12%\ScpVBus.sys 51 | 52 | ; 53 | ;--- ScpVBus_Device Coinstaller installation ------ 54 | ; 55 | 56 | [DestinationDirs] 57 | ScpVBus_Device_CoInstaller_CopyFiles = 11 58 | 59 | [ScpVBus_Device.NT.CoInstallers] 60 | AddReg=ScpVBus_Device_CoInstaller_AddReg 61 | CopyFiles=ScpVBus_Device_CoInstaller_CopyFiles 62 | 63 | [ScpVBus_Device_CoInstaller_AddReg] 64 | HKR,,CoInstallers32,0x00010000, "WdfCoInstaller01009.dll,WdfCoInstaller" 65 | 66 | [ScpVBus_Device_CoInstaller_CopyFiles] 67 | WdfCoInstaller01009.dll 68 | 69 | [SourceDisksFiles] 70 | WdfCoInstaller01009.dll=1 ; make sure the number matches with SourceDisksNames 71 | 72 | [ScpVBus_Device.NT.Wdf] 73 | KmdfService = ScpVBus, ScpVBus_wdfsect 74 | [ScpVBus_wdfsect] 75 | KmdfLibraryVersion = 1.9 76 | 77 | [Strings] 78 | SPSVCINST_ASSOCSERVICE= 0x00000002 79 | ManufacturerName="Nefarius Software Solutions" 80 | DiskName = "Scp Virtual Bus Installation Media" 81 | ScpVBus.DeviceDesc = "Scp Virtual Bus Driver" 82 | ScpVBus.SVCDESC = "Scp Virtual Bus Driver" 83 | -------------------------------------------------------------------------------- /ScpVBus/v1.7.1.2/x86/ScpVBus.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CemuUser8/mouse2joystick_custom_CEMU/c7cfdb830929ac46c24e89b112e3fcfbb18ae1d3/ScpVBus/v1.7.1.2/x86/ScpVBus.sys -------------------------------------------------------------------------------- /ScpVBus/v1.7.1.2/x86/WdfCoinstaller01009.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CemuUser8/mouse2joystick_custom_CEMU/c7cfdb830929ac46c24e89b112e3fcfbb18ae1d3/ScpVBus/v1.7.1.2/x86/WdfCoinstaller01009.dll -------------------------------------------------------------------------------- /ScpVBus/v1.7.1.2/x86/devcon.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CemuUser8/mouse2joystick_custom_CEMU/c7cfdb830929ac46c24e89b112e3fcfbb18ae1d3/ScpVBus/v1.7.1.2/x86/devcon.exe -------------------------------------------------------------------------------- /ScpVBus/v1.7.1.2/x86/scpvbus.cat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CemuUser8/mouse2joystick_custom_CEMU/c7cfdb830929ac46c24e89b112e3fcfbb18ae1d3/ScpVBus/v1.7.1.2/x86/scpvbus.cat -------------------------------------------------------------------------------- /controllerProfiles/vJoyDevice_GamePad.txt: -------------------------------------------------------------------------------- 1 | [General] 2 | emulate = Wii U GamePad 3 | api = DirectInput 4 | controller = 0 5 | 6 | [Controller] 7 | rumble = 0 8 | leftRange = 1 9 | rightRange = 1 10 | leftDeadzone = 0 11 | rightDeadzone = 0 12 | buttonThreshold = 0.5 13 | 1 = button_1 14 | 2 = button_2 15 | 3 = button_4 16 | 4 = button_8 17 | 5 = button_10 18 | 6 = button_20 19 | 7 = button_40 20 | 8 = button_80 21 | 9 = button_100 22 | 10 = button_200 23 | 11 = button_1000 24 | 12 = button_2000 25 | 13 = button_4000 26 | 14 = button_8000 27 | 15 = button_400 28 | 16 = button_800 29 | 17 = button_400000000 30 | 18 = button_10000000000 31 | 19 = button_8000000000 32 | 20 = button_200000000 33 | 21 = button_80000000 34 | 22 = button_2000000000 35 | 23 = button_1000000000 36 | 24 = button_40000000 37 | 25 = button_10000 38 | 26 = button_20000 39 | -------------------------------------------------------------------------------- /controllerProfiles/vJoyDevice_Pro.txt: -------------------------------------------------------------------------------- 1 | [General] 2 | emulate = Wii U Pro Controller 3 | api = DirectInput 4 | controller = 0 5 | 6 | [Controller] 7 | rumble = 0 8 | leftRange = 1 9 | rightRange = 1 10 | leftDeadzone = 0 11 | rightDeadzone = 0 12 | buttonThreshold = 0.5 13 | 1 = button_1 14 | 2 = button_2 15 | 3 = button_4 16 | 4 = button_8 17 | 5 = button_10 18 | 6 = button_20 19 | 7 = button_40 20 | 8 = button_80 21 | 9 = button_100 22 | 10 = button_200 23 | 11 = button_1000 24 | 12 = button_1000 25 | 13 = button_2000 26 | 14 = button_4000 27 | 15 = button_8000 28 | 16 = button_400 29 | 17 = button_800 30 | 18 = button_400000000 31 | 19 = button_10000000000 32 | 20 = button_8000000000 33 | 21 = button_200000000 34 | 22 = button_80000000 35 | 23 = button_2000000000 36 | 24 = button_1000000000 37 | 25 = button_40000000 38 | 26 = button_10000 39 | -------------------------------------------------------------------------------- /controllerProfiles/vXBox_GamePad.txt: -------------------------------------------------------------------------------- 1 | [General] 2 | emulate = Wii U GamePad 3 | api = XInput 4 | controller = 0 5 | 6 | [Controller] 7 | rumble = 0 8 | leftRange = 1 9 | rightRange = 1 10 | leftDeadzone = 0 11 | rightDeadzone = 0 12 | buttonThreshold = 0.5 13 | 1 = button_1 14 | 2 = button_2 15 | 3 = button_4 16 | 4 = button_8 17 | 5 = button_10 18 | 6 = button_20 19 | 7 = button_100000000 20 | 8 = button_800000000 21 | 9 = button_40 22 | 10 = button_80 23 | 11 = button_4000000 24 | 12 = button_8000000 25 | 13 = button_10000000 26 | 14 = button_20000000 27 | 15 = button_100 28 | 16 = button_200 29 | 17 = button_80000000 30 | 18 = button_2000000000 31 | 19 = button_1000000000 32 | 20 = button_40000000 33 | 21 = button_400000000 34 | 22 = button_10000000000 35 | 23 = button_8000000000 36 | 24 = button_200000000 37 | 25 = key_66 38 | 26 = key_220 39 | -------------------------------------------------------------------------------- /controllerProfiles/vXBox_Pro.txt: -------------------------------------------------------------------------------- 1 | [General] 2 | emulate = Wii U Pro Controller 3 | api = XInput 4 | controller = 0 5 | 6 | [Controller] 7 | rumble = 0 8 | leftRange = 1 9 | rightRange = 1 10 | leftDeadzone = 0 11 | rightDeadzone = 0 12 | buttonThreshold = 0.5 13 | 1 = button_1 14 | 2 = button_2 15 | 3 = button_4 16 | 4 = button_8 17 | 5 = button_10 18 | 6 = button_20 19 | 7 = button_100000000 20 | 8 = button_800000000 21 | 9 = button_40 22 | 10 = button_80 23 | 11 = button_4000000 24 | 12 = button_4000000 25 | 13 = button_8000000 26 | 14 = button_10000000 27 | 15 = button_20000000 28 | 16 = button_100 29 | 17 = button_200 30 | 18 = button_80000000 31 | 19 = button_2000000000 32 | 20 = button_1000000000 33 | 21 = button_40000000 34 | 22 = button_400000000 35 | 23 = button_10000000000 36 | 24 = button_8000000000 37 | 25 = button_200000000 38 | 26 = key_220 39 | -------------------------------------------------------------------------------- /mouse2joystick_Custom_CEMU.ahk: -------------------------------------------------------------------------------- 1 | ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; 2 | ; Modified for CEMU by: CemuUser8 (https://www.reddit.com/r/cemu/comments/5zn0xa/autohotkey_script_to_use_mouse_for_camera/) 3 | ; Last Modified Date: 2020-05-19 4 | ; 5 | ; Original Author: Helgef 6 | ; Date: 2016-08-17 7 | ; 8 | ; Description: 9 | ; Mouse to virtual joystick. For virtual joystick you need to install vJoy. See url below. 10 | ; 11 | ; Notes: 12 | ; -#q exit at any time. 13 | ; 14 | ; Urls: 15 | ; https://autohotkey.com/boards/viewtopic.php?f=19&t=21489 - First released here / help / instruction / bug reports. 16 | ; http://vjoystick.sourceforge.net/site/ - vJoy device drivers, needed for mouse to virtual joystick. 17 | ; https://autohotkey.com/boards/viewtopic.php?f=19&t=20703&sid=2619d57dcbb0796e16ea172f238f08a0 - Original request by crisangelfan. 18 | ; https://autohotkey.com/boards/viewtopic.php?t=5705 - CvJoyInterface.ahk 19 | ; 20 | ; Acknowledgements: 21 | ; crisangelfan and evilC on autohotkey.com forum provided useful input. 22 | ; Credit to author(s) of vJoy @ http://vjoystick.sourceforge.net/site/ 23 | ; evilC did the CvJoyInterface.ahk 24 | ; 25 | version := "v0.4.1.4" 26 | #NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases. 27 | SendMode Input ; Recommended for new scripts due to its superior speed and reliability. 28 | SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory. 29 | ;#Include CvJI/CvJoyInterface.ahk ; Credit to evilC. 30 | #Include CvJI/CvGenInterface.ahk ; A Modifed Interface that I (CemuUser8) added the vXBox device and functions to. 31 | #Include CvJI/MouseDelta.ahk ; Alternate way to see mouse movement 32 | #Include CvJI/SelfDeletingTimer.ahk 33 | ; Settings 34 | #MaxHotkeysPerInterval 210 35 | #HotkeyInterval 1000 36 | #InstallMouseHook 37 | #SingleInstance Force 38 | CoordMode,Mouse,Screen 39 | SetMouseDelay,-1 40 | SetBatchLines,-1 41 | 42 | ; On exit 43 | OnExit("exitFunc") 44 | 45 | IF (A_PtrSize < 8) { 46 | MsgBox,16,Now Requires 64bit, Starting with Version 0.4.0.0 this program requires 64bit. If you are getting this error you must be running the script directly and have 32bit AutoHotkey installed.`n`nPlease either use the released executable, or change your AutoHotkey installation to the 64bit Unicode version 47 | ExitApp 48 | } 49 | 50 | ;OrigMouseSpeed := "" 51 | ;DllCall("SystemParametersInfo", UInt, 0x70, UInt, 0, UIntP, OrigMouseSpeed, UInt, 0) ; Get Original Mouse Speed. 52 | 53 | toggle:=1 ; On/off parameter for the hotkey. Toggle 0 means controller is on. The placement of this variable is disturbing. 54 | 55 | ; If no settings file, create, When changing this, remember to make corresponding changes after the setSettingsToDefault label (error handling) ; Currently at bottom of script 56 | IfNotExist, settings.ini 57 | { 58 | defaultSettings= 59 | ( 60 | [General] 61 | usevXBox=0 62 | vJoyDevice=1 63 | vXBoxDevice=1 64 | gameExe=Cemu.exe 65 | autoActivateGame=1 66 | [General>Setup] 67 | r=30 68 | k=0.02 69 | freq=75 70 | nnp=.80 71 | [General>Hotkeys] 72 | controllerSwitchKey=F1 73 | exitKey=#q 74 | [Mouse2Joystick>Axes] 75 | invertedX=0 76 | invertedY=0 77 | [Mouse2Joystick>Keys] 78 | joystickButtonKeyList=e,LShift,Space,LButton,1,3,LCtrl,RButton,Enter,m,q,c,i,k,j,l,b 79 | [Keyboard Movement>Keys] 80 | upKey=w 81 | leftKey=a 82 | downKey=s 83 | rightKey=d 84 | walkToggleKey=Numpad0 85 | increaseWalkKey=NumpadAdd 86 | decreaseWalkKey=NumPadSub 87 | walkSpeed=0.5 88 | gyroToggleKey= 89 | [Extra Settings] 90 | BotWmouseWheel=0 91 | lockZL=0 92 | lockZLToggleKey=Numpad1 93 | hideCursor=1 94 | BotWmotionAim=0 95 | useAltMouseMethod=0 96 | alt_xSen=400 97 | alt_ySen=280 98 | ) 99 | FileAppend,%defaultSettings%,settings.ini 100 | IF (ErrorLevel) { 101 | Msgbox,% 6+16,Error writing to file., There was a problem creating settings.ini 102 | , make sure you have permission to write to file at %A_ScriptDir%. If the problem persists`, try to run as administrator or change the script directory. Press retry to try again`, continue to set all settings to default or cancel to exit application. 103 | IfMsgBox Retry 104 | reload 105 | Else IfMsgBox Continue 106 | Goto, setSettingsToDefault ; Currently at bottom of script 107 | Else 108 | ExitApp 109 | } 110 | firstRun := True ; Moved out of ini File. 111 | } 112 | 113 | ; Read settings. 114 | IniRead,allSections,settings.ini 115 | IF (!allSections || allSections="ERROR") { ; Do not think this is ever set to ERROR. 116 | MsgBox, % 2+16, Error reading file, There was an error reading the settings.ini file`, press retry to try again`, continue to set all settings to default or cancel to exit application. 117 | IfMsgBox retry 118 | reload 119 | Else IfMsgBox Ignore 120 | Goto, setSettingsToDefault ; Currently at bottom of script 121 | Else 122 | ExitApp 123 | } 124 | Loop,Parse,allSections,`n 125 | { 126 | IniRead,pairs,settings.ini,%A_LoopField% 127 | Loop,Parse,pairs,`n 128 | { 129 | StringSplit,keyValue,A_LoopField,= 130 | %keyValue1%:=keyValue2 131 | } 132 | } 133 | readSettingsSkippedDueToError: ; This comes from setSettingsToDefault If there was an error. 134 | 135 | pi:=atan(1)*4 ; Approx pi. 136 | 137 | ; Constants and such. Some values are commented out because they have been stored in the settings.ini file instead, but are kept because they have comments. 138 | moveStickHalf := False 139 | KeyList := [] 140 | KeyListByNum := [] 141 | 142 | md := new MouseDelta("MouseEvent") 143 | 144 | ih := InputHook() 145 | ih.KeyOpt("{All}", "ES") 146 | 147 | dr:=0 ; Bounce back when hit outer circle edge, in pixels. (This might not work any more, it is off) Can be seen as a force feedback parameter, can be extended to depend on the over extension beyond the outer ring. 148 | 149 | ; Hotkey(s). 150 | IF (controllerSwitchKey) 151 | Hotkey,%controllerSwitchKey%,controllerSwitch, on 152 | IF (exitKey) 153 | Hotkey,%exitKey%,exitFunc, on 154 | 155 | mouse2joystick := True 156 | IF (mouse2joystick) { 157 | Gosub, initCvJoyInterface 158 | Gosub, mouse2joystickHotkeys 159 | } 160 | 161 | ; Icon 162 | Menu,Tray,Tip, mouse2joystick Customized for CEMU 163 | Menu,Tray,NoStandard 164 | 165 | 166 | IF (!A_IsCompiled) { ; If it is compiled it should just use the EXE Icon 167 | IF (A_OSVersion < "10.0.15063") ; It appears that the Icon has changed number on the newest versions of Windows. 168 | useIcon := 26 169 | Else IF (A_OSVersion >= "10.0.16299") 170 | useIcon := 28 171 | Else 172 | useIcon := 27 173 | Try 174 | Menu,Tray,Icon,ddores.dll, %useIcon% 175 | } 176 | ;Menu,Settings,openSettings 177 | Menu,Tray,Add,Settings,openSettings 178 | Menu,Tray,Add, 179 | IF (vGenInterface.IsVBusExist()) 180 | Menu,Tray,Add,Uninstall ScpVBus, uninstallBus 181 | Else 182 | Menu,Tray,Add,Install ScpVBus, installBus 183 | Menu,Tray,Add, 184 | Menu,Tray,Add,Reset to CEMU, selectGameMenu 185 | Menu,Tray,Add 186 | Menu,Tray,Add,About,aboutMenu 187 | Menu,Tray,Add,Help,helpMenu 188 | Menu,Tray,Add 189 | Menu,Tray,Add,Reload,reloadMenu 190 | Menu,Tray,Add,Exit,exitFunc 191 | Menu,Tray,Default, Settings 192 | 193 | IF freq is not Integer 194 | freq := 75 195 | 196 | pmX:=invertedX ? -1:1 ; Sign for inverting axis 197 | pmY:=invertedY ? -1:1 198 | snapToFullTilt:=0.005 ; This needs to be improved. 199 | ;nnp:=4 ; Non-linearity parameter for joystick output, 1 = linear, >1 higher sensitivity closer to full tilt, <1 higher sensitivity closer to deadzone. Recommended range, [0.1,6]. 200 | ; New parameters 201 | 202 | ; Mouse blocker 203 | ; Transparent window that covers game screen to prevent game from capture the mouse. 204 | Gui, Controller: New 205 | Gui, Controller: +ToolWindow -Caption +AlwaysOnTop +HWNDstick 206 | Gui, Controller: Color, FFFFFF 207 | 208 | ; Spam user with useless info, first time script runs. 209 | IF (firstRun) 210 | MsgBox,64,Welcome,Settings are accessed via Tray icon -> Settings. 211 | 212 | 213 | Return 214 | ; End autoexec. 215 | 216 | selectGameMenu: 217 | TrayTip, % "Game reset to cemu.exe", % "If you want something different manually edit the settings, or 'settings.ini' file directly",,0x10 218 | gameExe := "cemu.exe" 219 | IniWrite, %gameExe%, settings.ini, General, gameExe 220 | Return 221 | 222 | reloadMenu: 223 | Reload 224 | Return 225 | 226 | aboutMenu: 227 | Msgbox,32,About, Modified for CEMU by:`nCemuUser8`n`nVersion:`n%version% 228 | Return 229 | 230 | helpMenu: 231 | Msgbox,% 4 + 32 , Open help in browser?, Visit Reddit post on /r/cemu for help?`n`nIt is helpful to know the version (%version%)`nand If possible a pastebin of your 'settings.ini' file will help me troubleshoot.`n`nWill Open link in default browser. 232 | IfMsgBox Yes 233 | Run, https://www.reddit.com/r/cemu/comments/5zn0xa/autohotkey_script_to_use_mouse_for_camera/ 234 | Return 235 | 236 | initCvJoyInterface: 237 | Global vXBox := usevXBox 238 | ; Copied from joytest.ahk, from CvJoyInterface by evilC 239 | ; Create an object from vJoy Interface Class. 240 | vGenInterface := new CvGenInterface() 241 | ; Was vJoy installed and the DLL Loaded? 242 | IF (!vGenInterface.vJoyEnabled()){ 243 | ; Show log of what happened 244 | Msgbox,% 4+16,vJoy Error,% "vJoy needs to be installed. Press no to exit application.`nLog:`n" . vGenInterface.LoadLibraryLog ; Error handling changed. 245 | IfMsgBox Yes 246 | { 247 | ;IniWrite, 0,settings.ini,General,mouse2joystick 248 | reload 249 | } 250 | ExitApp 251 | } 252 | IF (vXBox AND !vGenInterface.IsVBusExist()) { 253 | Msgbox,% 4 + 32 , Virtual xBox Bus not found, Press Yes If you would like to install ScpVBus, otherwise script will revert back to vJoy instead of vXBox.`n`nScript will reload after installing. 254 | IfMsgBox Yes 255 | InstallUninstallScpVBus(True) 256 | Else { 257 | vXBox := False 258 | IniWrite,0, settings.ini, General, usevXBox ; Turn off the setting for the next run as well. 259 | } 260 | } 261 | ValidDevices := "" 262 | Loop 15 { 263 | IF (vGenInterface.Devices[A_Index].IsAvailable()) 264 | ValidDevices .= A_Index . "|" 265 | } 266 | IF (vXBox) { 267 | IF (vXboxDevice != vstick.DeviceID OR !vstick.GetLedNumber()) { 268 | IF (isObject(vstick)) { 269 | vstick.Unplug() 270 | vstick.Relinquish() 271 | } 272 | ;vGenInterface.UnPlugAll() ; Not sure how this interacts when a real controller is also plugged in. But I seem to notice that there is an issue if not ran. 273 | Global vstick := vGenInterface.xDevices[vXBoxDevice] 274 | vstick.Acquire() 275 | TrayTip,, % "Controller #" vstick.GetLedNumber() 276 | } 277 | 278 | } 279 | Else { 280 | IF (isObject(vstick)) { 281 | vstick.Unplug() 282 | vstick.Relinquish() 283 | } 284 | Global vstick := vGenInterface.Devices[vJoyDevice] 285 | } 286 | Return 287 | 288 | ; Hotkey labels 289 | ; This switches on/off the controller. 290 | controllerSwitch: 291 | IF (toggle) { ; Starting controller 292 | IF (autoActivateGame) { 293 | WinActivate,ahk_exe %gameExe% 294 | WinWaitActive, ahk_exe %gameExe%,,2 295 | IF (ErrorLevel) { 296 | MsgBox,16,Error, %gameExe% not activated. 297 | Return 298 | } 299 | WinGetPos,gameX,gameY,gameW,gameH,ahk_exe %gameExe% ; Get game screen position and dimensions 300 | WinGet, gameID, ID, ahk_exe %gameExe% 301 | } 302 | Else { 303 | gameX:=0 304 | gameY:=0 305 | gameW:=A_ScreenWidth 306 | gameH:=A_ScreenHeight 307 | } 308 | 309 | ; Controller origin is center of game screen or screen If autoActivateGame:=0. 310 | OX:=gameX+gameW/2 311 | OY:=gameY+gameH/2 312 | 313 | IF (!OX OR !OY) { 314 | OX := 500 315 | OY := 500 316 | } 317 | 318 | ; Move mouse to controller origin 319 | MouseMove,OX,OY 320 | 321 | ; The mouse blocker 322 | Gui, Controller: Show,NA x%gameX% y%gameY% w%gameW% h%gameH%,Controller 323 | WinSet,Transparent,1,ahk_id %stick% 324 | 325 | IF (hideCursor) 326 | show_Mouse(False) 327 | ;DllCall("SystemParametersInfo", UInt, 0x71, UInt, 0, UInt, 10, UInt, 0) 328 | 329 | IF (useAltMouseMethod) { 330 | md.Start() 331 | LockMouseToWindow("ahk_id " . stick) 332 | } 333 | Else 334 | SetTimer,mouseTojoystick,%freq% 335 | 336 | } 337 | Else { ; Shutting down controller 338 | setStick(0,0) ; Stick in equilibrium. 339 | setStick(0,0, True) 340 | IF (useAltMouseMethod) { 341 | LockMouseToWindow(False) 342 | md.Stop() 343 | } 344 | Else 345 | SetTimer,mouseTojoystick,Off 346 | 347 | IF (hideCursor) 348 | show_Mouse() ; No need to show cursor if not hidden. 349 | ;DllCall("SystemParametersInfo", UInt, 0x71, UInt, 0, UInt, OrigMouseSpeed, UInt, 0) ; Restore the original speed. 350 | Gui, Controller:Hide 351 | 352 | } 353 | toggle:=!toggle 354 | Return 355 | 356 | ; Hotkeys mouse2joystick 357 | #IF (!toggle && mouse2joystick) 358 | #IF 359 | mouse2joystickHotkeys: 360 | Hotkey, IF, (!toggle && mouse2joystick) 361 | SetStick(0,0, True) 362 | IF (walkToggleKey) 363 | HotKey,%walkToggleKey%,toggleHalf, On 364 | IF (decreaseWalkKey) 365 | HotKey,%decreaseWalkKey%,decreaseWalk, On 366 | IF (increaseWalkKey) 367 | HotKey,%increaseWalkKey%,increaseWalk, On 368 | IF (lockZLToggleKey AND lockZL) 369 | HotKey,%lockZLToggleKey%,toggleAimLock, On 370 | IF (BotWmouseWheel) { 371 | Hotkey,WheelUp, overwriteWheelUp, on 372 | Hotkey,WheelDown, overwriteWheelDown, on 373 | } 374 | IF (gyroToggleKey) { 375 | HotKey,%gyroToggleKey%, GyroControl, on 376 | HotKey,%gyroToggleKey% Up, GyroControlOff, on 377 | } 378 | Hotkey,%upKey%, overwriteUp, on 379 | Hotkey,%upKey% Up, overwriteUpup, on 380 | Hotkey,%leftKey%, overwriteLeft, on 381 | Hotkey,%leftKey% Up, overwriteLeftup, on 382 | Hotkey,%downKey%, overwriteDown, on 383 | Hotkey,%downKey% Up, overwriteDownup, on 384 | Hotkey,%rightKey%, overwriteRight, on 385 | Hotkey,%rightKey% Up, overwriteRightup, on 386 | KeyList := [] 387 | Loop, Parse, joystickButtonKeyList, `, 388 | { 389 | useButton := A_Index 390 | Loop, Parse, A_LoopField, | 391 | { 392 | keyName:=A_LoopField 393 | IF (!keyName) 394 | Continue 395 | KeyList[keyName] := useButton 396 | Hotkey,%keyName%, pressJoyButton, on 397 | Hotkey,%keyName% Up, releaseJoyButton, on 398 | } 399 | } 400 | Hotkey, IF 401 | Return 402 | 403 | ; Labels for pressing and releasing joystick buttons. 404 | pressJoyButton: 405 | keyName:=A_ThisHotkey 406 | joyButtonNumber := KeyList[keyName] ; joyButtonNumber:=A_Index 407 | If InStr(keyName, "wheel") 408 | new SelfDeletingTimer(100, "ReleaseWheel", joyButtonNumber) 409 | IF (!vXBox){ 410 | IF (joyButtonNumber = 7 AND lockZL) { 411 | IF (ZLToggle) 412 | vstick.SetBtn(0,joyButtonNumber) 413 | Else 414 | vstick.SetBtn(1,joyButtonNumber) 415 | } 416 | Else IF (joyButtonNumber = 8 AND BotWmotionAim) { 417 | GoSub, GyroControl 418 | vstick.SetBtn(1,joyButtonNumber) 419 | } 420 | Else IF (joyButtonNumber) 421 | vstick.SetBtn(1,joyButtonNumber) 422 | } 423 | Else { 424 | Switch joyButtonNumber 425 | { 426 | Case 7: 427 | IF (lockZL AND ZLToggle) 428 | vstick.SetAxisByIndex(0,6) 429 | Else 430 | vstick.SetAxisByIndex(100,6) 431 | return 432 | Case 8: 433 | vstick.SetAxisByIndex(100,3) 434 | return 435 | Case 9: 436 | vstick.SetBtn(1,joyButtonNumber-1) 437 | return 438 | Case 10: 439 | vstick.SetBtn(1,joyButtonNumber-3) 440 | return 441 | Case 11,12: 442 | vstick.SetBtn(1,joyButtonNumber-2) 443 | return 444 | Case 13: 445 | vstick.SetPOV(0) 446 | return 447 | Case 14: 448 | vstick.SetPOV(180) 449 | return 450 | Case 15: 451 | vstick.SetPOV(270) 452 | return 453 | Case 16: 454 | vstick.SetPOV(90) 455 | return 456 | Default: 457 | vstick.SetBtn(1,joyButtonNumber) 458 | return 459 | } 460 | } 461 | Return 462 | 463 | ReleaseWheel(keyNum) { ; This is duplicated of the label below, it had to be added so I could release mouse wheel keys as they don't fire Up keystrokes. 464 | Global 465 | IF (!vXBox){ 466 | IF (keyNum = 7 AND lockZL) { 467 | IF (ZLToggle) 468 | vstick.SetBtn(1,keyNum) 469 | Else 470 | vstick.SetBtn(0,keyNum) 471 | } 472 | Else IF (keyNum = 8 AND BotWmotionAim) { 473 | vstick.SetBtn(0,keyNum) 474 | GoSub, GyroControlOff 475 | } 476 | Else IF (keyNum) 477 | vstick.SetBtn(0,keyNum) 478 | } 479 | Else { 480 | Switch keyNum 481 | { 482 | Case 7: 483 | IF (lockZL AND ZLToggle) 484 | vstick.SetAxisByIndex(100,6) 485 | Else 486 | vstick.SetAxisByIndex(0,6) 487 | Case 8: 488 | vstick.SetAxisByIndex(0,3) 489 | Case 9: 490 | vstick.SetBtn(0,keyNum-1) 491 | Case 10: 492 | vstick.SetBtn(0,keyNum-3) 493 | Case 11,12: 494 | vstick.SetBtn(0,keyNum-2) 495 | Case 13,14,15,16: 496 | vstick.SetPOV(-1) 497 | Default: 498 | vstick.SetBtn(0,keyNum) 499 | } 500 | } 501 | Return 502 | } 503 | 504 | releaseJoyButton: 505 | keyName:=RegExReplace(A_ThisHotkey," Up$") 506 | joyButtonNumber := KeyList[keyName] ; joyButtonNumber:=A_Index 507 | IF (!vXBox){ 508 | IF (joyButtonNumber = 7 AND lockZL) { 509 | IF (ZLToggle) 510 | vstick.SetBtn(1,joyButtonNumber) 511 | Else 512 | vstick.SetBtn(0,joyButtonNumber) 513 | } 514 | Else IF (joyButtonNumber = 8 AND BotWmotionAim) { 515 | vstick.SetBtn(0,joyButtonNumber) 516 | GoSub, GyroControlOff 517 | } 518 | Else IF (joyButtonNumber) 519 | vstick.SetBtn(0,joyButtonNumber) 520 | } 521 | Else { 522 | Switch joyButtonNumber 523 | { 524 | Case 7: 525 | IF (lockZL AND ZLToggle) 526 | vstick.SetAxisByIndex(100,6) 527 | Else 528 | vstick.SetAxisByIndex(0,6) 529 | Case 8: 530 | vstick.SetAxisByIndex(0,3) 531 | Case 9: 532 | vstick.SetBtn(0,joyButtonNumber-1) 533 | Case 10: 534 | vstick.SetBtn(0,joyButtonNumber-3) 535 | Case 11,12: 536 | vstick.SetBtn(0,joyButtonNumber-2) 537 | Case 13,14,15,16: 538 | vstick.SetPOV(-1) 539 | Default: 540 | vstick.SetBtn(0,joyButtonNumber) 541 | } 542 | } 543 | Return 544 | 545 | GyroControl: 546 | ;DllCall("SystemParametersInfo", UInt, 0x71, UInt, 0, UInt, 4, UInt, 0) ; Slow mouse movement down a little bit 547 | IF (BotWmouseWheel) { 548 | Hotkey, If, (!toggle && mouse2joystick) 549 | Hotkey,WheelUp, overwriteWheelUp, off 550 | Hotkey,WheelDown, overwriteWheelDown, off 551 | } 552 | SetStick(0,0) 553 | Gui, Controller:Hide 554 | IF (!useAltMouseMethod) { 555 | LockMouseToWindow("ahk_id " . gameID) 556 | SetTimer, mouseTojoystick, Off 557 | } 558 | Click, Right, Down 559 | Return 560 | 561 | GyroControlOff: 562 | Click, Right, Up 563 | IF (BotWmouseWheel) { 564 | Hotkey, If, (!toggle && mouse2joystick) 565 | Hotkey,WheelUp, overwriteWheelUp, on 566 | Hotkey,WheelDown, overwriteWheelDown, on 567 | } 568 | ;DllCall("SystemParametersInfo", UInt, 0x71, UInt, 0, UInt, 10, UInt, 0) ; Restore the original speed. 569 | Gui, Controller:Show, NA 570 | IF (!useAltMouseMethod){ 571 | LockMouseToWindow() 572 | SetTimer, mouseTojoystick, On 573 | } 574 | Return 575 | 576 | toggleAimLock: 577 | IF (vXbox) 578 | vstick.SetAxisByIndex((ZLToggle := !ZLToggle) ? 100 : 0,6) 579 | Else 580 | vstick.SetBtn((ZLToggle := !ZLToggle),7) 581 | Return 582 | 583 | toggleHalf: 584 | moveStickHalf := !moveStickHalf 585 | KeepStickHowItWas() 586 | Return 587 | 588 | decreaseWalk: 589 | walkSpeed -= 0.05 590 | IF (walkSpeed < 0) 591 | walkSpeed := 0 592 | KeepStickHowItWas() 593 | IniWrite, % walkSpeed:= Round(walkSpeed, 2), settings.ini, Keyboard Movement>Keys, walkSpeed 594 | GUI, Main:Default 595 | GUIControl,,opwalkSpeedTxt, % Round(walkSpeed * 100) "%" 596 | Return 597 | 598 | increaseWalk: 599 | walkSpeed += 0.05 600 | IF (walkSpeed > 1) 601 | walkSpeed := 1 602 | KeepStickHowItWas() 603 | IniWrite, % walkSpeed := Round(walkSpeed, 2), settings.ini, Keyboard Movement>Keys, walkSpeed 604 | GUI, Main:Default 605 | GUIControl,,opwalkSpeedTxt, % Round(walkSpeed * 100) "%" 606 | Return 607 | 608 | KeepStickHowItWas() { 609 | Global moveStickHalf, walkSpeed, upKey, leftKey, downKey, rightKey 610 | IF (GetKeyState(downKey, "P")) 611 | SetStick("N/A",(moveStickHalf ? -1 * walkSpeed : -1), True) 612 | IF (GetKeyState(rightKey, "P")) 613 | SetStick((moveStickHalf ? 1 * walkSpeed : 1),"N/A", True) 614 | IF (GetKeyState(leftKey, "P")) 615 | SetStick((moveStickHalf ? -1 * walkSpeed : -1),"N/A", True) 616 | IF (GetKeyState(upKey, "P")) 617 | SetStick("N/A",(moveStickHalf ? 1 * walkSpeed : 1), True) 618 | } 619 | 620 | overwriteUp: 621 | Critical, On 622 | IF (moveStickHalf) 623 | SetStick("N/A",1 * walkSpeed, True) 624 | Else 625 | SetStick("N/A",1, True) 626 | Critical, Off 627 | Return 628 | overwriteUpup: 629 | Critical, On 630 | IF (GetKeyState(downKey, "P")) { 631 | IF (moveStickHalf) 632 | SetStick("N/A",-1 * walkSpeed, True) 633 | Else 634 | SetStick("N/A",-1, True) 635 | } 636 | Else 637 | SetStick("N/A",0, True) 638 | Critical, Off 639 | Return 640 | 641 | overwriteLeft: 642 | Critical, On 643 | IF (moveStickHalf) 644 | SetStick(-1 * walkSpeed,"N/A", True) 645 | Else 646 | SetStick(-1,"N/A", True) 647 | Critical, Off 648 | Return 649 | overwriteLeftup: 650 | Critical, On 651 | IF (GetKeyState(rightKey, "P")) { 652 | IF (moveStickHalf) 653 | SetStick(1 * walkSpeed,"N/A", True) 654 | Else 655 | SetStick(1,"N/A", True) 656 | } 657 | Else 658 | SetStick(0,"N/A", True) 659 | Critical, Off 660 | Return 661 | 662 | overwriteRight: 663 | Critical, On 664 | IF (moveStickHalf) 665 | SetStick(1 * walkSpeed,"N/A", True) 666 | Else 667 | SetStick(1,"N/A", True) 668 | Critical, Off 669 | Return 670 | overwriteRightup: 671 | Critical, On 672 | IF (GetKeyState(leftKey, "P")) { 673 | IF (moveStickHalf) 674 | SetStick(-1 * walkSpeed,"N/A", True) 675 | Else 676 | SetStick(-1,"N/A", True) 677 | } 678 | Else 679 | SetStick(0,"N/A", True) 680 | Critical, Off 681 | Return 682 | 683 | overwriteDown: 684 | Critical, On 685 | IF (moveStickHalf) 686 | SetStick("N/A",-1 * walkSpeed, True) 687 | Else 688 | SetStick("N/A",-1, True) 689 | Critical, Off 690 | Return 691 | overwriteDownup: 692 | Critical, On 693 | IF (GetKeyState(upKey, "P")) { 694 | IF (moveStickHalf) 695 | SetStick("N/A",1 * walkSpeed, True) 696 | Else 697 | SetStick("N/A",1, True) 698 | } 699 | Else 700 | SetStick("N/A",0, True) 701 | Critical, Off 702 | Return 703 | 704 | overwriteWheelUp: 705 | SetStick(0,0) 706 | IF (!alreadyDown){ 707 | IF (vXbox) 708 | vstick.SetPOV(90) 709 | Else 710 | vstick.SetBtn(1,16) 711 | alreadyDown := True 712 | DllCall("Sleep", Uint, 250) 713 | } 714 | SetStick(-1,0) 715 | DllCall("Sleep", Uint, 30) 716 | SetStick(0,0) 717 | SetTimer, ReleaseDPad, -650 ; vstick.SetBtn(0,16) 718 | Return 719 | overwriteWheelDown: 720 | SetStick(0,0) 721 | IF (!alreadyDown){ 722 | IF (vXbox) 723 | vstick.SetPOV(90) 724 | Else 725 | vstick.SetBtn(1,16) 726 | alreadyDown := True 727 | DllCall("Sleep", Uint, 250) 728 | } 729 | SetStick(1,0) 730 | DllCall("Sleep", Uint, 30) 731 | SetStick(0,0) 732 | SetTimer, ReleaseDPad, -650 ; vstick.SetBtn(0,16) 733 | Return 734 | 735 | ReleaseDPad: 736 | IF (vXbox) 737 | vstick.SetPOV(-1) 738 | Else 739 | vstick.SetBtn(0,16) 740 | alreadyDown := False 741 | SetTimer, ReleaseDPad, Off 742 | Return 743 | 744 | ; Labels 745 | 746 | mouseTojoystick: 747 | Critical, On 748 | mouse2joystick(r,dr,OX,OY) 749 | Critical, Off 750 | Return 751 | 752 | ; Functions 753 | 754 | mouse2joystick(r,dr,OX,OY) { 755 | ; r is the radius of the outer circle. 756 | ; dr is a bounce back parameter. 757 | ; OX is the x coord of circle center. 758 | ; OY is the y coord of circle center. 759 | Global k, nnp, AlreadyDown 760 | MouseGetPos,X,Y 761 | X-=OX ; Move to controller coord system. 762 | Y-=OY 763 | RR:=sqrt(X**2+Y**2) 764 | IF (RR>r) { ; Check If outside controller circle. 765 | X:=round(X*(r-dr)/RR) 766 | Y:=round(Y*(r-dr)/RR) 767 | RR:=sqrt(X**2+Y**2) 768 | MouseMove,X+OX,Y+OY ; Calculate point on controller circle, move back to screen/window coords, and move mouse. 769 | } 770 | 771 | ; Calculate angle 772 | phi:=getAngle(X,Y) 773 | 774 | 775 | IF (RR>k*r AND !AlreadyDown) ; Check If outside inner circle/deadzone. 776 | action(phi,((RR-k*r)/(r-k*r))**nnp) ; nnp is a non-linearity parameter. 777 | Else 778 | setStick(0,0) ; Stick in equllibrium. 779 | 780 | MouseMove,OX,OY 781 | } 782 | 783 | action(phi,tilt) { 784 | ; This is for mouse2joystick. 785 | ; phi ∈ [0,2*pi] defines in which direction the stick is tilted. 786 | ; tilt ∈ (0,1] defines the amount of tilt. 0 is no tilt, 1 is full tilt. 787 | ; When this is called it is already established that the deadzone is left, or the inner radius. 788 | ; pmX/pmY is used for inverting axis. 789 | ; snapToFullTilt is used to ensure full tilt is possible, this needs to be improved, should be dependent on the sensitivity. 790 | Global pmX,pmY,pi,snapToFullTilt 791 | 792 | ; Adjust tilt 793 | tilt:=tilt>1 ? 1:tilt 794 | IF (snapToFullTilt!=-1) 795 | tilt:=1-tilt<=snapToFullTilt ? 1:tilt 796 | 797 | ; Two cases with forward+right 798 | ; Tilt is forward and slightly right. 799 | lb:=3*pi/2 ; lb is lower bound 800 | ub:=7*pi/4 ; ub is upper bound 801 | IF (phi>=lb && phi<=ub) 802 | { 803 | x:=pmX*tilt*scale(phi,ub,lb) 804 | y:=pmY*tilt 805 | setStick(x,y) 806 | Return 807 | } 808 | ; Tilt is slightly forward and right. 809 | lb:=7*pi/4 ; lb is lower bound 810 | ub:=2*pi ; ub is upper bound 811 | IF (phi>=lb && phi<=ub) 812 | { 813 | x:=pmX*tilt 814 | y:=pmY*tilt*scale(phi,lb,ub) 815 | setStick(x,y) 816 | Return 817 | } 818 | 819 | ; Two cases with right+downward 820 | ; Tilt is right and slightly downward. 821 | lb:=0 ; lb is lower bound 822 | ub:=pi/4 ; ub is upper bound 823 | IF (phi>=lb && phi<=ub) 824 | { 825 | x:=pmX*tilt 826 | y:=-pmY*tilt*scale(phi,ub,lb) 827 | setStick(x,y) 828 | Return 829 | } 830 | ; Tilt is downward and slightly right. 831 | lb:=pi/4 ; lb is lower bound 832 | ub:=pi/2 ; ub is upper bound 833 | IF (phi>=lb && phi<=ub) 834 | { 835 | x:=pmX*tilt*scale(phi,lb,ub) 836 | y:=-pmY*tilt 837 | setStick(x,y) 838 | Return 839 | } 840 | 841 | ; Two cases with downward+left 842 | ; Tilt is downward and slightly left. 843 | lb:=pi/2 ; lb is lower bound 844 | ub:=3*pi/4 ; ub is upper bound 845 | IF (phi>=lb && phi<=ub) 846 | { 847 | x:=-pmX*tilt*scale(phi,ub,lb) 848 | y:=-pmY*tilt 849 | setStick(x,y) 850 | Return 851 | } 852 | ; Tilt is left and slightly downward. 853 | lb:=3*pi/4 ; lb is lower bound 854 | ub:=pi ; ub is upper bound 855 | IF (phi>=lb && phi<=ub) 856 | { 857 | x:=-pmX*tilt 858 | y:=-pmY*tilt*scale(phi,lb,ub) 859 | setStick(x,y) 860 | Return 861 | } 862 | 863 | ; Two cases with forward+left 864 | ; Tilt is left and slightly forward. 865 | lb:=pi ; lb is lower bound 866 | ub:=5*pi/4 ; ub is upper bound 867 | IF (phi>=lb && phi<=ub) 868 | { 869 | x:=-pmX*tilt 870 | y:=pmY*tilt*scale(phi,ub,lb) 871 | setStick(x,y) 872 | Return 873 | } 874 | ; Tilt is forward and slightly left. 875 | lb:=5*pi/4 ; lb is lower bound 876 | ub:=3*pi/2 ; ub is upper bound 877 | IF (phi>=lb && phi<=ub) 878 | { 879 | x:=-pmX*tilt*scale(phi,lb,ub) 880 | y:=pmY*tilt 881 | setStick(x,y) 882 | Return 883 | } 884 | ; This should not happen: 885 | setStick(0,0) 886 | MsgBox,16,Error, Error at phi=%phi%. Please report. 887 | Return 888 | } 889 | 890 | scale(phi,lb,ub) { 891 | ; let phi->f(phi) then, f(ub)=0 and f(lb)=1 892 | Return (phi-ub)/(lb-ub) 893 | } 894 | 895 | setStick(x,y, a := False) { 896 | ; Set joystick x-axis to 100*x % and y-axis to 100*y % 897 | ; Input is x,y ∈ (-1,1) where 1 would mean full tilt in one direction, and -1 in the other, while zero would mean no tilt at all. Using this interval makes it easy to invert the axis 898 | ; (mainly this was choosen beacause the author didn't know the correct interval to use in CvJoyInterface) 899 | ; the input is not really compatible with the CvJoyInterface. Hence this transformation: 900 | IF (vXBox) { 901 | x:=(x+1)*50 ; This maps x,y (-1,1) -> (0,100) 902 | y:=(y+1)*50 903 | } 904 | Else { 905 | x:=(x+1)*16384 ; This maps x,y (-1,1) -> (0,32768) 906 | y:=(y+1)*16384 907 | } 908 | 909 | ; Use set by index. 910 | ; x = 1, y = 2. 911 | IF ( (!a AND vXbox) OR (a AND !vXBox) ) { ; IF (GetKeyState("RButton") OR a ) { 912 | axisX := 4 913 | axisY := 5 914 | } 915 | Else { 916 | axisX := 1 917 | axisY := 2 918 | } 919 | IF x is number 920 | vstick.SetAxisByIndex(x,axisX) 921 | IF y is number 922 | vstick.SetAxisByIndex(y,axisY) 923 | } 924 | 925 | ; Shared functions 926 | getAngle(x,y) { 927 | Global pi 928 | IF (x=0) 929 | Return 3*pi/2-(y>0)*pi 930 | phi:=atan(y/x) 931 | IF (x<0 && y>0) 932 | Return phi+pi 933 | IF (x<0 && y<=0) 934 | Return phi+pi 935 | IF (x>0 && y<0) 936 | Return phi+2*pi 937 | Return phi 938 | } 939 | 940 | exitFunc() { 941 | Global 942 | IF (mouse2Joystick) { 943 | setStick(0,0) 944 | SetStick(0,0, True) 945 | IF (vXBox) 946 | vstick.UnPlug() 947 | vstick.Relinquish() 948 | } 949 | 950 | md.Delete() 951 | md := "" 952 | show_Mouse() ; DllCall("User32.dll\ShowCursor", "Int", 1) 953 | ;DllCall("SystemParametersInfo", UInt, 0x71, UInt, 0, UInt, OrigMouseSpeed, UInt, 0) ; Restore the original speed. 954 | ExitApp 955 | } 956 | 957 | ; 958 | ; End Script. 959 | ; Start settings. 960 | ; 961 | openSettings: 962 | If !toggle ; This is probably best. 963 | Return 964 | 965 | tree := " 966 | ( 967 | General|Setup,Hotkeys 968 | Mouse2Joystick|Axes,Keys 969 | Keyboard Movement|Keys 970 | Extra Settings 971 | )" 972 | GUI, Main:New, -MinimizeBox, % "Mouse2Joystick Custom for CEMU Settings - " . version 973 | GUI, Add, Text,, Options: 974 | GUI, Add, TreeView, xm w150 r16 gTreeClick Section 975 | GUI, Add, Button,xs w73 gMainOk, Ok 976 | GUI, Add, Button,x+4 w73 gMainSave Default, Save 977 | GUI, Add, Tab2, +Buttons -Theme -Wrap vTabControl ys w320 h0 Section, General|General>Setup|General>Hotkeys|Mouse2Joystick|Mouse2Joystick>Axes|Mouse2Joystick>Keys|Keyboard Movement|Keyboard Movement>Keys|Extra Settings 978 | GUIControlGet, S, Pos, TabControl ; Store the coords of this section for future use. 979 | ;------------------------------------------------------------------------------------------------------------------------------------------ 980 | GUI, Tab, General 981 | GUI, Add, GroupBox, x%SX% y%SY% w320 h120 Section, Output Mode 982 | GUI, Add, Radio, % "xp+10 yp+20 Group vopusevXBox Checked" . !usevXBox, Use vJoy Device (Direct Input) 983 | GUI, Add, Radio, % "xp yp+20 Checked" . usevXBox, Use vXBox Device (XInput) 984 | 985 | GUI, Add, GroupBox, xs+10 yp+20 w90 h50 Section,vJoy Device 986 | GUI, Add, DropDownList, xp+10 yp+20 vopvJoyDevice w70, % StrReplace(ValidDevices, vJoyDevice, vJoyDevice . "|") 987 | GUI, Add, GroupBox, ys w90 h50,vXBox Device 988 | GUI, Add, DropDownList, xp+10 yp+20 vopvXBoxDevice w70, % StrReplace("1|2|3|4|", vXBoxDevice, vXBoxDevice . "|") 989 | 990 | GUI, Add, GroupBox, x%SX% yp+45 w320 h50,Executable Name 991 | GUI, Add, Edit, xp+10 yp+20 vopgameExe w90, %gameExe% 992 | GUI, Add, Text, x+m yp+3, The executable name for your CEMU 993 | 994 | GUI, Add, GroupBox, x%SX% yp+35 w320 h40,Auto Activate Executable 995 | GUI, Add, Radio, % "xp+10 yp+20 Group vopautoActivateGame Checked" !autoActivateGame, No 996 | GUI, Add, Radio, % "x+m Checked" autoActivateGame, Yes 997 | GUI, Add, Text, x+m, Switch to CEMU when toggling controller? 998 | ;------------------------------------------------------------------------------------------------------------------------------------------ 999 | GUI, Tab, General>Setup 1000 | GUI, Add, GroupBox, x%SX% y%SY% w320 h50 Section, Sensitivity 1001 | GUI, Add, Edit, xs+10 yp+20 w50 vopr gNumberCheck, %r% 1002 | GUI, Add, Text, x+4 yp+3, Lower values correspond to higher sensitivity 1003 | 1004 | GUI, Add, GroupBox, xs yp+30 w320 h50, Non-Linear Sensitivity 1005 | GUI, Add, Edit, xs+10 yp+20 w50 vopnnp gNumberCheck, %nnp% 1006 | GUI, Add, Text, x+4 yp+3, 1 is Linear ( < 1 makes center more sensitive ) 1007 | 1008 | GUI, Add, GroupBox, xs yp+30 w320 h50, Deadzone 1009 | GUI, Add, Edit, xs+10 yp+20 w50 vopk gNumberCheck, %k% 1010 | GUI, Add, Text, x+4 yp+3, Range (0 - 1) 1011 | 1012 | GUI, Add, GroupBox, xs yp+30 w320 h50, Mouse Check Frequency 1013 | GUI, Add, Edit, xs+10 yp+20 w50 vopfreq Number, %freq% 1014 | GUI, Add, Text, x+4 yp+3, I recommend 50-100 ( Default:75 ) 1015 | ;------------------------------------------------------------------------------------------------------------------------------------------ 1016 | GUI, Tab, General>Hotkeys 1017 | GUI, Add, GroupBox, x%SX% y%SY% w320 h50 Section, Toggle Controller On/Off 1018 | GUI, Add, Hotkey, xs+10 yp+20 w50 Limit190 vopcontrollerSwitchKey, % StrReplace(controllerSwitchKey, "#") 1019 | GUI, Add, CheckBox, % "x+m yp+3 vopcontrollerSwitchKeyWin Checked" InStr(controllerSwitchKey, "#"), Use Windows key? 1020 | 1021 | GUI, Add, GroupBox, x%SX% yp+40 w320 h50 Section, Quit Application 1022 | GUI, Add, Hotkey, xs+10 yp+20 w50 Limit190 vopexitKey, % StrReplace(exitKey, "#") 1023 | GUI, Add, CheckBox, % "x+m yp+3 vopexitKeyWin Checked" InStr(exitKey, "#"), Use Windows key? 1024 | ;------------------------------------------------------------------------------------------------------------------------------------------ 1025 | GUI, Tab, Mouse2Joystick 1026 | GUI, Add, Text, x%SX% y%SY% Section, How are you reading this?!? 1027 | ;------------------------------------------------------------------------------------------------------------------------------------------ 1028 | GUI, Tab, Mouse2Joystick>Axes 1029 | GUI, Add, GroupBox, x%SX% y%SY% w320 h40 Section,Invert X-Axis 1030 | GUI, Add, Radio, % "xp+10 yp+20 Group vopinvertedX Checked" . !invertedX, No 1031 | GUI, Add, Radio, % "x+m Checked" . invertedX, Yes 1032 | 1033 | GUI, Add, GroupBox, xs yp+30 w320 h40 Section,Invert Y-Axis 1034 | GUI, Add, Radio, % "xp+10 yp+20 Group vopinvertedY Checked" . !invertedY, No 1035 | GUI, Add, Radio, % "x+m Checked" . invertedY, Yes 1036 | ;------------------------------------------------------------------------------------------------------------------------------------------ 1037 | GUI, Tab, Mouse2Joystick>Keys 1038 | GUI, Add, GroupBox, x%SX% y%SY% w440 h80 Section, Active KeyList 1039 | GUI, Add, Edit, xs+10 yp+20 w420 vopjoystickButtonKeyList, %joystickButtonKeyList% 1040 | GUI, Add, Button, xs+10 yp+30 w420 gKeyListHelper, KeyList Helper 1041 | 1042 | GUI, Add, GroupBox, x%SX% yp+40 w440 h50, Saved KeyList Manager 1043 | IniRead,allSavedLists,SavedKeyLists.ini 1044 | allSavedLists := StrReplace(allSavedLists, "`n", "|") 1045 | GUI, Add, ComboBox, xs+10 yp+20 w210 vopSaveListName, %allSavedLists% 1046 | GUI, Add, Button, x+m w60 gLoadSavedList, Load 1047 | GUI, Add, Button, x+m w60 gSaveSavedList, Save 1048 | GUI, Add, Button, x+m w60 gDeleteSavedList, Delete 1049 | ;------------------------------------------------------------------------------------------------------------------------------------------ 1050 | GUI, Tab, Keyboard Movement 1051 | GUI, Add, Text, x%SX% y%SY% Section, How are you reading this?!? 1052 | ;------------------------------------------------------------------------------------------------------------------------------------------ 1053 | GUI, Tab, Keyboard Movement>Keys 1054 | GUI, Add, GroupBox, x%SX% y%SY% w320 h120 Section, Keyboard Movement 1055 | GUI, Add, Text, xs+10 yp+25 Right w80, Up: 1056 | GUI, Add, Hotkey, x+2 yp-3 w50 Limit190 vopupKey, %upKey% 1057 | GUI, Add, Text, xs+10 yp+25 Right w80, Left: 1058 | GUI, Add, Hotkey, x+2 yp-3 w50 Limit190 vopleftKey, %leftKey% 1059 | GUI, Add, Text, xs+10 yp+25 Right w80, Down: 1060 | GUI, Add, Hotkey, x+2 yp-3 w50 Limit190 vopdownKey, %downKey% 1061 | GUI, Add, Text, xs+10 yp+25 Right w80, Right: 1062 | GUI, Add, Hotkey, x+2 yp-3 w50 Limit190 voprightKey, %rightKey% 1063 | 1064 | GUI, Add, GroupBox, xs w320 h80, Walking 1065 | GUI, Add, Text, xs+10 yp+20 Right w80, Toggle Walk: 1066 | GUI, Add, Hotkey, x+2 yp-3 w50 Limit190 vopwalkToggleKey, %walkToggleKey% 1067 | GUI, Add, Text, x+2 yp+3 Right w20, + : 1068 | GUI, Add, Hotkey, x+2 yp-3 w50 Limit190 vopincreaseWalkKey, %increaseWalkKey% 1069 | GUI, Add, Text, x+2 yp+3 Right w20, - : 1070 | GUI, Add, Hotkey, x+2 yp-3 w50 Limit190 vopdecreaseWalkKey, %decreaseWalkKey% 1071 | GUI, Add, Text, xs+10 yp+35 Right w80, Walking Speed: 1072 | GUI, Add, Slider, x+2 yp-8 w180 Range0-100 TickInterval10 Thick12 vopwalkSpeed gWalkSpeedChange AltSubmit, % walkSpeed*100 1073 | GUI, Font, Bold 1074 | GUI, Add, Text, x+1 yp+8 w40 vopwalkSpeedTxt, % Round(walkSpeed*100) "%" 1075 | GUI, Font 1076 | 1077 | GUI, Add, GroupBox, xs w320 h50, Gyro Control 1078 | GUI, Add, Text, xs+10 yp+20 Right w80, Gyro Control: 1079 | GUI, Add, Hotkey, x+2 yp-3 w50 Limit190 vopgyroToggleKey, %gyroToggleKey% 1080 | GUI, Font, cBlue Underline 1081 | GUI, Add, Text, x+15 yp+4 gAndroidPhoneLink, Click Here For Better Options 1082 | GUI, Font, 1083 | ;------------------------------------------------------------------------------------------------------------------------------------------ 1084 | GUI, Tab, Extra Settings 1085 | GUI, Add, GroupBox, x%SX% y%SY% w320 h40 Section,BotW Mouse Wheel to Weapon Change 1086 | GUI, Add, Radio, % "xp+10 yp+20 Group vopBotWmouseWheel Checked" . !BotWmouseWheel, No 1087 | GUI, Add, Radio, % "x+m Checked" . BotWmouseWheel, Yes 1088 | 1089 | GUI, Add, GroupBox, xs yp+30 w320 h50,Use ZL Lock Toggle Key 1090 | GUI, Add, Radio, % "xp+10 yp+20 Group voplockZL Checked" . !lockZL, No 1091 | GUI, Add, Radio, % "x+m Checked" . lockZL, Yes 1092 | GUI, Add, Text, x+10 Right w80, ZL Lock Key: 1093 | GUI, Add, Hotkey, x+2 yp-3 w50 Limit190 voplockZLToggleKey, %lockZLToggleKey% 1094 | 1095 | GUI, Add, GroupBox, xs yp+40 w320 h40,Hide Cursor 1096 | GUI, Add, CheckBox, % "xp+10 yp+20 vophideCursor Checked" . hideCursor, Hide cursor when controller toggled on? 1097 | 1098 | GUI, Font, cRed Bold 1099 | GUI, Add, GroupBox, xs yp+30 w320 h65,EXPERIMENTAL Alternate Mouse Detection 1100 | GUI, Font, 1101 | GUI, Add, CheckBox, % "xp+10 yp+20 vopuseAltMouseMethod Checked" . useAltMouseMethod, Use Mouse Delta? (Experimental) 1102 | GUI, Add, Text, xs+10 yp+20 w40 Right, X-Sen: 1103 | GUI, Add, Edit, x+2 yp-3 vopalt_xSen w40, %alt_xSen% 1104 | GUI, Add, Text, x+10 yp+3 w30 Right, Y-Sen: 1105 | GUI, Add, Edit, x+2 yp-3 vopalt_ySen w40, %alt_ySen% 1106 | GUI, Add, Text, x+3 yp+3 w130 Left, Try 260-400? No Idea... 1107 | 1108 | GUI, Add, StatusBar 1109 | BuildTree("Main", tree) 1110 | Gui, Main: Show 1111 | Return 1112 | 1113 | TreeClick: 1114 | IF (A_GUIEvent = "S") { 1115 | useSection := selectionPath(A_EventInfo) 1116 | IF (useSection = "Keyboard Movement") { 1117 | useSection := "Keyboard Movement>Keys" 1118 | TV_Modify(findByName(useSection), "Select") 1119 | } 1120 | Else IF (useSection = "Mouse2Joystick") { 1121 | useSection := "Mouse2Joystick>Keys" 1122 | TV_Modify(findByName(useSection), "Select") 1123 | } 1124 | SB_SetText(useSection) 1125 | GUIControl, Choose, TabControl, %useSection% 1126 | } 1127 | Return 1128 | 1129 | WalkSpeedChange: 1130 | GUIControlGet,tmpSpeed,,opwalkSpeed 1131 | GUIControl,,opwalkSpeedTxt, %tmpSpeed%`% 1132 | Return 1133 | 1134 | MainGUIClose: 1135 | GUI, Main:Destroy 1136 | Return 1137 | 1138 | mainOk: 1139 | Gui, Main:Hide 1140 | mainSave: 1141 | Gui, Main:Submit, NoHide 1142 | Gosub, SubmitAll 1143 | ; Get old hotkeys. 1144 | ; Disable old hotkeys 1145 | IF (controllerSwitchKey) 1146 | Hotkey,%controllerSwitchKey%,controllerSwitch, off 1147 | IF (exitKey) 1148 | Hotkey,%exitKey%,exitFunc, off 1149 | 1150 | ; Joystick buttons 1151 | Hotkey, If, (!toggle && mouse2joystick) 1152 | IF (walkToggleKey) 1153 | HotKey,%walkToggleKey%,toggleHalf, Off 1154 | IF (decreaseWalkKey) 1155 | HotKey,%decreaseWalkKey%,decreaseWalk, Off 1156 | IF (increaseWalkKey) 1157 | HotKey,%increaseWalkKey%,increaseWalk, Off 1158 | IF (lockZLToggleKey AND lockZL) 1159 | HotKey,%lockZLToggleKey%,toggleAimLock, Off 1160 | IF (BotWmouseWheel) { 1161 | Hotkey,WheelUp, overwriteWheelUp, off 1162 | Hotkey,WheelDown, overwriteWheelDown, off 1163 | } 1164 | IF (gyroToggleKey) { 1165 | HotKey,%gyroToggleKey%, GyroControl, off 1166 | HotKey,%gyroToggleKey% Up, GyroControlOff, off 1167 | } 1168 | Hotkey,%upKey%, overwriteUp, off 1169 | Hotkey,%upKey% Up, overwriteUpup, off 1170 | Hotkey,%leftKey%, overwriteLeft, off 1171 | Hotkey,%leftKey% Up, overwriteLeftup, off 1172 | Hotkey,%downKey%, overwriteDown, off 1173 | Hotkey,%downKey% Up, overwriteDownup, off 1174 | Hotkey,%rightKey%, overwriteRight, off 1175 | Hotkey,%rightKey% Up, overwriteRightup, off 1176 | 1177 | Loop, Parse, joystickButtonKeyList, `, 1178 | { 1179 | useButton := A_Index 1180 | Loop, Parse, A_LoopField, | 1181 | { 1182 | keyName:=A_LoopField 1183 | IF (!keyName) 1184 | Continue 1185 | KeyList[keyName] := useButton 1186 | Hotkey,%keyName%, pressJoyButton, off 1187 | Hotkey,%keyName% Up, releaseJoyButton, off 1188 | } 1189 | } 1190 | Hotkey, If 1191 | 1192 | ; Read settings. 1193 | 1194 | IniRead,allSections,settings.ini 1195 | 1196 | Loop,Parse,allSections,`n 1197 | { 1198 | IniRead,pairs,settings.ini,%A_LoopField% 1199 | Loop,Parse,pairs,`n 1200 | { 1201 | StringSplit,keyValue,A_LoopField,= 1202 | %keyValue1%:=keyValue2 1203 | } 1204 | } 1205 | 1206 | IF (mouse2joystick) { 1207 | GoSub, initCvJoyInterface 1208 | GoSub, mouse2joystickHotkeys 1209 | } 1210 | pmX:=invertedX ? -1:1 ; Sign for inverting axis 1211 | pmY:=invertedY ? -1:1 1212 | 1213 | ; Enable new hotkeys 1214 | IF (controllerSwitchKey) 1215 | Hotkey,%controllerSwitchKey%,controllerSwitch, on 1216 | IF (exitKey) 1217 | Hotkey,%exitKey%,exitFunc, on 1218 | Return 1219 | 1220 | SubmitAll: 1221 | ;FileDelete, settings.ini ; Should I just delete the settings file before writing all settings to it? Guarantees a clean file, but doesn't allow for hidden options... 1222 | ; Write General 1223 | IniWrite, % opusevXBox - 1, settings.ini, General, usevXBox 1224 | IniWrite, % opvJoyDevice, settings.ini, General, vJoyDevice 1225 | IniWrite, % opvXBoxDevice, settings.ini, General, vXBoxDevice 1226 | IniWrite, % opgameExe, settings.ini, General, gameExe 1227 | IniWrite, % opautoActivateGame - 1, settings.ini, General, autoActivateGame 1228 | ; Write General>Setup 1229 | IniWrite, % opr, settings.ini, General>Setup, r 1230 | IniWrite, % opnnp, settings.ini, General>Setup, nnp 1231 | IniWrite, % opk, settings.ini, General>Setup, k 1232 | IniWrite, % opfreq, settings.ini, General>Setup, freq 1233 | ; Write General>Hotkeys 1234 | IniWrite, % opcontrollerSwitchKeyWin ? "#" . opcontrollerSwitchKey : opcontrollerSwitchKey, settings.ini, General>Hotkeys, controllerSwitchKey 1235 | IniWrite, % opexitKeyWin ? "#" . opexitKey : opexitKey, settings.ini, General>Hotkeys, exitKey 1236 | ; Write Mouse2Joystick>Axes 1237 | IniWrite, % opinvertedX - 1, settings.ini, Mouse2Joystick>Axes, invertedX 1238 | IniWrite, % opinvertedY - 1, settings.ini, Mouse2Joystick>Axes, invertedY 1239 | ; Write Mouse2Joystick>Keys 1240 | IniWrite, % opjoystickButtonKeyList, settings.ini, Mouse2Joystick>Keys, joystickButtonKeyList 1241 | ; Write Keyboard Movement>Keys 1242 | IniWrite, % opupKey, settings.ini, Keyboard Movement>Keys, upKey 1243 | IniWrite, % opleftKey, settings.ini, Keyboard Movement>Keys, leftKey 1244 | IniWrite, % opdownKey, settings.ini, Keyboard Movement>Keys, downKey 1245 | IniWrite, % oprightKey, settings.ini, Keyboard Movement>Keys, rightKey 1246 | IniWrite, % opwalkToggleKey, settings.ini, Keyboard Movement>Keys, walkToggleKey 1247 | IniWrite, % opincreaseWalkKey, settings.ini, Keyboard Movement>Keys, increaseWalkKey 1248 | IniWrite, % opdecreaseWalkKey, settings.ini, Keyboard Movement>Keys, decreaseWalkKey 1249 | IniWrite, % Round(opwalkSpeed/100, 2), settings.ini, Keyboard Movement>Keys, walkSpeed 1250 | IniWrite, % opgyroToggleKey, settings.ini, Keyboard Movement>Keys, gyroToggleKey 1251 | ; Write Extra Settings 1252 | IF (RegexMatch(opjoystickButtonKeyList, "i)wheel(down|up)")) ; If wheeldown/up is part of the keylist you cannot use the special wheel functions for BotW 1253 | opBotWmouseWheel := 1 1254 | IniWrite, % opBotWmouseWheel - 1, settings.ini, Extra Settings, BotWmouseWheel 1255 | IniWrite, % oplockZL- 1, settings.ini, Extra Settings, lockZL 1256 | IniWrite, % oplockZLToggleKey, settings.ini, Extra Settings, lockZLToggleKey 1257 | IniWrite, % ophideCursor, settings.ini, Extra Settings, hideCursor 1258 | IniWrite, % opuseAltMouseMethod, settings.ini, Extra Settings, useAltMouseMethod 1259 | IniWrite, % opalt_xSen, settings.ini, Extra Settings, alt_xSen 1260 | IniWrite, % opalt_ySen, settings.ini, Extra Settings, alt_ySen 1261 | Return 1262 | 1263 | selectionPath(ID) { 1264 | TV_GetText(name,ID) 1265 | IF (!name) 1266 | Return 0 1267 | parentID := ID 1268 | Loop 1269 | { 1270 | parentID := TV_GetParent(parentID) 1271 | IF (!parentID) 1272 | Break 1273 | parentName= 1274 | TV_GetText(parentName, parentID) 1275 | IF (parentName) 1276 | name := parentName ">" name 1277 | } 1278 | Return name 1279 | } 1280 | 1281 | findByName(Name){ 1282 | retID := False 1283 | ItemID = 0 ; Causes the loop's first iteration to start the search at the top of the tree. 1284 | Loop 1285 | { 1286 | ItemID := TV_GetNext(ItemID, "Full") ; Replace "Full" with "Checked" to find all checkmarked items. 1287 | IF (!ItemID) ; No more items in tree. 1288 | Break 1289 | temp := selectionPath(ItemID) 1290 | IF (temp = Name) { 1291 | retID := ItemID 1292 | Break 1293 | } 1294 | } 1295 | Return retID 1296 | } 1297 | 1298 | BuildTree(aGUI, treeString, oParent := 0) { 1299 | Static pParent := [] 1300 | Static Call := 0 1301 | Loop, Parse, treeString, `n, `r 1302 | { 1303 | startingString := A_LoopField 1304 | temp := StrSplit(startingString, ",") 1305 | Loop % temp.MaxIndex() 1306 | { 1307 | useString := Trim(temp[A_Index]) 1308 | IF (!useString) 1309 | Continue 1310 | Else IF (useString = "||") { 1311 | useIndex := A_Index+1 1312 | While (useIndex < temp.MaxIndex() + 1) { 1313 | useRest .= "," . temp[useIndex] 1314 | useIndex++ 1315 | } 1316 | useRest := SubStr(useRest, 2) 1317 | BuildTree(aGUI, useRest, pParent[--Call]) 1318 | Break 1319 | } 1320 | Else IF InStr(useString, "|") { 1321 | newTemp := StrSplit(useString, "|") 1322 | pParent[Call++] := oParent 1323 | uParent := TV_Add(newTemp[1], oParent, (oParent = 0 ) ? "Expand" : "") 1324 | useRest := RegExReplace(useString, newTemp[1] . "\|(.*)$", "$1") 1325 | useIndex := A_Index+1 1326 | While (useIndex < temp.MaxIndex() + 1) { 1327 | useRest .= "," . temp[useIndex] 1328 | useIndex++ 1329 | } 1330 | BuildTree(aGUI, useRest, uParent) 1331 | Break 1332 | } 1333 | Else 1334 | TV_Add(useString, oParent) 1335 | } 1336 | } 1337 | } 1338 | 1339 | NumberCheck(hEdit) { 1340 | static PrevNumber := [] 1341 | 1342 | ControlGet, Pos, CurrentCol,,, ahk_id %hEdit% 1343 | GUIControlGet, NewNumber,, %hEdit% 1344 | StrReplace(NewNumber, ".",, Count) 1345 | 1346 | If NewNumber ~= "[^\d\.-]|^.+-" Or Count > 1 { ; BAD 1347 | GUIControl,, %hEdit%, % PrevNumber[hEdit] 1348 | SendMessage, 0xB1, % Pos-2, % Pos-2,, ahk_id %hEdit% 1349 | } 1350 | 1351 | Else ; GOOD 1352 | PrevNumber[hEdit] := NewNumber 1353 | } 1354 | 1355 | AndroidPhoneLink: 1356 | Run, https://sshnuke.net/cemuhook/padudpserver.html 1357 | Return 1358 | 1359 | LoadSavedList: 1360 | GUIControlGet, slName,, opSaveListName 1361 | IniRead, ldKeyList, SavedKeyLists.ini, %slName%, KeyList 1362 | IF (ldKeyList != "ERROR") 1363 | GUIControl,, opjoystickButtonKeyList, %ldKeyList% 1364 | Return 1365 | 1366 | SaveSavedList: 1367 | GUIControlGet, slName,, opSaveListName 1368 | IF (!slName) { 1369 | MsgBox, Please enter anything as an identifier 1370 | Return 1371 | } 1372 | GUIControlGet, slList,, opjoystickButtonKeyList 1373 | IniWrite, %slList%, SavedKeyLists.ini, %slName%, KeyList 1374 | IniRead,allSavedLists,SavedKeyLists.ini 1375 | allSavedLists := StrReplace(allSavedLists, "`n", "|") 1376 | GUIControl,, opSaveListName, % "|" . allSavedLists 1377 | GUIControl, Text, opSaveListName, %slName% 1378 | Return 1379 | 1380 | DeleteSavedList: 1381 | GUIControlGet, slName,, opSaveListName 1382 | IniDelete, SavedKeyLists.ini, %slName% 1383 | IniRead,allSavedLists,SavedKeyLists.ini 1384 | allSavedLists := StrReplace(allSavedLists, "`n", "|") 1385 | GUIControl,, opSaveListName, % "|" . allSavedLists 1386 | Return 1387 | 1388 | ; Default settings in case problem reading/writing to file. 1389 | setSettingsToDefault: 1390 | pairsDefault= 1391 | ( 1392 | gameExe=Cemu.exe 1393 | usevXBox=0 1394 | vJoyDevice=1 1395 | vXBoxDevice=1 1396 | autoActivateGame=1 1397 | r=30 1398 | k=0.02 1399 | freq=75 1400 | nnp=.80 1401 | controllerSwitchKey=F1 1402 | exitKey=#q 1403 | invertedX=0 1404 | invertedY=0 1405 | joystickButtonKeyList=e,LShift,Space,LButton,1,3,LCtrl,RButton,Enter,m,q,c,i,k,j,l,b 1406 | upKey=w 1407 | leftKey=a 1408 | downKey=s 1409 | rightKey=d 1410 | walkToggleKey=Numpad0 1411 | increaseWalkKey=NumpadAdd 1412 | decreaseWalkKey=NumPadSub 1413 | walkSpeed=0.5 1414 | gyroToggleKey= 1415 | BotWmouseWheel=0 1416 | lockZL=0 1417 | lockZLToggleKey=Numpad1 1418 | hideCursor=1 1419 | BotWmotionAim=0 1420 | useAltMouseMethod=0 1421 | alt_xSen=400 1422 | alt_ySen=280 1423 | ) 1424 | Loop,Parse,pairsDefault,`n 1425 | { 1426 | StringSplit,keyValue,A_LoopField,= 1427 | %keyValue1%:=keyValue2 1428 | } 1429 | Goto, readSettingsSkippedDueToError 1430 | Return 1431 | 1432 | #IF KeyHelperRunning(setToggle) 1433 | #IF 1434 | KeyListHelper: 1435 | Hotkey, IF, KeyHelperRunning(setToggle) 1436 | HotKey,~LButton, getControl, On 1437 | Hotkey, IF 1438 | GUI, Main:Default 1439 | GUIControlGet, getKeyList,, opjoystickButtonKeyList 1440 | KeyListByNum := [] 1441 | Loop, Parse, getKeyList, `, 1442 | { 1443 | keyName := A_LoopField 1444 | If !keyName 1445 | continue 1446 | KeyListByNum[A_Index] := keyName 1447 | } 1448 | IF (vXBox) { 1449 | textWidth := 100 1450 | numEdits := 16 1451 | } 1452 | Else { 1453 | textWidth := 50 1454 | numEdits := 18 1455 | } 1456 | setToggle := False 1457 | GUI, Main:+Disabled 1458 | GUI, KeyHelper:New, +HWNDKeyHelperHWND -MinimizeBox +OwnerMain 1459 | GUI, Margin, 10, 7.5 1460 | GUI, Font,, Lucida Sans Typewriter ; Courier New 1461 | GUI, Add, Text, W0 H0 vLoseFocus, Hidden 1462 | GUI, Add, Text, W%textWidth% R1 Right Section, % vXBox ? Format("{1:-9.9s}{2:4.4s}","( A - ✕ )","A") : "A" 1463 | GUI, Add, Edit, W80 R1 x+m yp-3 Center ReadOnly -TabStop, % KeyListByNum[1] 1464 | GUI, Add, Text, W%textWidth% xs R1 Right, % vXBox ? Format("{1:-9.9s}{2:4.4s}","( B - ○ )","B") : "B" 1465 | GUI, Add, Edit, W80 R1 x+m yp-3 Center ReadOnly -TabStop, % KeyListByNum[2] 1466 | GUI, Add, Text, W%textWidth% xs R1 Right, % vXBox ? Format("{1:-9.9s}{2:4.4s}","( X - □ )","X") : "X" 1467 | GUI, Add, Edit, W80 R1 x+m yp-3 Center ReadOnly -TabStop, % KeyListByNum[3] 1468 | GUI, Add, Text, W%textWidth% xs R1 Right, % vXBox ? Format("{1:-9.9s}{2:4.4s}","( Y - △ )","Y") : "Y" 1469 | GUI, Add, Edit, W80 R1 x+m yp-3 Center ReadOnly -TabStop, % KeyListByNum[4] 1470 | GUI, Add, Text, W%textWidth% xs R1 Right, % vXBox ? Format("{1:-9.9s}{2:4.4s}","(LB - L1)","L") : "L" 1471 | GUI, Add, Edit, W80 R1 x+m yp-3 Center ReadOnly -TabStop, % KeyListByNum[5] 1472 | GUI, Add, Text, W%textWidth% xs R1 Right, % vXBox ? Format("{1:-9.9s}{2:4.4s}","(RB - R1)","R") : "R" 1473 | GUI, Add, Edit, W80 R1 x+m yp-3 Center ReadOnly -TabStop, % KeyListByNum[6] 1474 | GUI, Add, Text, W%textWidth% xs R1 Right, % vXBox ? Format("{1:-9.9s}{2:4.4s}","(LT - L2)","ZL") : "ZL" 1475 | GUI, Add, Edit, W80 R1 x+m yp-3 Center ReadOnly -TabStop, % KeyListByNum[7] 1476 | GUI, Add, Text, W%textWidth% xs R1 Right, % vXBox ? Format("{1:-9.9s}{2:4.4s}","(RT - R2)","ZR") : "ZR" 1477 | GUI, Add, Edit, W80 R1 x+m yp-3 Center ReadOnly -TabStop, % KeyListByNum[8] 1478 | GUI, Add, Text, W%textWidth% xs R1 Right, % vXBox ? Format("{1:-9.9s}{2:4.4s}","( Start )","+") : "+" 1479 | GUI, Add, Edit, W80 R1 x+m yp-3 Center ReadOnly -TabStop, % KeyListByNum[9] 1480 | GUI, Add, Text, W%textWidth% xs R1 Right, % vXBox ? Format("{1:-9.9s}{2:4.4s}","( Back )","-") : "-" 1481 | GUI, Add, Edit, W80 R1 x+m yp-3 Center ReadOnly -TabStop, % KeyListByNum[10] 1482 | GUI, Add, Text, w65 ys R1 Right Section, L-Click 1483 | GUI, Add, Edit, W80 R1 x+m yp-3 Center ReadOnly -TabStop, % KeyListByNum[11] 1484 | GUI, Add, Text, w65 ys R1 Right Section, R-Click 1485 | GUI, Add, Edit, W80 R1 x+m yp-3 Center ReadOnly -TabStop, % KeyListByNum[12] 1486 | GUI, Add, Text, w80 ys R1 Right Section, D-Up 1487 | GUI, Add, Edit, W80 R1 x+m yp-3 Center ReadOnly -TabStop, % KeyListByNum[13] 1488 | GUI, Add, Text, w80 xs R1 Right, D-Down 1489 | GUI, Add, Edit, W80 R1 x+m yp-3 Center ReadOnly -TabStop, % KeyListByNum[14] 1490 | GUI, Add, Text, w80 xs R1 Right, D-Left 1491 | GUI, Add, Edit, W80 R1 x+m yp-3 Center ReadOnly -TabStop, % KeyListByNum[15] 1492 | GUI, Add, Text, w80 xs R1 Right, D-Right 1493 | GUI, Add, Edit, W80 R1 x+m yp-3 Center ReadOnly -TabStop, % KeyListByNum[16] 1494 | GUI, Add, Text, w0 xs R1 Right, Dummy 1495 | IF(!vXBox) { 1496 | GUI, Add, Text, w80 xs R1 Right, Blow-Mic 1497 | GUI, Add, Edit, W80 R1 x+m yp-3 Center ReadOnly -TabStop, % KeyListByNum[17] 1498 | GUI, Add, Text, w80 xs R1 Right, Show-Screen 1499 | GUI, Add, Edit, W80 R1 x+m yp-3 Center ReadOnly -TabStop, % KeyListByNum[18] 1500 | } 1501 | GUI, Add, Text, w0 xm+230 R1 Right, Dummy 1502 | GUI, Add, Button, xp yp-30 w80 gSaveButton Section, Save 1503 | GUI, Add, Button, x+m w80 gCancelButton, Cancel 1504 | GUI, Add, Button, xs yp-30 w170 gAutoLoop, Auto Cycle 1505 | GUI, Add, Button, xs yp-60 w170 gClearButton, Clear 1506 | 1507 | GUI, Show,, KeyList Helper 1508 | GuiControl, Focus, LoseFocus 1509 | Return 1510 | 1511 | ClearButton: 1512 | GUI, KeyHelper:Default 1513 | Loop %numEdits% 1514 | GUIControl,,Edit%A_Index%, 1515 | Return 1516 | 1517 | CancelButton: 1518 | KeyHelperGUIClose: 1519 | IF (setToggle) 1520 | Return 1521 | Hotkey, IF, KeyHelperRunning(setToggle) 1522 | HotKey,~LButton, getControl, Off 1523 | Hotkey, IF 1524 | GUI, Main:-Disabled 1525 | GUI, KeyHelper:Destroy 1526 | Return 1527 | 1528 | SaveButton: 1529 | tempList := "" 1530 | Loop %numEdits% 1531 | { 1532 | GUIControlGet, tempKey,,Edit%A_Index% 1533 | tempList .= tempKey . "," 1534 | } 1535 | tempList := SubStr(tempList,1, StrLen(tempList)-1) 1536 | GUI, Main:Default 1537 | GUIControl,, opjoystickButtonKeyList, %tempList% 1538 | GoSub, KeyHelperGUIClose 1539 | Return 1540 | 1541 | getControl: 1542 | GUI, KeyHelper:Default 1543 | KeyWait, LButton 1544 | 1545 | setToggle := True 1546 | MouseGetPos,,, mouseWin, useControl, 1 1547 | IF (InStr(useControl, "Edit") AND mouseWin = KeyHelperHWND) 1548 | GetKey() 1549 | setToggle := False 1550 | 1551 | clearFocus: 1552 | GuiControl, Focus, LoseFocus 1553 | Return 1554 | 1555 | AutoLoop: 1556 | GUI, KeyHelper:Default 1557 | Loop 4 1558 | GUIControl, +Disabled, Button%A_Index% 1559 | setToggle := True 1560 | Loop %numEdits% { 1561 | useControl := "Edit" . A_Index 1562 | GetKey() 1563 | } 1564 | setToggle := False 1565 | Loop 4 1566 | GUIControl, -Disabled, Button%A_Index% 1567 | GoSub, clearFocus 1568 | MsgBox, Done 1569 | Return 1570 | 1571 | KeyHelperRunning(setTog){ 1572 | Return (WinActive("KeyList Helper") AND !setTog) 1573 | } 1574 | 1575 | GetKey() { 1576 | Global 1577 | GoSub, TurnOn 1578 | MousePressed := False 1579 | GUIControl, -E0x200, %useControl% 1580 | GuiControl,Text, %useControl%, Waiting 1581 | ih.Start() 1582 | ErrorLevel := ih.Wait() 1583 | singleKey := ih.EndKey 1584 | GoSub, TurnOff 1585 | 1586 | IF (MousePressed) 1587 | singleKey := MousePressed 1588 | Else IF (singleKey = "," OR singleKey = "=") ; Comma and equal sign Don't work 1589 | singleKey := "" 1590 | 1591 | singleKey := RegexReplace(singleKey, "Control", "Ctrl") 1592 | 1593 | GuiControl, Text, %useControl%, %singleKey% 1594 | GUIControl, +E0x200, %useControl% 1595 | Loop %numEdits% 1596 | { 1597 | GUIControlGet, tempKey,,Edit%A_Index% 1598 | IF (tempKey = singleKey AND useControl != "Edit" . A_Index) 1599 | GuiControl, Text, Edit%A_Index%, 1600 | } 1601 | Return singleKey 1602 | } 1603 | 1604 | WM_LBUTTONDOWN() { 1605 | Global useControl, MousePressed 1606 | Send, {Esc} 1607 | MousePressed := "LButton" 1608 | Return 0 1609 | } 1610 | 1611 | WM_RBUTTONDOWN() { 1612 | Global useControl, MousePressed 1613 | Send, {Esc} 1614 | MousePressed := "RButton" 1615 | Return 0 1616 | } 1617 | 1618 | WM_MBUTTONDOWN() { 1619 | Global useControl, MousePressed 1620 | Send, {Esc} 1621 | MousePressed := "MButton" 1622 | Return 0 1623 | } 1624 | 1625 | WM_XBUTTONDOWN(w) { 1626 | Global useControl, MousePressed 1627 | Send, {Esc} 1628 | SetFormat, IntegerFast, Hex 1629 | IF ((w & 0xFF) = 0x20) 1630 | MousePressed := "XButton1" 1631 | Else IF((w & 0xFF) = 0x40) 1632 | MousePressed := "XButton2" 1633 | Return 0 1634 | } 1635 | 1636 | WM_MOUSEHWHEEL(w) { 1637 | Global useControl, MousePressed 1638 | Send, {Esc} 1639 | SetFormat, IntegerFast, Hex 1640 | IF ((w & 0xFF0000) = 0x780000) 1641 | MousePressed := "WheelRight" 1642 | Else IF((w & 0xFF0000) = 0x880000) 1643 | MousePressed := "WheelLeft" 1644 | Return 0 1645 | } 1646 | 1647 | WM_MOUSEWHEEL(w) { 1648 | Global useControl, MousePressed 1649 | Send, {Esc} 1650 | SetFormat, IntegerFast, Hex 1651 | MousePressed := "" . w + 0x0 1652 | IF ((w & 0xFF0000) = 0x780000) 1653 | MousePressed := "WheelUp" 1654 | Else IF((w & 0xFF0000) = 0x880000) 1655 | MousePressed := "WheelDown" 1656 | Return 0 1657 | } 1658 | 1659 | TurnOn: 1660 | OnMessage(0x0201, "WM_LBUTTONDOWN") 1661 | OnMessage(0x0204, "WM_RBUTTONDOWN") 1662 | OnMessage(0x0207, "WM_MBUTTONDOWN") 1663 | OnMessage(0x020B, "WM_XBUTTONDOWN") 1664 | OnMessage(0x020E, "WM_MOUSEHWHEEL") 1665 | GUIControlGet, TempBotWmouseWheel,Main:,opBotWmouseWheel 1666 | IF (TempBotWmouseWheel) ; If this control is a 1, then BotW mousewheel is off and mouse wheel can be used as a key. 1667 | OnMessage(0x020A, "WM_MOUSEWHEEL") 1668 | Return 1669 | 1670 | TurnOff: 1671 | OnMessage(0x0201, "") 1672 | OnMessage(0x0204, "") 1673 | OnMessage(0x0207, "") 1674 | OnMessage(0x020B, "") 1675 | OnMessage(0x020E, "") 1676 | OnMessage(0x020A, "") 1677 | Return 1678 | 1679 | ;------------------------------------------------------------------------------- 1680 | show_Mouse(bShow := True) { ; show/hide the mouse cursor 1681 | ;------------------------------------------------------------------------------- 1682 | ; https://autohotkey.com/boards/viewtopic.php?p=173707#p173707 1683 | ; WINAPI: SystemParametersInfo, CreateCursor, CopyImage, SetSystemCursor 1684 | ; https://msdn.microsoft.com/en-us/library/windows/desktop/ms724947.aspx 1685 | ; https://msdn.microsoft.com/en-us/library/windows/desktop/ms648385.aspx 1686 | ; https://msdn.microsoft.com/en-us/library/windows/desktop/ms648031.aspx 1687 | ; https://msdn.microsoft.com/en-us/library/windows/desktop/ms648395.aspx 1688 | ;--------------------------------------------------------------------------- 1689 | static BlankCursor 1690 | static CursorList := "32512, 32513, 32514, 32515, 32516, 32640, 32641" 1691 | . ",32642, 32643, 32644, 32645, 32646, 32648, 32649, 32650, 32651" 1692 | local ANDmask, XORmask, CursorHandle 1693 | 1694 | IF (bShow) ; shortcut for showing the mouse cursor 1695 | Return, DllCall("SystemParametersInfo" 1696 | , "UInt", 0x57 ; UINT uiAction (SPI_SETCURSORS) 1697 | , "UInt", 0 ; UINT uiParam 1698 | , "Ptr", 0 ; PVOID pvParam 1699 | , "UInt", 0) ; UINT fWinIni 1700 | 1701 | IF (!BlankCursor) { ; create BlankCursor only once 1702 | VarSetCapacity(ANDmask, 32 * 4, 0xFF) 1703 | VarSetCapacity(XORmask, 32 * 4, 0x00) 1704 | BlankCursor := DllCall("CreateCursor" 1705 | , "Ptr", 0 ; HINSTANCE hInst 1706 | , "Int", 0 ; int xHotSpot 1707 | , "Int", 0 ; int yHotSpot 1708 | , "Int", 32 ; int nWidth 1709 | , "Int", 32 ; int nHeight 1710 | , "Ptr", &ANDmask ; const VOID *pvANDPlane 1711 | , "Ptr", &XORmask) ; const VOID *pvXORPlane 1712 | } 1713 | 1714 | ; set all system cursors to blank, each needs a new copy 1715 | Loop, Parse, CursorList, `,, %A_Space% 1716 | { 1717 | CursorHandle := DllCall("CopyImage" 1718 | , "Ptr", BlankCursor ; HANDLE hImage 1719 | , "UInt", 2 ; UINT uType (IMAGE_CURSOR) 1720 | , "Int", 0 ; int cxDesired 1721 | , "Int", 0 ; int cyDesired 1722 | , "UInt", 0) ; UINT fuFlags 1723 | DllCall("SetSystemCursor" 1724 | , "Ptr", CursorHandle ; HCURSOR hcur 1725 | , "UInt", A_Loopfield) ; DWORD id 1726 | } 1727 | } 1728 | 1729 | LockMouseToWindow(llwindowname="") { 1730 | IF (!llwindowname) { 1731 | DllCall("ClipCursor", "UInt", 0) 1732 | Return False 1733 | } 1734 | WinGetPos, llX, llY, llWidth, llHeight, %llwindowname% 1735 | VarSetCapacity(llrectA, 16) 1736 | IF (llWidth AND llHeight) { 1737 | NumPut(llX+10,&llrectA+0),NumPut(llY+54,&llrectA+4),NumPut(llWidth-10 + llX,&llrectA+8),NumPut(llHeight-10 + llY,&llrectA+12) 1738 | DllCall("ClipCursor", "UInt", &llrectA) 1739 | Return True 1740 | } 1741 | } 1742 | 1743 | installBus: 1744 | InstallUninstallScpVBus(True) 1745 | Return 1746 | uninstallBus: 1747 | InstallUninstallScpVBus(False) 1748 | Return 1749 | 1750 | InstallUninstallScpVBus(state:="ERROR") { 1751 | IF (state == "ERROR") 1752 | Return 1753 | IF (state){ 1754 | RunWait, *Runas devcon.exe install ScpVBus.inf root\ScpVBus, % A_ScriptDir "\ScpVBus", UseErrorLevel Hide 1755 | MsgBox,, Done Installing, reloading the script., 1 1756 | } Else { 1757 | RunWait, *Runas devcon.exe remove root\ScpVBus, % A_ScriptDir "\ScpVBus", UseErrorLevel Hide 1758 | IniWrite,0, settings.ini, General, usevXBox ; Turn off the setting for future runs as well. 1759 | MsgBox,, Done Un-Installing, reloading the script., 1 1760 | } 1761 | IF (ErrorLevel == "ERROR") 1762 | return 0 1763 | Reload 1764 | } 1765 | 1766 | ; Gets called when mouse moves 1767 | ; x and y are DELTA moves (Amount moved since last message), NOT coordinates. 1768 | MouseEvent(MouseID, x := 0, y := 0){ 1769 | Global alt_xSen, alt_ySen 1770 | Static useX, useY, xZero, yZero 1771 | intv := 1 1772 | 1773 | IF (MouseID == "RESET") { 1774 | useX := useY := 0 1775 | SetStick(0,0) 1776 | Return 1777 | } 1778 | 1779 | IF ((x < 0 AND useX > 0) OR (x > 0 AND useX < 0)) 1780 | useX := 0 1781 | IF ((y < 0 AND useY > 0) OR (y > 0 AND useY < 0)) 1782 | useY := 0 1783 | IF (x AND y) 1784 | intv := 4 1785 | 1786 | IF (!x) 1787 | xZero++ 1788 | IF (xZero > 2) { 1789 | useX := 0 1790 | xZero := 0 1791 | } 1792 | IF (x > 0) 1793 | useX += intv 1794 | Else 1795 | useX -= intv 1796 | 1797 | IF (!y) 1798 | yZero++ 1799 | IF (yZero > 2) { 1800 | useY := 0 1801 | yZero := 0 1802 | } 1803 | IF (y > 0) 1804 | useY += intv 1805 | Else 1806 | useY -= intv 1807 | 1808 | IF (abs(useX)>alt_xSen) 1809 | useX := useX/abs(useX) * alt_xSen 1810 | Else IF (abs(x) AND abs(useX) < alt_xSen/6) 1811 | useX := useX/abs(useX) * alt_xSen/6 1812 | 1813 | IF (abs(useY)>alt_ySen) 1814 | useY := useY/abs(useY) * alt_ySen 1815 | Else IF (abs(y) AND abs(useY) < alt_ySen/6) 1816 | useY := useY/abs(useY) * alt_ySen/6 1817 | 1818 | SetStick(useX/alt_xSen,-useY/alt_ySen) 1819 | Return 1820 | } 1821 | 1822 | MouseEvent_OFF(MouseID, x := 0, y := 0){ 1823 | Global alt_xSen, alt_ySen 1824 | Static useX, useY 1825 | IF (MouseID == "RESET") { 1826 | useX := useY := 0 1827 | SetStick(0,0) 1828 | Return 1829 | } 1830 | 1831 | IF ((x < 0 AND useX > 0) OR (x > 0 AND useX < 0)) 1832 | useX := 0 1833 | IF ((y < 0 AND useY > 0) OR (y > 0 AND useY < 0)) 1834 | useY := 0 1835 | 1836 | IF (!x) 1837 | useX /= 2 1838 | Else 1839 | useX += x 1840 | 1841 | IF (abs(useX)>alt_xSen) 1842 | useX := x/abs(x) * alt_xSen 1843 | 1844 | IF (!y) 1845 | useY /= 2 1846 | Else 1847 | useY += y 1848 | 1849 | IF (abs(useY)>alt_ySen) 1850 | useY := y/abs(y) * alt_ySen 1851 | 1852 | SetStick(useX/alt_xSen,-useY/alt_ySen) 1853 | Return 1854 | } 1855 | -------------------------------------------------------------------------------- /settings.ini: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CemuUser8/mouse2joystick_custom_CEMU/c7cfdb830929ac46c24e89b112e3fcfbb18ae1d3/settings.ini --------------------------------------------------------------------------------