ぉお、すごいぜ楽しいぜWonderWitch!!!
夢中になって情報に飢えてWitchTech MLを読んでいると、c.mosさんが一度だけ「(BIOSを使わず)IRAMに直接描画」と言う趣旨の書きこみをしているのを発見。ひょっとしてキャラクタ定義テーブルが見えている?と推測したが、まずは順当に(笑)、IRAMのアクセススピードを利用できないだろうかと考えた。
IRAMはSRAMよりも速いらしい。だからここにキャラクタデータを置いて、font_set_colordata()で一括設定すれば疑似的なVRAMになるんじゃないかってね。スタートアップルーチンはソースが提供されているので読むと、標準のjpn2はSPが0E00hから始まるのに、asc1だと2E00hから。それで思ったのは「asc1を使う事にしてSPを2000h引いてしまえば、IRAMが2000h使える。2000h(8192)と言ったら全キャラクタ定義に必要なメモリサイズ(512*16=8192)と同じ。」
よし、と思っていろいろやってみたのだが、どうもうまくいかない。挙動が変だし、そもそもBIOS呼び出し一回で全定義としてもかなり遅い。ところがこの変な挙動から最初の推測が甦った。「やっぱりキャラクタテーブルが見えてるんじゃないのか?」試しにfont_set_colordata()を呼ばないようにしてみる。それでも画面が変わる!当然だけどスピードも段違い。
あとはIRAMを片っ端から埋めて試すだけ(笑)。でも思ったより複雑な構成で画面のすべてを埋める事が出来ない。そこで思い出したのが、スタートアップルーチンで呼ばれているマニュアルに載っていない二つの画面BIOSルーチン。xxx_set_vram()なんていかにもって名前。何やっているかは分からんが、少なくともスタートアップルーチンの種類によって設定が違うようだ。というわけでいろいろ試すうち、実はデフォルトのjpn2ならすごくシンプルなマッピングになることが判明。ん〜遠回り。
screen_set_char()を使って28x18分きれいにキャラクタを並べれば、キャラクタ単位のメモリアドレスは(y*28+x)*16+0x2000(縦に並べる場合は(x*18+y)*16+0x2000)という単純な式で求められる。0x200をセグメントにすれば0x2000をたす必要もない。
この情報はIVRAMライブラリに関係なく有用だと思う。画面BIOSなどを使いながらちょっとだけエフェクトをかけるとか、ベクタ系の描画を高速にしたい場合とか。
注:このライブラリを発表するためにいろいろ準備しているうちに、この情報自体は先に発表されちゃっています。したがって自慢することでもありません(^^;。
・画面BIOSやテキストBIOSは一部を除いて使用できない(分かっていないと使えない)。
・スプライト、画面の重ね合わせ、スクロールと言ったハードウェア機能は使用出来ない。(頑張れば使えるかもしれないが。)
ほら、使いものにならんでしょ(笑)?しかしここまで諦めた見返りとして、IVRAMは以下の機能を実現出来ます。
・キャラクタ数512とかスプライト数128といった制限を無視した、完全ソフトウェアによるスプライト機能(ただしキャラクタ単位座標)。
きっとごく一部の方の眼が光ったことでしょう(笑)。あ、念のため書きますが、速くはないです、というか遅いです(泣)。それでも興味を持った方(うれしい)は、以下のファイルをダウンロードして、デモを実行してみてください。X十字,A,Bで操作、STARTで終了ね。キーセンスが辛いので各キーは押しっぱなしがお勧め(おいおい)。
iv101.zip(デモ、IVRAMソース付き、約54KB)
秒間およそ4フレーム(爆笑)しか出ていないデモなので、あらかじめ「遅い」と断言していますが、それでもなかなかのデモだと思いますよ(^^)。このデモはIVRAMの性能を知るために毎フレーム全画面更新をしてるのです。それも背景エフェクトのおまけ付きで、さらにハードウェアスプライトでは絶対無理な大量のキャラクタ表示を行った結果が4フレームなんです。
自慢モードは終了して(笑)、「うほぉ、これならこんなゲームが出来るぜ」と思い付くのでなければ、まったく不要な代物には違いないです。やっぱり自己満足。
それだけではあまり意味のない機構ですが、特殊な描画を行いたい場合には専用のレンダラーを書けば、それを登録出来るようになるのです。もちろん重ね合わせ順位なんかは普通のスプライトと同じルール(あとから登録したもの勝ち)。デモでは背景エフェクト用にサンプルレンダラーを登録しています。背景タイルがキャラクタ切替えをしているようにも見えますが、実際にはパターンは一種類だけで、その上からレンダラーによってビット演算をしているのです。
この節で「登録」という言葉を使っていますが、ivs_add_sprite()などは呼ばれた時にはスプライト(レンダラー)情報に登録を行うだけで描画は行いません。各フレームの処理の最後でivs_end_render()を呼び出すと、登録されたすべてのレンダラーを呼び出して描画処理を行います。重ね合わせなどはバッファ上で行ってからキャラクタ定義メモリに転送するので、チラツキがかなり防止されているはずです。
仮想VRAMは、各キャラクタごとの配列になっており、登録したスプライト(レンダラー)情報へのインデックスが並んでいます。0xFFFFは終了フラグなので、4個未満の場合は最後に0xFFFFを置いておきます。先頭に0xFFFFがあればそのキャラクタの描画処理をしないという意味になります。また4個すべてが登録された時は終了フラグは必要ありません。
そこでもう一歩進めて、専用キャラクタデータをリソースとして扱えるようにしました。これならmmap()によって違うセグメントに配置できます。このリソースを'IV'リソースと呼びます。'IV'リソースを作るために、とりあえずbm2iv.exeというツールを添付してあります。このツールは'BM'リソースファイルを'IV'リソースファイルに変換するだけのものです。
このアイデアには先があります。'IV'リソースはマスクパターンと描画パターンを分離しているので、描画パターンの方は4色全部使えるはずです。でもこれに対応するためには、bmpcnvの段階で直接'IV'リソースを出力できなければなりません。bmpcnvはすでに派生版も発表されているようだし、どうしようかなぁ。
IVRAMの場合、デフォルトで4つまでキャラクタテーブルを登録出来ます。メインと背景用と敵キャラ用を別々で登録するという芸当も可能です(^^)