COMPUTE! ISSUE 68 / JANUARY 1986 / PAGE 116

INSIGHT: Atari

Bill Wilkinson

Do You Need A 16-Bit Computer?

There has been a disturbing trend in my reader mail for the last couple of months. On the one hand, more and more people are asking for help: Where can I find out how to work with player/missile graphics? How do I hook a model 2300 argon laser to an Atari’s joystick ports and shoot down unfriendly flying saucers? (That’s not as much an exaggeration of the original question as you may think.) At the same time, and all too often from the same people, I hear of grandiose plans to buy an Atari ST or an Amiga and make the world safe for computocracy. I hate to burst any bubbles, but let’s reason together for a moment.

Over the past six years there have been at least 60 or 70 books published about the Atari 8-bit computers. Some are great, some are terrible, and most are at least adequate. True, most of these books are hard to find. Three years ago, the bookshelves had a handful of books about dozens of different kinds of computers. Now, instead, we find dozens of books about a handful of computers. Still, your bookstore can usually order what you need. And if it can’t, try an Atari dealer. If that doesn’t work, try one of the bigger mail order places that specializes in Atari.

Anyway, here’s my point: If you think information about the 8-bit line is sparse, wait until you try to find out anything about the 16-bit machines! As I write this, the only book published so far is called Presenting the Atari ST. But don’t expect to learn much from it that isn’t in Atari’s own somewhat skimpy (though attractive) manual. Yes, I have heard of additional books that are “in the works.” But how long do you think it will be before there are 60 or 70 titles?

So I’m asking: “Why buy one of the new machines? Why not buy an 800XL or 130XE?” On the basis of price alone, the 8-bit machines win handily. Atari recently announced a special promotion: 130XE, 1050 disk drive, 1027 printer, AtariWriter, and DOS 2.5 for $399. Use your TV for the video, throw in a better programming language or business package and a game or two, and you’re ready to enjoy computing for about five bills. Try to do the same thing with a 520ST, and you’re going to spend about $1,300 to $1,400, presuming you want a color monitor. For an equivalent Amiga, add about $800. What does this extra money buy?

Theory Versus Practice

In theory, the 16-bit machines should run programs 4 to 20 times faster than the 8-bit beasts. In truth, speed depends on the language and how well it is implemented. ST Logo is generally no faster than 8-bit Atari Logo. And for anything except possibly heavy math and intensive disk operations, neither Amiga’s ABasiC nor ST BASIC are significantly (i.e., more than 25 percent or so) faster than OSS BASIC XE running on an XL or XE computer.

How about the theories that the new machines can run larger programs, display better graphics, use mouse control, and so on? As I write this, those are mostly just theories, waiting for people to write software and prove them. I have often told people contemplating the purchase of a computer that they should seek out a piece of software to fulfill their needs first, and only then ask what machine(s) it runs on. I cannot emphasize that advice enough for these new computers.

Does this mean that I think everyone should buy 8-bit machines and forget the new ones? Not at all! I simply question whether most people can benefit from their as-yet unrealized potential And even when their power finally arrives, how many home users will need more than what they get with, say, a 130XE? Business, scientific, and other users may very well need the extra speed and power, but it’s pretty hard to justify an extra $500 to $1,500 if all you do with your computer is write a few letters a month and balance your checkbook.

What about people who want to learn how to program? They are total novices on computers, but enthusiasm is a great emptier of the pocketbook. Aside from the fact that there are lots of books on learning how to program an 800XL or 130XE, and none on how to use an ST or Amiga, how hard is it to learn to program on these new wonder machines? Well, writing plain-vanilla BASIC programs without graphics is reasonably easy. But that’s easy on the XL and XE machines, also. Simple graphics, with lines and colors? Easy on both kinds of machines. Moving objects? Now we are getting to where it depends on the language: very easy with Atari 8-bit Logo, BASIC XE, and Amiga ABasiC; nearly impossible for a beginner with Atari BASIC or ST BASIC.

I guess I’ve made my points. As for me, I am moving on to the 16-bit machines. I am ready to learn new and different things, such as how artificial intelligence programs work. Such as how to manipulate multiple screen windows when writing a business application in Pascal. Such as…well, you get the idea. But I still enjoy programming in BASIC. And I still have a library of dozens of programs (mostly public domain and therefore free, or nearly so) which I enjoy on my 130XE. So I won’t abandon any of you soon. As for yourself, think hard and read a lot before you abandon your trusty 8-bitter.

COMPUTE! ISSUE 69 / FEBRUARY 1986 / PAGE 107

INSIGHT: Atari

Bill Wilkinson

Avoiding Memory Confusion In Atari BASIC

After a couple of months of standing on my soap box, I’ve decided to step off and get back to business again. Before I do, though, here’s one more little rant and rave: I can now express my opinion of Atari’s new BASIC for the 520ST. In a word: disappointing. Neither ST Logo nor ST BASIC are viable production languages, which means you can’t write commercial applications with them. Since even the C compiler included in Atari’s $300 software developer’s package doesn’t support double-precision arithmetic, limiting you to six decimal digits of precision, you’d better be ready to purchase some language from an outside vendor if you’re serious about doing any programming on the ST machines.

Several months ago, I asked all you loyal readers to send me a postcard or letter giving ratings to the best or worst Atari-oriented books. Although I was a little underwhelmed by the response, I did get enough ballots to at least select the three favorites. Among these three, however, there was no clear-cut winner. And I happen to feel that is appropriate, since each addresses a different part of the knowledge an Atari programmer needs. Anyway, according to my readers, the best books are (drum roll…the envelope please): The ABC’s of Atari Computers, by Dave Mentley, published by Datamost; Your Atari Computer, by Lon Poole et al, published by Osborne/McGraw Hill; and Mapping the Atari, by Ian Chadwick, published by COMPUTE! Books. (Incidentally, you may have noticed that COMPUTE! Books has been shipping the new, revised version of Mapping the Atari, which has several appendices and notes devoted to the XL and XE machines.)

The rest of this column responds to a number of reader requests. Although the topic has been covered in COMPUTE! before (at least in part), there are many newcomers out there. And even if you aren’t a newcomer, maybe I can provide more insight into the concepts involved.

Finding Free Memory

Q: Where in memory can a programmer put machine language routines, character sets, player/missile graphics, and the like?

A: There is no simple answer, because it depends on which language you’re using, which DOS, etc. A couple of years ago, I did an entire series on relocatable machine language which was related to this problem. So this time, let’s tackle a simpler and more specific question: Where can I put a custom character set? The following techniques will also work for many other uses, including player/missile graphics.

When allocating memory, Atari BASIC—as well as BASIC XL and BASIC XE—looks at and believes the contents of two memory locations, LOMEM and HIMEM (located at $2E7, decimal 743, and $2E5, decimal 741, respectively). BASIC always starts your program where LOMEM tells it to and lets it grow as high as the value in HIMEM. Remember that this “growing” includes not just your BASIC code, but also the strings and arrays dimensioned by your program. Let’s consider LOMEM first.

The fact that a program always starts at LOMEM implies that if we increase the value of LOMEM and then load a program, the memory between the old value and the new one is available for whatever purposes we have in mind. On the other hand, once a BASIC program is loaded into memory, it ignores changes to LOMEM. This means we can have one program change the contents of LOMEM and then chain to another program. The first program is unaffected by the change, but the second will be loaded at the new LOMEM. Programs 1 and 2 demonstrate this technique.

Examine Program 1, which ensures that the memory we wish to reserve starts on a particular boundary. Remember that full character sets (128 characters) must start on 1K memory boundaries, and half sets must start on 512-byte boundaries. There are similar rules for player/missile graphics (see “Atari Animation With P/M Graphics,” a three-part series starting in the September 1985 issue of COMPUTE!). If you actually type in and run the programs below, you’ll be in for a little surprise. But do not omit the REMark statements from Program 2, or you’ll miss half the fun. Feel free to omit them from Program 1. For the programs to function properly, you must save Program 2 with the filename PROGRAM2.BAS (see line 900 of Program 1). If you’re using cassette instead of disk, change line 900 in Program 1 to RUN "C:" and make sure the tape is cued to Program 2 before you run Program 1.

