Files
spice2x-r3d/hooks/develhook.cpp
T
[ ] ea5d566218 feat: Test spicetools logging bmsound-wine side
> broken commit
> route bmsound messages back to spicetools log
2025-12-20 21:23:22 +09:00

159 lines
4.7 KiB
C++

#include "develhook.h"
#include "util/logging.h"
#include "util/detour.h"
#include "util/libutils.h"
#include "util/utils.h"
#include "avs/core.h"
#include "avs/game.h"
#include "hooks/wmischook.h"
#include "external/stackwalker/stackwalker.h"
#include <vector>
#include <string>
#include <sstream>
namespace hooks::devel
{
static class Thumbnail : public Routine
{
public:
using Routine::Routine;
void entry_main() override
{
log_warning("hooks::devel::thumbnail", "Forcing thumbnail patch..");
hooks::wmisc::apply_performance_hacks(avs::game::DLL_INSTANCE, "FORCE", "thumbnail");
}
} thumbnail_("thum_test");
static class Msacm : 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", "msacm");
}
} msacm_("acm_test");
static class Wmisc : public Routine
{
public:
using Routine::Routine;
void attach() override
{
log_warning("hooks::devel::wmisc", "Disabling auto-patching..");
hooks::wmisc::skip_patching_by_model(true);
hooks::wmisc::apply_performance_hacks(avs::game::DLL_INSTANCE, "FORCE", "bmsound");
}
} wmisc_("wmisc_test");
static class Avs_fs : public Routine
{
private:
static constexpr char needle_[] = ""; // set to "" to print all
inline static avs::core::AVS_FS_LSTAT_T avs_fs_lstat_;
inline static avs::core::AVS_FS_MOUNT_T avs_fs_mount_;
inline static avs::core::AVS_FS_OPEN_T avs_fs_open_;
static int on_avs_fs_lstat(const char *path, struct avs::core::avs_stat *stat)
{
if (strstr(path, needle_))
{
log_info("hooks::devel", "{}({})", __FUNCTION__, path);
}
return avs_fs_lstat_(path, stat);
}
static 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::devel", "{}({}=>{}) @{} :nullptr data?{} ", __FUNCTION__, fsroot, mountpoint, fstype, data == nullptr);
}
return avs_fs_mount_(mountpoint, fsroot, fstype, data);
}
static avs::core::avs_file_t on_avs_fs_open(const char *name, uint16_t mode, int flags)
{
if (strstr(name, needle_))
{
log_info("hooks::devel", "{}({}::{}) @{}", __FUNCTION__, name, mode, flags);
}
return avs_fs_open_(name, mode, flags);
}
public:
using Routine::Routine;
void entry_main() override
{
detour::trampoline(reinterpret_cast<void *>(avs::core::avs_fs_lstat), reinterpret_cast<void *>(on_avs_fs_lstat), reinterpret_cast<void **>(&avs_fs_lstat_));
detour::trampoline(reinterpret_cast<void *>(avs::core::avs_fs_mount), reinterpret_cast<void *>(on_avs_fs_mount), reinterpret_cast<void **>(&avs_fs_mount_));
detour::trampoline(reinterpret_cast<void *>(avs::core::avs_fs_open), reinterpret_cast<void *>(on_avs_fs_open), reinterpret_cast<void **>(&avs_fs_open_));
}
} avs_fs_("avs_fs_detour");
std::vector<std::string> from_env(const char *str)
{
std::vector<std::string> r;
std::stringstream ss(getenv(str) ? getenv(str) : "");
std::string flag;
while (std::getline(ss, flag, ';'))
{
r.push_back(flag);
}
return r;
}
static std::vector<Routine*> &routines()
{
static std::vector<Routine*> routines_;
if (routines_.empty())
{
//Default routines
routines_.push_back(&avs_fs_);
routines_.push_back(&thumbnail_);
routines_.push_back(&msacm_);
routines_.push_back(&wmisc_);
}
return routines_;
}
Routine *active_routine(const char *name)
{
unsigned int hash = to_hash(name);
for (auto &routine: routines())
{
if (routine->hash() == hash)
return routine;
}
return nullptr;
}
void bind_routine(Routine *routine)
{
routines().push_back(routine);
}
void log_environment()
{
log_warning("hooks::devel", "WINEDLLOVERRIDES: '{}'", getenv("WINEDLLOVERRIDES") ? getenv("WINEDLLOVERRIDES") : "null");
}
void entry_main()
{
log_environment();
const auto rnames = from_env("SPICE_DEVEL");
if (!rnames.empty()) log_info("hooks::devel", "Run subroutines..");
for (const auto &routinename: from_env("SPICE_DEVEL"))
{
Routine *routine = active_routine(routinename.c_str());
if (routine) routine->entry_main();
}
}
void attach()
{
const auto rnames = from_env("SPICE_DEVEL");
if (!rnames.empty()) log_info("hooks::devel", "Attach subroutines..");
for (const auto &rname: rnames)
{
Routine *routine = active_routine(rname.c_str());
if (routine) routine->attach();
}
}
}