ごちゃログぴこっ

はなまるデジタル創作紀行(DTM、TAS、いろいろな技術)

TAS用エミュレータの機能紹介

TASに興味がある方、エミュレータ開発者の方にひたすら機能を紹介する長い記事です。

すべてのTAS用エミュレータがここに書かれているすべての機能を有しているわけではありません。TAS用エミュレータオープンソースなので、これまでにない画期的なアイデアがあればぜひあなたの手で実現してみせてください!

用語

必要そうなものだけあらかじめ簡単に説明しておきます。

エミュレータ(emulator)

前提知識とみなして多くは語りませんし、尋ねないでください。まったく知らない人のために、アプリケーションの雰囲気のみ簡単にお伝えします。

ここで言うエミュレータは、ゲーム機本体の代わりをするアプリケーションのことです。スクリーンショットから見て取れるように、だいたいはメニューとゲーム画面からなるシンプルな外観を持ちます。

コントローラ入力はPCゲームのように、キーボードあるいはジョイスティックでおこないます*1。その他の補助機能は一般のアプリケーションのように、メニューから項目を選択したり、ショートカットキーを用いたりして使います。

ちなみに、エミュレータと区別して、本物のゲーム機は実機(console)と呼ばれます。

フレーム(frame)、フレームレート(framerate)、FPS(frames per second)

これらの用語は、一般の動画の世界で言われるのと同じ意味で用いられます。フレームというのは動画を構成する最小単位*2で、秒間のフレーム数をフレームレート、FPSと呼びます。これらの意味合いに関してはフレームレート用語解説 - アニメのフレームレートまとめwikiその他多数のサイトに解説があると思います。

通常、1フレームはコントローラの入力が読まれる最小間隔であり、操作の最小間隔です。TASがフレームという単位を重要視する理由はここにあるのです。TASで言う1フレームは何秒程度のものなのか、すなわち各種ゲーム機のフレームレートに関しては誰しも疑問に思うことかと思いますが、これに関しては「1フレーム = 1/60秒」くらいと覚えておけばだいたいあっています。

より厳密には 60.00 というわけではありません。TASVideosに実機やエミュレータのフレームレートに関するトピックが立てられたことがあります。より詳細な数値が知りたい方は参考にしてください。

desync(同期ずれ)

エミュレータの不具合で、動画記録時の状況を動画再生時に再現できないことを指します。

desync の根本解決にあたってはエミュレータを修正する必要があります。詳細は「なぜTASはdesyncする?」という別記事を書きましたので、そちらをご覧ください。

基本(有名どころ)

ステートセーブ・クイックセーブ(savestate, quicksave)

どこでもセーブ」という俗称の通り、好きな箇所でゲームの状態を保存・読込することができます。なにかミスをしてしまっても、その直前でセーブしておけば、とっさにそこからゲームをやり直すことができます。保存されたどこでもセーブのデータのことはステート(state、savestate)と呼びます。動画記録中に作成されたものをmovie snapshotと呼ぶこともあります。

言わずもがなTASに必須の機能で、TASの代名詞とも言えるものかもしれません。ゲームをロードして動画の記録を途中からやり直すことを「追記(rerecording)」、動画を記録するにあたっておこなわれた追記の合計回数を「追記回数(rerecord count)」と呼ぶのが一般的です。

動画記録(movie recording)

ここで言う動画はaviやmp4などの一般のマルチメディアファイルのことではなく、コントローラの入力操作を延々記録したエミュレータ独自の動画形式(キームービー)のことです(例: BKM)。混同を避けるため、前者を video、後者を movie と呼ぶ場合が多いように思います。リセットも記録できることが望ましいです。

コントローラの入力のほか、必要であればセーブデータ(SRAM)を含むことができます*3。また、エミュレータに記録タイミングに影響を与えるような設定項目がある場合は、それらの設定の記録時の状況も埋め込みます。

記録した動画を他の人と共有するためにアップロードする場合があります。TAS動画制作者の間では、YouTube のような動画サイトに映像を投稿する傍ら、TASVideos のアップローダーにキームービーもアップロードするのが一般的です。キー入力があることで、他の人が参考にしたり、指摘したり、引き継いだりすることが容易になるメリットがあります。

