4.9. ゴールド銀行解析

4.9.1. 解析
4.9.1.1. サブルーチン $C1F7D1 - 銀行処理

ここでは銀行の処理について述べる。 データ解析はないはずなので、処理の解読に焦点を置く。

4.9.1. 解析

いつものように GSD を利用して、 $C0CACA に Breakpoint をセット、銀行の受付嬢にはなす。 すると、銀行の処理実装のアドレスがわかる。 $C1F7D1 がそれである。 このサブルーチンを逆アセンブラでコードリストを抽出して、 いくつかの JSL の直後のコードを正しく修正したものを以下に記す。 長いのでキリのよいところで区切りながら進める。

4.9.1.1. サブルーチン $C1F7D1 - 銀行処理

4.9.1.1.1. メニュー決定まで

銀行の受付に話しかけてから、メニューウィンドウを終えるまでの処理である。

C1/F7D1:    08          PHP 
C1/F7D2:    C230        REP #$30
C1/F7D4:    48          PHA 
C1/F7D5:    DA          PHX 
C1/F7D6:    5A          PHY 
C1/F7D7:    8B          PHB 
C1/F7D8:    F47E7E      PEA $7E7E
C1/F7DB:    AB          PLB 
C1/F7DC:    AB          PLB 
C1/F7DD:    A90200      LDA #$0002          a = 0002h;
C1/F7E0:    223672C3    JSR $C37236         ■所持金ウィンドウ表示準備
C1/F7E4:    AF2C3D7E    LDA $7E3D2C
C1/F7E8:    290200      AND #$0002          // 初めての利用
C1/F7EB:    D012        BNE $F7FF           if($7E3D2C & 0002h = 0000h){
C1/F7ED:    221C2EC0    JSR $C02E1C             ■愛と信頼の ゴールド銀行へ ようこそ。[AD]皆さまの ~
C1/F7F1:    4719
C1/F7F3:    22502EC9    JSR $C92E50             ■$7E3D2C |= 0002h
C1/F7F7:    2C3D7E
C1/F7FA:    020000
C1/F7FD:    8006        BRA $F805               goto メニュー;
                                            }
C1/F7FF:    221C2EC0    JSR $C02E1C         ■愛と信頼の ゴールド銀行へ ようこそ。[AD][D3]さまは~
C1/F803:    4819
.label  ゴールド銀行::メニュー
C1/F805:    A92000      LDA #$0020          a = 0020h;
C1/F808:    223672C3    JSR $C37236         ■「あずける・ひきだす・やめる」表示&待ち
C1/F80C:    9006        BCC $F814           if(carry){
C1/F80E:    2228B7C3    JSR $C3B728             ■ウィンドウ消去
C1/F812:    8026        BRA $F83A               goto ありがとうございました;
                                            }
C1/F814:    C90200      CMP #$0002
C1/F817:    9009        BCC $F822           if(a > 0002h){
C1/F819:    CEB038      DEC $38B0               --$7E38B0;
C1/F81C:    2228B7C3    JSR $C3B728             ■ウィンドウ消去
C1/F820:    8018        BRA $F83A               goto ありがとうございました;
                                            }
C1/F822:    48          PHA 
C1/F823:    CEB038      DEC $38B0           --$7E38B0;
C1/F826:    2228B7C3    JSR $C3B728         ■ウィンドウ消去
C1/F82A:    68          PLA 
C1/F82B:    0A          ASL A
C1/F82C:    AA          TAX 
C1/F82D:    7C30F8      JMP ($F830,X)       ■処理へ
@end
.dataarea ゴールド銀行 メニュー処理ジャンプテーブル
C1/F830:    67F8  // あずける
C1/F832:    08F9  // ひきだす
@end

$7E3D2C#$02 の位のビットが 「銀行の受付に話しかけたことがあるかどうかフラグ」であることがわかる。 ゴールド銀行の受付に初めて話しかけたときに、 受付はゴールド銀行の宣伝文句(メッセージ ID: #$1947)を言うことになっていることがわかる。 また、その直後に同フラグをセットすることで、このメッセージは二度と見られなくなる。

