Classic Computer Magazine Archive ANTIC VOL. 2, NO. 11 / FEBRUARY 1984

CHARACTER GRAPHICS

Redifine the set anyway you choose

by CHRIS CHABRIS

The Operating System of every Atari computer comes with predefined "shapes" for up to 128 characters. These are normally displayed as white characters against a blue background. These characters include upper- and lower-case letters, numbers, punctuation, and graphics characters. These 128 characters may also be displayed in "inverse video" (a blue character against a white background), a feature which effectively doubles the number of discretely different characters available for screen display.

Some of you may not know, however, that you can customize this character set. This customizing feature, which is not provided by many other home computers, not only allows you to create different text characters, such as those found in foreign alphabets, it also allows you to create text objects for applications such as animated multicolor game shapes! Redefined characters are really quite easy to make and use in Atari BASIC.

First, a few definitions you will need to understand the techniques:

Character Sets: A character set is a table located in memory which defines the shapes of the characters to be displayed in Graphics Modes 0, 1, and 2. The character set supplied by Atari contains the patterns for128 characters and resides permanently in the Operating System ROM cartridge.

Memory Pages: A "page" of memory consists of 256 contiguous bytes of memory whose starting address (the location of the first byte) is evenly divisible by 256. Page Zero then, represents the 256 memory locations starting at location 0 in RAM and ending at location 255; Page Six starts at 1536 and ends at 1791.

Bits: A byte of memory is divided into eight "bits," each of whlch can be either zero or one. A bit equal to one is normally said to be "on." The positions of the bits in a byte are numbered 0 through 7 starting at the right and moving leftward. The decimal value of a byte, which may range from 0 to 255, is found by adding together the value of the "on" bits. An "on" bit in position 0 equals one, "on" in position equals two, "on" in position 2 equals four, "on" in position 3 equals eight, etc. For example, eight bits of a byte may look like 01001101. Bits 6, 3, 2, and 0 are "on." Thus 26 + 23 + 22 + 20 = 77, the decimal value of this byte. (Remember: two to the zero power equals one.)

BUILDING CHARACTERS

The easiest way to begin using character graphics is to follow a hands-on, step-by-step method for incorporating them into your programs. You will need some graph paper to plot out the new character shapes.

Step 1 -- Decide what you want your new characters to look like. As an example, let's say we want to design a character for capital omega, the last letter of the Greek alphabet.

