snes9xTYL 0.4.2meを使ったコード実験室

注意!
このページはMIPSCPUやコンパイラの特性調査等の個人的な探究欲に基づいているため、飽きたら放置プレイの可能性大です
あくまで比較はソース公開された最新の0.42版です。

ややこしいことになるので改良版と称しサイト等で紹介などしないでください。
テストしてくれる方を呼びかける紹介は歓迎。

現在のステータス&ToDo

・ソース解析して気になるところ洗い出し->完了
・サウンド処理の見直し->テストコードお試し中(0003〜)
・VBrank待ちをするとFPSが半減する->NesterJのコードを移植すればほぼ変化なしにできるんジャマイカ?->達成(0013)
・Sony純正の廉価版メモステ使用時のアクセスが異様に遅い->ランダムアクセスしてるから?

速度比較

動作比較対象ソフトは SNES9X Demo V1.16 (PD) を使います。何故これを選んだかというと、回転処理をしているのを見るのが好きだからですw
SNES9x Demo V0.24 (PD)も追加しました。パレット操作系とサウンド系も参考として確認していますが計測結果は載せていません。

測定用コンテンツ サウンド処理 特徴など
SNES9X Demo V1.16 (PD) 回転っていいねぇ〜
SNES9x Demo V0.24 (PD) なし サウンド処理が行われていないのでCPUエミュレーション部の高速化測定に最適。
Lynchpack3(PD) サウンド処理が上のより複雑みたい。
Rapid15(PD) なし パレット切り替えが激しい。連射測定機能つきw

 

SNES9X設定

VIDEO SOUND

FrameSkip: 0
GFX Engine: PSP accelerated + approx. soft.
Video mode: fullscreen
Smoothing: yes
Speed limit switch: no
Frameskip: 0
VSync: no
Render PAL as NTSL: yes
Ganma correction: 0
Screen calibration: default
Show FPS: yes

Sound mode: emulated, output
Output frequency: 44100Hz
APU Cycles ratio: 100.00%
※念のためバッテリーは50%以上もしくはAC接続で測定すること

測定方法

ファイルを選択し、デモが始まったらメニューに入る。その後、Resetを選択後 20 秒間動かしたあとの左上の数値を測定する。 数値は描画したフレーム数です。
222MHz,266MHz,333MHzの各クロック3回測定(メニューからReset)しその平均を算出(小数点は四捨五入)。
当然平均FPSは数値を20で割ると求まります。
また、カウンターは簡易なものなので内部値がオーバーフロー起こすとカウントしなおしますので注意

結果
ファームウェア1.00のPSPでの測定結果です。
ここで公開しているバイナリはテストバージョンです。他では絶対に配布はしないでください。有志によるテストのための公開です。またソースファイルも差分ファイルのみで公開です。
バグ報告は不具合の発生バージョンと正常に動作する一番新しいバージョンを記載してください。また、
TYLオリジナルバージョンで発生する問題は基本的に修正しません。

 

2010/05/25 Update: バイナリデータはWebサイズ上限の関係で削除しました。

Build No ベース 変更点 [+]追加 [!]修正 [^]高速化 [-]削除 [?]その他 Demo V0.24 (PD)結果 Demo V1.16 (PD)結果 備考/Memo

222MHz

266MHz 333MHz

222MHz

266MHz 333MHz
0001
(2,475,078)
-

比較対照物の作成
[+] フレームカウンタ追加
[+] 区別できるようにタイトルに"++"追加

593

738 937 766 902 1179 これが基準
0002
(2,471,942)
diff-src
0001
見つけたバグと思われるものを修正
[!] SPC700チップの処理(me側)のグローバル変数アクセスの修正
[!] Adhocはvoid*なのに**アクセスになってる修正
745 907 1162 803 962 1232

SPC700修正はmeとメインのCPUキャッシュアクセス領域が被らない
ようにする修正。コードは3k近く減ったので速くなるとは思うけど速くなりすぎ。
変更したのはme側だし、メモリ配置がよかったのかな?

