mirror of
https://github.com/TomHarte/CLK.git
synced 2024-09-28 09:54:49 +00:00
Adds an attempt to explain '6 and 2' encoding.
parent
f0c05ef915
commit
26014fb17c
@ -63,3 +63,63 @@ 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.
|
`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
|
Loading…
Reference in New Issue
Block a user