TOP > プログラミング関係解説&調査 > アイテム並び替え

アイテム並び替え

当ページの内容は、ある程度のプログラミングの知識を必要とする。
まず、プログラミング関係解説&調査をひととおり読んでいただきたい。

敵ターンにおける行動選択において、使用技判定時に、回復技が選択されたパターンについて、このページで説明する。

メニュー→持ち物では、Xボタンを押すと「せいとん」「回復先」「攻撃先」「装備先」から並び順を選ぶことができる。
いわゆる自動並べ替え、ソート機能である。

  • せいとん:一覧に空欄がある場合、上方向に詰める。詰めるのみで並び替えなし。
  • 回復先:回復アイテム優先で並び替える。回復アイテム以外はそのまま上に詰める。
  • 攻撃先:攻撃アイテム優先で並び替える。攻撃アイテム以外はそのまま上に詰める。
  • 装備先:装備アイテム優先で並び替える。装備アイテム以外はそのまま上に詰める。

というようにソートしてくれるのだが、実際のサブルーチンはどうなっているのかを確認してみた。
また、ソートとは別機能だが、アイテム入れ替えについても最後に記してある。

ちなみに、「装備先」の場合、装備品を、
主装備位置が頭→右→左→体→足→アクセサリー→自由
と、主装備位置によって並び替えもしてくれることがサブルーチンがわかるので、合わせて紹介していく。

なお、現代編はアイテム欄自体が開けないので考慮しない。

メモリアドレス

持ち物欄(アイテム欄)のデータが入っているメモリアドレスは以下の通り。
シナリオにより変動する。

アドレス内容
$00:0B01$00:0BFFアイテム欄に入っているアイテムID(最終編)
$00:0B01$00:0B27アイテム欄に入っているアイテムID(中世編)
$00:0B28$00:0B4Cアイテム欄に入っているアイテムID(原始編)
$00:0B4D$00:0B66アイテム欄に入っているアイテムID(西部編)
$00:0B67$00:0B88アイテム欄に入っているアイテムID(幕末編)
$00:0B89$00:0BBBアイテム欄に入っているアイテムID(近未来編)
$00:0BBD$00:0BE0アイテム欄に入っているアイテムID(功夫編)
$00:0BF5$00:0CF9アイテム欄に入っているアイテムID(SF編)
$00:0C01$00:0CFFアイテム欄に入っているアイテムIDの各個数(最終編)
$00:0C01$00:0C27アイテム欄に入っているアイテムIDの各個数(中世編)
$00:0C28$00:0C4Cアイテム欄に入っているアイテムIDの各個数(原始編)
$00:0C4D$00:0C66アイテム欄に入っているアイテムIDの各個数(西部編)
$00:0C67$00:0C88アイテム欄に入っているアイテムIDの各個数(幕末編)
$00:0C89$00:0CBBアイテム欄に入っているアイテムIDの各個数(近未来編)
$00:0CBD$00:0CE0アイテム欄に入っているアイテムIDの各個数(功夫編)
$00:0CF5$00:0DF9アイテム欄に入っているアイテムIDの各個数(SF編)

1種類のアイテムにつき99個($63)まで所持でき、$00:0C01$00:0CFFに記録されることになるが、種類数はシナリオにより変わることがわかる。
つまりアイテム欄の枠の数が変わる。
シナリオにより登場するアイテムの種類が変動するため、枠が足りなくなることはない。

シナリオ所持できるアイテムの
種類数最大値
原始編37
西部編26
幕末編34
近未来編33
功夫編24
SF編5
中世編39
最終編255

アイテムデータ00

「回復先」「攻撃先」「装備先」で優先されるアイテムを選択するためには、アイテムデータ00の値が必要である。
アイテムデータ00は以下のように各ビットに数値が入る。

上4ビット:
$1~$7なら主装備位置、$8以上なら罠アイテム。
$0が入っている場合はそれ以外。

数値主装備位置
$1
$2
$3
$4
$5
$6アクセサリー
$7自由

下4ビット:
装備品なら装備種類、装備品以外ならアイテム種別。

数値内容
$0(なし)
$1-
$2回復(無限)
$3回復(1回)
$4攻撃(無限)
$5攻撃(1回)
$6
$7
$8日用品
$9野性武器
$A
$Bグローブ
$C
$Dロボ
$E重要
$F

サブルーチン

基本的な手順は、

  1. アイテム一覧のアイテムIDと個数のメモリアドレス内容($00:0B01$00:0BFF, $00:0C01$00:0CFF)を、整頓用に確保してあるメモリアドレス($7E:8A00$7E:8AFE, $7E:8B00$7E:8BFE)にコピー。
  2. 「せいとん」以外は、アイテムデータ00の値から、それぞれ回復アイテム・攻撃アイテム・装備アイテムを先に分類して整頓用メモリアドレスに移動。
  3. 2.の後に残ったアイテム(「せいとん」の場合は全アイテム)を整頓用メモリアドレスに移動。
  4. MVN(データ転送)を使って、整頓用メモリアドレスから元のメモリアドレス($00:0B01$00:0BFF, $00:0C01$00:0CFF)に書き戻す。

と、なっている。
ちなみに、持ち物欄を開いた時点で、1.のコピー作業が一度行われている。
このため、整頓前には、$7E:8A00$7E:8AFE, $7E:8B00$7E:8BFEを一度リセット(すべてに00を書き込む)してから、各種整頓処理を行う。

実際のソートの前に、メニュー画面を開いた時の処理で、[$00:0555][$00:0559]に書き込まれる値が重要になるので、まずそちらを紹介する。
[$00:0555]は、シナリオによるアイテムID記録アドレスの開始位置、[$00:0559]はシナリオによるアイテム種類最大所持数が入る仕組みである。

$C2/0127 LDA $0A00  [$7E:0A00]   ;Aに[$7E:0A00](シナリオID)をロード
$C2/012A AND #$000F              ;Aと$000Fで論理積
$C2/012D STA $4D    [$00:054D]   ;A(シナリオID)を[$00:054D]に書き込み
$C2/012F JSR $44D9  [$C2:44D9]   ;[$C2:44D9]へジャンプ

$C2/44D9 PHP                     ;ステータスレジスタをスタックへプッシュ
$C2/44DA REP #$20                ;Aを16bit幅に変更、Mフラグをクリア
$C2/44DC LDA $4D    [$00:054D]   ;Aに[$00:054D](シナリオID)をロード
$C2/44DE AND #$000F              ;Aと$000Fで論理積
$C2/44E1 CMP #$0008              ;Aと$0008を減算比較(ステータスレジスタ変更のみ)
$C2/44E4 BEQ $1B    [$4501]      ;ゼロフラグが立っているとき[$4501]分岐
;ゼロフラグOFF 最終編以外
$C2/44E6 ASL A                   ;Aを算術左シフト *2
$C2/44E7 CLC                     ;キャリーフラグクリア
$C2/44E8 ADC $D50000[$D5:0000]   ;A + [$D5:0000]
$C2/44EC TAX                     ;Aの値をXレジスタに転送
$C2/44ED LDA $D50000,x           ;Aに[$D50000,x]をロード
$C2/44F1 AND #$00FF              ;Aと$00FFで論理積
$C2/44F4 STA $55    [$00:0555]   ;Aを[$00:0555]に書き込み
$C2/44F6 LDA $D50001,x           ;Aに[$D50001,x]をロード
$C2/44FA AND #$00FF              ;Aと$00FFで論理積
$C2/44FD STA $59    [$00:0559]   ;Aを[$00:0559]に書き込み
$C2/44FF BRA $0A    [$450B]      ;フラグにかかわりなく常に分岐[$450B]
;ゼロフラグON 最終編
$C2/4501 LDA #$0001              ;Aに$0001をロード
$C2/4504 STA $55    [$00:0555]   ;Aを[$00:0555]に書き込み
$C2/4506 LDA #$00FF              ;Aと$00FFで論理積
$C2/4509 STA $59    [$00:0559]   ;Aを[$00:0559]に書き込み
;処理合流
$C2/450B LDA $55    [$00:0555]   ;Aに[$00:0555]をロード
$C2/450D CLC                     ;キャリーフラグクリア
$C2/450E ADC $59    [$00:0559]   ;A + [$00:0559]
$C2/4510 STA $57    [$00:0557]   ;Aを[$00:0557]に書き込み
$C2/4512 PLP                     ;Pレジスタにスタックからプル
$C2/4513 RTS                     ;サブルーチン戻り

