5.21. 格闘場解析

5.21.1. 解析
5.21.1.1. 格闘場共通処理サブルーチン
5.21.1.2. 賭け金計算サブルーチン

本節は、格闘場の胴元の共通処理サブルーチンを解析する。

5.21.1. 解析

世界各地の格闘場受付(胴元)に「はなす」と呼び出されるサブルーチンは共通して $C3EE64 を呼び出す。

サブルーチンでは、胴元の話す台詞を、 メッセージ ID 2 バイト 値を引数として渡すサブルーチン $C1A92E でウィンドウに表示する。 逆アセンブルコードを解読する際には、ここを手掛かりとして処理を読み進めることができる。

5.21.1.1. 格闘場共通処理サブルーチン

サブルーチン $C3EE64 では、 パーティが受付に話しかけてから話し終わるまでの処理を実装する。 格闘場の処理の本筋とは外れた処理コードを排除して、受付男処理のアウトラインを示す。

  • A = $337A

  • 賭け金計算サブルーチンを呼び出す。

  • $3376 = 掛札の金額

  • メッセージ ID #$09BB の台詞を表示する。 「かけふだは一枚○○ゴールドだ。買うかい?」のような文言である。

  • はい・いいえウィンドウを表示して、プレイヤーの入力を待つ。

    • キャンセルボタン or いいえ ⇒【買わない】へ進む。

    • それ以外 ⇒ 次へ進む。

  • X レジスタと A レジスタに 0 と 賭け金をそれぞれロードしてから 所持金変更サブルーチン $C45B66 を呼び出し、 パーティの所持金から賭け金を徴収することを試みる。

    • 失敗した ⇒【所持金不足】へ進む。

    • それ以外は(所持金から賭け金を徴収された状態で)次へ進む。

  • 出場モンスターリストをウィンドウに表示する。 プレイヤーの入力を待つ。

    • キャンセルボタン抜け ⇒【途中でキャンセル】へ進む。

    • それ以外 ⇒ 次へ進む。

  • $3374 = 選択したモンスターが何番目か (0..)

  • ビットセット汎用サブルーチン $C902E9 を呼び出すことで、 $7E2011 & #$000C 部分に選択番号を詰め込む。

  • $BE71 = 選択したモンスターのモンスター構造体 ID として、予想モンスターの名前を調べるサブルーチン $C3F022 を呼び出す。 これは直後の台詞表示にモンスター名文字列を含むためである。

  • ビットセット汎用サブルーチン $C902E9 を呼び出すことで、 $7E2011 & #$0040 ビットを立てる

  • メッセージ ID #$09BE の台詞を表示する。 「毎度ありい! スタジアムへ行っておくれ」のような文言である。

  • 意味不明のスタック値直接操作コードが走る。 この時点での $08,S は、サブルーチン呼び出し直後の PHP 命令でスタックしたものである。

    C3/EEE2:    09A308      ORA #$08A3
    C3/EEE5:    090100      ORA #$0001
    C3/EEE8:    8308        STA $08,S
    
  • 【終了】へ進む。

  • 【所持金不足】

    • メッセージ ID #$09BF の台詞を表示する。 「お金が足りないみたいだよ」のような文言である。

    • 【また来てくれよな】へ進む。

  • 【途中でキャンセル】

    • X レジスタと A レジスタに 0 と 賭け金をそれぞれロードしてから 所持金変更サブルーチン $C45B1A を呼び出し、 パーティの所持金を更新することを試みる。

  • 【買わない】

    • メッセージ ID #$09BC の台詞を表示する。 「なんだやめるのか」のような文言である。

    • 次の【また来てくれよな】へ進む。

  • 【また来てくれよな】

    • メッセージ ID #$09BD の台詞を表示する。 「それじゃまた来てくれよな」のような文言である。

    • スタック上のアドレスにある値 $08,S (サブルーチン呼び出し直後の PHP 命令で退避しておいた値)にマスク #$FFFE をかける。 当サブルーチン呼び出し元に制御を戻したときに、 Carry ビットがリセットされている (CLC) 状態にするのが目的である。

  • 【終了】

    • サブルーチン呼び出し元に制御を戻す。

最初唐突に参照される $337A が奇異に思えるが、 これはマッチメイク処理を終えていることが事前条件になっているから問題ない。 勇者のレベルがこのアドレスに既に格納されていると考えればよい。

$7E2011 は戦闘時のコンテキストで参照されることで有名なアドレスだが、 このサブルーチンの解読から、一部のビットが格闘場処理のために機能していることが読み取れる。 例えば、$7E2011 & #$0040 ビットが立っていることは、 その戦闘が格闘場モードであることと同値だ。

余計なお世話だが、所持金から代金を徴収するタイミングが尚早な印象を受けた。 キャンセルが発生したときに、わざわざ所持金を元に戻している。 徴収は「毎度あり」すなわち購入成功確定と同時でよいのではなかろうか。

5.21.1.2. 賭け金計算サブルーチン

サブルーチン $EF29A レジスタの値を 10 倍にして $BE813 バイト長でセットするだけの仕事をする。 この値が格闘場での賭け金となる。 $BE81 はメッセージ表示用サブルーチンが参照する値を格納するアドレスである。 短いサブルーチンであるので、全コードを以下に載せる。

C3/EF29:    0A          ASL A
C3/EF2A:    48          PHA            1
C3/EF2B:    0A          ASL A
C3/EF2C:    0A          ASL A          2
C3/EF2D:    6301        ADC $01,S      3
C3/EF2F:    9C82BE      STZ $BE82
C3/EF32:    8D81BE      STA $BE81
C3/EF35:    FA          PLX 
C3/EF36:    60          RTS

1

A * 2 をスタックにプッシュ(倍プッシュ)する。

2

この時点での A の値は、サブルーチン開始直後の 8 倍になっている。

3

A にスタックの値を加算する。 これで A はサブルーチン開始直後の 10 倍になっている。

X レジスタに呼び出し直後の A レジスタの値を 2 倍したものがロードされることになるが、特に深い意味はない。