From 42689377e6e20b3ce5cebe94eab2e1d7aa6904df Mon Sep 17 00:00:00 2001 From: "[ ]" <[ ]> Date: Sun, 14 Dec 2025 23:17:40 +0900 Subject: [PATCH] feat: Resolve long load times before get ready for IIDX > see #4 > partial improvements for result screen hang, see #2 --- hooks/wmischook.cpp | 64 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/hooks/wmischook.cpp b/hooks/wmischook.cpp index 14a3173..55addd3 100644 --- a/hooks/wmischook.cpp +++ b/hooks/wmischook.cpp @@ -2,8 +2,71 @@ #include "util/logging.h" #include "util/detour.h" #include "util/sigscan.h" +#include "util/libutils.h" +#include +namespace hooks::wmisc::msacm +{ +typedef MMRESULT (*acmFormatSuggest_t)(HANDLE had, LPWAVEFORMATEX pwfxSrc, LPWAVEFORMATEX pwfxDst, DWORD cbwfxDst, DWORD fdwSuggest); +static acmFormatSuggest_t acmFormatSuggest; + +static uint64_t hash_waveformatex(const WAVEFORMATEX *pwfx, DWORD fdwSuggest) +{ + //_INFO: no clashes, likely faster than hashing sizeof(WAVEFORMATEX) buffer + uint64_t h = 0; + h ^= (uint64_t) pwfx->nSamplesPerSec << 0; + h ^= (uint64_t) pwfx->nAvgBytesPerSec << 1; + h ^= (uint64_t) pwfx->nBlockAlign << 2; + h ^= (uint64_t) pwfx->wBitsPerSample << 3; + h ^= (uint64_t) pwfx->cbSize << 4; + h ^= (uint64_t) fdwSuggest << 5; + h ^= (uint64_t) pwfx->wFormatTag << 6; + h ^= (uint64_t) pwfx->nChannels << 7; + return h; +} +MMRESULT __stdcall on_acmFormatSuggest(HANDLE had, LPWAVEFORMATEX pwfxSrc, LPWAVEFORMATEX pwfxDst, DWORD cbwfxDst, DWORD fdwSuggest) +{ + static std::unordered_map> acmformats; + static std::mutex mutex; + + // Find cached formats + size_t hash = hash_waveformatex(pwfxSrc, fdwSuggest); + { + std::lock_guard lock(mutex); + auto it = acmformats.find(hash); + if (it != acmformats.end()) + { + // Copy cached result + memcpy(pwfxDst, it->second.data(), std::min(cbwfxDst, (DWORD) (sizeof(WAVEFORMATEX) + ((WAVEFORMATEX *) it->second.data())->cbSize))); + return MMSYSERR_NOERROR; + } + } + + // Cache unique formats + log_info("hooks::wmisc::msacm", "Forwarding acmFormatSuggest({}) request due to cache miss", reinterpret_cast(hash)); + MMRESULT r = acmFormatSuggest(had, pwfxSrc, pwfxDst, cbwfxDst, fdwSuggest); + if (r == MMSYSERR_NOERROR) + { + std::lock_guard lock(mutex); + acmformats[hash].resize(sizeof(WAVEFORMATEX) + pwfxDst->cbSize); + memcpy(acmformats[hash].data(), pwfxDst, sizeof(WAVEFORMATEX) + pwfxDst->cbSize); + } + return r; +} +void run(HINSTANCE hmodule) +{ + // Override acmFormatSuggest + HMODULE msacm = nullptr; + if ((msacm = libutils::try_library("msacm32.dll"))) + { + acmFormatSuggest = (acmFormatSuggest_t) GetProcAddress(msacm, "acmFormatSuggest"); + } + log_info("hooks::wmisc::msacm", "Hooking acmFormatSuggest({})", reinterpret_cast(acmFormatSuggest)); + detour::trampoline_try(reinterpret_cast(acmFormatSuggest), reinterpret_cast(on_acmFormatSuggest), reinterpret_cast(&acmFormatSuggest)); +} +} + namespace hooks::wmisc::thumbnail { typedef bool (*ThumExists_t)(void *titleUTF_getter, int32_t id, char flag); @@ -60,6 +123,7 @@ void apply_performance_hacks(HINSTANCE hmodule, const char *model, const char *e { case by_model("LDJ"): thumbnail::run(hmodule); + msacm::run(hmodule); break; default: break;