Relative Files On The 1571 Disk Drive
This article demonstrates reliable methods for using relative files. A Commodore 128 and 1571 disk drive are required.
What is a relative file? A file, as you may know, is simply a collection of information stored on disk. A relative file differs from other files in that you can access any part of the file instantly, without having to read through other items of information first. Relative files have been considered a mystery by many Commodore 64 owners, because they are cumbersome to manipulate in BASIC 2.0.
The introduction of the Commodore 128 and 1571 disk drive changed this situation dramatically. BASIC 7.0 contains several commands for handling relative files, and the Commodore 1571 Disk Drive User's Guide contains an entire chapter devoted to explaining them.
This is not a general tutorial on using relative files on the 1571. That information can be found in Chapter 6 of the User's Guide. Instead, this article demonstrates several factors that affect the reliability of relative file handling on the 1541 and 1571 drives, including a bug in the 1571 DOS (Disk Operating System).
Beginning The Test
Before typing in the program, format a new, blank disk for use. It is important that you use a new disk for this demonstration because the bug in 1571 DOS can corrupt all the files on a disk.
Type in and save the program on disk (but not on the new one which you just formatted). Insert the newly formatted disk in the drive and run the program.
When questions appear on the screen, answer them as follows. (We'll begin conservatively.) First, request that the 128 operate in SLOW mode (enter S). Second, request that the disk drive operate as a 1541 drive (enter 41). Third, indicate that you want the program to check the disk drive error channel (enter ON). The error check also includes a slight time delay, which is explained below. Next, indicate that you want to create a total of 15 records (enter 15). Finally, indicate that you want to position the record pointer to the last record in the file (enter Y).
As the program runs, it displays the number of each record that it writes. When it prompts you to press a key, the program is ready to read back the file that it just created. Notice that each record consists of five items, or fields; each field is a different length. When all records have been read, the program displays the disk directory. As you can see, the name of the newly created file (R-S-41-ON-Y-15) is descriptive, showing the options you selected when creating the file. The S in the filename stands for SLOW, and so forth. You will not need this file again, so you may enter Y for yes when the program asks whether to scratch this file.
So far, everything worked perfectly. The program created and read back the file with complete accuracy. Now let's try some different options. Rerun the program and enter F for FAST mode when prompted. Select 1541 mode as before, but enter OFF when prompted to choose error checking. Choose 15 records as before, but do not position the record pointer to the last record in the file.
If you are using a 40-column monitor, your screen will blank while portions of this program run. However, some messages appear from time to time to assure you that everything is proceeding properly. When the program is finished, we see that it worked properly, reading back every record as written. When the drive is in 1541 mode, it doesn't seem to matter whether we use SLOW or FAST mode, whether we use error checking, or whether we position the record pointer at the last record in the file.
Now let's try the test in 1571 mode. Select SLOW mode and 1571 mode, turn on error checking, select 15 records, and select to position the record pointer. At the end of this test, you should see that everything worked properly again.
Rerun the test, selecting FAST mode and 1571 mode. Turn error checking off this time. Choose 15 records, and tell the program not to position the record pointer. After the tenth record is written, you should see the drive light blink, accompanied by sounds of protest from the drive. You will see an ILLEGAL TRACK OR SECTOR error message. (Even though error checking is turned off, the program automatically checks the error status after every tenth record.) The program continues trying to write the remaining five records, and eventually finishes with another error message.
At this point, the disk contains a corrupted relative file. If it had contained other files, the corrupted relative file might have damaged those files, as well.
It is nearly impossible to read a corrupted relative file reliably. When a program tries to do so, several things may happen.
The subroutine in lines 2050–2160 is designed to detect, corrupted records. When this occurs, you will see a flashing message and hear a bell sound. If the data is not too badly corrupted, this routine is called repeatedly, each time it encounters a garbled record.
If the data is more seriously corrupted, the program itself may abort with the error message STRING TOO LONG. If this happens, press RUN/STOP-RESTORE to recover control, then type DCLOSE:DCLEAR and press RETURN before proceeding further.
In the worst case of corruption, the computer and disk drive will silently lock up, ceasing all activity. If this occurs, follow the same procedure described in the preceding paragraph.
The test shows that it is necessary to check the error channel—with a slight time delay as shown in lines 2010–2020 of the program—when creating relative files in 1571 mode. To confirm that the corruption does not result from failing to position the record pointer, you can rerun the test if you like, entering Y when asked about the pointer. As long as the error/delay option is turned off, the file is corrupted.
Perhaps, you might think, the errors result because we are in FAST mode? To test this possibility, rerun the program, choosing SLOW mode and 1571 mode, turning the delay/error check option off, choosing 15 records and answering yes to the record pointer question. With these parameters, the relative file usually writes with accuracy, but occasionally aborts with the error message DEVICE NOT PRESENT. Reading the records back is a real problem. It is nearly impossible to read record 15 without a DEVICE NOT PRESENT error. (If this error occurs, press RUN/STOP-RESTORE, then type DCLOSE; DCLEAR and press RETURN.)
Clearly, some errors will occur when writing a relative file in SLOW mode on the 1571 without the time delay and error check used in this program. In 1541 mode, it didn't matter if we turned that option on or off, but it seems essential in 1571 mode.
Let's see whether the time delay is actually doing anything. Modify lines 2010–2020 so they look like this:
2010 REM : T2 = TI + 5 2020 REM : IF TI < T2 THEN 2020
We have disabled the delay (which normally consumes about 1/12 second), but line 2030 still checks the disk drive error channel. Rerun the program, choosing FAST mode and 1571 mode, turning error checking on, choosing 200 records, and choosing not to position the record pointer (that last option is actually irrelevant}. In most tests, you will find 1 or 2 corrupted records for each 100 records that you create. The time delay does seem to have an effect, after all.
As a rule, you can enhance, the reliability of relative file handling by checking the error channel, with this slight time delay, upon every file access. If you use the method employed in this program, the time delay will be consistent even if you later compile the program (compiling BASIC programs greatly speeds up their execution). It also is recommended that you follow Commodore's advice in positioning the record pointer both before and after you access a record.
This advice is imperative when using the 1571 drive in 1571 mode. When using it in 1541 mode (or when using an ordinary 1541 drive), you can often get away without the time delay/error check—provided that you access records in numerical sequence (record 1, record 2, and so on). However, if your program writes files in nonnumerical order (for instance, record 1, record 5, and so on), it is necessary to position the record pointer before and after each operation, and to use the time delay/error check, as well.