The ADTPro-Wide protocol is an evolution of the 1-byte command protocol that the original DOS-based ADT used and ADTPro v1 extended. The first problem the ADTDPro-Wide protocol was designed to solve is that there was no enveloping of commands, and just a little enveloping of payloads in the v1 protocol. If the client and server got out of sync, it was common for the server to go back to its command loop, and then receive a stream of seemingly random data from the client as it attempted to re-send a non-acknolwedged disk block. The server interpreted that block of data as a stream of commands, sometimes with undesired consequences.
A second design goal was to offer larger packet sizes than the original 256-byte checksummed chunks. ADTPro-wide can now have packet sizes that are checksummed, and limited only by the buffer size of the client. This offers dramatic performance improvements as it can greatly reduce the amount of protocol "chatter" between client and server. There is of course a practical limit of buffer size with Ethernet, bounded by the UDP frame size since there is only a thin layer of support above the physical media layer.
ADTPro-Wide servers can remain compatible with Version 1 clients, which would be necessary at least for the first transaction to create an ADTPro-Wide client disk! Speediboot and SOS bootstrapping operations from an ADTPro-Wide server will automatically create ADTPro-Wide clients.
CD - Change working directory
Directory - View contents of current working directory
Get - Initiate disk image download from host
Put - Initiate disk image upload to host (always overwrite)
Batch - Initiate batch upload (unique suffix added to specified filename prefix)
Nibble - Initiate nibble disk upload to host (always overwrite)
Multiple - Initiate multiple nibble batch upload (unique suffix added to specified filename prefix)
Speediboot - Initiate Speediboot ProDOS/ADTPro bootstrap
SOS - Initiate SOS/ADTPro bootstrap
VSDrive - Initiate Speediboot ProDOS/VSDrive/BASIC bootstrap
CD ('A'+'C' / $C1+$C3) - Change working directory
Directory ('A'+'D' / $C1+$C4) - View contents of current working directory
Size ('A'+'Z' / $C1+$DA) - Query file size
Get ('A'+'G' / $C1+$C7) - Initiate disk image download from host
Put ('A'+'P' / $C1+$D0) - Initiate disk image upload to host (always overwrite)
Batch ('A'+'B' / $C1+$C2) - Initiate batch disk image upload to host (unique suffix added to specified filename prefix)
Nibble ('A'+'N' / $C1+$CD) - Initiate nibble disk image upload to host
Multiple ('A'+'M' / $C1+$CC) - Initiate batch nibble disk image upload to host (unique suffix added to specified filename prefix)
Send Image Data ('A'+'S' / $C1+$D3) - RLE compressed data for image transfer (page-aligned)
Acknowledgement ('A'+'K' / $C1+$CB) - Acknowledgement - one of ACK, NAK, CAN
Summary ('A'+'Y' / $C1+$D9) - Final acknowledgement/summary of results
Return to Home State('A'+'X' / $C1+$D8) - Sender is in home state; partner should return there as well
Send File ('A'+'F' / $C1+$C6) - Send bootstrapping file
Read Block ('E'+$01) - ProDOS device driver compatible read block request
Write Block ('E'+$02/$04) - ProDOS device driver compatible write block request
Read Block with timestamp update ('E'+$03/$05) - ProDOS device driver compatible read block request with timestamp update
Client sends Change Working Directory Packet ('A'+'C' / $C1+$C3)
Host sends:
One byte: $00 = ok $06 = Unable to change directory
Apple sends: Directory Packet
Host sends Send Image Data Packet ('A'+'S' / $C1+$D3)
Packet contains 1K of screen-formatted data of directory contents; null-terminated
Final byte:
$00 = last screen
$01 = another screen is available
Client sends Query File Size Packet ('A'+'Z' / $C1+$DA)
Host sends:
Two bytes: file size in blocks (LSB, MSB) One byte: $00 = File exists (and file size is valid) $02 = File does not exist $04 = File exists, not recognized as a valid disk image
Client sends Image Get Packet ('A'+'G' / $C1+$C7)
Host sends:
One byte: $00 = Ok $02 = File not found (client aborts)
(loop for as much data is required)
Client sends Acknowledgement Packet ('A'+'K' / $C1+$CB) with payload according to results:
One byte:
$06 = ACK (Ready for first packet/client understood the packet, CRC is correct;
send next one) -or-
$15 = NAK (Resend this same packet again: block number tells what client
is still waiting to get a good packet for)
Two bytes: beginning block number being acknowledged (also means ready to start
with block zero) (LSB, MSB)
Host sends Send Image Data Packet ('A'+'S' / $C1+$D3)
(loop end)
Client sends Summary ('A'+'Y' / $C1+$D9) packet
Client sends Query File Size Packet ('A'+'Z' / $C1+$DA)
Host sends:
Two bytes: file size in blocks (LSB, MSB) One byte: $00 = File exists (and file size is valid) $02 = File does not exist $04 = File exists, not recognized as a valid disk image
Client sends Image Put Packet ('A'+'P' / $C1+$D0)
Host sends:
One byte: $00 = Ok $02 = Unable to write (client aborts)
(loop for as much data is required)
Client sends Send Image Data Packet ('A'+'S' / $C1+$D3)
Host sends:
One byte:
$06 = ACK (Host understood the packet, CRC is correct; send next one)
(Also: this is a duplicate packet, already received; acknowledge
so the client sends the next one)
$15 = NAK (Resend the same packet again)
(end loop)
Client sends Summary ('A'+'Y' / $C1+$D9) packet
Client sends Batch Send Packet ('A'+'B' / $C1+$C2)
Host sends:
One byte: $00 = Ok $02 = Unable to write (client aborts)
(loop for as much data is required)
Client sends Send Image Data Packet ('A'+'S' / $C1+$D3)
Host sends:
One byte:
$06 = ACK (Host understood the packet, CRC is correct; send next one)
(Also: this is a duplicate packet, already received; acknowledge
so the client sends the next one)
$15 = NAK (Resend the same packet again)
(end loop)
Client sends Summary ('A'+'Y' / $C1+$D9) packet
Client sends Query File Size Packet ('A'+'Z' / $C1+$DA)
Host sends:
Two bytes: file size in blocks (LSB, MSB) One byte: $00 = File exists (and file size is valid) $02 = File does not exist $04 = File exists, not recognized as a valid disk image
Client sends Nibble Send Packet ('A'+'N' / $C1+$CD)
Host sends:
One byte: $00 = Ok $02 = Unable to write (client aborts)
(loop for 35 tracks)
(loop for as much data is required within a track)
Client sends Send Image Data Packet ('A'+'S' / $C1+$D3)
Host sends:
One byte:
$06 = ACK (Host understood the packet, CRC is correct; send next one)
(Also: this is a duplicate packet, already received; acknowledge
so the client sends the next one)
$15 = NAK (Resend the same packet again)
(end data loop)
Host sends:
One byte:
$06 = ACK analysis was successful; please proceed with the next track
$15 = NAK analysis failed; abort the operation
$18 = CAN analysis failed, but please continue with next track
$05 = ENQ analysis was inconclusive; please re-read the same track and send the newly read data
(end track loop)
Client sends Summary ('A'+'Y' / $C1+$D9) packet
Client sends Multiple Nibble Send Packet ('A'+'M' / $C1+$CC)
Host sends:
One byte: $00 = Ok $02 = Unable to write (client aborts)
(loop for 35 tracks)
(loop for as much data is required within a track)
Client sends Send Image Data Packet ('A'+'S' / $C1+$D3)
Host sends:
One byte:
$06 = ACK (Host understood the packet, CRC is correct; send next one)
(Also: this is a duplicate packet, already received; acknowledge
so the client sends the next one)
$15 = NAK (Resend the same packet again)
(end data loop)
Host sends:
One byte:
$06 = ACK analysis was successful; please proceed with the next track
$15 = NAK analysis failed; abort the operation
$18 = CAN analysis failed, but please continue with next track
$05 = ENQ analysis was inconclusive; please re-read the same track and send the newly read data
(end track loop)
Client sends Summary ('A'+'Y' / $C1+$D9) packet
Client sends Send File ('A'+'F' / $C1+$C6) packet with '2' payload
Host sends:
One byte: 'P' ($50) Two bytes: image size in bytes (LSB, MSB) Continuous byte stream of ProDOS image - grub starts execution at $2000, returns to grub at $7000
Client sends Send File ('A'+'F' / $C1+$C6) packet with '6' payload
Host sends:
One byte: "A" ($41) Two bytes: image size in bytes (LSB, MSB) Continuous byte stream of ADTPro program file image - grub starts execution at $2000
Client sends Send File ('A'+'F' / $C1+$C6) packet with '3' payload
Host sends:
Continuous byte stream of $56 pages ($5600 bytes) of SOS kernel file image
Client sends Send File ('A'+'F' / $C1+$C6) packet with '4' payload
Host sends:
One byte: 'S' ($53) Two bytes: image size in bytes (LSB, MSB) Continuous byte stream of serial ADTPro SOS program file image
Client sends Send File ('A'+'F' / $C1+$C6) packet with '5' payload
Host sends:
Two bytes: image size in bytes (LSB, MSB) Continuous byte stream of SOS driver file image
Client sends Send File ('A'+'F' / $C1+$C6) packet with '7' payload
Host sends:
One byte: 'V' ($56) Two bytes: image size in bytes (LSB, MSB) Continuous byte stream of VSDrive program file image - grub starts execution at $2000, returns to grub at $7000
Client sends Send File ('A'+'F' / $C1+$C6) packet with '8' payload
Host sends:
One byte: 'B' ($42) Two bytes: image size in bytes (LSB, MSB) Continuous byte stream of BASIC file image - grub starts execution at $2000
Envelope: One byte: 'A' ($C1) Two bytes: payload length (file name + null, not including check byte) One byte: 'C' ($C3) One byte: EOR of prior four bytes Payload: Byte stream: file name, null terminated Check byte: One byte: EOR of the payload
Envelope: One byte: 'A' ($C1) Two bytes: payload length ($0001) One byte: 'D' ($C4) One byte: EOR of the first four bytes ($04) Payload: One byte: 1k "page" to send Check byte: One byte: EOR of the payload (will be same as the payload byte)
Envelope: One byte: 'A' ($C1) Two bytes: payload length (file name + null, not including check byte) One byte: 'Z' ($DA) One byte: EOR of prior four bytes Payload: Byte stream: file name, null terminated Check byte: One byte: EOR of the payload
Envelope: One byte: 'A' ($C1) Two bytes: payload length (file name + null, not including check byte) One byte: 'G' ($C7) One byte: EOR of prior four bytes Payload: Byte stream: file name (null terminated) One byte: number of blocks to send per packet Check byte: One byte: EOR of the payload
Envelope: One byte: 'A' ($C1) Two bytes: payload length (file name + null + 2-byte block size, not including check byte) One byte: 'P' ($D0) One byte: EOR of prior four bytes Payload: Byte stream: file name (null terminated) Two bytes: file size in blocks (LSB, MSB) Check byte: One byte: EOR of the payload
Envelope: One byte: 'A' ($C1) Two bytes: payload length (file name + null + 2-byte block size, not including check byte) One byte: 'B' ($C2) One byte: EOR of prior four bytes Payload: Byte stream: file name (null terminated) Two bytes: file size in blocks (LSB, MSB) Check byte: One byte: EOR of the payload
Envelope: One byte: 'A' ($C1) Two bytes: payload length (file name + null + 2-byte block size, not including check byte) One byte: 'M' ($CC) One byte: EOR of prior four bytes Payload: Byte stream: file name (null terminated) Two bytes: file size in blocks (LSB, MSB) Check byte: One byte: EOR of the payload
Envelope: One byte: 'A' ($C1) Two bytes: payload length in bytes after RLE decompression, not including block number or CRC (LSB, MSB) One byte: 'S' ($D3) One byte: EOR of prior four bytes Payload: Two bytes: starting block number (LSB, MSB) Page-based data, RLE encoded Checksum: Two bytes: CRC of all page-based data (LSB, MSB)
Envelope: One byte: 'A' ($C1) Two bytes: payload length (LSB, MSB) One byte: 'K' ($CB) One byte: EOR of prior four bytes Payload: One byte: acknowledgement type - ACK ($06), NAK ($15), or CAN ($18) Optional additional payload of length (minus one) of bytes Check byte: One byte: EOR of the payload, including acknowledgement byte
Envelope: One byte: 'A' ($C1) Two bytes: payload length ($01, $00) One byte: 'Y' ($D9) One byte: EOR of prior four bytes ($19) Payload: One byte: number of errors encountered Check byte: One byte: EOR of the payload (will be same as the payload byte)
Envelope: One byte: 'A' ($C1) Two bytes: payload length ($0000) One byte: 'X' ($D8) One byte: EOR of prior four bytes ($19)
Envelope:
One byte: 'A' ($C1)
Two bytes: payload length ($01, $00)
One byte: 'F' ($C6)
One byte: EOR of prior four bytes ($06)
Payload:
One byte: file to request - one of the following:
$B2/'2' = ProDOS
$B3/'3' = SOS Kernel
$B4/'4' = SOS Interpreter (Serial ADTPro on SOS)
$B5/'5' = SOS Driver
$B6/'6' = Serial ADTPro on ProDOS
$B7/'7' = VSDrive on ProDOS
$B8/'8' = Applesoft BASIC for ProDOS
Check byte:
One byte: EOR of the payload (will be same as the payload byte)
The Apple sends: byte stream: One byte: 'E' ($C5) One byte: $01 Two bytes: requested block number (LSB, MSB) One byte: EOR of the first four bytes Host sends: byte stream: One byte: 'E' ($C5) One byte: $01 Two bytes: requested block number (LSB, MSB) One byte: EOR of the first four bytes Requested block data (512 bytes) One byte: EOR of all bytes in block
The Apple sends: byte stream: One byte: 'E' ($C5) One byte: $03 (for drive 1) or $05 (for drive 2) Two bytes: requested block number (LSB, MSB) One byte: EOR of the first four bytes Host sends: byte stream: One byte: 'E' ($C5) One byte: $03 (for drive 1) or $05 (for drive 2) Two bytes: requested block number (LSB, MSB) Four bytes: ProDOS date and timestamp data (ultimately destined for $BF90 to $BF93) One byte: EOR of the first eight bytes 512 bytes: requested block data One byte: EOR of all bytes in block
The Apple sends: byte stream: One byte: 'E' ($C5) One byte: $02 (for drive 1) or $04 (for drive 2) Two bytes: requested block number (LSB, MSB) One byte: EOR of the first four bytes 512 bytes: requested block data One byte: EOR of all bytes in block Host sends: byte stream: One byte: 'E' ($C5) One byte: $02 (for drive 1) or $04 (for drive 2) Two bytes: requested block number (LSB, MSB) One byte: EOR of the first four bytes