Skip to content

Emulate Xbox 360 Controllers on Windows using Scarlet.Crush's SCP Virtual Bus Driver

License

Notifications You must be signed in to change notification settings

DavidRieman/ScpDriverInterface

 
 

Repository files navigation

ScpDriverInterface

ScpDriverInterface provides a .NET wrapper for the "SCP Virtual Bus Driver", for a means to emulate Xbox 360 controllers on PC and other devices.

Credits and major props go to Scarlet.Crush for his awesome SCP Server software which is the foundation of the driver itself. Without his work this wouldn't be possible.

One important goal for this software is to make it easier to bridge between custom accessibility hardware and software which honors standard gamepad controller input. The hope is that this could enable new possibilities for those which particular needs to participate in gaming which might otherwise be too difficult or impossible. Another use is enabling software test engineers in the games industry to build test automation without having to write bespoke input-automation hooks in the game code.

Usage

SimWinInput: First, if your goal is to emulate Xbox 360 controllers on your PC via a .NET app as simply as possible, you may will want to start with SimWinInput instead. It is a more user-friendly C# library using an instance of ScpDriverInstaller as an embedded dependency for seamless, automatic driver installation, as needed.

ScpDriverInterface: This is a .NET DLL file written in C#. It is a fairly minimal wrapper to interface with the SCP Virtual Bus Driver, meaning it intentionally carries the same quirks.

ScpDriverInstaller: This repository fork uses EmbeddedDIFx to manage the driver installation process more seamlessly than the base repository. (The base repository will not be updated with this feature, as noted here.)

ScpTester: This is a small C# application which demonstrates how to use ScpDriverInterface to plug in and unplug virtual controllers, and send inputs to them. For example, you can launch this test app, also launch another app which accepts Xbox 360 controller input, and see the other app then respond to simulated inputs from ScpTester. Note that this app will not work if you have not manually, correctly installed the SCP Virtual Bus Driver first.

A Note on Return Values

Before we begin, I just want to mention that ScpBus's PlugIn(), Unplug(), UnplugAll(), and Report() methods will all return boolean values indicating whether or not the operation was successful (i.e. True if the operation was successful, False otherwise). While you aren't required to use these returned values, I would recommend that you do use them whenever you want to make sure that what you wanted to happen actually happened.

Creating a New ScpBus Object

The example code here is all in C#, but it should be pretty similar for other languages.

After adding the DLL to your project, usage is very straightforward. First you must create a new ScpBus object:

ScpBus scpBus = new ScpBus();

Note that this will throw an IOException if ScpBus isn't able to get a handle to the SCP Virtual Bus Device (Usually this is because the SCP Virtual Bus Driver isn't installed).

Plugging In and Unplugging Virtual Controllers

Next you will want to plug in a virtual controller. Plugging in and unplugging is done with the PlugIn(), Unplug() and UnplugAll() methods. Multiple controllers can be plugged in at the same time, just use a unique controllerNumber for each separate controller. For example, this code will plug in 4 controllers:

scpBus.PlugIn(1);
scpBus.PlugIn(2);
scpBus.PlugIn(3);
scpBus.PlugIn(4);

Unplugging controllers works much the same way. If you wanted to unplug controller 3, you would use scpBus.Unplug(3);. If you wanted to unplug all currently plugged in controllers, you would use scpBus.UnplugAll();.

Sending Inputs to the Virtual Controllers

To send inputs to a controller, you use the Report() method. This method takes a 20-byte Xbox 360 controller input report, as specified here. To make this easier, ScpDriverInterface includes the X360Controller class, which can generate the report for you. To use it, first create a new X360Controller object:

X360Controller controller = new X360Controller();

Now you need to set up the state of the controller. Analog inputs (triggers and thumbsticks) are easy, just set them to the desired value (triggers use 8-bit unsigned integers, thumbsticks use 16-bit signed integers). For example, this code would set the left trigger to be fully pushed in, the right trigger to be halfway pushed in, and the right thumbstick to be pointing diagonally up and to the right:

controller.LeftTrigger = 255;
controller.RightTrigger = 128;
controller.RightStickX = 32767;
controller.RightStickY = 32767;

Buttons are also very straightforward; you can use them like flags. For example, to set A to be pressed, without affecting the states of any of the other buttons, you would use the bitwise or operator:

controller.Buttons |= X360Buttons.A;

You can assign multiple buttons in a single statement. For example, this code would set A, B, Up, and the left bumper to be pressed, again not affecting the state of any other buttons:

controller.Buttons |= X360Buttons.A | X360Buttons.B | X360Buttons.Up | X360Buttons.LeftBumper;

If instead of setting a button to be pressed, you just wanted to toggle its state, you would use the bitwsise xor operator. For example, this would toggle the A button:

controller.Buttons ^= X360Buttons.A;

And if you wanted to set a button to be not pressed, regardless of its initial state, you would use the bitwise and operator combined with a negation. For example, this would set A to be not pressed:

controller.Buttons &= ~X360Buttons.A;

Once you are done setting up the state of the controller, you can use the GetReport() method to get the 20-byte input report that can be used with ScpBus's Report() method. For example, if you had set up controller to be the state you wanted controller 2 to be in, then you would use this code to send that state to the virtual controller:

scpBus.Report(2, controller.GetReport());

Virtual Controller Rumble Data

ScpBus's Report() method can also give you rumble data about the specified controller. To get this data, add a third parameter when you call Report(), an 8-byte array that will have the controller's output report written to it. After calling Report(), you should verify that the output report it gives you is a rumble report by verifying that the second byte is equal to 0x08. If it is, then the fourth byte will have the speed for the rumble motor with the big weight, and the fifth byte will have the speed for the rumble motor with the small weight (0x00 to 0xFF in both cases).

IMPORTANT NOTE: The SCP Virtual Bus Device only returns rumble data with when the controller's rumble values have changed. This means that whenever the rumble values change, only the next call to Report() will receive those values. All subsequent calls will not receive any rumble report at all, at least not until the controller gets new rumble values. So, if you care about rumble data, you should always use the 3-parameter version of Report() (the one with the output report byte-array as the third parameter), and you should check the output report for new rumble data after every call to Report().

Here is some example code that will print the rumble data for controller 1 to the console, provided that Report() gives an output report with rumble data:

byte[] outputReport = new byte[8];
scpBus.Report(1, controller.GetReport(), outputReport);

if (outputReport[1] == 0x08)
{
	byte bigMotor = outputReport[3];
    byte smallMotor = outputReport[4];
    
    Console.WriteLine("Big Motor: {0}, Small Motor: {1}", bigMotor, smallMotor);
}

Disposing of ScpBus objects

Each instance of ScpBus contains a SafeFileHandle to an SCP Virtual Bus Device. If you call Close() or Dispose() on an ScpBus instance, then that SafeFileHandle will be closed immediately, and that ScpBus instance will become unusable. Whenever you are done with an ScpBus instance, you should call one of those methods to dispose of it and free up memory. If you don't then the .NET garbage collector should eventually dispose of it for you, but you have no control over how long this will take, so the object will just hang around taking up memory for some indeterminate amount of time.

Credits

Again, I want to stress that I am not the creator of the SCP Virtual Bus Driver, all I did was create this library that allows you to use it easily. The driver itself was made by pcsx2 forum user Scarlet.Crush. For more details, check out his awesome SCP Server software, which is what I based most of the code for this project off of.

Thank You!

About

Emulate Xbox 360 Controllers on Windows using Scarlet.Crush's SCP Virtual Bus Driver

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • C# 100.0%