X1 標準テープフォーマット

X1のテープについてのメモ書きです。間違ってたら教えてください。

■ 予備知識

ノーマルX1、つまりturboではないX1の割込みは、SUB CPU側からのキーボード割込みだけです。 他には、X1にはテレビ予約のタイマがあり、そのタイマを使うと1秒間隔で割込みをかけることができるようですが(詳しく知りません)、割込間隔が1秒というのが長すぎるのは言うまでもありません。

NMI割込みは、本体の物理的なボタンにつながっています。ソフトウェアでどうにかするものではないです。

つまり、ノーマルのX1は、一定の短い周期で何か決まった動作をさせるのが難しい機種だということです。音楽再生とか。

※垂直同期信号や帰線期間かどうかの信号は読み取れますが割込みはないです。

■ テープデッキとZ80

Z80からは8255を通してカセットテープの読み書きをします。

テープ上の記録状態は1bit単位で、それが8255の1bitのHigh/Low信号として出てきます。テープが走行してヘッダがテープを読み取ると、テープの読み取り速度に合わせて8255のbit信号が変化しますから、 Z80は、それを読み取って処理します。

読み取り信号以外に、テープが入っているかどうかの状態、テープの書き込み禁止ツメの状態、テープの走行状態も8255を通して読み取ることができます。 あと、テープへの書き込み信号用のBitもあります。これがZ80とテープの間でやり取りできる全てです。

■ テープを制御するには?

ここまでの話をまとめると...

  1. X1には細かいタイマ割込がないので、Z80でテープのデータを読み書きするには、CPUでタイミングを生成する
  2. テープには任意のHigh/Low情報を乗せられる

ということになります。

1は、Z80でタイミングを作って8255のbit変化を読み取るということですから、Z80の命令クロック数を計算して時間を調整するということになります。それから、 テープのbit読み込み、8bit毎にバイトデータへの変換、メモリへの保存をします。

2は、一定間隔のbit列どころか、自由なデジタル波形をテープに書き込めるということなので、1と組み合わせると、ソフトによって、どんな波形でも作れるということです。 その波形がどういう内容かは読み取りソフト次第ですから、解析するのが面倒そうですね。

このようにX1のテープでは、任意の波形を作れますが、ただ、それだと実運用には適していないので、SHARP/Hudsonでは、フォーマットを決めています。

また、X1起動時のIPLで読み取れる形式でなければ最初の読み込みができませんから、ここだけは、どのテープでも同じフォーマットになっています。 IPLから読み込まれるプログラムは固定フォーマット、それ以降はソフト次第というわけですね。

もうひとつ重要なのは、テープの信頼性はそれほど高くはありませんから、出来るだけエラーが起きにくいフォーマットにしておく必要があるということです。

極端な例として、1秒ごとにHigh/Low信号を変化させることで1bitを表すフォーマットにしたとします。1バイト(8bit)を記録するのに8秒で、1秒おきに信号がHigh/Lowと変化しますから、 Z80で1秒を測って8255のテープ読み取りbitを読むだけです。 フォーマットとしては究極シンプルですね。ただこの場合、ちょっとテープの走行が速くor 遅くなると、 読み取り位置がずれ始めるのです。Z80も厳密に1秒を作るのは難しいですし、CPUに供給されるクロックもいつもピッタリ同じ周波数ではありません。 1bit読むのに1秒ではなく、実際には1.1秒かかるとしたら、10秒後にはデータ読み取り位置でずれてしまいます。するとこれは、あまり良い記録方法ではないわけです。

そんなわけで、SHARPのテープフォーマットは、できるだけエラーが起きにくいような(確率的に低くなるような)記録方式になっています。

■ IPL起動時のテープフォーマット

X1マシン語活用百科を参考にしましたが、細かいところの説明が抜けてるので、あとは自分で調べました。

IPL起動時に読み込まれるテープフォーマットや、Hu-BASICで保存されたテープフォーマットは同じです。フォーマット内の属性値が異なります。

X1のテープフォーマットでは、ビット情報の0と1を、信号のレベルではなく、信号の幅で表現します。

