refactor: Soundbank runtime hooking improvement

> change default behaviour to pattern based patch for hooks::soundbank, see #13
> fix broken check for hooks::soundbank unsupported game version
This commit is contained in:
[ ]
2026-02-17 19:30:01 +09:00
parent 97cca85bc8
commit 82439962d6
3 changed files with 108 additions and 35 deletions
+8 -34
View File
@@ -901,7 +901,7 @@ void init(HINSTANCE hmodule, const char *model, const char *ext)
return; return;
} }
// Override .text .data per datacode _REV: prefer runtime offset lookup based on universal asm pattern // Override .text .data per datacode (pattern match)
long extl = strtol(ext, nullptr, 10); long extl = strtol(ext, nullptr, 10);
if (extl < 2019100800) if (extl < 2019100800)
{ {
@@ -925,42 +925,16 @@ void init(HINSTANCE hmodule, const char *model, const char *ext)
offset_.DAT_song_id = 0x67c; offset_.DAT_song_id = 0x67c;
offset_.is_lstr_wchar = true; offset_.is_lstr_wchar = true;
} }
switch (to_hash(ext)) intptr_t beg, match;
offset_.TX_EnumValidSoundbanks = beg = match = find_asm_leacstr_from(hmodule, R8, "%05d/%05d.2dx");
while (beg > sizeof(void *) && match >= offset_.TX_EnumValidSoundbanks) //_REV: probably should be sigscan helper due to find_pattern_from performance, unify with wmischook
{ {
case to_hash("2018091900"): beg -= sizeof(void *);
offset_.TX_EnumValidSoundbanks = (intptr_t) hmodule + 0x1170b0; match = find_pattern_from(hmodule, "4057", "XX", 0, 0, beg - reinterpret_cast<intptr_t>(hmodule));
break;
case to_hash("2019090200"):
case to_hash("2019100700"):
offset_.TX_EnumValidSoundbanks = (intptr_t) hmodule + 0x37a540;
break;
case to_hash("2020092900"):
offset_.TX_EnumValidSoundbanks = (intptr_t) hmodule + 0x5ac460;
break;
case to_hash("2021083000"):
offset_.TX_EnumValidSoundbanks = (intptr_t) hmodule + 0x766bc0;
break;
case to_hash("2021091500"):
offset_.TX_EnumValidSoundbanks = (intptr_t) hmodule + 0x766c60;
break;
case to_hash("2022082400"):
offset_.TX_EnumValidSoundbanks = (intptr_t) hmodule + 0x46e160;
break;
case to_hash("2023090500"):
offset_.TX_EnumValidSoundbanks = (intptr_t) hmodule + 0xafd780;
break;
case to_hash("2024082600"):
offset_.TX_EnumValidSoundbanks = (intptr_t) hmodule + 0x8eae40;
break;
case to_hash("2025082500"):
offset_.TX_EnumValidSoundbanks = (intptr_t) hmodule + 0x969fb0;
break;
default:
break;
} }
snd_bank::resampler_ = avcodec::BmswTranscoderResampler() == avcodec::bmswac_resampler_none ? snd_bank::resampler_ : avcodec::BmswTranscoderResampler(); snd_bank::resampler_ = avcodec::BmswTranscoderResampler() == avcodec::bmswac_resampler_none ? snd_bank::resampler_ : avcodec::BmswTranscoderResampler();
offset_.TX_EnumValidSoundbanks = avcodec::BmswTranscoderEnumValidSoundbanksAddr() == 0x0 ? offset_.TX_EnumValidSoundbanks : (intptr_t) hmodule + (int64_t) avcodec::BmswTranscoderEnumValidSoundbanksAddr(); offset_.TX_EnumValidSoundbanks = avcodec::BmswTranscoderEnumValidSoundbanksAddr() == 0x0 ? match : (intptr_t) hmodule + (int64_t) avcodec::BmswTranscoderEnumValidSoundbanksAddr();
if (offset_.TX_EnumValidSoundbanks == (intptr_t) hmodule) if (!offset_.TX_EnumValidSoundbanks)
{ {
log_warning("hooks::soundbank", "Unsupported game version({}), skipping..", ext); log_warning("hooks::soundbank", "Unsupported game version({}), skipping..", ext);
return; return;
+49
View File
@@ -249,3 +249,52 @@ bool get_pe_identifier(const std::filesystem::path& dll_path, uint32_t* time_dat
return true; return true;
} }
intptr_t find_asm_leacstr_from(HMODULE module, reg_t reg, const char *cstr)
{
// get module information
MODULEINFO module_info{};
if (!GetModuleInformation(GetCurrentProcess(), module, &module_info, sizeof(module_info)))
{
return 0;
}
const unsigned char *modbegp = reinterpret_cast<unsigned char *>(module);
const unsigned char *modendp = reinterpret_cast<unsigned char *>(module) + static_cast<size_t>(module_info.SizeOfImage);
// search cstr
const unsigned char *cstr_addr = std::search(
modbegp,
modendp,
reinterpret_cast<const unsigned char *>(cstr),
reinterpret_cast<const unsigned char *>(cstr) + strlen(cstr)
);
if (cstr_addr == modendp)
{
return 0;
}
#if defined(__i386__)
// find LEA REG, [abs32]
unsigned char asmop[6] = { 0x8D, reg.v, 0x00, 0x00, 0x00, 0x00};
int32_t dist32 = reinterpret_cast<int32_t>(cstr_addr);
memcpy(asmop + (sizeof(asmop) - 4), &dist32, 4);
return reinterpret_cast<intptr_t>(std::search(
modbegp,
modendp,
asmop,
asmop + sizeof(asmop)
));
#elif defined(__x86_64__)
// find LEA REG, [RIP + rel32]
unsigned char rex = reg.t == GPR_EXT ? 0x4C : 0x48;
unsigned char asmop[7] = {rex, 0x8D, reg.v, 0x00, 0x00, 0x00, 0x00};
for (const unsigned char *addr = modbegp; addr < modendp - sizeof(asmop); addr++)
{
auto dist32 = static_cast<int32_t>(reinterpret_cast<intptr_t>(cstr_addr) - reinterpret_cast<intptr_t>(addr + sizeof(asmop)));
memcpy(asmop + (sizeof(asmop) - 4), &dist32, 4);
if (memcmp(addr, asmop, sizeof(asmop)) == 0) return reinterpret_cast<intptr_t>(addr);
}
#endif
return 0;
}
+50
View File
@@ -90,3 +90,53 @@ intptr_t replace_pattern_from(
intptr_t start_from); intptr_t start_from);
bool get_pe_identifier(const std::filesystem::path& dll_path, uint32_t* time_date_stamp, uint32_t* address_of_entry_point); bool get_pe_identifier(const std::filesystem::path& dll_path, uint32_t* time_date_stamp, uint32_t* address_of_entry_point);
union reg_t{
struct{
unsigned char t;
unsigned char v;
};
unsigned short s;
constexpr reg_t(unsigned char t, unsigned char v) : s(v << 8 | t) {}
constexpr reg_t(unsigned short s) : s(s) {}
};
enum REGTYPE : unsigned char
{
GPR_32,
GPR_64,
GPR_EXT
};
enum REG : unsigned short
{
EAX = reg_t(GPR_32, 0x05).s,
ECX = reg_t(GPR_32, 0x0D).s,
EDX = reg_t(GPR_32, 0x15).s,
EBX = reg_t(GPR_32, 0x1D).s,
ESP = reg_t(GPR_32, 0x25).s,
EBP = reg_t(GPR_32, 0x2D).s,
ESI = reg_t(GPR_32, 0x35).s,
EDI = reg_t(GPR_32, 0x3D).s,
RAX = reg_t(GPR_64, 0x05).s,
RCX = reg_t(GPR_64, 0x0D).s,
RDX = reg_t(GPR_64, 0x15).s,
RBX = reg_t(GPR_64, 0x1D).s,
RSP = reg_t(GPR_64, 0x25).s,
RBP = reg_t(GPR_64, 0x2D).s,
RSI = reg_t(GPR_64, 0x35).s,
RDI = reg_t(GPR_64, 0x3D).s,
R8 = reg_t(GPR_EXT, 0x05).s,
R9 = reg_t(GPR_EXT, 0x0D).s,
R10 = reg_t(GPR_EXT, 0x15).s,
R11 = reg_t(GPR_EXT, 0x1D).s,
R12 = reg_t(GPR_EXT, 0x25).s,
R13 = reg_t(GPR_EXT, 0x2D).s,
R14 = reg_t(GPR_EXT, 0x35).s,
R15 = reg_t(GPR_EXT, 0x3D).s
};
intptr_t find_asm_leacstr_from(
HMODULE module,
reg_t reg,
const char *cstr);