!pr1
Faster Boot and More Space for DOS 3.3....Bob Sander-Cederlof

A freshly initialized DOS 3.3 disk has 496 free sectors, less whatever is used by your HELLO program.  There are 16 more sectors that are either never used or which are wasted, in tracks 0 and 2.  The following program modifies the code which writes the DOS image and the code which reads it back during boot, so that the entire image fits in tracks 0 and 1.  A further change makes the space in track 2 available for normal files.

The new boot procedure actually is faster than the standard one, and all the new code takes less space than that which is replaced.  All you give up is the ability to boot into machines with less than 48K.  Does anyone still have one?

Standard DOS 3.3 stores the DOS image in two pieces.  The code destined for $B600-BFFF is on track 0, sectors 0 through 9.  The code for $9D00-B500 follows, from track 0/sector 10 through track 2/sector 4.  Sectors 5-15 of track 2 are not used.  The information stored in sectors 3 and 4 of track 2 (aimed at $B400-B5FF) is useless, because all this space is variables for DOS which do not need to be initialized.  The same goes for sector 5 of track 0.  The contents of sectors 10 and 11 of track 0 is not used on a "slave" disk, which is what you get with the INIT command.  My disks have to stay slave disks, because we are going to reshuffle everything around so all the unused sectors end up in track 2.

My new layout stores $9D00-9DFF in track 0/sector 5, and $9E00-B3FF in track 0/sector 10 through track 1/sector 15.  The following table summarizes the old and new layouts.

     Sector    Track 0    Track 1    Track 2
              Old  New   Old  New   Old  New
       0       B6  B6     A1  A4     B1   ..
       1       B7  B7     A2  A5     B2   ..
       2       B8  B8     A3  A6     B3   ..
       3       B9  B9     A4  A7     B4   ..
       4       BA  BA     A5  A8     B5   ..
       5       BB  9D     A6  A9     ..   ..
       6       BC  BC     A7  AA     ..   ..
       7       BD  BD     A8  AB     ..   ..
       8       BE  BE     A9  AC     ..   ..
       9       BF  BF     AA  AD     ..   ..
      10       ..  9E     AB  AE     ..   ..
      11       ..  9F     AC  AF     ..   ..
      12       9D  A0     AD  B0     ..   ..
      13       9E  A1     AE  B1     ..   ..
      14       9F  A2     AF  B2     ..   ..
      15       A0  A3     B0  B3     ..   ..

I published the complete commented disassembly of the code which writes the DOS image on a disk and the code for the second stage boot in AAL way back in October, 1981.  The second stage boot code begins at $B700, and the DOS writer starts at $B74A.  They both use a subroutine at $B793 to read/write a range of sectors.  I preserved the starting points for these two routines in the program which follows, but there is a lot of new empty space.  If you are interested, you could go ahead and shove all the code segments together, patch all the calls for the new locations, and get one big area of free space for adding new features.

I was able to save coding space in several ways.  First, by deciding that I would not worry about running in less than 48K.  Second, that I could eliminate the extra code used to clobber the language card.  This is a very common patch anyway, because most of us do not want to have to keep re-loading the language card area just because we re-boot DOS.  Third, by eliminating the redundant calls to $FE89 and $FE93.  The first stage boot does both of these just before jumping to the second stage boot, so there is no reason to do them again.  And fourth, by being more efficient.  If you want to, you can save even more by doing away with the subroutine at $B7C2:  part of it is redundant, and the rest can be combined with the code at $B74A.

The standard DOS boot first loads $B600-BFFF from track 0, and then skips out to track 2 to read the rest hind-end-first.  The track steps are 0-1-2-1-0.  My new version starts in track 0, reads it all, then reads all of track 1, and it is done.  The track steps are simply 0-1.  It is a lot faster.  However, the overall boot time is not significantly faster, due to the time spent finding track 0 in the first place, and the time spent loading the HELLO program.

