This page gives some background detail on how I created the various versions of my Toss Up Simulators. I refer to these as being reasonably accurate. In truth they're actually very accurate but they aren't perfect. Using the term 'reasonably' is somewhat ironic since I went to, what most will consider, pretty extreme lengths to create them. I expect many readers will think that what I've done is sad (surely I've better things to do with my time) though I hope some will think it's clever. Whatever your point of view, I hope this page provides you with some entertainment.
There are two main problems areas faced when trying to emulate a game, the first issue is working out exactly how the original device works; the second is implementing this operation on the target platform. During each phase it's very easily to lose information, the end result is a poor translation.
Toss Up is one of the simplest Game & Watch game. Therefore coming up with accurate timing information should be easy. That's what I thought when I started but it proved to be more complex than I expected and required several iterations to get completely on top of it.
The classic approach of working out how a Game & Watch device works is to record the sound from the device as you play it. Not only does this give you sound samples to use in the simulator but more importantly you can use a standard sound editor to analyse the interval between beeps. Doing so gives you a measure of how fast the game runs and at which points the game play speeds up.
This approach works well up to a point. To really understand the game you need to know exactly what happens after large scores. For example what happens when the score on Game A reaches 9999 and then wraps around. The biggest problem for me, is that I'm a poor toss up player. To get 9999 points on Game A takes around 3 hours. I simply don't have the ability or the patience to play the game for this amount of time so I looked to alternatives to find out exactly what's going on.
Playing the game by hand I was pretty sure I knew how the game operated. While I didn't know for sure what happened after 9999 points, this wouldn't stop me implementing a reasonable simulator. After all I very much doubt anyone's going to play the game for more than 15 mins at a time. For me it was the challenge of finding out what really happens that prompted me to start thinking of ways to produce a computer player that would play Toss Up faultless for hours.
After several false starts I ended up building the system shown below. The operation is straightforward. Wires are connected (using the hitech attachment mechanism of cellotape) to the game's piezo-electric speaker, which in turn feed into my PC's sound card. When each ball moves the game makes a beep at a fixed frequency. By doing some relatively straightforward analysis of the input sound, I could determine exactly where each ball is and when they are due to move next. I wrote a relatively simple program that ran on my PC that kept track of the balls and then worked out exactly when to send a signal to the game to cause the juggler to catch each ball. The signal was sent via the parallel port into a couple of transistors. These transistors switch on and off, mimicking the action of pressing the buttons on the game. To complete the circuit the output from the transistors was fed, via another couple of wires, to the button contacts on the game PCB (the wires again were attached with cellotape).
With this, Heath Robinson like, device I was able to 'play' both variants of the game for several hours. And from this I was able to find out exactly what happens when Game A wraps around. Let me tell you, it's not very exciting.
Using the device described above I was able to log several hours' worth of data for both variants of the game. The next step was to munge it into a form that made some sense. I decided to graph the interval between ball movements as the game progresses. The graph below shows these readings up to a score just over 200 points. The game starts of quite slowly with around 400 msec between each ball movement, when the game reaches 5 points it speeds up to around 340 msec. It then continues to speed up every 10 points until it reaches 100 points, where is slows down. This pattern of speeding up every ten points and slowing down every 100 repeats forever (or for at least 8 hours - which is as long as I logged data for). Game B has very similar characteristics.
Knowing exactly how the game works is the first step the next step is to translate this into a program that runs on the target platform. There are a number of areas where I've taking shortcuts in the the translation. I've tended to take this line because certain features are too difficult (or impossible) to implement. For the sake of pedantry, the differences are listed here.
If you look at the graph of the game speed above you'll see that the interval between ball movements is slightly irregular. The timings tend to deviate by about 10 msecs around a constant value. To make life easier for me I chose to reimplement the game using constant intervals, I doubt anyone's going to notice this.
I also chose to use whole numbers of milliseconds for each interval. This means that an interval of 435.7 msec ends up being 436 msec, therefore each ball movement has a possible timing error of +/- 0.5 msec. This error is cumulative, which means that if you play the game for a long time it could be several seconds out of sync with the original. Most people won't notice this but if you own the original game and play it side by side with the simulator you'll notice that after about 20 points or so (200 odd ball movements) the games will be slightly out of sync. They are less then a second apart but it's enough to be noticeable.
This is a odd one. From building the controller described above I discovered two things about the game. Firstly they are times in the game when you press and release a button and the arms don't move. This tends to happen when two or there balls are being caught shortly after each other. This 'feature' is probably due to the way the real game polls each button to detect a press, when sounds are being played this polling doesn't occur as frequently and so it can miss button presses. I chose not to implement this 'feature' and instead the arms move every time you press a button.
The other thing I discovered is that if you press the buttons on the real game pretty fast, the game slows down. For example if you press the left and right buttons at around 50 times a second, each ball movement slows down to around 5 seconds. I chose not to implement this feature. Although saying that the Palm version does does slow down if you move the arms, this is not intentional and is just a 'feature' of the way PalmOS works.
After all this talk about obtaining accurate timings it may surprise many that there is no reliable way to implement precise timings on any of my target architectures. This is because most general purpose operating systems aren't designed to be real time systems. There are good reasons for this, if you're interested in the nitty gitty check out this this article on Code Project that explains why things are the way they are on Windows. From my point of view this means that, no matter what I do, there's a limit as to how accurately I can write the simulator. This accuracy limit varies between operating systems.
Win32 has very accurate timers (which can be sub millisecond) but these aren't available on all architectures and can be quite expensive to use. In order to support the widest range of hardware I choose to use Multimedia Timers. These are available on all Win32 systems and, in theory can reach millisecond accuracy but there's no guarantees. I'm not sure what the worse case value is, but it could be as low as 55 msecs.
Things are worse on the PalmOS where the best I can achieve is 1/100th second accuracy. In truth I'm quite disappointed by the Palm port. It is quite noticeable that the program can't play at the correct speed by the fact that you can clearly hear the tempo of beeps isn't constant. I'm not sure if this is due to the way the sound is played back or the way input events (pressing the buttons) are handled. If any PalmOS experts out there can offer any answers then give me a shout.
Java applets also don't give any guarantees about timing, which isn't surprising really since the Java virtual machine is designed to run on a very wide range of devices. Fortunately the Java port seems to work very well on the platforms I've tested it on, but depending on the implementation of the virtual machine, the Java applet could behave very erratically.