The Atari Tutorial - Part 2: Graphics Indirection

by Chris Crawford (taken from BYTE Magazine, October 1981)

Indirection is a powerful concept in computing, but a difficult one for the beginning programmer to appreciate. In 6502 assembly language, there are three levels of indirection in referring to numbers. The first and most direct level is the immediate addressing mode, in which the number itself is directly stated:

LDA #$F4

The second level of indirection is reached when the program refers to a memory location that holds the number:

LDA $0602

The third and highest level of indirection is attained when the program refers to a pair of memory locations that together contain the address of the memory location holding the number. In the 6502, this indirection is complicated by the addition of an index:

LDA ($D0),Y

Indirection provides a greater degree of generality and power to the programmer. Instead of trucking out the same old numbers every time something needs to be done, the programmer can simply point to them. By changing the pointer, the behavior of the program can be changed. Indirection is an important capability.

Graphics indirection is built into the Atari Personal Computer system in two ways: with color registers and character sets. Programmers using this computer after programming other systems often think in terms of direct colors. A color register is a more complex beast than a color. A color specifies a permanent value. A color register is indirect; it holds any color value. The difference between the two is analogous to the difference between a box-end wrench and a socket wrench. The box-end wrench comes in one size only, but a socket wrench holds almost any size socket. A socket wrench is more flexible, but takes a little more skill to use properly. Similarly, a color register is more flexible than a color, but takes more skill to use effectively.

Color-Register Indirection

The Atari 400/800 has nine color registers; four are for player-missile graphics and will be discussed in a later article in this series. The remaining five are not always used. Depending on the graphics mode used, as few as two registers, or as many as five, will show up on the screen. In BASIC mode 0, only one and one-half registers are used because the hue value of the characters is ignored. Characters take the same hue as playfield register 2, but take their luminance from register 1. The color registers are in CTIA (one of the Atari custom integrated circuits) at hexadecimal addresses D016 through D01A. They are "shadowed" (ie: copied) from certain RAM (random access read/write memory) locations in the Atari OS (operating system) into CTIA during the vertical blank interrupt of the video display. Table 1 gives color-register shadow and hardware addresses.


Image
Controlled
Hardware Operating
System Shadow
Label Hexadecimal
Address
Label Hexadecimal
Address
player 0 COLPM0 D012 PCOLR0 2C0
player 1 COLPM1 D013 PCOLR1 2C1
player 2 COLPM2 D014 PCOLR2 2C2
player 3 COLPM3 D015 PCOLR3 2C3
playfield 0 COLPF0 D016 COLOR0 2C4
playfield 1 COLPF1 D017 COLOR1 2C5
playfield 2 COLPF2 D018 COLOR2 2C6
playfield 3 COLPF3 D019 COLOR3 2C7
background COLBK D01A COLOR4 2C8

Table 1: Names and addresses of color registers used by the Atari 400/800.


For most purposes, the user controls the color registers by writing to the shadow locations. There are only two cases in which the programmer writes directly to the CTIA addresses. The first and most common is the display-list interrupt, which will be covered in a later article in this series. The second case arises when the user disables the OS vertical-blank interrupt routines, which move the shadow values from the OS into CTIA.

Colors are encoded in a color register by a simple formula, The upper nybble gives the hue value, which is identical to the second parameter of the BASIC SETCOLOR command. Table 9.3 of the Atari BASIC Reference Manual lists hue values. The lower nybble in the color register gives the luminance value of the color, It is the same as the third parameter in the BASIC SETCOLOR command. The lowest-order bit of this nybble is not significant. Thus, there are eight luminances for each hue. This gives a total of 128 colors from which to choose (eight luminances times sixteen hues). In this series of articles, the term color denotes a hue-luminance combination.

Once a color is encoded into a color register, it is mapped onto the screen by referring to the color register that holds it. In map-display modes that support four color registers, the screen data specify which color register is to be mapped onto the screen. Since there are four color registers, it takes only 2 bits to encode one pixel. Thus, each screen-data byte holds data for four pixels. The value in each pair of bits specifies which color register provides the color for that pixel.

