5.14. ルイーダの酒場解析

5.14.1. 解析
5.14.1.1. ルイーダの酒場共通処理サブルーチン
5.14.1.2. 「なかまをあずける」処理サブルーチン
5.14.1.3. パーティに生きている人が二人以上いるか調べるサブルーチン
5.14.1.4. 「なかまをよびだす」処理サブルーチン
5.14.1.5. 「めいぼをみる」処理サブルーチン
5.14.1.6. 習得呪文リスト作成サブルーチン
5.14.1.7. 移動時呪文リスト作成サブルーチン
5.14.1.8. アイテムをふくろに
5.14.2. データ

本節ではルイーダの酒場での定型処理を解析する。 つまり、パーティーにいる仲間キャラクターを酒場から呼び出したり、 逆に預けたり、どんなキャラクターが酒場にいるのかを調べたりする処理を見る。

5.14.1. 解析

ゲーム開始時直後の状態や、バラモスを征伐してきてアリアハン王に報告する前などの、特定のイベント中でなければ、 酒場の女主人ルイーダに「はなす」とすぐにサブルーチン $C3D760 が呼ばれる。 ここから処理を辿ることにする。 このサブルーチンと、その補助サブルーチン内の台詞表示は サブルーチンとして $C1A92E を、 ナレーション系のメッセージ表示にはサブルーチン $C1A8D4 がそれぞれ用いられているようなので、 それを手掛かりに逆アセンブルコードを読み解いていくのが基本だ。

5.14.1.1. ルイーダの酒場共通処理サブルーチン