メニュー閉じる時のエフェクト2種が測定の弊害になっているため、これ以降はエフェクト処理カットで測定する。(カットした際のファイル差約500byte)
0003
(2,456,454)
diff-src
0002
高速化してみたが不具合発生(詳細は備考欄)
[^] 65c816、SA1のグローバル変数アクセス修正
-
-
-
-
-
-
65c816、SA1の処理を変更し命令を約15k分の命令が減る。しかしme側との
キャッシュの衝突が原因と思われる動作不良が発生。me側が落ち着いたら
合流予定。
0003実験結果+0004に向けたテスト結果数回から、me側とメイン側のアクセスデータの住み分けがちゃんと出来ていない模様。コンパイラオプションの-G0は衝突を最小限にするための苦肉の策?
少しデータを追加したりデータサイズを変更するだけで挙動が変わる。対策きちんとしたらGP相対つかえるようになるから高速化期待できるかも。

私的メモ:とりあえず現時点での不具合/問題あると思われる個所列挙。以降対策したらこのメモ削除します。ひそかにコードチェックしてる人参考にしてくれたら嬉しいな。
修正履歴や考察をそのまま残しておくのもこのページの趣旨だとおもったので残しておきます。
・snapshot.cpp メインCPUがS9xFixSoundAfterSnapshotLoad()を呼び出している(me側apu_init_after_load&2のときの処理に呼んでいるのでこちらは要らないと思われる)
・sounddux.cpp の一部関数が両CPUからコールされている。Notify的なもので通知するべきかな?
・S9xSetAPUTimer()はメインCPU側から呼ばれているのでuncachedにセットすべし。現状だと上書きされて意味が無い上音の処理が変になる?
・Settingsが両CPUから呼び出されている。
・初期化などの処理はme側に通知して行なうようにしたほうが安全かも?
・ apu_init_after_load&2のときにもuncachedからのコピー処理が必要かも?
・修正諦めてなんとなく動いてるからリリースしたコードとしか思えないんだけど・・・。
ちゃんとsounddux.cpp、apu.cppのme側の処理を追っていかないと無理かも。作り直したほうが早い?

0004
(2,466,726)
0002
TYL版サウンド処理のリファクタリング
[+] 新サウンド処理実装
[-] 0.4.2オリジナルのサウンド処理は原型を留めてないくらい変更。
[+] 上記追加実装のデバッグ用コード&表示追加(遅い)
表示がチラチラしているのはVRAMにキャッシュありでアクセスしているからです

ファーストリリースのためソース公開は動作確&デバッグコード
削除後に(0005か0006?)

