CREATIVE COMPUTING VOL. 8, NO. 1 / JANUARY 1982 / PAGE 190
When the Atari computer was first designed, Atari planned on selling a good deal of software for it. They knew that the more varied and interesting displays they could program for it, the more software they could sell. So they designed in as much software-controlled hardware flexibility as possible. In this way they hoped to achieve widely varied effects, but never to have to change the basic hardware.
Over the past few months we’ve been looking at the capabilities of the Atari. We’ve covered playfield (i.e., display list generated) graphics and become familiar with player-missile graphics. In this column I’ll cover another of the many playfield features: the ability to reprogram a character set.
“What’s a character set?” you ask. A character set is the table of shapes the computer uses to define what a character looks like. This character set, or shape-table, is what makes an “A” character look different from a “B” character onscreen. With the Atari, these shapes may be altered at will.
With many computers, you’re stuck with the characters the designers provide. The shapes are stored in a ROM, which is an unmodified memory, and can’t be changed except by making a new chip. This places a limitation on those machines, for reprogramming character shapes is a powerful tool for certain applications. Here’s an example.
Let’s say you are writing a program that will be a lesson dealing with the Russian language. Naturally, you would like to be able to write words in that language. But since the Russian language has a different alphabet from English, with most machines, you would be stuck at this point. Unless you use high resolution graphics to draw characters— a slow and clumsy process— you can’t get them onscreen.
On the Atari, however, it’s easy to design your own characters. You can use those new letters for the lesson, and save yourself time and effort.
If you should happen to need some small, high resolution figures on a character screen, but don’t want to hassle with mixing graphics modes, a character set might be just the thing. You can control dots the size of an individual graphics 8 pixel with custom characters and you can mix the special symbols you create right in with your text. For mathematicians in need of special characters (summation, integral) this could be a real help.
As soon as you begin to consider characters as graphics 8 figures drawn at high speed onscreen, more and more interesting posibilities will occur to you. So first let’s review a bit about character shapes and generation, then learn how to modify them.
Byte #1 0 0 0 0 0 0 0 0 Byte #2 0 1 1 1 1 0 0 0 **** Byte #3 0 1 1 0 1 1 0 0 ** ** Byte #4 0 1 1 0 0 1 0 0 = ** * Byte #5 0 1 1 0 0 1 0 0 ** * Byte #6 0 1 1 0 1 1 0 0 ** ** Byte #7 0 1 1 1 1 0 0 0 **** Byte #8 0 0 0 0 0 0 0 0 8 bytes in memory per character. Diagram 1. Character Set Memory A Each character is stored as an 8 byte shape B table of dot patterns. C D E F G H I J K There are 128 characters per character set, . or 128 × 8 = 1024 bytes total. . . Each character has a fixed position in the character set. Diagram 2. Character Set Memory A+0 Each character shape is 8 bytes long. B+8 C+16 ANTIC finds the start of the character set, D+24 E+32 takes the character number, and multiplies F+40 G+48 that by 8 to find the position of the start .+56 . of any character’s position. . (Actually, the beginning of character set memory has other characters in it than letters; these are used for clarity). Diagram 3. Character Set Memory A B C _____ D __ │___ E │ 0 0 0 0 0 0 0 0 F │ 0 1 1 1 1 0 0 0 **** G │ 0 1 1 0 1 1 0 0 ** ** . │ 0 1 1 0 0 1 0 0 = ** * . │ 0 1 1 0 0 1 0 0 ** * . │ 0 1 1 0 1 1 0 0 ** ** │ 0 1 1 1 1 0 0 0 **** │______ 0 0 0 0 0 0 0 0 ANTIC pulls the data from the shape table in order to plot a given character. It plots one line at a time out of the character set table, from top to bottom. Diagram 4.
The Atari plots letters and graphics on the screen using the same individual TV dots. It uses 320 horizontal dots and 192 scan lines for this purpose. Characters are 8 × 8 groups of dots, some lit, some not. Since there are 320 horizontal dots, that’s 320/8 or 40 characters across and 192/8 or 24 rows. There is no space on the screen between characters; that space is provided within the character shapes. (Brief detour: This thoughtful add-on makes possible continuous script letters, which “flow” from one to the next with no interruption. It also allows screen graphics using characters that have no breaks in them.)
A character shape is stored as an 8 × 8 group of bits. A lit dot is represented by a 1 bit, an unlit dot by a 0 bit. (See Diagram 1.) Since each horizontal “slice” of the character is 8 bits, the Atari designers put each slice into one byte, making for eight bytes total per character. There are 128 different characters possible, and they are stored all grouped together, so the compatible “character set” is 128 × 8 or 1024 bytes long. (See Diagram 2.)
Every time a character is displayed, the Atari consults this table. Let’s quickly examine the process.
When Antic finds a display list entry to generate characters (modes 0-1-2 to Basic memory users), he looks to his current location in display memory, kept in an internal register.
Let’s assume graphics 0 for now. One graphics 0 instruction means 40 characters are plotted in one row (in one display block). In a character mode, one byte of display memory represents one character, so Antic fetches 40 bytes. Each character has a unique number, 0-127, and Antic uses that number to look up the shape of the characters in the character set. Let’s see how it finds the shape.
First Antic must find the character set. That’s easy, it is POKEd to Antic every sixtieth of a second by the operating system as part of the screen refresh process. It is given to Antic from location 2F4 hex or 756 decimal in memory.
This location we’ll call CHBAS, for “character set base.” The number in this byte, when mutiplied by 256, specifies the start of the character set in memory.
(Why by 256? In the Atari, like all 6502 processor machines, memory is divided up into “pages.” Each page is 256 bytes long, corresponding to 8 bits of address. In a 16-bit address, the upper 8 bits specify which page number, and the lower 8 bits specify which byte within the page. Because the character set always starts on an even page mark, we only need to tell Antic where the first page of the character set is.)
The character number in display memory, known as the “internal character set number” (not ATASCII!) is multiplied by 8. This is then added to the CHBAS*256 number to give Antic the starting address in memory of where the shape table for the character is stored. (See Diagram 3.) When displaying the character, Antic grabs the first byte of the shape table, displays it as eight on or off dots according to the bits in the shape table, then for the next line down, it just moves down one byte in the shape table. After eight passes, it has moved down eight scan lines and eight bytes and is finished with the character. (See Diagram 4.)
Now if we were to tell Antic the shape table began somewhere else in memory, he would faithfully look to the new location and start using whatever data was found there to display characters. You will recall a few columns back we told Antic that display memory was located in low memory, to watch him display pages 0 and 1 of memory as characters. This is the same idea. If the new area of memory happens to be a table of character shapes, redefined to what you want them to be. Antic will use them without complaint. If not, he will still use them, but what you see won’t be much like a character display!
Now we can’t change the existing character set. That’s stored in ROM at E000 hex and cannot be modified. So what we need to do is copy that ROM character set into RAM, where we can modify it, and tell Antic to start looking to RAM for a character set. All we do to change where Antic looks is to POKE a new page number in memory into location 756. A sixtieth of a second later, the operating system will give Antic that new value as part of the screen refresh, and he will start using it.
Time now for some examples and programs. Let’s run some routines to help us visualize the process and see how characters are stored.
Program 1 begins at the start of the unmodifiable character set the Atari normally uses, the ROM character set. It fetches the 8 bytes per charater, breaks each byte up into individual bits, and displays them as O’s and l’s. (Well, actually, it displays O’s as spaces to make the l’s stand out). It goes through the entire character set this way, displaying the characters in binary patterns. See the listing for an example.
You will soon notice that characters are not stored in ATASCII order. They are in the order of the internal character set, which is a different thing. You can find a listing of the internal order on page 55 of your Basic manual.
Program 2 dumps the specified character to the printer; just type in the letter whose bit pattern you want to display. It is converted into an ATASCII number, then into the internal character set number, then displayed. Hence, this program is handy for showing how to convert from ATASCII to internal format. To find the right bytes in the character set, the internal number is just multiplied by 8 and added to the number that represents the start of the character set, which you’ll recall is just how Antic does it (CHBAS+(8*char number)).
The character set at which we are currently looking is in ROM. Let’s learn how to move it to RAM so we can modify it. There are three steps we must follow:
1. Finding a place to put it; we need 1024 free contiguous bytes of RAM.
2. Copying the ROM character set to RAM.
3. Changing the “pointer” Antic uses to find the character set from its old ROM location to the new RAM location.
Step 1 is tricky. To understand how to do this, we must delve into some Atari memory secrets.
When the Atari is first turned on, a check is made to determine where RAM ends. This can be anywhere from 8K to 48K from the beginning of memory; it depends on how many boards you have installed. In location 106 decimal (6A hex) is stored the page number of the first byte of nonexistent memory. In other words, 256*PEEK(106) is the address of the first byte of nonexistent memory.
The Atari uses the very top of RAM memory, wherever that might be, for the display memory and display list storage. Right below that is free RAM, and below that is the Basic storage. (Hence. Basic and the graphics modes “grow” toward each other into free RAM when they use more memory.) (See Diagram 5.) So, whenever a graphics command is executed, and the Atari needs to set up a new display memory display list, it checks location 106 to see where RAM ends. It then backs up the required number of locations and puts the display memory in. Thus 106 can be thought of as a “fence.” that is used to find the end of memory.
70 REM PROGRAM 1 80 DIM BIN$(8) 90 REM O.S. SHADOW FOR CHBAS=2F4 HEX 100 CH=2*256+15*16+4 130 CHBAS=PEEK(CH)*256 200 REM 210 FOR CHNUM=0 TO 127 211 PRINT CHNUM,CHR$(CHNUM) 212 GOSUB 220 213 PRINT 214 NEXT CHNUM 215 REM FIDDLE CHR$ VALUE TO ROM VAL 220 IF CHNUM<32 THEN CH=CHNUM+64 230 IF CHNUM<96 THEN IF CHNUM>31 THEN CH=CHNUM-32 240 IF CHNUM>95 THEN CH=CHNUM 250 REM PULL 8 BYTES,TRANSLATE,PRINT 260 CLOC=CHBAS+(8*CH) 270 FOR B=0 TO 7 280 BYTE=PEEK(CLOC+B) 290 GOSUB 500 300 PRINT B+1;"* ";BIN$ 310 NEXT B 320 RETURN 500 REM DECIMAL TO BINARY 505 BIN$=" " 510 DIV=128 515 BYTE1=BYTE 520 FOR T=1 TO 8 530 BIT=INT(BYTE1/DIV) 535 IF BIT=1 THEN BIN$(T,T)="1" 540 IF BIT=1 THEN BYTE1=BYTE1-DIV 550 DIV=INT(DIV/2) 560 NEXT T 610 RETURN Program 1. 70 REM PROGRAM 2 80 DIM BIN$(8) 90 REM O.S. SHADOW FOR CHBAS=2F4 HEX 100 CH=2*256+15*16+4 130 CHBAS=PEEK(CH)*256 200 PRINT "ENTER CHARACTER NUMBER" 210 INPUT CHNUM 211 PRINT CHNUM,CHR$(CHNUM) 212 GOSUB 220 213 PRINT 214 GOTO 200 215 REM FIDDLE CHR$ VALUE TO ROM VAL 220 IF CHNUM<32 THEN CH=CHNUM+64 230 IF CHNUM<96 THEN IF CHNUM>31 THEN CH=CHNUM-32 240 IF CHNUM>95 THEN CH=CHNUM 250 REM PULL 8 BYTES, TRANSLATE,PRINT 260 CLOC=CHBAS+(8*CH) 270 FOR B=0 TO 7 280 BYTE=PEEK(CLOC+B) 290 GOSUB 500 300 PRINT B+1;"* ";BIN$ 310 NEXT B 320 RETURN 500 REM DECIMAL TO BINARY 505 BIN$=" " 510 DIV=128 515 BYTE1=BYTE 520 FOR T=1 TO 8 530 BIT=INT(BYTE1/DIV) 535 IF BIT=1 THEN BIN$(T,T)= "1" 540 IF BIT=1 THEN BYTE1=BYTE1-DIV 550 DIV=INT(DIV/2) 560 NEXT T 610 RETURN Program 2.
Now let’s assume we POKE 106, PEEK(106)-4. This will move the end-of-memory fence back four pages. Each page, you will recall, is 256 bytes, so that’s 4 × 256 or 1024 bytes moved back. We then re-execute a graphics command, so the Atari will move the display memory display list out of that 1024-byte area, behind its fence. (See Diagram 6.) In this way we reserve 1024 bytes of memory starting on a page border.
There are several advantages of getting 1024 bytes this way. It doesn’t matter what size memory your machine has, as long as the minimum 1024 bytes are available. Nor does it matter how long your Basic program is or what graphics mode you are in. You can see it is quite a handy general purpose thing to have.
This is also the preferred technique to use when reserving memory for the Player-Missile bitmap area. Eight pages are required for a 2048-byte bitmap (single line resolution) or four for 1024 bytes (double line resolution). You will see this byte 106 modification in most Player-Missile articles.
One warning note: Basic cannot handle setting up a display list and display memory for graphics modes 7 and 8 in all cases when you modify the 106 pointer by less than 4K at a time. This means graphics 8 will produce truly bizarre results if you use PEEK(106)-8. Use a minimum of 4K change, or PEEK(106H6. This may explain the problems some people have using Player-Missile graphics with high resolution graphics modes.
Address Usage ┌────┐ │0000│ │ │ Operating System │????│ ├────┤ │????│ │ │ │ │ Basic Program Storage │ │ │ Grows Downwards into Free Memory │????│ │ ├────┤ ∨ │????│ │ │ Free Memory │ │ (Size varies) │ │ │????│ ├────┤ │????│ ∧ │ │ │ Display List │????│ │ ├────┴─┐ │ │???? │ │ │ │ │ Display Memory │ │ Grow Upwards into Free Memory PEEK(106) │MEMTOP│ └──────┘ (Cartridge, etc, or end of ROM) Hence, PEEK(106) marks the last address of usable memory to the fttari. The display memory is put immediately above it. Diagram 5. ┌──────────┐ ┌──────────────┐ │ │ │ │ │ (free) │ │ (display │ │ │ │ area) │ │ │ │ │ │ │ ├──────────────┤ 106 "fence" │ │ │ │ │ │ │ (memory now │ │ (display │ │ open for │ │ area) │ │ user’s │ 1024 bytes │ │ │ needs) │ │ │ │ │ └──────────┘ 106 "fence" └──────────────┘ When the 106 "fence" is moved upwards, and a graphics command re-executed, memory below it is left open for user’s applications (character sets, player-missile graphics, and so forth). Diagram 6.
We now know the beginning of the RAM area, and where the ROM character set starts (E000 hex or 57344 decimal). Let’s use Program 3 to copy the ROM character set to RAM. This program moves the 106 pointer back four pages and copies the character set over. It takes a while — around ten seconds to copy 1024 bytes— but later we will see a better way to do this.
Finally, the CHBAS pointer is changed to reflect the page of the beginning of RAM. Antic is now using the RAM character set. (See Diagram 7.)
Now Program 3 doesn’t show you much, for Antic will still be displaying characters as usual. So, let’s watch the copy process in action. This time we will move the character set pointer first, then do the copy. Your screen will then display whatever junk is in memory at the start of the copy as the pointer is changed, then more and more letters will appear as Basic copies character shapes into the RAM table. At the end of the copy, the screen will once again appear normal. (See Program 4.)
Program 5 represents an interesting variation. It copies characters from ROM to RAM upside down. It does this by copying the eighth byte of every character into the first byte of the new bitmap for that character, the seventh to the second, and so forth. The result is that the new RAM bitmap is an inverted image of the ROM bitmap. This is fun; the characters are still onscreen, and you can edit and so forth, but they are upside down. (See Diagram 8.)
50 REM PROGRAM 3 60 REM COPIES CHARSET TO RAM 100 MEMTOP=PEEK(106) 110 GRTOP=MEMTOP-4 120 POKE 106,GRTOP 130 REM RESET 140 GRAPHICS 0 141 LIST 160 CHROM=PEEK(756)*256 170 CHRAM=GRTOP*256 180 PRINT "COPYING." 500 FOR N=0 TO 1023 510 POKE CHRAM+N,PEEK(CHROM+N) 520 NEXT N 530 PRINT "COPIED." 535 REM NOW MODIFY POINTER 540 POKE 756,GRTOP Program 3. 50 REM PROGRAMS 60 REM COPIES CHARSET TO RAM 100 MEMTOP=PEEK(106) 110 GRTOP=MEMTOP-4 120 POKE 106,GRTOP 130 REM'RESET 140 GRAPHICS 141 LIST 160 CHROM=PEEK(756)*256 170 CHRAM=GRTOP*256 172 REM NOW MODIFY POINTER 173 POKE 756,GRTOP 180 PRINT "COPYING. " 500 FOR N=0 TO 1023 510 POKE CHRAM+N,PEEK(CHROM+N) 520 NEAT N 530 PPINT "COPIED. " Program 4.
Program 6 shows yet another useful variation. It makes the last byte of every character a 255, or solid l’s. This puts a solid line at the base of the characters, and creates a line at the bottom of each of the 24 character rows— a nifty effect.
Program 7 illustrates another handy character set feature. We can POKE different values into the CHBAS pointer and thus switch between multiple character sets immediately. In Program 7 we have two character sets, one normal, one flipped upside down. The program switches between them rapidly for an effect that is hard on the eyes. Assembly language programmers take note: with a display list interrupt, you can change character sets midway down the screen. The possibilities are amazing. Just POKE a new value into the Antic hardware address for CHBAS.
Changing a Character
Now let’s assume we have decided to change a ROM character set character to a custom one. Let’s work it out by hand the first time. Incidentally, an editor based on this hand working out is none too difficult to write and there are many more on the market. None, however, has the storage scheme I’m going to explain which is so convenient.
First, let’s design the character we want as an 8 × 8 dot matrix. (See Diagram 9.)
This is, of course, the character from the “Have a Nice Day!” button.
Next, let’s determine the bit patterns. You can do this by converting to hex each nibble (four bits), and then going to decimal (as I do), or by adding the number shown on the top of the column to the total for that line whenever the dot it represents is on. For example, in the diagram, 16 and 18 are on, so add 16+8=24.
At the end of this process, you will have 8 bytes of data which represent the bitmap for that character. Next, let’s figure out which character we will replace with our character. How about the space character? There are plenty of those onscreen. OK, the space character is the first one in the ROM-RAM character set— character #0, in internal code., So what we do is to POKE these eight bytes into the location where the bitmap of the space character is located, replacing it with the “smile” character. See Program 8, which is our copy-the-character-set-from-ROM-to-RAM routine with the added POKEs. (The numbers are in the DATA statement.)
40 REM PROGRAM 5. COPIES UPSIDE DOWN. 50 REM COPY CHARSET UPSIDE DOWN 100 MEMTOP=PEEK(106) 110 GRTOP=MEMTOP-4 115 CLOC=GRTOP 120 POKE 106,GRTOP 130 REM RESET GR.0 DM/DL AREA 140 GRAPHICS 0 141 LIST 150 CH=756 160 CHROM=PEEK(CH)*256 170 CHRAM=GRTOP*256 175 PRINT "CHRAM=";CHRAM;" CHROM=";CHROM 180 PRINT "COPYING." 190 REM COPY ROM TO RAM 300 POKE CH,CLOC 500 FOR N=0 TO 1023 510 POKE CHRAM+N,PEEK(CHROM+N) 520 NEXT N 530 PRINT "COPIED." 550 REM NOW COPY UPSIDE DOWN 600 FOR CHNUM=0 TO 127 610 FOR BYTE=0 TO 7 615 Z=PEEK(CHROM+(CHNUM*8)+BYTE) 620 POKE (CHNUM*8)+(CHRAM)+(7-BYTE),Z 630 NEXT BYTE 635 NEXT CHNUM 640 PRINT "RECOPIED." Program 5. 40 REM PROGRAM 6. UNDERLINES CHARS. 100 MEMTOP=PEEK(106) 110 GRTOP=MEMTOP-4 115 CLOC=GRTOP 120 POKE 106,GRTOP 130 REM RESET GR.O DM/DL AREA 140 GRAPHICS 141 LIST 150 CH=756 160 CHROM=PEEK(CH)*256 170 CHRAM=GRTOP*256 175 PRINT "CHRAM=";CHRAM;" CHROM=";CHROM 180 POKE CH,GRTOP GOO FOR CHNUM=0 TO 127 610 FOR BYTE=0 TO 7 615 Z=PEEK(CHROM+(CHNUM*8)+BYTE) 616 IF BYTE=7 THEN LET Z=255 620 POKE (CHNLM*8)+(CHRAM)+(BYTE),Z 630 NEXT BYTE 635 NEXT CHNUM 640 PRINT "RECOPIED." Program 6. 40 REM PROGRAM 7. COPIES UPSIDE DOWN. 45 REM THEN FLIPS BACK AND FORTH 100 MEMTOP=PEEK(106) 110 GRTOP=MEMTOP-4 115 CLOC=GRTOP 120 POKE 106,GRTOP 130 REM RESET GR.O DM/DL AREA 140 GRAPHICS 141 LIST 150 CH=756 160 CHROM=PEEK(CH)*256 170 CHRAM=GRTOP*256 175 PRINT "CHRAM=";CHRAM;" CHROM=";CHROM 180 PRINT "COPYING." 190 REM COPY ROM TO RAM 300 POKE CH,CLOC 500 FOR N=0 TO 1023 510 POKE CHRAM+N,PEEK(CHROM+N) 520 NEXT N 530 PRINT "COPIED." 550 REM NOW COPY UPSIDE DOWN 600 FOR CHNUM=0 TO 127 610 FOR BYTE=0 TO 7 615 Z=PEEK(CHROM+(CHNUM*S)+BYTE) 620 POKE (CHNUM*8)+(CHRAM)+(7-BYTE),Z 630 NEXT BYTE 635 NEXT CHNUM 640 PRINT "RECOPIED" 700 REM FLIP 710 POKE CH, 224: REM NORMAL ROM 720 POKE CH,CLOC 730 GOTO 710 Program 7.
If we wanted to replace another character we would multiply its character number by 8, add it to the start of the address of the character set and start POKEing there. That’s why I added the LOC=(CHBAS + (8*0)), which at first seems nonsensical. Replace the with whatever number you wish. At this point your Atari will be smiling proudly. Take a minute and enjoy its happiness at your success.
│──────── │ │Basic │──────── │ The ROM character set is copied │Free to RAM, then the CHBAS pointer │RAM ANTIC uses is changed to tell │ ANTIC to use the RAM characters. │ │──────── │Display │Memory │ PEEK(106) │──────── │RAM CHBAS POINTER (new) │C-SET ─<─┐ <──── │──────── │ MEMTOP │ │ │ │ │──────── │ │ROM │ CHBAS POINTER (old) │C-Set ─>─┘ <──── │──────── Diagram 7. THIS AN ATARI INVERTED SCREEN Sample of inverted characters. Editing and all cursor functions can be performed with the Atari in this mode. Diagram 8.
You don’t want to have to re-POKE your character set each time you want to use it. And let’s face it, the POKE method of copying the 1024 bytes from ROM to RAM is incredibly slow. Let’s solve these problems with some custom routines. They all work with string manipulations, which I’m rapidly beginning to realize are extremely powerful and usable on the Atari. The reason for their power is their speed in an otherwise slow Basic; the string manipulation routines are just high speed assembly language copy routines. Let’s subvert them for our purposes, and have assembly speed without all the hassles.
Each string is stored in memory as a continuous group of bytes. A string has a DIMensioned length, a “currently in use” length, and a location in memory. Let’s say we have two strings. RAMS and ROMS, and assume they both have length 1024. Assume also that the storage location where the Atari thinks RAMS is in memory just happens to be our RAM character set area. (What a marvelous coincidence.) Let’s further assume that ROMS is in the ROM character set area (or so the Atari thinks.) What will happen then when we execute RAMS=ROM$?
The Basic string manipulation routines will copy 1024 bytes (dimensioned length) from ROMS to RAMS, and thus copy the ROM character set to the RAM character set at extremely high speed!
Now let’s modify the RAM character set. Bear in mind that you can do this with either a POKE or a string operator: when you modify the string, you’re modifying the RAM character set. (It won’t let you modify ROMS for obvious reasons). Then let’s write RAMS out to disk. Fine, the Atari will store your character set on disk as a string. Next, let’s read it back in, still using all string manipulation operators, and store it back into the character set area. You will have stored and recovered your character set. Nice, eh? No hassles with bits and bytes, just a PRINT to disk and an INPUT later on. (The details of reading and writing said string I’ll leave to you; it’s awfully easy).
Incidentally, the power of the copy capability is also usable in player-missile graphics. In the April 1981 “Outpost: Atari,” George Blank assigned a string to the player bitmap area, and then moved the player up or down at high speed using a $=$. This is a nice, fast way to move a player vertically, which before required either assembly language or slow POKE copies. And strings may be used for data storage; the display list interrupt routine I wrote and documented not too long ago used a string to store data bytes for color registers, and another string to hold the assembly program used for the interrupt handling.
Let’s learn how to change where the Atari thinks a string is located in memory. Then we’ll get to the actual subroutines you can use.
The Atari keeps two tables in memory for Basic that deal with string variables. One is called the variable table, the other the array table. There are 128 possible variable names on the Atari, numbered 0-127, and the variable table has an 8-byte entry for each name in use. All the entries are packed together. For strings this entry has dimensioned and in-use length, and location in the array table in which the string is stored.
The other table is the array table, in which the actual data of the string is kept. So, what we have to do is alter the dimensioned and in-use length as shown in the variable table, both to 1024, then modify where the Atari thinks the variable is stored in the array table. The only tricky part of this is that the address of where the string is actually stored is relative to the array table; in other words, a for this value doesn’t mean the string starts at location 9, it starts at the beginning of the array table.
You can find the beginning of the
variable table by:
and the array table by:
Next, we must consider the actual layout of the variable table entries. I will assume that RAMS and ROMS are the first two variables in the table. In reality, to do this they must be the first variables typed in a NEW program or ENTERed from a program LISTed to disk (A SAVE-LOAD won’t work, it stores the variable table along with the program). So if you are starting out with a new program, just have the DIM line (10 DIM RAM$(1),ROM$(1)) as the first line of your program after a NEW. If you’re adding these to an existing program, make that the first line and LIST-ENTER it to disk.
Note: The variable table entry is created for any variable referenced by your program. This includes variables you used once and then deleted; they are still there taking up space. You can run out of space in the variable table when it gets too full of these nonexistent variables. LIST, then ENTER the program from disk to clear out the table; it forces a new variable table to be built.
Table 1 shows the variable table with explanations.
This is the entry for RAMS, the first string in the table. The entry for ROMS immediately follows.
This subroutine should now become clear. It modifies the address and length of RAMS to that of the chracter set. It not only copies ROMS to RAMS, it also modifies the variable table data for ROMS. (All the modifying, by the way, is quite speedy, so the RAM$=ROM$ still executes much faster than the previous POKE copy). (See Program 9.)
Well, there you have it. A painless introduction to character sets. If you’ve a mind for a little experimenting, you can have a great deal of fun with them, while expanding the abilities of your Atari tremendously. I’m considering using multiple reprogrammed characters, for example, in a dungeon game I’m thinking of writing, to show in fine detail the monster approaching you. That’s just one of many applications.
|VT+0||129||"This is a string"|
|VT+1||0||"This is variable #0"|
|VT+2,VT+3||??||16 bits. Location from the start of AT.|
|VT+4, VT+5||??||DIMensioned length.|
|VT+6, VT+7||??||In-use length|
50 REM PROGRAM 8 60 REM COPIES CHARSET TO RAM 70 REM POKES POINTER B/4 COPY 80 REM ADDS SMILE 100 MEMTOP=PEEK(106) 110 GRTOP=MEMTOP-4 120 POKE 106,GRTOP 130 REM RESET 140 GRAPHICS 0 141 LIST 145 CHROM=PEEK(756)*256 150 REM NOW MODIFY POINTER 160 POKE 756,GRTOP 170 CHRAM=GRTOP*256 180 PRINT "COPYING." 500 FOR N=0 TO 1023 510 POKE CHRAM+N,PEEK(CHROM+N) 520 NEXT N 530 PRINT "COPIED." 540 REM ABCDEFGHIJKLMNOPQRSTUVWXYZ 550 REM 123567890!"#$;%&'0()<>-=+* 1000 REM SMILE BUTTON LAYOUT: 1010 REM 00000000 00 00 1020 REM 01100110 66 102 1030 REM 01100110 66 102 1040 REM 00000000 00 000 1050 REM 01000010 42 66 1060 REM 00111100 3C 60 1070 REM 00011000 16 24 1080 REM 00000000 00 00 1089 REM 1090 DATA 00,102,102,000,66,60,24,00 1100 FOR ADDR=CHRAM TO CHRAM+7 1110 READ DAT:POKE ADDR,DAT 1120 NEXT ADDR Program 8. 4 REM PROGRAM 9 5 REM PROGRAM TO COPY ROM TO RAM 6 REM USING STRING MANIPULATORS 7 REM 8 REM NOTE MOST CALCULATIONS ARE NOT 9 REM HARDCODED TO ALLOW OTHER USE 10 DIM RAM$(1),ROM$(1):REM VT ENTRY 1 90 REM GET ARRAY,VARIABLE,DL,DM LOC 105 AT=PEEK(140)+256*PEEK(141) 110 VT=PEEK(134)+256*PEEK(135) 120 POKE 106,PEEK(106)-16:REM 4K MOVE 125 GRAPHICS 0:REM RESET OUT OF TOP AREA 130 RAMLOC=PEEK(106)*256 150 REM CALCULATE OFFSET FROM AT 160 OFFRAM=RAMLOC-AT 170 OFFROM=(14*4096)-AT 220 REM CALCULATE LO,HI BYTES 225 LENS=1025:REM C-SET LENGTH 230 LENHI=INT(LENS/256) 240 LENLO=INT(LENS-(LENHI*256)) 245 REM 250 OFFRAMH=INT(OFFRAM/256) 260 OFFRAML=INT(OFFRAM-(256*OFFRAMH)) 270 OFFROMH=INT(OFFROM/256) 280 OFFPOML=INT(OFFROM-256*OFFROMH)) 300 REM REWRITE RAM$ DATA IN VT 310 REM VT+0 = 129 320 REM VT+1 = 0 (VAR #0) 320 POKE VT+2,OFFRAML:REM OFFSET 340 POKE VT+3,OFFRAMH:REM OFFSET 350 POKE VT+4,LENLO:REM DIM LENGTH 360 POKE VT+5,LENHI:REM DIM LENGTH 370 POKE VT+6,LENLO:REM USED LENGTH 380 POKE VT+7,LENHI:REM USED LENGTH 400 REM REWRITE ROM$ DATA IN VT 410 REM VT+8 = 129 420 REM VT+9 = 1 (VAR #0) 430 POKE VT+10,OFFROML:REM OFFSET 440 POKE VT+11,OFFPOMH:REM OFFSET 450 POKE VT+12,LENLO:REM DIM LENGTH 460 POKE VT+13,LENHI:REM DIM LENGTH 470 POKE VT+14,LENLO:REM USED LENGTH 480 POKE VT+15,LENHI:REM USED LENGTH 500 REM RESTORE CHBAS POINTER 510 POKE 756,PEEK(106) 515 REM NOW DO COPY. 520 RAM$=ROM$ Program 9.
CREATIVE COMPUTING VOL. 8, NO. 2 / FEBRUARY 1982 / PAGE 182
Once upon a time, a very imaginative company looked at the home computer market. It found the graphics available on many of the machines to be limited. So the company designed a powerful machine with particularly good graphics capabilities. And it sent this machine out onto the market.
But no one understood how it worked. It was not a mere clone of earlier machines; it incorporated some revolutionary ideas. So few were bought. The company began to see that until the inner workings were understood, this machine would not sell very well.
On the other hand, they felt, when the power and flexibility of the machine became known, it would have no competition in its field. But there was absolutely no tutorial material available to unwrap the powerful goodies in the Atari. And without a tutorial, discerning the concepts behind the computer was very, very difficult.
Compounding the problem was the fact that the only available documentation was reference manuals, which were never intended to be teaching guides. Once the basic concepts were understood, the machine wasn’t difficult to use, but mastering those concepts was nearly impossible.
A few magazines were running scattered tutorials in bits and pieces. For the most part, authors were in the same boat as the general public, but they shared what knowledge they had with the computing public. Gradually, the available information began to spread.
In June of 1981, Creative Computing began a tutorial series on the Atari in this column. The tutorial series has covered the abilities of the Atari from the point of view of the Basic programmer, and has assumed little knowledge on the reader’s part of esoteric computer buzzwords. (What was needed was explained. ) The series has been well-received by readers, and will be published shortly as part of The Creative Atari from Creative Computing Press. It remains the only beginner’s’ level tutorial on the Atari.
Creative does deserve kudos for publishing the series and really trying to help its Atari readers.
Even though the number of Atari owners in the readership is much smaller than, for example. TRS-80 owners. Creative has devoted a good deal of space to the series. If you’re in the letter writing mood, you might drop George Blank or Betsy Staples a line and thank them for their efforts and for taking the risk.
In future columns we plan to include more product reviews and the sorts of things one would expect in a column. Now that we have defined the basic concepts, we can discuss the Atari in other than beginning-level language, and add to the knowledge available. We will also try to keep you up to date on the latest from the rumour mill and from Atari.
Needless to say, as authors we leave many questions untouched— our articles sometimes raise more questions than they answer. Such is the way of the Atari: there is always another feature to cover. And we get many letters asking questions.
Sandy and I have been swamped with letters asking questions about the Atari. We try to answer them all, but we do tend to answer those with an S.A.S.E. enclosed the fastest (let’s say within two months). If you do send a letter, please don’t expect a typed reply, and try to keep the questions short so we can answer them fairly quickly. Also, if the answer is in a previous column, and long, we’ll probably just refer you to that column; you can order back copies of magazines from Creative and most computer stores stock a few back issues.
In this column, we’ll attempt to cover a variety of short subjects. None of them is broad enough to write a column about, yet all deserve an answer.
Q: PEEK(741)+256*PEEK(742) (from July ’81) is not a good way to find the display list. PEEK(560) is. Why didn’t you?
A: Knowledge about the Atari is a rapidly unfolding thing. We pass on what we know when we know it. And remember, we write columns about four months before you read them. Since we are experimenting with the Atari all the time, and learning more, sometimes we discover a better way of doing things about which we have already written. No matter: we try to give the best of what we know at the time.
Q: In the DLI article (December 1981) you don’t use memory page 6. Why? If you did, you could fix the location of the program and avoid the relocation code.
A: First, we left the page alone so the user could use it along with the DLI routine. Remember, the DLI routine will coexist and coexecute along with many assembly routines as it is an interrupt handler. Hence, it is potentially more useful located outside of page 6.
Second, it gives us a chance to explain all about string handling and the general principles behind regarding a string as just a collection of bytes in memory, useful in other ways besides merely holding characters. These are tutorials, remember, and often the stated goal is far less important than the getting there. The principles behind the demonstration will be far more useful, in many ways, than will be the demontration.
Q: In the July article you show a mixed mode display, which I can’t produce. Could you send me the code for this? (Multiply this by 80 letters or so.)
We omitted the code because I was addressing the principle of stacking display blocks, and the code is somewhat confusing. It tends to raise more questions that it answers, but I have included it here for the curious. See Listing 1.
Listing 1. 10 REM GRAPH PROGRAM 20 REM LAYOUT: 30 REM 40 REM 1 LINE GR.2 20 BYTES 16 50 REM 1 LINE GR.2 40 32 60 REM I LINE GR.0 80 40 70 REM 120 LINE GR.8 80+(4800) 160 80 REM 1 LINE GR.0 +40 168 90 REM 1 LINE GR.0 +40 176 100 REM 1 LINE GR.0 +40 184 110 REM 1 LINE GR.0 +40 192 200 REM SET MODE 210 GRAPHICS 8+16:REM FAKE LAST FOUR 220 REM DISPLAY LIST 230 ST=PEEK( 560 ) + 256*PEEK( 561 ) 240 REM ST+0,ST+1,ST+2=112..LEAVE BE 242 REM ST+3=79. CHANGE TO 7+64. 243 POKE ST+3,7+64 245 REM ST+4,+5=DATA. LEAVE BE. 246 REM ST+6,ST+7=15. MOD TO 7,2. 247 REM (MODE 2, THEN MODE 0). 248 POKE ST+6,7 249 POKE ST+7,2 250 REM DM + 0 - DM + 29 = MODE 2 L1 255 GOSUB 1000 260 DIM A$(60) 261 SETCOLOR 4,8,2 270 A$=" MODE 2 BIG TITLE " 280 REM 12345673901234567890 290 REM TRANSLATE A$ TO INTERNAL CSET 300 GOSUB 500 330 REM FIND DISPLAY MEMORY 340 DM=PEEK(ST+4)+256*PEEK(ST+5) 410 REM POKE INTO MEMORf 420 FOR T=1 TO 20 430 POKE DM+(T-1),ASC(A$(T,T)) 440 NEXT T 450 A$=" MODE 2 SECOND LINE " 460 REM 12345678901234567890 470 REM TRANSLATE A$ TO INTERNAL CSET 480 GOSUB 500 485 REM POKE INTO MEMORY 490 FOR T=1 TO 20 493 POKE DM+20+(T-1),ASC(A$(T,T)) 436 NEXT T 497 GOTO 600 500 REM SUBROUTINE TO XLATE ASC TO 510 REM INTERNAL CSET 520 FOP Z=1 TO LEN(A$) 530 IF A$(Z,Z)=" " THEN A$(Z,Z)=CHR$(0) 540 IF ASC(A$(Z,Z))<>0 THEN A$(Z,Z)=CHR$(ASC(A$(Z,Z))-32) 550 NEXT Z 560 RETURN 600 REM DO MODE LINE NEXT. 40 BYTES 610 A$=" A TEXT MODE SUBTITLE" 620 REM XLATE 630 GOSUB 500 640 REM POKE INTO MEMORY 650 FOR T=1 TO LENC A* ) 660 POKE DM+40+(T-1),ASC(A$(T,T)) 670 NEXT T 675 REM PLOT A SAMPLE GRAPH 676 SETCOLOR 2,8,0 680 XMIN=2 690 YMIN=5 700 XMAX=319 710 YMAX=159 720 COLOR 1 725 PLOT 1,70:DRAWTO 319,70:PLOT 1,70 726 XSAV=1:YSAV=70 730 FOR X=5 TO 315 STEP 5 740 Y=INT(RND(0)$70)+40 750 DRAWTO X,Y 752 PLOT XSAV+1,YSAV:DRAWTO X+1,Y 753 PLOT XSAV+2,YSAV:DRAWTO X+2,Y 755 XSAV=X:YSAV=Y 760 NEXT X 770 REM PUT IN 4 TEXT LINES AT BASE/ 780 REM AFTER 160 (GR.8) INSTRUCTIONS 790 GOTO 790 1000 FOR Y=ST+150 TO ST+210 1010 IF PEEK(Y)=65 THEN 1100 1020 NEXT Y 1030 PRINT "PLATO OFF." 1040 STOP 1100 B1=PEEK(Y+1) 1110 B2=PEEK(Y+2) 1120 POKE ST+162,B2 1130 POKE ST+161,B1 1140 POKE ST+160,65 1150 RETURN
Basically we are modifying a graphics 8 display list to:
Gr.8 x lots
We are not duplicating the July display exactly, but you can with the principles in the code.
We use two GR.2 lines to make the memory requirements come out to 40 bytes, to keep “in sync” with graphics 8. We then put data into the first 120 bytes of DM for character output.
Character data is translated from ATASCII to INTERNAL format for display: they are not the same. A machine language routine here would be quite nice: there is probably one in the operating system that could be used. The INTERNAL codes are then POKEd into memory.
Because we now generate 16+16+8+189 scan lines, instead of 192, we have a total of 229 generated lines. This will probably cause your TV to “roll.” So we chop out the lower 40 graphics 8 instructions by moving the JVB instruction up. I copy the data bytes first, then the JVB byte, to prevent the JVB taking off into random memory.
Or so we thought. (And so we told you.) JVB is the jump and wait for vertical blank: it makes the display list into a GOTO loop, so we said. Except that just by accident we found out that where it jumps to doesn’t matter. That’s right: the data bytes following the JVB are irrelevant. Why? Because at the start of every screen refresh, the operating system copies the display list location shadows (560. 561 ) into Antic and re-sets him to the start of the DL. So all is well even if Antic, at the end of the DL. jumps off to kingdom come.
Except: during disk accesses, where apparently the Vblank routine copy is nulled. Then the screen will go wild. (See what I mean about “rapidly changing knowledge”?)
Along these lines, a fun display is to set up two display lists and two display memories, and have Antic execute them alternately. (Use a DLI in the first 112 instruction to swap display memories.) You’ll get two displays superimposed on each other. For example, we had a graphics display of Basic code imposed on the graphics 8 display it produces. Nice, and nifty for an editor or such. However, it does tend to flicker.
Q: Speaking of flickers, your DLI routine has an annoying flicker in midscreen— a border between two colors that jumps back and forth. Why?
A: You’re right. Next question?
Seriously, the reason for this is that the 6502 just doesn’t have enough time to copy all the data into the CTIA color registers before the TV scan line begins. In fact, it can’t even start until midway through the last scan line of the display block with the interrupt flagged. The TV refresh process outruns this rather generalized routine. You’ll have to learn assembly language to deal with this properly: use WSYNC, then rapidly store up to three colors after the WSYNC using STX, STY, and STA. You’ll still be offscreen. For those of you I’ve lost, the timing of a DLI routine is a very touchy thing; if you don’t know machine language and how the Atari relates to the TV, forget it.
This routine will also crash in graphics 8 as it will not complete between interrupts if you have interrupts on two consecutive scan lines. If you want that, learn assembly language, then write your own driver.
Q: My Atari dies after being on for a while. Or, my Atari freaks out unexpectedly. Or, my Basic programs scrozzle themselves. Or....
A: 1. If you squeeze the last few bytes of available memory, Basic seems to screw up. Something in the upper memory management routines fails during tight squeezes, and there isn’t much you can do about it. Sorry.
2. The Atari memory boards may be giving you trouble. Here’s Small’s Memory Board Fix (which works amazingly often on bizarre Atari problems):
The Atari memory boards get hot, really hot, in their enclosed metal cans in the enclosed metal cage. This heat can mess things up, particularly in the connectors. The metal is necessary to avoid spraying radio frequency interference all over, but it does cause problems. So every month or so we pull all the boards out of the Atari and re-seat them. This re-establishes the socket connection. Cleaning the ends of the connector (a pencil eraser works wonders) and coating them with Lubriplate. then re-seating them is also a good idea— helps prevent corrosion.
If this fixes it, fine. If not, go the drastic route (as we had to on one very touchy 800):
1. Remove the lid. Bypass the interlock with a taped in Q-Tip.
2. Remove the memory board lids (pull the two Phillips head screws). Re-install the boards.
This will really help to keep things cool. Of course, you may not be able to watch TV nearby (nor will your neighbors) but it will prevent overheating.
Now that you have the lid open, some of you are doubtless going to get the clever idea of copying ROM cartridges onto disk. After all, you can boot up, then plug them in with DOS running. Then, a simple binary save, right?
Atari has some nasty, nasty surprises awaiting you if you try this. First, plugging the cartridges in sends a nice hefty spike into the memory lines, straight into sensitive Antic. CTIA, and the 6502B. Do you really want your Atari in the repair shop? All it takes to destroy these chips is a little static electricity in the wrong place, and your body is probably full of it in the winter.
Second, the Atari people have some special checks to prevent this. For example, disk I/O doesn’t work the way you might expect from cartridges. Ever had your directory mysteriously disappear? This should be food for thought.
Speaking of piracy in general. I have found copies of my software (what goes into these articles) floating around all over the place. This is really embarassing when the disk that was pirated is a development disk and you’ve saved all sorts of junk on it.
But second, when you think about it. the prices you pay for software nowadays in many cases are pretty low anyway (when was the last time you could go on a date for $20), so why not give the author his royalties, and get the documentation as well?
I wish that people didn’t consider protection schemes a Scott Adams adventure #30 to be broken. If you think about it, the hours you spend breaking the scheme are equal in dollars to what you would pay for the software in many cases. (And if you’re thinking about selling copies, don’t : all the software companies I’ve talked to are currently prosecuting people caught doing this.)
Q: I have 32K. Should I get 48K?
A: Maybe. If you use no cartridges, the Atari can use up to 48K RAM. If you use one cartridge, you are reduced to 40K available; if you use two,32K. Eventually, as more RAM-only programs become available. 48K will be more and more handy. For example. Microsoft Basic, which we are currently testing, requires 48K but has no cartridges (disk based). We’re in a transition period, in other words, and it may be to your advantage to wait a bit: hardware prices are dropping quickly, as usual.
Q: During a disk access, my disk stops for a while for no reason and then restarts. Why?
A: A bug in the O.S. program. No, the disk isn’t stopping to cool off (like an 820 printer) or anything. This is fixed in the new revision cartridges, which are slowly becoming available.
Q: What are DOS 2.5. 2.7, 2.8. 2S. 2.0S. 2.0D?
A: DOS 2.0S is the final, “cast in concrete” version of DOS 2. The others are developmental versions. They are pre-release copies. There are lots of 2S disks lying around: these have a bug in the interrupt subsystem, so best get rid of them. Also, if you boot up under 2S, you can’t “DOS” to a 2.0 version of DOS. They’re incompatible. So your best bet is to change your disks over to 2.0S and use it.
DOS 2.0D is for the double density 815 drive, which has been cancelled, delayed, sent back, or whatever (depending on who you talk to).
Q: What is a “fast formatted disk?”
A: Inside the 810 disk drive there is a microprocessor. When the Atari wants a given disk sector (128 bytes), it asks that microprocessor for it. The micro then spins the disk and moves the head to get that sector. If you have a disk with a more efficient layout, you can go between sectors (without a complete spin between them, for instance). A “fast formatted disk” has this improved layout, and, thus, when you access it, disk I/O is around 20% faster.
Disks that you format with your 810 will not have this improved layout, because it lays them out the old, slow way. A new ROM, called the “C” ROM, can be installed into your disk drive to make it format disks the fast way.
Who knows when it will be available? The rumour mill says that I ) all disk drives going to Europe have it; 2) all disks to the East Coast have it; 3) all disks shipped after September 1981 will have it, etc. Probably by the time this is printed some policy will have been established.
For those of you who can’t wait, the Chicago area user’s group has constructed their own version of die format ROM, which requires a few wiring changes to the disk and programming a new EPROM (not your beginner-level stuff). The Chicago ROM is 10% faster than the Atari ROM, which is definitely interesting. The ROMs work quite well; I’ve seen them tested. However, since the Chicago folks developed them I’ll let them document it and take the credit. Incidentally, modifying a drive this way (of course) violates the warranties.
Q: What’s the GTIA chip and how do I get one?
A: The CTIA chip actually generates color for your TV. A new chip. GTIA, replaces CTIA and allows graphics modes 9. 10, and 1 1 out of Basic. (The operating system was written with GTIA in mind, and so was Basic, by the way.) It is an upgrade to the CTIA chip. The rumour mill again says it is available everywhere except where the rumour originates. We have one as the result of extreme kindness on the part of Atari, and are testing it. The added modes are:
Graphics 9: Allows 16 intensities (select by COLOR #) of pixels to be displayed in the background color. Great for grey-scale shading.
Graphics 10: Allows eight different kinds of pixels to be displayed in any of the standard colors. Uses the four P-M registers and four play field registers to set colors.
Graphics 11: Allows 16 different colors for pixels, all in the same intensity.
The pixel size is four bits long, and one scan line high. This is 80 × 192 resolution, an interesting twist on the general rule that vertical resolution is less than horizontal.
There will be a more complete article on the GTIA chip when it is more widely available. (The problem is, most people at Atari don’t have them either, and are trying just as hard to get one. Who do you think will get priority?)
A: Forth is a dynamite programming language available for the Atari. Its speed is somewhere between Basic and assembly language, but much closer to assembly language. Best of all, it’s a reasonably high level language (very stack oriented, as a matter of fact). I’m trying to learn it now. Versions are available from many sources. Atari lists Forth in their APEX exchange. but will not release it yet. Beware of other versions which may use undocumented entry points in the operating system, and which will quit working when the new cartridges are generally available.
There has been a lot of good software written in Forth. I have a synthesizer program, lent to me by Ed Rotberg of Atari, which plays the best music I ever heard from an Atari (and has different instrument sounds, too: drums, guitar, hand clapping, etc.). The Atari demo with the “Disco Dirge” is written in Forth to give you an idea of its execution speed and flexibility.
Q: Microsoft Basic.
A: You will be hearing a great deal about this from us. We are currently working with Microsoft Basic and it is a fantastic product, indeed. It is much faster than the Atari 8K cartridge Basic and has many, many more functions. It really turns the Atari into a serious business computer, for example. Look at the description of Microsoft Basic in any Apple. TRS-80 or PET book and you will get an idea what is available. Add to that many special Atari functions, and soon you will be writing only in Microsoft. (Look for a complete review shortly).
CREATIVE COMPUTING VOL. 8, NO. 3 / MARCH 1982 / PAGE 212
First came the TRS-80, Model 1. It provided character-oriented graphics.
Next came the Apple. It provided both character and line graphics (one or the other).
Now we have the Atari. It provides 14 graphics modes, some character-oriented, some line-oriented.
“Fourteen modes?” you say. “The Basic manual lists nine.” Well, that’s because Basic only allows you to access nine directly. However, there are others lurking within the machine waiting for a programmer to find them. All are variations on the available modes, some quite useful. One is so useful that this article will be devoted to discussing its use.
All character-line graphics on the Atari (“playfield graphics”) are generated by the close co-operation of two chips. Antic and CTIA. Antic fetches data for 3.7 million points per second (320 per line × 192 lines × 60 per second) and feeds it to CTIA which generates the TV picture from that data. To determine what sort of image should be generated (character, line, pixel size, etc.). Antic looks to his program, the display list. This program coexists in memory with all the usual Basic and 6502 programs. Anyway, his program, composed of individual instruction codes, tells him what sort of image to generate.
There are 14 image-generating codes in Antic’s program. Now when Basic was designed, for some reason it was decided to allow access to only nine of these codes. rather than the full 14. And in particular, the highest resolution four-color mode was left out. This is “graphics 7+” (also known as “graphics seven-and-a-half.”)
We got a great deal of mail from people asking how to use this graphics mode when we documented its existence back in the July 1981 Creative. (If you wish to see a tutorial on the Atari for the Basic programmer, go back to the June issue and read the “Outpost” columns to date. Sadly, we can’t explain how Antic and such work in each article because the explanation is so long, but we can refer you to previous issues to get a background.)
It takes a bit of work and a fair grasp of what goes on inside the Atari, but the results are well worth it: in the highest four-color mode, we can get double the resolution of graphics 7 using graphics 7+.
Graphics 7, you will recall, gives us 96 vertical × 160 horizontal pixels in four colors. Graphics 8 gives us 192 vertical × 320 horizontal, but only in one color. Graphics 7+ gives us 192 vertical × 160 horizontal in four colors.
This is an extremely useful mode. Graphics 8 has several disadvantages; single dots sometimes become red or blue when white was intended because of “artifacting.” and candy-stripes tend to appear on all near-vertical lines. Graphics 7 has pixels the size of 2 × 2 graphics 8 dots, and is too “chunky” for really accurate graphics. Graphics 7+, with double the vertical resolution, brings us close to the limits of most monitors in terms of color resolution, with 2 × 1 graphics 8 dots. No artifacting. no funny stripes, just nice colors in truly high resolution.
I should also mention that the graphics 7+ resolution is equal to the resolution of a player or missile at size × 1.
Here at Houston Instruments, where I work, we have a project going to interface a plotter, capable of eight colors, to a digitizer. The image to be plotted must be displayed on the TV. Graphics 7 resolution is unacceptable; the individual pixel is too large for a quality display. But graphics 7+ provides twice the resolution while retaining the four colors of data. (Now, you’d like to know how I plan to get eight colors, right? I must confess to having a few sneaky ideas how to do so, and I promise to document the method should I succeed.) However, for now, four colors at 160 × 192 will do nicely.
Graphics 7+ is midway between 7 and 8, so let’s look at 7 and 8 to help understand how to generate 7+.
Graphics 7 is a “four color” mode. This means that for every point on screen, two bits of information are saved in memory. Depending on which of the four numbers possible is saved in those two bits, one of four color registers is selected to display color. (Actual color information is not saved in the display memory; rather, a color register number is saved, with the actual color being stored in the register.) Hence, one byte (eight bits) in graphics 7 display memory, looks like this: ww xx yy zz where w, x, y, and z are the information for a given point on screen.
The memory is mapped starting from the upper lefthand corner of the screen, from the beginning of display memory, across the screen, down one line, and so on. Hence, since we have 96 × 160, or 15,360 points, and four points stored per byte, we use 3840 bytes of data.
When Antic generates graphics 7 he does two scan lines of the same data. Hence, each Antic instruction generates two scan lines, and 96 of these instructions generate 192 lines—the height of the screen.
In graphics 8, we only save one bit of information per point. That bit is used to determine at what intensity a point is plotted, and where the background color and intensity and foreground intensity are stored in color registers. Since only one bit is saved per point, a graphics 8 display memory byte looks like this: a b c d e f g h where each letter represents one point. There are 320 × 192 points. 8 to a byte, which comes out to 7680 bytes of data.
Each graphics 8 Antic instruction generates one scan line, so there are 192 of them to a full screen.
Now graphics 7+ has the same vertical resolution as graphics 8—one line per Antic instruction. It also has the same horizontal resolution as graphics 7 ( 160), and the four colors. Do you begin to see why it is such a useful mode?
Note that different information must be written into display memory to draw a line in a different mode. In particular, in graphics 7 or 7+ two bits must be written for each pixel, whereas in graphics 8 one bit must be written. This will be very important shortly. An operating system routine, stored in the ROM plug-in cartridge, handles all of the bit-shifting and masking to write the required bits into memory, based on what graphics mode it thinks it is in.
Time for some sample programs: The first generates a simple graphics 7 display. The next generates a simple graphics 8 display. This is to allow you to compare the resolutions. See Programs 1 and 2.
Program 1. 10 REM PROGRAM 1 -- DAVE SHALL 20 REM PROGRAM TO GENERATE GR.7 30 REM SAMPLE DISPLAY 40 REM 50 REM 8K BASIC VERSION 60 REM 70 GRAPHICS 7 80 COLOR 1 90 PLOT 1,1 100 DRAWTO 159,1 110 COLOR Z 120 DRAWTO 159,80 130 COLOR 3 140 DRAWTO 1,1 141 FOR Z=1 TO 20 142 COLOR (INT(RND(0)*3)+1) 143 PLOT (INT(RND(0)*159)), (INT(RND(0)*80)) 144 NEXT Z 150 PRINT "NOTE EACH GRAPHICS 7 PIXEL" 160 PRINT "USES TWO SCAN LINES." 170 GOTO 170
Program 2. 10 REM PROGRAM 2 -- DAVE SMALL 20 REM PROGRAM TO GENERATE GR.8 30 REM SAMPLE DISPLAY 40 REM 50 REM 8K BASIC VERSION 60 REM 70 GRAPHICS 8 75 SETCOLOR 2,0,0 80 COLOR 1 90 PLOT 1,1 100 DRAWTO 159,1 120 DRAWTO 159,80 140 DRAWTO 1,1 141 FOR Z=1 TO 20 142 COLOR (INT(RND(0)*3)+1) 143 PLOT (INT(RND(0)*159)), (INT(RND(0)*80)) 144 NEXT Z 150 PRINT "NOTE EACH GRAPHICS 8 PIXEL" 160 PRINT "USES ONE SCAN LINE." 170 GOTO 170
Program 3. 10 REM PROGRAM 3 20 REM 30 REM CONVERT GR.7 TO GR.7+ 40 REM DAVE SMALL 50 REM 8K BASIC VERSION 60 REM 70 REM CREATE IMAGE 530 REM ************************* 540 REM ** FROM CREATIVE COMPUTING.. 545 REM ** GENERATES MULTICOLOR SPIRAL 550 GRAPHICS 7:DEG :DIM C(3) 555 PRINT "CREATING IMAGE." 590 R=20: COLOR UC-1 600 X0=79:Y0=47 610 FOR K=0 TO 3:C(K)=K+1*2:NEXT K 620 FOR K=1 TO 3 630 X=X0+R*COS(360):Y=Y0:PLOT X,Y 640 FOR I=0 TO 5*360 STEP 75 650 X=X0+R*COS(I):Y=Y0+R*SIN(I) 660 DRAWTO X,Y 665 C=C+1:IF C>3 THEN C=1 667 COLOR C 670 NEXT I:R=R+12 680 NEXT K 690 Z8=1 700 PRINT "MODIFYING DL." 1000 REM GR.7 TO GR.7+ 1010 START=PEEK(560)+256*PEEK(561) 1020 POKE START+3,14+64:REM LMS 1030 FOR Z=START+6 TO START+6+96 1040 IF PEEK(Z)=13 THEN POKE Z,14 1050 NEXT Z 1059 REM REMOVE THIS STOP FOR LOOP.. 1060 STOP 1100 REM GR.7+ TO GR.7 1110 FOR Z-START+6+96 TO START+6 STEP -1 1140 IF PEEK(Z)-14 THEN POKE Z,13 1150 NEXT Z 1155 POKE START+3,13+64:REM LMS 1160 GOTO 1020
Next, we will take a graphics 7 display and convert it to graphics 7+.
What will happen? Well, first, since we have 96 instructions in graphics 7, each generating two scan lines, we get a total of 192 scan lines. If each of those 96 instructions generates only one scan line, as in graphics 7+, the screen will only be half filled (only the top 96 scan lines). The same display that graphics 7 had in it will be retained, it will just shrink vertically.
So for our third program, let’s take a graphics 7 display, and convert it to graphics 7+. You’ll see the effect of doubling your vertical resolution, and won’t believe how fine a line can be drawn in four colors. All we’ll do is take the 96 bytes of Antic’s program, when he’s in graphics 7, and convert them from an Antic code 13 (graphics 7) to a 14 (graphics 7+). See Program 3.
Pretty neat, right? Nice resolution. Now if we could only get the whole screen in that resolution.
Well, we can. We could go the tough way, where we allocate memory, build 192 graphics 7(14) instructions, set memory pointers to display memory, ad infinitum. Were we working in assembly language, we would have to do it that way. But there’s an easier way : take an existing display list and convert it. That way Basic has already allocated memory space and so forth, and we don’t need to worry about fooling it into leaving memory alone.
We can take a graphics 8 display list, already 192 instructions long, and convert the 1 5’s (Antic code for graphics 8) to 1 4’s. That part is easy, just a FOR-NEXT loop to convert every 15 to a 14. The only slightly tricky part is catching the LMS instructions (64 + 15 or 79), changing them to 78, and leaving the display memory data bytes alone. (See August 1981 for a discussion of LMS). This way, the right amount of screen memory is already reserved for us, the display list is set up, pointers and all, and we’ve saved a great deal of work.
Next, since graphics 8 uses a different bit pattern to display material, we’ll have to fool the operating system into thinking we’re really in graphics 7 so it uses the graphics 7 bit/shift routines. This is a matter of one POKE to the low memory location where the operating system looks each time it does a line draw to determine what graphics mode it is in. The location contains the graphics number currently in effect. We will, thus, POKE a 7 in there: it should currently contain an 8 from when graphics 8 was set up.
Well, here we go. (See Program 4.) We set up graphics 8, change the display list to graphics 7+, and do a three-color draw at the top of the screen. No problem, works fine. But when we try to draw anywhere in the lower half of the screen, we get an ERROR #141—cursor out of range.
Program 4. 10 REM PROGRAM 1 20 REM 30 REM CONVERT GR.8 TO GR.7 + 10 REM DAVE SMALL 50 REM 8K BASIC VERSION 60 REM 65 DIM C(3) 70 REM DISPLAY LIST MODS 80 GRAPHICS 8 90 PRINT "CONVERTING DL FROM 8 TO 7+." 100 START=PEEK(560)+256*PEEK(561) 110 POKE START+3,11*61 120 FOR Z=START+6 TO START+6+192+6 130 IF PEEK(Z)=15 THEN POKE Z,14 140 IF PEEK(Z)=15+64 THEN POKE Z, 14+64:Z=Z+2:REM (SKIP LMS DATA BYTES) 150 NEXT Z 200 REM 210 REM LET OS THINK HERE IN GR.7.. 220 POKE 87,7 390 PRINT "CREATING UPPER HALF IMAGE" 100 YADD=1 110 GOSUB 500 120 PRINT "CREATING LONER HALF IMAGE" 125 YADD=30 130 GOSUB 500 110 STOP 500 REM 530 REM ************************* 510 REM ** FROM CREATIVE COMPUTING.. 515 REM ** GENERATES MULTICOLOR SPIRAL 550 DEG 590 R=10:COLOR 1:C=1 600 X0=79;Y0=17 610 FOR K=0 TO 3:C(K)=K+1*2:NEXT K 620 FOR K=1 TO 3 630 X=X0+R*COS(360):Y=Y0:PLOT X,Y+YADD 610 FOR I=0 TO 5*360 STEP 75 650 X=XO+R*COS(I):Y=YO+R*SIN(I) 660 DRAHTO X,Y+YADD 665 C=C+1:IF C>3 THEN C=1 667 COLOR C 670 NEXT I:R=R+12 680 NEXT K 690 Z8=1 700 RETURN
Many, many people have tried the above routine to get into graphics 7+. All of them have run into this problem. You see. the operating system, while drawing a line, constantly checks to see if the line is going off of the visible area. Should it do so, an ERROR 144 is returned and the line drawing process stops. The OS thinks were in graphics 7 96 × 160), so when we try to draw below line 96, it thinks it is at the bottom of the screen and terminates the draw. In computercse this is known as “bounds checking”—and anyone who has watched football knows what “out of bounds’” means. (See, these computer snob words really do have humble beginnings).
We can’t POKE an 8 into the OS location, because then the draw routine will use the wrong bit shifting routine and we’ll gel all sorts of crazy bit patterns and colors! I Feel free to try it — there are many interesting effects obtainable this way. Just delete the POKE 87,7 in Program 3.) And we cant get by with a POKE 7...because then the OS thinks we’re going out of bounds. Because both bounds checks and draw routine selection are based on the same location, we’re stuck. (The memory location is called DINDEX and is located at 57 hex or 87 decimal).
The problem resides in the extreme care taken to avoid out-of-bounds conditions. If we could draw out of bounds, and have the Atari blindly do the draw instead of telling us we were wrong, then graphics 7+ would work. Even though the operating system might conclude that we were out of our minds and drawing off the bottom edge of the screen, it would continue to draw in the right places for our graphics 7+ to work. (Screen memory, by the way. is 3780 bytes in graphics 7 and 7680 in graphics 7+. Graphics 7+ and graphics 8 use the same memory size.)
Well, the OS routine is in ROM and cannot be modified, short of pulling the chips out and putting new ones in. As I am no hardware expert this solution isn’t acceptable. Besides, if I did, my programs would run only on my machine. However, it did bring to mind an analogy which solved the problem. Character sets are stored in ROM, also, and are unmodifiable. unless they are copied into RAM first. So why not copy the OS draw routine into RAM, zap the bounds check, and use it for graphics 7+?
To make a long story even longer, that’s what I did. The rest of the article describes this process. The first time through. I did it all in Basic, but that was too slow, so 1 recoded the slow parts in 6502 assembler. Those routines I used in the graphics 7+ driver. (They should be usable in any graphics mode; they just ignore all bounds checks. However, the Atari caution extends beyond overprotecting the user: a line drawn out of bounds could go sailing straight through memory reserved for other things. and crash the Atari. Just be careful: don’t try to draw from 1.1 to 3000.6700.)
The final result is three assembly routines. They are fast and efficient and both fit into page 6 in memory (600-700 hex). 256 bytes set off by Atari for a user’s own purposes and left untouched by Atari routines. The first modifies the graphics 8 display list to a graphics 7+. The second copies the OS draw routine into free RAM for modification. I use Basic for the small amount of POKEing that must be done in the OS routine to make it work properly in its new memory location (it involves relocating a few addresses) and to DRAW a line using the OS routine (it just takes arguments from the Basic USR call and feeds them to the draw routine).
To use graphics 7+, one does a graphics 8 call, calls the first USR routine to set up the 7+ display list, calls the second routine to fetch the draw routine in RAM and modify it, and then all is ready. Line draws are made in one of two forms:
X=USR(third routine,X coordinate,Y coordinate,color #) or X=USR(third,X1, Y1,X2,Y2,COLOR)
The first performs a DRAWTO from the old cursor location to the specified X and Y coordinates. The second performs a line draw between the specified points (equivalent to PLOT X1,Y1 : DRAWTO X2,Y2). Both routines perform the draw in the specified color, not the color of the current COLOR statement.
Alas, the OS draw routine is too long to fit into the small page 6. So it must be stored elsewhere in RAM. Finding a free space in RAM isn’t too hard. However, finding a space that is free on everyone’s Atari is pretty hard. Memory sizes range from 8K to 48K (40K with Basic cartridge ). I decided to tailor the routine for my 40K system and let users do relocation as necessary for their own systems. Nowadays there is so much player-missile memory being reserved, charset arrays, and so forth that a general solution is very difficult.
The following is a bit technical but is intended for assembly programmers. The OS routines start at SFCFC and end at SFE44 (inclusive). They are copied to S7CFC through S7E44. Several JMPs inside are relocated back to the RAM routine, making this a non-relocatable routine. (The fact that I am copying it down an even $8000 makes it quite easy to relocate.) It should be simple to do this for other size memories; the calculations are self-documenting in the OS and assembly listings. Just make sure the JMPs are changed to JMP to the point in RAM where the corresponding statement to the ROM statement is. Note that S7E44 is just below the DL/DM in a 40K or 48K (same thing with a Basic cartridge) machine. Hence it is in a relatively “safe” area.
The bounds check is a simple JSR. This is changed to NOP I no-operation) with three NOP codes.
Programs 5, 6, 7, and 8 are listings of four assembly/Basic routines. (The Atari OS listing is copyrighted and doesn’t appear here, but you can easily look up the addresses specified to find where I am copying from yourself.)
Program 5 is the page 6 assembly listing. Program 6 is the assembly program converted to DATA statements. This program is appended to your code to load the assembly routine. Program 7 is the “Sunset” multiple color spiral run in graphics 7+, using an already loaded assembly routine, and provides an example of using graphics 7+ when the routines are loaded. Finally. Program H is an example of using the DATA statements of Program 6 to load and draw a pretty figure using graphics 7+.
Feel free to delete the REM statements: I document the code heavily in order to make it easy to understand, but the documentation isn’t needed in the final copy. (I also break up all hex opcodes for clarity: these could be calculated to save the machine the work each runthrough.i
On using AUTORUN.SYS: This is a handy way for disk users to load these routines. Boot up DOS (2.0S), and run Program 6. Next, go to DOS. Do the binary save (K), from SWX) to $6FF:
AUTORUN.SYS.600.6FF (return) and thereafter when you boot up with that disk, the graphics 7+, routines will be loaded automatically.
Generally DOS and Basic will leave these routines alone once loaded unless you reboot the system or have a particularly nasty crash. Hence, even users without disks may not have to reload the data each program run.
Well, there you have it, graphics 7+. I hope to see more and more use of it! These routines can easily be copied into a AUTORUN.SYS file and automatically loaded along with Basic, or POKEd into memory when needed. Enjoy the world of double resolution graphics 7.
Program 5. 10 ; 20 ; PROGRAM 5 LISTING.. 30 ; 40 ; THREE ASSEMBLY ROUTINES FOR 50 ; PAGE 6: 70 ; 1.CONVERTS DL FROM GR.B - GR7.5. 80 ; 2.COPIER FROM OS ROM TO RAM. 90 ; 3.GR7.+ DRAWTO. FULL SCREEN 0100 ; GR.7 + DRAW ROUTINE. 0110 ; 0120 ; COPYRIGHT 1981 BY DAVID M. SMALL 0130 ; 0140 ; 0150 ; ROUTINE 1: 0160 ; ASSEMBLY ROUTINE TO CONVERT 0170 ; A GR.8 DISPLAY LIST TO A GR 7.+ 0180 ; DISPLAY LIST. 0190 ; CONVERTS ALL 15'S TO 14'S 0200 ; CONVERTS ALL (64+15) TO (64*14) 0210 ; (BUT WILL SKIP LMS DATA BYTES) 0220 ; 0230 ; PLACED IN PAGE 6. 0240 ; 0000 0250 *= $06B0 06B0 68 0260 PLA SATISFY BASIC 0270 ; 06B1 AD3002 0280 LDA 560 06B4 8D9606 0290 STA FETCHL (FETCH STMT) 06B7 8DAC06 0300 STA STOREL (STORE STMT) 0310 ; 06BD 8D9706 0330 STA FETCHH (FETCH STMT) 0350 ; 0370 ; 0380 ; LOOP 202 TIMES. CHANGE 15 TO 0390 ; 15, 79 TO 78, SKIP LMS DATA. 0400 ; 0440 ; 0450 ; IF GR.2 ENCOUNTERED, QUIT -- 0460 ; HAS A TEXT WINDOW. 0470 ; 0500 ; 0550 ; 0590 ; 0660 ; 0690 ; 0693 A200 0360 LDX #0 INIT X 0695 BD3412 0430 LOOP LDA $1234,X GET DL BYTE 0696 0410 FETCHL = *+1 0697 0420 FETCHH = *+2 0698 C942 0480 CMP #66 069E D005 0520 BNE NOT15 0720 ; 0740 ; 0750 ;----------------------------- 0760 ; ROUTINE 2: 0770 ; 0780 ; COPIES O.S. ROM TO RAM (DRAW 0790 ; ROUTINES) TO ALLOW BOUNDS 0800 ; CHECK REMOVAL. 0810 ; 0820 ; COPIES $FCFC TO $FE44 0830 ; TO $7CFC TO $7E44 0840 ; 0850 ; (THIS IS QUITE EASY TO CHANGE 0860 ; TO CUSTOMIZE FOR YOUR ATARI; 0870 ; ON A 40K-48K MACHINE THIS 0880 ; IS RIGHT BELOW THE DL/DM.) 0890 ; 0900 ; (65092-64764=328 0910 ; 328 - 256 = 72 ) 0920 ; 0930 ;-- $FCFC TO $FDFB ($FF BYTES) 1010 ; 1020 ;-- $FDFC TO $FE44 1100 ; 1110 ;----------------------------- 1120 ; ROUTINE 3: 1130 ; 1140 ; THIS ROUTINE IS CALLED FROM 1150 ; BASIC TO PERFORM A DRAWTO 1160 ; FUNCTION IN GR 7.5. THERE ARE 1170 ; TWO POSSIBLE CALLS: 1180 ; 1190 ; D=USR(X1,Y1,X2,Y2,COLOR) 1200 ; D=USR(X2,Y2,COLOR) 1210 ; 1220 ; FIRST HILL DRAW A LINE BETWEEN 1230 ; THE SPECIFIED COORDINATES IN 1240 ; SPECIFIEDCOLOR. SECOND HILL 1250 ; "DRAWTO" FROM OLD LOCATION TO 1260 ; SPECIFIED COORDINATES. 1270 ; 1280 ; THIS ROUTINE REQUIRES THE O.S. 1290 ; DRAW ROUTINE BE COPIED INTO 1300 ; RAM AND MODIFIED. SEE ARTICLE. 1310 ; 005A 1340 OLDROM = $5A FROM Y 0056 1350 COLCRSH= $56 TO X HI 0055 1360 COLCRSL= $55 TO X LO 0054 1370 ROHCRS = $54 TO Y 0057 1380 DINDEX = $57 CURR GR. MODE 02FB 1390 ATACHR = $2FB COLOR DATA 0022 1400 ICCOMZ = $22 CIO DRAW FLAG 1410 ; PULL OFF AND STORE ARCS 1480 ; 6000 855C 1500 STA OLDCOLH 6000 68 1510 PLA GET FROM X LO 6000 855B 1520 STA OLDCOLL 1560 ; 1610 ; 1650 ; 1690 ; 1700 ; SETUP IS DONE. OTHER MISC: 1710 ; 1760 ; 1770 ; CALL DRAW RAM ROUTINE 1780 ; 06FD 4CFC7C 1790 JMP $7CFC O.S...MUST MOD 1800 END
Program 6. 9000 REM LOADER 9010 Z=6*256+8*16 9020 READ Z1 9030 IF Z=-1 THEN RETURN 9040 POKE Z,Z1 9050 Z=Z+1 9060 GOTO 9020 10000 DATA 104,173,48,2,141,150,6,141,172,6,173,49,2,141,151 10010 DATA 6,141,173,6,162,0,189,52,18,201,66,240,29,201,15 10020 DATA 208,5,169,14,76,171,6,201,79,208,2,169,78,157,52 10030 DATA 18,232,201,79,208,2,232,232,224,203,144,220,96,162,0 10040 DATA 104,189,252,252,157,252,124,232,224,0,208,245,162,0,189 10050 DATA 252,253,157,252,125,232,224,75,208,245,96,104,201,3,240 10060 DATA 15,201,5,240,1,96,104,133,92,104,133,91,104,104,133 10070 DATA 90,104,133,86,104,133,85,104,104,133,84,104,104,141,251 10080 DATA 2,169,17,133,34,76,252,124 11000 DATA -1
Program 7. 10 REM PROGRAM -- ASSEMBLY VERSION 15 REM REQUIRES AUTORUN.SYS OR LOAD 20 REM 40 REM DAVE SMALL 50 REM 8K BASIC VERSION 55 REM 56 IF PEEK(1536+128)<>104 THEN PRINT "ASSEMBLY NOT LOADED..":STOP 60 REM DEFINES 61 CONVERT=6*256+8*16:REM $0680 62 COPY=6*256+11*16+10:REM $06BA 63 DRAW=6*256+13*16+6:REM $06D6 65 DIM C(3) 67 REM 70 REM DISPLAY LIST MODS 80 GRAPHICS 8 90 X-USR(CONVERT) 97 REM 20 REM 210 REM LET OS THINK WE'RE IN GR.7.. 220 POKE 87,7 230 REM 300 PRINT "PERFORMING OS COPY." 310 X=USR(COPY) 320 REM RELOCATION 321 POKE (7*4096+13*256+9*16+8),(7*16+14) :REM FD98,FE TO 7E 322 POKE (7*4096+14*256+2*16+6),(7*16+14) :REM FE26,FE TU 7E 323 POKE (7*4096+14*256+4*16+1),(7*16+13):REM FE41,FD TO 7D 324 REM NOP OUT BOUNDS CHECKS 325 L=7*4096+13*256+15*16+6 326 FOR Z=L TO L+2 327 POKE Z,234:REM NOP 328 NEXT Z 350 REM 390 PRINT "CREATING FULLSCREEN IMAGE" 500 REM 530 REM ************************* 510 REM ** FROM CREATIVE COMPUTING.. 545 REM ** GENERATES MULTICOLOR SPIRAL 550 DEG 590 R=20:COLOR 1:C=1 600 X0=79:Y0=B5 610 FOR K=0 TO 3:C(K)=K+1*2:NEXT K 620 FOR K=1 TO 3 630 X=X0+R*COS(360):Y=Y0+R*SIN(360) 636 Z-USR(DRAW,X,Y,X,Y,0):REM (PLOT) 640 FOR I=0 TO 5*360 STEP 75 650 X-X0+R*COS(I):Y=Y0+R*SIN(I) 662 Z=USR(DRAW,X,Y,C):REM (DRAWTO) 665 C=C+1:IF C>3 THEN C=L 670 NEXT I:R=R+20 680 NEXT K 690 Z8=1 700 STOP
Program 8. 10 REM PROGRAM 8 -- DEMOS LOAD THRU 15 REM DATA STATEMENTS. 20 REM 40 REM DAVE SMALL 50 REM 8K BASIC VERSION 54 GOSUB 9000 55 REM 56 IF PEEK(1536+128)<>104 THEN PRINT "ASSEMBLY NOT LOADED..":STOP 60 REM DEFINES 61 CONVERT=6*256+8*16:REM $0680 62 COPY=6*256+11*16+10:REM $06BA 63 DRAW=6*256+13*16+6:REM $06D6 65 DIM C(3) 67 REM 70 REM DISPLAY LIST MODS 80 CRAPHICS 8+16 95 X=USR(CONVERT) 96 GOTO 200 97 REM 200 REM 210 REM LET OS THINK WE'RE IN GR.7.. 220 POKE 87,7 230 REM 300 REM 310 X=USR(COPY) 320 REM RELOCATION 321 POKE (7*4096+13*256+9*16+8), (7*16+14):REM FD98, FE TO 7E 322 POKE (7*4096+14*256+2*16+6), (7*16+14):REM FE26, FE TO 7E 323 POKE (7*4096+14*256+4*16+1), (7*16+13):REM FE41, FD TO 7D 324 REM NOP OUT BOUNDS CHECKS 325 L=7*4096+13*256+15*16+6 326 FOR Z=L TO L+2 327 POKE Z,234: REM NOP 328 NEXT Z 350 REM 390 REM 400 SETCOLOR 0,2,4:REM RED 410 SETCOLOR 1,7,4:REM BLUE 420 SETCOLOR 2,13,4: REM GREEN 500 DEG 505 X2=SIN(0)*70+70:Y2=COS(0)*80+80 507 Z=USR(DRAH,X2,Y2,X2,Y2,0):REM PLOT 508 C=1 510 FOR X=0 TO 360 STEP 4 520 X1=SIN(X*1.5)*70+70 530 Y1=COS(X*2)*80+80 531 X2=SIN(X+120)*40+60 532 Y2=COS(X-40)*50+60 540 Z=USR(DRAM,X1,Y1,X2,Y2,C) 545 C=C+1:IF C<4 THEN C=1 550 NEXT X 560 GOTO 560 9000 REM LOADER 9010 Z=6*256+8*16 9020 READ Z1 9030 IF Z1=-1 THEN RETURN 9040 POKE Z,Z1 9050 Z=Z+1 9060 GOTO 9020 9999 REM DATA FOR GR 7+ DRIVER 10000 DATA 104,173,48,2,141,150,6,141,172,6,173,49,2,141,151 10010 DATA 6,141,173,6,162,0,189,52,18,201,66,240,29,201,15 10020 DATA 208,5,169,14,76,171,6,201,79,208,2,169,78,157,52 10030 DATA 18,232,201,79,208,2,232,232,224,203,144,220,96,162,0 10040 DATA 104,189,252,252,157,252,124,232,224,0,208,245,162,0,189 10050 DATA 252,253,157,252,125,232,224,75,208,245,96,104,201,3,240 10060 DATA 15,201,5,240,1,96,104,133,92,104,133,91,104,104,133 10070 DATA 90,104,133,86,104,133,85,104,104,133,84,104,104,141,251 10080 DATA 2,169,17,133,34,76,252,124 11000 DATA -1
CREATIVE COMPUTING VOL. 8, NO. 4 / APRIL 1982 / PAGE 208
One problem many manufacturers have is in documenting their hardware— especially for beginning programmers. The problem arises because beginners do not have a great deal of knowledge about the machine, and it is very easy to deluge them with unnecessary details and trivia they don’t need just to get started. On the other hand, beginners don’t stay beginners for long, and soon the details and trivia become necessary information.
One approach is to treat the user manual as a manual for a complete beginner. Everything is explained in the simplest possible terms, and if a concept is too difficult to explain, then it is ignored. The result is a fine beginner’s manual that can take the user from the beginning to some point, but cannot continue from there. A user with this sort of documentation is then stuck.
A wonderful example is the Atari Basic Reference Manual. It is written for the beginning Atari user— someone who doesn’t understand the capabilities of the machine. That’s fine; we all started out pretty much at the beginning with the Atari, because it had such revolutionary ideas in its design. But the writers of this manual went too far.
They went to extremes to shield the user from the innards of the machine, and the result was complete confusion in some sections of the manual. For instance, the discussion of COLOR and SETCOLOR is abysmal. I had to work backwards, using the hardware manuals, to understand what they were trying to say in the Basic manual. Many people have commented on this to both Sandy and me. (Player-Missile Graphics were not even mentioned in this manual.)
Then there is the other approach. Tell everything. Heap it on— detail, trivia, useless data, anything, all mixed in with the relevant stuff. If a beginner reads this manual, too bad. An example of this is the Atari hardware manual. What does a beginner know of clock cycles, for instance? Or of Antic DMA? If a reader needs this information, he cannot get it.
Over the last few months (nearly a year now) we’ve been trying to fill this gap. We aim to explain the Atari’s innards to the users who are past the Basic Reference Manual but who are bewildered by the awesome Hardware Manual.
And this month we’re going to look at the Atari Disk.
For those of you who have read and been entertained by the discussion of the Atari disk in the Basic Reference Manual, this article will let you in on what is really going on. It is a ground level look at how the disk works and what the Atari does with it.
The information is quite useful and lets you access the disk more efficiently in many applications, as well as understand how Basic and DOS work with the disk at the lowest level.
This article, believe it or not, presented its authors with a real moral dilemma. Why? The information presented here can be used to copy disks that without this information are uncopyable. (Mind you, this information is also freely available in the Atari O.S. manual, if you can understand it.)
There is a horrendous software piracy problem in this country. Coasider the effect on the record industry if every time a person bought a cassette tape, he made ten cassette copies of it and gave them to his friends. This is exactly what is happening in the computer industry. (Indeed, the record companies have come out strongly against the sales of blank tapes recently and will no longer support ads for those products, for just this reason).
Immediately after a new program appears on the market, it is copied. The copier then distributes copies to friends, trades them for copies of other programs, and so on. And the writer of the software receives no royalties from the copies of his program.
There are ways of making disks uncopyable. This seems like an ideal solution until you realize that a diskette can be destroyed. A phone can ring near it and erase it; a cat can use it for a scratching post (our cat. Atari, tried this trick once), and so on.
If a user is depending on the disk, and it quits working, then he is in trouble. For this reason the practice of “backing up.” or making multiple copies of a disk, was started. Too many users had lost their only copies of badly needed material. It’s a good idea; I keep a minimum of two copies of everything on disk, so if I lose one, I still have what I need. And it has paid off; many times I have had to go to the backup copy when the original died for some reason. I don’t know why, but I seem to lose an amazing number of disk files— error 144, error 164, and so on.
And if a manufacturer has made his disk uncopyable, you can’t back it up. If the disk becomes unusable, you’re out of luck.
The software industry has been debating this problem for ages. The Apple, in particular, has been the subject of controversy, with some manufacturers selling programs written for the express purpose of copying “copy-protected” disks. In their literature they describe how backup copies are necessary, and thereby justify the purchase and use of their programs. But they know, and everyone else knows, that these programs are used to rip off an enormous amount of copy-protected software.
One program in particular, Locksmith. gave me a good laugh. Locksmith is an Apple program written specifically to copy disks that are copy-protected, and has sections to handle all of the latest protection techniques. It has caused a great deal of controversy.
In the Locksmith manual, the writers explain the need for backup copies, how disks can be erased, and so on, and condemn manufacturers for copy-protecting disks for this reason. Then, after going to great lengths to point out that Locksmith is for users to make backup copies of programs, the manual points out that Locksmith cannot make copies of itself.
In other words, they know what’s going on — who’s kidding whom? They even maintain a database on The Source which tells how to copy many of the copy-protected Apple programs using Locksmith.
Justice has been served, and there are now many, many bootleg copies of Locksmith floating around. As Scott Adams might say, “Yoho, and Jolly Roger.”
Well, Atari users are in the same boat; things just haven’t escalated quite that far...yet. The Atari disk is a different animal from the Apple disk. An Apple copy program, for instance, is an incredibly complex machine language construction, as the Apple CPU controls the disk directly.
The Atari is different; a copy program is very simple. And some companies are using the fact that most people don’t know how easy it is to copy an Atari disk to sell copy programs for fairly outrageous amounts. After all, to a user experienced with Apples, the price seems fair.
Frankly, they are a complete ripoff for the price. I do not feel that forty-odd dollars—the cost of a typical Atari disk-cloner program — is a fair price for twenty-odd lines of Basic code.
So much for the copy program makers. Now how about the poor software manufacturer? What do they do, now that I’ve revealed How To Rip Off Atari Disks? Send me letter bombs?
For the manufacturer’s sake, I’ll present a few of the latest techniques in copy protection— which the information presented here will now allow someone to copy. And there is no escalation possible; i.e., you won’t be able to figure out a way to copy disks protected with this scheme. There is no way, using Atari hardware, to write a program to copy these disks-period. In this way, the word on how to make uncopyable disks will be spread, as will the word on how overpriced (for what they are) the Atari disk copy programs are.
Yes, there are some old copy protection schemes, which we’ll discuss, that this information will allow someone to get around. These schemes don’t work against the average pirate’s copy programs and have not for some time; the disk information discussed here is old news to your average copy enthusiast.
I seriously doubt that anyone will be hurt by this information; if you are going to copy protect a disk, then you might as well use the techniques I will present which make it truly uncopyable, rather than the older ones which the copy programs can duplicate with no difficulty. Enough philosophy. Let’s learn about the disk.
Take a disk and look at it. Inside that envelope (sleeve) there is a circular piece of very thin plastic. On that plastic is the same material of which cassette tapes are made: various magnetic substances.
There are 40 “tracks” on the disk. Think of the circular grooves in a record and you’ll get the idea of what a track is. There are 40 concentric circles on the disk and each of these tracks is divided into 18 “sectors.” The division is done by pie-slicing the track into 18 contiguous segments. So we have 40 tracks with 18 sectors per track, or 720 sectors.
Atari disks are set up to hold 128 bytes of data (a byte, for you beginners, is one character) per sector. In other words, there are 720 × 128 bytes of data on an Atari disk, or 92,160 bytes.
To access a given sector of 128 bytes, that sector must be in the visible portion of the disk (the window cut into the disk sleeve), and the read-write head must move in or out until it’s on the right track number. It then reads the sector by examining magnetic fields written to the disk surface.
Please Note that the actual recording surface is the back, not the front, side of the disk. Most people set disks down with the label up, which means the surface that the data is recorded on is being rubbed in the dust and dirt below. Also be very careful not to touch the backside of the disk in the exposed portion.
The Atari talks to the disk over the “serial I/O bus cable.” This is the cable you daisy chain from device to device. Now here’s the secret of the Atari disk: The disk drive is intelligent. It contains a 6507 microprocessor, a little brother to the 6502 in the Atari itself, that is still capable of quite a lot. It also contains 256 bytes of RAM (read-write memory), and 2048 bytes of ROM (read-only-memory). In short, the disk drive has a complete computer of its own. (For you hardware buffs, there are 128 on the PIA-like chip). How is this different, and why is this good? On the Apple, the disk drive is “dumb.” The main computer must tell the disk head to move to here, the disk to spin to there, and tell the head what information to write. This neatly ties the computer up while the disk is running.
Apple has a standard scheme for storing data, a “standard format.” and if you use the Apple routines to read/write data, you’ll stay in that format. Alas, that format allows your disk to be copyable, so people have modified the Apple disk routines to make custom weird formats, that cannot be read by copy programs. (And then other folks have written programs, such as Locksmith, to read “uncopyable disks” and then other weirder formats were developed, etc. It’s a little like the arms race.)
On the Atari, the two computers work with each other. There are a net total of five, count them, five commands that pass between them. Since the 6507 in the disk drive is helping do the work, the Atari’s main processor doesn’t have to fiddle around with controlling the disk, and thus can be doing something else at the same time the disk is running. There are no other commands and the disk drive 6507 will ignore any but the five we’ll discuss.
Best of all, since the Atari disk controller is “off limits” and may not be programmed, as its program is in read-only memory inside the disk and is not modifiable, you cannot develop strange disk formats. There is one. and only one. Atari disk format. Hence well never get into one of these Apple disk escalations, for we cannot control the disk that exactly. Believe me, after viewing the present Apple disk copy mess, we’re not missing much.
An ordinary Atari user accesses the disk through what is known as the File Management System or FMS. The user never sees the lowest level of disk commands (the five mentioned) because FMS handles all that for him. Included in FMS is the ability to split the disk sectors, each 128 bytes long, into files, access the files through the operating system, get disk directories of file names. NOTE. POINT, and so on. FMS works in turn through the Five Commands (perhaps a movie should be made by that title?) with the disk drive 6507 to get your disk processing done.
FMS on disk is called DOS.SYS.
What are the Five Commands?
1. Get Status. This returns the status of the disk and in particular of the IN 1771 floppy disk controller chip inside the disk. “What?” you say. Me too. I don’t use, and have never used. Get Status. One day I may find out what it’s for.
2. Format Disk. This command instructs the disk drive 6507 to lay out the tracks and sectors on the disk, and to “clean off” old data. Think of it as the 6507 laying down record grooves that it can follow later. What actually occurs is that the 6507 writes data across the disk, reads it and makes sure it has stayed the same (this verifies that the disk surface is good), and then writes the sector numbers onto the various sectors of the disk. This information it used later to find a given sector.
3. Get Sector. This command instructs the 6507 to get the entire 128 bytes of a sector and ship them to the Atari through the serial I/O bus cable. The Atari issues the Get Sector command and tells the 6507 what sector number, from 1-720, to fetch. The 6507 then gets busy, spins the disk and positions the read/write head, reads the data, and returns it to the Atari.
4. Put Sector. This command instructs the 6507 to take the 128 bytes about to be shipped down from the Atari and put them onto the sector number specified. The 1 28 bytes are then sent, and the 6507 positions the disk, etc., and writes the data onto it. You probably do not use this command, you use its relative, which is:
5. Put Sector With Verify. Remember, disks are not all that reliable. So when we put a sector onto the disk with this command, it is first written, then immediately re-read and compared with the original 128 bytes. If they match, fine; all is well. If not, then they didn’t record correctly, and an ERROR message results. (In truth. I have never seen this particular ERROR message.)
The Atari’s designers decided to add a little audio to this whole process, so whenever a Get Sector occurs (like during a program LOAD), a pleasant “beep” is heard on the TV’s audio channel. Whenever a Put sector occurs (during a SAVE, for instance), a not-so-pleasant “clunk” is heard. You’ll note that the Put commands always seem to take twice as long as the Get commands: this is because the disk is physically putting, then reading, the information onto the disk for a verify. Hence, it takes twice as long.
In the net time I’ve worked with the Atari, I’ve used Put Sector with no verify once, when I was running OSS’s operating system. They apparently use this command, and it sounds a great deal different than the standard slow “clunk..clunk..” of the Atari save.
Now everything that happens to the Atari disk occurs through these commands. Next month, we’ll take a look at the process.
CREATIVE COMPUTING VOL. 8, NO. 5 / MAY 1982 / PAGE 180
This is Part 2 of the description of Atari disks begun in the April “Outpost: Atari.”
Disk I/O is a very slow process for the Atari. The disk must be physically spun, which takes a while, and data must be shipped back and forth, which is even slower. The idea behind Atari’s DOS is to minimize disk I/O. So we come to the concept of a “buffer.”
In Atari’s DOS, whenever you read or write to a file, you are reading/writing into a 128-byte reserved area in memory called a buffer. You are not writing to the disk at all. The Atari keeps the contents of one of the sectors of the disk in that buffer. So if you read/write to that buffer, the operation occurs at very high speed, which is what we want. For instance:
10 OPEN #1,4,0,"D1:FILE" 20 FOR A=1 TO 10000 30 GET#1,A 40 NEXT A
merely reads, byte by byte, 10000 bytes from disk. But if you run this program, you will note that the disk isn’t being accessed continually; only every once in a while will you hear a beep to indicate another read. What happens is that the Atari opens the file and pulls the first sector full of data into the memory buffer. When you do the first 125 GETs, the bytes are pulled out of that memory buffer. Then you try to read another byte, but the Atari doesn’t have that one in memory yet. So it requests the disk to send it the next 128 bytes, fills the buffer with those 128 bytes, and starts reading at the beginning of the buffer again.
(If you are wondering why I said the 125th byte, it is because the Atari DOS reserves three bytes per sector for its own uses, which we will talk about later.)
Similarly, when you PUT # to a disk file, the Atari lets you PUT 125 bytes to the buffer, then dumps it to the disk, moves in another 125, and so on.
The result of all this confusion is that the Atari doesn’t have to go to disk for every individual byte; rather, it stays in memory for a large number of “disk” accesses, and things run much faster.
When the Atari is LOADing or SAVEing a program, again it uses these buffers. The process is invisible to you, but you can hear the beep as each individual sector in the program is LOADed, or a clunk as a sector is SAVEd. Remember, the Atari can only talk to the disk in terms of complete 128-byte sectors.
Understanding the buffer is important in solving some of the mysterious problems that can occur while using the disk. For instance; let’s say you write something out to the buffer, and then your program bombs. You examine the disk file, and find the data never reached the disk. This is because the buffer was never written to disk. If you didn’t know about the buffer, you’d be wondering why the disk didn’t record what you wrote to it.
The CLOSE statement is provided for this case. It makes sure that everything in the buffer gets to the disk. It also updates the directory, where all file names are listed.
The DOS program handling all this keeps a table of free sectors on the disk, by the way, and when the buffer fills up and a place is needed to store the 128 bytes, a sector number is taken from that table. When a file is deleted, its sectors are returned to that table. (The XXX FREE SECTORS message at the end of the DOS directory is determined by this).
So much for Basic I/O. Everything done with Basic I/O is a version of the above; everything goes through the 128-byte buffer. How about DOS?
When you issue the COPY disk command from DOS, each sector of the file is sent to memory. In other words, DOS copies the contents of that file into memory, 128 bytes at a time. It then takes the file in memory and writes it out to disk, from memory, again in 128 byte chunks.
When you issue a Duplicate Disk command, DOS reads in every sector on the disk that is marked as “used” and stores it in memory. The unused sectors are ignored to save time. DOS then writes those used sectors out to the new disk, in the same position it found them on the old one, and doesn’t worry about the empty sectors. Since there are 92,000 bytes on a disk, and only 48K maximum of memory, it may have to do this in smaller pieces— let’s say 32K at a time. You then must physically change the disk several times on a single-drive system. If you are using a multiple disk system, you will see it do the copy in multiple stages.
Note: If you are copying disks for backups, remove any cartridge; each cartridge selects 8K of RAM and makes for more disk swaps.
In order to know what sectors are used, and what files are on the disk, some tables must be kept on that disk. The DOS reserves certain sectors on the disk for these tables. One is known as the VTOC (Volume Table of Contents) and is sector number 360. In it is a table of all 720 sectors on disk, stored as bit-map; i.e., one bit per sector. The disk directory is stored in sectors 361-368; this is the actual list of the file names and the sectors they occupy. To find a file. DOS must use this directory.
By the way, these reserved sectors explain why only 707 sectors are available on a “clean” disk; the rest are used for the directory tables, etc. You will also hear, during the disk formatting process, right near the end, the clunks as DOS writes out a fresh directory to the disk, after the disk 6507 has finished formatting it.
Remember, DOS at the lowest level, past all of the directory opens. XIO’s. and so forth, is only doing get sectors/put sectors. Let’s learn about those calls.
All get sector/put sector calls rely on a table called the Device Control Block. Data is put into this table, and a jump is made into the operating system, which in turn uses that table. Table 1 is the disk table, starting at $300 (or 768 decimal). One POKEs values into this table, and then does a JSR to DSKINV ($E453). DSKINV then does the requested operation and returns to you. Program 1 is a sample program that does the needed POKEs and requests from you a sector number (1-720) to read.
This program POKEs the DCB parameters, reserves 128 bytes in memory as a string for the buffer area, requests the sector number, then runs a very short assembly program which does a PLA, needed by Basic, then jumps off to DSKINV. DSKINV then does the operation, and returns to Basic.
There the status code placed in the table by DSKINV is printed, and the buffer area, as a string, is also printed. Sure, it will be strange, but you can examine individual bytes easily. If you read one of the directory sectors (try 361) you will see the directory entries.
If an 87 instead of an 82 were POKEd into DCOMND, then a Put Sector would occur ($57=Put Sector, $52=Get Sector). Then the contents of that buffer would be written to disk.
The status code will be a 1 if all goes well. If there is a problem, you may find a 144 as the error code. This Device Not Done Error occurs if the disk is bad, the disk is write protected, etc.
We have just done disk access the same way DOS does it, at the sector level. Note we have not done an OPEN or an XIO; we have directly accessed the disk. This can be handy if you have a need for a disk allocation scheme free of DOS; I use it to store directly fixed-length records. It is fast and efficient, and removes the DOS overhead.
Also, it enables you to access the directory and modify it as necessary; this allows you, for instance, to un-delete files.
Because we are not using DOS, but are still accessing the disk, we are not dependent on the DOS directory or “In-Use-Table.” We can read or write any sector on the disk, regardless of what DOS thinks that sector is for. You may want to take note: This is how to write a “boot record,” a special disk record that enables your disk to boot by itself, as so many games do. The boot record is record 1; see the hardware manual for further details.
Table 1. 0300 DDEVIC —Serial Bus ID. Not used by user. 0301 DUNIT —Disk number. 1-4. 0302 DCOMND —Command Byte. This is: $21 Format Disk $50 Put Sector, without verify $52 Get Sector $53 Get Status $57 Put Sector, with verify 0303 DSTATS —Disk Status. This is returned to you after the operation is done. 0304,0305 DBUFLO.HI. Buffer Address. This is a 16-bit address in memory that is the starting address of where to get or put 1 28 bytes. 0306 DTIMLO Disk Timeout Value. Leave it alone. 0308,0309 DBYTLO.HI Set by handler. Leave it alone. 030A,030B DAUX1.DAUX2 Sector Number. Which disk sector, 1-720. to read/write.
Program 1. 5 REM SAMPLE PROGRAM TO DO DIRECT 6 REM DISK I/O. DAVID SMALL, 12/21/81 7 REM 10 DCB=768:REM START OF DISK DCB 20 POKE DCB+1,1:REM DISK 1 30 POKE DCB+2,82:REM $52 = GET SECTOR 35 REM *** GET 128 BYTE OPEN BUFFER 40 DIM BUFFER$(128) 45 DIM CALL$(10) 50 FOR X=1 TO 128:BUFFER$(X)=" ":NEXT X 60 ADDR=ADR(BUFFER$) 70 ADDRHI=INT(ADDR/256) 80 ADDRLO=ADDR-(ADDRHI*256) 90 POKE DCB+4,ADDRLO:REM BUFFER ADR LOW 100 POKE DCB+5,ADDRHI:REM BUFFER ADR HI 110 REM *** SECTOR NUMBER *** 120 PRINT "INPUT SECTOR NUMBER" 130 INPUT SECTOR 140 SECTORHI=INT(SECTOR/256) 150 SECTORLO=SECTOR-(SECTORHI*256) 160 POKE DCB+10,SECTORLO 170 POKE DCB+11,SECTORHI 200 REM *** BUILD SHORT ASSY PROGRAM 210 REM *** OF PLA, JMP DSKINV. 230 CALL$(1)=CHR$(104):REM PLA 240 CALL$(2)=CHR$(32):REM JSR 250 CALL$(3)=CHR$(83):REM $53 260 CALL$(4)=CHR$(228):REM $E4 270 CALL$(5)=CHR$(96):REM RTS 300 X=USR(ADR(CALL$)) 310 DSTATS=PEEK(DCB+3) 320 PRINT "DISK STATUS=";DSTATS;" (1=0K)" 330 PRINT "DATA:" 340 PRINT BUFFER$ 341 REM *** CLEAN OUT BUFFER$ 342 FOR X=1 TO 128:BUFFER$(X)=" ":NEXT X 350 GOTO 110 400 END
Now that you can access the directory data directly, you can see all the data stored rather than just what OPENing “V” returns. A directory entry is 16 bytes long for each file. There are eight entries per sector in the directory, and eight directory sectors, hence 64 files maximum. See Table 2.
As an example of how the directory is used, if a file is LOCKed from DOS, all that occurs is that its flag byte has bit 5 set to 1.
When you delete a file, all that occurs is that the delete flag on the file is set. Then, next time DOS needs a place to put a new file entry, it knows it can overwrite the current entry.
In order to read the data in this file, one goes to the Starting Sector number found in the directory. Each sector contains information as shown in Table 3.
The “forward pointer” is where the next sector of the file can be found. It is a sector number from 1 to 720. When that next sector is read in, it in turn tells where the next sector can be found, and so on. This is called a “linked list” or chained sector scheme. This way, files don’t have to be in any particular order on the disk (e.g., running continuously from sector 30 to 40). The sectors can jump around all over the disk, yet to DOS they are still linked together.
The file number is the file number in the directory. It is set to the same number as the entry number in the directory for all sectors. This is a safety measure. Let’s say we are reading directory entry 6. and are going along, sector by sector. In the file number position in a given sector, we suddenly find a 13 (or whatever) instead of the 6 that should be there.
We know that the data for this sector has gotten scrambled, and the sector chain terminates there. This is an ERROR 164, which I am sure you have seen before; it is a warning that the data in this sector are likely to be bad. The sector link is also likely to be bad, so DOS normally stops an ERROR 164.
Reading in sectors one at a time, by getting the next sector number, reading, and so on, is called “sector tracing.” Atari DOS does it every time it reads in a file. Atari also sells a “disk Fix” program through their program exchange which uses the above information; you now know enough to use it. For instance, the forward “link” of a given section may be modified if desired.
We can do the same sector tracing out of Basic. We will find a given directory entry, read it in starting at the sector number given by the directory and proceed through each sector, with each new sector number obtained from the data in the previous one, until we have read in the number of sectors specified in the directory. Should anything be wrong (file number, etc.) we will know the file has gone bad.
Program 2 illustrates first how to read in the directory and interpret it, and second how to follow a sector chain for a given file. It reads in the directory, lists it to the screen, and asks which file to trace; if A is entered, all files will be traced (this takes a while). It will then trace the file through, stopping at any “broken links” or bad file numbers. It is an excellent way to check a disk which has some files going bad, and find out which ones are still readable and which aren’t. After each check the program produces a directory listing showing which files are good, bad, or still unknown.
The techniques used within the program will probably prove more useful than the program; however, remember that this is an example. It can serve as the basis for custom disk inspect/modify routines if you wish to write them. Also, the program is written in Microsoft Basic but translating it to the old Basic should be no problem at all. I highly recommend Microsoft Basic in terms of speed and features as compared to the old Basic; an in-depth review of the Atari version of Microsoft Basic will appear in an upcoming issue.
Sadly, the software pirate community also found out about direct disk I/O, literally years ago. Back then manufacturers were copy protecting disks by fouling up the directory and sector maps so that DOS couldn’t perform the copy. With the advent of direct disk I/O, all these schemes were bypassed with what is known as a “sector copier.”
As a side note, a sector copier is sometimes advertised as a “nibble copier” or “byte copier.” This is an Apple term, and refers to individual bytes being read off the disk. It is completely inaccurate when applied to the Atari; all Atari disk I/O is in 128-byte blocks.
A sector copier, as you have guessed, just issues a read of all the possible sectors, then writes them.
The program is simple to write now that you understand about sector I/O and how to call up DSKINV. It is just a matter of reading in 720 sectors and writing out 720 sectors. As I said, about 20 lines of Basic code are required. And now you understand why, as I mentioned last month, selling such a program, at the prices currently being charged, is such a ripoff.
Table 2. Byte 1: Flag byte. Bit 7 = 1 if this file has been deleted Bit 6 = 1 if this file is in use Bit 5 = 1 if this file is locked Bit 0 = 1 if this file is OPEN. Bytes 2,3. Sector Count; the number of sectors in the file, stored low, then high bytes. Bytes 4,5. Starting Sector. Where the file begins (what sector number). Bytes 6-16. File name. Last three bytes are the extension if you add one, otherwise they are blanks.
Table 3. Byte 1 .. Data Byte 125.. Byte 126 File Number (6 bits) and high two bits of "forward pointer" Byte 127 Forward Pointer Byte 128 Short Sector count .. indicates this sector not completely full.
But...how can a disk be protected against this sort of thing? Fortunately, there is a good way. Several software manufacturers hit on the same idea at the same time: bad sectoring. Let’s assume we have a special disk, with some sectors on it that have never been formatted, as with the FORMAT DISK command. Most of them are OK; just a few are bad, as if there were holes in the disk. Now when the disk is told to read these sectors, it can’t find them, for they were never formatted. So it returns an ERROR 144, instead of a normal return (1). Then, in the software on the disk, that sector is called, and if an ERROR 144 doesn’t result, the program quits.
Let’s say the program is then copied to another disk by an average sector copier. The “bad” spots on the disks will not copy; they will return ERROR 144, but on the destination disk, there will still be formatting information on those sectors. This is because the average Atari user cannot create a disk with bad spots in it; the FORMAT command is handled completely inside the disk by the disk 6507 microprocessor. The program will find that where it expected a bad sector, it now finds a good sector. Hence the program knows it is not residing on the original disk, and can quit.
The only way to defeat this scheme is to disassemble code and remove the sector check, and even if the author is slightly clever, it will take so long to find the sector checking routine that the program will be outdated by the time it is finally made copyable. Besides, consider what a person’s time is worth compared to the cost of a program; if it takes two weeks to break a copy protection scheme, isn’t it a better idea just to buy the program?
This bad-sectoring scheme works quite well in preventing a sector copier from being useful. Sure, a copy of the disk may be made, but without the bad spots on the disk, it will never run. And your average user cannot create these bad spots, for only access to the disk controller program allows that, and only very advanced users can accomplish this.
Atari currently uses this bad sector scheme in several of their disk-based programs. Jawbreakers uses the same scheme (hence the disk retry, or “snaaark,” sound when you first boot it up). The Wizard and The Princess use it also. In other words, the move is toward this sort of protection.
Software manufacturers can probably figure out a way to write some bad sectors onto a disk. For instance, what popular personal computer gives you complete control over the disk read/write process? There are other ways, too.
Another manufacturer doesn’t bother copy protecting his disks at all. However, a small module must be plugged into the front joystick port before the program will run. The module probably contains some sort of ROM-type circuit which is then read by the program through the PIA chip (joystick ports).
Well, we have covered a great deal, from piracy philosophy to sector chaining in these two columns. 1 hope you have enjoyed it and have learned something about the Atari disk, and how it really works. I also hope I have described some effective protection schemes for software manufacturers.
Direct disk I/O is a very powerful tool for Atari users; I hope you will use it to make your programs faster and more efficient.
Program 2. 10 REM DISK CHECKER - DAVE SMALL 20 REM 30 GOTO 290 40 REM SUBROUTINES PLACED IN FRONT 50 REM FOR SPEED. NO COMMENTING. 60 REM 70 REM DISK READ SUBROUTINE 80 POKE DCB+1,DFROM 90 POKE DCB+2,82 100 BHI=INT(BUFF/256):BLO=BUFF-(BHI*256) 110 POKE DCB+4,BLO 120 POKE DCB+5,BHI 130 SHI=INT(RSECTOR/256):SLO=RSECTOR-(SHI*256) 140 POKE DCB+10,SLO:POKE DCB+11,SHI 150 X=USR(CALL) 160 DSTATS=PEEK(DCB+3) 170 RETURN 180 REM DISK WRITE SUBROUTINE-(SAMPLE) 190 POKE DCB+1,DT0 200 POKE DCB+2,87 210 BHI=INT(BUFF/256):BLO=BUFF-(BHI*256) 220 POKE DCB+4,BLO 230 POKE DCB+5,BHI 240 SHI=INT(RSECTOR/256):SLO=RSECTOR-(SHI*256) 250 POKE DCB+10,SLO:POKE DCB+11,SHI 260 PRINT "ERROR":GRAPHICS 0 270 DSTATS=PEEK(DCB+3) 280 RETURN 290 REM DISK CHECKER. 300 REM DOES SECTOR TRACE OF ALL 310 REM FILES IN THE DIRECTORY. 320 REM PRODUCES LISTING HITH OK/ 330 REM BAD. 340 REM ASSUMES 48K, MICROSOFT. 350 REM 360 REM GET DISK NUMBER, WELCOME.--- 370 GRAPHICS 0 380 CLEAR 390 PRINT "WELCOME TO SMALL'S DISK CHECKER." 400 PRINT "INPUT DRIVE NUMBER"; 410 INPUT DF$ 420 IF DF$="" THEN DFROM=1:GOTO 440 430 DFP0M=VAL(DF$) 440 DTO-DFROM 450 CALL=&E453 !DSKINV ADDRESS 460 REM NOTE: MICROSOFT CAN CALL 470 REM DSKINV$ DIRECTLY, NO PLA 460 REM NEEDED. 470 DCB=&300 500 OPTION RESERVE 20*128 510 S=VARPTR(RESERVE) 520 IF B<0 THEN B=B+65536 530 REM FIRST, READ IN DIRECTORY---- 540 PRINT "GETTING DIRECTORY." 550 INCR=0 560 FOR RSECTOR=360 TO 368 570 BUFF=B+(128*INCR) !INPUT AREA 580 GOSUB 70 !GET SECTOR 590 IF DSTATS=1 THEN 630
CREATIVE COMPUTING VOL. 8, NO. 6 / JUNE 1982 / PAGE 198
LOGO 1 TRAP 80 2 DIM A$(30),SINE(450) 3 GOSUB 30000 4 DEG 10 GRAPHICS 10 15 FOR I=1 TO 8:READ A:POKE 704+I,I*16+6:NEXT I 20 COLR=1:Y=1 30 FOR X=10 TO 69 40 COLOR COLR 50 PLOT X,141-Y:DRAWTO X,191-Y 52 PLOT 79-X,141-Y:DRAWTO 79-X,191-Y 54 FOR Q=36 TO 43 55 PLOT Q,191-Y:DRAWTO Q,141-Y 56 NEXT Q 60 Y=Y*1.23 65 COLR=COLR+1:IF COLR>8 THEN COLR=1 70 NEXT X 80 X=USR(ADR(A$)) 90 FOR J=1 TO 12:NEXT J 100 GOTO 80 1000 DATA 2,4,6,8,6,4,2,2 30000 REM *** SET UP ASSY PROGRAM 30010 RESTORE 31000 30020 FOR Z=1 TO 27 30030 READ X:A$(Z)=CHR$(X) 30040 NEXT Z 30050 RESTORE 30060 RETURN 31000 DATA 104,162,0,172,193,2,189,194,2,157,193,2,232,224,8,144,245,140,200 31010 DATA 2,96,65,65,65,65,65,65
MELONS 2 DIM A$(30),SINE(480) 3 GOSUB 30000 4 DEG 9 FOR I=0 TO 90:? I:A=SIN(I):SINE(I)=A:SINE(180-I)=A:SINE(180+I)=-A:SINE(360-I)=-A:SINE(360+I)=A:NEXT I 10 GRAPHICS 10 15 RESTORE :FOR I=1 TO 8:READ A:POKE 704+I,A:NEXT I 18 FOR P=1 TO 2 20 Q=1 25 A=30 30 FOR ANG=180 TO 270 STEP 8 40 X=20*SINE(ANG+90)+25 50 Y=A*SINE(ANG) 55 Z=X:IF P=2 THEN Z=79-X 60 COLOR Q 65 IF ANG=180 THEN OLDX=Z:OLDY=Y 70 PLOT OLDX,96+OLDY 75 DRAWTO Z,96+Y 77 OLDX=Z:OLDY=Y 80 REM 90 NEXT ANG 95 Q=Q+1:IF Q>7 THEN Q=1 100 A=A-1 110 IF A>-30 THEN 30 200 FOR ANG=0 TO 180 STEP 10 210 COLOR 8 220 X=4*SINE(ANG+90)+25 225 Z=X:IF P=2 THEN Z=79-X 230 Y=30*SINE(ANG) 240 PLOT Z,96+Y 250 DRAWTO Z,96-Y 260 NEXT ANG 300 FOR I=1 TO 25 310 X=RND(0)*6+23 315 Z=X:IF P=2 THEN Z=79-X 320 Y=RND(0)*50+71 330 COLOR 0 340 PLOT Z,Y 350 NEXT I 400 NEXT P 900 REM X=USR(ADR(A$)) 910 FOR J=1 TO 10:NEXT J 920 GO TO 900 1000 DATA 226,228,230,232,230,228,226,70 30000 REM *** SET UP ASSY PROGRAM 30010 RESTORE 31000 30020 FOR Z=1 TO 27 30030 READ X:A$(Z)=CHR$(X) 30040 NEXT Z 30050 RESTORE 30060 RETURN 31000 DATA 104,162,0,172,193,2,189,194,2,157,193,2,232,224,8,144,245,140,200 31010 DATA 2,96,65,65,65,65,65,65
HYPNO 2 DIM A$(30) 3 GOSUB 30000 10 GRAPHICS 10 15 FOR I=1 TO 8:POKE 704+I,(I-1)*32+22:NEXT I 20 Q=1 30 FOR Y=0 TO 191 40 COLOR Q 50 PLOT 0,Y 60 DRAWTO 79,191-Y 70 Q=Q+0.416666666:IF Q>8 THEN Q=1 75 REM FOR T=1 TO 100:NEXT T 80 NEXT Y 120 Q=1 130 FOR X=79 TO 0 STEP -1 140 COLOR Q 150 PLOT X,0 160 DRAWTO 79-X,191 170 Q=Q+1:IF Q>8 THEN Q=1 180 NEXT X 190 REM COLOR 0:PLOT 0,0:DRAWTO 79,191:PLOT 79,0:DRAWTO 0,191 200 X=USR(ADR(A$)) 210 FOR J=1 TO 4:NEXT J 220 GOTO 200 30000 REM *** SET UP ASSY PROGRAM 30010 RESTORE 31000 30020 FOR Z=1 TO 27 30030 READ X:A$(Z)=CHR$(X) 30040 NEXT Z 30050 RESTORE 30060 RETURN 31000 DATA 104,162,0,172,193,2,189,194,2,157,193,2,232,224,8,144,245,140,200 31010 DATA 2,96,65,65,65,65,54,65
ESCAPE 2 DIM A$(30) 3 GOSUB 30000 10 GRAPHICS 10 15 FOR I=1 TO 8:READ A:POKE 704+I,A+224:NEXT I 17 Q=1 20 FOR I=0 TO 38 40 COLOR Q 42 X=1 45 Y=I*2 50 PLOT X,Y 60 DRAWTO 79-X,Y:PLOT X,Y+1:DRAWTO 79-X,Y+1 62 DRAWTO 79-X,190-Y 64 DRAWTO X,190-Y:PLOT 79-X,190-Y+1:DRAWTO X,190-Y+1 66 DRAWTO X,Y 70 Q=Q+1:IF Q>8 THEN Q=1 80 NEXT I 100 X=USR(ADR(A$)) 110 FOR J=1 TO 24:NEXT J 120 GOTO 100 1000 DATA 2,4,6,8,6,4,2,2 30000 REM *** SET UP ASSI PROGRAM 30010 RESTORE 31000 30020 FOR Z=1 TO 27 30030 READ X:A$(Z)=CHR$(X) 30040 NEXT Z 30050 RESTORE 30060 RETURN 31000 DATA 104,162,0,172,193,2,189,194,2,157,193,2,232,224,8,144,245,140,200 31010 DATA 2,96,65,65,65,65,65,65
ROLL 5 DEG 10 GRAPHICS 10 15 FOR I=0 TO 7:POKE 705+I,128+2:NEXT I 17 POKE 705,136 20 FOR ANG=180 TO 360+180 STEP 6 30 X=8+8*COS(ANG) 40 Y=16+8*SIN(ANG) 50 COLOR (ANG-180)/45+1:PLOT X,Y 60 DRAWTO X,50+Y 70 COLOR 0:PLOT X,Y 90 NEXT ANG 120 FOR ANG=180 TO 360+180 STEP 6 130 X=26+8*COS(ANG) 140 Y=16+8*SIN(ANG) 150 COLOR 9-(ANG-180)/45:PLOT X,Y 160 DRAWTO X,50+Y 170 COLOR 0:PLOT X,Y 190 NEXT ANG 220 FOR ANG=180 TO 360+180 STEP 6 230 X=44+8*COS(ANG) 240 Y=16+8*SIN(ANG) 250 COLOR (ANG-180)/45+1:PLOT X,Y 260 DRAWTO X,50+Y 270 COLOR 0:PLOT X,Y 290 NEXT ANG 320 FOR ANG=180 TO 360+180 STEP 6 330 X=62+8*COS(ANG) 340 Y=16+8*SIN(ANG) 350 COLOR 9-(ANG-180)/45:PLOT X,Y 360 DRAWTO X,50+Y 370 COLOR 0:PLOT X,Y 390 NEXT ANG 410 GO TO 500 420 FOR ANG=180 TO 360+180 STEP 6 430 X=50+8*COS(ANG) 440 Y=16+8*SIN(ANG) 450 COLOR (ANG-180)/45+1:PLOT X,Y 460 DRAWTO X,SO+Y 470 COLOR 0:PLOT X,Y 490 NEXT ANG 500 A=PEEK(705) 510 FOR I=705 TO 711 520 POKE I,PEEK(I+1) 530 NEXT I 540 POKE 712,A 550 GO TO 500
SAS 2 DIM A$(30),SINE(450) 3 GOSUB 30000 4 DEG 8 ? "STAND BY" 9 FOR I=0 TO 90:? I:A=SIN(I):SINE(I)=A:SINE(180-I)=A:SINE(I+180)=-A:SINE(360-I)=-A:SINE(I+360)=A:NEXT I 10 GRAPHICS 10 15 RESTORE :FOR I=1 TO 8:READ A:POKE 704+I,A+224:NEXT I 19 C=1 20 FOR ANG=0 TO 359 30 X=40+30*SINE(ANG+90) 40 Y=96+80*SINE(ANG) 50 COLOR INT(C) 60 PLOT 65,96 70 DRAWTO X,Y 75 PLOT 65,95 77 DRAWTO X,Y-1 78 PLOT 65,94 79 DRAWTO X,Y-2 80 Q=USR(ADR(A$)) 85 C=C+0.5:IF C>=9 THEN C=1 90 NEXT ANG 900 Q=USR(ADR(A$)) 910 FOR I=1 TO 14:NEXT I 920 GO TO 900 1000 DATA 2,4,6,8,6,4,2,2 30000 REM *** SET UP ASSY PROGRAM 30010 RESTORE 31000 30020 FOR Z=1 TO 27 30030 READ X:A$(Z)=CHR$(X) 30040 NEXT Z 30050 RESTORE 30060 RETURN 31000 DATA 104,162,0,172,193,2,189,194,2,157,193,2,232,224,8,144,245,140,200 31010 DATA 2,96,65,65,65,65,65,65
BRASS 10 GRAPHICS 9 15 SETCOLOR 4,15,0 20 FOR Y=55 TO 0 STEP -10 30 FOR X=0 TO 24 40 C=X:IF X>11 THEN C=24-X 45 C=C+3 50 Z=Y+(X) 55 D=INT(SQR(144-(X-12)*(X-12)))/2 57 COLOR 15-C 58 PLOT Z,Y+7-D 60 DRAWTO Z,Y+7+D 70 COLOR C 80 DRAWTO Z,180-Y+D 180 NEXT X 190 NEXT Y 200 GO TO 200
WHIRL 2 DIM A$(30),SINE(450) 3 GOSUB 30000 4 DEG 8 ? "STAND BY" 9 FOR I=0 TO 90:? I:A=SIN(I):SINE(I)=A:SINE(180-I)=A:SINE(I+180)=-A:SINE(360-I)=-A:SINE(I+360)=A:NEXT I 10 GRAPHICS 10 15 RESTORE S:FOR I=1 TO 8:READ A:POKE 704+I,A+224:NEXT I 17 GOSUB 2000 20 FOR ANG=0 TO 359 STEP 2 25 Q=8 30 X=20*SINE(ANG+90)+40 40 Y=20*SINE(ANG)+96 42 COLOR 0:PLOT X,Y:IF ANG<180 THEN 90 43 AS=0 45 FOR W=1 TO 45 50 LOCATE X,Y+W,QW:IF QW=0 THEN AS=1 55 IF AS=1 THEN 80 57 COLOR Q 60 PLOT X,Y+W 70 Q=Q-1:IF Q<1 THEN Q=3 80 NEXT W 90 NEXT ANG 95 Z=20:U=20 175 Q=Q+1:IF Q>8 THEN Q=1 900 X=USR(ADR(A$)) 910 FOR I=1 TO S:NEXT I 920 GO TO 900 1000 DATA 2,4,6,8,6,4,2,2 2000 REM THIS IS THE HEART OF DIZZY 2020 Q=1 2030 FOR Y=0 TO 191 2040 COLOR Q 2050 PLOT 0,Y 2060 DRAWTO 79,191-Y 2070 Q=Q+0.416666666:IF Q>8 THEN Q=1 2080 NEXT Y 2130 FOR X=79 TO STEP -1 2140 COLOR Q 2150 PLOT X,0 2160 DRAWTO 79-X,191 2170 Q=Q+1:IF Q>8 THEN Q=1 2180 NEXT X 2230 RETURN 30000 REM *** SET UP ASSY PROGRAM 30010 RESTORE 31000 30020 FOR Z=1 TO 27 30030 READ X:A$(Z)=CHR$(X) 30040 NEXT Z 30050 RESTORE 30060 RETURN 31000 DATA 104,162,0,172,193,2,189,194,2,157,193,2,232,224,8,144,245,140,200 31010 DATA 2,96,65,65,65,65,65,65
RING 100 REM GTIA TEST 110 DIM C(22,2) 115 GRAPHICS 10:FOR Z=704 TO 712:READ R:POKE Z,R:NEXT Z 116 DATA 0,26,42,58,74,30,106,122,138,154 118 LIM=22:T2=3.14159*2/LIM 120 GOSUB 2500:FOR V=1 TO LIM:T=T+T2:GOSUB 2500:NEXT V 200 GOTO 1000 400 FOR X=1 TO 8:Z=PEEK(704+X):Z=Z+16:IF Z>255 THEN Z=26 420 POKE 704+X,Z:NEXT X:POKE 77,0:GOTO 400 1000 REM 1010 FOR R=1 TO 8:T6=R 1020 GOSUB 1520:NEXT R 1110 FOR R=9 TO 15:T6=16-R 1120 GOSUB 1520:NEXT R 1210 FOR R=16 TO 23:T6=R-15 1220 GOSUB 1520:NEXT R 1310 FOR R=24 TO 30:T6=31-R 1320 GOSUB 1520:NEXT R 1400 IF T3=1 THEN GOTO 400 1410 T3=1:GOTO 1010 1520 COLOR T6:V=0:GOSUB 2000:PLOT X,Y:FOR V=1 TO LIM:T=T+T2:GOSUB 2000:GOSUB 3000:DRAWTO X,Y:NEXT V:RETURN 2000 X=(30-R)*C(V,1)+40:Y=(60-R)*C(V,2)+80:RETURN 2500 C(V,1)=SIN(T):C(V,2)=COS(T):RETURN 3000 IF T3=1 THEN IF (R=1 AND V>11) OR R>1 THEN POSITION X,Y:POKE 765,T6:XIO 18,#6,0,0,"S:" 3010 RETURN
RAINBOW 100 REM GTIA TEST 115 GRAPHICS 10:FOR Z=704 TO 712:READ R:POKE Z,R:NEXT Z 116 DATA 0,26,42,58,74,90,106,122,138,154 130 FOR X=1 TO 8:COLOR X:POKE 765,X 140 PLOT X*4+5,0:DRAWTO X*4+5,159:PLOT X*4+1,159:POSITION X*4+1,0:XIO 18,#6,0,0,"S:" 150 NEXT X 230 FOR X=8 TO 15:COLOR 16-X:POKE 765,16-X 240 PLOT X*4+5,0:DRAWTO X*4+5,159:PLOT X*4+1,159:POSITION X*4+1,0:XIO 18,#6,0,0,"S:" 250 NEXT X 300 COLOR 0:PLOT 65,159:DRAWTO 0,159 400 FOR X=1 TO 8:Z=PEEK(704+X):Z=Z+16:IF Z>255 THEN Z=26 420 POKE 704+X,Z:NEXT X:FOR Y=1 TO 5:NEXT Y:GOTO 400
BALL 100 REM GTIA TEST 115 DIM C(8):GRAPHICS 10:FOR Z=704 TO 712:READ R:R=R*16+8:C(Z-704)=R:POKE Z,R:NEXT Z 116 DATA -.5,1,3,4,5,7,9,12,13 118 LIM=22:T2=3.14153*2/LIM:COL=3:E1=1:DIM D(LIM,2) 120 GOSUB 1500:FOR V=1 TO LIM:T=T+T2:GOSUB 1500:NEXT V 400 GOTO 1000 490 REG=705 500 FOR X=1 TO 8:POKE REG,C(X):REG=REG+1:IF REG>712 THEN REG=705 510 NEXT X:REG=REG+1:IF REG>712 THEN REG=705 520 POKE 77,0:GOTO 500 1000 REM 1005 FOR E=1 TO 10:E2=INT(E/2-0.5) 1010 FOR R=E1 TO E1+E2:CR=8-COL:IF CR=0 THEN CR=8 1015 V=0:COLOR CR:GOSUB 2000:PLOT X,Y 1020 FOR V=1 TO LIM:T=T+T2:GOSUB 2000:DRAWTO X,Y:IF V>=LIM/2 THEN COLOR COL 1025 NEXT V:NEXT R:COL=COL+1:IF COL=9 THEN COL=1 1030 E1=E1+INT(E/2+0.5):NEXT E 1200 GOTO 490 1500 D(V,1)=SIN(T):D(V,2)=COS(T):RETURN 2000 X=(30-R)*0.6*D(V,1)+40:Y=60*D(V,2)+80:RETURN
CREATIVE COMPUTING VOL. 8, NO. 7 / JULY 1982 / PAGE 188
For this month’s column, a variety of interesting things, including some coverage of the recent West Coast Computer Faire (edited for Atari-interested readers), program listings, interesting news from the mail box, language reviews, and so Forth.
The 7th West Coast Computer Faire was held March 19-22 at the San Francisco Civic Center (in San Francisco, CA, naturally). It was quite a show. Being as near as it was to the various Atari offices in the southern Bay area, it attracted many Atari employees. A large number of software and hardware houses were also there to show off their Atari products.
There was some exciting new hardware demonstrated, such as the SOcolumn video output board from Bit-3 and the PROMmer package from MFC, and also some old friends, such as the RAMDisk from Axlon.
Of course, there was a large variety of software also, which ranged from the new Apple Panic for the Atari to the nth version of Protector from Synapse. We’ll be reviewing many of these products in future issues. I am especially interested in the 80-column word processor that UK is writing specially for Bit-3.
Some of the exhibitors had really classy booths. Scott Adams of Adventure International showed up with a complete castle, and ran business from within. Sirius had what looked like a coin-op arcade game set up with an Apple inside, and On-Line and Creative Computing had a large number of games set up to play. (John Harris was showing off his new “Frogger,” for instance).
I had a fine time, and talked with lots of people. One thing that consistently came out when talking to software houses (Sirius, Creative Computing, Synapse, Adventure International, Datasoft, Gebelli, etc.— the list gets longer every day) was the great interest in Atari software. If you have written some decent software, particularly a game, be sure to let a software house see it: it may be worth your while.
Now, let’s turn to our mail box. We have been a bit negligent in answering letters. There is a reason for this: our new son, Eric, was born in January. Those of you who know about newborns know exactly how much spare time we had for a while there. But we are learning to manage, and things are slowly returning to a new kind of normal.
Listing 1. WHEELS 5 REM WHEELES WITHIN WHEELS BY D. HOLCOMB 10 GRAPHICS 23:Y=INT(RND(0)*16):FOR X=708 TO 711:POKE X,Y*16+12:NEXT X:COLOR I:DEG 20 FOR X=1 TO RND(0)*4+2:A=INT(RND(0)*5)*1000+2000:POKE 77,0 30 B=(INT(RND(0)*11)*INT(RND(0)*5)^2-79)*INT((RND(0)*2)-1)/(A/1500)+79 35 C=(INT(RND(0)*4)*INT(RND(0)*5)^2-47)*INT((RND(0)*2)-1)/(A/1500)+47 40 D=0:E=INT(RND(0)*3)-1:IF E*0 THEN 40 50 FOR Y=0 TO A STEP 15:F=F+E:IF F<1 THEN F=3 60 IF F>3 THEN F=1 70 COLOR F:D=D+0.08:DRAWTO B+D*COS(Y),C+D*SIN(Y) 80 NEXT Y:NEXT X 90 FOR Z=0 TO 9 100 A=RND(0)*16:B=RND(0)*9+4:C=RND(0)*30+10 110 FOR X=0 TO 1500/C 120 FOR Y=0 TO 2:SETCOLOR Y,A,B:FOR F=0 TO C:NEXT F 130 SETCOLOR Y,0,0:NEXT Y:NEXT X:NEXT Z:GOTO 10
Opening the mailbox has become a bit like Christmas, with users sending in their latest code and accomplishments, plus new product announcements. Here’s some of the best we have seen; there will be more next month.
Drew Holcomb sends a very nice graphics demonstration (Listing 1) which is worth the five minutes it takes to type in.
Thomas Marshall (those of you on the CERL PLATO network system know him as marshall/phystemp) sends in the fine program in Listing 2 which uses the DL1 routine from the December column. It puts a 128-color menu onscreen, then allows the user to move a cursor around the colors. When the user settles on a color and presses the button, the decimal value of the color (for use in SETCOLOR I appears in players on the top and bottom of the screen. There are some very nice techniques being used here; the program deserves a good look. Thanks Tom.
Dennis Baer (868 Main St., Farmingdale. NY 11735) has Algol for the Atari. According to his letter, it supports all I/O and graphics also. He also has a word processor for the Atari written in Algol. Since there are quite a few folks familiar with Algol, you might want to get in touch. He mentioned he is interested in beta-testing his product.
The Young People’s LOGO Association wants to hear from people interested in Atari Pilot. Contact them at 1 208 Hillsdale Dr., Richardson, TX 75081. They have a very good newsletter and a great deal of interest in the Logo language.
Finally, Nigel Haslock in Switzerland wrote to give me details of the European Ataris. Software houses may be quite interested in this information. He writes:
I have also received a great deal of mail concerning piracy and disk copy protection, which Nigel mentions. He tells of not being able to fix US-version Atari programs to work on the European Ataris because of the copy-locks placed on them. He has a good point.
There is a European market looking for software. Besides the obvious language problems, software houses have another worry — will their software work as it is with a PAL TV?
Atari has provided a hardware location to determine if a given machine is PAL (European) or NTSC (North American); it looks as if it’s time to start writing software to check it.
For those of you with new Ataris, here is a short and highly opinionated discussion of the various languages available for your use. It may serve to clear up some of the confusion you may have over which language is best for you to buy and use. Doubtless, there will be those who will disagree with me; feel free to write and let me know if you do.
Atari Basic, in the 8K cartridge is the original language for this system, developed in a great hurry for the unveiling of the new Atari machines back in 1978. Like most things done in haste, it lacks something. In this case, speed and the fixing of obvious bugs were neglected to the point where the whole product was compromised.
Listing 2. COLOR128 19000 REM The following subroutine can 19001 REN be added to program 5 of 19002 REM ATARI OUTPOST in the December 19003 REM issue of Creative Conputing. 19004 REM It addes utility to displaying 19005 REM the 128 colors available to 19006 REM the Atari. By plugging a 19007 REM joystick in port 1, the sub- 19008 REM routine will give you the 19009 REM specific nunber one needs to 19010 REM poke in the color registers. 19011 REM 19020 REM POKE 708,XXX COLOR 0 19021 REM POKE 709,XXX COLOR 1 19022 REM POKE 710,XXX COLOR 2 19023 REM POKE 711,XXX COLOR 3 19021 REM POKE 712,XXX COLOR 4 19025 REM 19030 REM In program 5, besure to add 19031 REM 410 GOTO 20000 19032 REM 20000 X=105:Y=8 20010 A=PEEK(1061)-21:POKE 51279,A:PMBASE=256*A 20020 POKE 559,46:REM DOUBLE LINE RES. 20021 POKE 623,1:REM PLAYFIELD OVER PLAYER PRIORITY 20022 POKE 53277,3:REM TURN ON PM GR. 20030 FOR III=PMBASE+384 TO PMBASE+1024:POKE III,0:NEXT III:REM CLEAR P-M GR.... 20010 POKE 53218,X:REM PL 0 POSITION 20011 POKE 53219,X+16:REM PL 1 POSITION 20012 POKE 53250,X+32:REM PL 2 POSITION 20013 POKE 53251,X-32:REM PL 3 POSITION 20011 POKE 53252,X+18:REM MI 0 POSITION 20015 POKE 53253,X+56:RFH MI 1 POSITION 20016 POKE 53251,X+64:REM MI 2 POSITION 20017 POKE 53255,X+72:REM MI 3 POSITION 20050 POKE 701,53:REM PL COLOR ORANGE 20051 POKE 705,65:REM PL 1 COLOR RED 20052 POKE 706,145:REM PL 2 COLOR BLUE 20053 POKE 707,27:REM PL 3 COLOR YELLOW 20069 REM PLAYER SIZE: 0=NORMAL, 1=DOUBLE, 3,DQUADRUPLE 20070 POKE 53256,1:POKE 53257,1:POKE 53258,1:POKE 53259,3 20071 POKE 53260,255:REM SAME CONVENTION BUT 2 BITS FOR EACH MISSILE SIZE 20080 REM *** PRINTS MISSILE NOS. ***** 20090 CHR=17:II=0:FOR III=PMBASE+512+Y TO PMBASE+519+Y:POKE III,PEEK(57344+CHR*8+II):II=II+1:NEXT III 20091 CHR=18:II=0:FOR III=PMBASE+640+Y TO PMBASE+647+Y:POKE III,PEEK(57344+CHR*8+II):II=II+1:NEXT III 20092 CHR=21:II=0:FOR III=PMBASE+768+Y TO PMBASE+775+Y:POKE III,PEEK(57344+CHR*8+II):II=II+1:NEXT III 20093 FOR N=PMBASE+512 TO PMBASE+1024 STEP 128 20091 FOR M=16 TO 0 STEP -1 20095 POKE N-H,255:NEXT M:NEXT N 20096 XO=125:XN=125:YO=93:YN=93:COLR=255:Y=8:GOTO 20170 20099 REM ***** JOYSTICK ROUTINE ****** 20100 MOVE=STICK(0):IF STRIG(0)=0 THEN 20230 20105 IF MOVE<>7 AND MOVE<>11 AND MOVE<>13 AND MOVE<>14 THEN 20100 20110 IF MOVE=14 THEN YN=YO-3:COLR=COLR-2:IF YN<0 THEN YN=93:COLR=COLR+61 20120 IF MOVE=13 THEN YN=YO+3:COLR=COLR+2:IF YN>91 THEN YN=0:COLR=COLR-61 20110 IF MOVE=11 THEN XN=XD-10:COLR=COLR-61:IF XN<0 THEN XN=1251:COLR=COLR+256 20150 IF MOVE=7 THEN XN=XO+40:COLR=COLR+61:IF XNM11 THEN XN=5:COLR=COLR-256 20170 LOCATE XO+10,YO,CO:CN=CO-2:IF CN<0 THEN CN=CO+2 20180 COLOR CO:PLOT XO,YO:DRAWTO XO+5,YO:PLOT XO,YO+1:DRAWTO XO+5,YO+1 20190 COLOR CN:PLOT XN,YN:DRAWTO XN+5,YN:PLOT XN,YN+1:DRAWTO XN+5,YN+1 20200 XO=XN:YO=YN 20220 GOTO 20100 20230 FOR N=0 TO 3:POKE 701+N,COLR:NEXT N 20235 REM DISASEMBLE COLR FOR PM PRINT 20210 IF COLR>99 THEN CHR0*16+INT(COLR/100):CHR1=16+INT((COLR-(CHR0-16)*100)/10) 20211 IF COLR>99 THEN CHR2*16+COLR-(CHR0-16)*100-(CHR1-16)*10:GOTO 20300 20250 IF COLR>9 THEN CHR0=16:CHR1=16+INT(COLR/10):CHR2=16+COLR-(CHR1-16)*10:GOTO 20300 20260 CHR0=16:CHR1=16:CHR2=16+COLR 20300 II=0:FOR III=PMBASE+512+Y TO PMBASE+519+Y:POKE III,PEEK(57311+CHR0*8+II):II=II+1:NEXT III 20310 II=0:FOR III=PMBASE+640+Y TO PMBASE+617+Y:POKE III,PEEK(57311+CHR1*8+II):II=II+1:NEXT III 20320 II=0:FOR III=PMBASE+768+Y TO PMBASE+775+Y:POKE III,PEEK(57311+CHR2*8+II):II=II+1:NEXT III 20500 GOTO 20100 20890 REM 20900 REM If you change graphics modes 20905 REM from here, suggest you 20910 REM FOR N=0 TO 7 20920 REM POKE 53248+N,0 20930 REM NEXT N 20940 REM to remove the player-missile 20950 REM graphics from the screen.
All arithmetic done in this Basic is done in 6-byte BCD. While this gives great accuracy, it also slows execution to a crawl. Atari 8K Basic is the slowest Basic I have ever used. To be sure, all computers have a tradeoff between memory use and speed, but this is a little ridiculous.
Add to this the many known bugs that will crash the machine, the slowness and occasional inaccuracy of the floating point operations, and numerous other flaws, and it just isn’t much of a language. It could have been done better.
Unfortunately, so much of the available software uses the Basic, and even the bugs (remember the old saw about “documented bugs” becoming features in the next version*, that Atari can’t fix it. We’re stuck with it. Too bad.
For speed reasons, it is just about impossible to write professional software in Atari Basic: any assembly program runs so much faster than the Basic that there is no comparison. Games written in Basic are easily identifiable by their slow speed.
In all fairness, the Atari Basic cartridge was meant for small Basic programs, not the huge amounts of code it is sometimes asked to execute, so it must be forgiven. The overall design structure is just wrong for fast program execution.
In conclusion. I wish it were better, but we are stuck with it. Great things have been done with the computer in spite of the Basic, and many Atari users have been forced to fo()2 Assembler because of it.
Speaking of which...
The 8K Editor/ Assembler is a close relative of the Basic cartridge. It is absolutely unacceptable for major software development. I can remember delays of up to an hour assembling large programs, and I have heard many other horror stories. This cartridge is also 8K and has bugs.
For instance, any CPY instruction hangs the TRACE function. This cartridge has inspired many software houses to come out with their own assemblers, some of which are very good. The Atari cartridge has a handy debugger, but as an assembler, (how do I put this tactfully?) it is useful only for assembling small subroutines for Basic.
One good thing about the Basic and Assembler/Editor cartridges is that there are now books designed to help the beginner get going with both of them. This is a good way to learn about the Atari and to get started but don’t limit yourself to these products once you are past the beginning stage. Another advantage is that they are cartridges, so you don’t have to buy a disk drive or more memory in order to run them, as is the case with most other languages.
The above products are supported by a company called Optimized Systems Software, located in Cupertino, CA. OSS also markets a 16K disk-based Basic known as Basic A+ and an assembler in their operating system called EASMD. Lo and behold. Basic A+ and EASMD are so close to the original cartridge code that they even have the same bugs.
The Basic is just as slow, but it does have new commands for handling players and missiles and disk I/O. It is a big step up from the original Basic, but still needs work. I would like to see integer variables and something to speed up the execution?
Atari Microsoft Basic is the Basic that Atari should have released initially. It is a 19K disk-based Basic. Add to that about 8K of DOS which must also be booted with it, and the result is 21K of user memory available for the programmer on a 48K system or only I3K on a 40K system.
That could be hard to live with. For instance, if you go into graphics 8, you have only 13K left on the 48K system, and only 5K on the 40K system. Still, Microsoft Basic is a very powerful and convenient language to use, and I have found few bugs in it. But don’t get it unless you have 40 or 48K.
Microsoft Basic has integer variables which are very fast. PRINT USING for business applications, and 4- or 8-byte accuracy (whichever you select), which speeds everything up. It is very much like TRS-80 Basic or Applesoft. Best of all, it has several nice features for player-missile graphics, character set redefinition, and other Atari-specific capabilities.
I like it, and try to use it whenever I have to do anything serious in Basic. While the boot up process takes a while, the time saved in program development is worth it. Any professional developer should seriously consider Microsoft Basic.
A 16K single cartridge (yes, you can put 16K on a single cartridge, check the hardware manual for details) version of Microsoft Basic is planned, but some features, such as renumber or PRINT USING, may still have to boot in from disk. More on this later, things haven’t settled down yet.
Microsoft has extremely good documentation which looks even better when compared to the original Basic document. It was this documentation that was responsible for the delay in delivering the product: the disks have been ready to ship for some time but the manuals weren’t. Considerable time and effort have gone into them, and it shows. Good job.
The Atari Macro Assembler/Editor is a very, very powerful disk-based assembler, which is a joy to work with. Light years beyond the original cartridge, it is extremely fast: it will completely assemble 100 pages of code in six minutes. It features support for independent files with Include, macros. systext files, and raw speed. I have discovered a few trivial bugs in it, but this is one product I can rave about without reservation. I have worked with it for more than four months and like it better each time I use it.
If you have any serious assembly language programming to do, get the Macro Assembler/Editor.
The Editor is also quite nice, and is being sold through APEX. It is a powerful and reasonably fast editor for developing text with no line numbers. This allows easy input of data, since you need not bother to strip off extraneous line numbers. Pascal, the assembler, and future goodies rely on the editor to generate source text.
Atari Pascal is brand new, and not reviewed yet. It is not a UCSD Pascal, but those of you who like Pascal might want to look it over and send me comments.
The Atari version of Pilot is a pretty clean implementation of the famous educational language. I have not done much with it but the feedback I have gotten is all good. The documentation in particular is extremely well done.
To understand “Why Forth?” you must look at some basic programming philosophy. Many languages are unsuitable for serious software development work. For most high speed games, for example, even Microsoft Basic isn’t fast enough. For business applications Pilot is out, and so on.
Well, Forth is difficult to describe, but let me try: it is a stack-oriented language which you define yourself. You start with a basic set of commands (input, output, arithmetic), and define your own commands (called words) from there. The language executes extremely quickly, compared to everything except assembler, and once you get into it, is much easier to write and debug, which drastically cuts development time.
Assembly language provides the ultimate in speed and machine control, but is not much fun to work with. Even with the very good macro assembler, debugging assembly code (especially without very good debug tools) is a frustrating, time consuming process. Forth helps the user get away from that.
The Atari is a very good machine for Forth. There are so many unique hardware features that a generic language such as Basic isn’t good at handling them all, but Forth is.
You can define language commands to deal with players and missiles, character sets, vertical blank interrupts, and whatnot. Each user’s Forth thus ends up growing along with him.
Sandy and I had been thinking of going to Forth, but it seemed like too much effort to get started. There were even two Atari Forths on the market: QS Forth and Pink Noise Forth. Yet I had a difficult time following QS Forth, even with its reasonably good instructions, and it seemed more a generic Forth implementation than an Atari-specific Forth. So we waited.
Two things changed our minds: 1) The book Starting Forth by Leo Brodie, from Prentice-Hall, which is simply superb and easy to read (complete with really, really good illustrations), and 2) VALForth, a new Forth based on figForth, which is currently being sold by APEX.
VALForth has commands designed especially to take advantage of the features of the Atari. It also includes a character set editor, easy player graphics, a very nice screen editor, and several other useful features. We were shown a preliminary version, and after reading the Starting Forth book, could dive in immediately and do things.
The transition is reasonably painless, and the power of the language unfolds around the user; I’m very happy to be working in it and we plan to write our next game in VALForth. The stack orientation is easy to get used to, especially if you just consider the stack data as part of the instruction set format.
The development speed of Forth has not been overlooked by Atari. Atari’s Coin-Op group has a semi-legendary “Coin-Op Forth” which is supposed to be quite something to use. The Atari demo disk with the “Disco Dirge” background music-is all “coin-op Forth.” Rumor also has it that many of the new Coin-Op games are written in Forth (Battlezone, for one). This wouldn’t surprise me: it’s a powerful language.
As a point of philosophy, we feel that as Atari programmers we began in Basic, moved to 6502 Assembly for speed, and now, after experiencing assembly debugging, are moving to Forth to reduce the amount of time we must spend on programming. We have great hopes for VALForth and what we have seen already is very worthwhile.
This brings us to the end of the July column. I hope you have enjoyed the sample programs and information. See you next month.
CREATIVE COMPUTING VOL. 8, NO. 8 / AUGUST 1982 / PAGE 218
For this month’s column, we begin a look at Atari DOS, complete with the usual extraneous comments and detours down useful side tracks.
A disk is a very complex piece of hardware. It is a mass storage device: one disk contains about twice the data that fit into the Atari’s read-write-memory at one time. In addition, various functions must he supported: these include Storage of disk files, random access of data. Formatting and copying. All of these are controlled by the Disk Operating System: they are the “support” routines specific to the disk drive and are needed only to run it.
The Atari has a very sophisticated operating system, easily the best in the microcomputer market for the price. It is called the OS (not DOS that is for the disk alone) and is physically located in the OS 10K ROM cartridge of the NX) and internal to the 400.
The Atari OS is very flexible and can do many unique things because it is “device independent.” This means that any input/output device-to-device communications are done not to a specific device, but to a “unit number.” Whatever device is assigned to that unit number receives the instructions from the operating system.
For example, lets say that we have output going to unit number 2. An example might be a checkbook balance. Now if that unit number is assigned to device “TV screen.” the output goes to the screen. If the unit number is assigned to the printer, the output goes to the printer. The output tioes to the device to which the unit number is assigned.
This concept of device independent input output is very consistent with the rest of the design philosophy of the Atari, lor example, colors are not assigned directly: rather, a given screen image is drawn in a color register number. Whatever color is in that color register is then output to the screen. (See November and December 1981 “Outpost.”)
The ability, to reassign devices is extremely useful. Unfortunately, the workings of CIO (the Central Input Output system) are a bit beyond the scope of this article. Short detour il warned you): Here’s one bit of information for advanced users that is worth its weight in gold. In order to direct all output going to the TV screen to the printer, use:
C.M6< A6.EE from the assembler editor cartridge debugger.
Screen output can be restored with: C346< A3.F6
Let me cite an example. I was debugging a game that filled the screen with a graphic’s display. If output appeared on the screen, it would disturb that display— a rather common problem. By using the above modification, I got the debugging/trace output to appear on the printer instead, leaving the TV image intact.
Back to Atari DOS. The DOS is a set of assembly language routines dedicated to running the disk drive. They load from disk any time the Atari is turned on with a disk turned on and connected. They are physically located in a file named DOS.SYS on the diskette.
These routines are absolutely necessary to run the disk drive. If the file named DOS. SYS does not exist, is fouled up, or otherwise cannot be used, then the disk drive cant be used either. The Atari discovers on power-up whether a disk is present and attempts to load DOS.SYS from the plugged-in drive.
If the disk is blank, or anything else is wrong, the message BOOT ERROR appears, and the drive makes an awful “s-nn-aaa-rrr-kk” sound. Don’t worry; the snark is the sound of the disk completely resetting its internal functions, the equivalent of “if at first you don’t succeed...”
Okay, what happens after the DOS file loads? The Atari takes the disk routines and integrates them into its regular operating system. The’ routines to handle specific devices (such as the screen editor, cassette, or printer) now have the ability to handle the disk. (The DOS will go away whenever the Atari is turned off or crashed, incidentally.)
Regrettably, these routines occupy roughly 9000 bytes of memory, so you lose 9K for other uses. You need DOS to access the disk, so if you plan to use the disk at any time during the current power-on session, you must load DOS.SYS. This is something every Atari disk user has done— just turned the machine on, without disk, then tried to access the disk. When I did this last I typed a program in for half an hour, and typed SAVE- nope, couldn’t do it.
(If you should get stuck this way, save the program to the cassette recorder] power up with DOS, and reload it from the cassette. The cassette handler is always in memory.)
Now for a little more relevant history. Atari has had several DOSes. The “first” DOS was dated 9/24/79, the date that shows up when DOS is typed. In this version, called DOS 1, the utility functions were integrated along with the regular operating system functions. When a user typed DOS, the utility functions were immediately run from memory, and the DOS menu popped up onscreen.
Well, this wasn’t a winner, because these menu functions occupied about 3000 bytes of memory and were only needed when a specific disk utility function was required. DOS 1 also had other problems and bugs, so Atari came out with DOS 2.
In DOS 2 the utility functions occupied a separate file called DUP.SYS. When the user typed DOS, the utility routines were loaded from DUP.SYS off of the disk. They weren’t in memory all the time.
There are some minor compatibility problems between DOS 1 and 2. Binary files won’t work between them, as DOS 2 has a different “header” format, and copying is a problem.
Fortunately, most of the DOS 1 disks have disappeared, leaving users with an improved operating system which has eliminated many of the bugs. Alas, while Atari was working on the bugs, they “released” several preliminary DOS 2 versions, called DOS 2.4, 2.5, 2.8, and 2.S, all of which have bugs in them. Don’t use them.
DOS 2.0S is the most bug-free version. (Should you find an older version of DOS. just re-write the DOS files after powering up from a 2.0S disk.)
One minor problem with the new DOS concerned where to load the DUP.SYS menu package in memory. The way it was set up, a user who went to DOS wiped out the lower 6K of memory, including any programs (such as Basic) stored there. The result? If you had a Basic program, went to DOS, and returned to the cartridge, your Basic program would be gone.
The solution Atari provided was MEM.SAV. MEM.SAV is a special file created from the DOS menu. When you type DOS and a file named MEM.SAV exists, then the lower 6K of memory is moved to this file before the utility package I DUP.SYS) is read in. Hence, a copy of the lower blXX) bytes exists on disk. When DOS is left, the MEM.SAV file is read in, restoring memory to what it was. The process can be summed up as follows:
1. User enters a program into memory, including the 3000 bytes “shared” with DOS.
2. User types DOS.
3. Lower 6000 bytes of memory are copied to MEM.SAV on the disk.
4. The utility package (DUP.SYS) is read into the lower 6000 bytes, destroying the program data there.
5. User exits DOS.
6. MEM.SAV is read back in, restoring the lower b(XX) bytes, and the user can pick up where he left off.
The process of reading and writing to disk is quite slow, as are all operations with the Atari drives. For this reason I rarely use MEM.SAV: I just save whatever I’m doing to disk first, go to DOS, then recover it from disk later.
Speaking of disk speed, new drives from other manufacturers are becoming available for the Atari. As a general rule, if the drive uses the serial I O cable to attach to the Atari, it will run as slowly as the Atari disk: this cable is the bottleneck.
When the Atari writes something to disk, it normally re-reads the data written to disk immediately and compares what it finds there with what should have been written. This is a safety feature in case the disk doesn’t write correctly. Alas, this slows down the disk drive to one write operation every I 5 second, a very, very, slow speed. If you wish to cancel this read-after-write process, do this:
1. Power up with DOS 2 into Basic.
2. Type POKE 1913,80
3. Go to DOS and select H: Write DOS files.
The data at location 1913 determines what sort of write the disk drive does: read-after-write (87), or write alone (80). Next time you write to disk, you will notice an immediate increase in the write speed.
In all fairness, I have never once gotten the error message that means the read-after-write failed. Some of my associates have, but only on defective disk drives that gave numerous other errors. In my opinion, the write with no verify is the way to go, as disk operations are quite reliable. The time spent waiting for the Atari to verify data just isn’t worth it.
The DOS Menu
Okay, so we have gone to DOS and are now in the DOS menu. Let’s look it over.
The top line identifies the DOS and DOS 2.0S. The S means “single density” and refers to the amount of data written on a particular disk. Atari was going to offer a disk drive called the 815, which was a “double-density dual disk drive.” For various depressing reasons the 815 was cancelled, so the double-density operating system, called DOS 2.0D, was never released.
Next, there’s the copyright line. Then, the menu options begin. Let’s take them in order.
A. Disk Directory: Data on Atari DOS disks is organized into individual files. These files have names of eight characters with an optional three-character extender: e.g. FILE.ABC. PROGRAM.BAS, and so on. Note that I said Atari DOS; there are other disk operating systems available which do not use Atari DOS. For instance. Forth doesn’t generally use the Atari DOS at all, and an attempt to read the directory on a Forth disk is usually futile.
The directory is a list of the files, by name, which exist on the disk. Option “A” is used to read this list.
When you press A, the Atari asks. SEARCH SPEC. LIST FILE?
This means you can enter one of two items. The first is a “search specification.” You can search for all files, in which case a list of everything on disk is produced, or for a specific group of files. This specific search is accomplished with “wild cards.” A wild card is a special character which Atari DOS accepts as “any character.” The character “?” is used for a wild card for an individual character, and “*” is used to indicate any characters from that position on. For instance, a search spec of *.* will find all files on the disk. *.BAS will find all files with the extension .BAS. JONES V will find any files whose first five characters are JONES. ??XYZ? will find AAXYZJ, ZZXYZD, and A1XYZR.
The second spec tells where to write the directon, listing. Leaving it blank means .write it to the TV screen, also known as “Device E:” (where the E stands for Editor). Here we get into the I () system, which we have discussed previously. Devices on the Atari are identified by a letter and a colon. Here is a list of some of them:
K: Keyboard. Input only.
E: Screen Editor! TV). Input-Output.
S: Screen output. Output only.
C: Cassette unit. I/O.
P: Printer. Output only.
Dn:name.ext Disk drive #n, file name “name.ext.”
The directory option asks where you want to write the listing. You can select any of these devices for output but the keyboard (K:).
You could use P: (printer), D:filename (some disk file), and so on. Note the power of the I/O system: you can write the listing anywhere, including devices or file names. For example, writing a listing to a printer is handy for a reference. Writing it to disk might be nice for a directory program. Writing it to the TV is good for quick lookups. This is a powerful unit.
The directory will then proceed. Physically the directory is located in the middle of the disk. This is because the Atari spends so much time looking at the directory that it was fell that the middle would be a good place: it is equidistant from everywhere else, saving lookup time.
B. Run Cartridge. This option transfers control to the plugged-in cartridge. If you don’t have one, the Atari will figure it out and let you know it knows. This is how you get back to Basic, the ASM EDIT cartridge, and others from DOS. Languages which are “disk based” (such as Microsoft Basic) do not use this option. There are different ways of getting to and from DOS using non-cartridge-based languages.
C. Copy file. This option allows you to copy from any device or disk file to any other device or disk file. It is extremely powerful.
For instance, if we copy from E:,D:TEST whatever we then type on the screen will he sent to the disk file TEST. (Exit using the Break key.) Bang, an instant crude word processor! We can copy directly from the screen to the printer (E:.P:), from the keyboard to the screen, etc. We can display a file on disk by using D:filename.ext,E:. (This includes Basic files, although they are stored in a crunched formal and will look strange when listed.)
Finally, we can copy from disk to disk using this option: D:FROM.D:TO will copy all data in the disk file FROM to the file TO. Also, we can copy from disk to disk: DI:FROM.D2:TO will copy from FROM on disk #1 to TO on disk #2. The Atari can support up to four disk drives. D1-D4. The drive is identified by the two switches in the back of the disk unit: they can be set in four positions, and the position in which they are set determines the drive number of the disk.
Another short detour: If you can’t get your system to “wake up.” check these switches. The Atari will be looking for the disk #1 to get DOS. SYS from, and if no disk currently online has its switches set to 1, the Atari won’t find it. This leads to all sorts of strange things. So especially if you have a multi-disk system, check this if you get weird errors.
You cannot use the Copy option on a single disk system to transfer files between separate diskettes. Use the 0 option to do this. 0 reads the entire file into memory then prompts you to change diskettes. Then, it writes the file out to disk.
COPY uses as much memory as possible as an intermediate storage place. If you copy a disk file to the screen, you will note that the entire file is read off disk before it begins copying to the screen. This is the nature of Atari I/O. You will also see that when copying to the printer. you must terminate the input operation before the output begins.
This causes a problem when MEM.SAV is used. When MEM.SAV is active, the Atari assumes that all memory outside the 6K bytes copied on disk is inviolate. On a copy, it will ask you whether to use the rest of memory to speed things up.
If you don’t you will have a very slow copy, as only a small intermediate area in memory can be used. This also keeps memory intact for you to return to after you’re done with DOS. Should you elect to allow Copy to use the rest of memory. MEM.SAV is invalidated and you lose whatever is on disk. The choice is yours. (The Atari will warn you that a “Yes” to its prompt will invalidate MEM.SAV.)
Warning: Files with “.SYS” as the extension will not copy using the wildcard options. While this doesn’t really matter with DOS or DUP.SYS, as they may be written with the H option, it is critical with AUTORUN.SYS files. Be sure to force a copy of the AUTORUN.SYS file il you copy a disk this way.
D. Delete File. This is an option to allow you to delete a file from disk. If you use a wildcard, you can get rid of a whole group of files. For example, to delete every file with an extension .ASM, use: *.ASM at the prompt.
Delete will ask you if you wish to delete each individual file by printing the file name, then asking DELETE’.’ Y N. If you don’t want il to verify that you want the file deleted, add a N at the end of the file specification. For instance, to delete all files with SAM as the first three characters and not gel a prompt, use SAM*.* N. The DOS will then delete everything it finds with those specifications without asking again if you really want to do it.
Delete *.*/N will erase an entire disk.
E. Rename file. This option allows you to rename a disk file. You enter the first file name, then the second. HERMAN. FRED will rename HERMAN to FRED on disk. Wild cards can also be used, but he careful.
This option also allows you to create two files with the same name a significant problem. If you try to access the file by its name, the first occurrence will gel priority, and you will have lost the second file for all practical purposes. But delete or rename will get both occurrences of the file, alas. What to do?
Try this. Turn up the TV sound. Rename the file something else, and listen. Immediately after hearing the first clunk of a disk write inot a beep, that’s a disk read), pop the drive door open. This will prevent the Atari from renaming the second file, which would be the second clunk. Do this al vour own risk — you could also trash the directory and lose the disk if your liming is wrong.
An alternative is to use a Disk Fixer program, such as the one available from APX, to alter the directory.
That’s all we have room for this month. Next month we’ll finish discussing the DOS menu options and have a few surprises.
There were two lines missing in the GTIA demonstration programs that appeared in the June, 1982 column (LOGO, HYPNO, ESCAPE, MELONS, SAS, and WHIRL).
31000 DATA 104,162,0,172,193,2,189,194,2,157,193,2,232,224,8,144,245,140,200 31010 DATA 2,96,65,65,65,65,65,65
CREATIVE COMPUTING VOL. 8, NO. 9 / SEPTEMBER 1982 / PAGE 188
Continuing the discussion of DOS menu options that we began in the August column:
F. Lock file. A file that is locked may not be altered or deleted. This is a safety feature: I lock the editor and assembler files on my disks that have them. This prevents something like a wildcard delete from destroying them or something in DOS from accidentally modifying or destroying them.
G. Unlock file. The reverse of F.
H. Write DOS files. This option writes DOS.SYS and DUP.SYS on the current disk. I You are asked which drive number to write the files to. I Remember, you must have the DOS files on a disk to be able to power up using that disk, for the disk operating system must load at that time.
I generally use this option after modifying DOS (lets say with the “fast write” POKE) or after formatting a disk. By the way, old DOS files on the disk will be deleted. And in answer to a question 1 received, the DOS files do not need to be any place in particular on the disk. They can be put in any time.
I. Format disk. This option takes a new or used disk and completely blanks it out. putting “formatting information” onto the disk. It also sets up a blank directory and other information needed by the Atari to access the disk. And here we go on a short detour:
Fast Format Chips
A disk is laid out with the sectors in which data is saved in a particular order. As the disk spins at 290 rpm these sectors are accessed one by one. Now, depending on how the sectors are laid out, the Atari can access them more quickly. Atari has two popular sector layouts— the B and C layouts. The B layout is the original and is quite slow: there is a discernible pause between disk reads ( beep — pause — beep — pause— beep, where each beep is one read.)
The C format is about 20% quicker than the B format, because the disk is laid out more efficiently. Disks that come from Atari use the C layout.
When you format a disk, the way your disk was set up at the factory determines whether it uses the B or C layout. Most drives today have the B layout, but all new drives shipped from Atari have the C layout. Thus, disks formatted on new drives (using the C layout) will do everything 20% more quickly than disks formatted on B drives.
By the way, if you reformat a disk, the new format will be the one laid out by your disk drive, so don’t reformat Atari-formatted disks. Instead, if you want to delete old infomation from them, use Delete *.*.
A group of users in Chicago modified the B layout to what is called the Chicago layout. This layout is 30% quicker than the B format and indeed is 10% quicker than Atari’s own C layout. However, a price is paid: the disks become rather sensitive.
Atari disk drives have difficulty maintaining a given rpm, which causes several problems, including lots of read-write errors. If you install the Chicago format, and your disk spins at more than 288 rpm. it will skip sectors, doing a complete spin between reads. This is quite slow and has a distinctive “Beepbeepbeep (pause) beepbeepbeep (pause)” sound. If you get this, check your disk.
One other thing about the Chicago chips is that they may be illegal. Atari copyrighted the B format in the ROMs used in the drive. It would annoy them considerably if users didn’t buy the new C chips, complete with installation charge, but used the Chicago chips instead.
The legal question about copying the chips, then modifying them, is not one I would care to test. Yet many users have installed Chicago chips in their drives. and some groups even hold swap parties where hardware experts install Chicago chips into other people’s drives. Someone with pretty good hardware knowledge and an EPROM copier is needed even to make the Chicago chips from the available instructions (which have shown up in many newsletters), so this choice may not even be available to you.
Yet another consideration is that the difference between the B and C chips available from Atari does not consist solely of the formatting change. The chips are much different, and supposedly other improvements have been incorporated into the C revision. You may be missing out on these improvements if you install a Chicago chip.
Another goodie installed by Atari on later drives is a piece of hardware called a “data separator.” The story is this: Atari uses a floppy disk controller chip from Western Digital called the 1771. The 1771 is a fine chip, but has a weakness in clarifying data read from the disk, a process called data separation. Even the manufacturer’s own literature tells the user not to rely on the internal data separation of the chip.
So what did Atari do? They didn’t use an external separator. Result: bad disk reliability and lots of errors. Soon the more sophisticated users of Atari drives figured out the problem and began installing TRS-80 data separators in their Atari drives.
It seems that the makers of the TRS-80 had done the same thing (not used an external separator) and that TRS-80 disks had very poor reliability as a result. So outside companies began supplying data separators for the TRS-80. Since this machine also used the 1771 controller, the data separators for the TRS-80 fit the Atari.
I installed one some time ago and have been very pleased with the increase in reliability. The cost is $29.95 from one source, Percom, which now supplies kits for the Atari.
You need a soldering iron for two very minor solder touchups and a phillips head screwdriver to remove the cover of the machine. While the modification will violate the Atari warranty, it is worth it.
I recommend it to anyone who doesn’t have the Atari data separator, which is everyone with a drive made before January 1, 1982. Percom can be reached at (214) 340-7081. You should call for new pricing and availability information.
Depending on your local dealer, parts availability, and other factors, you may be eligible for a deal whereby you send your drive in for installation of a C formatting chip and an Atari data separator and a general check-up. The Atari separator seems to be pretty good, so you may want to look into this option to upgrade your drive.
A late breaking rumor is that Atari has released yet another add-on board to help control the drive. I don’t know whether this is true, but it sounds likely: drive rpm has caused many headaches.
DOS Menu Again
J. Duplicate Disk. (I know, you thought I’d never get back to the DOS menu. Right?) This option allows you to duplicate an Atari disk completely. What it does is read each sector from 1 to 720.
The user can either duplicate from drive to drive or with one drive by swapping disks. Use “1,1” at the prompt to duplicate a disk with one drive, and differing numbers to duplicate between drives.
Duplicate Disk is more or less identical to a copy using *.*. However, the disk duplication is complete, so errors in the disk will also be duplicated. Should you get an ERROR 14 or 164 on the disk. Duplicate Disk may not work, and you should copy individual files from disk to disk to recover what can be recovered. A discussion of sector chaining and what causes an Error 164 is beyond the scope of this article, but can be found in the April and May 1982 issues.
K. Binary Save. This is an option for the advanced user which saves a given area of memory to disk as a binary file. It is an assembly language entity used by the machine. Since this is a beginner’s guide, and hexadecimal input is required. I’ll leave it at that. See the DOS 2 manual for a lengthy, painful disussion of what happens.
L. Binary Load. This is an option to load a binary file from disk into memory and to execute it directly. Beginners may use it, although they may not understand what is going on. The Macro-Assembler Editor is only accessible by loading it from a binary file, for instance. And Microsoft Basic is just another binary load file. (Think of a cartridge as a binary load frozen into the cartridge which appears in memory when you plug the cartridge in, and a disk load as data that appears in memory loaded from disk. This will give you an idea as to how the two relate. I And no, you can’t copy a cartridge using the Binary Save option — Atari DOS checks for this to prevent people pirating the cartridges.
M. Run at address. Again, this is an advanced-user-only option. It enables DOS to jump directly into a program loaded in memory. It is handy for advanced users who want to run programs without a cartridge, but not so helpful for beginners. Again, knowledge of hexadecimal is required.
N. Create MEM.SAV. This is used to create the initial MEM.SAV file. To eliminate it, use the Delete option. You cannot create MEM.SAV any other way. although a disk that is Duplicated will have the MEM.SAV on the new copy if the FROM disk had it.
O. Duplicate file. This is used to copy a file from one disk to another without using two drives. Wildcards can be used to copy an entire disk.
Disk drives are relatively high-speed mass storage devices. Alas, the 5 1/4″ mechanisms represent a tradeoff between reliability and cost. The 8″ drives, which are more reliable, also cost much, much more. Atari probably couldn’t market an 8″ drive for less than $900; so they went with the 5 1/4″ mechanism and enabled many more to have disk drives. It was a good tradeoff.
Unfortunately, the way in which Atari designed their drives is developing into a controversy. The number one topic of conversation in many user’s groups seems to be peeves about Atari disk drives. The drives are neither reliable nor fast — even compared to the rest of the industry. Apple disk drives, for example, run up to 20 times faster.
Something will undoubtedly be done; Atari has not been deaf to the complaints. For the moment, they have issued several patches to the drives— data separators, rpm fixes— but they may not be able to correct what might be simply a bad design.
See you next time!
CREATIVE COMPUTING VOL. 8, NO. 11 / NOVEMBER 1982 / PAGE 276
It is a pleasure for me to man the outpost this month. It has been nearly three years now since I first unboxed my Atari 800, and I can report that it has performed unfailingly over all that time and heavy use. I’m not saying I have never had a system crash or lock-up, but the computer has never required any service beyond cleaning the board contacts once in a while (I can handle that).
The machine was and remains an engineering triumph, which is still ahead of its time in terms of capability and cost, as well as reliability.
Atari owners have had to be a tough-skinned breed now and then over the past three years, but that has changed. The “big three” are under the gun. Atari owners, now numbering over 300,000, know they made the right decision.
I am a member of this group, and a satisfying facet the hobby offers to me is the use of my machine to communicate with others who feel the same way I do about it: that the Atari is the best machine of its class, and that learning its secrets is an extremely pleasurable pastime.
Last May we instituted a call for reviewers, and many Atari owners responded. One thing that impressed all of us here at the magazine was our query concerning modems. Of the respondents who did not already use their microcomputers for telecommunication, nearly everyone responded that he had a modem on his “wish list,” and that it wouldn’t be long before he was hooked up. We have also had a very favorable response to the possibility of making Creative Computing downloads available over networks such as CompuServe and The Source. We are looking into this possibility.
A great deal of potential presents itself. The possibilities of travel reservations, ticket purchases, shop at home services, a broad range of databases at your finger tips, are very exciting. Telecommunications herald a truly practical role for the microcomputer in the home.
I do not believe, however, that any of these practical notions constitutes the real basis for the “modem mystique.” The thing that excites most people about microcomputer telecommunication is the opportunity to express themselves in a new medium, to tell others how they feel. They are less interested in using a modem to pay their bills than to state their opinions, to have their voices heard, and to respond to the voices of others.
The bulletin board service is growing in popularity. This is a phone line tied to a computer, running a program that accepts and displays information sent from other computers. The concept of the bulletin board is powerful and extensible. It creates a new kind of forum— a medium of communication — through which ideas can be expressed, shot down, modified, and spread. The importance of this kind of interaction, and its potential, is now being discovered. I think it may be a while before it emerges as a medium of major influence, but it is going to happen; it’s happening now.
I maintain contact with about five Atari bulletin boards regularly. I enjoy leaving messages as well as reading what others have to say. I check the download files to see if there is any software worth trying out. I find out what other Atari owners are thinking about, as well as expressing my own thoughts. I may even start a “real-time” conversation with someone at the other end.
You may be a new user with questions concerning hardware. You may be an assembly language programmer wishing to share the results of a routine you have developed. Or, you may simply wish to voice your opinions concerning Tron or E. T. or to boast of your latest score at Zaxxon. The bulletin board is a worthwhile place to do it. Your thoughts join other thoughts, in what amounts to a marketplace of ideas— ideas that are shared.
Communication via computer may seem at first to be rather impersonal, but this is not the case. Through what other medium might you become involved in a lengthy philosophical chat with a sysop (system operator) hundreds of miles distant and at three in the morning? It is almost like being able to call your own user’s group meeting whenever the mood strikes you— and then adjourn it without muss or fuss. It is at once personal and yet distant: and therein lies its unique value.
So get that Atari of yours talking to other Ataris, the way you’ve planned.
A very hot topic on nearly every board I have logged onto lately is the Forth language. This language offers hope to folks frustrated by the slowness of Basic, limitations of Pilot, bugs in APX Pascal, and obscurity of assembler. Although it has its own unique little quirks, Forth seems to be a natural for the Atari machine.
There are many implementations of the language available for the Atari, but the definitive version now seems to be Valforth, from Valpar International, 3801 E. 34th Street, Tucson, AZ 85713. We have received four packages from them, each of which shows a high level of professionalism and promise.
Valforth is a debugged and improved version of APX Forth, and is available with a powerful screen editor and utility package; a player missile graphics package, character and sound editor; and a display list formatter. We were able to create very smooth multicolored player/missile animation as well as modified display lists with very little fuss. The speed of movement is not as fast or as smooth as machine code, but is many times faster than Basic, and quite acceptable— so are the ease with which these packages can be used, and their reasonable cost. I hope to present a thorough evaluation of all the Valpar packages in the near future.
Despite whatever you may hear to the contrary, you need not renounce your worldly ways to grasp Forth. Nor does mastery of Reverse Polish Notation cause hair loss or halting speech. Sure, the language has its peculiarities, but that’s the challenge, right? Anyway, whenever you hit a real snag, you can ask for help on a bulletin board service! There’s nothing like access to someone who knows the answers when you’re trying to learn something.
Another byproduct of accessing user’s group bulletin boards is the spreading of rumors. One such rumor I discovered on the MACE BBS has lamentably been confirmed: John Harris, brilliant young author of Jawbreaker and Mouskattack, had the only extant source code for his latest work, Frogger, stolen during a charity benefit. It is hard to understand what the thief had in mind— if we assume the thief had anything resembling a reasoning mind. What could he have hoped to gain by stealing the source code of an unfinished program? This will certainly forestall the release of Frogger for some months, and is sure to have put a real crimp into John’s summer, if not his year. Upon capture, the thief should be forced to play Crystalware adventures to their solution or the thief’s collapse, whichever comes first. (Are you taking any bets?)
Other Atari Bulletin Boards R=Ringback L=Limited service
|AMIS||-||Baton Rouge, LA||504-273-3116|
|AMIS||GRASS||Grand Rapids, MI||616-241-1971|
|AMIS||TEAM||San Jose, CA||408-942-6975-L|
|ARMU||FLEGLG||New York, NY||212-598-0719-L|
|ARMU||GREKLCOM||Oklahoma City, OK||405-722-5056|
The “type” of bulletin board indicates what program is run on the host computer. Each program has its own strong and weak points; ergo each has its own adherents and detractors. It’s all part of the fun.
AMIS stands for “Atari Message and Information Service.” ARMUDIC began as a mnemonic for the phone number of the original service.
“Ringback” means to let the phone ring once, hang up, count to five, and redial. This allows a single line to serve as a voice and modem connection.
“Limited service” means the board is up only part-time, as opposed to 24 hours a day. If you can connect once, the hours will be listed for you.
These numbers were compiled by the MACE BBS, which is one of the most popular Atari boards in the country. Our thanks to the Michigan Atari Computer Enthusiasts for this list. Give them a call!
I have yet to see a definitive list of memory locations for the Atari in any manual, periodical or book. We are compiling a list currently, and it will appear soon in the pages of Creative Computing. In the meantime, here is a very brief collection of some of the most interesting locations, and what values to POKE them with (all values in decimal):
65 - if = 0, I/O data transfer tones from TV or monitor will be disabled. Load will take place in silence. Nice with titles or especially music, to suppress “noise.” If location 65 <> 0, I/O will be audible.
77 - if = 0, attract mode will be suppressed. It is surprising to me how many programs are missing this simple POKE in any loop of less than nine minutes duration. Although designed to prevent “burn-in” on an unattended machine, this mode drives me nuts. If location 77 = 128, attract mode is enabled without nine-minute clock countdown.
752 - if = 0, makes the cursor “invisible.” I say invisible rather than disabled because the cursor still functions as if it were visible. Nice in title cards and text programs to clean up screen “look.” If location 752 <> 0, cursor will be visible.
82 - if = 0, enables 40-column screen width. The Atari defaults to a 38-character screen width, which was a good thing for me when I used a regular color television with the computer. “Overscan,” as it is called, cut off the left-hand side of the screen. When I upgraded to a color monitor (much to my wife’s relief), I noticed two unused columns on the left side of the screen. A simple POKE brings them into play. If location 82 = any number from 0 to 39, that number becomes the left-hand column. The default value is two.
83 - Same as above but for right-hand margin. Default is 39. Less call for this one, but nice to know, anyhow. Right?
Third party game software for the Atari 400/800 computers continues to pour in to the magazine. Let’s take a look at just a part of the cream of the latest crop:
Datasoft was among the first commercial third-party sources of Atari software, and the quality of their product line has remained consistently high. Canyon Climber, by Tim Ferris, sets a new standard for Datasoft, as well as one that challenges comparison.
Beginning with strains of Bach, Canyon Climber sets its own tense, yet humor-filled pace. The musical opening is superb; it is hard to tell whether you are listening to your computer or a cut from the album “Switched-On Bach.” How Ferris manages the tone sustain is a mystery to me.
Suddenly the music vanishes, and your lone figure is left, clinging to a narrow canyon trail while dozens of surly, half-crazed billygoats seek to topple him from the precipice.
You are without weapons in your attempt to scale the many paths and ladders. Your only edge is a near ballet-like ability to leap into the air. If you time your leaps just right, you can hurdle goats on the fly. Your timing is crucial, of course; beginners will almost certainly earn a lot of horns in the keester.
The first task is to place explosive charges across a set of bridges spanning the canyon. Dodging oncoming goats from all sides, your fearless climber scales the sheer cliffs. And, upon reaching the detonator, you blow the bridges. This will hold the billygoats for a while.
However your problems are just beginning. The screen changes, and you find yourself at the foot of another set of cliffs.
Billygoats were child’s play. Here you meet a very sedate group of Indians: they neither move nor make a sound. They simply and continuously shoot arrows at your face. Hope you’ve been practicing your pirouettes.
At a couple of these cliffs you will find a shield, which may help fend off a few arrows. Be careful though, because your shield may disappear at any time. Carrying it also makes ladder climbing tougher, as you cannot climb a ladder while carrying a shield.
If you are lucky enough to make it past the Indians, you are greeted by a final set of cliffs. You can see the top now. In the sky above, great birds hinder your progress by dropping, well, bricks in your path. The trail itself becomes quite tricky, as the way is broken by deep fissures. One misstep and you’ll be goat feed by the time you hit bottom.
Finally you reach the top, just long enough for a breath of blue sky and a bit of Bach before the head billygoat butts you right back down to where you started. This time the going will be even tougher. Canyon Climber achieves a cartoon-like atmosphere in the rendering of its various screens, to very pleasing effect. Your figure has blond hair, and wears a blue shirt with jeans. It actually seems to throw a shadow on the canyon wall, as well. The animation is smooth and the colors superlative.
You will spend a while with Canyon Climber. It took me a couple of days just to reach the top on a regular basis. Now I have begun to work on my score.
Several epochs ago, when I was a lowly undergraduate, arcade games were just beginning to use video screens. I remember an early one called Circus, and that it sat between Tank and Pong in the student union. Ah, those were the days. “Oh, no,” was my first thought when I loaded Clowns and Balloons, also from Datasoft. An exhumation of Circus: where is author Frank Cohen’s respect for the moribund?
This report was exaggerated; I was dead wrong. This may very well be the most addictive game I have seen since Threshold.
In Clowns and Balloons, you manipulate a trampoline, shooting your player ever higher, as you try to break as many balloons as you can in your trajectory across the screen. The concept is simple, but play is not. You must anticipate where to move that trampoline at all times. Otherwise, in the flick of an eye, your player will land in a headfirst heap on the floor.
Stone Age devotees of the black and white coin-op Circus will especially appreciate the sophistication of Clowns and Balloons. The trampoline is carried by two silver-haired clowns, whose outsized shoes scamper wildly as they run from side to side. The balloons spin and shimmer as they glide across the screen, and they do so in vibrant colors.
The music, as in Canyon Climber, is superb. Even after I landed on my head, I found myself humming along with it. Again, all factors work together to form an “atmosphere” about the game. It is as if it were a cartoon rather than a computer representation. It works very nicely.
It was easy enough for me to predict that my bevy of kid playsters would go nuts for Clowns and Balloons. They liked it nearly as much as I do. Fortunately, they belong to someone else, so I can play to my heart’s content after they have gone home to eat dinner. Three levels of difficulty keep the action at a “breakneck” pace.
CREATIVE COMPUTING VOL. 8, NO. 12 / DECEMBER 1982 / PAGE 370
It’s getting to be the holiday season here at the outpost, and visions of hardware, software, and peripheral sugarplums are surely dancing in our heads.
As a service to our readers with extremely clear specifications to Santa regarding items for placement under the tree, Figure 1 is presented. Simply fill in the blanks, and leave the magazine in an obvious spot, conspicuously open to this page. The bathroom offers an inescapable point of sale, but be creative. (Warning: those desiring software may avoid last-minute disappointment by underscoring to loved ones the fragility of diskettes. Sure, you can stuff stockings in your boots, but you won’t be able to boot disks that have been stuffed in your stocking.)
Figure 1. To Whom It May Concern (That Means You) Let’s face facts. Your (relationship), usually known as (name), has been reading Creative Computing non-stop for weeks now. The bug has bitten, the hook is in. It’s hopeless, the addiction has been fostered. Things could be worse, right? As hobbies go, microcomputing fares pretty well. Maybe the time has come for you to acknowledge this. Make a hit this (holiday). Get (product). It is available at (source), (address), at a cost of $(dineros). Otherwise, (name) will probably sulk through the whole holiday. Sound like extortion? Not at all. But don’t chance it
Original Atari Basic has its strong and weak points, as do all computer languages. Because Atari Basic is a somewhat renegade dialect, however (as opposed to the orthodoxy of Microsoft Basic), it is subject to especially intense scrutiny. Those who dislike it tend to detest it; even those who like it tend toward ambivalence. C’est la langue.
There is at least one good reason why Atari Basic is a “splinter language.” It was designed in tandem with and in order to squeeze the most from the Atari operating system. And as such, it is capable of some exotic tricks — that much is undeniable.
One of these tricks is the ability to write-code that in turn rewrites itself. Imagine the possibilities.
The Atari has a very open-minded operating system. It will allow the screen editor to operate, from sources other than a human at the keyboard. The editor will go so far as to accept data pushed to the screen from Atari Basic, and Atari Basic can then execute commands directly from the screen editor.
Figure 2 is a short example of how this feature can work. First we clear the screen, and position the cursor. Then we straightforwardly print code lines to the screen. These lines will act as if the Atari has automatically pushed the RETURN key over them, thus incorporating them into the program (and eliminating any previous lines with the same line numbers). Notice the inclusion of a CONTinue command. You must print this command at the bottom of any list of modifications or the program will terminate before modification takes place. The program run must actually stop, accept the new data, and start itself again.
10 REM SELF-MODIFYING EXAMPLE 20 GRAPHICS 0: POSITION 2,5:REM CLEAR SCREEN AND POSITION CURSOR. Y COORDINATE = NUMBER OF LINES TO CHANGE (5) 30 ? 110;" . THESE ARE THE LINES" 40 ? 120;" . THAT WILL REPLACE" 50 ? 130;" . THE LINES AT THE" 60 ? 140;" . END OF THE PROGRAM." 70 ? 150;" . NOTE ABBREVIATIONS REMAIN ACCEPTABLE." 80 ? "CONT:REM THIS STATEMENT IS CRUCIAL, AND MUST NOT BE NUMBERED." 90 POSITION 2,0:REM REPOSITION CURSOR AT TOP OF SCREEN 100 POKE 842, 13:STOP :REM DON'T PUT ADDITIONAL COMMANDS ON THIS LINE 105 POKE 842, 12:REM POKES HALT PROGRAM, ENABLE EDITOR, ACCEPT COMMANDS, RETURN TO PROGRAM 110 REM WATCH THESE LINES CHANGE 120 REM TO THE LINES STIPULATED 130 REM IN LINES 30 THROUGH 70. 140 REM DON'T FORGET THE "CONT" 150 REM COMMAND AFTER LINE CHANGES! Figure 2.
The trickiest facet of the technique is placement of the cursor. If you position it incorrectly, you can lose modifications, or get locked into a loop. A bit of experimentation will lead to successful results.
Only now is the potential of this capability being fully explored. Two new programs from Artworx Software make use of the technique: Drawpic saves four color user drawings in graphics modes 3 through 7, by saving modified strings; Player/Missile Editor does the same for player/missile shape tables. You can get more information concerning these programs from Artworx, 150 North Main Street, Fairport, NY 14450.
A hint on how you might simply utilize the technique in your own programs is shown in Figure 3. Here the user is asked to input data, which is then incorporated into the modified program. This program can then be saved, thus saving the input information.
I’ve used the simplest possible approach in this example, saving up to one hundred phone numbers as REM statements. You might wish to improve radically on this approach.
Another use of the technique would be to delete lines when they are no longer needed. Line numbers devoted to user input of variables, for example, could be deleted after the variable table has been constructed. This would help conserve memory.
Countless other applications await your entry into Atari behavior modification. The limits are set by your imagination only.
Although the Atari does most things well, you can now customize it to do things better. The idea may seem to you akin to putting slicks on a BMW, but let me tell you about a few products we’ve tested that can make your machine faster and more versatile.
The Fastchip, from Newell Industries, replaces the floating point chip on the operating system board. Floating point routines, which involve mathematical operations with real numbers as well as integers, run extremely slowly on a standard Atari. Newell Industries claims that execution of these routines is boosted to three times the original rate.
I played Hail To the Chief twice on the same machine, once with the original chip, and once with Fastchip. Calculations within the program involve lengthy breaks in the action. Fastchip cut the waiting at least in half, from a maximum of 11 seconds to a maximum of about 5 seconds. It may not sound like much of a difference, but when you’re waiting it is.
If you are into floating point routines and don’t have a lot of time, Fastchip will help. It lists for $39.95, and installation in an Atari 800 takes less than five minutes. For more information, contact Newell Industries, 3340 Nottingham Lane, Piano, TX 75074.
You should resist with all your strength the temptation to confuse Fastchip with Fast Chip, the disk drive upgrade chip from Binary Corporation. This product will interest Atari owners with original 810 disk drives, as it provides a disk format 30% faster than the original. The company claims that the custom chip is 10% faster than even the new Atari upgrade chip.
It took about a half an hour for me to perform the upgrade, and was a bit more involved than I had initially anticipated. Still, the instructions are clear, and the process is broken into logical steps.
Binary Fast Chip without a doubt provides a faster format for your disks. I found that it cut about twenty seconds off the load time of a 12K file. But the disks are also rather sensitive—cases arose wherein Fast Chip-formatted disks took much longer to read or write. This was without exception true with disks for use with Valforth. It might therefore be advisable to wait until you have two drives, then install a Fast Chip in one. You can then choose the format to match the application.
The product lists for $39.95. For more information, contact Binary Corporation, 3237 Woodward Ave., Berkley, MI 48072.
Perhaps you’ve wondered if ROM cartridges could be copied to disk. Well they can now, with the Block from Protronics. The Block allows you to transfer from a ROM to a binary disk file. Up to ten ROM cartridges can be saved to a single disk. I was unable to find anything that the Block couldn’t copy.
Potential pirates should take note: the Block itself is a ROM cartridge, and no cartridge file will run unless the Block is installed.
The Block lists for $99.95. For more information, contact Protronics, 17537 Chatsworth, Granada Hills, CA 91344.
I remember, in the dim recesses of my mind, a time when information about the Atari was an extremely rare commodity. This was in ancient times, of course: maybe a year and a half ago. Now it seems a new book about the Atari arrives here every week. These are six of the best:
Atari Games and Recreations, by Herb Kohl, Ted Kahn, Len Lindsay, and Pat Cleland, Reston Publishing, Reston, VA 22090. Excellent starter for novices and kids, with an emphasis on fun programs the user can type in, play, and understand. Includes some nifty appendices.
Atari Sound and Graphics, by Herb Moore, Judy Lower, and Bob Albrecht, John Wiley and Sons, 605 Third Avenue, New York, NY 10158. The authors pace the text so that new concepts are introduced at a rate that can be absorbed. Sound and graphics are a motivating force with kids, but many hobbyists will want this one too.
110 REM A PRACTICAL DEMONSTRATION 120 DIM A$(10),N$(20),P$(18) 130 GRAPHICS 0 140 ? "*************************" 150 ? "* *" 160 ? "* TELEPHONE DIRECTORY *" 170 ? "* *" 180 ? "* (L)IST *" 190 ? "* (A)DD *" 200 ? "* (D)ELETE *" 210 ? "* (S)AVE *" 220 ? "* *" 230 ? "*************************" 240 INPUT A$: TRAP 130 250 IF A$(1,1)="A" THEN 300 260 IF A$(1,1)="D" THEN 360 270 IF A$(1,1)="S" THEN SAVE "D:DIRECTORY":REM CASSETTE USERS "CSAVE" 280 LIST 1,100 290 ? "PRESS RETURN TO CONTINUE":INPUT A$:GOTO 130 300 ? "WHAT WILL BE THE LISTING NUMBER";:INPUT N 310 ? "NAME";:INPUT N$:? "PHONE NUMBER";:INPUT P$:TRAP 310 320 GRAPHICS 0:POSITION 2,2 330 ? N;" REM",N$;" ";P$:? "CONT" 340 POSITION 2,0: POKE 842,13:STOP 350 POKE 842,12:GOTO 130 360 ? "LISTING NUMBER TO DELETE";:INPUT N:TRAP 360 370 GRAPHICS 0:POSITION 2,2 380 ? N:? "CONT" 390 POSITION 2,0:POKE 842,13:STOP 400 POKE 842,12:GOTO 130
The Atari Assembler, by Don Inman and Kurt Inman, Reston Publishing, Reston, VA 22090. Best beginners machine language book available for Atari owners. Assumes you have Basic and an editor/ assembler. Assembly language is tough stuff, but authors manage to keep things fresh with humor and good examples.
Games for the Atari, by S. Roberts, W. Hofacker, 53 Redrock Lane, Pomona, CA 91766. Includes good examples of player/missile movement from Basic, priority detection, and patching from Basic to machine language subroutines. Includes ten games to be typed in, unfortunately without much explanation.
Picture This, by David D. Thornburg, Addison-Wesley, Reading, MA 01867. A kid’s introduction to graphics through Atari Pilot. Excellent as a supplement to “Student Pilot” the reference guide supplied with the Pilot cartridge.
Your Atari Computer, by Lon Poole, Martin McNiff, and Steven Cook, Osborne McGraw-Hill, 630 Bancroft Way, Berkeley, CA 94710. It may have taken two and a half years, but there is finally a manual available which thoroughly documents the rudiments, as well as a number of advanced topics, concerning Atari personal computers.
Following a remarkably steady pace, the book progresses through beginning operation, getting started in Basic programming, and includes comprehensive chapters on the program recorder, disk drive, and printers.
The main body of the book deals with advanced Basic programming, and stands to serve the proficient Basic programmer as well as the novice.
Next the book focuses on the goodies. Graphics and sound are given a clear and thorough treatment — with a chapter devoted to advanced graphics techniques. Character set animation, display lists and player-missile graphics are explained simply and thoroughly, with examples helping to illuminate the way. Those of you (like myself) who need every last thing spelled out for you, are bound to benefit from this approach.
Later chapters examine sound routines and summarize Basic commands.
The book concludes with nine appendices, each of value to the Atari programmer. Finally we can turn to a single resource for an annotated list of error codes and their meanings, status and keyboard codes, memory usage charts, and a listing of important memory locations.
Your Atari Computer should be packed with each and every unit Atari ships, alongside or in lieu of current documentation. No Atari owner should be without it.
In the November issue, we gave a phone number for a Sunnyvale bulletin board system called TEAM Atari. Begun by an Atari employee, the board is unfortunately no longer in service. Apparently some Atari execs felt it was inappropriate, which is too bad.
You might try Bay Area Atari at (408) 244-6229. Sorry if we caused any inconvenience, but it is tough to compile a BBS list that remains totally accurate for any length of time.
A question many people are asking concerns the new Atari 5200 video system: is it or isn’t it a 400 without a keyboard? The answer: well, yes and no. It does have 6502, Antic, GTIA, and Pokey chips. It does run nearly identical ROM software. However, for reasons somewhat difficult to fathom, the 5200 has had enough changes made to ensure incompatibility with Atari computers. The most dramatic evidence of this is a redesigned game controller, which uses an analog input, in addition to a telephone-style keypad.
The advantages to a handheld keypad are obvious: the advantages of an analog joystick perhaps less so. A potentiometer-controlled stick allows for better control in games such as Missile Command, but a digital stick is faster in quick-turning games like Pac-Man. The 5200 controller ports are necessarily redesigned, as are the cartridges themselves. Whether this incompatibility is utterly surmountible remains to be seen, but it certainly would be a formidable task.
Another topic we hear a lot about is the “next generation” Atari. Have you heard about the Atari 600? We have, although we haven’t been able to confirm anything. It will be a single board computer, totally compatible with the 400 and 800. It will have RS-232 capability built-in, and a full-stroke keyboard. It will come with 48K standard, and sport programmable function keys. We have even heard about an Atari 1000, with a built-in dual density drive, and CP/M capability!
What, you may ask, has become of Dave and Sandy Small? They are responsible for some of the most informative articles concerning the Atari that have ever appeared in any magazine. I first learned about player/missile graphics, display lists, redefinable character sets, and a half dozen other topics from their series of articles, which began in the June, 1981, issue of Creative Computing.
Well Dave was unhappy with the speed of the 810 disk drive, and so he did something about it: he designed his own. His system is aimed at professionals, and in addition to its many other capabilities, is about seven times faster than an 810 drive. If you’d like more information concerning the system, you can contact Dave at the Leading Edge, 8642A Spicewood Springs Road, P.O. Box 10998, Austin, TX 78766.
All of us at Creative Computing wish you the best this holiday season, and a happy, healthy new year. And to all a good night!