!pr2
Tools for Restoring Lost Catalogs.........Bob Sander-Cederlof

From time to time it happens.  One way or another I manage to clobber a catalog track on a disk.  I have done it three times to Volume 1 in the DOS partition on my 10-megabyte Sider.  (All it takes is "INIT HELLO,V1", forgetting that the last slot I accessed was the Sider's.)

All of the other tracks are still intact, but there is no way to get to them because the catalog is totally wiped out.  One solution would be to have an accurate backup floppy for each Sider volume.  This should be especially easy for Volume 1, because it is mostly standard Sider utilities.  Mostly....  I have modifed several of them, and somehow I almost always have several programs-under-development that end up in V1.  Of course, I could just as easily destroy the catalog track on any other volume, or any floppy for that matter.

It is for mistakes like mine that the program FIXCAT in "Bag of Tricks" was invented.  FIXCAT looks over a diskette, finds all the sectors which look like they contain track/sector lists, and tries to piece together a new catalog track.  Even though it is fairly automatic, I find it very difficult to use.  I am always getting confused between old (deleted) copies of files and the current ones, and my disks usually have at least 2 or 3 dozen active files.

Recently it happened again.  In fact, while I was working on one of the other articles in this issue of AAL.  I decided to write a couple of utilities to help me make more effective use of FIXCAT.  My new tools turn out to be useful even without FIXCAT, and you might enjoy just playing with them.

I assume you have a copy of "Beneath Apple DOS", or some other reference work which explains the format of DOS disks, catalog tracks, and track/sector lists.

The first tool I wrote looks through the tracks and sectors of a damaged disk for any sectors containing what could be track/sector lists.  When one is found, I display the location of the supposed TS-list, all of the track/sectors in the list, and the first 64 bytes of the first data sector of the supposed file.  Here is an example of the display:

03-5:  03-4 03-3 03-2
       07 02 09 E8 03 81 2E 4C 49 46 00 16 F2 03 2A C0 ...h...LIF..r.*@
       06 08 53 41 56 45 81 42 43 44 81 4D 41 47 49 43 ..SAVE.BCD.MAGIC
       00 08 FC 03 2A C0 20 2D 00 05 06 04 54 00 0B 10 ..|.*@ -....T...
       04 87 4C 44 41 81 23 30 00 0C 1A 04 2E 31 85 53 ..LDA.#0.....1.S

The first 64 bytes are displayed in both hexadecimal and in ASCII, with periods being substituted for unprintable characters.

Having this information on paper before starting up FIXCAT is a big help.  I can peacefully analyze the data at my desk, without the fear and panic associated with making "life and death" decisions at the keyboard.  The first few bytes of a file will usually reveal what type of file it is.

If it is a source code file for the S-C Macro Assembler, Integer BASIC, or Applesoft, it will begin with a two-byte length for the file.  Binary files begin with the load address, then the length.  Text files start right in with data in ASCII, normally with all the high bits on.  Since I almost always have a line near the beginning of my source files which contains the file name, I can usually read that file name in the dump of the first 64 bytes.

The FIND.TS.LISTS program is fairly short and simple.  Starting from the bottom, the subroutine READTS at lines 2370-2430 calls on RWTS to read a particular track and sector.  I elected to use my own IOB, rather than the one inside DOS at $B7E8.  For simplicity's sake I assembled in the slot, drive, and volume information in my IOB.  READTS only has to store the desired track and sector numbers, and call RWTS.  I limited error handling to just re-calling RWTS, in the hopes of eventually succeeding.  Should this begin to be a problem, I could print out an error message and either quit or continue with the next sector.

The subroutine READ.NEXT.SECTOR, lines 2200-2350, is used to scan through the disk from beginning to end.  TS-lists cannot be in track 0, so I start with track 1.  Since DOS allocates sectors in a track starting with sector $0F and going backwards to sector $00, I decided to scan the same way.  This makes the files found list more closely to the same order as they were in the original catalog.  I first advance the track/sector to the next one, then read it.  Thus after reading, CUR.TRACK and CUR.SECTOR are pointing to the one we just read.

Now back to the top.  Lines 1100-1130 start CUR.TRACK and CUR.SECTOR at 0.  The first call to READ.NEXT.SECTOR will advance them to track 1, sector $0F.  Successive calls will read the rest of track 1, then advance to track 2, and so on until we have finished track $22.  When we try to read track $23, which does not exist, READ.NEXT.SECTOR will return with carry set and our program will end.

Lines 1170-1290 examine the data in the sector just read to see if it might be a track/sector list.  The method I use is to require that there be at least one TS-pair, at BUF+12.  I also require that all of the bytes beyond BUF+12 are within the range of valid track-sector pairs.  If any bytes are out of range, I assume the current sector is not a TS-list.  My tests seem to be adequate, because with every disk I have used it on it found all and only the TS-lists.

Having found TS-list, I call DISPLAY.TS.LIST to display it.  Lines 1450-1540 display the location of the TS-list.  The subroutine PR.TS prints the track and sector numbers from the A- and X-registers in the form "TT-S".  Lines 1550-1720 list the TS-pairs in the TS-list, stopping at the first pair with a track number of zero.  Up to 8 pairs are listed on a line.

Lines 1330-1430 read the first data sector of the supposed file, and display the first 64 bytes in hex and ASCII.  This display is done by calling DISPLAY.NEXT.16 four times.

As it happens, I did have a fairly recently made backup of the clobbered disk.  I thought I should also run my program against this good disk, and comparing the two displays would enable me to pinpoint each active file.  However, what I really want from the GOOD disk is the information in the CATALOG.  I decided to modify FIND.TS.LISTS to be driven from the catalog track, rather than from a search for TS-lists.  The result was another useful tool, BIG.CATALOG.DISPLAY.

BIG.CATALOG.DISPLAY has the same kind of output that FIND.TS.LISTS does, except that it also lists the file type, file name, and sector count from the catalog.  Information is included for deleted files for which entries are found in the catalog, as well as all the active files.

The subroutines DISPLAY.TS.LIST, DISPLAY.NEXT.16, SEVEN.SPACES, PR.TS, and READTS are used without any changes from the FIND.TS.LISTS program.  Instead of READ.NEXT.SECTOR, I have now READ.NEXT.CATALOG.SECTOR.  This starts at track $11, sector $0F, and works back as far as sector $01.  A better way might be to follow the actual chain, beginning in the VTOC sector, but the current scheme is easier and works with most of my disks.

Lines 1140-1180 set up the initial catalog track and sector.  Lines 1190-1210 read the catalog sector.  If the returned status is positive we did read a sector, and continue processing; if not, we are finished.  Lines 1220-1250 set up the buffer address in the IOB for reading TS-lists and data sectors:  we do not want to read them over the top of the catalog sector we are working with.

Lines 1270-1320 set up a loop for processing each of the seven file entries in the current catalog sector.  The "NEXT" part of the loop is at lines 1350-1440.  Each catalog entry takes 35 bytes, so lines 1350-1440 add 35 to the pointer.

DISPLAY.DATA.FOR.ONE.FILE first checks for a zero entry, meaning the end of the catalog.  A catalog is initialized to all zeroes, so as soon as we find a zero entry we know there are no more files.  Next, at lines 1520-1550, I check for a deleted file.  If the track number is negative, it is a deleted file.  The actual track number of a deleted file is saved on top of the 30th character of the file name, so I pick it up there.  Lines 1560-1590 save the track and sector of the TS-list, so I can read it later.  Lines 1600-1650 display the file type as a hex value, followed by two dashes.

Lines 1660-1700 print the first 29 characters of the file name.  I don't print the last character because for a deleted file it will have been clobbered by saving the track number there.  Probably what I should do here is print either the last character for an active file, or some special symbol for a deleted file.  You can add that code if you like.

Lines 1710-1770 pick up the file size, in number of sectors, and print it as a hex value.  The sector count includes the sector for the TS-list.

Lines 1780-1860 read the track/sector list for the file.  If either the track number or the sector number is out of range, nothing is read and we skip any further processing for this file.

Lines 1870-1940 read in the first data sector for the file.  Again, if either the track or sector number is out of range, we don't try to read it.  Finally, lines 1950-2000 display the first 64 bytes of the file.

I hope you find these new tools as useful as I have.  Of course, I could hope you will never NEED them, but that would prabably be a vain hope.  I also hope you have "Bag of Tricks" or some similar utility to put it all back together after you get the information my tools provide.  And if I ever clobber Volume 1 on my Sider again (perish the thought), I intend to modify my copies of DOS so they will not allow me to INIT a volume on the Sider.
