1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-23 15:29:29 +00:00

Adds an attempt to explain '6 and 2' encoding.

Thomas Harte 2018-05-10 12:39:37 -04:00
parent f0c05ef915
commit 26014fb17c

@ -62,4 +62,64 @@ A complete sector header is formed on disk as:
`volume` has at least two context-dependent meanings. In both of Apple's operating systems it defaults to `254` for Disk II-compatible media and in Pro DOS is used to confirm the volume *type*. Some software prefers to use it as volume *number*, for distinguishing different disks or sides of a disk. It should be written as `254` unless there is a reason to do otherwise.
In principle the entire disk contents could have been encoded in '4 and 4' form, to give exactly the same data density as FM encoding. In practice the more-efficient '5 and 3' encoding was the first to be deployed.
In principle the entire disk contents could have been encoded in '4 and 4' form, to give exactly the same data density as FM encoding. In practice the more-efficient '5 and 3' encoding was the first to be deployed.
# '6 and 2' Encoding
Apple's second deployed sector data encoding fits six data bits into every on-disk byte.
In overview:
* the two lowest bits are taken from each of the 256 source bytes;
* the remaining six bits for each of the source bytes fill the final 256 on-disk bytes of the sector;
* 86 bytes before those 256 contain the separated low bits, so the total data size is 256+86=342 bytes;
* an exclusive OR checksum is used, but to reduce decoding time it is applied within the six-bit data rather than as a completely orthogonal field, as described below; and
* a three-byte prologue and a three-byte epilogue are applied.
The first 84 bytes after the prologue are consistently formed as:
byte n = {
bits 4 & 5: low two bits of source byte n + 172, reversed
bits 2 & 3: low two bits of source byte n + 86, reversed
bits 0 & 1: low two bits of source byte n, reversed
}
n+172 would be out of bounds for the 85th and 86th bytes, so they are formed as:
byte n = {
bits 2 & 3: low two bits of source byte n + 86, reversed
bits 0 & 1: low two bits of source byte n, reversed
}
From the 87th byte onwards the content is then:
byte n+87 = high six bits of source byte n
For checksumming purposes, the 342nd byte is duplicated to create a 343rd. Each six-bit value is then exclusive ORd with the value one before it. The first value is unaltered. This allows the decoder to keep a running exclusive OR tally from the start of the data to the end; it is seeded with the decoded value in byte 0, and from then on determines the true value of byte n by running from start to finish, exclusive ORing the received value with the running tally and storing the result.
As long as the final byte decoded matches the one stored on disk as the 343rd, the exclusive OR test passes.
For writing to disk each six-bit value is mapped to an eight-bit value using the table:
const uint8_t six_and_two_mapping[] = {
0x96, 0x97, 0x9a, 0x9b, 0x9d, 0x9e, 0x9f, 0xa6,
0xa7, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb2, 0xb3,
0xb4, 0xb5, 0xb6, 0xb7, 0xb9, 0xba, 0xbb, 0xbc,
0xbd, 0xbe, 0xbf, 0xcb, 0xcd, 0xce, 0xcf, 0xd3,
0xd6, 0xd7, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde,
0xdf, 0xe5, 0xe6, 0xe7, 0xe9, 0xea, 0xeb, 0xec,
0xed, 0xee, 0xef, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6,
0xf7, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
Where six-bit value `n` maps to the 8-bit value `six_and_two_mapping[n]`.
The prologue for sector data is `d5, aa, ad`; the epilogue is `de, aa, eb`, which is the same epilogue as for sector headers.
So the complete sector data is formed on disk as:
prologue d5, aa, ad
[ XOR section:
86 bytes containing combinations of the low two bits of source bytes
256 bytes containing the high six bits of source bytes
], all encoded via the 6-to-8 table
the XOR check value, which is the same as the high six bits of the final source byte, 6-to-8 encoded
epilogue de, aa, eb