VAPI / ATX Disk Image Format

Overview

The VAPI disk format is used to accurately preserve Atari disk images. This page attempts to capture what (incomplete) information has been released about the format thus far. If any inaccuracies or additional information is known, please let me know so this page can be updated.

Structure

The general structure of an ATX file is a file header followed by one or more track records.

File Header (FH)

The file header can vary but is usually 48 bytes:

'A'
1 byte
'T'
1 byte
'8'
1 byte
'X'
1 byte
version_number
2 bytes (little-endian)
reserved
22 bytes
size
4 bytes (little-endian)
reserved
16 bytes

version_number: e.g. 1

size: offset from start of file to first track record.

Track Record (TR)

A track record is comprised of a track header (TH), a sector list (SL), sector data (SD) and optional extended sector data (XSD).

Track Header (TH)

The track header can vary but is normally 32 bytes:

record_size
4 bytes (little-endian)
record_type
2 bytes (little-endian)
reserved
2 bytes
track_number
1 byte
reserved
1 byte
sector_count
2 bytes (little-endian)
reserved
8 bytes
header_size
4 bytes (little-endian)
reserved
8 bytes

record_size: size of the whole track record in bytes (including header).

record_type: can be one of the following values:
ValueType
$00data track

track_number: zero-indexed (nominally 0-39).

sector_count: number of physical sectors in track.

header_size: offset from start of track header to start of track data in bytes.

Sector List (SL)

A sector list is comprised of a sector list header (SLH) and one or more sectors headers (SH).

Sector List Header (SLH)

The sector list header can vary but is normally 8 bytes:

size
4 bytes (little-endian)
record_type
1 byte
reserved
3 bytes
size: size of sector list in bytes.

record_type: can be one of the following values:
ValueType
$01sector list
Sector Header (SH)

The sector header is 8 bytes:

sector_number
1 byte
sector_status
1 byte
sector_position
2 bytes (little-endian)
start_data
4 bytes (little-endian)

sector_number: 1-indexed (note: if the track has duplicate sectors, there will be multiple sectors with the same sector number).

sector_status: 1 byte broken down as follows:
BitDescription
7Reserved (must be zero)
61 = extended data present for sector
51 = deleted sector (DAM $F8)
41 = missing sector data
31 = FDC CRC error
21 = FDC lost data error
1Reserved (must be zero)
0Reserved (must be zero)

sector_position: zero-based starting angular position of sector in 8us intervals (1/26042th of a rotation or ~0.0138238 degrees). Nominally 0-26042.

start_data: offset in bytes from the start of the track header to the sector data (SD). Note: no data is present if sector data is missing (sector status bit 4)

Extended Sector Data (XSD)

The extended sector data is 8 bytes and repeats once for every sector in the track that had bit 6 set in the sector header:

size
4 bytes
type
1 byte
sector_index
1 byte
weak_offset
2 bytes (little-endian)

type: can be on of the following values:
ValueDescription
$10weak sectors present

sector_index: zero-based index of physical sector within track.

weak_offset: offset of the first byte within the sector to be replaced with random data during read. This data should be different every time the sector is read.