メガトンコインRTAという動画でキノコングという敵が1匹でるべきである場面でそれが2匹でる, その原因は5つもバージョン違いだろう. という考察が書かれていました. 5つは多すぎでおかしいと思ったのでそれを調べました.
バージョン違いはあるが...
5個の根拠として[b]とか[h]とかついているファイル名があると書かれておりましたが、これは dump の手順を間違えているファイルが過去の混乱の遺物として残っているだけなので無視します.
かなり信憑性のある nescartdb は1つ登録があります. そこそこ信憑性のある MAME の hash/nes.xml には2つ登録があります.
この2つを見比べてみましたが、本当にバージョン違いなのか判断には困りました. 命令が増えたり減ったりしているのでそこの差分の部分をアセンブルするから命令とaddressが差分点からずれるていくものが普通のバージョン違いです. これは lda abs (3byte) 命令を jsr abs (3byte) 命令 にしていて ROM の末尾に命令を増やしています.
この手法は第3者がパッチを当てる場合は自分もよくやるんですが、その jsr 命令の中身が何かの計算の補正だったのでプログラマ当人かはわかりませんがたぶん当時の関係者が手をいれたものと思われます. *1
どちらとも敵の数は基本2匹、たまに1匹
両方のバージョンでキノコングが1匹でるはずであろうというところを確認しましたが、基本2匹、たまに1匹出るのでバージョン違いの可能性は低いと思います. (その2つ以外のバージョンがあるならべつの可能性はありそうだけど、1度生産して終わりの販売規模のこのソフトにはちょっと考えられない)
1匹でる条件を調べてみた
エンカウントで trace log を取りました. CPU address $6050 が敵の数なのはわかりました.
F969: lda ($fc), y <- 敵のテーブルのポインタらしい F96B: lsr a F96C: lsr a F96D: lsr a F96E: lsr a F96F: lsr a F970: sta $6050 <- bit7:6 を敵の数にしている (中略) 8987: lda $6050 898A: clc 898B: adc $6051 898E: adc $6052 8991: rts 8940: cmp #$02 8942: bcc $8986 ;敵の数が2以上か 8944: jsr $f195 F195: lda $038e ;乱数生成 F198: clc F199: adc #$17 F19B: sta $038e F19E: lda $21 ;frame カウンタらしい F1A0: clc F1A1: adc #$b1 F1A3: adc $5000 ;φ2カウンタ bit7:0 F1A6: sta $21 F1A8: lda $5800 ;φ2カウンタ bit15:8 F1AB: eor $22 F1AD: adc $21 F1AF: eor $1f F1B1: adc $038e F1B4: sta $21 F1B6: rts 8947: lsr a 8948: bcs $8986 ;乱数 bit0 == 0 なら減らさないので分岐 894A: lsr a 894B: bcs $8986 ;乱数 bit1 == 0 なら減らさないので分岐 894D: lsr a 894E: and #$03 8950: cmp #$03 8952: beq $8986 ;乱数 bit3:2 == 3 なら分岐 8954: tay 8955: lda $6050, y ;敵を減らすなら $6050 で乱数 bit3:2 == 0 でいてほしい 8958: beq $8986 ;それが 0 なら減らさないので分岐 895A: sec 895B: sbc #$01 895D: sta $6050, y ;敵の数を1つ減らす 8960: bne $8986 8986: rts
乱数生成のサブルーチンはミサイルポッドの確率を出してた動画(じゅうべえくえすとの鉄パイプ乱数を観察)でもでてきたものと同じです. PC (program counter) $8955 の y の値がちょっと気になるのですが変数 $6050 は敵の数で, 変数 $6051, $6052 は未調査ですが敵に関するパラメータだと思います. (別種類の敵の数かも)
このログからの考察ですと、下記のポイントとなります.
- 敵がでてくるときに乱数を引く
- 乱数の bit3:0 == 0 の場合は敵の数を1減らす
- 敵の数が1匹減る条件は 1/16 (6.2%)
- この命令は通常敵が出るときでも実行する(ボスはやらない)
- どちらのバージョンもここに違いはない
おまけ:ランダムエンカウントをなくす方法
FA1B: cmp $d2 FA1D: bcs $fa22 FA1F: inc $04c9 <= これを nop にするとランダムエンカウントがきえる FA22: jmp $fe05
cmp $d2 をユーザー入力にしてスタートボタンを押したときだけ敵が出るようにアレンジするとすごく遊びやすくなると思います.