●今回のTASに利用された主な解析結果
・ディレイスクロール
正確に計測したところ改善できそうというところから今回のTASがはじまりました。
今回はクラッシュマンステージでディレイ下スクロールの際に
アイテム1号×2からアイテム1号×1へと改善が行われました。
中規模のNMIに敵の着地音を重ねることで大きな負荷を得て成功しています。
そして、余ったアイテム1号を別の場所に配分することで、短縮となります。
処理量的にはエアーシューターでも足りるかなと思ったのですが、発射音により下スクロールを満たさないため、成功しませんでした。
また、その他のステージのディレイスクロールでも短縮ができる箇所は改善が行われています。
ディレイスクロールのために下記のLuaScriptを用いました。(また、今後ハックロムのTASなどに挑戦したい方のためにMegaMan2向けのLuaScriptも作成してあります。)
ディレイスクロール支援LuaScript (ロックマン2向け)(MegaMan2向け)
→ディレイスクロールを実際に行う際の各種支援情報を表示するLuaScript
ディレイスクロールテスト用LuaScript (ロックマン2向け)
→改造することで、意図的にディレイスクロールの状態を再現するLuaScript。経路調査向けです。
LuaScriptの詳細やディレイスクロールの詳細については下記を参照ください。
ディレイスクロールを成功させるには(日本語)
How to delay
scroll (English)
・アイテム1号、3号の上昇ルール
今回の改善点の大部分はこの考えに基づいています。
この考えを用いることで、各ステージで短縮を果たしています。
アイテム1号の上昇は毎回決まっているというわけではなく、変動します。
タイミングによって、
発射…0フレーム目上昇…3フレーム目上昇…6フレーム目上昇 ということもあれば、
発射…1フレーム目上昇…5フレーム目上昇…9フレーム目上昇 ということもあります。
このアイテム1号の上昇ルールについては、これまで良く判っていない部分が多かったので、正確に解析しました。
上昇部分のコードをトレースすると下記のようなものになります。
EECD:SEC
//キャリ-フラグセット
EECE:LDA $04C0,X @ $04C4 = $67 //$04C4: アイテム1号のY座標に関連する値
EED1:SBC $0660,X @ $0664 = $41 //0超えたときキャリ-フラグクリア
//$0664: 常に$41の値
EED4:STA $04C0,X @ $04C4 = $26
EED7:LDA $04A0,X @ $04A4 = $5F //$04A4: アイテム1号のY座標
EEDA:SBC $0640,X @ $0644 = $00 //キャリ-フラグがクリアされてるときアイテム1号のY座標を-1する
EEDD:STA $04A4,X @ $04A4 = $5F
EEE0:CMP #$F0
//画面外にアイテム1号が消える判定
EEE2:BCC $EEE7
EEE4:JMP $EF6A
この考えをまとめると、アイテム1号の上昇ルールはそれぞれ
1番目($4C4)、2番目($4C3)、3番目($4C2)、アイテム3号($4C2)に発射前に入っている値によります。
アイテム1号を発射すると$4C4は0x41ずつ減っていきます。そして、$4C4が0の境目を越えたときに、アイテム1号が上昇します。
上昇例(4C4の1フレームごとの値をトレース)
$8C->$4B->$0A->$C9(1号上昇)->$88->$47->$06->$C5(1号上昇)->$84->$43->$02->$C1(1号上昇)->$80->$3F->$FE(1号上昇)…
また、$4C4〜$4C2に影響を与える武器は下記となりました。
$04C4
:A,Q,M,C(爆風),1
$04C3 :A,B,M,Q,C(爆風),1
$04C2 :A,B,M,Q,C,1,2,3
さて、考えが定まったところで、今回も支援LuaScriptを作成しました。
アイテム1号3号上昇ルール支援LuaScript(ロックマン2向け)
「|...|」という表示は「上昇 待機 待機 待機 上昇」を表します。
つまり、このタイミングでアイテム1号1個目を発射した場合、 Y=180で、0フレーム目と4フレーム目にアイテム1号が上昇し、 4フレーム後にはY=178になります。
操作方法:
S=Seed調整別の高さリストCSVを出力する
P=高さのヒント表示「|..|.」を増やす
O=高さのヒント表示「|..|.」を減らす
Y=Item1x1Seed($4C4)をチートにより加算する
H=Item1x1Seed($4C4)をチートにより減算する
U=Item1x2Seed($4C3)をチートにより加算する
J=Item1x2Seed($4C3)をチートにより減算する
I=Item1x3Seed($4C2)をチートにより加算する
K=Item1x3Seed($4C2)をチートにより減算する
ヒント表示は増やすことができます。 (アイテム1号の40フレ後の高さもわかるわけです)
あとは、以下の手順で最適解を見つけることになります。
1:乗る直前フレームまでヒント表示を増やし、シードをチートにより変更しながら、
アイテム1号を発射したときに一番速くなるパターンを探します。
2:いいパターンが見つかったら実際のTASでは同じ上昇パターンになるように
シードの値を事前調整することで速くなるパターンの再現が可能です。
・ボスのHPのフレームルール&水中フレームルール
今回aglasscage氏が、バブルマン戦のボスのHPが溜まる処理で大きなロストフレームを出したことがあったので正確に解析することにしました。
さて、まずはボスのHP処理をトレースしてみます。
$812F:A5 1C LDA $001C = #$78
$8131:29 03 AND #$03
$8133:D0 08 BNE $813D
$8135:EE C1 06 INC $06C1 = #$00 //$1C AND
#$03=#$00ならボスのHPを加算
$813D:60 RTS
$1Cは毎フレーム増加する値で、$1C AND 0x03の結果が0x00なら、ボスのHPを加算するわけです。
普通のボス戦では、$1Cの値は調整は不可能なため、そう大きな変化はありませんが、バブルマン戦のみで大きく遅れることがあります。
疑問に思ったので正確に調べてみました。
通常4フレームごとにボスのHPが増加するはずですが、
水の中にいると、4フレームに1回、ボスのHPの計算処理も飛ばされます。
それにより、4フレームに一回くるべきのHP増加処理がスキップされ、 ボスのHPが8フレームに1回しか増加しないというタイミングが生じていたのです。
水の中フラグのめぐりあわせが悪く「8フレームに1回」のパターンが多く生じてしまうと、 大きなフレームの遅れが発生してしまうというわけです。
水の中フラグ「$FC」の値は水中にいる間にだけ「0-4」の間で循環するので、水の中にいる時間を変更することで事前調整可能です。
事前に調整しておくことで、めぐりあわせを良くし、 フレームの遅れを減らせます。
私たちの場合は、ゲートに入るタイミングで、0-4の値に改造コードを使って書き換え、良いパターンを見つけ、
それに合わせて水の外に出るフレーム数を延ばすことで、このフレームルールを回避しています。
・メカドラゴン、ガッツタンクのフレームルール
メカドラゴンとガッツマン戦では、爆発処理にフレームルールが存在します。
$B2の値が、爆発後の暗転処理、ロックマンが棒状になる処理のカウンタとなっています。
この図では、ボスを倒すのはv2のほうが速いのに、ブラックアウトが開始する時間が同一なのが判ります。
トレース結果は下記です。
9131 LDA $1C
9133 AND #$0F
9135 BNE $9164
915B DEC $B2
9164 RTS
$B2の値は16フレームごとに減算され、$0Cが#$0Cになったときに暗転処理が始まります。
$1Cの値は、毎フレーム増加するだけのカウンタなので、このフレームルールの変更は不可能です。
つまり、ロックマン2では16フレームほど速くなると、W1やW3で短縮できるということになります。
今回は、アイテム1号の上昇ルール改善により、W1でフレームルールを突破し、短縮となっています。
・当たり判定移し
クラッシュボムの爆発中に敵に体当たりすると、当たり判定がロックマンの位置に移るという有名なテクニックがあります。
しかし、この機構がなぜ生じているのかは謎が多かったので、今回正確に解析してみました。
トレースは下記となります。
$E606:BC 90 05 LDY $0590,X @ $0594 = #$00 A:01 X:04 Y:74 P:nvUbdIzc 当たり判定番号(武器)
$E609:B9 DC D4 LDA $D4DC,Y @ $D4DC
= #$00 A:01 X:04 Y:00
P:nvUbdIZc A=D4DC ?
$E60C:65 08 ADC
$0008 = #$74
A:00 X:04 Y:00 P:nvUbdIZc A+0008
$E60E:A8
TAY
A:74 X:04 Y:00 P:nvUbdIzc
Y=A
$E60F:38
SEC
A:74 X:04 Y:74 P:nvUbdIzc
$E610:A5 2E LDA
$002E = #$14
A:74 X:04 Y:74 P:nvUbdIzC
2E=敵のX座標上位
$E612:FD E0 06 SBC $06E0,X @ $06E4
= #$40 A:14 X:04 Y:74
P:nvUbdIzC A-(6E0-6EF画面内での武器のX座標)
$E615:B0 04 BCS
$E61B
A:D4 X:04 Y:74 P:NvUbdIzc キャリーフラグがセットされている時にブランチ
$E617:49 FF EOR
#$FF
A:D4 X:04 Y:74 P:NvUbdIzc A
XOR #$FF
$E619:69 01 ADC
#$01
A:2B X:04 Y:74 P:nvUbdIzc A
+ #$01
$E61B:D9 E1 D4 CMP $D4E1,Y @ $D555
= #$4C A:2C X:04 Y:74
P:nvUbdIzc ● D4E1+Y:当たり判定の幅(X座標)
$E61E:B0 11 BCS
$E631
A:2C X:04 Y:74 P:NvUbdIzc キャリーフラグがセットされている時にブランチ(X座標が一致)
$E620:38
SEC
A:2C X:04 Y:74 P:NvUbdIzc
$E621:A5 00 LDA
$0000 = #$64
A:2C X:04 Y:74 P:NvUbdIzC
$E623:FD A0 04 SBC $04A0,X @ $04A4
= #$4E A:64 X:04 Y:74
P:nvUbdIzC 4A0-4BF Y座標上位
$E626:B0 04 BCS
$E62C
A:16 X:04 Y:74 P:nvUbdIzC キャリーフラグがセットされている時にブランチ
$E62C:D9 81 D5 CMP $D581,Y @ $D5F5
= #$1C A:16 X:04 Y:74
P:nvUbdIzC ● D581+Y:当たり判定の幅(Y座標)
$E62F:90 0F BCC
$E640
A:16 X:04 Y:74 P:NvUbdIzc 衝突 キャリーフラグがクリアされている時にブランチ(Y座標も一致)
$E640:A4 A9 LDY
$00A9 = #$08
A:16 X:04 Y:74 P:NvUbdIzc A9 現在の特殊武器番号
この結果をまとめると
1:ダメージを受けると$06EEがロックマンのダメージの飛沫の座標に書き換わる
2:$06EEは武器のX座標や当たり判定番号としても使われている。
3:再度ダメージを受けると発射されている武器と敵との衝突判定処理が走る。
3:衝突判定処理の途中で「当たり判定の幅」や「当たり判定の高さ」が1のときの$06EEの影響を受け狂う
4:その結果、当たり判定の幅や高さが大きくなり敵と衝突したと誤判定され、当たり判定移しが起きる
当たり判定のX座標の幅≒Memory($D4E1,$06EE) 最大値は$D575のときの#$50
当たり判定のY座標の幅≒Memory($D581,$06EE) 最大値は$D678のときの#$FF
たとえば、W4で$06EE=0x46のときの当たり判定移しを考えると、
当たり判定のX座標の幅=($D4D1,0x46)=$D527=0x30
当たり判定のY座標の幅=($D581,0x46)=$D5C7=0x28 となる。
通常時の当たり判定の幅はこれくらい狭いが、
体当たりをした瞬間これくらいの当たり判定の幅になり、離れた場所にある敵も撃破することができる。
調整について考えると
1:$06EEを調整するには事前にダメージを受ける必用がある
2:武器の種類は問わない(クラッシュボム以外でも調整すればX方向でもY方向でも成功する)
3:当たり判定の幅や高さは$06EEの値によって参照先のメモリが変わるためである。
つまり、これまで考えられてきた$06EEが特定の範囲内なら成功するというのは間違い。
$06EEの値を00〜FFの範囲で変更してみて、
当たり判定の幅や高さとして読み込まれる値を確認するのが良いと思われる。
たとえば、W4の1回目の当たり判定移しは、$6EE=#$74の他に#$1Cでも成功するのである。
4:当たり判定の幅や高さを調整で最大化すると、かなり遠方まで当たり判定が届くことがある
・画面ズレ表示支援Lua
画面ズレ状態だと、岩男が本当はどこの地形にいるか
良く判らないことが多いので、 作ってみたのがこのLuaScriptです。(要LuaGD)
実際のロックマンがいるマップおよび位置が表示されます。
ニコ動のほうでは、このスクリプトをピロ彦先生がLua for aviutl向けに移植してます。
ロックマン2画面ズレ表示支援Lua(全ステージ対応版)