TRSdisk - TRS-DOS utilities and direct host filesystem access.

Posting to a USENET thread in comp.sys.tandy, Nick Andrew spoke of his desire to have a TRS-80 emulator access a native file system directly. Tim Mann responded with some implementation ideas. I read it all to myself quietly thinking: ``Yeah, that would be cool. And what better excuse to learn about the TRS-DOS file system?''

As much to see if it were even possible I hacked together this collection of command line utilities, TRS-DOS filesystem subroutines, block-level disk interfaces and a host directory to disk (and back) translator.

The utilities are marginally useful, but the best part is the minimally functional xtrs-4.9 additions to give it direct access to host file systems. Note that the actual TRS-80 emulation has not been changed. There are no new instructions or other fudgery. All I've done is make it understand that it can treat a host directory as a virtual disk and call my routines to translate it on-the-fly into low-level disk blocks.

Read on for download, installation and usage instructions. But first, an important note:

WARNING

In its current state, TRSdisk is a proof-of-concept prototype. To be clear, it has many known bugs that are guaranteed to corrupt files and otherwise lose your precious data. I'd tell you to use it at your own risk, but there's really no risk -- it will screw you over.

Well, okay, it's not that bad, but it's really no more than a toy to look at for now. Things should be OK if you only ever read from a dirdisk, but even then files can get inadvertantly hidden.

I've done limited testing. The xtrs patches are for version 4.9 and have only been tried against it running a Model I ROM and with single density LDOS 5.31 disks all on top of FreeBSD 4.2.

WARNING

Download

TRSdisk source code is available in two forms:
gzipped tar file:   trsdisk-0.4.tar.gz
zip archive:   trsdisk-0.4.zip

Installation

Extract the files from the archive you downloaded and run make. I tried to write generic UNIXy C code but then again I've only compiled it under FreeBSD 4.2. If you have problems then either apply your wizardly skills or give me a shout and I might be able to help.

Test Drive

Here's a sequence of commands that will give your newly built utilities a test and you a quick feel for what they do.

% mkdir test
% cp *.h test
% trsbackup test test.dsk
% trsdir test.dsk
directory on track 17, block 170
test     DD/MM/YY 35 tracks 2 gran/track
[a2] boot.sys        513  1 extents 0/1
[94] trsfile.h      4746  1 extents 1/4
[d5] jv1.h           264  1 extents 5/1
[76] disk.h         1628  1 extents 6/2
[7e] dirdisk.h       267  1 extents 8/1
[c4] dir.sys        2560  1 extents 34/2
% trsread test.dsk jv1.h
% diff jv1.h test/jv1.h
[ and if you see any differences ]
% cp test/jv1.h .
and then file a bug report.

With any luck you can open test.dsk under just about any TRS-80 Model I/III emulator with disk support.

xtrs-4.9 Installation

Copy the following files from the trsdisk source directory to your xtrs-4.9 source directory:

boot_sys.c dirdisk.c dirdisk.h disk.c disk.h trsfile.c trsfile.h

Now you can either replace the xtrs-4.9 Makefile and trs_disk.c files with the copies from the xtrs-4.9 directory of the trsdisk source directory or apply the patch files Makefile.patch and trs_disk.c.patch.

Build xtrs-4.9 as you normally do and you're ready to try it out.

xtrs-4.9 Test Drive

There are many different ways to run xtrs, but for the sake of simplicity lets assume it's emulating a Model I and is running an appropriate DOS in drive 0 such as LDOS 5.31.

In whatever directory that holds the boot disk (the disk1-0 file) make an empty dirdisk by creating the directory disk1-1. Run xtrs. After the DOS has booted you should see an empty disk in drive 1 (try a DIR :1 command).

If that works, try copying a file from drive 0 to drive 1. Verify that you see the new file on drive 1 within the emulator and in the disk1-1 directory.

As far as my limited testing has gone, the TRSDOS commands DIR, COPY, RENAME, KILL and LIST will all work fine. FORMAT and BACKUP will not except that BACKUP from a dirdisk drive to a ``normal'' single-density drive will work.

