Duplicate Controller Bug

If anyone can shed some light on this, it’d be super helpful.

So what’s happening is that if you start a MonoGame program with a PS4 controller connected and some other controller (tested with Xbox 360 and Xbox One controllers), instead of MG reporting the PS4 and Xbox controller, there are 2 instances of the Xbox controller. On 2 different GamePad indexes, and both report button presses to polling and such. If you disconnect the Xbox controller and reconnect, then the new one will work as expected, but leaves behind the “ghost” duplicate that does not report button presses or anything. If you connect the PS4 controller after the program starts (presumably, after MG/SDL have initialized), then everything works as expected, but if the programs starts with the PS4 controller and other controller connected you can see the bug. If you disconnect the PS4 controller, the “ghost” remains until you restart the program (presumably, until MG/SDL/both have re-Init-ed).

I wonder if this is a MonoGame bug, an SDL bug, or perhaps something even deeper. Seemingly not a driver-level bug, because Windows doesn’t report multiple copies of the Xbox device, and this only happens if you Init the program with both connected at the same time.

Tested with MonoGame 3.8 - DesktopGL on Windows 10 x64

Here’s a simple MG Game class to test what I have described above (you will need a simple font content file to load to render the debug info - in this code it loads an Arial.xnb spritefont):

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Diagnostics;


namespace ControllerReader
{
	public class Game1 : Game
	{
		private GraphicsDeviceManager _graphics;
		private SpriteBatch _spriteBatch;

		string outputStr;
		SpriteFont font;

		public Game1()
		{
			_graphics = new GraphicsDeviceManager(this);
			Content.RootDirectory = "Content";
			IsMouseVisible = true;
			IsFixedTimeStep = false;
		}

		protected override void Initialize()
		{
			_graphics.PreferredBackBufferWidth = 1600;
			_graphics.PreferredBackBufferHeight = 900;
			_graphics.ApplyChanges();

			GamePad.InitDatabase();

			base.Initialize();
		}

		protected override void LoadContent()
		{
			_spriteBatch = new SpriteBatch(GraphicsDevice);
			font = Content.Load<SpriteFont>("Arial");
		}

		protected override void Update(GameTime gameTime)
		{
			for (int i = 0; i < GamePad.MaximumGamePadCount; i++)
			{
				GamePadState gamepadState = GamePad.GetState(i, GamePadDeadZone.Circular);
				GamePadCapabilities capabilities = GamePad.GetCapabilities(i);

				outputStr += $"\n{i}: ({capabilities.Identifier}) {capabilities.DisplayName}";

				// check button presses
				foreach (Buttons button in Enum.GetValues(typeof(Buttons)))
					if (gamepadState.IsButtonDown(button))
						outputStr += $" - ({(int)button}) {button}";
			}

			base.Update(gameTime);
		}

		protected override void Draw(GameTime gameTime)
		{
			GraphicsDevice.Clear(Color.Black);

			_spriteBatch.Begin();
			_spriteBatch.DrawString(font, outputStr, new Vector2(20, 20), Color.White);
			_spriteBatch.End();

			base.Draw(gameTime);
		}
	}
}
1 Like

For any interested, this bug as well as some Steam Input stuff is being discussed here: PS4 Controller Init Bug · Issue #7457 · MonoGame/MonoGame · GitHub

I’m also having this problem, with or without Steam running. In my case, it’s with a Nintendo Switch Pro Controller but the results are the same.
When the app runs with an Xbox 360 controller only connected, connecting the Switch Pro over bluetooth gets detected correctly and displays as such. Restarting the app gets both controllers reported as “XInput controller”.

1 Like

Upon further testing with the Switch controller we are seeing this as well. In both bluetooth and wired connections. If the game is already running and you connect the controller, no problem, but if the Switch controller is already connected when the game is booted then the Xbox controller has 2 instances and the Switch has none.

1 Like

Just a bit more testing done. I have at hand 2 Xbox 360 controllers (wireless, using the USB receiver), a PS4 controller and a Switch Pro controller. It seems to act differently depending on the number of Xbox controllers connected. Here’s a quick overview:

  1. In testing, when no XInput-native devices are connected, supported controllers work as expected both during connection mid-game and on game (re)start. They each affect only their own PlayerIndex and have the correct player indicator LEDs on the controllers.
  2. When only one or more XInput-native devices are connected (tested with 2), controllers work as expected in both mid-game connection and on (re)start. They affect only their own PlayerIndex. Controller LEDs show the controllers registered as PlayerIndex 1 and 2.
  3. When 1 XInput-native controller is connected with one other controller (either Switch or PS4), connection works mid-game. XInput controller LEDs show itself connected as PlayerIndex 1, even if connected later, though the order is correct in-game.
  4. Game creates the “ghost” controller on (re)start. XInput controller affects its XInput player number AND the other controller’s, and both show up as “XInput controller”.

Here’s where it gets interesting.

  1. When 1 XInput-native controller is connected with the Switch AND PS4 controllers, connection works mid-game as expected. XInput controller LEDs show itself connected as PlayerIndex 1, even if connected later, though the order is correct in-game.

  2. On restart, the PS4 controller is taken over by the “ghost” XInput controller, as well as showing up as “XInput controller” in PlayerIndex.Three. The Switch Pro controller continues to work as expected and reports properly, in PlayerIndex.Two (even if it were previously in PlayerIndex.Three when connected mid-game). This restart outcome happens regardless of the connection order of the Switch and PS4 controllers. Player indicators on the PS4 or Switch controllers do not update themselves to match their new order.

  3. When 2 XInput controllers are connected along with both a Switch Pro and PS4 controller, connection works mid-game as expected. XInput devices show controller LEDs as PlayerIndex 1 and 2, even if connected after the DirectInput controllers, though the game correctly lists them in connection order.

  4. On restart, both the Switch Pro and PS4 controllers have been taken over by the XInput devices - XInput device registered as the first controller controls and appears as “XInput device” on PlayerIndex slots One and Three, whereas the second registered XInput controller controls and appears as “XInput device” on PlayerIndex Two and Four.

Not sure on the cause of it, but hope that the testing helps.

1 Like

For anyone else stumbling upon this before the next MonoGame update, this is solved by simply updating your SDL2 source to 2.0.14 (as opposed to the 2.0.12 that comes packed with MonoGame 3.8)

Per squarebananas: PS4 Controller Init Bug · Issue #7457 · MonoGame/MonoGame · GitHub

Tested and working :slight_smile: