# How did the Atari 2600 achieve a resolution of 160 x 192 pixels with only 128 bytes of memory?

According to wikipedia, the Atari 2600 had a resolution of 160 x 192 pixels. Had it been monochrome, it would had needed 160*192 = 30,720 bits of video RAM, or 3,840 bytes.

But the total memory was 128 BYTES.

How did it manage to reach that resolution with that memory? (Which was also needed to do the computations).

• According to the very Wikipedia article you linked to, "(additional RAM may be included in the game cartridges)". Under the circumstances, I'd consider it likely that "may" should actually be "was". Mar 18 at 11:50
• Also from the same article, I'd guess that pixels for display were not stored in the thing that the article calls "RAM". E.g., the shift register in the TIA.
– dave
Mar 18 at 11:52
• A screen can be operated without a memory-mapped display. Mar 18 at 12:08
• Quelle surprise, Wikipedia doesn’t quite grasp the facts. The Atari 2600 can do any number of lines down the screen that the programmer desires. So the nominal limit for NTSC is 241 though TVs will vary. Mar 18 at 12:51
• Short version: The Atari 2600 didn't have a resolution of `160x192`. It had a resolution of `160`. And it's not `160` by anything. It's `160` pixels. Source: David Crane Mar 20 at 19:56

## 5 Answers

According to wikipedia, the Atari 2600 had a resolution of 160 x 192 pixels. had it been monochrome, it would had needed 160*192 = 30,720 bits of video RAM, or 3,840 bytes.

Even more taking colour into account as the VCS could do 16 colours in 8 shades each. That'll be 7 bits per 'pixel' for a total of 215,040 bits or 26.25 KiB - not to mention that the PAL version could do 228 lines instead of 192. All with the same 128 Bytes not being used ::))

Note that already the basic Atari 2600 Wikipedia article explains the design as being not based on a frame buffer, but 'Racing the Beam'.

The corresponding TIA article (also linked in the very Wikipedia entry cited in your question) provides a dedicated section to its RAM-Less-Design.

How did managed to reach that resolution with that memory?

First of all, you're mixing up resolution - which is the number of screen positions that can be addressed - with placeable elements - that is the graphic items that can be present. In frame-buffer systems this is usually equal, with each addressable element having its own data storage. That's not true for non-frame-buffer systems.

The VCS was a non-frame-buffer system. The TIA 'graphics' chip worked more like today's GPUs. It rendered a new picture every frame from live data it got passed by the CPU. Think of it like DMA feeding the GPU (*1). And, while those elements (background, player, missiles, ball) could be places at (almost) every location, there weren't enough elements to also fill all locations.

Since rendering was done on a line by line basis, the base resolution was not 160 pixel, but a background of:

• 40 blocks, each 4 pixels wide, using two colours (out of 128).

Those blocks could be overlayed at any pixel position (0..159) by

• two 8 pixel wide 'players' using one colour each,
• two 1, 2, 4 or 8 pixel blocks called 'missiles', using the same two colours, and
• one 1, 2, 4 or 8 pixel wide block called 'ball', using one of the background colours.

That way, a single screen line used anywhere from 20 bits (3 bytes) for a simple background with no sprites, up to 8 bytes with sprites. All that data got transferred live, every line (*2), from CPU into TIA Registers.

Since all of that data was provided by the CPU, it could be sourced from any location, RAM, ROM or even code. Fixed screen data came almost always from ROM. For variable data RAM only held pointers to ROM sections with those bitmaps. If at all, it was only copied to RAM for some critical high speed sections.

Using some clever program timing it was possible to reload sprites and background during line display improving resolution a bit. For example maximum resolution could be reached for up to 48 consecutive pixels, but only once per line. Or 4-8 times 8 pixels within defined distances. But at that point we're way past beginner programming :))

*1 - Which is what the later Atari home computers did - their video design is a much powered up extension of the VCS. That's why they allow such awesome graphics without much programming.

*2 - Well, to be exact, only on lines with new content. As long as no timing tricks were needed, the TIA would repeat basic lines on their own.

• @supercat that's exactly what footnote 2 says, doesn't it? Mar 18 at 22:01
• @vakvakvak The TIA holds a set of registers for the elements describes above which are used to generate a line f video. Much like a GPU holds triangles and textures to be turned into a video line(s). For each pixel clock within a line the TIA decides which element wins, according to a fixed set of rules. Ball over missile over player over background. This calculation was done in real time when that pixel got send out toward the TV. No frame buffer present or needed. the 20 pixel background you mention isn't a frame buffer but one of the elements. Best to read manual (or book) to understand. Mar 18 at 22:14
• @Klaws True, but not sure what you want to correct here, as the whole point is that there is no memory and especially not for 40 bit - not even 20. Mar 19 at 23:42
• @Raffzahn: The TIA had 20 bits worth of writable registers for the playfield (effectively 20 bits of memory), each of which also had two shift register bits located right next to it. The shift registers were shifted in opposite directions once every four pixels, and a pixel would be treated as "playfield" if the any pixel which was "1" had its corresponding bit set in either shift register. The input to one shift register was 0 except at the start of a line, or the midpoint of a line if mirroring was off; the other shift register input would be set at the screen midpoint if mirroring was on. Mar 21 at 15:38
• @Raffzahn: I don't know any way for software to reveal the existence of the shifters, beyond the fact that the "mirror" bit is effectively sampled when the screen midpoint is reached, but they are present in the schematics and in the actual hardware. Mar 21 at 15:41

