Best little cat. (computer program) Bob Bergstrom.
This article will introduce the Basic programmer to simple machine language subroutine creation and use in a Basic program. It will also shed some light on the way the Apple sends text from the disk catalog to the screen. In addition, a useful disk cataloging utility is the end product.
If you are like me, you ran your Apple II with cassette storage until you could afford a disk drive. After you installed your disk system, you could load files in seconds instead of minutes--what a feeling of exhilaration. Using version 3.2 of Apple DOS allows you to store up to 84 files on each disk. And with DOS 3.3, each disk holds up to 105 files. Now your biggest problem seems to be what to do with all those cassettes.
But there can be a fly in the ointment. Suppose you catalog a disk containing 71 files in search of a file you want to load. The first 18 file names fill the screen and you spot the file you want. But before you can load the file, you must scroll the screen three times by pressing any key. After scrolling through the entire disk directory, you type LOAD plus the file name and press RETURN. But instead of loading the file, the computer emits a beep and prints FILE NOT FOUND. So you CATALOG again to find you have misspelled that cute computerese filename. If this scenario sounds familiar, you are a candidate for (drum roll please) The Best Little Cat In Alpha, Illinois. Program Features
This disk menu program works equally well under version 3.2 or 3.3 DOS and is written in Applesoft Basic. Although Best Little Cat was written on an Apple with 48K of memory, it can run on a 32K machine. Among its features:
* Files are numbered from 1 to 105.
* 34 files are shown at a time.
* Files are immediately available for load or run.
* Text files are not numbered but preceded by a T.
* Disks can be accessed from drive 1 or drive 2.
* The active disk drive can be cataloged.
Figure 1 shows the first menu screen of a disk containing 34 or more files. Figure 2 shows a final menu screen. Both menus print the first 16 characters of each file name preceded by an identifying number. There are always five operation options available (although there is room to show only four of the five on each screen). First, typing in a file number and RETURN will RUN or BRUN the specified file.
Second, preceding a file number by a minus sign will cause a LOAD or BLOAD of the specified file. Third, pressing only RETURN will scroll the next menu page onto the screen.
If the last page of the menu is already on the screen when return is pressed, the first menu page is scrolled onto the screen.
Fourth, pressing zero and RETURN will provide a menu from a disk in the same drive as the last menu. And fifth, pressing D and RETURN will provide a menu from a disk in the other drive on the same controller card. In other words, the D command causes a toggle between drive 1 and drive 2. The Machine Language Surbroutine
The explanation of how the subroutine works is detailed and may require that you read this section more than once. The numbers contained in this section are decimal expcept when preceded by a $ which indicates a hexadecimal number (base 16). The symbol < is read as "less than."
Best Little Cat creates a name look-up table in RAM to be used when a file is to be loaded or run. This table is also used to print the file names to the screen. This table is constructed by a machine language routine which is POKEd into memory by lines 10 and 20 of the Basic program. Listing 1 is a disassembled version of the routine and Figure 3 is a flowchart for it.
Actually, there are two routines which replace the normal input/output routines. The first one replaces the standard keyboard input routine which is in ROM. The other replaces the ROM routine which outputs text to the video screen.
The keyboard replacement routine is at address $300. It is the shortest routine possible, and it simply returns control to DOS when DOS calls it. Without this one-step wonder, you would have to press RETURN to get DOS to start reading the disk file names.
The text (screen) output replacement routine starts at address $301 and ends at $315. Instead of printing text to the video screen, the replacement output routine builds a look-up table in RAM. For each character to be stored, DOS first reads a byte from the disk directory track (track $11) and places it in the 6502 accumulator. Then it calls to the replacement text output routine at $301. When this routine is called, the value stored in the Y register is saved to memory so it can be brought back later. (When using a machine language subroutine, you should exit the subroutine with the various 6502 register contents unaltered.)
Next, the Y register is set equal to zero. The byte in the accumulator is checked to see if it is at least $40. IF it is less than $40, then $40 is added to it (this is important). After the code is tested, it is deposited in the memory location pointed to by $02 and $03 plus the offset contained in the Y register (which is always $00).
The pointer contained in $02 and $03 is then increased by one, the Y register is loaded back from memory (remember why?), and control is given back to DOS. DOS now reads another byte before calling $301 again. This cycle continues until the disk directory has been completely read and the table built. The normal keyboard/text output routine pointers are then reinstalled which causes the Apple to forget about the routines at $300 and $301. Why Add $40--A Slight Diversion
If the character byte transferred from the disk directory to the accumulator is less than $80, it was not placed in the disk directory by Apple DOS. Probably, somebody used one of the available disk utility programs to place inverse or flashing screen codes in the disk directory. How can this be done? If you look on page 15 in the Apple Reference Manual, you will find the ASCII screen character set. By POKEing character values which are less than $80, fancy inverse or flashing headers can be part of a disk catalog. This technique works because the disk CATALOG function uses the standard ROM tex output routine to print to the screen. Note, however, that Apple DOS will not LOAD or RUN flashing or inverse files so this technique can be used only for fancy catalog headers.
If you recall, the replacement output routine for Best Little Cat intercepts each character that DOS would send to the ROM screen print routine and sends it to a RAM location other than the text screen to be part of the look-up table. After the disk is completely cataloged, Best Little Cat uses a PRINT statement--i.e., PRINT CHR$ (PEEK(--))--to transfer the file names from the look-up table to the screen. So far, so good--or is it? When the CHR$ function is used to print an inverse screen character code, the character is converted to a control character (which is invisible on the text screen).
How does a screen inverse character become a control character? The CHR$ function was designed to work on standard keyboard ASCII, not Apple screen code ASCII. Normally, after the ROM keyboard input routine has read the keyboard for an ASCII value and the main program has received the character, the keyboard strobe is cleared so that the next character can be read. This clearing results in 128 ($80) being subtracted from the ASCII code of the character (refer to page 6 of the Apple Reference Manual).
These two different versions of ASCII are referred to as positive and negative ASCII. The CHR$ function has to work in an environment in which standard (positive) keyboard ASCII and/or "low band" (negative) keyboard ASCII could be encountered. Therefore it must recognize the negative ASCII codes and add 128 ($80) to them before translating from the numerical value to the actual character.
Try this: while in Applesoft Basic, type PRINT CHR$(193), CHR$(193), CHR$(65) (RETURN). Two letter A's will be printed to the screen even though the codes are 128 character codes apart. If you look at table 7 on page 15 of the Apple Reference Manual, you will see that decimal 65 is actually the screen character code for a flashing A. However, since the code was processed through the CHR$ function, it was treated as a low band keyboard character, and 128 was added to it. This resulted in a normal character being printed to the screen. Now type PRINT CHR$(1) (RETURN). Nothing is printed on the screen. Decimal 1 is the screen character value for an inverse A. Again, this value was interpreted as a low band ASCII code and 128 was added to it. But when 128 was added to it, the result was a control character, and control characters are invisible on the video screen.
To avoid control characters, the replacement output routine must determine if the ASCII code is an inverse code (<$40 or 64) before POKEing it to memory. When the code for an inverse character is found, 64 ($40) is added to it, converting it to the code for a flashing character. Since the CHR$ function interprets flashing screen characters as normal screen characters, the character will be printed in a normal fashion. It must be emphasized that this code conversion is for display purposes only--inverse or flashing files cannot be loaded or run. The Subroutine Summary
To sum it up, the replacement output routine converts inverse screen character ($00-$3F) to flashing screen characters ($40-$7F) before storing them in memory. This allows the Basic CHR$ function to be used as a screen character interpreter. The replacement routine stores control characters ($80-$9F) and alphanumeric characters ($A0-$DF) directly to memory without conversion. Therefore, Best Little Catalog correctly loads files with names that contain hidden control characters. Since DOS will not load file names which contain inverse or flashing screen characters, Best Little Catalog can only display these files. The Basic Listing
Before explaining the Basic listing. I want to make one clarification. To avoid confusion between the number zero and the letter O, the letter O has not been used in variable names. The letter O appears only in Basic command words and within PRINT statement quotes. Therefore, the statement AB = 0 is equating the variable AB to zero, not to a variable named letter O.
Figure 4 shows the printing logic for Best Little Cat. These are the logical steps taken by the program when printing the non-final screens of a multi-screen catalog. The final screen logic is much the same except it "drops through" line 160 to lines 170 and 180. This printing logic is somewhat involved. If you understand how the printing is done, the rest is straightforward.
As mentioned earlier, lines 10 and 20 POKE the new I/O routine into memory at $300. Line 20 also dimensions memory for the variable A and sets an error trap. The rest of the listing is explained as follows:
Line 30 initializes variables, sets CP% to point to free memory space, POKEs the value of CP% into $02-$03, and sets C as a pointer to the DOS I/O pointers.
Line 40 POKEs the location of a new I/O routine in DOS, catalogs the disk, resets I/O pointers to normal ROM routines, sets C=1, and reads DISK VOLUM and volume number from memory.
Line 50 prints the menu header.
Line 60 begins the file reading loop and checks whether a file is a text file.
Line 70 saves a memory pointer for each file name and prints a space if the current file number is less than 10.
Line 80 prints the file number to the screen and increments the current file number.
Line 90 prints the file name and checks if the cursor is above the bottom of menu area.
Line 100 checks if the cursor is in the righthand column.
Line 110 sets the scrolling window for right column printing.
Line 120 sets the scrolling window for full width printing instructions, requests input and prints the next menu screen if requested.
Line 130 checks if MENU OTHER DISK DRIVE was requested.
Line 140 converts a string variable to a real variable and checks if MENU SAME DISK DRIVE was requested.
Line 160 terminates the file reading loop and prints a space if fewer than 10 files are on the disk.
Line 170 prints a number equal to the number of files on the disk plus one, prints CATALOG, and sets the scrolling window to full width.
Line 180 prints instructions and requests input and checks if MENU OTHER DISK DRIVE was requested.
Line 190 checks if REPRINT MENU was requested.
Line 200 checks if CATALOG DISK was requested.
Line 210 checks if MENU ANOTHER DISK was requested.
Line 220 checks if LOAD command was requested.
Line 230 checks for invalid option number.
Line 240 assembles a string of the parameters chosen, and checks if it is a binary file.
Line 250 deletes the file parameters from the file name string and determines RUN or LOAD.
Line 260 RUNs the chosen file.
Line 270 LOADs the chosen file
Line 280 delets the file parameters from the file name string and determines BRUN or BLOAD.
Line 290 BRUNs the chosen file.
Line 300 BLOADs the chosen file.
Line 310 CATALOGs the disk.
Line 320 checks for an invalid option number.
Line 330 sets the LOAD flag and sets the file number positive.
Line 340 POKEs in the stack clean-up routine found on page 82 of the Applesoft manual and calls this routine
Line 350 resets the input/output pointers for keyboard input and text screen output and ends the program. Program Entry And Debugging
When you first type in Best Little Cat, I suggst that you leave the statement ON ERR GOTO 340 out of line 20. Then, if you have made a typographical error, the Apple will tell you where the syntax error exists when the program is run.
When the program is completely entered, save it to a disk and remove the disk from the drive. Next, insert into drive 1 a disk containing at least 34 files, type RUN and press RETURN. The first 34 files on the disk will be displayed with a corresponding number. Press RETURN and the next page of files will be shown. A CATALOG option will follow the last file on the disk.
Type in the number that runs the CATALOG option and press RETURN. A normal catalog should occur. Type RUN and press RETURN. The first menu page will be displayed again.
If you have a second drive, remove the disk from drive 1 and put it in drive 2. Press D then press RETURN. Drive 2 will spin and the first menu page will be displayed. Regardless of which drive the disk is sitting in, choose a program, enter its number and press RETURN. That program will now run.
If Best Little Cat has behaved as just described, add the statement ON ERR GOTO 340 to line 20. Now a master copy of the program can be saved and used as a HELLO program when new disks are initialized. Customization
Best Little Cat is a product of evolution. I suspect that two months from now it will have gone through at least one more generation. One handy change would be to include a CALL -151 on line 300 so that after a BLOAD, you will be in the monitor mode. Another would be for language card owners to have Best Little Cat load Integer Basic onto that card before displaying a disk menu. Several other ideas come to mind, but I don't want to stifle your creativity.