スロー(slowdown, slow motion)

ゲームの動作速度を通常より低い割合に落とします。機能としては実装されている場合がほとんどですが、TAS動画制作には利用しません(基本機能に入れたのはまず間違いなく実装されているという理由から)。代わりにframe advanceを用います。

コマ送り(frame advance、フレームアドバンス、1フレ入力)

フレームに関しては冒頭に説明したとおり、動画記録の最小時間単位です。Frame advanceは1フレームだけゲームを動作させて、エミュレータをポーズ状態にする機能、いわばコマ送り機能です。国内でも英語の名称がそのまま(あるいはカタカナ書きで)用いられることが多いです。(国内において)チャット等の比較的省略表現が用いられやすい場では、しばしばFAと略されることもあります。

追記と並んでTASに必須の機能です。追記とframe advanceがあれば、いかにもTAS動画らしい見た目の動画を作ることは誰にでも可能です。難しいのは「最速」のレベルまでそれを突き詰めることなのです。

高度なエミュレータではラグフレームをスキップする機能を有していることもあります。ラグの認識に関しては後述のラグカウンタの項で説明します。

早送り(fast forward)

可能な限り高速にゲームを動作させます。時折ターボと呼ばれることもありますが、連射機能との混同を避けるためかあまり使われない表現です。

TAS動画制作でも下記のような用途で重宝します。

  • 長いデモシーンを飛ばすため
  • 制作済みパートを高速再生し、desync しないことを確認したり、再生終了地点から続きを作成したりするため
  • bot の総当り処理を高速に処理させるため

ボタンを押している間早送りするタイプと、ボタンを押すたびに等速・高速の切り替えをするタイプがあります。どちらも実装されていると使い分けもできて便利です。

連射機能

ここで述べるのはエミュレータ自身の持つ連射機能です。時折ジョイパッドが連射機能を有していることがありますが、TAS動画制作における利用は推奨されません(周期が不確実なため)。

ボタンを押して、離してという一連の操作をエミュレータが自動的におこなうようになり、隙のない正確な連射が可能になります。通常1フレーム間隔(60fps時秒間30連射)の連射をおこないますが、エミュレータによってはこの間隔を設定することもできます。

キーを押している間は連射するという一般的な連射機能のほか、解除するまで連射状態を持続するハンズフリー連射機能もあります。後者はAutofireの項であらためて説明します。

高度なエミュレータではラグフレームをスキップして連射する機能を有していることもあります。ラグの認識に関しては後述のラグカウンタの項で説明します。

TAS Input Plugin

TAS方面の人でも何の話かと思ってしまうかもしれませんが、対象ゲーム機によっては重要なのでここで紹介してしまいます。

スクリーンショットニンテンドー64のTAS Input Pluginの動作例です(フォーラムから引用)。N64のコントローラにはアナログスティックがついています。いかに自由なタイミングで入力ができてもそこはアナログ、理想的な角度と強さを入力するのは容易ではありません。そこで、コントローラを用いる代わりにパラメータを数値入力する方法を提供してくれるのがTAS Input Pluginです。

TAS Input Pluginというのは広く普及している一般名詞というよりは、上述のN64用入力プラグイン固有の名称という感じです(そもそもこのような機能が必要な機種が、現状ではN64以外にないと思われます)。

プラグイン:知っている人にとっては常識かもしれませんが、N64PSXなどのエミュレータGPU、SPU、CDR処理など、各処理をプラグイン(DLL)として実装させ、エミュレータ本体はそれらを束ねることで動作するようになっています。こうすることで、本体の修正なしにゲーム・環境に応じた好きな実装を組み合わせて使うことができるのです。上記のTAS Input PluginはN64のPADプラグインの一種なのです。

メモリ関連機能

TAS 制作に欠かせないメモリ関連の主な機能をご紹介します。

メモリウォッチ(Memory Watch)

現代TAS制作には欠かせない、メモリ上の値を表示するための機能です。つまり、通常は画面に表示されないさまざまな内部の値を表示することができます。