$C2/0127でロードしたシナリオIDから、[$00:0555][$00:0559]に書き込む数値を記録したアドレスを計算するのだが、$C2/44E1で、「$0008 - シナリオID」を計算しゼロフラグ処理をしている。
シナリオID$08は最終編なので、最終編かそれ以外かで分岐なのだが、$C2/4501~の最終編用分岐を見ると、[$00:0555]$01、と[$00:0559]$FF、とアドレスを呼び出さず固定値をそのまま指定していることがわかる。
それ以外の8つのシナリオは、$D5:FC51$D5:FC60に順番に[$00:0555][$00:0559]が入っている。
更に、$C2/450B~からの処理で、[$00:0558][$00:0557][$00:0555] + [$00:0557]の値が入る(キャリーフラグ考慮)。
整理すると、以下のようになる。

シナリオID[$00:0555][$00:0559][$00:0558][$00:0557]
中世$00$D5:FC51
$01
$D5:FC52
$27
$0028
原始$01$D5:FC53
$28
$D5:FC54
$25
$004D
SF$02$D5:FC55
$F5
$D5:FC54
$05
$00FA
功夫$03$D5:FC57
$BD
$D5:FC54
$24
$00E1
西部$04$D5:FC59
$4D
$D5:FC54
$1A
$0067
現代$05$D5:FC5B
$BB
$D5:FC54
$02
$00BD
近未来$06$D5:FC5D
$89
$D5:FC5E
$33
$00BC
幕末$07$D5:FC5F
$67
$D5:FC60
$22
$0089
最終$08$01$FF$0100

[$00:0555]に入る値に+$0B00すると、アイテム欄のアイテムID開始アドレスになるし、+$0C00すると、各アイテムの個数の開始アドレスである。
例えば幕末編なら、[$00:0555]$67が入るので、$67 + $0B00$00:0B67がアイテム欄のアイテムID開始アドレス、個数開始アドレスは$00:0C67から、となる。
更に、[$00:0559]は各シナリオでのアイテム種類最大所持数、つまりアイテム欄の枠の総数である。
アイテム欄のアイテムID開始アドレスに更に[$00:0559]を加えれば、アイテム欄の最後の枠のアドレスになるが、これが[$00:0558][$00:0557]に入った値で算出できることになる。

ちなみに、所持アイテムが存在しない現代編用にも、アイテム欄用のアドレスが一応設定されていることがわかる。
ただし現代編では、メニュー画面で持ち物欄自体が選択できないので、実際のゲームにおいて意味はないはず。

もうひとつ重要なのが[$00:0544]である。
[$00:0544]には持ち物欄でXボタンを押した時に、4種類のコマンドをカーソルで選ぶたびに以下のように値が入る。

コマンド[$00:0544]
せいとん$00
回復先$01
攻撃先$02
装備先$03

[$00:0544]の値で処理が分岐するようになっている。

「せいとん」のサブルーチン

以上を踏まえて、まずは「せいとん」のサブルーチンを見てみる。
「せいとん」とあるが、実際には「空欄があったら前へ詰める」というコマンドである。
名前順、またはアイテムID順にソートなどという機能ではない。

$C2/0651 BCS $03    [$0656]      ;キャリーフラグが立っているとき[$0656]分岐
$C2/0653 JMP ($0532)[$C2:1026]   ;[$C2:1026]へジャンプ(レジスタをスタックに積まない)
$C2/1026 LDA $59    [$00:0559]   ;Aに[$00:0559](アイテム種類最大所持数)をロード
$C2/1028 BEQ $26    [$1050]      ;ゼロフラグが立っているとき[$1050]分岐
$C2/102A JSR $62EF  [$C2:62EF]   ;[$C2:62EF]へジャンプ

$C2/62EF PHP                     ;ステータスレジスタをスタックへプッシュ
$C2/62F0 REP #$20                ;Aを16bit幅に変更、Mフラグをクリア
$C2/62F2 LDX #$00FE              ;Xに$00FEをロード
;ループ処理
$C2/62F5 STZ $8A00,x             ;[$8A00,x+1][$8A00,x]に$00を書き込み
$C2/62F8 STZ $8B00,x             ;[$8B00,x+1][$8B00,xに$00を書き込み
$C2/62FB DEX                     ;Xをデクリメント -1
$C2/62FC DEX                     ;Xをデクリメント -1
$C2/62FD BPL $F6    [$62F5]      ;ネガティブフラグが立っていないとき[$62F5]分岐
;ループ処理ここまで

$C2/62FF PLP                     ;Pレジスタにスタックからプル
$C2/6300 RTS                     ;サブルーチン戻り

$C2/102D LDA $44    [$00:0544]   ;Aに[$00:0544](「せいとん」なら$00)をロード
$C2/102F AND #$0003              ;Aと$0003で論理積
$C2/1032 ASL A                   ;Aを算術左シフト *2
$C2/1033 TAX                     ;Aの値をXレジスタに転送
$C2/1034 JSR ($1053,x)[$C2:6317] ;[$C2:6317]へジャンプ

上のループ処理は、[$7E:8A00][$7E:8AFF]及び[$7E:8B00][$7E:8BFF]に初期値として$00を書き込む処理である。
アドレスをデクリメント(-1)して処理しているので、アドレスの大きい値から2バイトずつ書き込みをしている。
この領域が、アイテムの整頓・並び替えの計算用アドレスになる。
どのシナリオでも確保する領域は変わらない。
また、この時点でAには[$00:0559](アイテム種類最大所持数)が読み込まれている。

$C2/102Dで、コマンド別の値が入る[$00:0544]がロードされる。
「せいとん」の場合は$00が入っており、$C2/1034で呼び出すジャンプ先が決まる。
「せいとん」は$C2/6317にジャンプする。

$C2/6317 PHP                     ;ステータスレジスタをスタックへプッシュ
$C2/6318 SEP #$20                ;MフラグON Aレジスタは8bit幅
$C2/631A LDX $55    [$00:0555]   ;Xに[$00:0555](シナリオ毎の定数)をロード
$C2/631C LDY #$0000              ;Yに$0000をロード

;ループ処理
$C2/631F LDA $0B00,x             ;Aに[$0B00,x](アイテム欄のアイテムID)をロード
$C2/6322 BEQ $03    [$6327]      ;ゼロフラグが立っているとき[$6327]分岐
;ゼロフラグOFF 該当アドレスにアイテムがある
$C2/6324 JSR $6301  [$C2:6301]   ;[$C2:6301]へジャンプ

$C2/6301 LDA $0B00,x             ;Aに[$0B00,x](アイテム欄のアイテムID)をロード
$C2/6304 STA $8A00,y             ;Aを[$7E:8A00+y]に書き込み
$C2/6307 LDA $0C00,x             ;Aに[$0C00,x](アイテム個数)をロード
$C2/630A AND #$7F                ;Aと$7F(%0111 1111)で論理積
$C2/630C CMP #$64                ;Aと$64(10進数100)を減算比較(ステータスレジスタ変更のみ)
$C2/630E BMI $02    [$6312]      ;ネガティブフラグが立っているとき[$6312]分岐
;ネガティブフラグOFF(所持数100個以上)
$C2/6310 LDA #$63                ;Aに$63をロード
;ネガティブフラグON(所持数99個以下)
$C2/6312 STA $8B00,y             ;Aを[$7E:8B00+y]に書き込み
$C2/6315 INY                     ;Yをインクリメント +1
$C2/6316 RTS                     ;サブルーチン戻り

$C2/6327 INX                     ;Xをインクリメント +1
$C2/6328 CPX $57    [$00:0557]   ;Xと[$00:0558][$00:0557]を減算比較(ステータスレジスタ変更のみ)
$C2/632A BMI $F3    [$631F]      ;ネガティブフラグが立っているとき[$631F]分岐
;ループ処理ここまで

$C2/632C PLP                     ;Pレジスタにスタックからプル
$C2/632D RTS                     ;サブルーチン戻り

$C2/1037 JSR $4514  [$C2:4514]   ;[$C2:4514]へジャンプ

上のループ処理は、アイテム欄の枠をチェックし、何かのアイテムがある(アイテムIDが$00以外である)場合のみ、アイテムIDを$7E:8A00~にコピーする処理になる。
個数についても$7E:8B00~にコピーしていくが、アイテム個数が1~99個の間かどうかを$C2/6307$C2/6312でチェックし、$64以上(100以上)だったら$6399)に変更する処理が入っているが、この処理に引っかかることがあるのかはわからない。個数について何らかのバグがないようチェックしているのかもしれない。
もし枠に何のアイテムもなければ、$C2/6322から$C2/6327までジャンプなので、アドレスを+1する処理のみである。

