How would I go about creating a "gamepad" which appears to DirectInput applications as a normal game controller but the state of its controls is actually defined by software?
5 Answers
Write a device driver to pretend to be one.
Specifically, Windows device drivers handle what are called Interrupt Requests via the Interrupt Request Protocol - which boils down to a wrapped up structure and a set of buffers internally in the driver.
Now the next thing you need to know is that many drivers are actually layered, or stacked, or whichever name you want to use. So for example to write a disk driver, you might interface with the driver above it (as a disk class) but use a driver below it (scsi port, for example) to actually send commands to your devices.
That's how real devices work. Fake devices need to conform to the top level interface requirements, e.g. a disk, or a controller, or a mouse, or whatever it is. However, underneath they can do anything they like - return whatever values they like.
This opens up the possibility of controlling a driver via a user-mode application and pretending to "be" a device. To send a driver messages, you can DeviceIoControl
to it; then to actually get those messages you can either:
- Stuff them in the Irp that makes up that DeviceIoControl.
- Have the driver read them out of your process' memory space.
Drivers can also access \\Registry\\Machine
and various other, non-user-specific non-explorer registry areas, so it is possible to communicate that way.
Finally, there's no saying you can't filter existing IO, rather than make it all up via a new device. There are a great many options and ways you can go about doing this.
If you're going to do this, you'll need:
- VirtualKD or an expensive debugger cable and two PCs.
You probably also want to start with the references on this blog post. You'll find that there are essentially a bazillion different names for driver code, so I'll interpret some of them:
- WDM = Windows Driver Model, basically the NT driver model mixed with (some of) Windows 9x.
- KMDF = Kernel mode driver framework - drivers of the above type use this, plus additionally WDF (Windows Driver Foundation) which is a set of libraries on top of WDM to make it quicker to use.
- UMDF = User mode driver framework - write a driver without the danger of kernel mode. If you can, use this, as kernel mode drivers that go wrong will bluescreen (in driver parlance, bugcheck) your system.
Edit: I'm not massively knowledgeable on DirectInput - there may be a way to override the various API controls in use via DLL redirection and the like, which may be simpler than the way I've described.
-
Thanks for the intro to driver dev! My actual intent is to fix the 360 controller's DirectInput support. Currently, you can use it with DI but with limitations; can't address the triggers separately, can't use the triggers as buttons (so it won't work with anything expecting four shoulder buttons), and no vibr[...] Jul 29, 2012 at 20:37
-
[...]ation. Your edit was my original intention; but DI doesn't use traditionally linked functions, instead linking only DirectInputCreate which returns a structure with function pointers, and it also seems to provide different interfaces for C and C++. That turned me off that route, but a fake driver looks even harder, so I think I'll give it another try. (Before anyone suggests XBCD, it breaks native xinput support.) Jul 29, 2012 at 20:37
There is vJoy opensource project: http://sourceforge.net/projects/vjoystick/ - can be worth looking at.
-
Also, there might be bindings for vJoy in your language of choice -- e.g. github.com/tidzo/pyvjoy for Python, which I haven't used but am looking forward to.– DragonJul 5, 2019 at 18:58
I know it is an old question but for anyone which is interested in this topic it is also worth looking at this project called ViGEm.
You can emulate some well known gamepads like Microsoft Xbox 360 Controller, Sony DualShock 4 Controller and Microsoft Xbox One Controller. The project offers also some API to interact with these virtual controllers. E.g. the C# API can be found here
The easiest solution may be to emulate an XInput device (Xbox 360 and One). These are supported in most modern games and the set up is very simple. Here is a C++ project here that provides this without any installed drivers or external dependencies: https://github.com/shauleiz/vXboxInterface/
-
3That's not true. You have to install the ScpVBus on your System in order to use this API for virtual gamepad interactions. Just look at this release note. Nov 9, 2017 at 12:44
The simplest solution I found was using vJoy and its C# wrapper. You need to download the vJoy driver from here.
You can use the vJoy SDK for implementing a feeder program: https://github.com/njz3/vJoy/tree/master/SDK/c%23
Use the C# starter project for this, or simply add the two .dll
-s to your existing project as references from the x86 or x64 folder.
You can find instructions on how to use the api in the readme.odt file.