Video Output Hardware

The video output is achieved using just two outputs: One for sync and one for color. These two ports are tied together with a resistor divided and form a crude DAC. This is based off of the Arduino TVout library http://playground.arduino.cc/Main/TVout


Controller Input

The controller input is an Atari 2600 Joystick. The pinout is provided here. http://www.hardwarebook.info/Atari_2600_Joystick I only use Left, Right and Fire for this project.

Video Output Software

I found the TVout software to be very hard to understand. I took 1 small part of it: the wait_until inline-assembly routine. The rest was discarded.

I took some liberties to what constitutes a NTSC signal. After trying to implement most of the spec, I settled on something that ended up being the same thing Atari and other consoles did: A 'hack' called 240P. The screen is not interfaced as usual, and there are no 'odd' and 'even' scanlines. Only 240 lines are drawn every frame, and there are 240 lines on the screen that are black and never drawn at all. If you want some deep details on how full NTSC is supposed to work, visit this page: http://www.ntsc-tv.com/ntsc-index-02.htm For info on how I stumbled upon 240P instead, I have a project log just on screen syncing, so I won't repeat it here.


Racing the Beam

To generate the video signal, the technique used here is called racing the beam. This is exactly how the Atari 2600 generates an image. There is no framebuffer. As the electron beam is scanning the TV, the software must pull the output high, to produce white, or pull the output low, to produce black, at the exact instant the electroncs are shot into the screen glass. This means timing must be perfect. Fortunately for me, I don't have to do much cycle-counting at all thanks to Interrupts.

The Atari 2600 had NO interrupts. The programmer must carefully work everything out during the blanking period and output the signal on-time. Using the Attiny timer interrupt, I can split the program into two threads. Thread 1 is the 'main' thread running game logic. This reads the joystick, and calculates where everything should be on the screen. Thread 2 is the interrupt handler: Every so often, the interrupt fires and the interrupt handler outputs 1 scanline of video. One thing gained by this project is a tremendous amount of respect for the Atari 2600 programmers, who had a much worse CPU and no interrupts. Somehow Pitfall happened.

Video Frame Structure

To represent the gamestate to draw, there are some variables defined:

The position of an object is just a number representing a point on a grid. The top-left position is 0, the one to the right is 1, all the way up to (SCR_COLS-1). Position SCR_COLS starts the second row, 2*SCR_COLS is the 3rd row. It looks like this:


00 01 02 03 04 05 06 07 08

09 10 11 12 13 14 15 16 17 18

19 20 21 22 23 24 25 26 27

...

A typical mushrooms array might look like { 5, 12, 17, 23, ENDOFLINE}; This would mean to draw a mushroom in positions 5, 12, 17 and 23. ENDOFLINE is the value 255, which serves as a terminator of the array.

Suppose we only want to draw mushrooms. For a given scanline, we can look thru the mushroom array for mushrooms that would appear on our row. We can display a horizontal 'slice' of pixels for a mushroom, or keep the display black, for every position on this row. The mushroom array is kept sorted so that after we draw part of a mushroom on a scanline, if there is another mushroom on the same row, it will simply be referenced in the next byte of the array.

The mushroom pixel data array looks like this:

unsigned char mushpxp[]={
	0b10000000,
	0b10111100,
	0b11111110,
	0b11111110,
	0b10011000,
	0b10011000,
	0b10011000,
	0b10000000
};
The above array is 8 bytes long, representing 8 rows of pixels. The leading 1 for every row is keeping the sync line high; check out the code for an explanation.

As the electron beam scans the screen, we keep track of what position number the beam is aiming at. If the position number equals a number in the mushrooms array, a byte of pixels is shifted out onto the screen. The pointer into the mushrooms array is incremented, and the program waits for the electron beam to catch up to the next mushroom position.

It is very important the that mushrooms array is always sorted. For easy (compact) coding, when new entries are added to the array, they are not added in the proper position. Every time through the main loop ( not the video loop) each mushroom position is compared to the position ahead of it. If two items are out of order, they are swapped. After a small number of frames, any mis-sorting is quickly self-corrected. This basically takes the terrible bubble-sort algorithm, but spreads it over time, making a very efficient incremental sorter.

To display bugs, I do the exact same thing, but use the bugs array instead, and use slices of bug sprite pixels. There is not enough CPU time to alternate between bugs and mushrooms in the same scanline. If I used a 20 Mhz crystal instead of 10, maybe, and if I wrote this in assembly instead of C, maybe. Instead, to display both bugs AND mushrooms, I cheated. On even frames I display only bugs, and on odd frames I display only mushrooms. The Atari 2600 games have a lot of cheats like this to make more things appear to be on the display at the same time.

The player position is represented on the bottom of the screen by a white rectangle, which is out of the field of action: The player will never appear on screen rows as bugs or mushrooms. The original intention is the game-over condition will be when a bug hits the bottom, like Space Invaders.

The last element of the screen is the bullet. The bullet is a single pixel high, short horizontal line. When we display a bullet on a row, nothing else on that row is drawn. If you look very carefully when you fire, you will see a 1 pixel high horizontal line traveling up the screen. Atari games (especially the 'bad' ones) are also full of strange little artifacts like this.