PIC AVR 工作室->TopPage->AVRの工作->背景表示器V3

背景表示器V3

背景表示器V3の概要

スプライト表示器と組み合わせて使う背景表示器の機能追加版です。 主な変更点は、旧背景表示器にスクロール機能を搭載したものです。 例によってTINY2313を使用します。

スクロール機能を盛り込んだため、旧背景表示器よりも表示領域が少しだけ狭くなりました。表示領域は 横15キャラクター×縦11キャラクターとなっています。スクロール域のバッファとして縦・横それぞれ8ドット分(1キャラ分) を要し、既存のVRAMの一部をバッファに充てたためです。(SRAMに余裕が無く、新たに確保できませんでした)

キャラクタービットマップは16種類、背景マップを8画面分収録可能というのは旧型(V2) と同じです。

サンプルムービー:背景表示器V3のキャプチャ画面

ひとまずバグ取りが出来た段階でのムービーです。手抜きの為に以前のデモプログラムやキャラクターを流用したため、ドンキーコングの 画面がスクロールしながらパックマンとインベーダーが動き回るという理解不能なシチュエーションですが、機能の概要は一応説明できると 思うので、ひとまずこれでいい事にしました。(^_^)  そのうち、もっとマトモなデモを作り直します。

キャプチャー画面をフラッシュムービーにしました。画面をクリックすると再生します。
フラッシュで再生すると、なんかちょっとカクカクする時ありますが、実物はちゃんとスムーズに動きます。念のため。

このムービーは例によってPLAYERに書き込んでみたサンプルです。 ひとまず、上方向、及び下方向それぞれに32ライン分(4キャラクター分)を1ドット単位でスクロールする様子が見れます。

このデモでは新しい領域に乱数で適当なキャラクターコードを送信して埋めています。メインCPU側で背景マップのデータを 保持しておいて、(乱数の代わりに)それを背景表示器に逐次送ってあげることで、どこまででも延々とスクロールして行くことが可能です。

あとこのデモではスプライトと背景を同じ速度で動かしていますが、実際は背景のスクロール速度とスプライトの移動は、それぞれ 独立してコントロール可能です。

例によって、適当なウェイトを入れて表示しています。ウェイトを入れないと速すぎてマトモに見れません。

使い方

基本的には旧背景表示器と同様で、スプライト表示器 と組み合わせて(直列に接続して)使用します。組み合わせないと信号が出ませんのでご注意を! (スプライト表示器から出力される映像信号・複合同期信号と合成することでNTSC信号になります)

スクロール機能と表示領域の広さを除けば、制御コードなどは旧型(V2)と大差ありません。 スクロール機能の使い方や表示領域の違い、そして座標系の変換の仕方など、詳しい使い方はPDFファイルをご参照ください。

目下最新版はV3です。V3は画面全体洗い替え機能、1キャラ分だけの更新機能、上下方向のスクロールを搭載しています。 (相変わらず左右方向のスクロールやカラー表示は出来ません。)

スクロールの制御に関しては、スプライト座標系と背景座標系の換算は少々ややこしいので、PDFファイルと サンプルプログラムをよく読み合わせて応用してください。

スクロールの仕組み

(私はこれまでにMSXやファミコンのファミリーベーシックなどのようなスプライト搭載マシンを所有したことが 無いので、”背景スクロールって、きっとこんな風に実現しているんだろうなぁ…”って思って適当に組み込んだ 代物です。そういう前提でご購読ください。)

1ドット単位でのスクロールで一番重要なのは、「オフセット値」という概念です。

じゃぁ、そのオフセット値とは何かというと…?

背景画像は、8×8ドットのキャラクターがタイル状に並んだものです。もしこのキャラクター単位でスクロールを 行おうとすると、スクロール幅は8ドット毎になってしまいます。そこで出てくるのがオフセット値という概念です。

オフセット値というのは、「先頭何ライン(何ドット)を読み飛ばしてから表示を開始するか」という数値を指します。 0~7の値をとります。例えばオフセット値が3というと、上側2ライン分の表示を読み飛ばし、3ライン目から改めて 88ライン分の描画を行うということを指します。(オフセットが0というのは全く読み飛ばさない状態なので、 つまり旧背景表示器と全く同様の状態になります)

