2014年7月8日

私はゲームの内容そのものではなく、この画面の拡大縮小回転機能に衝撃を受け、いったいどんなハードで実現しているのだろうかと、自分なりに考えてロジック回路の回路図を書いてみたりしたのですが、実際に製作することなどできるわけもなく、夢想のままとなってしまいました。

あれから25年以上たった今、世の中の進歩はめざましく、画面が回転することなど何とも感じなくなってしまいましたが、今回はあの若き頃の夢をマイコンのハードとプログラムで実現しようとたくらんでみました。

(C) BANDAI NAMCO GAMES Inc.



実験回路

システム設計1

システム設計2

いよいよ肝心の拡大縮小回転機能の設計です。

まず、ビデオメモリとして256×256バイトの配列「VRAM」を用意します。1バイトで1ドットを表現するので、64Kバイトが必要となります。色数は256色を同時に表現できます。

通常のビデオメモリの場合、この領域の先頭アドレスから順次読み出し、カラー信号に変換して出力することで横一行分の映像を表示し、また次のアドレスから次の行を出力とするのですが、拡大縮小回転機能を実現するためには、アドレス順に読み出すのではなく、表示させたい順に読み出し出力する必要があります。

これを実現するため、次のような変数を用意しました。vscanstartxとvscanstartyは画面出力したときの左上のX、Y座標を表します。vscanv1_xとvscanv1_yは、画面横方向に順次出力するときのVRAM内の読み出し座標のX方向、Y方向それぞれの移動量（ベクトル）を表します。また、vscanv2_xとvscanv2_yは一行分出力後に次の行に移動するときのX方向、Y方向の移動量を表します。これらを読み出し座標を表す内部変数vscanx、vscanyに足していくことで、信号出力すべき座標を順次得ることができます。

実際にはこれらの変数は16ビットで、上位8ビットが整数部分、下位8ビットが小数部分を表すようにしています。vscanx、vscanyの座標からVRAM上の位置への変更は、単純にそれぞれの上位8ビットを図のようにvscanyが上位となるようにつなげるだけで生成できます。

画面表示解像度は横256ドット、縦224ドットとしました。勘のいい人ならすぐに気付くことですが、VRAM上の座標が端からはみ出した場合、例えばX座標が255を超えた場合、続きは左端からつながったように表示されることになります。広大なビデオメモリがあればあまり気にならないのかもしれませんが、今回はビデオメモリの大きさと実際の表示解像度がほぼ同じなので、少しでも回転させたりすると、端から反対の画像が表示されます。



映像信号タイミング

今回はシステムクロックをカラーサブキャリア周波数の3分の80倍、解像度を横256ドットとしたので、各信号のタイミングは下図のようになります。カラーサブキャリアの1周期が命令クロックで割り切れないので、カラーバースト信号が正常に認識されるか少し不安でしたが、特に問題なく認識されるようです。

プログラム製作

使い方

これまで同様、最初にinit_composite()という関数を呼び出すことで、映像出力が始まります。初期状態ではビデオメモリの先頭から読み出しで、拡大も縮小も回転もありません。

ビデオメモリに何か描画を行った後、前述した拡大縮小回転用の変数を変更することで、さまざまな表示を行うことができます。

vscanstartxを256ずつ足していくと、表示開始位置が右にずれるので、左向きの横スクロールとなります（256ずつ足すのは255以下が小数のため）。同様にvscanstartyを足すと上にスクロールします。

vscanv1_xとvscanv2_yを255以下にすると拡大画面となります。逆に256より大きくすると縮小画面となり、ビデオメモリの端を超えた部分は反対端からの繰り返し表示となります。2つの変数の値を違うものに設定すると、縦横比が変わるため、正方形が長方形になり、円が楕円となります。

上記2変数に加え、vscanv1_yとvscanv2_xも変更すると、画面がひずんだようになりますが、回転行列を用いて適切に設定すると、画面を回転させることができます。計算式は以下のようになります。





また、vscanstartx、vscanstartyはどこを画面の中央に表示するかで考えるとわかりやすいと思います。

考えればわかることですが、ベクトルの回転方向と実際に表示される画面の回転方向は逆になりますので、ご注意ください。

サンプルプログラム

これまで作ったシステムの実験でも使ってきたサンプル画面をほとんどそのまま流用しました。ただ、時間ごとに全体が縦や横にスクロールしたり、拡大したり回転したりします。動作は冒頭の紹介動画で見てください。なお、今回のデモプログラムでは、浮動小数点演算を特に工夫することもなく使っているため、コンパイルの最適化レベルを最低でも「1」にしないと処理が間に合わず、ちらつきが発生してしまいます。ビデオ出力システム本体自体は全て整数演算ですので、mainプログラムの書き方次第で高速化は可能です。



＜プロジェクトに追加するファイル＞

rotatevideodemo1.c （デモ用mainプログラム）

rotatevideo1.c （システム本体）

rotatevideo.h （システム用インクルードファイル）

graphlib.c （グラフィック関連ライブラリ）

graphlib.h （ライブラリ用インクルードファイル）



ダウンロード

画面出力システムとサンプルプログラムのソース、HEXファイル等の一式を公開します。なお私の環境はMPLAB X v2.10とXC32 v1.31です。 ソースプログラムのダウンロード

バグ修正でRev. 1.1に更新しました。（2014.11.3）

最後に