From 5c40178515f26e4188686b50d4ef01bd41a1ee1c Mon Sep 17 00:00:00 2001 From: RyuMiya Date: Sat, 19 Oct 2024 13:08:58 +0800 Subject: [PATCH 01/10] Add Freeze Timer for JPN39 --- README.md | 2 ++ dist/config.toml | 1 + src/helpers.h | 1 + src/patches/versions/JPN39.cpp | 56 +++++++++++++++++++++++++++++++++- 4 files changed, 59 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ab79fa1..83203c0 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,8 @@ unlock_songs = true [patches.jpn39] # sync test mode language to attract etc fix_language = false + # stop timer count down + freeze_timer = false # use cn font and chineseS wordlist value chs_patch = false # enable one piece collab mode diff --git a/dist/config.toml b/dist/config.toml index c5bd4bf..6ff0e65 100644 --- a/dist/config.toml +++ b/dist/config.toml @@ -18,6 +18,7 @@ unlock_songs = true [patches.jpn39] fix_language = false + freeze_timer = false chs_patch = false mode_collabo025 = false mode_collabo026 = false diff --git a/src/helpers.h b/src/helpers.h index fb2ba23..69e76fd 100644 --- a/src/helpers.h +++ b/src/helpers.h @@ -24,6 +24,7 @@ typedef double f64; #define FUNCTION_PTR_H(returnType, function, ...) extern returnType (*function) (__VA_ARGS__) #define PROC_ADDRESS(libraryName, procName) GetProcAddress (LoadLibrary (TEXT (libraryName)), procName) +#define PROC_ADDRESS_OFFSET(libraryName, offset) (u64)((u64)GetModuleHandle (TEXT (libraryName)) + offset) #define BASE_ADDRESS 0x140000000 #ifdef BASE_ADDRESS diff --git a/src/patches/versions/JPN39.cpp b/src/patches/versions/JPN39.cpp index 39f3d7b..4c93bec 100644 --- a/src/patches/versions/JPN39.cpp +++ b/src/patches/versions/JPN39.cpp @@ -1,7 +1,7 @@ #include "../patches.h" #include "helpers.h" #include -#include +#include namespace patches::JPN39 { @@ -17,6 +17,10 @@ HOOK_DYNAMIC (i64, __fastcall, curl_easy_setopt, i64 a1, i64 a2, i64 a3, i64 a4, FUNCTION_PTR (i64, lua_settop, PROC_ADDRESS ("lua51.dll", "lua_settop"), u64, u64); FUNCTION_PTR (i64, lua_pushboolean, PROC_ADDRESS ("lua51.dll", "lua_pushboolean"), u64, u64); FUNCTION_PTR (i64, lua_pushstring, PROC_ADDRESS ("lua51.dll", "lua_pushstring"), u64, u64); +FUNCTION_PTR (i64, lua_pushcclosure, PROC_ADDRESS ("lua51.dll", "lua_pushcclosure"), u64, u64, u64); + +FUNCTION_PTR (i64, lua_toboolean, PROC_ADDRESS ("lua51.dll", "lua_toboolean"), u64, u64); +FUNCTION_PTR (i64, lua_touserdata, PROC_ADDRESS ("lua51.dll", "lua_touserdata"), u64, u64); i64 lua_pushtrue (i64 a1) { @@ -25,6 +29,12 @@ lua_pushtrue (i64 a1) { return 1; } +i64 __fastcall +lua_freeze_timer (i64 a1) { + // i64 v2 = lua_touserdata (a1, 4294957292); + return lua_pushtrue (a1); +} + HOOK (i64, AvailableMode_Collabo024, ASLR (0x1402DE710), i64 a1) { return lua_pushtrue (a1); } HOOK (i64, AvailableMode_Collabo025, ASLR (0x1402DE6B0), i64 a1) { return lua_pushtrue (a1); } HOOK (i64, AvailableMode_Collabo026, ASLR (0x1402DE670), i64 a1) { return lua_pushtrue (a1); } @@ -65,6 +75,16 @@ ChangeLanguageType (SafetyHookContext &ctx) { if (*pFontType == 4) *pFontType = 2; } +SafetyHookMid freezeTimerHook{}; + +void +FreezeTimer (SafetyHookContext &ctx) { + auto a1 = ctx.rdi; + int v9 = (int)(ctx.rax + 1); + lua_pushcclosure(a1, reinterpret_cast(&lua_freeze_timer), v9); + ctx.rip = ASLR (0x14019FF65); +} + int language = 0; const char * languageStr () { @@ -92,12 +112,33 @@ HOOK (i64, GetCabinetLanguage, ASLR (0x1401D1A60), i64, i64 a2) { return 1; } +// int loaded_fail_count = 0; +// HOOK (i64, LoadedBankAll, ASLR (0x1404C6990), i64 a1) { +// std::cout << "LoadBankAll start" << std::endl; +// originalLoadedBankAll (a1); +// auto result = lua_toboolean(a1, -1); +// std::cout << "LoadedBankAll returns: " << result << std::endl; +// std::cout << "LoadedBankAll returns: " << *((int32_t*)result) << std::endl; +// lua_settop(a1, 0); +// if (result) { +// lua_pushboolean (a1, 1); +// } else if (loaded_fail_count > 10) { +// lua_pushboolean (a1, 1); +// } else { +// loaded_fail_count += 1; +// lua_pushboolean (a1, 0); +// } +// return 1; +// } + void Init () { + std::cout << "Init JPN39" << std::endl; i32 xRes = 1920; i32 yRes = 1080; bool unlockSongs = true; bool fixLanguage = false; + bool freezeTimer = false; bool chsPatch = false; bool modeCollabo025 = false; bool modeCollabo026 = false; @@ -112,6 +153,7 @@ Init () { auto jpn39 = openConfigSection (patches, "jpn39"); if (jpn39) { fixLanguage = readConfigBool (jpn39, "fix_language", fixLanguage); + freezeTimer = readConfigBool (jpn39, "freeze_timer", freezeTimer); chsPatch = readConfigBool (jpn39, "chs_patch", chsPatch); modeCollabo025 = readConfigBool (jpn39, "mode_collabo025", modeCollabo025); modeCollabo026 = readConfigBool (jpn39, "mode_collabo026", modeCollabo026); @@ -182,6 +224,12 @@ Init () { ReplaceLeaBufferAddress (datatableBuffer3Addresses, datatableBuffer3.data ()); } + // Freeze Timer + if (freezeTimer) { + freezeTimerHook = safetyhook::create_mid (ASLR (0x14019FF51), FreezeTimer); + + } + // patch to use chs font/wordlist instead of cht if (chsPatch) { WRITE_MEMORY (ASLR (0x140CD1AE0), char, "cn_64"); @@ -200,10 +248,14 @@ Init () { INSTALL_HOOK (GetCabinetLanguage); } + // Mode unlock if (modeCollabo025) INSTALL_HOOK (AvailableMode_Collabo025); if (modeCollabo026) INSTALL_HOOK (AvailableMode_Collabo026); if (modeAprilFool001) INSTALL_HOOK (AvailableMode_AprilFool001); + // // Fix normal song play after passing through silent song + // INSTALL_HOOK(LoadedBankAll); + // Disable live check auto amHandle = (u64)GetModuleHandle ("AMFrameWork.dll"); INSTALL_HOOK_DYNAMIC (AMFWTerminate, (void *)(amHandle + 0x42DE0)); @@ -221,5 +273,7 @@ Init () { // Redirect garmc requests auto garmcHandle = (u64)GetModuleHandle ("garmc.dll"); INSTALL_HOOK_DYNAMIC (curl_easy_setopt, (void *)(garmcHandle + 0x1FBBB0)); + + std::cout << "Finished Init JPN39" << std::endl; } } // namespace patches::JPN39 From b189ffb84f359b632b26de7f34be903b047b13fa Mon Sep 17 00:00:00 2001 From: RyuMiya Date: Sun, 20 Oct 2024 03:59:12 +0800 Subject: [PATCH 02/10] Add Silent Fix for JPN39 --- src/helpers.cpp | 2 +- src/helpers.h | 5 +- src/patches/versions/JPN39.cpp | 144 ++++++++++++++++++++++++++------- 3 files changed, 120 insertions(+), 31 deletions(-) diff --git a/src/helpers.cpp b/src/helpers.cpp index 5499668..ca437d8 100644 --- a/src/helpers.cpp +++ b/src/helpers.cpp @@ -108,4 +108,4 @@ printColour (int colour, const char *format, ...) { SetConsoleTextAttribute (consoleHandle, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED); va_end (args); -} +} \ No newline at end of file diff --git a/src/helpers.h b/src/helpers.h index 69e76fd..4005996 100644 --- a/src/helpers.h +++ b/src/helpers.h @@ -8,6 +8,9 @@ #include #include #include +#include +#include +#include typedef int8_t i8; typedef int16_t i16; @@ -128,4 +131,4 @@ bool readConfigBool (toml_table_t *table, const std::string &key, bool notFoundV int64_t readConfigInt (toml_table_t *table, const std::string &key, int64_t notFoundValue); const std::string readConfigString (toml_table_t *table, const std::string &key, const std::string ¬FoundValue); std::vector readConfigIntArray (toml_table_t *table, const std::string &key, std::vector notFoundValue); -void printColour (int colour, const char *format, ...); +void printColour (int colour, const char *format, ...); \ No newline at end of file diff --git a/src/patches/versions/JPN39.cpp b/src/patches/versions/JPN39.cpp index 4c93bec..0d7e434 100644 --- a/src/patches/versions/JPN39.cpp +++ b/src/patches/versions/JPN39.cpp @@ -18,9 +18,11 @@ FUNCTION_PTR (i64, lua_settop, PROC_ADDRESS ("lua51.dll", "lua_settop"), u64, u6 FUNCTION_PTR (i64, lua_pushboolean, PROC_ADDRESS ("lua51.dll", "lua_pushboolean"), u64, u64); FUNCTION_PTR (i64, lua_pushstring, PROC_ADDRESS ("lua51.dll", "lua_pushstring"), u64, u64); FUNCTION_PTR (i64, lua_pushcclosure, PROC_ADDRESS ("lua51.dll", "lua_pushcclosure"), u64, u64, u64); +FUNCTION_PTR (i64, lua_pushnumber, PROC_ADDRESS ("lua51.dll", "lua_pushnumber"), u64, u64); FUNCTION_PTR (i64, lua_toboolean, PROC_ADDRESS ("lua51.dll", "lua_toboolean"), u64, u64); -FUNCTION_PTR (i64, lua_touserdata, PROC_ADDRESS ("lua51.dll", "lua_touserdata"), u64, u64); +FUNCTION_PTR (i64, lua_tostring, PROC_ADDRESS ("lua51.dll", "lua_tostring"), u64, u64); +FUNCTION_PTR (double, lua_tonumber, PROC_ADDRESS ("lua51.dll", "lua_tonumber"), u64, u64); i64 lua_pushtrue (i64 a1) { @@ -29,12 +31,6 @@ lua_pushtrue (i64 a1) { return 1; } -i64 __fastcall -lua_freeze_timer (i64 a1) { - // i64 v2 = lua_touserdata (a1, 4294957292); - return lua_pushtrue (a1); -} - HOOK (i64, AvailableMode_Collabo024, ASLR (0x1402DE710), i64 a1) { return lua_pushtrue (a1); } HOOK (i64, AvailableMode_Collabo025, ASLR (0x1402DE6B0), i64 a1) { return lua_pushtrue (a1); } HOOK (i64, AvailableMode_Collabo026, ASLR (0x1402DE670), i64 a1) { return lua_pushtrue (a1); } @@ -67,7 +63,15 @@ ReplaceLeaBufferAddress (const std::vector &bufferAddresses, void *ne } } +// -------------- MidHook Area -------------- + SafetyHookMid changeLanguageTypeHook{}; +SafetyHookMid freezeTimerHook{}; +SafetyHookMid genNus3bankIdHook{}; + +std::map nus3bankMap; +int nus3bankIdCounter = 0; +std::mutex nus3bankMtx; void ChangeLanguageType (SafetyHookContext &ctx) { @@ -75,7 +79,10 @@ ChangeLanguageType (SafetyHookContext &ctx) { if (*pFontType == 4) *pFontType = 2; } -SafetyHookMid freezeTimerHook{}; +i64 __fastcall +lua_freeze_timer (i64 a1) { + return lua_pushtrue (a1); +} void FreezeTimer (SafetyHookContext &ctx) { @@ -85,6 +92,37 @@ FreezeTimer (SafetyHookContext &ctx) { ctx.rip = ASLR (0x14019FF65); } +int +get_bank_id(std::string bankName) { + std::lock_guard lock(nus3bankMtx); + if (nus3bankMap.find(bankName) == nus3bankMap.end()) { + nus3bankMap[bankName] = nus3bankIdCounter; + nus3bankIdCounter++; + } + return nus3bankMap[bankName]; +} + +void +GenNus3bankId (SafetyHookContext &ctx) { + int originalBankId = ctx.rax; + if ((uint8_t**)(ctx.rcx + 8) != nullptr) { + uint8_t* pNus3bankFile = *((uint8_t **)(ctx.rcx + 8)); + if (pNus3bankFile[0] == 'N' && pNus3bankFile[1] == 'U' && pNus3bankFile[2] == 'S' && pNus3bankFile[3] == '3') { + int tocLength = *((int*)(pNus3bankFile + 16)); + uint8_t* pPropBlock = pNus3bankFile + 20 + tocLength; + int propLength = *((int*)(pPropBlock + 4)); + uint8_t* pBinfBlock = pPropBlock + 8 + propLength; + std::string bankName((char*)(pBinfBlock + 0x11)); + ctx.rax = get_bank_id(bankName); + std::cout << "GenNus3bankId bankName: " << bankName << " changeId: " << originalBankId << " --> " << ctx.rax << std::endl; + } + } else { + std::cout << "GenNus3bankId load unexpected Id: " << ctx.rax << std::endl; + } +} + +// -------------- MidHook Area End -------------- + int language = 0; const char * languageStr () { @@ -112,31 +150,72 @@ HOOK (i64, GetCabinetLanguage, ASLR (0x1401D1A60), i64, i64 a2) { return 1; } -// int loaded_fail_count = 0; -// HOOK (i64, LoadedBankAll, ASLR (0x1404C6990), i64 a1) { -// std::cout << "LoadBankAll start" << std::endl; -// originalLoadedBankAll (a1); -// auto result = lua_toboolean(a1, -1); -// std::cout << "LoadedBankAll returns: " << result << std::endl; -// std::cout << "LoadedBankAll returns: " << *((int32_t*)result) << std::endl; -// lua_settop(a1, 0); -// if (result) { -// lua_pushboolean (a1, 1); -// } else if (loaded_fail_count > 10) { -// lua_pushboolean (a1, 1); -// } else { -// loaded_fail_count += 1; -// lua_pushboolean (a1, 0); -// } -// return 1; +const char* +fixToneName (std::string bankName, std::string toneName) { + if ((language == 2 || language == 4) && bankName.starts_with("voice_")) { + return (toneName + "_cn").c_str(); + } else return toneName.c_str(); +} + +// HOOK (i64, PlaySound, ASLR (0x1404C6DC0), i64 a1) { +// char* bankName = (char*)lua_tostring (a1, 1); +// char* toneName = (char*)lua_tostring (a1, 2); +// double slotNo = lua_tonumber (a1, 3); +// std::cout << "bankName: " << bankName << std::endl; +// std::cout << "toneName: " << toneName << std::endl; +// std::cout << "slotNo: " << slotNo << std::endl; +// lua_settop (a1, 0); +// lua_pushstring (a1, (u64)bankName); +// lua_pushstring (a1, (u64)fixToneName (bankName, toneName)); +// lua_pushnumber (a1, slotNo); +// return originalPlaySound(a1); // } +// HOOK (i64, PlaySoundMulti, ASLR (0x1404C6DC0), i64 a1) { +// double playerNum = lua_tonumber (a1, 1); +// double playerNo = lua_tonumber (a1, 2); +// char* bankName = (char*)lua_tostring (a1, 3); +// char* toneName = (char*)lua_tostring (a1, 4); +// double slotNo = lua_tonumber (a1, 5); +// std::cout << "playerNum: " << playerNum << std::endl; +// std::cout << "playerNo: " << playerNo << std::endl; +// std::cout << "bankName: " << bankName << std::endl; +// std::cout << "toneName: " << toneName << std::endl; +// std::cout << "slotNo: " << slotNo << std::endl; +// lua_settop (a1, 0); +// lua_pushnumber (a1, playerNum); +// lua_pushnumber (a1, playerNo); +// lua_pushstring (a1, (u64)bankName); +// lua_pushstring (a1, (u64)fixToneName (bankName, toneName)); +// lua_pushnumber (a1, slotNo); +// return originalPlaySoundMulti(a1); +// } + +int loaded_fail_count = 0; +HOOK (i64, LoadedBankAll, ASLR (0x1404C69F0), i64 a1) { + originalLoadedBankAll (a1); + auto result = lua_toboolean(a1, -1); + lua_settop(a1, 0); + if (result) { + loaded_fail_count = 0; + lua_pushboolean (a1, 1); + } else if (loaded_fail_count > 10) { + loaded_fail_count = 0; + lua_pushboolean (a1, 1); + } else { + loaded_fail_count += 1; + lua_pushboolean (a1, 0); + } + return 1; +} + void Init () { std::cout << "Init JPN39" << std::endl; i32 xRes = 1920; i32 yRes = 1080; bool unlockSongs = true; + bool fixNus3bank = true; bool fixLanguage = false; bool freezeTimer = false; bool chsPatch = false; @@ -152,6 +231,7 @@ Init () { unlockSongs = readConfigBool (patches, "unlock_songs", unlockSongs); auto jpn39 = openConfigSection (patches, "jpn39"); if (jpn39) { + fixNus3bank = readConfigBool (jpn39, "fix_nus3bank", fixNus3bank); fixLanguage = readConfigBool (jpn39, "fix_language", fixLanguage); freezeTimer = readConfigBool (jpn39, "freeze_timer", freezeTimer); chsPatch = readConfigBool (jpn39, "chs_patch", chsPatch); @@ -227,7 +307,6 @@ Init () { // Freeze Timer if (freezeTimer) { freezeTimerHook = safetyhook::create_mid (ASLR (0x14019FF51), FreezeTimer); - } // patch to use chs font/wordlist instead of cht @@ -243,18 +322,25 @@ Init () { // Fix language if (fixLanguage) { - INSTALL_HOOK (GetLanguage); + INSTALL_HOOK (GetLanguage); // Language will use in other place INSTALL_HOOK (GetRegionLanguage); INSTALL_HOOK (GetCabinetLanguage); } + // if (fixLanguage && chsPatch) { + // INSTALL_HOOK (PlaySound); + // INSTALL_HOOK (PlaySoundMulti); + // } + // Mode unlock if (modeCollabo025) INSTALL_HOOK (AvailableMode_Collabo025); if (modeCollabo026) INSTALL_HOOK (AvailableMode_Collabo026); if (modeAprilFool001) INSTALL_HOOK (AvailableMode_AprilFool001); - // // Fix normal song play after passing through silent song - // INSTALL_HOOK(LoadedBankAll); + // Fix normal song play after passing through silent song + if (fixNus3bank) { + genNus3bankIdHook = safetyhook::create_mid (ASLR (0x1407B97BD), GenNus3bankId); + } // Disable live check auto amHandle = (u64)GetModuleHandle ("AMFrameWork.dll"); From 31964c8c55374a7987b5e2bedd0322faa7af74c7 Mon Sep 17 00:00:00 2001 From: RyuMiya Date: Tue, 22 Oct 2024 22:53:31 +0800 Subject: [PATCH 03/10] Add chs_patch sound for JPN39 --- src/helpers.h | 27 ++++ src/patches/versions/JPN39.cpp | 235 +++++++++++++++++++++++---------- 2 files changed, 191 insertions(+), 71 deletions(-) diff --git a/src/helpers.h b/src/helpers.h index 4005996..95b8340 100644 --- a/src/helpers.h +++ b/src/helpers.h @@ -11,6 +11,7 @@ #include #include #include +#include typedef int8_t i8; typedef int16_t i16; @@ -53,6 +54,16 @@ const HMODULE MODULE_HANDLE = GetModuleHandle (nullptr); void *where##className##functionName = NULL; \ returnType implOf##className##functionName (className *This, __VA_ARGS__) +#define HOOK_MID(functionName, location, ...) \ + SafetyHookMid midHook##functionName{}; \ + u64 where##functionName = (location); \ + void implOf##functionName (SafetyHookContext &ctx) + +#define HOOK_MID_DYNAMIC(functionName, location, ...) \ + SafetyHookMid midHook##functionName{}; \ + u64 where##functionName = (location); \ + void implOf##functionName (SafetyHookContext &ctx) + #define INSTALL_HOOK(functionName) \ { \ MH_Initialize (); \ @@ -79,6 +90,21 @@ const HMODULE MODULE_HANDLE = GetModuleHandle (nullptr); INSTALL_HOOK (className##functionName); \ } +#define INSTALL_HOOK_MID(functionName) \ + { \ + midHook##functionName = safetyhook::create_mid(where##functionName, implOf##functionName); \ + } + +#define INSTALL_HOOK_MID_DYNAMIC(functionName, address) \ + { \ + midHook##functionName = safetyhook::create_mid(address, implOf##functionName); \ + } + +#define UNINSTALL_HOOK_MID(functionName) \ + { \ + midHook##functionName = {}; \ + } + #define READ_MEMORY(location, type) *(type *)location #define WRITE_MEMORY(location, type, ...) \ @@ -124,6 +150,7 @@ const HMODULE MODULE_HANDLE = GetModuleHandle (nullptr); #define printInfo(format, ...) printColour (INFO_COLOUR, format, __VA_ARGS__) #define printWarning(format, ...) printColour (WARNING_COLOUR, format, __VA_ARGS__) #define printError(format, ...) printColour (ERROR_COLOUR, format, __VA_ARGS__) +#define round(num) ((num > 0) ? (int)(num + 0.5) : (int)(num - 0.5)) toml_table_t *openConfig (std::filesystem::path path); toml_table_t *openConfigSection (toml_table_t *config, const std::string §ionName); diff --git a/src/patches/versions/JPN39.cpp b/src/patches/versions/JPN39.cpp index 0d7e434..f6be134 100644 --- a/src/patches/versions/JPN39.cpp +++ b/src/patches/versions/JPN39.cpp @@ -15,13 +15,15 @@ HOOK_DYNAMIC (i64, __fastcall, curl_easy_setopt, i64 a1, i64 a2, i64 a3, i64 a4, } FUNCTION_PTR (i64, lua_settop, PROC_ADDRESS ("lua51.dll", "lua_settop"), u64, u64); +FUNCTION_PTR (i64, lua_gettop, PROC_ADDRESS ("lua51.dll", "lua_gettop"), u64); +FUNCTION_PTR (i64, lua_replace, PROC_ADDRESS ("lua51.dll", "lua_replace"), u64, u64); FUNCTION_PTR (i64, lua_pushboolean, PROC_ADDRESS ("lua51.dll", "lua_pushboolean"), u64, u64); FUNCTION_PTR (i64, lua_pushstring, PROC_ADDRESS ("lua51.dll", "lua_pushstring"), u64, u64); FUNCTION_PTR (i64, lua_pushcclosure, PROC_ADDRESS ("lua51.dll", "lua_pushcclosure"), u64, u64, u64); FUNCTION_PTR (i64, lua_pushnumber, PROC_ADDRESS ("lua51.dll", "lua_pushnumber"), u64, u64); FUNCTION_PTR (i64, lua_toboolean, PROC_ADDRESS ("lua51.dll", "lua_toboolean"), u64, u64); -FUNCTION_PTR (i64, lua_tostring, PROC_ADDRESS ("lua51.dll", "lua_tostring"), u64, u64); +FUNCTION_PTR (i64, lua_tolstring, PROC_ADDRESS ("lua51.dll", "lua_tolstring"), u64, u64, u64); FUNCTION_PTR (double, lua_tonumber, PROC_ADDRESS ("lua51.dll", "lua_tonumber"), u64, u64); i64 @@ -65,16 +67,7 @@ ReplaceLeaBufferAddress (const std::vector &bufferAddresses, void *ne // -------------- MidHook Area -------------- -SafetyHookMid changeLanguageTypeHook{}; -SafetyHookMid freezeTimerHook{}; -SafetyHookMid genNus3bankIdHook{}; - -std::map nus3bankMap; -int nus3bankIdCounter = 0; -std::mutex nus3bankMtx; - -void -ChangeLanguageType (SafetyHookContext &ctx) { +HOOK_MID (ChangeLanguageType, ASLR (0x1400B2016), SafetyHookContext &ctx) { int *pFontType = (int *)ctx.rax; if (*pFontType == 4) *pFontType = 2; } @@ -84,17 +77,21 @@ lua_freeze_timer (i64 a1) { return lua_pushtrue (a1); } -void -FreezeTimer (SafetyHookContext &ctx) { +HOOK_MID (FreezeTimer, ASLR (0x14019FF51), SafetyHookContext &ctx) { auto a1 = ctx.rdi; int v9 = (int)(ctx.rax + 1); lua_pushcclosure(a1, reinterpret_cast(&lua_freeze_timer), v9); ctx.rip = ASLR (0x14019FF65); } +std::map nus3bankMap; +int nus3bankIdCounter = 0; +std::map voiceCnExist; +bool enableSwitchVoice = false; +std::mutex nus3bankMtx; + int get_bank_id(std::string bankName) { - std::lock_guard lock(nus3bankMtx); if (nus3bankMap.find(bankName) == nus3bankMap.end()) { nus3bankMap[bankName] = nus3bankIdCounter; nus3bankIdCounter++; @@ -103,8 +100,49 @@ get_bank_id(std::string bankName) { } void -GenNus3bankId (SafetyHookContext &ctx) { - int originalBankId = ctx.rax; +check_voice_tail(std::string bankName, uint8_t* pBinfBlock, std::map &voiceExist, std::string tail) { + // check if any voice_xxx.nus3bank has xxx_cn audio inside while loading + if (enableSwitchVoice && bankName.starts_with("voice_")) { + int binfLength = *((int*)(pBinfBlock + 4)); + uint8_t* pGrpBlock = pBinfBlock + 8 + binfLength; + int grpLength = *((int*)(pGrpBlock + 4)); + uint8_t* pDtonBlock = pGrpBlock + 8 + grpLength; + int dtonLength = *((int*)(pDtonBlock + 4)); + uint8_t* pToneBlock = pDtonBlock + 8 + dtonLength; + int toneSize = *((int*)(pToneBlock + 8)); + uint8_t* pToneBase = pToneBlock + 12; + for (int i = 0; i < toneSize; i++) { + if (*((int*)(pToneBase + i * 8 + 4)) <= 0x0C) continue; // skip empty space + uint8_t* currToneBase = pToneBase + *((int*)(pToneBase + i * 8)); + int titleOffset = -1; + switch (*currToneBase) { + case 0xFF: titleOffset = 9; break; // audio mark + case 0x7F: titleOffset = 5; break; // randomizer mark + default: continue; // unknown mark skip + } + if (titleOffset > 0) { + std::string title((char*)(currToneBase + titleOffset)); + if (title.ends_with(tail)) { + if (voiceExist.find(bankName) == voiceExist.end() || !voiceExist[bankName]) { + std::cout << "[MultiLang Patch] found " << tail << " voices from " << bankName << ".nus3bank!" << std::endl; + voiceExist[bankName] = true; + } + return; + } + } + } + if (voiceExist.find(bankName) == voiceExist.end()) { + voiceExist[bankName] = false; + } else if (voiceExist[bankName]) { + std::cout << "[MultiLang Patch] " << tail << " voices was removed, maybe you changed " << bankName << ".nus3bank file?" << std::endl; + voiceExist[bankName] = false; + } + } +} + +HOOK_MID (GenNus3bankId, ASLR (0x1407B97BD), SafetyHookContext &ctx) { + std::lock_guard lock(nus3bankMtx); + // int originalBankId = ctx.rax; if ((uint8_t**)(ctx.rcx + 8) != nullptr) { uint8_t* pNus3bankFile = *((uint8_t **)(ctx.rcx + 8)); if (pNus3bankFile[0] == 'N' && pNus3bankFile[1] == 'U' && pNus3bankFile[2] == 'S' && pNus3bankFile[3] == '3') { @@ -113,14 +151,16 @@ GenNus3bankId (SafetyHookContext &ctx) { int propLength = *((int*)(pPropBlock + 4)); uint8_t* pBinfBlock = pPropBlock + 8 + propLength; std::string bankName((char*)(pBinfBlock + 0x11)); + check_voice_tail(bankName, pBinfBlock, voiceCnExist, "_cn"); ctx.rax = get_bank_id(bankName); - std::cout << "GenNus3bankId bankName: " << bankName << " changeId: " << originalBankId << " --> " << ctx.rax << std::endl; + // std::cout << "FixNus3bankId bankName: " << bankName << " fixId: " << originalBankId << " --> " << ctx.rax << std::endl; } } else { - std::cout << "GenNus3bankId load unexpected Id: " << ctx.rax << std::endl; + // std::cout << "FixNus3bankId load unexpected Id: " << ctx.rax << std::endl; } } + // -------------- MidHook Area End -------------- int language = 0; @@ -150,46 +190,82 @@ HOOK (i64, GetCabinetLanguage, ASLR (0x1401D1A60), i64, i64 a2) { return 1; } -const char* +std::string fixToneName (std::string bankName, std::string toneName) { - if ((language == 2 || language == 4) && bankName.starts_with("voice_")) { - return (toneName + "_cn").c_str(); - } else return toneName.c_str(); + if (enableSwitchVoice && bankName.starts_with("voice_")) { + if (language == 2 || language == 4) { + bool existCnVoice = voiceCnExist.find(bankName) != voiceCnExist.end() && voiceCnExist[bankName]; + if (existCnVoice) { + return toneName + "_cn"; + } + } // if there is more language of voice, we could add them here + } + return toneName; } -// HOOK (i64, PlaySound, ASLR (0x1404C6DC0), i64 a1) { -// char* bankName = (char*)lua_tostring (a1, 1); -// char* toneName = (char*)lua_tostring (a1, 2); -// double slotNo = lua_tonumber (a1, 3); -// std::cout << "bankName: " << bankName << std::endl; -// std::cout << "toneName: " << toneName << std::endl; -// std::cout << "slotNo: " << slotNo << std::endl; -// lua_settop (a1, 0); -// lua_pushstring (a1, (u64)bankName); -// lua_pushstring (a1, (u64)fixToneName (bankName, toneName)); -// lua_pushnumber (a1, slotNo); -// return originalPlaySound(a1); -// } +HOOK (i64, PlaySound, ASLR (0x1404C6DC0), i64 a1) { + if (enableSwitchVoice) { + // int n_param = lua_gettop(a1); + // std::cout << "PlaySound param num: " << n_param << std::endl; + int size_bankName = 0; + const char* bankName = (char*)lua_tolstring (a1, -3, (u64)&size_bankName); + // std::cout << "PlaySound bankName: " << bankName << std::endl; + int size_toneName = 0; + const char* toneName = (char*)lua_tolstring (a1, -2, (u64)&size_toneName); + // std::cout << "PlaySound toneName: " << toneName << std::endl; + // int slotNoDouble = lua_tonumber (a1, -1); + // int slotNo = round(slotNoDouble); + // std::cout << "PlaySound slotNo: " << slotNo << std::endl; + lua_pushstring (a1, (u64)(fixToneName (bankName, toneName).c_str())); + lua_replace(a1, -3); + } + return originalPlaySound(a1); +} -// HOOK (i64, PlaySoundMulti, ASLR (0x1404C6DC0), i64 a1) { -// double playerNum = lua_tonumber (a1, 1); -// double playerNo = lua_tonumber (a1, 2); -// char* bankName = (char*)lua_tostring (a1, 3); -// char* toneName = (char*)lua_tostring (a1, 4); -// double slotNo = lua_tonumber (a1, 5); -// std::cout << "playerNum: " << playerNum << std::endl; -// std::cout << "playerNo: " << playerNo << std::endl; -// std::cout << "bankName: " << bankName << std::endl; -// std::cout << "toneName: " << toneName << std::endl; -// std::cout << "slotNo: " << slotNo << std::endl; -// lua_settop (a1, 0); -// lua_pushnumber (a1, playerNum); -// lua_pushnumber (a1, playerNo); -// lua_pushstring (a1, (u64)bankName); -// lua_pushstring (a1, (u64)fixToneName (bankName, toneName)); -// lua_pushnumber (a1, slotNo); -// return originalPlaySoundMulti(a1); -// } +HOOK (i64, PlaySoundMulti, ASLR (0x1404C6DC0), i64 a1) { + if (enableSwitchVoice) { + // double playerNumDouble = lua_tonumber (a1, -5); + // int playerNum = round(playerNumDouble); + // std::cout << "PlaySound playerNum: " << playerNum << std::endl; + // double playerNoDouble = lua_tonumber (a1, -4); + // int playerNo = round(playerNoDouble); + // std::cout << "PlaySound playerNo: " << playerNo << std::endl; + int size_bankName = 0; + const char* bankName = (char*)lua_tolstring (a1, -3, (u64)&size_bankName); + // std::cout << "PlaySound bankName: " << bankName << std::endl; + int size_toneName = 0; + const char* toneName = (char*)lua_tolstring (a1, -2, (u64)&size_toneName); + // std::cout << "PlaySound toneName: " << toneName << std::endl; + // double slotNoDouble = lua_tonumber (a1, -1); + // int slotNo = round(slotNoDouble); + // std::cout << "PlaySound slotNo: " << slotNo << std::endl; + lua_pushstring (a1, (u64)(fixToneName (bankName, toneName).c_str())); + lua_replace (a1, -3); + } + return originalPlaySoundMulti(a1); +} + +FUNCTION_PTR (u64*, __fastcall base_string_append, ASLR (0x140027DA0), u64*, void*, size_t); +HOOK_MID (PlaySoundInGame, ASLR (0x1404ED5F9), SafetyHookContext &ctx) { + char* originalPlaySound = *((char**)ctx.rax); + std::string playSound(originalPlaySound); + if (enableSwitchVoice && playSound.starts_with("voice_")) { + size_t slashIndex = playSound.find("/"); + if (slashIndex != std::string::npos) { + std::string bankName = playSound.substr(0, slashIndex); + std::string toneName = playSound.substr(slashIndex + 1, playSound.size()); + std::string finalDesc = bankName + "/" + fixToneName(bankName, toneName.c_str()); + if (playSound != finalDesc) { + std::cout << "PlaySoundInGame fix: " << playSound << " --> " << finalDesc << std::endl; + ctx.rax = (uintptr_t)((void*)&finalDesc); + + // std::string tail("_cn"); + // base_string_append((u64*)ctx.rax, *((void**)&tail), tail.size()); + // std::cout << "PlaySoundInGame after: " << *((char**)ctx.rax); + } + } + } +} int loaded_fail_count = 0; HOOK (i64, LoadedBankAll, ASLR (0x1404C69F0), i64 a1) { @@ -199,7 +275,7 @@ HOOK (i64, LoadedBankAll, ASLR (0x1404C69F0), i64 a1) { if (result) { loaded_fail_count = 0; lua_pushboolean (a1, 1); - } else if (loaded_fail_count > 10) { + } else if (loaded_fail_count > 100) { loaded_fail_count = 0; lua_pushboolean (a1, 1); } else { @@ -215,7 +291,6 @@ Init () { i32 xRes = 1920; i32 yRes = 1080; bool unlockSongs = true; - bool fixNus3bank = true; bool fixLanguage = false; bool freezeTimer = false; bool chsPatch = false; @@ -223,6 +298,8 @@ Init () { bool modeCollabo026 = false; bool modeAprilFool001 = false; + bool useLayeredfs = false; + auto configPath = std::filesystem::current_path () / "config.toml"; std::unique_ptr config_ptr (openConfig (configPath), toml_free); if (config_ptr) { @@ -231,7 +308,6 @@ Init () { unlockSongs = readConfigBool (patches, "unlock_songs", unlockSongs); auto jpn39 = openConfigSection (patches, "jpn39"); if (jpn39) { - fixNus3bank = readConfigBool (jpn39, "fix_nus3bank", fixNus3bank); fixLanguage = readConfigBool (jpn39, "fix_language", fixLanguage); freezeTimer = readConfigBool (jpn39, "freeze_timer", freezeTimer); chsPatch = readConfigBool (jpn39, "chs_patch", chsPatch); @@ -249,6 +325,11 @@ Init () { yRes = readConfigInt (res, "y", yRes); } } + + auto layeredfs = openConfigSection (config_ptr.get (), "layeredfs"); + if (layeredfs) { + useLayeredfs = readConfigBool (layeredfs, "enabled", useLayeredfs); + } } // Apply common config patch @@ -306,18 +387,27 @@ Init () { // Freeze Timer if (freezeTimer) { - freezeTimerHook = safetyhook::create_mid (ASLR (0x14019FF51), FreezeTimer); + INSTALL_HOOK_MID (FreezeTimer); } // patch to use chs font/wordlist instead of cht if (chsPatch) { - WRITE_MEMORY (ASLR (0x140CD1AE0), char, "cn_64"); - WRITE_MEMORY (ASLR (0x140CD1AF0), char, "cn_32"); - WRITE_MEMORY (ASLR (0x140CD1AF8), char, "cn_30"); - WRITE_MEMORY (ASLR (0x140C946A0), char, "chineseSText"); - WRITE_MEMORY (ASLR (0x140C946B0), char, "chineseSFontType"); + bool fontExistAll = true; + const char* fontToCheck[] {"cn_30.nutexb", "cn_30.xml", "cn_32.nutexb", "cn_32.xml", "cn_64.nutexb", "cn_64.xml"}; + for (int i = 0; i < 6; i++) { + if (useLayeredfs && std::filesystem::exists(std::string("..\\..\\Data_mods\\x64\\font\\") + fontToCheck[i])) continue; + if (std::filesystem::exists(std::string("..\\..\\Data\\x64\\font\\") + fontToCheck[i])) continue; + fontExistAll = false; + } - changeLanguageTypeHook = safetyhook::create_mid (ASLR (0x1400B2016), ChangeLanguageType); + if (fontExistAll) { + WRITE_MEMORY (ASLR (0x140CD1AE0), char, "cn_64"); + WRITE_MEMORY (ASLR (0x140CD1AF0), char, "cn_32"); + WRITE_MEMORY (ASLR (0x140CD1AF8), char, "cn_30"); + WRITE_MEMORY (ASLR (0x140C946A0), char, "chineseSText"); + WRITE_MEMORY (ASLR (0x140C946B0), char, "chineseSFontType"); + INSTALL_HOOK_MID (ChangeLanguageType); + } } // Fix language @@ -327,10 +417,14 @@ Init () { INSTALL_HOOK (GetCabinetLanguage); } - // if (fixLanguage && chsPatch) { - // INSTALL_HOOK (PlaySound); - // INSTALL_HOOK (PlaySoundMulti); - // } + // if both chsPatch & fixLanguage enabled, try use cn voice from nus3bank + // don't worry, we will check if cn voice existed + if (chsPatch && fixLanguage) { + enableSwitchVoice = true; + INSTALL_HOOK (PlaySound); + INSTALL_HOOK (PlaySoundMulti); + INSTALL_HOOK_MID (PlaySoundInGame); + } // Mode unlock if (modeCollabo025) INSTALL_HOOK (AvailableMode_Collabo025); @@ -338,9 +432,8 @@ Init () { if (modeAprilFool001) INSTALL_HOOK (AvailableMode_AprilFool001); // Fix normal song play after passing through silent song - if (fixNus3bank) { - genNus3bankIdHook = safetyhook::create_mid (ASLR (0x1407B97BD), GenNus3bankId); - } + INSTALL_HOOK_MID (GenNus3bankId); + INSTALL_HOOK (LoadedBankAll); // Disable live check auto amHandle = (u64)GetModuleHandle ("AMFrameWork.dll"); From 72aae3848d8afb8d7df8207c39502809a3bf3df0 Mon Sep 17 00:00:00 2001 From: RyuMiya Date: Fri, 25 Oct 2024 02:18:05 +0800 Subject: [PATCH 04/10] Add chs_patch sound for JPN39 & Clean up Code --- src/patches/versions/JPN39.cpp | 44 ++++------------------------------ 1 file changed, 5 insertions(+), 39 deletions(-) diff --git a/src/patches/versions/JPN39.cpp b/src/patches/versions/JPN39.cpp index f6be134..2229cb3 100644 --- a/src/patches/versions/JPN39.cpp +++ b/src/patches/versions/JPN39.cpp @@ -15,16 +15,13 @@ HOOK_DYNAMIC (i64, __fastcall, curl_easy_setopt, i64 a1, i64 a2, i64 a3, i64 a4, } FUNCTION_PTR (i64, lua_settop, PROC_ADDRESS ("lua51.dll", "lua_settop"), u64, u64); -FUNCTION_PTR (i64, lua_gettop, PROC_ADDRESS ("lua51.dll", "lua_gettop"), u64); FUNCTION_PTR (i64, lua_replace, PROC_ADDRESS ("lua51.dll", "lua_replace"), u64, u64); FUNCTION_PTR (i64, lua_pushboolean, PROC_ADDRESS ("lua51.dll", "lua_pushboolean"), u64, u64); FUNCTION_PTR (i64, lua_pushstring, PROC_ADDRESS ("lua51.dll", "lua_pushstring"), u64, u64); FUNCTION_PTR (i64, lua_pushcclosure, PROC_ADDRESS ("lua51.dll", "lua_pushcclosure"), u64, u64, u64); -FUNCTION_PTR (i64, lua_pushnumber, PROC_ADDRESS ("lua51.dll", "lua_pushnumber"), u64, u64); FUNCTION_PTR (i64, lua_toboolean, PROC_ADDRESS ("lua51.dll", "lua_toboolean"), u64, u64); FUNCTION_PTR (i64, lua_tolstring, PROC_ADDRESS ("lua51.dll", "lua_tolstring"), u64, u64, u64); -FUNCTION_PTR (double, lua_tonumber, PROC_ADDRESS ("lua51.dll", "lua_tonumber"), u64, u64); i64 lua_pushtrue (i64 a1) { @@ -124,17 +121,13 @@ check_voice_tail(std::string bankName, uint8_t* pBinfBlock, std::map lock(nus3bankMtx); - // int originalBankId = ctx.rax; if ((uint8_t**)(ctx.rcx + 8) != nullptr) { uint8_t* pNus3bankFile = *((uint8_t **)(ctx.rcx + 8)); if (pNus3bankFile[0] == 'N' && pNus3bankFile[1] == 'U' && pNus3bankFile[2] == 'S' && pNus3bankFile[3] == '3') { @@ -153,10 +145,7 @@ HOOK_MID (GenNus3bankId, ASLR (0x1407B97BD), SafetyHookContext &ctx) { std::string bankName((char*)(pBinfBlock + 0x11)); check_voice_tail(bankName, pBinfBlock, voiceCnExist, "_cn"); ctx.rax = get_bank_id(bankName); - // std::cout << "FixNus3bankId bankName: " << bankName << " fixId: " << originalBankId << " --> " << ctx.rax << std::endl; } - } else { - // std::cout << "FixNus3bankId load unexpected Id: " << ctx.rax << std::endl; } } @@ -198,24 +187,17 @@ fixToneName (std::string bankName, std::string toneName) { if (existCnVoice) { return toneName + "_cn"; } - } // if there is more language of voice, we could add them here + } } return toneName; } HOOK (i64, PlaySound, ASLR (0x1404C6DC0), i64 a1) { - if (enableSwitchVoice) { - // int n_param = lua_gettop(a1); - // std::cout << "PlaySound param num: " << n_param << std::endl; + if (enableSwitchVoice && language != 0) { int size_bankName = 0; const char* bankName = (char*)lua_tolstring (a1, -3, (u64)&size_bankName); - // std::cout << "PlaySound bankName: " << bankName << std::endl; int size_toneName = 0; const char* toneName = (char*)lua_tolstring (a1, -2, (u64)&size_toneName); - // std::cout << "PlaySound toneName: " << toneName << std::endl; - // int slotNoDouble = lua_tonumber (a1, -1); - // int slotNo = round(slotNoDouble); - // std::cout << "PlaySound slotNo: " << slotNo << std::endl; lua_pushstring (a1, (u64)(fixToneName (bankName, toneName).c_str())); lua_replace(a1, -3); } @@ -223,22 +205,11 @@ HOOK (i64, PlaySound, ASLR (0x1404C6DC0), i64 a1) { } HOOK (i64, PlaySoundMulti, ASLR (0x1404C6DC0), i64 a1) { - if (enableSwitchVoice) { - // double playerNumDouble = lua_tonumber (a1, -5); - // int playerNum = round(playerNumDouble); - // std::cout << "PlaySound playerNum: " << playerNum << std::endl; - // double playerNoDouble = lua_tonumber (a1, -4); - // int playerNo = round(playerNoDouble); - // std::cout << "PlaySound playerNo: " << playerNo << std::endl; + if (enableSwitchVoice && language != 0) { int size_bankName = 0; const char* bankName = (char*)lua_tolstring (a1, -3, (u64)&size_bankName); - // std::cout << "PlaySound bankName: " << bankName << std::endl; int size_toneName = 0; const char* toneName = (char*)lua_tolstring (a1, -2, (u64)&size_toneName); - // std::cout << "PlaySound toneName: " << toneName << std::endl; - // double slotNoDouble = lua_tonumber (a1, -1); - // int slotNo = round(slotNoDouble); - // std::cout << "PlaySound slotNo: " << slotNo << std::endl; lua_pushstring (a1, (u64)(fixToneName (bankName, toneName).c_str())); lua_replace (a1, -3); } @@ -249,19 +220,14 @@ FUNCTION_PTR (u64*, __fastcall base_string_append, ASLR (0x140027DA0), u64*, voi HOOK_MID (PlaySoundInGame, ASLR (0x1404ED5F9), SafetyHookContext &ctx) { char* originalPlaySound = *((char**)ctx.rax); std::string playSound(originalPlaySound); - if (enableSwitchVoice && playSound.starts_with("voice_")) { + if (enableSwitchVoice && language != 0 && playSound.starts_with("voice_")) { size_t slashIndex = playSound.find("/"); if (slashIndex != std::string::npos) { std::string bankName = playSound.substr(0, slashIndex); std::string toneName = playSound.substr(slashIndex + 1, playSound.size()); std::string finalDesc = bankName + "/" + fixToneName(bankName, toneName.c_str()); if (playSound != finalDesc) { - std::cout << "PlaySoundInGame fix: " << playSound << " --> " << finalDesc << std::endl; ctx.rax = (uintptr_t)((void*)&finalDesc); - - // std::string tail("_cn"); - // base_string_append((u64*)ctx.rax, *((void**)&tail), tail.size()); - // std::cout << "PlaySoundInGame after: " << *((char**)ctx.rax); } } } From 64e328c35988f16d9462dc902d8d4bcc9b64c4b3 Mon Sep 17 00:00:00 2001 From: RyuMiya Date: Fri, 25 Oct 2024 23:37:59 +0800 Subject: [PATCH 05/10] optimize PlaySoundInGame --- src/patches/versions/JPN39.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/patches/versions/JPN39.cpp b/src/patches/versions/JPN39.cpp index f303139..7686947 100644 --- a/src/patches/versions/JPN39.cpp +++ b/src/patches/versions/JPN39.cpp @@ -220,14 +220,15 @@ FUNCTION_PTR (u64*, __fastcall base_string_append, ASLR (0x140027DA0), u64*, voi HOOK_MID (PlaySoundInGame, ASLR (0x1404ED5F9), SafetyHookContext &ctx) { char* originalPlaySound = *((char**)ctx.rax); std::string playSound(originalPlaySound); - if (enableSwitchVoice && language != 0 && playSound.starts_with("voice_")) { + if (enableSwitchVoice && language != 0 && playSound[0] == 'v') { size_t slashIndex = playSound.find("/"); if (slashIndex != std::string::npos) { std::string bankName = playSound.substr(0, slashIndex); - std::string toneName = playSound.substr(slashIndex + 1, playSound.size()); - std::string finalDesc = bankName + "/" + fixToneName(bankName, toneName.c_str()); - if (playSound != finalDesc) { - ctx.rax = (uintptr_t)((void*)&finalDesc); + if (language == 2 || language == 4) { + if (voiceCnExist.find(bankName) != voiceCnExist.end() && voiceCnExist[bankName]) { + std::string finalPlaySound = playSound + "_cn"; + ctx.rax = (uintptr_t)((void*)&finalPlaySound); + } } } } From 2f1d9ec1416609bfd855d3002fe57da4402d516c Mon Sep 17 00:00:00 2001 From: RyuMiya Date: Sun, 27 Oct 2024 23:02:35 +0800 Subject: [PATCH 06/10] Add PlaySoundInAiEnso hook for JPN39 --- src/patches/versions/JPN39.cpp | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/patches/versions/JPN39.cpp b/src/patches/versions/JPN39.cpp index 7686947..efcc01a 100644 --- a/src/patches/versions/JPN39.cpp +++ b/src/patches/versions/JPN39.cpp @@ -216,8 +216,24 @@ HOOK (i64, PlaySoundMulti, ASLR (0x1404C6DC0), i64 a1) { return originalPlaySoundMulti(a1); } -FUNCTION_PTR (u64*, __fastcall base_string_append, ASLR (0x140027DA0), u64*, void*, size_t); -HOOK_MID (PlaySoundInGame, ASLR (0x1404ED5F9), SafetyHookContext &ctx) { +HOOK_MID (PlaySoundInEnso, ASLR (0x1404ED5F9), SafetyHookContext &ctx) { + char* originalPlaySound = *((char**)ctx.rax); + std::string playSound(originalPlaySound); + if (enableSwitchVoice && language != 0 && playSound[0] == 'v') { + size_t slashIndex = playSound.find("/"); + if (slashIndex != std::string::npos) { + std::string bankName = playSound.substr(0, slashIndex); + if (language == 2 || language == 4) { + if (voiceCnExist.find(bankName) != voiceCnExist.end() && voiceCnExist[bankName]) { + std::string finalPlaySound = playSound + "_cn"; + ctx.rax = (uintptr_t)((void*)&finalPlaySound); + } + } + } + } +} + +HOOK_MID (PlaySoundInAiEnso, ASLR (0x1404ED296), SafetyHookContext &ctx) { char* originalPlaySound = *((char**)ctx.rax); std::string playSound(originalPlaySound); if (enableSwitchVoice && language != 0 && playSound[0] == 'v') { @@ -254,7 +270,6 @@ HOOK (i64, LoadedBankAll, ASLR (0x1404C69F0), i64 a1) { void Init () { - std::cout << "Init JPN39" << std::endl; i32 xRes = 1920; i32 yRes = 1080; bool unlockSongs = true; @@ -390,7 +405,8 @@ Init () { enableSwitchVoice = true; INSTALL_HOOK (PlaySound); INSTALL_HOOK (PlaySoundMulti); - INSTALL_HOOK_MID (PlaySoundInGame); + INSTALL_HOOK_MID (PlaySoundInEnso); + INSTALL_HOOK_MID (PlaySoundInAiEnso); } // Mode unlock @@ -419,7 +435,5 @@ Init () { // Redirect garmc requests auto garmcHandle = (u64)GetModuleHandle ("garmc.dll"); INSTALL_HOOK_DYNAMIC (curl_easy_setopt, (void *)(garmcHandle + 0x1FBBB0)); - - std::cout << "Finished Init JPN39" << std::endl; } } // namespace patches::JPN39 From 2633b2497882f0f3dff70b85773f30da3f624743 Mon Sep 17 00:00:00 2001 From: RyuMiya Date: Mon, 28 Oct 2024 00:03:24 +0800 Subject: [PATCH 07/10] fix PlaySoundEnso & PlaySoundSpecial for JPN39 --- src/patches/versions/JPN39.cpp | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/src/patches/versions/JPN39.cpp b/src/patches/versions/JPN39.cpp index efcc01a..0aabc5c 100644 --- a/src/patches/versions/JPN39.cpp +++ b/src/patches/versions/JPN39.cpp @@ -84,6 +84,7 @@ HOOK_MID (FreezeTimer, ASLR (0x14019FF51), SafetyHookContext &ctx) { std::map nus3bankMap; int nus3bankIdCounter = 0; std::map voiceCnExist; +// std::map voiceCnInGameCache; bool enableSwitchVoice = false; std::mutex nus3bankMtx; @@ -146,7 +147,7 @@ HOOK_MID (GenNus3bankId, ASLR (0x1407B97BD), SafetyHookContext &ctx) { check_voice_tail(bankName, pBinfBlock, voiceCnExist, "_cn"); ctx.rax = get_bank_id(bankName); } - } + } } @@ -216,35 +217,33 @@ HOOK (i64, PlaySoundMulti, ASLR (0x1404C6DC0), i64 a1) { return originalPlaySoundMulti(a1); } -HOOK_MID (PlaySoundInEnso, ASLR (0x1404ED5F9), SafetyHookContext &ctx) { +HOOK_MID (PlaySoundEnso, ASLR (0x1404ED5F9), SafetyHookContext &ctx) { char* originalPlaySound = *((char**)ctx.rax); std::string playSound(originalPlaySound); - if (enableSwitchVoice && language != 0 && playSound[0] == 'v') { + if (enableSwitchVoice && playSound[0] == 'v') { size_t slashIndex = playSound.find("/"); if (slashIndex != std::string::npos) { std::string bankName = playSound.substr(0, slashIndex); - if (language == 2 || language == 4) { - if (voiceCnExist.find(bankName) != voiceCnExist.end() && voiceCnExist[bankName]) { - std::string finalPlaySound = playSound + "_cn"; - ctx.rax = (uintptr_t)((void*)&finalPlaySound); - } + if (voiceCnExist.find(bankName) != voiceCnExist.end() && voiceCnExist[bankName]) { + std::string *finalPlaySound = new std::string(playSound + "_cn"); + std::cout << "PlaySoundEnso fixed: " << *finalPlaySound << std::endl; + ctx.rax = (uintptr_t)finalPlaySound; } } } } -HOOK_MID (PlaySoundInAiEnso, ASLR (0x1404ED296), SafetyHookContext &ctx) { +HOOK_MID (PlaySoundSpecial, ASLR (0x1404ED296), SafetyHookContext &ctx) { char* originalPlaySound = *((char**)ctx.rax); std::string playSound(originalPlaySound); - if (enableSwitchVoice && language != 0 && playSound[0] == 'v') { + if (enableSwitchVoice && playSound[0] == 'v') { size_t slashIndex = playSound.find("/"); if (slashIndex != std::string::npos) { std::string bankName = playSound.substr(0, slashIndex); - if (language == 2 || language == 4) { - if (voiceCnExist.find(bankName) != voiceCnExist.end() && voiceCnExist[bankName]) { - std::string finalPlaySound = playSound + "_cn"; - ctx.rax = (uintptr_t)((void*)&finalPlaySound); - } + if (voiceCnExist.find(bankName) != voiceCnExist.end() && voiceCnExist[bankName]) { + std::string *finalPlaySound = new std::string(playSound + "_cn"); + std::cout << "PlaySoundSpecial fixed: " << *finalPlaySound << std::endl; + ctx.rax = (uintptr_t)finalPlaySound; } } } @@ -405,8 +404,8 @@ Init () { enableSwitchVoice = true; INSTALL_HOOK (PlaySound); INSTALL_HOOK (PlaySoundMulti); - INSTALL_HOOK_MID (PlaySoundInEnso); - INSTALL_HOOK_MID (PlaySoundInAiEnso); + INSTALL_HOOK_MID (PlaySoundEnso); + INSTALL_HOOK_MID (PlaySoundSpecial); } // Mode unlock From e91ca95d2f69b4e3843c7affb7bfa844fb4080d4 Mon Sep 17 00:00:00 2001 From: RyuMiya Date: Wed, 30 Oct 2024 02:42:06 +0800 Subject: [PATCH 08/10] Fix PlaySoundMulti --- src/patches/versions/JPN39.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/patches/versions/JPN39.cpp b/src/patches/versions/JPN39.cpp index 0aabc5c..baac629 100644 --- a/src/patches/versions/JPN39.cpp +++ b/src/patches/versions/JPN39.cpp @@ -205,7 +205,7 @@ HOOK (i64, PlaySound, ASLR (0x1404C6DC0), i64 a1) { return originalPlaySound(a1); } -HOOK (i64, PlaySoundMulti, ASLR (0x1404C6DC0), i64 a1) { +HOOK (i64, PlaySoundMulti, ASLR (0x1404C6D60), i64 a1) { if (enableSwitchVoice && language != 0) { int size_bankName = 0; const char* bankName = (char*)lua_tolstring (a1, -3, (u64)&size_bankName); From 8391a1cd2f3d2d3393d8d25e5138fcf84b206835 Mon Sep 17 00:00:00 2001 From: RyuMiya Date: Wed, 30 Oct 2024 09:55:24 +0800 Subject: [PATCH 09/10] Use Hook instead of MidHook for PlaySoundSpecial --- src/patches/versions/JPN39.cpp | 91 +++++++++++++++------------------- 1 file changed, 41 insertions(+), 50 deletions(-) diff --git a/src/patches/versions/JPN39.cpp b/src/patches/versions/JPN39.cpp index baac629..402e1fb 100644 --- a/src/patches/versions/JPN39.cpp +++ b/src/patches/versions/JPN39.cpp @@ -84,7 +84,6 @@ HOOK_MID (FreezeTimer, ASLR (0x14019FF51), SafetyHookContext &ctx) { std::map nus3bankMap; int nus3bankIdCounter = 0; std::map voiceCnExist; -// std::map voiceCnInGameCache; bool enableSwitchVoice = false; std::mutex nus3bankMtx; @@ -181,72 +180,64 @@ HOOK (i64, GetCabinetLanguage, ASLR (0x1401D1A60), i64, i64 a2) { } std::string -fixToneName (std::string bankName, std::string toneName) { - if (enableSwitchVoice && bankName.starts_with("voice_")) { - if (language == 2 || language == 4) { - bool existCnVoice = voiceCnExist.find(bankName) != voiceCnExist.end() && voiceCnExist[bankName]; - if (existCnVoice) { - return toneName + "_cn"; - } +FixToneName (std::string bankName, std::string toneName) { + if (language == 2 || language == 4) { + if (voiceCnExist.find(bankName) != voiceCnExist.end() && voiceCnExist[bankName]) { + return toneName + "_cn"; } } return toneName; } +int commonSize = 0; HOOK (i64, PlaySound, ASLR (0x1404C6DC0), i64 a1) { if (enableSwitchVoice && language != 0) { - int size_bankName = 0; - const char* bankName = (char*)lua_tolstring (a1, -3, (u64)&size_bankName); - int size_toneName = 0; - const char* toneName = (char*)lua_tolstring (a1, -2, (u64)&size_toneName); - lua_pushstring (a1, (u64)(fixToneName (bankName, toneName).c_str())); - lua_replace(a1, -3); + std::string bankName((char*)lua_tolstring (a1, -3, (u64)&commonSize)); + if (bankName[0] == 'v') { + lua_pushstring(a1, (u64)(FixToneName(bankName, (char*)lua_tolstring (a1, -2, (u64)&commonSize)).c_str())); + lua_replace(a1, -3); + } } return originalPlaySound(a1); } HOOK (i64, PlaySoundMulti, ASLR (0x1404C6D60), i64 a1) { if (enableSwitchVoice && language != 0) { - int size_bankName = 0; - const char* bankName = (char*)lua_tolstring (a1, -3, (u64)&size_bankName); - int size_toneName = 0; - const char* toneName = (char*)lua_tolstring (a1, -2, (u64)&size_toneName); - lua_pushstring (a1, (u64)(fixToneName (bankName, toneName).c_str())); - lua_replace (a1, -3); - } - return originalPlaySoundMulti(a1); -} - -HOOK_MID (PlaySoundEnso, ASLR (0x1404ED5F9), SafetyHookContext &ctx) { - char* originalPlaySound = *((char**)ctx.rax); - std::string playSound(originalPlaySound); - if (enableSwitchVoice && playSound[0] == 'v') { - size_t slashIndex = playSound.find("/"); - if (slashIndex != std::string::npos) { - std::string bankName = playSound.substr(0, slashIndex); - if (voiceCnExist.find(bankName) != voiceCnExist.end() && voiceCnExist[bankName]) { - std::string *finalPlaySound = new std::string(playSound + "_cn"); - std::cout << "PlaySoundEnso fixed: " << *finalPlaySound << std::endl; - ctx.rax = (uintptr_t)finalPlaySound; - } + std::string bankName((char*)lua_tolstring (a1, -3, (u64)&commonSize)); + if (bankName[0] == 'v') { + lua_pushstring(a1, (u64)(FixToneName(bankName, (char*)lua_tolstring (a1, -2, (u64)&commonSize)).c_str())); + lua_replace(a1, -3); } } + return originalPlaySound(a1); } -HOOK_MID (PlaySoundSpecial, ASLR (0x1404ED296), SafetyHookContext &ctx) { - char* originalPlaySound = *((char**)ctx.rax); - std::string playSound(originalPlaySound); - if (enableSwitchVoice && playSound[0] == 'v') { - size_t slashIndex = playSound.find("/"); - if (slashIndex != std::string::npos) { - std::string bankName = playSound.substr(0, slashIndex); - if (voiceCnExist.find(bankName) != voiceCnExist.end() && voiceCnExist[bankName]) { - std::string *finalPlaySound = new std::string(playSound + "_cn"); - std::cout << "PlaySoundSpecial fixed: " << *finalPlaySound << std::endl; - ctx.rax = (uintptr_t)finalPlaySound; - } +FUNCTION_PTR (u64*, append_chars_to_basic_string, ASLR (0x140028DA0), u64*, char*, size_t); + +u64* +FixToneNameEnso(u64* Src, std::string &bankName) { + if (language == 2 || language == 4) { + if (voiceCnExist.find(bankName) != voiceCnExist.end() && voiceCnExist[bankName]) { + Src = append_chars_to_basic_string (Src, (const char*)"_cn", 3); } } + return Src; +} + +HOOK (bool, PlaySoundEnso, ASLR (0x1404ED590), u64* a1, u64* a2, i64 a3) { + if (enableSwitchVoice && language != 0) { + std::string bankName = a1[3] > 0x10 ? std::string(*((char**)a1)) : std::string((char*)a1); + if (bankName[0] == 'v') a2 = FixToneNameEnso(a2, bankName); + } + return originalPlaySoundEnso(a1, a2, a3); +} + +HOOK (bool, PlaySoundSpecial, ASLR (0x1404ED230), u64* a1, u64* a2) { + if (enableSwitchVoice && language != 0) { + std::string bankName = a1[3] > 0x10 ? std::string(*((char**)a1)) : std::string((char*)a1); + if (bankName[0] == 'v') a2 = FixToneNameEnso(a2, bankName); + } + return originalPlaySoundSpecial(a1, a2); } int loaded_fail_count = 0; @@ -404,8 +395,8 @@ Init () { enableSwitchVoice = true; INSTALL_HOOK (PlaySound); INSTALL_HOOK (PlaySoundMulti); - INSTALL_HOOK_MID (PlaySoundEnso); - INSTALL_HOOK_MID (PlaySoundSpecial); + INSTALL_HOOK (PlaySoundEnso); + INSTALL_HOOK (PlaySoundSpecial); } // Mode unlock From 817cf6a34e6444a8f2defee6613ac9f00e93e06d Mon Sep 17 00:00:00 2001 From: RyuMiya Date: Wed, 30 Oct 2024 20:15:17 +0800 Subject: [PATCH 10/10] Fix originalPlaySoundMulti --- src/patches/versions/JPN39.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/patches/versions/JPN39.cpp b/src/patches/versions/JPN39.cpp index 402e1fb..0be3ada 100644 --- a/src/patches/versions/JPN39.cpp +++ b/src/patches/versions/JPN39.cpp @@ -209,7 +209,7 @@ HOOK (i64, PlaySoundMulti, ASLR (0x1404C6D60), i64 a1) { lua_replace(a1, -3); } } - return originalPlaySound(a1); + return originalPlaySoundMulti(a1); } FUNCTION_PTR (u64*, append_chars_to_basic_string, ASLR (0x140028DA0), u64*, char*, size_t);