-
-
-
-
-
-
デバッグ用パラメータ表示やら内部的なデバッグコードが増えているため遅いです。
試せるROMが殆ど無いので動作報告&不具合報告お待ちしています。
不具合の場合の報告の際は再現手順や画面に表示しているパラメータも教えて下さい。
(ないとコードを追えないので調査できません。(あと0.4.2では正常なのかの比較情報も)
追加コードのパフォーマンス改善は報告が落ち着いたらやる予定
注意
オリジナルの0.4.2で作成したsram、stateはサウンドデータ部が異常なものが含まれて
要る可能性が大いにあります。ですので上記データ用いての不具合報告は しないよう
におねがいします。 また、確認前にデータのバックアップは行ないましょう。
0005
(2,552,998)
0004
バグ報告の反映修正
[!] stateload時のS9xFixSoundAfterSnapshotLoad()呼び出し追加
[+] デバッグコード増量
[!][~] SoundStatus 構造体のサイズ変更&配置調整
[~][?] Soundux.cpp内の不要な関数をコメントアウト
-
-
-
-
-
-
ステートロードで止まってしまう問題はたぶんS9xFixSoundAfterSnapshotLoad()を
呼び出していないためだと思われる。
他メモリ配置変更など安定性向上に向けた修正。
0006
(2,553,318)
0005
ポカミス
[!] DebugCode埋込み時に間違って必要なコードを削除しちゃった問題修正
-
-
-
-
-
-
me処理を一時止めるコードが抜け落ちていた・・・
0007
(2,547,942)
0006
とりあえずデバッグコードを削除
[-] デバッグコード&表示削除。
内部で一部個所にデバッグ用コードが動いてるため気持ち遅い。
[~] volatile 変数の見直し(まだいけると思うが安定性重視)

サウンド処理部最適化(データサイズ、バッファサイズ等)
掲示板に遅いとの報告があり、実際回転処理が異様に遅くなっていた
ので心配したのでデバッグコードを外したバージョン作成。  

-
-
-
-
-
-
エミュレーション動作的には0006と変わりません。
stateload時かsave時にデータもしくは挙動のみがおかしくなるタイミングがあるようです。
詳細なレポートをいただけると早めに解決できますのでご協力をおねがいします。
レポートがないと調査に時間が掛かってしまって高速化対応が遅れてしまいます。
どんな感じのレポートを書けば良いのかは掲示板の投稿者:UFO さんの
レポートが素晴らしいので参考にして下さい。
(stateデータに互換性があるエミュ
があるのならそれにて読ませた結果、もしくは互換性エミュで作成したstateデータ
をPSPで読ませるレポート等できれば提供していただけると特定しやすくなります )
※TYL版に互換性があるのかが判っていませんが・・・orz
0008
(2,529,702)
diff-src
0007
APU側はとりあえずこれで放置
[~]
main->meデータ渡し処理改善
バッファサイズ半減。データ取得タイミング変更
[~] 0003コードマージ
[?] ソース公開に向けたコードの可読性向上&整理
[~] APU構造大幅見直し構造体まとめてデータ参照レジスタ使用数を
減らした上パッキングによるキャッシュラインを節約
640 778 1008 816 999 1278 主にAPU(me側処理)の高速化。 std版だったら速くなってるかも?
APU構造見直しはソースコード読める人は見てください。かなり笑えますw。
でもこのAPU構造見直しはuoSNES版(実験室のほう)でもやってたりします。
uoSNES版はCPU(SA1)側もやってます。現状同じような事をしてるが中途
半端なので TYL版にも導入するかも?
ボトルネック調査をしたらme側に余裕があり、メインCPU側の負担が多く
なっていた。以降はメインCPU側に取り掛かる予定。
0007で記載したバグ報告引き続きお待ちしています。
とりあえずMediaEngineのサウンド処理の刷新は終わり。バグ修正のみ?
0009
(2,509,542)
diff-src
0008
CPU側初陣
[~]
SRAM,VRAMメモリ配置をmallocしない
[~] CPU(SA1)構造体まとめてデータ参照レジスタ使用数を
減らした上パッキングによるキャッシュラインを節約
[~] CPUのOpCodeテーブルもメモリ配置も調整
725 866 1100 836 1019 1299 メモリの配置を効率的にしたのみ。0010版作成する前のスナップショット的
なもの。
CPUエミュレーションはコード/データのキャッシュヒット率向上が鍵と踏んでる。
お互い減らす努力をしてみる。今回はコード量が20K減った?
0010
(2,502,118)
diff-src
0009
Tile系初陣
[~] solid_lineclipの使い方をもう一工夫した
[~] 画面描画をPSP(MIPS)で最適になるように書き直し
(地味な作業だったので不具合あるかも)
[~] Tile部のメモリ配置調整
-
-
-
-
-
-
描画処理の実際描画をしているTile処理をチューニング。コード量だけでみると7Kくらい
減ったのかな?呼び出し回数はかなり多いので地味に良くなるかも。
しかしサンプル測定だと殆ど意味なし(メモリ配置の影響で上下するだけ)なので測定パス
(地味に面倒なので)。
描画部を弄っているので0009と比べて画面がオカシイところがありましたら報告
おねがいします。
(通常描画/合成描画などがオカシイ等詳細な情報があればイイナ!)
0011
(2,489,574)
diff-src
0010
CPU側処理最適化
[~] OpAddressをグローバルからローカル変数に移動
[~] CPUCyclesの更新タイミングを変更
720 875 1133 817 998 1297 ローカル変数で済むので移動しました。ローカルなら常にキャッシュヒットするだろうし、
無駄なストア処理がなくなるので速くなるかなぁと。コードは12kほど減る。CPUコアで
12k(CPUとSA1があるから1つあたり6Kだけど)は結構大きいんジャマイカ!?
測定だと速くなったのか遅くなったのか判らない感じだけど、CPU命令を色々使うゲーム
系なら効果あるかなぁ???
0012
(2,485,158)
diff-src
0011
メモリ操作エミュレーション最適化
[~] メモリマップテーブルを最適化しキャッシュラインを節約。
811 969 1253 836 1021 1302 数々の地味なキャッシュライン節約により大幅アップキタ?
コードが増えると思ったけど減ってた。
SA1にも同じような最適化できそうなものがあるが先送り
0013
(2,485,350)
diff-src
0012
表示処理の改善
[~] 画面への描画を非同期処理に変更
内部構造体に直接アクセスしてる・・・
854 1035 1315 851 1056 1342 描画処理がSync処理になっていたのでASync処理に変更しました。Geでどう書けば
いいのか判らないから直接内部構造体アクセスして強引に行なっています。
コード量的には若干増えてるがコールバック関数など追加したからですね。
副産物としてVbrankをYesにしてもほぼ速度落ちは発生しません。通常Yesに
してる人には凄い効果ありそう。
0014
(2,485,414)
diff-src
0013
報告のあった問題の修正とTYL版からあるバグ修正
[!] 0012で発生したバグの修正
[!] statesave時にPCの値を間違えていた問題修正
[!][~] PPUアクセス時にサウンドとの同期をしまくるので修正(TYL
オリジナル版からの修正)

ちゃんとした確認は取れていません。
857 1037 1317 925 1113 1399 ・報告のあった0011から0012になると挙動が変になる問題の修正
(コードを見比べておかしくなる個所を修正しました)
・statesave時にAPUのPC値とFlag値が異常になる問題修正。
stateload時にOutPortの値をロードするように修正(たぶん関係ないとは思うけど)
(0004〜0013までのデータは使えないと思ったほうが良いかもしれません。動いたら
ラッキー程度の扱いでおねがいします。)

上記不具合調査時に発見したTYL版でのPPUアクセス時にサウンド同期処理を
してしまう問題修正(予想では遅くなるシーンが緩和すると思われます)
実際の不具合発生ゲームでの確認は取れていません。お試し版的扱いです。
測定結果的には両PDROM最初しかPPUアクセスしないからそんなに変わらず。
回転するほうのは開始時の部分が速くなったのは体感できた。
ゲーム系ならシーンによって結構速くなるかもしれません・・・私の理論上でですが
動作確認結果の報告お待ちしています。

問題なさそうなら引き続き処理高速化実験続きに移ります...
0014バージョン以前はステートセーブ/ロード時の不具合があります。使用する際は注意してください。
0015
(2,485,350)
diff-src
0014
バグ報告修正その2
[!] 0012で発生したバグ修正
[!] 0014で修正したPPUアクセスを元に戻す
(構造作り直したら解決しそうかなぁ?)
-
-
-
-
-
-
バグ報告の対応。報告ありがとうございました。
測定は予想できるのでしません。0013程度だと思います。

動作確認結果の報告お待ちしています。
0016
(2,484,774)
diff-src
0015
GFX初陣 (1/2)
[~]
PPUアクセス時の負荷少し緩和
[~] GFXのBG構造体変更とTileSizeの使い方工夫
-
-
-
-
-
-
GFX系結構弄る予定なのでバグ特定しやすいように2分割リリース。
なので測定は次ので。
0017
(2,481,318)
diff-src
0016
GFX初陣 (2/2)
[~]
GFX構造体スリム化
[~]
不要な固定値を比較するコード等を削除(SixteenBitとか)
854
1041
1322
852
1056
1343
データ保持領域を半分程度に減らすもそんなに変化なし。メモリ配置は指定してない
からそんなに変化無かったかも?ファイルサイズ減少は呼ばれない関数がなくなった
から。一番でかかったのは回転処理の8ビット版。
0016、0017共に地味な変更でした。
バイナリにreadme.txtを添付するようにした。何かあったら報告おねがいします。
0018
(2,477,478)
diff-src
0017
スクラッチパッド使ってみるテスト
[~] CPUPackの配置をスクラッチパッドに変更
825
1003
1275
868
1057
1344

CPUエミュレーション全般を担うCPUPack配置をスクラッチパッドに置くテスト。
CPUPackアドレス取得が2命令から1命令になるので速くなる筈なのだが
逆に遅くなる結果に。ファイルサイズは4Kも減ったのに。
スクラッチパッド領域ってアクセススピードが違うのか?それともデータ依存な
命令配列になって結果的に変化ないようなことになっているのか・・・??
ゲーム系なら改善は見られるかも!?

0019
(2,476,774)
diff-src
0018
PPUとIPPUまとめるテスト
[~] まとめて参照レジスタ数を減らすテスト
791
978
1241
877
1066
1351
スクロールのほうは逆に遅くなった。誤差範囲とも取れるけど保留。参考程度に。
0020
(2,480,358)
diff-src
0017
cpuopsの固定値変数削除
[~] BranchCheckの固定値変数削除
792
978
1243
870
1059
1344
結果がアレだったので0017にロールバックしてコード修正。
(あくまでこの2つのサンプルのみの結果なので、改善が見られた場合は報告ください。)

ジャンプ命令時の処理を高速化。地味な修正なので地味な結果に。
0021
(2,476,454)
diff-src
0020
DSP1チップの改善(1/3)
[~] DSP1のコードをリトルエンディアン依存に変更
[~] 孫呼び出しになっていたので直接呼出しに変更
DSP2とかDSP3とか対応しようとしたコードの名残?
-
-
-
-
-
-
0016と同じように2つに分けてリリース。
DSP1のエミュレーションはコードを見れば判りますがエンディアンに依存しないコード
になっています。そこでPSP(リトルエンディアン)用にコードを変更を行ないました。
コード量が結構減ってるが未使用関数もなくしたので実質減ったのは2Kくらいかな?
※DSP1を使っているPDROMが見つからなかったので動作未確認です。
0022
(2,472,486)
diff-src
0021
DSP1チップの改善(2/3)
[~] グローバル変数のローカル変数化
[~] 無駄な処理の削除(テストコードの残骸?)
-
-
-
-
-
-
外部変数になっているDSP1の変数郡を変更。無駄なストアがなくなるので速くなる筈。
不具合があったら報告ヨロシクおねがいいたします。
※DSP1を使っているPDROMが見つからなかったので動作未確認です。
0023
(2,466,790)
diff-src
0022
DSP1チップの改善(3/3)
[~] グローバル変数のローカル変数化
[~] 無駄な処理の削除(テストコードの残骸?)
-
-
-
-
-
-
修正量が多いので2分割から3分割リリースに変更。。。
修正結果が確認できないので全く面白くないなぁ。←当然だけど
※DSP1を使っているPDROMが見つからなかったので動作未確認です。
間違ってdsp1.cpp開いたときに見たコードが気になったので気まぐれ改善でした。(´ー`*)
0024
(2,465,766)
diff-src
0023
フラグセットタイミング変更(CPU,SA1)
[~] Opcodeのフラグセットタイミング変更
849
1031
1309
872
1061
1347

SetZN16、SetZN8の呼び出しタイミング変更。ちょっとの工夫で1K削減。
副作用がないようにチェックをしたけど念のため一応この変更のみでリリース。

0025
(2,481,638)
diff-src
0020
SetPPU,GetPPU,SetCPU,GetPPUプロファイル用
[?] 上記関数に呼び出し回数カウンタをつけた。
個人で使用するテスト用です。
また処理回数調べたい人用(そんな人いるの?)
-
-
-
-
-
-
プロファイル用。0020頃に作成したものなので0020ベース。表示してるカウンタの
意味は上はCPUクロック3種(今回意味なし)2段目は各関数の呼び出し回数。
描画コールバック中に文字を表示しているので若干の音割れが発生しています。
またメニューからExit Snes9xTYLを選択した際に詳細なプロファイルの作成するか
の問い合わせもあります。出力先は %SNES9X%/PROFILES/foo.prof.txt です。
ためしにDemo V0.24少し動かして出力したprof.txtファイルはこちら(詳細コメント付)
※カウンタは終了するまでリセットしません。注意。
0026
(2,463,014)
diff-src
0024
ちょっとPPU変更
[~] 不要なコントローラの処理を削除
[^] PPU部をリトルエンディアン依存に変更。
他、パレット保持変数をuint32からuint8に変更したりとか
-
-
-
-
-
-
エンディアン依存しない部分をリトルエンディアン依存に変更。またマウス処理を
カットするようにした。パレットのuint8化はキャッシュライン節約のため。
測定は0027で。
0027
(2,462,502)
diff-src
0026

CPUコア処理改善
[~] PB、DBとそれぞれのShift値の統一

804
976
1241
841
1024
1328
測定したら結果は微妙。コード量的には0024比で2.5k減少だけど。
メモリ配置の影響による一時的な速度減かなぁ。
0028
(2,462,950)
diff-src
0026
ソフトウェアレンダ時のキャッシュ制御
[~] ソフトウェア描画時はScreenアクセスのアクセス方法を工夫。
[~] mode7時の不要なパラメータセットや固定値変数の撲滅
下はおまけ的な修正。メインは上
822
999
1267
998
1219
1517
   。 。
  / / ポーン!
( Д )

↑まさにこれw。結構速くなるだろうと思ったけどビックリするほど速くなった。
ソフトウェア描画時のみなのでDemo V0.24ではPSP-HW描画なので影響ほぼなし。
ファイルサイズが0026から若干減ったのは下の変更によるもの。
結構前からこの改善チェックしていたけど後回ししてた。←好物は後に食べるタイプ
0027はコンパイラの解釈によっては不具合になる可能性がある気がするので封印。
0029
(2,462,054)
diff-src
0028
[!] 掲示板報告の画面崩壊バグ修正(したつもり)
[~] Bufferの初期化高速化
754
934
1187
987
1207
1507
画面崩壊バグ対策のため0013で入れた非同期描画処理をロールバックしました。
ただそれだけだと勿体無いのでVBrankが有効になっていても速度が落ちないように
修正はしておきました。
0013の非同期処理は有効なので根本原因を突き止めて再導入できれば・・・
Demo V0.24のほうは安定しないなぁ。
あとBufferの初期化高速化。地味に速くなる(測定だと回転処理のほうだけ影響)
0030
(2,457,958)
diff-src
0029
[~] 0018の修正追加
[~] 未使用値の削除
789
941
1216
993
1215
1513
0018で遅くなったのはメモリ配置の影響のようだ。
0031
(2,457,574)
diff-src
0030
[~] SA1実行毎に無駄なストアがあったので削除
[~] dmaちょっと高速化
[~] PPUアクセス時のtileリセット処理中の無駄な処理削除
-
-
-
-
-
-
変更点は全く影響なしなので測定しません。
(メモリ配置が変わって上下するだろうけど)
0032
(2,456,550)
diff-src
0031
2つのCPU間のやり取りを工夫
[~] MAIN<->MediaEngine間のやり取り量削減
796
965
1222
1041
1267
1575
MAIN処理とMediaEngine処理の同期をとるEvent通知を纏めて半分の量に削減。
キャッシュなしアクセス数が減ったので全体的に若干パフォーマンスが上がって
いるのが確認できた。
ゲーム中にガクンと処理が一瞬落ちるシーンとかが緩和されると思う・・・たぶん。
0033
()
diff-src
               
 
               
 
               

 

上記結果を試してみて、結果と極端に違う値になったり、動作異常が起こった場合は連絡していただけると助かります。
その際は異常の発生した番号のベースとなっている番号でも発生するのかを確認してください。

基本的には出力画面、出力サウンド両方が不具合修正を除き0.42meと同じ結果になるのを前提としています。

その他

資料等へのリンク

www.snes9x.com SNES9X総本山。

snesadvance.org 65816の仕様書があり、読み込み時にROM自体にパッチをあてて速くしようと試みるものもある。
どのくらい変わるのだろうか・・・面白そう。

cgfm2.emuviews.com SPC700に関する資料あり。