第1章 CRTC(暫定稿)

Ver.2013.6.28

CRTCとビデオ回路はX1エミュレータの鬼門である。
X1は汎用CRTCを搭載しているため、実に様々な設定や操作が可能である。
40桁x50行x4ラスタに設定するゲームなどは問題にならないが、一瞬だけ同期信号をずらしてCRTのブレを誘う被弾演出などは、OS上のウィンドウ画面にどの ように投影するのか、いつの日か問題になることだろう。
PCG定義のタイミングやVRAMアクセスウェイトなどもビデオ回路が密接に関連しており、スーパーインポーズなども表示タイミングやウェイトに影響を与える。
さらにturboではハイレゾ表示、16dotフォント、漢字VRAM、200/400ライン切り替えと、8bitクラシックPCの中でも最も複雑化なものかもしれない。
ビデオ回路の掌握なくしてエミュレータは完成しないと言っても過言ではないだろう。

しかしCRTCをいくら叩き倒したところで実用的な技術はほとんど得られない。そんな知識こそが試験に出ないX1にとってのメインターゲットなのだ。
だからしっかりと気負って書きたいと思いつつ、奥が深すぎて書ききれずに何度となく書き直していた。
しかし、それではエミュレータは一向に改善されず、復活X1ユーザの助けにも全くならない。それもまた不本意なので、読み物の前に、まずは情報源として、知り得たことはできるだけ書いて公開することにした。

CRTCは単なるカウンターである


X1のCRTCはHD46505SPで、水平/垂直期間、水平垂直パルス、キャラクタアドレス、パターンラスタなどを生成する機能がある。ビデオ信号を生 成するタ イミング発生器であり、GPUのようなメモリ管理、描画、表示などの機能はない。GPUでいうところのカスタム解像度設定に相当、と言えばわかりやすいだ ろうか。
そう聞くとVGAも繋がるんじゃねーの?と期待したくなるが、それは出来ない。正確に言えば映せるが実用に耐えない。

ネットで拾えるCRTCのデータシートとしては、HD46505よりモトローラ型番のMC6845(19pages)の物が説明が詳しい。

X1ではビデオ系の原発振は28.63636MHzで、CPU側の原発振16MHzとは非同期となっている。
ピクセルクロックは80桁の時に14.31818MHz、40桁は80桁の半分の7.15909MHzとなる。
X1turbo/Zのハイレゾでは、それぞれ1.5倍の21.47727MHzと10.738635MHzになる。
CRTCにはピクセルクロックを8分周したクロックが入力されているのでタイミング調整できるのは横8ドット、つまりキャラクタ単位となる。調整できる自由度は意外と低く、単体でNTSCに準拠することも出来ない。
スーパーインポーズでは外部からのNTSC信号に同期するが、ピクセルクロックをフリーズする方式のため、CRTCはもとよりVRAMをアクセスする CPUも金縛りにしてしまう仕様で、スーパーインポーズでFD<->GRAM転送・・・ソーサリアンでエラーが発生するのはこのためだ。

VGAは映っても使えないのである

VGAモードとXGAモードの近似タイミングでPC用モニタに映せる事は、何年か前に確認をしていた。しかしどこにも公開していなかったのは、実用性が全くもって 低いからである。
X1のスタンダード、SCART、NTSCなどは水平走査周波数が約15KHz、垂直走査周波数が約60Hzとなっている。
一方VGAモードでは水平走査周波数が31KHz、垂直走査周波数が60Hzで、水平のみ約2倍となっている。
ピクセルクロックを2倍、総ラスタ数も2倍出力すれば、VGAタイミングに近似することとなる。後者の総ラスタ数はCRTCで調整可能だが、前者のピクセルクロックは2倍に設定することが出来ない。

本当にできない?

「40桁は80桁の半分の7.15909MHzである。」

できるじゃないか。

WIDTH 40のCRTC設定でWIDTH 80のクロックにすれば水平31KHzに近傍、垂直周期も2倍になるのでキャラクタ-ラスタ数を8から16に増やせば元の周期にもどる。
実行してみるとこうなる。プログラムコードはこれと、もう1つ下の画像も参考にしていただきたい。

