feat: Resolve long load times before get ready for IIDX
> see #4 > partial improvements for result screen hang, see #2
This commit is contained in:
@@ -2,8 +2,71 @@
|
||||
#include "util/logging.h"
|
||||
#include "util/detour.h"
|
||||
#include "util/sigscan.h"
|
||||
#include "util/libutils.h"
|
||||
#include <mmsystem.h>
|
||||
|
||||
|
||||
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<uint64_t, std::vector<char>> 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<void *>(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<void *>(acmFormatSuggest));
|
||||
detour::trampoline_try(reinterpret_cast<void *>(acmFormatSuggest), reinterpret_cast<void *>(on_acmFormatSuggest), reinterpret_cast<void **>(&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;
|
||||
|
||||
Reference in New Issue
Block a user