箱エミュ弄り:xenia現状

 アクセス数が(あくまで当社比で)伸びてると『EDFのセールかな?』ってなるこの頃ですね。
 私の方はようやくDLC1のHARDクリアまで漕ぎ着けました。
 正直大変めっちゃ好みの内容でございましたが、DLC2はうーん、これはまた5のチャレンジミッションの路線なのだろうかと。これを40面はきっついかなぁ、、。 前回に増援タイミングを知るのに通信重要とか書いてたら、成る程そう来たかーと。
 デジボク2も折角だからやってあげたいけどこの調子だといつになるのか、先にやったら6再開はまず無理なんで、、(難易度落差的に)。

 さてと年の頭に少し触れていましたが、今回はドリクラ話と言うよりもXbox360エミュレータその物のお話。
 プログラム的にはめっちゃ作業してますが、傍目に見える成果はちょっと一部機能追加したくらいなのでもう暫く動画投稿は様子見になるかなと。色々思う所もあるのでそちらは急いでいないというか、悪しからずで期待している人にはすみません。


●xenia-canaryの描画高速化
 xboxエミュレータxeniaには本家と、その派生xenia-canaryがありまして。
 現状は本家でも(自前の改修も含めた上で)十分動かせているのと、canaryはcanaryで色々問題もあったので使っていなかったけれど、今回ふと改めて試してみたら「あ、これ描画ロジックめっちゃ改善してる」
 自分でへこへこと最適化だの何だのしていた話が、全部canaryでは見事に解決して不要になっていたのですね。
(※ただ一応言うと、描画最適化に伴うパーツ描画順制御は他の改造にも関わっているし、分割描画処理の話はそれ自体が二画面改造の改修に繋がっているので、どちらも別に無駄にはなってないのが救いですね。)

 canaryでは大分前からアセンブラの最適化だの内部処理の見直しで「super boost」だとか言っていたのは見掛けていたんですが、その時はまだそれ程大きな変化があった訳でもなく。如何せんそれと同時にパフォーマンス表示用のprofiler機能が無効化されてしまっていたので、その後どう改善されていったのかを当面知る由もないまま。(ビルドレベルでoffになっていただけだというのをつい最近知った)
 実際は更にそこから続けて内部ロジックのリファクタリングにも手を広げられて行った結果、件の描画問題もすっかり解決されておりました。

 以前に触れた際、一応当時は控えめに「エミュ本体のロジックと噛み合ってないのだろう」と書いてましたが、結局そこもプログラム上で効率化可能な問題だったと。
 まぁ強いて言うなれば、このcanary改修版だと無印もめっちゃスムーズに描画されるようになるんだけど、一つ本家では起きてなかった事象が発生するようにはなってます。
 pauseで止めて実質の処理落ちを発生させた際にただフレームが飛ぶのではなくて描画がバグり出す。内部効率化のトレードオフでエミュレーションとしての正確性は犠牲にしていたりするのかもしれない。もっとも秒単位で飛ばすという普通は発生しないケースなので想定外の計算が発生した可能性はあるけれど、一応本家では起きない話なので。

 ともあれ普通に使う分には特に問題なく、無印・ZERO共にめっちゃ自然に描画されるようになってました。俺の苦労は一体というレベルで、、。
 ってまぁ、この手の改善が始められたのが自分の改造より後の時期なので仕方ない話ですけどね。当初の描画最適化も二画面化改造なんかも全て一区切り付いた後のタイミング。
 ただその後で更に高速化調査で界王拳だのと息巻いていた頃合いにはcanaryではとっくに最適化も終わっていたので、双方の事情に精通していればとんだピエロ状態だったというか、ベジータには鼻で笑われる話だったのでしょうけどね。そんな何一つ苦労なく最長老様に潜在能力の底上げをしてもらった二代目主人公の事なんて知りませんよ。
 何であの時canaryのこと思い出さなかったんだろうなと思いますけど、後述の問題で諦めてたんだっけ?

 以下が容赦ない比較図。
img(本家(+最適化改造)) img(canary)

img(本家・wait取っ払い)
img(canary・同上)

 あ、うんめっちゃ高速化してますわこれ(苦笑)。
 今でも制服で120fps越えくらいは出来てたけど、200fps越えてますわ。(標準解像度で)

 ただまぁ一応内情として補足しておくと、実際には一部のCPUスレッド側のボトルネックが改善されたという所のようで、上記はその結果として全体の回転率が上がっている模様。
 しかし倍解像度で多画面同時描画みたいにGPU自体に負荷を掛けまくっている場合は大きくは変わらず。CPU処理はとっくに終わっていても、GPU描画自体がもう60fpsギリギリだと。
 それでもCPU側が軽くはなるので若干余裕も出て録画のフレームドロップ率は少し下がるかなという感じ。これまでは三画面は水着くらいが限界だったけれど、スカート衣装系も少しは選択肢に入れられるようになるかな、どうだろう。


 という訳で録画レベルではcanary版で若干変わるかなどうかなくらいの結果でしかないんですが、何でわざわざこんな事をやっていたかというとですね、「canaryに移行するかどうか」、それ自体が大問題でありまして。