このオフセット値を0~7へ、もしくは7~0へ順々に変化させていけば、8ドット単位スクロールに対する「中間の状態」を 作り出すことができるわけです。

ここまで記載すれば、「どうやったら1ライン単位でスクロールすればよいか」はご想像いただけるかと思います。 つまり、1~7ラインという中間的なズレはオフセット値の変化によって実現し、8ドット目になったら一気に1キャラクター分を ずらしつつ、同時にオフセットを0に戻す。そういうことを延々と繰り返していくと、1ドット単位(1ライン単位)の スクロールを延々と行うことができるわけです。

ここまではOKですか?

さらに当背景表示器V3では、8ドット単位のスクロール時に、「キャラクター単位で一気にスクロール+オフセット値のクリア」 を一気に行ための”特殊コード”を設けることで、メインCPU側では複雑な処理をせずにスムーズなスクロールを実現できるように 努めました。(その特殊コードに関する具体的な説明はPDFファイルに記載しますが、具体的には「オフセット値=8」 や「オフセット値=9」を指定すると、表示器内部で一気にこれらの処理を行います。)

こういった内蔵機能を利用することで、メインCPU側からは0~7のオフセット値の送信と、8ドット毎に新たな領域へに 書き込むキャラクターの送信を行うことで、1ドット単位のスムーズなスクロールができるようになります。

本家のMSXやファミリーベーシック、X68000などが同じような処理をしていたのかはよくわかりません。すみません。 (もしご存知の方はご連絡いただけるとありがたいです。)

コメント

相変わらずTINY2313はメモリ容量との戦いです!

背景表示器V2を元にバージョンアップを行ったのですが、既にSRAMに余裕無し!8ドット分 のスクロールバッファ(=オフセット値で食いつぶす領域)は既存のVRAMを削ることで実現せざるを得ませんでした。 なので、旧版(V2)に比べ右側8ドット、下側8ドット (各1キャラ分に相当)ほど表示領域がせまくなっております。まぁ、スクロールできるということは、実画面以上に 広い世界を作れるということなので、それでもまぁいいかなぁと。

いずれ、横方向のスクロールにも対応したいと思っていますが、横方向は縦方向よりも実現は難しそうです。 いつになるか分かりませんが、少しずつ歩みをすすめて行きたいと思います。乞うご期待。

当初目論んでいたとおりにスプライトと背景を重ねてリアルタイムで動かすことが出来たのですが、 1点気になっていることがあります。なにかというと、各映像信号をOR回路で合成しているということ。

そのため、背景に使うキャラクターにドット数が多いものを使ってしまうと、スプライトのキャラクター が重なって白一色になって見えにくくなることです。

これを回避するためには、スプライトの映像信号だけでなくマスク信号も出力して、映像信号と背景信号の 間に隙間を作るとか(テレビの放送など見てると、字幕と映像の間に黒い隙間がありますよね?ああいう感じの話をしてます)、 もしくは、オペアンプを使うなどしてスプライト信号と背景の輝度に差を設けるなど。

特にカラー映像となるとOR回路で合成などという手っ取り早いイカサマは通じないと思うので、マスク信号は 必須になるでしょうね。私の能力で解決できるのかどうか…

(追伸)目下、横スクロールの実験中です。横スクロールの処理時間で問題が発生しています。

横スクロールもオフセット値をセットすることで表示を1ドットずつずらしながらスクロールするのは 一緒なんですが、縦スクロールと同様に8ドットスクロールするごとにVRAMを1キャラ分ずらす必要が あります。

問題はそこ。VRAMには2キャラが1バイトに入っているので、4ビット単位でスクロールする 必要があります。AVRには4ビット単位でシフトするような便利な命令は無く、力技でゴリゴリやる必要が…。 (大抵のCPUにも無いって?)

で、とりあえず力技で試しにロジック組んでみたんですが、やっぱり処理時間がはみ出てしまいました…

どうしようかなぁ…対策はこれからちょっとずつ考えます…

できちゃいましたよ!横スクロール!

