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); }