テキストの上2行はアトリビュートRAMを直接書き込んで縦倍角表示にしている。そうしないと3行目以降のように2行重複表示になる。つまり BASIC側にパッチが必要となる。
グラフィックは8ラスタごとに2回づつ繰り返してしまい、実用状態にはならない。
CRTCにはラスタアドレスを間引くモードがあるのだが、逆に重複させるモードがない、残念。
使用したモニタは24KHz対応、15KHzは不可のSXGAパネルの物で、OSD表示は640x480 62Hzとなっていた。

turbo/Zなら裏ワザがあり、ポート1FD0Hの12桁モードのスイッチをいれるとCSIZE0でも正しく表示できる。

CZ8FB01であれば、VGAモニタで普通に編集などができるが、WIDTH命令実行でブラックアウトするのでIOCSのCRTCデータへのパッチ当ては必要になる。
一見正しく見えるグラフィックも、SCREEN0とSCREEN1が1ラスタごとに交互に表示されている。よく言えば 320x400表示可能だが、SCREEN1をクリアしなければBASICでは不都合が出る。
CZ8FB02ではBREAKキー等が押されるとポート1FD0Hを元に戻すので、BIOSのワークエリアを弄るなどの対策が必要となる。

ラスタ数を16にする代わりに40桁x50行モードにする方法もある。これならX1でも320x400のグラフィックが使えるが、当然専用プログラムを書く必要がある。
そして、全ての条件において80桁モードにすることはできない。MZ-700ユーザーには当たり前な制限も、X1ユーザーにとっては苦痛であろう。人間は一度向上した生活レベルを元に戻すことは耐えがたいのだ。

そいういうことで、結論としては裏ワザは所詮裏ワザでしかないということだ。

X1turbo/Zであれば512x192ドットでVGAという選択が可能であるが、独自のプログラムが必要な事に変わりはない。
ファミコンやMSXのアスペクト比が大好きな人はそれを満喫すればよいが、筆者はそうではないので各自の宿題としておこう。

2倍角表示は気むずかし家さんである

X1はスーパーインポーズによるデジタルテロッパマシンだからなのか、当時としては珍しいキャラクタの2倍角表示ができた。しかし、これほど使い道が細かった機能も他には少ない。なぜなら、

●横倍角の文字は、偶数桁から書き始めなければならない
●縦倍角の文字は、水平方向には縦倍角ではない文字と混在できない

という制約が、「PCGの敵キャラが巨大化して襲ってくる」、ということを不可能にしているからだ。倍角指定はアトリビュートVRAMのビット6,7で行うが、キャラクタ毎に設定できる意味はほとんどない。
そもそも倍角文字はPCG定義すればテキスト表示できるのだから、代わりにH反転、V反転をサポートしておけば、X1ユーザーがどれだけ幸せになれたか計り知れない。
CRTCにはラスタ数を半分に間引く設定があり、それを縦等倍に適合しておけば、文字単位での縦倍は出来ないが、Turboで追加された12行モード、 320x100ドットグラフィックなどがおそらく追加部品無しで実装できた。さらにX1truboで追加された機能の回路が簡略化できたはずであるが、た ら、れば、は言ってもきりがないのでこの辺で止めておこう。

さて、制約があるということは、それを破ると表示が乱れる訳だが、現象から理解しようとすると実に不可解であり、エミュレータ書きを散々悩ませるのである。その不可解な現象とは、

●縦倍角の行に縦等倍を混在させると、一番左側の縦等倍キャラから右端までは等倍表示になり、その1つ左から左端までは少し変な縦倍角表示となる。
●その行が縦倍角の上半分なら、1行下は下半分から上半分に代わり、縦倍角の行が連続している限り、上半分と下半分が順繰りに入れ替わる。

●横倍角を奇数列から書き始めると、左側パターンが2回連続してしまう。
●横倍角を偶数列で書き終わると、右隣の横等倍のキャラのパターンが無効になり、左隣りの横倍角キャラの右半分のパターンが、等倍サイズで左半分に表示される。ただし、右端から1行下の左端には影響が出ない。

文章にしてみても、書いている本人ですら、なにがなんだかさっぱり分からない。
こんな時はBASICのプログラムの登場だ。若者にはC言語への通訳が必要かもしれない古代語も、オヤジ世代にとっては日本語よりも通じる標準語なのだ。

実行したのがこのプログラム

上から4行(等倍で8行)に、直角三角形のグラフィックキャラクタを、縦倍(CSIZE1)で3つ、縦横倍(CSIZE3)で逆向きパターン を2つ書いた所に、等倍(CSIZE0)のアトリビュートデータを緑色で2箇所だけ上書きしたものだ。
カラフルな横線は、ラスタを識別するためにグラフィックで書いたもの。

