feat: Resolve low framerate during song select for IIDX32+

> caused by bad code around thumbnail fetching logic including file checks in every draw call, see #4
> added `hooks::wmisc` for linux specific minor performance fixes and similar
This commit is contained in:
[ ]
2025-11-19 08:13:37 +09:00
parent 6561ea9230
commit e15c689061
8 changed files with 115 additions and 5 deletions
+1
View File
@@ -488,6 +488,7 @@ set(SOURCE_FILES ${SOURCE_FILES}
hooks/audio/implementations/pipewire.cpp hooks/audio/implementations/pipewire.cpp
hooks/develhook.cpp hooks/develhook.cpp
hooks/sndbhook.cpp hooks/sndbhook.cpp
hooks/wmischook.cpp
hooks/avshook.cpp hooks/avshook.cpp
hooks/cfgmgr32hook.cpp hooks/cfgmgr32hook.cpp
hooks/debughook.cpp hooks/debughook.cpp
+3 -1
View File
@@ -19,6 +19,7 @@
#include "hooks/setupapihook.h" #include "hooks/setupapihook.h"
#include "hooks/sleephook.h" #include "hooks/sleephook.h"
#include "hooks/sndbhook.h" #include "hooks/sndbhook.h"
#include "hooks/wmischook.h"
#include "launcher/options.h" #include "launcher/options.h"
#include "touch/touch.h" #include "touch/touch.h"
#include "misc/wintouchemu.h" #include "misc/wintouchemu.h"
@@ -408,7 +409,8 @@ namespace games::iidx {
cfgmgr32hook_init(avs::game::DLL_INSTANCE); cfgmgr32hook_init(avs::game::DLL_INSTANCE);
// wine fixes // wine fixes
hooks::soundbank::init(avs::game::DLL_INSTANCE, avs::game::EXT); hooks::wmisc::apply_performance_hacks(avs::game::DLL_INSTANCE, avs::game::MODEL, avs::game::EXT);
hooks::soundbank::init(avs::game::DLL_INSTANCE, avs::game::MODEL, avs::game::EXT);
// report common errors on iidx31 and above // report common errors on iidx31 and above
if (avs::game::is_ext(2023091500, MAXINT) && GRAPHICS_9_ON_12_STATE == DX9ON12_FORCE_ON) { if (avs::game::is_ext(2023091500, MAXINT) && GRAPHICS_9_ON_12_STATE == DX9ON12_FORCE_ON) {
+28 -1
View File
@@ -1,11 +1,33 @@
#include "develhook.h" #include "develhook.h"
#include "util/logging.h" #include "util/logging.h"
#include "util/detour.h" #include "util/detour.h"
#include "util/libutils.h"
#include "avs/core.h" #include "avs/core.h"
#include "avs/game.h"
#include "hooks/wmischook.h"
#include "external/stackwalker/stackwalker.h"
#include <vector> #include <vector>
#include <string> #include <string>
#include <sstream> #include <sstream>
namespace hooks::devel::thumbnail
{
typedef int (*BmswSymlink_t)(const char *srcwpath, const char *dstwpath, int canonic);
static BmswSymlink_t BmswSymlink;
void run()
{
HMODULE bmsw_ = nullptr;
if ((bmsw_ = libutils::try_library(MODULE_PATH / "bmsound-wine.dll")))
{
BmswSymlink = (BmswSymlink_t) GetProcAddress(bmsw_, "BmswSymlink");
}
log_warning("hooks::devel::thumbnail", "Forcing thumbnail patch..");
hooks::wmisc::apply_performance_hacks(avs::game::DLL_INSTANCE, "LDJ", "20250825");
}
}
namespace hooks::devel::avs_fs namespace hooks::devel::avs_fs
{ {
@@ -49,7 +71,9 @@ void run()
namespace hooks::devel namespace hooks::devel
{ {
void (*routine_cb_[devel_routine_last])() ={ void (*routine_cb_[devel_routine_last])() ={
[avs_fs_detour] = avs_fs::run [avs_fs_detour] = avs_fs::run,
[sndb_test] = nullptr,
[thum_test] = thumbnail::run
}; };
static constexpr unsigned int by_str(const char *str, int h = 0) static constexpr unsigned int by_str(const char *str, int h = 0)
@@ -85,6 +109,9 @@ static devel_routine_t routines()
case by_str("sndb_test"): case by_str("sndb_test"):
routines_ |= 1 << sndb_test; routines_ |= 1 << sndb_test;
break; break;
case by_str("thum_test"):
routines_ |= 1 << thum_test;
break;
default: default:
break; break;
} }
+1
View File
@@ -9,6 +9,7 @@ enum devel_routine : uint32_t
{ {
avs_fs_detour = 0, avs_fs_detour = 0,
sndb_test, sndb_test,
thum_test,
devel_routine_last devel_routine_last
}; };
typedef uint32_t devel_routine_t; typedef uint32_t devel_routine_t;
+2 -2
View File
@@ -494,7 +494,7 @@ private:
static snd_bank *cache_; static snd_bank *cache_;
static size_t cachesz_; static size_t cachesz_;
static avcodec::pcm_resampler_t resampler_; static avcodec::pcm_resampler_t resampler_;
friend void hooks::soundbank::init(HINSTANCE hmodule, const char *ext); friend void hooks::soundbank::init(HINSTANCE hmodule, const char *model, const char *ext);
uint8_t uid_; uint8_t uid_;
uint32_t mnt_; uint32_t mnt_;
@@ -872,7 +872,7 @@ void run_tests()
snd_bank::flush_cache(); snd_bank::flush_cache();
mf_broken::deinit(); mf_broken::deinit();
} }
void init(HINSTANCE hmodule, const char *ext) void init(HINSTANCE hmodule, const char *model, const char *ext)
{ {
if (false && IsDebuggerPresent()) if (false && IsDebuggerPresent())
{ {
+1 -1
View File
@@ -3,6 +3,6 @@
namespace hooks::soundbank namespace hooks::soundbank
{ {
void init(HINSTANCE hmodule, const char *ext); void init(HINSTANCE hmodule, const char *model, const char *ext);
void deinit(HINSTANCE hmodule); void deinit(HINSTANCE hmodule);
} }
+72
View File
@@ -0,0 +1,72 @@
#include "wmischook.h"
#include "util/logging.h"
#include "util/detour.h"
#include "util/sigscan.h"
namespace hooks::wmisc::thumbnail
{
typedef bool (*ThumExists_t)(void *titleUTF_getter, int32_t id, char flag);
static ThumExists_t ThumExists;
bool on_thum_exists_(void *titleUTF_getter, int32_t id, char flag)
{
static std::unordered_map<int32_t, bool> thumids;
auto it = thumids.find(id);
if (it != thumids.end())
{
return it->second;
}
else
{
log_misc("hooks::wmisc::thumbnail", "Caching state for [{}]", id);
it = thumids.insert({id, ThumExists(titleUTF_getter, id, flag)}).first;
}
return it->second;
}
void run(HINSTANCE hmodule)
{
// Reverse lookup function head (PUSH RDI) for ThumExists() specific signature, quietly fail if invalid
intptr_t beg, match, TX_ThumExists;
TX_ThumExists = beg = match = find_pattern_from(hmodule, "83f801750c4084ff750732c0", "XXXXXXXXXXXX", 0, 0, 0);
while (beg > sizeof(intptr_t) && match >= TX_ThumExists)
{
beg--;
match = find_pattern_from(hmodule, "4057", "XX", 0, 0, beg - reinterpret_cast<intptr_t>(hmodule));
}
TX_ThumExists = match;
log_info("hooks::wmisc::thumbnail", "Hooking ThumExists({})", reinterpret_cast<void *>(TX_ThumExists));
detour::trampoline_try(reinterpret_cast<void *>(TX_ThumExists), reinterpret_cast<void *>(on_thum_exists_), reinterpret_cast<void **>(&ThumExists));
}
}
namespace hooks::wmisc
{
static constexpr unsigned int by_model(const char *model, int h = 0)
{
return !model[h] ? 5381 : (by_model(model, h + 1) * 33) ^ model[h];
}
static constexpr unsigned int by_ext(const char *ext, int h = 0)
{
return !ext[h] ? 5381 : (by_ext(ext, h + 1) * 33) ^ ext[h];
}
void apply_performance_hacks(HINSTANCE hmodule, const char *model, const char *ext)
{
log_info("hooks::wmisc", "Enabling performance patches for {}-{}", model, ext);
switch (by_model(model))
{
case by_model("LDJ"):
thumbnail::run(hmodule);
break;
default:
break;
}
}
}
+7
View File
@@ -0,0 +1,7 @@
#pragma once
#include <windows.h>
namespace hooks::wmisc
{
void apply_performance_hacks(HINSTANCE hmodule, const char *model, const char *ext);
}