My Brill Game Site My Brill Game Site

Arduino Master System Player

Here's a fun little project I've wanted to work on for a while, an automated system that is able to play console based games.

Initially I thought about making a series of wires that connected my PC to a variety of video game consoles via their control ports but since I have the Arduino I think I can throw together something simpler yet just as effective with it.

Current State (Last updated - 25 Aug 2013)

Completed

History

There are already a few blogs out there showing how to do this, for example this one on instructables which shows you how to tap into a Snes controller or this one also on instructables which shows you how to do the same to an Xbox 360 controller, however, this isn't quite what I'm looking to do. I want to connect my Arduino directly to the control port of the system, not to the controller. I will admit though using the Arduino as a controller 'expansion' to allow macros and the like is a pretty cool idea and I may come back to that at some point.

I also want to do more with this project than just connect the Arduino to the target system, I also want it to play the games on the system. I've italicised the word play as I'm not exactly certain how I'm going to define the word play yet. Is just moving the character enough or does the character have to be moved towards the goal? Does the system have to work out the goal or can it be pre-programmed in? Does the path to the goal need to be the optimum one or can it be anything as long as it is in the right direction? Does it need to learn?

As you can see there is a pretty wide scope as to what could be considered playing but for now I'm going to focus on just getting the character moving and worry about more details later.

Regardless of your definition it is clear this project has 2 key parts:

  1. Connecting the Arduino to the system.
  2. Sending commands to have the character do what we want.

So let's start with the first part.

Connecting the Arduino to the System

To start off with I'm going to look at the Sega Master System. It's the simplest system I have sitting around the house and I remember from previous reading that it has a pretty straight forward controller.

I've opened up one of the controllers and here are the results:

Original Sega Master System controller Original Sega Master System controller.
The screws taken off and the top flipped over The screws taken off and the top flipped over

The PCB boards flipped back down The PCB boards flipped back down.

As you can see it is pretty basic. We have a D-pad which maps to 4 buttons - Up, Down, Left, Right and 2 action buttons - 1 and 2 (yet I prefer to call them A and B). There are 7 wires coming from the controller 6 of which connect to their own button and then a 7th which connects to them all. I believe the 7th is ground or 5v but I'll confirm this later in the post.

Here is the mapping of wire colour to button:

  • Brown - Up - 1
  • Red - Down - 2
  • Orange - Left - 3
  • Yellow - Right - 4
  • Blue - A (1) button - 9
  • White - B (2) button - 6
  • Black - 5v or ground - 8

Notice I've put some numbers next to the mappings as well, these are written on the PCB next to each wire connection. I'm not sure what they mean (probably just instructions to guide the original assembler) but I thought it might be worth documenting.

Now in the blogs I've linked to they've kept the controller in as part of the circuit but I'm going to remove it from the equation completely. This means we can simplify things as we won't have to use a series of diodes like they do to protect the Arduino which is always nice. I'm also going to do something I don't normally do and take the original controller apart to get the connector from it.

I hate destroying original hardware and normally wouldn't but when I opened up what was going to be my donor connector (an old serial mouse) I found it only had 4 wires running through it, not nearly enough! Thankfully I have about 5 Master System controllers so can afford to donate one to this project and also the soldering sections on the controller are really well spaced apart so I should be able to take it apart and put it back together again without issue.

Right lets de-solder!

Pre-de-soldering. Nice spaced out connections Pre-de-soldering. Nice spaced out connections.
Post-de-soldering. Shouldn't be hard to resolder Post-de-soldering. Shouldn't be hard to resolder.

And now we have our connector!

I'm still not certain how to check a if a wire is ground or not without the risk of damaging some of the components it is connected to so rather than connecting my multimeter across the wires I've looked on-line for the information on the pin-outs from the controller. This useful page here at http://pinouts.ru tells us that each wire except black, which is in fact ground, puts out a small voltage. When the circuit with ground is complete the voltage drops across the button and the system reads this as the button being pressed. You can test this, and the colour chart above, by touching the wires to the black wire when you have a game running. You should see your character move about as if you were pressing the corresponding button on a controller.

Now to connect it to the Arduino. I was a little confused as to how to do this since there is a voltage coming from all the button wires which is the opposite of what I expected. I thought there would be no voltage on the wires until they were pressed so we could simulate it by connecting it to a digital out pin on the Arduino and setting it to high, this is not the case but not far off it. Thanks to Grumpy Mike's help on my topic in the Arduino forums I was able to get everything hooked up properly.

Turns out we can still connect to the Arduino ports without risk even though there is a voltage coming from the wires. Then we set the pin to be an input when we want it to simulate not being pressed and an output set to low when we want to simulate it being pressed. I'm still a little uncertain as to why this works but here is Grumpy Mike's explanation:

An output low is the same as ground, a low impedance connection to ground.
An input is a high impedance path, therefore is the same as nothing connected at all.

