Jon Thysell

Father. Engineer. Retro games. Ukuleles. Nerd.

Category: Howtos

Automatically generating version numbers in Visual Studio

Having intelligible version numbers is one of the easiest ways for developers to keep track of their software in the wild. However, having to maintain version numbers manually across multiple projects can be an annoying, error-prone process, especially if you’re trying to build and release often.

So how can we automate this task away?

The Goal

I have a Visual Studio solution with multiple projects, that therefore generates multiple assemblies for my app. In no particular order, here’s what I want:

  1. Every assembly has the exact same version number
  2. The option to manually specify a version number (say for infrequent builds that I release to the general public)
  3. The option for VS to auto-generate a build number (say for frequent builds that are released to beta testers)

So, what are my options?

Sharing one version number

Let’s tackle the first requirement. By default, every code project in a Visual Studio solution has its own AssemblyInfo.cs, and each specifies their own version number that needs to be updated and maintained.

But there’s no reason we have to stick with that. A better idea is to:

  1. Remove the AssemblyVersion attribute from AssemblyInfo.cs in all of your projects
  2. Create a new file, say SharedInfo.cs in one of your projects (typically the one the builds first) and put the AssemblyVersion attribute there.
  3. For all of your other projects, simply add that SharedInfo.cs as a link. (In the “Add Existing Item…” dialog, click the arrow next to the “Add” button and choose “Add As Link”.)

Now you only have one file to update your version information in, making it much more manageable. Bonus, you can move all common assembly tags you want in your SharedInfo.cs, like Copyright, Product, etc.

Automatic versions

Being able to manually specify a version number is easy enough. Whether you keep the default Visual Studio AssemblyInfo.cs paradigm or the SharedInfo.cs method above, it’s just a matter of you picking and setting a new version number when you feel like it.

But now let’s see what we can do about having automatic versions.

Option 1: Use the built-in wildcards

The first option is given to us right in the default AssemblyInfo.cs, letting us know that we can simply set our version to Major.Minor.* and let Visual Studio auto-generate the Build and Release numbers.

Visual Studio then sets the Build based on the number of days that have passed since January 1st, 2000, and sets the Release to the number of two-second intervals that have elapsed since midnight. Sounds good so far, and of course you can always switch back to a manual version at any time. But there are a couple of caveats:

  1. This only works with AssemblyVersion, not AssemblyFileVersion. To make this work for both, you have to specify just the AssemblyVersion (comment out or delete the AssemblyFileVersion line) and then Visual Studio is smart enough to use the same value for AssemblyFileVersion.
  2. Both numbers are generated at the exact time the particular project was built. So if you have multiple projects in your solution and any one takes more than two seconds to build, you will end up with different versions for different assemblies.

Option 2: Use an extension

The next option, one I used for years, is to simply hand over the responsibility of generating versions to the VS extension Automatic Versions.

If features a very nice GUI and there are lots of styles of automatic versions you can specify for your projects. It resolves both of the issues with using the built-in wildcards, letting you specify AssemblyVersion and AssemblyFileVersion, and also making sure that every project has the same version number (whether you share a linked file or not).

Downsides?

  1. You might not find a version style that you like. While there are lot of version number patterns to choose from, if you have a specific format you need to adhere to (say to match existing releases), you might be out of luck.
  2. You’ve just added a dependency to your code. Are you sharing your code with other developers? Now they have to install the extension too.

Adding dependencies means adding risk. For over a year, the VS Performance Profiler simply would not work for me, throwing an error and crashing whenever I tried to analyze my applications. I thought maybe my VS 2013 install was simply borked, but the problem followed me to VS 2015.

Turns out Automatic Versions was the culprit. Now, to be fair, once I reported the bug the developer very quickly issued a fix and now the Profiler is fine. But I searched for a solution to that Profiler error for a year, and at no point did it occur to me that an extension might be causing the problem.

Option 3: Use a T4 text template

The last option I want to talk about, is using a T4 template. What are T4 templates? From Code Generation and T4 Text Templates on MSDN:

In Visual Studio, a T4 text template is a mixture of text blocks and control logic that can generate a text file.

I’ve you’ve ever made a website in ASP.NET or PHP, then you’ll have no problem with T4 text templates. Basically, you can create a template file with some in-line blocks of C# that will get run when you build your project to generate your actual file.

So, instead of creating a straight SharedInfo.cs like we did before, now we create a SharedInfo.tt and write a little bit of code to handle generating new version numbers.

Simply add a new T4 text template to your project paste in the following to get started:

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ output extension=".cs" #>
<#
    int major    = 1;
    int minor    = 0;
    int build    = 0;
    int revision = 0;

    // TODO: Write code here to automatically generate a version

    string version = String.Format("{0}.{1}.{2}.{3}",
                                   major,
                                   minor,
                                   build,
                                   revision);
#>
// This code was generated by a tool. Any changes made manually will be lost
// the next time this code is regenerated.

using System.Reflection;

[assembly: AssemblyVersion("<#= version #>")]
[assembly: AssemblyFileVersion("<#= version #>")]

Now, if you’re having trouble reading this, basically, the first couple lines are directives that the template is going to create a .cs file. The code in the <# #> blocks will be run when the project is built, and where you’re going to need to decide how you want to generate your build numbers. After that is the static template text of the output file, and you can see where you see <#= version #>, that’s where the value of the version string will be inserted.

As it stands, if you created a SharedInfo.tt with the above template, you’ll get a SharedInfo.cs with the following:

// This code was generated by a tool. Any changes made manually will be lost
// the next time this code is regenerated.

using System.Reflection;