Step 2 -- Draw your character on the graph paper. Each character occupies an eight-by-eight grid which represents eight rows of bytes (vertical) and eight columns of bits (7 through O horizontal). Each one of the 64 bits in this character square represents one pixel (short for "picture element") that can be turned on or off at the programmer's command. Keeping this in mind, let's design the Greek letter omega, which looks somewhat like an upside-down U with upturns at the sides (See Figure 1, noting that each pixel to be displayed has its bit "on" and each pixel not to be displayed has its bit turned "off').

Step 3 -- Calculate the byte value for each of the eight rows of your character as described in the definition of "bit" above, and make a list of the values next to each row on your grid. For the omega character, the decimal byte values are (from top to bottom): 0, 24, 60, 36, 36, 165, 231, and 0.

Step 4 - Decide which existing character you wish to replace with the new character. In this example we will replace the ampersand ("&") character, one of the least used punctuation marks.

Step 5 -- Find the location in the OS ROM character set of the character to be replaced. Use Table 9.6 on page 55 of the Atari BASIC Reference Manual to find the position of the desired character. Write this number down at the beginning of the list of byte values that you recorded in Step 3. For the ampersand, this number is six.

Step 6 - Place these nine numbers in a DATA statement. In our case, the BASIC line looks like this:

DATA 6,0,24,60,36,36,165,231,0

Now go back and repeat Steps 1 through 6 for each character that you wish to redefine. Play around a little with some shapes you would like to create. When you are ready to see them displayed on the screen, go on to Step 7 below.

Step 7 -- "Download" the standard character set into RAM memory. We want to replace some of the characters (or all of them, if you've been really creative) with our own designs, but we can't change bytes of ROM memory. The solution? Move the entire standard character set into RAM where it is easily accessed and modified. Since there are 128 characters in a set and each character consists of eight bytes, we must move the contents of 1024 bytes (one kilobyte). To do this, PEEK at the value in ROM and POKE it into RAM. First, we use memory location 106 to find out how many pages of RAM are in your computer:

CH = PEEK(106)

Next, subtract four (the number of pages in a one-kilobyte-long character set) and multiply the result by 256 to find the exact address of the beginning of our memory area:

CH=(CH-4)*256

Now use a FOR/NEXT loop to transfer the standard character set to this new area. To do this, we need to know that the OS permanent character set begins at memory location 57344.

FOR LOOP = 0 TO 1023
BYTE = PEEK(57344 + LOOP)
POKE CH + LOOP,BYTE
NEXT LOOP

The standard set now resides in two places in memory (one In the OS ROM, another now in RAM). You can modify the set located in RAM.

Step 8 - Modify the relocated RAM character set to Include your new characters. Using the DATA statement written previously, we modify the ampersand character by multiplying the position of this character by eight and adding the result to the variable CH, which is the starting address of the new character set. Another FOR/NEXT loop POKEs these eight - bytes of character data into RAM at the proper location:

READ NUM
NUM = NUM*8
FOR LOOP = 0 TO 7
READ BYTE
POKE CH + NUM + LOOP,BYTE
NEXT LOOP

If you modify more than one character you can, of course, use more FOR/NEXT loops to POKE the character(s) into memory.

Step 9 - Tell the OS to use the new character set instead of the standard set. This is accomplished with a single POKE command to location 756, which is known as the Character Base Address because the value found here points to the character set currently being used by the computer. All character sets must start on a new page of memory, or page boundary, which is evenly divisible by four. So divide the variable CH by 256 to find the page number of your new set and POKE this number into location 756:

CH = CH/256
POKE 756,CH

That's it! We are now ready to PRINT our new characters on the screen.

PROGRAM EXPLANATION

Listing 1 is an example of the use of redefined character sets in educational and scientific programming. It displays a schematic diagram of an electric circuit in Graphics Mode 2 and asks first-year physics questions in the text window.

Here is a line-by-line explanation of the sample program; many of the techniques used are adaptable to other programs and applications.

1000-1040: Dimension variables, set up title screen.
1050-1060: Jump to the subroutine that redefines the characters and POKE in the new location as in Step 9.
1070-1120: Draw the circuit on the screen.
1130-1170: Initial message; wait for [START] button to be pressed.
1180-1280: Display a question and input an answer.
1290: Is answer correct?
1300-1390: Wrong answer -- display correct answer and go on.
1400-1440: Correct answer - increment number right and go on.
1500-1510: Go on to the next question.
1520-1560: Quiz over -- display score and start endless loop.
1570-1710: Subroutine to redefine the character set.
1720-1900: DATA statements for new character shapes.
1910-2010: DATA statements that use the new characters to draw the circuit diagram.
2020-2220: DATA statements that contain the text of the questions, choices, correct answers, and explanations.

Figure 1
00000000
00011000
00111100
00100100
00100100
10100101
11100111
00000000
7 6 5 4 3 2 1 0
Bit #
Capital omega.
Figure 2
00011011
11000110
10110001
01101100
00011011
11000110
10110001
01101100
7 6 5 4 3 2 1 0
Bit #
Checkerboard pattern produces
characters at left and right in
ANTIC Mode 4.

Table 1 shows which characters were redefined in this program and how they were changed.

There are several points worth remembering when you use redefined character sets in your programs. Notice that in line 1590 the step-back from the top of RAM was eight pages. Since the screen memory and display list reside at the top of RAM, and they occupy more than a page of memory, we stepped back two pages. Now, since we want to relocate the entire four-page (1K) character set, we step back another four pages. These additional two pages were required because a 1K character set must start on a page that is evenly divisible by four!

You may remember that in Graphics Modes 1 and 2, only 64 of the128 characters in a set may be displayed at one time (see the Atari BASIC Reference Manual, pp. 46-47, for an explanation of this). If you are using one of these modes, the character set only needs to be 64 characters long, or two pages instead of four, and must begin on an even-numbered page. But since our sample program prints text in the Graphics Mode 0 text window, which uses all 128 characters, we moved the entire set. If you are confused, see Table 2, which shows that the amount of memory you must reserve depends on the graphics mode you are using. When in doubt, use a larger step-back to avoid conflicting with the display list or screen.

You may notice a long pause after the title is displayed. This results from the FOR/NEXT loop used to download the character set from ROM into RAM. Fortunately, you can use a ready-made, machine-language routine to accomplish the same thing in a fraction of the time. Replace lines 1610-1640 in Listing 1 with these:

1610 DIM MOVE$(32):RESTORE1630
1620 FOR LOOP = 1 TO 32:READ BYTE:MOVE$ (LOOP)= CHR$(BYTE):NEXT LOOP
1625 JUNK = USR(ADR(MOVE$),CH,57344)
1630 DATA 104,104,133,215,104,133
1632 DATA 214,104,133 ,213,104,133
1634 DATA 212,162,4,160,0,177
1636 DATA 212,145,214,200,208,249
1638 DATA 230,213,230,215,202,208
1640 DATA 240,96

For those of you who are familiar with 6502 assembly language, Listing 2 provides the source code for this 32-byte subroutine. For those of you who know nothing about assembly language, the routine is fully usable as is, as long as the variable "CH" contains the memory addres of the new character set area.

If you're using BASIC A + , replace lines 1610-1640 with the following:

1610 MOVE 57344,CH,1024

Since BASIC A + has a reserved memory area for character sets and the like, you can set the variable "CH" to this address (see pg. L-l of the manual). Whatever you do, do not use the PEEK(106)-4 method from Step 7, because BASIC A + resides at the top of RAM. If you plan to redefine virtually every character in the set (for the particular graphics mode you're using), consider reserving an area of memory, placing the new character definitions there, and using the POKE to location 756 without ever downloading the standard set. That part of Step 7 becomes useless if none of the standard characters are to be used.

A problem may arise if you wish to redifine letters and numbers for a Graphics Mode 1 or 2 display and still wish to use the standard characters in the text window. To reinstruct the ANTIC processor to display the standard set, it is necessary to insert a display list interrupt (DLI) before the text window (if you're not familiar with DLI's, see ANTIC, June 1983, for an excellent tutorial). Once you have set up your graphics mode, use the following code:

DL=PEEK(560)+256*PEEK(561)
FOR LOOP=0 TO 10:READ BYTE:POKE 1536+LOOP,BYTE:NEXT LOOP
DATA 72,169,224,141,10,212
DATA 141,9,212,104,64
POKE 512,0:POKE 513,6
POKE DL+14,135:REM - USE POKE DL+24,134 IN GRAPHICS MODE ONE
POKE 54286,192

Listing 3 is the source code for this DLI service routine. It sets the character base address to point to the standard set on the line before the text window is displayed.

Figure 2a
NORMAL VIDEO
0123
3012
2301
1230
0123
3012
2301
1230
Numbers are color
registers;
0=background color.
Figure 2b
INVERSE VIDEO
0124
4012
2401
1240
0124
4012
2401
1240
Numbers are color
registers;
0=background color.

MULTICOLOR CHARACTERS

Now, on to multicolor characters, a little-known feature of your Atari. If you looked at Table 2, you noticed "ANTIC Modes 4 and 5." They don't have a BASIC mode number because they can't be called directly from BASIC like Graphics Modes 0, 1, and 2. To access them, you must modify the display list, a machine-language program that tells the ANTIC chip how to display data on the screen.

If you are unfamiliar with custom display lists, read "Display Lists Simplified" (ANTIC, February-March 1983). You do not need to completely understand display lists to implement multicolor characters, however, as you can use the ready-made routines provided below.

ANTIC mode 4 creates four-color characters that are the size of BASIC Mode 0 characters - 24 rows of 40 will fit on the screen. ANTIC Mode 5 doubles the height of these characters. Therefore, only 12 rows of 40 will fit on the screen.

The following code will set up a full ANTIC Mode 4 screen:

GRAPHICS 0
DL=PEEK(560)+256*PEEK(561)
POKE DL+3,68
FOR LOOP=6 TO 28
POKE DL+LOOP,4
NEXT LOOP

And this routine will set up an ANTIC Mode 5 screen:

GRAPHICS 0
DL=PEEK(560)+256*PEEK(561)
A=PEEK(559):POKE 559,0
POKE DL+3,69
FOR LOOP=6 TO 16
POKE DL+LOOP,5
NEXT LOOP
POKE DL+17,65
POKE DL+18,PEEK(560):POKE DL+19,PEEK(561)
POKE 559,A

The POKE to location 559 completely shuts down the screen display while the display list is being modified. If this were not included, ANTIC might get confused by our changes to its program and display some garbage on the screen. This measure is not needed when setting up ANTIC Mode 4 because its display list is just as long as BASIC Graphics Mode 0's. If you know something about display lists, you will notice that the display list for ANTIC Mode 5 is shorter than most. It only requires 12 lines. Consequently, the original display list must be shortened while ANTIC is following it.

Character redefinition is basically the same for multicolor modes as for "normal" modes. Steps 1 through 9 remain the same, but the process of designing new shapes is different.

Each character is only four pixels or dots wide, and each pixel can be any one of four colors. In each of the eight bytes that make up a character, two bits determine the color of a pixel:

00 = Background color
01 = Color register zero
10 = Color register one
11= Color register two (or color register three, if the character is displayed in inverse video)

Figure 2 is an example of a four-color checkerboard character. Listing 4 is an example of animation with a multicolor character mode. In this program, I've kept the last line of the screen in BASIC Graphics Mode 0 for the display of various messages. The animation is not flicker-free, of course, but it is easy to program and uses several characters. Note that this program incorporates the machine-language routine for moving the character set.


chargraphics3.jpg

Table 2
GRAPHICS MODEMEMORY RESERVATION*
0 4 Pages
1 2 Pages (4 with text window)
2 2 Pages (4 with text window)
ANTIC Mode 4 4 Pages
ANTIC Mode 5 4 Pages
*Not including screen, display list memory.
Memory reservation required for character sets.


Christopher Chabris corrects his previous bio. He has not yet graduated from high school, but does work as a junior Programmer for CSIBM, a computer servrce company in Yonkers, N.Y. He Is a Chess Master candidate and has represented the U.S. in international matches.

Listing 1: CHARSET1.BAS Download

Listing 2: CHARSET2.SYN Download

Listing 3: CHARSET3.SYN Download

Listing 4: CHARSET4.BAS Download