開発着手したコレの画面をどうやって作っているか、という話をする。誰かの参考になることを願って、ではなく、こうして書いておかないと、いつも言っていることであるが他ならぬボク自身が何をやったか忘れるから、である。ボク以外の人がこういう面倒臭いことを敢えてするとは思えない。3であることは一目瞭然だろう。このモードはデフォルトのVRAMの構成に難があってアクションゲームには使い難いが、ちょっと一工夫することで後述する制約がありつつも、使えなくはないことは以前書いた。して、1フレームにつき64÷2×48=1,536バイト、VRAM上のパターンジェネレータテーブルに然るべきデータを書き込めば、メモリ構造と画面表示の関係が90度捻られていることを除けば、普通のゲームプログラミングの手法で任意の図柄を表示することができる体制は整った。ここで“任意の図柄”と言っているのは、無印MSXのゲーム開発で常々問題になる「8ドット中2色」の制約がここにはない、ということである。文字通り“マルチカラー”なのである(なのだろうか?<右端に何かいるが多分気のせい>その代わり、色制約とは違う他の制約が、当然のことながらいろいろとある。・言わずもがなだが、画面解像度が64×48ピクセルしかない。平たく言えば絵がめっちゃ粗くなる。GRAPHIC4におけるVDPコマンドHMMCに課せられた制約と本質的に同じ)。・1フレーム1,536バイトは結構重い。画面解像度は、つきつめればどう使うかのセンス次第であり、本作については自分では何とかなっている、と勝手に思っているのだが、これは人それぞれの好みにもよるだろうから深入りはしない。Bladeシリーズのボスキャラと同じになるが、キャラクタの動きが横方向に限ってそれになる、というだけの話ではあるのだ。これも使い方のセンス次第だろう。ちなみに、前稿に示した動作デモ動画において、二重スクロールする奥側の背景は横方向に1ピクセル単位で動いているように見える。これは、圧縮状態でROMのページ0に収蔵してある背景データをRAMに展開する際、元絵の他に横方向へ4ビットシフトしたものをもう1枚生成しておいて、1フレーム毎に交互にこれをフレームバッファへコピーすることで実現している。背景以外の図柄についても同じことをしてはならない法はないが、そんなことをしていたらメモリがいくらあっても足りないので、今のところはそこまでするつもりはない。同じ動画の手前側前景(登場人物をときどき隠している竹)は2ピクセル単位で動いているのだが、奥手がピクセル単位で動いているのとの速度差もあって、さほどその粗さは気にならないのではないか、と個人的には勝手に思っている。<知らない人向け、源平討魔伝はこんなゲーム>で、本稿本題は、全画面書き換えのコストとしては破格に少ない、とは言え、MSXのハードウェア性能からすれば十分に大きい1,536バイトのVRAM転送をどうしたか、という話になるのであるが。前提として断っておくと、単純かつリニアにループする処理中でLDIRVM等を使ってRAM->VRAM間1,536バイト転送をすること自体は、MSX的には特に造作もない話なのである。これは何を言っているかというと、ゲーム速度が一定にならない(たとえば敵が多いとゲームが遅くなる等)を許容でき、かつ、VBLANKをまたいでおこなったVRAM書き込みが画面をチラつかせるのを無視するのであれば、以下に述べるようなことを真面目に考える必要はない、ということである。ボクは、ゲームの速度は可能な限り一定に保ちたいし、画面のチラつきも可能な限り回避したいのであるけれども、より本質的に問題になるのは、拙作ではスプライトローテータの実装が慣例化しているのであり、今回ももちろん使うのである。・タイマー割込みの外でVRAMアクセスせざるを得ない場合、あるいは、その方がベターな場合は、割り込みを禁止しておこなうが主処理側に求められる。画面初期化など単発的な処理を除けば、ループ中で実行する場合、上記のいずれの場合であるにせよ、一度のRAM->VRAM間転送はVSYNC期間(最短1/60秒)に収まっていないと都合が悪い、というか、正常に動作しなくなってしまう。こちらの拙稿も参照されたい。仮組みしてみて気づいたのだが、タイマー割込み中でRAM->VRAM間1,536バイト転送のみをやっている分にはギリギリ間に合っているらしい。ここにBGM/SEドライバを組み込んだら、途端に動作が怪しくなった。RAMとPSGへのI/Oだけで成り立つBGM/SEドライバのみでコレでは、段違いに遅いVRAMアクセスをおこなうスプライトローテータが組み込めるはずもない。そこで本作ではこのRAM->VRAM間転送を3分割し、RAM上のスクリーンバッファに絵が完成した時点から順に、VSYNC毎に614、614、308バイト(この不均一については後述)ずつ送ることにした。2)で1画面分のネームテーブルを送るのにほぼ等しいから、十二分に余裕がある。ここに二つ問題がある。・308バイトは画面を横に5分割した横13×48ドット弱に対応するが、この描画がVSYNCごとにずれて繰り返されると境目が視覚上悪目立ちする可能性がある。・VRAM転送が終わるまでスクリーンバッファは内容を保持せねばならず、この間CPUが遊ぶのがもったいない。そこでこの両者を同時に解決するために、表題に掲げたようにスクリーンバッファとジェネレータテーブルをそれぞれ2つ設けることにした。以下のようにゲームの処理は進む。スクリーンバッファ#1に画面データの書き込みが終わる。この時点で、次フレームの画面データ書き込み先がスクリーンバッファ#2に変更される。VSYNCが来たらスクリーンバッファ#1の最初の2/5がVRAMに転送されるが、このときジェネレータテーブルのベースアドレスは別のアドレスを向いていて画面には反映されない。あと2回のVSYNCでスクリーンバッファ#1の内容が順次VRAMに転送される。この途中でゲームの1フレーム(10fps.)時間が経過した場合、地の処理では次フレームの準備、すなわち、キー入力、敵アルゴリズムを受けてスクリーンバッファ#2への画面データ書き込みが始まる。スクリーンバッファ#1の最後の1/5がVRAMへ転送し終えると、ジェネレータテーブルのベースアドレスが新たに描き終わったデータ構造側に切り替わる。実際に画面に表示される。この切替に余裕を持たせる......厳密に言うとVBLANK期間内にベースアドレス変更を終わらせて見た目への影響を避ける......ために3回目の転送のみ量を少な目にしている。以下、スクリーンバッファとVRAM書き込み先アドレスがトグルして(1)に戻って繰り返し。わからない人には何が何だかわからん話だろう、とは思うが、以上のような水面下の白鳥の水掻きの如き苦闘......いや、これも車輪の再発明の類なのだが......を経て、前稿に示したような動作が可能になった、という話である。それはともかくとして、これまた毎度のコトであるが、ここまでに書いたことは要するに理屈が理解できるか、それをニーモニックとして記述できるか、という話に過ぎず、それができるボクからすれば面倒でも何でもない......っつーか、むしろコレを楽しく感じる救いようのない感性なのでこんなことやってるのだ。面倒なのは、このロジックに乗る画像データを用意する作業、である。Bladeのときも同じようなことをしていたような気がしないでもない。アレと比べるとパターン抽出の手間がない分マシだが、その代わりに間引き圧縮をやっている。これは何かというと、本作における重ね合わせ順に背景、登場キャラクタ、前景は、すべてマルチカラーモードのジェネレータテーブル上のデータ構造そのままであり、縦×横÷2バイトを要するのであるが、これを素のまま抱えているとメモリがいくらあっても足りないので、透過する部分や同じデータが繰り返される部分(上掲スクリーンショットで黄色で示している)は、ゲーム中に使用しない紫のカラーコード(0Dh)に特別な意味を与えて圧縮しているのである。Excel上でこれをやっているのだが、当然のことながらコレが阿呆ほど面倒臭い上に、条件付き書式でそれっぽくしているとは言え、やはりExcel上で見るのとMSX上で見るのは雰囲気が大きくことなるので、一旦ROMイメージに収蔵して動かしてみてからデザインを微修正することが頻繁に起こり、圧縮の都合上大抵の場合それは当該パターンの全データ入れ替えになるから、これまた死ぬほど面倒臭いのである。何が言いたいかというと、ここまで動いてりゃ完成はもうすぐだろ?と素人目には思われてしまうかも知れないが、本当に大変なのはこれからメモリを使い尽くすまで延々と続くこのドット絵との格闘なのであり、年内完成はまぁまずあり得ない、ということをエクスキューズしたかった、と、まぁそういう話。投稿者メールコメントURL画像内の文字列(認証コード)を入力してください。認証コードを正しく入力するとコメントが反映されます。※大文字/小文字の区別はありません。コメントは新しいものから表示されます。コメント本文中とURL欄にURLを記入すると、自動的にリンクされます。“AutoPage”AutoPage最新お知らせ。