Using Disks With Atari Basic
Dave Johnson and Embee Humphrey
This article will help you write programs that use data files that are saved on disk. We hope you will use this information as a beginning point for experimentation. We believe that the only way to really learn programming is to try things and make mistakes in the process. We have included answers to what we have found to be the most common questions.
These are the Atari disk input/output commands:
OPEN #reference number, open code, 0, filespec: The first parameter, reference number, is a number between 1 and 7 that is used to refer to that file throughout a program. It must be preceded by the "#" symbol. The second parameter, open code, is a number that tells the computer if you want to read, write, etc. See Table 1.
The third parameter is reserved for special control codes that will not affect you in disk operations. Always use a 0 for this third parameter. The last parameter, filespec, is the device and file name. Filespec can be a string variable, or the device and filename enclosed in quotes. Example: You may declare A$="D:FILENAME" and use A$ in the OPEN statement, or you may just use "D:FILENAME" itself.
CLOSE #reference number: This tells the computer that reference number is no longer being used. (Note--if you are writing data, and fail to close a file, any data in the buffer will not be saved on disk.)
PRINT #reference number;[What you want printed]: This is used the same way as a regular Basic PRINT statement. The reference number tells the computer to PRINT to the file you have opened using that reference number.
INPUT #reference number; [Input list]: This works like a regular Basic INPUT statement. The reference number tells the computer to look for input from the file opened using that reference number.
NOTE #reference number, variable for SECTOR location, variable for BYTE location.
POINT #reference number, SECTOR variable, BYTE variable: NOTE and POINT are explained later.
OPENing a file tells the computer that you are going to use a particular file in a particular way, and that you will refer to that file in your program using a particular reference number. (Atari Basic manuals call this reference number an IOCB number, for Input/Output Control Block.)
For example, if you want to read from file TEST.DAT, and you decide to refer to that file as number 4, you would use the following open statement example. (The number doesn't matter as long as whenever you want a certain file, you refer to it with the same number.)
An example of OPEN: OPEN 4,4,0,"D:TEST.DAT". This means OPEN a file, read data from the file, the file will be on device "D:" (disk), whose name is TEST.DAT, and remember that this file will be referred to as #4 for future I/O operations.
To read from the file you would say:
INPUT #4; expressions ....
And finally, when you are done with the file: CLOSE #4.
INPUT and PRINT
INPUTing and PRINTing with the disk is the same as inputting from the keyboard and printing to the screen. The reference number tells the computer that you are using the disk instead. (You must have OPENed a disk file with that number).
The easiest way to experiment with this is in DIRECT mode, typing in statements without line numbers. Now try a few things:
OPEN 1,8,0,"D1:TEST.DAT": This opens a file, TEST.DAT, for write only. It will be referred to later as 1.
PRINT #1;"THIS IS A STRING": This writes this message to the file.
PRINT #1; 12345.6: This writes the number 12345.6 into the file.
PRINT #1;"THIS IS ANOTHER STRING"; 12345.6: This writes both the string and the number to the file with the same statement.
CLOSE #1: This closes the file.
To see what is on the disk: OPEN #2,4,0,"D:TEST.DAT".
We used 2 here to demonstrate again that the number itself does not matter. What matters is that the same number be used for all references to that file after the OPEN.
Since you will be reading strings, you need to DIM a string to read into: DIM S$(30)
Now, to read it, type: INPUT #2,S$. Then type: PRINT S$, and the screen displays: THIS IS A STRING, which is what you put on the disk.
Now, a surprise! We told you that PRINTing to disk was the same as printing to the screen. When you type PRINT #4; 12345.6, you put the CHARACTERS "12345.6" on the disk, not a binary representation.
- Now type:
- INPUT #2,S$
and the screen displays: 12345.6
Reading the number into a string gets the string representation of the number that was on the disk. Reading the number into a number variable would also have worked. If the binary representation of the number was put on the disk, you would not have been able to read it into a string and see it. This is important to remember, because putting the number 10 on the disk takes two bytes of disk space, while putting the number 123 on the disk takes three bytes. This will be important in the discussion of random access.
Remember: the number of digits is equal to the number of bytes the number will take up on the disk.
The next example shows another way that similarity between screen and disk output may surprise you. From the above example the file is still open:
- INPUT #2;S$
and the screen displays: THIS IS A STRING 12345.6
It read into the one string both the string and the number that you had put on the disk. When you put this data into your file using PRINT #1;"THIS IS A STRING";12345.6, it went onto the disk exactly as it would have appeared on the screen. When reading it, the computer had no way of knowing where the string stopped and the number started on the disk.
You could not have said INPUT #2;S$, NUM because inputting S$ would have taken you past the number so, if you are going to read data back as different lines, put it on the disk as different lines.
Now you can experiment with APPEND. You already have a file, TEST.DAT, on the disk. If you want to add data to this file you must use APPEND, because opening the file to write again (with an 8) will erase what you have already put into it.
In OPEN #5,9,0,"D:TEST.DAT", the 9 means APPEND.
Now, try this. Type:
PRINT #5;"THIS IS ADDED"
To see what happened, type the lines in Figure 1. The screen displays: THIS IS ADDED
Trying to type INPUT #1,S$ one more time would cause an ERROR 136, which means END OF FILE.
NOTE and POINT
NOTE #reference number, sector variable, byte variable: This takes NOTE of where the disk read/write head is physically positioned. The #reference number is the IOCB number. If you want to mark where you are in a file opened as 1, you say NOTE #1 ,variable 1,variable2. Variable1 saves the sector and variable2 saves the byte.
POINT #reference number, sector variable, byte variable: This physically POINTs the disk head to the sector and byte. If that sector and byte are not located within the file opened with that reference number, you get an error message.
NOTE and POINT are useful for repositioning the read/write head to the beginning of a file. For example, if you want to read the first string in your TEST.DAT file twice before proceeding, you would type the lines in Figure 2.
The screen displays: THIS IS A STRING
If you read again, you will be reading the second item in the file, which is: 12345.67.
To point back to the beginning:
and the screen will again display: THIS IS A STRING, which is the first record in the file!
NOTE and POINT are useful for random access. If you keep track of where you put data, using NOTEs, you can later get at the data, using a POINT, without reading everything in front of it.
Briefly, suppose you have a mailing list. Each time you save a record, you NOTE where it is physically written, and save those sector and byte numbers in arrays -- SECTOR(record number),BYTE(record number). Then you save those arrays in another file on the disk.
To look up records, you would first read the array data file to put the information back into the arrays. You would then look up the individual records by POINTing directly at them. (SECTOR and BYTE are the variable names we have assigned to our arrays.)
X=SECTOR (indexed by record number). (To read the 23rd record you would use X=SECTOR(23).)
Y=BYTE (indexed by record number)
POINT #reference number,X,Y and you are ready to read that record.
Be careful. If you want to modify a record and write it back into the file in the same place, you must not change the length of that record. If it is changed, it could overlap into the next record, overwriting the data there. Remember that numbers use as many bytes as there are digits.
Before you modify records, you must format numbers into strings with leading blanks or zeroes that are always the same length. The subroutine in Figure 3 accomplishes this. Before calling, put the number you want formatted into the variable DSKNUM. The number will be formatted into a string of length 10 with leading zeroes and placed in string variable DSK$.
Atari Basic has a TRAP command. The format for the TRAP command is: TRAP line number.
To TRAP to a line number means to go to that line number if an error occurs. This can be useful for disk operations. For example, if you want to go to a certain line number when you reach an END OF FILE, you can take advantage of the ERROR 136 that happens when you try to read past the end. See Figure 4.
David Johnson and Embee Humphrey, Atari, Inc., 1272 Borregas Ave., Sunnyvale, CA 94086.