cassette(1) data cassette image manipulator for xtrs TRS-80 emulator




To control the emulated cassette used by xtrs, a file called ".cassette.ctl" in the current directory keeps track of what file is currently "loaded" as the cassette tape and the current position within that file. The cassette shell script provides a way to manipulate this file; typing "help" at its prompt shows its commands. You may use this script to load and position cassette tape files. The operation works very much like an actual tape recorder.

This manual page also describes the image formats that the emulator supports and their limitations.


pos generates a status message including the filename being used as the cassette image and the current position within the image, in bytes.

load [filename] changes the cassette image currently being used to the file specified, and resets the position counter to zero.

type typename tells the emulator what type of image is loaded. Usually this is detected from the file extension, but you can override the detected value with this command. The supported types are listed in the next section.

rew [position] changes the position counter to the position specified. If no position is given, the counter is reset to zero.

ff [position] changes the position counter to the position specified. If no position is given, the counter is set to the end of the file.

quit exits the cassette shell script.


xtrs supports several different types of cassette images, each of which represents cassette data in a different format.

cas format is fairly compact and is compatible with other TRS-80 emulators that have cassette support. This format represents the bit stream that (the emulator thinks) the TRS-80 cassette routines were trying to save to the tape, not the actual electrical signals on the tape.

On writing, the emulator monitors the values that the TRS-80 software is sending to the cassette port and their timing, auto-recognizes whether a 250-bps, 500-bps, or 1500-bps format is being written, decodes the signals into a string of 0 and 1 bits, packs the bits into bytes, and writes them to the cas file. On reading, the emulator auto-detects whether software is trying to read at 250, 500, or 1500 bps and encodes the 0's and 1's back into the signals that the TRS-80 software is expecting. This somewhat roundabout method should work with most TRS-80 cassette routines that read and write signals compatible with the ROM cassette routines, but it may fail with custom routines that are too different.

Note that generally nothing useful will happen if you try to write a cas image at one speed and read it at another. There are differences in the actual bit streams that standard TRS-80 software records at each of the three different speeds, not just differences in encoding the electrical signals on the tape. Thus an incoming bit stream that was originally recorded at one speed will not be understood when read back in at a different speed. For example, Level 2 Basic programs are tokenized, while Level 1 Basic programs are not, and the two Basic implementations record different binary information at the start of the program and between lines. Also, when a file is saved at 1500 bps, standard TRS-80 software puts an extra 0 bit after every 8 data bits, and these extra bits are packed into the cas file along with the data bits.

cpt format (for "cassette pulse train") encodes the exact values and timing of the signals that the TRS-80 cassette routine sends to the cassette output port to be recorded on the tape. Timing is to the nearest microsecond. This format emulates a perfect, noise-free cassette, so any cassette routines that even halfway worked on real hardware should work with it.

wav format is a standard sound file format. The wav format is intermediate in emulation accuracy between cas and cpt. It does represent actual signals, not decoded bits, but its timing precision is limited by the sample rate used. The default rate for new wav files is 44,100 Hz; you can change this with the -samplerate command line option to xtrs.

You can play wav files written by xtrs through your sound card and hear roughly what a real TRS-80 cassette sounds like. A real TRS-80 should be able to read wav files written by xtrs if you copy them to a cassette or connect the TRS-80 directly to the sound card's output. This feature has not been tested extensively, but it does seem to work, at least for short programs.

xtrs can also read wav files. It can read back the wav files that it writes without error. Reading wav files sampled from real cassettes is more difficult because of the noise introduced, but in brief testing it does seem to work. The signal processing algorithms used are very crude, and better ones could probably do a better job of reading old, noisy cassettes, but I don't have any such cassettes to test with (and I don't know much about signal processing!). Help in this area would be welcome.

The wav file parsing code has several limitations. Samples must be 8-bit mono, and the wav file must contain only one data chunk and no extra optional RIFF chunks in the header. If you have a wav file whose header xtrs rejects, try using sox(1) to convert it to a more vanilla format.

direct format is similar to wav format, except that the samples go to (or come from) your sound card directly, not a wav file. Direct format requires the Open Sound System /dev/dsp device. Extending the code to work with other sound interfaces would probably not be hard, but is left as an exercise for the reader. Please send me the changes if you do this.

debug format is the same as cpt format except that the data is written in human-readable ASCII. The cassette output is assumed to be 0 initially. Each line of output gives a new value (0, 1, or 2), and the amount of time (in microseconds) to wait before changing the output to this value.


xtrs 1.0 was written by David Gingold and Alec Wolman. The current version was revised and much extended by Timothy Mann (see An initial version of this man page, and the translation from C-shell (cassette) to Bourne shell (, are due to Branden Robinson.