In this entry I’ll be describing the motivation behind porting Minotaur to x86 as well as describing some of the challenges I encountered along the way. Most of this information can be found in the FAQ and other various documents in the source tree, but I am going to recap everything here in an attempt to keep things in one place.
Probably the first question that comes to mind is why port this archaic game in the first place? To answer, we need to go back to 1982. Back then, I had an original TRS-80 Color Computer with 4k of memory. Shortly after, I acquired Madness and the Minotaur as a present. Unfortunately, this game required 16k, and I only had 4k. Since I wanted to use Extended Color Basic with all its fancy features anyway, I went for the 16k upgrade. After the upgrade, I must have played Minotaur for hours, but never did beat it – partially because the game is so difficult, and partially because back then, we saved our data to cassette tape which wasn’t very reliable. Anyone who has used cassette tape for storage knows what I’m talking about. After spending what seemed like hours trying to load your saved game, listening to sounds similar to that made by a modem, 7 out of 10 times the load would fail with the dreaded “CLOADM ?IOERROR”. Sometimes repeated attempts would successfully load the game, but more often than not it wouldn’t help. So that saved game you just spent 10 hours playing was lost forever. Then sometime in 1982, “cheap” ($1200) IBM XT clones began appearing on the market and I traded in my my trusty CoCo for an 8088 clone, learning all about this new MS-DOS operating system, quickly forgetting about Madness and the Minotaur and the days of cassette storage.
Fast-forward 30 years to the Internet age. Sitting around one day, Minotaur popped into my head for no apparent reason and I decided to google it. Lo & behold, there were a couple of links talking about how hard Madness was to beat. One page, http://www.figmentfly.com/madnessandtheminotaur, even had the binary and information on how to run Madness in a simulator. So I downloaded it and tried some of the simulators, but found them too cumbersome to use, especially around saving and restoring the game. One of the links on the figmentfly page was to a disassembled binary by Chris Cantrell (http://www.computerarcheology.com), complete with full commentary.
Looking over Chris’s source made me think that a port to x86 Linux would be the most beneficial thing for me to do – that way I could easily play the game on my Linux box and also implement a simple save/restore mechanism myself. So with that goal in mind, I set out to port Chris’s commented 6809 sources to x86. Technically, I originally made Chris’s source code compilable and relocatable on the 6809 and then used that code for the port, but in the end the result was the same – Madness and the Minotaur running natively on Linux.
So with the question of why the port to Linux answered, the next logical question is why port to assembler, and not some other high-level language like C? The reason for that is two-fold:
1) Considering the age of the original game and its strong ties to the 6809 processor, porting to x86 assembly might actually have been easier than porting to a high-level language first. Some of the reasons for this are the 8-bit nature of the game, where things such as variable size matter. Another reason is the standard assembly practice (at least back then) of using jumps instead of subroutines, as well as tail recursion. Yet another reason would be the popular tricks used back then such as the LXI Trick (which you can read more about here in item #9: http://www.drdobbs.com/embedded-systems/assembly-language-tricks-of-the-trade/184408315. Such tricks, though very useful back then when memory was tight, are hardly needed today and are fading fast from the memory banks of most programmers. Since all of these tricks and practices would need to be unrolled before porting to a higher-level language anyway, assembly seemed the best choice.
2) The second, and perhaps most important reason, is that I now had an excuse to work with assembly again and sharpen my skills. It’s not often these days that I get to use assembly, never mind two assembly languages at the same time – 6809 and x86.
On the subject of assemblers, I imagine some assembly folks will be upset that I chose the GNU assembler for the port rather than NASM. Simply put, I prefer the AT&T assembly style, and since that is the default style on UNIX, it just made sense. Plus the GNU assembler is available on many platforms, though that argument could be made for NASM as well. If anyone really wants a NASM version, there is a Linux utility named intel2gas that can help translate from AT&T to Intel style. Despite its name, the utility also translates from GAS to NASM.
Another assembly decision I had to make was whether to port to 32-bit or 64-bit. I thought 32-bit would reach the most audiences, as there are still a lot of 32-bit architectures out there. Also, the 32-bit version will run just fine on a 64-bit processor, as there is nothing in the program that requires anything greater than 16-bits. 64-bit assembly would be really overkill for this program, and I imagine the resulting binary would be quite bigger. If for some reason a 64-bit port is needed, it should be a simple matter of changing the register names and taking care of overflow/underflow operations from the original 8-bit design.
I also skipped over 16-bit assembly because it is obsolete and would require working with segments. Segments? Enough said.
More to follow …