-
Notifications
You must be signed in to change notification settings - Fork 119
ZMODEM Protocol
matsuo edited this page Oct 19, 2025
·
6 revisions
This is documentation for the ZMODEM implementation in Tera Term. This documentation was created to help understand ZMODEM and does not cover all ZMODEM specifications.
The following items were referenced.
- The ZMODEM Inter Application File Transfer Protocol / Chuck Forsberg
-
lrzsz
- defact standard impliment
- lrzsz/doc/zmodem.doc
General transmit sequence
sequenceDiagram
participant s as Sender
participant r as Receiver
s->>r: ZRQINIT
r-->>s: ZRINIT
opt option
s->>r: ZSINIT
r-->>s: ZACK
end
loop files
s->>r: ZFILE
alt next file
r->>s: ZSKIP
else
r->>s: ZCRC (ZMCRC option)
s-->>r: ?
end
loop one file
r->>s: ZRPOS
s-->>r: ZDATA
end
s-->>r: ZEOF
r->>s: ZRINIT (receive file is ok)
end
s->>r: ZFIN
r->>s: ZFIN
s->>r: "OO" (0x4f 0x4f)
The following frame is not implemented in Tera Term.
- ZCRC 0x0d
- ZCHALLENGE 0x0e
- ZFREECNT 0x11
- ZCOMMAND 0x12
- ZSTDERR 0x13
3 types
- Header
- Header only frame, Data Subpacket length = 0
- Header + Data Subpackets
- Header + Data Subpackets + Footer
- Hex Header only
- The beginning of frame is the header
- There are two types of headers + HEX
- 16 Bit CRC Binary Header
- 32 Bit CRC Binary Header (Tera Term:send not impliment)
- HEX Header (Based on 16bit CRC binary header)
- Use either HEX header or Binary header depending on the situation or frame type.
- Considering communication channels that are not 8-bit clean, ZRQINIT and ZRINIT must use Hex Header.
10 byte length
| offset | length | means | remark |
|---|---|---|---|
| 0 | 1 | ZPAD (0x2A, "*") | |
| 1 | 1 | ZDLE (0x18) | |
| 2 | 1 | ZBIN (0x41, "A") | 16 Bit CRC Binary Header |
| 3 | 1 | (0x??) | Frame Type |
| 4 | 1 | ZF3 or ZP0 (0x??) | |
| 5 | 1 | ZF2 or ZP1 (0x??) | |
| 6 | 1 | ZF1 or ZP2 (0x??) | |
| 7 | 1 | ZF0 or ZP3 (0x??) | |
| 8 | 1 | CRC-1 | |
| 9 | 1 | CRC-2 | |
| -------- | -------- | ------------------- | -------------------------- |
| 10 | ? | Data Subpackets | |
| : |
- 16bit CRC = CRC-1 * 2^8 + CRC-2
- ZF? flag bytes
- ZP? position bytes
12 byte length
| offset | length | means | remark |
|---|---|---|---|
| 0 | 1 | ZPAD (0x2A, "*") | |
| 1 | 1 | ZDLE (0x18) | |
| 2 | 1 | ZBIN (0x43, "C") | 32 Bit CRC Binary Header |
| 3 | 1 | (0x??) | Frame Type |
| 4 | 1 | ZF3 or ZP0 (0x??) | |
| 5 | 1 | ZF2 or ZP1 (0x??) | |
| 6 | 1 | ZF1 or ZP2 (0x??) | |
| 7 | 1 | ZF0 or ZP3 (0x??) | |
| 8 | 1 | CRC-1 | |
| 9 | 1 | CRC-2 | |
| 10 | 1 | CRC-3 | |
| 11 | 1 | CRC-4 | |
| -------- | -------- | ------------------- | -------------------------- |
| 12 | ? | Data Subpackets | |
| : |
- 32bit CRC = CRC-1 * 2^(83) + CRC-2 * 2^(82) + CRC-3 * 2^8 + CRC-4
- Hex Header is usable on communication channels that are not 8-bit clean.
- Based on 16bit CRC binary header
- When receiving Hex Header, ignore MSB(0x80)
| offset | length | means | remark |
|---|---|---|---|
| 0 | 1 | ZPAD (0x2A, "*") | |
| 1 | 1 | ZPAD (0x2A, "*") | |
| 2 | 1 | ZDLE (0x18) | |
| 3 | 1 | ZHEX (0x42, "B") | Hex Header |
| 4 | 1 | (0x??, "??") | Frame Type |
| 6 | 2 | ZF3 or ZP0 (0x??, "??") | |
| 8 | 2 | ZF2 or ZP1 (0x??, "??") | |
| 10 | 2 | ZF1 or ZP2 (0x??, "??") | |
| 12 | 2 | ZF0 or ZP3 (0x??, "??") | |
| 14 | 4 | 16bit CRC | 4char = 16bit |
| -------- | -------- | ------------------------- | --------------- |
| 18 | ? | Data Subpackets | |
| : | |||
| -------- | -------- | ------------------------- | --------------- |
| ? | 1 | CR (0x0D) | #889 |
| ? | 1 | LF|0x80 (0x8A) | |
| ? | 1 | XON (0x11) |
- convert binary -> "01234567890abcdef" (upper case hex are not allowed)
footer
-
Datas(CR,LR,etc) following data subpacket are discarded until the next frame (starting with '*'(ZPAD 0x2a)).
-
add CR/LF (one or two characters)
- LF(0x0A)
- CR(0x0D) LF(0x0A)
- CR(0x0D) LF|0x80(0x8A)
- 0x0D 0x8A is defact standard
- MSB is ignored
- CR/LF aids debugging from printouts
-
add XON(0x11)
- expect frame type is ZFIN or ZACK.
- XON for releases from spurious XOFF flow control characters
- length is 0...1024 bytes
- convert ZDLE(0x18)
- ZDLE(0x18) -> ZDLE(0x18) ZDLEE(0x58)
- ASCII Encoded Data Subpacket is used in 7 bit environment.
- ASCII Encoded Data Subpacket follows Hex Header.
To avoid sending control codes in communication channel, convert the control codes.
send
- When sending following data
- ZDLE(0x18)
- DLE(0x10) or 0x90(DLE|0x80)
- XON(0x11) or 0x91(XON|0x80)
- XOFF(0x13) or 0x93(XOFF|0x80)
- '@'(0x40) or 0xc0('@'|0x80)
- CR(0x0d) or 0x8d(CR|0x80)
- ((data & 0x60) == 0) && (ESCCTL == 1)
- ESCCTL is in ZSINIT frame
- send ZDLE and data inverted bit 6
- send ZDLE(0x18) and (data ^ 0x40)
- ZDLEE(0x58) = ZDLE ^ 0x40
- ZDLE -> ZDEL ZDLEE
receive
- ignore
- XON(0x11) or 0x91(XON|0x80)
- XOFF(0x13) or 0x93(XOFF|0x80)
- receive ZDEL data
- data ^ 0x40
- Frame descriptions are written in 32 Bit CRC Binary Header.
- In some cases, frames may use a HEX header.
- HEX Header
- Sender→Receiver
| offset | length | means | remark |
|---|---|---|---|
| 0 | 1 | ZPAD (0x2A, "*") | |
| 1 | 1 | ZPAD (0x2A ,"*") | |
| 2 | 1 | ZDLE (0x18) | |
| 3 | 1 | ZHEX (0x42, "B") | Hex Header |
| 4 | 2 | ZRQINIT (0x00, "00") | |
| 6 | 2 | 0x00 | |
| 8 | 2 | 0x00 | |
| 10 | 2 | 0x00 | |
| 12 | 2 | 0x00 | |
| 14 | 4 | 16bit CRC | 4char = 16bit |
| -------- | -------- | ---------------------- | --------------- |
| 18 | 1 | CR (0x0D) | |
| 19 | 1 | LF|0x80 (0x8A) | |
| 20 | 1 | XON (0x11) |
flags (ZF0...ZF3)
| flag byte | byte/bit | means |
|---|---|---|
| ZF0 | ?? | use ZCOMMAND (Not implimented in Tera Term) |
- HEX Header
- Receiver→Sender
| offset | length | means | remark |
|---|---|---|---|
| 0 | 1 | ZPAD (0x2A, "*") | |
| 1 | 1 | ZPAD (0x2A ,"*") | |
| 2 | 1 | ZDLE (0x18) | |
| 3 | 1 | ZHEX (0x42, "B") | Hex Header |
| 4 | 2 | ZRINIT (0x01, "01") | |
| 6 | 2 | ZF3(0x00, "00") | MaxDataLen Low |
| 8 | 2 | ZF2(0x00, "00") | MaxDataLen High |
| 10 | 2 | ZF1(0x00, "00") | |
| 12 | 2 | ZF0(0x??, "??") | |
| 14 | 4 | 16bit CRC | 4char = 16bit |
| -------- | -------- | --------------------- | -------------------- |
| 18 | 1 | CR (0x0D) | |
| 19 | 1 | LF|0x80 (0x8A) | |
| 20 | 1 | XON (0x11) |
flags (ZF0...ZF3)
| flag byte | byte/bit | means |
|---|---|---|
| ZF0 | 0x01 | CANFDX (Tera Term : 1) |
| ZF0 | 0x02 | CANOVIO (Tera Term : 1) |
| ZF0 | 0x04 | CANBRK (Not implimented in Tera Term) |
| ZF0 | 0x08 | CANCRY (Not implimented in Tera Term) |
| ZF0 | 0x10 | CANLZW (Not implimented in Tera Term) |
| ZF0 | 0x20 | CANFC32 (Not implimented in Tera Term?) |
| ZF0 | 0x40 | ESCCTL |
| ZF0 | 0x80 | ESC8 (Not implimented in Tera Term) |
MaxDataLen = (ZP1 << 8) + ZP0
Tera Term
- ESCCTL=1 when TERATERM.INI ZmodemEscCtl=ON
- (Binary header)
- Sender→Receiver
| offset | length | means | remark |
|---|---|---|---|
| 0 | 1 | ZPAD (0x2A, "*") | |
| 1 | 1 | ZDLE (0x18) | |
| 2 | 1 | ZBIN (0x41, "A") | Bin Header |
| 3 | 1 | ZSINIT (0x02) | |
| 4 | 1 | ZF3(0x??) | |
| 5 | 1 | ZF2(0x??) | |
| 6 | 1 | ZF1(0x??) | |
| 7 | 1 | ZF0(0x??) | |
| 8 | 2 | 16bit CRC | 2byte = 16bit |
flags (ZF0...ZF3)
| flag byte | byte/bit | means |
|---|---|---|
| ZF0 | 0x01 | CANFDX (Tera Term : 1) |
| ZF0 | 0x02 | CANOVIO (Tera Term : 1) |
| ZF0 | 0x04 | CANBRK (Not implimented in Tera Term) |
| ZF0 | 0x08 | CANCRY (Not implimented in Tera Term) |
| ZF0 | 0x10 | CANLZW (Not implimented in Tera Term) |
| ZF0 | 0x20 | CANFC32 (Not implimented in Tera Term?) |
| ZF0 | 0x40 | ESCCTL |
| ZF0 | 0x80 | ESC8 (Not implimented in Tera Term) |
- (Binary header)
- Ack to ZRQINIT ZRINIT or ZSINIT
| offset | length | means | remark |
|---|---|---|---|
| 0 | 1 | ZPAD (0x2A, "*") | |
| 1 | 1 | ZDLE (0x18) | |
| 2 | 1 | ZBIN (0x41, "A") | Bin Header |
| 3 | 1 | ZACK (0x03) | |
| 4 | 1 | 0x00 | |
| 5 | 1 | 0x00 | |
| 6 | 1 | 0x00 | |
| 7 | 1 | 0x00 | |
| 8 | 2 | 16bit CRC | 2byte = 16bit |
- Binary/Hex Header
- Sender→Receiver
| offset | length | means | remark |
|---|---|---|---|
| 0 | 1 | ZPAD (0x2A, "*") | |
| 1 | 1 | ZDLE (0x18) | |
| 2 | 1 | ZBIN (0x41, "A") | Bin Header |
| 3 | 1 | ZFILE (0x04) | |
| 4 | 1 | ZF3(0x??) | |
| 5 | 1 | ZF2(0x??) | |
| 6 | 1 | ZF1(0x??) | |
| 7 | 1 | ZF0(0x??) | |
| 8 | 2 | 16bit CRC | 4byte = 16bit |
| -------- | -------- | ------------------- | ------------------------------------------ |
| 10 | ? | PATHNAME | UTF-8? |
| ? | ? | 0x00 | |
| ? | ? | LENGTH | "[0-9]+" %lu |
| ? | ? | 0x20, " " | |
| ? | ? | MODIFICATION DATE | "[0-7]+" %lo (seconds from 1970年1月1日 UTC) |
| ? | ? | 0x20, " " | |
| ? | ? | FILE MODE | "[0-7]+" %lo (UNIX由来) |
| ? | ? | 0x00 | terminator |
- MODIFICATION DATE and FILE MODE is option
flags (ZF0...ZF3)
| flag byte | byte/bit | means |
|---|---|---|
| ZF0 | 0x01 | ZCBIN (Tera Term : only 1) |
| ZF0 | 0x02 | ZCNL |
| ZF0 | 0x04 | ZCRECOV (Not implimented in Tera Term) |
| ZF1 | 0x01 | ZMNEWL (Not implimented in Tera Term) |
| ZF1 | 0x02 | ZMCRC (Not implimented in Tera Term) |
| ZF1 | 0x04 | ZMAPND (Not implimented in Tera Term) |
| ZF1 | 0x08 | ZMCLOB (Not implimented in Tera Term) |
| ZF1 | 0x10 | ZMDIFF (Not implimented in Tera Term) |
| ZF1 | 0x20 | ZMPROT (Not implimented in Tera Term) |
| ZF1 | 0x40 | ZMNEW (Not implimented in Tera Term) |
| ZF2 | 0x01 | ZTLZW (Not implimented in Tera Term) |
| ZF2 | 0x02 | ZTCRYPT (Not implimented in Tera Term) |
| ZF2 | 0x04 | ZTRLE (Not implimented in Tera Term) |
| ZF3 | 0x01 | ZTSPARS (Not implimented in Tera Term) |
- HEX header
- Receiver→Sender
| offset | length | means | remark |
|---|---|---|---|
| 1 | 1 | ZPAD (0x2A ,"*") | |
| 2 | 1 | ZDLE (0x18) | |
| 3 | 1 | ZHEX (0x42, "B") | HEX Header |
| 4 | 2 | ZRPOS (0x09, "09") | |
| 6 | 2 | ZP0 | file pos, little endian |
| 8 | 2 | ZP1 | |
| 10 | 2 | ZP2 | |
| 12 | 2 | ZP3 | |
| 14 | 4 | 16bit CRC | 4char = 16bit |
| -------- | -------- | -------------------- | ------------------------- |
| 18 | 1 | CR (0x0D) | |
| 19 | 1 | LF|0x80 (0x8A) | |
| 20 | 1 | XON (0x11) |
- Binary header
- Sender→Receiver
| offset | length | means | remark |
|---|---|---|---|
| 0 | 1 | ZPAD (0x2A, "*") | |
| 1 | 1 | ZDLE (0x18) | |
| 2 | 1 | ZBIN (0x41, "A") | Bin Header |
| 3 | 1 | ZDATA (0x04) | |
| 4 | 1 | ZP0 | file pos, little endian |
| 5 | 1 | ZF2 | |
| 6 | 1 | ZF1 | |
| 7 | 1 | ZF0 | |
| 8 | 2 | 16bit CRC | 2byte = 16bit |
| : | ? | Data | |
| ? | 1 | ZCRCE (0x68, 'h') | last frame |
| ZCRCG (0x69, 'i') | sender dose not wait | ||
| ZCRCQ (0x6A, 'j') | sender waits response (Query?) | ||
| ZCRCW (0x6B, 'k') | sender waits response (Wait?) | ||
| 2 | 2 | CRC 16bit |
- Binary header
- Sender→Receiver
| offset | length | means | remark |
|---|---|---|---|
| 0 | 1 | ZPAD (0x2A, "*") | |
| 1 | 1 | ZDLE (0x18) | |
| 2 | 1 | ZBIN (0x41, "A") | Bin Header |
| 3 | 1 | ZEOF (0x0B) | |
| 4 | 1 | ZP0 | file length, little endian |
| 5 | 1 | ZF2 | |
| 6 | 1 | ZF1 | |
| 7 | 1 | ZF0 | |
| 8 | 2 | 16bit CRC | 2byte = 16bit |
- Binary header
| offset | length | means | remark |
|---|---|---|---|
| 0 | 1 | ZPAD (0x2A, "*") | |
| 1 | 1 | ZDLE (0x18) | |
| 2 | 1 | ZBIN (0x41, "A") | Bin Header |
| 3 | 1 | ZDATA (0x08) | |
| 4 | 1 | 0x00 | |
| 5 | 1 | 0x00 | |
| 6 | 1 | 0x00 | |
| 7 | 1 | 0x00 | |
| 8 | 2 | 16bit CRC | 2byte = 16bit |