基礎知識
戦闘関係
前ページのオディオモールのダメージ量処理の続き。
オディオモールのダメージ量処理から、サモの技「ほいこーろー」の仕様はどうなっているのかが気になってくるところである。
「ほいこーろー」そのものの計算方法もさることながら、単発ダメージ量を強制的に1にするオディオモールに「ほいこーろー」を当てた時、オディオモールに対して、STEP数+1のダメージを与えられる理由は何だろうか。
調べた結果、「ほいこーろー」のダメージ量計算は、かなり特殊な仕様となっている。
敵味方のステータスは関係なく、範囲内の敵に、サモが踊ったSTEPS数だけダメージを与える。
STEPS数は戦闘乱数から計算されているが、他の技のように、技を出す前にダメージ量を計算するのではなく、技のモーションの最中に戦闘乱数を生成し、次のSTEPに移るかどうかを決めている。
STEPS数は2~99で、99STEPSの時のみサモが四股を踏むモーションが入る。
なお、幕末編の家老、商人および、最終編のポリディクティスが使う技「わいろ」も、似た仕様であるため、最後に追記した。
大まかにまとめると、以下のようになる。
STEPSは1から増加開始。
また、STEPS増加判定フラグがあり、このフラグがONかOFFかでSTEPSの増加条件が変わる。
増加判定フラグは初期値0(フラグはオフ)。
増加判定フラグの仕様により、1STEP→2STEPSの増加は乱数に関係なく必ず起こるので、「ほいこーろー」のSTEPSは2以上ということになる。1STEPが出ることはない。
(ダメージ量表示の時にSTEPS数が表示されるが、グラフィックデータには「STEPS」というスプライトはあっても、「STEP」はないので、単数形になる1STEPが出ない仕様にしているのではないだろうか。筆者の想像でしかないが)
また、99STEPSに到達した時に、増加判定フラグが0か1かで、サモが四股を踏むモーション前のサモ回転モーションの長さが変わるというちょっとしたネタがある。
(増加判定フラグが0だと回転モーションが長くなる)
なお、「わいろ」は、STEPS増加判定フラグがないバージョンである。
ただし、ダメージ量は1~100までと思われる(実際には「ほいこーろー」と同じく99までしか値の増加はないのだが、「わいろ」は回避属性が適用されることがあるため、「単発ダメージ量×ヒット数」(=0)/2+1により、99+1が最大値になるはず)。
以上より、STEPSが2以上98未満の時、STEPS = nが出る確率は、
(n-1) * (15/16)^(n-2) * (1/16)^2
= ((n-1)/256) * (15/16)^(n-2)
で計算される。
99が出る確率は、
1 -(2~98STEPSが出る確率の総和)
約0.0135(1.35%)くらい。
16~17が出る確率がそれぞれ0.0237(2.37%)くらいで最大。
STEPS平均値は31.8くらいになる。
y = ((x-1)/256) * (15/16)^(x-2) (2 ≦ x ≦ 98)
y = 1 -(2~98STEPSが出る確率の総和) (x = 99)
という確率関数のグラフを表計算ソフトに書いてもらうと下のようになる。
lal_Huiguorou - Google ドキュメント
x = 16~17まで増加し、以降はなだらかに減少していく。
また、99STEPSが出る「1-(2~98が出る確率の総和)」が割と高いので、そこそこの確率で99STEPSが見られることになる。
98STEPSの出る確率が0.00077(0.077%)に対し、99STEPSが出る確率は約0.0135(1.35%)である。
98STEPS時は、増加判定フラグが0だと回転モーションが長くなるが、それぞれの確率は以下のようになっている。
なので、モーションが長くなる確率の方がかなり低め。
筆者は確率や統計には詳しくないが、STEPSが2以上98未満については、おそらく、
いわゆる負の二項分布で表すことができる確率分布になるのだと思う。
負の二項分布では、「成功回数を表す定数rと、おのおのの試行で成功する確率p」の2つのパラメータで成り立っているが、「ほいこーろー」のSTEPS数は、成功回数2、確率15/16の負の二項分布になる、と思う。
ここからは、実際のプログラムの内容を紹介していく。
技のモーションの最中、「キャラの動き(向き、座標など)」「エフェクト」「効果音」などを計算・記録する領域は$7E:A000~$7E:A47Fに割り振られている。
技モーション開始時に初期化(すべて$00が書き込まれる)され、技モーション終了時にも初期化される。
実際には$7E:A000~$7E:A01Fには技固有の変数のようなものが記録され、$7E:A020~がモーションのサブルーチンに関わっているようである。
「ほいこーろー」のSTEPS数に関わる重要なメモリアドレスは以下。
[$7E:A019][$7E:A018]初期値は$0000。2バイト値。
戦闘乱数から計算される「ほいこーろー」用乱数が記録されるアドレス。
「ほいこーろー」用乱数は後で説明する通り、漸化式であり、漸化式Anとすると以下のようになる。
An = ((乱数$0000~$007F) - $0040) + An-1
A0 = $0000
※減算・加算時はキャリーフラグを考慮(符号付き16ビット整数)
※乱数$0000~$007Fは、(戦闘乱数$0000~$FFFF * $0080)/$100で計算
乱数判定に使うのは実質[$7E:A018]のみ。
[$7E:A02C]初期値は$00。1バイト値。
上で記した「増加判定フラグ」にあたる。
乱数判定に失敗しても、この値が$00だったら成功になりSTEPS回数が増える。
その代わり[$7E:A02C]に$01が入り、[$7E:A02C]が$01の時に乱数判定失敗するとSTEPS増加終了。
99STEPSの時は、$00と$01どちらが入っているかによって、サモのモーションが少し変化するというちょっとした分岐要素がある。
[$7E:A01B][$7E:A01A]「ほいこーろー」のSTEP数を記録するアドレス。2バイト値。
初期値として[$7E:A01B][$7E:A01A]に$2000が入る。
2バイト値だが、[$7E:A01A]にSTEPS回数が入り、[$7E:A01B]は$20のまま。
$00が初期値だが、「ほいこーろー」を開始すると、乱数を使わず$01に増える。以降の増加は乱数による。
また、$01→$02は[$7E:A02C]の仕様上、必ず増えるはず。
記録される値は16進数だが、10進数に対応している。
というのは、$09まで増えたら、次は+$01されて$0Aになるはずなのに、サブルーチンでは+$07され、$10になるからである。
$10だと10進数では16だが、[$7E:A01A]に$10が入っている時に「ほいこーろー」のSTEPが止まると、「10STEPS」と表示されてダメージ量も10となる。
技のモーションは、技データの00~05に入っている値から、技モーションを指定するサブルーチンのアドレスを計算し、サブルーチンを実行することで行われる。
その計算はややこしいし、すべて紹介するとキリがないので、「ほいこーろー」のSTEP数計算に重要な部分だけ紹介していく。
[$7E:A02C]は、技モーション開始時、サブルーチン$C1/A3E4~$C1/A3F3の、$7E:A000~$7E:A47Fを$00で初期化する処理で$00が入った状態から開始になる。
[$7E:A018]と[$7E:A01A]もここで$00が入るのだが、更に、「ほいこーろー」のモーションのサブルーチンが開始した直後で初期値が入る。
[$7E:A018]の処理は以下で、$0000が入る。
$C1/A810 LDA $10 [$00:0310] ;Aに[$00:0311][$00:0310]をロード $C1/A812 AND #$0F ;Aと$0Fで論理積 $C1/A814 ASL A ;Aを算術左シフト *2 $C1/A815 STX $1C [$00:031C] ;Xを[$00:031D][$00:031C]に書き込み $C1/A817 REP #$21 ;Aを16bit幅に変更、キャリーフラグクリア $C1/A819 AND #$00FF ;Aと$00FFで論理積 $C1/A81C ADC $1E [$00:031E] ;A + [$00:031F][$00:031E] $C1/A81E TAX ;Aの値をXレジスタに転送 X:A018 $C1/A81F LDA #$0000 ;Aに$0000をロード $C1/A822 STA $7E0000,x[$7E:A018] ;Aを[$7E:A018][$7E:A018]に書き込み $C1/A826 SEP #$20 ;MフラグON Aレジスタは8bit幅 $C1/A828 LDX $1C [$00:031C] ;Xに[$00:031D][$00:031C]をロード $C1/A82A BRL $FE8E [$A6BB] ;フラグにかかわりなく常に分岐[$A6BB]
[$7E:A01B][$7E:A01A]の初期値は以下で書き込まれる。
$C1/A6E7 LDA $D50000,x[$D5:AB8D] ;Aに[$D5:AB8D](00)をロード $C1/A6EB STA $11 [$00:0311] ;Aを[$00:0311]に書き込み $C1/A6ED INX ;Xをインクリメント +1 $C1/A6EE LDA $D50000,x[$D5:AB8E] ;Aに[$D5:AB8E](20)をロード $C1/A6F2 STA $12 [$00:0312] ;Aを[$00:0312]に書き込み $C1/A6F4 INX ;Xをインクリメント +1 $C1/A6F5 STX $1C [$00:031C] ;Xを[$00:031C]に書き込み $C1/A6F7 RTS ;サブルーチン戻り $C1/A754 LDA $10 [$00:0310] ;Aに[$00:0310]をロード $C1/A756 AND #$0F ;Aと$0Fで論理積 $C1/A758 ASL A ;Aを算術左シフト *2 $C1/A759 REP #$21 ;Aを16bit幅に変更、キャリーフラグクリア $C1/A75B AND #$00FF ;Aと$00FFで論理積 $C1/A75E ADC $1E [$00:031E] ;A + [$00:031E] $C1/A760 TAX ;Aの値をXレジスタに転送 $C1/A761 LDA $11 [$00:0311] ;Aに[$00:0312][$00:0311]をロード $C1/A763 STA $7E0000,x[$7E:A01A] ;Aを[$7E:A01B][$7E:A01A]に書き込み ;(中略) $C1/A6DA JMP ($031A)[$C1:AF58] ;[$C1:AF58]へジャンプ(レジスタをスタックに積まない) $C1/AF58 JSR $A6E7 [$C1:A6E7] ;[$C1:A6E7]へジャンプ
以上から、[$7E:A01B][$7E:A01A]の初期値は[$D5:AB8E][$D5:AB8D]($2000)である。
ほいこーろーのSTEPS回数として使うのは実質[$7E:A01A]の1バイトで、初期値$00である。
STEPSに1が書き込まれる処理が以下だが、この処理は乱数計算などはせず、モーション開始時に[$7E:A01A]に必ず書き込まれる。
;(中略) $C1/A6BB LDA $D50000,x[$D5:ACA3] ;Aに[$D5:ACA3]($0D)をロード $C1/A6BF STA $10 [$00:0310] ;Aを[$00:0310]に書き込み ;(後略) ; $C1/A6E7 LDA $D50000,x[$D5:ACA4] ;Aに[$D5:ACA4]($01)をロード $C1/A6EB STA $11 [$00:0311] ;Aを[$00:0311]に書き込み $C1/A6ED INX ;Xをインクリメント +1 $C1/A6EE LDA $D50000,x[$D5:ACA5] ;Aに[$D5:ACA5]($00)をロード $C1/A6F2 STA $12 [$00:0312] ;Aを[$00:0312]に書き込み $C1/A6F4 INX ;Xをインクリメント +1 $C1/A6F5 STX $1C [$00:031C] ;Xを[$00:031C]に書き込み $C1/A6F7 RTS ;サブルーチン戻り $C1/A732 LDA $10 [$00:0310] ;Aに[$00:0310]($0D)をロード $C1/A734 AND #$0F ;Aと$0Fで論理積 $C1/A736 ASL A ;Aを算術左シフト *2 $C1/A737 REP #$21 ;Aを16bit幅に変更、キャリーフラグクリア $C1/A739 AND #$00FF ;Aと$00FFで論理積 $C1/A73C ADC $1E [$00:031E] ;A + [$00:031E] $C1/A73E TAX ;Aの値をXレジスタに転送 $C1/A73F LDA $7E0000,x[$7E:A01A] ;Aに[$7E:A01B][$7E:A01A](STEPS回数)をロード $C1/A743 CLC ;キャリーフラグクリア $C1/A744 ADC $11 [$00:0311] ;A + [$00:0312][$00:0311]($0001) $C1/A746 STA $7E0000,x[$7E:A01A] ;Aを[$7E:A01B][$7E:A01A]に書き込み $C1/A74A SEP #$20 ;MフラグON Aレジスタは8bit幅 $C1/A74C LDX $1C [$00:031C] ;Xに[$00:031C]をロード $C1/A74E BRL $FF6A [$A6BB] ;フラグにかかわりなく常に分岐[$A6BB]
ここでは、[$D5:ACA3]~[$D5:ACA5]が「ほいこーろー」用の定数として機能していることがわかる。
[$D5:ACA3]はアドレス呼び出しの値、[$D5:ACA5][$D5:ACA4]はSTEPS回数の加算用数値である。
$C1/A73F~$C1/A746で、
[$7E:A01B][$7E:A01A](STEPS回数) = [$7E:A01B][$7E:A01A] + $0001
となり、元のSTEPS回数に+1した値が新たなSTEPS回数となって、[$7E:A01B][$7E:A01A] = $2001となる。
[$7E:A01A]に入っている$01がSTEPS回数扱い。
STEPSが1に増える時、上の通り乱数は使わず、必ず増加するのであるが、それとは別に戦闘乱数が計算されはじめている。
技のモーションは基本的に決まった動きを行うだけなので乱数計算の必要はないのだが、「ほいこーろー」については、STEPS数以外にも乱数でモーションを選んでいる(?)らしく、モーション中に戦闘乱数を何度も計算して作っている。
更に、戦闘乱数をそのまま使うのではなく、戦闘乱数から計算した「ほいこーろー」用乱数を別途用意しているので、サブルーチンはなかなか複雑である。
(なぜここまで複雑な仕様にしたのかは、筆者にはよくわからない。後でわかる通り、「ほいこーろー」のSTEPS数を増加するかどうかの判定は1バイトの乱数で判定しているので、戦闘乱数でも判定可能である)
「ほいこーろー」用乱数が記録されるアドレスが[$7E:A019][$7E:A018]の2バイト値。
戦闘乱数計算のサブルーチン$C1/6150~$C1/61A4は中略としている。
;(中略) $C1/A6BB LDA $D50000,x[$D5:ABA1] ;Aに[$D5:ABA1](8C)をロード $C1/A6BF STA $10 [$00:0310] ;Aを[$00:0310]に書き込み ;(後略) $C1/A6E7 LDA $D50000,x[$D5:ABA2] ;Aに[$D5:ABA2](80)をロード $C1/A6EB STA $11 [$00:0311] ;Aを[$00:0311]に書き込み $C1/A6ED INX ;Xをインクリメント +1 $C1/A6EE LDA $D50000,x[$D5:ABA3] ;Aに[$D5:ABA3](00)をロード $C1/A6F2 STA $12 [$00:0312] ;Aを[$00:0312]に書き込み $C1/A6F4 INX ;Xをインクリメント +1 $C1/A6F5 STX $1C [$00:031C] ;Xを[$00:031C]に書き込み $C1/A6F7 RTS ;サブルーチン戻り $C1/A83C JSR $6150 [$C1:6150] ;[$C1:6150]へジャンプ $C1/6150 PHX ;Xをスタックにプッシュ ;(中略 戦闘乱数生成サブルーチン 乱数1) $C1/61A4 RTS ;サブルーチン戻り $C1/A83F JSR $6150 [$C1:6150] ;[$C1:6150]へジャンプ $C1/6150 PHX ;Xをスタックにプッシュ ;(中略 戦闘乱数生成サブルーチン 乱数2) $C1/61A4 RTS ;サブルーチン戻り ; ;乱数1は[$00:033A]、乱数2は[$00:033B]とAレジスタに入っている ; ;ここから16bit×16bitサブルーチン ;[$00:033A][$00:033B] * $0080 $C1/A842 LDA $11 [$00:0311] ;Aに[$00:0311]をロード=[$D5:ABA2]80 $C1/A844 STA $4202 [$00:4202] ;Aを[$00:4202]に書き込み $C1/A847 LDA $3A [$00:033A] ;Aに[$00:033A]をロード 乱数1 $C1/A849 STA $4203 [$00:4203] ;Aを[$00:4203]に書き込み $C1/A84C NOP ;計算待ち $C1/A84D NOP ;計算待ち $C1/A84E NOP ;計算待ち $C1/A84F NOP ;計算待ち $C1/A850 LDA $4217 [$00:4217] ;Aに[$00:4217]をロード 乗算の上2桁 $C1/A853 STA $16 [$00:0316] ;Aを[$00:0316]に書き込み $C1/A855 LDA $3B [$00:033B] ;Aに[$00:033B]をロード 乱数2 $C1/A857 STA $4203 [$00:4203] ;Aを[$00:4203]に書き込み $C1/A85A NOP ;計算待ち $C1/A85B NOP ;計算待ち $C1/A85C CLC ;キャリーフラグクリア $C1/A85D LDA $16 [$00:0316] ;Aに[$00:0316]をロード $C1/A85F ADC $4216 [$00:4216] ;A + [$00:4216] $C1/A862 STA $16 [$00:0316] ;Aを[$00:0316]に書き込み $C1/A864 LDA #$00 ;Aに$00をロード $C1/A866 ADC $4217 [$00:4217] ;A + [$00:4217] $C1/A869 STA $17 [$00:0317] ;Aを[$00:0317]に書き込み $C1/A86B LDA $12 [$00:0312] ;Aに[$00:0312](00)をロード $C1/A86D STA $4202 [$00:4202] ;Aを[$00:4202]に書き込み $C1/A870 LDA $3A [$00:033A] ;Aに[$00:033A]をロード 乱数1 $C1/A872 STA $4203 [$00:4203] ;Aを[$00:4203]に書き込み $C1/A875 NOP ;計算待ち $C1/A876 NOP ;計算待ち $C1/A877 LDA $16 [$00:0316] ;Aに[$00:0316]をロード $C1/A879 CLC ;キャリーフラグクリア $C1/A87A ADC $4216 [$00:4216] ;A + [$00:4216] $C1/A87D STA $16 [$00:0316] ;Aを[$00:0316]に書き込み $C1/A87F LDA $17 [$00:0317] ;Aに[$00:0317]をロード $C1/A881 ADC $4217 [$00:4217] ;A + [$00:4217] $C1/A884 STA $17 [$00:0317] ;Aを[$00:0317]に書き込み $C1/A886 LDA #$00 ;Aに$00をロード $C1/A888 ADC #$00 ;A + $00 $C1/A88A STA $18 [$00:0318] ;Aを[$00:0318]に書き込み $C1/A88C LDA $3B [$00:033B] ;Aに[$00:033B]をロード $C1/A88E STA $4203 [$00:4203] ;Aを[$00:4203]に書き込み $C1/A891 NOP ;計算待ち $C1/A892 NOP ;計算待ち $C1/A893 CLC ;キャリーフラグクリア $C1/A894 LDA $17 [$00:0317] ;Aに[$00:0317]をロード $C1/A896 ADC $4216 [$00:4216] ;A + [$00:4216] $C1/A899 STA $17 [$00:0317] ;Aを[$00:0317]に書き込み $C1/A89B LDA $18 [$00:0318] ;Aに[$00:0318]をロード $C1/A89D ADC $4217 [$00:4217] ;A + [$00:4217] $C1/A8A0 STA $18 [$00:0318] ;Aを[$00:0318]に書き込み ;[$00:0318][$00:0317][$00:0316]が乗算結果の上3バイト $C1/A8A2 LDA $10 [$00:0310] ;Aに[$00:0310]をロード=[$D5:ABA1] 8C $C1/A8A4 AND #$0F ;Aと$0Fで論理積 $C1/A8A6 ASL A ;Aを算術左シフト *2 $C1/A8A7 REP #$21 ;Aを16bit幅に変更、キャリーフラグクリア $C1/A8A9 AND #$00FF ;Aと$00FFで論理積 $C1/A8AC ADC $1E [$00:031E] ;A + [$00:031F][$00:031E](A000) $C1/A8AE TAX ;Aの値をXレジスタに転送 $C1/A8AF LDA $11 [$00:0311] ;Aに[$00:0312][$00:0311]をロード $0080 $C1/A8B1 LSR A ;Aを論理右シフト (/2) $C1/A8B2 STA $19 [$00:0319] ;A($0040)を[$00:031A][$00:0319]に書き込み $C1/A8B4 LDA $17 [$00:0317] ;Aに[$00:0318][$00:0317]をロード 乗算結果上2バイト($0000~$007F) $C1/A8B6 SEC ;キャリーフラグON $C1/A8B7 SBC $19 [$00:0319] ;A - [$00:031A][$00:0319]($0040) $C1/A8B9 CLC ;キャリーフラグクリア $C1/A8BA ADC $7E0000,x[$7E:A018] ;A + [$7E:A019][$7E:A018](初期値$0000) $C1/A8BE STA $7E0000,x[$7E:A018] ;Aを[$7E:A019][$7E:A018]に書き込み ;(中略) $C1/A6DA JMP ($031A)[$C1:AFA8] ;[$C1:AFA8]へジャンプ(レジスタをスタックに積まない) $C1/AFA8 JSR $A710 [$C1:A710] ;[$C1:A710]へジャンプ
まとめると、戦闘乱数を2回発生させ、繋げて2バイト値とし($C1/A842の時点で[$00:033A][$00:033B])、更に、$C1/A842以降の処理で、[$D5:ABA3][$D5:ABA2]($0080)の2バイト値と掛け算している。
つまり、
[$00:033A][$00:033B] * [$D5:ABA3][$D5:ABA2]
= [$00:033A][$00:033B] * $0080
である。
65C816のアセンブリ言語では乗算の命令がないので乗算を行うには一工夫必要になるのだが、2バイト×2バイト(16bit×16bit)の掛け算をする方法として、$C1/A842~では、符号付8bit×8bitの方法(65C816命令表 ロード・ストア命令参照)を4回に分けて行っている。
つまり、
$1234 * $0080
= ($1200 + $34) * ($0000 + $80)
= $12*$00*$10000 + ($12*$80 + $34*$00)*$100 + $34*$80
$10000や$100を掛け算する場合は小数点を左にずらすだけである。
答えは4バイト(32bit)になる。
上の計算を$C1/A842~$C1/A8A0で実行した結果、乗算結果の上3バイトは[$00:0318][$00:0317][$00:0316]に入ることになる。
$1234 * $0080 = $00091A00
だが、「$00091A」の部分が順に[$00:0318][$00:0317][$00:0316]に入る、ということである。
また、乱数$0000~$FFFF * $0080を計算した場合、答えは$00000000~$007FFF80になる。
上2バイトの[$00:0318][$00:0317]は$0000~$007Fしかとらない。
この計算により、実質、$0000~$007Fの乱数に計算し直したことになる。
さて、$C1/A8AF以降でこの乱数を更に計算していく。
$C1/A8B7で、キャリーフラグを立て、16ビットで、
[$00:0318][$00:0317] - [$D5:ABA3][$D5:ABA2]/2
という引き算を計算している。
[$D5:ABA3][$D5:ABA2]($0080)/2 = $0040
であり、[$00:0318][$00:0317]は$0000~$007Fの乱数だから、
($0000~$007Fの乱数) - $0040
キャリーフラグを立てて考えるので、
($10000~$1007Fの乱数) - $0040
の、下2バイトが答えになると考えても良い。
つまり、乱数により、
$FFC0~$FFFF、または $0000~$003F
が、引き算の答えである。
符号付き16ビット整数で考えたら、10進数の-64~0~+63ということになる。
最後に、キャリーフラグをクリアして、$C1/A8BA~で、以下の足し算を計算する。
[$7E:A019][$7E:A018] = A + [$7E:A019][$7E:A018](初期値$0000)
Aレジスタは先の引き算の答えであり、[$7E:A019][$7E:A018]は「ほいこーろー」用乱数を記録するアドレス2バイトで、先に述べた通り初期値は$0000である。
よって、
[$7E:A019][$7E:A018] = ($FFC0~$FFFF、または $0000~$003F) + $0000
先の引き算の答えがそのまま、[$7E:A019][$7E:A018]に入る。
以降はこのサブルーチンで[$7E:A019][$7E:A018]が計算され続けるので、漸化式で考えると、
An = ((乱数$0000~$007F) - $0040) + An-1
A0 = $0000
※減算・加算時はキャリーフラグを考慮(符号付き16ビット整数)
※乱数$0000~$007Fは、(戦闘乱数$0000~$FFFF * $0080)/$100で計算
このようになる。
仕様上、乱数として有効なのは下1バイトの[$7E:A018]だけであろう。
上の計算でわかるとおり、最初の計算で[$7E:A019]に入るのは$FFか$00のどちらかであり、この時点で2パターンしか乱数が算出できないからである。
実際、「ほいこーろー」のSTEPSの判定でも、下1バイトの[$7E:A018]しか使わない。
では、STEPS2回目以降、つまりSTEPSが増加するか、そこで止まるかの判定部分を見てみよう。
上の乱数生成のサブルーチンは$C1/AFA8で終わって、$C1/A710にジャンプする。
そこから先について見ていく。
$C1/AFA8 JSR $A710 [$C1:A710] ;[$C1:A710]へジャンプ $C1/A710 LDA $D50000,x[$D5:ABC6] ;Aに[$D5:ABC6]をロード $C1/A714 STA $11 [$00:0311] ;Aを[$00:0311]に書き込み 0F $C1/A716 INX ;Xをインクリメント +1 $C1/A717 LDA $D50000,x[$D5:ABC7] ;Aに[$D5:ABC7]をロード 00 $C1/A71B STA $12 [$00:0312] ;Aを[$00:0312]に書き込み $C1/A71D INX ;Xをインクリメント +1 $C1/A71E LDA $D50000,x[$D5:ABC8] ;Aに[$D5:ABC8]をロード 99 $C1/A722 STA $13 [$00:0313] ;Aを[$00:0313]に書き込み $C1/A724 INX ;Xをインクリメント +1 $C1/A725 LDA $D50000,x[$D5:ABC9] ;Aに[$D5:ABC9]をロード AB $C1/A729 STA $14 [$00:0314] ;Aを[$00:0314]に書き込み $C1/A72B INX ;Xをインクリメント +1 $C1/A72C STX $1C [$00:031C] ;Xを[$00:031C]に書き込み $C1/A72E RTS ;サブルーチン戻り $C1/AFAB LDA $10 [$00:0310] ;Aに[$00:0310]をロード $C1/AFAD AND #$0F ;Aと$0Fで論理積 $C1/AFAF ASL A ;Aを算術左シフト *2 $C1/AFB0 REP #$21 ;Aを16bit幅に変更、キャリーフラグクリア $C1/AFB2 AND #$00FF ;Aと$00FFで論理積 $C1/AFB5 ADC $1E [$00:031E] ;A + [$00:031F][$00:031E] $C1/AFB7 TAX ;Aの値をXレジスタに転送 $C1/AFB8 SEP #$20 ;MフラグON Aレジスタは8bit幅 $C1/AFBA LDA $7E0000,x[$7E:A018] ;Aに[$7E:A018]をロード $C1/AFBE AND $11 [$00:0311] ;Aと[$00:0311]で論理積 0F $C1/AFC0 BNE $0D [$AFCF] ;ゼロフラグが立っていないとき[$AFCF]分岐 ;(後略)
乱数判定前の$C1/A710~$C1/A72Eでは、[$D5:ABC6]~[$D5:ABC9]の4バイト分が[$00:0311]~[$00:0314]に入る。
値は$0F, $00, $99, $AB。
$C1/AFABからが判定のサブルーチンである。
$C1/AFBAで、「ほいこーろー」用乱数の下1バイトの[$7E:A018]がAにロードされる。
$C1/AFBEで、Aと[$00:0311]と論理積を取り、ゼロフラグ判定をしている。[$00:0311]は先程呼び出された[$D5:ABC6]($0F)が入っているから、
[$7E:A018] & $0F
であり、ゼロフラグ判定をすることになるから、実質、「[$7E:A018]の下1桁が0かどうか」の判定である。
[$7E:A018]が$?0のように下1桁が0であればゼロフラグが立ち、それ以外の値ならゼロフラグが立たない。
$C1/AFC0では、ゼロフラグが立たない場合、$C1/AFCFに分岐することになるが、この$C1/AFCF~以降が後々でわかる通り、「STEPS数が加算される」処理である。
ということで、
[$7E:A018]の下1桁が1~Fの時はSTEPS数が加算される(確率15/16)
まず、これが成立する。
ちなみにこの「[$7E:A018]と$0Fの論理積を取って判定」は、2STEPS目の判定だろうが、98STEPS目の判定だろうが、同一の処理である。論理積を取る値は一切変わらない。
では、[$7E:A018]の下1桁が0だと続きはどうなるか。
$C1/AFC0 BNE $0D [$AFCF] ;ゼロフラグが立っていないとき[$AFCF]分岐 ;ゼロフラグON [$7E:A018]の下1桁が0 $C1/AFC2 LDA $7E0001,x[$7E:A019] ;Aに[$7E:A019]をロード $C1/AFC6 AND $12 [$00:0312] ;Aと[$00:0312](00)で論理積 $C1/AFC8 BNE $05 [$AFCF] ;ゼロフラグが立っていないとき[$AFCF]分岐 $C1/AFCA LDX $1C [$00:031C] ;Xに[$00:031D][$00:031C]をロード $C1/AFCC BRL $F6EC [$A6BB] ;フラグにかかわりなく常に分岐[$A6BB] ;(中略) $C1/B016 JMP ($031A)[$C1:B419] ;[$C1:B419]へジャンプ(レジスタをスタックに積まない) $C1/B419 JSR $A6F8 [$C1:A6F8] ;[$C1:A6F8]へジャンプ $C1/A6F8 LDA $D50000,x[$D5:ABCB] ;Aに[$D5:ABCB](99)をロード $C1/A6FC STA $11 [$00:0311] ;Aを[$00:0311]に書き込み $C1/A6FE INX ;Xをインクリメント +1 $C1/A6FF LDA $D50000,x[$D5:ABCC] ;Aに[$D5:ABCC](AB)をロード $C1/A703 STA $12 [$00:0312] ;Aを[$00:0312]に書き込み $C1/A705 INX ;Xをインクリメント +1 $C1/A706 LDA $D50000,x[$D5:ABCD] ;Aに[$D5:ABCD](01)をロード $C1/A70A STA $13 [$00:0313] ;Aを[$00:0313]に書き込み $C1/A70C INX ;Xをインクリメント +1 $C1/A70D STX $1C [$00:031C] ;Xを[$00:031C]に書き込み $C1/A70F RTS ;サブルーチン戻り $C1/B41C BRL $02D3 [$B6F2] ;フラグにかかわりなく常に分岐[$B6F2] $C1/B6F2 LDX $1E [$00:031E] ;Xに[$00:031E]をロード $C1/B6F4 LDA $7E002C,x[$7E:A02C] ;Aに[$7E:A02C]をロード $C1/B6F8 BEQ $13 [$B70D] ;ゼロフラグが立っているとき[$B70D]分岐 ;ゼロフラグON [$7E:A02C]は初期値$00 $C1/B70D LDA $13 [$00:0313] ;Aに[$00:0313](01)をロード $C1/B70F STA $7E002C,x[$7E:A02C] ;Aを[$7E:A02C]に書き込み
[$7E:A018]の下1桁が0だと$C1/AFC2に進むが、次の処理は[$7E:A019]と[$00:0312]($00)で論理積を取ってゼロフラグ判定だから、[$7E:A019]の値は関係なくゼロフラグが立って、$C1/AFCAに進む。
(他の値の処理だと別の分岐処理が入るのだろうが、STEPS判定のこのケースでは確定で処理が進むことになる)
しばらくそのまま処理が続き、次の分岐は$C1/B6F4である。
[$7E:A02C]、増加判定フラグによる分岐になる。
[$7E:A02C]のゼロフラグ判定で分岐であり、ここでゼロフラグが立っている場合、つまり初期値$00のままだったら、$C1/B70Dに進む。
これで、STEPS数増加処理確定の分岐になる。
ただし、このサブルーチンでは、$C1/B70Fで[$7E:A02C]に[$D5:ABCD]($01)の値を書き込む。
つまり、増加判定フラグが$00から$01になる。
では、増加判定フラグ[$7E:A02C]が$01だったらどうなるか。
$C1/B6F8でゼロフラグが立たないから、$C1/B6FAへ進む。
$C1/B6F8 BEQ $13 [$B70D] ;ゼロフラグが立っているとき[$B70D]分岐 ;ゼロフラグOFF [$7E:A02C]$01 $C1/B6FA DEC A ;Aをデクリメント -1 $C1/B6FB STA $7E002C,x[$7E:A02C] ;Aを[$7E:A02C]に書き込み $C1/B6FF BEQ $07 [$B708] ;ゼロフラグが立っているとき[$B708]分岐 $C1/B708 LDX $1C [$00:031C] ;Xに[$00:031C]をロード $C1/B70A BRL $EFAE [$A6BB] ;フラグにかかわりなく常に分岐[$A6BB] ;(後略)
ここで一度[$7E:A02C]が$00に戻るのだが、結局この先はモーション終了処理へ進むことになり、STEPS数増加は止まる(STEPS数確定)。
以上が分岐の仕組みである。
つまり、
[$7E:A018]の下1桁が1~Fの時はSTEPS数が加算される[$7E:A018]の下1桁が0かつ、増加判定フラグ[$7E:A02C]が$00の時も、STEPS数が加算される(ただし増加判定フラグ[$7E:A02C]が$01になる)[$7E:A018]の下1桁が0かつ、増加判定フラグ[$7E:A02C]が$01の時は、STEPS数は加算されず処理終了(STEPS数確定)この3パターンに分かれていることがわかった。
また、この仕様のため、STEPS数は必ず2以上になる。
もし1STEPから2STEPSに増える最初の乱数判定で[$7E:A018]の下1桁が0だったとしても、この時点では増加判定フラグ[$7E:A02C]は必ず$00だから、STEPS数が加算されるからである。
「ほいこーろー」で1STEPが出ない理由がここでわかった。
実際にSTEPS数が増加する処理は以下になる。
分岐処理からそこそこ先である。
$C1/AFC0で分岐して$C1/AFCFに進んだ場合は以下のようになる。
$C1/AFC0 BNE $0D [$AFCF] ;ゼロフラグが立っていないとき[$AFCF]分岐 ;ゼロフラグOFF $C1/AFCF LDX $13 [$00:0313] ;Xに[$00:0314][$00:0313]をロード X:AB99 ;(中略) $C1/B413 JSR $A6E7 [$C1:A6E7] ;[$C1:A6E7]へジャンプ $C1/A6E7 LDA $D50000,x[$D5:AB9A] ;Aに[$D5:AB9A]をロード A3 ;(中略) $C1/A6F7 RTS ;サブルーチン戻り $C1/B416 BRL $0307 [$B720] ;フラグにかかわりなく常に分岐[$B720] ;(中略) $C1/A72F JSR $A6E7 [$C1:A6E7] ;[$C1:A6E7]へジャンプ $C1/A6E7 LDA $D50000,x[$D5:ACA4] ;Aに[$D5:ACA4](01)をロード $C1/A6EB STA $11 [$00:0311] ;Aを[$00:0311]に書き込み $C1/A6ED INX ;Xをインクリメント +1 $C1/A6EE LDA $D50000,x[$D5:ACA5] ;Aに[$D5:ACA5](00)をロード $C1/A6F2 STA $12 [$00:0312] ;Aを[$00:0312]に書き込み $C1/A6F4 INX ;Xをインクリメント +1 $C1/A6F5 STX $1C [$00:031C] ;Xを[$00:031C]に書き込み $C1/A6F7 RTS ;サブルーチン戻り $C1/A732 LDA $10 [$00:0310] ;Aに[$00:0310]をロード $C1/A734 AND #$0F ;Aと$0Fで論理積 $C1/A736 ASL A ;Aを算術左シフト *2 $C1/A737 REP #$21 ;Aを16bit幅に変更、キャリーフラグクリア $C1/A739 AND #$00FF ;Aと$00FFで論理積 $C1/A73C ADC $1E [$00:031E] ;A + [$00:031F][$00:031E] $C1/A73E TAX ;Aの値をXレジスタに転送 $C1/A73F LDA $7E0000,x[$7E:A01A] ;Aに[$7E:A01B][$7E:A01A]をロード STEPS回数 $C1/A743 CLC ;キャリーフラグクリア $C1/A744 ADC $11 [$00:0311] ;A + [$00:0312][$00:0311]($0001) $C1/A746 STA $7E0000,x[$7E:A01A] ;Aを[$7E:A01B][$7E:A01A]に書き込み $C1/A74A SEP #$20 ;MフラグON Aレジスタは8bit幅 $C1/A74C LDX $1C [$00:031C] ;Xに[$00:031D][$00:031C]をロード $C1/A74E BRL $FF6A [$A6BB] ;フラグにかかわりなく常に分岐[$A6BB] ;(後略)
$C1/A73FでSTEPS回数のアドレス[$7E:A01B][$7E:A01A]をロードし、[$D5:ACA5][$D5:ACA4]($0001)を加算して、$C1/A746にて[$7E:A01B][$7E:A01A]に書き戻している。
ここでSTEPSが+1されたことになる。
ただ、この処理だと、たとえば[$7E:A01B][$7E:A01A]に$2009が入っていた時、+1して$200Aになる。
下1桁が16進数のAになった場合は、少し後で分岐処理がある。
$200Aになった後の処理が以下。
$C1/A6E7 LDA $D50000,x[$D5:ACB3] ;Aに[$D5:ACB3](F0)をロード $C1/A6EB STA $11 [$00:0311] ;Aを[$00:0311]に書き込み $C1/A6ED INX ;Xをインクリメント +1 $C1/A6EE LDA $D50000,x[$D5:ACB4] ;Aに[$D5:ACB4](FF)をロード $C1/A6F2 STA $12 [$00:0312] ;Aを[$00:0312]に書き込み $C1/A6F4 INX ;Xをインクリメント +1 $C1/A6F5 STX $1C [$00:031C] ;Xを[$00:031C]に書き込み $C1/A6F7 RTS ;サブルーチン戻り $C1/A7D1 LDA $10 [$00:0310] ;Aに[$00:0310]をロード $C1/A7D3 AND #$0F ;Aと$0Fで論理積 $C1/A7D5 ASL A ;Aを算術左シフト *2 $C1/A7D6 REP #$21 ;Aを16bit幅に変更、キャリーフラグクリア $C1/A7D8 AND #$00FF ;Aと$00FFで論理積 $C1/A7DB ADC $1E [$00:031E] ;A + [$00:031E] $C1/A7DD TAX ;Aの値をXレジスタに転送 $C1/A7DE LDA $7E0000,x[$7E:A01A] ;Aに[$7E:A01B][$7E:A01A]をロード $C1/A7E2 AND $11 [$00:0311] ;Aと[$00:0312][$00:0311](FFF0)で論理積 $C1/A7E4 STA $7E0000,x[$7E:A01A] ;Aを[$7E:A01B][$7E:A01A]に書き込み $C1/A7E8 SEP #$20 ;MフラグON Aレジスタは8bit幅 $C1/A7EA LDX $1C [$00:031C] ;Xに[$00:031C]をロード $C1/A7EC BRL $FECC [$A6BB] ;フラグにかかわりなく常に分岐[$A6BB] $C1/A6BB LDA $D50000,x[$D5:ACB5] ;Aに[$D5:ACB5](0D)をロード $C1/A6BF STA $10 [$00:0310] ;Aを[$00:0310]に書き込み $C1/A6C1 INX ;Xをインクリメント +1 $C1/A6C2 STX $1C [$00:031C] ;Xを[$00:031C]に書き込み $C1/A6C4 REP #$20 ;Aを16bit幅に変更、Mフラグをクリア $C1/A6C6 AND #$00F0 ;Aと$00F0で論理積 $C1/A6C9 LSR A ;Aを論理右シフト (/2) $C1/A6CA LSR A ;Aを論理右シフト (/2) $C1/A6CB LSR A ;Aを論理右シフト (/2) $C1/A6CC ADC #$A5E6 ;A + $A5E6 $C1/A6CF TAX ;Aの値をXレジスタに転送 $C1/A6D0 LDA $C10000,x[$C1:A5E6] ;Aに[$C1:A5E6]をロード $C1/A6D4 STA $1A [$00:031A] ;Aを[$00:031A]に書き込み $C1/A6D6 LDX $1C [$00:031C] ;Xに[$00:031C]をロード $C1/A6D8 SEP #$20 ;MフラグON Aレジスタは8bit幅 $C1/A6DA JMP ($031A)[$C1:A72F] ;[$C1:A72F]へジャンプ(レジスタをスタックに積まない) $C1/A72F JSR $A6E7 [$C1:A6E7] ;[$C1:A6E7]へジャンプ $C1/A6E7 LDA $D50000,x[$D5:ACB6] ;Aに[$D5:ACB6]をロード $C1/A6EB STA $11 [$00:0311] ;Aを[$00:0311](10)に書き込み $C1/A6ED INX ;Xをインクリメント +1 $C1/A6EE LDA $D50000,x[$D5:ACB7] ;Aに[$D5:ACB7](00)をロード $C1/A6F2 STA $12 [$00:0312] ;Aを[$00:0312]に書き込み $C1/A6F4 INX ;Xをインクリメント +1 $C1/A6F5 STX $1C [$00:031C] ;Xを[$00:031C]に書き込み $C1/A6F7 RTS ;サブルーチン戻り $C1/A732 LDA $10 [$00:0310] ;Aに[$00:0310]をロード $C1/A734 AND #$0F ;Aと$0Fで論理積 $C1/A736 ASL A ;Aを算術左シフト *2 $C1/A737 REP #$21 ;Aを16bit幅に変更、キャリーフラグクリア $C1/A739 AND #$00FF ;Aと$00FFで論理積 $C1/A73C ADC $1E [$00:031E] ;A + [$00:031F][$00:031E] $C1/A73E TAX ;Aの値をXレジスタに転送 $C1/A73F LDA $7E0000,x[$7E:A01A] ;Aに[$7E:A01B][$7E:A01A]をロード $C1/A743 CLC ;キャリーフラグクリア $C1/A744 ADC $11 [$00:0311] ;A + [$00:0312][$00:0311](0010) $C1/A746 STA $7E0000,x[$7E:A01A] ;Aを[$7E:A01B][$7E:A01A]に書き込み $C1/A74A SEP #$20 ;MフラグON Aレジスタは8bit幅 $C1/A74C LDX $1C [$00:031C] ;Xに[$00:031C]をロード $C1/A74E BRL $FF6A [$A6BB] ;フラグにかかわりなく常に分岐[$A6BB] $C1/A6BB LDA $D50000,x[$D5:ACB8] ;Aに[$D5:ACB8]をロード $C1/A6BF STA $10 [$00:0310] ;Aを[$00:0310]に書き込み $C1/A6C1 INX ;Xをインクリメント +1 $C1/A6C2 STX $1C [$00:031C] ;Xを[$00:031C]に書き込み $C1/A6C4 REP #$20 ;Aを16bit幅に変更、Mフラグをクリア $C1/A6C6 AND #$00F0 ;Aと$00F0で論理積 $C1/A6C9 LSR A ;Aを論理右シフト (/2) $C1/A6CA LSR A ;Aを論理右シフト (/2) $C1/A6CB LSR A ;Aを論理右シフト (/2) $C1/A6CC ADC #$A5E6 ;A + $A5E6 $C1/A6CF TAX ;Aの値をXレジスタに転送 $C1/A6D0 LDA $C10000,x[$C1:A600] ;Aに[$C1:A600]をロード $C1/A6D4 STA $1A [$00:031A] ;Aを[$00:031A]に書き込み $C1/A6D6 LDX $1C [$00:031C] ;Xに[$00:031C]をロード $C1/A6D8 SEP #$20 ;MフラグON Aレジスタは8bit幅 $C1/A6DA JMP ($031A)[$C1:AFA8] ;[$C1:AFA8]へジャンプ(レジスタをスタックに積まない) $C1/AFA8 JSR $A710 [$C1:A710] ;[$C1:A710]へジャンプ
まず、
[$7E:A01B][$7E:A01A] & [$D5:ACB4][$D5:ACB3]($FFF0)
で、下1桁のAを0に変えてしまう。
$200Aが$2000になり[$7E:A01B][$7E:A01A]に書き戻されることになる。
続けて、
[$7E:A01B][$7E:A01A] + [$D5:ACB7][$D5:ACB6]($0010)
で、[$7E:A01B][$7E:A01A]が$2010となる。
よって、[$7E:A01B][$7E:A01A]は、
$2009→$200A→$2010
このように変わる。
16進数だと+7だが、10進数とみなすと、9から10に+1された、ということになる。
$C1/A7D1~の処理へ進むのは、下1桁が16進数のAになった時のみのようである。
以上の処理により、乱数次第で、STEPS数が増加していく。
だが、「ほいこーろー」の仕様ではSTEPSは99が最大で、ここで必ず停止する。
98回から99回に増える場合は通常通りに処理される(99回目のモーション処理などを行うため)。
99回から更にSTEPSが増加するか、増加せず乱数で増加が停止するか、いずれにしても処理は合流するが、99回でも乱数判定により増加が決まった場合は以下のようになる。
上で紹介したように、下1桁が9だから、別処理が入っている。
$C1/A732 LDA $10 [$00:0310] ;Aに[$00:0310]をロード $C1/A734 AND #$0F ;Aと$0Fで論理積 $C1/A736 ASL A ;Aを算術左シフト *2 $C1/A737 REP #$21 ;Aを16bit幅に変更、キャリーフラグクリア $C1/A739 AND #$00FF ;Aと$00FFで論理積 $C1/A73C ADC $1E [$00:031E] ;A + [$00:031E] $C1/A73E TAX ;Aの値をXレジスタに転送 $C1/A73F LDA $7E0000,x[$7E:A01A] ;Aに[$7E:A01B][$7E:A01A](0099)をロード $C1/A743 CLC ;キャリーフラグクリア $C1/A744 ADC $11 [$00:0311] ;A + [$00:0312][$00:0311](0001) $C1/A746 STA $7E0000,x[$7E:A01A] ;A(009A)を[$7E:A01B][$7E:A01A]に書き込み $C1/A74A SEP #$20 ;MフラグON Aレジスタは8bit幅 $C1/A74C LDX $1C [$00:031C] ;Xに[$00:031C]をロード $C1/A74E BRL $FF6A [$A6BB] ;フラグにかかわりなく常に分岐[$A6BB] $C1/A6BB LDA $D50000,x[$D5:ACA6] ;Aに[$D5:ACA6]をロード $C1/A6BF STA $10 [$00:0310] ;Aを[$00:0310]に書き込み $C1/A6C1 INX ;Xをインクリメント +1 $C1/A6C2 STX $1C [$00:031C] ;Xを[$00:031C]に書き込み $C1/A6C4 REP #$20 ;Aを16bit幅に変更、Mフラグをクリア $C1/A6C6 AND #$00F0 ;Aと$00F0で論理積 $C1/A6C9 LSR A ;Aを論理右シフト (/2) $C1/A6CA LSR A ;Aを論理右シフト (/2) $C1/A6CB LSR A ;Aを論理右シフト (/2) $C1/A6CC ADC #$A5E6 ;A + $A5E6 $C1/A6CF TAX ;Aの値をXレジスタに転送 $C1/A6D0 LDA $C10000,x[$C1:A600] ;Aに[$C1:A600]をロード $C1/A6D4 STA $1A [$00:031A] ;Aを[$00:031A]に書き込み $C1/A6D6 LDX $1C [$00:031C] ;Xに[$00:031C]をロード $C1/A6D8 SEP #$20 ;MフラグON Aレジスタは8bit幅 $C1/A6DA JMP ($031A)[$C1:AFA8] ;[$C1:AFA8]へジャンプ(レジスタをスタックに積まない) $C1/AFA8 JSR $A710 [$C1:A710] ;[$C1:A710]へジャンプ $C1/A710 LDA $D50000,x[$D5:ACA7] ;Aに[$D5:ACA7]をロード ;(中略) $C1/A72E RTS ;サブルーチン戻り $C1/AFAB LDA $10 [$00:0310] ;Aに[$00:0310]をロード ;(中略) $C1/AFA8 JSR $A710 [$C1:A710] ;[$C1:A710]へジャンプ $C1/A710 LDA $D50000,x[$D5:ACAD] ;Aに[$D5:ACAD]をロード ;(中略) $C1/A72E RTS ;サブルーチン戻り $C1/AFAB LDA $10 [$00:0310] ;Aに[$00:0310]をロード ;(中略) $C1/A7CE JSR $A6E7 [$C1:A6E7] ;[$C1:A6E7]へジャンプ $C1/A6E7 LDA $D50000,x[$D5:ACB3] ;Aに[$D5:ACB3](F0)をロード $C1/A6EB STA $11 [$00:0311] ;Aを[$00:0311]に書き込み $C1/A6ED INX ;Xをインクリメント +1 $C1/A6EE LDA $D50000,x[$D5:ACB4] ;Aに[$D5:ACB4](FF)をロード $C1/A6F2 STA $12 [$00:0312] ;Aを[$00:0312]に書き込み $C1/A6F4 INX ;Xをインクリメント +1 $C1/A6F5 STX $1C [$00:031C] ;Xを[$00:031C]に書き込み $C1/A6F7 RTS ;サブルーチン戻り $C1/A7D1 LDA $10 [$00:0310] ;Aに[$00:0310]をロード $C1/A7D3 AND #$0F ;Aと$0Fで論理積 $C1/A7D5 ASL A ;Aを算術左シフト *2 $C1/A7D6 REP #$21 ;Aを16bit幅に変更、キャリーフラグクリア $C1/A7D8 AND #$00FF ;Aと$00FFで論理積 $C1/A7DB ADC $1E [$00:031E] ;A + [$00:031E] $C1/A7DD TAX ;Aの値をXレジスタに転送 $C1/A7DE LDA $7E0000,x[$7E:A01A] ;Aに[$7E:A01B][$7E:A01A](009A)をロード $C1/A7E2 AND $11 [$00:0311] ;Aと[$00:0312][$00:0311](FFF0)で論理積 $C1/A7E4 STA $7E0000,x[$7E:A01A] ;A(0090)を[$7E:A01B][$7E:A01A]に書き込み $C1/A7E8 SEP #$20 ;MフラグON Aレジスタは8bit幅 $C1/A7EA LDX $1C [$00:031C] ;Xに[$00:031C]をロード $C1/A7EC BRL $FECC [$A6BB] ;フラグにかかわりなく常に分岐[$A6BB] $C1/A6BB LDA $D50000,x[$D5:ACB5] ;Aに[$D5:ACB5]をロード $C1/A6BF STA $10 [$00:0310] ;Aを[$00:0310]に書き込み $C1/A6C1 INX ;Xをインクリメント +1 $C1/A6C2 STX $1C [$00:031C] ;Xを[$00:031C]に書き込み $C1/A6C4 REP #$20 ;Aを16bit幅に変更、Mフラグをクリア $C1/A6C6 AND #$00F0 ;Aと$00F0で論理積 $C1/A6C9 LSR A ;Aを論理右シフト (/2) $C1/A6CA LSR A ;Aを論理右シフト (/2) $C1/A6CB LSR A ;Aを論理右シフト (/2) $C1/A6CC ADC #$A5E6 ;A + $A5E6 $C1/A6CF TAX ;Aの値をXレジスタに転送 $C1/A6D0 LDA $C10000,x[$C1:A5E6] ;Aに[$C1:A5E6]をロード $C1/A6D4 STA $1A [$00:031A] ;Aを[$00:031A]に書き込み $C1/A6D6 LDX $1C [$00:031C] ;Xに[$00:031C]をロード $C1/A6D8 SEP #$20 ;MフラグON Aレジスタは8bit幅 $C1/A6DA JMP ($031A)[$C1:A72F] ;[$C1:A72F]へジャンプ(レジスタをスタックに積まない) $C1/A72F JSR $A6E7 [$C1:A6E7] ;[$C1:A6E7]へジャンプ $C1/A6E7 LDA $D50000,x[$D5:ACB6] ;Aに[$D5:ACB6](10)をロード $C1/A6EB STA $11 [$00:0311] ;Aを[$00:0311]に書き込み $C1/A6ED INX ;Xをインクリメント +1 $C1/A6EE LDA $D50000,x[$D5:ACB7] ;Aに[$D5:ACB7](00)をロード $C1/A6F2 STA $12 [$00:0312] ;Aを[$00:0312]に書き込み $C1/A6F4 INX ;Xをインクリメント +1 $C1/A6F5 STX $1C [$00:031C] ;Xを[$00:031C]に書き込み $C1/A6F7 RTS ;サブルーチン戻り $C1/A732 LDA $10 [$00:0310] ;Aに[$00:0310]をロード $C1/A734 AND #$0F ;Aと$0Fで論理積 $C1/A736 ASL A ;Aを算術左シフト *2 $C1/A737 REP #$21 ;Aを16bit幅に変更、キャリーフラグクリア $C1/A739 AND #$00FF ;Aと$00FFで論理積 $C1/A73C ADC $1E [$00:031E] ;A + [$00:031E] $C1/A73E TAX ;Aの値をXレジスタに転送 $C1/A73F LDA $7E0000,x[$7E:A01A] ;Aに[$7E:A01B][$7E:A01A](0090)をロード $C1/A743 CLC ;キャリーフラグクリア $C1/A744 ADC $11 [$00:0311] ;A + [$00:0312][$00:0311](0010) $C1/A746 STA $7E0000,x[$7E:A01A] ;A(00A0)を[$7E:A01B][$7E:A01A]に書き込み $C1/A74A SEP #$20 ;MフラグON Aレジスタは8bit幅 $C1/A74C LDX $1C [$00:031C] ;Xに[$00:031C]をロード $C1/A74E BRL $FF6A [$A6BB] ;フラグにかかわりなく常に分岐[$A6BB] $C1/A6BB LDA $D50000,x[$D5:ACB8] ;Aに[$D5:ACB8]をロード $C1/A6BF STA $10 [$00:0310] ;Aを[$00:0310]に書き込み $C1/A6C1 INX ;Xをインクリメント +1 $C1/A6C2 STX $1C [$00:031C] ;Xを[$00:031C]に書き込み $C1/A6C4 REP #$20 ;Aを16bit幅に変更、Mフラグをクリア $C1/A6C6 AND #$00F0 ;Aと$00F0で論理積 $C1/A6C9 LSR A ;Aを論理右シフト (/2) $C1/A6CA LSR A ;Aを論理右シフト (/2) $C1/A6CB LSR A ;Aを論理右シフト (/2) $C1/A6CC ADC #$A5E6 ;A + $A5E6 $C1/A6CF TAX ;Aの値をXレジスタに転送 $C1/A6D0 LDA $C10000,x[$C1:A600] ;Aに[$C1:A600]をロード $C1/A6D4 STA $1A [$00:031A] ;Aを[$00:031A]に書き込み $C1/A6D6 LDX $1C [$00:031C] ;Xに[$00:031C]をロード $C1/A6D8 SEP #$20 ;MフラグON Aレジスタは8bit幅 $C1/A6DA JMP ($031A)[$C1:AFA8] ;[$C1:AFA8]へジャンプ(レジスタをスタックに積まない) $C1/AFA8 JSR $A710 [$C1:A710] ;[$C1:A710]へジャンプ
ここまでは、これまでの「[$7E:A01A]の下1桁が9の時の処理」と同じである。
$0099に+1するので$009Aになるが、一度$FFF0と論理積を取って$0090とし、上の$C1/A73F~で、
$0090 + $0010
と、計算する。
これまでなら、例えば$0089→$008A→$0080 + $0010→$0090と処理したのであるが、$0090 + $0010では$00A0である。
見た目10進数にならない。
この場合は以下のように処理が続く。
$C1/A710 LDA $D50000,x[$D5:ACB9] ;Aに[$D5:ACB9](80)をロード ;(中略) $C1/A72E RTS ;サブルーチン戻り $C1/AFAB LDA $10 [$00:0310] ;Aに[$00:0310]をロード ;(中略) $C1/AFA8 JSR $A710 [$C1:A710] ;[$C1:A710]へジャンプ $C1/A710 LDA $D50000,x[$D5:ACBF] ;Aに[$D5:ACBF]をロード ;(中略) $C1/A72E RTS ;サブルーチン戻り $C1/AFAB LDA $10 [$00:0310] ;Aに[$00:0310]をロード ;(中略) $C1/A72F JSR $A6E7 [$C1:A6E7] ;[$C1:A6E7]へジャンプ $C1/A6E7 LDA $D50000,x[$D5:ACC5] ;Aに[$D5:ACC5](F9)をロード $C1/A6EB STA $11 [$00:0311] ;Aを[$00:0311]に書き込み $C1/A6ED INX ;Xをインクリメント +1 $C1/A6EE LDA $D50000,x[$D5:ACC6] ;Aに[$D5:ACC6](FF)をロード $C1/A6F2 STA $12 [$00:0312] ;Aを[$00:0312]に書き込み $C1/A6F4 INX ;Xをインクリメント +1 $C1/A6F5 STX $1C [$00:031C] ;Xを[$00:031C]に書き込み $C1/A6F7 RTS ;サブルーチン戻り $C1/A732 LDA $10 [$00:0310] ;Aに[$00:0310]をロード $C1/A734 AND #$0F ;Aと$0Fで論理積 $C1/A736 ASL A ;Aを算術左シフト *2 $C1/A737 REP #$21 ;Aを16bit幅に変更、キャリーフラグクリア $C1/A739 AND #$00FF ;Aと$00FFで論理積 $C1/A73C ADC $1E [$00:031E] ;A + [$00:031E] $C1/A73E TAX ;Aの値をXレジスタに転送 $C1/A73F LDA $7E0000,x[$7E:A01A] ;Aに[$7E:A01B][$7E:A01A](00A0)をロード $C1/A743 CLC ;キャリーフラグクリア $C1/A744 ADC $11 [$00:0311] ;A + [$00:0312][$00:0311](FFF9) $C1/A746 STA $7E0000,x[$7E:A01A] ;Aを[$7E:A01B][$7E:A01A](0099)に書き込み $C1/A74A SEP #$20 ;MフラグON Aレジスタは8bit幅 $C1/A74C LDX $1C [$00:031C] ;Xに[$00:031C]をロード $C1/A74E BRL $FF6A [$A6BB] ;フラグにかかわりなく常に分岐[$A6BB] $C1/A6BB LDA $D50000,x[$D5:ACC7] ;Aに[$D5:ACC7]をロード $C1/A6BF STA $10 [$00:0310] ;Aを[$00:0310]に書き込み $C1/A6C1 INX ;Xをインクリメント +1 $C1/A6C2 STX $1C [$00:031C] ;Xを[$00:031C]に書き込み $C1/A6C4 REP #$20 ;Aを16bit幅に変更、Mフラグをクリア $C1/A6C6 AND #$00F0 ;Aと$00F0で論理積 $C1/A6C9 LSR A ;Aを論理右シフト (/2) $C1/A6CA LSR A ;Aを論理右シフト (/2) $C1/A6CB LSR A ;Aを論理右シフト (/2) $C1/A6CC ADC #$A5E6 ;A + $A5E6 $C1/A6CF TAX ;Aの値をXレジスタに転送 $C1/A6D0 LDA $C10000,x[$C1:A5E6] ;Aに[$C1:A5E6]をロード $C1/A6D4 STA $1A [$00:031A] ;Aを[$00:031A]に書き込み $C1/A6D6 LDX $1C [$00:031C] ;Xに[$00:031C]をロード $C1/A6D8 SEP #$20 ;MフラグON Aレジスタは8bit幅 $C1/A6DA JMP ($031A)[$C1:A72F] ;[$C1:A72F]へジャンプ(レジスタをスタックに積まない) $C1/A72F JSR $A6E7 [$C1:A6E7] ;[$C1:A6E7]へジャンプ
$C1/A73F~の処理は、キャリーフラグクリア後、
[$7E:A01B][$7E:A01A]($00A0) + [$D5:ACC6][$D5:ACC5]($FFF9)
を計算している。
答えは$10099、つまり$0099(キャリーフラグON)である。
ここで、[$7E:A01B][$7E:A01A]が$0099の状態で乱数処理によりSTEPS数が+1されても$0099に戻る、という処理が行われたことになり、ここでSTEPS増加は終了となる。
また、99STEPSの時は、これよりも後で別途、増加判定フラグである[$7E:A02C]の処理も入る。
99STEPS確定の時点では、[$7E:A02C]には$00か$01が入っているはずだが、99STEPS確定時から後は増加判定フラグとしては機能せず、サモの締めのモーションの変化に関わってくる。以下サブルーチンで分岐処理を行っている。
$C1/A6F8 LDA $D50000,x[$D5:ABDF] ;Aに[$D5:ABDF](DB)をロード $C1/A6FC STA $11 [$00:0311] ;Aを[$00:0311]に書き込み $C1/A6FE INX ;Xをインクリメント +1 $C1/A6FF LDA $D50000,x[$D5:ABE0] ;Aに[$D5:ABE0](AB)をロード $C1/A703 STA $12 [$00:0312] ;Aを[$00:0312]に書き込み $C1/A705 INX ;Xをインクリメント +1 $C1/A706 LDA $D50000,x[$D5:ABE1] ;Aに[$D5:ABE1](07)をロード $C1/A70A STA $13 [$00:0313] ;Aを[$00:0313]に書き込み $C1/A70C INX ;Xをインクリメント +1 $C1/A70D STX $1C [$00:031C] ;Xを[$00:031C]に書き込み $C1/A70F RTS ;サブルーチン戻り $C1/B41C BRL $02D3 [$B6F2] ;フラグにかかわりなく常に分岐[$B6F2] $C1/B6F2 LDX $1E [$00:031E] ;Xに[$00:031E]をロード $C1/B6F4 LDA $7E002C,x[$7E:A02C] ;Aに[$7E:A02C]をロード $C1/B6F8 BEQ $13 [$B70D] ;ゼロフラグが立っているとき[$B70D]分岐 ;ゼロフラグOFF([$7E:A02C]が$01) $C1/B6FA DEC A ;Aをデクリメント -1 $C1/B6FB STA $7E002C,x[$7E:A02C] ;A(00)を[$7E:A02C]に書き込み $C1/B6FF BEQ $07 [$B708] ;ゼロフラグが立っているとき[$B708]分岐 ;(以降省略) ;ゼロフラグON $C1/B70D LDA $13 [$00:0313] ;Aに[$00:0313](07)をロード $C1/B70F STA $7E002C,x[$7E:A02C] ;Aを[$7E:A02C]に書き込み ;(中略) $C1/B413 JSR $A6E7 [$C1:A6E7] ;[$C1:A6E7]へジャンプ
ここで増加判定フラグ[$7E:A02C]に入っていた値が$00か$01かで分岐処理する。
$00だった場合、[$7E:A02C]には[$D5:ABE1]($07)が入る。
これにより、サモがくるくる回る処理が追加され、その後に四股を踏んで99STEPSの文字が出る。
サモの回転は1回転で[$7E:A02C]が-1されるので7回転(7回のモーション)が行われ、[$7E:A02C]が$00になると回転モーションが終わる。
一方、[$7E:A02C]が$01の場合、上の処理の$C1/B6FBで[$7E:A02C]に$00が書き込まれ、回転モーション1回で四股を踏むモーションへと移行する。
つまり99STEPSの時は、2パターンのモーションが見られるということになる。
回転数が変わるだけなので、わかりにくいといえばわかりにくいが……
モーションが異なるだけでダメージ量自体は99で共通である。
[$7E:A01B][$7E:A01A]に入ったSTEPS数は、他の技と同じく、敵へのダメージ量として処理される。
そのサブルーチンが以下。
まず、以下処理で[$7E:A01A]の値が[$00:036E]にコピーされる。
$C1/A4F7 LDA $7EA01A[$7E:A01A] ;Aに[$7E:A01A]をロード $C1/A4FB STA $6E [$00:036E] ;Aを[$00:036E]に書き込み $C1/A4FD JSR $A3E4 [$C1:A3E4] ;[$C1:A3E4]へジャンプ
もちろんこの時点での[$7E:A01A]は、「16進数だが10進数で読み取れるSTEPS数」のままである。
25STEPSなら[$7E:A01A]には$25が入っているが、16進数での$25は10進数変換すると37である。
上のサブルーチンは、敵味方どちらも技を使用した時に、モーションが終了した時点で処理されるのだが、[$7E:A01A]に00以外の値が入るのが「ほいこーろー」しかないようで(未確認)、他の技はだいたい[$00:036E]に$00が入ったまま処理が進むことになる。
ここから少し飛んで、他の技との共通処理(ダメージ量処理)のサブルーチン$C1/CDE7~から分岐が発生する。
$C1/CDE7 STZ $22 [$00:0322] ;[$00:0322]に$00を書き込み $C1/CDE9 STZ $23 [$00:0323] ;[$00:0323]に$00を書き込み $C1/CDEB LDA $77 [$00:0377] ;Aに[$00:0377]をロード $C1/CDED AND #$0F ;Aと$0Fで論理積 $C1/CDEF CMP #$08 ;Aと$08を減算比較(ステータスレジスタ変更のみ) $C1/CDF1 BNE $17 [$CE0A] ;ゼロフラグが立っていないとき[$CE0A]分岐 $C1/CDF3 LDA $6E [$00:036E] ;Aに[$00:036E](STEPS数)をロード $C1/CDF5 BEQ $13 [$CE0A] ;ゼロフラグが立っているとき[$CE0A]分岐 ;ゼロフラグOFF 「ほいこーろー」及び「わいろ」用処理 $C1/CDF7 AND #$F0 ;Aと$F0で論理積 $C1/CDF9 LSR A ;Aを論理右シフト (/2) $C1/CDFA STA $22 [$00:0322] ;Aを[$00:0322]に書き込み $C1/CDFC LSR A ;Aを論理右シフト (/2) $C1/CDFD LSR A ;Aを論理右シフト (/2) $C1/CDFE ADC $22 [$00:0322] ;A + [$00:0322] $C1/CE00 STA $22 [$00:0322] ;Aを[$00:0322]に書き込み $C1/CE02 LDA $6E [$00:036E] ;Aに[$00:036E](STEPS数)をロード $C1/CE04 AND #$0F ;Aと$0Fで論理積 $C1/CE06 ADC $22 [$00:0322] ;A + [$00:0322] $C1/CE08 STA $22 [$00:0322] ;Aを[$00:0322]に書き込み ;処理合流 $C1/CE0A RTS ;サブルーチン戻り
$C1/CDF3で[$00:036E](STEPS数)のゼロフラグ分岐がある。
「ほいこーろー」だと$02以上の値が入っているはずなので(後で紹介するが「わいろ」もここで$01以上の値が入っている)、ここで$C1/CDF7~$C1/CE08の「ほいこーろー」用処理が入る。
ここが、「2桁の16進数の値を10進数に解釈し直すサブルーチン」である。
例えば、STEPS数として[$00:036E]に$67が入っていた場合、「ほいこーろー」のモーション終了時には10進数として「67STEPS」と表示される。
だが、16進数$67 (%0110 0111)は、10進数に直すと103である。これでは後々で「103ダメージ」と算出されてしまう。
10進数で67は、16進数だと幾つか? という計算をして、その値を「ほいこーろー」のダメージ量とする。
そこで上では、まず$C1/CDF7で[$00:036E]と$F0の論理積を取る。
これで$67の上の桁、10進数で見なした時の10の位が取り出せて、$60になる。(%0110 0000)
$C1/CDFAで、$60/2を[$00:0322]に書き込む。(%0011 0000)
この値は実質、$6(%0000 0110)を×8した値(%0011 0000)と等しい。つまり16進数$67の10の位の値×8である。
更に$C1/CDFC~で、論理右シフト3回分(/8)だから、$6(%0000 0110)を×2した値と等しい。
$C1/CE00で求められたのは、
STEPS数の上の位×8 + STEPS数の上の位×2
= STEPS数の上の位×10
である。
ここに、$C1/CE02~からの[$00:036E]と$0Fで論理積を取った値(つまり1の位)を足せば、「10進数で67は、16進数だと幾つか?」が計算できたことになる。
ということで、$C1/CE08で[$00:0322]に書き込んだ値が、「2桁の16進数の値を10進数に解釈」した値である。
$C1/CD32 REP #$20 ;Aを16bit幅に変更、Mフラグをクリア $C1/CD34 LDA $2134 [$00:2134] ;Aに[$00:2135][$00:2134](この時点での総ダメージ量)をロード $C1/CD37 STA $20 [$00:0320] ;Aを[$00:0321][$00:0320]に書き込み $C1/CD39 LDA $7E920A,x ;Aに[$7E:ADxB][$7E:ADxA]をロード $C1/CD3D AND #$00FF ;Aと$00FFで論理積 $C1/CD40 BEQ $04 [$CD46] ;ゼロフラグが立っているとき[$CD46]分岐 ;ゼロフラグON $C1/CD46 LDA $20 [$00:0320] ;Aに[$00:0321][$00:0320]をロード $C1/CD48 CLC ;キャリーフラグクリア $C1/CD49 ADC $22 [$00:0322] ;A + [$00:0323][$00:0322](STEPS数ダメージ量) $C1/CD4B CMP #$03E7 ;Aと$03E7を減算比較(ステータスレジスタ変更のみ) $C1/CD4E BCC $03 [$CD53] ;キャリーフラグが立っていないとき[$CD53]分岐 ;キャリーフラグOFF ダメージ量は999未満 $C1/CD53 STA $7E9200,x ;Aを[$7E:ADx1][$7E:ADx0]に書き込み $C1/CD57 STA $4204 [$00:4204] ;Aを[$00:4205][$00:4204]に書き込み $C1/CD5A SEP #$20 ;MフラグON Aレジスタは8bit幅 $C1/CD5C JSR $CE0B [$C1:CE0B] ;[$C1:CE0B]へジャンプ
[$00:2135][$00:2134]に入っているのは「単発ダメージ量×ヒット数」になる(処理省略)。
「ほいこーろー」は単発ダメージ量が計算上0、ヒット数1なのだが、例外になるのは最終編のオディオモールで、「単発ダメージ量の計算を通常通り行った後、単発ダメージ量を1に変更する」という処理が入る。オディオモールのダメージ量処理を見ていただきたい。
このため、$C1/CD37で[$00:0321][$00:0320]に入る値は、オディオモール以外は$0000、オディオモールのみ$0001ということになる。
$C1/CD39~の判定は回避属性判定値からダメージ量を半減するかどうかの分岐である。詳細は回避属性のサブルーチン(敵が回避属性で半減)を見ていただきたい。
$C1/CD39でロードする[$7E:ADxA]が$00の時は回避属性判定なしでダメージ量は半減されない。
「ほいこーろー」は無属性技だから半減なし。
$C1/CD49~で、
[$00:0321][$00:0320](単発ダメージ量×ヒット数 回避属性反映) + [$00:0323][$00:0322](STEPS数ダメージ量)
を計算し、$C1/CD4B~で$03E7(10進数999)と比較して、999以下であればダメージ量は変化せず、そのまま最終的なダメージ量となる。
「ほいこーろー」の最大ダメージ量は99($63)だから、$C1/CD4Eでキャリーフラグが立つことはなく、そのままダメージ量が書き込まれる。
「ほいこーろー」以外だと[$00:0323][$00:0322]は$0000なので、[$00:0321][$00:0320](単発ダメージ量×ヒット数 回避属性反映)がそのままダメージ量扱いとなる。
「ほいこーろー」の場合は、オディオモール以外なら、
$0000 + [$00:0323][$00:0322](STEPS数ダメージ量)
だから、STEPSの値がそのままダメージ量である。
だが、オディオモールだと、
$0001 + [$00:0323][$00:0322](STEPS数ダメージ量)
となってしまい、STEPS数+1のダメージを与えることになる。
これが、オディオモールに「ほいこーろー」を当てると、STEPSで表示される値とダメージ量とに1の差がある原因である。
(リメイク版ではこの現象が起こらないようになっている)
幕末編の家老、商人および、最終編のポリディクティスが使う技「わいろ」は回転数だけダメージを与える技だが、簡単に言えば「ほいこーろー」のSTEPS増加判定フラグがないバージョンである。
つまり、確率関数は底が0~1の右下がりな指数関数になり、小さい回転数ほど出やすい。
メモリアドレスや、「ほいこーろー」用乱数も、「ほいこーろー」と同じように使われる。
ただ、[$7E:A018] & $0Fでの判定後、増加判定フラグでの判定がないため、1から2に増加する時にも乱数判定で増加が止まるケースがあり、ダメージ量1があり得る。
回転数の最大値は「ほいこーろー」と同じく99である。
「ほいこーろー」は無属性だが、「わいろ」は精神属性のため、回避属性が適用されることがある。
「わいろ」も「ほいこーろー」と同じく、「単発ダメージ量×ヒット数」自体は0なのだが、回避属性が適用される時は、0/2+1が「単発ダメージ量×ヒット数 回避属性反映」である。
このため、最大ダメージ量は99 + 0/2+1で100となる。
なお、味方の防御力はダメージ量に反映されない。
つまり、防御の値でダメージ量が減ることはない。
もし、回避属性が適用されるのなら、トータルのダメージ量は以下のようになる。
(敵から味方への攻撃なのでサブルーチンは$C1/CD9F~が適用される)
$C1/CD9F REP #$20 ;Aを16bit幅に変更、Mフラグをクリア $C1/CDA1 LDA $2134 [$00:2134] ;Aに[$00:2135][$00:2134](この時点での総ダメージ量)をロード $C1/CDA4 SEC ;キャリーフラグON $C1/CDA5 SBC $20 [$00:0320] ;A - [$00:0321][$00:0320](防御合計値 0000) $C1/CDA7 BCS $03 [$CDAC] ;キャリーフラグが立っているとき[$CDAC]分岐 $C1/CDAC STA $20 [$00:0320] ;Aを[$00:0321][$00:0320]に書き込み 0000 $C1/CDAE LDA $7ECE35,x[$7E:EAB5] ;Aに[$7ECE35,x+1][$7ECE35,x]をロード 味方の回避属性適用 $C1/CDB2 AND #$00FF ;Aと$00FFで論理積 $C1/CDB5 BEQ $04 [$CDBB] ;ゼロフラグが立っているとき[$CDBB]分岐 ;ゼロフラグON 味方キャラの回避属性が精神属性 $C1/CDB7 LSR $20 [$00:0320] ;[$00:0321][$00:0320](0000)を論理右シフト (/2) $C1/CDB9 INC $20 [$00:0320] ;[$00:0321][$00:0320]をインクリメント +1 $C1/CDBB LDA $20 [$00:0320] ;Aに[$00:0321][$00:0320]をロード 0001 ;処理合流 $C1/CDBD CLC ;キャリーフラグクリア $C1/CDBE ADC $22 [$00:0322] ;A + [$00:0323][$00:0322](「わいろ」回転数) $C1/CDC0 CMP #$03E7 ;Aと$03E7を減算比較(ステータスレジスタ変更のみ) $C1/CDC3 BCC $03 [$CDC8] ;キャリーフラグが立っていないとき[$CDC8]分岐 $C1/CDC8 STA $7ECE2E,x[$7E:EAAE] ;Aを[7ECE2E,x+1][7ECE2E,x]に書き込み $C1/CDCC STA $4204 [$00:4204] ;Aを[$00:4205][$00:4204]に書き込み $C1/CDCF SEP #$20 ;MフラグON Aレジスタは8bit幅 $C1/CDD1 JSR $CE0B [$C1:CE0B] ;[$C1:CE0B]へジャンプ
「わいろ」のダメージ量nの確率は、回避属性なしなら、
nが1以上98未満:
(15/16)^(n-1)*(1/16)
nが99:
1 -(1以上98未満が出る確率の総和)
と、いうことになる。
ダメージ平均値は15.97となる。