A minor caution: The reason we base the changes to LOMEM on the contents of locations 128 and 129 (BASIC’s internal MEMLO pointer) instead of the actual LOMEM contents is complex. I have discussed it in this column before, but the heart of the problem is that some Atari device drivers (including the 850 Interface Module’s R: handler) do not correctly restore LOMEM when the SYSTEM RESET button is pressed. After a reset, BASIC’s pointer is more reliable. For the same reason, and for safety’s sake, programs bumping LOMEM should always bump it higher than the top of the BASIC program currently in memory. And one last piece of advice: If you run Program 1 over and over again, it keeps raising LOMEM higher and higher. Eventually you’ll run out of memory. You probably need some sort of flag elsewhere in memory (Page 6?) which tells the program not to raise LOMEM again.

Modifying HIMEM

Enough about LOMEM; what about HIMEM? Truthfully, if you know how big your program is and what it’s going to use in the system, you can put anything you want (character sets, machine language, player/missile shape data, etc.) in the memory between the top of your program and the bottom of screen memory. The only time the contents of HIMEM are used is when BASIC checks to ensure that APPMHI (location 14, $0E) hasn’t collided with it. APPMHI is essentially BASIC’s high water mark. It keeps track of the top of the runtime stack, which is always above the string and array space, which in turn is always above your program. So, if you know that your program, its data, and its stack will never grow too large, you could ignore HIMEM altogether. It’s much cleaner, though, to tell the system what you’re using by modifying HIMEM.

How and why does HIMEM change if you don’t do this? The most usual cause is a change in the graphics mode. For example, while ordinary text screen graphics (GRAPHICS 0) occupy less than 1K of memory, several graphics modes (such as modes 8, 9,10, 11, and 15) require 8K of screen memory. To demonstrate this, type in and run the following line, preferably after hitting the SYSTEM RESET button:

G0=FRE(0):GR.8:PRINT G0,FRE(0),G0-FRE(0)

This displays three numbers: memory available for your program in text mode, usable memory in mode 8, and the extra amount used by mode 8 graphics.

Generally, the best method is to always put your own goodies below the area occupied by the most memory-intensive graphics mode you plan to use. So either look in a memory map book to find out how much room a certain graphics mode will take, or simply change modes before using the memory.

For an example, try Program 3. It’s essentially the same as Program 2. The difference is simply where we move the character set. The REMarks explain where you should insert your own graphics mode declaration.

For instructions on entering this listing, please refer to “COMPUTE!’s Guide to Typing In Programs” in this issue of COMPUTE!.

Program 1: MEMLO Bumper
100 REM
110 REM THIS PROGRAM IS USED TO
120 REM RESERVE SIZE"PAGE S" OF
130 REM MEMORY FOR PROGRAM2.BAS
140 REM
150 REM (A "PAGE" IS 256 BYTES
160 REM
170 REM THIS PROGRAM ALSO ENSURES
180 REM THAT THE RESERVED SPACE
190 REM STARTS ON THE GIVEN BOUNDARY
200 REM (TO INSURE,FOR EXAMPLE, THAT
210 REM CHARACTER SETS START ON 1K
220 REM BYTE BOUNDARIES)
230 REM
500 SIZE=4:REM MUST BE AT LEAST 4 PAGES (1024 BYTES)!
510 B0UNDARY=4:REM ALSO GIVEN IN PAGES
520 IF PEEK(128)<>0 THEN POKE 128,0:POKE 743,0:SIZE=SIZE+1
530 MEMLO=PEEK(129) + SIZE
540 MEMLO=INT((MEMLO+BOUNDARY-1)/BOUNDARY)*BOUNDARY
550 POKE 744,MEMLO
560 POKE 129,MEMLO
900 RUN "D:PROGRAM2.BAS"
Program 2: Character Set Mover, Version 1
150 REM JUST AS A DEMO, THIS PROGRAM
160 REM CHANGES THE CHAR SET POINTER,
170 REM COPIES THE CHARACTER SET
180 REM TO THE RESERVED MEMORY,
190 REM AND THEN RADOMLY DESTROYS
200 REM THE CHARACTERS! HH210 REM
220 REM HIT RESET TO QUIT AND GET
230 REM NORMAL CHARACTERS AGAIN.
240 REM BI 250 GRAPHICS 0
260 SIZE=4:REM SHOULD BE THE SAME AS PROGRAM 1
270 POKE 756,PEEK(129)-SIZE:REM CHBAS IS CHANGED
280 BUFFER=PEEK(756)*256
290 POKE 752,1:PRINT :REM NO MORE CURSOR
300 FOR ADDR=BUFFER TO BUFFER+1023
310 POKE ADDR,0:REM FIRST CHANGE ALL CHARS
320 NEXT ADDR:REM TO SAME REPEATED PATTERN
330 LIST 150,240:REM JUST SOMETHING TO SHOW
340 REM READY TO MOVE THE CHARACTERS
350 FOR ADDR=0 TO 1023
360 POKE BUFFER+ADDR,PEEK(57344+ADDR)
370 NEXT ADDR
400 REM MOVED...SLOWLY DESTROYED
390 POKE INT(RND(0)*1024)+BUFFER,INT(RND(0)*256)
Program 3: Character Set Mover, Version 2
150 REM JUST AS A DEMO, THIS PROGRAM
160 REM CHANGES THE CHAR SET POINTER
170 REM COPIES THE CHARACTER SET
180 REM TO THE RESERVED MEMORY,
190 REM AND THEN RANDOMLY DESTROYS
200 REM THE CHARACTERS!
210 REM
220 REM HIT RESET TO QUIT AND GET
230 REM NORMAL CHARACTERS AGAIN.
240 REM
250 GRAPHICS 7:REM JUST TO CLEAR ABOUT 4K OF MEMORY!
260 GRAPHICS 0:REM OR OTHER MODE
270 SIZE=4
280 REM ALWAYS DO FOLLOWING AFTER THE GRAPHICS STATEMENT
290 POKE 741,255:REM ENSURE END-OF-PAGE BOUND
300 MEMHI=INT(PEEK(742)/SIZE)*SIZE-SIZE
310 POKE 742,MEMHI-1:REM LOWER HIMEM
320 POKE 756,MEMHI:REM CHBAS IS CHANGED
330 BUFFER=PEEK(756)*256
340 POKE 752,1:PRINT :REM NO MORE CURSOR
350 LIST 150,240:REM JUST SOMETHING TO SHOW
360 REM READY TO MOVE THE CHARACTERS
370 FOR ADDR=0 TO 1023
380 POKE BUFFER+ADDR,PEEK(57344+ADDR)
390 NEXT ADDR
400 REM MOVED... SLOWLY DESTROYED
410 POKE INT(RND(0)*1024)+BUFFER,INT(RND(0)*256)
420 GOTO 410
COMPUTE! ISSUE 70 / MARCH 1986 / PAGE 112

INSIGHT: Atari

Bill Wilkinson

Atari Character Codes

Last month’s discussion about where and how to place things in memory served as a good lead-in to this month’s topic: character codes. If you’ve read the heftier reference material, including COMPUTE! BooksMapping the Atari, you may have discovered that your eight-bit Atari computer actually uses three different types of codes to represent the various characters (letters, numbers, punctuation, graphics symbols) it works with. All of these codes assign a unique number to represent each character, but the three codes are incompatible with each other because they use different numbering schemes.

The most commonly encountered code is called ATASCII, which stands for ATari-version American Standard Code for Information Interchange. Except for the so-called control characters—such as carriage return, tab, and so on—ATASCII is compatible with standard ASCII. (Why Atari chose to modify the standard is anyone’s guess.) ATASCII is the character code used by PRINT, INPUT, CHR$(), ASC(), and most external devices such as printers and modems.

For example, in ATASCII (and ASCII), the code for uppercase A is 65. You can verify this in BASIC:

PRINT CHR$(65)
or
PRINT ASC("A")

Virtually every Atari BASIC book (even Atari’s own) shows the character represented by each ATASCII code. You can also run Program 1 below to display each character and its code. (Press CTRL-1 to pause and continue the display.)

Screen Codes

The second character code found in your Atari is the keyboard code. The keyboard code for any character is actually the value read from a hardware register in memory when the key for that character on the keyboard is pressed. Program 2 below lets you find the keyboard code for any character. Just for fun, try some of the keys or key combinations which don’t normally produce characters, such as CTRL-SHIFT-CAPS). Neat, huh?

Finally: screen codes. This term refers to the byte value you must store in memory to display the desired character on the screen. “What?” you ask, “How do those differ from the ATASCII codes?” After all, to put the string BANANA PICKLE PUDDING on the screen, all it takes is a simple BASIC statement:

PRINT "BANANA PICKLE PUDDING"