メニューを「あずける」または「ひきだす」を選択した場合、 $C1F82D JMP 命令で然るべき処理へジャンプする。 ジャンプテーブルは $C1F830 に、 すなわちこの JMP のすぐ直後に定義されている。

4.9.1.1.2. あずける

「あずける」を選択してから、その処理が終わるまでの処理は以下の通りである。

.label ゴールド銀行::あずける
C1/F867:    22ED28C4    JSR $C428ED         ■$70 = $7E3EA5; 残高(一千単位)
C1/F86B:    70          // $C42797 LDA のアドレス
C1/F86C:    A570        LDA $70
C1/F86E:    C91027      CMP #$2710          // 2710h == 10000d
C1/F871:    9008        BCC $F87B           if($70 >= 2710h){
.label ゴールド銀行::預金オーバーフロー
C1/F873:    221C2EC0    JSR $C02E1C             ■お客さま 申しわけありませんが~
C1/F877:    4919
C1/F879:    80BF        BRA $F83A               goto ありがとうございました;
                                            }
C1/F87B:    221C2EC0    JSR $C02E1C         ■ご入金は 1000ゴールド単位で
C1/F87F:    4A19
C1/F881:    A90200      LDA #$0002
C1/F884:    8DE43A      STA $3AE4           $7E38E4 = 0002h;
C1/F887:    AEB038      LDX $38B0           x = $7E38B0;
C1/F88A:    224D2BC9    JSR $C92B4D         ■$7E38B4 構造体[16] らしいが意味不明
            00
            2000
            B438
            7E
            1600
C1/F896:    A92100      LDA #$0021          a = 0021h;
C1/F899:    221373C3    JSR $C37313         ■金額入力ウィンドウ表示&待ち
C1/F89D:    9007        BCC $F8A6           if(carry){
C1/F89F:    2228B7C3    JSR $C3B728             ■ウィンドウ消去
C1/F8A3:    828EFF      BRL $F834               goto キャンセル処理;
                                            }
C1/F8A6:    AD7A38      LDA $387A           // 入力金額チェック
C1/F8A9:    D00A        BNE $F8B5           if($7E387A == 0000h){
C1/F8AB:    CEB038      DEC $38B0               --$7E38B0;
C1/F8AE:    2228B7C3    JSR $C3B728             ■ウィンドウ消去
C1/F8B2:    827FFF      BRL $F834               goto キャンセル処理;
                                            }
C1/F8B5:    8590        STA $90             $90 = $7E387A;
C1/F8B7:    22BAF9C1    JSR $C1F9BA         ■$70 *= 03E8h; (1000d)
C1/F8BB:    A570        LDA $70
C1/F8BD:    8D7A38      STA $387A           $7E387A = $70;  (4 byte) // 残高をちゃんと 1000 倍
C1/F8C0:    8D2E5A      STA $5A2E           $7E5A2E = $70;  (4 byte) // 表示用アドレス
C1/F8C3:    A572        LDA $72
C1/F8C5:    8D7C38      STA $387C
C1/F8C8:    8D305A      STA $5A30
C1/F8CB:    2259EEC3    JSR $C3EE59         ●残高と入力金額との大小チェックのハズ
C1/F8CF:    9010        BCC $F8E1           if(carry){
C1/F8D1:    221C2EC0    JSR $C02E1C             ■しつれいですが[AD]お客さまは 今 それほど
C1/F8D5:    4B19
C1/F8D7:    CEB038      DEC $38B0               --$7E38B0;
C1/F8DA:    2228B7C3    JSR $C3B728             ■ウィンドウ消去
C1/F8DE:    8259FF      BRL $F83A               goto ありがとうございました;
                                            }
C1/F8E1:    221729C4    JSR $C42917         ■$90
C1/F8E5:    90
C1/F8E6:    9010        BCC $F8F8           if(10001 以上){
C1/F8E8:    221C2EC0    JSR $C02E1C             ■[BB]ゴールドですね。[AF][D5]
C1/F8EC:    4D19
C1/F8EE:    CEB038      DEC $38B0               --$7E38B0;
C1/F8F1:    2228B7C3    JSR $C3B728             ■ウィンドウ消去
C1/F8F5:    827BFF      BRL $F873               goto 預金オーバーフロー;
                                            }
