The Atari 2600: A Personal Journey into the Past
How I rediscovered my first game console and wrote a small game for it.
Childhood Memories
I was born in the early eighties and spent the vast majority of my childhood in Venezuela. My dad was offered a job in the booming oil industry and we all moved down there and lived in an expat trailer park in Puerto Ordaz. This was a kind of gated community with a fence and a security guard, with cheap housing and security for foreign personnel like my father. The community had an American school, a playground and a tennis court. We didn’t go out much, except for groceries.
Every once in a while, my father or a colleague would return from a trip abroad and bring home something from the outside world. Probably around 1988 or 1989, I must have been eight years old, a magical box appeared in our living room. The Atari VCS 2600 Jr.
The Atari 2600 has an 8-bit MOS 6507 processor running at 1.17 MHz and 128 bytes of RAM, which was measly even back then. Notably the system did not feature a frame buffer, making it necessary to draw the picture as the electron gun moved across the screen. This is known as “racing the beam”, and I can highly recommend the fascinating book that goes by the same name if you’re interested in the history of the Atari. If you’re more of a TL;DR type, check out the WIRED article.
Later I found out what was now gracing our small living room was actually the 2nd generation, miniaturized version of the original Atari 2600, which came in a more stylish, wooden enclosure. Back then I couldn’t have cared less, but I’m pretty sure the hipsters of the mid-eighties would have regarded the Jr. with disdain.
My brother and I, as well as the other boys from the neighbourhood, spent many, many happy hours playing all kinds of games on the Atari. When I grew older, we moved to Switzerland and the Atari was replaced with an NES, a Sega Mega Drive, a Super NES, … vastly superior consoles in technical terms. The Atari did not travel with us, I assume that we gifted it to the locals.
Fast-forward a couple of years to when I was around fourteen or fifteen, almost a decade after my first encounter with the Atari. I was in high school and joined an elective course for kids interested in computers. The main appeal for me and my comrades was the half hour of Command & Conquer after class, on the Ethernet-connected Intel PCs in the classroom. The actual goal of the class was to learn how to use Office productivity software and acquire basic programming skills. The IDE of choice was Q-Basic, an IDE and interpreter for the BASIC programming language.
Using Q-Basic, I wrote my first computer game. I called it Hund, which is the German word for dog. The game was incredibly simple and featured two dogs running across the screen from left to right, randomly. The first dog to reach the right side of the screen would win. No user interaction required.
You could play with a friend and speculate which dog would win, even bet money on it. Needless to say, it was a pretty boring game. I wish I could say that I was hooked on game development from that moment and went on to produce a bestseller. But as already mentioned, we primarily wanted to play Command & Conquer. Nevertheless Hund became the first game I remember writing.
These days, I write software for a living and still enjoy it. But with increased age, marriage, fatherhood and whatnot comes sentimentality… just recently I suffered a bout of nostalgia and wanted to relive some of my childhood experiences. I decided that I wanted to know more about the Atari, my first game console, and write a game for it. What better place to start than Hund?
Obtaining the Console
As I am no longer in possession of the original, I first had to buy a used Atari 2600 Jr. This proved to be surprisingly easy. They were produced in such numbers that they are still readily available. A search on Ebay yields around 500 results. I also procured a copy of River Raid, my favourite game back then.
When everything had arrived, I excitedly unpacked and connected it to the television in my office. To my dismay, I did not get a picture. I soon realised that our office television was too modern and did not have an analog TV tuner anymore. Luckily I had a 10 year old television at home. That TV managed to tune to the channel where the Atari was sending its picture, but somehow couldn’t hold the picture. Sometimes it wouldn’t find the channel at all.
At this point I was extremely frustrated with myself and the world in general. How would I ever write a game for the Atari, if I wasn’t even capable of playing on it in the first place?
Phase 0 — Minor Modifications
In the quiet first few days of the new year, I met a friend of mine over a beer and told him my story. Having some experience with vintage consoles, he pointed me to an article (German-only) describing how to modify the Atari 2600 to connect it to a modern TV. Some soldering and milling would be involved. Lucky for me, the Atari’s mainboard was easy to access and proved to be very solder-friendly.
The modification involves removing some material from the case and the mainboard, and drilling three holes to hold cinch terminals.
Some soldering is also required, acouple of resistors and capacitors need to be added, and connected to the cinch terminals with some cable.
A couple of hours later, the modification was complete, and my Atari retrofitted with cinch terminals for composite A/V output. I anxiously connected it to the TV again, changed its input source to Composite, and turned on the console. To my delight, I got an acceptable picture and was finally able to play some River Raid.
This marked the completion of phase 0 of my Atari 2600 project. Like in real life, I did not initially think there would be a phase 0.
Developing for the Atari 2600
Development Environment
Full of positive energy I proceeded to install the tooling I needed to write a game for the Atari. All you need is the dasm assembler (“a versatile macro assembler with support for several 8-bit microprocessors”) and the Atari 2600 emulator Stella. Both can be installed via Homebrew on a Mac, so that part was super easy.
$ brew install dasm stella
Apart from that, only a text editor is needed.
Racing the Beam
The Atari 2600 is an unusual machine to program for. The environment is very limited, with only three registers (with only one general purpose register) on the MOS6057 and a measly 128 bytes of RAM. That is not the main challenge though.
What makes developing for the Atari 2600 so interesting (or should I say, infuriating) is the absence of a frame buffer. Simply put, a frame buffer allows displaying a picture by writing color values to memory addresses. It is basically a bitmap of an entire screen somewhere in memory. Change the contents of the bitmap, and the displayed pixels change. And crucially, once you’ve written to the frame buffer, the picture stays that way.
That is not how it works on the Atari.
On the Atari, rendering must occur while the picture is drawn by the TV. The entire programming model of an Atari game revolves around the movement of the electron beam inside a classic TV. The beam moves from top to bottom, generating so-called scan lines. Scan lines are traced from left to right. As the electron beamreaches the bottom, it needs to be turned off and repositioned to the top. This is known as the vertical blanking interval. At the end of every scan line, horizontal repositioning needs to occur as well, in the horizontal blanking interval. The diagram below is an excerpt from the Atari 2600 programming manual and visualizes the situation.
Game logic must reside in the vertical blank and overscan regions, executing when the electron beam is off. The Atari 2600’s graphic chip needs to be told what to draw for every scan line, during the horizontal blank interval, which lasts about 22 processor cycles. To put this in perspective, even simple operations like an addition take two processor cycles. Every cycle counts, and in fact cycle counting is an essential part of Atari programming.
In essence, your code is always trying to stay ahead of the electron beam, hence the term “racing the beam”.
Hello World
To get an idea of the structure of typical Atari 2600 game, a hello world example helps. I will not go into detail here, as there are many excellent tutorials, especially over at AtariAge.
The example draws a one-line player sprite (pixel values 01010101) on every scan line. A count of the number of visible scan lines generated is kept inside the x register, and is also used as the color value of the player sprite, creating a vertical rainbow pattern.
The MOS6057 CPU communicates with the graphics chip via specially mapped memory addresses. In the example, a “sta WSYNC” means “store the contents of register a (the accumulator) at the address WSYNC (0x02)”. This will cause the graphics chip to halt the CPU until the scan line has ended, and wake it up afterwards, at the beginning of the horizontal blank interval of the next scan line. This allows the CPU to be in sync with the movement of the electron beam. The CPU and the graphic chip are constantly performing this handshake to synchronize program execution with what is displayed on the screen.
A “sta RESP0” tells the graphics chip to “draw player 0 sprite”. The instruciton must execute at exactly the right time, when the beam is at the horizontal position where we want our sprite to appear. In the example, we use a series of nop (no-operation or dummy) instructions that are designed to waste two processor cycles, to position the beam towards the center of the screen.
It should be obvious now that the code that executes in the visible scan lines is very time-critical, so it needs to be really efficient. There are all sorts of tricks you can pull, and the AtariAge forums are full of priceless advice. Any game logic should reside in the vertical blank and overscan regions, where the beam is off.
Running it in the Emulator
Now that we have our hello world example ready, let’s compile it into a binary with dasm, and run it in the emulator.
$ dasm hello.asm -ohello.bin -f3
$ Stella hello.bin
That’s the basic development workflow for the Atari 2600.
Running it on the Hardware
To run the game on the Atari 2600, we need to first load it onto a cartridge. The Harmony Cartridge simulates an Atari cart and allows us to run our game on real hardware, simply by copying it to FAT-formatted SD card.
Writing “Hund”
Armed with running hardware and a functional development environment, I proceeded to bring the “Hund experience” to the Atari 2600.
Hund on the Atari 2600 is a 2-player game, with each player moving their dog forward by repeatedly mashing the joystick’s single button. There is also an epilepsy inducing welcome screen displaying the game’s name, and a screen displaying the winner of a match.
I will quickly summarize how each screen is implemented. If you’d like more detail, the full source code is available on Github.
Welcome Screen
This screen is displayed when the game starts up, and simply displays “HUND” vertically, with alternating colors.
The text is stored as a bitmap towards the end of the ROM source.
WelcomePhrase:
.BYTE %00000000 ; H
.BYTE %01000010
.BYTE %01000010
.BYTE %01111110
.BYTE %01000010
.BYTE %01000010
.BYTE %01000010
.BYTE %00000000
... and so so on ...
The scan line loop keeps the number of visible lines in the x register (like in the hello world example), and an offset into the bitmap in the y register. Every line of the bitmap is repeated overfour scan lines. The Atari’s PF1 playfield register (a kind of background sprite) is used to draw the bitmap.
The screen is dismissed when both players press their joystick button simultaneously.
Game Screen
This is the actual game screen.
- The two player sprites GRP0 and GRP1 are used to display the dogs
- Both player’s horizontal positions are stored in variables (P0_X and P0_Y)
- In the vertical blank, the states of the joystick buttons are queried. The dogs advance whenever a button is released (P0_PRESSED and P1_PRESSED variables go from 1 to 0)
- Sprites are positioned horizontally by writing to the RESP0 and RESP1 strobe registers at the right time (just like in the example). A divide-by-15 loop wastes the appropriate amount of CPU cycles before the sprite is drawn. A table holds the remainder values of a division by 15. The position is fine-tuned using the HMP0 and HMP1 registers, which allow to horizontally shift a sprite by -8 to +7 pixels. See this explanation if you’re interested in what these sentences mean.
- When either player’s position reaches 160 (the number of pixels in the horizontal), that player wins, and the win screen is displayed.
Win Screen
This screen is almost identical to the Welcome screen, except a different text is displayed, depending on which dog won (“WIN1” or “WIN2”).
Conclusion
In writing Hund, I’ve really only scratched the surface of Atari 2600 development. It is amazing and incredibly humbling to see the kind of games developers of that time managed to write, given the console’s constraints.
Once again, for anyone interested in the Atari 2600 platform and the types of games it spawned, I highly recommend reading the book “Racing the Beam”.
For myself, this was a fun way of indulging my own nostalgia.