So I hooked it up and give it a try. At first I connected it with LEDs in series with the buttons but the Master System didn't register when they were there so I removed them but kept the resistors just in case.

Initial set up with the LEDs in place. Doesn't work Initial set up with the LEDs in place. Doesn't work.
Revised set up with no LEDs. Not as pretty but works Revised set up with no LEDs. Not as pretty but works.

Result! It works!

Sending Commands to Have the Character Do What We Want

I started off just having the system simulate the A button since this also doubles as the Start button and is the button that need to be pressed to start the game. This worked nicely. I then revised the code to iterate through all the buttons. This also worked nicely! Here's a short video showing the results and also lets you see the code:

Arduino - Sega Master System Controller (1/2)

After playing around a little bit I set about refactoring the code and this is what I came up with:

// Master System Player

byte pinUP = 2;
byte pinDOWN = 3;
byte pinLEFT = 4;
byte pinRIGHT = 5;
byte pinA = 6;
byte pinB = 7;

void setup() {
  //Set all the buttons to un-pressed
  pinMode(pinUP, INPUT);
  pinMode(pinDOWN, INPUT);
  pinMode(pinLEFT, INPUT);
  pinMode(pinRIGHT, INPUT);
  pinMode(pinA, INPUT);
  pinMode(pinB, INPUT);
  //Wait whilst the Sega logo appears
  delay(10000);
  //Hit start and wait for the game to begin!
  pushButton(&pinA, 1, 50);
  delay(5000);
}

void loop() {
  //Down to the first bird
  pushButton(&pinRIGHT, 1, 730);
  pushButton(&pinLEFT, 1, 860);
  pushButton(&pinRIGHT, 1, 500);
  pushButton(&pinLEFT, 1, 800);
  pushButton(&pinRIGHT, 1, 500);
  //Wait for the second one
  delay(1400);
  pushButton(&pinRIGHT, 1, 300);
  pushButton(&pinLEFT, 1, 100);
  //Ring time
  pushButton(&pinRIGHT, 1, 1000);
  pushButton(&pinA, 1, 50);
  pushButton(&pinRIGHT, 1, 500);
  pushButton(&pinLEFT, 1, 1500);
  pushButton(&pinRIGHT, 1, 1500);
  pushButton(&pinLEFT, 1, 1000);
  //BLAM!!
  pushButton(&pinA, 1, 50);
  pushButton(&pinLEFT, 1, 1500);
  pushButton(&pinRIGHT, 1, 1500);
}

/**
* Pushes a combination of buttons for the given amount of time.
*
* A negitive number can be used to hold the button indefinitely and 0 used to release it.
* Anything smaller than 50ms runs the risk of not being registered (this is through experimentation,
* not through checking the Sega documentation which could improve accuracy if needed).
*
**/
void pushButton(byte* buttons, byte count, int time){
  for (byte i = 0; i < count; ++i){
    pinMode(buttons[i], OUTPUT);
    digitalWrite(pinUP, LOW);
  }
  if (time < 0){ return; }
  if (time > 0){ delay(time); }
  for (byte i = 0; i < count; ++i){
    pinMode(buttons[i], INPUT);
  }
}

You'll notice I've refactored the code a bit so that the button pressing code is now just 1 method where we pass in the buttons we want to press, the amount of buttons we want to press and the length of time we want to press them for.

This makes a lot more sense on a platform like the Arduino due its limited memory, no point in filling it up with six methods that do pretty much the same thing. Of course it is good practice in programming in general as well since now if we want to change how we press a button we only have to change it in one place, not six.

You may also notice I've changed the code to do more than iterate through each of the buttons. It now plays the game for a few moments to advance Alex the Kidd through the first level.

Now here is something that actually came as a surprise to me (and I'm not being sarcastic) but making the code to go through a level is actually very, very dull! I was genuinely surprised! I am a guy who enjoys ROM hacking, reading through line after line of hex changing a little here and a little there to try and find my goal yet generating the level solving code above was really boring. I was going to do the whole level but got so fed up I couldn't bring myself to complete it all!

So for now I don't have a huge use for this, at least not on the Sega Master System, unless of course you are a speed run perfectionist in which case this can certainly be used to achieve the perfect speed run on the real hardware, it'll just bore you to death making it.

Here's a video of the end results:

Arduino - Sega Master System Controller (2/2)

Here is the schematic to the fairly simple circuit:

Note the orange wire goes to pin 4. 

I made the diagram using Fritzing which you can get from http://fritzing.org. It's pretty straight forward to use (I'd never used it before this post) but looks to be pretty powerful. It also has a huge projects page to give you lots more ideas for fun things to do.

Thanks again to all those who helped and to all those who continue to share information online.

Screenshots

Nothing to see here at the moment.

Want To Know More?

If you want to know more about this project you can email me using the details in the contact page.

Download

None yet.