In color-text display modes (BASIC's graphics modes 1 and 2), the selection of color registers is made by the top 2 bits of the character code. This leaves only 6 bits for defining the character, which is why these two modes have only 64 characters available.

Color-register indirection gives the programmer four special capabilities. First, the programmer can choose from 128 different colors for displays.

Second, the programmer can manipulate the color registers in real time to produce pretty effects. The simplest version of this is demonstrated by the following BASIC line:

FOR I=0 TO 254 STEP 2:POKE 712,I:NEXT I

This line cycles the border color through all possible colors. The effect is quite pleasing and certainly grabs attention. The fundamental technique can be extended in a variety of ways. A special variation of this is to create simple cyclic animation by drawing a figure in four colors, and then cycling the colors through the color registers, rather than redrawing the figure. The program in listing 1 illustrates the idea.


10 GRAPHICS 23
20 FOR X=0 TO 39
30 FOR I=0 TO 3
40 COLOR I
50 PLOT 4*X+I,0
60 DRAWTO 4*X+I,95
70 NEXT I
80 NEXT X
90 A = PEEK(712)
100 POKE 712,PEEK(710)
110 POKE 710,PEEK(709)
120 POKE 709,PEEK(708)
130 POKE 708,A
140 GOTO 90


Listing 1: A short graphics program demonstrating the illusion of movement by changing color-register assignments.


The third application of color registers is to logically key colors to situations. For example, a paged-menu system can be made more understandable by changing the background color or the border color for each page in the menu. Perhaps the screen could flash red when an illegal key is pressed. The use of the color characters available in BASIC graphics modes 1 and 2 can greatly extend the impact of textual material. An account sum could be shown in red if the account is in the red, or black if the account is in the black. Words or phrases of import can be emphasized in special colors. The use of colors in map modes (no text) can also improve the utility of such graphics. A single graphics image (a monster, a boat, or whatever) could be presented in several different colors to represent several versions of the same thing. It costs a great deal of RAM to store an image, but it costs very little to change the color of an existing image. For example, it is much easier to show three different boats by presenting one boat shape in three different colors than three different boat shapes.

The fourth and most important application of color registers is used with display-list interrupts. A single color register can be used to put up to 128 colors onto a single screen. This important capability will be discussed in part 4 of this series.

Character Sets

Graphics indirection is also provided through the redefinable character set. A standard character set is provided in ROM (read-only memory), but there is no reason why this particular character set must be used. The user can create and display any character set desired. There are three steps necessary to use a redefined character set. First, the programmer must define the character set. This is the most time-consuming step. Each character is displayed on the screen on an 8 by 8 grid, which is encoded in memory as an 8-byte table. Table 2 depicts the encoding arrangement.


CHARACTER
IMAGE
BINARY
REPRESENTATION
HEXADECIMAL
REPRESENTATION
0 0 0 0 0 0 0 0
0 0 0 1 1 0 0 0
0 0 1 1 1 1 0 0
0 1 1 0 0 1 1 0
0 1 1 0 0 1 1 0
0 1 1 1 1 1 1 0
0 1 1 0 0 1 1 0
0 0 0 0 0 0 0 0
0 0
1 8
3 C
6 6
6 6
7 E
6 6
0 0

Table 2: Internal representation of a character ín memory. One character needs 8 bytes to represent it. Although the standard character set is in ROM, the pointer to the beginning of the character set can be changed to point to other memory locations, allowing the user to create a modified or completely new character set.


A full character set has 128 characters in it, each with a normal and inverse video incarnation. Such a character set needs 1024 bytes of space and must start on a 1 K-byte boundary. Character sets for BASIC modes 1 and 2 have only 64 distinct characters. These require only 512 bytes and must start on a ½ K-byte boundary. The first 8 bytes define the zeroth character, the next 8 bytes define the first character, and so on. Each group of 8 bytes is termed a character definition; the index that designates such a group (FIRST character, FIFTH character, etc) is called the character name. Obviously, defining a new character set is a big job. Fortunately, there are software packages to make this job easier.

Once the character set is defined and placed into RAM, the second step is to tell ANTIC (another custom integrated circuit on the Atari 400/800) where it can find the character set. This is done by poking the page number of the beginning of the character table into hexadecimal location D409 (decimal 54281). The OS shadow location, the location normally used, is called CHBAS and resides at hexadecimal 2F4 (decimal 756). The third step in using character sets is to print the character wanted onto the screen. This can be done directly from BASIC with simple PRINTs or by writing numbers directly into the screen memory.

A special capability of the system not supported in BASIC is the four-color, character-set option. BASIC graphics modes 1 and 2 support five colors, but each character in these modes is really a two-color character; each one has a foreground color and a background color. The foreground color can be any of four single colors, but only one color at a time can be shown within a single character. This can be a serious hindrance when using character graphics.

There are two other text modes designed especially for character graphics, ANTIC modes 4 and 5. Each character in these modes is only four pixels wide, but each pixel can have four colors (counting background). The characters are defined like BASIC graphics mode 0 characters, except that each pixel is twice as wide and has 2 bits assigned to it to specify the color register used. Unlike ANTIC modes 6 and 7 (BASIC modes 1 and 2), color-register selection is not made by the character-name byte, but instead by the defined character set. Each byte in the character table is broken into four bit pairs, each of which selects the color for a pixel. (This is why there are only four horizontal pixels per character.) The highest bit (D7) of the character-name byte modifies the color register used. Color-register selection is made according to table 3.


Bit Pair In
Character
Definition
Color
Register Selected
 
00
01
10
11
D7=0 D7=1
COLBAK COLBAK
PF0 PF0
PF1 PF1
PF2 PF3

Table 3: Use of color registers in character definition during ANTIC graphics modes 4 and 5. See the text for details.


Using these text modes, multicolored graphics characters can be put onto the screen.

Another interesting ANTIC character mode is the lowercasedescenders mode (ANTIC mode 3). This mode displays ten scan lines per mode line, but since characters use only 8 bytes vertically, the lower two scan lines are normally left empty. If a character in the last quarter of the character set is displayed, the top two scan lines of the character will be left empty. The data that should have been displayed there will be shown on the bottom two lines (see figure 1). This allows the user to create lowercase characters with descenders.




Figure 1: Lowercase descenders in ANTIC mode 3. Using the method shown here, the Atari 400/800 can display characters in an 8 by 10 matrix, even though their internal representation is an 8 by 8 matrix.


Modified Character Sets

Many interesting and useful application possibilities spring from character-set indirection. The obvious application is the modified font. A different font can give a program a unique appearance. It is possible to have Greek, Cyrillic, or other special character sets. Going one step further, graphics fonts can be created. The Energy Czar computer program (sold by Atari) uses a redefined character set for bar graphs. A character occupies eight pixels. This means that bar charts implemented with standard characters have a resolution of eight pixels, a rather poor resolution. Energy Czar uses a special character set in which some of the less useful text symbols (ampersands, pound signs, etc) have been replaced with special bar-chart characters. One character is a one-pixel bar, another is a two-pixel bar, and so on to the full eight-pixel bar. The program can thus draw detailed bar charts with resolution of a single pixel. Photo 1 shows a typical display from this program. The mix of text with map graphics is only apparent; the entire display is constructed with characters.




Photo 1: A bar chart made using character graphics, Even though each character is eight pixels wide, the horizontal bars can be any number of pixels wide by using redefined characters representing bars of varying width.

In many applications, character sets can be created that show special images. For example, by defining a terrain graphics character set with river characters, forest characters, mountain characters, and so forth, it is possible to make a terrain map of any country. With imagination, a terrain map of a different planet can just as easily be done. When doing this, it is best to define five to eight characters for each terrain type. Each variation of a single type should be positioned slightly differently in the character pixel. By mixing the different characters together, it is possible to avoid the monotonous look characteristic of primitive character graphics. Most people won't realize that the resulting map uses character graphics until they study the map closely. Photo 2 shows two views of a terrain map created with character-set graphics.






Photo 2: Two views of a war-game map made totally from character graphics. The map is several times larger than the video display, and a player can use a joystick to view different parts of the map. Even though character-sized graphics are used, the scrolling appears to be smooth due to some advanced Atari display techniques.


You could create an electronics character set with transistor characters, diode characters, wire characters, and so forth to produce an electronics schematics program. Or you could create an architectural character set with doorway characters, wall characters, corner characters, and so on to make an architectural blueprint program.

Characters can be turned upside down by POKEing a 4 into decimal location 755. One possible application of this feature might be for displaying playing cards (as in a blackjack game). The upper half of the card can be shown right-side up; with a display-list interrupt, the characters can be turned upside down for the lower half of the card. This feature might also be useful in displaying images with mirror reflections (reflection pools, lakes, etc).

Even more exciting possibilities spring to mind when it is realized that it is practical to change character sets while the program is running. A character set costs either 512 bytes or 1024 bytes; in either case, it is inexpensive to keep multiple character sets in memory and flip between them during program execution. There are three time regimes for such characterset multiplexing: human slow (more than 1 second), human fast (1/60 second to 1 second), and machine fast (faster than 1/60 second).

Human-slow character-set multiplexing is useful for change of scenery work. For example, a space-travel program might use one graphics haracter set for one planet, another set for space, and a third set for another planet. As the traveler changes locations, the program changes the character set to give exotic new scenery. An adventure-type program might change character sets as the player changes locales.

Human-fast character-set multiplexing is primarily of value for animation. This can be done in two ways: changing characters within a single character set, and changing whole character sets. The Space Invaders game on the Atari 400/800 uses the former technique. The invaders are actually characters. By rapidly changing the characters, the programmer was able to animate them, This was easy because there are only six different monsters, each with four different incarnations. Highspeed cyclic animation of an entire screen is possible by setting up a number of character sets, drawing the screen image, and then cycling through the character sets. If each character has a slightly different incarnation in each of the character sets, that character will go through an animated sequence as the character sets are changed. In this way, a screen full of objects could be made to cyclically move with a simple loop. Once the character-set data are in place and the screen has been drawn, the code to animate the screen would be this simple:

1000 FOR I=1 TO 10
1010 POKE 756,CHARBASE(I)
1020 NEXT I
1030 GOTO 1000

Computer-fast character-set animation is used to put multiple character sets onto a single screen. This makes use of the display-list interrupt capability of the computer. This topic will be addressed further in a later article in this series.

The use of character sets for graphics and animation has many advantages and some limitations. The biggest advantage is that it costs little RAM to produce detailed displays. A graphics display using BASIC mode 2 characters (such as the ones in photo 2) can give as much detail and one more color than a BASIC mode 7 display. Yet, the character image will cost 200 bytes, while the map image will cost 4000 bytes. The RAM cost for multiple character sets is only 512 bytes per set, so it is inexpensive to have multiple character sets. Screen manipulations with character graphics are much faster because you have less data to manipulate. However, character graphics are not as flexible as map graphics. You cannot put anything you want anywhere on the screen, This limitation precludes the use of character graphics in some applications. However, many graphics applications remain for which the program need display only a limited number of predefined shapes in fixed locations. In these cases, character graphics provide great utility. ¤