Lines 1060-1140 install the new code.  The entire $B7 page is replaced, as well as a single byte at $AEB3.  This byte changes the VTOC on the newly initialized disk so that track 2 is available.  While I was looking at this area, I noticed that the VTOC written on the new disk is not necessarily correct.  DOS does not create an entirely new VTOC for the new disk.  The bitmap area is new, and several other bytes are set up.  However, DOS does not store any values in the bytes which tell how many tracks, sectors per track, sector size, and T/S entries per T/S list.  This means that if the last access to a disk prior to initializing a new one was to a non-standard disk, the VTOC may be incorrect on the new disk.  If I load a file from a large volume on my Sider, and then INIT a floppy, the floppy's VTOC indicates 32 sectors per track and 50 tracks!  Ouch!  Beware!

Lines 1180-1480 are the second stage boot code.  The first stage boot is located at $B601, and actually executed at $801.  It loads in sectors 0-9 of track 0 into $B600-BFFF, calls $FE89 and $FE93 to set the standard 40-column input hooks, and then jumps to $B700 with the slot*16 in the X-register.  My stage two begins by copying the information which came from sector 5, now found at $BB00-BBFF, to the place it belongs at $9D00-9DFF (lines 1270-1320).  Next I set up a call to my RWFT subroutine.

RWFT stands for Read/Write From Table.  I have a table that describes all of the segments which must be loaded from the disk during boot, or written during initialization.  Stage two boot must read the same things written by initialization, but init-ing requires first writing the stuff which will be loaded by stage one boot.  Stage two boot calls RWFT with A=1 (read opcode for the IOB) and Y=2 (skipping the first two entries in the table).  Initialization calls RWFT with A=2 (write opcode) and Y=0 (start at the beginning of the table).

RWFT gets four items out of the table for each step.  The page number and sector number indicate the end of the range to be read or written.  The count tells how many pages (or sectors) need to be read or written.  All of the sectors must be in the track specified by the table entry.  After one range has been read, RWFT steps to the next.  The table terminates when the page address of 0 is found.

For some reason the code at $AEFF looks like this:

       AEFF-  JSR $B7C2
       AF02-  JSR $B74A

Both of these subroutines are never called from any other place, so they could be combined into one.  Doing so would save several bytes.  Furthermore, at least with my new RWFT program, lines 2120 and 2130 could be deleted, saving six more bytes.

There are still more ways to increase the storage on standard floppies, as you probably know.  You can shorten the catalog, make a few other patches, and use some sectors in track 17 ($11).

You can usually use more than 35 tracks, since most drives will handle at least 36 and many a full 40.  This also only takes a few simple patches.  At $AEB5 you normally find a value $8C.  Add 4 to this value for each additional track.  This controls the loop that builds the bitmap of available sectors in the VTOC.  The byte at $BEFE controls how many tracks the formatter in RWTS lays down.  It is normally $23 (decimal 35), so add one for each additional track.  Just before you start the INIT command, change the byte at $B3EF.  This is normally $23, the number of tracks.  Add 1 for each additional track.  You have to be sure to do this last patch just prior to the INIT, because reading or writing another disk will cause it to be changed back.

Incidentally, this reminds me of the potential bug I mentioned above regarding writing out an incorrect VTOC.  Once today I tried to catalog a disk that had been only partially initialized.  The tracks had been written, but no VTOC or catalog sectors were.  Of course I got an I/O ERROR.  Next I decided to INIT that same disk.  It went through the formatting stage, then bombed out with an I/O error when trying to write the catalog.  Looking at the VTOC on this disk, the bytes for number of tracks, et cetera, were all zero!.

Now back to extra tracks.  After making a disk with the extra tracks, you really need to check them to be sure your drive handles them.  Use a disk zap program and try to write on the last track.  Then try to write on the previous track.  If your drive will go out that far, you will be successful.  If you get an error trying to find the next to the last track, keep backing up until you find a track that does work.  All the ones in between were written in the same location on the disk surface as the last track.  If there were any missing tracks, you need to reformat the disk with fewer tracks.

And interesting side not to this discussion is that you could format a disk with LESS than 35 tracks if you wish.  Just so you at least include track 17 ($11), you can reduce the values at $BEFE, $B3EF, and $AEB5 and stop short of a full disk.  Some copy protection schemes do this, along with other tricks, to frustrate the making of copies.