Technical Notes

How feasible is it to map sector-level disk operations back into file-level operations? I believe it is entirely possible as long as you are willing to buffer disk sectors for an arbitrarily long period of time. Here's a proof sketch. At startup construct a disk image from the source directory and store it in a file. Whenever sectors are read or written by the emulator access the disk image respectively. Whenever the file system on the disk image is in a consistent state, erase the source directory and re-populate it based on the disk image file system.

Can a limit be imposed on the time we must buffer sectors? Trivially the answer is no. The emulated DOS can keep a file open for an arbitrary length of time. How about if we assume that we will regularly arrive at a state where no files are open? That restriction helps tremendously, but we're still stuck with sectors that are written but not allocated to any files. We can't ever get rid of them as at any time a file could be created that uses one of those sectors. We may be able to avoid that situation by assuming that sector editors are not used, but the commonly used BACKUP command presents the same property.

While it's true in general that once a sector is written you're stuck with remembering it, I do think a few heuristics will give a practical if not provably perfect solution. That is, we only need temporary sector storage and will store data in real host files. BACKUP can be solved by looking for its dogged pattern of sequential sector writes. Verifying for filesystem consistency seems pretty unassailable as a check against open files. Preferably something taking less that a full disk check, though.

As it turns out, the order of operations used by LDOS (and no doubt other TRS-80 DOSes) makes even an extremely simple directory disk implementation work. When copying onto a disk the directory entry is initialized before any sectors are written to the file. Moreover, the directory entry notes the sector allocations before they are written. A straightforward implementation can expect to know definitively if a sector belongs to a file or not and expect that file to exist.

It also seems apparent that file operations happen one at a time which keeps things simple. Imagine the challenge posed if a single directory sector write showed file A renamed to B and file B renamed to A. But practically speaking only one change in a directory will happen with any write. Mind you, I remember old MS-DOS utilities that would sort directory entries (because DIR was too stupid to do it automatically). Such a TRS-DOS utility would stress a directory-based disk implementation quite well.

Future Directions

As is typical of my projects I have a long list of places I'd like to go with TRSdisk. My number one priority is making it possible to boot a TRS-80 emulator from a dirdisk. It'd nicely round out my knowledge of TRS-DOS and provide me with all the tools to make turnkey TRS-80 systems. Yes, that could easily be done with a disk image, but the cleanliness of a dirdisk is too appealing. The security/privacy conscious may wish to take note that disk images pose a risk of exposing unintended information. Look in the unallocated sectors of a disk image and who knows what you'll find beyond the files listed in the directory.

My number two priority is support for other floppy sizes and hard disks. Shouldn't be too hard as the code nearly supports other floppy sizes and the hard disks are more a matter of choosing DOS extensions. But a lack of experience in these emulation matters and no immediate need are keeping this a lower priority.

Number three is fully supporting format and backup operations in both xtrs and the command line tools. It'd be cool and raises some interesting challenges. You could make it work by being more aggressive about remembering sectors that were written. The trick is figuring out when it is safe to flush all sectors not reachable from the directory. That's easy for format as formatted sectors can be 100% simulated by unallocated blocks in the dirdisk. Not so easy for backup as the sectors themselves will look non-empty and, in the general case, you could never be 100% sure that a directory write is about to come along and reference those sectors. Still, some cheap heuristics could no doubt solve the problem well enough for the expectedly hard-core user base.

Otherwise, the bugs should be fixed and there needs to be a trswrite to complement trsread. Might as well add trskill and trsrename to round out the file operations. While in theory such utilities are obsolete because host file operations can be used on a directory-backed disk, you'll still have disk images and sometimes a bit of direct manipulation is the easiest way forward. Along similar lines, the utilities could support JV3 and DMK format images.

Then there are the more far out ideas:


George Phillips, June 15, 2002.   gp2000 -at- shaw.ca