The 2600 didn’t have a frame buffer. Instead, programs running on it had to draw the picture on the screen pretty much in real time.

This actually had some advantages on a low-cost system. Each line could be set up differently from the others. In particular this meant that sprites could be re-used, so that inventive developers could write programs using more sprites than the small number supported in hardware (two player sprites, two missile sprites, and one ball sprite).

So memory wasn’t used to describe the display, at least not in pixel-by-pixel detail. 128 bytes was still a small amount however, and developers had to be creative — for example the barrier in Yars’ Revenge is drawn using the game’s code itself as display data.

There’s an excellent book which goes into a lot of detail on this topic, Racing the Beam by Nick Montfort and Ian Bogost. See also How does Space Invaders on the Atari 2600 display all the aliens?

• There's also Retro Game Mechanics Explained's Racing the Beam Explained - Atari 2600 CPU vs. CRT Television on YouTube, which goes into great detail. Mar 18 at 14:05
• The barrier in Yars' Revenge is based on the game code because the programmer felt like it and not because of some technical limitation. It could just as well have been a LFSR-based PRNG, although I don't think they were popular at the time. Mar 21 at 0:39
• @user253751: It is indeed a technical limitation, just not the RAM size one. Making the noise barrier by other means would have required a larger ROM for the game. The ATARI CPU didn't have enough speed remaining to make a PRNG version good enough. LFSR PRNGs look like something when graphed like that. Mar 21 at 3:19
• @Joshua Since the programmer had time to make the barrier consist of two sets of counter-scrolling game code and with random colours, I don't think there weren't enough cycles. Mar 21 at 3:51
• @user253751: The most efficient 16-bit LFSR-style RNG on the 6502 would probably be something like `LDA \$01 / LSR / ROL \$02 / BCC skip / EOR #\$DB / STA \$02 / EOR \$01`. 3+2+5+2+3+3+3 = 21 cycles. By comparison, "LDA (zp),Y" would be five cycles if Y is being used as a line counter. Mar 22 at 14:46