これはX millenium T-tune STEP1.43で実行した画面だが、ほぼ正確に再現されているので、これに合わせて実装すれば実害はないだろう。
しかし、実用性の無い所を追求するのが試験に出ないX1である。実は上の結果には間違いがあるのだが、お分かりになるだろうか。
それには真のロジックが何かという情報が必要だが、それはCZ-800Cの回路図が全て語っている。
そう言っても、ハード音痴な秀逸プログラマに、今さら使う当てのない74シリーズTTLの学習を勧めるのも違う気がするので、簡単に説明してしまおう。
ここで言うラスタカウンタはCGパターンの何ライン目かを指定するもので、シフトレジスタは8ビットのパターンデータをシリアル出力する回路を指す。この意味が分からなければおそらく理解できないので、ファミコンでもMSXでも構わないから、当時の横8ドット系のビデオ回路の概要を理解してから読み進めて欲しい。

さて、肝心の倍角ロジックであるが、CZ-800Cの回路図においては、

●縦等倍の時は、キャラクタ毎にCRTCのRA0-2がCGのラスタカウンタにロードされる
●縦倍角の時は、ラスタカウンタはロードせず、RA0の立下り(奇数から偶数に変わる時)に、ラスタカウンタをインクリメント(+1)する。

●横等倍の時は、キャラクタ境界でCGパターンをシフトレジスタにロードする。シフトレジスタは1ピクセルクロック毎にシフトする。
●横倍角の時は、CRTCのMA0=0(偶数桁)なら次のキャラクタ境界でCGパターンをロードしない。シフトレジスタは2ピクセルクロック毎にシフトする。

と、これだけである。
●横倍角は右隣りのキャラに影響を与える
●ラスタカウンタは縦倍角では行をまたいでインクリメントされる
●ラスタカウンタは縦等倍の出現で、即座に上書きされる
というポイントを抑えると理解しやすくなるかもしれない。

X millenium T-tune STEP1.43とCZ-881Cの実機動作

左がエミュレータ、右側がCZ-881C
CZ-881Cはロジックと合ってる?、後日CZ-800Cでも調べてみよう。

縦倍角を素直にセレクタで構成すれば、等倍と横並びに表示できたのに何故わざわざカウンターにしたのだろうか?
その答えは、おそらく74シリーズにラッチ付きデータセレクタがなかったからである。セレクタとラッチでは2つ必要なTTLが、4bitカウンタを使えば1つで済むからだ。X1は最小限の回路から可能な限りの機能を得る、そういう設計思想で作られている。

さて、ここまでは全てノーマルX1とX1turbo/Zのスタンダード解像度の話であり、実はX1turbo/Zのハイレゾモードには適用されないのだ。
そちらもturboの回路図から解読できるはずだが、turboのビデオ周りは追いかけていてもうんざりするほど面倒な事になっていて、設計はさぞかし大変ではなかったのかと思う。X1の設計思想とは真逆の方向性を感じてしまうのだが、どうだろうか。
turboのロジックはまだ解読していないので、そこは筆者の課題とさせていただきたい。

X millenium T-tune STEP1.43とCZ-881Cの実機動作、ハイレゾモード

おしい。こちらも同じ場所が少し違う。

テロップ表示としても美しくない倍角表示は、「PCGテイキ゛チュウ、オマチクダサイ」を画面中央にデカデカと表示する以外にほとんど役をなさなかった。その表示も3倍速PCGが普及してからは必要なくなった。

実用的な使い道で唯一思いついたのは、640x200モードにおける横2倍角のPCG 40x25表示だ。
オブジェクトはグラフィックで綺麗に書きたいが、PCGは見栄えよりパターン数の方が重要な時とか。奇数桁のテキストVRAMが無視される制限を逆手にとれば、更新を省略して高速化すると共に仮想VRAMなどに流用することが出来るはずだ。
実際に解像度を落としたいのは、より処理が重いグラフィックの方なので、PCG 80x25+GFX 320x200ドットのほうが嬉しいだろうな。

ビデオRAMはCRTCの傘下にあり

最も重要な情報は、CPUにウェイトをもたらすこの項だろう。早く書かねば...

テキストのドットとグラフィックのドットは違うのである

ブラウン管モニタが壊れる前に試験をやらねばならない、そういう次元の話。