DQ3 「みのまもり」を導入する6+登録所の性格決定

今回は身の守りを追加することで登録所の性格決定にどう影響が出るのかについて、今まで解析をしていなかったので真面目にコードを読みながら変更するべき点を調べていくことにします。

  • SR: $03DE95 登録時仲間性格決定?
03DE95 PHP Push P Flag
03DE96 REP #$30 m=off(A/M:16b), x=off(X/Y:16b)
03DE98 PHA Push A
03DE99 PHX Push X
03DE9A PHY Push Y
03DE9B PHB Push DB
03DE9C PEA #$7E7E Push #$7E7E
03DE9F PLB Pull DB
03DEA0 PLB Pull DB
03DEA1 STA $2BBC $7E2BBC=A
03DEA4 STA $7A $00007A=A
03DEA6 JSL $046951 SR: $046951 引数:1#$06 引数:2#$7A 引数:3#$FF 職業ID取得
03DEAD STA $2BB8 $7E2BB8=A
03DEB0 JSL $042E19 SR: $042E19 引数:1#$06 引数:2#$7A 引数:3#$FF 性別取得
03DEB7 STA $2BBA $7E2BBA=A
03DEBA STA $4054 $7E4054=A
03DEBD JSL $042FEB SR: $042FEB 引数:1#$06 引数:2#$7A 引数:3#$FD レベル取得
03DEC4 LDA $2BB8 A=$7E2BB8
03DEC7 LDX #$0135 X=#$0135 「職業」中の力の開始アドレス
03DECA JSL $046B9E SR: $046B9E 指定パラメーターの新レベルでの理論値を取得
03DECE STA $78 $000078=A
03DED0 JSL $043414 SR: $043414 引数:1#$06 引数:2#$7A 引数:3#$FF 力取得
03DED7 STA $2BD2 $7E2BD2=A
03DEDA SEC c=on
03DEDB SBC $78 A-=$000078 新キャラクターの理論値からの差分作成
03DEDD STA $2BC8 $7E2BC8=A
03DEE0 LDA #$0000 A=#$0000
03DEE3 STA $2BBE $7E2BBE=A
03DEE6 LDA $2BB8 A=$7E2BB8
03DEE9 LDX #$0141 X=#$0141
03DEEC JSL $046B9E SR: $046B9E 指定パラメーターの新レベルでの理論値を取得
03DEF0 STA $78 $000078=A
03DEF2 JSL $043644 SR: $043644 引数:1#$06 引数:2#$7A 引数:3#$FF ステータス画面上の素早さ取得
03DEF9 STA $2BD4 $7E2BD4=A
03DEFC SEC c=on
03DEFD SBC $78 A-=$000078 新キャラクターの理論値からの差分作成
03DEFF STA $2BCA $7E2BCA=A
03DF02 LDA #$0001 A=#$0001
03DF05 STA $2BC0 $7E2BC0=A
03DF08 LDA $2BB8 A=$7E2BB8
03DF0B LDX #$014D X=#$014D
03DF0E JSL $046B9E SR: $046B9E 指定パラメーターの新レベルでの理論値を取得
03DF12 STA $78 $000078=A
03DF14 JSL $04350C SR: $04350C 引数:1#$06 引数:2#$7A 引数:3#$FF ステータス画面上の体力取得
03DF1B STA $2BD6 $7E2BD6=A
03DF1E SEC c=on
03DF1F SBC $78 A-=$000078 新キャラクターの理論値からの差分作成
03DF21 STA $2BCC $7E2BCC=A
03DF24 LDA #$0002 A=#$0002
03DF27 STA $2BC2 $7E2BC2=A
03DF2A LDA $2BB8 A=$7E2BB8
03DF2D LDX #$015B X=#$015B
03DF30 JSL $046B9E SR: $046B9E 指定パラメーターの新レベルでの理論値を取得
03DF34 STA $78 $000078=A
03DF36 JSL $0437C1 SR: $0437C1 引数:1#$06 引数:2#$7A 引数:3#$FF ステータス画面上の賢さ取得
03DF3D STA $2BD8 $7E2BD8=A
03DF40 SEC c=on
03DF41 SBC $78 A-=$000078 新キャラクターの理論値からの差分作成
03DF43 STA $2BCE $7E2BCE=A
03DF46 LDA #$0003 A=#$0003
03DF49 STA $2BC4 $7E2BC4=A
03DF4C LDA $2BB8 A=$7E2BB8
03DF4F LDX #$0167 X=#$0167
03DF52 JSL $046B9E SR: $046B9E 指定パラメーターの新レベルでの理論値を取得
03DF56 STA $78 $000078=A
03DF58 JSL $0438FB SR: $0438FB 引数:1#$06 引数:2#$7A 引数:3#$FF ステータス画面上の運のよさ取得
03DF5F STA $2BDA $7E2BDA=A
03DF62 SEC c=on
03DF63 SBC $78 A-=$000078 新キャラクターの理論値からの差分作成
03DF65 STA $2BD0 $7E2BD0=A
03DF68 LDA #$0004 A=#$0004
03DF6B STA $2BC6 $7E2BC6=A
03DF6E JSR $DF8E SR: $03DF8E デフォルトから差分の大きいステータスの順に並べ替え
03DF71 JSR $DFF9 SR: $03DFF9 登録所性格決定2ID取得
03DF74 JSR $E018 SR: $03E018 登録所性格決定1ID取得
03DF77 JSR $E134 SR: $03E134 性格決定アクセス
03DF7A LDX $2BB4 X=$7E2BB4
03DF7D JSL $042ED6 SR: $042ED6 引数:1#$06 引数:2#$FE 引数:3#$FF 性格変更
03DF84 STA $06,S Stack($06)=A
03DF86 PLB Pull DB
03DF87 REP #$30 m=off(A/M:16b), x=off(X/Y:16b)
03DF89 PLY Pull Y
03DF8A PLX Pull X
03DF8B PLA Pull A
03DF8C PLP Pull P Flag
03DF8D RTL return

