From 4a45f4d9c4ed692f4f9bcddb171c68aa43e13550 Mon Sep 17 00:00:00 2001
From: "[ ]" <[ ]>
Date: Mon, 26 May 2025 23:14:57 +0900
Subject: [PATCH] refactor: Add transcoding support for more styles
> some styles still won't work due to SOUND DATA CREATE ERROR
> related to #1
---
games/iidx/iidx.cpp | 4 +--
hooks/bmsbhook.cpp | 79 +++++++++++++++++++++++++++++++++------------
hooks/bmsbhook.h | 2 +-
3 files changed, 62 insertions(+), 23 deletions(-)
diff --git a/games/iidx/iidx.cpp b/games/iidx/iidx.cpp
index 08ca2b6..a5fac16 100644
--- a/games/iidx/iidx.cpp
+++ b/games/iidx/iidx.cpp
@@ -376,7 +376,7 @@ namespace games::iidx {
cfgmgr32hook_init(avs::game::DLL_INSTANCE);
// wine fixes
- hooks::bmsb::init(avs::game::DLL_INSTANCE);
+ hooks::bmsb::init(avs::game::DLL_INSTANCE, avs::game::EXT);
}
@@ -414,7 +414,7 @@ namespace games::iidx {
"!!! please do the following instead: !!!\n"
"!!! !!!\n"
"!!! Revert your changes to XML file so it says !!!\n"
- "!!! LDJ !!!\n"
+ "!!! LDJ !!!\n"
"!!! !!!\n"
"!!! In SpiceCfg, enable 'IIDX TDJ Mode' or provide -iidxtdj flag !!!\n"
"!!! in command line !!!\n"
diff --git a/hooks/bmsbhook.cpp b/hooks/bmsbhook.cpp
index 0024852..ad40935 100644
--- a/hooks/bmsbhook.cpp
+++ b/hooks/bmsbhook.cpp
@@ -15,7 +15,7 @@
#include
-void dump(const char *path, const uint8_t *src, size_t sz)
+void dump_(const char *path, const uint8_t *src, size_t sz)
{
FILE *fh = fopen(path, "wb");
fwrite(src, sz, 1, fh);
@@ -526,7 +526,15 @@ static struct offset_t
intptr_t RD_05d_2dx; // %05d/%05d.2dx
intptr_t RD_05d_c_2dx; // %05d/%05d%c.2dx
intptr_t TX_BmsbEnumValidSoundbanks; // enumerates above databank paths, simple exist check (lstat()/OPEN -> CLOSE_NOWRITE only)
+ intptr_t DAT_song_titlel;
+ intptr_t DAT_song_artistl;
+ intptr_t DAT_song_id;
memutils::VProtectGuard *guard;
+
+ static constexpr unsigned int by_ext(const char *ext, int h = 0)
+ {
+ return !ext[h] ? 5381 : (by_ext(ext, h + 1) * 33) ^ ext[h];
+ }
} offset_;
soundbank *soundbank::cache_ = nullptr;
@@ -597,7 +605,7 @@ void soundbank::cache_bank_any(const uint8_t *sndbuf, size_t sz)
char path[AVSPATHMAX];
snprintf(path, sizeof(path), "%s.2dx", this->avspath);
log_info("hooks::bmsb", "Storing as intermediate soundbank at '{}'", (const char *) path);
- dump(path, sndbuf, sz);
+ dump_(path, sndbuf, sz);
}
soundbank::soundbank() : id(0), avspath(""), uid_(UID_INVALID), mnt_(E_NOT_FOUND), next_(nullptr)
{
@@ -714,11 +722,11 @@ avs::core::avs_file_t soundbank::map_ifs(char *avspath)
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
- // Struct memory layout 1:1 with data/info/music_*.bin _BUG: therefore differs a bit between some styles
+ // Struct memory layout 1:1 with data/info/(0/1)/music_*.bin
soundbank *keysounds = nullptr;
- const char *titlel = (const char *) song;
- const char *artistl = (const char *) song + 0xc0;
- const int32_t id = *(int32_t *) ((const char *) song + 0x3b0);
+ const char *titlel = (const char *) song + offset_.DAT_song_titlel;
+ const char *artistl = (const char *) song + offset_.DAT_song_artistl;
+ const int32_t id = *(int32_t *) ((const char *) song + offset_.DAT_song_id);
log_info("hooks::bmsb", "Processing s3p->2dx transcoding routine for [{}]({} - {})", id, artistl, titlel);
if (!(keysounds = soundbank::get_bank(id)))
@@ -790,11 +798,11 @@ void run_tests()
log_info("hooks:bmsb", "{}::Bank[S3P]::Voice[0]::Size {}", id, snds3p->voice_ptr(0)->sz);
memcpy(sig, snds3p->voice(0)->sig, 4);
log_info("hooks:bmsb", "{}::Bank[S3P]::Voice[0]::Signature {}", id, sig);
- dump("raw_wma.wma", snds3p->voice(0)->asf(), snds3p->voice(0)->sz);
+ dump_("raw_wma.wma", snds3p->voice(0)->asf(), snds3p->voice(0)->sz);
// MF codec (tainted PCM data, bad)
mf_broken::asf_to_wav(snds3p->voice(0)->asf(), snds3p->voice(0)->sz, &wav, &wavsz);
- dump("mf_wav.wav", wav, wavsz);
+ dump_("mf_wav.wav", wav, wavsz);
free(wav);
wav = nullptr;
wavsz = 0;
@@ -802,7 +810,7 @@ void run_tests()
// AV codec (1:1 unmodified PCM data, other than resampling if enabled)
wav = (BYTE *) malloc(snd_2dx::assertsz_asf(snds3p->voice(0)->sz));
avcodec::BmswTranscoderAsfToWav(snds3p->voice(0)->asf(), snds3p->voice(0)->sz, &wav, &wavsz, avcodec::bmswac_resampler_s16);
- dump("ac_wav.wav", wav, wavsz);
+ dump_("ac_wav.wav", wav, wavsz);
free(wav);
wav = nullptr;
wavsz = 0;
@@ -825,9 +833,9 @@ void run_tests()
}
// Valid 2DX (trim is not necessary)
- log_info("hooks:bmsb", "25073::Bank[2DX]::dump()");
+ log_info("hooks:bmsb", "25073::Bank[2DX]::Dumping");
snd_2dx::bank *buf2dx = snd2dx->serialize(false);
- dump("ac_25073.2dx", reinterpret_cast(buf2dx), buf2dx->sz());
+ dump_("ac_25073.2dx", reinterpret_cast(buf2dx), buf2dx->sz());
}
else
@@ -849,10 +857,9 @@ void run_tests()
// Caching and intermediate 2dx storage detection
BmsbEnumValidSoundbanks_t t = BmsbEnumValidSoundbanks;
- BmsbEnumValidSoundbanks = [](void *, int32_t, int32_t) { log_info("hooks:bmsb", "BmsbEnumValidSoundbanks(0x0)"); };
+ BmsbEnumValidSoundbanks = [](void *, int32_t, int32_t) { log_info("hooks::bmsb", "BmsbEnumValidSoundbanks(fallback)"); };
char *tmp = (char *) malloc(0x3b0 + sizeof(int32_t));
- int arr[10] = {25073, 26020, 26094, 24016, 26057, 25073, 26069, 26070, 26059, 26087};
- //int arr[10] = {25073, 24016, 26057, 25073, 26087};
+ int arr[6] = {25073, 24016, 26057, 25073, 26087, 29095};
strcpy(tmp, "SJISTITLE");
strcpy(tmp + 0xc0, "SJISARTIST");
for (int it: arr)
@@ -866,26 +873,57 @@ void run_tests()
}
-void init(HINSTANCE hmodule)
+void init(HINSTANCE hmodule, const char *ext)
{
if (false && IsDebuggerPresent())
{
log_warning("hooks::bmsb", "Debugger detected, skipping..");
return;
}
-
if (!mf_broken::init())
{
log_warning("hooks::bmsb", "MF initialization failed, skipping..");
}
-
if (!avcodec::init())
{
log_warning("hooks::bmsb", "AVCodec initialization failed, skipping..");
}
- // Override .text
- offset_.TX_BmsbEnumValidSoundbanks = (intptr_t) hmodule + 0xafd780; //_TODO: Hardcoded for iidx30 for now, requires asm pattern lookup
+ // Override .text .data per datacode _REV: prefer unique asm pattern offset lookup
+ offset_.DAT_song_titlel = 0x00;
+ offset_.DAT_song_artistl = 0xc0;
+ offset_.DAT_song_id = 0x3b0;
+ switch (offset_t::by_ext(ext))
+ {
+ case offset_t::by_ext("2018091900"):
+ offset_.TX_BmsbEnumValidSoundbanks = (intptr_t) hmodule + 0x1170b0;
+ offset_.DAT_song_id = 0x1C8;
+ break;
+ case offset_t::by_ext("2019090200"):
+ case offset_t::by_ext("2019100700"):
+ offset_.TX_BmsbEnumValidSoundbanks = (intptr_t) hmodule + 0x37a540;
+ offset_.DAT_song_id = 0x1C8;
+ break;
+ case offset_t::by_ext("2020092900"):
+ offset_.TX_BmsbEnumValidSoundbanks = (intptr_t) hmodule + 0x5ac460;
+ break;
+ case offset_t::by_ext("2021083000"):
+ offset_.TX_BmsbEnumValidSoundbanks = (intptr_t) hmodule + 0x766bc0;
+ break;
+ case offset_t::by_ext("2021091500"):
+ offset_.TX_BmsbEnumValidSoundbanks = (intptr_t) hmodule + 0x766c60;
+ break;
+ case offset_t::by_ext("2022082400"):
+ offset_.TX_BmsbEnumValidSoundbanks = (intptr_t) hmodule + 0x46e160;
+ break;
+ case offset_t::by_ext("2023090500"):
+ offset_.TX_BmsbEnumValidSoundbanks = (intptr_t) hmodule + 0xafd780;
+ break;
+ default:
+ log_warning("hooks::bmsb", "Unsupported game version({}), skipping..", ext);
+ return;
+ }
+ log_info("hooks::bmsb", "Supported game version({})", ext);
// Override .rdata
offset_.RD_05d_s3p = replace_pattern(hmodule, "253035642f253035642e73337000", "003035642f253035642e73337000", 0, 0);
@@ -907,7 +945,8 @@ void init(HINSTANCE hmodule)
// Tests _REM: tests
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_));
- run_tests();
+ if (offset_t::by_ext(ext) == offset_t::by_ext("2023090500"))
+ run_tests();
}
diff --git a/hooks/bmsbhook.h b/hooks/bmsbhook.h
index e8df3de..45decda 100644
--- a/hooks/bmsbhook.h
+++ b/hooks/bmsbhook.h
@@ -4,6 +4,6 @@
namespace hooks::bmsb
{
-void init(HINSTANCE hmodule);
+void init(HINSTANCE hmodule, const char *ext);
void deinit(HINSTANCE hmodule);
}