更新ありがとうございます。
kbGuru2SMF.kpi の取り込みも本当にありがとうございます。
ソースを引き継いで本体に同梱するのはこちらも想定していた形ですので全く問題ありません。
動作確認してみたところ、kbGuru2SMF.kpi → kbdmusic.kpi の切り替えは問題なく再生されました。
ただ、64bit版本体で起動直後の kbGuru2SMF.kpi の再生や、kbdmusic.kpi → kbGuru2SMF.kpi の切り替え後の再生が出来ないことが有りました。
ソースも公開されているので調査してみたところ、GuruGuruSMF\dxmus.core\Port.cpp に原因がありそうです。
理屈としては起動直後以外のタイミングや32bit版の本体でも発生するはずですが、今のところ発生を確認できていません。
修正したソースを添付しますので確認してみてください。
Port::Open() 内の処理で、PostCommand() でOpenコマンドをキューに追加して
Wait(1) でワーカースレッド Port::OnWorker() の処理完了を待っていますが、
ワーカースレッドが Sleep(1) を実行しているタイミングで Wait(1) が呼ばれると、
処理完了を待たずに Wait(1) を抜けてしまい、その結果未初期化の変数 resultOpen が Port::Open() の戻り値になります。
KbGuru2SMFPlayer::Open() 内で呼んでいる m_pGGS->OpenDevice() の戻り値は未初期化の resultOpen の値がそのまま返されるので
GuruGuruSmf::GgsError::NoError にならず、KbGuru2SMFPlayer::Open() が FALSE を返すことになりそこで処理が中断されます。
対策として、Port::Wait() でスピンロックに使用している isBusy を
true に設定する場所を Port::PostCommand() の commands.push() の直後に移し、
false に設定する場所を Port::OnWorker() の commands.pop() の直後に移すことで、
PostCommand() → OnWorker() で Open2() を実行 → 処理完了後に Wait() から抜ける の順序を保証出来るようにしました。
v4.0.7での FreeLibrary() 時のフリーズも解消しているようです。
DllMain() でスレッドの同期をしてはいけないのは、マイクロソフトの開発者向けページでも明記されていますね。
https://learn.microsoft.com/ja-jp/windows/win32/dlls/dynamic-link-library-best-practices解放処理用の関数をexportし、FreeLibrary() の前に呼ぶのは解決法として間違っていないと思います。
(9KB)