●xeniaプロジェクトの現状
 このxenia本家と、派生xenia-canary
 大分以前からなんですが残念ながら本家の方はもうほぼほぼ開発休止状態になってしまっており。PR(プルリクエスト)は積み重なっても中核メンバーが不在なのか何なのか何一つ処理されない。その状況が長く続く内にcanaryの開発内容をフィードバックしてくれていた人もいよいよ見切りを付けてPRは上げなくなってしまって久しい。そして他の修正PR等もcanaryにしか上がらなくなったので、この先何か大きな影響のある修正が入った場合はcanaryを使わざるを得なくなってきた状況。

 それはもう大分前から察していても本家を使い続けていた大きな理由は、canaryは本来機能拡張テスト版なのでエミュ本来の安定性を求めるなら本家であって欲しかったという事と、実際canaryではかなりド派手な最適化改修が行われてしまったことで最早「自前の改造コードが全く全て何一つ動かなくなってしまっていた」というところ。移行しようにも出来るものではなかった。

 年の頭にちょっくら書きましたけどもその再掲、
「ブリザードの大集団とHPが1/4になったデビルロードが同時に襲いかかってきたようなもの」(無論FC版基準)
 当初はザラキやメガンテ系の確率死呪文祭りの喩えとしてロンダルキアを思い浮かべただけの筈が、改めて確認したらDQ2のメガンテって唱えられたら「全滅確定」とかいう超クソゲーじゃないですか(笑うしかない)。
 もうこれほど相応しい比喩が他にあろうかと、、。
 レベル5デスなんて可愛いもんで、レベル1デスですわ。リフレクもマホカンタも無いんですわ。


●xenia-canaryのアセンブラ出力
 元々がアセンブラを直接弄るという荒技なのでリスクというか代償は込みではあるのだけれど、それにしてもここまでの大変化を食らうのは想定外。

img
(左:本家、右:canary)
※まぁ別に見なくて良いんですが文章だけでなくて具体的イメージもと。エミュ本体のexeじゃなくて、オリジナルのxbox-CPU用コードをこう読み替えて実行してますというエミュレーション用変換コードの例。

 例えばメモリアクセスのコードが全然変わっているとか、データ構造体のオフセットも大きく変わっているとか。もう変わってない箇所の方が少ないくらい。
 そりゃあ現在進行形の開発プロジェクトなのだから変更が入るのは仕方ないとはいえ、それでも既に開発から長年経って「この辺の基礎はそう変わらないでしょ?」と思っていた部分ですら、大きくリファクタリングで書き換えられてしまっていた。

 この辺、大分前からアセンブラ職人がちまちまとコード最適化を掛けているのを見掛けてはいて、コンパイラ開発の類いの目線では面白いだろうけどそれが画期的な差を生む訳でもなかろうと、「あーもうこれcanary使うのは無理かな」「本家にフィードバックされるなら覚悟を決めよう」くらいの温度感だったのだけれど。
 ただその最適化用のコード変更が入った上で、そこから更に続けて描画ロジックのリファクタリングなどといった大掛かりな改修も進められてしまいましてね。問題はここ。自分が欲しいのはその後者の方だけなのに、前者コードがちりばめられていて差分がもうしっちゃかめっちゃか。
 この辺りでcanaryと本家との共存は最早諦められていたのかもしれない。

 そこで自分の今後としては、このまま止まった本家を使い続けるのか、canaryに移行するのかという大きな選択の瀬戸際に。
 本家でも当面支障ないとはいえ、このまま続ければ続けるほどどんどん古いコードが積み重なっていく。かといってその変わってしまったcanaryの上でやり直すというのを、優に200を越えているアセンブラ改造コードとそれに関わるluaコード全てでやりますか、って。
 こういうちゃぶ台返しが発生すると、ぶっちゃけそれを切っ掛けに手が止まる話にもなりかねないんですよね。そういう理由を作ってしまう事自体が、個人的には度し難く許し難い。
 「止める理由は飽きた時くらいにさせて貰いたい」、などと息巻いて今回対策を講じました。

 詰まるところの問題は「エミュレーション用のアセンブラ変換コードが変わっているだけ」なので、その原因を一つ一つ潰していけば何とかなる筈なんですね。
 ぶっちゃけ前のままでも動作同じだろぅー?と。
 ”cmp 0 → test”とか、”add 1 → inc”とか「どっちも同じじゃないですか」って。
 まぁミクロの世界では当然違うけれど、1フレームに100万回も流れるようなコードならいざ知らずの誤差問題。

 そういう所を片っ端から当たっていって、前の動作に戻せるなら戻す、変わった理由があるなら何なのか、 などと色々xeniaのコード実装を見て回ることになりました。(まぁアセンブラ展開周りの極一部だけですけども。全てを把握するには到底程遠い)

 結果としてただ全て戻すんじゃなくて、改造コードに大きく関わって辛い箇所を中心に戻したコンパチバージョンを作成。こういう箇所はコードが変わるので今後避ける等というポイントも押さえて、あくまで本家とcanaryで改造コードを共存できる形に収めるようにしました。
 canaryはcanaryでまだ色々不安もありますんで。それに変わったコードの影響でめっちゃ可読性が落ちてるので(元フローとは関係の無いjmp命令まみれになった)、普段の解析作業は本家のままでいいかなみたいな使い分け状態。


 因みに言うと副次的問題として、吐かれるアセンブラが変わることでCheatEngineのコードスキャンの問題だとか、これまで長いこと(元のソースコードなんてものが無い以上)テキストに書き下していたコード解析メモが片っ端から役に立たなくなるという話もありまして。
 この辺も色々工夫して何とかしておりました。もう長くなるだけなんで省きますけども。色々やってましたんでという話。
 デビルロードにただマホトーンを掛けるだけじゃなくて、メガンテがメガンテたる理由にテコ入れしてただのザラキかザキに変えてやったので、この先も大分気がラクになりました。


 おっと、しまった
 当初はこれを機にエミュの動作状況の話とかをまとめようとしてた気がするんですよね。その与太として苦労話をする筈だったんですが。うんまぁうん。

