5.8. 王様解析

5.8.1. 解析
5.8.1.1. 王様共通処理サブルーチン
5.8.1.2. 冒険の書が使用済かチェックするサブルーチン
5.8.1.3. 冒険の書の名前文字列 ID を取得するサブルーチン
5.8.1.4. 冒険の書の勇者レベルを取得するサブルーチン
5.8.1.5. 次のレベルに必要な経験値を知らせる処理サブルーチン
5.8.1.6. 王様処理台詞用メッセージ ID 配列群

いろいろな国の城の王様・女王様に話すと、一言二言しゃべったあとにおなじみの処理に入る。 すなわち、パーティの各メンバーについて、次のレベルになるまでに必要な経験値を教えてから、 それまでのプレイ内容を冒険の書に記録するかどうかを問う処理だ。 本節ではその処理を解析する。

5.8.1. 解析

5.8.1.1. 王様共通処理サブルーチン

各国の王・女王に「はなす」と、まずはそれぞれに固有の台詞を言うが、 その後には全員同じく、レベルアップまでの残り経験値告知と、冒険の書記録の問い合わせからなる手続きを行う。 この共通した手続きを、ここでは王様共通処理サブルーチンと称する。

王様共通処理サブルーチンは $C3C07E に定義されている。 なお、このサブルーチンを呼び出す前に A レジスタに台詞セット ID をロードすることが事前条件となっている。 一例を挙げよう。

C3/C4BA:    08          PHP
C3/C4BB:    C230        REP #$30
C3/C4BD:    48          PHA
C3/C4BE:    DA          PHX
C3/C4BF:    5A          PHY
C3/C4C0:    8B          PHB
C3/C4C1:    F47E7E      PEA $7E7E
C3/C4C4:    AB          PLB
C3/C4C5:    AB          PLB
C3/C4C6:    8DA033      STA $33A0
C3/C4C9:    8CA233      STY $33A2
C3/C4CC:    A90000      LDA #$0000          1
C3/C4CF:    227EC0C3    JSR $C3C07E         2
C3/C4D3:    AB          PLB
C3/C4D4:    C230        REP #$30
C3/C4D6:    7A          PLY
C3/C4D7:    FA          PLX
C3/C4D8:    68          PLA
C3/C4D9:    28          PLP
C3/C4DA:    6B          RTL

1

$C3C07E 呼び出し直前に A レジスタにセットされている値が、人物の台詞を決める。

一連の処理では、台詞をウィンドウに表示するのに、 LDA addr,X(ここで X は上記 A の値と一致する)と、 台詞表示サブルーチン $C1A95A 呼び出しを組み合わせて実現している。 ここで、addr は王様共通処理サブルーチンの直後に定義されている メッセージ ID 各配列の配置アドレスだ。

2

$C3C07E に定義されている王様共通処理サブルーチンを呼び出す。

