上に戻る
4.PPUメモリにアクセス
概要
 ファミコンには二つくらい(?)メモリマップがあって、そのうち一つがメインのメモリのマップです。
 RAMだのROMだのがマップされているやつですね。
 そうではなく、ファミコン内蔵のピクチャ処理ユニット(PPU)のメモリがあり、それにアクセスするためのメモリマップが存在します。
 これにアクセスすることで、ネームテーブルやパレットや、VRAM搭載のロックマン4でしたら、パターンテーブルにアクセスすることが出来ます。
 任意のシーンで、使うグラフィックが変更できたらイロイロとできそうです。
 しかし、PPUメモリはvblank中しかアクセスしてはいけないのでした。
方針
 ということで、vblank中に実行するコードを弄るというのも考えられるのですが、自分の知識ではそれはちょっと危険ですw
 ということで、正規の手続きのためのルーチンを利用して、PPUメモリにアクセスしていこうということにします。

 PPUメモリにアクセスするために、いつでもアクセスできるメインメモリに、PPUメモリに書き込もうとしているデータを書いておきます。
 書き終わったら、「PPUメモリにアクセスしてくれ〜」というフラグを立てます。
 そうして、次にvblank中の処理が実行されたときに、メインメモリのデータがPPUメモリにデータが書き込まれる……

 たぶん、正規手続きは、どのファミコンのソフトでもこんな感じだと思います。
 ……そんなにイロイロ調べたわけではないですけどねw DQなんかでもこんな感じだったかと。
 ロックマン4でもやはり、こういった風の処理になっていました。
ロックマン4におけるvblank中のPPUメモリへの書き込み処理
 まず、メインメモリ$0780-$07FFに、PPUに書き込むデータをスタンバイさせます。
 書式は……

・書き込みPPUアドレス上位
・書き込みPPUアドレス下位
・書き込み量(バイト数マイナス1)
・書き込み量分のデータ

 と、繰り返しになっています。アドレス上位に負の値が来たときに、処理を終えます。
 さて、スタンバイさせたら、「準備OK〜」というフラグを立てます。
 それは、$19もしくは$1Aです。それぞれ、非ゼロを書き込むとフラグが立ちます。
 $19ですと、1バイト書き込んだときに、書き込み位置が1プラスされます。
 普通に書き込みたいときは、コレを利用することになります。
 $1Aの方を用いますと、1バイト書き込んだときに、書き込み位置が20hプラスされます。
 ネームテーブルに縦方向にアクセスしたいときはこちらを用いるといいのでしょう。たぶん。

 かくして、PPUメモリへのアクセスが自由に行なえるようにな……るわけはないのです。
競合
 PPUメモリにアクセスしたくてウズウズしている人(?)は多いです。
 最たるはスクロール処理。ロックマンが横に動いたときに、まだ描いていないネームテーブルは直ちに書き込まないといけません。
 他にも、「リングマンステージの虹足場」だとか「ダストマンステージの崩せる壁」だとか、一部の(中)ボスだとか、多くの処理が、PPUメモリにアクセスする必要があります。
 ところが、困ったことに、ロックマン4では、2つ以上の処理からPPUメモリアクセスの依頼を(簡単には)受けられない仕様になっているのです。
 そこで、どの処理でも、$19と$1Aをorって、ゼロであることを確認してから処理を開始する必要があります。
 この二つのorが非ゼロなら、既に他の処理がPPU書き込み予約をしているので、大人しく次の機会を待ちます。
 さて、一人だけ(いやもうちょっといるかも……)このルールを無視するやつが居ます。
 それが、最初に述べたスクロール処理です。まぁ、スクロール処理の優先度が高いのはしょうがないですね。
 スクロール処理では、$19や$1AをチェックすることなくPPU書き込み予約を入れ始めます。
 逆にその他の、PPU書き込み予約を入れる処理は、スクロール処理より後に行なわないといけません。
問題点
 オブジェクト処理をしているときに、PPUメモリにアクセスをしたくなったとしても、実はスクロール処理はその後に控えているので、PPU書き込み予約をぐっと我慢しないとダメです。
 ということで、スクロール処理より後で処理をするようなルーチンをガリガリ書く必要が出てきます。

 後は、特定のボスも、高優先度で処理を行なうかも……スクエアマシンとか。

 今回「倫理的な問題」がなかったなw
(73)2008年9月15日 プレさ兵衛
inserted by FC2 system