C1/F8F8:    221C2EC0    JSR $C02E1C         ■[BB]ゴールドですね。[AD]では たしかに
C1/F8FC:    4C19
C1/F8FE:    CEB038      DEC $38B0           --$7E38B0;
C1/F901:    2228B7C3    JSR $C3B728         ■ウィンドウ消去
C1/F905:    8232FF      BRL $F83A           goto ありがとうございました;
@end

処理の要点は以下の通りである。

  • $7E3EA3 に所持金が格納されている。

  • $7E3EA5 に預金残高(の一千分の一)が格納されている。

  • 預金額が 10,000,000 ゴールドの場合、預金を断られる。

  • $7E387A に入力金額(の一千分の一)が格納されている。

  • $7E5A2E に金額を格納するのは、 画面下メッセージウィンドウに数値を表示するのに必要であるから。

  • 所持金を越える金額を預金しようとすると、銀行員からやんわりと指摘される。 そして全処理終了扱いになる。

  • 残高が 10,000,000 ゴールドを越えるような預金は受け付けない。 そして全処理終了扱いになる。

4.9.1.1.3. ひきだす

「ひきだす」を選択してから、その処理が終わるまでの処理は以下の通りである。

.label ゴールド銀行::ひきだす
C1/F908:    22ED28C4    JSR $C428ED         ■$70 = $7E3EA5; 残高(一千単位)
C1/F90C:    70
C1/F90D:    A570        LDA $70
C1/F90F:    8D3E30      STA $303E           $7E303E = $70;
C1/F912:    D009        BNE $F91D           if($70 == 0000h){
C1/F914:    221C2EC0    JSR $C02E1C             ■これは ごじょうだんを。
C1/F918:    4E19
C1/F91A:    821DFF      BRL $F83A               goto ありがとうございました;
                                            }
C1/F91D:    22BAF9C1    JSR $C1F9BA         ■$70 *= 03E8h; (1000d)
C1/F921:    A570        LDA $70
C1/F923:    8D2E5A      STA $5A2E
C1/F926:    A572        LDA $72             // 表示用アドレス
C1/F928:    8D305A      STA $5A30           $7E5A2E = $70;  (4 byte)
.label ゴールド銀行::いくら引き出す?
C1/F92B:    221C2EC0    JSR $C02E1C         ■現在 [BB]ゴールド[AD]お預かりしていますが
C1/F92F:    4F19
C1/F931:    A90200      LDA #$0002
C1/F934:    8DE43A      STA $3AE4           $7E3AE4 = 0002h;
C1/F937:    AEB038      LDX $38B0           x = $7E38B0;
C1/F93A:    224D2BC9    JSR $C92B4D         ■$7E38B4 構造体[16] らしいが意味不明
            00
            2000
            B438
            7E
            1600
C1/F946:    A92100      LDA #$0021          a = 0021h;
C1/F949:    221373C3    JSR $C37313         ■金額入力ウィンドウ表示&待ち
C1/F94D:    9007        BCC $F956           if(キャンセル){
C1/F94F:    2228B7C3    JSR $C3B728             ■ウィンドウ消去
C1/F953:    82DEFE      BRL $F834               goto キャンセル処理;
                                            }
C1/F956:    AD7A38      LDA $387A           // ゼロを入力したか
C1/F959:    D00A        BNE $F965           if($7E387A == 0000h){
C1/F95B:    CEB038      DEC $38B0               --$7E38B0;
C1/F95E:    2228B7C3    JSR $C3B728             ■ウィンドウ消去
C1/F962:    82CFFE      BRL $F834               goto キャンセル処理;
                                            }
C1/F965:    CD3E30      CMP $303E
C1/F968:    9012        BCC $F97C           // 過剰な引き出しを試みたか
C1/F96A:    F010        BEQ $F97C           if($7E387A > $7E303E){
C1/F96C:    221C2EC0    JSR $C02E1C             ■そんなに たくさん[AD]お預かりしておりませんが
C1/F970:    5019
C1/F972:    CEB038      DEC $38B0               --$7E38B0;
C1/F975:    2228B7C3    JSR $C3B728             ■ウィンドウ消去
C1/F979:    82AFFF      BRL $F92B               goto いくら引き出す?;
                                            }
