TRS-80 Tips and Tricks – Tape and File Formats/Structures

Page Index:

Tape Structures

File Structures

Level I Tape Format (Model I and III)

Sync Byte
MSB of Start Address (yes, big endian)
LSB of Start Address
MSB of End Address
LSB of End Address
Tape Data
Checksum. Data bytes plus checksum should equal 0. The checksum byte is loaded into RAM right after the data.

This format is used for both BASIC programs and system tapes. Start address must be 4200H for BASIC. Machine language programs will overwrite 41FEH with a little endian start address. Most machine language programs will load from 41FEH, but as low as 4091H is reasonable. 41FEH is initialized with 0EECH if you wish to consider loading only the high byte. Practically speaking, 42xxH means Level I Basic and $40xxH or $41xxH mean Level I system.

BASIC File Tape Format

LEADER                  256 zeroes followed by an A5 (sync byte)
D3 D3 D3                BASIC header bytes
xx                      1 character file name in ASCII

        lsb,msb         address pointer to next line
        lsb,msb         line #
        xx ... xx       BASIC line (compressed)
        00              end of line marker

00 00                   end of file markers

SYSTEM File Tape Format

TAPE LEADER             256 zeroes followed by a A5 (sync byte)
55                      header byte indicating system format
xx xx xx xx xx xx       6 character file name in ASCII

        3C              data header
        xx              length of data 01-FFH, 00=256 bytes
        lsb,msb         load address
        xx ... xx       data (your program)
        xx              checksum of your data & load address

        .               repeat from 3C through checksum
78                      end of file marker
lsb,msb                 entry point address

Editor/Assembler Source Tape Format

TAPE LEADER             256 zeroes followed by a A5 (sync byte)
D3                      header byte indicating source format
xx xx xx xx xx xx       6 character file name in ASCII

        xx xx xx xx xx  line # in ASCII with bit 7 set in each byte
        20              data header
        xx ... xx       source line (128 byte maximum)
        0D              end of line marker


1A                      end of file marker

CMD File Format

A CMD File is set up with a record type header followed by data. The record type header does not need to be in any particular order, so the order below isn’t necessarily dispositive:

Record Type 05 – Filename

05 nn xx yy zz …
nn = length of the filename block followed by the applicable data.

Record Type 01 – Object Code / Load Block

01 nn xx yy zz …
nn = 00, 01, or 02 meaning that following the next 2 bytes (xx and yy) of the loading address, are followed either by a block of 254, 255, or 256 bytes.

For example, A 01 02 00 6E xx yy zz would mean to set up the load block, indicate that the address for the block is 6E00, and that 256 bytes will follow.

Another example, A 01 01 00 6E xx yy zz would mean to set up the load block, indicate that the address for the block is 6E00, and that 255 bytes will follow.

Record Type 02 – Transfer Address

02 nn xx zz …
nn = length of the block followed by the applicable data. xx = LSB, yyy = MSB

02 is usually the last header of the file.

Editor/Assembler Source File Format


This information was provided by Knut Roll-Lund on August 28, 2018 and explains the structure of EDTASM document files.

