C# – XBox 360 Controller library with a sample application

Created an easy to use XBox 360 Controller library in C# (with a sample application) using the SharpDX.XInput managed .NET wrapper of the DirectX API.

 https://github.com/okmer/XBoxController

Screenshot of the sample application.
Screenshot of the sample application.

A BUG in SharpDX.XInput ci-ci217, resulting in issues with the  left Thumb Stick, Left Trigger, and Right Trigger! Please stick to SharpDX.XInput v4.1.0-ci184 for now.

using System;
 
using Com.Okmer.GameController;
 
namespace XBoxSampleConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            XBoxController controller = new XBoxController();
 
            Console.WriteLine("XBox 360 Controller (Press ENTER to exit...)");
 
            //Connection
            controller.Connection.ValueChanged += (s, e) => Console.WriteLine($"Connection state: {e.Value}");
 
            //Battery
            controller.Battery.ValueChanged += (s, e) => Console.WriteLine($"Battery level: {e.Value}");
 
            //Buttons A, B, X, Y
            controller.A.ValueChanged += (s, e) => Console.WriteLine($"A state: {e.Value}");
            controller.B.ValueChanged += (s, e) => Console.WriteLine($"B state: {e.Value}");
            controller.X.ValueChanged += (s, e) => Console.WriteLine($"X state: {e.Value}");
            controller.Y.ValueChanged += (s, e) => Console.WriteLine($"Y state: {e.Value}");
 
            //Buttons Start, Back
            controller.Start.ValueChanged += (s, e) => Console.WriteLine($"Start state: {e.Value}");
            controller.Back.ValueChanged += (s, e) => Console.WriteLine($"Back state: {e.Value}");
 
            //Buttons D-Pad Up, Down, Left, Right
            controller.Up.ValueChanged += (s, e) => Console.WriteLine($"Up state: {e.Value}");
            controller.Down.ValueChanged += (s, e) => Console.WriteLine($"Down state: {e.Value}");
            controller.Left.ValueChanged += (s, e) => Console.WriteLine($"Left state: {e.Value}");
            controller.Right.ValueChanged += (s, e) => Console.WriteLine($"Right state: {e.Value}");
 
            //Buttons Shoulder Left, Right
            controller.LeftShoulder.ValueChanged += (s, e) => Console.WriteLine($"Left shoulder state: {e.Value}");
            controller.RightShoulder.ValueChanged += (s, e) => Console.WriteLine($"Right shoulder state: {e.Value}");
 
            //Buttons Thumb Left, Right
            controller.LeftThumbclick.ValueChanged += (s, e) => Console.WriteLine($"Left thumb state: {e.Value}");
            controller.RightThumbclick.ValueChanged += (s, e) => Console.WriteLine($"Right thumb state: {e.Value}");
 
            //Trigger Position Left, Right 
            controller.LeftTrigger.ValueChanged += (s, e) => Console.WriteLine($"Left trigger position: {e.Value}");
            controller.RightTrigger.ValueChanged += (s, e) => Console.WriteLine($"Right trigger position: {e.Value}");
 
            //Thumb Positions Left, Right
            controller.LeftThumbstick.ValueChanged += (s, e) => Console.WriteLine($"Left thumb X: {e.Value.X}, Y: {e.Value.Y}");
            controller.RightThumbstick.ValueChanged += (s, e) => Console.WriteLine($"Right thumb X: {e.Value.X}, Y: {e.Value.Y}");
 
            //Rumble Left, Right
            controller.LeftRumble.ValueChanged += (s, e) => Console.WriteLine($"Left rumble speed: {e.Value}");
            controller.RightRumble.ValueChanged += (s, e) => Console.WriteLine($"Right rumble speed: {e.Value}");
 
            //Rumble 0.25f speed for 500 milliseconds when the A or B button is pushed
            controller.A.ValueChanged += (s, e) => controller.LeftRumble.Rumble(0.25f, 500);
            controller.B.ValueChanged += (s, e) => controller.RightRumble.Rumble(0.25f, 500);
 
            //Rumble at 1.0f speed for 1000 milliseconds when the X or Y button is pushed
            controller.X.ValueChanged += (s, e) => controller.LeftRumble.Rumble(1.0f, 1000);
            controller.Y.ValueChanged += (s, e) => controller.RightRumble.Rumble(1.0f, 1000);
 
            //Rumble at the speed of the trigger position
            controller.LeftTrigger.ValueChanged += (s, e) => controller.LeftRumble.Rumble(e.Value);
            controller.RightTrigger.ValueChanged += (s, e) => controller.RightRumble.Rumble(e.Value);
 
            //Wait on ENTER to exit...
            Console.ReadLine();
        }
    }
}

