From bb0fd62ec3fbbec09a69a153acdfff074783d21b Mon Sep 17 00:00:00 2001 From: "[ ]" <[ ]> Date: Tue, 20 Jan 2026 08:31:17 +0900 Subject: [PATCH] feat: Crude SDVX 5 support > disable lobby video (cause for crashes in lobby), see #9 > suppress dmoeffector log messages, see #9 --- hooks/develhook.cpp | 76 ++++++++++++++++++++++++++++++++++++++++++--- hooks/wmischook.cpp | 60 +++++++++++++++++++++++++++++++++-- 2 files changed, 129 insertions(+), 7 deletions(-) diff --git a/hooks/develhook.cpp b/hooks/develhook.cpp index 33c3488..0902aaa 100644 --- a/hooks/develhook.cpp +++ b/hooks/develhook.cpp @@ -3,6 +3,7 @@ #include "util/detour.h" #include "util/libutils.h" #include "util/utils.h" +#include "util/sigscan.h" #include "avs/core.h" #include "avs/game.h" #include "hooks/wmischook.h" @@ -23,7 +24,7 @@ public: log_warning("hooks::devel::thumbnail", "Forcing thumbnail patch.."); hooks::wmisc::apply_performance_hacks(avs::game::DLL_INSTANCE, "FORCE", "thumbnail"); } -} thumbnail_("thum_test"); +} thumbnail_("wmisc_thum"); static class Msacm : public Routine { @@ -34,7 +35,18 @@ public: log_warning("hooks::devel::msacm", "Forcing msacm patch.."); hooks::wmisc::apply_performance_hacks(avs::game::DLL_INSTANCE, "FORCE", "msacm"); } -} msacm_("acm_test"); +} msacm_("wmisc_acm"); + +static class DmoEffector : public Routine +{ +public: + using Routine::Routine; + void entry_main() override + { + log_warning("hooks::devel::msacm", "Forcing msacm patch.."); + hooks::wmisc::apply_performance_hacks(avs::game::DLL_INSTANCE, "FORCE", "dmoeffector"); + } +} dmoeffector_("wmisc_dmoeffector"); static class Wmisc : public Routine { @@ -45,7 +57,12 @@ public: log_warning("hooks::devel::wmisc", "Disabling auto-patching.."); hooks::wmisc::skip_patching_by_model(true); } -} wmisc_("wmisc_test"); + void entry_main() override + { + // Reenable logging + hooks::wmisc::apply_performance_hacks(avs::game::DLL_INSTANCE, "FORCE", "bmsound"); + } +} wmisc_("disable_auto_wmisc"); static class Avs_fs : public Routine { @@ -90,6 +107,53 @@ public: } } avs_fs_("avs_fs_detour"); +static class CMoviePlayer : public Routine +{ +private: + typedef void (*GetWmvChunk_t)(uint8_t *param_1); + inline static GetWmvChunk_t GetWmvChunk_; + + + static void on_get_wmv_chunk_(uint8_t *param_1) + { + static FILE *fp = nullptr; + if (!fp) + { + fp = fopen("data/movie/testbg2_fhd.wmv", "rb"); + if (!fp) + log_warning("hooks::devel::CMoviePlayer", "Missing wmv file"); + } + + // Read from file (skip AVS) + if (fp) + { + int chunksz = *(uint32_t *) (param_1 + 0x10); + log_misc("hooks::devel::CMoviePlayer", "Reading {} bytes", chunksz); + int readsz = fread((void *) *(intptr_t *) (param_1 + 0x08), chunksz, 1, fp); + *(int *) (param_1 + 0x14) = readsz; + if(readsz < chunksz) + { + fclose(fp); + fp = nullptr; + } + } + + } + +public: + using Routine::Routine; + void entry_main() override + { + log_warning("hooks::devel", "Test code for SDVX5::CMoviePlayer only"); + + intptr_t TX_ThumExists = find_pattern_from(avs::game::DLL_INSTANCE, "40534883ec20448b4110488bd9488b51088b09ff150000000089431485c0791d448bc0488d1500000000488d0d000000004883c4205b48ff25000000004883c4205bc3", "XXXXXXXXXXXXXXXXXXXXX????XXXXXXXXXXXXX????XXX????XXXXXXXX????XXXXXX", 0, 0, 0); + if (!detour::trampoline_try(reinterpret_cast(TX_ThumExists), reinterpret_cast(on_get_wmv_chunk_), reinterpret_cast(&GetWmvChunk_))) + { + log_fatal("hooks::devel", "Hook failed"); + } + } +} cmovieplayer_("wmisc_cmovieplayer"); + std::vector from_env(const char *str) { std::vector r; @@ -103,9 +167,9 @@ std::vector from_env(const char *str) return r; } -static std::vector &routines() +static std::vector &routines() { - static std::vector routines_; + static std::vector routines_; if (routines_.empty()) { //Default routines @@ -113,6 +177,8 @@ static std::vector &routines() routines_.push_back(&thumbnail_); routines_.push_back(&msacm_); routines_.push_back(&wmisc_); + routines_.push_back(&cmovieplayer_); + routines_.push_back(&dmoeffector_); } return routines_; } diff --git a/hooks/wmischook.cpp b/hooks/wmischook.cpp index 1df3144..25436dc 100644 --- a/hooks/wmischook.cpp +++ b/hooks/wmischook.cpp @@ -135,9 +135,49 @@ void attach(HINSTANCE hmodule) { BmswLogInit = (BmswLogInit_t) GetProcAddress(bmsw, "BmswLogInit"); } - if(BmswLogInit) //_REM: keep 0.2.x backward compatibility until 0.3.0 + if (BmswLogInit) //_REM: keep 0.2.x backward compatibility until 0.3.0 { - BmswLogInit(reinterpret_cast(on_log_msg)); + BmswLogInit(reinterpret_cast(on_log_msg)); + } +} +} + +namespace hooks::wmisc::cmovieplayer +{ +typedef void (*GetWmvChunk_t)(uint8_t *unk); +static GetWmvChunk_t GetWmvChunk_; + +void on_get_wmv_chunk_(uint8_t *unk) +{ + size_t chunksz = *(uint32_t *) (unk + 0x10); + void *readbuf = (void *) *(intptr_t *) (unk + 0x08); + int *readsz = (int *) (unk + 0x14); + + //_REV: For now simply disable broken video stream + *readsz = 0; +} +void attach(HINSTANCE hmodule) +{ + // Remove crashing movie + intptr_t TX_ThumExists = find_pattern_from(hmodule, "40534883ec20448b4110488bd9488b51088b09ff150000000089431485c0791d448bc0488d1500000000488d0d000000004883c4205b48ff25000000004883c4205bc3", "XXXXXXXXXXXXXXXXXXXXX????XXXXXXXXXXXXX????XXX????XXXXXXXX????XXXXXX", 0, 0, 0); + log_info("hooks::wmisc::cmovieplayer", "Hooking GetWmvChunk({})", reinterpret_cast(TX_ThumExists)); + if (detour::trampoline_try(reinterpret_cast(TX_ThumExists), reinterpret_cast(on_get_wmv_chunk_), reinterpret_cast(&GetWmvChunk_))) + { + log_warning("hooks::wmisc::cmovieplayer", "Video playback for wmv won't work"); + } +} +} + +namespace hooks::wmisc::dmoeffector +{ +void attach(HINSTANCE hmodule) +{ + //_REM: Disable dmoeffector error printing for line55, could not find unique pattern (9 matches, but patching all of them is harmless) + intptr_t next = (intptr_t) hmodule; + while (next) + { + next = replace_pattern_from(hmodule, "793ae8????????895424??4c8d05????????488bc8488d15????????41b937000000e8????????ff15????????", "eb3ae8????????895424??4c8d05????????488bc8488d15????????41b937000000e8????????ff15????????", 0, 0, next - reinterpret_cast(hmodule)); + if (next) log_info("hooks::wmisc::dmoeffector", "Muting error message({})", reinterpret_cast(next)); } } } @@ -154,6 +194,7 @@ void apply_performance_hacks(HINSTANCE hmodule, const char *model, const char *e if (!patchmodel_ && strcmp(model, "FORCE") != 0) return; log_info("hooks::wmisc", "Enabling performance patches for {}-{}", model, ext); + long extl = strtol(ext, nullptr, 10); switch (to_hash(model)) { case to_hash("LDJ"): @@ -165,6 +206,15 @@ void apply_performance_hacks(HINSTANCE hmodule, const char *model, const char *e msacm::attach(hmodule); bmsound::attach(hmodule); break; + case to_hash("KFC"): + msacm::attach(hmodule); + bmsound::attach(hmodule); + if (extl > 2019020600 && extl < 2021011800) // SDVX5 + { + cmovieplayer::attach(hmodule); + dmoeffector::attach(hmodule); + } + break; case to_hash("FORCE"): switch (to_hash(ext)) { @@ -177,6 +227,12 @@ void apply_performance_hacks(HINSTANCE hmodule, const char *model, const char *e case to_hash("bmsound"): bmsound::attach(hmodule); break; + case to_hash("cmovieplayer"): + cmovieplayer::attach(hmodule); + break; + case to_hash("dmoeffector"): + dmoeffector::attach(hmodule); + break; default: break; }