Basic Structure of a EDTASM File

  1. Normal header of many [0x00] then [0x5A] and marker [0xD3] (just 1 where basic has 3).

  2. 6 character uppercase filename. If the filename is less than 6 characters, the remainder is padded with spaces [0x20].

  3. Assembly Code (Repeat for Each Line):
    • 5 digit line numbers begin: 0xB0=0 0xB1=1 and so on 5 digits first is like written, most significant first 110 would be 0xB0 0xB0 0xB1 0xB1 0xB0 i.e. ‘00110’
    • A space [0x20]
    • The text of the line in uppercase with space 0x20 and tab 0x09 as appropriate.
    • CRLF [0x0D] to end the line.

  • This continues until [0x1A] to end the file.

  • General

    Typically the last line of the assembly code would be END START where START is the label indicating execution start. “/” in SYSTEM command would execute from there.

    The format is pretty much straight ASCII – no tokenizing or anything. The only special characters are line numbers and the end marker.

    It is possible that cassette storage is tokenized because saving will pause for each line. Maybe it is just for or-ing line number with 0xB0. Unfortunately CAS format can’t represent those pauses and fortunately load does not need them.

    The EDTASM assembly output is so called load format.

    SuperSCRIPSIT Document Files


    This article was written by Tom Price on February 17, 1984 and explains the structure of SuperSCRIPSIT document files, which may be of assistance in repairing damaged files with the aid of a ‘zap’ program or a file editor.

    Basic Structure of a SuperScripsit File

    Each SuperScripsit file has four distinct areas:

    Record 0
    Document header and other vital information
    Records 1 thru 4
    Disk block index
    Record 5
    List of new page markers
    Record 6-END
    Disk blocks containing the text.

    Before getting into the details, it is necessary to define the meaning of a “disk block”. It is 1K in size, consisting of 4 256 byte records. Each block contains a 7 byte header (explained later), up to 985 bytes of text, paragraph and control information, and 32 bytes of overflow space to accomodate minor changes without starting a new block. Each of the four possible header/footer pages will occupy its own block, if present. A document may not contain more than 174 blocks. Blocks are numbered from 0 to 173, with Block 0 starting at document record 6.

    Structure of Document Record 0 – Header

    ID – Always E0, identifies a SS document
    01 – 18
    24 bytes for the document name
    Maximum lines per page in half-line increments
    Pitch – PS=00
    Line spacing in half-line increments
    1C – 23
    8 bytes for printer driver filename
    24 – 25
    Page number to start footers
    26 – 27
    Page number to start headers
    Odd footer length in half-lines
    Odd header length in half-lines
    Even footer length in half-lines
    Even footer length in half-lines
    Horizontal posit of cursor on video display at document close
    Vertical posit of cursor on video display at document close
    Column position of cursor at document close time
    2F – 30
    Document line number of cursor at document close time
    31 – 45
    Tab line 0 (21 bytes)
    46 – 5A
    Tab line 1 (21 bytes)
    NOTE: The 21 byte tab line contains 168 bits, each bit representing a column position. If a bit is set, there is a tab stop at that position.
    5B – 71
    Bit map of disk block allocation (23 bytes)
    NOTE: The first 174 bits of this map represent disk blocks 0-173. If a bit is set, that block is allocated. If the bit is reset, the block is available.
    Disk block number of odd footer (if any)
    Disk block number of odd header (if any)
    Disk block number of even footer (if any)
    Disk block number of even header (if any)
    Disk block number of tab line table (FF = none)
    NOTE: This block has space for 48, 21 byte tab lines, which added to the two available in this record, make up the maximum of 50 tab lines per document.
    Number of tab lines currently assigned to the document.
    78 – 97
    Name of Author (32 bytes)
    98 – B7
    Name of Operator (32 bytes)
    B8 – D7
    Comments (32 bytes)
    D8 – FF
    Not currently used

    Structure of Document Records 1-4 – Disk Block Index

    Byte 00 of the index contains the number of active text blocks in the entire document, not including any blocks assigned to headers, footers or tab lines. Starting with Byte 01 of Record 1, there is room for 174, 5 byte groups, each group representing a disk block containing text. The groups are arranged in the actual order of the document’s text as printed. The meaning of each byte in a group is as follows:

    Disk block number (range 00 to AD). If the value is FF, it denotes the end of the index and all following bytes have no meaning. The actual record number in the file can be found by multiplying the block number by 4 and adding 6.
    01 – 02
    Actual length of valid text in the block
    03 – 04
    Number of lines of text in the block. The upper nybble of byte 04 is used to contain block control information as follows:
    Bit 7 – set if the first line of the block is a whole line, not part of a line from a previous block.
    Bit 6 – set if the block contains an open marker “[“
    Bit 5 – set if the block contains a close marker “]”
    Bit 4 – set if the block has been changed (edited)

    Structure of a Disk Block

    Each disk block starts with a 7 byte header. Bytes 00-01 contain the number of text bytes following the header. This value must be identical to bytes 01-02 of the index group for this block. Bytes 02-06 of the header comprise the default paragraph format for the block as follows:

    Column containing the left margin
    Column containing the right margin
    Column containing the indent tab
    Number of the tab line in use.
    Control byte – following bits are used:
    Bit 4 – Set if the paragraph is frozen
    Bit 3 – Set if the paragraph is centered
    Bits 2 thru 0 – used to indicate line spacing in half-lines.

    After the header comes the actual text. If the block starts with a complete paragraph (line), there will be a 5 byte paragraph group identical in format to the default group in the block header followed by an EF control byte indicating the end of the paragraph info. Then comes the actual text of the paragraph, terminated by an FD, denoting a hard carriage return. This will be followed by a 5 byte paragraph info group for the next paragraph, followed by an EF, and so forth until the number of bytes shown in Bytes 00-01 of the block has been reached. Everything after this point is MEANINGLESS; the text continues on the next block shown in the disk block index. In the text, the following control codes may be encountered:

    Null – deleted text
    Soft page marker
    Hard page marker
    End of paragraph control info
    Start block marker (shows as “[” on screen)
    End block marker (shows as “]” on screen)
    Normal tab
    Align tab
    ‘Code’ for printer control (underline, bold, etc)
    Filler bytes for insert mode
    Space compression for two succeeding spaces (delta)
    Soft carriage return replacing a space
    Soft carriage return replacing a double space
    Hard hyphen
    Hard space (for hyhenation)
    Hard carriage return during inserting
    Hard carriage return
    End of file/text

    Structure of Document Record 5 – List of New Page Markers

    This record contains the location of any hard page breaks (^) in the document. Byte 00 is the number of markers in the document, followed by 127 pairs of bytes (byte FF is not used). Each non-zero byte pair contains the line number, relative to the start of the document (line 0), where a page break is located.

    Armed with the above information, a user with a clobbered file may be able to zap it to the point where it will load properly and allow final repair with the normal SuperSCRIPSIT editing functions. The information in the disk block index MUST agree with what is actually contained in the disk blocks themselves. For example, when the FF byte is encountered in the index, it is a sign that the previous block should contain the FF end of text code some where among the valid bytes of that block.

    DSK Format (DSK/JV1/JV3) Details

    Files with a .DSK or .DMK extension could be JV1, JV3, or DMK format.

    The JV1 format, created by Jeff Vavasour, is just one long string. Since JV1 can only handle single sided, single density, 10 sector-per-track disks, every 257th byte is the beginning of a new sector. Just like the TRS-80 Model I, every sector which is not a directory sector, carries a DAM of FBH. Directory sectors carry a DAM of FAH.

    The JV3 format, also created by Jeff Vavasour, is more complex and can support double density, double sided, write protect, different sector sizes, and other additional changes. It cannot, however, handle copy protected or intentionally scrambled disks. A great writeup of the format can be found here.

    DMK Format Details


    The DMK format is a format developed by David Keil which allows for the storing of TRS-80 disks in pure form, which would allow for the representation of copy protected disks into emulator images. The DMK format gives the ability to support any FM or MFM encoded format that is reasonably close to the IBM 3740 or IBM System 34 standards.

    DMK format disks are easy to discern because of its 16 byte header. Emulators made after 2005 should handle the DMK format.

    The DMK virtual disk format is as close to the way data on a real disk is stored as possible. There is very little added overhead and the data is easily examined and edited using PC based hex editors. The actual design is really quite simple and enables support of ALL the WD-17xx controller functions and formats. While the design is simple however the programming requirements for this format are much more extensive then for the JV1/JV3 formats.

    Disk header:

    Virtual disks have a 16 byte disk header which is initialized when the user creates a new virtual disk. This header may be modified before or after a virtual disk has been formatted to change some of its characteristics.

    Byte 0
    If this byte is set to FFH the disk is ‘write protected’, 00H allows writing.

    Byte 1
    Number of tracks on virtual disk. Since tracks start at 0 this value will be one greater than the highest track written to the disk. So a disk with 40 tracks will have a value of 40 (28H) in this field after formatting while the highest track written would be 39. This field is updated after a track is formatted if the track formatted is greater than or equal to the current number of tracks. Re-formatting a disk with fewer tracks will NOT reduce the number of tracks on the virtual disk. Once a virtual disk has allocated space for a track it will NEVER release it. Formatting a virtual disk with 80 tracks then re-formatting it with 40 tracks would waste space just like formatting only 40 tracks on an 80 track drive. The emulator and TRS-80 operating system don’t care. To re-format a virtual disk with fewer tracks use the /I option at start-up to delete and re-create the virtual disk first, then re-format to save space.

    Note: This field should NEVER be modified. Changing this number will cause TRS-80 operating system disk errors. (Like reading an 80 track disk in a 40 track drive)

    Byte 2 & 3
    This is the track length for the virtual disk. By default the value is 1900H, 80H bytes more than the actual track length, this gives a track length of 6272 bytes. A real double density track length is aprox. 6250 bytes. This is the default value when a virtual disk is created. Values for other disk and format types are 0CC0H for single density 5.25? floppies, 14E0H for single density 8? floppies and 2940H for double density 8? floppies. The max value is 2940H. For normal formatting of disks the values of 1900H and 2940H for 5.25? and 8? are used. The emulator will write two bytes and read every second byte when in single density to maintain proper sector spacing, allowing mixed density disks. Setting the track length must be done before a virtual disk is formatted or the disk will have to be re-formatted and since the space for the disk has already been allocated no space will be saved.

    WARNING: Bytes are entered in reverse order (ex. 2940H would be entered, byte 2=40, byte 3=29).

    Note: No modification of the track length is necessary, doing so only saves space and is not necessary to normal operation. The values for all normal 5.25? and 8? disks are set when the virtual disk is created. DON’T modify the track length unless you understand these instructions completely. Nothing in the PC world can be messed up by improper modification but any other virtual disk mounted in the emulator with an improperly modified disk could have their data scrambled.

    Byte 4
    Bit 4 of this byte, if set, means this is a single sided ONLY disk. This bit is set if the user selects single sided during disk creation and should not require modification. This flag is used only to save PC hard disk space and is never required.

    Bit 6 of this byte, if set, means this disk is to be single density size and the emulator will access one byte instead of two when doing I/O in single density. Double density can still be written to a single density disk but with half the track length only 10 256 byte sectors can be written in either density. Mixed density is also possible but sector timing may be off so protected disks may not work, a maximum of 10 256 byte sectors of mixed density can be written to a single density disk. A program like “Spook House” which has a mixed density track 0 with 1 SD sector and 1 DD sector and the rest of the disk consisting of 10 SD sectors/track will work with this flag set and save half the PC hard disk space. The protected disk “Super Utility + 3.0” however has 6 SD and 6 DD sectors/track for a total of 12 256 byte sectors/track. This disk cannot be single density.

    This bit is set if the user selects single density during disk creation and should not require modification. This flag is used only to save PC hard disk space and is never required.

    Bit 7 of this byte, if set, means density is to be ignored when accessing this disk. The disk MUST be formatted in double density but the emulator will then read and write the sectors in either density. The emulator will access one byte instead of two when doing I/O in single density.

    This flag was an early way to support mixed density disks it is no longer needed for this purpose. It is now used for compatibility with old virtual disks created without the double byte now used when in single density. This bit can be set manually in a hex editor to access old virtual disks written in single density.
    Byte 5-B
    Reserved for future options.
    Byte C-F
    Must be zero if virtual disk is in emulator’s native format.

    Must be 12345678h if virtual disk is a REAL disk specification file used to access REAL TRS-80 floppies in compatible PC drives.

    Track Header
    Each track has a 128 (80H) byte header which contains an offset to each IDAM in the track. This is created during format and should NEVER require modification. The actual track data follows this header and can be viewed with a hex editor showing the raw data on the track. Modification should not be done as each IDAM and sector has a CRC, this is just like a real disk, and modifying the sector data without updating the CRC value will cause CRC errors when accessing the virtual disk within the emulator.

    Note: Modification within MSDOS could however be done to emulate a protected disk in the TRS-80 emulator. Each side of each track has a 128 (80H) byte header which contains an offset pointer to each IDAM in the track. This allows a maximum of 64 sector IDAMs/track. This is more than twice what an 8 inch disk would require and 3.5 times that of a normal TRS-80 5 inch DD disk. This should more than enough for any protected disk also.

    Each IDAM pointer has two flags. Bit 15 is set if the sector is double density. Bit 14 is currently undefined. These bits must be masked to get the actual sector offset. For example, an offset to an IDAM at byte 90h would be 0090h if single density and 8090h if double density.

    These IDAM pointers MUST adhere to the following rules.
    • Each pointer is a 2 byte offset to the FEh byte of the IDAM. In double byte single density the pointer is to the first FEh.
    • The offset includes the 128 byte header. For example, an IDAM 10h bytes into the track would have a pointer of 90h, 10h+80h=90h.
    • The IDAM offsets MUST be in ascending order with no unused or bad pointers.
    • If all the entries are not used the header is terminated with a 0000h entry. Unused entries must also be zero filled.
    • Any IDAMs overwritten during a sector write command should have their entry removed from the header and all other pointer entries shifted to fill in.
    • The IDAM pointers are created during the track write command (format). A completed track write MUST remove all previous IDAM pointers. A partial track write (aborted with the forced interrupt command) MUST have it’s previous pointers that were not overwritten added to the new IDAM pointers.
    • The pointer bytes are stored in reverse order (LSB/MSB).
    Track Data
    The actual track data follows the header and can be viewed with a hex editor showing the raw data on the track. If the virtual disk doesn’t have bits 6 or 7 set of byte 4 of the disk header then each single density data byte is written twice, this includes IDAMs and CRCs (the CRCs are calculated as if only 1 byte was written however). The IDAM and sector data each have CRCs, this is just like on a real disk.

    Modification should not be done since doing so without updating  the CRCs would cause data errors. Modification could be done however to create protected tracks for importing protected disks to virtual disk format. Examples of disks created using this technique are “Super Utility+ 3.0” and “Forbidden City”.