まずは、$03DEA1~F6Dまで、何をしているかというと、新キャラクターの種投与後のステータスと、各職業のLv1のステータスとの差分を作成してバッファにセットしています。種を重点的に投与している場合は差分は大きくなり、種を投与していない場合は差分は0となります。$7E2BC8-D1(2*5Byte)に差分、$7E2BD2-DB(2*5Byte)にステータスの絶対値、$7E2BBE-C7(2*5Byte)にインデックス(力:0…運の良さ:4)がセットされます。SR: $03DF8Eは詳細は省きますが、これらの値を差分の大きい順番に並べ替えています(同じ場合は1/2の確率で順番を決定)。ステータスの絶対値、インデックスも差分の並べ替えに対応して並べ替えられます。

  • SR: $03DFF9 登録所性格決定2ID取得
03DFF9 LDA $2BBE A=$7E2BBE 差分の一番大きいインデックス
03DFFC ASL A<<1
03DFFD TAX X=A
03DFFE LDA $03E00E,X A=$03E00E+X 「職業」の登録所性格決定1IDへのオフセット
03E002 TAX X=A
03E003 LDA $2BB8 A=$7E2BB8
03E006 JSL $046AFD SR: $046AFD 引数:1#$FF 引数:2#$FE 引数:3#$FF 登録所性格決定1ID取得
03E00D RTS return

パッと見何をやっているかよくわかりませんが、$03E00E-1Dに並んでいるのは#$0006, #$0007, #$0008, #$0009, #$000Aです。それを引数にして$03E006でSR: $046AFDをコールして取得しているのは、固定長データ「職業」の6バイト目~10バイト目です。つまり、一番差分の大きいステータスに応じた該当部分の1Byteを取得している、ということになります。

  • SR: $03E018 登録所性格決定1ID取得
03E018 TAX X=A
03E019 JSL $09050D SR: $09050D 引数:1#$00 引数:2#$000F 引数:3#$C30EFD 引数:4#$78 構造体アクセス X番目の先頭アドレスを$00,第4引数にセット
03E024 LDY #$0001 Y=#$0001
03E027 LDA $78,Y A=$($000078+Y)
03E029 AND #$00FF A&=#$00FF ステータス種別
03E02C STA $7C $00007C=A
03E02E LDY #$0000 Y=#$0000
03E031 LDA $78,Y A=$($000078+Y)
03E033 AND #$007F A&=#$007F 閾値
03E036 STA $7E $00007E=A
03E038 LDY #$0000 Y=#$0000
03E03B LDA $78,Y A=$($000078+Y)
03E03D AND #$0080 A&=#$0080
03E040 BNE #$0E if(z==off) goto $03E050
03E042 JSR $E11A SR: $03E11A 指定したステータスが閾値を超えているか(該当c=on)
03E045 BCC #$0E if(c==off) goto $03E055
03E047 LDY #$0002 Y=#$0002
03E04A LDA $78,Y A=$($000078+Y)
03E04C AND #$00FF A&=#$00FF 登録所性格決定1のID
03E04F RTS return
03E050 JSR $E12E SR: $03E12E 2番目に差分の多いステータスが一致しているか(該当z=on)
03E053 BEQ #$F2 if(z==on) goto $03E047
以下略
  • SR: $03E11A 指定したステータスが閾値を超えているか(該当c=on)