このループを、X - [$00:0558][$00:0557]が負の数になるまで繰り返す。つまり、該当シナリオのアイテム欄の個数だけ繰り返すということになる。
これで、$7E:8A00~には所持アイテムのアイテムID、$7E:8B00~には所持アイテムの個数が順番に入ったことになる。空欄部分はコピーしていないから、アイテム欄のアイテムを順に詰めたことになる。

$C2/4514 PHB                     ;DBレジスタをスタックにプッシュ
$C2/4515 PHP                     ;ステータスレジスタをスタックへプッシュ
$C2/4516 REP #$20                ;Aを16bit幅に変更、Mフラグをクリア
$C2/4518 LDX #$8A00              ;Xに$8A00をロード
$C2/451B LDA $55    [$00:0555]   ;Aに[$00:0555](シナリオ毎の定数)をロード
$C2/451D CLC                     ;キャリーフラグクリア
$C2/451E ADC #$0B00              ;A + $0B00
$C2/4521 TAY                     ;Aの値をYレジスタに転送
$C2/4522 LDA $59    [$00:0559]   ;Aに[$00:0559]をロード
$C2/4524 DEC A                   ;Aをデクリメント -1
$C2/4525 BMI $13    [$453A]      ;ネガティブフラグが立っているとき[$453A]分岐
$C2/4527 MVN 7E 00               ;データ転送
;
;Aに転送したいデータサイズ-1 : [$00:0559]-1
;Xに転送元アドレス : 8A00
;Yに転送先アドレス : 0B00+[$00:0555]
;オペランドに転送元と転送先バンクを指定 : 7E 00
;
$C2/452A LDX #$8B00              ;Xに$8B00をロード
$C2/452D LDA $55    [$00:0555]   ;Aに[$00:0555]をロード
$C2/452F CLC                     ;キャリーフラグクリア
$C2/4530 ADC #$0C00              ;A + $0C00
$C2/4533 TAY                     ;Aの値をYレジスタに転送
$C2/4534 LDA $59    [$00:0559]   ;Aに[$00:0559]をロード
$C2/4536 DEC A                   ;をデクリメント -1
$C2/4537 MVN 7E 00               ;データ転送
;
;Aに転送したいデータサイズ-1 : [$00:0559]-1
;Xに転送元アドレス : 8B00
;Yに転送先アドレス : 0C00+[$00:0555]
;オペランドに転送元と転送先バンクを指定 : 7E 00
;
$C2/453A PLP                     ;Pレジスタにスタックからプル
$C2/453B PLB                     ;DBレジスタに値をプル
$C2/453C RTS                     ;サブルーチン戻り

後は、MVNを使って、$7E:8A00~及び$7E:8B00~から元の$00:0B01~及び$00:0C01~に転送・上書きして終了である。
転送したいデータサイズは[$00:0559]の値を、転送先アドレスの開始位置は[$00:0555]から計算できる。

「せいとん」の仕組みは、実質空欄を詰めるだけであったため、シンプルである。
続いて「回復先」のサブルーチンを見てみよう。

「回復先」のサブルーチン

回復アイテムかどうかを判別するには、アイテムデータ00の値が必要である。
回復アイテムなら下から2ビット目に1が立つ。
%0000 0010%0000 0011のどちらかで、%0000 0010なら無限回数使用可能、%0000 0011なら1回のみの消費アイテム。

「せいとん」と同じく$C2/0651~からの処理を追いかけていく。

$C2/0651 BCS $03    [$0656]      ;キャリーフラグが立っているとき[$0656]分岐
$C2/0653 JMP ($0532)[$C2:1026]   ;[$C2:1026]へジャンプ(レジスタをスタックに積まない)
$C2/1026 LDA $59    [$00:0559]   ;Aに[$00:0559]をロード
$C2/1028 BEQ $26    [$1050]      ;ゼロフラグが立っているとき[$1050]分岐
$C2/102A JSR $62EF  [$C2:62EF]   ;[$C2:62EF]へジャンプ