下記の Memory Search と組み合わせることで、重要な値を見つけ出して表示できます。表示するのはたとえば、キャラクターの位置と速度、体力、ゲーム内部の時間、乱数などです。

メモリ検索(Memory Search, aka. Cheat Search)

Memory Watch の項で述べたとおり、目的の数値が格納された変数のアドレス(場所)を探す機能です。

Memory Search はメモリ領域の個々の内容に対して値の比較を繰り返すことで、候補を絞り込んで目的のアドレスを見つけます。「さっきと違う値になったものを探す」とか「100より小さい値を探す」とかで検索できます。

検索の具体例を挙げましょう。ある敵の体力が格納されているアドレスを知りたい場合を例に、検索候補の絞り込みの概念を示します。

  1. 目的の敵に遭遇します。同時に「検索開始(検索結果をリセット)」します。
  2. 敵を攻撃してダメージを与えます。敵の体力は最初よりは減っているはずですので、「最初の値よりも現在の値が少ない」変数のみに候補を絞り込みます。
  3. さらに敵を攻撃してダメージを与えます。敵の体力はさっきよりも減っているはずですので、「前回検索時の値よりも現在の値が少ない」変数のみに候補を絞り込みます。
  4. さらに攻撃したら敵が倒れました。マイナスになっていなければ体力は0のはずですので、「値が0」の変数のみに候補を絞り込みます。

こうした絞り込みを繰り返して目的のアドレスを探します。Memory Searchの形はエミュレータによって多少異なりますが、基本的な概念は皆同じです*4

Cheat Search という別名が示すとおり、この機能は改造コードの検索にも用いられます。改造コードの中には特殊な形式のものもありますが、基本的には「書き換え対象のアドレス」と「書き込む値」からなる形式であることがほとんどです。そのため、改造コードの情報を集めることでも、有用なメモリアドレスを知ることができることがあります

改造コード(Cheats, RAM hacking)

通常、TAS動画はゲームの改造はしないという規則のものに作られるものなので、改造コードはTAS動画に使ってはいけないものです。しかし、制作前の調査段階では有用な機能として活用することができます。

メモリの値を任意の値へと強制的に変更することで、体力やアイテムが減らないようにしたり、キャラを無敵状態にしたり、通常あり得ない速度で移動させたりすることができます。調査用にゲームを一通りクリアした状態のセーブデータがほしいときには、こういった機能を積極的に活用すると効率的です。

改造コードの情報を集めることは、メモリアドレスの情報を集めることとほぼ同義です。これに関しては上記Memory Searchの項に記してあります。

メモリビューア(Memory Viewer, Hex Viewer)

メモリ内容の閲覧(・書換)をおこなう機能です。一般的なバイナリエディタ(hex editor)の形をしていて、より広い範囲を見渡すのに向いている点が Memory Watch と異なります。16進表示される形に注目して、Hex Viewer と呼ぶ方が多いかもしれません。

そのほかよく使う機能

まだまだかゆいところに手が届く機能がいろいろ!

入力キー表示(Input Display)、フレームカウンタ(Frame Counter)、ラグカウンタ(Lag Counter)

それぞれ異なった機能ですが、情報表示系ということでまとめて紹介します。いずれも重要な機能です。

Input Displayは、その名のとおりコントローラの入力を画面に表示する機能です(スクリーンショット左下)。自分が入力した内容の確認にも使えますし、他の人の動画を入力とあわせて観賞する目的にも使えます。押されたボタンを文字で表示するもの、コントローラ型の図を表示してくれるものがあります。この表示を利用して文字などを表示させる、input animationに利用されることがしばしばあります。JXQさんのスーパーメトロイド100%Mr.さんのスーパーマリオワールドany%はその代表例です。

フレームカウンタ(frame counter)は、動画の再生状況をフレーム単位で表示する機能です*5スクリーンショット左上、上段)。ある地点までの経過時間を知るのに用いたり、ある動作にかかるフレーム数を計測したりするのに用います。

ラグカウンタ(lag counter)は、ラグフレーム数の合計を表示する機能です(スクリーンショット左上、下段)。ラグ(処理落ち)がいつ、どの程度起きたのかを把握することが容易になるので、それらを積極的に除去したいときに役立ちます。

