Saturday 31 August 2013

Arduino Game Player - Sega Master System (2 of 2)

Here is the code and the sketch that I promised in part one.

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 it's 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.

Here is the refactored code:

// 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 can also see 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 couldn't be bothered!

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 result:

Arduino - Sega Master System Controller (2/2)

And as I mention 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.

God knows making level solvers isn't one!

Happy computing!

No comments:

Post a Comment