And besides, aren’t the characters in quotes supposed to be ATASCII codes? Good questions. Now for some complicated answers.

Actually, if the original Atari designers had thought just a little harder and added just a few more logic gates to the thousands already in the ANTIC and GTIA chips, ATASCII and screen codes could have been one and the same. It’s similar to the mistake of making ATASCII incompatible with ASCII. Sigh. But we’re stuck with what we’ve got, so let’s figure out how it works.

For starters, consider GRAPHICS 1 and GRAPHICS 2, the large-size character modes. You may have noticed that in either of these modes you can display only 64 different characters on the screen. Now, if you recall last month’s demo programs, note that we can specify the base address of the character set. That is, we can tell ANTIC where the character set starts by changing the contents of memory location 756 (which is actually a shadow register of the hardware location which does the work—see Mapping the Atari for more on this).

In a sense, the ANTIC chip is fairly simplistic. When it finds a byte in memory which is supposed to represent a character on the screen, it simply adds the value of that byte (multiplied times eight, because there are eight bytes in the displayable form of a character) to the character set base address. This points to the memory address for that particular character. Except… well, let’s get to that in a moment.

Exception To The Rule

Because we want GRAPHICS 1 and 2 (with their limited sets of 64 different characters) to display numbers and uppercase letters (omitting lowercase letters and graphics), for these two modes it makes sense that the character set starts with the dot representation of the space character and ends with the underline—codes 32 through 95, respectively.

But why are these 64 characters the only ones available in GRAPHICS 1 or 2? Because the upper two bits of a screen byte in these modes are interpreted as color information, not as part of the character (see the modification to Program 3 below). So only the lower six bits choose a character from the character set. Six bits can represent only 64 possible combinations, which is why these modes can display only 64 characters. Bit pattern 000000 becomes a space, 100101 is an E, and 111111 becomes an underline, and so on.

When you use GRAPHICS 0 (normal text), however, there is a strange side effect. In this mode, only the single upper bit is the color bit (actually, it’s the inverse video bit). This leaves 7 bits to represent a character, so we can have values from 0 to 127 decimal (0000000 to 1111111 binary, $00 to $7F hex). Again, this value—after being multiplied by eight—is added to the value of the character set base address. But which numbers in that 0 to 127 range represent which characters?

Well, we already know what the first 64 characters are—since the Atari’s hardware limitations dictate that they must be the same as in modes 1 and 2. So the next 64 are the other characters. Program 3 illustrates how the ATASCII character set is linked to the screen set. Note how all the characters are presented twice, once in screen code (i.e., character ROM) order and once in ATASCII order. For some additional fun and info on modes 1 and 2, change line 10 to GRAPHICS 1. (Do not change it to GRAPHICS 2 unless you put a STOP in line 65 after the first FOR-NEXT loop.) Do you see what I mean about the upper two bits being color information?

Now you know why there are three different character codes used in your computer. How can you take advantage of this information? Well, if you combine this knowledge with the programs I presented last month, you could invent your own character set and design a word processor for some foreign language. (If you come up with a good Cyrillic character set, let me know.)

Actually, if you own an XL or XE machine, you have a second character set already built in. Just add this line to Program 3:

20 POKE 756,204

This tells the operating system and ANTIC that the base of the character set is at $CC00, which is where the international character set resides. Someday you might find some use for these characters. How will you know until you try?

For Instructions on entering these listings, please refer to “COMPUTE!’s Guide to Typing In Programs” In this Issue of COMPUTE!.

Program 1: ATASCII Codes
10 GRAPHICS 0
20 FOR I=0 TO 235:PRINT I
30 IF I=155 THEN PRINT " [RETURN]"GOTO 50
40 PRINT CHR$(27);CHR$(I)
50 NEXT I
60 REM USE CONTROL-1 TO PAUSE
Program 2: Keyboard Codes
10 DIM HEX$(16):HEX$="0123456789ABCDEF"
20 POKE 764,255
30 KEYCODE=PEEK(764)
40 IF KEYCODE=255 THEN 30
50 HI=INT(KEYCODE/16):LOW=KEYCODE-16*HI
60 PRINT "KEYCODE: HEX $";
70 PRINT HEX$(HI+1,HI+1);HEX$(LOW+1,LOW+1);
80 PRINT ", DECIMAL ";KEYCODE
90 GOTO 20
Program 3: Screen Codes
10 GRAPHICS 0
30 SCREEN=PEEK(88)+256*PEEK(89)
40 REM FIRST: SCREEN CODE ORDER
50 FOR C=0 TO 255:POKE SCREEN+C,C
60 NEXT C
70 REM THEN:   ATASCII ORDER
80 SCR2=SCREEN+40*8
90 FOR C=0 TO 255:CHAR=C
100 IF C>127 THEN CHAR=C-127
110 IF CHAR<32 THEN CHAR=C+64:GOTO 140
120 IF CHAR>95 THEN CHAR=C;GOTO 140
130 CHAR=C-32
140 POKE SCR2+C,CHAR
150 NEXT C
999 GOTO 999:REM WAIT FOR BREAK KEY
COMPUTE! ISSUE 71 / APRIL 1986 / PAGE 117

INSIGHT: Atari

Bill Wilkinson

Binary Files, Unite!

I’ve had several people write me that various programs designed for use with binary (machine language) files don’t work with Atari’s Macro Assembler (AMAC), OSS’s MAC/65, or a couple of other assemblers. Or possibly a program will work with a small binary file produced by these assemblers, but not with a larger one. Why all these problems when the simple Atari Assembler/Editor cartridge works so well?

The root of the problem is the Atari Disk Operating System definition of a binary file, so let’s examine that first. (Besides, maybe we’ll learn a few extra goodies on the way.) A legal Atari binary file has the following format:

  1. A header of two bytes, each with a value of 255 (hex $FF).
  2. Two more bytes indicating the starting address of a segment of the binary file. The two bytes are in standard 6502 low-byte/high-byte order.
  3. Two more bytes indicating the ending address of that same file segment.
  4. A sequence of bytes which constitute the actual binary code to be loaded into memory for the segment defined by the preceding four bytes. The number of bytes may be determined by subtracting the starting address from the ending address and then adding one.
  5. If there are no further segments, there should be no more bytes in the file.
  6. If there are more segments, then repeat this sequence of steps starting at either step 1 or step 2.

And that’s it. A really neat, clean, format. Watch out for that last step, though. First, it says that the number of segments is theoretically unlimited. Second, it says that header bytes (dual hex $FF bytes) may occur at the start of any segment. It also implies that there is no particular order necessary to a binary file; it’s perfectly OK to load the segment(s) at higher memory addresses before the one(s) at lower addresses.

RUN And INIT Vectors

Before moving on, there are two other niceties about DOS binary files worth knowing. When DOS loads a binary file (including an AUTORUN.SYS file at powerup), it monitors two locations. The simpler of the two is the RUN vector. Before DOS begins loading the binary file, it puts a known value into the two bytes at locations 736–737 (hex $2E0–$2E1). When the file is completely loaded (i.e., when DOS encounters the end of the file, step 5 above), if the contents of location 736 have been changed, then DOS assumes the new contents specify the address of the beginning of the program just loaded. DOS then calls the program (via a JSR) at that address.

The second monitored location is the INIT vector at address 738 (hex $2E2). This vector works much the same as the RUN vector, but DOS initializes and checks it for each segment as the segments are loaded. If the INIT vector’s contents are altered, then DOS assumes the user program wants to stop the loading process for a moment, long enough to call a subroutine. So DOS calls (via a JSR) at the requested address, expecting that the subroutine will return so the loading process can continue. This is a very handy feature. Most of you have probably seen it at work, such as when you run (or boot) a program which puts up an introductory screen (maybe just a title and a PLEASE WAIT message) and then continues to load.

The other important difference between the RUN and INIT vectors is that DOS leaves channel number one open while the INIT routine is called. (DOS always opens and loads the binary file via this channel.) I suppose a really tricky program could close channel one, open up a different binary file, and then return to DOS. DOS would proceed to load the new file as if it were continuing the load of the original one. Most of the time, though, INIT routines should not touch channel one.

More On Segmented Files

