├── Screenshot.png
├── HookDLL
├── stdafx.h
├── dllmain.cpp
├── stdafx.cpp
├── Exports.def
├── ControllerManager.h
├── DirectInput.h
├── Controller.h
├── HookDLL.vcxproj.filters
├── Exports.h
├── DIBinding.h
├── ControllerManager.cpp
├── DirectInput.cpp
├── Controller.cpp
└── HookDLL.vcxproj
├── di2xinput
├── Resources
│ └── Xbox_Controller.png
├── App.config
├── packages.config
├── Properties
│ ├── Settings.settings
│ ├── Settings.Designer.cs
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ ├── app.manifest
│ └── Resources.resx
├── app.manifest
├── Program.cs
├── XIManager.cs
├── Mapping.cs
├── ProfileManager.cs
├── InputDialog.Designer.cs
├── InputDialog.cs
├── ProgramManager.cs
├── WinAPI.cs
├── DIManager.cs
├── InputDialog.resx
├── MainForm.resx
├── di2xinput.csproj
├── MainForm.cs
└── MainForm.Designer.cs
├── README.md
├── .gitattributes
├── di2xinput.sln
└── .gitignore
/Screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/acceleration3/di2xinput/HEAD/Screenshot.png
--------------------------------------------------------------------------------
/HookDLL/stdafx.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/acceleration3/di2xinput/HEAD/HookDLL/stdafx.h
--------------------------------------------------------------------------------
/HookDLL/dllmain.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/acceleration3/di2xinput/HEAD/HookDLL/dllmain.cpp
--------------------------------------------------------------------------------
/HookDLL/stdafx.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/acceleration3/di2xinput/HEAD/HookDLL/stdafx.cpp
--------------------------------------------------------------------------------
/di2xinput/Resources/Xbox_Controller.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/acceleration3/di2xinput/HEAD/di2xinput/Resources/Xbox_Controller.png
--------------------------------------------------------------------------------
/di2xinput/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/di2xinput/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/di2xinput/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/di2xinput/app.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/HookDLL/Exports.def:
--------------------------------------------------------------------------------
1 | LIBRARY StubDLL
2 | EXPORTS
3 | XInputEnable = Export_XInputEnable @5
4 | XInputGetAudioDeviceIds = Export_XInputGetAudioDeviceIds @10
5 | XInputGetDSoundAudioDeviceGuids = Export_XInputGetDSoundAudioDeviceGuids @6
6 | XInputGetBatteryInformation = Export_XInputGetBatteryInformation @7
7 | XInputGetCapabilities = Export_XInputGetCapabilities @4
8 | XInputGetKeystroke = Export_XInputGetKeystroke @8
9 | XInputGetState = Export_XInputGetState @2
10 | XInputSetState = Export_XInputSetState @3
11 | XInputGetStateEx = Export_XInputGetStateEx @100
--------------------------------------------------------------------------------
/HookDLL/ControllerManager.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Controller.h"
4 |
5 | #define MAX_CONTROLLERS 4
6 |
7 | class ControllerManager
8 | {
9 | public:
10 | static void Init();
11 | static bool IsConnected(DWORD controllerIndex);
12 | static DWORD GetState(DWORD controllerIndex, XINPUT_STATE* pState);
13 | static DWORD GetCapabilities(DWORD controllerIndex, DWORD dwFlags, XINPUT_CAPABILITIES* pCapabilities);
14 |
15 | private:
16 | static std::vector> controllers;
17 | static std::mutex stateLock;
18 |
19 | static bool PollGamepad(int index, XINPUT_GAMEPAD* gamepad);
20 | };
21 |
22 |
--------------------------------------------------------------------------------
/di2xinput/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Management;
7 | using System.Threading;
8 | using System.Windows.Forms;
9 | using System.Xml.Serialization;
10 |
11 | namespace di2xinput
12 | {
13 | public static class Program
14 | {
15 |
16 | ///
17 | /// The main entry point for the application.
18 | ///
19 | [STAThread]
20 | static void Main()
21 | {
22 | DIManager.Init();
23 | Application.EnableVisualStyles();
24 | Application.SetCompatibleTextRenderingDefault(false);
25 | Application.Run(new MainForm());
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/HookDLL/DirectInput.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | class DirectInput
4 | {
5 | private:
6 | static LPDIRECTINPUT8 directInput;
7 | static std::vector> devices;
8 | static HWND dummyWindow;
9 | static LPDIRECTINPUTDEVICE8 currentDevice;
10 | static std::string GUIDToString(const uint64_t& data1, const uint16_t& data2, const uint16_t& data3, const unsigned char* data4);
11 |
12 | public:
13 |
14 | static LPDIRECTINPUT8 GetInstance() { return directInput; };
15 | static bool Init();
16 | static void RefreshDeviceList();
17 | static LPDIRECTINPUTDEVICE8 FindDevice(std::string productGUID, std::string instanceGUID);
18 | static bool InitializeDevice(LPDIRECTINPUTDEVICE8 device);
19 |
20 | static BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE* instance, VOID* context);
21 | static BOOL CALLBACK EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* pContext);
22 |
23 | };
24 |
25 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DI2XInput - A DirectInput to XInput converter
2 |
3 | 
4 |
5 | ## What is it?
6 | This tool is designed to convert DirectInput controller commands or keyboard inputs to XInput counterparts. The main uses for it are for making XInput controller games compatible with other controllers that use DirectInput as well as allowing games that originally don't support a mix of keyboard and controllers to do so by making the keyboard work as an additional controller instead.
7 |
8 | ## Features:
9 | - Uses a per-game configuration basis so different input configurations can be used for different games.
10 | - Different devices can be configured for different players including keyboard inputs.
11 | - All configurations can be changed within the program itself without the need for multiple copies of the program.
12 |
13 | ## Download:
14 | [Binaries/Source code](https://github.com/acceleration3/di2xinput/releases)
15 |
--------------------------------------------------------------------------------
/HookDLL/Controller.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include "DIBinding.h"
5 |
6 | class Controller
7 | {
8 |
9 | public:
10 |
11 | typedef enum
12 | {
13 | NONE,
14 | KEYBOARD,
15 | GAMEPAD
16 | } DEVICE_TYPE;
17 |
18 | Controller();
19 | ~Controller() = default;
20 |
21 | void AssignDIDevice(const std::string& instanceGUID, const std::string& productGUID, DEVICE_TYPE type, const std::vector& mappings);
22 | bool IsConnected();
23 | HRESULT Acquire();
24 | HRESULT Unacquire();
25 |
26 | XINPUT_GAMEPAD GetState();
27 | DEVICE_TYPE GetType() { return type; };
28 |
29 | private:
30 |
31 | typedef struct
32 | {
33 | int negativeX;
34 | int positiveX;
35 | int negativeY;
36 | int positiveY;
37 | } ANALOG_SUBVALUES;
38 |
39 | std::array, 24> bindings;
40 | std::string instanceGUID;
41 | std::string productGUID;
42 | XINPUT_GAMEPAD gamepad;
43 | DEVICE_TYPE type;
44 | LPDIRECTINPUTDEVICE8 DIDevice;
45 | XINPUT_GAMEPAD lastState;
46 |
47 | static std::vector buttonFlags;
48 | };
49 |
50 |
--------------------------------------------------------------------------------
/di2xinput/XIManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace di2xinput
8 | {
9 | static class XIManager
10 | {
11 | public static List xinputButtonNames = new List()
12 | {
13 | "DPad Up",
14 | "DPad Down",
15 | "DPad Left",
16 | "DPad Right",
17 | "Start",
18 | "Back",
19 | "Left Thumb",
20 | "Right Thumb",
21 | "Left Shoulder",
22 | "Right Shoulder",
23 | "A",
24 | "B",
25 | "X",
26 | "Y",
27 | "Left Trigger",
28 | "Right Trigger",
29 | "Left Stick Up", // 16
30 | "Left Stick Down",
31 | "Left Stick Left",
32 | "Left Stick Right",
33 | "Right Stick Up",
34 | "Right Stick Down",
35 | "Right Stick Left",
36 | "Right Stick Right"
37 | };
38 |
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/di2xinput/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace di2xinput.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.7.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/di2xinput/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("di2xinput")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("di2xinput")]
13 | [assembly: AssemblyCopyright("Copyright © 2018")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("bea07272-27ce-44ac-b2b1-1e47e6436d19")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/HookDLL/HookDLL.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Header Files
20 |
21 |
22 | Header Files
23 |
24 |
25 | Header Files
26 |
27 |
28 | Header Files
29 |
30 |
31 | Header Files
32 |
33 |
34 | Header Files
35 |
36 |
37 |
38 |
39 | Source Files
40 |
41 |
42 | Source Files
43 |
44 |
45 | Source Files
46 |
47 |
48 | Source Files
49 |
50 |
51 | Source Files
52 |
53 |
54 |
55 |
56 | Source Files
57 |
58 |
59 |
--------------------------------------------------------------------------------
/HookDLL/Exports.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "stdafx.h"
4 | #include "ControllerManager.h"
5 |
6 | void WINAPI Export_XInputEnable(BOOL enable)
7 | {
8 | std::cout << "XInputEnable." << std::endl;
9 | }
10 |
11 | DWORD WINAPI Export_XInputGetAudioDeviceIds(DWORD dwUserIndex, LPWSTR pRenderDeviceId, UINT* pRenderCount, LPWSTR pCaptureDeviceId, UINT* pCaptureCount)
12 | {
13 | std::cout << "XInputGetAudioDeviceIds." << std::endl;
14 | return 0;
15 | }
16 |
17 | DWORD WINAPI Export_XInputGetDSoundAudioDeviceGuids(DWORD dwUserIndex, GUID* pDSoundRenderGuid, GUID* pDSoundCaptureGuid)
18 | {
19 | std::cout << "XInputGetDSoundAudioDeviceGuids." << std::endl;
20 | return 0;
21 | }
22 |
23 | DWORD WINAPI Export_XInputGetBatteryInformation(DWORD dwUserIndex, BYTE devType, XINPUT_BATTERY_INFORMATION* pBatteryInformation)
24 | {
25 | std::cout << "XInputGetBatteryInformation." << std::endl;
26 |
27 | if (devType == BATTERY_DEVTYPE_GAMEPAD && !ControllerManager::IsConnected(dwUserIndex))
28 | return ERROR_DEVICE_NOT_CONNECTED;
29 |
30 | pBatteryInformation->BatteryLevel = BATTERY_LEVEL_FULL;
31 | pBatteryInformation->BatteryType = BATTERY_TYPE_WIRED;
32 |
33 | return 0;
34 | }
35 |
36 | DWORD WINAPI Export_XInputGetKeystroke(DWORD dwUserIndex, DWORD dwReserved, PXINPUT_KEYSTROKE pKeystroke)
37 | {
38 | std::cout << "XInputGetKeystroke." << std::endl;
39 | return 0;
40 | }
41 |
42 | DWORD WINAPI Export_XInputGetState(DWORD dwUserIndex, XINPUT_STATE* pState)
43 | {
44 | if (!ControllerManager::IsConnected(dwUserIndex))
45 | return ERROR_DEVICE_NOT_CONNECTED;
46 |
47 | return ControllerManager::GetState(dwUserIndex, pState);
48 | }
49 |
50 | DWORD WINAPI Export_XInputGetStateEx(DWORD dwUserIndex, XINPUT_STATE* pState)
51 | {
52 | std::cout << "XInputGetStateEx." << std::endl;
53 | return ControllerManager::GetState(dwUserIndex, pState);
54 | }
55 |
56 | DWORD WINAPI Export_XInputSetState(DWORD dwUserIndex, XINPUT_VIBRATION* pVibration)
57 | {
58 | if (!ControllerManager::IsConnected(dwUserIndex))
59 | return ERROR_DEVICE_NOT_CONNECTED;
60 |
61 | return ERROR_SUCCESS;
62 | }
63 |
64 | DWORD WINAPI Export_XInputGetCapabilities(DWORD dwUserIndex, DWORD dwFlags, XINPUT_CAPABILITIES* pCapabilities)
65 | {
66 | if (!ControllerManager::IsConnected(dwUserIndex))
67 | return ERROR_DEVICE_NOT_CONNECTED;
68 |
69 | return ControllerManager::GetCapabilities(dwUserIndex, dwFlags, pCapabilities);
70 | }
--------------------------------------------------------------------------------
/di2xinput/Mapping.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Linq;
5 | using System.Runtime.InteropServices;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 | using System.Xml.Serialization;
9 |
10 | namespace di2xinput
11 | {
12 | public static class Mapping
13 | {
14 | public enum MappedDeviceType : byte
15 | {
16 | None,
17 | Keyboard,
18 | Controller
19 | }
20 |
21 | [Serializable]
22 | public class ControllerConfig
23 | {
24 | [XmlElement("Type")]
25 | public MappedDeviceType deviceType;
26 | [XmlElement("InstanceGUID")]
27 | public string instanceGUID;
28 | [XmlElement("ProductGUID")]
29 | public string productGUID;
30 | [XmlElement("ButtonMapping")]
31 | public ushort[] mapping;
32 |
33 | public ControllerConfig()
34 | {
35 | mapping = new ushort[24];
36 | deviceType = MappedDeviceType.None;
37 | instanceGUID = Guid.Empty.ToString();
38 | productGUID = Guid.Empty.ToString();
39 | }
40 |
41 | public byte[] ToByteArray()
42 | {
43 | List byteArray = new List();
44 |
45 | byteArray.Add((byte)deviceType);
46 | byteArray.AddRange(BitConverter.GetBytes(instanceGUID.Length));
47 | byteArray.AddRange(Encoding.ASCII.GetBytes(instanceGUID));
48 | byteArray.AddRange(BitConverter.GetBytes(productGUID.Length));
49 | byteArray.AddRange(Encoding.ASCII.GetBytes(productGUID));
50 |
51 | for (int i = 0; i < mapping.Length; i++)
52 | byteArray.AddRange(BitConverter.GetBytes(mapping[i]));
53 |
54 | return byteArray.ToArray();
55 | }
56 |
57 | public void ChangeDeviceType(MappedDeviceType devicetype)
58 | {
59 | deviceType = devicetype;
60 |
61 | for (int i = 0; i < mapping.Length; i++)
62 | mapping[i] = 0;
63 | }
64 | }
65 |
66 | public static string GetNameFromScancode(ushort scancode)
67 | {
68 | StringBuilder keyName = new StringBuilder(256);
69 | WinAPI.GetKeyNameText((uint)(scancode << 16), keyName, 256);
70 | return keyName.ToString();
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/di2xinput/ProfileManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 | using System.Xml;
9 | using System.Xml.Serialization;
10 |
11 | namespace di2xinput
12 | {
13 | public class ProfileManager
14 | {
15 | [Serializable]
16 | [XmlRoot("Profile")]
17 | public class Profile
18 | {
19 | [XmlArray("Controllers")]
20 | public Mapping.ControllerConfig[] controllers = new Mapping.ControllerConfig[4]
21 | {
22 | new Mapping.ControllerConfig(),
23 | new Mapping.ControllerConfig(),
24 | new Mapping.ControllerConfig(),
25 | new Mapping.ControllerConfig()
26 | };
27 | }
28 |
29 | const string profileFolder = "./profiles/";
30 |
31 | public static List> profiles = new List>();
32 | public static Profile activeProfile;
33 |
34 | public static void SaveCurrentProfile(string profileName)
35 | {
36 | if (!Directory.Exists(profileFolder))
37 | Directory.CreateDirectory(profileFolder);
38 |
39 | XmlSerializer xmlSerializer = new XmlSerializer(typeof(Profile));
40 |
41 | using (var stream = File.Create(profileFolder + profileName + ".xml"))
42 | {
43 | xmlSerializer.Serialize(stream, activeProfile);
44 | }
45 | }
46 |
47 | public static void ReloadProfiles()
48 | {
49 | if(!Directory.Exists(profileFolder))
50 | Directory.CreateDirectory(profileFolder);
51 |
52 | profiles.Clear();
53 |
54 | XmlSerializer xmlSerializer = new XmlSerializer(typeof(Profile));
55 |
56 | foreach (string fileName in Directory.EnumerateFiles(profileFolder, "*.xml"))
57 | {
58 | using (FileStream fileStream = new FileStream(fileName, FileMode.Open))
59 | {
60 | int slashIndex = fileName.LastIndexOf('/') + 1;
61 | int extensionIndex = fileName.LastIndexOf('.');
62 | string profileName = fileName.Substring(slashIndex, (fileName.Length - slashIndex) - (fileName.Length - extensionIndex));
63 |
64 | Profile newProfile = (Profile)xmlSerializer.Deserialize(fileStream);
65 |
66 | profiles.Add(new KeyValuePair(profileName, newProfile));
67 | }
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/di2xinput.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.27703.2042
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "di2xinput", "di2xinput\di2xinput.csproj", "{BEA07272-27CE-44AC-B2B1-1E47E6436D19}"
7 | EndProject
8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StubDLL", "HookDLL\HookDLL.vcxproj", "{24569797-2891-48A2-84F6-DD9E343BF0F8}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Debug|x64 = Debug|x64
14 | Debug|x86 = Debug|x86
15 | Release|Any CPU = Release|Any CPU
16 | Release|x64 = Release|x64
17 | Release|x86 = Release|x86
18 | EndGlobalSection
19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
20 | {BEA07272-27CE-44AC-B2B1-1E47E6436D19}.Debug|Any CPU.ActiveCfg = Debug|x64
21 | {BEA07272-27CE-44AC-B2B1-1E47E6436D19}.Debug|Any CPU.Build.0 = Debug|x64
22 | {BEA07272-27CE-44AC-B2B1-1E47E6436D19}.Debug|x64.ActiveCfg = Debug|x64
23 | {BEA07272-27CE-44AC-B2B1-1E47E6436D19}.Debug|x64.Build.0 = Debug|x64
24 | {BEA07272-27CE-44AC-B2B1-1E47E6436D19}.Debug|x86.ActiveCfg = Debug|Any CPU
25 | {BEA07272-27CE-44AC-B2B1-1E47E6436D19}.Debug|x86.Build.0 = Debug|Any CPU
26 | {BEA07272-27CE-44AC-B2B1-1E47E6436D19}.Release|Any CPU.ActiveCfg = Release|x64
27 | {BEA07272-27CE-44AC-B2B1-1E47E6436D19}.Release|Any CPU.Build.0 = Release|x64
28 | {BEA07272-27CE-44AC-B2B1-1E47E6436D19}.Release|x64.ActiveCfg = Release|x64
29 | {BEA07272-27CE-44AC-B2B1-1E47E6436D19}.Release|x64.Build.0 = Release|x64
30 | {BEA07272-27CE-44AC-B2B1-1E47E6436D19}.Release|x86.ActiveCfg = Debug|Any CPU
31 | {BEA07272-27CE-44AC-B2B1-1E47E6436D19}.Release|x86.Build.0 = Debug|Any CPU
32 | {24569797-2891-48A2-84F6-DD9E343BF0F8}.Debug|Any CPU.ActiveCfg = Debug|Win32
33 | {24569797-2891-48A2-84F6-DD9E343BF0F8}.Debug|Any CPU.Build.0 = Debug|Win32
34 | {24569797-2891-48A2-84F6-DD9E343BF0F8}.Debug|x64.ActiveCfg = Debug|Win32
35 | {24569797-2891-48A2-84F6-DD9E343BF0F8}.Debug|x64.Build.0 = Debug|Win32
36 | {24569797-2891-48A2-84F6-DD9E343BF0F8}.Debug|x86.ActiveCfg = Debug|Win32
37 | {24569797-2891-48A2-84F6-DD9E343BF0F8}.Debug|x86.Build.0 = Debug|Win32
38 | {24569797-2891-48A2-84F6-DD9E343BF0F8}.Release|Any CPU.ActiveCfg = Release|Win32
39 | {24569797-2891-48A2-84F6-DD9E343BF0F8}.Release|Any CPU.Build.0 = Release|Win32
40 | {24569797-2891-48A2-84F6-DD9E343BF0F8}.Release|x64.ActiveCfg = Release|x64
41 | {24569797-2891-48A2-84F6-DD9E343BF0F8}.Release|x64.Build.0 = Release|x64
42 | {24569797-2891-48A2-84F6-DD9E343BF0F8}.Release|x86.ActiveCfg = Release|Win32
43 | {24569797-2891-48A2-84F6-DD9E343BF0F8}.Release|x86.Build.0 = Release|Win32
44 | EndGlobalSection
45 | GlobalSection(SolutionProperties) = preSolution
46 | HideSolutionNode = FALSE
47 | EndGlobalSection
48 | GlobalSection(ExtensibilityGlobals) = postSolution
49 | SolutionGuid = {E46335BF-D8EA-4F55-B2E2-3C9A325055E5}
50 | EndGlobalSection
51 | EndGlobal
52 |
--------------------------------------------------------------------------------
/di2xinput/InputDialog.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace di2xinput
2 | {
3 | partial class InputDialog
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.components = new System.ComponentModel.Container();
32 | this.label1 = new System.Windows.Forms.Label();
33 | this.inputTimer = new System.Windows.Forms.Timer(this.components);
34 | this.SuspendLayout();
35 | //
36 | // label1
37 | //
38 | this.label1.Dock = System.Windows.Forms.DockStyle.Fill;
39 | this.label1.Location = new System.Drawing.Point(0, 0);
40 | this.label1.Name = "label1";
41 | this.label1.Size = new System.Drawing.Size(263, 95);
42 | this.label1.TabIndex = 0;
43 | this.label1.Text = "Press the button to map \r\nor\r\nClose this dialog to cancel the mapping";
44 | this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
45 | this.label1.Click += new System.EventHandler(this.label1_Click);
46 | //
47 | // inputTimer
48 | //
49 | this.inputTimer.Interval = 10;
50 | this.inputTimer.Tick += new System.EventHandler(this.inputTimer_Tick);
51 | //
52 | // InputDialog
53 | //
54 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
55 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
56 | this.ClientSize = new System.Drawing.Size(263, 95);
57 | this.Controls.Add(this.label1);
58 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
59 | this.MaximizeBox = false;
60 | this.MinimizeBox = false;
61 | this.Name = "InputDialog";
62 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
63 | this.Text = "Assigning mapping...";
64 | this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.InputDialog_FormClosed);
65 | this.Load += new System.EventHandler(this.InputDialog_Load);
66 | this.ResumeLayout(false);
67 |
68 | }
69 |
70 | #endregion
71 |
72 | private System.Windows.Forms.Label label1;
73 | private System.Windows.Forms.Timer inputTimer;
74 | }
75 | }
--------------------------------------------------------------------------------
/HookDLL/DIBinding.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "stdafx.h"
4 |
5 | class DIBinding
6 | {
7 | public:
8 |
9 | typedef enum
10 | {
11 | BUTTON_BINDING = 1,
12 | POV_BINDING,
13 | AXIS_BINDING
14 | } BINDING_TYPE;
15 |
16 | DIBinding(BINDING_TYPE type) { this->type = type; };
17 | ~DIBinding() = default;
18 |
19 | virtual void Update(const DIJOYSTATE2& joystate) = 0;
20 |
21 | BINDING_TYPE type;
22 | };
23 |
24 | class DIButtonBinding : public DIBinding
25 | {
26 |
27 | public:
28 | DIButtonBinding(int index, bool bKeyboard = false)
29 | : DIBinding(DIBinding::BINDING_TYPE::BUTTON_BINDING), index(index), bKeyboard(bKeyboard)
30 | {
31 | }
32 |
33 | virtual void Update(const DIJOYSTATE2& joystate)
34 | {
35 | if (bKeyboard)
36 | {
37 | index &= ~0x100;
38 | int vkCode = MapVirtualKey(index, MAPVK_VSC_TO_VK);
39 | state = GetAsyncKeyState(vkCode) != 0;
40 | }
41 | else
42 | {
43 | state = joystate.rgbButtons[index] != 0;
44 | }
45 | }
46 |
47 | bool GetState() { return state; };
48 |
49 | private:
50 | bool state;
51 | int index;
52 | bool bKeyboard;
53 | };
54 |
55 | class DIPovBinding : public DIBinding
56 | {
57 |
58 | public:
59 | typedef enum
60 | {
61 | UP,
62 | DOWN,
63 | LEFT,
64 | RIGHT
65 | }POV_DIRECTION;
66 |
67 | POV_DIRECTION direction;
68 |
69 | DIPovBinding(int index, POV_DIRECTION direction)
70 | : DIBinding(DIBinding::BINDING_TYPE::POV_BINDING), index(index), direction(direction)
71 | {
72 | }
73 |
74 | ~DIPovBinding() = default;
75 |
76 | bool GetState() { return state; };
77 |
78 | virtual void Update(const DIJOYSTATE2& joystate)
79 | {
80 | const int value = joystate.rgdwPOV[index];
81 |
82 | if (value == -1)
83 | {
84 | state = false;
85 | return;
86 | }
87 |
88 | const int angleDiv = ((value + 2250) / 4500) % 8;
89 |
90 | switch (direction)
91 | {
92 | case POV_DIRECTION::UP:
93 | state = (angleDiv == 0 || angleDiv == 1 || angleDiv == 7);
94 | break;
95 | case POV_DIRECTION::RIGHT:
96 | state = (angleDiv == 1 || angleDiv == 2 || angleDiv == 3);
97 | break;
98 | case POV_DIRECTION::DOWN:
99 | state = (angleDiv == 3 || angleDiv == 4 || angleDiv == 5);
100 | break;
101 | case POV_DIRECTION::LEFT:
102 | state = (angleDiv == 5 || angleDiv == 6 || angleDiv == 7);
103 | break;
104 | }
105 | }
106 |
107 | private:
108 | int index;
109 | bool state;
110 | };
111 |
112 | class DIAxisBinding : public DIBinding
113 | {
114 | public:
115 |
116 | int index;
117 |
118 | DIAxisBinding(int index, bool isNegative)
119 | : DIBinding(DIBinding::BINDING_TYPE::AXIS_BINDING), index(index), isNegative(isNegative)
120 | {
121 | }
122 |
123 | virtual void Update(const DIJOYSTATE2& joystate)
124 | {
125 | switch (index)
126 | {
127 | case 0: value = joystate.lX; break;
128 | case 1: value = joystate.lY; break;
129 | case 2: value = joystate.lZ; break;
130 | case 3: value = joystate.lRx; break;
131 | case 4: value = joystate.lRy; break;
132 | case 5: value = joystate.lRz; break;
133 | }
134 | }
135 |
136 | int GetValue()
137 | {
138 | return value;
139 | }
140 |
141 | bool IsNegative()
142 | {
143 | return isNegative;
144 | }
145 |
146 | private:
147 | int value;
148 | bool isNegative;
149 | };
--------------------------------------------------------------------------------
/di2xinput/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace di2xinput.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("di2xinput.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 |
63 | ///
64 | /// Looks up a localized resource of type System.Drawing.Bitmap.
65 | ///
66 | internal static System.Drawing.Bitmap Xbox_Controller {
67 | get {
68 | object obj = ResourceManager.GetObject("Xbox_Controller", resourceCulture);
69 | return ((System.Drawing.Bitmap)(obj));
70 | }
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/di2xinput/Properties/app.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
48 |
55 |
56 |
70 |
--------------------------------------------------------------------------------
/di2xinput/InputDialog.cs:
--------------------------------------------------------------------------------
1 | using SharpDX.DirectInput;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.ComponentModel;
5 | using System.Data;
6 | using System.Diagnostics;
7 | using System.Drawing;
8 | using System.Linq;
9 | using System.Text;
10 | using System.Threading.Tasks;
11 | using System.Windows.Forms;
12 | using System.Windows.Input;
13 |
14 | namespace di2xinput
15 | {
16 | public partial class InputDialog : Form
17 | {
18 | DIManager.GamepadEntry gamepad;
19 |
20 | public ushort resultScancode;
21 | public ushort resultJoystickMapping;
22 |
23 | private class KeyProcessor : IMessageFilter
24 | {
25 | public bool PreFilterMessage(ref Message m)
26 | {
27 | if (m.Msg == 0x0100 || m.Msg == 0x0104)
28 | {
29 | uint keyCode = (uint)m.WParam.ToInt32();
30 | bool extended = (m.LParam.ToInt32() & 0x01000000) != 0;
31 |
32 | uint scanCode = WinAPI.MapVirtualKey(keyCode, 0);
33 |
34 | if (extended)
35 | scanCode |= 0x00000100;
36 |
37 | MainForm.inputDialog.resultScancode = (ushort)scanCode;
38 | MainForm.inputDialog.DialogResult = DialogResult.OK;
39 |
40 | Application.RemoveMessageFilter(this);
41 |
42 | MainForm.inputDialog.Close();
43 |
44 | return true;
45 | }
46 |
47 | return false;
48 | }
49 | }
50 |
51 | public InputDialog(string mapping, DIManager.GamepadEntry gamepad)
52 | {
53 | InitializeComponent();
54 |
55 | this.gamepad = gamepad;
56 |
57 | label1.Text = "Press the button to map " + mapping.ToUpper() + "\nor\nClose this dialog to cancel the mapping";
58 |
59 | if (gamepad == null)
60 | {
61 | Application.AddMessageFilter(new KeyProcessor());
62 | }
63 | }
64 |
65 | private void InputDialog_Load(object sender, EventArgs e)
66 | {
67 | if(gamepad != null)
68 | {
69 |
70 | gamepad.joystick.Properties.DeadZone = 7500;
71 | gamepad.joystick.Properties.AxisMode = DeviceAxisMode.Absolute;
72 | gamepad.joystick.SetCooperativeLevel(this.Handle, (CooperativeLevel.NonExclusive | CooperativeLevel.Background));
73 | gamepad.joystick.Acquire();
74 |
75 | foreach (DeviceObjectInstance doi in gamepad.joystick.GetObjects(DeviceObjectTypeFlags.Axis))
76 | gamepad.joystick.GetObjectPropertiesById(doi.ObjectId).Range = new InputRange(-5000, 5000);
77 |
78 | inputTimer.Enabled = true;
79 | inputTimer.Start();
80 | }
81 | }
82 |
83 | private void inputTimer_Tick(object sender, EventArgs e)
84 | {
85 | var joyState = gamepad.joystick.GetCurrentState();
86 | var joyMapping = DIManager.GetMappingFromState(gamepad.joystick, joyState);
87 |
88 | if(joyMapping != 0)
89 | {
90 | resultJoystickMapping = joyMapping;
91 | DialogResult = DialogResult.OK;
92 | Close();
93 | }
94 | }
95 |
96 | private void InputDialog_FormClosed(object sender, FormClosedEventArgs e)
97 | {
98 | if (gamepad != null)
99 | {
100 | gamepad.joystick.Unacquire();
101 | inputTimer.Enabled = false;
102 | inputTimer.Stop();
103 | }
104 | }
105 |
106 | private void label1_Click(object sender, EventArgs e)
107 | {
108 |
109 | }
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/di2xinput/ProgramManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 | using System.Xml.Serialization;
9 |
10 | namespace di2xinput
11 | {
12 | public class ProgramManager
13 | {
14 | [Serializable]
15 | public class ProgramEntry
16 | {
17 | [XmlIgnore]
18 | public Icon icon;
19 | [XmlAttribute("Path")]
20 | public string path;
21 | [XmlAttribute("XInputVersion")]
22 | public string XIVersion;
23 | [XmlAttribute("Profile")]
24 | public string profile;
25 |
26 |
27 | public void RemoveConfig()
28 | {
29 | try
30 | {
31 | string version = XIVersion.Split(' ')[0];
32 | string destinationPath = path.Substring(0, path.LastIndexOf('\\') + 1);
33 | string destinationDLL = destinationPath + "xinput" + version + ".dll";
34 |
35 | if (File.Exists(destinationDLL))
36 | File.Delete(destinationDLL);
37 |
38 | if (File.Exists(destinationPath + "di2xiprofile.bin"))
39 | File.Delete(destinationPath + "di2xiprofile.bin");
40 | }
41 | catch
42 | {
43 |
44 | }
45 | }
46 |
47 | public void ApplyConfig()
48 | {
49 | try
50 | {
51 | string architecture = XIVersion.Split(' ')[1];
52 | string version = XIVersion.Split(' ')[0];
53 | string DLLFile = Environment.CurrentDirectory + "\\DLLs\\StubDLL" + architecture + ".dll";
54 | string destinationPath = path.Substring(0, path.LastIndexOf('\\') + 1);
55 | string destinationDLL = destinationPath + "xinput" + version + ".dll";
56 |
57 | if (!File.Exists(destinationDLL))
58 | File.Copy(DLLFile, destinationDLL);
59 |
60 | var selectedProfile = ProfileManager.profiles.FirstOrDefault(x => x.Key == profile);
61 |
62 | if (!selectedProfile.Equals(default(KeyValuePair)))
63 | {
64 | using (var profileFile = File.Create(destinationPath + "di2xiprofile.bin"))
65 | {
66 | for(int i = 0; i < 4; i++)
67 | {
68 | var contents = selectedProfile.Value.controllers[i].ToByteArray();
69 | profileFile.Write(contents, 0, contents.Length);
70 | }
71 | }
72 | }
73 | }
74 | catch
75 | {
76 |
77 | }
78 | }
79 |
80 | }
81 |
82 | public class Entries
83 | {
84 | [XmlArray("Entries"), XmlArrayItem(typeof(ProgramEntry), ElementName = "Entry")]
85 | public List programs = new List();
86 | }
87 |
88 | private const string entriesFile = "./entries.xml";
89 | public static Entries entries = new Entries();
90 |
91 | public static void LoadEntries()
92 | {
93 | XmlSerializer xmlSerializer = new XmlSerializer(typeof(Entries));
94 |
95 | try
96 | {
97 | using (var file = File.Open(entriesFile, FileMode.Open))
98 | {
99 | entries = (Entries)xmlSerializer.Deserialize(file);
100 | }
101 | }
102 | catch
103 | {
104 | }
105 | }
106 |
107 | public static void SaveEntries()
108 | {
109 | XmlSerializer xmlSerializer = new XmlSerializer(typeof(Entries));
110 |
111 | using (var file = File.Create(entriesFile))
112 | {
113 | xmlSerializer.Serialize(file, entries);
114 | }
115 | }
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/HookDLL/ControllerManager.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 | #include "ControllerManager.h"
3 |
4 | #include
5 | #include "DirectInput.h"
6 |
7 | std::vector> ControllerManager::controllers;
8 |
9 | void ControllerManager::Init()
10 | {
11 | if (!DirectInput::Init())
12 | {
13 | std::cout << "DirectInput failed to initialize." << std::endl;
14 | return;
15 | }
16 |
17 | std::cout << "DirectInput initialized." << std::endl;
18 |
19 | controllers.clear();
20 |
21 | for (int i = 0; i < 4; i++)
22 | controllers.emplace_back(std::make_unique());
23 |
24 | wchar_t executablePath[MAX_PATH];
25 | GetModuleFileNameW(NULL, executablePath, MAX_PATH);
26 |
27 | std::wstring configPath(executablePath);
28 | configPath = configPath.substr(0, configPath.find_last_of(L'\\')) + L"\\di2xiprofile.bin";
29 |
30 | std::ifstream configFile(configPath, std::ios::binary | std::ios::ate);
31 | std::wcout << "Path: " << configPath << std::endl;
32 |
33 | if (!configFile || !configFile.good())
34 | {
35 | std::cout << "Failed to read config file di2xiprofile.bin." << std::endl;
36 | return;
37 | }
38 |
39 | std::ifstream::pos_type fileSize = configFile.tellg();
40 |
41 | std::wcout << "di2xiprofile.bin is " << fileSize << " bytes long." << std::endl;
42 |
43 | std::vector buffer(fileSize);
44 |
45 | configFile.seekg(0, std::ios::beg);
46 | configFile.read(&buffer[0], fileSize);
47 |
48 | Controller::DEVICE_TYPE type;
49 | int guidLength1 = 0;
50 | int guidLength2 = 0;
51 | char* instanceGUID = nullptr;
52 | char* productGUID = nullptr;
53 | std::vector mappings;
54 | int byteIndex = 0;
55 |
56 | mappings.resize(24);
57 |
58 | for (int i = 0; i < MAX_CONTROLLERS; i++)
59 | {
60 | type = static_cast(buffer[byteIndex]);
61 | std::memcpy(&guidLength1, &buffer[byteIndex + 1], sizeof(int));
62 | byteIndex += 5;
63 |
64 | instanceGUID = new char[guidLength1 + 1];
65 | std::memcpy(instanceGUID, &buffer[byteIndex], guidLength1);
66 | instanceGUID[guidLength1] = 0;
67 | byteIndex += guidLength1;
68 |
69 | std::memcpy(&guidLength2, &buffer[byteIndex], sizeof(int));
70 | byteIndex += 4;
71 |
72 | productGUID = new char[guidLength2 + 1];
73 | std::memcpy(productGUID, &buffer[byteIndex], guidLength2);
74 | productGUID[guidLength2] = 0;
75 | byteIndex += guidLength2;
76 |
77 | std::memcpy(&mappings[0], &buffer[byteIndex], sizeof(uint16_t) * 24);
78 | byteIndex += sizeof(uint16_t) * 24;
79 |
80 | controllers[i]->AssignDIDevice(instanceGUID, productGUID, type, mappings);
81 | }
82 | }
83 |
84 | bool ControllerManager::IsConnected(DWORD controllerIndex)
85 | {
86 | return controllers[controllerIndex]->IsConnected();
87 | }
88 |
89 | DWORD ControllerManager::GetState(DWORD controllerIndex, XINPUT_STATE* pState)
90 | {
91 | if (PollGamepad(controllerIndex, &pState->Gamepad))
92 | {
93 | pState->dwPacketNumber = GetTickCount();
94 | return ERROR_SUCCESS;
95 | }
96 | else
97 | {
98 | std::cout << "Failed to poll for gamepad state." << std::endl;
99 | return ERROR_DEVICE_UNREACHABLE;
100 | }
101 | }
102 |
103 | DWORD ControllerManager::GetCapabilities(DWORD controllerIndex, DWORD dwFlags, XINPUT_CAPABILITIES* pCapabilities)
104 | {
105 | if (PollGamepad(controllerIndex, &pCapabilities->Gamepad))
106 | {
107 | pCapabilities->Type = XINPUT_DEVTYPE_GAMEPAD;
108 | pCapabilities->SubType = XINPUT_DEVSUBTYPE_GAMEPAD;
109 | return ERROR_SUCCESS;
110 | }
111 | else
112 | {
113 | std::cout << "Failed to poll for gamepad capabilities." << std::endl;
114 | return ERROR_DEVICE_UNREACHABLE;
115 | }
116 | }
117 |
118 | bool ControllerManager::PollGamepad(int index, XINPUT_GAMEPAD* gamepad)
119 | {
120 | auto res = controllers[index]->Acquire();
121 |
122 | if (SUCCEEDED(res))
123 | {
124 | auto gamepadState = controllers[index]->GetState();
125 | std::memcpy(gamepad, &gamepadState, sizeof(XINPUT_GAMEPAD));
126 | res = controllers[index]->Unacquire();
127 |
128 | if (FAILED(res))
129 | {
130 | std::cout << "Failed to unacquire. HRESULT=0x" << std::hex << res << std::endl;
131 | }
132 |
133 | return true;
134 | }
135 | else
136 | {
137 | std::cout << "Failed to acquire. HRESULT=0x" << std::hex << res << std::endl;
138 | return false;
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/HookDLL/DirectInput.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 | #include "DirectInput.h"
3 |
4 | #include
5 |
6 | #include
7 | #include
8 |
9 | LPDIRECTINPUT8 DirectInput::directInput;
10 | std::vector> DirectInput::devices;
11 | HWND DirectInput::dummyWindow;
12 | LPDIRECTINPUTDEVICE8 DirectInput::currentDevice;
13 |
14 | BOOL CALLBACK DirectInput::EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* pContext)
15 | {
16 | DIPROPRANGE propRange;
17 | propRange.diph.dwSize = sizeof(DIPROPRANGE);
18 | propRange.diph.dwHeaderSize = sizeof(DIPROPHEADER);
19 | propRange.diph.dwHow = DIPH_BYID;
20 | propRange.diph.dwObj = pdidoi->dwType;
21 | propRange.lMin = -32768;
22 | propRange.lMax = +32768;
23 |
24 | if (FAILED(currentDevice->SetProperty(DIPROP_RANGE, &propRange.diph)))
25 | {
26 | std::cout << "Failed to set axis " << pdidoi->wDesignatorIndex << " range." << std::endl;
27 | return DIENUM_STOP;
28 | }
29 |
30 | return DIENUM_CONTINUE;
31 | }
32 |
33 | BOOL CALLBACK DirectInput::EnumJoysticksCallback(const DIDEVICEINSTANCE* instance, VOID* context)
34 | {
35 | LPDIRECTINPUTDEVICE8 device;
36 |
37 | std::string instanceGUID = GUIDToString(instance->guidInstance.Data1, instance->guidInstance.Data2, instance->guidInstance.Data3, instance->guidInstance.Data4);
38 | std::string productGUID = GUIDToString(instance->guidProduct.Data1, instance->guidProduct.Data2, instance->guidProduct.Data3, instance->guidProduct.Data4);
39 |
40 | std::wcout << "Name: " << instance->tszProductName << "." << std::endl;
41 | std::cout << "Instance GUID: " << instanceGUID << "." << std::endl;
42 | std::cout << "Product GUID: " << productGUID << "." << std::endl;
43 |
44 | HRESULT res = directInput->CreateDevice(instance->guidInstance, &device, NULL);
45 |
46 | if (!FAILED(res))
47 | {
48 | currentDevice = device;
49 |
50 | if (FAILED(device->EnumObjects(EnumObjectsCallback, NULL, DIDFT_AXIS)))
51 | {
52 | std::cout << "Failed to enum controller objects." << std::endl;
53 | return DIENUM_CONTINUE;
54 | }
55 |
56 | devices.push_back(std::make_tuple(productGUID, instanceGUID, device));
57 | return DIENUM_CONTINUE;
58 | }
59 |
60 | return DIENUM_STOP;
61 | }
62 |
63 | void DirectInput::RefreshDeviceList()
64 | {
65 | directInput->EnumDevices(DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, nullptr, DIEDFL_ATTACHEDONLY);
66 | }
67 |
68 | LPDIRECTINPUTDEVICE8 DirectInput::FindDevice(std::string instanceGUID, std::string productGUID)
69 | {
70 | for (const auto& device : devices)
71 | {
72 | std::string currentProductGUID = std::get<0>(device);
73 | std::string currentinstanceGUID = std::get<1>(device);
74 |
75 | std::cout << "Checking against " << currentProductGUID << ", " << currentinstanceGUID << std::endl;
76 |
77 | if (currentProductGUID == productGUID || currentinstanceGUID == instanceGUID)
78 | return std::get<2>(device);
79 | }
80 |
81 |
82 | return nullptr;
83 | }
84 |
85 | bool DirectInput::InitializeDevice(LPDIRECTINPUTDEVICE8 device)
86 | {
87 | HRESULT res = device->SetDataFormat(&c_dfDIJoystick2);
88 |
89 | if (FAILED(res))
90 | {
91 | std::cout << "Failed to set data format. Error: 0x" << std::hex << res << std::endl;
92 | return false;
93 | }
94 |
95 | res = device->SetCooperativeLevel(dummyWindow, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE);
96 |
97 | if (FAILED(res))
98 | {
99 | std::cout << "Failed to set cooperative level. Error: 0x" << std::hex << res << std::endl;
100 | return false;
101 | }
102 |
103 | return true;
104 | }
105 |
106 | std::string DirectInput::GUIDToString(const uint64_t& data1, const uint16_t& data2, const uint16_t& data3, const unsigned char* data4)
107 | {
108 | std::stringstream guidString;
109 |
110 | guidString << std::hex << std::setfill('0') << std::setw(8) << data1 << "-";
111 | guidString << std::setw(4) << data2 << "-";
112 | guidString << std::setw(4) << data3 << "-";
113 |
114 | for (int i = 0; i < 2; i++)
115 | guidString << std::setw(2) << +data4[i];
116 |
117 | guidString << "-";
118 |
119 | for (int i = 2; i < 8; i++)
120 | guidString << std::setw(2) << +data4[i];
121 |
122 | return guidString.str();
123 | }
124 |
125 | bool DirectInput::Init()
126 | {
127 | HRESULT res = DirectInput8Create(GetModuleHandle(NULL), 0x0800, IID_IDirectInput8, (LPVOID*)&directInput, nullptr);
128 |
129 | if (FAILED(res))
130 | {
131 | std::cout << "Failed to initialize DirectInput8." << std::endl;
132 | return false;
133 | }
134 |
135 | dummyWindow = CreateWindowEx(NULL, TEXT("Message"), TEXT("di2xinput"), WS_TILED, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL);
136 |
137 | if (!dummyWindow)
138 | {
139 | std::cout << "Failed to create a dummy window." << std::endl;
140 | return false;
141 | }
142 |
143 | RefreshDeviceList();
144 | return true;
145 | }
146 |
147 |
148 |
--------------------------------------------------------------------------------
/di2xinput/WinAPI.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Diagnostics;
5 | using System.IO;
6 | using System.Linq;
7 | using System.Runtime.InteropServices;
8 | using System.Runtime.Serialization.Formatters.Binary;
9 | using System.Text;
10 | using System.Threading.Tasks;
11 | using System.Windows.Forms;
12 |
13 | namespace di2xinput
14 | {
15 | static class WinAPI
16 | {
17 | [DllImport("user32.dll")]
18 | public static extern IntPtr GetKeyboardLayout(uint idThread);
19 |
20 | [DllImport("user32.dll")]
21 | public static extern uint MapVirtualKeyEx(uint uCode, uint uMapType, IntPtr dwhkl);
22 |
23 | [DllImport("user32.dll")]
24 | public static extern uint MapVirtualKey(uint uCode, uint uMapType);
25 |
26 | [DllImport("user32.dll")]
27 | public static extern int GetKeyNameText(uint lParam, [Out] StringBuilder lpString, int nSize);
28 |
29 | [DllImport("psapi.dll")]
30 | public static extern uint GetModuleFileNameEx(IntPtr hProcess, IntPtr hModule, [Out] StringBuilder lpBaseName, [In] [MarshalAs(UnmanagedType.U4)] uint nSize);
31 |
32 | [DllImport("kernel32.dll")]
33 | public static extern bool GetBinaryType(string lpApplicationName, out BinaryType lpBinaryType);
34 |
35 | [DllImport("psapi.dll", SetLastError = true)]
36 | public static extern bool EnumProcessModulesEx(IntPtr hProcess, [Out] IntPtr lphModule, UInt32 cb, [MarshalAs(UnmanagedType.U4)] out UInt32 lpcbNeeded, DwFilterFlag dwff);
37 |
38 | [Flags]
39 | public enum FileMapProtection : uint
40 | {
41 | PageReadonly = 0x02,
42 | PageReadWrite = 0x04,
43 | PageWriteCopy = 0x08,
44 | PageExecuteRead = 0x20,
45 | PageExecuteReadWrite = 0x40,
46 | SectionCommit = 0x8000000,
47 | SectionImage = 0x1000000,
48 | SectionNoCache = 0x10000000,
49 | SectionReserve = 0x4000000,
50 | }
51 |
52 | [Flags]
53 | public enum FileMapAccess : uint
54 | {
55 | FileMapCopy = 0x0001,
56 | FileMapWrite = 0x0002,
57 | FileMapRead = 0x0004,
58 | FileMapAllAccess = 0x001f,
59 | FileMapExecute = 0x0020,
60 | }
61 |
62 | public enum BinaryType : uint
63 | {
64 | SCS_32BIT_BINARY = 0, // A 32-bit Windows-based application
65 | SCS_64BIT_BINARY = 6, // A 64-bit Windows-based application.
66 | SCS_DOS_BINARY = 1, // An MS-DOS – based application
67 | SCS_OS216_BINARY = 5, // A 16-bit OS/2-based application
68 | SCS_PIF_BINARY = 3, // A PIF file that executes an MS-DOS – based application
69 | SCS_POSIX_BINARY = 4, // A POSIX – based application
70 | SCS_WOW_BINARY = 2 // A 16-bit Windows-based application
71 | }
72 |
73 | public enum DwFilterFlag : uint
74 | {
75 | LIST_MODULES_DEFAULT = 0x0, // This is the default one app would get without any flag.
76 | LIST_MODULES_32BIT = 0x01, // list 32bit modules in the target process.
77 | LIST_MODULES_64BIT = 0x02, // list all 64bit modules. 32bit exe will be stripped off.
78 | LIST_MODULES_ALL = (LIST_MODULES_32BIT | LIST_MODULES_64BIT) // list all the modules
79 | }
80 |
81 | public const uint MAPVK_VK_TO_VSC = 0x00;
82 | public const uint MAPVK_VSC_TO_VK = 0x01;
83 | public const uint MAPVK_VK_TO_CHAR = 0x02;
84 | public const uint MAPVK_VSC_TO_VK_EX = 0x03;
85 | public const uint MAPVK_VK_TO_VSC_EX = 0x04;
86 | public const UInt32 INFINITE = 0xFFFFFFFF;
87 |
88 | public static IntPtr LLAddress32 = IntPtr.Zero;
89 |
90 | public static List GetModuleNames(Process proc, bool x64 = false)
91 | {
92 | List moduleList = new List();
93 |
94 | try
95 | {
96 | uint sizeNeeded = 0;
97 | IntPtr procHandle = IntPtr.Zero;
98 |
99 | if (!proc.HasExited)
100 | procHandle = proc.Handle;
101 |
102 | EnumProcessModulesEx(procHandle, IntPtr.Zero, 4, out sizeNeeded, x64 ? DwFilterFlag.LIST_MODULES_64BIT : DwFilterFlag.LIST_MODULES_32BIT);
103 |
104 | if (sizeNeeded == 0)
105 | return new List();
106 |
107 | IntPtr[] modules = new IntPtr[sizeNeeded / Marshal.SizeOf(typeof(IntPtr))];
108 | GCHandle gch = GCHandle.Alloc(modules, GCHandleType.Pinned);
109 | IntPtr pModules = gch.AddrOfPinnedObject();
110 |
111 | EnumProcessModulesEx(procHandle, pModules, sizeNeeded, out sizeNeeded, x64 ? DwFilterFlag.LIST_MODULES_64BIT : DwFilterFlag.LIST_MODULES_32BIT);
112 |
113 | if (sizeNeeded == 0)
114 | return new List();
115 |
116 | StringBuilder sb = new StringBuilder(256);
117 |
118 | for (int i = 0; i < modules.Length; i++)
119 | {
120 | if (GetModuleFileNameEx(proc.Handle, modules[i], sb, 256) == 0)
121 | continue;
122 |
123 | if (!moduleList.Contains(sb.ToString()))
124 | moduleList.Add(sb.ToString());
125 | }
126 | }
127 | catch { }
128 |
129 | return moduleList;
130 | }
131 |
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | bld/
21 | [Bb]in/
22 | [Oo]bj/
23 | [Ll]og/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 | # Uncomment if you have tasks that create the project's static files in wwwroot
28 | #wwwroot/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | # DNX
44 | project.lock.json
45 | project.fragment.lock.json
46 | artifacts/
47 |
48 | *_i.c
49 | *_p.c
50 | *_i.h
51 | *.ilk
52 | *.meta
53 | *.obj
54 | *.pch
55 | *.pdb
56 | *.pgc
57 | *.pgd
58 | *.rsp
59 | *.sbr
60 | *.tlb
61 | *.tli
62 | *.tlh
63 | *.tmp
64 | *.tmp_proj
65 | *.log
66 | *.vspscc
67 | *.vssscc
68 | .builds
69 | *.pidb
70 | *.svclog
71 | *.scc
72 |
73 | # Chutzpah Test files
74 | _Chutzpah*
75 |
76 | # Visual C++ cache files
77 | ipch/
78 | *.aps
79 | *.ncb
80 | *.opendb
81 | *.opensdf
82 | *.sdf
83 | *.cachefile
84 | *.VC.db
85 | *.VC.VC.opendb
86 |
87 | # Visual Studio profiler
88 | *.psess
89 | *.vsp
90 | *.vspx
91 | *.sap
92 |
93 | # TFS 2012 Local Workspace
94 | $tf/
95 |
96 | # Guidance Automation Toolkit
97 | *.gpState
98 |
99 | # ReSharper is a .NET coding add-in
100 | _ReSharper*/
101 | *.[Rr]e[Ss]harper
102 | *.DotSettings.user
103 |
104 | # JustCode is a .NET coding add-in
105 | .JustCode
106 |
107 | # TeamCity is a build add-in
108 | _TeamCity*
109 |
110 | # DotCover is a Code Coverage Tool
111 | *.dotCover
112 |
113 | # NCrunch
114 | _NCrunch_*
115 | .*crunch*.local.xml
116 | nCrunchTemp_*
117 |
118 | # MightyMoose
119 | *.mm.*
120 | AutoTest.Net/
121 |
122 | # Web workbench (sass)
123 | .sass-cache/
124 |
125 | # Installshield output folder
126 | [Ee]xpress/
127 |
128 | # DocProject is a documentation generator add-in
129 | DocProject/buildhelp/
130 | DocProject/Help/*.HxT
131 | DocProject/Help/*.HxC
132 | DocProject/Help/*.hhc
133 | DocProject/Help/*.hhk
134 | DocProject/Help/*.hhp
135 | DocProject/Help/Html2
136 | DocProject/Help/html
137 |
138 | # Click-Once directory
139 | publish/
140 |
141 | # Publish Web Output
142 | *.[Pp]ublish.xml
143 | *.azurePubxml
144 | # TODO: Comment the next line if you want to checkin your web deploy settings
145 | # but database connection strings (with potential passwords) will be unencrypted
146 | #*.pubxml
147 | *.publishproj
148 |
149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
150 | # checkin your Azure Web App publish settings, but sensitive information contained
151 | # in these scripts will be unencrypted
152 | PublishScripts/
153 |
154 | # NuGet Packages
155 | *.nupkg
156 | # The packages folder can be ignored because of Package Restore
157 | **/packages/*
158 | # except build/, which is used as an MSBuild target.
159 | !**/packages/build/
160 | # Uncomment if necessary however generally it will be regenerated when needed
161 | #!**/packages/repositories.config
162 | # NuGet v3's project.json files produces more ignoreable files
163 | *.nuget.props
164 | *.nuget.targets
165 |
166 | # Microsoft Azure Build Output
167 | csx/
168 | *.build.csdef
169 |
170 | # Microsoft Azure Emulator
171 | ecf/
172 | rcf/
173 |
174 | # Windows Store app package directories and files
175 | AppPackages/
176 | BundleArtifacts/
177 | Package.StoreAssociation.xml
178 | _pkginfo.txt
179 |
180 | # Visual Studio cache files
181 | # files ending in .cache can be ignored
182 | *.[Cc]ache
183 | # but keep track of directories ending in .cache
184 | !*.[Cc]ache/
185 |
186 | # Others
187 | ClientBin/
188 | ~$*
189 | *~
190 | *.dbmdl
191 | *.dbproj.schemaview
192 | *.jfm
193 | *.pfx
194 | *.publishsettings
195 | node_modules/
196 | orleans.codegen.cs
197 |
198 | # Since there are multiple workflows, uncomment next line to ignore bower_components
199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
200 | #bower_components/
201 |
202 | # RIA/Silverlight projects
203 | Generated_Code/
204 |
205 | # Backup & report files from converting an old project file
206 | # to a newer Visual Studio version. Backup files are not needed,
207 | # because we have git ;-)
208 | _UpgradeReport_Files/
209 | Backup*/
210 | UpgradeLog*.XML
211 | UpgradeLog*.htm
212 |
213 | # SQL Server files
214 | *.mdf
215 | *.ldf
216 |
217 | # Business Intelligence projects
218 | *.rdl.data
219 | *.bim.layout
220 | *.bim_*.settings
221 |
222 | # Microsoft Fakes
223 | FakesAssemblies/
224 |
225 | # GhostDoc plugin setting file
226 | *.GhostDoc.xml
227 |
228 | # Node.js Tools for Visual Studio
229 | .ntvs_analysis.dat
230 |
231 | # Visual Studio 6 build log
232 | *.plg
233 |
234 | # Visual Studio 6 workspace options file
235 | *.opt
236 |
237 | # Visual Studio LightSwitch build output
238 | **/*.HTMLClient/GeneratedArtifacts
239 | **/*.DesktopClient/GeneratedArtifacts
240 | **/*.DesktopClient/ModelManifest.xml
241 | **/*.Server/GeneratedArtifacts
242 | **/*.Server/ModelManifest.xml
243 | _Pvt_Extensions
244 |
245 | # Paket dependency manager
246 | .paket/paket.exe
247 | paket-files/
248 |
249 | # FAKE - F# Make
250 | .fake/
251 |
252 | # JetBrains Rider
253 | .idea/
254 | *.sln.iml
255 |
256 | # CodeRush
257 | .cr/
258 |
259 | # Python Tools for Visual Studio (PTVS)
260 | __pycache__/
261 | *.pyc
--------------------------------------------------------------------------------
/di2xinput/DIManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using SharpDX.DirectInput;
8 |
9 | namespace di2xinput
10 | {
11 | public static class DIManager
12 | {
13 | public class GamepadEntry
14 | {
15 | public Joystick joystick;
16 | public Guid productGUID;
17 | public Guid instanceGUID;
18 | }
19 |
20 | private static List gamepads = new List();
21 |
22 | private static DirectInput di;
23 |
24 | public static void Init()
25 | {
26 | di = new DirectInput();
27 | }
28 |
29 | private static void SearchDevices()
30 | {
31 | gamepads.Clear();
32 |
33 | foreach(DeviceInstance dev in di.GetDevices(DeviceClass.GameControl, DeviceEnumerationFlags.AttachedOnly))
34 | {
35 | gamepads.Add(new GamepadEntry()
36 | {
37 | instanceGUID = dev.InstanceGuid,
38 | productGUID = dev.ProductGuid,
39 | joystick = new Joystick(di, dev.ProductGuid)
40 | });
41 | }
42 |
43 | }
44 |
45 | public static List GetGamepads()
46 | {
47 | SearchDevices();
48 | return gamepads;
49 | }
50 |
51 | public static GamepadEntry GetGamepadFromName(string name)
52 | {
53 | SearchDevices();
54 |
55 | var result = gamepads.Where(x => x.joystick.Properties.ProductName == name);
56 |
57 | if (result.Count() > 0)
58 | return result.ToList()[0];
59 | else
60 | return null;
61 | }
62 |
63 | public static GamepadEntry GetGamepadFromGUIDs(string productGUID, string instanceGUID)
64 | {
65 | SearchDevices();
66 |
67 | return gamepads.FirstOrDefault(x => x.productGUID.ToString() == productGUID.ToString() || x.instanceGUID.ToString() == instanceGUID.ToString());
68 | }
69 |
70 | public static string GetNameFromMapping(ushort mapping)
71 | {
72 | if ((mapping & 1) == 1 && (mapping & 2) == 2)
73 | {
74 | int index = (mapping & 0x3C) >> 2;
75 | string sign = (mapping & 0x40) >> 6 == 1 ? "-" : "+";
76 | return "Axis " + index + " " + sign;
77 | }
78 | else if((mapping & 2) == 2)
79 | {
80 | int index = (mapping & 0x3C) >> 2;
81 | int dir = (mapping & 0xFFC0) >> 6;
82 | string[] direction = new string[] { "Up", "Down", "Left", "Right" };
83 | return "POV " + index + " " + direction[dir];
84 | }
85 | else if((mapping & 1) == 1)
86 | {
87 | int index = (mapping & 0x3C) >> 2;
88 | return "Button " + (index + 1);
89 | }
90 |
91 | return "Unknown";
92 | }
93 |
94 | public static ushort GetMappingFromState(Joystick joy, JoystickState state)
95 | {
96 | int maxButtons = joy.Capabilities.ButtonCount;
97 | int maxAxis = joy.Capabilities.AxeCount;
98 | int maxPov = joy.Capabilities.PovCount;
99 |
100 | ushort mapping = 0;
101 |
102 | for(int i = 0; i < maxButtons; i++)
103 | {
104 | if (state.Buttons[i])
105 | {
106 | mapping = (ushort)((mapping | 1) | (mapping | (i << 2)));
107 | return mapping;
108 | }
109 | }
110 |
111 | for (int i = 0; i < maxPov; i++)
112 | {
113 | if (state.PointOfViewControllers[i] != -1)
114 | {
115 | int angleDiv = ((state.PointOfViewControllers[i] + 2250) / 4500) % 8;
116 | int direction = 0;
117 |
118 | if (angleDiv == 0 || angleDiv == 1 || angleDiv == 7) direction = 0;
119 | if (angleDiv == 1 || angleDiv == 2 || angleDiv == 3) direction = 3;
120 | if (angleDiv == 3 || angleDiv == 4 || angleDiv == 5) direction = 1;
121 | if (angleDiv == 5 || angleDiv == 6 || angleDiv == 7) direction = 2;
122 |
123 | mapping = (ushort)((mapping | 2) | (i << 2) | (direction << 6));
124 | return mapping;
125 | }
126 | }
127 |
128 | Func axisMapping = (index, sign) =>
129 | {
130 | return (ushort)((mapping | 3) | (index << 2) | (sign == "-" ? 1 : 0) << 6);
131 | };
132 |
133 | if (state.X < 0) return axisMapping(0, "-");
134 | if (state.X > 0) return axisMapping(0, "+");
135 | if (state.Y < 0) return axisMapping(1, "-");
136 | if (state.Y > 0) return axisMapping(1, "+");
137 | if (state.Z < 0) return axisMapping(2, "-");
138 | if (state.Z > 0) return axisMapping(2, "+");
139 |
140 | if (state.RotationX < 0) return axisMapping(3, "-");
141 | if (state.RotationX > 0) return axisMapping(3, "+");
142 | if (state.RotationY < 0) return axisMapping(4, "-");
143 | if (state.RotationY > 0) return axisMapping(4, "+");
144 | if (state.RotationZ < 0) return axisMapping(5, "-");
145 | if (state.RotationZ > 0) return axisMapping(5, "+");
146 |
147 | return mapping;
148 | }
149 |
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/di2xinput/InputDialog.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | 17, 17
122 |
123 |
--------------------------------------------------------------------------------
/di2xinput/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 |
122 | ..\Resources\Xbox_Controller.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
123 |
124 |
--------------------------------------------------------------------------------
/di2xinput/MainForm.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | True
122 |
123 |
124 | True
125 |
126 |
127 | True
128 |
129 |
130 | True
131 |
132 |
133 | True
134 |
135 |
136 | True
137 |
138 |
139 | True
140 |
141 |
142 | True
143 |
144 |
145 | 17, 17
146 |
147 |
--------------------------------------------------------------------------------
/di2xinput/di2xinput.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {BEA07272-27CE-44AC-B2B1-1E47E6436D19}
8 | WinExe
9 | di2xinput
10 | di2xinput
11 | v4.6.1
12 | 512
13 | true
14 |
15 | false
16 | publish\
17 | true
18 | Disk
19 | false
20 | Foreground
21 | 7
22 | Days
23 | false
24 | false
25 | true
26 | 0
27 | 1.0.0.%2a
28 | false
29 | true
30 |
31 |
32 | AnyCPU
33 | true
34 | full
35 | false
36 | ..\bin\Debug\
37 | DEBUG;TRACE
38 | prompt
39 | 4
40 | false
41 |
42 |
43 | AnyCPU
44 | pdbonly
45 | true
46 | bin\Release\
47 | TRACE
48 | prompt
49 | 4
50 | false
51 |
52 |
53 | true
54 | ..\bin\Debug\
55 | DEBUG;TRACE
56 | full
57 | x64
58 | prompt
59 | MinimumRecommendedRules.ruleset
60 | false
61 |
62 |
63 | ..\bin\Release\
64 | TRACE
65 | true
66 | pdbonly
67 | x64
68 | prompt
69 | MinimumRecommendedRules.ruleset
70 | false
71 |
72 |
73 | LocalIntranet
74 |
75 |
76 | false
77 |
78 |
79 | app.manifest
80 |
81 |
82 |
83 | False
84 | ..\packages\SharpDX.4.2.0-ci259\lib\net45\SharpDX.dll
85 |
86 |
87 | ..\packages\SharpDX.DirectInput.4.2.0-ci259\lib\net45\SharpDX.DirectInput.dll
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 | Form
106 |
107 |
108 | InputDialog.cs
109 |
110 |
111 | Form
112 |
113 |
114 | MainForm.cs
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 | InputDialog.cs
125 |
126 |
127 | MainForm.cs
128 |
129 |
130 | ResXFileCodeGenerator
131 | Resources.Designer.cs
132 | Designer
133 |
134 |
135 | True
136 | Resources.resx
137 | True
138 |
139 |
140 |
141 |
142 |
143 | SettingsSingleFileGenerator
144 | Settings.Designer.cs
145 |
146 |
147 | True
148 | Settings.settings
149 | True
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 | False
158 | Microsoft .NET Framework 4.6.1 %28x86 and x64%29
159 | true
160 |
161 |
162 | False
163 | .NET Framework 3.5 SP1
164 | false
165 |
166 |
167 |
168 |
169 |
170 |
171 |
--------------------------------------------------------------------------------
/HookDLL/Controller.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 | #include "Controller.h"
3 |
4 | #include "DirectInput.h"
5 |
6 | #define CLAMP(x, upper, lower) (min(upper, max(x, lower)))
7 |
8 | std::vector Controller::buttonFlags =
9 | {
10 | XINPUT_GAMEPAD_DPAD_UP,
11 | XINPUT_GAMEPAD_DPAD_DOWN,
12 | XINPUT_GAMEPAD_DPAD_LEFT,
13 | XINPUT_GAMEPAD_DPAD_RIGHT,
14 | XINPUT_GAMEPAD_START,
15 | XINPUT_GAMEPAD_BACK,
16 | XINPUT_GAMEPAD_LEFT_THUMB,
17 | XINPUT_GAMEPAD_RIGHT_THUMB,
18 | XINPUT_GAMEPAD_LEFT_SHOULDER,
19 | XINPUT_GAMEPAD_RIGHT_SHOULDER,
20 | XINPUT_GAMEPAD_A,
21 | XINPUT_GAMEPAD_B,
22 | XINPUT_GAMEPAD_X,
23 | XINPUT_GAMEPAD_Y
24 | };
25 |
26 | Controller::Controller() : type(DEVICE_TYPE::NONE), productGUID(""), instanceGUID("") {}
27 |
28 | void Controller::AssignDIDevice(const std::string& instanceGUID, const std::string& productGUID, DEVICE_TYPE type, const std::vector& mappings)
29 | {
30 | if (type == DEVICE_TYPE::NONE)
31 | {
32 | std::cout << "Controller unassigned." << std::endl;
33 | return;
34 | }
35 |
36 | if (type == DEVICE_TYPE::GAMEPAD)
37 | {
38 | std::cout << "Trying to find device with GUIDS " << instanceGUID << ", " << productGUID << std::endl;
39 | DIDevice = DirectInput::FindDevice(instanceGUID, productGUID);
40 |
41 | if (!DIDevice)
42 | {
43 | std::cout << "Couldn't assign device. Device GUIDs not found." << std::endl;
44 | return;
45 | }
46 |
47 | if (!DirectInput::InitializeDevice(DIDevice))
48 | {
49 | std::cout << "Failed to initialize device." << std::endl;
50 | return;
51 | }
52 |
53 | std::cout << "Device found." << std::endl;
54 | DIDevice->Unacquire();
55 | }
56 |
57 | this->instanceGUID = instanceGUID;
58 | this->productGUID = productGUID;
59 | this->type = type;
60 |
61 | for (int i = 0; i < mappings.size(); i++)
62 | {
63 | if (type == DEVICE_TYPE::GAMEPAD)
64 | {
65 | short mappingType = mappings[i] & 3;
66 |
67 | switch (mappingType)
68 | {
69 | case DIBinding::BINDING_TYPE::BUTTON_BINDING:
70 | {
71 | int index = (mappings[i] & 0x3C) >> 2;
72 | bindings[i] = std::unique_ptr(new DIButtonBinding(index));
73 | std::cout << "BUTTON: index=" << index << std::endl;
74 | }
75 | break;
76 |
77 | case DIBinding::BINDING_TYPE::POV_BINDING:
78 | {
79 | int index = (mappings[i] & 0x3C) >> 2;
80 | int dir = (mappings[i] & 0xFFC0) >> 6;
81 |
82 | std::cout << "POV: index=" << index << ", dir=" << dir << std::endl;
83 |
84 | bindings[i] = std::unique_ptr(new DIPovBinding(index, (DIPovBinding::POV_DIRECTION)dir));
85 | }
86 | break;
87 |
88 | case DIBinding::BINDING_TYPE::AXIS_BINDING:
89 | {
90 | int index = (mappings[i] & 0x3C) >> 2;
91 | bool isNegative = (mappings[i] & 0x40) >> 6;
92 |
93 | std::cout << "AXIS: index=" << index << ", negative=" << std::boolalpha << isNegative << std::endl;
94 | bindings[i] = std::unique_ptr(new DIAxisBinding(index, isNegative));
95 | }
96 | }
97 | }
98 | else if(type == DEVICE_TYPE::KEYBOARD)
99 | {
100 | std::wcout << "Key binding: " << mappings[i] << std::endl;
101 | bindings[i] = std::unique_ptr(new DIButtonBinding(mappings[i], true));
102 | }
103 | }
104 | }
105 |
106 | bool Controller::IsConnected()
107 | {
108 | return type != DEVICE_TYPE::NONE;
109 | }
110 |
111 | HRESULT Controller::Acquire()
112 | {
113 | if (type == DEVICE_TYPE::KEYBOARD)
114 | return true;
115 |
116 | if (!DIDevice)
117 | return false;
118 |
119 | return DIDevice->Acquire();
120 | }
121 |
122 | HRESULT Controller::Unacquire()
123 | {
124 | if (type == DEVICE_TYPE::KEYBOARD)
125 | return true;
126 |
127 | if (!DIDevice)
128 | return false;
129 |
130 | return DIDevice->Unacquire();
131 | }
132 |
133 | XINPUT_GAMEPAD Controller::GetState()
134 | {
135 | XINPUT_GAMEPAD XInputState = { 0 };
136 | DIJOYSTATE2 joystate = { 0 };
137 |
138 | if (type == DEVICE_TYPE::GAMEPAD)
139 | {
140 | HRESULT res = DIDevice->GetDeviceState(sizeof(joystate), &joystate);
141 |
142 | if (res == DIERR_INPUTLOST)
143 | {
144 | if (FAILED(DIDevice->Acquire()))
145 | {
146 | std::cout << "Failed to reacquire, returning last state instead." << std::endl;
147 | return lastState;
148 | }
149 |
150 | if(FAILED(DIDevice->GetDeviceState(sizeof(joystate), &joystate)))
151 | {
152 | std::cout << "Reacquired but failed to get state again. Returning last state." << std::endl;
153 | return lastState;
154 | }
155 | }
156 | else if(FAILED(res))
157 | {
158 | std::cout << "Failed to get state. HRESULT:" << std::hex << res << "(" << std::dec << res << ")" << std::endl;
159 | return lastState;
160 | }
161 | }
162 |
163 | for (auto& binding : bindings)
164 | if(binding)
165 | binding->Update(joystate);
166 |
167 | ANALOG_SUBVALUES subValues[2];
168 |
169 | for (int i = 0; i < bindings.size(); i++)
170 | {
171 | if (!bindings[i])
172 | continue;
173 |
174 | //XBOX Buttons
175 | if (i < 14)
176 | {
177 | switch (bindings[i]->type)
178 | {
179 | case DIBinding::POV_BINDING:
180 | case DIBinding::BUTTON_BINDING:
181 | {
182 | DIButtonBinding* button = dynamic_cast(bindings[i].get());
183 | DIPovBinding* pov = dynamic_cast(bindings[i].get());
184 |
185 | if ((pov && pov->GetState()) || (button && button->GetState()))
186 | XInputState.wButtons |= buttonFlags[i];
187 | }
188 | break;
189 | }
190 | }
191 | //Triggers
192 | else if (i >= 14 && i < 16)
193 | {
194 | switch (bindings[i]->type)
195 | {
196 | case DIBinding::POV_BINDING:
197 | case DIBinding::BUTTON_BINDING:
198 | {
199 | DIButtonBinding* button = dynamic_cast(bindings[i].get());
200 | DIPovBinding* pov = dynamic_cast(bindings[i].get());
201 |
202 | if ((pov && pov->GetState()) || (button && button->GetState()))
203 | {
204 | if (i == 14)
205 | XInputState.bLeftTrigger = 255;
206 | else
207 | XInputState.bRightTrigger = 255;
208 | }
209 | }
210 | break;
211 | }
212 | }
213 | //Analogs
214 | else
215 | {
216 | int direction = (i - 16) % 4;
217 | int analogIndex = (i - 16) / 4;
218 |
219 | switch (bindings[i]->type)
220 | {
221 | case DIBinding::BUTTON_BINDING:
222 | {
223 | DIButtonBinding* button = dynamic_cast(bindings[i].get());
224 |
225 | if (direction == 0)
226 | subValues[analogIndex].positiveY = button->GetState() ? 32768 : 0;
227 | else if (direction == 1)
228 | subValues[analogIndex].negativeY = button->GetState() ? -32768 : 0;
229 | else if (direction == 2)
230 | subValues[analogIndex].negativeX = button->GetState() ? -32768 : 0;
231 | else if (direction == 3)
232 | subValues[analogIndex].positiveX = button->GetState() ? 32768 : 0;
233 |
234 | }
235 | break;
236 |
237 | case DIBinding::AXIS_BINDING:
238 | {
239 | DIAxisBinding* axis = dynamic_cast(bindings[i].get());
240 |
241 | if (direction == 0)
242 | subValues[analogIndex].positiveY = axis->IsNegative() ? axis->GetValue() : axis->GetValue();
243 | else if(direction == 1)
244 | subValues[analogIndex].negativeY = axis->IsNegative() ? axis->GetValue() : -axis->GetValue();
245 | else if (direction == 2)
246 | subValues[analogIndex].negativeX = axis->IsNegative() ? axis->GetValue() : -axis->GetValue();
247 | else if (direction == 3)
248 | subValues[analogIndex].positiveX = axis->IsNegative() ? -axis->GetValue() : axis->GetValue();
249 | }
250 | break;
251 | }
252 | }
253 | }
254 |
255 | int LXValue = subValues[0].negativeX != 0 ? subValues[0].negativeX : subValues[0].positiveX;
256 | int LYValue = subValues[0].negativeY != 0 ? subValues[0].negativeY : subValues[0].positiveY;
257 | int RXValue = subValues[1].negativeX != 0 ? subValues[1].negativeX : subValues[1].positiveX;
258 | int RYValue = subValues[1].negativeY != 0 ? subValues[1].negativeY : subValues[1].positiveY;
259 |
260 | XInputState.sThumbLX = std::max(INT16_MIN, std::min(LXValue, INT16_MAX));
261 | XInputState.sThumbLY = std::max(INT16_MIN, std::min(LYValue, INT16_MAX));
262 | XInputState.sThumbRX = std::max(INT16_MIN, std::min(RXValue, INT16_MAX));
263 | XInputState.sThumbRY = std::max(INT16_MIN, std::min(RYValue, INT16_MAX));
264 |
265 | lastState = XInputState;
266 |
267 | return XInputState;
268 | }
269 |
--------------------------------------------------------------------------------
/HookDLL/HookDLL.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | 15.0
23 | {24569797-2891-48A2-84F6-DD9E343BF0F8}
24 | Win32Proj
25 | StubDLL
26 | 10.0.17134.0
27 | StubDLL
28 |
29 |
30 |
31 | DynamicLibrary
32 | true
33 | v141
34 | Unicode
35 |
36 |
37 | DynamicLibrary
38 | false
39 | v141
40 | true
41 | Unicode
42 |
43 |
44 | DynamicLibrary
45 | true
46 | v141
47 | Unicode
48 |
49 |
50 | DynamicLibrary
51 | false
52 | v141
53 | true
54 | Unicode
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | true
76 | $(SolutionDir)bin\$(Configuration)\DLLs\
77 | $(ProjectName)x86
78 |
79 |
80 | true
81 | $(SolutionDir)bin\$(Configuration)\DLLs
82 | $(ProjectName)x64
83 |
84 |
85 | false
86 | $(ProjectName)x86
87 | $(SolutionDir)bin\$(Configuration)\DLLs\
88 |
89 |
90 | false
91 | $(ProjectName)x64
92 | $(SolutionDir)bin\$(Configuration)\DLLs
93 |
94 |
95 |
96 | Use
97 | Level3
98 | Disabled
99 | true
100 | WIN32;_DEBUG;HOOKDLL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
101 | true
102 |
103 |
104 | Windows
105 | true
106 | Exports.def
107 | dinput8.lib;dxguid.lib;%(AdditionalDependencies)
108 |
109 |
110 |
111 |
112 | Use
113 | Level3
114 | Disabled
115 | true
116 | _DEBUG;HOOKDLL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
117 | true
118 |
119 |
120 | Windows
121 | true
122 | Exports.def
123 | dinput8.lib;dxguid.lib;%(AdditionalDependencies)
124 |
125 |
126 |
127 |
128 | Use
129 | Level3
130 | MaxSpeed
131 | true
132 | true
133 | true
134 | WIN32;NDEBUG;HOOKDLL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
135 | true
136 |
137 |
138 | Windows
139 | true
140 | true
141 | true
142 | Exports.def
143 | dinput8.lib;dxguid.lib;%(AdditionalDependencies)
144 |
145 |
146 |
147 |
148 | Use
149 | Level3
150 | MaxSpeed
151 | true
152 | true
153 | true
154 | NDEBUG;HOOKDLL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
155 | true
156 |
157 |
158 | Windows
159 | true
160 | true
161 | true
162 | Exports.def
163 | dinput8.lib;dxguid.lib;%(AdditionalDependencies)
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 | Create
181 | Create
182 | Create
183 | Create
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
--------------------------------------------------------------------------------
/di2xinput/MainForm.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Diagnostics;
6 | using System.Drawing;
7 | using System.IO;
8 | using System.Linq;
9 | using System.Text;
10 | using System.Threading;
11 | using System.Threading.Tasks;
12 | using System.Windows.Forms;
13 | using System.Xml.Serialization;
14 |
15 | namespace di2xinput
16 | {
17 | public partial class MainForm : Form
18 | {
19 | public static InputDialog inputDialog;
20 | private static DIManager.GamepadEntry selectedGamepad;
21 | private static int currentIndex = 0;
22 |
23 | public MainForm()
24 | {
25 | InitializeComponent();
26 | }
27 |
28 | private void MainForm_Load(object sender, EventArgs e)
29 | {
30 | ProgramManager.LoadEntries();
31 | ProfileManager.ReloadProfiles();
32 |
33 | for (int i = 0; i < ProgramManager.entries.programs.Count; i++)
34 | if (!ProfileManager.profiles.Any(x => x.Key == ProgramManager.entries.programs[i].profile))
35 | ProgramManager.entries.programs.RemoveAt(i);
36 |
37 | ProfileCombo_DropDown(null, null);
38 | DeviceCombo_DropDown(null, null);
39 |
40 | if (ProfileManager.profiles.Count == 0)
41 | {
42 | ProfileManager.activeProfile = new ProfileManager.Profile();
43 | }
44 | else
45 | {
46 | var startupProfile = ProfileManager.profiles.First();
47 | ProfileManager.activeProfile = startupProfile.Value;
48 | ProfileCombo.Text = startupProfile.Key;
49 | }
50 |
51 | UpdateDeviceCombo();
52 | UpdateMappingGrid();
53 | UpdateEntryList();
54 |
55 | foreach (var entry in ProgramManager.entries.programs)
56 | entry.ApplyConfig();
57 |
58 | }
59 |
60 | private void DeviceCombo_SelectedIndexChanged(object sender, EventArgs e)
61 | {
62 | for (int i = 0; i < 24; i++)
63 | ProfileManager.activeProfile.controllers[currentIndex].mapping[i] = 0;
64 |
65 | ChangeDeviceType();
66 |
67 | UpdateMappingGrid();
68 | }
69 |
70 | private void ChangeDeviceType()
71 | {
72 | if (DeviceCombo.SelectedItem.ToString() == "None")
73 | {
74 | ProfileManager.activeProfile.controllers[currentIndex].deviceType = Mapping.MappedDeviceType.None;
75 | selectedGamepad = null;
76 | }
77 | else if (DeviceCombo.SelectedItem.ToString() == "Keyboard")
78 | {
79 | ProfileManager.activeProfile.controllers[currentIndex].deviceType = Mapping.MappedDeviceType.Keyboard;
80 | selectedGamepad = null;
81 |
82 | }
83 | else
84 | {
85 | ProfileManager.activeProfile.controllers[currentIndex].deviceType = Mapping.MappedDeviceType.Controller;
86 |
87 | var gamepad = DIManager.GetGamepadFromName(DeviceCombo.SelectedItem.ToString());
88 |
89 | ProfileManager.activeProfile.controllers[currentIndex].instanceGUID = gamepad.instanceGUID.ToString();
90 | ProfileManager.activeProfile.controllers[currentIndex].productGUID = gamepad.productGUID.ToString();
91 |
92 | selectedGamepad = gamepad;
93 | }
94 | }
95 |
96 | private void DeviceCombo_DropDown(object sender, EventArgs e)
97 | {
98 | DeviceCombo.Items.Clear();
99 |
100 | DeviceCombo.Items.Add("None");
101 | DeviceCombo.Items.Add("Keyboard");
102 |
103 | foreach (var gamepad in DIManager.GetGamepads())
104 | DeviceCombo.Items.Add(gamepad.joystick.Properties.ProductName);
105 | }
106 |
107 |
108 | private void MappingGrid_CellClick(object sender, DataGridViewCellEventArgs e)
109 | {
110 | if (e.RowIndex >= 0 && e.ColumnIndex == 1)
111 | {
112 | inputDialog = new InputDialog(MappingGrid.Rows[e.RowIndex].Cells[0].Value.ToString(), selectedGamepad);
113 | var result = inputDialog.ShowDialog();
114 |
115 | if (result != DialogResult.Cancel)
116 | {
117 | if (ProfileManager.activeProfile.controllers[currentIndex].deviceType == Mapping.MappedDeviceType.Controller)
118 | {
119 | MappingGrid.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = DIManager.GetNameFromMapping(inputDialog.resultJoystickMapping);
120 | ProfileManager.activeProfile.controllers[currentIndex].mapping[e.RowIndex] = inputDialog.resultJoystickMapping;
121 | }
122 | else if (ProfileManager.activeProfile.controllers[currentIndex].deviceType == Mapping.MappedDeviceType.Keyboard)
123 | {
124 | MappingGrid.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = Mapping.GetNameFromScancode(inputDialog.resultScancode);
125 | ProfileManager.activeProfile.controllers[currentIndex].mapping[e.RowIndex] = inputDialog.resultScancode;
126 | }
127 | }
128 | else
129 | {
130 | ProfileManager.activeProfile.controllers[currentIndex].mapping[e.RowIndex] = 0;
131 | }
132 | }
133 | }
134 |
135 |
136 | private void ProfileCombo_DropDown(object sender, EventArgs e)
137 | {
138 | ProfileManager.ReloadProfiles();
139 | ProfileCombo.Items.Clear();
140 |
141 | foreach (var profile in ProfileManager.profiles)
142 | ProfileCombo.Items.Add(profile.Key);
143 | }
144 |
145 | private void ProfileCombo_SelectedIndexChanged(object sender, EventArgs e)
146 | {
147 | ProfileManager.Profile profile = ProfileManager.profiles.FirstOrDefault(x => x.Key == ProfileCombo.SelectedItem.ToString()).Value;
148 |
149 | if (profile != null)
150 | {
151 | ProfileManager.activeProfile = profile;
152 | UpdateDeviceCombo();
153 | ChangeDeviceType();
154 | UpdateMappingGrid();
155 | }
156 |
157 | }
158 |
159 | private void SaveButton_Click(object sender, EventArgs e)
160 | {
161 | if(ProfileCombo.Text != "")
162 | {
163 | ProfileManager.SaveCurrentProfile(ProfileCombo.Text);
164 | ProfileManager.ReloadProfiles();
165 | UpdateEntryList();
166 |
167 | foreach(ProgramManager.ProgramEntry entry in ProgramManager.entries.programs.Where(x => x.profile == ProfileCombo.Text))
168 | entry.ApplyConfig();
169 | }
170 | }
171 |
172 | private void AddButton_Click(object sender, EventArgs e)
173 | {
174 | if(ProfileManager.profiles.Count == 0)
175 | {
176 | MessageBox.Show("No profiles have been created. Please create a new profile.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
177 | return;
178 | }
179 |
180 | var result = openProgramDialog.ShowDialog();
181 |
182 | if(result == DialogResult.OK)
183 | {
184 |
185 | if(ProgramManager.entries.programs.Any(x => x.path == openProgramDialog.FileName))
186 | {
187 | MessageBox.Show("This program has already been added to the list.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
188 | return;
189 | }
190 |
191 | var newEntry = new ProgramManager.ProgramEntry()
192 | {
193 | icon = null,
194 | path = openProgramDialog.FileName,
195 | profile = ProfileManager.profiles.First().Key,
196 | XIVersion = "Finding..."
197 | };
198 |
199 | string fileName = openProgramDialog.FileName;
200 | int entryIndex = ProgramManager.entries.programs.Count;
201 |
202 | ProgramManager.entries.programs.Add(newEntry);
203 |
204 | UpdateEntryList();
205 |
206 | Task> getVersionTask = new Task>(() =>
207 | {
208 | return GetXInputVersion(fileName, entryIndex);
209 | });
210 |
211 | getVersionTask.Start();
212 |
213 | getVersionTask.ContinueWith(task =>
214 | {
215 | ProgramManager.entries.programs[task.Result.Item1].XIVersion = task.Result.Item2;
216 | ProgramManager.entries.programs[task.Result.Item1].ApplyConfig();
217 | ProgramManager.SaveEntries();
218 | UpdateEntryList();
219 | });
220 | }
221 | }
222 |
223 | private void RemoveButton_Click(object sender, EventArgs e)
224 | {
225 | if(ProgramGrid.SelectedRows.Count > 0)
226 | {
227 | var entry = ProgramManager.entries.programs[ProgramGrid.CurrentCell.RowIndex];
228 | entry.RemoveConfig();
229 | ProgramManager.entries.programs.Remove(entry);
230 | ProgramManager.SaveEntries();
231 | UpdateEntryList();
232 | }
233 | }
234 |
235 | private void ControllerTabs_SelectedIndexChanged(object sender, EventArgs e)
236 | {
237 | if (ControllerTabs.SelectedIndex < 4)
238 | {
239 | Control[] controls = new Control[ControllerTabs.TabPages[currentIndex].Controls.Count];
240 | ControllerTabs.TabPages[currentIndex].Controls.CopyTo(controls, 0);
241 | ControllerTabs.TabPages[currentIndex].Controls.Clear();
242 | ControllerTabs.TabPages[ControllerTabs.SelectedIndex].Controls.AddRange(controls);
243 |
244 | currentIndex = ControllerTabs.SelectedIndex;
245 |
246 | UpdateDeviceCombo();
247 | UpdateMappingGrid();
248 | }
249 | }
250 |
251 | private void UpdateEntryList()
252 | {
253 | this.BeginInvoke(new Action(() =>
254 | {
255 | ProgramGrid.Rows.Clear();
256 | ProfileColumn.Items.Clear();
257 |
258 | foreach (var profile in ProfileManager.profiles)
259 | ProfileColumn.Items.Add(profile.Key);
260 |
261 | foreach (var entry in ProgramManager.entries.programs)
262 | {
263 | ProgramGrid.Rows.Add(new object[] { Icon.ExtractAssociatedIcon(entry.path), entry.path, entry.XIVersion, entry.profile });
264 | }
265 | }));
266 | }
267 |
268 | private void UpdateMappingGrid()
269 | {
270 | MappingGrid.Rows.Clear();
271 |
272 | if(ProfileManager.activeProfile.controllers[currentIndex].deviceType != Mapping.MappedDeviceType.None)
273 | {
274 | for(int i = 0; i < XIManager.xinputButtonNames.Count; i++)
275 | {
276 | ushort mappingValue = ProfileManager.activeProfile.controllers[currentIndex].mapping[i];
277 | string mappingName = "";
278 |
279 | if (ProfileManager.activeProfile.controllers[currentIndex].deviceType == Mapping.MappedDeviceType.Keyboard)
280 | {
281 | if (mappingValue != 0)
282 | mappingName = Mapping.GetNameFromScancode(mappingValue);
283 | }
284 | else
285 | {
286 | if (mappingValue != 0)
287 | mappingName = DIManager.GetNameFromMapping(mappingValue);
288 | }
289 |
290 | MappingGrid.Rows.Add(new object[] { XIManager.xinputButtonNames[i], mappingName });
291 | }
292 | }
293 | }
294 |
295 | private void UpdateDeviceCombo()
296 | {
297 | DeviceCombo.SelectedIndexChanged -= new EventHandler(DeviceCombo_SelectedIndexChanged);
298 |
299 | if (ProfileManager.activeProfile.controllers[currentIndex].deviceType == Mapping.MappedDeviceType.None)
300 | {
301 | DeviceCombo.Text = "None";
302 | }
303 | else if (ProfileManager.activeProfile.controllers[currentIndex].deviceType == Mapping.MappedDeviceType.Keyboard)
304 | {
305 | DeviceCombo.Text = "Keyboard";
306 | }
307 | else if (ProfileManager.activeProfile.controllers[currentIndex].deviceType == Mapping.MappedDeviceType.Controller)
308 | {
309 | DIManager.GamepadEntry gamepad = DIManager.GetGamepadFromGUIDs(ProfileManager.activeProfile.controllers[currentIndex].productGUID, ProfileManager.activeProfile.controllers[currentIndex].instanceGUID);
310 |
311 | if (gamepad != null)
312 | {
313 | DeviceCombo.Text = gamepad.joystick.Properties.ProductName;
314 | }
315 | else
316 | {
317 | DeviceCombo.Text = "None";
318 | ProfileManager.activeProfile.controllers[currentIndex].deviceType = Mapping.MappedDeviceType.None;
319 | }
320 | }
321 |
322 | DeviceCombo.SelectedIndexChanged += new EventHandler(DeviceCombo_SelectedIndexChanged);
323 | }
324 |
325 | private Tuple GetXInputVersion(string filename, int entryIndex)
326 | {
327 | string version = "Unknown";
328 |
329 | ProcessStartInfo processStartInfo = new ProcessStartInfo()
330 | {
331 | WindowStyle = ProcessWindowStyle.Minimized,
332 | UseShellExecute = true,
333 | WorkingDirectory = filename.Substring(0, filename.LastIndexOf("\\") + 1),
334 | FileName = filename
335 | };
336 |
337 | Process proc = Process.Start(processStartInfo);
338 |
339 | WinAPI.BinaryType binaryType;
340 | WinAPI.GetBinaryType(filename, out binaryType);
341 |
342 | for (int i = 0; i < 10; i++)
343 | {
344 | if (proc.HasExited)
345 | break;
346 |
347 | var xinputDLLx86 = WinAPI.GetModuleNames(proc).Where(x => x.ToLower().Contains("xinput")).FirstOrDefault();
348 | var xinputDLLx64 = WinAPI.GetModuleNames(proc, true).Where(x => x.ToLower().Contains("xinput")).FirstOrDefault();
349 |
350 | if (xinputDLLx86 != null)
351 | {
352 | version = xinputDLLx86.ToLower();
353 | version = version.Substring(version.LastIndexOf("\\") + 1).Replace("xinput", "");
354 | version = version.Substring(0, version.Length - 4);
355 | version += " x86";
356 | break;
357 | }
358 | else if (xinputDLLx64 != null)
359 | {
360 | version = xinputDLLx64.ToLower();
361 | version = version.Substring(version.LastIndexOf("\\") + 1).Replace("xinput", "");
362 | version = version.Substring(0, version.Length - 4);
363 | version += " x64";
364 | break;
365 | }
366 |
367 | Thread.Sleep(1000);
368 | }
369 |
370 | if (!proc.HasExited)
371 | proc.Kill();
372 |
373 | if (version == "Unknown")
374 | version += binaryType == WinAPI.BinaryType.SCS_32BIT_BINARY ? " x86" : " x64";
375 |
376 | return new Tuple(entryIndex, version);
377 | }
378 |
379 | private void ProgramGrid_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
380 | {
381 | if (ProgramGrid.CurrentCell.ColumnIndex == 3 && e.Control is ComboBox)
382 | {
383 | ComboBox comboBox = e.Control as ComboBox;
384 | comboBox.SelectedIndexChanged -= ProfileChangedEvent;
385 | comboBox.SelectedIndexChanged += ProfileChangedEvent;
386 | }
387 | }
388 |
389 | private void ProfileChangedEvent(object sender, EventArgs e)
390 | {
391 | var currentCell = ProgramGrid.CurrentCellAddress;
392 | var comboBox = sender as DataGridViewComboBoxEditingControl;
393 |
394 | ProgramManager.entries.programs[currentCell.Y].profile = comboBox.EditingControlFormattedValue.ToString();
395 | ProgramManager.entries.programs[currentCell.Y].ApplyConfig();
396 | ProgramManager.SaveEntries();
397 | }
398 | }
399 | }
400 |
--------------------------------------------------------------------------------
/di2xinput/MainForm.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace di2xinput
2 | {
3 | partial class MainForm
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new System.Windows.Forms.DataGridViewCellStyle();
32 | this.tabControl1 = new System.Windows.Forms.TabControl();
33 | this.ProgramTab = new System.Windows.Forms.TabPage();
34 | this.RemoveButton = new System.Windows.Forms.Button();
35 | this.AddButton = new System.Windows.Forms.Button();
36 | this.ProgramGrid = new System.Windows.Forms.DataGridView();
37 | this.IconColumn = new System.Windows.Forms.DataGridViewImageColumn();
38 | this.PathColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
39 | this.VersionColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
40 | this.ProfileColumn = new System.Windows.Forms.DataGridViewComboBoxColumn();
41 | this.ProfileTab = new System.Windows.Forms.TabPage();
42 | this.ControllerTabs = new System.Windows.Forms.TabControl();
43 | this.tabPage3 = new System.Windows.Forms.TabPage();
44 | this.DeviceCombo = new System.Windows.Forms.ComboBox();
45 | this.label1 = new System.Windows.Forms.Label();
46 | this.ControllerPicture = new System.Windows.Forms.PictureBox();
47 | this.MappingGrid = new System.Windows.Forms.DataGridView();
48 | this.Column1 = new System.Windows.Forms.DataGridViewTextBoxColumn();
49 | this.Column2 = new System.Windows.Forms.DataGridViewTextBoxColumn();
50 | this.tabPage4 = new System.Windows.Forms.TabPage();
51 | this.tabPage5 = new System.Windows.Forms.TabPage();
52 | this.tabPage6 = new System.Windows.Forms.TabPage();
53 | this.button1 = new System.Windows.Forms.Button();
54 | this.ProfileCombo = new System.Windows.Forms.ComboBox();
55 | this.label2 = new System.Windows.Forms.Label();
56 | this.SettingsTab = new System.Windows.Forms.TabPage();
57 | this.openProgramDialog = new System.Windows.Forms.OpenFileDialog();
58 | this.tabControl1.SuspendLayout();
59 | this.ProgramTab.SuspendLayout();
60 | ((System.ComponentModel.ISupportInitialize)(this.ProgramGrid)).BeginInit();
61 | this.ProfileTab.SuspendLayout();
62 | this.ControllerTabs.SuspendLayout();
63 | this.tabPage3.SuspendLayout();
64 | ((System.ComponentModel.ISupportInitialize)(this.ControllerPicture)).BeginInit();
65 | ((System.ComponentModel.ISupportInitialize)(this.MappingGrid)).BeginInit();
66 | this.SuspendLayout();
67 | //
68 | // tabControl1
69 | //
70 | this.tabControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
71 | | System.Windows.Forms.AnchorStyles.Left)
72 | | System.Windows.Forms.AnchorStyles.Right)));
73 | this.tabControl1.Controls.Add(this.ProgramTab);
74 | this.tabControl1.Controls.Add(this.ProfileTab);
75 | this.tabControl1.Controls.Add(this.SettingsTab);
76 | this.tabControl1.Location = new System.Drawing.Point(8, 9);
77 | this.tabControl1.Name = "tabControl1";
78 | this.tabControl1.SelectedIndex = 0;
79 | this.tabControl1.Size = new System.Drawing.Size(569, 346);
80 | this.tabControl1.TabIndex = 0;
81 | //
82 | // ProgramTab
83 | //
84 | this.ProgramTab.Controls.Add(this.RemoveButton);
85 | this.ProgramTab.Controls.Add(this.AddButton);
86 | this.ProgramTab.Controls.Add(this.ProgramGrid);
87 | this.ProgramTab.Location = new System.Drawing.Point(4, 22);
88 | this.ProgramTab.Name = "ProgramTab";
89 | this.ProgramTab.Padding = new System.Windows.Forms.Padding(3);
90 | this.ProgramTab.Size = new System.Drawing.Size(561, 320);
91 | this.ProgramTab.TabIndex = 0;
92 | this.ProgramTab.Text = "Program List";
93 | this.ProgramTab.UseVisualStyleBackColor = true;
94 | //
95 | // RemoveButton
96 | //
97 | this.RemoveButton.Anchor = System.Windows.Forms.AnchorStyles.Bottom;
98 | this.RemoveButton.Location = new System.Drawing.Point(283, 289);
99 | this.RemoveButton.Name = "RemoveButton";
100 | this.RemoveButton.Size = new System.Drawing.Size(103, 23);
101 | this.RemoveButton.TabIndex = 2;
102 | this.RemoveButton.Text = "Remove program";
103 | this.RemoveButton.UseVisualStyleBackColor = true;
104 | this.RemoveButton.Click += new System.EventHandler(this.RemoveButton_Click);
105 | //
106 | // AddButton
107 | //
108 | this.AddButton.Anchor = System.Windows.Forms.AnchorStyles.Bottom;
109 | this.AddButton.Location = new System.Drawing.Point(174, 289);
110 | this.AddButton.Name = "AddButton";
111 | this.AddButton.Size = new System.Drawing.Size(103, 23);
112 | this.AddButton.TabIndex = 1;
113 | this.AddButton.Text = "Add program";
114 | this.AddButton.UseVisualStyleBackColor = true;
115 | this.AddButton.Click += new System.EventHandler(this.AddButton_Click);
116 | //
117 | // ProgramGrid
118 | //
119 | this.ProgramGrid.AllowUserToAddRows = false;
120 | this.ProgramGrid.AllowUserToDeleteRows = false;
121 | this.ProgramGrid.AllowUserToResizeRows = false;
122 | this.ProgramGrid.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
123 | | System.Windows.Forms.AnchorStyles.Left)
124 | | System.Windows.Forms.AnchorStyles.Right)));
125 | this.ProgramGrid.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.DisplayedCells;
126 | this.ProgramGrid.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
127 | this.ProgramGrid.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
128 | this.IconColumn,
129 | this.PathColumn,
130 | this.VersionColumn,
131 | this.ProfileColumn});
132 | this.ProgramGrid.EditMode = System.Windows.Forms.DataGridViewEditMode.EditOnEnter;
133 | this.ProgramGrid.Location = new System.Drawing.Point(4, 3);
134 | this.ProgramGrid.MultiSelect = false;
135 | this.ProgramGrid.Name = "ProgramGrid";
136 | this.ProgramGrid.RowHeadersVisible = false;
137 | this.ProgramGrid.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
138 | this.ProgramGrid.ShowCellErrors = false;
139 | this.ProgramGrid.ShowCellToolTips = false;
140 | this.ProgramGrid.ShowEditingIcon = false;
141 | this.ProgramGrid.ShowRowErrors = false;
142 | this.ProgramGrid.Size = new System.Drawing.Size(552, 280);
143 | this.ProgramGrid.TabIndex = 0;
144 | this.ProgramGrid.EditingControlShowing += new System.Windows.Forms.DataGridViewEditingControlShowingEventHandler(this.ProgramGrid_EditingControlShowing);
145 | //
146 | // IconColumn
147 | //
148 | this.IconColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.ColumnHeader;
149 | this.IconColumn.FillWeight = 20F;
150 | this.IconColumn.HeaderText = "Icon";
151 | this.IconColumn.Name = "IconColumn";
152 | this.IconColumn.ReadOnly = true;
153 | this.IconColumn.Resizable = System.Windows.Forms.DataGridViewTriState.False;
154 | this.IconColumn.Width = 32;
155 | //
156 | // PathColumn
157 | //
158 | this.PathColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.None;
159 | dataGridViewCellStyle2.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
160 | this.PathColumn.DefaultCellStyle = dataGridViewCellStyle2;
161 | this.PathColumn.FillWeight = 80F;
162 | this.PathColumn.HeaderText = "Path";
163 | this.PathColumn.Name = "PathColumn";
164 | this.PathColumn.ReadOnly = true;
165 | this.PathColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
166 | this.PathColumn.Width = 277;
167 | //
168 | // VersionColumn
169 | //
170 | this.VersionColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.None;
171 | this.VersionColumn.HeaderText = "XI Version";
172 | this.VersionColumn.Name = "VersionColumn";
173 | this.VersionColumn.ReadOnly = true;
174 | this.VersionColumn.Resizable = System.Windows.Forms.DataGridViewTriState.False;
175 | this.VersionColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
176 | this.VersionColumn.Width = 90;
177 | //
178 | // ProfileColumn
179 | //
180 | this.ProfileColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.None;
181 | this.ProfileColumn.DisplayStyle = System.Windows.Forms.DataGridViewComboBoxDisplayStyle.ComboBox;
182 | this.ProfileColumn.FillWeight = 20F;
183 | this.ProfileColumn.HeaderText = "Profile";
184 | this.ProfileColumn.Name = "ProfileColumn";
185 | this.ProfileColumn.Resizable = System.Windows.Forms.DataGridViewTriState.False;
186 | this.ProfileColumn.Width = 150;
187 | //
188 | // ProfileTab
189 | //
190 | this.ProfileTab.Controls.Add(this.ControllerTabs);
191 | this.ProfileTab.Controls.Add(this.button1);
192 | this.ProfileTab.Controls.Add(this.ProfileCombo);
193 | this.ProfileTab.Controls.Add(this.label2);
194 | this.ProfileTab.Location = new System.Drawing.Point(4, 22);
195 | this.ProfileTab.Name = "ProfileTab";
196 | this.ProfileTab.Padding = new System.Windows.Forms.Padding(3);
197 | this.ProfileTab.Size = new System.Drawing.Size(561, 320);
198 | this.ProfileTab.TabIndex = 1;
199 | this.ProfileTab.Text = "Edit Profile";
200 | this.ProfileTab.UseVisualStyleBackColor = true;
201 | //
202 | // ControllerTabs
203 | //
204 | this.ControllerTabs.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
205 | | System.Windows.Forms.AnchorStyles.Left)
206 | | System.Windows.Forms.AnchorStyles.Right)));
207 | this.ControllerTabs.Controls.Add(this.tabPage3);
208 | this.ControllerTabs.Controls.Add(this.tabPage4);
209 | this.ControllerTabs.Controls.Add(this.tabPage5);
210 | this.ControllerTabs.Controls.Add(this.tabPage6);
211 | this.ControllerTabs.Location = new System.Drawing.Point(7, 37);
212 | this.ControllerTabs.Name = "ControllerTabs";
213 | this.ControllerTabs.SelectedIndex = 0;
214 | this.ControllerTabs.Size = new System.Drawing.Size(548, 277);
215 | this.ControllerTabs.TabIndex = 9;
216 | this.ControllerTabs.SelectedIndexChanged += new System.EventHandler(this.ControllerTabs_SelectedIndexChanged);
217 | //
218 | // tabPage3
219 | //
220 | this.tabPage3.Controls.Add(this.DeviceCombo);
221 | this.tabPage3.Controls.Add(this.label1);
222 | this.tabPage3.Controls.Add(this.ControllerPicture);
223 | this.tabPage3.Controls.Add(this.MappingGrid);
224 | this.tabPage3.Location = new System.Drawing.Point(4, 22);
225 | this.tabPage3.Name = "tabPage3";
226 | this.tabPage3.Padding = new System.Windows.Forms.Padding(3);
227 | this.tabPage3.Size = new System.Drawing.Size(540, 251);
228 | this.tabPage3.TabIndex = 0;
229 | this.tabPage3.Text = "Controller 1";
230 | this.tabPage3.UseVisualStyleBackColor = true;
231 | //
232 | // DeviceCombo
233 | //
234 | this.DeviceCombo.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
235 | | System.Windows.Forms.AnchorStyles.Right)));
236 | this.DeviceCombo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
237 | this.DeviceCombo.FormattingEnabled = true;
238 | this.DeviceCombo.Items.AddRange(new object[] {
239 | "None",
240 | "Keyboard"});
241 | this.DeviceCombo.Location = new System.Drawing.Point(99, 8);
242 | this.DeviceCombo.Name = "DeviceCombo";
243 | this.DeviceCombo.Size = new System.Drawing.Size(433, 21);
244 | this.DeviceCombo.TabIndex = 13;
245 | this.DeviceCombo.DropDown += new System.EventHandler(this.DeviceCombo_DropDown);
246 | this.DeviceCombo.SelectedIndexChanged += new System.EventHandler(this.DeviceCombo_SelectedIndexChanged);
247 | //
248 | // label1
249 | //
250 | this.label1.AutoSize = true;
251 | this.label1.Location = new System.Drawing.Point(9, 11);
252 | this.label1.Name = "label1";
253 | this.label1.Size = new System.Drawing.Size(84, 13);
254 | this.label1.TabIndex = 12;
255 | this.label1.Text = "Mapped device:";
256 | //
257 | // ControllerPicture
258 | //
259 | this.ControllerPicture.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
260 | | System.Windows.Forms.AnchorStyles.Left)
261 | | System.Windows.Forms.AnchorStyles.Right)));
262 | this.ControllerPicture.Image = global::di2xinput.Properties.Resources.Xbox_Controller;
263 | this.ControllerPicture.Location = new System.Drawing.Point(9, 35);
264 | this.ControllerPicture.Name = "ControllerPicture";
265 | this.ControllerPicture.Size = new System.Drawing.Size(275, 208);
266 | this.ControllerPicture.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
267 | this.ControllerPicture.TabIndex = 11;
268 | this.ControllerPicture.TabStop = false;
269 | //
270 | // MappingGrid
271 | //
272 | this.MappingGrid.AllowUserToAddRows = false;
273 | this.MappingGrid.AllowUserToDeleteRows = false;
274 | this.MappingGrid.AllowUserToResizeColumns = false;
275 | this.MappingGrid.AllowUserToResizeRows = false;
276 | this.MappingGrid.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
277 | | System.Windows.Forms.AnchorStyles.Right)));
278 | this.MappingGrid.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
279 | this.MappingGrid.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
280 | this.Column1,
281 | this.Column2});
282 | this.MappingGrid.EditMode = System.Windows.Forms.DataGridViewEditMode.EditProgrammatically;
283 | this.MappingGrid.Location = new System.Drawing.Point(292, 35);
284 | this.MappingGrid.MultiSelect = false;
285 | this.MappingGrid.Name = "MappingGrid";
286 | this.MappingGrid.ReadOnly = true;
287 | this.MappingGrid.RowHeadersVisible = false;
288 | this.MappingGrid.RowHeadersWidthSizeMode = System.Windows.Forms.DataGridViewRowHeadersWidthSizeMode.DisableResizing;
289 | this.MappingGrid.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
290 | this.MappingGrid.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.CellSelect;
291 | this.MappingGrid.ShowCellErrors = false;
292 | this.MappingGrid.ShowCellToolTips = false;
293 | this.MappingGrid.ShowEditingIcon = false;
294 | this.MappingGrid.ShowRowErrors = false;
295 | this.MappingGrid.Size = new System.Drawing.Size(240, 208);
296 | this.MappingGrid.TabIndex = 10;
297 | this.MappingGrid.CellClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.MappingGrid_CellClick);
298 | //
299 | // Column1
300 | //
301 | this.Column1.HeaderText = "Binding";
302 | this.Column1.Name = "Column1";
303 | this.Column1.ReadOnly = true;
304 | //
305 | // Column2
306 | //
307 | this.Column2.HeaderText = "Mapping";
308 | this.Column2.Name = "Column2";
309 | this.Column2.ReadOnly = true;
310 | this.Column2.Width = 120;
311 | //
312 | // tabPage4
313 | //
314 | this.tabPage4.Location = new System.Drawing.Point(4, 22);
315 | this.tabPage4.Name = "tabPage4";
316 | this.tabPage4.Padding = new System.Windows.Forms.Padding(3);
317 | this.tabPage4.Size = new System.Drawing.Size(540, 251);
318 | this.tabPage4.TabIndex = 1;
319 | this.tabPage4.Text = "Controller 2";
320 | this.tabPage4.UseVisualStyleBackColor = true;
321 | //
322 | // tabPage5
323 | //
324 | this.tabPage5.Location = new System.Drawing.Point(4, 22);
325 | this.tabPage5.Name = "tabPage5";
326 | this.tabPage5.Size = new System.Drawing.Size(540, 251);
327 | this.tabPage5.TabIndex = 2;
328 | this.tabPage5.Text = "Controller 3";
329 | this.tabPage5.UseVisualStyleBackColor = true;
330 | //
331 | // tabPage6
332 | //
333 | this.tabPage6.Location = new System.Drawing.Point(4, 22);
334 | this.tabPage6.Name = "tabPage6";
335 | this.tabPage6.Size = new System.Drawing.Size(540, 251);
336 | this.tabPage6.TabIndex = 3;
337 | this.tabPage6.Text = "Controller 4";
338 | this.tabPage6.UseVisualStyleBackColor = true;
339 | //
340 | // button1
341 | //
342 | this.button1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
343 | this.button1.Location = new System.Drawing.Point(485, 9);
344 | this.button1.Name = "button1";
345 | this.button1.Size = new System.Drawing.Size(67, 23);
346 | this.button1.TabIndex = 12;
347 | this.button1.Text = "Save";
348 | this.button1.UseVisualStyleBackColor = true;
349 | this.button1.Click += new System.EventHandler(this.SaveButton_Click);
350 | //
351 | // ProfileCombo
352 | //
353 | this.ProfileCombo.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
354 | | System.Windows.Forms.AnchorStyles.Right)));
355 | this.ProfileCombo.FormattingEnabled = true;
356 | this.ProfileCombo.Location = new System.Drawing.Point(86, 10);
357 | this.ProfileCombo.Name = "ProfileCombo";
358 | this.ProfileCombo.Size = new System.Drawing.Size(393, 21);
359 | this.ProfileCombo.TabIndex = 11;
360 | this.ProfileCombo.DropDown += new System.EventHandler(this.ProfileCombo_DropDown);
361 | this.ProfileCombo.SelectedIndexChanged += new System.EventHandler(this.ProfileCombo_SelectedIndexChanged);
362 | //
363 | // label2
364 | //
365 | this.label2.AutoSize = true;
366 | this.label2.Location = new System.Drawing.Point(10, 13);
367 | this.label2.Name = "label2";
368 | this.label2.Size = new System.Drawing.Size(70, 13);
369 | this.label2.TabIndex = 10;
370 | this.label2.Text = "Profile Name:";
371 | //
372 | // SettingsTab
373 | //
374 | this.SettingsTab.Location = new System.Drawing.Point(4, 22);
375 | this.SettingsTab.Name = "SettingsTab";
376 | this.SettingsTab.Padding = new System.Windows.Forms.Padding(3);
377 | this.SettingsTab.Size = new System.Drawing.Size(561, 320);
378 | this.SettingsTab.TabIndex = 2;
379 | this.SettingsTab.Text = "Settings";
380 | this.SettingsTab.UseVisualStyleBackColor = true;
381 | //
382 | // openProgramDialog
383 | //
384 | this.openProgramDialog.Filter = "Executable File | *.exe";
385 | //
386 | // MainForm
387 | //
388 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
389 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
390 | this.ClientSize = new System.Drawing.Size(584, 361);
391 | this.Controls.Add(this.tabControl1);
392 | this.MinimumSize = new System.Drawing.Size(600, 400);
393 | this.Name = "MainForm";
394 | this.Text = "DirectInput to XInput Converter";
395 | this.Load += new System.EventHandler(this.MainForm_Load);
396 | this.tabControl1.ResumeLayout(false);
397 | this.ProgramTab.ResumeLayout(false);
398 | ((System.ComponentModel.ISupportInitialize)(this.ProgramGrid)).EndInit();
399 | this.ProfileTab.ResumeLayout(false);
400 | this.ProfileTab.PerformLayout();
401 | this.ControllerTabs.ResumeLayout(false);
402 | this.tabPage3.ResumeLayout(false);
403 | this.tabPage3.PerformLayout();
404 | ((System.ComponentModel.ISupportInitialize)(this.ControllerPicture)).EndInit();
405 | ((System.ComponentModel.ISupportInitialize)(this.MappingGrid)).EndInit();
406 | this.ResumeLayout(false);
407 |
408 | }
409 |
410 | #endregion
411 |
412 | private System.Windows.Forms.TabControl tabControl1;
413 | private System.Windows.Forms.TabPage ProgramTab;
414 | private System.Windows.Forms.TabPage ProfileTab;
415 | private System.Windows.Forms.Button button1;
416 | private System.Windows.Forms.ComboBox ProfileCombo;
417 | private System.Windows.Forms.Label label2;
418 | private System.Windows.Forms.TabControl ControllerTabs;
419 | private System.Windows.Forms.TabPage tabPage3;
420 | private System.Windows.Forms.TabPage tabPage4;
421 | private System.Windows.Forms.TabPage tabPage5;
422 | private System.Windows.Forms.TabPage tabPage6;
423 | private System.Windows.Forms.DataGridView ProgramGrid;
424 | private System.Windows.Forms.Button RemoveButton;
425 | private System.Windows.Forms.Button AddButton;
426 | private System.Windows.Forms.TabPage SettingsTab;
427 | private System.Windows.Forms.OpenFileDialog openProgramDialog;
428 | private System.Windows.Forms.DataGridViewImageColumn IconColumn;
429 | private System.Windows.Forms.DataGridViewTextBoxColumn PathColumn;
430 | private System.Windows.Forms.DataGridViewTextBoxColumn VersionColumn;
431 | private System.Windows.Forms.DataGridViewComboBoxColumn ProfileColumn;
432 | private System.Windows.Forms.ComboBox DeviceCombo;
433 | private System.Windows.Forms.Label label1;
434 | private System.Windows.Forms.PictureBox ControllerPicture;
435 | private System.Windows.Forms.DataGridView MappingGrid;
436 | private System.Windows.Forms.DataGridViewTextBoxColumn Column1;
437 | private System.Windows.Forms.DataGridViewTextBoxColumn Column2;
438 | }
439 | }
--------------------------------------------------------------------------------