EvilDir, create an EVIL named directory in Windows

A little “fun” Qt5 console application to create a directory (a.k.a. folder) ending with a space character (” “). This directory can not be removed with standard Windows tools, including most console applications.

#include <QCoreApplication>
#include <QDir>

int main(int argc, char *argv[])
{
  QCoreApplication a(argc, argv);

  QString evil_dir_name("Remko is a little Evil !!! ");

  for(int i=1; i<a.arguments().count(); i++)
  {
    if(a.arguments().at(i).compare("-d", Qt::CaseInsensitive) != 0)
    {
      evil_dir_name = a.arguments().at(i);
      evil_dir_name.append(" ");
      break;
    }
  }

  if(a.arguments().contains("-d"))
  {
    if(QDir(evil_dir_name).exists())
    {
      QDir().rmdir(evil_dir_name);
    }
  }
  else
  {
    QDir().mkdir(evil_dir_name);
  }
 
  return 0;
}

Reduce size (static) executables

This little (cross-platform) executable compression tool Ultimate Packer for eXecutables (UPX) can greatly reduce the size of (static build) executables. The executable filesize will be reduced to the size of a ZIP file containing the same executable.

The tool is very easy to use, just drag-and-drop your executable onto the upx.exe to use the default (fast) compression option of the tool, or type “upx <filename>” in the command-line. Adding the (much slower) “–utra-brute” command-line argument will reduce the filesize even further.

A static build Qt5.1.1 MinGW compiled application with a filesize of 12.972.032 bytes (12.3MB):

DEFAULT: 12.972.032 bytes (12.3MB) is reduced to 5.218.816 bytes (4.97 MB) using the (fast) default settings.

ULTRA-BRUTE: 12.972.032 bytes (12.3MB) is reduced to 4.488.704 bytes (4.28 MB) using the (much slower) “–ultra-brute” argument.

Qt 5.1.1 static build with MinGW

This is a small step-by-step howto compile a static Qt5.1.1 framework from source, using the MinGW 4.8.1 development environment.

Download MinGW Installer:
http://sourceforge.net/projects/mingwbuilds/files/mingw-builds-install/

Download Qt5 Source Zip:
http://download.qt-project.org/official_releases/qt/5.1/5.1.1/single/qt-everywhere-opensource-src-5.1.1.zip

Patch mkspecs (line 69):
<Qt5.1.x>\qtbase\mkspecs\win32-g++\qmake.conf

QMAKE_LFLAGS = -static -static-libgcc

Patch mkspecs (line 28) optional (reduce file size static builds):

QMAKE_CFLAGS = -ffunction-sections -fdata-sections ...

Patch Makefile.win32 (line 50):
<Qt5.1.x>\qtbase\qmake\Makefile.win32

LFLAGS = -static-libgcc ...

Patch for MinGW 4.8.1 (older MinGW 4.6.x works with-out patch):
https://codereview.qt-project.org/#change,63747

Replace file with patched version:
<Qt5.1.x>\qtbase\src\corelib\ioqfilesystemengine_win.cpp
https://codereview.qt-project.org/#patch,sidebyside,63747,3,src/corelib/io/qfilesystemengine_win.cpp

Patch for MinGW 4.8.1 (older MinGW 4.6.x works with-out patch):
https://codereview.qt-project.org/#change,64330,patchset=1

Replace file with patched version:
<Qt5.1.x>\qtbase\src\plugins\platforms\windows\qwindowstheme.cpp
https://codereview.qt-project.org/#patch,sidebyside,64330,1,src/plugins/platforms/windows/qwindowstheme.cpp

Python (needed by the qtjsbackend to fix the v8 error):
http://www.python.org/download/releases/

Add Python to Path:

set PATH=%PATH%;C:\Python33

Add MinGW to Path:

set PATH=%PATH%;C:\MinGWx32\mingw32\bin

Configure in <Qt5.1.x>\:

configure -platform win32-g++ -release -static -opensource -no-opengl -qt-zlib -qt-libpng -qt-libjpeg -nomake examples

Build with MinGW make in <Qt5.1.x>\:

mingw32-make -j

Build with Qt Creator:

Tools->Options
Build & Run
Compilers -> Add MinGW used to build Qt5.1.x -> Add->MinGW -> Browse to <MinGW>\bin\g++.exe (Apply)
Qt Versions -> Add Qt5.1.x static MinGW build -> Add -> browse to <Qt5.1.x>\qtbase\bin\qmake.exe (Apply)
Kits -> Add Qt5.1.x static with MinGW compiler -> Add -> compiler:MinGW & qtVersion:Qt5.1.xStaticMinGW & qtmkspecs:win32-g++

Ready to build !!!