Back to the main subject: Why do some programs have problems with binary files produced by some assemblers? Well, if all programs followed the complete binary file format as given by steps 1 through 6 above, there would probably be no incompatibilities. Unfortunately, many people who have used no assembler except the old cartridge have ignored segmented files. They have assumed that a binary file consists of steps 1 through 4, one time only, with a single large segment. Perhaps this is because many programmers first worked with Apple DOS, CP/M, and other operating systems with not-so-intelligent binary file formats. Or perhaps it is because the supposedly simple assembler cartridge is, in some ways, smarter than more advanced assemblers. In particular, the assembler cartridge will not produce multiple segments unless the programmer specifically asks for them (via an *= directive to force a change to the location counter).

Yet other assemblers (including AMAC and MAC/65) never produce a segment longer than a particular size (usually a page-256 bytes-or less). If the programmer coded a longer segment, these assemblers automatically break it up into smaller pieces. Why? Probably to gain speed and lessen the work of assembly, since the assembler cartridge is doing a lot of work remembering the ending addresses of segments.

Now, if my only concern were those few programs which don’t properly load all binary files, I would simply have showed their authors the way to fix them. But there is a secondary advantage to programs which consist of larger segments: They load faster! Sometimes much faster. So this month I give you the BASIC program below, which takes any binary file and attempts to “unify” it. In particular, if the start address of one segment directly follows the end address of the preceding segment, they are consolidated into a single segment. And so on, so far as the space in BUF$ allows.

And, last but not least, there’s another minor bonus. Often, someone who writes an assembly language program purposely leaves space to be filled in later (e.g., by a filename, counter, etc.). If this reserved space occurs in the midst of code (probably not good practice, but it happens), it forces even the assembler cartridge to break the file into segments. But if the reserved space is significantly less than a sector (say under 50 bytes or so), it may be faster to let DOS load filler bytes. So you can change the value of the variable FILL in line 1160 (to 40, perhaps), and this program will automatically generate up to the specified number of fill bytes in an effort to better unify the file.

Whew! Was this month’s topic too heavy for you? Then write me (P.O. Box 710352, San Jose, CA 95071-0352) with your suggestions for a topic. No treatises please. One or two pages works best. Thanks.

Binary File Unifier

For instructions on entering this listing, please refer to “COMPUTE!’s Guide to Typing In Programs” in this issue of COMPUTE!.
1110 REM allocate buffer
1120 REM
1130 BUFSIZE=FRE(0)-300
1140 DIM BUF$(BUFSIZE)
1150 DIM FILEOLD$(40),FILENEW$(40)
1200 REM
1210 REM get file name
1220 REM
1230 PRINT "I need two file names: An existing"
1240 PRINT " object file and a new file which"
1250 PRINT " will get the 'unified' object code."
1260 PRINT
1270 PRINT "Existing file ? ";
1280 INPUT #16,FILEOLD$
1290 PRINT "     New file? ";
1300 INPUT #16,FILENEW$
1400 REM
1410 REM open files, validate existing one
1420 REM
1430 OPEN #1,4,0,FILEOLD$
1440 GET #1,SEGLOW:GET #1,SEGHIGH
1450 IF SEGLOW=255 AND SEGHIGH=255 THEN 1500
1460 PRINT :PRINT "Existing file: invalid format"
1470 END
1480 REM input file okay
1490 REM
1500 OPEN #2,8,0,FILENEW$
1510 PUT #2,SEGLOW:PUT #2,SEGHIGH
1600 REM
1610 REM process a new origin
1620 REM
1630 BUFPTR=0
1640 BUF$=CHR$(0):BUF$(BUFSIZE)=CHR$(0)
1650 BUF$(2)=BUF$:REM zap buffer
1660 PUT #2,SEGLOW:PUT #2,SEGHIGH
1700 REM
1710 REM process a segment
1720 REM
1730 GET #1,ENDLOW:GET #1,ENDHIGH
1740 SEGSTART=SEGLOW+256*SEGHIGH:SEGEND=ENDLOW+256#ENDHIGH
1750 SEGLEN=SEGEND-SEGSTART+1
1760 REM read segment into buffer
1770 FOR PTR=1 TO SEGLEN
1780 GET #1,BYTE:BUF$(BUFPTR+PTR)=CHR$(BYTE)
1790 NEXT PTR
1800 REM
1810 REM check head of next segment
1820 REM
1830 GET #1,SEGLOW:GET #1,SEGHIGH
1840 IF SEGLOW=255 AND SEGHIGH=255 THEN GET #1,SEGLOW:GET #1,SEGHIGH
1850 SEGNEXT=SEGLOW+256*SEGHIGH
1860 GAP=SEGNEXT-SEGEND-1
1870 IF GAP>FILL ORGAP<0 THEN 2000
1880 BUFPTR=BUFPTR+SEGLEN+GAP
1890 IF BUFPTR+256>BUFSIZE THEN 2000
1900 GOTO 1700
2000 REM
2010 REM need to dump buffer to
2020 REM prepare for new origin
2030 REM
2040 PUT #2,ENDLOW:PUT #2,ENDHIGH
2050 FOR PTR=1 TO LEN(BUF$)
2060 PUT #2,ASC(BUF$(PTR))
2070 NEXT PTR
COMPUTE! ISSUE 72 / MAY 1986 / PAGE 101

INSIGHT: Atari

Bill Wilkinson

Avoiding Disk Errors

I know many of you will find this hard to believe, but I’ve never encountered a disk error on the Atari which I couldn’t explain. Further, I have had very few DOS errors, ever. (The reasons for the few errors I have encountered, by the way, were always related to random access files—a common problem with Atari DOS 2.0 and its derivatives.) Yet after a few hundred phone calls and letters, I know that many of you have experienced the frustration of wiped-out disk files. Why? Well, I can’t know each and every reason, and I can’t repair damage that’s already been done, but maybe I can give you some helpful hints for the future.

Hands Off That Disk

Hint 1: Never, never, never take a disk out of a drive unless the program you’re using tells you to. (This goes beyond even the good advice about never removing a disk when the drive is still spinning.) In particular, never swap disks until prompted to do so. Why? Well, because the Atari disk drive has no way to tell the computer that the disk has been removed or changed.

Consider: How does any DOS know what disk sectors to allocate to a new file? Generally, a DOS keeps a list of unused disk sectors. The next time it needs to find a sector (for example, to extend a file), it takes one from this list. The list (called a Volume Table Of Contents or VTOC in Atari parlance) is usually kept on disk until a file is opened, when it is read into memory. It is rewritten to the disk when a file is closed.

Okay, now open a file for output, write some information, swap disks, and write more data. What happens? The list of sectors was correct for the first disk, but it’s extremely unlikely that it bears any reasonable relation to what exists on the second disk. Most probably, DOS will allocate several sectors which were already part of other files on the second disk. Kablooey!

If you’re using an application program, then, follow the prompts and don’t swap disks unless told to. If you’re programming and working with disk files, make sure you close all open files before swapping disks (END automatically closes all open files in BASIC). If you’re using DOS, you should be safe as long as you change disks only at the DOS prompt. Of course, when duplicating files or disks, you must swap disks when DOS tells you to.

Beware Of  RESET

Hint 2: Never hit the SYSTEM RESET button during a disk operation. For example, if you hit RESET in the middle of a SAVE, it’s possible to end up with a completely blown program. In fact, if you then SAVE the program to disk again, you could end up with a blown disk file.

This results from a really subtle bug in DOS 2.0. When DOS enters what is known as burst I/O mode (to speed up input/output), it “copies” the memory to disk. But DOS 2.0’s file organization requires that the last three bytes of each sector contain a link to the next sector in the file. How can it do this when it is writing directly from memory? Answer: By “swapping” three bytes of memory long enough to write a sector, and then restoring the bytes.

Now suppose you happen to hit RESET when those three bytes are swapped out. Oops…say goodbye to your program.

There are two ways to fix this problem. First, since DOS gets control after a RESET, it could check to see if a disk write was interrupted. If so, it could restore the three bytes. Or, second, DOS could always copy bytes to be written into a buffer, thus never disturbing the program (or data) in memory. The second approach is successfully used by DOS 2.5.

Missing Sectors