C1/F97C:    22E027C4    JSR $C427E0         ●$70
C1/F980:    70
C1/F981:    22DAF9C1    JSR $C1F9DA         ●数値計算のみ
C1/F985:    A570        LDA $70
C1/F987:    18          CLC 
C1/F988:    6D7A38      ADC $387A           a = $70 + $7E387A;  // 所持金+指定金額
C1/F98B:    C9E803      CMP #$03E8
C1/F98E:    9010        BCC $F9A0           if(a >= 03E8h){  // >= 1000d
C1/F990:    221C2EC0    JSR $C02E1C             ■お客さまは そんなに たくさん[AD]おもちに
C1/F994:    5119
C1/F996:    CEB038      DEC $38B0               --$7E38B0;
C1/F999:    2228B7C3    JSR $C3B728             ■ウィンドウ消去
C1/F99D:    828BFF      BRL $F92B               goto いくら引き出す?;
                                            }
C1/F9A0:    AD7A38      LDA $387A
C1/F9A3:    8570        STA $70             $70 = $7E387A;  // 入力金額 (/ 1000d)
C1/F9A5:    226A29C4    JSR $C4296A         ●所持金と残高を同時更新
C1/F9A9:    70
C1/F9AA:    221C2EC0    JSR $C02E1C         ■しょうちいたしました。
C1/F9AE:    5219
C1/F9B0:    CEB038      DEC $38B0           --$7E38B0;
C1/F9B3:    2228B7C3    JSR $C3B728         ■ウィンドウ消去
C1/F9B7:    8280FE      BRL $F83A           goto ありがとうございました;
@end

処理の要点は以下の通りである。

  • 残高ゼロにもかかわらず「ひきだす」を選択した場合、 銀行員から「ご冗談を」といわれてしまう。 そして全処理終了扱いになる。

  • 引出金額にゼロを入力した場合、「ひきだす」処理が取り消し扱いになる。

  • 残高を越える金額を引き出そうとした場合、 銀行員から「そんなに預かっていない」と言われる。 そして再度引出金額を問われる。

  • 引出金額と所持金の和が 1,000,000 ゴールド以上になる場合、 銀行員から「そんなにたくさん持てない」と言われる。 そして再度引出金額を問われる。

4.9.1.1.4. 取り消し

銀行処理の色々なところからここへ来ることができる。 銀行員のセリフの後、終了処理が走る。

.label ゴールド銀行::キャンセル処理
C1/F834:    221C2EC0    JSR $C02E1C         ■おやめに なるのですね。
C1/F838:    5319
4.9.1.1.5. 終了

銀行処理の終了である。 プレイヤーに取引直後の所持金と、預金残高の両方を確認させる。

.label ゴールド銀行::ありがとうございました
C1/F83A:    A90300      LDA #$0003          a = 0003h;
C1/F83D:    223672C3    JSR $C37236         ■所持金ウィンドウ表示
C1/F841:    CEB038      DEC $38B0           --$7E38B0;
C1/F844:    22ED28C4    JSR $C428ED         ■$70 = $7E3EA5; 残高(一千単位)
C1/F848:    70
C1/F849:    A570        LDA $70             a = $70;
C1/F84B:    22BAF9C1    JSR $C1F9BA         ■$70 *= 03E8h; (1000d)
C1/F84F:    A570        LDA $70
C1/F851:    8D2E5A      STA $5A2E
C1/F854:    A572        LDA $72             // 表示用アドレス
C1/F856:    8D305A      STA $5A30           $7E5A2E = $70; (4 byte)
C1/F859:    221C2EC0    JSR $C02E1C         ■現在[BB]ゴールド[AD]お預かりしています
C1/F85D:    5519
C1/F85F:    AB          PLB 
C1/F860:    C230        REP #$30
C1/F862:    7A          PLY 
C1/F863:    FA          PLX 
C1/F864:    68          PLA 
C1/F865:    28          PLP 
C1/F866:    6B          RTL
@end