> disable lobby video (cause for crashes in lobby), see #9 > suppress dmoeffector log messages, see #9
224 lines
6.8 KiB
C++
224 lines
6.8 KiB
C++
#include "develhook.h"
|
|
#include "util/logging.h"
|
|
#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"
|
|
#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_("wmisc_thum");
|
|
|
|
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_("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
|
|
{
|
|
public:
|
|
using Routine::Routine;
|
|
void attach() override
|
|
{
|
|
log_warning("hooks::devel::wmisc", "Disabling auto-patching..");
|
|
hooks::wmisc::skip_patching_by_model(true);
|
|
}
|
|
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
|
|
{
|
|
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");
|
|
|
|
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<void *>(TX_ThumExists), reinterpret_cast<void *>(on_get_wmv_chunk_), reinterpret_cast<void **>(&GetWmvChunk_)))
|
|
{
|
|
log_fatal("hooks::devel", "Hook failed");
|
|
}
|
|
}
|
|
} cmovieplayer_("wmisc_cmovieplayer");
|
|
|
|
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_);
|
|
routines_.push_back(&cmovieplayer_);
|
|
routines_.push_back(&dmoeffector_);
|
|
}
|
|
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();
|
|
}
|
|
}
|
|
} |