honeylab's blog

各種ハードウェアの改造、主にファミコンミニなどをやってます(ました)

DAM カラオケコマンダ XG1000に自前BGV再生機能を追加

honeylab.hatenablog.jp

 

カラオケ、本人映像や専用アニメ映像が入っていると嬉しいですよね。
でも、皆さんがカラオケで歌うようなあまりメジャーではないアーティストや曲のBGVに
そういう専用映像が入ってくることは、公式ではほとんどないじゃないですか

せっかくなので、自分専用の映像を背景にカラオケしたいですよね。

多分、外部入力から入れる、っていう手ができる気もしますが、それだと同期が大変です。
ここは、本体を改造して自分用の映像を再生できたらいいなぁ、と30年ぐらい前から思っていました。

引き続きじわじわと逆コンパイルする日々の中、実現できそうな気がしたのでサクッと実装してみました。

大抵のカラオケ機では、曲のジャンルやアーティスト、事前設定されたパラメータなどから本体内に保存されている映像DBを参照し、専用映像があればそれを、なければ無難な映像を探し出して再生してくれます。

DAMでもそのようになっていて、ログを見るとその流れが確認できます。Image

まずはDBを見て、専用動画があるかを確認、なければさらに検索して動画を選択しているようです。

動画を検索する関数でファイル名リストを取得したあと、それぞれの動画が本当に存在しているかを「CMDVIndex::CheckPresentBGV」という関数でチェックし、OKならプレイリストに追加している、ということがわかりました。
ならば、この関数にファイル名が渡された時点でそのファイル名を自分専用の動画ファイル名に書き換えて仕舞えばそのファイルを再生してくれそうな気がします。

早速やっていきます。

CheckPresentBGVはファイル名を受け取りますが、実際にそのファイル名の格納されたフォルダを複数のフォルダ(304,305)から検索するようになっています。

見つかった場合、そのフォルダを引数で渡されたフォルダポインタ(LPWORD lpFolderNumber)に格納し、trueを返してくれるようになっていました。


なんと好都合。指定したフォルダから探す、として値渡しだった場合、関数一つ戻ってそっちで書き換える必要があるんですが、これならこの中で自分専用のフォルダを返してやればいいんじゃないでしょうか。
専用フォルダ番号は「666」とし、ファイル名に指定されたファイルを準備してやります。
動画ファイルは、あらかじめ曲番号に準じた形式で保存しておきます。
このファイルをコピーすると遅くなってしまいますので、シンボリックリンクで処理します。
対応しているファイル形式はいくつかありますが、とりあえずWMVがうまくいったためこれでやっていきます。

ついでに、同じ曲でも複数のBGV、バージョン違いが存在する場合、ランダムに選択されるようにしてみました。これなら最大10個のバージョンを準備できます。素敵!

で、この関数をどうやって書き換えるか、という話なんですが、よく私の使う

「LD_PRELOAD」でライブラリを読み込ませる、という方法を使います。

qiita.com

ATOMCamなどのハックもこの手法でやっています。

実際に記述した関数はこんな感じになります。

gist.github.com

大変ヘンテコな関数名「_ZN9CMDVIndex15CheckPresentBGVEPtmP15tagVSTREAM_TYPE」になっていますが、これは

「bool __thiscall CMDVIndex::CheckPresentBGV(CMDVIndex *this,LPWORD lpFolderNumber,DWORD dwFileNumber,VSTREAM_TYPE *type)」

C言語名前空間に配置した時に行われる「名前マングリング」という処理の結果です。

C++のクラス関数を上書きする際には、この名前で関数を書く必要があります。
また、引数にクラスオブジェクトのポインタが渡される場合、型情報は自分で定義するか、
ポインタを自分でインクリメントして型を設定し、アクセスする必要があります。
今回は本来の関数へ橋渡しするのと、数値を書き換えるだけなのでそこまでめんどくさいことをする必要はありません。

 

で、できたーーーーー

これでマジで好きな動画ファイルでカラオケができるぞ素敵すぎる!