●ドリクラエミュ動作状況
 この辺、結論から言ってしまうと、canaryなら表向きはかなり良くなってるけど一部まだ問題もあるし、デグレもある。まぁ結局のところ、ドリクラをエミュで動かす際はこちらで改造を入れないとちょっとまだ完全ではないという感じ。制約ありとしてならcanaryならOKかなという感じです。

 主な所では、
・動作速度はめっちゃ改善、もう素でもヌルヌル動く
・音声問題は use_new_decoder = true にすればかなり解決はしているが、微妙にズレが起きている
・自環境ではAPUドライバを apu = sdl にすると大分収まるが完全ではない
・モーションフレーム補正が何故か誤爆して60fps計算されるのでこれまたズレる(59.94fps計算じゃないと曲と合わない)
・DLC読み込み時に延々終わらない物がある(本家では起きないのでデグレ)


 一番肝心の音声問題なんですが、一見して通常再生できるくらいには改善しているものの、細かな部分ではまだ再現性が怪しい。結局「ffmpegから旧libavに戻してビルドし直す」、この現状からは逃れられてないです。
 原曲と並べてみると徐々に再生がずれていくのが分かる。約2分の曲で概算10フレーム弱くらいっぽいけど(60fps計算のズレかとも思ったけどまた何か違う)、0.1秒もズレると振り付けタイミングによっては致命的。「え、なんでアイリちゃんこんなヘタになってんの?」と誤認するくらい歌が滅茶苦茶ズレてる。実際、libavに直して再生すればめっちゃ自然に戻るので気の所為とか気にしすぎとかいう問題じゃない。

 元々長い曲の再生はサブフレームに分割して逐一コールバック処理されているのだけれど、そのフレーム計算をffmpegでは細かくケアしないといけないっぽくて、ffmpeg実装の初期verではその辺りが甘くて音声が途切れるケースが多発していたし、ループ曲のタイミングもこれまたズレていた。そこは一見して直っているものの、まだ完全ではないということなのか。(結局こういうissueは残ってるし)
 内部のドライバ選択でも変わるのでコールバック周りの微妙な処理の違いなのかなぁとか、またゲーム側の処理の相性問題も考えたんだけども。流石にxeniaの実装コードを全部追う気にはなれないというか、もう「私、ffmpegきらい」で済ませた方が早いって言うか、、。libavに差し戻せばいいだけなんだもの。(動画編集してた頃から音声トラブルあってあまり良い印象ないんだよなぁ。めっちゃ多機能なのは分かってますが、それだけに動作もピーキーなんだろうなって。)
 ただ新機能(music player) をffmpegで組んでいてそのlibav実装はないので無効化する前提。まぁドリクラだけなら関係無いです。

 DLCは何だろうね、実機でタイムアウトまで待ってしまっているのと似たような現象が起きてるんですが、そんなとこまでエミュらなくても(?)。というかそれより更に酷くて抜けなくなる事が多々。(デグレ箇所は突き止めてるのでひとまずrevertで直りますが、何故それが影響しているのかはよく分かっておらず)

 その他細かい問題はこちらで対処してます。xenia側だったりCE改造だったり。
 まぁなかなか上手く行かないもんですね。

 そんなこんなで何とか現状報告できたかなと思います。
 その作業自体は少し前に終わらせてるんですが、それと同時に今まで書いてきたコードの見直し等、今は保留してたコード作業を中心にやってます。
 今回の話で「何とかなるからと放置しているとどんどん負債が溜まる」というのを痛感しましたからね、、。分かっちゃいても後回しになる、というのは仕事ならあるあるですけども。これ遊びでやってますので。自戒の意味で。

 なので、ちょっと今は特にお出し出来るものもないと申しましょうか。一応一つ機能追加はしてますけども、それでお披露目って程でもないし。結局何を録るかが肝要なので。その辺今は何を録ろうか(&何に手を掛けようか)って割と悩みがちではありますね。
 エロ衣装系ネタは申し訳ないですけどテンション合わないとできないので当分優先度下がるかなと思います。本当に申し訳ない()。