03E11A LDX #$000A X=#$000A
03E11D DEX X–
03E11E DEX X–
03E11F BEQ #$07 if(z==on) goto $03E128
03E121 LDA $2BBE,X A=$7E2BBE+X ステータスのインデックス
03E124 CMP $7C A==$00007C?
03E126 BNE #$F5 if(z==off) goto $03E11D
03E128 LDA $2BC8,X A=$7E2BC8+X
03E12B CMP $7E A==or>=$00007E?
03E12D RTS return
  • SR: $03E12E 2番目に差分の多いステータスが一致しているか(該当z=on)
03E12E LDA $2BC0 A=$7E2BC0 2番目に差分の多いステータスのインデックス取得
03E131 CMP $7C A==or>=$00007C?
03E133 RTS return
  • SR: $03E134 登録所性格決定
03E134 TAX X=A
03E135 JSL $09050D SR: $09050D 引数:1#$00 引数:2#$000C 引数:3#$C30FFC 引数:4#$78 構造体アクセス X番目の先頭アドレスを$00,第4引数にセット
03E140 STZ $2BBE $7E2BBE=#$00
03E143 STZ $2BC0 $7E2BC0=#$00
03E146 LDX #$000E X=#$000E
03E149 STZ $2BC2,X $7E2BC2+X=#$00
03E14C STZ $2BD2,X $7E2BD2+X=#$00
03E14F DEX X–
03E150 DEX X–
03E151 BPL #$F6 if(n==off) goto $03E149
03E153 LDY #$0004 Y=#$0004
03E156 LDA $78,Y A=$($000078+Y)
03E158 AND #$00FF A&=#$00FF
03E15B STA $2BC2 $7E2BC2=A
03E15E LDY #$0005 Y=#$0005
03E161 LDA $78,Y A=$($000078+Y)
03E163 AND #$00FF A&=#$00FF
03E166 STA $2BC4 $7E2BC4=A
03E169 LDY #$0006 Y=#$0006
03E16C LDA $78,Y A=$($000078+Y)
03E16E AND #$00FF A&=#$00FF
03E171 STA $2BC6 $7E2BC6=A
03E174 LDY #$0007 Y=#$0007
03E177 LDA $78,Y A=$($000078+Y)
03E179 AND #$00FF A&=#$00FF
03E17C STA $2BC8 $7E2BC8=A
03E17F LDY #$0008 Y=#$0008
03E182 LDA $78,Y A=$($000078+Y)
03E184 AND #$00FF A&=#$00FF
03E187 STA $2BCA $7E2BCA=A
03E18A LDY #$0009 Y=#$0009
03E18D LDA $78,Y A=$($000078+Y)
03E18F AND #$00FF A&=#$00FF
03E192 STA $2BCC $7E2BCC=A
03E195 LDY #$000A Y=#$000A
03E198 LDA $78,Y A=$($000078+Y)
03E19A AND #$00FF A&=#$00FF
03E19D STA $2BCE $7E2BCE=A
03E1A0 LDY #$000B Y=#$000B
03E1A3 LDA $78,Y A=$($000078+Y)
03E1A5 AND #$00FF A&=#$00FF
03E1A8 STA $2BD0 $7E2BD0=A
03E1AB PEA #$0078 Push #$0078
03E1AE PEA #$000F Push #$000F
03E1B1 PEA #$0000 Push #$0000
03E1B4 JSL $090717 SR: $090717 構造体アクセス
03E1B8 STA $2BD2 $7E2BD2=A
03E1BB PEA #$0078 Push #$0078
03E1BE PEA #$00F0 Push #$00F0
03E1C1 PEA #$0000 Push #$0000
03E1C4 JSL $090717 SR: $090717 構造体アクセス
03E1C8 STA $2BD4 $7E2BD4=A
03E1CB PEA #$0078 Push #$0078
03E1CE PEA #$000F Push #$000F
03E1D1 PEA #$0001 Push #$0001
03E1D4 JSL $090717 SR: $090717 構造体アクセス
03E1D8 STA $2BD6 $7E2BD6=A
03E1DB PEA #$0078 Push #$0078
03E1DE PEA #$00F0 Push #$00F0
03E1E1 PEA #$0001 Push #$0001
03E1E4 JSL $090717 SR: $090717 構造体アクセス
03E1E8 STA $2BD8 $7E2BD8=A
03E1EB PEA #$0078 Push #$0078
03E1EE PEA #$000F Push #$000F
03E1F1 PEA #$0002 Push #$0002
03E1F4 JSL $090717 SR: $090717 構造体アクセス
03E1F8 STA $2BDA $7E2BDA=A
03E1FB PEA #$0078 Push #$0078
03E1FE PEA #$00F0 Push #$00F0
03E201 PEA #$0002 Push #$0002
03E204 JSL $090717 SR: $090717 構造体アクセス
03E208 STA $2BDC $7E2BDC=A
03E20B PEA #$0078 Push #$0078
03E20E PEA #$000F Push #$000F
03E211 PEA #$0003 Push #$0003
03E214 JSL $090717 SR: $090717 構造体アクセス
03E218 STA $2BDE $7E2BDE=A
03E21B PEA #$0078 Push #$0078
03E21E PEA #$00F0 Push #$00F0
03E221 PEA #$0003 Push #$0003
03E224 JSL $090717 SR: $090717 構造体アクセス
03E228 STA $2BE0 $7E2BE0=A
03E22B LDA $2BBA A=$7E2BBA
03E22E CMP #$0001 A==#$0001? 性別が女か
03E231 BEQ #$33 if(z==on) goto $03E266
03E233 LDX #$0000 X=#$0000
03E236 LDA $2BC2,X A=$7E2BC2+X
03E239 BEQ #$25 if(z==on) goto $03E260
03E23B JSL $046BED SR: $046BED 引数:1#$FF 引数:2#$FF 性格の男女専用情報を取得?
03E241 CMP #$0002 A==#$0002? 女専用なら潰す
03E244 BNE #$06 if(z==off) goto $03E24C
03E246 JSR $E2B4 SR: $03E2B4 性別に応じて使用できない性格を潰す
03E249 JMP $E236 goto $03E236
03E24C LDA $2BD2,X A=$7E2BD2+X
03E24F CLC c=off
03E250 ADC $2BC0 A+=$7E2BC0
03E253 STA $2BC0 $7E2BC0=A
03E256 STA $2BD2,X $7E2BD2+X=A
03E259 INX X++
03E25A INX X++
03E25B CPX #$0010 X>=#$0010 ?
03E25E BCC #$D6 if(c==off) goto $03E236
03E260 STX $2BBE $7E2BBE=X
03E263 JMP $E296 goto $03E296
03E266 LDX #$0000 X=#$0000
03E269 LDA $2BC2,X A=$7E2BC2+X
03E26C BEQ #$25 if(z==on) goto $03E293
03E26E JSL $046BED SR: $046BED 引数:1#$FF 引数:2#$FF 性格の男女専用情報を取得?
03E274 CMP #$0001 A==#$0001? 男専用なら潰す
03E277 BNE #$06 if(z==off) goto $03E27F
03E279 JSR $E2B4 SR: $03E2B4 性別に応じて使用できない性格を潰す
03E27C JMP $E269 goto $03E269
03E27F LDA $2BD2,X A=$7E2BD2+X
03E282 CLC c=off
03E283 ADC $2BC0 A+=$7E2BC0
03E286 STA $2BC0 $7E2BC0=A
03E289 STA $2BD2,X $7E2BD2+X=A
03E28C INX X++
03E28D INX X++
03E28E CPX #$0010 X>=#$0010 ?
03E291 BCC #$D6 if(c==off) goto $03E269
03E293 STX $2BBE $7E2BBE=X
03E296 LDA $2BC0 A=$7E2BC0
03E299 DEC A–
03E29A JSL $00135F SR: $00135F 乱数発生 00-A A(2B)
03E29E LDX #$0000 X=#$0000
03E2A1 CMP $2BD2,X A>=$7E2BD2+X?
03E2A4 BCC #$0A if(c==off) goto $03E2B0
03E2A6 INX X++
03E2A7 INX X++
03E2A8 CPX $2BBE X>=$7E2BBE?
03E2AB BCC #$F4 if(c==off) goto $03E2A1
03E2AD LDX #$0000 X=#$0000
03E2B0 LDA $2BC2,X A=$7E2BC2+X
03E2B3 RTS return

