Errors in Abacus
by Charles F. Johnson
Charles F. Johnson is a professional musician, and now semi-professional computer programmer/reviewer/author. He lives in Los Angeles with his wife Patty and Spike, the world's most intelligent (and gluttonous) cat. Charles is a sysop on the Analog and ST-LOG Atari SIG on Delphi; his user name is CFJ.
One of the hardest things about programming the ST is just figuring out what everything means. You come across cryptic terms like "message pipes," "object trees," "memory form definition blocks"...yikes! What are these things? Who can you turn to for help? This is not my beautiful house! This is not my beautiful wife! (Apologies to the Talking Heads.)
In this article, I'm going to take a close look at a couple of the reference books available to the would-be ST programmer who doesn't want to cough up $300 for the Atari Developer's Kit. I've used just about all of the popular ones myself (including the Developer's Kit), and unfortunately every one of them contains numerous mistakes. I'll provide a listing of some of the errors I've encountered in my own programming exploits, and hopefully spare one or two of you the woes I've had to go through. (Sob! Boohoo!...SLAP! Thanks—I needed that.)
By now, everyone knows that Abacus has cornered the market on reference books for the ST. At last count, they had no less than 12 titles, covering everything from beginner's Logo and ST Basic to 3D graphics in assembly language. Most of the Abacus books do a very decent job of covering their subjects and are fairly well organized, although some lack indexes and other niceties. One has to wonder, though, if Abacus employs a proofreader at all... many of their books are inexcusably full of typos, misspellings, and just plain bad English. Of course, some of them are translated from German, which probably accounts for the contorted phrasing; but at times, reading an Abacus book is somewhat akin to reading Lewis Carroll's Through the Looking Glass.
For the programmer, two of these books are essential: ST Internals and the GEM Programmer's Reference. These two books contain most (certainly not all) of the information you'll need to program the ST; in fact, if you don't want to use GEM (i.e. no dialog boxes, drop-down menus, or any of that stuff), ST Internals will do quite nicely by itself. Actually, I have to admit I'm surprised that Abacus got permission to print the section on the Line A graphics primitives at all—the Line A document in the Atari Developer's Kit is marked "Confidential!" on each and every page!
Unfortunately, as valuable as ST Internals is, the typo monster ran amok in this book. There are so many mistakes that I'm not even going to try to list them all. Watch out for the function numbers they use in the examples for the GEMDOS calls; sometimes they're wrong, even though the descriptions use the right numbers. Another common error in Internals shows up in a lot of the GEM-DOS examples in assembly language. GEMDOS is called from assembly language by pushing parameters on the stack, doing a TRAP #1 (the 68000's TRAP instruction causes a branch through a vector contained in low memory; there are 16 possible TRAP vectors), and then correcting the stack pointer. In many of the examples in Internals, they add the wrong value to the stack pointer to correct it. This can lead to big trouble, and it can be very hard to find this kind of error in a large program; so if you use the examples in Internals as guides for your own routines be sure to double-check your stack corrections.
Since this article was first written, Abacus has released two subsequent editions of ST Internals. The second edition fixed some but not all of the most glaring errors. The recently-released "Third Revision" is a substantial improvement over its predecessors, although many errors and typos still remain. This edition contains quite a bit of new material, including information about GEMDOS memory management and the blitter chip, and a commented disassembly of the first part of the ST's ROM. Many more assembly language examples are given as well. If you're considering buying ST Internals, by all means try to make sure you get the third revision. If, however, you already own a copy of the first or second edition, you may find the error list provided below invaluable.
Some of the worst mistakes in the first and second editions of ST Internals:
Pg. 105—The second line of the example for the TERM function should read "TRAP #1." They left out the "#1."
Pg. 110—The description of the SETDRV function (# $0E) is misleading. It reads, "The current drive can be determined with the function SETDRV." It should say, "The current drive can be set...." Also, the last sentence in the description is wrong. It should say, "After the call, D0 contains a bit map of the active drives."
Pg. 113—In the example for the SUPER call (# $20) the fourth instruction is given as "ADD.L $6,SP." This should be "ADD.L #6,SP."
Pg. 114—The wrong value is added to the stack in the example for SET DATE, function number $2B. That "ADDQ.L #6,SP" should be "ADDQ.L #4,SP."
Pg. 115—The same mistake is made in the example for the SET TIME function.
Pg. 120—In the third paragraph of the description of the CREATE function, the second sentence contains a typo. It should read, "Attribute $04 creates a ‘hidden’ file and attribute $02 a ‘hidden system’ file."
Pg. 122—In the example for the OPEN function, the second line of code should read, "MOVE.L #filename,—(SP)."
Pg. 124—The wrong function number is used in the example for READ—function number $3F. The example incorrectly uses $3E.
Pg. 125—In the example for UNLINK (function $41) there's a "#" sign missing from in front of the label "pathname." The first line of code in the example should read "MOVE.L #pathname,—(SP)."
Pg. 130—In the second example for the MALLOC function (# $48), the fifth line of code is wrong. It says, "TST.W D0." It should read, "TST.L D0."
Pg. 133—Some important information is missing from the description of the EXEC call (# $4B). The mode word can be 0, 3, 4, or 5, not simply 0 or 3 as Abacus states. Here are the functions of each mode:
0 = Load a program and immediately start.
3 = Load a program without executing. The address of the program's basepage (or an error message) is returned in D0.
4 = Execute program loaded with mode 3. Pass zeroes for the environment and filename, and pass the address of the basepage (returned from mode 3) as the command line.
5 = Create a basepage.
Also on page 133, the wrong value is added to the stack in the example. "ADD.L #14,SP" should be "ADD.L #16,SP." Pg. 135—In the paragraph dealing with the 44-byte DTA buffer, bytes 26 through 29 are described as the "File size in bytes (low byte, high byte)." This is incorrect; the file size is in standard Motorola format, high byte to low byte. Also on page 135, the example given for the SFIRST call is very confusing. Here's how it should appear:
(SEE TABLE 2)
Pg. 160—The top line of this page should read:
3 logbase get logical screen base
Pg. 162—Another wrong value added to the stack! This time it's in the example for the XBIOS setscreen function (# 5). In both examples, the "ADD.L #10,SP" should be "ADD.L #12,SP".
Pg. 165—In the description of the XBIOS floprd function the possible sector numbers are listed as 0-9. They should be 1-9. (Do you think the person who wrote that ever actually used this function?)
Pg. 176—The description of the XBIOS keytbl function is rather garbled. To get the address of a table containing the three keyboard table pointers, pass —1 for all three parameters.
Pgs. 192,193—The descriptions of the offgibit (- 29) and ongibit (- 30) functions are reversed. Also, the descriptions say to pass the number of the bit you want to change—wrong; you pass a word value that will be ANDed or ORed with the register.
Pg. 203—In the assembly examples for the wvbl function (wait for vertical blank), the wrong function number is used. It should be 37, not 36.
Pg. 223—The description of the Line A TRANSFORM MOUSE opcode is missing some important data. The book says 34 words are necessary to define the new mouse form; actually, 37 words are necessary. Add these three lines to the beginning of their list of parameters:
INTIN(0) Hot spot X position. (0-15).
INTIN(1) Hot spot Y position. (0-15).
INTIN(2) Number of color planes.
Pg. 224—In the description of the Line A DRAW SPRITE opcode, word 3 (the format flag) is given incorrectly. The book says "0 = VDI format, 1 = XOR format"; it should be "0 or 1 = VDI format, -1 = XOR format." Actually, I think any positive number denotes VDI, and any negative number denotes XOR.
Pg. 249—Location $44C is described as a word value (two bytes). This location contains the current screen resolution (0 = low, 1 = medium, 2 = high) and is a byte value, not a word.
Pg. 251—At the top of the page, the system variable swv__vee at location $46E is described incorrectly. The book says, "A branch is made via this vector with the screen resolution is changed." That "with" should be "when." Also, the book doesn't say that this vector is only used if you change from a monochrome to a color monitor, or vice versa. The vector is not used when you switch between medium and low resolutions.
Pg. 251—The default value for location $484 is incorrect. It should be 7 not 6.
Pg. 253—The default value for location $4BA (the 200Hz timer) is given as $71280. This isn't strictly wrong; but it is kind of ridiculous, since location $4BA is incremented every 200th of a second. The Abacus "default value" is just what happened to be there at the instant they looked.
This error listing probably doesn't cover all of the mistakes in ST Internals; but it should give you an idea of the kinds of things to watch out for if you're using this book.
Another problem with the Abacus ST Internals book is that the names given for the GEMDOS function calls are all different from the names listed in the bindings for both Alcyon and Megamax C. This isn't really an error; after all, it doesn't matter what names you use for the functions. However, if you're programming in C it can be hard to find the proper descriptions since Abacus and your C manual will disagree on the function names. The chart in Figure 1 lists each GEMDOS function with both its "Abacus" and its "legal" name ("legal" meaning the name given to it in the C bindings).
The GEM Programmer's Reference contains fewer errors than ST Internals. The worst error (one that caused me tons of frustration during a recent programming project) is lurking in their examples for application initialization in assembly language (not in the C example). The initialization examples are found in three places in the Programmer's Reference; pages 50-53, 249-254, and 271-272. In all three examples, they fail to save and use the proper value for the VDI handle. GEM initialization is achieved by several steps:appl__init, followed by graf__handle, followed by v__opnvwk. The graf__handle call returns a value that is passed to the v__opnvwk call; then v__opnvwk returns a value of its own, which should be used as the "handle" number for all VDI function calls. In the Programmer's Reference, they use the value returned by graf__handle as the VDI handle ....this is wrong, wrong, wrong! After the v__opnvwk call, the real VDI handle is returned in the application's control array, in control. Using the value from graf__handle can lead to all kinds of impossible-to-track-down bugs. In the case of my program, it ran fine without a single problem but caused mucho havoc with other programs after I exited. After running my program, some other programs would come up without a mouse cursor, and if I called accessories from the desktop they would not be erased from the screen when I closed them.
I suspect that a lot of the programs that have a reputation for causing trouble with other programs are using the wrong VDI handle value, and hopelessly confusing the poor ST! If you're programming in assembly language, always be sure to save the value that the VDI returns to you in control after the v__opnvwk call, and pass it as the handle when you call any other VDI functions. A note of interest—in the C examples in the Abacus books, the VDI handle is always obtained correctly. In the C statement:
v__opnvwk (work__in, &handle, work_out);
the ampersand symbol in front of the variable "handle" indicates that a value is returned in that variable. The C bindings for the v__opnvwk call take care of getting the proper VDI handle from your program's control array for you.
On page 199 of the Programmer's Reference, there is an error in the description of the VDI vq__mouse call. After the call, intout will contain the status of the mouse buttons (not "button," as Abacus says). Bit 0 indicates the left button status, bit 1 the right; if the bit is on, that button is being pressed. Therefore, the possible button values returned from vq__mouse are:
0 = No buttons pressed
1 = Left button
2 = Right button
3 = Both buttons
When you click on a window to activate it ("top" it) or when you call an accessory from the ‘Desk’ drop-down menu, GEM lets the chosen application know of your desires by sending a "message" to it. The programmer sets aside a small buffer that serves as the "message pipe," the place where GEM will write these messages as they occur. (See, message pipes aren't all that mysterious, are they?) The first word (two bytes) in the message pipe is always the message identifier, and each message has a unique identifier. In the GEM Programmer's Reference, the message events are described on pages 308 through 311—and here we find some more errors.
Pg. 309—the WM_FULLED message is missing its description. This message indicates that the user has clicked on a window's "full box" (in the upper right-hand corner) to enlarge the window to full screen size. When a WM_FULLED message occurs, word 0 of the message pipe will contain 23, and word 3 will contain the window handle of the chosen window.
Pg. 311—several mistakes rear their ugly heads. The information for the WM__NEWTOP, AC__OPEN, and AC__CLOSE messages is all wrong. Here's how they should appear:
The application is informed that a window was activated.
Word 0 = 29 (Abacus says 30. . .)
Word 3 = Window handle (They got this one right!)
The user selected one of the six desk accessories.
Word 0 = 40 (Abacus says 30. . .again.)
Word 4 = The menu identification number, which can be read through the function MENU__REGISTER. (Abacus says this value is in word 3.)
This event occurs under the following conditions:
The screen is cleared,
The window data has changed,
The running application was interrupted.
Word 0 = 41 (Abacus says 31. . .) Word 4 = Menu ID number (see also AC__OPEN)
Sadly, the wrong info for the AC__OPEN and AC__CLOSE messages is repeated throughout every source of documentation for the ST (including the Developer's Kit!). This little tidbit caused me a few days of grief while I was developing my Font Tricks accessory (from ST-LOG #10), since when an accessory isn't active it just sits and waits for the AC__OPEN message. If you follow the does, you'll be watching for a message that never comes. Font Tricks was written in assembly language; once again, if you program in C and use the standard files for equates, you'll never run into this problem . . .
because the C bindings have these messages listed correctly! In fact, that's how I eventually found out the truth about the message numbers—by looking through the C equate files in the Developer's Kit.
On page 322 in the description of the AES appl__write call, the parameters for the control array are given incorrectly. The input parameters should be:
control(0) = 12 control(1) = 2 control(2) = 1 control(3) = 1 control(4) = 0
Corrected SFIRST call
There are quite a lot of AES functions missing from the Programmer's Reference. For example, there is no mention at all of the fsel__input call. . . odd, because this is one of the most handy and easy-to-use functions in the AES Libraries. This is the call which puts the ‘Item Selector’ dialog box on the screen, allowing you to select files from disk for saving, loading, etc.
To close this tale of heartache and woe, here's a description of the syntax for the fsel_input call (just for the heck of it, in the Abacus style), for those of you without any does on it:
FSEL__INPUT: Opcode = 90
Display the GEM File Selector Dialog Box.
control(0) = 90 control(1) = 0 control(2) = 2 control(3) = 2 control(4) = 0
addrin(0) = dir__spec addrin(1) = file__sel
intout(0) = ret__code intout(1) = exit__but
dir__spec: Pointer to a string that describes the original directory specification. On exit, this points at the directory selected by the user.
file__sel: Pointer to a string that contains the filename selected by the user.
ret__code: If zero, an error occurred. If greater than zero, everything's fine.
exit__but: Indicates which exit button was selected. 0 = Cancel, 1 = OK.