Ragnarok OnlineにおけるDirectSoundの初期化、及びサウンドレート、そして高音質化へ

今回はサウンド関連というネタを提示しますが、ネタをもとに書きながら解析及び方法模索、コーディングを行っているので、長談になりがちですが、よろしくお付き合いください。

ROのexeやdllのインポートを参照してもdsound.dllは見つかりません。
サウンド関連の初期化はBinkw32.dll(Bink RAD Game Tools )というヘルパーライブラリによってdsound.dllが動的に読み込まれ初期化されます。
内部処理を詳しく知りたい方は、 デバッグやマルウェア解析等に関する有力ツール | Planetleaf.com Lab.で紹介したIDAで BinkOpenDirectSound というファンクションを見てみましょう。

この通り、direct soundで音響関連が実装されていることが分かります。

さて、実は本題はサウンドレートを22kHzから44kHzに引き上げようという話になります。
現在のiROのクライアントはSetupからサウンドレートの設定が削除されていますが、サウンドレートの設定自体はレジストリのDIGITALRATETYPEという値を参照しています。
サウンドレートが弄れないため、レジストリの知識が無く旧クライアントでレートを11kや8kにしてしまうと変更するすべがないという罠もあったりなかったりで、相変わらずな適当ぶりだなと・・・。

DIGITALRATETYPEは0~2でそれぞれ22kHz、11kHz、8kHzの値へ内部で振り分けられます。
レジストリの値自体は以下のようなコードで読み込まれています。

分からない人のために解説すると、C言語のファンクションの呼び出し引数はスタックに積まれます。つまりこの場合は、
RegQueryValueExA( ecx , “DIGITALRATETYPE” , null , eax , &dword_8F2850 ,edx );という呼び出しが行われることになります。
このコードから、(DWORD)dword_8F2850に、DIGITALRATETYPEの値が格納される事が分かります。
あとはこの、インデックスを参照している場所を捜索すると、実際のサウンドレートの値を設定しているコードが判明します。

これでサンプルレートがdword_8E3594に格納されることが判明しました。
その後、AIL_open_digital_driverというMSS32.dll(Miles Sound System RAD Game Tools )内のファンクションをコールしていることが分かります。サンプルレートは1番目の引数です。ROのメモリ上のコードを書き換えるのはリスクが大きいため、ここではMSS32.dllのAIL_open_digital_driverファンクションをフックすることを考えます。

では実際MSS32.dllの該当ファンクションを見ていきましょう。

都合がいいことに、ファンクションの下位アドレスに8バイトのパディングが存在するので、これを利用して処理を挟み込みます。今どき、超低レートでの再生を考える必要はないと思えるので単純にレートを2倍化するコードを挟み込むことにします。
以下は可読性を上げるため、成形したコードを提示します。

スタックフレームの都合上通常のプロクシ関数呼び出しというわけにはいかないので、プロクシファンクションをスタックフレームなしの純粋なアセンブラコードとして記述することにします。

そして、肝心の今回書き起こしたコードはこちら、

今回のコードは、CBTフックにより、ウインドウ作成時に実行することで、簡単に導入が出来る物です。
ただし、同じような事をするアプリケーションとの協調性は無いので、注意したいところです。

この記事のトラックバック用URL


コメントを残す