Lesson 2: Moving Characters
This series teaches you how to make Atari 8-bit graphics move. It is written for programmers with some experience in Atari BASIC. But any 8-bit Atari user with minimurn 32K memory, disk or cassette, can enjoy the short BASIC type-in graphics demonstrations accompanying each lesson.
Last month we drew the shape of a haunted house. Now we will begin to put animated characters into the picture.
First we must find a safe place for the new character set we'll create. You must always protect data by placing it somewhere that won't be written over. Both BASIC and the operating system are constantly moving code all over the place. Fortunately it's easy to create safe havens.
MEMTOP AND RAMTOP
Memory use limitation is controlled by RAMTOP at location 106 and MEMTOP at locations 741 and 742. These locations hold values representing 256-byte pages of memory. By changing the values at these locations, we can fool the computer into thinking that some of its unused memory is already full.
See Figure 1. RAMTOP holds the highest page number of free RAM memory available for use. The operating system won't use memory above this number. By lowering the number, you can use the RAM between the original number and the new number without disturbance. RAMTOP is easier to use than MEMTOP, since you just have to POKE a lower value into it and do a GRAPHICS call. Everything moves into proper place, except for one problem! When your program ends and you load in another program, it will find less memory than expected.
One way to get location 106 back to its original value is to press the [RESET] key, which cleans out every other new setting as well. You could also end your program properly with a POKE RAMTOP to return its original value, if you saved its value in a variable. But here is an example of an even better way to do this:
100 NEWSET = PEEK(740)-8
110 POKE 106, NEWSET-8
120 GRAPHICS 0
This way whenever 106 is moved down, it is referenced to location 740, which will be constant. It works with Atari BASIC, but not with all BASICs from other companies. Use the RAMTOP (location 106) method with these languages. After moving RAMTOP down by 2K (8 times 256), we have our safe area. Sometimes the first 1K is still unsafe, so we will use the second 1K for our character set. There is a very good reason for the extra precaution: Anytime a CLEAR SCREEN is executed in Graphics 0, the first 64 bytes of RAM above RAMTOP are CLEARed! Whenever you make a GRAPHICS call which also causes a CLEAR SCREEN, the first eight characters of your character set will disappear.
This situation is even worse if you allow your screen to scroll up. Did you ever wonder where the old text goes when you LIST and the text flows up the screen? Yep, into the 800 memory locations above RAMTOP. That number 800 comes from the 20 lines of the screen times 40 characters per line.
But why start the new character set 1,024 bytes up in memory, instead of 800? The computer requires a memory location that can be divided by 1,024 for the start of the character set when using Graphics 0, and one that can be divided by 512 when using GRAPHICS 1 or 2. This means either two or four pages at a time.
Now we are ready to start moving an animated character into the HOUSE01.BAS program from last month. We'll need to modify three characters. But first we must move the regular character set from ROM into RAM, so we can work on it:
130 CHSET = 57344
140 FOR BYTE = 0 TO 1023
150 POKE NEWSET*256+BYTE, PEEK(CHSET+ BYTE)
160 NEXT BYTE
Wow, it takes a long time to move 1024 bytes, doesn't it? What we need is a machine language routine to do it faster. The machine language routines in these lessons are written so that you can use them in your own BASIC programs--even if do not understand machine language.
But we do need to know how to move machine language routines into our BASIC programs. There are a number of ways to do this, some quite complex. Below is MOVMEM, a simple machine language method translated into BASIC:
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,0,138,208,2,104,168,177
90 DATA 206,202,224,255,208,233,96
130 CHSET= 57344
Now the Atari character set is in the RAM area we protected. You can verify this by changing CHBAS:
Next you decide which characters to change into new shapes. There is no point in messing up any of the regular letters, so let's change [CONTROL] [A] through [CONTROL] [C]. These are normally Atari graphics characters and have ATASCII values of one through three.
However, as stated in last month's lesson, the character set has a different order than ATASCII. Look at the chart in your BASIC reference guide. (See Recommended Books at end of article.) You'll see that our three characters have INTERNAL values of 65 to 67.
Now for the new shapes. Meet my favorite character-- Prototype! Here are three views (with data) for good old Proto:
Now here is the code to make Proto move.
170 SET = NEWSET*256
180 FOR CHAR=65 TO 67
190 FOR BYTE = 0 TO 7
200 READ DAT
210 POKE SET+ CHAR * 8+ BYTE,DAT
220 NEXT BYTE
230 NEXT CHAR
1000 DATA 56,92,254,124,68,74,64,160
1010 DATA 56,108,254,124,68,68,68,170
1020 DATPI 56,116,254,124,68,164,4,10
Our character set is now all ready to use, so let's tell the computer where it is:
240 POKE 756,NEWSET
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 3
300 READ CHAR
310 POSlTION 10,2
320 PRINT CHR$(CHAR)
330 FOR WAIT=1 TO 2
340 NEXT WAIT
350 NEXT LP
360 GOTO 270
1100 DATA 1,2,3
Notice that all we have to do to animate Proto is print the different versions one after another in the same place, with a small delay between each of them to slow things down so we can see each picture. This technique is used by a lot of programs to do simple (and sometimes complex) animation. For example, the aliens in Space Invaders are created using a redefined character set.
Make the following changes to the program if you want to try the character set in Graphics 1 or 2:
120 GRAPHICS 1: REM (OR 2)
240 POKE 756, NEWSET+ 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 (the data is all 0's). The hearts show up because the heart character is the first character of the set that these graphics modes use. If you need both upper and lowercase characters, all you have to do is redefine the character set so that the graphics characters become upper case letters. You can even use MOVEMEM (MM$ from above) to do this quickly for you. The following statement will move the uppercase letters into the graphics characters locations in memory:
X = USR(ADR(MM$), 57377,NEWSET * 256 + 65,26)
Now a [CONTROL] [A] will give you an uppercase A.
If you want to switch quickly between several character sets, there are two techniques you can use:
1. You can simply load several character fonts into RAM and switch the character base pointer to the appropriate font. This is inefficient because you must keep many character sets in memory.
2 Use MOVMEM (MM$). This little utility will move your character set from a string variable into RAM while the CHARACTER BASE POINTER is already pointing to your newly protected memory reserved for custom fonts. You need only one area for all of your data because the routine will place the correct 1,024 bytes of data into your reserved area so fast you can't tell it's happening.
MAIN PROGRAM ADDS
Now you should type in Listing 1, HOUSE02.LST, checking it with TYPO II. ENTER it into HOUSE01.BAS from last month to make use of the things we have learned so far. Save this version as HOUSE02.BAS. If you have trouble typing the special characters in lines 110 and 150, Listing 2 will create these lines for you, and write them to disk file called LINES02.LST.
HOUSE animates by printing modified #, $ and % characters, all in the same spot on the screen.
Line 110 contains the memory move routine from above.
Lines 140 and 150 place the data for three new characters into a string called (naturally) "CHARSET$".
Line 160 saves the RAMTOP value
Line 170 sets the character base, CB, at 4 pages or 1K down in memory.
Line 180 safeguards RAMTOP by lowering it another1K below the character set.
Line 190 uses the MM$ routine to move the 1,024 bytes of the character set from its regular place at 224 pages to the new location 1K down in our safe area.
Line 200 moves only the 24 new bytes in the character string into the old set we just moved into RAM. It is placed into the set starting at the third character, because NCA, which is the starting point for this move, is 24 bytes or 3 x 8 past CA, which is the start of the whole set. Translated into English, the first eight numbers starting at CA are the first character, the next eight the second, and so on.
Line 2000 tells the computer the new location of the character set data and will switch character sets instantly. Now we need Proto.
Lines 2010 to 2080 simply print our modified characters on the screen, using #$% over and over again with their new data.
Finally comes a loop to slow down our frisky friend Proto.
Our pal is pretty small doesn't move around much. After all, Proto is only one character tall. But we can make him larger by using several characters to draw him on the Screen.
Type in Listing 3, HOUSE03.LST, checking it with TYPO II. If you have trouble typing the special characters in lines 2110-2120, Listing 4 will create these lines for you, and write them to a disk file called LINES03.LST.
HOUSE03 adds some new lines to the program and enlarges Proto. Be sure and type in the REM statements, because they blank out old line numbers that are no longer used. You ENTER the code while HOUSE02.BAS is LOADed into your Atari. SAVE this version as HOUSE03.BAS.
Line 100, the delay loop, has been moved to the front of the code. This is because timing loops take longer to run the further back in the code they are. BASIC always starts each loop by going to the top of the code and searching for the lines it needs. Placing it here will keep the timing the same as the program grows. Lines 150, 160, and 180 delete the old lines in the last version of the program. If you're typing this in, you can delete the old lines simply by typing the line number and pressing [RETURN].
Line 200 places the new shapes, starting at character 96 in the set-- abcdefghijklmnopqr. The other trick in this line involves SEC=0 to 1. This and line 210 place two strings into the Proto character. The second set of data starts 76 bytes into the data. The two sets allow us to keep our strings short. You can do this several ways, but you can't have 300-character strings all on one line. I could have had line 2120 say CHARSET$ (77,152) = "whatever goes here" to define the string.
2000 to 2060 work as usual, we just print three vrsions of the little guy using more characters this time. Here are the three versions of Proto:
VERSION 1 ab cd ef
VERSION 2 gh ij kl
VERSION 3 mn op qr
Of course, we have given these letters new shapes of a more artistic nature.
The most interesting change we've made is to store the shape of the characters in a string called CHARSET$. It is efficient because each number (like 240) previously stored in a data statement is now stored in one number. Those are the characters you see in the string.
A simple way to check the progress of your work with custom characters is to stop the computer after you think you have changed the characters. Now press the keys you have modified and see if they print out on the screen with the new shapes. In our example, press the keys in this order:
abc def ghi jkl mno pqr
This should display the different parts of the new shapes we have created. It is easier to look at the shapes this way than to wait for the program to use them. Also, you can study each shape when it is not moving around.
Creating the masterpiece I promised you will take lots of custom characters. Figuring out a few shapes for Proto was not bad, but 30 or 40 shapes sounds hard. However, next month we will deliver the tools to make it easy!
Robin Sherer is co-author of the Atari programming books Tricky Tutorials, Master Memory Map For Atari, BASIC Arcade Graphics and Atari Game Design.
Your Atari Computer by Lon Poole, Osborne/McGraw-Hill.
Mapping The Atari by Ian Chadwick, Compute! Publications, Inc.