処理時間で少し困っていたのですが、実際に組んでみたらなんとかなりました。といってもまだ 実機確認ができてませんけど。これから実機に載せて確認します。…いま忙しいので、1~2週間かかる かもしれませんが…

いや、なんだかんだで弄りたくなって、テストしちゃう可能性もあるかな… もう少し自制心を 持たないといかんな…。

(さらに追伸)

1時間だけ!って決めて、デモプログラムサクッと作ってテストしてみちゃいました。

やはり、シミュレータとダンプリストだけでは上手く追いきれなかったらしバグが残っていたようです。 デモプログラムを実行してみたら、少し変な表示になってしまいました。

左→右→上→下、の順でそれぞれ32ドットずつスクロールするデモを作ってみたんですが、 横方向のオフセット値分だけビットシフトする処理にバグが残っているようです。

ひとまず、現時点のムービーを載せておきます。

一番心配していた「横8ドット単位毎のシフト処理」についてはどうやら上手く動いているような 感じで一安心。

ビットシフトの結果上下に1ドットズレが出ていたり、ノイズが乗っていたり、短時間は逆方向にシフトしているような 感じに見えたりと、不可解な動き。うーん。今回は紙に朱書きしたりせずに、いきなりキーボードに向かって 思いつくままにプログラム修正しちゃったからなぁ… いかんかったなぁ…。考慮不足があったんでしょう。 やっぱり、能力以上のことをしてはいけません。

うーん、それにしてもこの不可解な動きはなんだろう?まさか、デモプログラムの方のバグ??? いや、それでは ノイズが乗ったり縦に1ドットズレることの説明はできないから、少なくともビットシフトの処理にバグが残っていることは 間違えなさそうだな。

まぁ、ここまで動いていることだし、あとはソース刷りだしてじっくり眺めれば、すぐにバグも見つかるでしょう。 というわけで、当面の関心事は実生活の忙しさの方! バグ取りは落ち着いてからゆっくりやることにします。

(最新情報)

ひとまず動くようになりました!ちゃんと1ドット単位でスクロールしています。ムービーを載せておきます。

ひとまず、デモプログラムが動いた状態というだけで、ちゃんと動作確認できたわけではありません。 (コンパイルが通ったらすぐに書き込んで実機動作させてみた結果です。)心配なのはやっぱり動作速度ですが…

動くことは確認出来たので、時間ができたらあとできちんとテストします。シミュレーター掛けて処理時間の評価を 行ったり、デモプログラムで消化できてないパターンも消化したり、背景キャラクターマップやキャラクタービットマップを 作り直したり、マニュアル作ったり、ツール作ったり…

まだまだやることは残ってますねぇ。次のことに手を出したいのですが、それにはもうちょっとかかりそう…

いずれにしても、上下左右に自由自在にスクロールができるようになったので、70年代、80年代の ゲームなら、大抵のものは実現できるんではないかなぁと思います。

そうそう。追加機能としてUART出力機能を加えたので、背景表示器の下流にもう一つ背景表示器を 接続するして多重スクロールを実現することもできます。もちろん、さらにその下流に背景表示器を 延々と接続していくこともできますが、そこまでやるならPCでやったほうが良さそうです。まぁ、オマケということで。

現在の暫定バージョン(テスト未済です)を載せておきます。横スクロールを取り込んだので、バージョンはV4となります。

デモプログラムも一緒に載せておくので、一緒に書き込んで頂けば動くかと思います。 暫定版は、正式版が完成した段階で破棄しますので、よろしくお願いします。

ダウンロード

背景表示器用アーカイブ(クリックすると開きます)

(暫定版プログラムとデモプログラムの遊び方)

デモプログラムをPLAYERのMEGA48に、 背景表示器V4実行ファイルを同背景用TINY2313に、 スプライト表示器のHEXファイルを 同スプライト用TINY2313にそれぞれ書き込んでください。

電源を入れたら、何かボタンを押すたびに左右上下にスクロールします。

スクロール機能を搭載したら、ますます変態的なプログラムになってしまいました…。 スプライト同様こっちのソースも見てみたいぞ!というご意見がたくさん集まるようでしたら ソース公開したいと思います。リクエストください。