Hint 3: Avoid hitting RESET during disk operations even if you’re using DOS 2.5, because you may still mess up the disk a bit. Here’s one way: Open a file for write (OPEN #5,8,0,"D:FILE" in BASIC, for example), write some data, OPEN another file for write, write data to both files, CLOSE the first file, write some more data to the second file, and then hit RESET. What happens?

The VTOC says the sectors in the second file which were written before the CLOSE are now in use (and that was true when the CLOSE took place). If you add the number of free sectors remaining on the disk to the number of sectors used in all files, the total is no longer 707 in single density or 1010 in enhanced density, as it should be. You just lost some of your disk space.

Hint 4: Everything I just mentioned about RESET also applies to turning off the power. For example, if you have a power failure in the middle of a SAVE from BASIC or while there are some data files open in a business program, be prepared for some problems.

Fortunately, DOS 2.5 comes with a program called DISKFIX.COM which does a pretty good job of fixing up a “damaged” disk (either DOS 2.0 or 2.5). It allows you to undelete files as long as you haven’t written any new files since the deletion. At your choice it will either try to recover or permanently remove a file which was left open for output. And, most importantly, it checks each file on the disk to make sure it is OK, and then reconstructs the VTOC to ensure that all 707 or 1010 sectors are accounted for.

COMPUTE! ISSUE 73 / JUNE 1986 / PAGE 112

INSIGHT: Atari

Bill Wilkinson

Atari Printer Trivia

This month’s COMPUTE! is a printer issue, so I decided to break with (my) tradition and write a column on printers. Before we start, though, an erratum: My April column listed a program designed to “unify” a machine language file on disk. But when I sent the column to COMPUTE!, I accidentally included a couple of older versions of the program on the same disk. Guess which version got published? Anyway, COMPUTE! listed a corrected version in the article entitled “Custom Characters for Atari SpeedScript” in the May issue. (By coincidence, it happens that my program is needed to unify the COMPUTE! DISK version of SpeedScript before installing a custom character set.) On to the printers.

Number, Please

John Skruch at Atari gets credit for revealing this first tidbit. You are all aware that disk drives can be assigned device numbers (from D1: to D8:, though Atari drives can only go to D4:), but did you know that printers can have numbers, also? If you have an 800XL, 65XE, or 130XE, you may connect two or more printers at the same time and direct output to one or the other. From BASIC, for example, it’s as simple as typing

LIST "P2:"
or
LIST "P5:"

Two major drawbacks: all printers still respond as P1:, so using P1: or just P: when two printers are attached leads to humorous and/or disastrous results. Since many programs always address printers as P:, this trick may be useful only in your own programs. Also, only the following printers have these secondary numbers:

Printer Secondary
Number
850 P2:
1025 P3:
1020 P4:
1027 P5:
1029 P6:

(The 850 refers to any printer attached via an 850 Interface Module. The 1029 printer is rare in the U.S.)

The fact that the 850 can handle different printer numbers indicates that provision for this feature was included as far back as 1979 (when the 850 was first made). Do you wonder why nothing was said sooner? Why don’t the 400, 800, and 1200XL work with multiple printers? Do any other interface modules (from third-party vendors) have secondary device numbers? A prize for the best answer.

The Nine-Minute Nap

If you have a 1027 printer which is not lucky enough to be hooked up to an XE computer, you’ve probably experienced the infamous sleeping printer bug. Sometimes the 1027 just suddenly stops printing. Many people believe they need to reboot their system to wake the printer up. Actually, after about nine minutes, the printer just as suddenly springs to life again. The reasons for this are too strange and lengthy to go into here. Suffice it to say that the problem has existed since the first Atari computer was built and is related to the (also infamous) sleeping disk drive phenomenon—though the drive only sleeps about five seconds. You’ll be pleased to know that Atari’s newest operating system ROMs in the XE computers finally fix the problem.

If you do have a 1027, but don’t have an XE, and still want to fix this problem, type in, save, and run the accompanying program. It automatically seeks out the LOMEM value for your system and then creates an AUTORUN.SYS file to patch the timeout problem. The AUTORUN.SYS file will load at that LOMEM point and then move LOMEM above itself. Since it reads the current LOMEM, be sure to create the AUTORUN.SYS file on the same disk, booted in the same fashion, that you later want to use. This means, for example, that any special drivers (RAM disk, RS-232, and so on) must be installed before you run this BASIC program.

For a more specific example, let’s say you intend to use the 850’s R: driver with AtariWriter and the 1027. You must start by booting the 850’s AUTORUN.SYS file to install the R: driver in memory, then run the program below.

Also, if you have true double-density drives (not “enhanced density” 1050s), boot with double density disks inserted. This patch should work with almost any DOS, such as DOS XL, SpartaDOS, DOS 2.5, or whatever—but I wasn’t able to test them all.

Two final points: If an AUTORUN.SYS file already exists on the disk when this program is run, the 1027 patch is appended to that file. Again, using the 850 as an example, this means you’ll have a single file which serves two purposes: It boots the R: driver and makes the 1027 patch. Finally, line 170 of the listing is a REMark; if you delete the REM to enable this line, it reserves two pages (512 bytes) of extra memory. If you have any trouble running this patch, try deleting the REM. For instance, if your system has more than one disk drive, you might want to make this change.

Obviously, I did not develop this program by arbitrarily typing in funny numbers for my DATA statements. I started with a program written by Joe Miller (formerly of Atari), then fixed it so that it survives SYSTEM RESET, is relocatable, moves LOMEM if appropriate, and does not install itself twice. If you’re interested in studying the source code for this program, you can download it from CompuServe. Look in the Atari eight-bit SIG’s DL (DownLoad) section under utilities. The filename is P1027.FIX, and it’s a document (ASCII) file.

1027 Printer Timeout Fixer
140 REM first, find where LOMEM is now
150 LOPAGE=PEEK(744)
160 IF PEEK(743)<>0 THEN LOPAGE=LOPAGE+1
170 REM (see text) LOPAGE=LOPAGE+2
180 MODE=B:TRAP 200
190 OPEN #3,4,0,"D:AUTORUN.SYS":MODE=9
260 CLOSE #3
210 OPEN #3,MODE,0,"D2:AUTOTEST"
220 IF MODE=0 THEN PUT #3,255:PUT #3,255
230 READ BYTE:IF BYTE<-1 THEN 300
240 IF BYTE=-1 THEN BYTE=LOPAGE
250 PUT #3,BYTE:GOTO 230
290 REM (all data in file)
300 CLOSE #3
310 END
890 DATA
900 DATA 163,49,208,19,104,133,49,140
910 DATA 81,-1,160,1,24,177,50,161
920 DATA 49,105,0,72,172,81,-1,76
930 DATA 80,-1,8,120,162,0,160,-1
940 DATA 236,12,2,208,3,204,13,2
950 DATA 240,18,173,12,2,141,24,-1
960 DATA 173,13,2,141,23,-1,142,12
970 DATA 2,140,13,2,40,32,86,-1
980 DATA 160,-1,204,232,2,144,9,200
990 DATA 140,232,2,169,0,141,231,2
1000 DATA 96
1005 DATA 0,64,33,64
1010 DATA 169,-1,203,232,2,144,26,208
1020 DATA 3,173,231,2,208,21,32,26
1030 DATA -1,163,12,141,62,-1,165,13
1040 DATA 141,63,-1,169,26,133,12,169
1050 DATA -1,133,13,96
1060 DATA 226,2,227,2,0,64
1070 DATA -9999
COMPUTE! ISSUE 74 / JULY 1986 / PAGE 106

INSIGHT: Atari

Bill Wilkinson

Tried And True Tools

In keeping with COMPUTE!’s programming languages theme for this month, I’d like to share some thoughts about programming in general and better use of the available languages in particular. I have long contended that, for most purposes, owners of Atari 400/800, XL, and XE computers have all the languages they need. You won’t do parallel array processing with a 6502, no matter what language you use, but you can balance your checkbook, keep track of your mailing list, access online services via modem, write a book or two, and (of course) play some games. All of those applications and many more have been written with languages now available for the eight-bit Atari computers. What more can you ask for?

In a previous column I said it would be hard for most users to justify trading up to an ST, an Amiga, or whatever. If anything, I feel more strongly about that now. I still write this column using a good old Atari 1200XL (I like its keyboard best) and an Atari 825 printer (ancient history). Sometimes I wish for an 80-column screen or a hard disk drive—keeping track of 200 floppies is not my idea of fun—but I can’t justify the expense for the extra convenience.

The same is true when it comes to programming languages. Admittedly, I’m a language junkie. I love learning new languages and/or tricks with old languages. So it would seem that the ST would be a dream machine for me. Despite its youth, the number of languages either available or coming soon is phenomenal: several varieties of BASIC, Logo, Pascal, C, LISP, Modula-2, COBOL, FORTRAN, Prolog, Forth, and 68000 machine language. There are probably others, too.

Old Machines, New Projects

But for owners of eight-bit Ataris, the situation is far from bleak. Though some of the language implementations are not as rich as those on the ST, we can enjoy Pascal, C, Logo, Action!, Forth, PILOT, 6502 machine language, and some extraordinarily easy-to-use BASICs.

Even though I’ve been using Ataris for six years now, I still see some interesting projects to do—projects that I’ve never done or which I think can be done better. A few examples: How about a terminal program written in Action! that is designed to work well with CompuServe’s conference mode? Or a GEM-like interface for DOS? Or a combined spreadsheet/database written in BASIC XE and commented liberally so that even beginners can see the methods used? I know I’ll never do all of these, but they are challenges I’d like to tackle.

Rethinking The Problem

Moving to new languages on new machines is not always an advantage. Eor instance, in ST BASIC, strings cannot exceed 255 characters in length. Atari BASIC strings can be up to 32,767 characters long, if you have the memory available. (Yes, ST BASIC allows string arrays, but so do BASIC XL, BASIC XE, and Atari Microsoft BASIC.) There are many other examples.

Another factor is that the speed and power of the newer machines is of little advantage for some applications. Other than missing an 80-column screen, I can use CompuServe or various bulletin boards just as well with my $100 computer as I can with the company’s $1,000 machine. Besides, the modem for the $100 computer is cheaper. And by the time you read this, Atari may have released its 80-column adapter for the eight-bit line.

Suppose you’re writing a program that does need more speed, however. What can you do other than buy a newer, faster computer? Well, you could buy a better, faster language. That’s a lot cheaper than buying a new computer—for which you still might need an extra language or two. On the other hand, maybe you don’t have to buy anything at all; maybe you just need to rethink your solution to the problem. Let me show you what I mean.

Program 1 is very similar to one which I found in a recent user group newsletter. The author was responding to a member’s inquiry about writing a routine to shuffle a deck of cards. As you know, when BASIC gives you a random number, there’s no guarantee it won’t give you that same random number twice, perhaps even several times. For a quick example, type the following line and press RETURN: FOR I=0 TO 9:PRINT INT(10*RND(0)):NEXT I

This asks for ten random numbers in the range 0 to 9. Did you actually get ten different numbers? The odds are very much against it.

The Super Shuttle

Program 1 demonstrates this problem by dealing out an entire deck of 52 cards. As each card is dealt (by suit S and rank R, line 210), its spot in the C (card) array is marked. Then, if the random number generator picks that card again, the pick is ignored (line 230). The only things I added to the original routine are the counters (C and T) which count how many picks it takes to get each card and the entire deck. Can you guess how many picks it takes to get the entire deck? In 50 tests, it took a minimum of 128 picks and a maximum of 457, with the average around 220. The result, as you’ll see if you run the program, is that it can take as long as five or six seconds to pick a card.

Now look at Program 2, which does exactly the same job but never takes more than one pick to get the next card in the deck. It works by using a single string (CARD$) to represent the entire deck. When it gets a random number from 1 to 52, the program removes the corresponding “card” from the “deck” (lines 400 and 410). The next time it picks a card, it gets a random number from 1 to 51. Each time the computer gets a card, the range of random numbers gets smaller. Simple. And it works by taking advantage of the string operations in Atari BASIC.

The point of this exercise is to show that sometimes the best way to fix a slow or inefficient program is to rethink it and then rewrite it. I’d be willing to bet that Program 2 on an eight-bit Atari runs faster than Program 1 on an Atari ST. If you have access to both machines, you might want to try it. And try improving your own programs. (Even while writing this column, I found a way to improve Program 2 even more. Can you find it?)

One last comment: Notice the readability of the two programs. Which one is cryptic and which one almost explains itself? Meaningful variable names can add a great deal of value to any program.

COMPUTE! ISSUE 75 / AUGUST 1986 / PAGE 106

INSIGHT: Atari

Bill Wilkinson

Many people have asked me to discuss the use of the DOS 2.5 RAM disk with Atari computers other than the 130XE. Most are interested either in one of the 800XL memory upgrade kits now available or in simply using the extra 16K memory of an XL as a very small RAM disk. Since I’ve seen the subject treated incorrectly in several user group newsletters, I decided that some mildly technical discussion here would not be amiss.

Many months ago, in one of my columns, I described the memory map of an Atari XL computer. This time, let’s see how a 130XE is a fairly simple expansion of the XL models.

An Atari 130XE has 126K—not 128K—of Random Access Memory. (Keep in mind that one kilobyte equals 1,024 bytes.) The first 62K is used and accessed exactly the same way as the 62K in the 1200XL and 800XL (that 62K is not a typo, either—more on this later). Now, a 6502 microprocessor can address a total of only 64K of contiguous memory, because the address counter goes from 0 to 65535 (64 * 1024). In the hexadecimal (base 16) numbering system used by computers, those addresses are expressed as $0000 (0) to $FFFF (65535). When the address counter passes $FFFF, it rolls back to $0000 again. This is kind of like a car speedometer which only goes to 99,999.9 miles; another tenth of a mile and you have a new car again.

So, how does the 130XE access its extra 64K of memory? By a technique known as bank selection.

Cashing In At The Memory Bank

The extra 64K in the 130XE is divided into four separate 16K banks. The 6502 can access only one of these banks at a time. But wait, you say, if the main memory uses up the full addressable range of the 6502, where do these extra banks fit in?

The answer. 16K of the main memory (that is, of the regular 64K) is disabled. Effectively, then, a 130XE has five banks of RAM, each consisting of 16K, plus another 46K (not a typo) which is not bank selected.

Now comes the important part: Just where, within the 64K address space of the 6502, are these five banks addressed? As Appendix H of the 130XE owner’s manual states, the selectable 16K bank falls between locations 16384 (hex $4000) and 32767 ($7FFF). This is the second quarter of the 6502’s 64K memory space. Why was this 16K area chosen instead of some other area? Because the first quarter of memory includes zero page, and bank-selecting zero page is a tricky proposition in a computer which is handling interrupts. The other two quarters of memory share space with cartridges and/or the operating system ROM, which would make programming more complicated. Thus, the second quarter of memory wins by default.

Okay so far. Now let’s consider where BASIC programs reside in memory. Generally they begin at a memory location called LOMEM, which can vary but is usually between $1C00 and $2400 (about 7000 and 9000) when DOS is booted. BASIC programs always end below screen memory, which in turn is below the BASIC ROM. In practice, this means that BASIC programs and their variables are limited to a length of about 31K.

Let’s assume that LOMEM is at $2000 (8192). Let us also assume that we have loaded or typed in a BASIC program which is 12,000 bytes long. Where does that program end? Smack dab in the middle of the second quarter of memory, where the banks are selected.

You might think that this would cause a problem on a 130XE, since it has to switch that bank of memory on and off. But it’s not a problem, because one of those five banks is assigned to be main memory—that is, the memory corresponding to the only memory at that address in a 1200XL or 800XL. The DOS 2.5 RAM disk never touches that bank; it limits itself to the other four banks.

Okay, enough background on the 130XE. Is there a way to use the extra 16K memory of the 800XL as a RAM disk? Yes, but it isn’t easy. That extra memory is addressed from $C000 to $FFFF (but see below for an exception). Aside from the fact that DOS 2.5 wasn’t designed to see a RAM disk in this address range, this range is shared with the operating system ROMs and the hardware input/output area. Shared? Yep, more bank selection. And this bank is even trickier to use.

To Be Continued

Just as things start to get interesting, I run out of room. There is much more to this topic. For example, we haven’t even looked for the missing 2K of RAM in the XLs and XEs, have we? And wouldn’t it be nice to consider the effects of some of the add-on memory kits for the XLs? Until next month, let me tantalize you with some tidbits.

The RAM disk which emulates drive 8 (D8:) is one of the nice features of DOS 2.5. One of the not-so-nice features is that the RAM disk is always D8:. Many, many programs which want two disk drives assume that the second drive is D2:. Wouldn’t it be nice if we could change the RAM disk’s drive number? Say no more. The BASIC program listings below accomplish this for you.

Program 1, “REPLACE.BAS,” is for use with the RAMDISK.COM program supplied with DOS 2.5. After you boot the system with DOS 2.5 and RAMDISK.COM, this program simply changes all the magic memory locations in DOS so that the RAM disk is now addressed as D2:, (Or you can change lines 190 and 260 to make the RAM disk emulate any drive from D2: to D8:.) If you use Program 1, the DOS files DUP.SYS and MEM.SAV will be on D2:, but otherwise DOS 2.5 will be unchanged.

Program 2, “MAKERAM.BAS,” serves another purpose. As you’ve probably noticed, DUP.SYS and MEM.SAV take up a lot of room on the RAM disk. True, keeping them on the RAM disk does make DOS easier to use. However, if your program won’t use DOS but could use more RAM disk space, why not leave them on D1:? That’s exactly what MAKERAM.BAS does. It initializes and installs the RAM disk, but copies no files to it— all 499 RAM disk sectors are available for your use. Naturally, you may choose any drive number for the RAM disk (see lines 190 and 260 again). And, although we could change this program to allow it to work after RAMDISK.COM has booted, it is a waste of time since this program reinitializes the RAM disk, anyway. Therefore, you should erase or rename the RAMDISK.COM file when using MAKERAM.BAS (but don’t erase your only copy of RAMDISK.COM).

Finally, Program 3, “MAKERAM.SUB,” simply changes Program 2 into a subroutine which you can include in your own programs. Use it anytime you want your program to initialize a blank RAM disk.

COMPUTE! ISSUE 76 / SEPTEMBER 1986 / PAGE 111

INSIGHT: Atari

Bill Wilkinson

Five-Year Retrospective

This month marks my fifth anniversary writing “INSIGHT: Atari” for COMPUTE!. In the course of the last five years, I’ve covered a lot of different topics. Just for fun, I decided to look back through the last 60 issues of COMPUTE! and engage in some healthy self-criticism—listing the worst of Wilkinson as well as the best.

You may or may not agree with my assessments. But the point isn’t simply to rate what’s been done. After five years of writing about the same family of machines, it can be difficult to come up with a fresh topic every month. As you read these lists, let me know about some new topics you want me to cover, or some old topics that could stand further explanation or a fresh treatment. Not all of you have been reading COMPUTE! for a full five years, after all. And even long-time programmers can grow rusty in certain areas. This column is designed to serve you, the readers, so please provide some feedback in a card or letter addressed to:

Bill Wilkinson
P.O. Box 710352
San Jose, CA 95171-0352

The Brightest And Best

First, here’s what I consider the best of “INSIGHT: Atari.” Whether you agree will depend on your own viewpoint and needs. I have listed articles chronologically within broad categories.

Not So Memorable

Now for the less memorable columns. Some of my self-appointed projects have met with less than enthusiastic response. Perhaps the worst of these was “BAIT,” a pseudo-BASIC interpreter written in Atari BASIC. The program was supposed to show you how language interpreters worked: It was so slow that you could literally watch the FOR-NEXT loops plod along. I prolonged the agony for four months (March, May, June, and August 1983).

Then I tried to rescue 1050 disk drive owners with an enhanced version of DOS 2.0S. It worked, but I doubt that more than a couple of dozen readers managed to get it installed properly. This series appeared May through September 1984. Less than four months later, we reworked DOS 2.0S for Atari to produce DOS 2.5. More time and energy down the drain.

My April Fool’s columns have always received mixed reviews. This year, I got distracted and actually forgot to do a joke column. A couple of readers wrote me to compliment me on my restraint. Thanks, folks.

Some of the funniest installments of “INSIGHT: Atari” were unintentionally humorous, consisting of various predictions regarding future Atari products. I could have done better with a ouija board.

In addition to the obvious honkers, I’ve omitted from this list several columns which were relevant at the time they were written, but have since become outdated. One general regret is that I covered certain topics in less depth than now seems desirable. But that’s a difficult factor to measure. When I invite you to explore a subject, do you ever sit down to research it further? If so, then I have succeeded. If not, perhaps the topic is inappropriate, or the treatment needs to be refined. Again, the more feedback you provide, the better I can meet your needs.

Truth Stranger Than Fiction

Since I just made fun of my precognitive powers, it’s only fair to mention that one of my predictions is actually coming true. In July 1984, Jack Tramiel and company had just bought Atari. I wrote a column (published in October that same year) containing several predictions about what the “new” Atari would produce. On some points, I was correct: The 1450 died quickly, and the “Atari MAC” was already under development (it became what is now the ST).

Though it caused chuckles at the time, I also stated that Atari would continue to produce game machines and that they would soon come out with the already-designed 7800. As it happened. Atari sold over a million 2600 game machines in 1985. And, at the 1986 Summer Consumer Electronics Show, Atari announced that the 7800 will be available this autumn. Now, how would you like to know what’s in store for 1988?

COMPUTE! ISSUE 77 / OCTOBER 1986 / PAGE 110

INSIGHT: Atari

Bill Wilkinson

A Special RAMdisk For The 800XL

This is a continuation of my August column, wherein I discussed some of the ins and outs of memory bank selection on a 130XE computer and gave you a means of referring to your RAMdisk as something other than D8:. At the end of that article, I promised that the September issue would talk about why a 130XE has only 126K bytes of RAM, and other oddities. As you probably noticed, I got sidetracked last month. I hope you didn’t mind too much my reminiscing, and I promise to get back to work with this issue.

In fact, let’s start working now: You’ll recall that I had posed the question “Is there a way to use the extra 16K memory of the 800XL as a RAMdisk?” My answer was a hesitant yes, because it isn’t easy (it took me a relatively long time to prepare this article). For example, the extra memory of the XL is located from $C000 to $FFFF (the top 16K bytes of the 6502’s address space), which is the same space used by the OS ROMs and the I/O hardware registers (another instance of bank selection). What’s wrong with that, you ask? Why can’t I just turn off the ROMs and I/O registers and start using the underlying RAM?

With Frightening Regularity

Well, to start with, any time an interrupt occurs, the 6502 looks in some locations in the top of memory (between $FFFA and $FFFF) to find the address of the routine which will process the interrupt. If we have turned off the OS in order to use the extra RAM, those locations surely will contain garbage. And interrupts occur on Atari computers with frightening regularity: once every 1/60 second for screen refresh, once every time a display list interrupt is encountered, once for each key press; the list goes on.

Still there are more problems. Remember all those references in the August issue to 62K of RAM and 126K of RAM, when you would expect the figures to be 64K and 128K? Well, it turns out that, even if we disable the OS ROMs in order to access the extra RAM, there is no way to disable the hardware I/O space (which occupies addresses $D000 through $D7FF). There simply is no RAM in these 2K. Period. So we are down to 14K of hard-to-use RAM with a nasty hole in the middle of it.

Any more nasties to contend with? Yes. When your Atari is displaying text of any kind (GRAPHICS 0, 1, or 2, or the text window in other modes), the ANTIC chip gets the shapes of the characters to display from one of two character sets in ROM (American version at location $E000, international set at $CC00). If we turn off the ROMs, either we must first copy the character sets to RAM (thus decreasing usable RAM still further) or we must turn them off only while no characters are being displayed (for example, during the vertical blank interval).

And let’s throw in one more monkey wrench: With all versions of DOS 2, including DOS 2.5, the VTOC (Volume Table Of Contents) sector and the directory sectors are smack-dab in the middle of a 720-sector disk. That means they use sector numbers 360 through 368. Hmmm—if we have a 16K RAM-disk, we have 128 simulated sectors. And 360 is bigger than 128. Kablooey.

A Tall Order

So, without major surgery, DOS 2.5 cannot use the 800XL’s extra RAM as even a small RAMdisk. Work to be done includes (1) changing DOS 2.5’s RAMdisk handler to use a different 16K range of memory; (2) fixing the bank select logic so that it turns the OS ROMs on and off instead of actually selecting banks; (3) somehow changing the RAMdisk initialization code so that it knows we have only one bank of RAM and that even that bank has a 2K hole in it; (4) somehow moving the simulated VTOC and directory sectors into our limited 14K (112 pseudo-sector) range; (5) disabling all interrupts while we access the RAM; and (6) only accessing the RAM during the vertical blank interval.

Whew. Tall order, no? The only easy task here is item 6. When we first worked on DOS 2.5, the 130XE hardware had this same restriction, and there is still a flag buried in DOS 2.5 which tells it to wait for the vertical blank period before doing its simulated sector I/O.

Well, the listing accompanying this article does all of the above. When you enter and run this program, it creates a new version of RAMDISK.COM, the special boot file that DOS 2.5 uses, which indeed gives you a 14K RAMdisk. The program is only for 800XL owners, and only for DOS 2.5. It won’t work with any other combination of computer or DOS. The program overwrites the existing RAMDISK.COM file on the DOS disk, so be sure you have a backup if you want to keep a copy of the original file.

Some other cautions are also in order:

  1. Don’t hit the RESET key while the RAMdisk is active. This is a sure way to scramble the contents of the RAMdisk.
  2. Don’t try to format the RAM-disk (and this means don’t use a BASIC program which uses XIO 254). This version of RAMDISK.COM cheats a little: Because of the need for making a hole in the middle of the pseudodisk where the I/O registers are, and because we have to insure that the directory area is within the 16K bounds, we have to tell DOS that some sectors on the disk are already in use. We do this by modifying the VTOC of the RAMdisk after it has been formatted. If you reformat the RAMdisk, DOS may try to use those nonexistent pseudosectors and crash your computer.
  3. This is a very small RAM-disk. If you use it, you’ll find 105 free sectors is the maximum. Even to get that figure, I cheated: I allowed only 3 sectors for the directory instead of the customary 8, so you can have a maximum of 24 files on this RAMdisk (probably still overkill). However, DOS does not know about this limitation, and you can crash the system by creating 25 files.
  4. Don’t use DOS’s Write DOS Files menu command after booting with the RAMDISK.COM created here. This program actually puts patches right in the middle of DOS, and trying to use an ordinary RAM-disk with the patched DOS could be disastrous.

Although the program here is written in BASIC and creates the RAMDISK.COM file directly, I’ve made the original assembly language source code available on CompuServe under the filename RAM14K.ASM in the Utilities section of the DownLoad libraries (also known as DL3). I know I promised to do that with the 1027 printer fixer program back in June, but the file never appeared. The explanation is sad, but simple: The disk with my June program on it went bad shortly after I wrote the article. Let that be a lesson: Back up everything. I promise to back up this program many times over.

Also, here’s an idea for improving this program: It turns out that a total of 105 sectors is 18 sectors greater than the minimum needed to put DUP.SYS and MEM.SAV on the RAMdisk. So why not do so and aid the performance of DOS 2.5 tremendously? The source code is on CompuServe, so have at it.

Finally, there is an error in the 1027 printer fixer listing in my column in the June issue. Line 210 should read:

210 OPEN #3,MODE,0,"D:AUTORUN.SYS"

The error is mine; I gave a test version to COMPUTE! instead of the final one, hence the name “AUTOTEST” in the listing in June.

1000 REM This program creates a
1010 REM DOS 2.5 RAMDISK.COM file
1020 REM for 800XL owners to allow
1030 REM use of RAM under OS ROMs
1040 REM as a small (105 sector)
1050 REM RAMdisk.
1060 REM
1070 OPEN #1,8,0,"D:RAMDISK.COM"
1100 READ BYTE
1110 IF BYTE>=0 THEN PUT #1,BYTE:CKSUM=CKSUM+BYTE:GOTO 1100
1120 CLOSE #1:IF CKSUM<>15523 THEN PRINT "ERROR IN DATA STATEMENTS":STOP
1130 END
5000 DATA 255,255,223,7,223,7,0,128
5010 DATA 7,128,7,8,137,11,137,11
5020 DATA 8,63,21,63,21,49,141,20
5030 DATA 157,20,201,3,144,4,40,160
5040 DATA 139,96,32,203,18,165,67,74
5050 DATA 74,9,192,222,18,235,18,106
5060 DATA 106,106,8,173,1,211,74,40
5070 DATA 42,141,1,211,96,0,128,58
5080 DATA 128,173,10,7,9,128,141,10
5090 DATA 7,32,224,7,162,112,169,254
5100 DATA 157,66,3,169,55,157,68,3
5110 DATA 169,128,157,69,3,169,0,157
5120 DATA 74,3,157,75,3,32,86,228
5130 DATA 48,13,160,74,185,0,129,145
5140 DATA 69,136,16,248,32,148,16,96
5150 DATA 68,56,58,0,0,129,73,129
5160 DATA 2,105,0,105,0,0,0,0
5170 DATA 0,0,15,255,255,255,0,0
5180 DATA 255,255,255,255,255,255,255,15
5190 DATA 255,255,128,0,0,0,0,0
5200 DATA 0,0,0,0,0,0,0,0
5210 DATA 0,0,0,0,0,0,0,0
5220 DATA 0,0,0,0,0,0,0,0
5230 DATA 0,0,0,0,0,0,0,0
5240 DATA 0,0,0,0,0,0,0,0
5250 DATA 0,0,224,2,225,2,0,128
5260 DATA -1,(END OF DATA)
COMPUTE! ISSUE 78 / NOVEMBER 1986 / PAGE 90

INSIGHT: Atari

Bill Wilkinson

Your Roving Reporter

I attended (and exhibited at) the Los Angeles Atari Computer Faire on August 15 and 16, and I would like to share a few things I saw and a few thoughts I had. The most significant part of this Faire was probably Atari’s presence. As far as I know, this was their first real participation in a user group-sponsored event, and they were there in force. Such Atari notables as Sam Tramiel, Sig Hartmann, John Feagans, Neil Harris, Mel Stevens, and Sandy Austin (and others who will undoubtedly embarrass me by asking me why I forgot them) all made an appearance.

Faster ST Graphics

Most important were the products being shown there for the first time. Atari’s new blitter chip for the ST was being put through its paces. This chip takes over some of the graphics processing (such as moving sprites) that must be done in software on current ST machines. Depending on the type of processing, this chip should make graphics-oriented programs run from two to six (my estimate) times faster.

The 80-column adapter for the eight-bit machines was also on display, as was a new word processor for the ST: Microsoft Write. Although it is another nice, solid word processor, I did not see any really exciting features. But the very presence of Microsoft in the Atari world is expected by many to lend respectability to the ST machines.

The real battle for attention, though, was among the various purveyors of music software for the ST machines, particularly by the MIDI-oriented companies. Sounds ranged from exotically electronic to a guitar so realistic I thought it was a live accompaniment.

The Catalog (honest, that’s the company’s official name) people were showing off animated 3-D graphics, which wasn’t too surprising, given the capabilities of Tom Hudson’s CAD 3-D program. But then they added liquid crystal “shutter” glasses for true 3-D vision and a glimpse into some fascinating future possibilities. Liquid crystal glasses are not exactly a convenience store item (they usually go for hundreds or even thousands of dollars—mostly to the military), but you can expect to buy a pair sometime early next year for $150 or so, according to the exhibitors.

Significantly missing, though: the game companies. No Brøderbund, no Sierra On-Line, and so on. What a turnaround from the early days of the West Coast Computer Faire. Most attendees probably didn’t complain, though, since there was a good deal of software for eight-bit and ST machines. There were literally hundreds of titles available in each category, even though the Faire organizers purposely limited the number of dealers at the Faire to four, and one of those sold no eight-bit software.

Finally, the show was put on by an association of user groups, and almost every member I talked to was pleased by the show and the turnout. Final figures were not in as I left, but John Tarpanian, president of both HACKS and ACENET, estimated the crowd for the two-day event at 3000 people. It seemed at least that big. Atari is encouraging at least two more such shows that I know of: one right here in San Jose in September, and one in Portland in October. There’s another show in Virginia in November, though it’s not as closely tied to Atari as these other three. I suggest attending one of these if you can.

Join Your Local User Group

This is the first of my answers to readers’ inquiries, and it ties in neatly with the discussion above. Several people asked me where they could get (1) help with their hardware and/or software, (2) cheap public-domain programs, or (3) up-to-date news on events of the Atari world. My answer to all three? Join a user group.

I have pushed user groups in this column before, and I will probably do so again. At the Faire, for example, one person thanked me for getting him involved in a group—he had quickly gotten the help he needed. I asked him if he’s now returning the favor to newer members. He is. He’s the club’s librarian.

There are over 300 active user groups in the U.S. now, so there’s a good chance there is one near you. And if you join one, maybe you can help put on one of these Faires in the next year or two.

How do you find a user group? Ask a local dealer or look for announcements in newspapers. And user groups: Be sure to have a publicity chairperson who gets you mentioned in your hometown paper from time to time. If you are absolutely desperate, send me a self-addressed, stamped envelope, and I will give you the address of the closest group on my list. Send your request to P.O. Box 710352, San Jose, CA, 95171-0352. No guarantees of a good match, though.

Also, if you have a modem, you might like to know that I have an account on CompuServe. You can leave messages for me by using my account number: 73177,2714. I expect to be active on Delphi in the near future, too, but I don’t have an account name for that service yet. Please understand that I cannot give long-winded answers online. It costs money, remember. But I don’t mind comments, suggestions, or even quick questions.