diff --git a/CMakeLists.txt b/CMakeLists.txt index 3b88a54..bc12575 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -464,6 +464,7 @@ set(SOURCE_FILES ${SOURCE_FILES} hooks/audio/implementations/wave_out.cpp hooks/audio/implementations/none.cpp hooks/audio/implementations/pipewire.cpp + hooks/develhook.cpp hooks/sndbhook.cpp hooks/avshook.cpp hooks/cfgmgr32hook.cpp diff --git a/hooks/develhook.cpp b/hooks/develhook.cpp new file mode 100644 index 0000000..039fddd --- /dev/null +++ b/hooks/develhook.cpp @@ -0,0 +1,112 @@ +#include "develhook.h" +#include "util/logging.h" +#include "util/detour.h" +#include "avs/core.h" +#include +#include +#include + + +namespace hooks::devel::avs_fs +{ +static constexpr char needle_[] = ""; // set to "" to print all +static avs::core::AVS_FS_LSTAT_T avs_fs_lstat_; +static avs::core::AVS_FS_MOUNT_T avs_fs_mount_; +static avs::core::AVS_FS_OPEN_T avs_fs_open_; + +int on_avs_fs_lstat(const char *path, struct avs::core::avs_stat *stat) +{ + if (strstr(path, needle_)) + { + log_info("hooks::soundbank", "{}({})", __FUNCTION__, path); + } + return avs_fs_lstat_(path, stat); +} +avs::core::avs_file_t on_avs_fs_mount(const char *mountpoint, const char *fsroot, const char *fstype, void *data) +{ + if (strstr(fsroot, needle_)) + { + log_info("hooks::soundbank", "{}({}=>{}) @{} :nullptr data?{} ", __FUNCTION__, fsroot, mountpoint, fstype, data == nullptr); + } + return avs_fs_mount_(mountpoint, fsroot, fstype, data); +} +avs::core::avs_file_t on_avs_fs_open(const char *name, uint16_t mode, int flags) +{ + if (strstr(name, needle_)) + { + log_info("hooks::soundbank", "{}({}::{}) @{}", __FUNCTION__, name, mode, flags); + } + return avs_fs_open_(name, mode, flags); +} +void run() +{ + detour::trampoline(reinterpret_cast(avs::core::avs_fs_lstat), reinterpret_cast(on_avs_fs_lstat), reinterpret_cast(&avs_fs_lstat_)); + detour::trampoline(reinterpret_cast(avs::core::avs_fs_mount), reinterpret_cast(on_avs_fs_mount), reinterpret_cast(&avs_fs_mount_)); + detour::trampoline(reinterpret_cast(avs::core::avs_fs_open), reinterpret_cast(on_avs_fs_open), reinterpret_cast(&avs_fs_open_)); +} +} + +namespace hooks::devel +{ +void (*routine_cb_[devel_routine_last])() ={ + [avs_fs_detour] = avs_fs::run +}; + +static constexpr unsigned int by_str(const char *str, int h = 0) +{ + return !str[h] ? 5381 : (by_str(str, h + 1) * 33) ^ str[h]; +} +std::vector from_env(const char *str) +{ + std::vector r; + std::stringstream ss(getenv(str) ? getenv(str) : ""); + std::string flag; + + while (std::getline(ss, flag, ';')) + { + r.push_back(flag); + } + + return r; +} +static devel_routine_t routines() +{ + static devel_routine_t routines_ = -1; + if (routines_ == static_cast(-1)) + { + routines_ = 0; + for (const auto &routine: from_env("SPICE_DEVEL")) + { + switch (by_str(routine.c_str())) + { + case by_str("avs_fs_detour"): + routines_ |= 1 << avs_fs_detour; + break; + case by_str("sndb_test"): + routines_ |= 1 << sndb_test; + break; + default: + break; + } + } + } + + return routines_; +} +bool active_routine(hooks::devel::devel_routine_t val) +{ + return routines() & (1 << val); +} +void bind_routine(devel_routine_t val, void (*cb)()) +{ + routine_cb_[val] = cb; +} +void entry_main() +{ + if (routines()) log_info("hooks:devel", "Processing subroutines.."); + for (devel_routine_t i = 0; i < devel_routine_last; i++) + { + if (active_routine(i) && routine_cb_[i]) routine_cb_[i](); + } +} +} \ No newline at end of file diff --git a/hooks/develhook.h b/hooks/develhook.h new file mode 100644 index 0000000..89eb741 --- /dev/null +++ b/hooks/develhook.h @@ -0,0 +1,19 @@ +#pragma once +#include + + +namespace hooks::devel +{ +//_INFO: order matters, low level routines first (if you want them active during later routines) +enum devel_routine : uint32_t +{ + avs_fs_detour = 0, + sndb_test, + devel_routine_last +}; +typedef uint32_t devel_routine_t; + +bool active_routine(devel_routine_t val); +void bind_routine(devel_routine_t val, void (*cb)()); +void entry_main(); +} diff --git a/hooks/sndbhook.cpp b/hooks/sndbhook.cpp index 01431ec..b2e81a4 100644 --- a/hooks/sndbhook.cpp +++ b/hooks/sndbhook.cpp @@ -1,4 +1,5 @@ #include "sndbhook.h" +#include "hooks/develhook.h" #include "util/logging.h" #include "util/memutils.h" #include "util/sigscan.h" @@ -701,25 +702,6 @@ snd_bank *snd_bank::cache_ = nullptr; size_t snd_bank::cachesz_ = 0; avcodec::pcm_resampler_t snd_bank::resampler_ = avcodec::bmswac_resampler_s16; static BmsbEnumValidSoundbanks_t BmsbEnumValidSoundbanks; -static avs::core::AVS_FS_LSTAT_T avs_fs_lstat_; -static avs::core::AVS_FS_MOUNT_T avs_fs_mount_; - -int on_avs_fs_lstat(const char *path, struct avs::core::avs_stat *stat) -{ - if (strstr(path, "29095")) - { - log_info("hooks::soundbank", "avs_fs_lstat_({})", path); - } - return avs_fs_lstat_(path, stat); -} -avs::core::avs_file_t on_avs_fs_mount(const char *mountpoint, const char *fsroot, const char *fstype, void *data) -{ - if (strstr(fsroot, "29095")) - { - log_info("hooks::soundbank", "avs_fs_mount({}=>{}) @{} :nullptr data?{} ", fsroot, mountpoint, fstype, data == nullptr); - } - return avs_fs_mount_(mountpoint, fsroot, fstype, data); -} void *on_enum_valid_soundbanks(void *song, int32_t difficulty, int32_t unk2) { // Keysounds populated into CtrlSound::Bank[2][X] = [0:s3p][1:2dx][2:_pre.2dx], always uses lowest i databank for resource confirmed valid by this function @@ -788,8 +770,6 @@ void run_tests() { log_warning("hooks::soundbank", "MF initialization failed, skipping.."); } - detour::trampoline(reinterpret_cast(avs::core::avs_fs_lstat), reinterpret_cast(on_avs_fs_lstat), reinterpret_cast(&avs_fs_lstat_)); - detour::trampoline(reinterpret_cast(avs::core::avs_fs_mount), reinterpret_cast(on_avs_fs_mount), reinterpret_cast(&avs_fs_mount_)); // Filesystem tests, s3p unpacking snprintf(avspath, sizeof(avspath), "data/sound/%05d", id); @@ -921,7 +901,7 @@ void init(HINSTANCE hmodule, const char *ext) offset_.TX_BmsbEnumValidSoundbanks = (intptr_t) hmodule + 0xafd780; break; case offset_t::by_ext("2024082600"): - offset_.TX_BmsbEnumValidSoundbanks = (intptr_t) hmodule + 0x81dd40; + offset_.TX_BmsbEnumValidSoundbanks = (intptr_t) hmodule + 0x8eae40; break; default: log_warning("hooks::soundbank", "Unsupported game version({}), skipping..", ext); @@ -940,15 +920,12 @@ void init(HINSTANCE hmodule, const char *ext) return; } - // Setup on_enum_valid_ksbd + // Setup on_enum_valid_ksbd and optional tests offset_.guard = new memutils::VProtectGuard((void *) offset_.RD_05d_2dx, SNDPATHFMTMAX); detour::trampoline(reinterpret_cast(offset_.TX_BmsbEnumValidSoundbanks), reinterpret_cast(on_enum_valid_soundbanks), reinterpret_cast(&BmsbEnumValidSoundbanks)); + hooks::devel::bind_routine(hooks::devel::sndb_test, run_tests); log_info("hooks::soundbank", "Soundbank preprocessor ready"); - - // Tests - if (getenv("SPICE_TESTING")) - run_tests(); } void deinit(HINSTANCE hmodule) { diff --git a/hooks/sndbhook.h b/hooks/sndbhook.h index c7acc35..9657ed8 100644 --- a/hooks/sndbhook.h +++ b/hooks/sndbhook.h @@ -1,5 +1,4 @@ #pragma once - #include namespace hooks::soundbank diff --git a/launcher/launcher.cpp b/launcher/launcher.cpp index 4aff697..82e4bab 100644 --- a/launcher/launcher.cpp +++ b/launcher/launcher.cpp @@ -61,6 +61,7 @@ #include "games/qks/qks.h" #include "games/mfg/mfg.h" #include "games/museca/museca.h" +#include "hooks/develhook.h" #include "hooks/avshook.h" #include "hooks/audio/audio.h" #include "hooks/debughook.h" @@ -2159,6 +2160,9 @@ int main_implementation(int argc, char *argv[]) { #endif }; + // devel start + hooks::devel::entry_main(); + // game start log_info("launcher", "calling game entry"); avs::game::entry_main();