ラグ(処理落ち)とは、処理量が多すぎるために本来1フレームでおこなわれる処理が1フレーム以内に完結せず、動作速度の低下となって表れる現象です。TASはより早くゲームを終えることを目標としているのですから、ラグは当然邪魔な存在となります。

正確に言えば、ラグカウンタが検知するのは入力を受け付けないことが確実なフレームです。ゲームのプログラムは通常、ハードウェアレジスタと呼ばれるような領域にアクセスしてコントローラからの入力を知り、それに応じて処理をします。ラグカウンタが「ラグ」としてカウントするのは、このような入力処理がおこなわれなかったフレームです。それゆえ、ロード処理やデモシーンもカウントの対象になりえますし、フレームごとの割り込みの中で入力をおこなっているようなゲームでは、ラグカウンタは理想どおりには動いてくれません(ラグカウンタが反応しない例: ロックマンX)。

Autohold, Autofire

AutoholdAutofire特定のキーを押しっぱなし*6、あるいは連射しっぱなしにする機能です。適当な日本語を与えるなら自動押下自動連射といった名前になるのでしょうか。

Aボタンを連射状態に切り替えるキー、Bボタンを連射状態に切り替えるキー……と、ボタンごとに切り替えキーを割り当てできるエミュレータもありますが、どちらかと言えばAutohold用キー、Autofire用キー、解除用キーの3つを用いる形が一般的かと思われます[要出典]。Autoholdキーを押しながら押しっぱなしにしたいキーを押すことで押しっぱなし状態を設定、同様の操作を繰り返すことで状態を解除、Autofireも同様の方法で設定、解除キーでそれらの状態をすべて解除……という具合です。

Autofireを用いると、キーボードの同時押し制約を気にしなくて済みますし、多くのボタンを同時に押すために複雑に指を置く必要もなくなります。その応用として、一人のプレイヤーが複数のコントローラの入力をおこなえば、擬似的な多人数プレイ動画を作ることができます

巻き戻し(Rewind)

ゲームの状態変化は非可逆なので、原理的には巻き戻すことは不可能です。しかし、「小刻みにステートを記録しておいて、それを連続ロードすることでスムーズな巻き戻しを可能にしよう」というパラパラ漫画的な発想で巻き戻しを実現しているのが Rewind という機能です。

Rewind 機能を有効にすると、一定時間ごとに自動でステートが記録されます。記録間隔とスロット数はユーザ側で設定します。密にステートを記録するほど詳細な巻き戻しが可能になります。動作速度がボトルネックとなるので、ステートはディスクには出力せず、メモリ上で保持する実装が望ましいです。

スローダウンと同様、TAS制作よりもむしろリアルタイムのプレイで利用すると楽しい機能です。

ムービーエディタ(Movie editor)

http://cdn-ak.f.st-hatena.com/images/fotolife/G/GOCHA/20090405/20090405172833.png
一部の先進的なエミュレータは、ムービーのキー入力を Excel のようなインタフェースで編集できる機能を有しています。

なお、近年ではムービーファイルのフォーマットが、テキストファイル(を圧縮した形式)であることが多くなりました。この場合、特別なエディタを使わなくても、メモ帳などのテキストエディタで一部のキー入力を変更することができます。

より古い時代には、TASVideos / Emulator Resources / Formats でファイルフォーマットを確認しながら、Stirling> などのバイナリエディタで慎重に編集することも実施されていました。時代の進歩を感じます。

エディタを使わなくて良い方向性にシフトしているものの、個人的にはまだ理想のエディタを追求する余地があるように感じています。わたしは過去にMIDIシーケンサのようなピアノロール式の内蔵エディタを提案しました(画像編集による仮想スクリーンショット)。まだまだ素晴らしいインタフェースが登場することに期待したいです。

デバッガ(Debugger)

プログラミングやゲーム機の仕様を知る人向けの高度な機能です。十分な知識を持った人が使うことで、ゲーム内部の詳細な動作を確認することができます。

たとえばフレームよりもさらに細かい「命令」単位で実行したり、CPU が持つ変数のような「レジスタ」の値を書き換えたりできます。

