Use ViGEm to create XBox 360 controller in C#



  • Hi

    I have an ESP32 development board that I'll be using to send data over serial port to the computer. I can do all of the Serial stuff in C# no problem.

    I'd like to control a virtual xbox 360 controller based on the received serial data.

    I'm hoping to create a C# application that allows me to do this. Am I in the right place?

    I would expect to be able to reference a dll library in my project, create a virtual gamepad, and then be able to send button presses etc to it.

    Is there any sample code available to achieve something similar?

    Help is much appreciated.



  • Hi

    Have muddled through and added the NuGet package and created a client and an xbox360 controller.

    When I run the program, it connects a virtual xbox360 controller - yay - fantastic!

    My question is now: how to I populate the Xbox360Report with button presses etc before calling: myController.SendReport(xbox360Report);

    Getting close - thanks in advance


  • administrators

    Hey,

    this is currently still a bit C-ish; you're expected to manipulate the properties of the Xbox360Report object and then submit it.



  • Thanks for the reply

    Thinking the code below should work - but buttons are not pressed. Any ideas?

    while (true)
    {
    	Task.Run(() =>
    	{
    		Xbox360Report controller1Report = new Xbox360Report();
    
    		controller1Report.SetButtons(Xbox360Buttons.A, Xbox360Buttons.B, Xbox360Buttons.X);
    		controller1Report.SetAxis(Xbox360Axes.LeftTrigger, 0xFF);
    		controller1Report.SetAxis(Xbox360Axes.RightTrigger, 0xFF);
    
    		myController.SendReport(controller1Report);
    		Thread.Sleep(20);
    	});
    }
    

  • administrators

    So far looking correct. And you've connected the controller before and verified that it is spawned on the system?


  • administrators

    Here's an old but still functional example you can use as inspiration.



  • @nefarius

    Well - it comes up in the device manager - and the USB game controller properties shows a picture of the buttons, but none of them are pressed...


  • administrators

    You checked with joy.cpl?



  • yeah - the controller is there - just no buttons are pressed

    I assume:

    controller1Report.SetButtons(Xbox360Buttons.A, Xbox360Buttons.B, Xbox360Buttons.X);

    Should make them pressed?



  • fyi - I converted the code to DualShock4Controller and the buttons are pressing fine

    any idea why the xbox 360 isn't working?

    thanks again for your help



  • Buttons not working:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using Nefarius.ViGEm.Client;
    using Nefarius.ViGEm.Client.Targets;
    using Nefarius.ViGEm.Client.Targets.Xbox360;
    using Nefarius.ViGEm.Client.Targets.DualShock4;
    
    
    namespace ConsoleApp1
    {
        class Program
        {
            static ViGEmClient myViGEmClient = new ViGEmClient();
            static Xbox360Controller myController = new Xbox360Controller(myViGEmClient);
    
            static void Main(string[] args)
            {
                myController.Connect();
    
                while (true)
                {
                    Xbox360Report controller1Report = new Xbox360Report();
    
                    controller1Report.SetButtons(Xbox360Buttons.A, Xbox360Buttons.B);
                    controller1Report.SetAxis(Xbox360Axes.LeftThumbX, 128);
    
                    myController.SendReport(controller1Report);
                    Thread.Sleep(20);
                }
            }
        }
    

    Buttons working:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using Nefarius.ViGEm.Client;
    using Nefarius.ViGEm.Client.Targets;
    using Nefarius.ViGEm.Client.Targets.Xbox360;
    using Nefarius.ViGEm.Client.Targets.DualShock4;
    
    
    namespace ConsoleApp1
    {
        class Program
        {
            static ViGEmClient myViGEmClient = new ViGEmClient();
            static DualShock4Controller myController = new DualShock4Controller(myViGEmClient);
    
            static void Main(string[] args)
            {
                myController.Connect();
    
                while (true)
                {
                    DualShock4Report controller1Report = new DualShock4Report();
    
                    controller1Report.SetButtons(DualShock4Buttons.Circle, DualShock4Buttons.Cross);
                    controller1Report.SetAxis(DualShock4Axes.LeftThumbX, 0);
    
                    myController.SendReport(controller1Report);
                    Thread.Sleep(20);
                }
            }
        }
    }
    

  • administrators

    Please format code snippets accordingly for better readability. So far I don't see an obvious error...



  • @nefarius said in Use ViGEm to create XBox 360 controller in C#:

    Please format code snippets accordingly for better readability. So far I don't see an obvious error...

    Thanks for the reply. I see how you added the ``` before and after to markup the code - will do that in future.

    Also, what can I do to try and troubleshoot the xbox360 controller not detecting button presses and axis movements? Is it a bug? Do I have an out-of-date version? Seems weird that PS4 works fine and xbox360 doesn't.



  • Hi

    Did some further testing

    ViGEmClient.dll version 1.13.1 is working with xbox360 correctly

    ViGEmClient.dll version 1.15.16 is not working with xbox360



  • Hmmn - now the 1.13.1 version isn't working for xbox360 either.

    Was playing around with updating dependencies, but put everything back the way it was, but am now having the same problem with 1.13.1 as 1.15.16

    Will restart and see how I go...

    EDIT --> nope - same issue

    going out of my mind



  • Tried it on another computer with the same result. Thinking it might be a bug of some sort



  • My Virtual Gamepad Emulation Bus version is 1.14.3.0

    I see 1.16.95.0 is up on Github

    Could I trouble you to compile and sign it so I can give it a go? The one at https://nuget.vigem.org/ installed through Powershell and on the caveman instructions: at https://docs.vigem.org/#!vigem-bus-driver-installation-caveman-edition.md are both the 1.14.3.0 version.

    Hoping it may get the Xbox360 gamepads working

    Thanks


  • administrators

    Version 1.15 or higher isn't ready for a public release yet and not guaranteed to be compatible so I don't recommend you use any other nuget package other than the official older one.



  • Thanks for getting back to me. Any idea what could be stopping it from working properly?

    Are there special timing requirements? Does it require special threading stuff?

    Could it be something to do with me running the latest official Windows 10 update?

    I tried SimWinGamepad at https://github.com/DavidRieman/SimWinInput or https://www.nuget.org/packages/SimWinGamePad and am having similar results.

    The gamepad is connected, but the reports don't seem to be registering properly.

    If I do a simple button press and release with SimGamePad.Instance.Use(GamePadControl.A); it works properly, but if I try to do other stuff and then call simPad.Update(0);, nothing at all registers.

    This leads me to believe it's a problem with my code setup or an incompatibility with a Windows update or something similar.

    Could you try compiling my code on your PC and checking if it works?

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using Nefarius.ViGEm.Client;
    using Nefarius.ViGEm.Client.Targets;
    using Nefarius.ViGEm.Client.Targets.Xbox360;
    using Nefarius.ViGEm.Client.Exceptions;
    
    namespace ControllerConverter
    {
        class Program
        {
            static ViGEmClient client = new ViGEmClient();
            static Xbox360Controller controller = new Xbox360Controller(client);
            static Xbox360FeedbackReceivedEventArgs previousXbox360FeedbackReceivedEventArgs;
    
            static void Main(string[] args)
            {
                previousXbox360FeedbackReceivedEventArgs = new Xbox360FeedbackReceivedEventArgs(0, 0, 1);
    
                controller.FeedbackReceived += new Xbox360FeedbackReceivedEventHandler(OnXbox360FeedbackReceived);
                controller.Connect();
                Console.WriteLine("Virtual Xbox360 gamepad connected.");
    
                while (true)
                {
                    Xbox360Report report = new Xbox360Report();
                    report.SetButtons(Xbox360Buttons.A, Xbox360Buttons.B, Xbox360Buttons.Up, Xbox360Buttons.LeftShoulder);
                    report.SetAxis(Xbox360Axes.LeftThumbX, 0);
                    report.SetAxis(Xbox360Axes.LeftThumbY, 0);
                    report.SetAxis(Xbox360Axes.RightThumbX, 128);
                    report.SetAxis(Xbox360Axes.RightThumbY, 0);
                    report.SetAxis(Xbox360Axes.LeftTrigger, 0);
                    report.SetAxis(Xbox360Axes.RightTrigger, 0);
                    //Xbox360ReportExtensions.SetButtons(report, Xbox360Buttons.A);
                    //Xbox360ReportExtensions.SetButtonState(report, Xbox360Buttons.A, true);
                    controller.SendReport(report);
                    Thread.Sleep(1);
                }
            }
    
            static void OnXbox360FeedbackReceived(object sender, Xbox360FeedbackReceivedEventArgs e)
            {
                if (e.LargeMotor != previousXbox360FeedbackReceivedEventArgs.LargeMotor && e.SmallMotor != previousXbox360FeedbackReceivedEventArgs.SmallMotor & e.LedNumber != previousXbox360FeedbackReceivedEventArgs.LedNumber)
                {
                    // Store passed in values
                    byte largeMotorData = e.LargeMotor;
                    byte smallMotorData = e.SmallMotor;
                    byte ledNumberData = e.LedNumber;
    
                    // Deal with new values
                    Console.WriteLine("Large Motor Data: {0}", largeMotorData);
                    Console.WriteLine("Small Motor Data: {0}", smallMotorData);
                    Console.WriteLine("LED Number: {0}", ledNumberData);
                }
    
                previousXbox360FeedbackReceivedEventArgs = e;
            }
        }
    }
    


  • Update

    !!!PROGRESS!!! --> with getting the Xbox 360 controller working.

    Seems I've been able to get it working; somewhat.

    I can set the buttons with eg:

    report.SetButtonState(Xbox360Buttons.A, true);
    report.SetButtonState(Xbox360Buttons.B, false);
    

    And I can set the triggers with eg:

    report.SetAxis(Xbox360Axes.LeftTrigger, 0x00); 
    report.SetAxis(Xbox360Axes.RightTrigger, 0xFF);
    

    However I can't get the left and right analogs to move with eg:

    report.SetAxis(Xbox360Axes.LeftThumbX, 0x00);
    report.SetAxis(Xbox360Axes.LeftThumbY, 0xFF);
    report.SetAxis(Xbox360Axes.RightThumbX, 0x00);
    report.SetAxis(Xbox360Axes.RightThumbY, 0xFF);
    

    Any ideas how I can set them properly?