世間では 3.5インチフロッピーの国内生産が終了というニュースが流れていましたが、
ハードと共に取り扱いに関する情報も失われていくのは残念ですね。
いまさら何か書くのもためらわれる所ではありますが、エミュレータでの扱いのこともありますし、
メモ書き程度に残しておくことにします。
ディスクの構造は上の図のようになっています。
あくまで P6 で使用する「標準的な 1D フォーマット」の場合です。
変態フォーマットは扱う機会も考える必要もないかと思います。
外周から 1 周ずつトラックという単位になっていて、最内周までで全部で 40 トラック。
1周(1トラック)を 16 分割した単位がセクタで、1セクタ内には 256 バイトが格納できます。
注意点として、セクタ番号は 0-15 でなく 1-16 ということです。
全部で 256 * 16 * 40 = 163,840 バイト書き込めるということになります。
フロッピードライブ側に読みだしや書き込みを指示する際にも、「どのドライブの」
「どのトラックの」「どのセクタ」という指定を行うことになります。
セクタより細かい指定はできないので、一度に読み書きできる単位は 256バイトです。
もうちょっとメジャーな 2D,2DD,2HD などのディスクでは、表面だけでなく裏面(サーフェス1)も使います。
この時、トラック番号は、表・裏・表・裏と交互に使っていきます。トラック数は 2 倍の、全部で 80 トラックです。
エミュレータでよく使われる D88 イメージは 2D は正式にサポートしているのですが、
1D はサポートされていないようなので、2D のフォーマットに間借りする形で表します。
すなわち、「表サーフェスだけ書き込んである 2D ディスク」といった感じです。
D88 イメージをバイナリエディタで開いたところです。
トラックテーブルの所で、4バイトずつのアドレステーブルになっていますが、
トラック 0 の次が 4バイト空きになっています。トラック1の次も同じ。一つずつ飛んでいるのが分かると思います。
これは裏サーフェスを使っていないということを意味します。
よって 1D のトラック番号は 2D フォーマットにおいては 2倍で考える必要があります。
最終のトラック 39 は 2D ディスクにおけるトラック 79 の場所にアドレスが書き込んであります。
※ 2012.03追記
同梱していた D88TOOL にバグがあったので修正しました。
ディスクイメージ作成時、セクタ ID の CHRN の CH に書き込む値が間違っていたというものです。
長らく気づかず大変ご迷惑をおかけしました。
ついでに 1DD サポートや BASIC との連携を深めるために機能を追加しました。
・1D/1DD イメージ作成
・セクタ単位指定でバイナリ書き込み(従来通り。1DD を新たにサポート)
・BASIC で扱うプログラムファイルをディスクイメージにアスキーセーブ/BSAVE 形式で書き込み
・BASIC ファイルの KILL / FILES
なお、BASIC をについてはディスク全体を 35トラックとして扱います。詳細は readme.txt をご覧下さい。
・IPL
トラック 0 セクタ 1 は IPL (Initial Program Loader)が入ります。
ディスクドライブが接続され、ディスクを入れた状態でマシンを起動すると、
最初にこのセクタを読みにいきます。
このセクタ 256 バイトの先頭に "SYS"の 3 文字が書き込まれていると、
$F900-$F9FF のメインメモリに IPL をロードし、"SYS"の次(=$F903)からプログラムを実行します。
256(-3)バイトだけではたいしたことは出来ないので、そこからさらに他のプログラムをロードできるように
ディスク読み込みサブルーチンを IPL に配置して、より大きなプログラムをメモリに展開していきます。
ディスクコントローラーへは I/O ポートからコマンドを発行してやりとりを行います。
コマンドはリード・ライト他フォーマット等いろいろありますがここでは割愛。
p6v のソースコード disk.cpp が大変参考になります。
入出力は一旦作ってしまえば、頻繁に作り替えるということも無いと思うので、
今回作ったようなもので十分実用になるのではないかと思います。
外付けの 1Dドライブはインテリジェントタイプなので 88 のようにプログラムを送り込んで使いたいところ
なのですが、どうやらそれはできないようです。
※ 2012.03追記
MODE 5 以上であれば、上記の方法でディスクのオートスタートができるのですが、MODE 4 以下(PC60拡張ベーシック)では
オートスタートに対応していないので、一旦 BASIC を起動してから LOAD または BLOAD する必要があります。
IPL から独自のディスクローダーを起動できる MODE 5 と違って BASIC を経由するとなると、ディスク上のファイルの管理方法が全く違うので
少なくとも BASIC から起動する最初のプログラムだけは BASIC 方式でのイメージ書き込み手順が必要になるわけです。
BASIC のファイル管理はクラスタという単位で行っています。
1D ディスクでは 8 セクタ = 1 クラスタという換算で、ディスク 1 枚では 35 トラック * 16セクタ = 560 セクタ を 70 クラスタとして管理します。
何故新たにクラスタなどという単位にするかというと、560 もあったのでは細かすぎるからです。
どうせ 1 セクタ 256 バイト以内で済むようなプログラムはほとんど無いので、ある程度おおざっぱでも良いということでもあります。
このクラスタという単位でのディスク管理ですが、『そのクラスタはどのファイルが使用中か』『使用中ならば次はどのクラスタに繋がるか』
という情報を管理します。そのために必要な記録領域がディレクトリや FAT という特別な領域です。
この管理領域は 1D の場合クラスタ番号 36,37 (トラック18全部)、1DD の場合クラスタ番号 74,75(トラック 37全部)が充てられます。
ちょうどディスクの真ん中辺りを 1周まるごと使うわけです。邪魔くさいです。
管理領域として使われるトラック中、セクタ 1-12 をディレクトリ、セクタ 13 を ID、セクタ 14-16 を FAT として使います。
このうち重要なのはディレクトリと FAT です。(P6 では ID は使っているかどうか不明、0x00 で埋められています。)
以下はディレクトリの一部(1D ディスクのトラック18セクタ1) を抜粋したものです。
16byte で 1 ファイルの情報が表されています。
最初の 9byte がファイル名、次の 1byte がファイルの属性、その次がファイルの格納開始クラスタ番号です。
先頭が 0x00 になっているのは消去されたファイルで、これは FILES しても表示されません。
属性は 0x80 が BASIC(中間言語形式=普通の SAVE)0x00 がアスキーセーブ、0x01 が機械語 BSAVE を表しています。
BASIC がディスクからロードするときは、該当ファイルの開始クラスタを調べ、次に FAT を調べに行きます。
以下は 1D ディスクの FAT、トラック 18 セクタ 14 を抜粋したものです。
1D なので全部で 70 クラスタの使用状況が記されています。
0xFF は未使用領域です。
0xFE となっている部分が 2 つありますが、これはクラスタ 36,37 つまり管理領域自身です。
それ以外の数値は『次に繋がるクラスタ番号』あるいは『ファイルの最後尾クラスタ』を指し示しています。
開始クラスタから順に次に繋がる使用クラスタをたどっていき、最後尾のクラスタに到達したときには、
『クラスタ中何セクタを使っているか』を記すことになっています。これによりオーバーランせずに済みます。
1 クラスタ = 8 セクタなので 1〜8 なのですが、クラスタ番号と間違えないように最後尾マーク 0xC0 と加算されます。
クラスタ 0x23 から始まった SAMPLE は FAT を見ると 0x23->0x22->0x21->0x20->0x1F->0xC4 で合計 5クラスタと最後に 4 セクタ使って終了と分かります。
もし 256byte 以内で収まるファイルがあるとすると、FAT の該当クラスタには 0xC1 だけが記されることになります。図中の YAHOO がそれにあたります。
その場合でも管理単位はあくまでクラスタなので 8 セクタ中残りの 7 セクタは無駄になってしまいます。そこは利便性とのトレードオフということで。
というわけでまとめ。
読み込みは以上の通りです。
書き込む際は、ディレクトリに名前を登録し空いているクラスタ番号を得て FAT を埋めていけば良し。
消す際はディレクトリの名前部分に 0x00 を書いて、読み込み同様クラスタをたどって 0xFF で未使用に戻していけばOK
書いたり消したりを繰り返すとデフラグが必要になる様が想像できれば完璧です。
FAT はセクタ 14-16 の 3 セクタにまったく同じものが 3 つ書き込まれています。
重要な情報なのでバックアップ必須というわけです。
同梱の D88TOOL では BASIC プログラムの書き込みに対応しましたので、ディスクを使った自作プログラムの制作にも使えると思います。