チャレンジャーのAボタンとBボタンの役割を交換させたい

先入観とはおそろしいものだ。おそらく発売当時から槍玉に挙がっていたと思われる、AボタンとBボタンが逆! という問題に対処したい。
.... どうせだれかパッチを作っているだろうと思ったら、誰も公開していない驚愕の事実も判明。

調べる

とりあえず普通にチャレンジャーをエミュレータで起動して、AボタンとBボタンを押しながら CPU の RAM を眺める。そのうち反応があるメモリアドレスがわかるので、ここでは $009b, $009c が怪しいとなる。
データは Aボタン -> $80, B ボタン -> $40 となるので, bit7, bit6 が対応する。(シフトレジスタから取るわけで、ソフトによっては bit0, bit1 の場合もよくある)

MESS + debugger で wp 9b,2,r と打って、該当の命令をみてみる。

AB3E: lda  $9C
AB40: and  #$7F <- bit6 以外有効
AB42: sta  $9C
AB44: lda  $9B
AB46: and  #$40 <- bit6 検出
AB48: beq  $AB70
AB4A: lda  $99
AB4C: beq  $AB53
AB4E: jsr  $AC88
AB51: bcc  $AB76
AB53: lda  $9C
AB55: and  #$40 <- bit6 検出
AB57: bne  $AB76
AB59: lda  $9C
AB5B: ora  #$40 <- よくわからんが bit6 を立てる?
AB5D: sta  $9C
AB5F: lda  $8E
AB61: sta  $96
AB63: lda  #$00
AB65: sta  $94
AB67: lda  #$01
AB69: sta  $8D
AB6B: lda  #$02
AB6D: sta  $DE
AB6F: rts  

とりあえずここだけ bit6 (Bボタン) 関連を bit7 (Aボタン)へ書き換えたものの、うまく動かない。他の命令をみたら延々と似たような命令が並んでいる。というわけで変更箇所だけ列挙する。

AB40: and  #$7F <- #$bf
AB46: and  #$40 <- #$80
AB55: and  #$40 <- #$80
AB5B: ora  #$40 <- #$80
AB72: and  #$BF <- #$7f
ABCB: and  #$80 <- #$40
ABD1: and  #$80 <- #$40
ABEA: and  #$7F <- #$bf

これらを書き換えると列車ステージでは A ボタンがジャンプになり、B ボタンが攻撃になる。列車ステージでは。

噴水ステージでも似たような処理があるのでここも直す。

C28C: and  #$80 <- #$40
C292: and  #$80 <- #$40
C29C: ora  #$80 <- #$40
C2AD: and  #$7F <- #$bf
C2B3: and  #$40 <- #$80
C2B9: and  #$40 <- #$80
C2BF: ora  #$40 <- #$80
C2F0: and  #$BF <- #$7f

最後のシーンはこれらの書き換えでA ボタンがジャンプになり、B ボタンが攻撃になった。

品質を疑う

列車ステージと噴水ステージで同じような動きをしているのに処理がわかれるのはなぜか。おそらくはソースコードをコピペして修正している。こういったことをするとバグ修正時にコピペした数だけ修正箇所が増えるのでやってはならない。

6502 の場合, bit7 の検出は lda をしただけで分岐できる。

	lda  $9B
	and  #$80
	beq  xxxx

lda xx; and #$80; beq/bne は lda xx; bpl/bmi にすることができる。無駄な and 命令が入っていたので #$80 を #$40 に簡単に書き換えられたというのは不幸中の幸いなのだろうか...

	lda  $9B
	bpl  xxxx

マップ移動画面は画面表示がカクカクしているので、 vblank 更新をかなり間引いているようだ。敵処理が多くて捌けなかった?

2重の先入観と戦う

筆者はチャレンジャーを遊んだことがあるので、列車の連結部分の前に来たら B ボタンを押す先入観を持っている。
hack 成功直後は連結部分から落ちたのは言うまでもない。普通の操作感にすぐになれたけど。