Page Index:
Level I Tape Format (Model I and III)
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
SYSTEM File Tape Format
Editor/Assembler Source Tape Format
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:
nn is actually the size of the data plus 2 mode 256, so if nn is 8 it means 2 address bytes and then 6 data bytes, or if nn is 0 then that means 2 address bytes and 254 data bytes, or if nn is 2 then that means 2 address bytes and 256 data 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.
NEWDOS/80’s SYS0/SYS will return an error of 0x24 (TRIED TO LOAD READ-ONLY MEMORY) if the record tries to write into non-existent memory.
Since this is a transfer address and not a load address, nn is actually irrelevant as it isn’t going to load any data.
02 is supposed to be the last header of the file.
NEWDOS/80 SYS0/SYS actually implements this by trying to load the data into memory between 0x0300 and 0x1fff, where the high order byte of the load address comes from the record type. These addresses are assumed to be ROM, and the error 0x24 is suppressed.
Other record types cause DOSERR_LOAD_FILE_FORMAT_ERROR on load.
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.
- 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.
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.
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.
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:
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:
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”.
HDV1 Format Details
Matthew Reed (RIP) designed this emulator hard disk format back in 1997 for his MS-DOS based TRS-80 Model I/III emulator. He intended for it to be used by an emulator-based hard disk driver which communicated directly with the emulator using special hooks.
But it also worked surprisingly well for a hardware emulated hard drive and became the unoffical standard for TRS-80 emulated hard drives. The odd data structure comes about because it was derived from an earlier (no longer in use) disk image format.
My Windows TRS-80 emulator uses an updated version of this format (HDV version 2.0). But version 1.0 is still useful because of its simplicity: any sector position can be calculated using just the information in the header.
Each file starts with a 256 byte header, and sectors follow sequentially after.
- bit 7-1: reserved
- bit 0: set if auto-boot
0 = Model 4 LS-DOS
1 = Model I/III LDOS
2 = CP/M
3 = NEWDOS
If zero, number of heads per cylinder is calculated as number of sectors per cylinder (byte 29) divided by 32.
This is the number of cylinders on the drive. which shouldn’t be higher than 1024. To preserve backwards compatibility, values of 0 in both bytes 27 and 28 means 256.