The Atari VCS (it only became the Atari 2600, when the 5200 became a thing) is somewhat peculiar, as its video and audio chip, the "Television Interface Adapter", better known as TIA, manages just a single dimension of video. The TIA just draws a single scan-line of video, over and over again. (You don't need a CPU for this, if you pull a cartridge, the signal just repeats as vertical stripes.)

The TIA does this by the help of a few registers:

• There are two and a half registers for 20 wide pixels making the "playfield" graphics, which are either mirrored or repeated for a total of 40 wide pixels. (These "wide pixels" extend over 4 normal screen pixels, each, usually providing background graphics.)
• Then, there are the so-called missile and player graphics, which provide 2 sprites of 8 pixels, each (again, just in the horizontal direction), 2 "missiles" of a single pixel in the color of one of the players, and, finally, a "ball", again a single pixel.

The TIA will produce a line of video composed of these elements. Any vertical logic and change of graphics is left to the program, even the vertical retrace of the video signal (V-BLANK) has to be managed by the program. (This part of a program managing the visible image is known as a video kernel.)

There are a few tricky things involved in this:

• First, the TIA produces not only the clock signal for the video pixels (the so-called color clocks), but also the clock signal for the CPU, a MOS 6507 processor (which is a 6502 with a reduced address bus). The ratio of these clock signals is 1:3, there are 228 color clocks (68 in the horizontal blank phase and 160 visible pixels) in a video line, but only 74 CPU clocks (still, rather speedy at 1.19MHz).

• Secondly, you can't just position the sprites. (Mind that there are only horizontal positions, as there is no concept of a vertical image.) The problem being, while there are registers for sprite positions in the TIA – or rather counters, which keep sync with the progressing video signal –, you can't position them at an arbitrary position, say, "at x pixels". The reason for this is that these registers are not linear counters, but, for cost efficiency, linear-feedback shift registers (LFSR), which count out of order. Hence, the only way to position these sprites is to tell the TIA "this sprite, now!", and the TIA will display the sprite at the position the cathode beam happens to be at this moment. (As the TIA also exposes different functions on read and write at its various addresses, you can't simply read out the value of these LSFRs in order to use them directly. You have to operate this in a time-based manner.)

• The third problem arises from the fact that there are 3 color clocks or sprite positions for any CPU cycle and that the minimal loop on a 6502-type processor takes 5 cycles. Meaning, this ways, we can only position a sprite at the granularity of 15 pixels! (Since it takes 5 cycles or 15 pixels to wait for anything on the CPU side of things.) However, there are also registers for moving any of these objects by up to 7 pixels left or right, which by "coincidence" allows us to fine tune the position in a range of 15 pixels.

• A final element in this is synchronization of the CPU with the video scan-line produced by the TIA, for which the CPU may touch (strobe) a register of the TIA, in order to be put to sleep by the TIA (remember, it's the TIA that produces the CPU clock signal), just to be woke up again at the very beginning of the next video line.

The general idea was that a game would set up sprite positions in the vertical blank phase and then would manage the vertical extent of the graphics by activating and deactivating them and/or swapping the pixel pattern stored in the sprite and playfield registers. The TIA includes registers that allow this to take effect merely every second line, which would provide ample of time to manage this at the price of half the vertical resolution. As this is somewhat limited, soon techniques emerged to take advantage of the full resolution and even to reposition the sprites/objects on-the-fly during the the visible image phase. As this affords close synchronization of the code with the progress of the video signal (you need to know your 6502 instructions by cycle count for the trickier parts), this became known as "racing the beam".

At least, this was how it had to be done in the "classical era". There are modern cartridges, which will produce a constant stream of bytes at a known address, leaving the CPU just with the tasks of shuffling them over to the TIA, while the actual control over this stream is on an ARM chip inside the cartridge. (But where is the fun in that?)

• The notion of having hardware on a cartridge pre-compute what should be sent to the TIA dates back to the classic era--the cartridge Pitfall II features the David Patrick Crane chip (DPC) which generates sprite and audio samples and could also have generated HMOVE values for vine drawing if Pitfall II had included any vines. Mar 19 at 14:44
• Another thing to note is that the vertical size of the picture (192 lines for NTSC) is more a convention. Since it's left to the program when/where the video signal goes into V-BLANK, it can be anything, a usual TV can deal with. And there is some wiggle room. And, indeed, there are variations between games.(It should be an even number of lines for PAL, though, otherwise you may lose color.) 192 lines for NTSC and 228 for PAL (at 50 Hz) are considered safe values, but not an absolute requirement. Mar 19 at 17:57
• Indeed, the number of scan lines output per frame is also a convention with some flexibility. Most games output 262, but the Stella's Stocking audio code worked out more conveniently when the scan line count was a multiple of 4, so it uses 264. Some games would cause televisions to momentarily lose vertical sync because they output a short frame or went awhile without producing any vertical sync signal. Mar 19 at 18:15
• Regarding the 264, we have to go into even more detail, in order to make this understandable: A standard non-interlaced NTSC frame consist of 40 lines V-BLANK (vertical retrace phase, no image), then the 192 standard visible lines, followed by an overscan of 30 lines, which may be visible or not (sort of a tolerance), making 262 lines in total. (For PAL at 50Hz, it's 48 V-BLANK + 228 picture + 36 overscan = 312 lines total.) TVs are somewhat tolerant and sync with the actual timing, so it may vary by a few lines. While half a frame is a bit too much of a variation, the TV will still recover. Mar 19 at 19:46
• % For our VCS game, this means (for standard NTSC): 30 lines of overscan + 40 lines of V-BLANK provide 70 lines with video off to manage the game state and for setting up sprites, and 192 lines, where we manage the visible image (the video kernel). However, we may "steal" a few lines to extend the visible picture into the overscan area (which should be still visible), and we even may extend the entire line count by a small amount, or we can go into V-BLANK early (but not by too much, else we may lose sync). Mar 19 at 20:03

It seems you think that there is a frame buffer for a full video screen. And that the CPU draws stuff into the frame buffer and some video chip reads out the frame buffer and sends out as video.

But it does not work like that, there is no frame buffer, and the video chip can't read from a frame buffer and send out ready-made screens. This comes much later in gaming consoles.

What you see on screen is directly generated from video chip under CPU command, so the CPU has to constantly update the video chip about what to do for each line of video, sometimes even during the video line.

You don't have to store the frame "in memory" before you "serve" it to the display; you would "compute" the image as you transmit it.

Here is an FPGA example: https://wiki.sipeed.com/hardware/en/tang/Tang-Nano-9K/examples/rgb_screen.html

This example would work in theory even with a 8K/120 Hz image (assuming the chip is fast enough to generate 33Mx3x120 bytes every second, which would require 11 GHz).

Such an approach is 100 % hardware accelerated, because your game state must only know a list of sprites and their position. When the "beam" moves over the image to generate it, the programmer looks if at the current location is any sprite, and if yes, it will return the specific pixel of the frame.

128 bytes for the stack and game state is obviously a "little" limiting to create rich games.