サブルーチン $C3D760 が、ルイーダの酒場での通常処理を実装している。

  • 台詞「ここはルイーダの店~」(ID: #$0AC5) を表示する。

  • 【メニュー表示】

    「なかまをよびだす・なかまをあずける・めいぼをみる」ウィンドウを表示し、 プレイヤーの入力を待つ。

    • キャンセルボタン抜け⇒【またいらしてね】へ制御をスキップする。

    • なかまをあずける⇒【なかまをあずける】へ制御をスキップする。

    • なかまをよびだす⇒【なかまをよびだす】へ制御をスキップする。

    • めいぼをみる⇒【めいぼをみる】へ制御をスキップする。

  • 【またいらしてね】

    • 台詞「じゃまたいらしてね」(ID: #$0ADA) を表示する。

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

  • 【なかまをあずける】

  • 【なかまをよびだす】

  • 【めいぼをみる】

  • 【ほかにご用は】

    • 台詞「ほかに ご用は?」(ID: #$0AD9) を表示する。

    • 【メニュー表示】へ制御をスキップする。

メニューウィンドウを表示して、プレイヤーの選択項目に従って処理を振り分けるというのが、 このサブルーチンの役割のようだ。

5.14.1.2. 「なかまをあずける」処理サブルーチン

サブルーチン $D7BB は「なかまをあずける」を選択したら呼び出すサブルーチンだ。

  • キャラクター人数カウントサブルーチン $C4297C 呼び出しにより、 パーティの人数を取得 (A) する。

    • A == 1 のとき、台詞「あずけるって…… だれを?」(ID: #$0AC6) を表示する。 そのあと、サブルーチン呼び出し元に制御を戻す。

  • 【だれを】

    • 台詞「だれを おあずかりすれば いいの?」(ID: #$0AC8) を表示する。

    • だれをウィンドウを表示して、プレイヤーの入力を待つ

      • キャンセル抜け⇒【キャンセル 1】へ制御をスキップする。

    • 選択したキャラクター (A) の登録インデックスを得る (X) ため、 サブルーチン $C42F5E を呼び出す。

    • 選択したキャラクター (A) が主人公か否かをテストするべく、 サブルーチン $C42DA1 を呼び出す。

      • 主人公ではなかったら【テスト後】へ制御をスキップする。

    • サブルーチン $CC8C5A を呼び出して、バラモスを倒していることと、 ゾーマを倒していること (($3546 & 0004h) && ($3545 & 0004h)) をテストする。

      • 両方のビットがセットされていれば【テスト後】へ制御をスキップする。

      • どちらかのビットがゼロであれば、 台詞「○○○○さんがいなくなったら旅の指揮を執る人が~」(ID: #$0AC9) を表示する。 そのあと、サブルーチン呼び出し元に制御を戻す。

  • 【キャンセル 1】

    • 台詞「あら おやめになるのね」(ID: #$0AD8) を表示する。

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

  • 【死人だけ】

    • 台詞「死んでるひと ばかりで旅には 出られなくてよ」(ID: #$0AC7) を表示する。

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

  • 【テスト後】

    • 生死判定サブルーチン $C43F87 を呼び出し、 キャラクター (A) の生死を表現するデータを取得 (A) する。

      • キャラクターが死んでいれば (A & #$0010) 【死んでいるキャラクターを預けようとする】へ制御をスキップする。

    • サブルーチン $D8C8 を呼び出し、 パーティに生きている人が二人以上いるかをテストする。

      • テストが失敗した場合は【死人だけ】に制御を移す。

    • 台詞「○○○○さんをお預かりすればいいのね?」(ID: #$0ACD) を表示する。

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

      • キャンセル抜けまたは「いいえ」と答えた場合は【キャンセル 1】に制御を移す。

    • 台詞「じゃあ○○○○さん。しばらくお休みだわよ」(ID: #$0ACE) を表示する。

  • 【装備品を袋に】

    • 台詞「装備しているもの以外はそのふくろに~」(ID: #$0ACF) を表示する。

    • フラグテストサブルーチン $C909AE を呼び出し、 $7E353E の最下位ビットから #$000F ビット目に位置するビット をテストする。

      • ビットがゼロの場合、

        • 台詞「こうしておかないと大切なものを~」(ID: #$0AD0) を表示する。

        • フラグセットサブルーチン $C908F0 を呼び出し、同ビットをセットする。

    • サブルーチン $C3DA97 を呼び出し、アイテム移動を行う。

    • サブルーチン $C42A6D を呼び出し、 キャラクターのデータ格納アドレス配列 ($36E8,X) を更新する。

    • TODO $C3BD64

    • キャラクター人数カウントサブルーチン $C4297C 呼び出しにより、 パーティの人数を取得 (A) する。

      • A < 2 ならば、 サブルーチン呼び出し元に制御を戻す。

    • 台詞「ほかにも誰かお預かりしましょうか」(ID: #$0AD1) を表示する。

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

      • キャンセル抜けまたは「いいえ」と答えた場合は サブルーチン呼び出し元に制御を戻す。

    • 【だれを】へ制御を移す。

  • 【死んでいるキャラクターを預けようとする】

    • 台詞「まあ! ○○○○さんをそんな姿のまま~」(ID: #$0ACA) を表示する。

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

      • キャンセル抜けまたは「いいえ」と答えた場合は 【ルイーダに諭される】へ制御を移す。

    • 台詞「それならしかたないわね」(ID: #$0ACB) を表示する。

    • 【装備品を袋に】へ制御を移す。

  • 【ルイーダに諭される】

    • 台詞「だったら助けてあげたほうが~」(ID: #$0ACC) を表示する。

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

5.14.1.3. パーティに生きている人が二人以上いるか調べるサブルーチン

サブルーチン $D8C8 は(生きている)メンバーを預ける直前のパーティにおいて、 生きているメンバーが二人以上いるか否かを調べて、Carry ビットを更新する。

  • キャラクター人数カウントサブルーチン $C4297C 呼び出しにより、 パーティの人数を取得 (X) する。

  • Y = 0 とし、これを「生きているメンバーの人数カウンター」とする。

  • 【for-each X in X - 1 .. 0】

    • 死に状態テストサブルーチン $C43F87 呼び出しにより、 パーティキャラクター (X) が死んでいるかどうかのビットを含む値を取得 (A) する。 生きているときに限り、Y をインクリメントする。

  • Carry ビットを条件 Y >= 2 でセットする。

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

  • 【事後条件】

    • パーティで生きているメンバー人数が 2 以上のときに限り Carry ビットがセット。

5.14.1.4. 「なかまをよびだす」処理サブルーチン

サブルーチン $D8E8 は「なかまをよびだす」を選択したら呼び出すサブルーチンだ。

  • キャラクター人数カウントサブルーチン $C4297C 呼び出しにより、 パーティの人数を取得 (A) する。

    • A == 4 のとき【既に 4 人パーティ】に制御を戻す。

  • キャラクター人数カウントサブルーチン $C4297C 呼び出しにより、 酒場にいる仲間の人数を取得 (A) する。

    • A == 0 のとき【酒場に誰もいない】に制御を戻す。

  • 【誰を呼ぶ】

    • 台詞「だれをお呼びしましょうか?」(ID: #$0AD4) を表示する。

    • 「だれを」ウィンドウを表示して、プレイヤーの入力を待つ。

      • キャンセル抜け⇒【キャンセル】へ制御をスキップする。

  • 選択したキャラクター (A) の登録インデックスを得る (X) ため、 サブルーチン $C42F5E を呼び出す。

  • $BE77 = X とする(次の台詞が含む名前を表示するため)。

  • 台詞「○○○○さんを 仲間にくわえるのね」(ID: #$0AD5) を表示する。

  • メッセージ「○○○○が 仲間に くわわった」(ID: #$0ADB) を表示する。

  • サブルーチン $C42A6D を呼び出し、 キャラクターのデータ格納アドレス配列 ($36E8,X) を更新する。

  • TODO $C3BD64

  • キャラクター人数カウントサブルーチン $C4297C 呼び出しにより、 パーティの人数を取得 (A) する。

    • A == 4 のとき【終了】へ制御をスキップする。

  • キャラクター人数カウントサブルーチン $C4297C 呼び出しにより、 酒場にいる仲間の人数を取得 (A) する。

    • A == 0 のとき【終了】へ制御をスキップする。

  • 台詞「他にも誰か~」(ID: #$0AD6) を表示する。

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

    • キャンセル抜け⇒【終了】へ制御を移す。

    • 「はい」⇒【誰を呼ぶ】へ制御を移す。

  • 【終了】

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

  • 【既に 4 人パーティ】

    • 台詞「そんなにぞろぞろお仲間がいるのに?」(ID: #$0AD2) を表示する。

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

  • 【酒場に誰もいない】

    • 台詞「でもお店にはあなたの仲間にできるような人は~」(ID: #$0AD3) を表示する。

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

5.14.1.5. 「めいぼをみる」処理サブルーチン

サブルーチン $D983 は「めいぼをみる」を選択したら呼び出すサブルーチンだ。 ウィンドウの表示が主な処理だ。 処理の概略は以下のようになっている。

  • キャラクター人数カウントサブルーチン $C4297C 呼び出しにより、 酒場にいる仲間の人数を取得 (A) する。

    • A == 0 のとき【酒場に誰もいない】に制御を戻す。

  • 【だれを】

    • 「だれを」ウィンドウと、その中のカーソルが指すキャラクターの「つよさ」ウィンドウを、 画面左側と右側にそれぞれ表示する。

      • キャラクターを選択⇒【呪文リスト開始】

      • キャンセル抜け⇒【終了】

  • 【酒場に誰もいない】

    • 台詞「お仲間はひとりもおあずかりしてなくてよ」(ID: #$0AD7) を表示する。

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

  • 【呪文リスト開始】

    • キャラクター ID を憶えておく。$33B8 = $33D6 = A

    • X = 5 としてからサブルーチン $DA75 を呼び出し、 対象キャラクターの魔法使い系統の習得呪文リストを作成する。

    • $3398 = (魔法使い系統の戦闘時用習得呪文個数 | 魔法使い系統の移動時用習得呪文個数)

    • X = 6 としてからサブルーチン $DA75 を呼び出し、 対象キャラクターの僧侶系統の習得呪文リストを作成する。

    • $339A = (僧侶系統の戦闘時用習得呪文個数 | 僧侶系統の移動時用習得呪文個数)

    • X = 7 としてからサブルーチン $DA89 を呼び出し、 対象キャラクターの魔法使い・僧侶系統以外の習得呪文リストを作成する。

    • $339C = (その他戦闘時用習得呪文個数 | その他移動時用習得呪文個数)

    • 職業 ID 取得サブルーチン $C46951 を呼び出し、キャラクターの職業 (A) を得る。

      • A != 8 ⇒【呪文リスト魔法使い】へスキップ。

    • X = 3 としてからサブルーチン $DA75 を呼び出し、 対象キャラクターの勇者系統の習得呪文リストを作成する。

    • $3396 = (勇者系統の戦闘時用習得呪文個数 | 勇者系統の移動時用習得呪文個数)

  • 【呪文リスト勇者】

    • 勇者呪文習得個数 ($3396) がゼロならば、【呪文リスト魔法使い】へスキップする。

    • 勇者呪文リストを表示して、プレイヤーの入力を待つ。

      • キャンセル抜け⇒【だれを】へ戻る。

      • キャンセル抜けでない⇒【終了】へスキップする。

  • 【呪文リスト魔法使い】

    • 魔法使い呪文習得個数 ($3398) がゼロならば、【呪文リスト僧侶】へスキップする。

    • 魔法使い呪文リストを表示して、プレイヤーの入力を待つ。

      • キャンセル抜け⇒【だれを】へ戻る。

      • キャンセル抜けでない⇒

        • 僧侶呪文習得個数 ($339A) がゼロでなければ、 効果音 (ID: #$003D) を鳴らす。

        • その他呪文習得個数 ($339C) がゼロでなければ、 【呪文リストその他】へスキップする。

    • 次へ。

  • 【呪文リスト僧侶】

    • 僧侶呪文習得個数 ($339A) がゼロならば、【呪文リストその他】へスキップする。

    • 僧侶呪文リストを表示して、プレイヤーの入力を待つ。

      • キャンセル抜け⇒

        • 魔法使い習得呪文個数がゼロでなければ、【呪文リスト魔法使い】へ戻る。

        • それ以外は【だれを】へ戻る。

      • キャンセル抜けでない⇒

        • その他呪文習得個数 ($339C) がゼロでなければ、効果音 (ID: #$003D) を鳴らす。

    • 次へ。

  • 【呪文リストその他】

    • その他呪文習得個数 ($339C) がゼロならば、【終了】へスキップする。

    • 盗賊・商人・遊び人習得移動時呪文リストを表示して、プレイヤーの入力を待つ。

      • キャンセル抜けでなければ、【終了】へスキップする。

      • 僧侶習得呪文個数がゼロでなければ、【呪文リスト僧侶】へ戻る。

      • 魔法使い習得呪文個数がゼロでなければ、【呪文リスト魔法使い】へ戻る。

      • それ以外は【だれを】へ戻る。

  • 【終了】

    • サブルーチン $C32413 を呼び出すことで、 プレイヤーの最近の入力 ($33B6) をチェックする。

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

5.14.1.6. 習得呪文リスト作成サブルーチン

サブルーチン $DA75 は、キャラクターと職業系統を指定して、 その習得呪文リストを作成する。

  • 【事前条件】

    • A == キャラクター ID

    • X == 職業 ID

  • 移動時呪文リスト作成サブルーチンを呼び出す。

  • 習得呪文リスト作成サブルーチン $C45796 を呼び出す。 これは、キャラクターの習得呪文ビットを見て、 $C415B7 構造体から呪文名をある配列にセットする、 というような働きをする。

  • 前者の呪文個数と、後者の呪文個数を ORA する

  • 【事後条件】

    • A == 戦闘用習得呪文の個数 | 移動用習得呪文の個数

5.14.1.7. 移動時呪文リスト作成サブルーチン

サブルーチン $DA89 は、キャラクターと職業系統を指定して、 その移動時における習得呪文リストを作成する。

  • 【事前条件】

    • A == キャラクター ID

    • X == 職業 ID

  • 習得呪文リスト作成サブルーチン $C456BC を呼び出す。 これは、キャラクターの習得呪文ビットを見て、 $C41480 構造体から呪文名をある配列にセットする、 というような働きをする。

  • 【事後条件】

    • Y == 習得呪文の個数

5.14.1.8. アイテムをふくろに

サブルーチン $C3DA97 は、キャラクターの装備品でない所持品をふくろに入れる処理だ。

  • サブルーチン $C446A4 呼び出しにより、 パーティキャラクター ($78) のすべての所持品個数を取得 ($7A) する。

  • サブルーチン $C446D6 呼び出しにより、 パーティキャラクター ($78) のすべての所持品個数を取得 (X) する。

  • 【for-each Y in $7A .. X

    • サブルーチン $C4487F 呼び出しにより、 パーティキャラクター ($78) の Y 番目のアイテムを所持品から削除し、 そのアイテムのアイテム構造体 ID を A にロードする。

    • サブルーチン $C45399 呼び出しにより、 ふくろの中にあるアイテム (A) を一個増やす。

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

5.14.2. データ

移動時呪文のリスト処理に関係する $C41480 構造体と、 戦闘時呪文のリスト処理に関係する $C415B7 構造体を表にしたいが、 構造体の解析を含め、現在調査中。