- Level I Tape Format
- Level II BASIC File Tape Format
- System Tape Format
- Editor/Assembler Source Tape Format
- CMD File Format
- Editor/Assembler Source File Format
- SuperSCRIPSIT Document Files
- DSK/JV1/JV3 File Structure
- DMK File Structure
Level I Tape Format (Model I and III)
Leader A5 Sync Byte MSB Start Address (yes, big endian) LSB MSB End Address LSB data bytes (end - start bytes) XX Checksum; data bytes plus checksum should equal 0. The checksum byte gets loaded into memory right after the data. Format is used for both Basic programs and system tapes. Start address must be $4200 for Basic. Machine language programs will overwrite $41FE with a little endian start address. Most machine language programs will load from $41FE, but as low as $4091 is reasonable. $41FE is initialized with $0EEC if you wish to consider loading only the high byte. Practically speaking, $42 means Level I Basic and $40 or $41 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
Record Type 01 – Object Code / Load Block
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 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
- Normal header of many [0x00] then [0x5A] and marker [0xD3] (just 1 where basic has 3).
- 6 character uppercase filename. If the filename is less than 6 characters, the remainder is padded with spaces [0x20].
- 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.
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:
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
[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.
[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.
[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.
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:
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:
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:
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.
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.
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)
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.
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.
Must be 12345678h if virtual disk is a REAL disk specification file used to access REAL TRS-80 floppies in compatible PC drives.
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).
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”.