やたらと長いですが、やっていることは例によって幅の異なるルーレットを回すことです。こうしてみると、登録所の性格決定は種投与の結果、同じステータス値になったとしても、その後の処理によってかなり確率に左右される、ということがわかります。勇者の性格はオープニングの質問の答え方によってかなり確定的に決まるのとは対照的です。性格決定のプロセスの手間の違いなんでしょうか(登録所のキャラクターメイクは短時間でできるのでリトライが簡単)。また、初期の性格決定では職業ごとに取り得る性格もある程度限定されていることがわかります。細かく見ていくのは時間がかかるので省略しますが、女戦士がセクシーギャルになることはありません(男戦士がむっつりスケベになることはある)。この決定プロセスを積極的に変更する気にはなりませんが、問題はむしろ種投与による仲間キャラクターの過度なドーピングが可能な点です。例えば、僧侶に賢さの種を重点的に投与することで、Lv2になった時点で40以上のMPを確保することができるわけで、FC版のときのようにアリアハン大陸を出るにあたりホイミ用のMP切れになる恐れが大幅に低下します(ふくろもあるのでアイテム切れになる心配もない)。アリアハン脱出の道中はおばけありくいやアルミラージに恐れおののきながら長丁場の洞窟を進んでいくのが楽しかったわけで、なんとかならないかなあと思考停止しながら今回は終りにします。