djvj icon

keymapper test with numput

djvj | PRO | 02/09/16 09:23:50 PM UTC | 0 ⭐ | 586 👁️ | Never ⏰ | []
text |

33.06 KB

|

None

|

0 👍

/

0 👎

MCRC=D7AF959A
MVersion=1.1.5
 RunAHKKeymapper(method) {
	Global ahkDefaultProfile,ahkFEProfile,ahkRomProfile,ahkEmuProfile,ahkSystemProfile,ahkRocketLauncherProfile,ahkLauncherPath,ahkLauncherExe,keymapperFrontEndProfile
	Global systemName,dbName,emuName,moduleExtensionsPath,contextOnExit
	Log("RunAHKKeymapper - Started")
 	If (method = "load")
	{	Log("RunAHKKeymapper - Loading " . dbName . ", " . emuName . ", " . systemName . ", or _Default AHK Keymapper profile",4)
		profile := GetAHKProfile(ahkRomProfile . "|" . ahkEmuProfile . "|" . ahkSystemProfile . "|" . ahkDefaultProfile)
		unloadAHK := 1	; this method we don't want to run any ahk profile if none were found
	} Else If (method = "unload" && keymapperFrontEndProfile = "ahk" && !contextOnExit)	; user must have ahk selected to load an ahk FE profile
	{	Log("RunAHKKeymapper - Loading Front End AHK Keymapper profile",4)
		profile := GetAHKProfile(ahkFEProfile)
		unloadAHK := 1	; this method we don't want to run any ahk profile if none were found
	} Else If (method = "menu")	; this method we do not want to unload AHK if a new profile was not found, existing profile should stay running
	{	Log("RunAHKKeymapper - Loading RocketLauncher AHK Keymapper profile",4)
		profile := GetAHKProfile(ahkRocketLauncherProfile)
	} Else If (method = "unload")
	{	Log("RunAHKKeymapper - Unloading AhkLauncher",4)
		unloadAHK := 1
	}
	If (unloadAHK || profile)	; if a profile was found or this method should unload the existing AHK profile
	{	Log("RunAHKKeymapper - If " . ahkLauncherExe . " is running, need to close it first before a new profile can be loaded",4)
		If Process("Exist", ahkLauncherExe) {
			Process("Close", ahkLauncherExe)	; close ahkLauncher first
			Process("WaitClose", ahkLauncherExe)
		}
	}
 	If profile {	; if a profile was found, load it
		If FileExist(moduleExtensionsPath . "\autohotkey.dll")
			ScriptError("Please delete autohotkey.dll from the folder """ . moduleExtensionsPath . """ as it will cause errors with " . ahkLauncherExe)
		Log("RunAHKKeymapper - This profile was found and needs to be loaded: " . profile,4)
		Run(ahkLauncherExe . " -notray """ . profile . """", ahkLauncherPath)	; load desired ahk profile
	}
	Log("RunAHKKeymapper - Ended")
}
 ; Only use FEProfile if you want to ignore rom and system profile
; ProfilePrefixes separate prefixes with a "|"
GetAHKProfile(ProfilePrefixes) {
	Global systemName, dbName, emuName, keymapperProfilePath ;for script error
	Log("GetAHKProfile - Started")
	Loop, Parse, ProfilePrefixes, |
	{	profile := A_LoopField . ".ahk"
		Log("GetAHKProfile - Searching for: " . profile,5)
		If FileExist(profile)
		{	foundProfile := 1
			Log("GetAHKProfile - Ended and found: " . profile)
			Return profile
		}
	}
	If !foundProfile
		Log("GetAHKProfile - Ended and no profile found")
	Return
}
 ;##################################################################
;LoadPreferredControllers(JoyIDsPreferredControllers)
;##################################################################
;Creates a list for Joy IDs by creating a list of currently connected controllers and re-arranging that list to match the order presented in the Preferred Controller List.
;If both an Oem Name and a related custom joy name is found in the list, the oem name position is used
;JoyIDsPreferredControllers this is the list of preferred controllers
;it should be a list of controller names separated with |
;##################################################################
 LoadPreferredControllers(JoyIDsPreferredControllers) {
	Global CustomJoyNameArray
	Log("LoadPreferredControllers - Started")
	Log("LoadPreferredControllers - JoyIDsPreferredControllers = " . JoyIDsPreferredControllers,5)
	; 16 is max number of joysticks windows and joyids allows
	Log("LoadPreferredControllers - Creating a list of currently connected joysticks",5) 
	JoystickArray := GetJoystickArray()
	Loop, 16
	{	ControllerName := JoystickArray[A_Index,1]
		MID := JoystickArray[A_Index,2]
		PID := JoystickArray[A_Index,3]
		GUID := JoystickArray[A_Index,4]
		If ControllerName
		{	;CustomJoyNameArray is an Associative Array that associates a custom joy name to a controller name. See ahk_l documentation for objects.
			CustomJoyName := CustomJoyNameArray[ControllerName]
			;prepare for string position searching
			JoyIDsPreferredControllersModified := "|" . JoyIDsPreferredControllers . "|"
			;store last position this will be used for controllers not in PreferredControllerList
			LastPosition := StrLen(JoyIDsPreferredControllersModified)
			;position order 1 is for the normal controller name and position order 2 is for the custom name
			;normal controller name always takes higher priority over custom names since it is more specific
			PositionOrder_1 := InStr(JoyIDsPreferredControllersModified, "|" . ControllerName . "|")
			If CustomJoyName
				PositionOrder_2 := InStr(JoyIDsPreferredControllersModified, "|" . CustomJoyName . "|")
 			If PositionOrder_1
				PositionOrder := PositionOrder_1
			Else If PositionOrder_2
				PositionOrder := PositionOrder_2
			Else
				PositionOrder := LastPosition
			;Position Order is the order found in the JoyIDsPreferredControllersModified list
			;it will be appended with a decimal value relative to order they were found in.
			;create sorting string also add the order found. If controllers are not found in preferred, plug-in order is used.
			;example format: 123.01|360 Controller
			Log("LoadPreferredControllers - Preferred Order Sorting List -> " . PositionOrder . "." . SubStr("0" . A_Index, -1) . "|" . MID . "|" . PID . "|" . GUID,5)
			If !String2Sort
				String2Sort := PositionOrder . "." . SubStr("0" . A_Index, -1) . "|" . MID . "|" . PID . "|" . GUID
			Else
				String2Sort .= "`n" . PositionOrder . "." . SubStr("0" . A_Index, -1) . "|" . MID . "|" . PID . "|" . GUID
		}
	}
	Log("LoadPreferredControllers - Sorting Currently Connected joysticks List to match the order of the Preferred Controller List")  
	;sort numerically
	Sort, String2Sort, N
	Log("LoadPreferredControllers - Assigning the New Joystick IDs according to the preferred list for the active controllers")
	;parse the string
	Loop, Parse, String2Sort, `n
	{	StringSplit, JoyIDsSortArray, A_LoopField, |
		MID := JoyIDsSortArray2
		PID := JoyIDsSortArray3
		GUID := JoyIDsSortArray4
		ChangeJoystickID(MID,PID,GUID,A_Index)
	}
	Log("LoadPreferredControllers - Ended")
}
 ;##################################################################
;RunKeyMapper(keymapperLoad_Or_Unload,keymapper)
;##################################################################
;keymapperLoad_Or_Unload  can be = "load" or "unload" or "menu"
; menu is for loading the RocketLauncher menu profile
; keymapper can be = "xpadder", "joytokey" or "joy2key"
; this function returns FEProfile
;##################################################################
 RunKeymapper(keymapperLoad_Or_Unload,Keymapper) {
	Global blankProfile,defaultProfile,FEProfile,romProfile,emuProfile,xPadderSystemProfile,systemProfile,RocketLauncherProfile
	Global systemName,dbName,emuName,keymapperFrontEndProfileName,keymapperFrontEndProfile,contextOnExit
	Global CustomJoyNameArray
	Global keymapperFullPath 
	Global KeymapperRocketLauncherProfileEnabled, keymapperEnabled
	Static keymapperExists
	;Global keymapperLoad_Or_Unload
	Log("RunKeymapper - Started, using method """ . keymapperLoad_Or_Unload . """")
 	If ((KeymapperRocketLauncherProfileEnabled = "false") OR (keymapperEnabled = "false")) AND (keymapperLoad_Or_Unload = "menu")
		Return
 	joystickArray := GetJoystickArray()
	If keymapperFullPath {
		SplitPath, keymapperFullPath, keymapperExe, keymapperPath, keymapperExt ; splitting pathname into variables
		If !keymapperExists {
			If !FileExist(keymapperPath . "\" . keymapperExe) {
				Log("RunKeymapper - Could not locate your keymapper application here: """ . keymapperFullPath . """",2)
				Return
			} Else {
				Log("RunKeymapper - Found your keymapper application here: """ . keymapperFullPath . """",5)
				keymapperExists := 1
			}
		}
	} Else
		ScriptError("There was an error with getting your keymapperFullPath, please report this: """ . keymapperFullPath . """")
 	;define profiles to load and run keymappers
 	If (keymapper="xpadder")
	{	Log("RunKeymapper - Looping through controllers to find xpadder profiles for each one",5)
		Loop,16
		{	ControllerName := joystickArray[A_Index,1]
			If ControllerName
			{	Log("RunKeymapper - ID: " . A_Index . " Now searching for a matching profile for this controller: """ . ControllerName . """",5)
				If (keymapperLoad_Or_Unload = "load")
					Profile2Load := GetProfile(keymapper, romProfile . "|" . emuProfile . "|" . xPadderSystemProfile . "|" . defaultProfile . "|" . blankProfile, keymapperLoad_Or_Unload, ControllerName, Player_Number)
				Else If (keymapperLoad_Or_Unload = "unload")
					Profile2Load := GetProfile(keymapper, (If keymapperFrontEndProfile = "xpadder" && !contextOnExit ? FEProfile . "|"  : "") . blankProfile, keymapperLoad_Or_Unload, ControllerName, Player_Number)
				Else If (keymapperLoad_Or_Unload = "menu")
					Profile2Load := GetProfile(keymapper, RocketLauncherProfile . "|" . blankProfile, keymapperLoad_Or_Unload, ControllerName, Player_Number)
 				If !ProfilesInIdOrder
					ProfilesInIdOrder := Profile2Load 
				Else
					ProfilesInIdOrder .= "|" . Profile2Load	
			}
		}
		RunXpadder(keymapperPath,keymapperExe,ProfilesInIdOrder,joystickArray)
	} Else If (keymapper="joy2key") OR (keymapper = "joytokey")
	{	Log("RunKeymapper - Looping through controllers to find joytokey profiles for each one",5)
		If (keymapperLoad_Or_Unload = "load")
			Profile2Load := GetProfile(keymapper, romProfile . "\" . dbName . "|" . emuProfile . "\" . emuName . "|" . systemProfile . "\" . systemName . "|" . defaultProfile . "\_Default", keymapperLoad_Or_Unload)
		Else If (keymapperLoad_Or_Unload = "unload" && keymapperFrontEndProfile = "joytokey" && !contextOnExit)
			Profile2Load := GetProfile(keymapper, FEProfile . "\" . keymapperFrontEndProfileName, keymapperLoad_Or_Unload)
		Else If (keymapperLoad_Or_Unload = "unload" && keymapperFrontEndProfile != "joytokey" && !contextOnExit)
			Profile2Load :=	; user does not have joytokey set as their FE profile choice, keeping this blank will unload joytokey
		Else If (keymapperLoad_Or_Unload = "menu")
			Profile2Load := GetProfile(keymapper, RocketLauncherProfile . "\RocketLauncher", keymapperLoad_Or_Unload)
 		RunJoyToKey(keymapperPath,keymapperExe,Profile2Load)
	}	
	Log("RunKeymapper - Ended")
	Return FEProfile
}
 ;#########################
; GetProfile(ControllerName,keymapper, ProfilePrefixes [,PlayerNumber], keymapperLoad_Or_Unload)
; Only use FEProfile if you want to ignore rom and system profile
; PlayerNumber is there for possible use by other functions including this one
; keymapperLoad_Or_Unload can be load, unload, or menu. for error purposes
; ControllerName must not be empty (no error checks in function)
; keymapper needs to be a valid keymapper (no error checks in function)
; ProfilePrefixes separate prefixes with a "|"
; this function is menat only for use by the Load keymapper function.
;#########################
 GetProfile(keymapper, ProfilePrefixes, keymapperLoad_Or_Unload = "load",  ControllerName = "", ByRef PlayerNumber = 1) {
	Global CustomJoyNameArray, blankProfile, systemName, dbName, emuName, keymapperFrontEndProfileName, keymapperProfilePath
	Static ExtensionList := {xpadder: ".xpadderprofile",joy2key: ".cfg",joytokey: ".cfg"}	; static associative array that is holds what extension is for what keymapper.
	;keymapper: "keymapper profile extension". Adding name variations to this array should not slow down the script which means name variations can be accounted for.
	keymapperExtension := ExtensionList[keymapper]
	PlayerNumber := (If PlayerNumber = "" ? (1) : (PlayerNumber)) ; perform check for blank PlayerNumber
 	If (keymapperExtension = ".xpadderprofile") {
		PlayerIndicator := "\p" . PlayerNumber
 		CustomJoyName := CustomJoyNameArray[ControllerName]
		;If CustomJoyName Exists look for it. If not, don't look for an empty [].
		If CustomJoyName 
		{	LoopNumber := 3
			PossibleJoyNames1 := "\" . ControllerName
			PossibleJoyNames2 := "\" . CustomJoyName
			PossibleJoyNames3 := ""
		} Else {
			LoopNumber := 2
			PossibleJoyNames1 := "\" . ControllerName
			PossibleJoyNames2 := ""
		}
 	} Else {
		PlayerIndicator := "" ;joy2key does not need a player number since the numbers are stored in the cfg
 		;this is so we don't look for controller specific profiles
		LoopNumber := 1
		PossibleJoyNames1 := ""
	}
  	;start looking for profiles
	;profile prefixes for loading should look like %romProfile%|%emuProfile%|%systemProfile%|%defaultProfile%|%blankProfile%
	;profile prefixes for unloading should look like %FEProfile%|%blankProfile%
	Profile2Load := ""
	Log("GetProfile - Searching for these profiles (| delimited): " . ProfilePrefixes,5)
	Loop,Parse,ProfilePrefixes,|
	{	ProfileName := A_LoopField
		Loop, %LoopNumber%
		{	JoyName := PossibleJoyNames%A_Index%
			If (ProfileName = blankProfile) ;blankProfile is global variable. This check is here because blank profiles don't need player number.
			{	Profile := ProfileName . keymapperExtension
				Log("GetProfile - Searching -> " . Profile,5)
				If FileExist(Profile)
				{	Profile2Load := Profile
					Log("GetProfile - Loading Profile -> " . Profile2Load)
					PlayerNumber++
					Return Profile2Load
				}
				Break
			} Else {
				Profile := ProfileName . JoyName . PlayerIndicator . keymapperExtension
				Log("GetProfile - Searching for a Player " . PlayerNumber . " profile -> " . Profile,5)
				If FileExist(Profile)
				{	Profile2Load := Profile
					Log("GetProfile - Loading Player " . PlayerNumber . " Profile -> " . Profile2Load)
					PlayerNumber++
					Return Profile2Load
				}
			}
		}
	}
	If !Profile2Load
		If (keymapperLoad_Or_Unload = "load")
			Log("GetProfile - Keymapper support is enabled for """ . keymapper . """`, but could not find a """ . dbName . """`, """ . emuName . """`, """ . systemName . """`, default`, a """ . ControllerName . """ player " . PlayerNumber . " profile or a blank profile in """ . keymapperProfilePath . """ for controller """ . ControllerName . """",2)
		Else If (keymapperLoad_Or_Unload = "unload")
			Log("GetProfile - Keymapper support is enabled for """ . keymapper . """`, but could not find a " . keymapperFrontEndProfileName . " profile or a blank profile in " . keymapperProfilePath . " for controller " . ControllerName,2)
		Else If (keymapperLoad_Or_Unload = "menu")
			Log("GetProfile - Keymapper support is enabled for """ . keymapper . """`, but could not find a RocketLauncher profile or a blank profile in " . keymapperProfilePath . " for controller " . ControllerName,2)
}
 ;#########################
; GetJoystickArray()
; returns a 4 column by 17 row table.
; the row number is the same as the player number or id #. this is equivalent to port number + 1 
; so if your joystick is in port 0 or has an id of 1 it's name will be in JoyStickArray[1,1]
; column 1 contains the oem name, column 2 contains the mid and column 3 contains the pid, column 4 contains the guid
; Guid is a Global Universal ID that is assigned by the OS. It is 128 bits and randomly generated, It is the devices unique identifier while it is plugged in.
; row 0 column 1 contains the a pipedelimited list of the ids with connected controllers. (ex: 1|2|4) this means there is a joystick for id 1, 2 and 4.
; row 0 columns 2, 3, and 4 are empty. Future info may be added here.
;#########################
 GetJoystickArray() {
	Log("GetJoystickArray - Started")
	DllCall("winmm\joyConfigChanged", UInt, 0)
	Loop,16
	{
		port := A_Index - 1
		VarSetCapacity(joyState,512)
		NumPut(64,joyState,0,"UInt")
		joyError := DllCall("winmm\joyGetPosEx", "ptr", port, "ptr", &joyState)
		If joyError = 0
			joysDetected .= 1
		Else
			joysDetected .= 0
	}
	Log("GetJoystickArray - Joysticks Detected: " . joysDetected,5)
	joyArray := Object()
	Loop, 5
		joyArray[0,A_Index] := ""
	Loop, Parse, joysDetected
	{	CurrentController := A_Index
		currentJoyGUID := ""
		Mid := "", Pid := "", joyName := ""	; Erase values
		If (A_LoopField = 1)
		{	If joyArray[0,1]
				joyArray[0,1] := joyArray[0,1] . "|" . CurrentController 
			Else
				joyArray[0,1] := CurrentController
			VarSetCapacity(joybank,1024,0)
			i := 0
			port := CurrentController - 1
			Loop, 1024
			{	; Get driver information
				err := dllcall("winmm.dll\joyGetDevCapsA",Int,port,UInt,&joybank,UInt,i)
				i++
				; A successful dllcall returns a 0
				If (err = 0)
				{	; Converting decimal values to hex since windows uses the hex value more often
					offset := 0
					Loop, 2 
					{	SetFormat, IntegerFast, hex
						ret := NumGet(&joybank,offset,"UShort")
						ret .= ""
						SetFormat, IntegerFast, d
						; Remove the 0x we don't need it and padding it with 0's to have a width of four
						; Advice: leave these two lines out if using this function in other scripts
						StringTrimLeft,ret,ret,2
						ID%A_Index% := SubStr("0000" . ret,-3)
						offset := offset+2
					}
					Mid := ID1, Pid := ID2
				}
			}
			If !Mid && !Pid
				joyName := ""
			Else {
				regFolder := "VID_" . Mid . "&PID_" . Pid
				joyName := RegRead("HKEY_CURRENT_USER", "System\CurrentControlSet\Control\MediaProperties\PrivateProperties\Joystick\OEM\" . regFolder, "OEMName")
				If ErrorLevel
					joyName := RegRead("HKEY_LOCAL_MACHINE", "SYSTEM\CurrentControlSet\Control\MediaProperties\PrivateProperties\Joystick\OEM\" . regFolder, "OEMName")
			}
			currentJoyGUID := GetJoystickGUID(Mid,Pid,CurrentController)
			Log("GetJoystickArray - ID: " . CurrentController . " | Port: " . port . " | Name: " . joyName . " | MID: " . mid . " | PID: " . pid . " | GUID: " . currentJoyGUID,5)
		}
		joyName := Trim(joyName)	; Xpadder trims leading and trailing whitespace so we will do the same
		; Append empty string to avoid ahk's auto converting string type containing integers to integer type because we want the leading zeros
		joyArray[CurrentController,1] := joyName . ""
		joyArray[CurrentController,2] := Mid . ""
		joyArray[CurrentController,3] := Pid . ""
		joyArray[CurrentController,4] := currentJoyGUID . ""
		joyArray[CurrentController,5] := ""
	}
	Log("GetJoystickArray - Ended")
	Return joyArray
}
 ;#########################
; GetJoystickGUID(Mid,Pid,JoystickID)
; This function is used internally by the GetJoystickArray() function
; It returns the matching guid for a joystick device. Empty if error occurred.
; Mid = JoystickArray[JoystickID,2]
; PID = JoystickArray[JoystickID,3]
; JoystickID = 1 through 16
;#########################
 GetJoystickGUID(Mid,Pid,JoystickID) {
	If !Mid OR !PID OR !JoystickID
		Return
	If JoystickID not between 1 and 16
		Return
 	Log("GetJoystickGUID - Started")
	SetFormat, IntegerFast, hex
	REG_JOY_ID := JoystickID - 1
	REG_JOY_ID .= "000000"
	StringReplace, REG_JOY_ID , REG_JOY_ID, x
	SetFormat, IntegerFast, d
 	If A_OSVersion in WIN_2003,WIN_XP,WIN_2000,WIN_NT4,WIN_95,WIN_98,WIN_ME
		RootKey := "HKEY_LOCAL_MACHINE"
	Else
		RootKey := "HKEY_CURRENT_USER"
 	Loop, %RootKey%, System\CurrentControlSet\Control\MediaProperties\PrivateProperties\DirectInput\VID_%Mid%&PID_%Pid%\Calibration,1,1
	{
		If (A_LoopRegName = "Joystick Id") {
			RegRead, regvar
			If (regvar = REG_JOY_ID) {
				RegSubKey := A_LoopRegSubKey
				Break
			}
		}
	}
	GUID := RegRead(RootKey, RegSubKey, "GUID")
	Log("GetJoystickGUID - Ended and found GUID: " . GUID)
	Return GUID
}
 ;#########################
; ChangeJoystickID(Mid,Pid,GUID,NewJoystickID)
; This is an awesome little function that changes the joystick id.
; It gives us more control over what devices are moved than JoyIDs.exe ever did.
; It returns 0 if successful, 1 if unsuccessful.
; Mid = JoystickArray[JoystickID,2]
; PID = JoystickArray[JoystickID,3]
; GUID = JoystickArray[JoystickID,4]
; NewJoystickID = 1 through 16, this is the new ID for the joystick with the matching MID,PID,GUID
; it has no way of checking to make sure it's not assigning the same id as an already active controller,
; so this check must be done outside the function.
;#########################
 ChangeJoystickID(Mid,Pid,GUID,NewJoystickID) {
	Log("ChangeJoystickID - Started")
	If !Mid OR !Pid OR !GUID OR !NewJoystickID
		Return 1
	If NewJoystickID not between 1 and 16
		Return 1
 	SetFormat, IntegerFast, hex
	NewJoystickID := NewJoystickID - 1
	NewJoystickID .= "000000"
	StringReplace, NewJoystickID , NewJoystickID, x
	SetFormat, IntegerFast, d
 	If A_OSVersion in WIN_2003,WIN_XP,WIN_2000,WIN_NT4,WIN_95,WIN_98,WIN_ME
		RootKey := "HKEY_LOCAL_MACHINE"
	Else
		RootKey := "HKEY_CURRENT_USER"
 	Loop, %RootKey%, System\CurrentControlSet\Control\MediaProperties\PrivateProperties\DirectInput\VID_%Mid%&PID_%Pid%\Calibration,1,1
	{
		If (A_LoopRegName = "GUID") {
			RegRead, regvar
			If (regvar = GUID) {
				RegSubKey := A_LoopRegSubKey
				break
			}
		}
	}
	jid := RegRead(RootKey, RegSubKey, "Joystick Id")
	RegWrite("REG_BINARY", RootKey, RegSubKey, "Joystick Id", NewJoystickID)
	Log("ChangeJoystickID - Swapping Joystick ID: " . jid . " to the New Joystick ID: " . NewJoystickID . ", for the Joystick VID_" . Mid . "&PID_" . Pid . "&GUID_" . GUID,5)
	Log("ChangeJoystickID - Ended")
	Return ErrorLevel
}
 RunXpadder(keymapperPath,keymapperExe,ProfilesInIdOrder,joystickArray) {
	Global joyToKeyFullPath
	Log("RunXpadder - Started")
 	; Closing joytokey to avoid dual keymapper conflict.
	SplitPath, joyToKeyFullPath, joyToKeyExe, joyToKeyPath
	errLvl := Process("Exist", joyToKeyExe)
	If errLvl
		Process("Close", joyToKeyExe)
 	; Close xpadder to refresh controllers
	Log("RunXpadder - Closing xpadder to refresh controllers seen by xpadder",5)
	Run(keymapperExe . " /C", keymapperPath,,,,1)	; enabling bypassCmdWindow
 	StringSplit,Profiles,ProfilesInIdOrder,|
	Log("RunXpadder - Creating an array of connected controllers and profiles to arrange according to the order found in " . keymapperPath . "\xpadder.ini",5)
	XpadderArray := []
	ProfileCount := 0
	Loop,16
	{	ControllerName := joystickArray[A_Index,1]
		MID := joystickArray[A_Index,2]
		PID := joystickArray[A_Index,3]
		; Check to see if controller name has been previously been found
		String := XpadderArray[ControllerName]	
		StringSplit,SplitArray,String,|
		If SplitArray0
		{	ProfileCount++
			Profile2Load := Profiles%ProfileCount%
			; Store ID numbers that are compatible xpadder in SplitArray1
			; Append the newly found profile2load with the previously found profiles associated with this controller separated with a ? to be later replaced with " "
			XpadderArray[ControllerName] := SplitArray1 . "|" . SplitArray2 . "?" . Profile2Load
		} Else If ControllerName
		{	ProfileCount++
			Profile2Load := Profiles%ProfileCount%
 			; Convert hexadecimal Mid and Pid values into a format compatible with xpadder's xpadder.ini
			ID1:=SubStr(Mid,1,2),ID2:=SubStr(Mid,3,2),ID3:=SubStr(Pid,1,2),ID4:=SubStr(Pid,3,2)
			Loop,4
			{	ID%A_Index% := "0x" . ID%A_Index%
				ID%A_Index% += 0
			}
			ControllerID := ID1 . "`," . ID2 . "`," . ID3 . "`," . ID4
			Value := ControllerID . "|" . Profile2Load
			XpadderArray.Insert(ControllerName,Value)
		}
	}
	errLvl := Process("WaitClose", keymapperExe, 2)		;wait for xpadder to finish writing its values to xpadder.ini before reading and editing it
	If errLvl
		Process("Close", keymapperExe)
	Log("RunXpadder - Reading the order in " . keymapperPath . "\xpadder.ini and arranging profiles found to match that order",5)
	Loop {
		; Get profiles in order as appears in xpadder.ini
		LoopIndex := A_Index ;record number in case we need to add a new key to xpadder.
		IniControllerName := IniRead(keymapperPath . "\Xpadder.ini", "Controllers", "Controller" . LoopIndex . "Name")
		If (IniControllerName = "ERROR") { ;this means there are no more controllers to be found in the ini
			Log("RunXpadder - No more controllers to be found",5)
			Break
		}
		; Look to see if the controller found in the ini is already in our array
		XpadderArrayValue := XpadderArray[IniControllerName]
		If XpadderArrayValue
		{	StringSplit,SplitArray,XpadderArrayValue,|
			; Make sure controller is not hidden. if it is one xpadder does not recognize controller and the profile loading is messed up.
			IniWrite(0, keymapperPath . "\Xpadder.ini", "Controllers", "Controller" . LoopIndex . "Hidden")
			; This is for later use
			If !IniControllersFound
				IniControllersFound := IniControllerName
			Else
				IniControllersFound .= "," . IniControllerName
			; Start creating the string of profiles to send to xpadder
			If !ProfilesInXpadderOrder
				ProfilesInXpadderOrder := SplitArray2
			Else
				ProfilesInXpadderOrder .= """ """ . SplitArray2
			; Because we looped and looked up profiles in the array in the order of the ini, they will be in order when sent to xpadder
		}
	}
	For key, XpadderArrayValue in XpadderArray
	{
		If !RegExMatch(key,"i)" . IniControllersFound)
		{	Log("RunXpadder - Could not find " . key . " in xpadder.ini. Writing the new controller to xpadder.ini",5)
			StringSplit,SplitArray,XpadderArrayValue,|
			; Write new key values for the controllers not found in xpadder.ini to xpadder so it sees them when it restarts.
			IniWrite(key, keymapperPath . "\Xpadder.ini", "Controllers", "Controller" . LoopIndex . "Name")
			IniWrite(SplitArray1, keymapperPath . "\Xpadder.ini", "Controllers", "Controller" . LoopIndex . "ID")
			IniWrite(0, keymapperPath . "\Xpadder.ini", "Controllers", "Controller" . LoopIndex . "Hidden")
 			; Look for matching xpaddercontroller file in xpadder.exe root directory
			CustomJoyName := CustomJoyNameArray[key]
			; Profiles can be named after CustomJoyName or controller name. Oem Name takes priority.
			If (FileExist(keymapperPath . key . ".xpaddercontroller")) {
				Log("RunXpadder - Loading " . keymapperPath . "\" . key  ".xpaddercontroller layout for the new controller",5)
				IniWrite(key . ".xpaddercontroller", keymapperPath . "\Xpadder.ini", "Controllers", "Controller" . LoopIndex . "File")
			} Else If (CustomJoyName AND FileExist(keymapperPath . CustomJoyName . ".xpaddercontroller")) {
				Log("RunXpadder - Loading " . keymapperPath . "\" . CustomJoyName  ".xpaddercontroller layout for the new controller",5)
				IniWrite(CustomJoyName . ".xpaddercontroller", keymapperPath . "\Xpadder.ini", "Controllers", "Controller" . LoopIndex . "File")
			} Else {
				; This means a xpaddercontroller profile has not been found
				ScriptError("Please create a xpaddercontroller profile named either " . key . " or " . CustomJoyName . ". It also needs to be in the same folder as xpadder.exe")
			}
			Loop, 4
				IniWrite(A_Space, keymapperPath . "\Xpadder.ini", "Controllers", "Controller" . LoopIndex . "Recent" . A_Index)
			LoopIndex++
			If !ProfilesInXpadderOrder
				ProfilesInXpadderOrder := SplitArray2
			Else
				ProfilesInXpadderOrder .= """ """ . SplitArray2
		}
	}
	StringReplace, ProfilesInXpadderOrder, ProfilesInXpadderOrder, ?, " ", All
	If ProfilesInXpadderOrder
		Run(keymapperExe . " """ . ProfilesInXpadderOrder . """ /M", keymapperPath, "Hide",,,1)	; enabling bypassCmdWindow)
	Else
		Log("RunXpadder - No profiles found and nothing to tell Xpadder to load",2)
	Log("RunXpadder - Ended")
}	
 RunJoyToKey(keymapperPath,keymapperExe,Profile="") {
	Global xpadderFullPath
	Log("RunJoyToKey - Started")
	; Closing xpadder to avoid dual keymapper conflict.
	If FileExist(xpadderFullPath) {
		SplitPath, xpadderFullPath, xpadderexe, xpadderdir
		errLvl := Process("Exist", xpadderexe)
		If errLvl
		{	Log("RunJoyToKey - Closing xpadder to avoid dual keymapper conflict",2)
			Run(xpadderexe . " /C", xpadderdir,,,,1)	; enabling bypassCmdWindow)
			errLvl := Process("Exist", xpadderexe)
			If errLvl
				Process("Close", xpadderexe)
		}
	}
 	exitMeansMinimize := IniRead(keymapperPath . "\JoyToKey.ini", "LastStatus", "ExitMeansMinimize")
	If (exitMeansMinimize = "ERROR")
		ScriptError("You are using KeyMapper support but are not up-to-date with JoyToKey or cannot find JoyToKey.ini in " . keymapperPath . "`nPlease make sure you are running JoyToKey v5.1.0 or later",10)
	Else If ( exitMeansMinimize = 1 ) {
		Process("Close", keymapperExe)
		Process("WaitClose", keymapperExe)
		IniWrite(0, keymapperPath . "\JoyToKey.ini", "LastStatus", "ExitMeansMinimize")
	}
	DetectHiddenWindows, On
	WinClose("JoyToKey ahk_class TMainForm")
 	errLvl := Process("WaitClose", keymapperExe, 2)
	If errLvl
		Process("Close", keymapperExe)
	; RocketLauncherUI may turn off joytokey from starting minimized, let's set it just in case
	startMinimized := IniRead(keymapperPath . "\JoyToKey.ini", "LastStatus", "StartIconified")
	If startMinimized != 1
		IniWrite(1, keymapperPath . "\JoyToKey.ini", "LastStatus", "StartIconified")
	; Finally we start the keymapper with the cfg profile we found
	If Profile
		Run(keymapperExe . " """ . Profile . """", keymapperPath,,,,1)	; enabling bypassCmdWindow)
	Log("RunJoyToKey - Ended")
}
 Keymapper_PauseProfileList(ControllerName,PlayerNumber,keymapper) {
	; [file name (no extension), type (options are default,system,emulator,game),0 or 1 (1 if controller specific), full path to file]
	Global blankProfile,defaultProfile,romProfile,emuProfile,xPadderSystemProfile,systemProfile
	Global systemName,dbName,emuName ;for use with joytokey
	Global CustomJoyNameArray ;for use with xpadder
	Log("Keymapper_PauseProfileList - Started")
 	If (keymapper = "xpadder")
	{	keymapperExtension = .xpadderprofile
		sProfile := xPadderSystemProfile
		PlayerIndicator := "\p" . PlayerNumber
		CustomJoyName := CustomJoyNameArray[ControllerName]
		If CustomJoyName 
		{	LoopNumber := 3
			PossibleJoyNames1 := "\" . ControllerName
			PossibleJoyNames2 := "\" . CustomJoyName
			PossibleJoyNames3 := ""
		} Else {
			LoopNumber := 2
			PossibleJoyNames1 := "\" . ControllerName
			PossibleJoyNames2 := ""
		}
	} Else {	; keymapper = joy2key
		keymapperExtension := ".cfg"
		sProfile := systemProfile
		LoopNumber := 1
		PossibleJoyNames1 := "" ;joy2key does not use a profile per controller
		PlayerIndicator := "" ;joy2key and ahk do not need a player number
	}
 	; used for finding the normally loaded profile
	normalProfileFound := 0
 	; loop counters
	i := 1
	j := 0
 	ProfileList := []
	ProfileFolderArray := ["Game","Emulator","System","Default"]
	If (keymapper = "xpadder")
		String2Parse := romProfile . "|" . emuProfile . "|" . sProfile . "|" . defaultProfile
	Else {	;joytokey 
		String2Parse := romProfile . "|" . emuProfile . "|" . sProfile . "|" . defaultProfile
		normProfileName := [dbName,emuName,systemName,"_Default"]
	}
	Log(String2Parse)
	Loop,Parse,String2Parse,|
	{	j++
		FolderPath := A_LoopField
		;If CustomJoyName Exists look for it. If not, don't look for a \\ directory
		Loop % LoopNumber
		{	
			joyName := PossibleJoyNames%A_Index%
			If joyName
				Controller_Specific_Boolean := 1
			Else
				Controller_Specific_Boolean := 0
 			If (keymapper = "xpadder") {
				normProfile := FolderPath . joyName . PlayerIndicator . keymapperExtension
				FilePattern := FolderPath . joyName . "\*" . keymapperExtension
			} Else {	; keymapper = joy2key
				normProfile := FolderPath . "\" . normProfileName[j] . keymapperExtension
				FilePattern := FolderPath . "\*" . keymapperExtension
			}
			Loop % FilePattern
			{	
				SplitPath,A_LoopFileFullPath,,,,FileNameNoExt
 				If (keymapper = "joytokey") OR (keymapper = "joy2key") {
					; I find this information to be more useful because it determines if a profile will actually work if you use joytokey.
					; the boolean value means profile will work, but due to joy2key limitations we don't know if the profile was made for this controller
					SectionName := "Joystick " . PlayerNumber
					CheckForSection := IniRead(A_LoopFileFullPath, "SectionName", "Axis1p")	; this key will always exist if the section exists and was properly created by joytokey
					If CheckForSection
						Controller_Specific_Boolean := 1
					Else
						Controller_Specific_Boolean := 0
				}
 				If (normProfile = A_LoopFileFullPath) && !normalProfileFound 
				{	normalProfileFound := 1
					Log("Keymapper_PauseProfileList - Creating Profile List (normal load profile) -> 1`," . FileNameNoExt . "`," . ProfileFolderArray[j] . "`," . Controller_Specific_Boolean . "`," . A_LoopFileFullPath,5)
					ProfileList[1,1] := FileNameNoExt
					ProfileList[1,2] := ProfileFolderArray[j]
					ProfileList[1,3] := Controller_Specific_Boolean
					ProfileList[1,4] := A_LoopFileFullPath
				} Else If A_LoopFileFullPath
				{	i++
					Log("Keymapper_PauseProfileList - Creating Profile List -> " . i . "`," . FileNameNoExt . "`," . ProfileFolderArray[j] . "`," . Controller_Specific_Boolean . "`," . A_LoopFileFullPath,5)
					ProfileList[0,1] := i
					ProfileList[i,1] := FileNameNoExt
					ProfileList[i,2] := ProfileFolderArray[j]
					ProfileList[i,3] := Controller_Specific_Boolean
					ProfileList[i,4] := A_LoopFileFullPath
				}
			}
		}
	}
	Log("Keymapper_PauseProfileList - Ended")
	Return ProfileList
}

Comments