[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

And just like before, you can then add links to that SharedInfo.cs (not the .tt file!) into your other projects. So all you need to do is write the code that generates the automatic versions. What does that code look like? It’s up to you!

In my projects, I usually have a “manual” mode whereby the version numbers I entered are used for public production builds, and overwritten by something based on DateTime.UtcNow for private or test builds. If you want plain, auto-incrementing numbers, you might go with reading in your current SharedInfo.cs to parse out the previous version number, increment, and save it back out.

Well, there you have it, completely customizable automatic versioning in Visual Studio solutions. Like it? Have a different approach? Sound off in the comments!

/jon

P.S. If you want to see a “real-world” example of how I pick version numbers check out What the Chordious version numbers mean.

Consolidating the Sega Genesis, Sega CD, and Sega 32x power supplies

As I’ve mentioned before, the Sega Genesis was my first and favorite childhood gaming console, and though over the years I’ve come to rely on emulators, re-releases and clone systems to get my Sega nostalgia, I recently decided to set up some original hardware.

Whether you’re new to the system, or a long-time fan, the holy trinity is to get a Sega Genesis along with its two biggest add-ons, the Sega CD and the Sega 32X. Now, one of the major annoyances is that each has its own wall-wart power supply, which are a pain to use: they’re hard to get situated on power strips due to their size and they generate a lot of heat, even with nothing turned on.

I thought there had to be a way to have a single consolidated power supply that supports all three systems at once. And after a little research, I found two solutions:

  1. The Sega Trio, which is a commercial power supply made specifically to solve this problem at the reasonable cost of $28.99. Only problem seems to be the very limited availability.
  2. Follow what others have done (see this forum post), and build my own custom harness on top of a generic power supply.

So I decided to build my own, and document the build along the way.

The Investigation

The first step was to collect all of the relevant power requirements for each system (thanks to this page for a lot of it). For my own setup, I have a model 2 Genesis, model 2 Sega CD, and a 32X. Here’s what the original power supplies look like:

System Voltage Amperage Plug Type Polarity
Sega Genesis Model 2 10V 0.85A 1.7mm Pos. center
Sega CD Model 2 9V 1.2A 2.1mm Neg. center
Sega 32X 10V 0.85A 1.7mm Pos. center

Now the next step is to find a suitable generic power supply. It is important to note that none of these systems actually needs exactly 9 or 10 volts to operate. In fact, the rating on the label is more like the “average voltage” that adapters of that model produce. So a particular one of these power adapters may actually produce anywhere from 8 to 12V.

This is all fine because the first thing each system does is step down that input power to the steady 5 volts that the chips inside are designed to use.

Since it’s very easy to source 9V power supplies, I’ll go with 9V for my generic.

As for the amperage, I need to add up the ratings of each power supply to get a minimum safe value. Amperage ratings show the maximum amperage that the power supplies can safely provide, not the actual amount the systems will necessarily draw. To be safe, OEM manufacturers typically provide power supplies that can offer slightly more amps than they expect their product to draw at full intensity.

So in the original setup, 2.9A is probably safely above the maximum current I’d expect the three systems to draw at once. Round that up to 3A, and now I’m looking for a 9V, minimum 3A power supply, preferably one that isn’t a wall-wart.

The next consideration is how to get one power supply to have three plugs. So I’m going to need to make or buy some kind of harness to split or daisy-chain three separate plugs. As for the plugs themselves, I have couple of things to consider.

Generic power supplies typically come standard with barrel plugs with a 2.1mm diameter center hole with positive polarity. The Genesis Model 2 and 32X both use the more common positive polarity center. Unfortunately, they use the less common EIAJ-03 barrel plugs with a smaller 1.7mm diameter center hole. The Sega CD Model 2 uses the common 2.1mm center hole, but the less common negative polarity center.

So in both cases I’m going to need some adapters.

At this point I have a spectrum of options. On one end is to buy all raw parts and try to solder up a completely custom harness. More extreme, I could even build my own power supply from scratch. On the other end of the spectrum is to try and get away with buying off-the-shelf cables and adapters.

Building from scratch is fine if you have the time, skills and tools. To save money you’ll need to buy parts in bulk, which is great if you’re going to build a bunch, or might use the parts in other projects.

Anyone can buy off-the-shelf parts and just plug them all together. No special skills required. But you will pay a premium.

For this project, I thought it would be interesting to source off-the-shelf parts, just to prove that I could make it work with no soldering required. Yes it probably wouldn’t look as slick, but anyone could replicate it. Also I was feeling lazy. I can always play cable doctor later and transform the off-the-shelf parts into a slicker, more permanent solution.

Bill of Materials

Item Product Quantity Unit Price
9V 3A DC Power Supply Output 9V 3A AC/DC Power Supply Cord Charger IEC320 C8 Socket Adapter 1 $14.37
AC Power Cord SF Cable, 6ft 18 AWG 2-Slot Non-Polarized Power Cord (IEC320 C7 to NEMA 1-15P) 1 5.75
3-Way DC Power Cable Splitter 1:3 DC Power Splitter Cable Cord 1 Female to 3 Male 5.5×2.1mm Port Pigtals 12V 1 3.99
2.1mm to 1.7mm DC Power Adapter Cable 4.8mm x 1.7mm Male Plug to 5.5mm x 2.1mm female socket DC Power Adapter cable 2 3.59
2.1mm Power Jack Polarity Changer MODE 2.1MM JACK-PLUG POLARITY CHANGER BLACK 68-102-0 1 3.80
Subtotal $35.09
Shipping 4.49
Total $39.58

First off, I’ll say that I didn’t spend a ton of time sourcing the parts. Just a couple days casually browsing Amazon and Ebay. If I found something that looked like it’d work, I bought it. For $40, this is definitely not the cheapest way to do this, but it’s not much worse than buying three new power supplies at $9.99 each.

The nicest thing was finding out that the CCTV security camera market supports an industry of nice DC power cable splitters in a variety of configurations, which was the part I assumed I’d have to make myself.

The Build

Once I had the parts, it was a simply a matter of connecting everything. If it’s not straight-forward for you, it goes like this:

  1. Connect AC cord to the power supply.
  2. Connect the 3-way splitter to the power supply.
  3. Connect each of the two 2.1mm to 1.7mm adapter cables to a cable coming out of the 3-way splitter (one each for the Genesis and 32X).
  4. Connect the 2.1mm polarity changer to the remaining cable coming out of the 3-way splitter (for the Sega CD).

The end result should look something like this:

Since the plugs have different sizes, it shouldn’t be too hard to figure out which plug connects to each system. For the sake of simplicity, I put a bit of colored tape on each: red for Genesis, blue for CD, yellow for 32X, corresponding with the primary colors of the game boxes for each system.

The power supply works like a charm. I’m free from the three-wart tyranny!

Have questions or comments? Sound off below.

/jon

Building a custom retro console running RetroPie

Ever since I first heard about Raspberry Pi and the RetroPie project, I’ve wanted to build a retro console. Something with all my favorite old game systems emulated in a compact classy box, with nice controllers and fully customizable.

Back in the day I used to have a soft-modded Xbox original to play retro games, but it was loud, bulky, and the controllers weren’t great. When I got my first Raspberry Pi, I tried to make my custom console, but I ran into several problems:

  1. Power issues: A non-clean shutdown meant corrupting the SD card, which isn’t user-friendly, and no power switch
  2. Weak ports: Connecting straight to the light-weight Pi meant it was often left hovering in the air, which would strain the HDMI and USB connections
  3. Available cases: Raspberry Pi cases all seem to fall into the category of tight as possible, giving no internal room to address 1 and 2 above

My first successful attempt was of course building the Picade, but it has two major limitations:

  1. One player only
  2. Kind of heavy to play on a couch

Since then I’ve been planning a new machine. The goal has been a small, two-player console that connects to modern TVs. Then after I discovered this lovely Polycase ZN-40 electronics enclosure, I new it was time to get to work. Yesterday was Pi Day, and I’d just cloned my Picade SD card, so I decided to finally try putting a console together.

It went together way faster than I anticipated! Now I can’t wait to make a couple more: one for home, one for work, one for the game room… the opportunities are endless.

Okay, enough typing, time to play!

/jon

P.S. Here’s a quick video and some development pics:

 

retroconsole01 retroconsole02 retroconsole03 retroconsole04 retroconsole05 retroconsole06 retroconsole07 retroconsole08 retroconsole09 retroconsole10 retroconsole11

Sega Genesis controllers and Arduino revisited

NOTICE: This research and implementation in this post is not 100% correct. Please check out my SegaController Arduino library for better code and How To Read Sega Controllers for details on how it works.

Version 1.0

A couple of months ago I detailed the process by which I used an Arduino Uno to read the button presses of a pair of Sega Genesis controllers. It was my first bit of micro-controller programming, and it has exposed me to a whole new world of possibilities for hardware hacking. So it is with some certain future projects in mind that I’ve revisited and updated that initial code.

Version 1.1

Other than some minor code cleanup, the only major feature-add to the core of the sketch is to support reading the “Mode” button on six-button controllers (thanks to a comment from soe for that). The other change, now that I’ve acquired an Arduino Leonardo, is to create a fork of the sketch which reports the button presses as keyboard key presses via the ATmega32u4 chip’s ability appear as a USB keyboard.

Anyway, here’s the updated code (for reporting over the Serial connection):

/*
 * Sega Controller Reader
 * Author: Jon Thysell <thysell@gmail.com>
 * Version: 1.1
 * Date: 9/29/2014
 *
 * Reads buttons presses from Sega Genesis 3/6 button controllers
 * and reports their state via the Serial connection. Handles hot
 * swapping of controllers and auto-switches between 3 and 6 button
 * polling patterns.
 *
 */

const int PLAYERS = 2;

// Controller Button Flags
const int ON = 1;
const int UP = 2;
const int DOWN = 4;
const int LEFT = 8;
const int RIGHT = 16;
const int START = 32;
const int A = 64;
const int B = 128;
const int C = 256;
const int X = 512;
const int Y = 1024;
const int Z = 2048;
const int MODE = 4096;

// Controller DB9 Pin 7 Mappings
const int SELECT[] = { 8, 9 };

typedef struct
{
  int player;
  int pin;
  int lowFlag;
  int highFlag;
  int pulse3Flag;
} input;

// Controller DB9 Pin to Button Flag Mappings
// First column is the controller index, second column
// is the Arduino pin that the controller's DB9 pin is
// attached to, remaing columns are the button flags
input inputMap[] = {
  { 0,  2,  UP,    UP,     Z    }, // P0 DB9 Pin 1
  { 0,  3,  DOWN,  DOWN,   Y    }, // P0 DB9 Pin 2
  { 0,  4,  ON,    LEFT,   X    }, // P0 DB9 Pin 3
  { 0,  5,  ON,    RIGHT,  MODE }, // P0 DB9 Pin 4
  { 0,  6,  A,     B,      0    }, // P0 DB9 Pin 6
  { 0,  7,  START, C,      0    }, // P0 DB9 Pin 9
  { 1,  A0, UP,    UP,     Z    }, // P1 DB9 Pin 1
  { 1,  A1, DOWN,  DOWN,   Y    }, // P1 DB9 Pin 2
  { 1,  A2, ON,    LEFT,   X    }, // P1 DB9 Pin 3
  { 1,  A3, ON,    RIGHT,  MODE }, // P1 DB9 Pin 4
  { 1,  A4, A,     B,      0    }, // P1 DB9 Pin 6
  { 1,  A5, START, C,      0    }  // P1 DB9 Pin 9
};

// Controller State
int currentState[] = { 0, 0 };
int lastState[] = { -1, -1 };

// Default to three-button mode until six-button connects
boolean sixButtonMode[] = { false, false };

void setup()
{
  // Setup input pins
  for (int i = 0; i < sizeof(inputMap) / sizeof(input); i++)
  {
    pinMode(inputMap[i].pin, INPUT);
    digitalWrite(inputMap[i].pin, HIGH);
  }

  // Setup select pins
  for (int i = 0; i < PLAYERS; i++)
  {
    pinMode(SELECT[i], OUTPUT);
    digitalWrite(SELECT[i], HIGH);
  }

  Serial.begin(9600);
}

void loop()
{
  readButtons();
  sendStates();
}

void readButtons()
{
  for (int i = 0; i < PLAYERS; i++)
  {
    resetState(i);
    if (sixButtonMode[i])
    {
      read6buttons(i);
    }
    else
    {
      read3buttons(i);
    }
  }
}

void resetState(int player)
{
  currentState[player] = 0;
}

void read3buttons(int player)
{
  // Set SELECT LOW and read lowFlag
  digitalWrite(SELECT[player], LOW);

  delayMicroseconds(20);

  for (int i = 0; i < sizeof(inputMap) / sizeof(input); i++)
  {
    if (inputMap[i].player == player && digitalRead(inputMap[i].pin) == LOW)
    {
      currentState[player] |= inputMap[i].lowFlag;
    }
  }

  // Set SELECT HIGH and read highFlag
  digitalWrite(SELECT[player], HIGH);

  delayMicroseconds(20);

  for (int i = 0; i < sizeof(inputMap) / sizeof(input); i++)
  {
    if (inputMap[i].player == player && digitalRead(inputMap[i].pin) == LOW)
    {
      currentState[player] |= inputMap[i].highFlag;
    }
  }

  // When a six-button first connects, it'll spam UP and DOWN,
  // which signals the game to switch to 6-button polling
  if (currentState[player] == (ON | UP | DOWN))
  {
    sixButtonMode[player] = true;
  }
  // When a controller disconnects, revert to three-button polling
  else if ((currentState[player] & ON) == 0)
  {
    sixButtonMode[player] = false;
  }

  delayMicroseconds(20);
}

void read6buttons(int player)
{
  // Poll for three-button states twice
  read3buttons(player);
  read3buttons(player);

  // After two three-button polls, pulse the SELECT line
  // so the six-button reports the higher button states
  digitalWrite(SELECT[player], LOW);
  delayMicroseconds(20);
  digitalWrite(SELECT[player], HIGH);

  for(int i = 0; i < sizeof(inputMap) / sizeof(input); i++)
  {
    if (inputMap[i].player == player && digitalRead(inputMap[i].pin) == LOW)
    {
      currentState[player] |= inputMap[i].pulse3Flag;
    }
  }

  delayMicroseconds(1000);
}

void sendStates()
{
  // Only report controller states if at least one has changed
  boolean hasChanged = false;

  for (int i = 0; i < PLAYERS; i++)
  {
    if (currentState[i] != lastState[i])
    {
      hasChanged = true;
    }
  }

  if (hasChanged)
  {
    for (int i = 0; i < PLAYERS; i++)
    {
      Serial.print((currentState[i] & ON) == ON ? "+" : "-");
      Serial.print((currentState[i] & UP) == UP ? "U" : "0");
      Serial.print((currentState[i] & DOWN) == DOWN ? "D" : "0");
      Serial.print((currentState[i] & LEFT) == LEFT ? "L" : "0");
      Serial.print((currentState[i] & RIGHT) == RIGHT ? "R" : "0");
      Serial.print((currentState[i] & START) == START ? "S" : "0");
      Serial.print((currentState[i] & A) == A ? "A" : "0");
      Serial.print((currentState[i] & B) == B ? "B" : "0");
      Serial.print((currentState[i] & C) == C ? "C" : "0");
      Serial.print((currentState[i] & X) == X ? "X" : "0");
      Serial.print((currentState[i] & Y) == Y ? "Y" : "0");
      Serial.print((currentState[i] & Z) == Z ? "Z" : "0");
      Serial.print((currentState[i] & MODE) == MODE ? "M" : "0");

      Serial.print((i == 0) ? "," : "\n");
      lastState[i] = currentState[i];
    }
  }
}

As with the previous version, all you have to do is upload the sketch and connect the controller’s DB9 pins to the Arduino following the mapping in inputMap in the code.

Now, if you have an Arduino Leonardo (or compatible board), and want the controller button presses to map to keyboard keys instead, you can upload the following sketch:

/*
 * Sega Controller Reader (Keyboard)
 * Author: Jon Thysell <thysell@gmail.com>
 * Version: 1.1
 * Date: 9/29/2014
 *
 * Reads buttons presses from Sega Genesis 3/6 button controllers
 * and reports their state via keyboard button presses. Handles hot
 * swapping of controllers and auto-switches between 3 and 6 button
 * polling patterns.
 *
 */

const int PLAYERS = 2;

// Controller Button Flags
const int ON = 1;
const int UP = 2;
const int DOWN = 4;
const int LEFT = 8;
const int RIGHT = 16;
const int START = 32;
const int A = 64;
const int B = 128;
const int C = 256;
const int X = 512;
const int Y = 1024;
const int Z = 2048;
const int MODE = 4096;

// Controller DB9 Pin 7 Mappings
const int SELECT[] = { 8, 9 };

typedef struct
{
  int player;
  int pin;
  int lowFlag;
  int highFlag;
  int pulse3Flag;
} input;

// Controller DB9 Pin to Button Flag Mappings
// First column is the controller index, second column
// is the Arduino pin that the controller's DB9 pin is
// attached to
input inputMap[] = {
  { 0,  2,  UP,    UP,     Z    }, // P0 DB9 Pin 1
  { 0,  3,  DOWN,  DOWN,   Y    }, // P0 DB9 Pin 2
  { 0,  4,  ON,    LEFT,   X    }, // P0 DB9 Pin 3
  { 0,  5,  ON,    RIGHT,  MODE }, // P0 DB9 Pin 4
  { 0,  6,  A,     B,      0    }, // P0 DB9 Pin 6
  { 0,  7,  START, C,      0    }, // P0 DB9 Pin 9
  { 1,  A0, UP,    UP,     Z    }, // P1 DB9 Pin 1
  { 1,  A1, DOWN,  DOWN,   Y    }, // P1 DB9 Pin 2
  { 1,  A2, ON,    LEFT,   X    }, // P1 DB9 Pin 3
  { 1,  A3, ON,    RIGHT,  MODE }, // P1 DB9 Pin 4
  { 1,  A4, A,     B,      0    }, // P1 DB9 Pin 6
  { 1,  A5, START, C,      0    }  // P1 DB9 Pin 9
};

typedef struct
{
  int player;
  int flag;
  char key;
} output;

// Controller Button Flag to Keyboard Mappings
// First column is the controller index, second column
// is the button flag, third is keyboard key
output outputMap[] = {
  { 0, UP,    KEY_UP_ARROW },
  { 0, DOWN,  KEY_DOWN_ARROW },
  { 0, LEFT,  KEY_LEFT_ARROW },
  { 0, RIGHT, KEY_RIGHT_ARROW },
  { 0, START, KEY_RETURN },
  { 0, A,     'z' },
  { 0, B,     'x' },
  { 0, C,     'c' },
  { 0, X,     'a' },
  { 0, Y,     's' },
  { 0, Z,     'd' },
  { 0, MODE,  'q' },
  { 1, UP,    'i' },
  { 1, DOWN,  'k' },
  { 1, LEFT,  'j' },
  { 1, RIGHT, 'l' },
  { 1, START, 't' },
  { 1, A,     'v' },
  { 1, B,     'b' },
  { 1, C,     'n' },
  { 1, X,     'f' },
  { 1, Y,     'g' },
  { 1, Z,     'h' },
  { 1, MODE,  'r' }
};

// Controller State
int currentState[] = { 0, 0 };
int lastState[] = { -1, -1 };

// Default to three-button mode until six-button connects
boolean sixButtonMode[] = { false, false };

void setup()
{
  // Setup input pins
  for (int i = 0; i < sizeof(inputMap) / sizeof(input); i++)
  {
    pinMode(inputMap[i].pin, INPUT);
    digitalWrite(inputMap[i].pin, HIGH);
  }

  // Setup select pins
  for (int i = 0; i < PLAYERS; i++)
  {
    pinMode(SELECT[i], OUTPUT);
    digitalWrite(SELECT[i], HIGH);
  }

  Keyboard.begin();
}

void loop()
{
  readButtons();
  sendStates();
}

void readButtons()
{
  for (int i = 0; i < PLAYERS; i++)
  {
    resetState(i);
    if (sixButtonMode[i])
    {
      read6buttons(i);
    }
    else
    {
      read3buttons(i);
    }
  }
}

void resetState(int player)
{
  currentState[player] = 0;
}

void read3buttons(int player)
{
  // Set SELECT LOW and read lowFlag
  digitalWrite(SELECT[player], LOW);

  delayMicroseconds(20);

  for (int i = 0; i < sizeof(inputMap) / sizeof(input); i++)
  {
    if (inputMap[i].player == player && digitalRead(inputMap[i].pin) == LOW)
    {
      currentState[player] |= inputMap[i].lowFlag;
    }
  }

  // Set SELECT HIGH and read highFlag
  digitalWrite(SELECT[player], HIGH);

  delayMicroseconds(20);

  for (int i = 0; i < sizeof(inputMap) / sizeof(input); i++)
  {
    if (inputMap[i].player == player && digitalRead(inputMap[i].pin) == LOW)
    {
      currentState[player] |= inputMap[i].highFlag;
    }
  }

  // When a six-button first connects, it'll spam UP and DOWN,
  // which signals the game to switch to 6-button polling
  if (currentState[player] == (ON | UP | DOWN))
  {
    sixButtonMode[player] = true;
  }
  // When a controller disconnects, revert to three-button polling
  else if ((currentState[player] & ON) == 0)
  {
    sixButtonMode[player] = false;
  }

  delayMicroseconds(20);
}

void read6buttons(int player)
{
  // Poll for three-button states twice
  read3buttons(player);
  read3buttons(player);

  // After two three-button polls, pulse the SELECT line
  // so the six-button reports the higher button states
  digitalWrite(SELECT[player], LOW);
  delayMicroseconds(20);
  digitalWrite(SELECT[player], HIGH);

  for(int i = 0; i < sizeof(inputMap) / sizeof(input); i++)
  {
    if (inputMap[i].player == player && digitalRead(inputMap[i].pin) == LOW)
    {
      currentState[player] |= inputMap[i].pulse3Flag;
    }
  }

  delayMicroseconds(1000);
}

void sendStates()
{
  for (int i = 0; i < sizeof(outputMap) / sizeof(output); i++)
  {
    int last = (lastState[outputMap[i].player] & outputMap[i].flag);
    int current = (currentState[outputMap[i].player] & outputMap[i].flag);

    if (last != current)
    {
      if (current == outputMap[i].flag)
      {
        Keyboard.press(outputMap[i].key);
      }
      else
      {
        Keyboard.release(outputMap[i].key);
      }
    }
  }

  for (int i = 0; i < PLAYERS; i++)
  {
    lastState[i] = currentState[i];
  }
}

If you want to change the button to key mapping, simply update outputMap in the code. You can use any key on the keyboard, including special keys and modifiers.

I hope this is a worthy updated to the sketch – it was a great delight to test it by playing emulated games on my laptop with real Genesis controllers. It worked wonderfully, and I can’t wait to get this integrated into a bigger project.

So happy hacking and stay tuned for more!

/jon

Update 26-JUN-2017: The source is now available on GitHub here.

Update 28-JUN-2017: I’ve announced a newer, stable, reusable version at Introducing the SegaController Arduino library.

Reading Sega Genesis controllers with Arduino

segaarduino1

NOTICE: This research and implementation in this post is not 100% correct. Please check out my SegaController Arduino library for better code and How To Read Sega Controllers for details on how it works.

Background

The Sega Genesis was my first and favorite childhood game console, so when I first picked up an Arduino a couple years ago, my first thought was to build something, anything, that used a Genesis controller. Unfortunately I got side-tracked by other projects, and the Arduino Uno I’d purchased got set aside.

Fast-forward to this year’s picade build, when I had to re-flash the main controller board, which at its heart is an Arduino Leonardo. Seeing how easy it was to work with, I finally decided to break out my Uno. After a couple sample sketches, I figured it was time start interfacing with some Genesis controllers.

Research

I started poking around online to see what others had done, and couldn’t find quite what I was looking for. What I did find was plenty of information on how the three-button pads worked. Some used that info to implement full three-button support – others, it seems, were satisfied with having just some of the buttons working (essentially using the controller’s innate backward compatibility with the simpler Sega Master System’s two-button controller design). No one had six-button controllers working.

What I want is full three and six-button support, something that I can plug any Genesis controller into and it’ll “just work”, like an actual Genesis console. My requirements therefore are:

  1. Correctly reads connected three-button controllers.
  2. Correctly reads connected six-button controllers.
  3. Automatically detects which type of controller is connected, with hot-swapping.
  4. Bonus: Support more than one controller at a time.

The real godsend to the first two was finding Charles Rosenberg’s Sega Six Button Controller Hardware Info. There he describes almost everything you need to know about how Genesis controllers work. I highly recommend giving it a full read for the really gory details before continuing, but here’s a “quick” overview:

How Sega Genesis controllers work

All Genesis controllers use a standard nine-pin DB9 serial port. On your regular three-button controller, you really have a total of eight buttons: Up, Down, Left, Right, A, B, C, and Start. With nine pins to work with, Sega could easily have gone with one +5v in and eight outputs back to the console and be done with it. But instead, in the interest of backwards compatibility with the Sega Master System (and potentially other DB9 based controllers like the old Atari joysticks), they implemented a simple multiplexer circuit.

Essentially you have three control pins (+5v power, ground, select) and six output pins. By default, all of the output pins are set high (meaning a button press will bring the pin down to ground). The Genesis (or more specifically, the game running on the Genesis) sets the select pin (DB9 pin seven) low, then reads the state of the six output pins to get the states for the Up, Down, A, and Start buttons. Then the game toggles the select pin to high, and re-reads those same six output pins to get the states of the Up (again), Down (again), Left, Right, B, and C buttons.

DB9 Pin Select is low Select is high
1 Up Up
2 Down Down
3 Ground Left
4 Ground Right
5 Control: +5V
6 A B
7 Control: Select
8 Control: Ground
9 Start C

The algorithm is pretty straight forward to implement on the Arduino, polling the controller exactly the way a Genesis game would. This satisfies my first requirement. Now, things get a little more complicated with the six-button controller:

DB9 Pin Select is low Select is high Every 3rd select pulse
1 Up Up Z
2 Down Down Y
3 Ground Left X
4 Ground Right
5 Control: +5V
6 A B
7 Control: Select
8 Control: Ground
9 Start C

First, let’s call each dropping of the select pin to low then back to high a “select pulse”. Now, on every third select pulse the six-button controller will instead report back the states of the X, Y, and Z buttons (instead of Up, Down, and Left). On its face, it looks like we couldn’t have a game that supports both three and six-button controllers, because how does a game know what kind of controller is connected? On every third pulse how does a six-button enabled game know whether to use the first table or the second? On every third pulse, how does a six-button controller know not to report X, Y, Z for games that only support three-buttons? If the game and controller aren’t on the same page and they use the wrong mappings, they’ll record incorrect button presses.

How do the games and controllers make the right decisions?

One part of the answer (as described in Rosenberg’s notes) is in how often games actually poll the controller. The three-button controller uses dumb direct logic, which means it always uses the first table. It also means that technically you can poll the controller state super-fast (say every 50 microseconds) or super-slow (say every 20 milliseconds) and always get the same result. Now typically, a game is only going to poll the controller once per game frame (sixty times per second, or every 16.6 milliseconds). Which means, at the time of the six-button controller’s release, the vast majority of the games already published (which were three-button enabled only) only sent a single select pulse every ~16 milliseconds.

The six-button controller can use this to its advantage. Instead of dumb direct logic, it uses an IC to watch how often the select pulses come in. The IC knows that (given the game indicates it wants six-button mode), it should return the states of X, Y, and Z on every third select pulse. But it also knows that most games only support three-button mode, so a safe default is to just pretend to be a three-button controller and ignore reporting X, Y, and Z on every third pulse.

How does the controller decide? The frequency of the select pulses. If the IC only sees one select pulse every ~16 milliseconds, or one pulse per game frame, then its best bet is to take the safe route and assume three-button mode. In this way, the six-button controller is backwards-compatible, and most games will never get any incorrect button presses.

If that’s the case, how does a game indicate that it actually wants those X, Y, and Z buttons?

If the game believes that a six-button controller is attached, it will instead pulse the select line three times very quickly in one game frame. The first two times the game reads (and the controller reports) the button presses for three-button mode. Then the game pulses the controller a third time. At that point, the controller’s IC, seeing how quickly those pulses came in, presumes the game wants X, Y, and Z, so it reports X, Y, and Z.

So to sum up: if a game just wants the three-button control states, it pulses once every frame and uses the first table to read the results. If a game wants six-button control states, it pulses three times in one frame, using the second table to read the results. With this in mind, we can now read both controller types, which satisfies the first two of my requirements. We can easily implement an Arduino sketch that implements one or the other algorithm, if we already know which type of controller we’re going to have connected.

But what about my third requirement? What if we want one sketch that implements both modes? How do we make our board detect what kind of controller is connected?

This one took a little bit of experimenting to figure out, since Rosenberg’s notes don’t address the issue. Turns out the six-button controller’s IC has another trick up its sleeve with watching how fast those select pulses come in. As we just saw, since most games only expect three-button controls, the controller can default to three-button mode, and seeing slow pulses, will stay in three-button mode.

But now, if the game wants to check for a six-button controller, it can send rapid select pulses when a controller is connected, and if it’s a six-button controller, the IC will report that both the Up and Down buttons are being pressed at the same time!

Under normal circumstances this is impossible, as the controller’s d-pad rocks in the direction you press it. So with this neat trick, the controller lets the game know that a six-button controller is connected, giving the game to option to start polling the controller in six-button mode.

The way we implement this is simple: by default we poll in three-button mode very quickly. For three-button controllers, this works perfectly. After every pulse, we can check for both Up and Down being pressed at the same time. If we see that, we know a six-button controller is attached, so we switch to six-button mode, pulsing more slowly so that we don’t reset the IC.

This solves the first part of my third requirement: detecting when a six-button controller is connected. But what about the other way? The way it stands, once we connect a six-button controller, and our board switches to six-button polling, it’s stuck that way until we reset the board. If we hot-swap from a six-button to a three-button controller, we’ll get those annoying paired inputs (specifically, pressing Up will return Up and Z, Down will return Down and Y, Left will return Left and X).

What we need is a way of knowing when a controller is disconnected, so that we can switch back to the default three-button polling. Turns out we have everything we need in the tables above, something that works for both three and six-button controllers.

At the very beginning I said that by default the console puts all six of the DB9 output pins high, so that a button press causes the pin to drop low. So if no controllers are connected those output pins should stay high. Only a button press from a connected controller will drop a pin low, right? We could just press a button to let the board know we have a controller connected, but wait, there’s a better way!

As we can see in the tables above, when the select pin is low, DB9 pins three and four both go low, regardless of any button presses. So in effect, the controller presses imaginary buttons on pins three and four when select is low automatically. So, all we have to do is watch those pins – if they go low when select is low, then we know a controller is connected. If they’re high when select is low, it means the controller is no longer connected.

In implementation terms, when select is low, we can simply check those two pins like we would for any other button, and map the results of those imaginary “On” buttons. Watching those “buttons” we know when a controller is connected or not, and therefore we can easily switch back to three-button mode when a controller is disconnected. With that we now have everything we need to satisfy my main three requirements for the board. As for the 4th and final bonus requirement, recognizing that we only needed seven pins to read one controller, we’ve got plenty of left-over pins on the Uno to cover connecting one more.

The Sketch

Ok, so now for the sketch. Our basic algorithm is the following:

  • Default to three-button polling as fast as possible, using the first table and select pulsing algorithm.
  • If you ever see both Up and Down pressed at the same time, switch to six-button polling, using the second table and select pulsing algorithm.
  • If you ever see the “On” button state go away, switch back to three-button controller polling.
/*
 * Sega Controller Reader
 * Author: Jon Thysell &amp;lt;thysell@gmail.com&amp;gt;
 * Version: 1.0
 * Date: 7/26/2014
 *
 * Reads buttons presses from Sega Genesis 3/6 button controllers
 * and reports their state via the Serial connection. Handles hot
 * swapping of controllers and auto-switches between 3 and 6 button
 * polling patterns.
 *
 */

// Controller Button Flags
const int ON = 1;
const int UP = 2;
const int DOWN = 4;
const int LEFT = 8;
const int RIGHT = 16;
const int START = 32;
const int A = 64;
const int B = 128;
const int C = 256;
const int X = 512;
const int Y = 1024;
const int Z = 2048;

// Controller DB9 Pin 7 Mappings
const int SELECT[] = { 8, 9 };

typedef struct
{
  int player;
  int pin;
  int lowFlag;
  int highFlag;
  int pulse3Flag;
} input;

// Controller DB9 Pin to Button Flag Mappings
// First column is the controller index, second column
// is the Arduino pin that the controller's DB9 pin is
// attached to
input inputMap[] = {
  { 0,  2,  UP,    UP,     Z}, // P0 DB9 Pin 1
  { 0,  3,  DOWN,  DOWN,   Y}, // P0 DB9 Pin 2
  { 0,  4,  ON,    LEFT,   X}, // P0 DB9 Pin 3
  { 0,  5,  ON,    RIGHT,  0}, // P0 DB9 Pin 4
  { 0,  6,  A,     B,      0}, // P0 DB9 Pin 6
  { 0,  7,  START, C,      0}, // P0 DB9 Pin 9
  { 1,  A0, UP,    UP,     Z}, // P1 DB9 Pin 1
  { 1,  A1, DOWN,  DOWN,   Y}, // P1 DB9 Pin 2
  { 1,  A2, ON,    LEFT,   X}, // P1 DB9 Pin 3
  { 1,  A3, ON,    RIGHT,  0}, // P1 DB9 Pin 4
  { 1,  A4, A,     B,      0}, // P1 DB9 Pin 6
  { 1,  A5, START, C,      0}  // P1 DB9 Pin 9
};

// Controller State
int currentState[] = { 0, 0 };
int lastState[] = { -1, -1 };

// Default to three-button mode until six-button connects
boolean sixButtonMode[] = { false, false };

void setup()
{
  // Setup input pins
  for (int i = 0; i &amp;lt; sizeof(inputMap) / sizeof(input); i++)
  {
    pinMode(inputMap[i].pin, INPUT);
    digitalWrite(inputMap[i].pin, HIGH);
  }

  // Setup select pins
  for (int i = 0; i &amp;lt; 2; i++)
  {
    pinMode(SELECT[i], OUTPUT);
    digitalWrite(SELECT[i], HIGH);
  }

  Serial.begin(9600);
}

void loop()
{
  readButtons();
  sendStates();
}

void readButtons()
{
  for (int i = 0; i &amp;lt; 2; i++)
  {
    resetState(i);
    if (sixButtonMode[i])
    {
      read6buttons(i);
    }
    else
    {
      read3buttons(i);
    }
  }
}

void resetState(int player)
{
  currentState[player] = 0;
}

void read3buttons(int player)
{
  // Set SELECT LOW and read lowFlag
  digitalWrite(SELECT[player], LOW);

  delayMicroseconds(20);

  for (int i = 0; i &amp;lt; sizeof(inputMap) / sizeof(input); i++)
  {
    if (inputMap[i].player == player &amp;amp;&amp;amp; digitalRead(inputMap[i].pin) == LOW)
    {
      currentState[player] |= inputMap[i].lowFlag;
    }
  }

  // Set SELECT HIGH and read highFlag
  digitalWrite(SELECT[player], HIGH);

  delayMicroseconds(20);

  for (int i = 0; i &amp;lt; sizeof(inputMap) / sizeof(input); i++)
  {
    if (inputMap[i].player == player &amp;amp;&amp;amp; digitalRead(inputMap[i].pin) == LOW)
    {
      currentState[player] |= inputMap[i].highFlag;
    }
  }

  // When a six-button first connects, it'll spam UP and DOWN,
  // which signals the game to switch to 6-button polling
  if (currentState[player] == (ON | UP | DOWN))
  {
    sixButtonMode[player] = true;
  }
  // When a controller disconnects, revert to three-button polling
  else if ((currentState[player] &amp;amp; ON) == 0)
  {
    sixButtonMode[player] = false;
  }

  delayMicroseconds(20);
}

void read6buttons(int player)
{
  // Poll for three-button states twice
  read3buttons(player);
  read3buttons(player);

  // After two three-button polls, pulse the SELECT line
  // so the six-button reports the higher button states
  digitalWrite(SELECT[player], LOW);
  delayMicroseconds(20);
  digitalWrite(SELECT[player], HIGH);

  for(int i = 0; i &amp;lt; sizeof(inputMap) / sizeof(input); i++)
  {
    if (inputMap[i].player == player &amp;amp;&amp;amp; digitalRead(inputMap[i].pin) == LOW)
    {
      currentState[player] |= inputMap[i].pulse3Flag;
    }
  }

  delayMicroseconds(1000);
}

void sendStates()
{
  // Only report controller states if at least one has changed
  boolean hasChanged = false;

  for (int i = 0; i &amp;lt; 2; i++)
  {
    if (currentState[i] != lastState[i])
    {
      hasChanged = true;
    }
  }

  if (hasChanged)
  {
    for (int i = 0; i &amp;lt; 2; i++)
    {
      Serial.print((currentState[i] &amp;amp; ON) == ON ? "+" : "-");
      Serial.print((currentState[i] &amp;amp; UP) == UP ? "U" : "0");
      Serial.print((currentState[i] &amp;amp; DOWN) == DOWN ? "D" : "0");
      Serial.print((currentState[i] &amp;amp; LEFT) == LEFT ? "L" : "0");
      Serial.print((currentState[i] &amp;amp; RIGHT) == RIGHT ? "R" : "0");
      Serial.print((currentState[i] &amp;amp; START) == START ? "S" : "0");
      Serial.print((currentState[i] &amp;amp; A) == A ? "A" : "0");
      Serial.print((currentState[i] &amp;amp; B) == B ? "B" : "0");
      Serial.print((currentState[i] &amp;amp; C) == C ? "C" : "0");
      Serial.print((currentState[i] &amp;amp; X) == X ? "X" : "0");
      Serial.print((currentState[i] &amp;amp; Y) == Y ? "Y" : "0");
      Serial.print((currentState[i] &amp;amp; Z) == Z ? "Z" : "0");

      Serial.print((i == 0) ? "," : "\n");
      lastState[i] = currentState[i];
    }
  }
}

All you have to do is upload the sketch and connect the controller’s DB9 pins to the Arduino following the mapping in inputMap in the code. Then start up the Serial Monitor so you can see the output from the controller on your PC.

Here’s a closeup of how I’ve wired my Uno to a male DB9 breakout board (you can wire straight to the controller, or a male DB9 port, but I found the board the easiest solution):

segaarduino2

The sketch is also set up for a second controller connected to the analog pins on the other side of the Arduino, though I only had one male DB9 breakout board. Also note that this is my first real Arduino sketch, so I’m sure there are some best practices I’m breaking in my design.

I can already see room for future improvements. Right now I report the controller states over the serial connection as strings – easy to debug, but slow and wasteful. Of course, in your own sketches, you can just read the currentState integers directly.

Hope this helps anyone else out there trying to interface with Genesis controllers. Happy hacking!

/jon

PS. Obviously in the process of plugging and unplugging controllers, you may see some errant random button presses recorded. In the world of video games, this is to be expected, and only lasts for a second. If however, you’re planning on doing anything “bad” with a button press (say enabling a thermonuclear detonator), you might want to avoid hot-swapping controllers.

PPS. Final note, concerning the six-button controller’s “mode” button. Some games (notably Ms. Pac Man), don’t follow the rule of only polling the controller once per game frame, and select pulses more often. This causes erratic behavior as incorrect buttons presses are recorded. Ostensibly, when you plug in a six-button controller with the mode button held down, that signals the IC in the controller to always be in three-button mode and never report X, Y, or Z. Unfortunately, I couldn’t get it to work with my sketch and gave up because I saw no reason to limit my six-button controller to three-buttons anyway.

Update 29-SEP-2014: I’ve uploaded a new version of the sketch in Sega Genesis controllers and Arduino revisited, which includes support for reading the “Mode” button and reporting button presses as keyboard key presses (on compatible Arduino boards).

Update 26-JUN-2017: The source is now available on GitHub here.

Update 28-JUN-2017: I’ve announced a newer, stable, reusable version at Introducing the SegaController Arduino library.