diff --git a/src/bnusio.cpp b/src/bnusio.cpp index da64988..7593442 100644 --- a/src/bnusio.cpp +++ b/src/bnusio.cpp @@ -52,20 +52,24 @@ Keybindings P2_RIGHT_BLUE = {.keycodes = {'V'}}; // CARD_INSERT_1, CARD_INSERT_2, QR_DATA_READ, QR_IMAGE_READ, P1_LEFT_BLUE, P1_LEFT_RED, // P1_RIGHT_RED, P1_RIGHT_BLUE, P2_LEFT_BLUE, P2_LEFT_RED, P2_RIGHT_RED, P2_RIGHT_BLUE }; -int exited = 0; -bool testEnabled = false; -int coin_count = 0; -int service_count = 0; -bool inited = false; -bool updateByCoin = false; -HWND windowHandle = nullptr; -bool usePoll = false; +const int exitWait = 100; +int exited = 0; +bool testEnabled = false; +int coin_count = 0; +int service_count = 0; +bool inited = false; +bool updateByCoin = false; +HWND windowHandle = nullptr; +bool usePoll = false; HKL currentLayout; namespace bnusio { #define RETURN_FALSE(returnType, functionName, ...) \ returnType functionName (__VA_ARGS__) { return 0; } +typedef u16 (__fastcall *AnalogMethod) (const u8); +AnalogMethod analogMethod = nullptr; + extern "C" { RETURN_FALSE (i64, bnusio_Open); RETURN_FALSE (i64, bnusio_Close); @@ -124,13 +128,14 @@ bnusio_GetSwIn () { } bool waitAll = false; -u16 drumWaitPeriod = 4; +short drumWaitPeriod = 4; +bool analogInput = false; bool valueStates[] = {false, false, false, false, false, false, false, false}; Keybindings *analogButtons[] = {&P1_LEFT_BLUE, &P1_LEFT_RED, &P1_RIGHT_RED, &P1_RIGHT_BLUE, &P2_LEFT_BLUE, &P2_LEFT_RED, &P2_RIGHT_RED, &P2_RIGHT_BLUE}; -u16 cooldown[8] = { 0 }; +// u16 cooldown[8] = { 0 }; u16 buttonWaitPeriod[] = { 0, 0 }; std::queue buttonQueue[] = { {}, {} }; @@ -139,7 +144,7 @@ std::queue buttonQueue[] = { {}, {} }; // std::queue buttonQueueP1; // std::queue buttonQueueP2; -bool analogInput; + SDLAxis analogBindings[] = { SDL_AXIS_LEFT_LEFT, SDL_AXIS_LEFT_RIGHT, SDL_AXIS_LEFT_DOWN, SDL_AXIS_LEFT_UP, // P1: LB, LR, RR, RB SDL_AXIS_RIGHT_LEFT, SDL_AXIS_RIGHT_RIGHT, SDL_AXIS_RIGHT_DOWN, SDL_AXIS_RIGHT_UP, // P2: LB, LR, RR, RB @@ -147,41 +152,8 @@ SDLAxis analogBindings[] = { u16 bnusio_GetAnalogIn (const u8 which) { - if (analogInput) { - const u16 analogValue = static_cast (32768 * ControllerAxisIsDown (analogBindings[which])); - if (analogValue > 100) return analogValue; - else return 0; - } - const auto button = analogButtons[which]; - const bool blue = !(which % 4 % 3); - const int player = which / 4; - - u16 analogValue = 0; - if (which == 0) { - for (int i=0; i<2; i++) if (buttonWaitPeriod[i] > 0) buttonWaitPeriod[i]--; - for (int i=0; i<8; i++) if (cooldown[i] > 0) cooldown[i]--; - } - if (buttonWaitPeriod[player] == 0 && !buttonQueue[player].empty () && buttonQueue[player].front () == which) { - buttonWaitPeriod[player] = drumWaitPeriod; - buttonQueue[player].pop (); - - const u16 hitValue = !valueStates[which] ? 50 : 51; - valueStates[which] = !valueStates[which]; - analogValue = (hitValue << 15) / 100 + 1; - } - if (IsButtonTapped (*button)) { - if ((waitAll || blue) && buttonWaitPeriod[player] > 0) { - buttonQueue[player].push (which); - return analogValue; - } else if ((waitAll || blue) && cooldown[which] > 0) return 0; - buttonWaitPeriod[player] = drumWaitPeriod; - if (waitAll || blue) cooldown[which] = 4; - - const u16 hitValue = !valueStates[which] ? 50 : 51; - valueStates[which] = !valueStates[which]; - analogValue = (hitValue << 15) / 100 + 1; - } - return analogValue; + if (analogMethod) return analogMethod (which); + else return 0; } u16 __fastcall bnusio_GetCoin (i32 a1) { @@ -237,6 +209,54 @@ FUNCTION_PTR (i64, bnusio_DecCoin_Original, PROC_ADDRESS ("bnusio_original.dll", FUNCTION_PTR (u64, bnusio_DecService_Original, PROC_ADDRESS ("bnusio_original.dll", "bnusio_DecService"), i32, u16); FUNCTION_PTR (i64, bnusio_ResetCoin_Original, PROC_ADDRESS ("bnusio_original.dll", "bnusio_ResetCoin")); +u16 __fastcall +AnalogInputAxis (const u8 which) { + const u16 analogValue = static_cast (32768 * ControllerAxisIsDown (analogBindings[which])); + if (analogValue > 100) return analogValue; + else return 0; +} + +u16 __fastcall +AnalogInputWaitPeriod (const u8 which) { + const auto button = analogButtons[which]; + const bool blue = !(which % 4 % 3); + const int player = which / 4; + + u16 analogValue = 0; + if (which == 0) for (int i=0; i<2; i++) if (buttonWaitPeriod[i] > 0) buttonWaitPeriod[i]--; + if (buttonWaitPeriod[player] == 0 && !buttonQueue[player].empty () && buttonQueue[player].front () == which) { + buttonWaitPeriod[player] = drumWaitPeriod; + buttonQueue[player].pop (); + + const u16 hitValue = !valueStates[which] ? 50 : 51; + valueStates[which] = !valueStates[which]; + analogValue = (hitValue << 15) / 100 + 1; + } + if (IsButtonTapped (*button)) { + if ((waitAll || blue) && buttonWaitPeriod[player] > 0) { + buttonQueue[player].push (which); + return analogValue; + } + buttonWaitPeriod[player] = drumWaitPeriod; + + const u16 hitValue = !valueStates[which] ? 50 : 51; + valueStates[which] = !valueStates[which]; + analogValue = (hitValue << 15) / 100 + 1; + } + return analogValue; +} + +u16 __fastcall +AnalogInputSimple (const u8 which) { + const auto button = analogButtons[which]; + if (IsButtonTapped (*button)) { + const u16 hitValue = !valueStates[which] ? 50 : 51; + valueStates[which] = !valueStates[which]; + return (hitValue << 15) / 100 + 1; + } + return 0; +} + #ifndef ASYNC_UPDATE void Update () { @@ -250,10 +270,10 @@ void UpdateLoop () { LogMessage (LogLevel::WARN, "(experimental) Using Async Update!"); std::unique_lock syncLock(syncMtx); - while (exited < 120) { + while (exited < exitWait) { syncCV.wait (syncLock); #endif - if (exited && ++exited >= 120) ExitProcess (0); + if (exited && ++exited >= exitWait) ExitProcess (0); #ifndef ASYNC_IO if (!inited) { @@ -307,9 +327,8 @@ Init () { if (config_ptr) { const toml_table_t *config = config_ptr.get (); if (const auto controller = openConfigSection (config, "controller")) { - drumWaitPeriod = static_cast (readConfigInt (controller, "wait_period", drumWaitPeriod)); + drumWaitPeriod = static_cast (readConfigInt (controller, "wait_period", drumWaitPeriod)); analogInput = readConfigBool (controller, "analog_input", analogInput); - if (analogInput) LogMessage (LogLevel::WARN, "Using analog input mode. All the keyboard drum inputs have been disabled."); } auto graphics = openConfigSection (config, "graphics"); if (graphics) { @@ -317,6 +336,17 @@ Init () { } } + if (analogInput) { + LogMessage (LogLevel::WARN, "[Analog Type] Axis: All the keyboard drum inputs have been disabled"); + analogMethod = AnalogInputAxis; + } else if (drumWaitPeriod > 0) { + LogMessage (LogLevel::WARN, "[Analog Type] WaitPeriod: Fast input might be queued"); + analogMethod = AnalogInputWaitPeriod; + } else { + LogMessage (LogLevel::INFO, "[Analog Type] Simple: Fastest and original input"); + analogMethod = AnalogInputSimple; + } + updateByCoin = fpsLimit == 0; if (updateByCoin) { LogMessage (LogLevel::INFO, "fpsLimit is set to 0, bnusio::Update() will invoke in getCoin callback"); @@ -324,6 +354,7 @@ Init () { const auto keyConfigPath = std::filesystem::current_path () / "keyconfig.toml"; const std::unique_ptr keyConfig_ptr (openConfig (keyConfigPath), toml_free); if (keyConfig_ptr) { + if (analogInput) usePoll = true; const toml_table_t *keyConfig = keyConfig_ptr.get (); SetConfigValue (keyConfig, "EXIT", &EXIT, &usePoll); diff --git a/src/dllmain.cpp b/src/dllmain.cpp index 9d6c166..1bec855 100644 --- a/src/dllmain.cpp +++ b/src/dllmain.cpp @@ -4,6 +4,7 @@ #include "patches/patches.h" #include "poll.h" #include "logger.h" +#include auto gameVersion = GameVersion::UNKNOWN; std::vector plugins; @@ -22,7 +23,6 @@ char accessCode1[21] = "00000000000000000001"; char accessCode2[21] = "00000000000000000002"; char chipId1[33] = "00000000000000000000000000000001"; char chipId2[33] = "00000000000000000000000000000002"; -bool highResTimer = true; bool windowed = false; bool autoIme = false; bool jpLayout = false; @@ -36,22 +36,22 @@ std::string logLevelStr = "INFO"; bool logToFile = true; HWND hGameWnd; -HOOK (i32, ShowMouse, PROC_ADDRESS ("user32.dll", "ShowCursor"), bool) { return originalShowMouse (true); } -HOOK (i32, ExitWindows, PROC_ADDRESS ("user32.dll", "ExitWindowsEx")) { ExitProcess (0); } -HOOK (HWND, CreateWindow, PROC_ADDRESS ("user32.dll", "CreateWindowExW"), DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName, DWORD dwStyle, +FAST_HOOK (i32, ShowMouse, PROC_ADDRESS ("user32.dll", "ShowCursor"), bool) { return originalShowMouse.stdcall (true); } +FAST_HOOK (i32, ExitWindows, PROC_ADDRESS ("user32.dll", "ExitWindowsEx")) { ExitProcess (0); } +FAST_HOOK (HWND, CreateWindow, PROC_ADDRESS ("user32.dll", "CreateWindowExW"), DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName, DWORD dwStyle, i32 X, i32 Y, i32 nWidth, i32 nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam) { if (lpWindowName != nullptr) { if (wcscmp (lpWindowName, L"Taiko") == 0) { if (windowed) dwStyle = WS_TILEDWINDOW ^ WS_MAXIMIZEBOX ^ WS_THICKFRAME; hGameWnd - = originalCreateWindow (dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); + = originalCreateWindow.stdcall (dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); return hGameWnd; } } - return originalCreateWindow (dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); + return originalCreateWindow.stdcall (dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); } -HOOK (bool, SetWindowPosition, PROC_ADDRESS ("user32.dll", "SetWindowPos"), HWND hWnd, HWND hWndInsertAfter, i32 X, i32 Y, i32 cx, i32 cy, +FAST_HOOK (bool, SetWindowPosition, PROC_ADDRESS ("user32.dll", "SetWindowPos"), HWND hWnd, HWND hWndInsertAfter, i32 X, i32 Y, i32 cx, i32 cy, u32 uFlags) { if (hWnd == hGameWnd) { RECT rw, rc; @@ -60,29 +60,29 @@ HOOK (bool, SetWindowPosition, PROC_ADDRESS ("user32.dll", "SetWindowPos"), HWND cx = rw.right - rw.left - (rc.right - rc.left) + cx; cy = rw.bottom - rw.top - (rc.bottom - rc.top) + cy; } - return originalSetWindowPosition (hWnd, hWndInsertAfter, X, Y, cx, cy, uFlags); + return originalSetWindowPosition.stdcall (hWnd, hWndInsertAfter, X, Y, cx, cy, uFlags); } -HOOK (void, ExitProcessHook, PROC_ADDRESS ("kernel32.dll", "ExitProcess"), u32 uExitCode) { +FAST_HOOK (void, ExitProcessHook, PROC_ADDRESS ("kernel32.dll", "ExitProcess"), u32 uExitCode) { bnusio::Close (); - originalExitProcessHook (uExitCode); + originalExitProcessHook.stdcall (uExitCode); } -HOOK (i32, XinputGetState, PROC_ADDRESS ("xinput9_1_0.dll", "XInputGetState")) { return ERROR_DEVICE_NOT_CONNECTED; } -HOOK (i32, XinputSetState, PROC_ADDRESS ("xinput9_1_0.dll", "XInputSetState")) { return ERROR_DEVICE_NOT_CONNECTED; } -HOOK (i32, XinputGetCapabilites, PROC_ADDRESS ("xinput9_1_0.dll", "XInputGetCapabilities")) { return ERROR_DEVICE_NOT_CONNECTED; } +FAST_HOOK (i32, XinputGetState, PROC_ADDRESS ("xinput9_1_0.dll", "XInputGetState")) { return ERROR_DEVICE_NOT_CONNECTED; } +FAST_HOOK (i32, XinputSetState, PROC_ADDRESS ("xinput9_1_0.dll", "XInputSetState")) { return ERROR_DEVICE_NOT_CONNECTED; } +FAST_HOOK (i32, XinputGetCapabilites, PROC_ADDRESS ("xinput9_1_0.dll", "XInputGetCapabilities")) { return ERROR_DEVICE_NOT_CONNECTED; } -HOOK (i32, ssleay_Shutdown, PROC_ADDRESS ("ssleay32.dll", "SSL_shutdown")) { return 1; } +FAST_HOOK (i32, ssleay_Shutdown, PROC_ADDRESS ("ssleay32.dll", "SSL_shutdown")) { return 1; } -HOOK (i64, UsbFinderInitialize, PROC_ADDRESS ("nbamUsbFinder.dll", "nbamUsbFinderInitialize")) { return 0; } -HOOK (i64, UsbFinderRelease, PROC_ADDRESS ("nbamUsbFinder.dll", "nbamUsbFinderRelease")) { return 0; } -HOOK (i64, UsbFinderGetSerialNumber, PROC_ADDRESS ("nbamUsbFinder.dll", "nbamUsbFinderGetSerialNumber"), i32 a1, char *a2) { +FAST_HOOK (i64, UsbFinderInitialize, PROC_ADDRESS ("nbamUsbFinder.dll", "nbamUsbFinderInitialize")) { return 0; } +FAST_HOOK (i64, UsbFinderRelease, PROC_ADDRESS ("nbamUsbFinder.dll", "nbamUsbFinderRelease")) { return 0; } +FAST_HOOK (i64, UsbFinderGetSerialNumber, PROC_ADDRESS ("nbamUsbFinder.dll", "nbamUsbFinderGetSerialNumber"), i32 a1, char *a2) { strcpy (a2, chassisId.c_str ()); return 0; } -HOOK (i32, ws2_getaddrinfo, PROC_ADDRESS ("ws2_32.dll", "getaddrinfo"), const char *node, char *service, void *hints, void *out) { - return originalws2_getaddrinfo (server.c_str (), service, hints, out); +FAST_HOOK (i32, ws2_getaddrinfo, PROC_ADDRESS ("ws2_32.dll", "getaddrinfo"), const char *node, char *service, void *hints, void *out) { + return originalws2_getaddrinfo.stdcall (server.c_str (), service, hints, out); } void @@ -140,6 +140,51 @@ CreateCard () { WritePrivateProfileStringA ("card", "chipId2", buf, ".\\card.ini"); } +void +ElevateProcess () { + HANDLE hToken; + TOKEN_PRIVILEGES tp; + LUID luid; + + // 获取当前进程的访问令牌 + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { + LogMessage (LogLevel::ERROR, "OpenProcessToken failed: {}", GetLastError()); + return; + } + + // 获取 SE_DEBUG_NAME 权限的 LUID + if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) { + LogMessage (LogLevel::ERROR, "LookupPrivilegeValue failed: {}", GetLastError()); + CloseHandle(hToken); + return; + } + + tp.PrivilegeCount = 1; + tp.Privileges[0].Luid = luid; + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + + // 调整权限 + if (!AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL)) { + LogMessage (LogLevel::ERROR, "AdjustTokenPrivileges failed: {}", GetLastError()); + CloseHandle(hToken); + return; + } + + LogMessage (LogLevel::INFO, "Privileges adjusted successfully!"); + CloseHandle(hToken); +} + +bool DisableDEP() { + if (SetProcessDEPPolicy(PROCESS_DEP_ENABLE)) { + // std::cout << "DEP disabled successfully.\n"; + return true; + } else { + LogMessage (LogLevel::ERROR, "Failed to disable DEP: {}", GetLastError()); + // std::cerr << "Failed to disable DEP: " << GetLastError() << std::endl; + return false; + } +} + BOOL DllMain (HMODULE module, const DWORD reason, LPVOID reserved) { if (reason == DLL_PROCESS_ATTACH) { @@ -147,14 +192,19 @@ DllMain (HMODULE module, const DWORD reason, LPVOID reserved) { // I/O in DllMain can easily cause a deadlock // Init logger for loading config + + auto start = std::chrono::high_resolution_clock::now(); InitializeLogger (GetLogLevel (logLevelStr), logToFile); - LogMessage (LogLevel::INFO, "Loading config..."); - + // ElevateProcess (); + // DisableDEP (); + patches::Timer::Init (); #ifdef ASYNC_IO LogMessage (LogLevel::WARN, "(experimental) Using Async IO!"); InitializeKeyboard (); #endif + LogMessage (LogLevel::INFO, "Loading config..."); + std::string version = "auto"; const std::filesystem::path configPath = std::filesystem::current_path () / "config.toml"; const std::unique_ptr config_ptr (openConfig (configPath), toml_free); @@ -177,10 +227,7 @@ DllMain (HMODULE module, const DWORD reason, LPVOID reserved) { std::strcat (placeId, countryCode.c_str ()); std::strcat (placeId, "0FF0"); } - if (const auto patches = openConfigSection (config, "patches")) { - version = readConfigString (patches, "version", version); - highResTimer = readConfigBool (patches, "high_res_timer", highResTimer); - } + if (const auto patches = openConfigSection (config, "patches")) version = readConfigString (patches, "version", version); if (const auto emulation = openConfigSection (config, "emulation")) { emulateUsio = readConfigBool (emulation, "usio", emulateUsio); emulateCardReader = readConfigBool (emulation, "card_reader", emulateCardReader); @@ -221,7 +268,7 @@ DllMain (HMODULE module, const DWORD reason, LPVOID reserved) { MessageBoxA (nullptr, "Unknown patch version", nullptr, MB_OK); ExitProcess (0); } - LogMessage (LogLevel::INFO, "GameVersion is %s", GameVersionToString (gameVersion)); + LogMessage (LogLevel::INFO, "GameVersion is {}", GameVersionToString (gameVersion)); patches::Plugins::LoadPlugins (); patches::Plugins::InitVersion (gameVersion); @@ -234,24 +281,24 @@ DllMain (HMODULE module, const DWORD reason, LPVOID reserved) { LogMessage (LogLevel::INFO, "==== Loading patches, please wait..."); - if (cursor) INSTALL_HOOK (ShowMouse); - INSTALL_HOOK (ExitWindows); - INSTALL_HOOK (CreateWindow); - INSTALL_HOOK (SetWindowPosition); + if (cursor) INSTALL_FAST_HOOK (ShowMouse); + INSTALL_FAST_HOOK (ExitWindows); + INSTALL_FAST_HOOK (CreateWindow); + INSTALL_FAST_HOOK (SetWindowPosition); - INSTALL_HOOK (ExitProcessHook); + INSTALL_FAST_HOOK (ExitProcessHook); - INSTALL_HOOK (XinputGetState); - INSTALL_HOOK (XinputSetState); - INSTALL_HOOK (XinputGetCapabilites); + INSTALL_FAST_HOOK (XinputGetState); + INSTALL_FAST_HOOK (XinputSetState); + INSTALL_FAST_HOOK (XinputGetCapabilites); - INSTALL_HOOK (ssleay_Shutdown); + INSTALL_FAST_HOOK (ssleay_Shutdown); - INSTALL_HOOK (UsbFinderInitialize); - INSTALL_HOOK (UsbFinderRelease); - INSTALL_HOOK (UsbFinderGetSerialNumber); + INSTALL_FAST_HOOK (UsbFinderInitialize); + INSTALL_FAST_HOOK (UsbFinderRelease); + INSTALL_FAST_HOOK (UsbFinderGetSerialNumber); - INSTALL_HOOK (ws2_getaddrinfo); + INSTALL_FAST_HOOK (ws2_getaddrinfo); bnusio::Init (); @@ -270,11 +317,8 @@ DllMain (HMODULE module, const DWORD reason, LPVOID reserved) { patches::LayeredFs::Init (); patches::TestMode::Init (); - if (highResTimer) { - patches::Timer::Init (); - } - - LogMessage (LogLevel::INFO, "==== Finished Loading patches!"); + std::chrono::duration duration = std::chrono::high_resolution_clock::now() - start; + LogMessage (LogLevel::INFO, "==== Finished Loading patches! using: {:.2f}ms", duration.count () * 1000); } return true; } diff --git a/src/helpers.h b/src/helpers.h index e7a848e..ef3b708 100644 --- a/src/helpers.h +++ b/src/helpers.h @@ -66,6 +66,17 @@ const HMODULE MODULE_HANDLE = GetModuleHandle (nullptr); std::map mapOf##functionName; \ void implOf##functionName (SafetyHookContext &ctx) +#define FAST_HOOK(returnType, functionName, location, ...) \ + typedef returnType (*functionName) (__VA_ARGS__); \ + SafetyHookInline original##functionName; \ + void *where##functionName = (void *)(location); \ + returnType implOf##functionName (__VA_ARGS__) + +#define FAST_HOOK_DYNAMIC(returnType, functionName, ...) \ + typedef returnType (*functionName) (__VA_ARGS__); \ + SafetyHookInline original##functionName; \ + returnType implOf##functionName (__VA_ARGS__) + #define INSTALL_HOOK(functionName) \ { \ LogMessage (LogLevel::DEBUG, std::string ("Installing hook for ") + #functionName); \ @@ -103,27 +114,46 @@ const HMODULE MODULE_HANDLE = GetModuleHandle (nullptr); #define INSTALL_MID_HOOK_DYNAMIC(functionName, location) \ { mapOf##functionName[location] = safetyhook::create_mid (location, implOf##functionName); } +#define INSTALL_FAST_HOOK(functionName) \ + { \ + LogMessage (LogLevel::DEBUG, std::string ("Installing fast hook for ") + #functionName); \ + original##functionName = safetyhook::create_inline (where##functionName, (void*)implOf##functionName); \ + } + +#define INSTALL_FAST_HOOK_DYNAMIC(functionName, location) \ + { \ + LogMessage (LogLevel::DEBUG, std::string ("Installing fast hook dynamic for ") + #functionName); \ + if (auto hook = safetyhook::InlineHook::create((void *)location, (void*)implOf##functionName)) {\ + original##functionName = std::move(*hook); \ + } else { \ + LogMessage (LogLevel::ERROR, std::string ("Error Installing fast hook dynamic for ") + #functionName);\ + ExitProcess (1); \ + } \ + } + // original##functionName = safetyhook::create_inline ((void *)location, (void*)implOf##functionName); \ + // } + inline bool sendFlag = false; #define SCENE_RESULT_HOOK(functionName, location) \ - HOOK (void, functionName, location, i64 a1, i64 a2, i64 a3) { \ + FAST_HOOK (void, functionName, location, i64 a1, i64 a2, i64 a3) { \ if (TestMode::ReadTestModeValue (L"ModInstantResult") != 1 && TestMode::ReadTestModeValue (L"NumberOfStageItem") <= 4) { \ - original##functionName (a1, a2, a3); \ + original##functionName.fastcall (a1, a2, a3); \ return; \ } \ sendFlag = true; \ - original##functionName (a1, a2, a3); \ + original##functionName.fastcall (a1, a2, a3); \ ExecuteSendResultData (); \ } #define SEND_RESULT_HOOK(functionName, location) \ - HOOK (void, functionName, location, i64 a1) { \ + FAST_HOOK (void, functionName, location, i64 a1) { \ if (TestMode::ReadTestModeValue (L"ModInstantResult") != 1 && TestMode::ReadTestModeValue (L"NumberOfStageItem") <= 4) { \ - original##functionName (a1); \ + original##functionName.fastcall (a1); \ return; \ } \ if (sendFlag) { \ sendFlag = false; \ - original##functionName (a1); \ + original##functionName.fastcall (a1); \ } \ } diff --git a/src/logger.cpp b/src/logger.cpp index 898cfb5..639edc4 100644 --- a/src/logger.cpp +++ b/src/logger.cpp @@ -70,11 +70,16 @@ LogMessageHandler (const char *function, const char *codeFile, int codeLine, Log std::string logMessage = logStream.str (); // Print the log message - std::cout << "[" << timeStamp.str () << "] "; // Timestamp - SetConsoleTextAttribute (consoleHandle, GetLogLevelColor (messageLevel)); // Set Level color - std::cout << logType; // Level - SetConsoleTextAttribute (consoleHandle, FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY); // Reset console color - std::cout << logMessage << std::endl; // Log message + std::cout << "[" << timeStamp.str () << "] "; // Timestamp + SetConsoleTextAttribute (consoleHandle, GetLogLevelColor (messageLevel)); // Set Level color + std::cout << logType; // Level + if (messageLevel != LogLevel::ERROR) { + SetConsoleTextAttribute (consoleHandle, FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY); // Reset console color + } + std::cout << logMessage << std::endl; // Log message + if (messageLevel == LogLevel::ERROR) { + SetConsoleTextAttribute (consoleHandle, FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY); // Reset console color + } std::cout.flush (); // Flush to ensure immediate writing if (loggerInstance->logFile != nullptr) { diff --git a/src/patches/amauth.cpp b/src/patches/amauth.cpp index 6c9fe78..e2b6511 100644 --- a/src/patches/amauth.cpp +++ b/src/patches/amauth.cpp @@ -525,7 +525,7 @@ public: HRESULT LockServer (i32 lock) override { return 0; } }; -static HRESULT (STDAPICALLTYPE *g_origCoCreateInstance) (const IID *rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, const IID *riid, LPVOID *ppv); +SafetyHookInline originalCoCreateInstanceHook; static HRESULT STDAPICALLTYPE CoCreateInstanceHook (const IID *const rclsid, const LPUNKNOWN pUnkOuter, const DWORD dwClsContext, const IID *const riid, LPVOID *ppv) { @@ -540,7 +540,7 @@ CoCreateInstanceHook (const IID *const rclsid, const LPUNKNOWN pUnkOuter, const const auto cauth = new CAuth (); result = cauth->QueryInterface (*riid, ppv); } else { - result = g_origCoCreateInstance (rclsid, pUnkOuter, dwClsContext, riid, ppv); + result = originalCoCreateInstanceHook.stdcall (rclsid, pUnkOuter, dwClsContext, riid, ppv); } CoTaskMemFree (clsidStr); @@ -552,10 +552,8 @@ void Init () { LogMessage (LogLevel::INFO, "Init AmAuth patches"); - MH_Initialize (); - MH_CreateHookApi (L"ole32.dll", "CoCreateInstance", reinterpret_cast (CoCreateInstanceHook), - reinterpret_cast (&g_origCoCreateInstance)); - MH_EnableHook (nullptr); + auto whereCoCreateInstance = GetProcAddress (LoadLibraryW (L"ole32.dll"), "CoCreateInstance"); + originalCoCreateInstanceHook = safetyhook::create_inline ((void *)whereCoCreateInstance, CoCreateInstanceHook); addrinfo *res = nullptr; getaddrinfo (server.c_str (), "", nullptr, &res); diff --git a/src/patches/audio.cpp b/src/patches/audio.cpp index 03663e9..394faf0 100644 --- a/src/patches/audio.cpp +++ b/src/patches/audio.cpp @@ -24,16 +24,16 @@ std::string asioDriver; float volumeRate = 0.0f; -HOOK_DYNAMIC (i64, NUSCDeviceInit, void *a1, nusc_init_config_t *a2, nusc_init_config_t *a3, void *a4) { +FAST_HOOK_DYNAMIC (i64, NUSCDeviceInit, void *a1, nusc_init_config_t *a2, nusc_init_config_t *a3, void *a4) { LogMessage (LogLevel::INFO, std::string ("Device mode is ") + (asio ? "ASIO" : wasapiShared ? "wasapi shared" : "wasapi exclusive")); if (asio) LogMessage (LogLevel::INFO, (std::string ("ASIO driver is ") + asioDriver).c_str ()); a2->device_mode = asio; a2->asio_driver_name = asio ? asioDriver.c_str () : ""; a2->wasapi_exclusive = asio ? 1 : wasapiShared ? 0 : 1; - return originalNUSCDeviceInit (a1, a2, a3, a4); + return originalNUSCDeviceInit.fastcall (a1, a2, a3, a4); } -HOOK_DYNAMIC (bool, LoadASIODriver, void *a1, const char *a2) { - const auto result = originalLoadASIODriver (a1, a2); +FAST_HOOK_DYNAMIC (bool, LoadASIODriver, void *a1, const char *a2) { + const auto result = originalLoadASIODriver.fastcall (a1, a2); if (!result) { LogMessage (LogLevel::ERROR, (std::string ("Failed to load ASIO driver ") + asioDriver).c_str ()); MessageBoxA (nullptr, "Failed to load ASIO driver", nullptr, MB_OK); @@ -41,13 +41,13 @@ HOOK_DYNAMIC (bool, LoadASIODriver, void *a1, const char *a2) { } return result; } -HOOK_DYNAMIC (u64, NuscBusVolume, u64 a1, u64 a2, float a3) { +FAST_HOOK_DYNAMIC (u64, NuscBusVolume, u64 a1, u64 a2, float a3) { if (volumeRate == 0.0f) { int value = patches::TestMode::ReadTestModeValue (L"OutputLevelSpeakerItem"); - if (value == -1) return originalNuscBusVolume (a1, a2, a3); + if (value == -1) return originalNuscBusVolume.fastcall (a1, a2, a3); volumeRate = value <= 100 ? 1.0f : value / 100.0f; } - return originalNuscBusVolume (a1, a2, a3 * volumeRate); + return originalNuscBusVolume.fastcall (a1, a2, a3 * volumeRate); } void @@ -71,24 +71,24 @@ Init () { switch (gameVersion) { case GameVersion::JPN00: { - INSTALL_HOOK_DYNAMIC (NUSCDeviceInit, ASLR (0x140552160)); - INSTALL_HOOK_DYNAMIC (LoadASIODriver, ASLR (0x14055A950)); + INSTALL_FAST_HOOK_DYNAMIC (NUSCDeviceInit, ASLR (0x140552160)); + INSTALL_FAST_HOOK_DYNAMIC (LoadASIODriver, ASLR (0x14055A950)); break; } case GameVersion::JPN08: { - INSTALL_HOOK_DYNAMIC (NUSCDeviceInit, ASLR (0x140692E00)); - INSTALL_HOOK_DYNAMIC (LoadASIODriver, ASLR (0x14069B750)); + INSTALL_FAST_HOOK_DYNAMIC (NUSCDeviceInit, ASLR (0x140692E00)); + INSTALL_FAST_HOOK_DYNAMIC (LoadASIODriver, ASLR (0x14069B750)); break; } case GameVersion::JPN39: { - INSTALL_HOOK_DYNAMIC (NUSCDeviceInit, ASLR (0x1407C8620)); - INSTALL_HOOK_DYNAMIC (LoadASIODriver, ASLR (0x1407D0F70)); - INSTALL_HOOK_DYNAMIC (NuscBusVolume, ASLR (0x1407B1C30)); + INSTALL_FAST_HOOK_DYNAMIC (NUSCDeviceInit, ASLR (0x1407C8620)); + INSTALL_FAST_HOOK_DYNAMIC (LoadASIODriver, ASLR (0x1407D0F70)); + INSTALL_FAST_HOOK_DYNAMIC (NuscBusVolume, ASLR (0x1407B1C30)); break; } case GameVersion::CHN00: { - INSTALL_HOOK_DYNAMIC (NUSCDeviceInit, ASLR (0x140777F70)); - INSTALL_HOOK_DYNAMIC (LoadASIODriver, ASLR (0x1407808C0)); + INSTALL_FAST_HOOK_DYNAMIC (NUSCDeviceInit, ASLR (0x140777F70)); + INSTALL_FAST_HOOK_DYNAMIC (LoadASIODriver, ASLR (0x1407808C0)); break; } default: { diff --git a/src/patches/patches.h b/src/patches/patches.h index 03cc8d6..4e95601 100644 --- a/src/patches/patches.h +++ b/src/patches/patches.h @@ -38,8 +38,10 @@ void Init (); } // namespace AmAuth namespace LayeredFs { void Init (); -void RegisterBefore (const std::function &fileHandler); -void RegisterAfter (const std::function &fileHandler); +void RegisterBeforeA (const std::function &fileHandler); +void RegisterAfterA (const std::function &fileHandler); +void RegisterBeforeW (const std::function &fileHandler); +void RegisterAfterW (const std::function &fileHandler); } // namespace LayeredFs namespace TestMode { class Applicable { @@ -68,6 +70,7 @@ void RegisterItemAfter (const std::wstring &query, const std::wstring &item); void RegisterItemAfter (const std::wstring &query, Applicable *item); void RegisterModify (const std::wstring &query, const std::function &nodeModify, const std::function &initMethod); void RegisterModify (const std::wstring &query, const std::function &nodeModify); +void RegisterHook (const std::function &initMethod); } // namespace TestMode namespace Plugins { // typedefs diff --git a/src/patches/scanner.cpp b/src/patches/scanner.cpp index 1b4a469..251d2c2 100644 --- a/src/patches/scanner.cpp +++ b/src/patches/scanner.cpp @@ -52,6 +52,17 @@ namespace Card { if (callbackTouch) { state = internalInvoke ? State::Disable : State::CopyWait; patches::Plugins::UpdateStatus (1, false); + if (!internalInvoke) { + LogMessage (LogLevel::DEBUG, "[Card] Call CallbackTouch!"); + for (int i = 0; i < 8; i++) { + std::ostringstream cardDataOut; + cardDataOut << std::hex << std::uppercase; + for (int j = 0; j < 21; j++) { + cardDataOut << std::setw (2) << std::setfill ('0') << (int)cardData[i * 21 + j] << " "; + } + LogMessage (LogLevel::DEBUG, cardDataOut.str ()); + } + } callbackTouch (0, 0, cardData, touchData); } } @@ -99,37 +110,37 @@ namespace Card { } } - HOOK (u64, bngrw_Init, PROC_ADDRESS ("bngrw.dll", "BngRwInit")) { return 0; } - HOOK (void, bngrw_Fin, PROC_ADDRESS ("bngrw.dll", "BngRwFin")) { return; } - HOOK (u64, bngrw_IsCmdExec, PROC_ADDRESS ("bngrw.dll", "BngRwIsCmdExec")) { return 0xFFFFFFFF; } - HOOK (i32, bngrw_ReqSendUrl, PROC_ADDRESS ("bngrw.dll", "BngRwReqSendUrlTo")) { return 1; } - HOOK (u64, bngrw_ReqLed, PROC_ADDRESS ("bngrw.dll", "BngRwReqLed")) { return 1; } - HOOK (u64, bngrw_ReqBeep, PROC_ADDRESS ("bngrw.dll", "BngRwReqBeep")) { return 1; } - HOOK (u64, bngrw_ReqAction, PROC_ADDRESS ("bngrw.dll", "BngRwReqAction")) { return 1; } - HOOK (u64, bngrw_ReqSetLedPower, PROC_ADDRESS ("bngrw.dll", "BngRwReqSetLedPower")) { return 0; } - HOOK (u64, bngrw_GetRetryCount, PROC_ADDRESS ("bngrw.dll", "BngRwGetTotalRetryCount")) { return 0; } - HOOK (u64, bngrw_GetFwVersion, PROC_ADDRESS ("bngrw.dll", "BngRwGetFwVersion")) { return 0; } - HOOK (u64, bngrw_ReqFwVersionUp, PROC_ADDRESS ("bngrw.dll", "BngRwReqFwVersionUp")) { return 1; } - HOOK (u64, bngrw_ReqFwCleanup, PROC_ADDRESS ("bngrw.dll", "BngRwReqFwCleanup")) { return 1; } - HOOK (u64, bngrw_ReadMifare, PROC_ADDRESS ("bngrw.dll", "BngRwExReadMifareAllBlock")) { return 0xFFFFFF9C; } - HOOK (u64, bngrw_GetStationID, PROC_ADDRESS ("bngrw.dll", "BngRwGetStationID")) { return 0; } - HOOK (i32, bngrw_ReqSendMail, PROC_ADDRESS ("bngrw.dll", "BngRwReqSendMailTo")) { return 1; } - HOOK (i32, bngrw_ReqLatchID, PROC_ADDRESS ("bngrw.dll", "BngRwReqLatchID")) { return 1; } - HOOK (u64, bngrw_ReqAiccAuth, PROC_ADDRESS ("bngrw.dll", "BngRwReqAiccAuth")) { return 1; } - HOOK (u64, bngrw_DevReset, PROC_ADDRESS ("bngrw.dll", "BngRwDevReset")) { return 1; } // Invoke when enter testmode - HOOK (i32, bngrw_ReqCancel, PROC_ADDRESS ("bngrw.dll", "BngRwReqCancel")) { + FAST_HOOK (u64, bngrw_Init, PROC_ADDRESS ("bngrw.dll", "BngRwInit")) { return 0; } + FAST_HOOK (void, bngrw_Fin, PROC_ADDRESS ("bngrw.dll", "BngRwFin")) { return; } + FAST_HOOK (u64, bngrw_IsCmdExec, PROC_ADDRESS ("bngrw.dll", "BngRwIsCmdExec")) { return 0xFFFFFFFF; } + FAST_HOOK (i32, bngrw_ReqSendUrl, PROC_ADDRESS ("bngrw.dll", "BngRwReqSendUrlTo")) { return 1; } + FAST_HOOK (u64, bngrw_ReqLed, PROC_ADDRESS ("bngrw.dll", "BngRwReqLed")) { return 1; } + FAST_HOOK (u64, bngrw_ReqBeep, PROC_ADDRESS ("bngrw.dll", "BngRwReqBeep")) { return 1; } + FAST_HOOK (u64, bngrw_ReqAction, PROC_ADDRESS ("bngrw.dll", "BngRwReqAction")) { return 1; } + FAST_HOOK (u64, bngrw_ReqSetLedPower, PROC_ADDRESS ("bngrw.dll", "BngRwReqSetLedPower")) { return 0; } + FAST_HOOK (u64, bngrw_GetRetryCount, PROC_ADDRESS ("bngrw.dll", "BngRwGetTotalRetryCount")) { return 0; } + FAST_HOOK (u64, bngrw_GetFwVersion, PROC_ADDRESS ("bngrw.dll", "BngRwGetFwVersion")) { return 0; } + FAST_HOOK (u64, bngrw_ReqFwVersionUp, PROC_ADDRESS ("bngrw.dll", "BngRwReqFwVersionUp")) { return 1; } + FAST_HOOK (u64, bngrw_ReqFwCleanup, PROC_ADDRESS ("bngrw.dll", "BngRwReqFwCleanup")) { return 1; } + FAST_HOOK (u64, bngrw_ReadMifare, PROC_ADDRESS ("bngrw.dll", "BngRwExReadMifareAllBlock")) { return 0xFFFFFF9C; } + FAST_HOOK (u64, bngrw_GetStationID, PROC_ADDRESS ("bngrw.dll", "BngRwGetStationID")) { return 0; } + FAST_HOOK (i32, bngrw_ReqSendMail, PROC_ADDRESS ("bngrw.dll", "BngRwReqSendMailTo")) { return 1; } + FAST_HOOK (i32, bngrw_ReqLatchID, PROC_ADDRESS ("bngrw.dll", "BngRwReqLatchID")) { return 1; } + FAST_HOOK (u64, bngrw_ReqAiccAuth, PROC_ADDRESS ("bngrw.dll", "BngRwReqAiccAuth")) { return 1; } + FAST_HOOK (u64, bngrw_DevReset, PROC_ADDRESS ("bngrw.dll", "BngRwDevReset")) { return 1; } // Invoke when enter testmode + FAST_HOOK (i32, bngrw_ReqCancel, PROC_ADDRESS ("bngrw.dll", "BngRwReqCancel")) { if (state != State::Disable) { state = State::Disable; patches::Scanner::Card::Internal::Commit0 (accessCodeTemplate, chipIdTemplate, true); } return 1; } - HOOK (u64, bngrw_Attach, PROC_ADDRESS ("bngrw.dll", "BngRwAttach"), i32 a1, char *a2, i32 a3, i32 a4, CallbackAttach callback, i32 *a6) { + FAST_HOOK (u64, bngrw_Attach, PROC_ADDRESS ("bngrw.dll", "BngRwAttach"), i32 a1, char *a2, i32 a3, i32 a4, CallbackAttach callback, i32 *a6) { callbackAttach = callback; attachData = a6; return 1; } - HOOK (u64, bngrw_ReqWaitTouch, PROC_ADDRESS ("bngrw.dll", "BngRwReqWaitTouch"), u32 a1, i32 a2, u32 a3, CallbackTouch callback, u64 a5) { + FAST_HOOK (u64, bngrw_ReqWaitTouch, PROC_ADDRESS ("bngrw.dll", "BngRwReqWaitTouch"), u32 a1, i32 a2, u32 a3, CallbackTouch callback, u64 a5) { state = State::Ready; patches::Plugins::UpdateStatus (1, true); patches::Plugins::WaitTouch (Internal::AgentInsertCardPlugin, a5); @@ -143,7 +154,7 @@ namespace Card { state = State::Disable; patches::Plugins::UpdateStatus (1, false); } - return originalbngrw_ReqCancelOfficial(a1); + return originalbngrw_ReqCancelOfficial (a1); } HOOK (u64, bngrw_ReqWaitTouchOfficial, PROC_ADDRESS ("bngrw.dll", "BngRwReqWaitTouch"), u32 a1, i32 a2, u32 a3, CallbackTouch callback, u64 a5) { state = State::Ready; @@ -190,27 +201,27 @@ namespace Card { return; } - INSTALL_HOOK (bngrw_Init) - INSTALL_HOOK (bngrw_Fin); - INSTALL_HOOK (bngrw_IsCmdExec); - INSTALL_HOOK (bngrw_ReqCancel); - INSTALL_HOOK (bngrw_ReqWaitTouch); - INSTALL_HOOK (bngrw_ReqSendUrl); - INSTALL_HOOK (bngrw_ReqLed); - INSTALL_HOOK (bngrw_ReqBeep); - INSTALL_HOOK (bngrw_ReqAction); - INSTALL_HOOK (bngrw_ReqSetLedPower); - INSTALL_HOOK (bngrw_GetRetryCount); - INSTALL_HOOK (bngrw_GetFwVersion); - INSTALL_HOOK (bngrw_ReqFwVersionUp); - INSTALL_HOOK (bngrw_ReqFwCleanup); - INSTALL_HOOK (bngrw_ReadMifare); - INSTALL_HOOK (bngrw_GetStationID); - INSTALL_HOOK (bngrw_ReqSendMail); - INSTALL_HOOK (bngrw_ReqLatchID); - INSTALL_HOOK (bngrw_ReqAiccAuth); - INSTALL_HOOK (bngrw_Attach); - INSTALL_HOOK (bngrw_DevReset); + INSTALL_FAST_HOOK (bngrw_Init) + INSTALL_FAST_HOOK (bngrw_Fin); + INSTALL_FAST_HOOK (bngrw_IsCmdExec); + INSTALL_FAST_HOOK (bngrw_ReqCancel); + INSTALL_FAST_HOOK (bngrw_ReqWaitTouch); + INSTALL_FAST_HOOK (bngrw_ReqSendUrl); + INSTALL_FAST_HOOK (bngrw_ReqLed); + INSTALL_FAST_HOOK (bngrw_ReqBeep); + INSTALL_FAST_HOOK (bngrw_ReqAction); + INSTALL_FAST_HOOK (bngrw_ReqSetLedPower); + INSTALL_FAST_HOOK (bngrw_GetRetryCount); + INSTALL_FAST_HOOK (bngrw_GetFwVersion); + INSTALL_FAST_HOOK (bngrw_ReqFwVersionUp); + INSTALL_FAST_HOOK (bngrw_ReqFwCleanup); + INSTALL_FAST_HOOK (bngrw_ReadMifare); + INSTALL_FAST_HOOK (bngrw_GetStationID); + INSTALL_FAST_HOOK (bngrw_ReqSendMail); + INSTALL_FAST_HOOK (bngrw_ReqLatchID); + INSTALL_FAST_HOOK (bngrw_ReqAiccAuth); + INSTALL_FAST_HOOK (bngrw_Attach); + INSTALL_FAST_HOOK (bngrw_DevReset); patches::Plugins::InitCardReader (patches::Scanner::Card::Commit); } } @@ -219,29 +230,29 @@ namespace Qr { State state = State::Disable; long long lastScan; - HOOK_DYNAMIC (char, QrInit, i64) { return 1; } - HOOK_DYNAMIC (char, QrClose, i64) { return 1; } - HOOK_DYNAMIC (char, QrRead, i64 a1) { + FAST_HOOK_DYNAMIC (char, QrInit, i64) { return 1; } + FAST_HOOK_DYNAMIC (char, QrClose, i64) { return 1; } + FAST_HOOK_DYNAMIC (char, QrRead, i64 a1) { *(DWORD *)(a1 + 40) = 1; *(DWORD *)(a1 + 16) = 1; *(BYTE *)(a1 + 112) = 0; return 1; } - HOOK_DYNAMIC (i64, CallQrUnknown, i64) { return 1; } - HOOK_DYNAMIC (bool, Send1, i64 a1) { + FAST_HOOK_DYNAMIC (i64, CallQrUnknown, i64) { return 1; } + FAST_HOOK_DYNAMIC (bool, Send1, i64 a1) { *(BYTE *)(a1 + 88) = 1; *(i64 *)(a1 + 32) = *(i64 *)(a1 + 24); *(WORD *)(a1 + 89) = 0; return true; } - HOOK_DYNAMIC (bool, Send2, i64 a1) { + FAST_HOOK_DYNAMIC (bool, Send2, i64 a1) { *(WORD *)(a1 + 88) = 0; *(BYTE *)(a1 + 90) = 0; return true; } - HOOK_DYNAMIC (bool, Send3, i64, char) { return true; } - HOOK_DYNAMIC (bool, Send4, i64, const void *, i64) { return true; } - HOOK_DYNAMIC (i64, CopyData, i64, void *dest, int length) { + FAST_HOOK_DYNAMIC (bool, Send3, i64, char) { return true; } + FAST_HOOK_DYNAMIC (bool, Send4, i64, const void *, i64) { return true; } + FAST_HOOK_DYNAMIC (i64, CopyData, i64, void *dest, int length) { patches::Plugins::UsingQr (); lastScan = std::chrono::duration_cast(std::chrono::system_clock::now ().time_since_epoch ()).count (); if (state == State::CopyWait && scanQueue.size () > 0) { @@ -406,51 +417,51 @@ namespace Qr { auto amHandle = reinterpret_cast (GetModuleHandle ("AMFrameWork.dll")); switch (gameVersion) { case GameVersion::JPN00: { - INSTALL_HOOK_DYNAMIC (QrInit, (LPVOID)(amHandle + 0x1B3E0)); - INSTALL_HOOK_DYNAMIC (QrClose, (LPVOID)(amHandle + 0x1B5B0)); - INSTALL_HOOK_DYNAMIC (QrRead, (LPVOID)(amHandle + 0x1B600)); - INSTALL_HOOK_DYNAMIC (CallQrUnknown, (LPVOID)(amHandle + 0xFD40)); - INSTALL_HOOK_DYNAMIC (Send1, (LPVOID)(amHandle + 0x1BBB0)); - INSTALL_HOOK_DYNAMIC (Send2, (LPVOID)(amHandle + 0x1BBF0)); - INSTALL_HOOK_DYNAMIC (Send3, (LPVOID)(amHandle + 0x1BC60)); + INSTALL_FAST_HOOK_DYNAMIC (QrInit, (LPVOID)(amHandle + 0x1B3E0)); + INSTALL_FAST_HOOK_DYNAMIC (QrClose, (LPVOID)(amHandle + 0x1B5B0)); + INSTALL_FAST_HOOK_DYNAMIC (QrRead, (LPVOID)(amHandle + 0x1B600)); + INSTALL_FAST_HOOK_DYNAMIC (CallQrUnknown, (LPVOID)(amHandle + 0xFD40)); + INSTALL_FAST_HOOK_DYNAMIC (Send1, (LPVOID)(amHandle + 0x1BBB0)); + INSTALL_FAST_HOOK_DYNAMIC (Send2, (LPVOID)(amHandle + 0x1BBF0)); + INSTALL_FAST_HOOK_DYNAMIC (Send3, (LPVOID)(amHandle + 0x1BC60)); // JPN00 has no Send4 - INSTALL_HOOK_DYNAMIC (CopyData, (LPVOID)(amHandle + 0x1BC30)); + INSTALL_FAST_HOOK_DYNAMIC (CopyData, (LPVOID)(amHandle + 0x1BC30)); break; } case GameVersion::JPN08: { - INSTALL_HOOK_DYNAMIC (QrInit, (LPVOID)(amHandle + 0x1BA00)); - INSTALL_HOOK_DYNAMIC (QrClose, (LPVOID)(amHandle + 0x1BBD0)); - INSTALL_HOOK_DYNAMIC (QrRead, (LPVOID)(amHandle + 0x1BC20)); - INSTALL_HOOK_DYNAMIC (CallQrUnknown, (LPVOID)(amHandle + 0xFD40)); - INSTALL_HOOK_DYNAMIC (Send1, (LPVOID)(amHandle + 0x1C220)); - INSTALL_HOOK_DYNAMIC (Send2, (LPVOID)(amHandle + 0x1C260)); - INSTALL_HOOK_DYNAMIC (Send3, (LPVOID)(amHandle + 0x1C2D0)); + INSTALL_FAST_HOOK_DYNAMIC (QrInit, (LPVOID)(amHandle + 0x1BA00)); + INSTALL_FAST_HOOK_DYNAMIC (QrClose, (LPVOID)(amHandle + 0x1BBD0)); + INSTALL_FAST_HOOK_DYNAMIC (QrRead, (LPVOID)(amHandle + 0x1BC20)); + INSTALL_FAST_HOOK_DYNAMIC (CallQrUnknown, (LPVOID)(amHandle + 0xFD40)); + INSTALL_FAST_HOOK_DYNAMIC (Send1, (LPVOID)(amHandle + 0x1C220)); + INSTALL_FAST_HOOK_DYNAMIC (Send2, (LPVOID)(amHandle + 0x1C260)); + INSTALL_FAST_HOOK_DYNAMIC (Send3, (LPVOID)(amHandle + 0x1C2D0)); // JPN08 has no Send4 - INSTALL_HOOK_DYNAMIC (CopyData, (LPVOID)(amHandle + 0x1C2A0)); + INSTALL_FAST_HOOK_DYNAMIC (CopyData, (LPVOID)(amHandle + 0x1C2A0)); break; } case GameVersion::JPN39: { - INSTALL_HOOK_DYNAMIC (QrInit, (LPVOID)(amHandle + 0x1EDC0)); - INSTALL_HOOK_DYNAMIC (QrClose, (LPVOID)(amHandle + 0x1EF60)); - INSTALL_HOOK_DYNAMIC (QrRead, (LPVOID)(amHandle + 0x1EFB0)); - INSTALL_HOOK_DYNAMIC (CallQrUnknown, (LPVOID)(amHandle + 0x11A70)); - INSTALL_HOOK_DYNAMIC (Send1, (LPVOID)(amHandle + 0x1F5B0)); - INSTALL_HOOK_DYNAMIC (Send2, (LPVOID)(amHandle + 0x1F5F0)); - INSTALL_HOOK_DYNAMIC (Send3, (LPVOID)(amHandle + 0x1F660)); - INSTALL_HOOK_DYNAMIC (Send4, (LPVOID)(amHandle + 0x1F690)); - INSTALL_HOOK_DYNAMIC (CopyData, (LPVOID)(amHandle + 0x1F630)); + INSTALL_FAST_HOOK_DYNAMIC (QrInit, (LPVOID)(amHandle + 0x1EDC0)); + INSTALL_FAST_HOOK_DYNAMIC (QrClose, (LPVOID)(amHandle + 0x1EF60)); + INSTALL_FAST_HOOK_DYNAMIC (QrRead, (LPVOID)(amHandle + 0x1EFB0)); + INSTALL_FAST_HOOK_DYNAMIC (CallQrUnknown, (LPVOID)(amHandle + 0x11A70)); + INSTALL_FAST_HOOK_DYNAMIC (Send1, (LPVOID)(amHandle + 0x1F5B0)); + INSTALL_FAST_HOOK_DYNAMIC (Send2, (LPVOID)(amHandle + 0x1F5F0)); + INSTALL_FAST_HOOK_DYNAMIC (Send3, (LPVOID)(amHandle + 0x1F660)); + INSTALL_FAST_HOOK_DYNAMIC (Send4, (LPVOID)(amHandle + 0x1F690)); + INSTALL_FAST_HOOK_DYNAMIC (CopyData, (LPVOID)(amHandle + 0x1F630)); break; } case GameVersion::CHN00: { - INSTALL_HOOK_DYNAMIC (QrInit, (LPVOID)(amHandle + 0x161B0)); - INSTALL_HOOK_DYNAMIC (QrClose, (LPVOID)(amHandle + 0x16350)); - INSTALL_HOOK_DYNAMIC (QrRead, (LPVOID)(amHandle + 0x163A0)); - INSTALL_HOOK_DYNAMIC (CallQrUnknown, (LPVOID)(amHandle + 0x8F60)); - INSTALL_HOOK_DYNAMIC (Send1, (LPVOID)(amHandle + 0x16940)); - INSTALL_HOOK_DYNAMIC (Send2, (LPVOID)(amHandle + 0x16990)); - INSTALL_HOOK_DYNAMIC (Send3, (LPVOID)(amHandle + 0x16A00)); - INSTALL_HOOK_DYNAMIC (Send4, (LPVOID)(amHandle + 0x16A30)); - INSTALL_HOOK_DYNAMIC (CopyData, (LPVOID)(amHandle + 0x169D0)); + INSTALL_FAST_HOOK_DYNAMIC (QrInit, (LPVOID)(amHandle + 0x161B0)); + INSTALL_FAST_HOOK_DYNAMIC (QrClose, (LPVOID)(amHandle + 0x16350)); + INSTALL_FAST_HOOK_DYNAMIC (QrRead, (LPVOID)(amHandle + 0x163A0)); + INSTALL_FAST_HOOK_DYNAMIC (CallQrUnknown, (LPVOID)(amHandle + 0x8F60)); + INSTALL_FAST_HOOK_DYNAMIC (Send1, (LPVOID)(amHandle + 0x16940)); + INSTALL_FAST_HOOK_DYNAMIC (Send2, (LPVOID)(amHandle + 0x16990)); + INSTALL_FAST_HOOK_DYNAMIC (Send3, (LPVOID)(amHandle + 0x16A00)); + INSTALL_FAST_HOOK_DYNAMIC (Send4, (LPVOID)(amHandle + 0x16A30)); + INSTALL_FAST_HOOK_DYNAMIC (CopyData, (LPVOID)(amHandle + 0x169D0)); break; } default: { diff --git a/src/patches/testmode.cpp b/src/patches/testmode.cpp index 46353ac..dede594 100644 --- a/src/patches/testmode.cpp +++ b/src/patches/testmode.cpp @@ -3,6 +3,7 @@ #include "patches.h" #include #include +#include extern GameVersion gameVersion; @@ -10,6 +11,31 @@ bool chsPatch = false; #define MIN(a, b) ((a)<(b)?(a):(b)) namespace patches::TestMode { +bool hookInstallFinished = false; +std::vector> hooks = {}; +std::thread *hookInstall; +std::mutex hooksMutex; +std::condition_variable hooksCV; + +// void +// AddHookInLoop (std::function installMethod) { +// // hooks.push (installMethod); +// hooksCV.notify_all (); +// } + +// void +// HookInstallLoop () { +// std::unique_lock hooksLock(hooksMutex); +// while (!hookInstallFinished) { +// while (!hooks.empty ()) { +// auto installMethod = hooks.front (); +// hooks.pop (); +// if (installMethod) installMethod (); +// } +// if (!hookInstallFinished) hooksCV.wait (hooksLock); +// } +// } + std::wstring mergeCondition (std::wstring original, std::wstring addition, std::wstring value) { size_t pos = original.find (L"/"); @@ -30,7 +56,18 @@ addConditionValue (pugi::xml_node *node, std::wstring key, std::wstring addition attr.set_value (mergeCondition(attr.value (), addition, value).c_str ()); } else node->append_attribute (key.c_str ()) = std::format(L"True/{}:{}", addition, value).c_str (); } - +class RegisteredHook : public Applicable { +public: + std::function registerInit; + RegisteredHook (const std::function &initMethod) { + this->registerInit = initMethod; + } + pugi::xml_node * + Apply (pugi::xml_node *doc, pugi::xml_node *node) override { + // AddHookInLoop (this->registerInit); + return node; + } +}; class RegisteredItem : public Applicable { public: std::wstring selectItem; @@ -49,7 +86,7 @@ public: LogMessage (LogLevel::ERROR, L"Failed to parse item: {}\n", this->selectItem); itemDoc.load_string (L""); } - if (success) this->registerInit (); + // if (success) AddHookInLoop (this->registerInit); std::wstring layoutName = L"layout"; if (layoutName == node->name ()) { temp = node->append_copy (itemDoc.first_child ().first_child ()); @@ -189,7 +226,7 @@ public: try { if (pugi::xml_node modifyNode = node->select_node (modifyQuery).node ()) { this->nodeModify (modifyNode); - this->registerInit (); + // AddHookInLoop (this->registerInit); } } catch ([[maybe_unused]] std::exception &e) { LogMessage (LogLevel::ERROR, L"Failed to find node by xpath: {}\n", this->query); } return nullptr; @@ -200,6 +237,7 @@ Menu *modManager = new RegisteredMenu (L"MOD MANAGER", L"ModManagerMenu"); // std::vector registeredItems = {}; std::vector registeredSingleItems = {}; std::vector registeredModifies = {}; +std::vector registeredHooks = {}; std::wstring moddedInitial = L""; std::wstring modded = L""; @@ -221,8 +259,10 @@ ReadXMLFileSwitcher (std::wstring &fileName) { return fileName; } -HOOK_DYNAMIC (void, TestModeSetMenuHook, u64 testModeLibrary, const wchar_t *lFileName) { +FAST_HOOK_DYNAMIC (void, TestModeSetMenuHook, u64 testModeLibrary, const wchar_t *lFileName) { + auto start = std::chrono::high_resolution_clock::now(); const auto originalFileName = std::wstring (lFileName); + LogMessage (LogLevel::DEBUG, L"Begin Loading {}", originalFileName); std::wstring fileName = originalFileName; if (fileName.ends_with (L"DeviceInitialize.xml") || fileName.ends_with (L"DeviceInitialize_asia.xml") || fileName.ends_with (L"DeviceInitialize_china.xml")) { @@ -280,6 +320,13 @@ HOOK_DYNAMIC (void, TestModeSetMenuHook, u64 testModeLibrary, const wchar_t *lFi LogMessage (LogLevel::DEBUG, "End Apply Modify Items"); } + if (!registeredHooks.empty ()) { + LogMessage (LogLevel::DEBUG, "Begin Apply Hooks"); + for (RegisteredHook *hook : registeredHooks) hook->Apply (&doc, &doc); + LogMessage (LogLevel::DEBUG, "End Apply Hooks"); + } + + // AddHookInLoop ([&](){ hookInstallFinished = true; }); [[maybe_unused]] auto _ = doc.save_file (modFileName.c_str ()); modded = modFileName; fileName = modFileName; @@ -288,8 +335,9 @@ HOOK_DYNAMIC (void, TestModeSetMenuHook, u64 testModeLibrary, const wchar_t *lFi } else fileName = modded; } - LogMessage (LogLevel::DEBUG, L"TestModeLibrary load: " + fileName); - originalTestModeSetMenuHook (testModeLibrary, fileName.c_str ()); + std::chrono::duration duration = std::chrono::high_resolution_clock::now() - start; + LogMessage (LogLevel::DEBUG, L"TestModeLibrary load: {}, spend: {:.2f}ms", fileName, duration.count () * 1000); + originalTestModeSetMenuHook.fastcall (testModeLibrary, fileName.c_str ()); } // HOOK_DYNAMIC (void, TestModeGetValueHook, u64 *reader, const wchar_t *lItemName, int *value) { @@ -462,7 +510,8 @@ Init () { CommonModify (); - INSTALL_HOOK_DYNAMIC (TestModeSetMenuHook, testModeSetMenu); + INSTALL_FAST_HOOK_DYNAMIC (TestModeSetMenuHook, testModeSetMenu); + for (auto method : hooks) method (); // INSTALL_HOOK_DYNAMIC (TestModeGetValueHook, testModeGetValue); // INSTALL_HOOK_DYNAMIC (TestModeSetValueHook, testModeSetValue); } @@ -508,25 +557,27 @@ CreateMenu (const std::wstring &menuName, const std::wstring &menuId) { void RegisterItem (const std::wstring &item, const std::function &initMethod, Menu *menu) { - LogMessage (LogLevel::DEBUG, L"Register Item: {}", item); - menu->RegisterItem (new RegisteredItem (item, initMethod)); + LogMessage (LogLevel::DEBUG, L"Register \nItem: {}", item); + hooks.push_back (initMethod); + menu->RegisterItem (new RegisteredItem (item, [](){})); } void RegisterItem (const std::wstring &item, const std::function &initMethod) { - LogMessage (LogLevel::DEBUG, L"Register Item: {}", item); - modManager->RegisterItem (new RegisteredItem (item, initMethod)); + LogMessage (LogLevel::DEBUG, L"Register \nItem: {}", item); + hooks.push_back (initMethod); + modManager->RegisterItem (new RegisteredItem (item, [](){})); } void RegisterItem (const std::wstring &item, Menu *menu) { - LogMessage (LogLevel::DEBUG, L"Register Item: {}", item); + LogMessage (LogLevel::DEBUG, L"Register \nItem: {}", item); menu->RegisterItem (new RegisteredItem (item, [](){})); } void RegisterItem (const std::wstring &item) { - LogMessage (LogLevel::DEBUG, L"Register Item: {}", item); + LogMessage (LogLevel::DEBUG, L"Register \nItem: {}", item); modManager->RegisterItem (new RegisteredItem (item, [](){})); } @@ -544,34 +595,43 @@ RegisterItem (Applicable *item) { void RegisterItemAfter (const std::wstring &query, const std::wstring &item, const std::function &initMethod) { - LogMessage (LogLevel::DEBUG, L"Register Query: {} Item: {}", query, item); - registeredSingleItems.push_back (new RegisteredSingleItem (query, new RegisteredItem (item, initMethod))); + LogMessage (LogLevel::DEBUG, L"Register \nQuery: {} \nItem: {}", query, item); + hooks.push_back (initMethod); + registeredSingleItems.push_back (new RegisteredSingleItem (query, new RegisteredItem (item, [](){}))); } void RegisterItemAfter (const std::wstring &query, const std::wstring &item) { - LogMessage (LogLevel::DEBUG, L"Register Query: {} Item: {}", query, item); + LogMessage (LogLevel::DEBUG, L"Register \nQuery: {} \nItem: {}", query, item); registeredSingleItems.push_back (new RegisteredSingleItem (query, new RegisteredItem (item, [](){}))); } void RegisterItemAfter (const std::wstring &query, Applicable *item) { - LogMessage (LogLevel::DEBUG, L"Register Query: {} Item: ptr", query); + LogMessage (LogLevel::DEBUG, L"Register \nQuery: {} \nItem: ptr", query); registeredSingleItems.push_back (new RegisteredSingleItem (query, item)); } void RegisterModify (const std::wstring &query, const std::function &nodeModify, const std::function &initMethod) { - LogMessage (LogLevel::DEBUG, L"Register Modify: {}", query); - registeredModifies.push_back (new RegisteredModify (query, nodeModify, initMethod)); + LogMessage (LogLevel::DEBUG, L"Register \nModify: {}", query); + hooks.push_back (initMethod); + registeredModifies.push_back (new RegisteredModify (query, nodeModify, [](){})); } void RegisterModify (const std::wstring &query, const std::function &nodeModify) { - LogMessage (LogLevel::DEBUG, L"Register Modify: {}", query); + LogMessage (LogLevel::DEBUG, L"Register \nModify: {}", query); registeredModifies.push_back (new RegisteredModify (query, nodeModify, [](){})); } +void +RegisterHook (const std::function &initMethod) { + LogMessage (LogLevel::DEBUG, L"Register Hook"); + hooks.push_back (initMethod); + // registeredHooks.push_back (new RegisteredHook (initMethod)); +} + void Append (const pugi::xml_node &node, const wchar_t *attr, const std::wstring &append) { pugi::xml_attribute attribute = node.attribute (attr); diff --git a/src/patches/versions/JPN39.cpp b/src/patches/versions/JPN39.cpp index fd4d1f4..6ee5022 100644 --- a/src/patches/versions/JPN39.cpp +++ b/src/patches/versions/JPN39.cpp @@ -5,18 +5,18 @@ namespace patches::JPN39 { int language = 0; -HOOK_DYNAMIC (char, AMFWTerminate, i64) { +FAST_HOOK_DYNAMIC (char, AMFWTerminate, i64) { LogMessage (LogLevel::HOOKS, "AMFWTerminate was called"); return 0; } -HOOK_DYNAMIC (i64, curl_easy_setopt, i64 a1, i64 a2, i64 a3, i64 a4, i64 a5) { +FAST_HOOK_DYNAMIC (i64, curl_easy_setopt, i64 a1, i64 a2, i64 a3, i64 a4, i64 a5) { LogMessage (LogLevel::HOOKS, "Garmc curl_easy_setopt was called"); - originalcurl_easy_setopt (a1, 64, 0, 0, 0); - originalcurl_easy_setopt (a1, 81, 0, 0, 0); - return originalcurl_easy_setopt (a1, a2, a3, a4, a5); + originalcurl_easy_setopt.call (a1, 64, 0, 0, 0); + originalcurl_easy_setopt.call (a1, 81, 0, 0, 0); + return originalcurl_easy_setopt.call (a1, a2, a3, a4, a5); } -HOOK_DYNAMIC (void, garmc_logger_log, i64 a1, int a2, void *a3, char a4) { +FAST_HOOK_DYNAMIC (void, garmc_logger_log, i64 a1, int a2, void *a3, char a4) { // remove garmc log return; } @@ -24,7 +24,7 @@ HOOK_DYNAMIC (void, garmc_logger_log, i64 a1, int a2, void *a3, char a4) { FUNCTION_PTR (i64, GetPlayDataManagerRef, ASLR (0x140024AC0), i64); i64 lua_State = 0; -HOOK (i64, luaL_newstate, PROC_ADDRESS ("lua51.dll", "luaL_newstate")) { return lua_State = originalluaL_newstate (); } +FAST_HOOK (i64, luaL_newstate, PROC_ADDRESS ("lua51.dll", "luaL_newstate")) { return lua_State = originalluaL_newstate.call (); } FUNCTION_PTR (void, lua_settop, PROC_ADDRESS ("lua51.dll", "lua_settop"), i64, i32); FUNCTION_PTR (void, lua_replace, PROC_ADDRESS ("lua51.dll", "lua_replace"), i64, i32); FUNCTION_PTR (void, lua_pushcclosure, PROC_ADDRESS ("lua51.dll", "lua_pushcclosure"), i64, i64, i32); @@ -50,12 +50,12 @@ lua_pushbool (const i64 a1, const bool val) { u64 appAccessor = 0; u64 componentAccessor = 0; -HOOK (i64, DeviceCheck, ASLR (0x140464FC0), i64 a1, i64 a2, i64 a3) { +FAST_HOOK (i64, DeviceCheck, ASLR (0x140464FC0), i64 a1, i64 a2, i64 a3) { LogMessage (LogLevel::HOOKS, "DeviceCheck was called"); TestMode::SetupAccessor (a3, RefTestModeMain); componentAccessor = a2; appAccessor = a3; - return originalDeviceCheck (a1, a2, a3); + return originalDeviceCheck.fastcall (a1, a2, a3); } i64 @@ -66,49 +66,49 @@ GetUserStatus () { return -1; } -HOOK (bool, IsSongRelease, ASLR (0x1403F4510), i64 a1, i64 a2, int a3) { +FAST_HOOK (bool, IsSongRelease, ASLR (0x1403F4510), i64 a1, i64 a2, int a3) { if (TestMode::ReadTestModeValue (L"ModUnlockSongs") == 1) return true; - return originalIsSongRelease (a1, a2, a3); + return originalIsSongRelease.fastcall (a1, a2, a3); } -HOOK (bool, IsSongReleasePlayer, ASLR (0x1403F45F0), i64 a1, u64 a2, i32 a3) { +FAST_HOOK (bool, IsSongReleasePlayer, ASLR (0x1403F45F0), i64 a1, u64 a2, i32 a3) { if (TestMode::ReadTestModeValue (L"ModUnlockSongs") == 2) return true; - return originalIsSongReleasePlayer (a1, a2, a3); + return originalIsSongReleasePlayer.fastcall (a1, a2, a3); } MID_HOOK (DifficultyPanelCrown, ASLR (0x1403F2A25), SafetyHookContext &ctx) { if (TestMode::ReadTestModeValue (L"ModUnlockSongs") != 1) return; ctx.r15 |= 1; } -HOOK (i64, AvailableMode_Collabo024, ASLR (0x1402DE710), i64 a1) { +FAST_HOOK (i64, AvailableMode_Collabo024, ASLR (0x1402DE710), i64 a1) { LogMessage (LogLevel::HOOKS, "AvailableMode_Collabo024 was called"); const int tournamentMode = TestMode::ReadTestModeValue (L"TournamentMode"); - if (tournamentMode == 1) return originalAvailableMode_Collabo024 (a1); + if (tournamentMode == 1) return originalAvailableMode_Collabo024.fastcall (a1); const int status = TestMode::ReadTestModeValue (L"ModModeCollabo024"); if (status == 1 && GetUserStatus () == 1) return lua_pushbool (a1, true); - return originalAvailableMode_Collabo024 (a1); + return originalAvailableMode_Collabo024.fastcall (a1); } -HOOK (i64, AvailableMode_Collabo025, ASLR (0x1402DE6B0), i64 a1) { +FAST_HOOK (i64, AvailableMode_Collabo025, ASLR (0x1402DE6B0), i64 a1) { LogMessage (LogLevel::HOOKS, "AvailableMode_Collabo025 was called"); const int tournamentMode = TestMode::ReadTestModeValue (L"TournamentMode"); - if (tournamentMode == 1) return originalAvailableMode_Collabo025 (a1); + if (tournamentMode == 1) return originalAvailableMode_Collabo025.fastcall (a1); const int status = TestMode::ReadTestModeValue (L"ModModeCollabo025"); if (status == 1 && GetUserStatus () == 1) return lua_pushbool (a1, true); - return originalAvailableMode_Collabo025 (a1); + return originalAvailableMode_Collabo025.fastcall (a1); } -HOOK (i64, AvailableMode_Collabo026, ASLR (0x1402DE670), i64 a1) { +FAST_HOOK (i64, AvailableMode_Collabo026, ASLR (0x1402DE670), i64 a1) { LogMessage (LogLevel::HOOKS, "AvailableMode_Collabo026 was called"); const int tournamentMode = TestMode::ReadTestModeValue (L"TournamentMode"); - if (tournamentMode == 1) return originalAvailableMode_Collabo026 (a1); + if (tournamentMode == 1) return originalAvailableMode_Collabo026.fastcall (a1); const int status = TestMode::ReadTestModeValue (L"ModModeCollabo026"); if (status == 1 && GetUserStatus () == 1) return lua_pushbool (a1, true); - return originalAvailableMode_Collabo026 (a1); + return originalAvailableMode_Collabo026.fastcall (a1); } -HOOK (i64, AvailableMode_AprilFool001, ASLR (0x1402DE5B0), i64 a1) { +FAST_HOOK (i64, AvailableMode_AprilFool001, ASLR (0x1402DE5B0), i64 a1) { LogMessage (LogLevel::HOOKS, "AvailableMode_AprilFool001 was called"); const int tournamentMode = TestMode::ReadTestModeValue (L"TournamentMode"); - if (tournamentMode == 1) return originalAvailableMode_AprilFool001 (a1); + if (tournamentMode == 1) return originalAvailableMode_AprilFool001.fastcall (a1); const int status = TestMode::ReadTestModeValue (L"ModModeAprilFool001"); if (status == 1) return lua_pushbool (a1, true); - return originalAvailableMode_AprilFool001 (a1); + return originalAvailableMode_AprilFool001.fastcall (a1); } i64 __fastcall lua_freeze_timer (const i64 a1) { LogMessage (LogLevel::HOOKS, "lua_freeze_timer was called"); @@ -183,40 +183,59 @@ SEND_RESULT_HOOK (SendResultData_Enso, ASLR (0x1401817B0)); SEND_RESULT_HOOK (SendResultData_AI, ASLR (0x1401755E0)); SEND_RESULT_HOOK (SendResultData_Collabo025_026, ASLR (0x140179A00)); SEND_RESULT_HOOK (SendResultData_AprilFool, ASLR (0x140177800)); - CHANGE_RESULT_SIZE_HOOK (ChangeResultDataSize_Enso, ASLR (0x140180074), rax); CHANGE_RESULT_SIZE_HOOK (ChangeResultDataSize_AI, ASLR (0x140173774), rax); CHANGE_RESULT_SIZE_HOOK (ChangeResultDataSize_Collabo025_026, ASLR (0x140178244), rax); CHANGE_RESULT_SIZE_HOOK (ChangeResultDataSize_AprilFool, ASLR (0x140176044), rax); - CHANGE_RESULT_INDEX_HOOK (ChangeResultDataIndex_Enso, ASLR (0x14018074B), rax, 0x34, 0x07); CHANGE_RESULT_INDEX_HOOK (ChangeResultDataIndex_AI, ASLR (0x140173EDD), r13, 0x24, 0x08); CHANGE_RESULT_INDEX_HOOK (ChangeResultDataIndex_Collabo025_026, ASLR (0x1401789AD), r13, 0x24, 0x08); CHANGE_RESULT_INDEX_HOOK (ChangeResultDataIndex_AprilFool, ASLR (0x140176716), rax, 0x34, 0x06); -HOOK (i64, GetLanguage, ASLR (0x140024AC0), i64 a1) { +FAST_HOOK (i64, GetLanguage, ASLR (0x140024AC0), i64 a1) { LogMessage (LogLevel::HOOKS, "GetLanguage was called"); - const auto result = originalGetLanguage (a1); + const auto result = originalGetLanguage.fastcall (a1); language = *reinterpret_cast (result); return result; } -HOOK (i64, GetRegionLanguage, ASLR (0x1401CE9B0), i64 a1) { +FAST_HOOK (i64, GetRegionLanguage, ASLR (0x1401CE9B0), i64 a1) { LogMessage (LogLevel::HOOKS, "GetRegionLanguage was called"); if (patches::TestMode::ReadTestModeValue (L"ModFixLanguage") == 1) { lua_settop (a1, 0); lua_pushstring (a1, languageStr (language)); return 1; - } else return originalGetRegionLanguage (a1); + } else return originalGetRegionLanguage.fastcall (a1); } +std::thread::id *LoadMovieThreadId = nullptr; FUNCTION_PTR (void **, std_string_assign, ASLR (0x1400209E0), void **, const void *, size_t); -HOOK (i64, GetCabinetLanguage, ASLR (0x14014DB80), u64 *a1, i64 a2) { +FAST_HOOK (i64, GetCabinetLanguage, ASLR (0x14014DB80), u64 *a1, i64 a2) { LogMessage (LogLevel::HOOKS, "GetCabinetLanguage was called"); - i64 result = originalGetCabinetLanguage (a1, a2); + i64 result = originalGetCabinetLanguage.fastcall (a1, a2); if (patches::TestMode::ReadTestModeValue (L"ModFixLanguage") == 1) { - std_string_assign ((void **)result, (const void*)languageStr (language), (language == 0 || language == 3) ? 3 : 5); + if (language == 2 && LoadMovieThreadId != nullptr && *LoadMovieThreadId == std::this_thread::get_id()) { + LogMessage (LogLevel::DEBUG, "Loading DemoMovie cn_tw, redirect to cn_cn"); + std_string_assign ((void **)result, (const void*)languageStr (4), 5); + } else { + std_string_assign ((void **)result, (const void*)languageStr (language), (language == 0 || language == 3) ? 3 : 5); + } } return result; } +FAST_HOOK (i64, LoadDemoMovie, ASLR (0x1404313F0), i64 a1, i64 a2, i64 a3) { + std::thread::id this_id = std::this_thread::get_id(); + LoadMovieThreadId = &this_id; + i64 result = originalLoadDemoMovie.fastcall (a1, a2, a3); + LoadMovieThreadId = nullptr; + return result; +} +std::string onpCn = "textures/onpu_cn/onp_all.nutexb"; +MID_HOOK (ChangeOnpFile, ASLR (0x140134D16), SafetyHookContext &ctx) { + if (language == 2 && patches::TestMode::ReadTestModeValue (L"ModFixLanguage") == 1) { + LogMessage (LogLevel::DEBUG, "Load onp_all_cn"); + ctx.rdx = (uintptr_t) onpCn.c_str (); + ctx.r8 = 0x1F; + } +} MID_HOOK (ChangeLanguageType, ASLR (0x1400B2016), SafetyHookContext &ctx) { LogMessage (LogLevel::HOOKS, "ChangeLanguageType was called"); @@ -240,6 +259,7 @@ get_bank_id (const std::string &bankName) { nus3bankMap[bankName] = nus3bankIdCounter; nus3bankIdCounter++; } + LogMessage (LogLevel::DEBUG, "LoadBank {} id={}", bankName, nus3bankMap[bankName]); return nus3bankMap[bankName]; } @@ -305,7 +325,7 @@ FixToneName (const std::string &bankName, std::string toneName, int voiceLang) { } size_t commonSize = 0; -HOOK (i64, PlaySoundMain, ASLR (0x1404C6DC0), i64 a1) { +FAST_HOOK (i64, PlaySoundMain, ASLR (0x1404C6DC0), i64 a1) { LogMessage (LogLevel::HOOKS, "PlaySoundMain was called"); int lang = TestMode::ReadTestModeValue (L"VoiceLanguageItem"); if (enableSwitchVoice && lang != 0) { @@ -315,10 +335,10 @@ HOOK (i64, PlaySoundMain, ASLR (0x1404C6DC0), i64 a1) { lua_replace (a1, -3); } } - return originalPlaySoundMain (a1); + return originalPlaySoundMain.fastcall (a1); } -HOOK (i64, PlaySoundMulti, ASLR (0x1404C6D60), i64 a1) { +FAST_HOOK (i64, PlaySoundMulti, ASLR (0x1404C6D60), i64 a1) { LogMessage (LogLevel::HOOKS, "PlaySoundMulti was called"); int lang = TestMode::ReadTestModeValue (L"VoiceLanguageItem"); if (enableSwitchVoice && lang != 0) { @@ -328,7 +348,7 @@ HOOK (i64, PlaySoundMulti, ASLR (0x1404C6D60), i64 a1) { lua_replace (a1, -3); } } - return originalPlaySoundMulti (a1); + return originalPlaySoundMulti.fastcall (a1); } FUNCTION_PTR (u64 *, append_chars_to_basic_string, ASLR (0x140028DA0), u64 *, const char *, size_t); @@ -341,50 +361,48 @@ FixToneNameEnso (u64 *Src, const std::string &bankName, int voiceLang) { return Src; } -HOOK (bool, PlaySoundEnso, ASLR (0x1404ED590), u64 *a1, u64 *a2, i64 a3) { +FAST_HOOK (bool, PlaySoundEnso, ASLR (0x1404ED590), u64 *a1, u64 *a2, i64 a3) { LogMessage (LogLevel::HOOKS, "PlaySoundEnso was called"); int lang = TestMode::ReadTestModeValue (L"VoiceLanguageItem"); if (enableSwitchVoice && lang != 0) { const std::string bankName = a1[3] > 0x10 ? std::string (*reinterpret_cast (a1)) : std::string (reinterpret_cast (a1)); if (bankName[0] == 'v') a2 = FixToneNameEnso (a2, bankName, lang); } - return originalPlaySoundEnso (a1, a2, a3); + return originalPlaySoundEnso.fastcall (a1, a2, a3); } -HOOK (bool, PlaySoundSpecial, ASLR (0x1404ED230), u64 *a1, u64 *a2) { +FAST_HOOK (bool, PlaySoundSpecial, ASLR (0x1404ED230), u64 *a1, u64 *a2) { LogMessage (LogLevel::HOOKS, "PlaySoundSpecial was called"); int lang = TestMode::ReadTestModeValue (L"VoiceLanguageItem"); if (enableSwitchVoice && lang != 0) { const std::string bankName = a1[3] > 0x10 ? std::string (*reinterpret_cast (a1)) : std::string (reinterpret_cast (a1)); if (bankName[0] == 'v') a2 = FixToneNameEnso (a2, bankName, lang); } - return originalPlaySoundSpecial (a1, a2); + return originalPlaySoundSpecial.fastcall (a1, a2); } int loaded_fail_count = 0; -HOOK (i64, LoadedBankAll, ASLR (0x1404C69F0), i64 a1) { +FAST_HOOK (char, LoadedBankAll, ASLR (0x1404EC2F0), u64 a1) { LogMessage (LogLevel::HOOKS, "LoadedBankAll was called"); - originalLoadedBankAll (a1); - const auto result = lua_toboolean (a1, -1); - lua_settop (a1, 0); + char result = originalLoadedBankAll.fastcall (a1); if (result) { loaded_fail_count = 0; - lua_pushboolean (a1, 1); - } else if (loaded_fail_count > 100) { + return 1; + } else if (loaded_fail_count > 60) { + LogMessage (LogLevel::WARN, "LoadBankAll Guardian!!!"); loaded_fail_count = 0; - lua_pushboolean (a1, 1); + return 1; } else { loaded_fail_count += 1; - lua_pushboolean (a1, 0); + return 0; } - return 1; } float soundRate = 1.0F; -HOOK (i32, SetMasterVolumeSpeaker, ASLR (0x140160330), i32 a1) { +FAST_HOOK (i32, SetMasterVolumeSpeaker, ASLR (0x140160330), i32 a1) { LogMessage (LogLevel::HOOKS, "SetMasterVolumeSpeaker was called"); patches::Audio::SetVolumeRate (a1 <= 100 ? 1.0f : a1 / 100.0f); - return originalSetMasterVolumeSpeaker (a1 > 100 ? 100 : a1); + return originalSetMasterVolumeSpeaker.fastcall (a1 > 100 ? 100 : a1); } // std::string *fontName = nullptr; @@ -407,45 +425,45 @@ MID_HOOK (AttractDemo, ASLR (0x14045A720), SafetyHookContext &ctx) { if (TestMode::ReadTestModeValue (L"AttractDemoItem") == 1) ctx.r14 = 0; } -HOOK (u64, EnsoGameManagerInitialize, ASLR (0x1400E2520), u64 a1, u64 a2, u64 a3) { +FAST_HOOK (u64, EnsoGameManagerInitialize, ASLR (0x1400E2520), u64 a1, u64 a2, u64 a3) { LogMessage (LogLevel::DEBUG, "Begin EnsoGameManagerInitialize"); - u64 result = originalEnsoGameManagerInitialize (a1, a2, a3); + u64 result = originalEnsoGameManagerInitialize.fastcall (a1, a2, a3); LogMessage (LogLevel::DEBUG, "End EnsoGameManagerInitialize result={}", result); return result; } -HOOK (u64, EnsoGameManagerLoading, ASLR (0x1400E2750), u64 a1, u64 a2, u64 a3) { +FAST_HOOK (u64, EnsoGameManagerLoading, ASLR (0x1400E2750), u64 a1, u64 a2, u64 a3) { LogMessage (LogLevel::DEBUG, "Begin EnsoGameManagerLoading"); - u64 result = originalEnsoGameManagerLoading (a1, a2, a3); + u64 result = originalEnsoGameManagerLoading.fastcall (a1, a2, a3); LogMessage (LogLevel::DEBUG, "End EnsoGameManagerLoading result={}", result); return result; } -HOOK (bool, EnsoGameManagerPreparing, ASLR (0x1400E2990), u64 a1, u64 a2, u64 a3) { +FAST_HOOK (bool, EnsoGameManagerPreparing, ASLR (0x1400E2990), u64 a1, u64 a2, u64 a3) { LogMessage (LogLevel::DEBUG, "Begin EnsoGameManagerPreparing"); - bool result = originalEnsoGameManagerPreparing (a1, a2, a3); // crashes here + bool result = originalEnsoGameManagerPreparing.fastcall (a1, a2, a3); // crashes here LogMessage (LogLevel::DEBUG, "End EnsoGameManagerPreparing result={}", result); return result; } -HOOK (u64, EnsoGraphicManagerPreparing, ASLR (0x1400F0AB0), u64 a1, u64 a2, u64 a3) { +FAST_HOOK (u64, EnsoGraphicManagerPreparing, ASLR (0x1400F0AB0), u64 a1, u64 a2, u64 a3) { LogMessage (LogLevel::DEBUG, "Begin EnsoGraphicManagerPreparing"); - u64 result = originalEnsoGraphicManagerPreparing (a1, a2, a3); + u64 result = originalEnsoGraphicManagerPreparing.fastcall (a1, a2, a3); LogMessage (LogLevel::DEBUG, "End EnsoGraphicManagerPreparing result={}", result); return result; } -HOOK (u64, EnsoGameManagerStart, ASLR (0x1400E2A10), u64 a1, u64 a2, u64 a3) { +FAST_HOOK (u64, EnsoGameManagerStart, ASLR (0x1400E2A10), u64 a1, u64 a2, u64 a3) { LogMessage (LogLevel::DEBUG, "Begin EnsoGameManagerStart"); - u64 result = originalEnsoGameManagerStart (a1, a2, a3); + u64 result = originalEnsoGameManagerStart.fastcall (a1, a2, a3); LogMessage (LogLevel::DEBUG, "End EnsoGameManagerStart result={}", result); return result; } -HOOK (u64, EnsoGameManagerChechEnsoEnd, ASLR (0x1400E2A10), u64 a1, u64 a2, u64 a3) { +FAST_HOOK (u64, EnsoGameManagerChechEnsoEnd, ASLR (0x1400E2A10), u64 a1, u64 a2, u64 a3) { LogMessage (LogLevel::DEBUG, "Begin EnsoGameManagerChechEnsoEnd"); - u64 result = originalEnsoGameManagerChechEnsoEnd (a1, a2, a3); + u64 result = originalEnsoGameManagerChechEnsoEnd.fastcall (a1, a2, a3); LogMessage (LogLevel::DEBUG, "End EnsoGameManagerChechEnsoEnd result={}", result); return result; } @@ -457,41 +475,45 @@ HOOK (u64, EnsoGameManagerChechEnsoEnd, ASLR (0x1400E2A10), u64 a1, u64 a2, u64 // return originalAcquireMostCompatibleDisplayMode (a1, a2, a3); // } -HOOK (char, SceneTestModeLoading, ASLR (0x1404793D0), u64 a1, u64 a2, u64 a3) { - LogMessage (LogLevel::DEBUG, "Begin SceneTestModeLoading"); - char result = originalSceneTestModeLoading (a1, a2, a3); - LogMessage (LogLevel::DEBUG, "End originalSceneTestModeLoading"); +FAST_HOOK (char, SceneTestModeLoading, ASLR (0x1404793D0), u64 a1, u64 a2, u64 a3) { + // LogMessage (LogLevel::DEBUG, "Begin SceneTestModeLoading"); + char result = originalSceneTestModeLoading.fastcall (a1, a2, a3); + // LogMessage (LogLevel::DEBUG, "End originalSceneTestModeLoading result={}", (int)result); TestMode::SetTestModeValue (L"EnableSwitchVoice", (int)enableSwitchVoice); - if (!enableSwitchVoice) TestMode::SetTestModeValue (L"VoiceLanguageItem", 0); - LogMessage (LogLevel::DEBUG, "End SceneTestModeLoading"); + // if (!enableSwitchVoice) TestMode::SetTestModeValue (L"VoiceLanguageItem", 0); + // LogMessage (LogLevel::DEBUG, "End SceneTestModeLoading"); return result; } -constexpr i32 datatableBufferSize = 1024 * 1024 * 12; -safetyhook::Allocation datatableBuffer1; -safetyhook::Allocation datatableBuffer2; -safetyhook::Allocation datatableBuffer3; -const std::vector datatableBuffer1Addresses = {0x1400ABE40, 0x1400ABEB1, 0x1400ABEDB, 0x1400ABF4C}; -const std::vector datatableBuffer2Addresses = {0x1400ABE2C, 0x1400ABF5B, 0x1400ABF8E}; -const std::vector datatableBuffer3Addresses = {0x1400ABF7F, 0x1400ABF95, 0x1400ABFBF}; -const std::vector memsetSizeAddresses = {0x1400ABE26, 0x1400ABE3A, 0x1400ABF79}; - -void -AllocateStaticBufferNear (void *target_address, const size_t size, safetyhook::Allocation *newBuffer) { - const auto allocator = safetyhook::Allocator::global (); - const std::vector desired_addresses = {static_cast (target_address)}; - auto allocation_result = allocator->allocate_near (desired_addresses, size); - if (allocation_result.has_value ()) *newBuffer = std::move (*allocation_result); +MID_HOOK (LogLoadTexture12, ASLR (0x14065BC8A), SafetyHookContext &ctx) { + char* src = (char*)(ctx.rsp + 0x2B0); + if (src != nullptr) { + std::string srcStr = std::string (src); + LogMessage (LogLevel::HOOKS, "LogLoadTexture12 src={}", srcStr); + } else LogMessage (LogLevel::HOOKS, "LogLoadTexture12 src=nullptr"); } +constexpr i32 datatableBufferSize = 1024 * 1024 * 12; +uint8_t *datatableBuffer[3] = { nullptr }; +std::vector datatable_patch = {}; +#define DATATABLE_PATCH_REGISTER(location, reg, value, skip) { datatable_patch.push_back(safetyhook::create_mid(location, [](SafetyHookContext &ctx) {ctx.reg = (uintptr_t)(value); ctx.rip = location + skip;})); } void -ReplaceLeaBufferAddress (const std::vector &bufferAddresses, void *newBufferAddress) { - for (const auto bufferAddress : bufferAddresses) { - const uintptr_t lea_instruction_dst = ASLR (bufferAddress) + 3; - const uintptr_t lea_instruction_end = ASLR (bufferAddress) + 7; - const intptr_t offset = reinterpret_cast (newBufferAddress) - lea_instruction_end; - WRITE_MEMORY (lea_instruction_dst, i32, static_cast (offset)); - } +ReplaceDatatableBufferAddresses () { + LogMessage (LogLevel::INFO, "Set Datatable Size to 12MB"); + for (int i = 0; i < 3; i ++) datatableBuffer[i] = (uint8_t *)malloc (datatableBufferSize); + DATATABLE_PATCH_REGISTER (ASLR (0x1400ABE26), r8, datatableBufferSize, 6); + DATATABLE_PATCH_REGISTER (ASLR (0x1400ABE3A), r8, datatableBufferSize, 6); + DATATABLE_PATCH_REGISTER (ASLR (0x1400ABF79), r8, datatableBufferSize, 6); + DATATABLE_PATCH_REGISTER (ASLR (0x1400ABE40), rcx, datatableBuffer[0], 7); + DATATABLE_PATCH_REGISTER (ASLR (0x1400ABEB1), rdi, datatableBuffer[0], 7); + DATATABLE_PATCH_REGISTER (ASLR (0x1400ABEDB), rdi, datatableBuffer[0], 7); + DATATABLE_PATCH_REGISTER (ASLR (0x1400ABF4C), rdi, datatableBuffer[0], 7); + DATATABLE_PATCH_REGISTER (ASLR (0x1400ABE2C), rcx, datatableBuffer[1], 7); + DATATABLE_PATCH_REGISTER (ASLR (0x1400ABF5B), rcx, datatableBuffer[1], 7); + DATATABLE_PATCH_REGISTER (ASLR (0x1400ABF8E), r8 , datatableBuffer[1], 7); + DATATABLE_PATCH_REGISTER (ASLR (0x1400ABF7F), rcx, datatableBuffer[2], 7); + DATATABLE_PATCH_REGISTER (ASLR (0x1400ABF95), rcx, datatableBuffer[2], 7); + DATATABLE_PATCH_REGISTER (ASLR (0x1400ABFBF), rdx, datatableBuffer[2], 7); } void @@ -526,16 +548,10 @@ Init () { } // Hook to get AppAccessor and ComponentAccessor - INSTALL_HOOK (DeviceCheck); - INSTALL_HOOK (luaL_newstate); - INSTALL_HOOK (EnsoGameManagerInitialize); - INSTALL_HOOK (EnsoGameManagerLoading); - INSTALL_HOOK (EnsoGameManagerPreparing); - INSTALL_HOOK (EnsoGraphicManagerPreparing); - INSTALL_HOOK (EnsoGameManagerStart); - INSTALL_HOOK (EnsoGameManagerChechEnsoEnd); + INSTALL_FAST_HOOK (DeviceCheck); + INSTALL_FAST_HOOK (luaL_newstate); + INSTALL_MID_HOOK (LogLoadTexture12); // INSTALL_HOOK (AcquireMostCompatibleDisplayMode); - INSTALL_HOOK (SceneTestModeLoading); // Apply common config patch WRITE_MEMORY (ASLR (0x140494533), i32, xRes); @@ -574,21 +590,22 @@ Init () { WRITE_MEMORY (ASLR (0x140CC05B0), char, ".\\Garmc\\ErrorLogData\\GarmcOErrorLogData.dat"); // Remove datatable size limit - { - for (auto address : memsetSizeAddresses) - WRITE_MEMORY (ASLR (address) + 2, i32, datatableBufferSize); + ReplaceDatatableBufferAddresses (); + // { + // for (auto address : memsetSizeAddresses) + // WRITE_MEMORY (ASLR (address) + 2, i32, datatableBufferSize); - auto bufferBase = MODULE_HANDLE - 0x03000000; - AllocateStaticBufferNear (bufferBase, datatableBufferSize, &datatableBuffer1); - bufferBase += datatableBufferSize; - AllocateStaticBufferNear (bufferBase, datatableBufferSize, &datatableBuffer2); - bufferBase += datatableBufferSize; - AllocateStaticBufferNear (bufferBase, datatableBufferSize, &datatableBuffer3); + // auto bufferBase = MODULE_HANDLE - 0x03000000; + // AllocateStaticBufferNear (bufferBase, datatableBufferSize, &datatableBuffer1); + // bufferBase += datatableBufferSize; + // AllocateStaticBufferNear (bufferBase, datatableBufferSize, &datatableBuffer2); + // bufferBase += datatableBufferSize; + // AllocateStaticBufferNear (bufferBase, datatableBufferSize, &datatableBuffer3); - ReplaceLeaBufferAddress (datatableBuffer1Addresses, datatableBuffer1.data ()); - ReplaceLeaBufferAddress (datatableBuffer2Addresses, datatableBuffer2.data ()); - ReplaceLeaBufferAddress (datatableBuffer3Addresses, datatableBuffer3.data ()); - } + // ReplaceLeaBufferAddress (datatableBuffer1Addresses, datatableBuffer1.data ()); + // ReplaceLeaBufferAddress (datatableBuffer2Addresses, datatableBuffer2.data ()); + // ReplaceLeaBufferAddress (datatableBuffer3Addresses, datatableBuffer3.data ()); + // } // Language TestMode::Menu *langPatchesMenu = TestMode::CreateMenu (L"LANGUAGE PATCHES", L"LanguagePatchesMenu"); @@ -597,9 +614,9 @@ Init () { L"", [&]() { - INSTALL_HOOK (GetLanguage); - INSTALL_HOOK (GetRegionLanguage); - INSTALL_HOOK (GetCabinetLanguage); + INSTALL_FAST_HOOK (GetLanguage); + INSTALL_FAST_HOOK (GetRegionLanguage); + INSTALL_FAST_HOOK (GetCabinetLanguage); }, langPatchesMenu ); TestMode::RegisterItem( @@ -609,13 +626,13 @@ Init () { ); TestMode::RegisterItemAfter( L"/root/menu[@id='OthersMenu']/layout[@type='Center']/select-item[@id='LanguageItem']", - L"", [&](){ - INSTALL_HOOK (PlaySoundMain); - INSTALL_HOOK (PlaySoundMulti); - INSTALL_HOOK (PlaySoundEnso); - INSTALL_HOOK (PlaySoundSpecial); + INSTALL_FAST_HOOK (PlaySoundMain); + INSTALL_FAST_HOOK (PlaySoundMulti); + INSTALL_FAST_HOOK (PlaySoundEnso); + INSTALL_FAST_HOOK (PlaySoundSpecial); } ); TestMode::RegisterItem(langResourceIndicator, langPatchesMenu); @@ -626,8 +643,8 @@ Init () { L"", [&]() { - INSTALL_HOOK (IsSongRelease); - INSTALL_HOOK (IsSongReleasePlayer); + INSTALL_FAST_HOOK (IsSongRelease); + INSTALL_FAST_HOOK (IsSongReleasePlayer); INSTALL_MID_HOOK (DifficultyPanelCrown); } ); @@ -642,22 +659,22 @@ Init () { TestMode::RegisterItem ( L"", - [&] { INSTALL_HOOK (AvailableMode_Collabo024); }//, modeUnlock + [&] { INSTALL_FAST_HOOK (AvailableMode_Collabo024); }//, modeUnlock ); TestMode::RegisterItem ( L"", - [&] { INSTALL_HOOK (AvailableMode_Collabo025); }//, modeUnlock + [&] { INSTALL_FAST_HOOK (AvailableMode_Collabo025); }//, modeUnlock ); TestMode::RegisterItem ( L"", - [&] { INSTALL_HOOK (AvailableMode_Collabo026); }//, modeUnlock + [&] { INSTALL_FAST_HOOK (AvailableMode_Collabo026); }//, modeUnlock ); TestMode::RegisterItem ( L"", - [&] { INSTALL_HOOK (AvailableMode_AprilFool001); }//, modeUnlock + [&] { INSTALL_FAST_HOOK (AvailableMode_AprilFool001); }//, modeUnlock ); // TestMode::RegisterItem (modeUnlock); // InstantResult @@ -665,15 +682,15 @@ Init () { L"", [&] { - INSTALL_HOOK (SceneResultInitialize_Enso); - INSTALL_HOOK (SceneResultInitialize_AI); - INSTALL_HOOK (SceneResultInitialize_Collabo025); - INSTALL_HOOK (SceneResultInitialize_Collabo026); - INSTALL_HOOK (SceneResultInitialize_AprilFool); - INSTALL_HOOK (SendResultData_Enso); - INSTALL_HOOK (SendResultData_AI); - INSTALL_HOOK (SendResultData_Collabo025_026); - INSTALL_HOOK (SendResultData_AprilFool); + INSTALL_FAST_HOOK (SceneResultInitialize_Enso); + INSTALL_FAST_HOOK (SceneResultInitialize_AI); + INSTALL_FAST_HOOK (SceneResultInitialize_Collabo025); + INSTALL_FAST_HOOK (SceneResultInitialize_Collabo026); + INSTALL_FAST_HOOK (SceneResultInitialize_AprilFool); + INSTALL_FAST_HOOK (SendResultData_Enso); + INSTALL_FAST_HOOK (SendResultData_AI); + INSTALL_FAST_HOOK (SendResultData_Collabo025_026); + INSTALL_FAST_HOOK (SendResultData_AprilFool); INSTALL_MID_HOOK (ChangeResultDataSize_Enso); INSTALL_MID_HOOK (ChangeResultDataSize_AI); INSTALL_MID_HOOK (ChangeResultDataSize_Collabo025_026); @@ -692,7 +709,7 @@ Init () { node.attribute (L"max").set_value (L"300"); node.attribute (L"delta").set_value (L"1"); }, - [&] () { INSTALL_HOOK (SetMasterVolumeSpeaker); } + [&] () { INSTALL_FAST_HOOK (SetMasterVolumeSpeaker); } ); TestMode::RegisterItemAfter( L"/root/menu[@id='OthersMenu']/layout[@type='Center']/select-item[@id='AttractMovieItem']", @@ -700,7 +717,15 @@ Init () { L"replace-text=\"0:ON, 1:OFF\" group=\"Setting\" id=\"AttractDemoItem\" max=\"1\" min=\"0\" default=\"0\"/>", [&](){ INSTALL_MID_HOOK (AttractDemo); } ); - + TestMode::RegisterHook([&](){ + INSTALL_FAST_HOOK (EnsoGameManagerInitialize); + INSTALL_FAST_HOOK (EnsoGameManagerLoading); + INSTALL_FAST_HOOK (EnsoGameManagerPreparing); + INSTALL_FAST_HOOK (EnsoGraphicManagerPreparing); + INSTALL_FAST_HOOK (EnsoGameManagerStart); + INSTALL_FAST_HOOK (EnsoGameManagerChechEnsoEnd); + INSTALL_FAST_HOOK (SceneTestModeLoading); + }); // for (size_t i=0; i < 40; i++) TestMode::RegisterItem(std::format (L"", i + 1)); // Instant Result @@ -712,6 +737,11 @@ Init () { // Use chs font/wordlist instead of cht if (chsPatch) { + WRITE_MEMORY (ASLR (0x140CD1E40), wchar_t, L"加載中\0"); + WRITE_MEMORY (ASLR (0x140CD1E28), wchar_t, L"加載中.\0"); + WRITE_MEMORY (ASLR (0x140CD1E68), wchar_t, L"加載中..\0"); + WRITE_MEMORY (ASLR (0x140CD1E50), wchar_t, L"加載中...\0"); + 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++) { @@ -719,38 +749,54 @@ Init () { if (std::filesystem::exists (std::string ("..\\..\\Data\\x64\\font\\") + fontToCheck[i])) continue; fontExistAll = false; } - if (fontExistAll) { + LogMessage (LogLevel::INFO, "Font all exist, using chs_patch font part!"); 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"); - WRITE_MEMORY (ASLR (0x140CD1E40), wchar_t, L"加載中\0"); - WRITE_MEMORY (ASLR (0x140CD1E28), wchar_t, L"加載中.\0"); - WRITE_MEMORY (ASLR (0x140CD1E68), wchar_t, L"加載中..\0"); - WRITE_MEMORY (ASLR (0x140CD1E50), wchar_t, L"加載中...\0"); INSTALL_MID_HOOK (ChangeLanguageType); // INSTALL_HOOK (SetupFontInfo); // INSTALL_HOOK (ReadFontInfoInt); } - LayeredFs::RegisterBefore ([=] (const std::string &originalFileName, const std::string ¤tFileName) -> std::string { - if (currentFileName.find ("\\lumen\\") == std::string::npos) return ""; - std::string fileName = currentFileName; - fileName = replace (fileName, "\\lumen\\", "\\lumen_cn\\"); - if (std::filesystem::exists (fileName)) return fileName; - return currentFileName; - }); + bool demoMovieExistAll = true; + const char *movieToCheck[]{"movie\\attractdemo_cn_cn.wmv", "sound\\attractdemo_cn_cn.nus3bank"}; + for (int i = 0; i < 2; i++) { + if (useLayeredfs && std::filesystem::exists (std::string ("..\\..\\Data_mods\\x64\\") + movieToCheck[i])) continue; + if (std::filesystem::exists (std::string ("..\\..\\Data\\x64\\") + movieToCheck[i])) continue; + demoMovieExistAll = false; + } + if (demoMovieExistAll) { + LogMessage (LogLevel::INFO, "Resource all exist, using chs_patch attractdemo part!"); + INSTALL_FAST_HOOK (LoadDemoMovie); + } + + bool onpCnExist = false; + if (useLayeredfs && std::filesystem::exists (std::string ("..\\..\\Data_mods\\x64\\textures\\onpu_cn\\onp_all.nutexb"))) onpCnExist = true; + if (std::filesystem::exists (std::string ("..\\..\\Data\\x64\\textures\\onpu_cn\\onp_all.nutexb"))) onpCnExist = true; + if (onpCnExist) { + LogMessage (LogLevel::INFO, "onpu_cn/onp_all exist, using chs_patch onp part!"); + INSTALL_MID_HOOK (ChangeOnpFile); + } + + // LayeredFs::RegisterBeforeA ([=] (const std::string &originalFileName, const std::string ¤tFileName) -> std::string { + // if (currentFileName.find ("\\lumen\\") == std::string::npos) return ""; + // std::string fileName = currentFileName; + // fileName = replace (fileName, "\\lumen\\", "\\lumen_cn\\"); + // if (std::filesystem::exists (fileName)) return fileName; + // return ""; + // }); } // Fix normal song play after passing through silent song INSTALL_MID_HOOK (GenNus3bankId); - INSTALL_HOOK (LoadedBankAll); + INSTALL_FAST_HOOK (LoadedBankAll); // Disable live check auto amHandle = reinterpret_cast (GetModuleHandle ("AMFrameWork.dll")); - INSTALL_HOOK_DYNAMIC (AMFWTerminate, reinterpret_cast (amHandle + 0x42DE0)); + INSTALL_FAST_HOOK_DYNAMIC (AMFWTerminate, reinterpret_cast (amHandle + 0x42DE0)); // Move various files to current directory WRITE_MEMORY (amHandle + 0x15252, u8, 0xEB); // CreditLogPathA @@ -764,7 +810,7 @@ Init () { // Redirect garmc requests auto garmcHandle = reinterpret_cast (GetModuleHandle ("garmc.dll")); - INSTALL_HOOK_DYNAMIC (curl_easy_setopt, reinterpret_cast (garmcHandle + 0x1FBBB0)); - INSTALL_HOOK_DYNAMIC (garmc_logger_log, reinterpret_cast (garmcHandle + 0x13AB70)); + INSTALL_FAST_HOOK_DYNAMIC (curl_easy_setopt, reinterpret_cast (garmcHandle + 0x1FBBB0)); + INSTALL_FAST_HOOK_DYNAMIC (garmc_logger_log, reinterpret_cast (garmcHandle + 0x13AB70)); } } // namespace patches::JPN39 diff --git a/src/pollasync.cpp b/src/pollasync.cpp index 964ac83..b9296eb 100644 --- a/src/pollasync.cpp +++ b/src/pollasync.cpp @@ -12,14 +12,15 @@ extern int exited; bool wndForeground = false; bool currentKeyboardState[0xFF] = { false }; -int keyboardCount[0xFF] = { 0 }; -int keyboardDiff[0xFF] = { 0 }; +uint8_t keyboardCount[0xFF] = { 0 }; +uint8_t keyboardDiff[0xFF] = { 0 }; +bool keyboardClean = false; bool currentControllerButtonsState[SDL_CONTROLLER_BUTTON_MAX] = { false }; -int controllerCount[SDL_CONTROLLER_BUTTON_MAX] = { 0 }; -int controllerDiff[SDL_CONTROLLER_BUTTON_MAX] = { 0 }; +uint8_t controllerCount[SDL_CONTROLLER_BUTTON_MAX] = { 0 }; +uint8_t controllerDiff[SDL_CONTROLLER_BUTTON_MAX] = { 0 }; char currentMouseWheelDirection = 0; -int mouseWheelCount[2] = { 0 }; -int mouseWheelDiff[2] = { 0 }; +uint8_t mouseWheelCount[2] = { 0 }; +uint8_t mouseWheelDiff[2] = { 0 }; int maxCount = 1; @@ -227,16 +228,20 @@ UpdatePoll (HWND windowHandle, bool useController) { currentMouseState.ScrolledUp = false; currentMouseState.ScrolledDown = false; - for (int i=0; i<255; i++) keyboardCount[i] -= (bool)keyboardDiff[i]; - for (int i=0; i 0) mouseWheelCount[i] -= (bool)mouseWheelDiff[i]; - std::fill_n (keyboardDiff, 0xFF, 0); - std::fill_n (controllerDiff, SDL_CONTROLLER_BUTTON_MAX, 0); - std::fill_n (mouseWheelDiff, 2, 0); + if (keyboardClean) { + keyboardClean = false; + for (int i=0; i<0xFF; i++) keyboardCount[i] -= (bool)keyboardDiff[i]; + memset (keyboardDiff, 0, 0XFF); + } + if (mouseWheelCount[0] > 0) mouseWheelCount[0] -= (bool)mouseWheelDiff[0]; + if (mouseWheelCount[1] > 0) mouseWheelCount[1] -= (bool)mouseWheelDiff[1]; + memset (mouseWheelDiff, 0, 2); // GetCursorPos (¤tMouseState.Position); // ScreenToClient (windowHandle, ¤tMouseState.Position); if (useController) { + for (int i=0; i 0) { - // mouseWheelCount[0] = MIN (mouseWheelCount[0] + event.wheel.y, maxCount); - // // mouseWheelCount[1] = 0; - // currentMouseState.ScrolledUp = true; - // } else if (event.wheel.y < 0) { - // mouseWheelCount[1] = MIN (mouseWheelCount[1] - event.wheel.y, maxCount); - // // mouseWheelCount[0] = 0; - // currentMouseState.ScrolledDown = true; - // } - // } - // break; case SDL_CONTROLLERBUTTONUP: // keyup will accepted even if you're not focus in this window currentControllerButtonsState[event.cbutton.button] = false; break; @@ -356,11 +347,12 @@ int maxKeyboardCount = 1; bool KeyboardIsTapped (const uint8_t keycode) { if (keyboardCount[keycode] > 0) { - if (maxKeyboardCount < keyboardCount[keycode]) { - maxKeyboardCount = keyboardCount[keycode]; - LogMessage (LogLevel::DEBUG, "MAX KEYBOARD COLLECTED {} {}", keycode, maxKeyboardCount); - } + // if (maxKeyboardCount < keyboardCount[keycode]) { + // maxKeyboardCount = keyboardCount[keycode]; + // LogMessage (LogLevel::DEBUG, "MAX KEYBOARD COLLECTED {} {}", keycode, maxKeyboardCount); + // } keyboardDiff[keycode] = 1; + keyboardClean = true; return true; } return false; } @@ -386,10 +378,10 @@ bool GetMouseScrollIsTapped (const Scroll scroll) { if (scroll == MOUSE_SCROLL_INVALID) return false; if (mouseWheelCount[scroll - 1] > 0) { - if (maxWheelCount < mouseWheelCount[scroll - 1]) { - maxWheelCount = mouseWheelCount[scroll - 1]; - LogMessage (LogLevel::DEBUG, "MAX WHEEL COLLECTED {} {}", (int)scroll, maxWheelCount); - } + // if (maxWheelCount < mouseWheelCount[scroll - 1]) { + // maxWheelCount = mouseWheelCount[scroll - 1]; + // LogMessage (LogLevel::DEBUG, "MAX WHEEL COLLECTED {} {}", (int)scroll, maxWheelCount); + // } mouseWheelDiff[scroll - 1] = 1; return true; } return false; @@ -404,10 +396,10 @@ int maxButtonCount = 1; bool ControllerButtonIsTapped (const SDL_GameControllerButton button) { if (controllerCount[button] > 0) { - if (maxButtonCount < controllerCount[button]) { - maxButtonCount = controllerCount[button]; - LogMessage (LogLevel::DEBUG, "MAX BUTTON COLLECTED {} {}", (int)button, maxButtonCount); - } + // if (maxButtonCount < controllerCount[button]) { + // maxButtonCount = controllerCount[button]; + // LogMessage (LogLevel::DEBUG, "MAX BUTTON COLLECTED {} {}", (int)button, maxButtonCount); + // } controllerDiff[button] = 1; return true; } return false;