サブルーチン $C3C07E の実装は以下の通り。 紙面が煩雑になるのを避けるため、本筋の処理とは本質的に関係のない処理の説明は省く。

  • A <= #$0009 のときに限り A = 0 とする。 A レジスタの値は王様それぞれの台詞グループの ID だ。 X = A としておく。

  • パーティの各メンバーが次のレベルになるまでに必要な経験値を教えるために、 サブルーチン $C3C3E4 を呼び出す。

  • メッセージ ID を $C3C1E3,X からロードして、 汎用メッセージ表示サブルーチンを呼び出すことで 「そなたらの旅の成果をこの冒険の書に記録してもよいかな?」 系統の台詞を表示する。

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

    • キャンセルボタン or いいえ ⇒【冒険の書は更新しない】へ進む。

    • それ以外 ⇒【冒険の書番号を尋ねる】へ進む。

  • 【冒険の書番号を尋ねる】

    • メッセージ ID を $C3C1F7,X からロードして、 汎用メッセージ表示サブルーチンを呼び出すことで 「何番の冒険の書に書きとめるかの?」 系統の台詞を表示する。

    • 冒険の書リストウィンドウを表示して、プレイヤーの入力を待つ。

      • 冒険の書を選択した ⇒【冒険の書を選択した】へ進む。

      • それ以外 ⇒

        • メッセージ ID を $C3C229,X からロードして、 汎用メッセージ表示サブルーチンを呼び出すことで 「ではまたいつでも来るがよい。○○○○よ!」 系統の台詞を表示する。

        • 【終了】へ進む。

  • 【冒険の書は更新しない】

    • メッセージ ID を $C3C1ED,X からロードして、 汎用メッセージ表示サブルーチンを呼び出すことで 「では書きとめないでおこう」 系統の台詞を表示する。

    • 【ゲーム終了の意思を確認】へ進む。

  • 【冒険の書を選択した】

    選択した冒険の書 ID と $40AB すなわち現在プレイ中の冒険の書 ID を比較する。

    • 違うならば、【現在のものではない冒険の書を選択した】へ制御を進める。

    • 同じならば、次の処理【セーブ】へ制御を進める。

  • 【セーブ】

    シスターセーブと同様の処理をする。 すなわち、以下のコードを実行する。

    C3/C0FB:    ACA033      LDY $33A0
    C3/C0FE:    22CE2BC4    JSR $C42BCE         ■(RTL+1) 未解析サブルーチン
    C3/C102:    FD
    C3/C103:    ACA233      LDY $33A2
    C3/C106:    222C2CC4    JSR $C42C2C         ■(RTL+1) 未解析サブルーチン
    C3/C10A:    FD
    C3/C10B:    224E62C4    JSR $C4624E         ■(RTL+1) 未解析サブルーチン
    C3/C10F:    FF
    
  • 効果音 (ID: #$002B) を鳴らし、終わるまで待つ。

  • 【現在のものではない冒険の書を選択した】

    A レジスタにプレイヤーが選択した冒険の書 ID (0..2) がロード済みとなっている。

    • 選択した冒険の書が未使用かどうかをテストするため、 サブルーチン $C3C300 を呼び出す。

      • 未使用であれば【セーブ】に制御を移す。

    • 選択した冒険の書の識別用文字列 ID を取得するために サブルーチン $C3C31F を呼び出す。 そして $BE77 にセットする。

    • 選択した冒険の書の勇者レベルを取得するために サブルーチン $C3C332 を呼び出す。 そして $BE813 バイトサイズでセットする。

    • メッセージ ID を $C3C201,X からロードして、 汎用メッセージ表示サブルーチンを呼び出すことで 「すると○○○○ LV○○の記録は消えてしまうが?」 系統の台詞を表示する。

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

      • キャンセルボタン or いいえ ⇒【冒険の書番号を尋ねる】へ戻る。

      • それ以外 ⇒【セーブ】に制御を移す。

  • 【記録終了】

    • メッセージ ID を $C3C20B,X からロードして、 汎用メッセージ表示サブルーチンを呼び出すことで 「しかときろくしたぞよ。またすぐに旅立つつもりか?」 系統の台詞を表示する。

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

      • キャンセルボタン or いいえ ⇒【また会おう】へ進む。

      • それ以外 ⇒【終了】へ進む。

  • 【ゲーム終了の意思を確認】

    • メッセージ ID を $C3C20B,X からロードして、 汎用メッセージ表示サブルーチンを呼び出すことで 「また すぐに旅立つ つもりかの?」 系統の台詞を表示する。

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

      • キャンセルボタン or いいえ ⇒【さらに確認】へ進む。

      • それ以外 ⇒【終了】へ進む。

  • 【さらに確認】

    • メッセージ ID を $C3C21F,X からロードして、 汎用メッセージ表示サブルーチンを呼び出すことで 「旅の記録が前に書きとめたところまで戻ってしまうが?」 系統の台詞を表示する。

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

      • キャンセルボタン or いいえ ⇒【冒険の書番号を尋ねる】へ戻る。

      • それ以外 ⇒【また会おう】へ進む。

  • 【また会おう】

    • メッセージ ID を $C3C233,X からロードして、 汎用メッセージ表示サブルーチンを呼び出すことで 「ではしばし休むがよい! また会おう! ○○○○よ!」 系統の台詞を表示する。

    • JMP $C67B76 して画面暗転。

  • 【終了】

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

5.8.1.2. 冒険の書が使用済かチェックするサブルーチン

サブルーチン $C3C300A レジスタの値で示される冒険の書が既に使用されているかどうかを調べるものだ。

  • 【事前条件】

    A レジスタには調べたい冒険の書 ID がロード済み。 A == 0, 1, 2 のどれかである。

  • LDA $C3C319,X (where X == A * 2) により、A レジスタに 2 バイトの定数をロードする。 これはアドレス値だ。

  • $0000,X (where X == A) の値と 1 を比較する。

    • 等しい ⇒ Carry ビットをリセット

    • それ以外 ⇒ Carry ビットをセット

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

  • 【事後条件】

    冒険の書が未使用ならば Carry == 1; そうでなければ Carry == 0

小さなデータ領域 $C3C319 は以下の通りになっている。 つまり、それぞれの $7Exxxx に存在する 2 バイト値が、 それぞれの冒険の書の使用・未使用のフラグになっているのだ。

C3/C319:    6940  ; 冒険の書 1 が使用済ならば $7E4069 == 1
C3/C31B:    6B40  ; 冒険の書 2
C3/C31D:    6D40  ; 冒険の書 3

5.8.1.3. 冒険の書の名前文字列 ID を取得するサブルーチン

サブルーチン $C3C31FA レジスタの値で示される冒険の書の名前文字列 ID を取得する。 実装は以下の通り。

  • 【事前条件】

    A レジスタには調べたい冒険の書 ID がロード済み。 A == 0, 1, 2 のどれかである。

  • LDA $C3C32C,X (where X == A * 2) により、 A レジスタに 2 バイトの定数をロードする。 これはアドレス値だ。

  • $0000,X (where X == A) の値を A レジスタにロードする。

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

  • 【事後条件】

    A レジスタには冒険の書の名前文字列 ID がロードされている。

小さなデータ領域 $C3C32C は以下の通りになっている。 つまり、それぞれの $7Exxxx に存在する 2 バイト値が、 それぞれの冒険の書の名前文字列 ID だ。

C3/C32C:    7540  ; $7E4075 を意味する
C3/C32E:    7740  ; $7E4077
C3/C330:    7940  ; $7E4079

5.8.1.4. 冒険の書の勇者レベルを取得するサブルーチン

サブルーチン $C3C332A レジスタの値で示される冒険の書の勇者レベルを取得する。 実装は以下の通り。

  • 【事前条件】

    A レジスタには調べたい冒険の書 ID がロード済み。 A == 0, 1, 2 のどれかである。

  • LDA $C3C33F,X (where X == A * 2) により、 A レジスタに 2 バイトの定数をロードする。

  • $0000,X (where X == A) の値を A レジスタにロードする。

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

  • 【事後条件】

    A レジスタには冒険の書の勇者レベルがロードされている。

小さなデータ領域 $C3C33F は以下の通りになっている。 つまり、それぞれの $7Exxxx に存在する 2 バイト値が、 それぞれの冒険の書の勇者のレベルだ。

C3/C33F:    6F40  ; $7E406F を意味する
C3/C341:    7140  ; $7E4071
C3/C343:    7340  ; $7E4073

5.8.1.5. 次のレベルに必要な経験値を知らせる処理サブルーチン

王様共通処理の中で、この処理だけは個別にサブルーチン化されている。 サブルーチン $C3C3E4 の実装は以下の通り。

  • A <= #$0009 のときに限り A = 0 とする。 A レジスタの値は王様それぞれの台詞グループの ID だ。 さらに $74 にこの値をとっておく。

  • パーティの人数取得サブルーチン $C4297C を呼び出す。 Y レジスタに人数をロードする。

  • 【一人分の処理開始】

    • パーティメンバーの先頭から A 番目のキャラクターの現在のレベルを取得するために、 サブルーチン $C42FEB を呼び出す。

    • X = 現在のレベル + 1 とする。すなわち次のレベルだ。

    • キャラクターの次のレベルの経験値を取得するために、 サブルーチン $C43C07 を呼び出す。 呼び出し終了後、値が $703 バイトサイズでセットされている。

      • この呼び出し先によって Carry ビットがリセットされている場合、 【現在の経験値を見る】に進む。

    • メッセージ ID を $C3C23D,X (where X == $74) からロードして【台詞表示】に進む。 これは「○○○○はもう十分に強い!」 系統の台詞 ID を意味する。

  • 【現在の経験値を見る】

    • 3 バイトコピー代入処理として $BE81 = $70 する。すなわち、 キャラクターの次のレベルの経験値を $BE81 にセットする。

    • キャラクターの現在の経験値を調べるべく、 サブルーチン $C43B5F を呼び出す。 呼び出し先で $70 が現在の経験値で上書きされる。

    • $71$BE82 を比較する。 3 バイト値の上位 2 バイトの比較だ。

      • $71 == $BE82 ⇒ さらに $70$BE81 を比較する。

      • $71 > $BE82 ⇒【現在の経験値が多すぎ】に進む。

      • それ以外は【経験値の差を計算】に進む。

    • $70$BE81 を比較する。

      • $70 < $BE81 ⇒【経験値の差を計算】に進む。

      • それ以外 ⇒【現在の経験値が多すぎ】に進む。

  • 【経験値の差を計算】

    • $BE81 -= $70 の算術処理を 3 バイトサイズで行う。

    • メッセージ ID を $C3C1D9,X (where X == $74) からロードして【台詞表示】に進む。 これは「次のレベルになるにはあと○○○の経験が必要じゃ」 系統の台詞 ID を意味する。

  • 【現在の経験値が多すぎ】

    • メッセージ ID を $C3C247,X (where X == $74) からロードして【台詞表示】に進む。 これは「○○○○はわしにもわからぬ経験を積んだようじゃな」 系統の台詞 ID を意味する。

  • 【台詞表示】

    • メッセージ表示サブルーチン $C1A95A を呼び出す。

    • 次のキャラクターがいれば、$BE7D を 次のキャラクターにセットして、制御を【一人分の処理開始】に戻す。

  • 【終了】

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

5.8.1.6. 王様処理台詞用メッセージ ID 配列群

これまで述べてきた各処理中には、LDA addr,X によってメッセージ ID を参照する箇所がいくつかあった。 今後の解析作業用に、その一覧を以下にまとめる。 各 addr,X2 バイトサイズの値が 5 個からなる配列であり、 各 2 バイトの値は王様の台詞メッセージ ID だが、 ここでは X がゼロのときの台詞を記しておけば、作業には十分役立つだろう。

$C3C1D9,X

[CD][D6]王「[C0]が つぎのレベルに[AD]なるには あと[BB]の[AD]けいけんが 必要じゃ。[AF][AC]

$C3C1E3,X

[CD][D6]王「そなたらの 旅の せいかを[AD]この 冒険の書に[AD]きろくしても よいかな?[AC]

$C3C1ED,X

[CD][D6]王「そうか… では[AD]書きとめないでおこう。[AF][AC]

$C3C1F7,X

[CD][D6]王「では なん番の 冒険の書に[AD]書きとめるかの?[AC]

$C3C201,X

[CD][D6]王「すると [B2] LV[BB]の[AD]きろくは 消えてしまうが[AD]それでも いいかな?[AC]

$C3C20B,X

[CD][D6]王「しかと きろくしたぞよ。[AD]どうじゃ? また すぐに[AD]旅立つ つもりか?[AC]

$C3C215,X

[CD][D6]王「また すぐに[AD]旅立つ つもりかの?[AC]

$C3C21F,X

[CD][D6]王「なんと! きろくせずに[AD]休むというのか。[AF]...

$C3C229,X

[CD][D6]王「おや やめるのかね。[AD]では また いつでも 来るがよい。[AD][CB]よ![AC]

$C3C233,X

[CD][D6]王「では しばし 休むがよい![AD]また 会おう! [CB]よ![AC]

$C3C23D,X

[CD][D6]王「[C0]は[AD]もう じゅうぶんに 強い![AF][AC]

$C3C247,X

[CD][D6]王「[C0]は わしにも わからぬ[AD]けいけんを つんだようじゃな。[AF]...