Character Generation on the Atari
This article is a tutorial on a little-known feature of the Atari microcomputers — the ability to re-define the character set. The character set is the group of 255 alphanumeric characters that can appear on the screen. It comprises the upper and lower case alphabet, the numbers, special symbols, and punctuation. Also included in the Atari character set are 29 "control graphics" characters. When the CTRL key is held down and a letter of the alphabet is typed, the corresponding graphics symbol is displayed. These symbols are much like those found on the PET. Unlike the PET, however, the Atari can re-define any of these characters. This allows custom graphics, user-defined special symbols (like pi, theta, or foreign language alphabets), and logos.
There is no built-in command to perform the changes; it has to be done the hard way with PEEK and POKE. These are commands to look at and modify memory, respectively. First of all, you must understand how the Atari stores and displays these characters. It is beneficial if you know how to work with binary numbers, but it is not a prerequisite.
Start out by designing your characters. Fill in the blocks on an 8×8 grid; each block will represent a pixel (picture element, dot). Observe the "A" in figure one. Notice the heavy vertical lines. A television screen will display horizontal lines brighter than vertical lines, so it is necessary to have two vertical lines in order for it to be clearly visible. Therefore, the "pi" in figure two may be hard to see unless enlarged in grapics mode 1 or 2.Figure one
After you have designed your characters, you have to convert them to the numbers that a computer loves. Each row in your grid represents a binary byte. A filled in block represents a 1 and a blank one means 0. Hence, the top row of the "A" is 00011000 or 24 decimal. Now write the bytes for each row. If you do not work with binary numbers, you can convert each line in the following manner:
- Notice the numbers above each column. They are the powers of base two.
- If a block is filled in, take the number above it and add it to a "Sum". Sum up all the blocks in the row. (e.g. the fourth line of the "pi" would be 128 + 32 + 4 = 164)
- Do this for all eight rows.
Next, assemble the numbers into DATA statements. The numbers for "pi" would then look like this:
1000 DATA 0, 1, 126, 164, 36, 36, 36, 36
Finally, you have your numbers. Now all you have to do is replace the numbers of the character you want to re-define with your numbers. Unfortunately, this table is stored in ROM, so it can not be altered. The solution is to copy this table into RAM memory, which can be changed, and then tell the computer where you have moved the characters to.
The first part of the program would then look like this:
10 ROM = 57344 : REM START OF ROM CHARACTER TABLE 20 RAM = 8192 : REM HIGH UP IN MEMORY 30 FOR I = 0 TO 1023 40 POKE RAM + I, PEEK(ROM + I) 50 NEXT I
The transfer takes about 15 seconds, a seemingly LONG time. It need not be executed more than once, unless you go into a GAPHICS mode greater than 3.
The next line:
60 POKE 756, 32 : REM 32*256 = 8192
Now that the table is in RAM, we can now find the place in it for the new numbers. Look up the character you want to replace in table 9.6 — Internal Character Set, on page 55 of the Atari BASIC Reference Manual. Write down this number as well. Notice that it is not the ATASCII value of the character. Include this number preceeding your eight bytes in the data statements. For our "pi":
1000 DATA 32, 1, 126, 164, 36, 36, 36, 36
A few more lines, and the program is finished:
65 READ NCHR : REM NUMBER OF CHARACTER TO BE RE-DEFINED 70 FOR I = 1 TO NCHR 80 READ RPLC : REM CHARACTER TO BE REPLACED 90 FOR J = 0 TO 7 100 READ A 110 POKE RAM + 8'RPLC + J, A 120 NEXT J 130 NEXT I 140 REM FOLLOWING LINE IS OPTIONAL 150 FOR I = 0 TO 255 : PRINT CHR$(27);CHR$(I); : : NEXT I : REM DISPLAYS CHARACTERS 160 END 999 DATA 1 : REM NUMBER OF CHARACTERS TO BE RE-DEFINED
A few program notes:
- You can use multiple statements per line and squeeze the program into less memory; delete REMs if you like.
- This program should be appropriately renumbered for use as a subroutine
- VERY IMPORTANT:
This is not the only way to accomplish the changes in the character set. Also see "Card Games in Graphics Modes 1 and 2" and the program on page 69 in COMPUTE!, November/December, 1980. EXPERIMENT!
- Entering any GRAPHICS mode will reset the pointer to the table (line 60). Any time you enter a new text mode, re-execute POKE 756, 32.
The complete program, and a utility program that lets you look at characters wrap up this article. Study them, puzzle them out, and get down to business!
Program to re-define characters
10 ROM = 57344 : REM START OF ROM CHARACTER TABLE 20 RAM = 8192 : REM HIGH UP IN MEMORY 30 FOR I = 0 TO 1023 40 POKE RAM + I, PEEK (ROM + I) 50 NEXT I 60 POKE 756, 32 :REM 32*256 = 8192 65 READ NCHR : REM # OF CHARACTERS 70 FOR I = 1 TO NCHR 80 READ RPLC : REM CHARACTER TO BE REPLACED 90 FOR J = 0 TO 7 100 READ A 110 POKE RAM + 8*RPLC + J, A 120 NEXT J 130 NEXT I 140 FOR I = 0 TO 255 : PRINT CHR*(27); CHR$(I); : NEXT I : REM DISPLAYS CHARACTERS 150 END 160 REM DATA FOR CHARACTERS FOLLOWS : READY.
Program to view characters in ROM. Note that the characters appear in GRAPHICS mode 4 !
10 GRAPHICS 4 20 SCR = PEEK (560) + 256*PEEK(561) + 4 30 SCR = PEEK(SCR) + 256*PEEK(SCR + 1) 40 PRINT "CHARACTER #? (0-127)"; 50 INPUT CHR 60 IF CHR < 0 OR CHR>127 THEN 40 70 PRINT #6; CHR$(25); 80 FOR I = 0 TO 7 90 POKE SCR + 4 + 10*I, PEEK(57344 + CHR*8 + I) 100 NEXT I 110 GOTO 40 READY.