An ATARI Tutorial
Atari Disc Menu
Len Lindsay
Anyone with an ATARI disk will really appreciate this program. You will probably put a copy of MENU on each of your diskettes.
MENU will display the programs on the diskette along with an ID number (1-44). It then asks you which program you wish to RUN. If you wish to RUN program number 8, you simply answer 8. It then LOADS and RUNs that program. No more hassles trying to remember exactly what name you used for the program, or typing the name exactly. MENU does it all for you.
Since MENU uses some special techniques, I will explain how it works. You should be able to apply many of these concepts to your own programs.
LINE 10-11 — Dimension the STRINGs. ARRAY$ will hold all the names of the programs on the disk (12 characters per name). FILE$ and NAME$ are used for the program names. DISK$ is used to hold the drive number prefix.
LINE 15 — Set the margins to default, in case the previous program used different ones.
LINE 20 — Use GRAPHICS 0 full screen text mode. It also clears the screen for you.
LINE 30 — Turn the cursor off — it looks nicer while writing the program names on the screen.
LINE 40 — Set the color registers to the preferred colors. A light orange background with warm brown letters is the easiest on your eyes (so that is what I use).
LINE 50 — Set DISK$ to the disk drive to be used. See modification notes to make this more flexible.
LINE 60-70 — "D1:*.*" will refer to the disks directory. It is a two step process to add the DISK$ with "*.*" and call it NAME$.
LINE 100 — Open the disk directory for a READ. This line should be useful for other applications.
LINE 110 — Initialize the counter which counts each program as it is read from the directory. This also acts as the program ID number.
LINE 120 — READ one file from the directory. A program entry is 17 characters long. It is two spaces, 8 characters for name, 3 characters for extension, one space, 3 characters for sectors used. After all the programs is a separate record of the number of free sectors left on the diskette.
LINE 130 — Check if this is the short record of tracks left on diskette, if it is then we are done and should go on to the next part starting at line 500.
LINE 140 — Since we read in another program name, add one to the counter.
LINE 150 — If this is the 23rd program, we must switch to the right half of the screen (prevent scrolling and fit more on the screen this way). To do this we set the left margin to 20 and position the cursor at the top line, 20th spot.
LINE 160 — Check if the screen is completely filled with program names (44 is the maximum display allowed on one screen). If it is full, ignore all the rest, adjust the counter accordingly. See modification notes for other ideas.
LINE 200 — Initialize the name field. To manipulate the string by character position, the positions all must exist -thus initializing to "" (null) will not work. Note the extention dot is in position 9.
LINE 210 — If there is no extension get rid of the dot in position 9.
LINE 220 — Assign the program name from FILE$ which we just READ from the diskette. This is only the first 8 characters of the name, not including the extension.
LINE 230 — Assign the extension of the program name. If there is no extension, we still can assign it since the dot has already been removed.
LINE 300 — To keep a justified column of ID numbers, we must allow for ONE digit numbers. So if the number is less than 10 print an extra space.
LINE 310 — Print the ID number followed by ) and a space.
LINE 320 — Print the program name.
LINE 400 — Add the name on to the ARRAY$ we are building. It can now be referenced by number times 12 (since every name is exactly 12 characters long).
LINE 410 — Processing complete for the program just read. Go and do the next one.
LINE 500 — Set the trap to come back and redo the input if an error occurs.
LINE 505 — CLOSE the file used to input the programs from the directory.
LINE 510 — Turn the cursor back on for the INPUT request.
LINE 520 — Position the cursor on the message line (line 22). First print a line delete to erase the previous message. Then print the current message. End the message with a BEEP (control 2).
LINE 525 — Set the left margin back to default so the next program will not be affected.
LINE 530 — INPUT the ID number of the program to be RUN.
LINE 540 — Get rid of any fractions.
LINE 550 — If the choice was not in the range available, go and ask again.
LINE 600 — Start FILE$ with the disk number. The rest of the name is assigned in line 630.
LINE 610 — Assign the name of the program chosen to NAME$ (taken from the ARRAY$ we just put together).
LINE 620 — Start a loop to go through the whole 12 character program name and remove all spaces (spaces cannot be imbedded within a program name when you ask for a LOAD or RUN).
LINE 630 — Add the characters in the program name one at a time to FILE$. Ignore spaces.
LINE 640 — Do the next character.
LINE 700 — Set the trap to line 900 to print a can't load message if there is a disk error.
LINE 720 — Position the cursor to the message line. First do a line delete to erase the previous message. Then print the message LOADING with the file name. Then print a BEEP (control 2).
LINE 730 — RUN the program and spring the trap.
LINE 900 — Print message the program can't be run (maybe diskette was switched or removed since the directory was read).
LINE 910 — Pause to allow message to be read.
LINE 920 — Go and ask for program to RUN again.
Possible Modifications
MENU is set up to work with disk drive 1. It is easy to have it work with both drive 1 and drive 2, and even alternate between them for a wider MENU choice. Line 50 sets the disk drive number prefix to be used by the MENU program. Some possible modifications follow; the first asks you which drive to use for the MENU, while the second can flip back and forth from drive to drive. I have implemented the second set of modifications and find it works quite well. Either way, it seems that it doesn't like trying to give you a MENU for an empty drive.
Modification Set 1 — Ask Which Drive
50 PRINT "[CLEAR] WHAT DISK DRIVE TO USE)"; 51 OPEN #1, 4, 0, "K:" :REM OPEN KEYBOARD FOR GET 52 TRAP 52 : GET#1, DRIVE : REM GET KEY PRESSED ATASCII VALUE 53 NAME$ = CHR$(DRIVE): REM CONVERT TO STRING - USE NAME$ SINCE IT IS DIMed 54 IF NAME$ <"1" OR NAME$> "4" THEN 52: REM TRY AGAIN 55 PRINT NAME$: REM PRINT THE REPLY 56 CLOSE #1 : REM CLOSE THE FILE 57 DISKS$ = "D1:" :REM INITIALIZE STRING 58 DISK$(2,2) = NAME$ :REM INSERT DRIVE NUMBER
Modifications For Alternating Drives
17 DRIVE = 2 : REM INITIALIZE FOR A TWO DRIVE SYSTEM - DRIVE 1 WILL BE FIRST 18 DISK$ = "D1:" : REM INITIALIZE 50 DRIVE = 3-DRIVE : REM SWITCH DRIVES, WILL DO DRIVE 1 FIRST 55 DISK$(2,2) = STR$(DRIVE) : REM PUT CORRECT DRIVE NUMBER INTO DISK$ 59 TRAP 50 : REM TRAP DISK ERROR 105 ARRAY$ = " " : REM INITIALIZE 115 PRINT "[CLEAR]" : REM CLEAR SCREEN 520 POKE 82,2 : REM LEFT MARGIN TO DEFAULT 525 POSITION 2,22 : PRINT "[DELETE LINE]0 = NEXT DRIVE WHICH TO RUN[CONTROL 2]"; 535 IF CHOICE = 0 THEN 50 : REM SWITCH DRIVES ON CHOICE OF 0
Another modification you may wish to make has to do with the ability to jump into DOS directly from MENU. If you try to RUN it as your MENU choice, it will say "can't run dos". Thus if you think you may need to jump directly to DOS add this line:
615 IF NAME$ = "DOS.SYS" THEN DOS
Modifications To Overcome The 44 Program Limit
The MENU can only display 44 program choices at one time, thus line 160 checks if the screen is full (44). If it is, it skips all the rest of the programs. In practice this should not be a problem since most diskettes will be filled before they reach the 45th program unless the programs are all short.
Modifications might be made so that after 44 programs, they no longer are printed on the screen, but still are added to ARRAY$ with FILECOUNT continuing its count. The DIM in line 10 for ARRAY$ should be increased accordingly. The message line (520-525) should also be appropriately changed. Perhaps a choice of 99 would mean "display second screen of menu". A subroutine could calculate what program number to start with (filecount minus 43) and another subroutine could print the menu from ARRAY$ as appropriate.
0 REM *** MENU (44 PROGRAM MAX) 1 REM *** (C) 1980 LEN LINDSAY 2 REM *** LAST REVISION 11-15-80 3 REM 10 DIM ARRAY$(528), FILE$(20), NAME$(20) 11 DIM DISK$(3) 15 POKE 82, 2 : POKE 83, 39 : REM DEFAULT MARGINS 20 GRAPHICS 0 : REM CLEAR SCREEN AND GO IN TO TEXT MODE 0 30 POKE 752, 1 : REM CURSOR OFF 40 SETCOLOR 2, 2, 6 : SETCOLOR 4, 2, 6 : SETCOLOR 1, 2, 2 50 DISK$ = "D1" : REM THE DISK TO BE USED FOR A MENU 60 NAME$ = DISK$ : REM THE NAME MUST START WITH THE DISK DRIVE NUMBER 70 NAME$(LEN(NAME$)+1) = "*.*" : REM LOADING D1 : *.* GIVES THE DISKS DIRECTORY 100 OPEN #1, 6, 0, NAME$:REM OPEN THE DISK DIRECTORY FOR A READ 110 FILECOUNT = 0 : REM INITIALIZE COUNT 120 INPUT #1, FILE$ : REM READ NEXT PROGRAM NAME 130 IF LEN(FILE$ × 5 THEN 500 : REM NOT A PROGRAM - THIS IS THE SECTORS LEFT COUNT 140 FILECOUNT = FILECOUNT + 1 : REM ADD ONE TO COUNT 150 IF FILECOUNT = 23 THEN POKE 82, 20 : POSITION 20, 0 : REM SWITCH TO RIGHT HALF OF SCREEN (CHANGE LEFT MARGIN TOO) 160 IF FILECOUNT > 44 THEN FILECOUNT = 44 : GOTO 120:REM TOO MANY PROGRAMS - JUST KEEP READING 200 NAME$ = " " : REM INITIALIZE THE NAME FIELD TO ALL BLANKS EXCEPT THE DOT BEFORE THE EXTENSION 210 IF FILE$(11, 13) = " "THEN NAME$(9, 9) = " " : REM THERE IS NO EXTENSION SO GET RID OF THE DOT 220 NAME$(1, 8) = FILE$(3, 10) : REM ASSIGN THE FIRST 8 CHARACTERS OF THE PROGRAM NAME 230 NAME$(10, 12) = FILE$(11, 13) : REM ASSIGN THE EXTENSION OF THE PROGRAM NAME 300 IF FILECOUNT < 10 THEN PRINT " "; : REM ADD AN EXTRA SPACE BEFORE THE SINGLE DIGIT NUMBERS TO ALIGN WITH 2 DIGITS 310 PRINT FILECOUNT;") "; : REM PRINT FILE NUMBER 320 PRINT NAME$ : REM PRINT THE PROGRAM NAME 400 ARRAY$(LEN(ARRAY$) +1 ) = NAME$ : REM ADD ON THE LATEST NAME TO END OF STRING OF NAMES THUS FAR 410 GOTO 120 : REM GO READ NEXT FILE NAME 500 TRAP 500 : REM SET TRAP FOR BAD INPUT 505 CLOSE #1 : REM CLOSE THE FILE USED TO INPUT DISK DIRECTORY 510 POKE 752, 0 : REM TURN CURSOR BACK ON 520 POSITION 2, 22 : PRINT "RUN NUMBERD"; : REM PRINT MESSAGE ON MESSAGE LINE 525 POKE 82, 2 : REM SET LEFT MARGIN TO DEFAULT 530 INPUT CHOICE : REM GET THE NUMBER OF THE PROGRAM TO RUN 540 CHOICE = INT(CHOICE) : REM GET RID OF FRACTIONS 550 IF CHOICE <1 OR CHOICE> FILECOUNT THEN 500 : REM OUT OF RANGE FOR THIS MENU 600 FILE$ = DISK$ : REM THE NAME TO USE WITH A RUN STATEMENT MUST BEGIN WITH THE DISK DRIVE NUMBER 610 NAME$ = ARRAY$(CHOICE*12-11, CHOICE*12) : REM THE NAME OF THE PROGRAM INCLUDING EXTRA SPACES 620 FOR LOOP = 1 TO 12 630 IF NAME$(LOOP, LOOP)< >" "THEN FILE$(LEN(FILE$) +1) = NAME$(LOOP, LOOP) 640 NEXT LOOP 700 TRAP 900 : REM SET TRAP FOR DISK ERROR 720 POSITION 10, 22 : PRINT "LOADING)"; NAME$ : REM PRINT MESSAGE ON MESSAGE LINE 730 RUN FILE$ : TRAP 34567 : REM RUN THE PROGRAM AND TURN OFF TRAP 900 POSITION 10, 22 : PRINT "CAN'T RUN}"; NAME$ : REM PRINT MESSAGE ON MESSAGE LINE 910 FOR PAUSE = 1 TO 999 : NEXT PAUSE : REM DELAY TO ALLOW TIME TO READ MESSAGE 920 GOTO 500 : REM GO AND TRY AGAIN