APPENDIX
ONE
DESIGNING
YOUR OWN CHARACTER SETS
Make sure you have read the description of CHBAS at location 756, RAMTOP at location 106, and the section on the character set at location 57344 before you attempt to use this appendix.
As you can imagine, being able to redefine the character set opens up a lot of graphics capabilities. You can create special graphics characters, do simple animation, or just make the letters look nicer. It's not even that difficult to do, so let's get right into it.
The first step is to decide what you want your new characters to look like. This is the step that's going to take the most time, since there is a total of 128 characters. Of course, you don't have to change them all, but if you do you will have to decide which of over 8,000 dots you want on, and which you want off. To help you out in this task, even if you're only changing a few, you may want to purchase a character editor. The one put out by Educational Software, Inc. is probably one of the best and even comes with a software tutorial on how to use custom character sets. In any case, for the sake of this explanation we'll only change four characters (we'll also see how to use the Atari characters for the ones we don't change). Figure 50 is how we are going to want our first three characters to look.
####
#### #### |
#####
## ## |
######
#####
## |
######
###### ##### |
####
###### ###### |
#### ###### |
#### |
FIGURE 50. Three notes
These funny-looking things are going to create a bouncing musical note when we're done with them. Before we continue, however, you should notice that the largest one only uses seven bytes. Most Atari characters, in fact, only use six, and are only six bits wide. Why? When we print characters side by side, especially letters, most of the time we don't want them to touch. By leaving the first and last bytes and first and last bits blank, we make sure that they won't. If we have a situation where we need them to touch, then all the bits and bytes can be used. Another thing to notice is that everything is at least two bits wide. This is because of artifacting, which we ran into at COLOR1 (709). Since each pixel in a graphics mode zero character is the same size as a pixel in graphics mode eight, we run into artifacting problems here also. If lines are not at least two pixels wide, then the line will not be white. We'll see this with our fourth character (Figure 51).
# # |
# |
# |
# # |
# # # |
# # # |
# |
FIGURE 51. Single note
OK, so now we know what we want our characters to look like. The next step is to convert them into numbers the computer can understand. This is another benefit of the character editor, since it will do the conversion automatically. If you're doing it by hand, just remember that each pixel represents a bit. Also, don't forget to include bytes with a value of zero. You have to end up with eight bytes for each character. With all this in mind, let's convert our four characters (Figure 52).
#### |
= |
00001111 |
= |
15 |
##### |
= |
01111100 |
= |
124 |
###### |
= |
11111100 |
= |
252 |
###### |
= |
11111100 |
= |
252 |
#### |
= |
01111000 |
= |
120 |
= |
00000000 |
= |
0 |
|
= |
00000000 |
= |
0 |
|
= |
00000000 |
= |
0 |
|
#### |
= |
00001111 |
= |
15 |
## |
= |
00001100 |
= |
12 |
##### |
= |
01111100 |
= |
124 |
###### |
= |
11111100 |
= |
252 |
###### |
= |
11111100 |
= |
252 |
#### |
= |
01111000 |
= |
120 |
= |
00000000 |
= |
0 |
|
= |
00000000 |
= |
0 |
|
#### |
= |
00001111 |
= |
15 |
## |
= |
00001100 |
= |
12 |
## |
= |
00001100 |
= |
12 |
##### |
= |
01111100 |
= |
124 |
###### |
= |
11111100 |
= |
252 |
###### |
= |
11111100 |
= |
252 |
#### |
= |
01111000 |
= |
120 |
= |
00000000 |
= |
0 |
|
# # |
= |
00001010 |
= |
10 |
# |
= |
00001000 |
= |
8 |
# |
= |
00001000 |
= |
8 |
# # |
= |
00101000 |
= |
40 |
#
# # |
= |
10101000 |
= |
168 |
#
# # |
= |
10101000 |
= |
168 |
# |
= |
00100000 |
= |
32 |
= |
00000000 |
= |
0 |
FIGURE 52. Note character bit chart
Now we're all set to put it somewhere. But where? The regular character set is in ROM, so we can't put it there. We have to protect a segment of RAM that we can use for the character set. The easiest way to do this is to use RAMTOP at location 106 and RAMSIZ at location 740. This is done by the following program lines:
100
SETNEW=PEEK(740)-4
110 POKE 106,SETNEW-4
120 GRAPHICS 0
110 POKE 106,SETNEW-4
120 GRAPHICS 0
The reason we use RAMSIZ is because if we didn't, and had NEWSET=PEEK(106)-4 instead, we would change RAMTOP everytime we ran the program (that's because RAMTOP doesn't get set back to its original value unless you press SYSTEM RESET). So if we ran the program four times, RAMTOP would be decreased by 32 from its original value. If we ran it enough times, we would eventually get an out-of-memory error (try it), so we use RAMSIZ as well. Anyway, this gives us 2K of protected RAM to work with. Remember that under some circumstances the first 1K isn't really safe, so we'll be using the second 1K for our character set.
Since we're only changing four characters, we'll want to use some of the regular character set, so let's move it from ROM to RAM:
130
CHSET=57344
140 FOR BYTE=0 TO 1023
150 POKE SETNEW*256+BYTE,PEEK(CHSET+BYTE)
160 NEXT BYTE
140 FOR BYTE=0 TO 1023
150 POKE SETNEW*256+BYTE,PEEK(CHSET+BYTE)
160 NEXT BYTE
Wow, it takes a long time to move 1024 bytes, doesn't it? Let's do that again in machine language:
10 DIM MM$(41)
20 FOR CHAR=1 TO 41
30 READ CODE
40 MM$(CHAR,CHAR)=CHR$(CODE)
50 NEXT CHAR
60 DATA 104,104,133,204,104,133,203,104,133,206,104
70 DATA 133,205,104,170,160,255,138,208,2,104,168,177
80 DATA 203,145,205,136,192,255,208,247,230,204,230
90 DATA 206,202,224,255,208,231,96
130 CHSET=57344
140 X=USR(ADR(MM$),CHSET,SETNEW*256,1024)
150 REM
160 REM
Before I give you the assembly language code for the machine language routine stored in MM$, let me tell you a little bit about it. MM stands for "Move Memory," and I wrote the routine so you can use it for other things as well. Your USR statement should have the following format for MM$:
X=USR(ADR(MM$), FROM, TO, NUMBER)
FROM is the starting address you want to move from, TO is the starting address you want to move to, and NUMBER is the number of bytes you want to move. Note that MM$ will not work properly if FROM+NUMBER is less than TO, or if TO+256 is less than FROM.
Here's what the routine looks like:
68 PLA
68 PLA
85CC STA FROMHI
68 PLA
85CB STA FROMLO
68 PLA
85CE STA TOHI
68 PLA
85CD STA TOLO
68 PLA
AA TAX
A0FF LOOP 1 LDY #255
8A TXA
D002 BNE LOOP2
68 PLA
A8 TAY
B1CB LOOP 2 LDA (FROMLO),Y
91CD STA (TOLO),Y
88 DEY
C0FF CPY #255
D0F7 BNE LOOP2
E6CC INC FROMHI
E6CE INC TOHI
CA DEX
E0FF CPX #255
D0E7 BNE LOOP1
60 RTS
There, that's much better. Now the Atari character set is in the RAM area that we protected. You can verify this by changing CHBAS:
POKE 756, NEWSET
The next step is to decide which of the characters we want to change to our new characters. There's no point in messing up any of the letters here, so let's change CTRL-A through CTRL-D. These are normally Atari graphics characters and have ATASCII values of 1 through 4. You'll recall, however, that the character set has a different order than ATASCII. Looking at Appendix Nine, we see that the characters we want have internal values of 65 through 68. We're all set now to make the changes:
170
SET=SETNEW*256
180 FOR CHAR=65 TO 68
190 FOR BYTE=0 TO 7
200 READ DAT
210 POKE SET+CHAR*8+BYTE,DAT
220 NEXT BYTE
230 NEXT CHAR
1000 DATA 15,124,252,252,120,0,0,0
1010 DATA 15,12,124,252,252,120,0,0
1020 DATA 15,12,12,124,252,252,120,0,0
1030 DATA 10,8,8,40,168,168,32,0
180 FOR CHAR=65 TO 68
190 FOR BYTE=0 TO 7
200 READ DAT
210 POKE SET+CHAR*8+BYTE,DAT
220 NEXT BYTE
230 NEXT CHAR
1000 DATA 15,124,252,252,120,0,0,0
1010 DATA 15,12,124,252,252,120,0,0
1020 DATA 15,12,12,124,252,252,120,0,0
1030 DATA 10,8,8,40,168,168,32,0
Our character set is now all ready to be used, so let's tell the computer where it is:
240
POKE 756,SETNEW
And let's use it:
250
POKE 752,1
260 POSITION 10,4
270 PRINT CHR$(4)
280 RESTORE 1100
290 FOR LP=1 TO 4
300 READ CHAR
310 POSITION 10,2
320 PRINT CHR$(CHAR);
330 FOR WAIT=1 TO 25
340 NEXT WAIT
350 NEXT LP
360 GOTO 280
1100 DATA 1,2,3,1
260 POSITION 10,4
270 PRINT CHR$(4)
280 RESTORE 1100
290 FOR LP=1 TO 4
300 READ CHAR
310 POSITION 10,2
320 PRINT CHR$(CHAR);
330 FOR WAIT=1 TO 25
340 NEXT WAIT
350 NEXT LP
360 GOTO 280
1100 DATA 1,2,3,1
Notice that all we have to do to animate the note is print the different versions one after another in the same place, with a small delay between them to slow things down. This technique is used by a lot of programs to do simple (and sometimes complex) animation. For example, the aliens in Atari's Space Invaders program are created using a redefined character set. So don't feel you just have to use character sets for letters. By the way, the artifacted note is printed by itself so you can see what it looks like. It isn't supposed to be doing anything.
Make the following changes to the preceding program if you want to try the character set in graphics modes one or two:
120
GRAPHICS 1
240 POKE 756,SETNEW+2
270 PRINT #6;CHR$(4)
320 PRINT #6;CHR$(CHAR)
240 POKE 756,SETNEW+2
270 PRINT #6;CHR$(4)
320 PRINT #6;CHR$(CHAR)
You can get rid of the hearts by redefining the heart character to a space. To find out why they're there and why we need SETNEW+2, see CHBAS. Incidentally, I said at CHBAS in the same section that you can't have upper and lowercase letters at the same time in graphics modes one and two. I lied. All you have to do is redefine the character set so that the graphics characters become uppercase letters. You can even use MM$ to do this. The following statement will move the uppercase letters into the graphics characters:
X=USR(ADR(MM$),57377,SETNEW*256+65,26
Now a CTRL-A will give you an uppercase "A".
A few final bits of information. If you're using graphics mode seven or eight, you may have to move RAMTOP by 16 pages instead of 8. This is because of a limitation of the system. I personally have never had any problems, but other people have. Just be aware of it. You should also be aware that a GRAPHICS command will restore CHBAS to its original value. Make sure you reset it after each GRAPHICS command if you want to keep using your character set. Also, SYSTEM RESET will reset CHBAS and RAMTOP, thereby destroying the character set completely. So stay away from SYSTEM RESET.
Return to Table of Contents | Previous Chapter | Next Chapter