"0"は4KHz、"1"は2KHzの矩形波ということになりますね。この信号を正確に記録するには、少なくとも8KHzでサンプリングする必要がありますから、ちょっと質の悪い周波数特性のよくないテープでは厳しいです。

ちなみに、"0"と"1"の波形の周波数の平均値が約2666Hzですから、ここからX1のカセットは2700baudだと言われています。

Z80では、8255経由で送られてくるテープの記録信号の立ち上がり位置を検出してから、184μ秒経過後の信号の状態をみて、Lowなら"0"、Highなら"1"として判断します。

テープフォーマットは、大きく分けて、インフォメーションブロックとデータブロックに別れています。それぞれのブロックの先頭には、ブロック検出用のビット列があり、ブロック後方にはチェックサムがあります。

上記の図では、ファイル情報とファイル本体はbyte単位になっていることに注意してください。バイト情報の並びは少し特殊で、最初に"1"があり、そのあと上位bitから8bit分の"0"か"1"が並びます。その後、立ち上がり検出をしてから、次の1byteの読み込みをします。立ち上がり検出用の信号は"1"になっているのが一般的のようですから、1byte毎に"1"が挟まれているということになります。

チェックサム部もbyte単位(2byte)ですが、ファイル情報やファイル本体と違い、最初の"1"はなく、各バイトの終わりに立ち上がりの検出をしています。

チェックサムは、読み込んだデータの加算値ではなく"1"の個数です。2バイト範囲での加算なので、65535以上は0からカウントし直しです。

ファイル情報の中身(32byte)

00h 属性(1...マシン語, 2...BASIC, 3...ASCIIファイル)
01h-1Dh ファイル名 13byte
1Eh-10h 拡張子 3byte
11h パスワード(通常は20h)
12h-13h データサイズ(下位,上位の順)
14h-15h 読込アドレス(下位,上位の順)
16h-17h 実行アドレス(下位,上位の順)
18h 年...西暦の下位2桁をBCD形式
19h 月,曜日...上位4bitが月、下位が曜日
1Ah 日...BCD形式
1Bh 時...BCD形式
1Ch 分...BCD形式
1Dh-1Fh 00h(ディスク用)

インフォメーションブロックのチェックサムが一致しなかった場合、その時点でエラーとなり、IPLの起動メニューに戻されます。チェックサムに問題が無ければ、ファイル情報内に含まれている各種の情報を処理して、データブロックの読み込みに進みます。ファイル名の表示もここで行っています。つまり、チェックサムにエラーがあるとファイル名の表示はされませんから、少なくとも、画面にファイル名が表示された場合は、インフォメーションブロックは正しく読み込めているということになります。

データブロックのチェックサムも同様で、ファイル情報内に含まれているファイル本体のサイズ分だけ読み取った後、チェックサムとの比較をしますから、最後までエラー検出はされないということです。

テープの読み込み途中でエラーとなるケースは、テープが停止した(イジェクトした)時だけです。読み取る予定のバイト数分だけのデータを読み取れず、テープを最後まで再生してしまった場合もエラー扱いです。

X1マシン語活用百科によると、インフォメーションブロックの最初には、"1"が1000個並んでいますが、IPLの読み取り処理では、これは無視され、0が40(20)個並んでいる箇所を検出するところから始まります。テープデッキの回転開始時は速度が不安定なのと、テープに信号を書き込み始めた時には波形が歪むので、"1"を書き込むことで安定化させているのだと思います。データブロックの"1"が3000個の方も同様に、"0"を20個検出するところからで、3000個の"1"は無視されます。

これらの0と1の検出に失敗した場合は、検出を最初からやり直します。例えば、データブロックの"1"を20個検出する段階で読み取れなかった場合は、"0"を20個検出するところからやり直しとなります。そういったケースではおそらくテープを最後まで読み取ってしまい、エラーになると思います。

■ おまけ:カセットコントロールコード

n 名称 機能
00h EJECT イジェクト
01h STOP 停止
02h PLAY(READ) 再生
03h FAST 早送り
04h REW 巻き戻し
05h APSS1 順方向頭出し
06h APSS-1 逆方向頭出し
0Ah RECORD(WRITE) 録音