代表的な機能の名前をいくつか挙げておきます。

  • アセンブル(disassemble): ゲームが実行する命令列を表示できる
  • ブレークポイント(breakpoint): 特定の命令でエミュレータの実行を一時停止させることができる
  • トレースログ(trace logger): プログラムの実行経過を逐一出力できる

上述のとおり高度な知識を要しますが、TAS の成熟にともなってプログラミングの知識をフル活用した TAS も存在するようになってきました。「任意コード実行(Arbitrary Code Execution; ACE)」はその最たる例と言えます。

その他の実装が望ましい機能

少しTAS制作の本流からは外れるものをリストアップしておきます。

  • AVIファイル出力(Export to AVI)
  • ショートカットキー編集(Key remapping)
  • グラフィックレイヤーの表示・非表示切り替え

マイナーな機能

またの名を「使ったことがない機能」。あまり多くのエミュレータに実装されていない機能や、聞いたことがあるけれど見たことがない機能に言及します。

ステートの「元に戻す・やり直し」(Savestate Undo)

上書きしてしまったステートを読み込む機能です。上書きされるステートをエミュレータが自動的にバックアップすることで実現されます。FCEUXに実装されているそうです。

ステートビューア(Savestate Viewer)

フォーラムでこのような機能の要望を耳にしたような覚えがあるだけで、実在の機能を見たことがありません。おそらく現存しません。

保持しているステートの閲覧・入出力を効率的におこなう補助をしてくれるものと思われます。実在する機能がないのでどのような図を思い描いていいのか悩むところですが、個人的にはビジュアルノベルのセーブ選択画面のように、スクリーンショットのサムネイルや時間などの情報を表示したウィンドウのようなものを想定しています。その形が正解だとすれば、ZSNESのステート一覧表示はそれを実現したものと言えなくもないでしょう。

savestate treeという言葉もどこかで聞いた覚えがあります。上書きされたステートを含めた履歴のツリーを提供する機能でしょうか。ビューアとの関連も深いと思われる話です。

LuaスクリプトLua scripting, EmuLua)

一言で言うと、簡単なプログラミングで機能を作るための機能です。

その手軽さ、応用性の高さから、さまざまなTAS制作で使用されています。TAS制作以外でも楽しめる機能です。

Lua とは

Luaプログラミング言語です。「汎用性が高い」「動作が高速」「比較的容易に実装が可能で、移植性に優れている」といった特徴から、組み込み(特定のソフトウェア上で動作する機能拡張用言語)としてよく用いられます。

言語のノリはどことなく JavaScript に似ている気がします。

for i = 1, 9 do
  for j = 1, 9 do
    io.write(string.format("%2d ", i * j))
  end
  io.write("\n") -- new line
end
EmuLua

この Luaエミュレータ上で実行できるようにしたのが Lua Scripting 機能であり、しばしば EmuLua とも称されます。

EmuLua では、追加で提供されている関数を呼び出すことで、エミュレータの状態を取得したり、エミュレータの動作を制御したりすることができます。たとえば以下の関数があります。

  • メモリの読み書き
  • ステートの読み書き
  • ゲーム画面の上に好きな絵を描ける(半透明の重ね合わせも可能)
  • 動画の再生・記録の開始・停止。速度変更などの動作制御
  • コントローラ入力、フレームカウンタ、ラグカウンタ、動画を読み書きしているかなど、各種状態取得
  • キーボード入力、マウス座標などユーザ入力の取得
  • ファイル入出力、GUIウィンドウ表示 ※EmuLuaの機能ではないですが紹介。前者はLuaの基本ライブラリで、後者はiup等のモジュール拡張で可能です。
  • 各種処理はいくつかの特定の操作時・タイミングにあわせておこなえる(フレームエミュレーション直前、フレームエミュレーション直後、画面描画直前、ステート入出力時、特定メモリアドレスの読み・書き・実行時など)

これらによって実現できることは無限大です。

  • 汎用的な便利機能
  • 特定ゲーム向けの総当りbot
  • 特定ゲーム向けの画面に各種ステータスを表示するスクリプト(HUD)
  • メモリの読み書きなどを駆使して、大胆に新たな遊びを開発してしまうスクリプト

