THE TRANS-WARP DRIVE
by DAVID SMALL and DAN MOORE
This program lets you run all of your floppy disks at up to twice their present speed. Copy it into your Auto folder; that's all you need to do. You'll notice the difference immediately the next time you go to floppy.
To make your copy of Trans-Warp, type in the ST BASIC program shown in Listing 1. When you've finished, check your typing with ST Check (ST-Log, September '88), then run the program by loading it into ST BASIC and typing "RUN." The Trans-Warp program will be written to the disk in drive A.
Dan and I have long been obsessed with speeding up and improving the ST computer. It might seem like overkill; after all, the ST is already one fast machine. However, there are certain parts of the ST which can stand some improvement. (Besides, it's always fun to soup up a computer.)
There have been several programs written recently that correct a subtle bug in Atari's seek-with-verify code. Using disks that are formatted by such programs, you can get data to and from the floppy disk at twice the normal floppy speed.
Now, wouldn't it be nice if all your floppies ran at high speed? Most of us already have a considerable library of floppies, and copying/reformatting them to a new format takes a lot of work.
However, destiny waits for no one, not even us. One evening Dan and I were sitting in his office, grimly swigging Boodles and Strohs after crashing yet another hard disk. I was staring at his Bill the Cat doll. It's a cute thing, what with its bug eyes, lolling tongue, and "Ack!" vocabulary. (Ever seen Teddy Ruxpin? Imagine a Teddy that just says, "Ack!", and you'll get the idea.)
I was staring at Bill—and—and—Bill began to speak to me. A strange sight in deed, but probably no stranger than a Shirley MacLaine novel.
It said, "Dave! Ack! Dave, what you need to do is re-code RWABS to handle sector latency! Do two reads instead of one per track, skew them, and all floppies will then run at double speed! Oop Ack!"
In the throes of inspiration, I turned to Dan, trying to speak. All I could manage to choke out was, "Ack!" Dan looked intensely interested, stared at me in concern, and said, "If you're going to be sick, go outside."
A few evening's hacking sessions gave us what we cheerfully call the Trans-Warp drive. Only the interest in a high-tech sounding name, and Berke Breathed's copyright, prevent us from calling it the Trans-Bill drive.
A brief review of the problem that we're correcting will help explain why Trans-Warp works.
Atari diskettes have nine sectors, labeled one through nine in a circular track. An "index pulse" marks the beginning and end of a track. From the point of view of the disk head, the sectors spin by underneath, like this:
(index pulse) 1-2-3-4-5-6-7-8-9
(index pulse) 1-2-3-4-5-6-7-8-9
and so forth. Floppy disks rotate at five revolutions per second (300 RPM). When you read a large amount of data (each track is about 6K), the process goes like this:
- —Read Sectors 1–9 of current track
- —Step head to next track
- —Read Sectors 1–9 of that track
- —Step head to next track
and so on.
Ideally, this should be done so that you "land" on the next track in time for Sector #1 to spin underneath the head. You then "catch" Sectors 1 through 9 in your next read. The floppy controller is pretty dumb, so if it doesn't catch Sector 1, it waits for Sector #1 to spin all the way around again, then reads 1 through 9. (There isn't any good way to tell the floppy controller to "read the next sector that spins by regardless of what it is," or there wouldn't be much of an article here.)
Alas, Atari made a small slip-up in their "Step head," or "seek," routine. They made it a seek-with-verify. In this variation of a regular seek, the head is moved to the new track, then the first sector "mark" encountered is read to verify that the head landed on the proper track.
Unfortunately, this screws up high-speed data transfer, as follows:
- Read Sectors 1 through 9 of current track. (The disk is now right near the end of the track.)
- Step to next track. (The disk has now spun to about the beginning of the next track.)
- Read sector mark to verify track number. (The disk now spins until we find Sector 1, which is used to verify the track number.)
- The seek now completes. We now try to read Sectors 1 through 9.
Alas, the disk is now coming up on Sector 2. So, we wait until Sectors 2 through 9 spin around (a complete revolution), and then find Sector 1, read Sectors 1 through 9, and continue. In short, every time we step the head, we cost ourselves a revolution—and one-fifth of a second.
Now, a one-fifth of a second delay per track may not seem like much. But there's 80 tracks on the disk; that delay adds up to 16-seconds per disk side (32 seconds on a double-sided floppy, such as 1040ST or SF 314 drive).
What can we do about this delay?
The first way around it is to lay out the sectors on the track differently, providing a few sectors to satisfy seek-with-verify without slowing us down very much. The second solution is to change the operating-system code.
Both of these have advantages and disadvantages. The format solution requires you to reformat all your disks. The operating-system solution requires a terminate-and-stay-resident routine that may not always be allowed. Hence, you can pick the one that works for you best.
How do we "steal away" floppy-disk requests so we can handle them? The solution is RWABS.
The last place we have control of the disk is at the RWABS "vector" (Read/Write Absolute), a memory location that all disk accesses jump through. RWABS is provided as a convenient place to steal all disk accesses for devices such as hard disks and RAMdisks.
Whenever you do a disk access through RWABS, the system jumps to wherever the RWABS vector points to. For instance, if RWABS contains $12345678, then anytime you go to disk, the system jumps to address $12345678. Ordinarily, the RWABS vector points to somewhere in ROM, to the floppy disk RWABS routine (somewhere in the $FCxxxx area).
However, because this RWABS is a RAM location, we can redirect disk requests to other places. Typically we will also save the old RWABS value, so we can always go to where the original RWABS was pointing (e.g., the floppy-disk handler).
Let's assume you "steal" RWABS, by putting your routine's location in RWABS. Now, when a disk request is made, your routine gets jumped to. You get control of the system. You look at the various parameters which have been placed on the stack (device number, sector number to start at, number of sectors you want, and where to put them). If the device number is one you want to process, then you take control and never let the floppy RWABS routine handle the request. On the other hand, if it's a floppy disk request, you'd go to where the old RWABS used to point—to the floppy handler.
Let's say you have a two-floppy system (drives A and B) and a RAMdisk as drive C. (This is a very common setup.) The RAMdisk steals RWABS and directs all disk requests to the RAMdisk RWABS handler. Then the RAMdisk installation routine quits, typically with a terminate-and-stay-resident (TSR) call.
What's a TSR? It's a way for a program to return control to the operating system (GEM/TOS) leaving the program code itself in memory. In our case that's pretty important; we've just redirected all disk I/O requests to our program, so it had better hang around! (Desk accessories, incidentally, are another example of a TSR.)
Now, when the user calls the operating system with a disk request, our RWABS handler gets called. It says, "Is this a request for me (Drive C, The RAMdisk)?" If the answer is "yes," the RAMdisk handler takes care of the request and returns to the user. If it's a request for drives A or B, however, it just passes the request to the floppy RWABS and lets the floppy RWABS handle it.
Hard disks just add another level to this daisy-chaining; the hard-disk RWABS looks at the device number (drive letter), decides if it wants to handle the request, and if not, goes back to the original RWABS. Generally, the hard-disk handler is installed first after boot-up, then any further handlers (such as RAMdisks).
Now, we don't have to give the operating system control if drive A or B is requested. In fact, we don't want to, because the OS handler is slow. So let's recode the system floppy RWABS handler and steal away all floppy-disk requests, forever. Our new handler will take care of floppy read/write requests in a special way which will mollify the seek-with-verify routine and thus not slow us down. Then, as long as our new RWABS routine is around, all floppy requests will run at double speed—we'll quit missing a revolution each time we read a track.
Basically, our installation routine will do what's described above in terms of stealing away RWABS and passing control to non-floppy devices. The only difference is we'll handle floppy requests ourselves.
Of course, our routine must stay resident, as all floppy disk requests will be going to it. If you want to write your own TSR utilities, this will probably be a good place to start.
We'll dig into exactly how we short out the system handler in a moment. First, some research on RWABS.
Inside of RWABS
RWABS does several things. Coming into RWABS, we have a request for a certain number of sectors, starting at a certain absolute sector number. This number of sectors can, and often does, span several tracks. Hence, RWABS must "break up" the request into multiple track requests. RWABS must also worry whether you've changed the disk—lest it accidentally write to a new disk—and whether or not the disk is double-sided.
RWABS calls a routine known as FLOPRW, which takes your disk request (which drive, starting sector, number of sectors, etc.) and breaks it up into track-sized requests. FLOPRW then goes and reads in a track at a time, using floprd and flopwr, the lowest-level sector requests.
Ordinarily, if FLOPRW wants an entire track, it just reads Sectors 1 through 9 on the current track. This is where we interfere. We break up an ordinary "read Sectors 1 through 9" request like this:
- —If we're on Track 0, just go read Sectors 1 through 9.
- —If we're on Track 1, read Sectors 3 through 9, then read 1 and 2.
- —If we're on Track 2, read Sectors 5 through 9, then read 1 through 4.
- —If we're on Track 3, read Sectors 7 through 9, then read 1 through 6.
- —If we're on Track 4, just read 1 through 9.
The pattern repeats across all 80 tracks of the disk.
At first, this may seem confusing. However, let's draw a map of what sectors we're reading, on what track, and at what point in time. That'll help clear up what's going on. We'll assume a long sequential read, which is what we're trying to speed up.
Also remember that any time we place a new read request, we need to give one or two sectors up to the seek-with-verify routine to complete the seek. Remember, at least one sector is going to have to spin by before the seek will finish up.
The logistics of breaking up one track request into two sequential reads aren't that difficult. We take the modulus/4 of the track number (the remainder after dividing by four), then use it to look up in two arrays where to begin reading on the first read and where to end reading on the second read. In our code, we call this the "primary read" and "secondary read." On "even" tracks, there is no secondary read.
You've got to look at a track read as occurring after a read from the previous track, a read which we don't know about anymore. We assume that the head is at a certain location on the track we are currently on, and begin reading where the head is (or will be quite shortly). After that, we go grab the beginning of the track.
What happens if we "miss," or if this is the start of a read? The worst is that we miss nearly one spin, which is what Atari's code does at best. Not bad at all.
The Revenge of the Seek-With-Verify
We thought we had it conquered. We wrote the code, got the syntax errors out, (I hate to say, "debugged" it), and fired it up. Yes, the beer and Boodles were flowing freely; we were celebrating.
Alas, the celebration soon turned to mourning.
There was no speed increase at all!
Atari's seek-with-verify wasn't finished with us yet, regrettably. If you like, refer to your Atari BIOS listing—every time you do a floppy-read request, you do a seek-with-verify to whatever track you need to read, even if it is the track you're on. This means every time you issue a read request, you're probably going to lose a spin. Seek-with-verify doesn't care that it already knows what track you're on; it's too dumb. It'll go ahead and re-verify the current track, using up a sector mark.
You can confirm this for yourself (and it's something to keep in mind when you're writing software!). Do a floppy read (floprd) of all nine sectors on a track. You'll find the read will complete in about two and three-fifths seconds: one spin to mollify the seek, one spin to do the read, and some extra depending on where the head was.
Now, go do nine individual reads of one sector: 1,2,3,4,5,6,7,8,9. You'll find it takes nine spins to do it, or nine times as long as the track-sized read! It's because every time you go do the read, the seek-with-verify grabs the next sector to verify the track—and that next sector is usually the one you want. For the software designer, this means always read a track at a time unless you want to get some really bad floppy-disk response.
I know, your hair is standing on end. But it gets worse.
Nightmare on Track Street
If you go to the second side of a double-sided disk, guess what? You get another seek-with-verify. This is why we had to "double twist" the double-sided version of our disk formatter, adding an extra two sectors to any second-side request. (At the time, we didn't know why it was needed, only that it was needed.)
That's sad, because ordinarily double-sided disks are quite fast; switching heads is instantaneous, and you don't have to do a seek, which is the slowest part of a disk operation. This one seek-with-verify operation manages to slow up three different aspects of floppy operation.
Our number one request for the new ROMS: Get rid of the seek-with-verify! Bribes available upon request. Write for details. (Note: Atari has now already done this. Hooray!)
Back to Our Story
At this point, the supply of Boodles and Stroh's was getting thin, and the program still wasn't working. So Dan and I decided to commit the unpardonable sin and go straight to the ROMS, bypassing the seek-with-verify, to get the routine working. There just wasn't any other way to do it.
Well, when the ROMS change, preferably sometime before the next Ice Age, we'll be happy to update the code—but in the meantime, that's no reason not to enhance the old ones. We even put a check in to make sure you're running with the right ROM set.
If you'll look at our listing (available on this month's disk version), you'll see two new routines, which handle floppyread and floppywrite. They bypass the seek-with-verify routine part of floppy read/write, then jump to the "real" ROM handlers. We use these new routines anytime we're content that we're on the proper track (e.g., we know we have seeked to the right track, for instance, on double-sided requests).
So, we put in the new routines, fired the system up, opened our last beer and tonic water, and zoom!—it worked. Ordinary mortal floppies began to read and write at Twister speed. Thank heavens.
Of course, the read-after-write-verify must be switched off. If this offends you, remove the MOVE to location $444 and reassemble. We also make all Resets into real Resets, which prevents lots of problems; if you don't like that, get rid of the "memvalid" clear.
Does It Work on Ten-Sector Disks?
Ever since floppy owners have figured out that you can put ten sectors on a track, and get 400K per disk side instead of 360K, the ten-sector format has been popular. Proper credit should go to James Eli, whose public domain program FORMAT turned us on to ten sectors per disk.
It's a little more work for us, because there's little or no room left at the end of the track in a ten-sector format. This room gives lots of "slop" for seek time. However, we make up for it by skipping two sectors per spin; the seek ends right around the first sector's start, leaving the second sector to verify the seek.
Trans-Warp uses GEM's variable, passed to RWABS, which tells how many sectors there are per track. (It's straight from the boot block data that protobt writes.)
Well, there you have it: maximum floppy speed for ordinary floppy disks. Put Trans-Warp (TWARP.PRG) in your AUTO folder, and you'll really hear the floppies accelerate. (Just listen to the tick-pause-tick-pause of the floppy seek changing to tick-tick-tick). We hope you enjoy Trans-Warp, and hope that it finds its way to many of your AUTO folders. Certainly it's a permanent resident in ours.
You install Trans-Warp by either placing it in your AUTO folder, then starting up the computer, or just double-clicking on TWARP.PRG directly. Either way, you'll get a friendly sign-in message, then return to the regular desktop/command line. Your floppies are now set up for double speed.
People doing GEM-based DISKCOPY should be warned—DISKCOPY does so much screen drawing between each track that it fouls up our careful sector skewing. You'll see this as a slow-down to normal speed during DISKCOPY. We decided not to slow down all floppy requests to handle this one special case.