windows 如何创建虚拟游戏手柄?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11711947/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 09:44:17  来源:igfitidea点击:

How do I create a virtual gamepad?

windowsvirtualgamecontroller

提问by Dataflashsabot

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?

我将如何创建一个“游戏手柄”,它在 DirectInput 应用程序中显示为普通游戏控制器,但其控件的状态实际上是由软件定义的?

回答by

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.

具体来说,Windows 设备驱动程序通过中断请求协议处理所谓的中断请求——这归结为驱动程序内部的一个包装结构和一组缓冲区。

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.

现在您需要知道的下一件事是,许多驱动程序实际上是分层的、堆叠的,或者您想使用的任何名称。因此,例如要编写磁盘驱动程序,您可能会与其上方的驱动程序(作为磁盘类)交互,但使用其下方的驱动程序(例如,scsi 端口)来实际向您的设备发送命令。

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 DeviceIoControlto it; then to actually get those messages you can either:

这开辟了通过用户模式应用程序控制驱动程序并假装“是”设备的可能性。要发送一个驱动程序消息,你可以DeviceIoControl给它;然后要实际获取这些消息,您可以:

  • Stuff them in the Irp that makes up that DeviceIoControl.
  • Have the driver read them out of your process' memory space.
  • 将它们填充到构成 DeviceIoControl 的 Irp 中。
  • 让驱动程序从进程的内存空间中读取它们。

Drivers can also access \\Registry\\Machineand various other, non-user-specific non-explorer registry areas, so it is possible to communicate that way.

驱动程序还可以访问\\Registry\\Machine和其他各种非用户特定的非资源管理器注册表区域,因此可以通过这种方式进行通信。

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.

最后,没有说你不能过滤现有的 IO,而不是通过一个新设备来弥补它。有很多选择和方法可以做到这一点。

If you're going to do this, you'll need:

如果你要这样做,你需要:

  • VirtualKDor 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.
  • VirtualKD或昂贵的调试器电缆和两台 PC。
  • 您可能还想从这篇博文中的参考资料开始。您会发现驱动程序代码本质上有无数不同的名称,因此我将解释其中的一些:

    • WDM = Windows 驱动程序模型,基本上是与(部分)Windows 9x 混合的 NT 驱动程序模型。
    • KMDF = 内核模式驱动程序框架 - 上述类型的驱动程序使用它,另外还有 WDF(Windows 驱动程序基础),它是 WDM 之上的一组库,以使其使用起来更快。
    • UMDF = 用户模式驱动程序框架 - 编写没有内核模式危险的驱动程序。如果可以,请使用它,因为出错的内核模式驱动程序将使您的系统蓝屏(用驱动程序的说法,错误检查)。

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.

编辑:我对 DirectInput 不是很了解 - 可能有一种方法可以通过 DLL 重定向等覆盖正在使用的各种 API 控件,这可能比我描述的方式更简单。

回答by Josh Brown

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/

最简单的解决方案可能是模拟 XInput 设备(Xbox 360 和 One)。大多数现代游戏都支持这些,并且设置非常简单。这里有一个 C++ 项目,它在没有安装任何驱动程序或外部依赖项的情况下提供了这个:https: //github.com/shauleiz/vXboxInterface/

回答by Josh Brown

There is vJoy opensource project: http://sourceforge.net/projects/vjoystick/- can be worth looking at.

有 vJoy 开源项目:http: //sourceforge.net/projects/vjoystick/- 值得一看。

回答by grill2010

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.

我知道这是一个老问题,但对于对这个话题感兴趣的任何人来说,这个名为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

您可以模拟一些众所周知的游戏手柄,例如 Microsoft Xbox 360 控制器、Sony DualShock 4 控制器和 Microsoft Xbox One 控制器。该项目还提供了一些 API 来与这些虚拟控制器进行交互。例如,可以在此处找到 C# API