MFM記録のフロッピーディスクで使われているCRC(Cyclic Redundancy Check) コードについての考察です。
Macintoshの1.4MBのFD(フロッピーディスク)やMSDOSのFDでは記録変調方式としてMFMが使われています。なおMacintoshの2DDに使われているのはGCRでこれとは異なっています。(OTN-1参照)
IBMフォーマット(3.5インチ、2DDまたは2HD)の1トラックは、次のようになっています。(文献2)
セクタの中のID部とデータ部の最後に1回づつ現われる2バイトのCRCが今回の考察の対象です。これはハードウエア(FDC:フロッピーディスクコントローラーというLSI)で実現されているためか、一般の興味の範囲外とみえ、私が見たどの参考書にも具体的な記述がありませんでした。
なお今回の場合(double density)その他の値は次のように参考書には説明されています。
GAPに書かれる値は"4E"の連続
SYNCに書かれる値は"00"の連続
IM(インデックス・マーク)に書かれる値は"C2C2C2FC"
IAM(IDアドレス・マーク)に書かれる値は"A1A1A1FE"
IDは4バイトでセクタを特定する。1バイト毎にC,H,R,Nと呼ばれ
C:シリンダ番号(0〜79)
H:ヘッド番号(0 〜1)
R:セクタ番号 (1〜18: 1.4MB)(1〜9: 720K)(1〜8: 640K)
N:セクタ長コード(0〜8)128バイトが0、256バイトが1、512バイトが2、・・・・
DAM(データアドレスマーク)に書かれる値は"A1A1A1FB"
(ただしDDAMと名前が変わり、値が"A1A1A1F8"となる場合がある)
CRCコードの計算法は生成多項式と初期値で一意的に規定されます。
今回これを検討した結果、MFMのFDに使われているCRCコードの
生成多項式はP(x) = x^16 + x^12 + x^5 + 1
初期値は0x84CF、ただしIAMまたはDAMを含めて計算する。
CRCが16ビット(2バイト)なので生成多項式は16次となります。16次の多項式でよく使われるのを調べたところ、
(1)CRC-16:x^16 + x^15+ x^2 + 1
(2)CCITT:x^16 + x^12 + x^5 + 1
の2つが推奨されていることがわかりました。たぶん2つの多項式のどちらかが使われているだろうと、まずねらいを絞ることができました。
CRCのハードウエアを実現するのはきわめて簡単で(それだからこそ実用化されている)、下の図(CCITTの例)のように、巡回シフトレジスタからタップを取り出しExculsive-ORを作るだけです。
したがって、これをソフトウエアでシミュレートするのもそれほど難しいことではありません(次節参照)。
RawTrackDumpルーチンを使ってMacintosh 1.4MBのディスクのID部とそれに続くCRCを読み出したところ、次の様になりました。
C H R N CRC (例1)02 00 03 02 41 65 (例2)02 00 04 02 D8 F26バイト分のCRCを計算したところ、
CRC-16 CCITT (例1) CB73 7C02 (例2) F20B 7C02となり、CCITTの方はどのID部でも同じ値(7C02)でしたが、CRC-16の方はそうはなりませんでした。
同じ値ではあるが、CRCの計算結果がゼロにならないということは、ゼロでない初期値が設定されているということになります。初期値を0x0000から0xFFFFまで変化させてCRCを計算し、結果がゼロになる値を探しました。見つかった初期値は0x3775でした。
この多項式と初期値は、MSDOS 1.4MB、MSDOS 720K、NEC 640K等のFDでも全く同じでした。
RawTrackDumpルーチンをもう一度使って、データ部とそれに続くCRCについて調べたところ、次の様になりました。
DATA CRC (例3) 0x00 の512回繰り返し DA 6E (例4) 0xF6 の512回繰り返し 2B F6この例に対し、CCITT推奨の生成多項式でCRC計算結果がゼロになる初期値を探したところ、0x3770が見つかりました。
ID部とデータ部の初期値が違うのは不合理なので、前置のIAMまたはDAMを含めて計算し直しました。この結果、初期値は単一の0x84CFでよいことがわかりました。
(今回はDDAMの入ったFDがなかったので、この場合にどうなるかは不明です。)
前節で説明したCRCを計算するソース・コードはここにあります。
このソースでは16ビットを1ビットづつシフトしながら計算を進めて行きます。今回の目的ではこれで十分でしたが、実はもっと高速の計算アルゴリズムもあります。16回シフトの演算をあらかじめ計算して表として持っておき、1回の索表ですます方法です。
初期値を探索するのに使った、プログラムのソース・コードはここにあります。
私の結論では、初期値は0x84CFで、IAMまたはDAMを含めて計算するとなっています。しかし0x84CFはあまり「きりのいい」数字ではありません。
IAMまたはDAMの2バイト目からの計算だと、初期値は0x5E5Eとなりますが、このほうが「きりがいい」でしょうか?
実際のハードウエアではどうなっているのでしょう?
FDCのハードウエア等をよくご存じの方で、おわかりの方はぜひメールで私に教えて下さい。それに合わせて、すぐにこの稿を改訂したいと思います。
ルポ/Mac変換のソフトを模索する過程で、CRCコーディングを解読する必要が生じ、追究したのがこの成果です。ちなみに東芝ルポ(1セクタ256バイト)に使用のCRCコーディングはこれと全く同じでした。
Mac内蔵のドライブで異種フォーマットのFDをRawTrackDumpで読み出すときに、これを使えばソフトウエアで誤り検出をすることができます。