上に戻る
5.ラスターの調整
概要
 自分はラスター自体を良くわかっていないですが、あるラインまで描画した段階で割り込みをかけ、そこで、画面位置などを調整することで、ステータス欄を設けたり、BGにでかキャラを描いて動かしたりできるのではないかと解釈しています。
 割り込みを書ける方法は、素朴なファミコンにも、「0番スプライトヒット」(?)を使うと、いけるようです……が、それだけだと自由が少ないので、MMC3にはIRQ機能があります。
追記(2015年8月15日)
 この記述は、通称「0爆弾」と呼ばれている機能の事なのですが、この記述は間違いであり、「割り込み」をかけることはできません。0爆弾は、何度も同じレジスタを読み続け、変化した時に処理を行う、という方法で行われます。その間は別の処理が全く出来ず、また、処理落ちにも弱い作りになります。
 IRQってのはInterrupt ReQuestの略らしいです。
 MMC3に、あらかじめ、指定した描画ラインで割り込みをかけてくれるように頼んでおくと、そのタイミングで割り込みを実行してくれます。
 割り込み実行時は、処理中の場所やフラグがスタックに詰まれ、割り込み用ルーチンに飛びます。
 その中で、画面位置の変更などを行なって、また、更なるIRQ設定を行なって、rti命令で復帰します。
 こうしてラスターが実行された……と。あくまで個人的な解釈ですけどね。
 MMC5にも、同様なIRQ機能が存在します。これに置き換えていけば良さそうですね。
レジスタ叩き方比較
 MMC3においては、レジスタ$C000と$E000と$E001を用いるようです。
 $C000に、「次の割り込みまでのライン数」を書きます。現在の位置との「相対位置」です。
 そして、テキトーな値を$E001に書き込むと、IRQが有効になります。
 また、テキトーな値を$E000に書き込むと、IRQを無効に出来るようです。

 MMC5においては、レジスタ$5203と$5204を用いるようです。
 $5203に、「次の割り込みライン」を書きます。画面上の「絶対位置」です。
 そして、$5204に80当たりを書き込むと、IRQが有効になるようです。
 また、$5204にロードをかけると、IRQが無効になるようです。
(有効な状態で、00をストアするとどうなるだろう?)

 元のプログラムは、割り込み位置を「相対位置」で決めているので、「絶対位置」に換算しないといけません。
 が、元のプログラム中では、「絶対位置」に演算(引き算とかね……相対位置だから)することで「相対位置」を決めるので、実は、多くの場所で処理を削るだけでいけます。
 あとは、IRQを有効にするレジスタを叩く値が違ったり、無効にする方法が違ったりと細かい調整が必要になりそうです。

ロックマン4におけるIRQの使い方
 ロックマン4においては、
(1)3EC0D2当たり(たぶんvblank開始時)でIRQをセット
(2)3EC149当たりに割り込みがかかる
(3)3EC14F当たりで、IRQを 無効→有効 とする(そうしないと動かない?)
(4)ラスターの種別ごとに、画面位置などを調整
(5−1)ラスターの種別ごとに、$C000当たりに書き込みをして次のラインを決める
(5−2)もうIRQしないときは、再び無効にする(3EC30E当たり)

 となっているようです。  つまり、もうそれ以上(次のvblankまで)IRQはしないぞ……というときは、
 無効→有効→無効 と細かく設定されなおすようです。

 MMC5においては、イロイロ調整してみたのですが……
(1)は処理を変えるだけ
(3)では、「無効」にする
(5−1)のように再度IRQするときは再び「有効」にする
 とすると、エミュでは上手く動くようです。
(実機でどうなるかは全く不明ですが、自分には確かめようがありません)
追記(2015年8月15日)
 その後、実機で動くことがわかりました。仕様書的に「正しい」かどうかはともかく。

 「再び有効」ということで、その分処理が増えます。
 その為に、レインフラッシュを削ったスペースを少々拝借して利用します。
 「再び有効」にするときは、そこに飛ばしてやります。
実際にどう弄った?
 書いていきます……

(1)
BANKORG_D $7EC0D4
sta $5203
lda <$9b
lsr a
ror a
nop
sta $5204
 80なんか書くためにちょっと面倒です。
 なんとか、スペースに収まりました。
 といいたいところですが、$9bが00の時は、lda $5204にすべきだと思います。
 一応コレでもエミュでは動くのですけどねぇ。

(3)
BANKORG_D $7EC14F
nop
nop
nop
lda $5204
 $5204にロードをかけて、IRQを無効にしています。
 元のプログラムだと、直後に、再度有効にしますが、止めておきます……
追記(2015年8月15日)
 凄くどうでもいいのですが、nop/nop/nopと書くくらいなら、bit $0000と書いたほうが速いです。フラグが変わってしまうので使えないこともありますが。

割り込みライン調整
BANKORG_D $7EC178
nop
nop
nop
sta $5203

BANKORG_D $7EC1BF
nop
nop
nop
sta $5203

BANKORG_D $7EC271
lda #$8F
sta $5203

BANKORG_D $7EC290
lda #$BF
sta $5203

BANKORG_D $7EC2EE
lda #$A8
sta $5203
 絶対位置を与えるように調整します。
 とはいえ、元のコードより短いので苦労はありませんかね……

(5−2)
BANKORG_D $7EC30E
lda $5204
 IRQを無効にしていますが要らなかったかも(汗)

 IRQを再度有効に
RESET_IRQ:
lda #$80
sta $5204
jmp $C311

BANKORG_D $7EC186
jmp RESET_IRQ
BANKORG_D $7EC1CD
jmp RESET_IRQ
BANKORG_D $7EC27E
jmp RESET_IRQ
BANKORG_D $7EC29D
jmp RESET_IRQ
BANKORG_D $7EC2FB
jmp RESET_IRQ

 IRQ後に再度IRQをかけるときのルーチンを自作して、そこに飛ばすようにします。


 以上でパッと見問題なくMMC5への移殖が終了します。
 こんなことやったこと無かったですが、同じシリーズの上位型への移殖ということで、思いのほか順調に進んだかと思います。
 けどもう二度とやりたくないw
 ……しかしカービィでもやるかもなー……今後。
追記(2015年8月15日)
 その後、やりました。
(80)2008年9月21日 プレさ兵衛
(292)2015年8月15日 改:補足追加
inserted by FC2 system