【TAS】ドクターマリオ(FC)の知見を書けるだけ書いてみた
閉じる
閉じる

新しい記事を投稿しました。シェアして読者に伝えましょう

×

【TAS】ドクターマリオ(FC)の知見を書けるだけ書いてみた

2018-09-29 22:34
    あっという間の3ヶ月でしたね。
    ドクターマリオしかしていない気がします。
    折角なのでその成果を残しておきたいと思います。
    TAS技がメインとなります。

    ドクターマリオ何それ?って人はドクターマリオドクターマリオ医学会をどうぞ

    基本テクニック
    ・下移動は偶数フレームのみ可能です。(soft resetを行うと奇数になる場合があります)
    ・左右移動は毎フレーム可能です。(下移動と重なった場合は優先されます)
    ・カプセルの回転(A/B)もいつでも入力可能です。
    ・AとBと左を同時入力すると左に2マス移動します。
     (ただし上方向が空いていて回転できる場合のみ)
    ■■■
    ■  □□
    ■■■
    □:操作カプセル
    こういう場合は左に2マス移動はできません。

    ・A/Bによる回転は上方向に回転します。
    ですので、上側に障害物がある場合は回転できません。
     ■
     □ ←この配置はできません
    ■□■

    ■□■
     □ ←この配置はできます。(上に回転するため)
     ■

    ・SPEEDはLOW/MED/HIがありますが、下入力による落下なら速度に違いはありません。
    ただ、LOWはカプセルを投げるまでの時間も長くなるので遅くなります。
    ・これとは別にターンがかかるほど自然落下の速度が速くなっていきます。
    (下入力しない落下速度が上がります)

    配置とツモ
    ・配置とツモはレベル選択時に決まります。
     一度決定したらもう一度レベル選択画面に戻らない限り変更されません。
    ・これは起動時からのフレーム数で決まります。
    ・配置のアルゴリズムはTaoTao氏により解析済みとなります。
    ドクターマリオ (FC) LEVEL20 ツモ/初期配置表
    ドクターマリオ (FC) ツモ&初期配置シミュレータ
    概要は
    ---------
    ドクマリ初期配置概略 4*(level+1)回以下を繰り返す:
    ・乱数でx,y,色を決める。yについてはレベル別制限にかかったら振り直し
    ・目的マスが埋まってたら次のマスへ。最後まで埋まってたら諦める
    ・一間飛びで色がかぶったら適当に補正。既に3色あるなら諦めて次のマスへ
    ・ウイルスを1個配置
    --------

    ・同じ乱数でレベルが違う場合は、前のレベルから4つウイルスが増えた配置となるだけで、(前のレベルと比較して)ツモなどは変わりません。


    リセット
    ・Hard reset:普通に起動する場合と同じ状態に戻ります。
    ・Soft reset
     -レベル選択画面の情報を保持したままリセットします。
     -起動からのフレーム数もリセットされるので配置吟味の選択肢が増えます。
     (いなりはちまん氏により発見)
    ・コマンドリセット
     -1pのA,B,select,startを同時押しするとタイトル画面に移動します。
     -こちらは逆に起動からのフレームはリセットされません。(ので配置吟味がさらに増えるよ!やったね)
     -動画で実践したときはまだありません

    エミュレータ
    ・起動時とリセット時に、タイトル画面が表示されるまでに差があります。
    BizHawk(2.3.0) 、Core QuickNes : 10f
    BizHawk(2.3.0) 、Core NesHawk : 11f
    FCEUX(2.2.3) : 12f

    ・ファミコンの動画のフレームレートは60.0988139らしいです。
    なのでframe→秒変換時と動画は微妙にずれる可能性があります。
    (最初間違えていた)

    ・解像度
    横256px×縦224pxらしいです。縦240pxという説もあるらしいですが、224pxで問題なさそうです。
    動画を作る場合にひっかかりました。


    消去バグ
    消去バグとは、1回の連鎖内でウイルスを大量に消すと(14匹が目安)発生します。
    発生した場合はフリーズしたりしなかったりしますが、2コンを操作することでフリーズ解除できます。
    そして、消去バグが発生した時、そのウイルスが縦方向に消されたか、横方向に消されたかで挙動が変わります。
    縦方向:その1列すべてのウイルスとカプセルが消えます。
    横方向:その1行から下すべてのウイルスとカプセルが消えます。(※)
    ※2コンの操作によっては上方向を含めた全マスの消去が可能になります。

    TaoTao氏によってかなり解析されました。twitterのコメントを参考に書いているので間違いがあったらすいません。


    ・フリーズの原因
    処理量が一定を超えるとNMIが発生し、雑用変数 $49が書き換えられます。
    $49 は消去処理の終点を表していて、これが書き換わることで無限ループが発生します。

    ・フリーズ回避
    NMI中は、$48 は1pの入力、$49 は2pの入力と連動するようになり、書き換えることができます。
    なので、2pを操作するとフリーズが回避できるようになります。

    ちなみにキーと数値のバインドは、1byteの各bitで表現されており、押されていれば1が立ちます。
    左から AB select start UDLRです。
    例えばAが押されていれば128になります。

    この値によって終点をある程度操作することができます。
    押し方によってウイルスの消え方が変わります。
    (全部消える前に処理が止まったり等)


    ・フリーズに関しての詳細
    横バグと縦バグは同じフリーズでもループしている箇所が違うっぽいです。
    ------------------------------以下より詳細な仕組み(のコピペ)------------------------
    横バグでもフリーズすることがあるんだけど、これは縦バグのフリーズとは異質だな
    縦バグのフリーズは同じ列を延々ループしてる(終点が違う列にあるため一生終わらない)だけだが、横バグの場合なんか違うルーチン内で無限ループしてるくさい

    4連ができたとき消去処理が走る。
    横の場合、左から右へ走査し、終点の手前で消去が止まる: 始→→→終
    縦の場合、上から下へ走査し、終点の手前で消去が止まる:





    しかし、処理量が多くなるとこの消去処理の途中で割り込みがかかる

    始→☆→終

    消去中に割り込みがかかると、「終点座標が2P入力で上書きされる」よって、
    2P入力次第ではこんな消し方もできてしまう:

    始→→→→→→→
    →→終

    フィールドは内部的に 8*32 マスで、右下に達すると左上へループするため、適切に2P入力を行えば上のウイルスを消すこともできる。
    縦バグの場合も同様だが、この場合は終点を現在走査している列に合わせる必要がある。終点が違う列にあると




    ↓ 終


    こんな感じになって一生終わらない。
    基本的な考え方は以上。横バグで変なフリーズが発生したりする件については未解析。


    横バグの際に $890A-$8937 で無限ループするパターンがあるが、ここでポインタ $47-$48 を使ってるのが面白い。
    $48 は1P入力なので、1P入力によってポインタの上位Byteをいじれる。残念ながらここでの $47-$48 は読み込み用ポインタなので、そんなに悪さはできなさそうだが。
    ちなみにこの辺のコードはスプライト書き込みなので、画面がチラチラするのはそういうことです
    書き込み用ポインタをいじれると面白いんだけど、仮にできたとしても多分上位Byteしかいじれないので、できることは限られるかも?


    縦のみで6~10匹消したときのNMI発生位置を調べた(スピードHI, チート併用)
    6匹:NMI待ちループ内(処理落ちなし)
    7匹: ルーチン$D435内(多分サウンド関連)
    8匹: スプライトコピー処理$88F6内(1P入力で直せるフリーズ)
    9匹: $9486直後(縦の色すり替え可能)
    10匹: スコア加算処理$8FF4内(縦バグ消し発動)

    一応横のみで消した場合のNMI発生位置も(スピードHI, チート併用)
    6匹: NMI待ちループ内(処理落ちなし)
    7匹: ルーチン$DD15内(多分サウンド関連)
    8匹: $0300-$032F から $80-$AF へのコピー処理($9075)内
    9匹: ルーチン$9B73内(詳細未解析)
    10匹: $9225直後(横の色すり替え可能)
    11匹: 横バグ消し発動
    --------------------------------------------------------------

    ・処理量
    NMIを発生させるためには?その条件です。
    どの処理が重いのかとなりますが、一番重い処理はスコア加算です。
    消去バグの発生はほぼこれ依存です。

    ・スコア加算
    ------------------TaoTao氏の発言コピペです><----------------
    i匹目のウイルスについて、100*((スピード+1) * (i匹目に対応する値) を加える
    ドクマリのスコア加算処理は $8FF4 で、100*((スピード)+1) を消したウイルスの数に応じて規定回数加える。加える回数はテーブル $A21F を参照。
    という処理になっており、スコアがBCDで表現されていることも加味すると相当時間がかかるはず

    スコア加算($8FF4)を擬似コード化すると
    j = (i匹目のウイルスに対応する値 (1..256))
    while(j){
    score += 100*(speed+1)
    スコアの繰り上げ処理
    j++
    }
    という感じ。
    14匹目ともなるとwhileループ内が256回実行されるため相当時間がかかる(これだけで1Fの80%程度)。

    ・スコア加算ルーチンの処理量 (概算値)

    https://gist.github.com/taotao54321/65190bcd58bad955c584e6551b9a47b7

    14匹目のウイルスでは24000cycle前後かかるので、他の処理も含めれば絶対バグを起こせるはず。よって14匹消せばバグるのは確定と言っていいだろう

    13匹以下のケースだが、例えば1つの連鎖で6~11匹目のウイルスを消した場合、約18000cycleかかる。これだと他の処理を含めても届くかどうか微妙だろう
    ------------------

    ・スコア表
    -----
    01 100
    02 300(+200)
    03 700(+400)
    04 1500(+800)
    05 3100(+1600)
    06 6300(+3200)
    07 9500(+3200)
    08 12700(+3200)
    09 15900(+3200)
    10 19100(+3200)
    11 22300(+3200)
    12 23300(+1000)
    13 23600(+300)
    14 49200(+25600)
    15 49300(+100)
    16 49500(+200)
    17 49900(+400)
    18 75500(+25600)

    ・より詳細なスコア表
    https://taotao54321.github.io/appsouko/work/Game/DrMario_NES/score/
    ----
    見てもらえればわかりますが、14匹目で激増します。
    14匹目を消すとバグ消去が発生する原因はここにあります。

    また、スコア加算が原因なので、同時に複数ウイルスを消去した場合でもバグ消去は発生させることができます。
    例えば3~10匹目のウイルスを同時に消せば18800点加算処理が走るので、高確率で消去バグが発生します。
    微妙なスコアな場合は別の処理による影響で発生したりしなかったりしますが、以下による発生は確認できています。
    0~10 の10匹
    2~10 の8匹
    3~10 の7匹
    3~11 の8匹
    14の1匹

    ・その他
    ・LOWよりMED、MEDよりHIの方が処理量が多くなる時がある。

    ・音遅延

    ・BGMのタイミングによっても処理量が変わる。
    処理量計測結果:https://gist.github.com/taotao54321/f0bd4b8392fa465f891684323e342624
    処理量表示(FCEUX):https://gist.github.com/taotao54321/90de4d48324c7a9e00dedbbb5e4237cd
    処理量表示(BuzHawk):https://gist.github.com/pocokhc/354aacd6070392a5ebf85d59c316fd2e


    ・TASで使われている連鎖形
    ・シンプルな14個消し
    昔からあるウイルスを14匹消して消去バグを発生させる方法です。
    14匹目を横にする必要があります。

    ・縦バグ→横バグ
    高レベルのステージでよく見られる形です。
    縦バグを発生させて(2+8や3+7が多いです)縦バグにより、その列のウイルスを大量に消すことで、その次の連鎖を横バグにするやり方です。

    ・2+8横バグ、3+7横バグ
    低レベル~中レベルのステージで見られます。
    縦バグを挟まずに直接横バグを発生させる方法です。
    ただし、2連鎖目の7匹や8匹はすべて横消しにする必要があるため難易度高めです。


    色すり替え
    TaoTao氏により考案されているテクニック。
    FCEUXで使用できるluaが公開されています。
    ドクターマリオ (FC) NMI戻りアドレス表示 (for FCEUX)

    こちらは実際に色すり替えを行ったキーファイル
    http://tasvideos.org/userfiles/info/49083849148630968

    原理は…TaoTao氏のツイートを抜粋します。
    ------------
    タイミングがかなりシビアだが、$9225 または $9486 の直後にNMIを割り込ませると1P入力で現在見ているマスの色をすり替えられるはず。

    前者は横消し、後者は縦消しに影響する。
    後者については一応それっぽいパターンがあることは確認。

    (上記キーファイルの)ムービー末尾のL入力により、上から9行目の右端の黄色が青にすり替わり、4連ができて消える(そして縦バグも発生)
    L入力を消すと通常の消え方に戻ることが確認できる。
    このムービーでは $948D で割り込みが発生している。

    色すり替えについてもう少し
    色すり替えは4連を探す始点の色をすり替える。4連を探す処理は左から右、上から下にのみ行われるので、始点より左/上に同じ色があっても無視されることに注意
    例えば
    YRBRRY
    この図でBをRにすり替えても4連でなく3連として認識され、Rが消えない
    ------------


    1手消し
    http://www.nicovideo.jp/watch/sm33675755
    これの原理。TaoTao氏のTweetを抜粋。
    ---------------
    ドクターマリオはハードリセット時はRAM初期化を行うが、ソフトリセット時は行わない。これは $0710-$0719 に初期化済マーカを置くことで実現されている。
    よって、電源を切らずに

    ・ドクマリ起動
    ・別ゲーム($0710-$0719 を破壊しないもの)起動
    ・ドクマリ起動

    とすることで、スピードを変な値にしたままゲームを開始でき、値によっては初期配置の時点で4連がたくさんできててすぐに横バグへ移行できる。以上
    ---------------


    2p対戦テクニック
    ・配置やツモは1pと2pで同じです。
    ・2連鎖以上(同時消し含む)でおじゃまカプセルが降ります。
    ・同時の場合、おじゃまカプセルの落下は2pから先に降ります。
    ・おじゃまカプセルの落下位置と色はランダムです。

    ・ピロ彦先生が発見したテクニックです。
    おじゃまカプセルの出現位置(最上位)にカプセルがあった場合、上書きされます。
    この上書きされたカプセルが連結状態の場合は浮いた状態のままになります。
    この後の処理順ですが、
     カプセル設置→落下判定→消去判定→(おじゃまがあればおじゃま落下)
    らしいです。

    最大同時消し時に発見されたテクニックで、これにより滞空時間が稼げ、おじゃま利用による連鎖が理論上は可能になります。


    ・おじゃまカプセル
    -------- tas_suki氏よりコピペ -------
    おじゃまカプセルは消したウィルスorカプセルに対応してたはず。 たとえば、青→赤と2連鎖した場合、(左側から)青・赤のおじゃまカプセルが降ってくる(はず)。

    --------------------------------------


    未解決問題
    ・ポーズを使うとフリーズバグが回避出来たりできなかったり
    ・配置は全く一緒で特定のタイミングだけバグ消去が発生する事があったりなかったり
    (BGMのタイミング次第で処理が重くなる瞬間がある気がする)
    (3+8個では確実にバグ消去なのに3+7個ではバグ消去が起きたり起きなかったりとかすごい微妙なラインの時限定です)
    (サイクル数を求めるlua関数を使えばもう少し詳しく調べられるかも?)

    外部サイト
    ・TaoTao氏のNESを解析するための情報があるブログ(昔書いたそうです)
    http://taotao54321.hatenablog.com/entry/2017/04/11/135825

    ・TaoTao氏のgitHubGist
    https://gist.github.com/taotao54321
    ・TaoTao氏作成、LV20の配置一覧
    https://taotao54321.github.io/appsouko/work/Game/DrMario_NES/hands-lv20/
    ・Dr.MarioのRAM map
    https://datacrystal.romhacking.net/wiki/Dr._Mario:RAM_map



    広告
    コメントを書く
    コメントをするには、
    ログインして下さい。