今回からプログラム部分の実装を見ていきます。エンカウントの解析する上で一番やっかいなのは「RAMアクセスが多すぎて、そのアドレスの意味が何を表しているのかよくわからない」ことです。普通はその場で固定長のデータアクセス用のSRをコールするので、その場その場でこのアドレスにはどの値がセットされるというのはすぐわかるのですが、必要なパラメーターが多すぎるためにあらかじめ用意したRAM領域にごそっとコピーしてから処理を開始する、という実装になっているようです。この処理はSR: $068195で行っているので、それぞれの値がどのアドレスにセットされるのかをまずまとめておきます(その1のエントリ参照のこと)。なお、このSRでは延々とエンカウント、エンカウント種別から値を取得してRAMにセット、という処理しかしていないのでここでは省略します。
- $067DF5 エンカウント準備
| 略 | c=on | ||
|---|---|---|---|
| 067E06 | JSR $8195 | SR: $068195 | エンカウント固定情報設定 |
| 067E09 | LDA #$3FFF | A=#$3FFF | 混成モンスター1から固定パーティ2まで14種類が選択対象 |
| 067E0C | JSR $8059 | SR: $068059 | 出現モンスター決定 |
| 067E0F | JSR $7E89 | SR: $($067E89+X) | |
| 067E12 | JSR $7E19 | SR: $067E19 | 最大出現数を見て出現モンスター数調整(画面幅考慮なし) |
| 略 | c=on |
- SR: $068059 出現モンスター決定
| 068059 | STA $1C | $00001C=A | 選択する種別をセット |
|---|---|---|---|
| 06805B | STZ $1E | $00001E=#$00 | |
| 06805D | STZ $20 | $000020=#$00 | |
| 06805F | LDX #$0000 | X=#$0000 | |
| 068062 | LSR $1C | $00001C>>1 | |
| 068064 | BCC #$0B | if(c==off) goto $068071 | |
| 068066 | LDA $F798,X | A=$7EF798+X | |
| 068069 | CLC | c=off | |
| 06806A | BEQ #$05 | if(z==on) goto $068071 | |
| 06806C | ADC $20 | A+=$000020 | |
| 06806E | STA $20 | $000020=A | |
| 068070 | SEC | c=on | |
| 068071 | ROR $1E | ($00001E+C)>>1 | |
| 068073 | INX | X++ | |
| 068074 | INX | X++ | |
| 068075 | CPX #$0020 | X>=#$0020 ? | |
| 068078 | BCC #$E8 | if(c==off) goto $068062 | |
| 06807A | LDA $20 | A=$000020 | |
| 06807C | DEC | A– | |
| 06807D | BMI #$24 | if(n==on) goto $0680A3 | |
| 06807F | JSL $00133E | SR: $00133E | 乱数発生 00-A A(1B) |
| 068083 | PHA | Push A | |
| 068084 | STZ $20 | $000020=#$00 | |
| 068086 | LDX #$0000 | X=#$0000 | |
| 068089 | LSR $1E | $00001E>>1 | |
| 06808B | BCC #$0E | if(c==off) goto $06809B | |
| 06808D | LDA $F798,X | A=$7EF798+X | |
| 068090 | CLC | c=off | |
| 068091 | ADC $20 | A+=$000020 | |
| 068093 | STA $20 | $000020=A | |
| 068095 | LDA $01,S | A=Stack($01) | |
| 068097 | CMP $20 | A>=$000020? | |
| 068099 | BCC #$0F | if(c==off) goto $0680AA | |
| 06809B | INX | X++ | |
| 06809C | INX | X++ | |
| 06809D | CPX #$0020 | X>=#$0020 ? | |
| 0680A0 | BCC #$E7 | if(c==off) goto $068089 | |
| 0680A2 | PLA | Pull A | |
| 0680A3 | LDX #$001C | X=#$001C | |
| 0680A6 | LDA #$0000 | A=#$0000 | |
| 0680A9 | RTS | return | |
| 0680AA | PLA | Pull A | |
| 0680AB | LDA $F7B8,X | A=$7EF7B8+X | 出現モンスターIDを取得 |
| 0680AE | RTS | return |
よくわからない処理が延々と続きます。ここで覚えておいてもらいたいのは、混成モンスター1から固定パーティ2まで順番に0から13のインデックスが振られていること、さらにエンカウント種別の0~13バイトの1バイトずつの値がこれに対応した閾値?であるということです。このSRの処理は、各閾値を順番に合計していき、0から合計値までの乱数をとり、乱数の値を含んでいる閾値を特定する、というものです。早い話が幅が一定でないルーレットみたいなものです。同じ仕組みはすごろくのパネルに止まったときのイベント発生判定時にも使用されていました。
当然ながらモンスターIDが設定されていないインデックスはそもそも選択肢から除外されます。さらに、このSRを呼ぶ直前でAレジスタにセットされた値も影響します。$067E0A-で#$3FFFがセットされていますが、これを2進数にすると0011111111111111となり、右から順番に各ビットが混成モンスター1から固定パーティ2に相当します。これがOFFになっていると、これまたモンスター選択から除外されます。例えば、#0FFFの場合は、固定パーティ1,2は選択されないことを意味します。ここでは#$03FFFとなっているので14種すべてが選択される可能性があることを意味します。ちなみに、昼の場合は夜のみ出現モンスター(ID:10)、固定パーティ2(夜のみ出現,ID:13)はSR: $068195の時点で0がセットされているのでそもそも選択肢には入りません。
- アリアハン周辺の例
エンカウント(ID:#$09)
| 混1 | 混2 | 混3 | 混4 | 混5 | 供 | 単1 | 単2 | 単3 | 単4 | 夜 | ソロ | 固1 | 固2 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| おおがらす | スライム | いっかくうさぎ | おおありくい | (空) | (空) | いっかくうさぎ | スライム | おおがらす | おおありくい | (空) | (空) | 00 | 00 |
エンカウント種別(ID:#$01)
| 混1 | 混2 | 混3 | 混4 | 混5 | 供 | 単1 | 単2 | 単3 | 単4 | 夜 | ソロ | 固1 | 固2 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 20 | 20 | 15 | 15 | 30 | 20 | 20 | 10 | 15 | 10 | 40 | 11 | 15 | 15 |
(赤字は対象外)
合計値 125(=20+20+15+15+20+10+15+10)で、0から125までの乱数を取る。乱数の結果が73だったら、単1(71~90)が選択される。
※SR: $068059をコールする前にAレジスタに#000Fをセットしていた場合(混1-4のみ有効になる)
エンカウント種別(ID:#$01)
| 混1 | 混2 | 混3 | 混4 | 混5 | 供 | 単1 | 単2 | 単3 | 単4 | 夜 | ソロ | 固1 | 固2 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 20 | 20 | 15 | 15 | 30 | 20 | 20 | 10 | 15 | 10 | 40 | 11 | 15 | 15 |
(赤字・青字は対象外)
合計値 70(=20+20+15+15)で、0から70までの乱数を取る。乱数の結果が30だったら、混2(21~40)が選択される。
ちなみに、この閾値の合計は255以下であることが必須になります。超えると乱数の取られる範囲が下位1バイトのみになって出現パターンが偏ることになる(多分)なので閾値をいじる場合は注意が必要です。
このSRを出るとAレジスタには決定されたモンスターID、Xレジスタには0-13のオフセット(0-26)がセットされています。このXの値によって$067E0Fで呼ばれるSRが変わります。
- $67E89- エンカウント時モンスター決定処理SRアドレス(2Byte*14rec)
| インデックス | 開始ドレス | |
|---|---|---|
| 00 | 7F01 | 混成モンスター1用 |
| 01 | 7F01 | 混成モンスター2用 |
| 02 | 7F01 | 混成モンスター3用 |
| 03 | 7F01 | 混成モンスター4用 |
| 04 | 7F01 | 混成モンスター5用 |
| 05 | 7F58 | 1体のみ+混成5種をお供にするモンスター用 |
| 06 | 7F71 | 単一種出現モンスター1用 |
| 07 | 7F71 | 単一種出現モンスター2用 |
| 08 | 7F71 | 単一種出現モンスター3用 |
| 09 | 7F71 | 単一種出現モンスター4用 |
| 0A | 7F71 | 夜のみモンスター用 |
| 0B | 7FAE | 1体のみ出現用 |
| 0C | 7FB5 | 固定パーティ1用 |
| 0D | 7FB5 | 固定パーティ2用 |
| 0E | 8058 | 空 |
長くなったのでこの辺で。次回はそれぞれのSRでどのように1体目以降の出現モンスターが決定されるか見ていきます。


コメント