TX-0 エミュの進捗。
自分で納得いくレベルまで出来上がったので、公開しようと複数ブラウザでの動作試験。
…遅い。
僕は Chrome 使いなので、納得いく速度で動いていた。
しかし、Chrome 以外のブラウザでは Canvas は非常に遅いらしい。
IE はまだ許せるレベル。FireFox は遅くて話にならない。
とはいえ、「Chrome 専用です」と公開するのは面白くない。出来るだけ多くのブラウザで動くようにしないと。
ただでさえ興味を持つ人が少ないエミュレータだと思うのに、「自分のブラウザでは動かない」で見てもらえないのは残念だから。
高速化の技法をあれこれ試してみる。
もっとも、当初は Chrome でも遅すぎて話にならず、ある程度高速化技法を使ってあるので、劇的には早くならない。
前提条件を書いておこう。
TX-0 のディスプレイは、511*511 の表示領域を持っていた。
この数字が中途半端に見える説明は今はしない。気になる人は TX-0 の記事を読むように。
さて、511 は現代のコンピューターには扱いづらいので、512x512 の canvas を用意する。
ここに、TX-0 の表示命令が送られたときに描画を行うわけだが…
TX-0 は、VRAM を持たない。というか、当時メモリは高価で、VRAM なんていう発想はなかった。
結果、CPU が直接座標を指定し、表示命令で点を一つ描くことになる。
座標を変えながら点を打ち続ければ、図形を描画できる。
でも、描いた点はすぐに消える。
ディスプレイの表面の蛍光体が、「ビームが当たるとしばらく光る」ようになっているのだけど、多分0.25秒~0.5秒程度で消えたと思う。
#当時の動画が残されていて、ディスプレイを撮影しているのだが、フリッカーが激しい。
フリッカーが激しいということは、残光時間はそれほど長くなかった、ということだ。
もっとも、映画カメラには移らなくても、人間の目は暗いあかりでも敏感にとらえられる。
いろいろな条件を勘案し、0.25~0.5秒程度と推察した。
さて、現代のディスプレイは、1/60 秒程度の周期で描き変えられている。
残光時間もその程度だ、ということだ。TX-0 に比べて、はるかに短い。
だから、TX-0 エミュレータでは、残光時間の長いディスプレイ(長残光ディスプレイ)を再現する必要がある。
「だんだん光が暗くなっていくさま」も再現しようとすると、描画ドット数はその分だけ増加する。
残光時間を長くすれば、書き換えるドットも増えるため、さらに増加する。
一番動作が重かったプログラムは、「lightGunTst」と言うプログラムだ。
ひたすら「隣のドット」に点を描きつつ、その光がライトペンに拾われたときだけ、別のところにも点を打つ。
これだけのプログラム。
シンプルであるがゆえに、単位時間あたりに描くドットの数が多い。
メインループが6ワードしかないので…単純計算で、1秒に1万3千ドットほど書き込む。
画面は 1/60 秒ごとに書き変えるので、1回の「新しい」ドットは 230ドットほど。
残光時間が 0.25秒の設定だと、16段階に暗くなっていくドットを描く。全部で、描き変えは 3700ドット程度。
…というわけで、1/60 秒で 3700ドットを書き込めれば問題はないのだが、Chrome 以外の canvas では遅すぎてこれが難しい。
lightGunTst では、「隣のドット」にひたすら書いていくので、画面上の変更は局所的だ。
一種のダブルバッファで描画しているので、転送を最小限の面積にすると、少し処理速度が上がった。
これで、chrome はほぼ 60 FPS(Frame Per Second: 1秒の描画回数) 出る。
IE だと 58 程度で、遅くはなっているが許容範囲。
FireFox は非常に動作が不安定。
あまり描画速度が安定せず、30~50くらいの間でふらふらし続ける。
内部的には、動作開始からの実時間(マイクロ秒)と、TX-0 の内部的な「クロック」を両方計測していて、それぞれのフレームで「どこまで TX-0 の処理を進めてよいか」を判断している。
このため、描画が一瞬だけ遅くなった場合でも、次のフレームで内部処理が追いつくことがある。
ほぼリアルタイムに動作できる、ということだ。
(もっとも、TX-0 実機の速度を見たことがないので、TX-0 内部クロックの計算は資料をもとに想像しただけのものだ。だいたい動画とはあっているみたいなので、大きくは外していないと思う)
ただ、実時間はどんどん過ぎていくので、遅くなったために一度に計算する量が増えてさらに遅く…という悪循環を起こす可能性がある。
そこで、どんなに実時間から遅れても、1回の処理はTX-0 の 4000 クロック分まで、と上限を決めてある。
これは、通常の内部処理は 2777 クロック分なので、ちょっと多いくらい。
遅れた場合は少しづつ挽回してもよい、と言う程度。
lightGunTst 以外のプログラムは、内部処理も多いため、こんなに描画量は多くない。
そのかわり、描画も局所的ではなく、画面全体に及ぶようになる。
TX-0 が VRAM を持たない特性上、常に描画を「リフレッシュ」し続けるため、常に画面全体が描画されている状態になる。
描画が少ないために速度が上がるかと言うと、画面全体を常に転送し続けることになるので、あまり速度が上がらない。
なかなか微妙な問題だ。
ところで、一種のダブルバッファと描いたが、canvas に対して getImageData した配列に対して書き込みを行い、putImageData で実際の canvas に転送している。
canvas では「1ドットを描く」命令はない。かならず、1ドットの矩形を描くことになり、効率が悪い。実際測定しみると遅い。
配列に対して1ドットを描くのは、アドレスを計算して代入を行うだけ。
TX-0 は白黒2諧調なのだが、実際の画面の色は不明(資料がない。当時の写真もほとんど白黒)なので「オシロスコープの改造ディスプレイだから、緑」ということにしている。
そうなると、1ドットに4つある色情報のうち、緑だけ書き込めばよい。こうやって速度を稼ぐわけだ。
写真と言えば、少なくとも1枚はカラー写真がある。残念ながらディスプレイは点灯していないのだが。
コンソールの色などはなんとなくわかるので、その色に合わせてエミュレータの各種パネルを描いている。
…もっとも、絵心はないのですべてテキスト + CSS 。
完成後に、絵を描いてくれる人がいたら差し替えます (^^;
同じテーマの日記(最近の一覧)
別年同日の日記
申し訳ありませんが、現在意見投稿をできない状態にしています。 |