$C2/62EF PHP                     ;ステータスレジスタをスタックへプッシュ
$C2/62F0 REP #$20                ;Aを16bit幅に変更、Mフラグをクリア
$C2/62F2 LDX #$00FE              ;Xに$00FEをロード
;ループ処理
$C2/62F5 STZ $8A00,x             ;[$8A00,x+1][$8A00,x]に$00を書き込み
$C2/62F8 STZ $8B00,x             ;[$8B00,x+1][$8B00,xに$00を書き込み
$C2/62FB DEX                     ;Xをデクリメント -1
$C2/62FC DEX                     ;Xをデクリメント -1
$C2/62FD BPL $F6    [$62F5]      ;ネガティブフラグが立っていないとき[$62F5]分岐
;ループ処理ここまで

$C2/62FF PLP                     ;Pレジスタにスタックからプル
$C2/6300 RTS                     ;サブルーチン戻り

$C2/102D LDA $44    [$00:0544]   ;Aに[$00:0544](「回復先」なら$01)をロード
$C2/102F AND #$0003              ;Aと$0003で論理積
$C2/1032 ASL A                   ;Aを算術左シフト *2
$C2/1033 TAX                     ;Aの値をXレジスタに転送
$C2/1034 JSR ($1053,x)[$C2:6342] ;[$C2:6342]へジャンプ

「せいとん」と処理が変わるのは$C2/102Dから先である。
「せいとん」は[$00:0544]に$0が入っていたが、「回復先」は$01が入っているため、$C2/1034でのジャンプ先が$C2/6342になる。
「せいとん」では$C2/6317だったので別アドレスであり、ここからが分岐である。

$C2/6342 PHP                     ;ステータスレジスタをスタックへプッシュ
$C2/6343 SEP #$20                ;MフラグON Aレジスタは8bit幅
$C2/6345 LDX $55    [$00:0555]   ;Xに[$00:0555](シナリオ毎の定数)をロード
$C2/6347 LDY #$0000              ;Yに$0000をロード

;ループ処理
$C2/634A LDA $0B00,x             ;Aに[$0B00,x](アイテム欄のアイテムID)をロード
$C2/634D BEQ $19    [$6368]      ;ゼロフラグが立っているとき[$6368]分岐
$C2/634F JSR $49A6  [$C2:49A6]   ;[$C2:49A6]へジャンプ

;アイテムIDからアイテムデータアドレス計算
$C2/49A6 PHX                     ;Xをスタックにプッシュ
$C2/49A7 PHY                     ;Yをスタックへプッシュ
$C2/49A8 PHP                     ;ステータスレジスタをスタックへプッシュ
$C2/49A9 REP #$20                ;Aを16bit幅に変更、Mフラグをクリア
$C2/49AB AND #$00FF              ;Aと$00FFで論理積
$C2/49AE STA $2A7B  [$7E:2A7B]   ;A(アイテムID)を[$7E:2A7C][$7E:2A7B]に書き込み
$C2/49B1 LDA #$0068              ;Aに$0068をロード
$C2/49B4 STA $A3    [$00:05A3]   ;Aを[$00:05A4][$00:05A3]に書き込み
$C2/49B6 LDA #$00D5              ;Aに$00D5をロード
$C2/49B9 STA $A5    [$00:05A5]   ;Aを[$00:05A6][$00:05A5]に書き込み
$C2/49BB LDA $2A7B  [$7E:2A7B]   ;Aに[$7E:2A7C][$7E:2A7B](アイテムID)をロード
$C2/49BE JSR $6238  [$C2:6238]   ;[$C2:6238]へジャンプ

$C2/6238 PHP                     ;ステータスレジスタをスタックへプッシュ
$C2/6239 PHY                     ;Yをスタックへプッシュ
$C2/623A SEP #$20                ;MフラグON Aレジスタは8bit幅
$C2/623C STA $004202[$00:4202]   ;Aを[$00:4202]に書き込み
$C2/6240 LDY #$0004              ;Yに$0004をロード
$C2/6243 LDA [$A3],y[$D5:006C]   ;Aに[$D5:006C]をロード
$C2/6245 STA $004203[$00:4203]   ;Aを[$00:4203]に書き込み
$C2/6249 NOP                     ;計算待ち
$C2/624A NOP                     ;計算待ち
$C2/624B NOP                     ;計算待ち
$C2/624C REP #$20                ;Aを16bit幅に変更、Mフラグをクリア
$C2/624E LDA $004216[$00:4216]   ;Aに[$00:4217][$00:4216]をロード
$C2/6252 CLC                     ;キャリーフラグクリア
$C2/6253 ADC [$A3]  [$D5:0068]   ;A + [$D5:0069][$D5:0068]($71C4)
$C2/6255 PLY                     ;Yレジスタにスタックからプル
$C2/6256 PLP                     ;Pレジスタにスタックからプル
$C2/6257 RTS                     ;サブルーチン戻り
;符号付8bit x 8bit
;アイテムID * [$D5:006C]($10)
;アイテムID * [$D5:006C]($10) + [$D5:0069][$D5:0068]($71C4)
;でアイテムデータ開始アドレスが算出
;
$C2/49C1 TAX                     ;Aの値をXレジスタに転送
$C2/49C2 LDY #$2A7D              ;Yに$2A7Dをロード
$C2/49C5 LDA $D5006C[$D5:006C]   ;Aに[$D5:006C]をロード
$C2/49C9 DEC A                   ;Aをデクリメント -1
$C2/49CA MVN D5 7E               ;データ転送
;Aに転送したいデータサイズ-1 : [$D5:006C]=$0F(10)-1
;Xに転送元アドレス : (アイテムデータ開始アドレス)
;Yに転送先アドレス : 2A7D
;オペランドに転送元と転送先バンクを指定 : D5 7E
$C2/49CD PLP                     ;Pレジスタにスタックからプル
$C2/49CE PLY                     ;Yレジスタにスタックからプル
$C2/49CF PLX                     ;Xレジスタにスタックからプル
$C2/49D0 RTS                     ;サブルーチン戻り

$C2/6352 LDA $2A7D  [$7E:2A7D]   ;Aに[$7E:2A7D](アイテムデータ00)をロード
$C2/6355 AND #$0F                ;Aと$0Fで論理積
$C2/6357 CMP #$02                ;Aと$02を減算比較(ステータスレジスタ変更のみ)
$C2/6359 BEQ $04    [$635F]      ;ゼロフラグが立っているとき[$635F]分岐
;ゼロフラグOFF(回復アイテム判定)
$C2/635B CMP #$03                ;Aと$03を減算比較(ステータスレジスタ変更のみ)
$C2/635D BNE $09    [$6368]      ;ゼロフラグが立っていないとき[$6368]分岐
;ゼロフラグON
$C2/635F JSR $6301  [$C2:6301]   ;[$C2:6301]へジャンプ

$C2/6301 LDA $0B00,x             ;Aに[$0B00,x]をロード
$C2/6304 STA $8A00,y             ;Aを[$7E:8A00+y]に書き込み
$C2/6307 LDA $0C00,x             ;Aに[$0C00,x]をロード
$C2/630A AND #$7F                ;Aと$7Fで論理積
$C2/630C CMP #$64                ;Aと$64を減算比較(ステータスレジスタ変更のみ)
$C2/630E BMI $02    [$6312]      ;ネガティブフラグが立っているとき[$6312]分岐
;ネガティブフラグOFF(所持数100個以上)
$C2/6310 LDA #$63                ;Aに$63をロード
;ネガティブフラグON(所持数99個以下)
$C2/6312 STA $8B00,y             ;Aを[$7E:8B00+y]に書き込み
$C2/6315 INY                     ;Yをインクリメント +1
$C2/6316 RTS                     ;サブルーチン戻り

$C2/6362 STZ $0B00,x             ;[$0B00,x]に$00を書き込み
$C2/6365 STZ $0C00,x             ;[$0C00,x]に$00を書き込み
$C2/6368 INX                     ;Xをインクリメント +1
$C2/6369 CPX $57    [$00:0557]   ;Xと[$00:0557]を減算比較(ステータスレジスタ変更のみ)
$C2/636B BMI $DD    [$634A]      ;ネガティブフラグが立っているとき[$634A]分岐
;ループ処理ここまで

$C2/636D JSR $632E  [$C2:632E]   ;[$C2:632E]へジャンプ

ループ処理が長くなっているが、基本的には「せいとん」時とやることは似ている。
ただ、アイテム欄のアイテムIDをロードしてから、$C2/49A6$C2/49D0までが該当アイテムのアイテムデータ開始位置アドレス計算なので少々長い。
最終的に、$C2/6352にアイテムデータ00がロードされる。
$0Fと論理積を取り、$02と減算比較してゼロフラグが立つ場合は、無限回数使用可能な回復アイテムで確定であり、$C2/635Fにジャンプ。
$03と減算比較して、ゼロフラグが立つ場合は、1回のみ使用の消費回復アイテムで確定であり、$C2/635Fに進む。
$C2/635Fに進むのなら回復アイテムで確定、それ以外は$C2/6368にジャンプ、つまり回復アイテムではない。

回復アイテムで確定の場合、$C2/635F$C2/6301と進むが、ここからは「せいとん」と共通処理である。
つまり、該当アイテムIDを$7E:8A00~に、個数を$7E:8B00~にコピーする。

「せいとん」と異なるのは、ここでコピーした回復アイテムについては、$C2/6362$C2/6365$00を書き込んで一度アイテム欄から削除するという点である。
ここでループ処理が終了となり、あとはアイテム欄ひとつずつループして、すべて処理する。

つまり、

  • 回復アイテムはアイテムIDを$7E:8A00~に、個数を$7E:8B00~にコピーしてから、元のアイテム欄からはアイテムIDと個数を削除
  • それ以外のアイテムはそのまま

という処理がループ処理終了の$C2/636Dまでに行われる、ということである。

では、$C2/636Dから先の処理を見てみる。

$C2/636D JSR $632E  [$C2:632E]   ;[$C2:632E]へジャンプ

$C2/632E PHP                     ;ステータスレジスタをスタックへプッシュ
$C2/632F SEP #$20                ;MフラグON Aレジスタは8bit幅
$C2/6331 LDX $55    [$00:0555]   ;Xに[$00:0555](シナリオ毎の定数)をロード

;ループ処理
$C2/6333 LDA $0B00,x             ;Aに[$0B00,x]をロード
$C2/6336 BEQ $03    [$633B]      ;ゼロフラグが立っているとき[$633B]分岐
$C2/633B INX                     ;Xをインクリメント +1
$C2/633C CPX $57    [$00:0557]   ;Xと[$00:0558][$00:0557]を減算比較(ステータスレジスタ変更のみ)
$C2/633E BMI $F3    [$6333]      ;ネガティブフラグが立っているとき[$6333]分岐
$C2/6333 LDA $0B00,x             ;Aに[$0B00,x]をロード
$C2/6336 BEQ $03    [$633B]      ;ゼロフラグが立っているとき[$633B]分岐
$C2/6338 JSR $6301  [$C2:6301]   ;[$C2:6301]へジャンプ

$C2/6301 LDA $0B00,x             ;Aに[$0B00,x]をロード
$C2/6304 STA $8A00,y             ;Aを[$7E:8A00+y]に書き込み
$C2/6307 LDA $0C00,x             ;Aに[$0C00,x]をロード
$C2/630A AND #$7F                ;Aと$7Fで論理積
$C2/630C CMP #$64                ;Aと$64を減算比較(ステータスレジスタ変更のみ)
$C2/630E BMI $02    [$6312]      ;ネガティブフラグが立っているとき[$6312]分岐
;ネガティブフラグOFF(所持数100個以上)
$C2/6310 LDA #$63                ;Aに$63をロード
;ネガティブフラグON(所持数99個以下)
$C2/6312 STA $8B00,y             ;Aを[$7E:8B00+y]に書き込み
$C2/6315 INY                     ;Yをインクリメント +1
$C2/6316 RTS                     ;サブルーチン戻り

$C2/633B INX                     ;Xをインクリメント +1
$C2/633C CPX $57    [$00:0557]   ;Xと[$00:0557]を減算比較(ステータスレジスタ変更のみ)
$C2/633E BMI $F3    [$6333]      ;ネガティブフラグが立っているとき[$6333]分岐
;ループ処理ここまで

$C2/6340  PLP                    ;Pレジスタにスタックからプル
$C2/6341  RTS                    ;サブルーチン戻り

$C2/6370  PLP                    ;Pレジスタにスタックからプル
$C2/6371  RTS                    ;サブルーチン戻り

$C2/1037  JSR $4514  [$C2:4514]  ;[$C2:4514]へジャンプ

アドレスが一部異なるが、「せいとん」時と同じ処理になっている。
ただし、回復アイテムはアイテム欄から除かれているので、回復アイテム以外のアイテムを$7E:8A00~と$7E:8B00~の回復アイテム以降のアドレスにコピーしていく処理である。
これで、$7E:8A00~と$7E:8B00~には、回復アイテム→それ以外のアイテムの順にアイテムが並び替えられて並んだことになる。
回復アイテムにしろ他のアイテムにしろ、アイテムデータ00しか参照していないから、アイテムIDの順に並び替えなどということはしていないことがわかる。

ここまで処理をすると、ジャンプ先は$C2/4514である。
これは「せいとん」時に、$7E:8A00~及び$7E:8B00~から元の$00:0B01~及び$00:0C01~に転送・上書きしたサブルーチン開始位置である。
実際、この後の$C2/4514$C2/453Cは「せいとん」時と全く同じ手順なので、紹介は省略する。
以上が「回復先」のサブルーチンである。

「攻撃先」のサブルーチン

では、「攻撃先」のサブルーチンも見てみよう。
仕組み自体は「回復先」とだいたい同じである。
分岐は同じく$C2/1034のジャンプ先からなので、そこから紹介する。
[$00:0544]は、「攻撃先」なら$02が入っているので、ジャンプ先が$C2/6372になる。

$C2/102D LDA $44    [$00:0544]   ;Aに[$00:0544](「攻撃先」なら$02)をロード
$C2/102F AND #$0003              ;Aと$0003で論理積
$C2/1032 ASL A                   ;Aを算術左シフト *2
$C2/1033 TAX                     ;Aの値をXレジスタに転送
$C2/1034 JSR ($1053,x)[$C2:6372] ;[$C2:6372]へジャンプ

$C2/6372 PHP                     ;ステータスレジスタをスタックへプッシュ
$C2/6373 SEP #$20                ;MフラグON Aレジスタは8bit幅
$C2/6375 LDX $55    [$00:0555]   ;Xに[$00:0555]をロード
$C2/6377 LDY #$0000              ;Yに$0000をロード

;ループ処理
$C2/637A LDA $0B00,x             ;Aに[$0B00,x]をロード
$C2/637D BEQ $19    [$6398]      ;ゼロフラグが立っているとき[$6398]分岐
$C2/637F JSR $49A6  [$C2:49A6]   ;[$C2:49A6]へジャンプ

;アイテムIDからアイテムデータアドレス計算
$C2/49A6 PHX                     ;Xをスタックにプッシュ
$C2/49A7 PHY                     ;Yをスタックへプッシュ
$C2/49A8 PHP                     ;ステータスレジスタをスタックへプッシュ
$C2/49A9 REP #$20                ;Aを16bit幅に変更、Mフラグをクリア
$C2/49AB AND #$00FF              ;Aと$00FFで論理積
$C2/49AE STA $2A7B  [$7E:2A7B]   ;Aを[$7E:2A7B]に書き込み
$C2/49B1 LDA #$0068              ;Aに$0068をロード
$C2/49B4 STA $A3    [$00:05A3]   ;Aを[$00:05A3]に書き込み
$C2/49B6 LDA #$00D5              ;Aに$00D5をロード
$C2/49B9 STA $A5    [$00:05A5]   ;Aを[$00:05A5]に書き込み
$C2/49BB LDA $2A7B  [$7E:2A7B]   ;Aに[$7E:2A7B]をロード
$C2/49BE JSR $6238  [$C2:6238]   ;[$C2:6238]へジャンプ

$C2/6238 PHP                     ;ステータスレジスタをスタックへプッシュ
$C2/6239 PHY                     ;Yをスタックへプッシュ
$C2/623A SEP #$20                ;MフラグON Aレジスタは8bit幅
$C2/623C STA $004202[$00:4202]   ;Aを[$00:4202]に書き込み
$C2/6240 LDY #$0004              ;Yに$0004をロード
$C2/6243 LDA [$A3],y[$D5:006C]   ;Aに[$A3]をロード
$C2/6245 STA $004203[$00:4203]   ;Aを[$00:4203]に書き込み
$C2/6249 NOP                     ;計算待ち
$C2/624A NOP                     ;計算待ち
$C2/624B NOP                     ;計算待ち
$C2/624C REP #$20                ;Aを16bit幅に変更、Mフラグをクリア
$C2/624E LDA $004216[$00:4216]   ;Aに[$00:4216]をロード
$C2/6252 CLC                     ;キャリーフラグクリア
$C2/6253 ADC [$A3]  [$D5:0068]   ;A + [$A3]
$C2/6255 PLY                     ;Yレジスタにスタックからプル
$C2/6256 PLP                     ;Pレジスタにスタックからプル
$C2/6257 RTS                     ;サブルーチン戻り

$C2/49C1 TAX                     ;Aの値をXレジスタに転送
$C2/49C2 LDY #$2A7D              ;Yに$2A7Dをロード
$C2/49C5 LDA $D5006C[$D5:006C]   ;Aに[$D5:006C]をロード
$C2/49C9 DEC A                   ;をデクリメント -1
$C2/49CA MVN D5 7E               ;データ転送
;Aに転送したいデータサイズ-1 : [$D5:006C]=$0F(10)-1
;Xに転送元アドレス : (アイテムデータ開始アドレス)
;Yに転送先アドレス : 2A7D
;オペランドに転送元と転送先バンクを指定 : D5 7E
$C2/49CD PLP                     ;Pレジスタにスタックからプル
$C2/49CE PLY                     ;Yレジスタにスタックからプル
$C2/49CF PLX                     ;Xレジスタにスタックからプル
$C2/49D0 RTS                     ;サブルーチン戻り

$C2/6382 LDA $2A7D  [$7E:2A7D]   ;Aに[$7E:2A7D](アイテムデータ00)をロード
$C2/6385 AND #$0F                ;Aと$0Fで論理積
$C2/6387 CMP #$04                ;Aと$04を減算比較(ステータスレジスタ変更のみ)
$C2/6389 BEQ $04    [$638F]      ;ゼロフラグが立っているとき[$638F]分岐
;ゼロフラグOFF(攻撃アイテム判定)
$C2/638B CMP #$05                ;Aと$05を減算比較(ステータスレジスタ変更のみ)
$C2/638D BNE $09    [$6398]      ;ゼロフラグが立っていないとき[$6398]分岐
;ゼロフラグON
$C2/638F JSR $6301  [$C2:6301]   ;[$C2:6301]へジャンプ

$C2/6301 LDA $0B00,x             ;Aに[$0B00,x]をロード
$C2/6304 STA $8A00,y             ;Aを[$7E:8A00+y]に書き込み
$C2/6307 LDA $0C00,x             ;Aに[$0C00,x]をロード
$C2/630A AND #$7F                ;Aと$7Fで論理積
$C2/630C CMP #$64                ;Aと$64を減算比較(ステータスレジスタ変更のみ)
$C2/630E BMI $02    [$6312]      ;ネガティブフラグが立っているとき[$6312]分岐
;ネガティブフラグOFF(所持数100個以上)
$C2/6310 LDA #$63                ;Aに$63をロード
;ネガティブフラグON(所持数99個以下)
$C2/6312 STA $8B00,y             ;Aを[$7E:8B00+y]に書き込み
$C2/6315 INY                     ;Yをインクリメント +1
$C2/6316 RTS                     ;サブルーチン戻り

$C2/6392 STZ $0B00,x             ;[$0B00,x]に$00を書き込み
$C2/6395 STZ $0C00,x             ;[$0C00,x]に$00を書き込み
$C2/6398 INX                     ;Xをインクリメント +1
$C2/6399 CPX $57    [$00:0557]   ;Xと[$00:0557]を減算比較(ステータスレジスタ変更のみ)
$C2/639B BMI $DD    [$637A]      ;ネガティブフラグが立っているとき[$637A]分岐
;ループ処理ここまで

$C2/639D JSR $632E  [$C2:632E]   ;[$C2:632E]へジャンプ

回復先と異なるのは、アイテムデータ00を呼び出してからの処理だけである。

$C2/6382 LDA $2A7D  [$7E:2A7D]   ;Aに[$7E:2A7D](アイテムデータ00)をロード
$C2/6385 AND #$0F                ;Aと$0Fで論理積
$C2/6387 CMP #$04                ;Aと$04を減算比較(ステータスレジスタ変更のみ)
$C2/6389 BEQ $04    [$638F]      ;ゼロフラグが立っているとき[$638F]分岐
;ゼロフラグOFF(攻撃アイテム判定)
$C2/638B CMP #$05                ;Aと$05を減算比較(ステータスレジスタ変更のみ)
$C2/638D BNE $09    [$6398]      ;ゼロフラグが立っていないとき[$6398]分岐
;ゼロフラグON
$C2/638F JSR $6301  [$C2:6301]   ;[$C2:6301]へジャンプ

アイテムデータ00の下4ビット目が1なら無限使用可能な攻撃アイテム、下5ビット目が1なら1回のみ使用の消費攻撃アイテムである。
$C2/638Fまで進んだ場合は攻撃アイテムで確定で、後は回復先と同じように分けていくだけである。
ループ処理を抜けた後の飛び先$C2/639D$C2/632Eの処理も、回復先と全く同じなので省略する。

最後に、装備先の処理を見てみよう。

「装備先」のサブルーチン

これまでと同じく、分岐が生じるのは$C2/1034でのジャンプ先である。
$C2/63CCにジャンプするのだが、その先の処理はこれまでと少し異なる。

$C2/102D LDA $44    [$00:0544]   ;Aに[$00:0544](「装備先」なら$03)をロード
$C2/102F AND #$0003              ;Aと$0003で論理積
$C2/1032 ASL A                   ;Aを算術左シフト *2
$C2/1033 TAX                     ;Aの値をXレジスタに転送
$C2/1034 JSR ($1053,x)[$C2:63CC] ;[$C2:63CC]へジャンプ

$C2/63CC PHP                     ;ステータスレジスタをスタックへプッシュ
$C2/63CD SEP #$20                ;MフラグON Aレジスタは8bit幅
$C2/63CF LDA #$01                ;Aに$01をロード
$C2/63D1 STA $5B    [$00:055B]   ;A($01)を[$00:055B]に書き込み
$C2/63D3 LDY #$0000              ;Yに$0000をロード
$C2/63D6 JSR $63A2  [$C2:63A2]   ;[$C2:63A2]へジャンプ

;ループ処理 $C2/63A2~$C2/63D6
$C2/63A2 PHP                     ;ステータスレジスタをスタックへプッシュ
$C2/63A3 SEP #$20                ;MフラグON Aレジスタは8bit幅
$C2/63A5 LDX $55    [$00:0555]   ;Xに[$00:0555](シナリオ毎の定数)をロード

;ループ処理 $C2/63A7~$C2/63C8
$C2/63A7 LDA $0B00,x             ;Aに[$0B00,x]をロード
$C2/63AA BEQ $19    [$63C5]      ;ゼロフラグが立っているとき[$63C5]分岐
$C2/63AC JSR $49A6  [$C2:49A6]   ;[$C2:49A6]へジャンプ

;アイテムIDからアイテムデータアドレス計算
$C2/49A6 PHX                     ;Xをスタックにプッシュ
$C2/49A7 PHY                     ;Yをスタックへプッシュ
$C2/49A8 PHP                     ;ステータスレジスタをスタックへプッシュ
$C2/49A9 REP #$20                ;Aを16bit幅に変更、Mフラグをクリア
$C2/49AB AND #$00FF              ;Aと$00FFで論理積
$C2/49AE STA $2A7B  [$7E:2A7B]   ;A(アイテムID)を[$7E:2A7C][$7E:2A7B]に書き込み
$C2/49B1 LDA #$0068              ;Aに$0068をロード
$C2/49B4 STA $A3    [$00:05A3]   ;Aを[$00:05A4][$00:05A3]に書き込み
$C2/49B6 LDA #$00D5              ;Aに$00D5をロード
$C2/49B9 STA $A5    [$00:05A5]   ;Aを[$00:05A6][$00:05A5]に書き込み
$C2/49BB LDA $2A7B  [$7E:2A7B]   ;Aに[$7E:2A7C][$7E:2A7B](アイテムID)をロード
$C2/49BE JSR $6238  [$C2:6238]   ;[$C2:6238]へジャンプ

$C2/6238 PHP                     ;ステータスレジスタをスタックへプッシュ
$C2/6239 PHY                     ;Yをスタックへプッシュ
$C2/623A SEP #$20                ;MフラグON Aレジスタは8bit幅
$C2/623C STA $004202[$00:4202]   ;Aを[$00:4202]に書き込み
$C2/6240 LDY #$0004              ;Yに$0004をロード
$C2/6243 LDA [$A3],y[$D5:006C]   ;Aに[$D5:006C]をロード
$C2/6245 STA $004203[$00:4203]   ;Aを[$00:4203]に書き込み
$C2/6249 NOP                     ;計算待ち
$C2/624A NOP                     ;計算待ち
$C2/624B NOP                     ;計算待ち
$C2/624C REP #$20                ;Aを16bit幅に変更、Mフラグをクリア
$C2/624E LDA $004216[$00:4216]   ;Aに[$00:4217][$00:4216]をロード
$C2/6252 CLC                     ;キャリーフラグクリア
$C2/6253 ADC [$A3]  [$D5:0068]   ;A + [$D5:0069][$D5:0068]($71C4)
$C2/6255 PLY                     ;Yレジスタにスタックからプル
$C2/6256 PLP                     ;Pレジスタにスタックからプル
$C2/6257 RTS                     ;サブルーチン戻り

$C2/49C1 TAX                     ;Aの値をXレジスタに転送
$C2/49C2 LDY #$2A7D              ;Yに$2A7Dをロード
$C2/49C5 LDA $D5006C[$D5:006C]   ;Aに[$D5:006C]をロード
$C2/49C9 DEC A                   ;をデクリメント -1
$C2/49CA MVN D5 7E               ;データ転送
;Aに転送したいデータサイズ-1 : [$D5:006C]=$0F(10)-1
;Xに転送元アドレス : (アイテムデータ開始アドレス)
;Yに転送先アドレス : 2A7D
;オペランドに転送元と転送先バンクを指定 : D5 7E
$C2/49CD PLP                     ;Pレジスタにスタックからプル
$C2/49CE PLY                     ;Yレジスタにスタックからプル
$C2/49CF PLX                     ;Xレジスタにスタックからプル
$C2/49D0 RTS                     ;サブルーチン戻り

$C2/63AF LDA $2A7D  [$7E:2A7D]   ;Aに[$7E:2A7D](アイテムデータ00)をロード
$C2/63B2 AND #$70                ;Aと$70(%0111 0000)で論理積
$C2/63B4 LSR A                   ;Aを論理右シフト (/2)
$C2/63B5 LSR A                   ;Aを論理右シフト (/2)
$C2/63B6 LSR A                   ;Aを論理右シフト (/2)
$C2/63B7 LSR A                   ;Aを論理右シフト (/2)
$C2/63B8 CMP $5B    [$00:055B]   ;Aと[$00:055B]($01~$08)を減算比較(ステータスレジスタ変更のみ)
$C2/63BA BNE $09    [$63C5]      ;ゼロフラグが立っていないとき[$63C5]分岐
;ゼロフラグON(装備アイテム判定)
$C2/63BC JSR $6301  [$C2:6301]   ;[$C2:6301]へジャンプ

$C2/6301 LDA $0B00,x             ;Aに[$0B00,x]をロード
$C2/6304 STA $8A00,y             ;Aを[$7E:8A00+y]に書き込み
$C2/6307 LDA $0C00,x             ;Aに[$0C00,x]をロード
$C2/630A AND #$7F                ;Aと$7Fで論理積
$C2/630C CMP #$64                ;Aと$64を減算比較(ステータスレジスタ変更のみ)
$C2/630E BMI $02    [$6312]      ;ネガティブフラグが立っているとき[$6312]分岐
;ネガティブフラグOFF(所持数100個以上)
$C2/6310 LDA #$63                ;Aに$63をロード
;ネガティブフラグON(所持数99個以下)
$C2/6312 STA $8B00,y             ;Aを[$7E:8B00+y]に書き込み
$C2/6315 INY                     ;Yをインクリメント +1
$C2/6316 RTS                     ;サブルーチン戻り

$C2/63BF STZ $0B00,x             ;[$0B00,x]に$00を書き込み
$C2/63C2 STZ $0C00,x             ;[$0C00,x]に$00を書き込み
;ゼロフラグOFF($C2/63BAで、装備アイテムではない)
$C2/63C5 INX                     ;Xをインクリメント +1
$C2/63C6 CPX $57    [$00:0557]   ;Xと[$00:0557]を減算比較(ステータスレジスタ変更のみ)
$C2/63C8 BMI $DD    [$63A7]      ;ネガティブフラグが立っているとき[$63A7]分岐
;ループ処理ここまで

$C2/63CA PLP                     ;Pレジスタにスタックからプル
$C2/63CB RTS                     ;サブルーチン戻り

$C2/63D9 LDA $5B    [$00:055B]   ;Aに[$00:055B](初期値$01)をロード
$C2/63DB INC A                   ;Aをインクリメント +1
$C2/63DC STA $5B    [$00:055B]   ;Aを[$00:055B]に書き込み
$C2/63DE CMP #$08                ;Aと$08を減算比較(ステータスレジスタ変更のみ)
$C2/63E0 BMI $F4    [$63D6]      ;ネガティブフラグが立っているとき[$63D6]分岐
;ネガティブフラグON([$00:055B]が$07以下)
$C2/63D6 JSR $63A2  [$C2:63A2]   ;[$C2:63A2]へジャンプ
;ループ処理ここまで
;ネガティブフラグOFF
$C2/63E2 JSR $632E  [$C2:632E]   ;[$C2:632E]へジャンプ

以上が「装備アイテムなら[$7E:8A00]~及び[$7E:8B00]~にコピーして元データを削除」のループ処理なのだが、ループ処理が入れ子になっている。
$C2/63A2$C2/63D6というループ処理の中に、$C2/63A7$C2/63C8というループ処理が入っているのである。
どういうことなのか、$C2/63AFから見てみるとわかる。

$C2/63AF LDA $2A7D  [$7E:2A7D]   ;Aに[$7E:2A7D](アイテムデータ00)をロード
$C2/63B2 AND #$70                ;Aと$70(%0111 0000)で論理積
$C2/63B4 LSR A                   ;Aを論理右シフト (/2)
$C2/63B5 LSR A                   ;Aを論理右シフト (/2)
$C2/63B6 LSR A                   ;Aを論理右シフト (/2)
$C2/63B7 LSR A                   ;Aを論理右シフト (/2)
$C2/63B8 CMP $5B    [$00:055B]   ;Aと[$00:055B]($01~$08)を減算比較(ステータスレジスタ変更のみ)
$C2/63BA BNE $09    [$63C5]      ;ゼロフラグが立っていないとき[$63C5]分岐
;ゼロフラグON(装備アイテム判定)
$C2/63BC JSR $6301  [$C2:6301]   ;[$C2:6301]へジャンプ

アイテムデータ00をロードした後、まず$70(%0111 0000)と論理積を取っている。
アイテムデータ00の上2~4ビットに何らかの数値が入っている場合、装備アイテムで確定である。
上2~4ビットの値は主装備位置で、以下のようになる。

数値主装備位置
$1
$2
$3
$4
$5
$6アクセサリー
$7自由

論理右シフトを4回しているから、上4ビットの値を下4ビットに持ってきたことになり、$C2/63B8の時点で、装備アイテムなら$01$07のいずれかになっている。
そして$C2/63B8[$00:055B]と減算比較しているのだが、この[$00:055B]は、入れ子の外側のループの開始前$C2/63D1にて、$01が書き込まれている。
更にループ終わりの$C2/63D9$C2/63D6で、[$00:055B]をインクリメント +1し、$08と減算比較して、ネガティブフラグ判定だから、[$00:055B]$08まで増えた時点でループ終了である。
ということは、$C2/63B8のアイテムデータ00上4ビットと[$00:055B]の減算比較は、

アイテムデータ00上4ビット - [$00:055B]($01~$07)

を、アイテム欄のアイテム全てに行い、ゼロフラグ判定で分類させることになる。
これまでの回復アイテムや攻撃アイテムは、アイテム欄のアイテム全てに対し1回のループで判定してきたが、装備アイテムについては7ループ分の処理を繰り返すことになる。
装備アイテムの中で更に7種類に分類しているのと同義である。
結果、[$7E:8A00]~及び[$7E:8B00]~にコピーするアイテムの順序は、

主装備位置が頭→右→左→体→足→アクセサリー→自由

と、装備アイテムであっても分類されてコピーされていく、ということがわかる。

このループを終えた後のジャンプ先$C2/632Eは、他の処理と同じであるから省略。
$7E:8A00~及び$7E:8B00~から元の$00:0B01~及び$00:0C01~への書き戻しである。

装備先で並び替えると、

主装備位置が頭→右→左→体→足→アクセサリー→自由→その他

の順に並び替えが行われることがわかった。

以上が持ち物欄における整頓処理である。

アイテム入れ替え

アイテムの入れ替えは、

  1. カーソル位置の交換元アイテムをAボタンで選択
  2. カーソルを動かして、交換先アイテムをAボタンで選択で入れ替え

というように行うため、カーソル位置が記録されるアドレスが重要である。
カーソル位置が入るアドレスは、
[$00:0544][$00:0545]
の2バイトで、現在のカーソル位置の値が入る。
このアドレスには、メニュー画面であればどの階層(ページ)でもカーソルの位置が入る。
持ち物欄なら、左上から右下へ、順に$0000から番号が入る、といったような処理である。
隊形なら4キャラ分の位置、$0000$0003が入る。

もうひとつ重要なのが、「カーソル位置の何かをAボタンで選択している状態」を記録するアドレスである。
[$00:0565][$00:0568]に記録されるのだが、まずこのアドレスに入る値の処理が持ち物欄を開いた時に行われる。
(先に記したが、アイテム一覧のアイテムIDと個数のメモリアドレス内容($00:0B01$00:0BFF, $00:0C01$00:0CFF)を、整頓用に確保してあるメモリアドレス($7E:8A00$7E:8AFE, $7E:8B00$7E:8BFE)にコピーすることも、持ち物欄を開いた時点で行っている)

$C2/0EA5 LDA #$FFFF              ;Aに$FFFFをロード
$C2/0EA8 STA $65    [$00:0565]   ;Aを[$00:0566][$00:0565]に書き込み
$C2/0EAA STA $67    [$00:0567]   ;Aを[$00:0568][$00:0567]に書き込み
$C2/0EAC LDX #$7DF9              ;Aに$7DF9をロード
$C2/0EAF JSR $35AD  [$C2:35AD]   ;[$C2:35AD]へジャンプ

上の処理で、[$00:0565][$00:0568]の4バイト分すべて$FFで埋まる。
さて、Aボタンで交換元のアイテムを選ぶと以下のような処理になる。

$C2/0651 BCS $03    [$0656]      ;キャリーフラグが立っているとき[$0656]分岐
$C2/0653 JMP ($0532)[$C2:0BB9]   ;[$C2:0BB9]へジャンプ(レジスタをスタックに積まない)
$C2/0BB9 LDA $65    [$00:0565]   ;Aに[$00:0566][$00:0565]($FFFF)をロード
$C2/0BBB BPL $13    [$0BD0]      ;ネガティブフラグが立っていないとき[$0BD0]分岐
;ネガティブフラグON
$C2/0BBD LDA $44    [$00:0544]   ;Aに[$00:0545][$00:0544](現在のカーソル位置)をロード
$C2/0BBF CLC                     ;キャリーフラグクリア
$C2/0BC0 ADC $36    [$00:0536]   ;A + [$00:0537][$00:0536](初期値$0000)
$C2/0BC2 AND #$00FF              ;Aと$00FFで論理積
$C2/0BC5 STA $65    [$00:0565]   ;Aを[$00:0566][$00:0565]に書き込み
$C2/0BC7 LDA #$0200              ;Aに$0200をロード
$C2/0BCA JSR $4281  [$C2:4281]   ;[$C2:4281]へジャンプ

[$00:0566][$00:0565]のネガティブフラグ判定は、「Aボタンで既に何かを選択しているかどうか」である。
初期状態で$FFFFが入っており、Aボタンで何か選択していない状態である。
この時にAボタンを押すと、$C2/0BBD~の処理を行い、[$00:0545][$00:0544](カーソル位置)を[$00:0566][$00:0565]に上書きする。

続いて、交換先アイテム位置にカーソルを移動する。
[$00:0545][$00:0544](現在のカーソル位置)が更新されることになる。
この上でAボタンを押すと、交換元アイテムと交換先アイテムが交換されるが、それが以下処理である。

$C2/0651 BCS $03    [$0656]      ;キャリーフラグが立っているとき[$0656]分岐
$C2/0653 JMP ($0532)[$C2:0BB9]   ;[$C2:0BB9]へジャンプ(レジスタをスタックに積まない)
$C2/0BB9 LDA $65    [$00:0565]   ;Aに[$00:0566][$00:0565](交換元アイテム位置)をロード
$C2/0BBB BPL $13    [$0BD0]      ;ネガティブフラグが立っていないとき[$0BD0]分岐
;ネガティブフラグOFF
$C2/0BD0 LDA $44    [$00:0544]   ;Aに[$00:0545][$00:0544](現在のカーソル位置)をロード
$C2/0BD2 CLC                     ;キャリーフラグクリア
$C2/0BD3 ADC $36    [$00:0536]   ;A + [$00:0537][$00:0536](初期値$0000)
$C2/0BD5 AND #$00FF              ;Aと$00FFで論理積
$C2/0BD8 STA $67    [$00:0567]   ;A(現在のカーソル位置)を[$00:0568][$00:0567]に書き込み
$C2/0BDA LDA $000050[$00:0050]   ;Aに[$00:0051][$00:0050]をロード
$C2/0BDE AND #$000F              ;Aと$000Fで論理積
$C2/0BE1 CMP #$0004              ;Aと$0004を減算比較(ステータスレジスタ変更のみ)
$C2/0BE4 BEQ $4E    [$0C34]      ;ゼロフラグが立っているとき[$0C34]分岐
$C2/0BE6 CMP #$0005              ;Aと$0005を減算比較(ステータスレジスタ変更のみ)
$C2/0BE9 BEQ $44    [$0C2F]      ;ゼロフラグが立っているとき[$0C2F]分岐
$C2/0BEB LDA $67    [$00:0567]   ;Aに[$00:0568][$00:0567](現在のカーソル位置)をロード
$C2/0BED CMP $65    [$00:0565]   ;Aと[$00:0566][$00:0565](交換元アイテム位置)を減算比較
$C2/0BEF BEQ $6A    [$0C5B]      ;ゼロフラグが立っているとき[$0C5B]分岐
;ゼロフラグOFF(交換元と交換先のアイテム位置が同一ではない)
$C2/0BF1 LDX $65    [$00:0565]   ;Xに[$00:0566][$00:0565]をロード
$C2/0BF3 LDY $67    [$00:0567]   ;Yに[$00:0568][$00:0567]をロード
$C2/0BF5 SEP #$20                ;MフラグON Aレジスタは8bit幅
$C2/0BF7 LDA $8A00,x             ;Aに[$8A00,x](交換元アイテムID)をロード
$C2/0BFA XBA                     ;Aレジスタの上位バイトと下位バイトを交換
$C2/0BFB LDA $8A00,y             ;Aに[$8A00,y](交換先アイテムID)をロード
$C2/0BFE STA $8A00,x             ;Aを[$8A00,x]に書き込み
$C2/0C01 XBA                     ;Aレジスタの上位バイトと下位バイトを交換
$C2/0C02 STA $8A00,y             ;Aを[$8A00,y]に書き込み
$C2/0C05 LDA $8B00,x             ;Aに[$8B00,x](交換元アイテム個数)をロード
$C2/0C08 XBA                     ;Aレジスタの上位バイトと下位バイトを交換
$C2/0C09 LDA $8B00,y             ;Aに[$8B00,y](交換先アイテム個数)をロード
$C2/0C0C STA $8B00,x             ;Aを[$8B00,x]に書き込み
$C2/0C0F XBA                     ;Aレジスタの上位バイトと下位バイトを交換
$C2/0C10 STA $8B00,y             ;Aを[$8B00,y]に書き込み
$C2/0C13 REP #$20                ;Aを16bit幅に変更、Mフラグをクリア
$C2/0C15 JSR $4514  [$C2:4514]   ;[$C2:4514]へジャンプ

まず$C2/0BBB[$00:0566][$00:0565]のネガティブフラグ判定だが、先ほど、[$00:0566][$00:0565]には交換元アイテムの位置が入っており、上位バイトの[$00:0566]$00なので、ネガティブフラグが立たない。
よって、$C2/0BD0に進む。つまり、何かのアイテムが選択されている時の処理に進む。
続いて、[$00:0545][$00:0544](現在のカーソル位置)を[$00:0568][$00:0567]に書き込む。
[$00:0568][$00:0567]にはこれまで$FFFFが入っていたが、ここで交換先のアイテム位置が書き込まれたことになる。

$C2/0BDA~の[$00:0051][$00:0050]だが、メニュー画面を開いた時点で以下処理で$0003が入っており、持ち物欄でも変化しない。

$C0/08BA LDA #$03                ;Aに$03をロード
$C0/08BC STA $50    [$00:0050]   ;Aを[$00:0050]に書き込み
$C0/08BE JSR $0DCC  [$C0:0DCC]   ;[$C0:0DCC]へジャンプ

このため、$C2/0BEBまで処理が進む。
$C2/0BEBからは、[$00:0568][$00:0567][$00:0566][$00:0565]の減算比較だが、[$00:0568][$00:0567]は交換先アイテムの位置、[$00:0566][$00:0565]は交換元アイテムの位置が入っている。
$C2/0BEFでゼロフラグ判定をしているが、ここでゼロフラグが立つのは、交換先アイテムと交換元アイテムが同じ位置にある時のみである。
この場合は交換処理をする必要がないので分岐処理になる。
ゼロフラグが立たない時は、交換先アイテムと交換元アイテムが別の位置にある場合である。
よって、$C2/0BF1からが交換処理になる。

$C2/0BF1からは、

  • Xに交換元アイテムの位置[$00:0566][$00:0565]
  • Yに交換先アイテムの位置[$00:0568][$00:0567]

をロードし、まずA[$8A00,x]、つまり整頓用メモリアドレスのアイテムIDを格納してある[$7E:8Axx]をロードする。
$C2/0BFAXBAで、Aの上位バイトと下位バイトを交換するから、Aの上位バイトに交換元アイテムIDが入る。
更に、A[$8A00,y]、つまり[$7E:8Ayy](交換先アイテムID)をロードするので、Aの下位バイトに交換先アイテムIDが入る。
後は、再びXBAを使いつつ、

  • Aの下位バイト(交換先アイテムID)→[$8A00,x](交換元のアドレス)
  • Aの上位バイト(交換元アイテムID)→[$8A00,y](交換先のアドレス)

と処理して、アイテムIDを入れ替える。

$C2/0C05$C2/0C10は同じ処理をアイテム個数の[$8B00,x][$8B00,y]で行っている。
これで、交換元・交換先のアイテムIDとアイテム個数が入れ替えられた。
ジャンプ先の$C2/4514$C2/453Cは既に上で紹介した$7E:8A00$7E:8AFE, $7E:8B00$7E:8BFEを、$00:0B01$00:0BFF, $00:0C01$00:0CFFに書き戻すサブルーチンなので、紹介は省く。
交換したアイテムは2種類だけだが、その部分だけ書き戻しではなく、持ち物欄すべて書き戻しになる。



このページをシェアする

上へ