発想次第でまだまだ応用の余地がありそうです。

実装状況

実装状況およびドキュメントの整備情報については、エミュレータごとに異なります。

まずは TASVideos / Lua Scripting を確認し、使用したいエミュレータの情報を探してみてください。

2016年現在、多くの機種のエミュレーションが BizHawk というマルチエミュレータに統合されてきています。BizHawk の Lua は他と異なる独自の様式を持ちますが、今後の主流として学ぶ価値はあります。

C/C++ 製のエミュレータの実装は、派生(分裂)と独自改良が行われておりカオスですが、非常に良好な状況にあるのは DeSmuME(DS)と Gens rerecordingメガドライブ) です。とくに他のエミュレータスクリプト機能を移植したいと考えている方には、一見の価値ありとおすすめします。

入門の扉

EmuLuaに手を出す以前に、スタンドアロンLuaをインストールして、まずはLuaという言語に関して学ぶことを個人的にはおすすめします。Lua公式ページほか、いくらかの解説サイトをあたれば、インストールに困難を感じることはまずないでしょう。

リファレンスマニュアルは学習を目的として読むにはあまり向かないので、入門向けの解説サイトを探して読むとよいでしょう。わたしはKaretta|Luaプログラミング入門でひととおりの言語の雰囲気をつかみました。

エミュレータによっては昨今サンプルスクリプトを添付しているので、まずはそれらを参考にするのが第一歩としてはおすすめです。まずは画面に何かを表示してみるような簡単なものがおすすめです。

エミュレータ特有のイベント処理さえわかれば、あとはほとんど通常のプログラミングです。リファレンスとサンプルをあたりながらがんばってみてください。

サンプル -映像で見るEmuLuaの世界-

YouTubeに先人たちの素晴らしいスクリプトの動作例があるので紹介します。これらのソースはFCEUXのサンプルに含まれています。XKeeperさんとmiauさんのスクリプトの楽しさにはたびたび驚かされています。

もうひとつ、最近書かれたものなのでサンプルには含まれていませんが、EmuLuaでテトリスの通信対戦を実現している驚きの動画。

以下、わたしが書いた半端なSnes9x用スクリプトの動画もついでに掲載。まずは初スクリプト、SMWのデバッグパッチの再現+α。

続いてはマウスカーソルグラディウスを動かすだけの簡単なお仕事です。

マウスカーソル操作に絡んでまた他者製スクリプト紹介。WiiハンドルF-Zeroを遊んでいます。よく思いつくものです。

もっといろいろ見てみたいですね。あなたの力作もお待ちしています。

*1:TAS制作者にもキーボード派とジョイパッド派がいるようです。ジョイパッドはゲーム特化のデバイスであること、同時押しの制約を受けにくいことが魅力です。一方、キーボードにも多数のキーがあるという利点があります。

*2:大多数の TAS はフレームを入力の最小単位としていますが、昨今は命令単位でタイミングを狙ってリセットするような TAS もわずかに存在します。

*3:セーブデータの不正改変を見抜くことの困難さゆえ、TASでは基本的にはまっさらな状態からゲームを開始します。クリア後に出る隠しキャラを用いた動画を記録したい場合などはセーブデータからゲームを開始しますが、この場合もセーブデータの制作過程が明確であることが求められます。既存のTAS動画から得られるセーブデータを用いるか、あるいはクロノトリガーのつよくてニューゲームTASのように、セーブデータ作成用の動画を書き下ろすのが一般的です。

*4:スクリーンショットに示した Gens rerecording の RAM Search は機能が優秀なため多くのエミュレータに移植されています。2016年現在では BizHawk の実装が最も洗練されていると思います。

*5:TAS動画制作ではフレーム単位で表示させるのが普通ですが、設定によって一般的な時間表記で表示できるエミュレータもあります。また、近年は動画再生時でなくともフレームカウンタを表示させられる形式が一般的で、この場合はリセットからの経過時間を表示します

*6:より正確には、押した押してないの情報を反転させるような実装であることが多いです。そうすることで、1フレームだけキーを離すような操作もAutoholdの解除なしにおこなえるようになります。