From f338074851e56e363f10cc63e239f525b5ba4462 Mon Sep 17 00:00:00 2001 From: ptmaster Date: Thu, 12 Dec 2024 23:30:58 +0800 Subject: [PATCH 01/10] safetyhook + poll/bnusio optimize --- src/bnusio.cpp | 131 +++++++----- src/dllmain.cpp | 132 ++++++++---- src/helpers.h | 42 +++- src/logger.cpp | 15 +- src/patches/amauth.cpp | 10 +- src/patches/audio.cpp | 32 +-- src/patches/patches.h | 7 +- src/patches/scanner.cpp | 183 +++++++++-------- src/patches/testmode.cpp | 100 +++++++-- src/patches/versions/JPN39.cpp | 358 +++++++++++++++++++-------------- src/pollasync.cpp | 68 +++---- 11 files changed, 649 insertions(+), 429 deletions(-) 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; From e2ff0b4630aeabfa5ede98538d48c1bc0caf920e Mon Sep 17 00:00:00 2001 From: ptmaster Date: Sat, 14 Dec 2024 02:07:27 +0800 Subject: [PATCH 02/10] optimized boot speed(use safetyhook) & more optimized IO latency & update SDL3(fix conflict, thanks @asesidaa) --- CMakeLists.txt | 13 ++- src/bnusio.cpp | 26 +++--- src/patches/scanner.cpp | 56 +++++++++---- src/poll.cpp | 146 ++++++++++++++++++--------------- src/poll.h | 28 +++---- src/pollasync.cpp | 176 +++++++++++++++++++++++----------------- src/polldef.h | 44 +++++----- 7 files changed, 276 insertions(+), 213 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index abf3be6..2d2b41e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -94,15 +94,15 @@ FetchContent_Declare( set(SAFETYHOOK_FETCH_ZYDIS ON CACHE BOOL "" FORCE) FetchContent_MakeAvailable(safetyhook) -# Fetch SDL2 +# Fetch SDL3 FetchContent_Declare( - SDL2 - URL https://github.com/libsdl-org/SDL/releases/download/release-2.26.5/SDL2-2.26.5.tar.gz + SDL3 + URL https://github.com/libsdl-org/SDL/releases/download/preview-3.1.6/SDL3-3.1.6.tar.gz ) set(SDL_SHARED OFF CACHE BOOL "" FORCE) set(SDL_STATIC ON CACHE BOOL "" FORCE) set(SDL_TEST OFF CACHE BOOL "" FORCE) -FetchContent_MakeAvailable(SDL2) +FetchContent_MakeAvailable(SDL3) # Fetch xxHash FetchContent_Declare( @@ -137,7 +137,6 @@ set(SOURCES src/patches/audio.cpp src/patches/plugins.cpp src/patches/scanner.cpp - # src/patches/qr.cpp src/patches/layeredfs.cpp src/patches/testmode.cpp src/patches/timer.cpp @@ -157,7 +156,7 @@ set_target_properties(bnusio PROPERTIES PREFIX "") target_include_directories(bnusio PRIVATE src ${tomlc99_SOURCE_DIR} - ${SDL2_SOURCE_DIR}/include + ${SDL3_SOURCE_DIR}/include ${xxhash_SOURCE_DIR} ${zlib_SOURCE_DIR} ${libtomcrypt_SOURCE_DIR}/src/headers @@ -177,7 +176,7 @@ endif() # Link libraries target_link_libraries(bnusio PRIVATE tomlc99 - SDL2-static + SDL3-static xxhash zlibstatic libtomcrypt diff --git a/src/bnusio.cpp b/src/bnusio.cpp index 7593442..0f82475 100644 --- a/src/bnusio.cpp +++ b/src/bnusio.cpp @@ -35,7 +35,7 @@ Keybindings SERVICE = {.keycodes = {VK_F2}}; Keybindings DEBUG_UP = {.keycodes = {VK_UP}}; Keybindings DEBUG_DOWN = {.keycodes = {VK_DOWN}}; Keybindings DEBUG_ENTER = {.keycodes = {VK_RETURN}}; -Keybindings COIN_ADD = {.keycodes = {VK_RETURN}, .buttons = {SDL_CONTROLLER_BUTTON_START}}; +Keybindings COIN_ADD = {.keycodes = {VK_RETURN}, .buttons = {SDL_GAMEPAD_BUTTON_START}}; Keybindings CARD_INSERT_1 = {.keycodes = {'P'}}; Keybindings CARD_INSERT_2 = {}; Keybindings QR_DATA_READ = {.keycodes = {'Q'}}; @@ -52,15 +52,17 @@ 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 }; -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; +const int exitWait = 100; +int exited = 0; +bool testEnabled = false; +bool insert_coin = false; +bool insert_service = false; +u16 coin_count = 0; +u16 service_count = 0; +bool inited = false; +bool updateByCoin = false; +HWND windowHandle = nullptr; +bool usePoll = false; HKL currentLayout; namespace bnusio { @@ -293,9 +295,9 @@ UpdateLoop () { #endif std::vector buffer = {}; if (IsButtonTapped (COIN_ADD)) coin_count++; - if (IsButtonTapped (SERVICE) && !testEnabled) service_count++; + if (IsButtonTapped (SERVICE)) service_count++; if (IsButtonTapped (TEST)) testEnabled = !testEnabled; - if (IsButtonTapped (EXIT)) { + if (IsButtonTapped (EXIT)) { LogMessage (LogLevel::INFO, "Exit By Press Exit Button!"); exited += 1; testEnabled = 1; patches::Plugins::Exit (); } diff --git a/src/patches/scanner.cpp b/src/patches/scanner.cpp index 251d2c2..5a574b8 100644 --- a/src/patches/scanner.cpp +++ b/src/patches/scanner.cpp @@ -47,8 +47,10 @@ namespace Card { }; namespace Internal { + enum CardErrorCode { ReadError = -201, NotSupport = -400 }; + void - AgentInsertCard (uint8_t cardData[168], bool internalInvoke) { + InsertCard (uint8_t cardData[168], bool internalInvoke) { if (callbackTouch) { state = internalInvoke ? State::Disable : State::CopyWait; patches::Plugins::UpdateStatus (1, false); @@ -68,7 +70,16 @@ namespace Card { } void - AgentInsertCardPlugin (int32_t a1, int32_t a2, uint8_t *a3, uint64_t a4) { + InsertError (CardErrorCode errorCode) { + if (callbackTouch) { + state = State::CopyWait; + patches::Plugins::UpdateStatus (1, false); + callbackTouch (0, errorCode, cardData, touchData); + } + } + + void + AgentCallbackTouch (int32_t a1, int32_t a2, uint8_t *a3, uint64_t a4) { if (callbackTouch) { state = State::CopyWait; patches::Plugins::UpdateStatus (1, false); @@ -77,10 +88,11 @@ namespace Card { } void - AgentInsertCardOfficial (int32_t a1, int32_t a2, uint8_t *a3, uint64_t a4) { + AgentCallbackTouchOfficial (int32_t a1, int32_t a2, uint8_t *a3, uint64_t a4) { if (callbackTouch) { state = State::CopyWait; patches::Plugins::UpdateStatus (1, false); + LogMessage (LogLevel::DEBUG, "Official CallbackTouch a1={} a2={}", a1, a2); if (acceptInvalidCards && !a3[0]) { char AccessId[21] = "00000000000000000001"; uint8_t UID[8] = {a3[12], a3[14], a3[15], a3[16], 0x90, 0x00, 0x00, 0x00}; @@ -105,7 +117,7 @@ namespace Card { for (size_t i = 0; i < 32; i++) *(cardData + 0x2C + i) = i < chipId.length() ? chipId[i] : 0; for (size_t i = 0; i < 20; i++) *(cardData + 0x50 + i) = i < accessCode.length() ? accessCode[i] : 0; if (!internalInvoke) LogMessage (LogLevel::INFO, "[Card] Insert Card accessCode: \"{}\" chipId: \"{}\"", accessCode, chipId); - patches::Scanner::Card::Internal::AgentInsertCard (cardData, internalInvoke); + patches::Scanner::Card::Internal::InsertCard (cardData, internalInvoke); return true; } } @@ -143,7 +155,7 @@ namespace Card { 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); + patches::Plugins::WaitTouch (Internal::AgentCallbackTouch, a5); callbackTouch = callback; touchData = a5; return 1; @@ -161,7 +173,7 @@ namespace Card { patches::Plugins::UpdateStatus (1, true); callbackTouch = callback; touchData = a5; - return originalbngrw_ReqWaitTouchOfficial (a1, a2, a3, Internal::AgentInsertCardOfficial, a5); + return originalbngrw_ReqWaitTouchOfficial (a1, a2, a3, Internal::AgentCallbackTouchOfficial, a5); } bool @@ -176,10 +188,12 @@ namespace Card { } if (accessCode.length() == 0 || accessCode.length() > 20) { LogMessage (LogLevel::ERROR, "[Card] Not an effective accessCode: \"{}\"", accessCode); + patches::Scanner::Card::Internal::InsertError (Internal::CardErrorCode::NotSupport); return false; } if (chipId.length() > 32) { LogMessage (LogLevel::ERROR, "[Card] Not an effective chipId: \"{}\"", chipId); + patches::Scanner::Card::Internal::InsertError (Internal::CardErrorCode::NotSupport); return false; } return patches::Scanner::Card::Internal::Commit0 (accessCode, chipId, false); @@ -226,7 +240,7 @@ namespace Card { } } namespace Qr { - std::queue> scanQueue; + std::queue *> scanQueue; State state = State::Disable; long long lastScan; @@ -256,20 +270,26 @@ namespace Qr { patches::Plugins::UsingQr (); lastScan = std::chrono::duration_cast(std::chrono::system_clock::now ().time_since_epoch ()).count (); if (state == State::CopyWait && scanQueue.size () > 0) { - std::vector data = scanQueue.front (); - if ((int)data.size () > length) { - LogMessage (LogLevel::ERROR, "[QR] Not an effective code, length: {} require: {}", data.size (), length); + std::vector *data = scanQueue.front (); + if ((int)data->size () > length) { + LogMessage (LogLevel::ERROR, "[QR] Not an effective code, length: {} require: {}", data->size (), length); } std::stringstream hexStream; hexStream << std::hex << std::uppercase << std::setfill ('0') << std::setw (2); - for (size_t i = 0; i < data.size (); i++) hexStream << static_cast (data[i]) << " "; - LogMessage (LogLevel::INFO, "[QR] Read QRData size: {} data: {}\n", data.size (), hexStream.str ()); - memcpy (dest, data.data (), data.size () + 1); + for (size_t i = 0; i < data->size (); i++) hexStream << static_cast ((*data)[i]) << " "; + LogMessage (LogLevel::INFO, "[QR] Read QRData size: {} data: {}\n", data->size (), hexStream.str ()); + size_t finalCopySize = std::min (data->size () + 1, (size_t)length); + memcpy (dest, data->data (), finalCopySize); scanQueue.pop (); + delete data; if (scanQueue.size () == 0) state = State::Ready; - return data.size (); + return finalCopySize; } else if (state == State::Disable) { - while (!scanQueue.empty ()) scanQueue.pop (); + while (!scanQueue.empty ()) { + std::vector *data = scanQueue.front (); + delete data; + scanQueue.pop (); + } state = State::Ready; patches::Plugins::UpdateStatus (2, true); } @@ -290,10 +310,10 @@ namespace Qr { LogMessage (LogLevel::ERROR, "[QR] Not an effective code, length: 0"); return false; } - if (scanQueue.empty() || scanQueue.back() != buffer) { - std::vector scanData = {}; + if (scanQueue.empty() || *scanQueue.back() != buffer) { + std::vector *scanData = new std::vector (); for (uint8_t byte_data : buffer) - scanData.push_back (byte_data); + scanData->push_back (byte_data); scanQueue.push (scanData); } if (state == State::Ready) state = State::CopyWait; diff --git a/src/poll.cpp b/src/poll.cpp index cc2d778..15092c3 100644 --- a/src/poll.cpp +++ b/src/poll.cpp @@ -2,18 +2,20 @@ #ifndef ASYNC_IO #include "polldef.h" +#include extern bool jpLayout; + bool currentKeyboardState[0xFF]; bool lastKeyboardState[0xFF]; -bool currentControllerButtonsState[SDL_CONTROLLER_BUTTON_MAX]; -bool lastControllerButtonsState[SDL_CONTROLLER_BUTTON_MAX]; +bool currentControllerButtonsState[SDL_GAMEPAD_BUTTON_COUNT]; +bool lastControllerButtonsState[SDL_GAMEPAD_BUTTON_COUNT]; SDLAxisState currentControllerAxisState; SDLAxisState lastControllerAxisState; SDL_Window *window; -SDL_GameController *controllers[255]; +SDL_Gamepad *controllers[255]; void SetKeyboardButtons () { @@ -32,7 +34,7 @@ SetConfigValue (const toml_table_t *table, const char *key, Keybindings *key_bin memset (key_bind, 0, sizeof (*key_bind)); for (size_t i = 0; i < std::size (key_bind->buttons); i++) - key_bind->buttons[i] = SDL_CONTROLLER_BUTTON_INVALID; + key_bind->buttons[i] = SDL_GAMEPAD_BUTTON_INVALID; for (int idx = 0;; idx++) { const auto [ok, u] = toml_string_at (array, idx); @@ -54,7 +56,7 @@ SetConfigValue (const toml_table_t *table, const char *key, Keybindings *key_bin case button: { *usePoll = true; for (int i = 0; i < std::size (key_bind->buttons); i++) { - if (key_bind->buttons[i] == SDL_CONTROLLER_BUTTON_INVALID) { + if (key_bind->buttons[i] == SDL_GAMEPAD_BUTTON_INVALID) { key_bind->buttons[i] = value.button; break; } @@ -95,36 +97,51 @@ InitializePoll (const HWND windowHandle) { SDL_SetHint (SDL_HINT_JOYSTICK_HIDAPI_PS5, "1"); SDL_SetHint (SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1"); - if (SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS | SDL_INIT_VIDEO) != 0) { - if (SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS | SDL_INIT_VIDEO) == 0) { + if (SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMEPAD | SDL_INIT_EVENTS | SDL_INIT_VIDEO) != 0) { + if (SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD | SDL_INIT_EVENTS | SDL_INIT_VIDEO) == 0) { hasRumble = false; } else { LogMessage (LogLevel::ERROR, - std::string ("SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS | SDL_INIT_VIDEO): ") + std::string ("SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMEPAD | SDL_INIT_EVENTS | SDL_INIT_VIDEO): ") + SDL_GetError ()); return false; } } if (const auto configPath = std::filesystem::current_path () / "gamecontrollerdb.txt"; - SDL_GameControllerAddMappingsFromFile (configPath.string ().c_str ()) == -1) + SDL_AddGamepadMappingsFromFile (configPath.string ().c_str ()) == -1) LogMessage (LogLevel::ERROR, "Cannot read gamecontrollerdb.txt"); - SDL_GameControllerEventState (SDL_ENABLE); - SDL_JoystickEventState (SDL_ENABLE); + SDL_SetGamepadEventsEnabled (true); + SDL_SetJoystickEventsEnabled (true); - for (int i = 0; i < SDL_NumJoysticks (); i++) { - if (!SDL_IsGameController (i)) continue; + int numJoysticks = 0; + auto* joyStickIds = SDL_GetJoysticks(&numJoysticks); + if (joyStickIds == nullptr) { + LogMessage (LogLevel::ERROR, "Error getting joystick ids"); + exit(1); + } + for (auto id:joyStickIds) { + if (!SDL_IsGamepad (id)) continue; + SDL_Gamepad *controller = SDL_OpenGamepad (id); - SDL_GameController *controller = SDL_GameControllerOpen (i); if (!controller) { - LogMessage (LogLevel::WARN, std::string ("Could not open gamecontroller ") + SDL_GameControllerNameForIndex (i) + ": " + SDL_GetError ()); + LogMessage (LogLevel::WARN, std::string ("Could not open gamecontroller ") + SDL_GetGamepadNameForID (id) + ": " + SDL_GetError ()); continue; } - controllers[i] = controller; - } - window = SDL_CreateWindowFrom (windowHandle); - if (window == nullptr) LogMessage (LogLevel::ERROR, std::string ("SDL_CreateWindowFrom (windowHandle): ") + SDL_GetError ()); + LogMessage (LogLevel::DEBUG, "Init Controller connected!"); + controllers[id] = controller; + } + SDL_free (joyStickIds); + + SDL_PropertiesID props = SDL_CreateProperties(); + if(props == 0) { + LogMessage (LogLevel::ERROR, "Unable to create SDL_Properties"); + exit(1); + } + SDL_SetPointerProperty (props, SDL_PROP_WINDOW_CREATE_WIN32_HWND_POINTER, windowHandle); + window = SDL_CreateWindowWithProperties (props); + if (window == NULL) LogMessage (LogLevel::ERROR, std::string ("SDL_CreateWindowFrom (windowHandle): ") + SDL_GetError ()); atexit (DisposePoll); return hasRumble; @@ -149,71 +166,71 @@ UpdatePoll (const HWND windowHandle) { ScreenToClient (windowHandle, ¤tMouseState.Position); SDL_Event event; - SDL_GameController *controller; + SDL_Gamepad *controller; while (SDL_PollEvent (&event) != 0) { switch (event.type) { - case SDL_CONTROLLERDEVICEADDED: - if (!SDL_IsGameController (event.cdevice.which)) break; + case SDL_EVENT_GAMEPAD_ADDED: + if (!SDL_IsGamepad (event.cdevice.which)) break; - controller = SDL_GameControllerOpen (event.cdevice.which); + controller = SDL_OpenGamepad (event.cdevice.which); if (!controller) { - LogMessage (LogLevel::ERROR, std::string ("Could not open gamecontroller ") + SDL_GameControllerNameForIndex (event.cdevice.which) + LogMessage (LogLevel::ERROR, std::string ("Could not open gamecontroller ") + SDL_GetGamepadNameForID (event.cdevice.which) + ": " + SDL_GetError ()); continue; } controllers[event.cdevice.which] = controller; break; - case SDL_CONTROLLERDEVICEREMOVED: - if (!SDL_IsGameController (event.cdevice.which)) break; - SDL_GameControllerClose (controllers[event.cdevice.which]); + case SDL_EVENT_GAMEPAD_REMOVED: + if (!SDL_IsGamepad (event.cdevice.which)) break; + SDL_CloseGamepad (controllers[event.cdevice.which]); break; - case SDL_MOUSEWHEEL: + case SDL_EVENT_MOUSE_WHEEL: if (event.wheel.y > 0) currentMouseState.ScrolledUp = true; else if (event.wheel.y < 0) currentMouseState.ScrolledDown = true; break; - case SDL_CONTROLLERBUTTONUP: - case SDL_CONTROLLERBUTTONDOWN: currentControllerButtonsState[event.cbutton.button] = event.cbutton.state; break; - case SDL_CONTROLLERAXISMOTION: - if (event.caxis.value > 1) { - switch (event.caxis.axis) { - case SDL_CONTROLLER_AXIS_LEFTX: currentControllerAxisState.LeftRight = static_cast (event.caxis.value) / 32767; break; - case SDL_CONTROLLER_AXIS_LEFTY: currentControllerAxisState.LeftDown = static_cast (event.caxis.value) / 32767; break; - case SDL_CONTROLLER_AXIS_RIGHTX: currentControllerAxisState.RightRight = static_cast (event.caxis.value) / 32767; break; - case SDL_CONTROLLER_AXIS_RIGHTY: currentControllerAxisState.RightDown = static_cast (event.caxis.value) / 32767; break; - case SDL_CONTROLLER_AXIS_TRIGGERLEFT: currentControllerAxisState.LTriggerDown = static_cast (event.caxis.value) / 32767; break; - case SDL_CONTROLLER_AXIS_TRIGGERRIGHT: - currentControllerAxisState.RTriggerDown = static_cast (event.caxis.value) / 32767; + case SDL_EVENT_GAMEPAD_BUTTON_UP: + case SDL_EVENT_GAMEPAD_BUTTON_DOWN: currentControllerButtonsState[event.gbutton.button] = event.gbutton.down; break; + case SDL_EVENT_GAMEPAD_AXIS_MOTION: + if (event.gaxis.value > 1) { + switch (event.gaxis.axis) { + case SDL_GAMEPAD_AXIS_LEFTX: currentControllerAxisState.LeftRight = static_cast (event.gaxis.value) / 32767; break; + case SDL_GAMEPAD_AXIS_LEFTY: currentControllerAxisState.LeftDown = static_cast (event.gaxis.value) / 32767; break; + case SDL_GAMEPAD_AXIS_RIGHTX: currentControllerAxisState.RightRight = static_cast (event.gaxis.value) / 32767; break; + case SDL_GAMEPAD_AXIS_RIGHTY: currentControllerAxisState.RightDown = static_cast (event.gaxis.value) / 32767; break; + case SDL_GAMEPAD_AXIS_LEFT_TRIGGER: currentControllerAxisState.LTriggerDown = static_cast (event.gaxis.value) / 32767; break; + case SDL_GAMEPAD_AXIS_RIGHT_TRIGGER: + currentControllerAxisState.RTriggerDown = static_cast (event.gaxis.value) / 32767; break; default: break; } - } else if (event.caxis.value < -1) { - switch (event.caxis.axis) { - case SDL_CONTROLLER_AXIS_LEFTX: currentControllerAxisState.LeftLeft = static_cast (event.caxis.value) / -32768; break; - case SDL_CONTROLLER_AXIS_LEFTY: currentControllerAxisState.LeftUp = static_cast (event.caxis.value) / -32768; break; - case SDL_CONTROLLER_AXIS_RIGHTX: currentControllerAxisState.RightLeft = static_cast (event.caxis.value) / -32768; break; - case SDL_CONTROLLER_AXIS_RIGHTY: currentControllerAxisState.RightUp = static_cast (event.caxis.value) / -32768; break; + } else if (event.gaxis.value < -1) { + switch (event.gaxis.axis) { + case SDL_GAMEPAD_AXIS_LEFTX: currentControllerAxisState.LeftLeft = static_cast (event.gaxis.value) / -32768; break; + case SDL_GAMEPAD_AXIS_LEFTY: currentControllerAxisState.LeftUp = static_cast (event.gaxis.value) / -32768; break; + case SDL_GAMEPAD_AXIS_RIGHTX: currentControllerAxisState.RightLeft = static_cast (event.gaxis.value) / -32768; break; + case SDL_GAMEPAD_AXIS_RIGHTY: currentControllerAxisState.RightUp = static_cast (event.gaxis.value) / -32768; break; default: break; } } else { - switch (event.caxis.axis) { - case SDL_CONTROLLER_AXIS_LEFTX: + switch (event.gaxis.axis) { + case SDL_GAMEPAD_AXIS_LEFTX: currentControllerAxisState.LeftRight = 0; currentControllerAxisState.LeftLeft = 0; break; - case SDL_CONTROLLER_AXIS_LEFTY: + case SDL_GAMEPAD_AXIS_LEFTY: currentControllerAxisState.LeftDown = 0; currentControllerAxisState.LeftUp = 0; break; - case SDL_CONTROLLER_AXIS_RIGHTX: + case SDL_GAMEPAD_AXIS_RIGHTX: currentControllerAxisState.RightRight = 0; currentControllerAxisState.RightLeft = 0; break; - case SDL_CONTROLLER_AXIS_RIGHTY: + case SDL_GAMEPAD_AXIS_RIGHTY: currentControllerAxisState.RightDown = 0; currentControllerAxisState.RightUp = 0; break; - case SDL_CONTROLLER_AXIS_TRIGGERLEFT: currentControllerAxisState.LTriggerDown = 0; break; - case SDL_CONTROLLER_AXIS_TRIGGERRIGHT: currentControllerAxisState.RTriggerDown = 0; break; + case SDL_GAMEPAD_AXIS_LEFT_TRIGGER: currentControllerAxisState.LTriggerDown = 0; break; + case SDL_GAMEPAD_AXIS_RIGHT_TRIGGER: currentControllerAxisState.RTriggerDown = 0; break; default: break; } } @@ -272,7 +289,7 @@ GetInternalButtonState (const Keybindings &bindings) { if (KeyboardIsTapped (bindings.keycodes[i])) buttons.Tapped = true; } for (size_t i = 0; i < std::size (ConfigControllerButtons); i++) { - if (bindings.buttons[i] == SDL_CONTROLLER_BUTTON_INVALID) continue; + if (bindings.buttons[i] == SDL_GAMEPAD_BUTTON_INVALID) continue; if (ControllerButtonIsReleased (bindings.buttons[i])) buttons.Released = true; if (ControllerButtonIsDown (bindings.buttons[i])) buttons.Down = 1; if (ControllerButtonIsTapped (bindings.buttons[i])) buttons.Tapped = true; @@ -295,11 +312,12 @@ GetInternalButtonState (const Keybindings &bindings) { } void -SetRumble (const int left, const int right, const int length) { +SetRumble (int left, int right, int length) { for (auto &controller : controllers) { - if (!controller || !SDL_GameControllerHasRumble (controller)) continue; - - SDL_GameControllerRumble (controller, left, right, length); + const auto props = SDL_GetGamepadProperties(controller); + const bool hasRumble = SDL_GetBooleanProperty (props, SDL_PROP_GAMEPAD_CAP_RUMBLE_BOOLEAN, false); + if (!controller || !hasRumble) continue; + SDL_RumbleGamepad (controller, left, right, length); } } @@ -389,32 +407,32 @@ GetMouseScrollIsTapped (const Scroll scroll) { } bool -ControllerButtonIsDown (const SDL_GameControllerButton button) { +ControllerButtonIsDown (const SDL_GamepadButton button) { return currentControllerButtonsState[button]; } bool -ControllerButtonIsUp (const SDL_GameControllerButton button) { +ControllerButtonIsUp (const SDL_GamepadButton button) { return !ControllerButtonIsDown (button); } bool -ControllerButtonWasDown (const SDL_GameControllerButton button) { +ControllerButtonWasDown (const SDL_GamepadButton button) { return lastControllerButtonsState[button]; } bool -ControllerButtonWasUp (const SDL_GameControllerButton button) { +ControllerButtonWasUp (const SDL_GamepadButton button) { return !ControllerButtonWasDown (button); } bool -ControllerButtonIsTapped (const SDL_GameControllerButton button) { +ControllerButtonIsTapped (const SDL_GamepadButton button) { return ControllerButtonIsDown (button) && ControllerButtonWasUp (button); } bool -ControllerButtonIsReleased (const SDL_GameControllerButton button) { +ControllerButtonIsReleased (const SDL_GamepadButton button) { return ControllerButtonIsUp (button) && ControllerButtonWasDown (button); } diff --git a/src/poll.h b/src/poll.h index a184ed2..29e7d8c 100644 --- a/src/poll.h +++ b/src/poll.h @@ -1,5 +1,5 @@ #pragma once -#include +#include #include "helpers.h" #include "bnusio.h" @@ -41,7 +41,7 @@ enum Scroll { MOUSE_SCROLL_INVALID, MOUSE_SCROLL_UP, MOUSE_SCROLL_DOWN }; struct Keybindings { u8 keycodes[255]; - SDL_GameControllerButton buttons[255]; + SDL_GamepadButton buttons[255]; SDLAxis axis[255]; Scroll scroll[2]; }; @@ -52,7 +52,7 @@ struct ConfigValue { EnumType type; union { u8 keycode; - SDL_GameControllerButton button; + SDL_GamepadButton button; SDLAxis axis; Scroll scroll; }; @@ -72,16 +72,16 @@ void SetConfigValue (const toml_table_t *table, const char *key, Keybindings *ke InternalButtonState GetInternalButtonState (const Keybindings &bindings); void SetRumble (int left, int right, int length); -bool KeyboardIsDown (const uint8_t keycode); -bool KeyboardIsTapped (const uint8_t keycode); +bool KeyboardIsDown (uint8_t keycode); +bool KeyboardIsTapped (uint8_t keycode); bool GetMouseScrollUp (); bool GetMouseScrollDown (); -bool GetMouseScrollIsDown (const Scroll scroll); -bool GetMouseScrollIsTapped (const Scroll scroll); -bool ControllerButtonIsDown (const SDL_GameControllerButton button); -bool ControllerButtonIsTapped (const SDL_GameControllerButton button); -float ControllerAxisIsDown (const SDLAxis axis); -bool ControllerAxisIsTapped (const SDLAxis axis); +bool GetMouseScrollIsDown (Scroll scroll); +bool GetMouseScrollIsTapped (Scroll scroll); +bool ControllerButtonIsDown (SDL_GamepadButton button); +bool ControllerButtonIsTapped (SDL_GamepadButton button); +float ControllerAxisIsDown (SDLAxis axis); +bool ControllerAxisIsTapped (SDLAxis axis); bool IsButtonTapped (const Keybindings &bindings); float IsButtonDown (const Keybindings &bindings); @@ -99,9 +99,9 @@ void SetMousePosition (const POINT newPosition); bool GetWasMouseScrollUp (); bool GetWasMouseScrollDown (); bool GetMouseScrollIsReleased (const Scroll scroll); -bool ControllerButtonWasDown (const SDL_GameControllerButton button); -bool ControllerButtonWasUp (const SDL_GameControllerButton button); -bool ControllerButtonIsReleased (const SDL_GameControllerButton button); +bool ControllerButtonWasDown (const SDL_GamepadButton button); +bool ControllerButtonWasUp (const SDL_GamepadButton button); +bool ControllerButtonIsReleased (const SDL_GamepadButton button); bool ControllerAxisIsUp (const SDLAxis axis); float ControllerAxisWasDown (const SDLAxis axis); bool ControllerAxisWasUp (const SDLAxis axis); diff --git a/src/pollasync.cpp b/src/pollasync.cpp index b9296eb..361adad 100644 --- a/src/pollasync.cpp +++ b/src/pollasync.cpp @@ -2,22 +2,21 @@ #ifdef ASYNC_IO #include "polldef.h" +#define SDL_MAIN_NOIMPL +#include + extern bool jpLayout; extern int exited; -#ifndef MIN -#define MIN(a,b) ((a)<(b)?(a):(b)) -#endif - bool wndForeground = false; bool currentKeyboardState[0xFF] = { false }; uint8_t keyboardCount[0xFF] = { 0 }; uint8_t keyboardDiff[0xFF] = { 0 }; bool keyboardClean = false; -bool currentControllerButtonsState[SDL_CONTROLLER_BUTTON_MAX] = { false }; -uint8_t controllerCount[SDL_CONTROLLER_BUTTON_MAX] = { 0 }; -uint8_t controllerDiff[SDL_CONTROLLER_BUTTON_MAX] = { 0 }; +bool currentControllerButtonsState[SDL_GAMEPAD_BUTTON_COUNT] = { false }; +uint8_t controllerCount[SDL_GAMEPAD_BUTTON_COUNT] = { 0 }; +uint8_t controllerDiff[SDL_GAMEPAD_BUTTON_COUNT] = { 0 }; char currentMouseWheelDirection = 0; uint8_t mouseWheelCount[2] = { 0 }; uint8_t mouseWheelDiff[2] = { 0 }; @@ -27,7 +26,8 @@ int maxCount = 1; SDLAxisState currentControllerAxisState; SDL_Window *window; -SDL_GameController *controllers[255]; +SDL_Gamepad *controllers[255]; +bool flipped[255]; std::thread updatePollThread; @@ -48,7 +48,7 @@ SetConfigValue (const toml_table_t *table, const char *key, Keybindings *key_bin memset (key_bind, 0, sizeof (*key_bind)); for (size_t i = 0; i < std::size (key_bind->buttons); i++) - key_bind->buttons[i] = SDL_CONTROLLER_BUTTON_INVALID; + key_bind->buttons[i] = SDL_GAMEPAD_BUTTON_INVALID; for (int idx = 0;; idx++) { const auto [ok, u] = toml_string_at (array, idx); @@ -69,7 +69,7 @@ SetConfigValue (const toml_table_t *table, const char *key, Keybindings *key_bin case button: { *usePoll = true; for (int i = 0; i < std::size (key_bind->buttons); i++) { - if (key_bind->buttons[i] == SDL_CONTROLLER_BUTTON_INVALID) { + if (key_bind->buttons[i] == SDL_GAMEPAD_BUTTON_INVALID) { key_bind->buttons[i] = value.button; break; } @@ -108,9 +108,9 @@ LRESULT CALLBACK InputProc(int nCode, WPARAM wParam, LPARAM lParam) { if (nCode == HC_ACTION) { switch (wParam) { case WM_KEYDOWN: if (wndForeground) { - KBDLLHOOKSTRUCT* pKeyboard = reinterpret_cast(lParam); + auto* pKeyboard = reinterpret_cast(lParam); DWORD keyCode = pKeyboard->vkCode; - if (!currentKeyboardState[keyCode]) keyboardCount[keyCode] = MIN (keyboardCount[keyCode] + 1, maxCount); + if (!currentKeyboardState[keyCode]) keyboardCount[keyCode] = std::min (keyboardCount[keyCode] + 1, maxCount); currentKeyboardState[keyCode] = true; } break; // keyup will accepted even if you're not focus in this window @@ -123,13 +123,14 @@ LRESULT CALLBACK InputProc(int nCode, WPARAM wParam, LPARAM lParam) { MSLLHOOKSTRUCT *pMouseStruct = (MSLLHOOKSTRUCT*)lParam; int wheelDelta = GET_WHEEL_DELTA_WPARAM(pMouseStruct->mouseData); if (wheelDelta > 0) { - mouseWheelCount[0] = MIN (mouseWheelCount[0] + wheelDelta, maxCount); + mouseWheelCount[0] = std::min (mouseWheelCount[0] + wheelDelta, maxCount); currentMouseState.ScrolledUp = true; } else if (wheelDelta < 0) { - mouseWheelCount[1] = MIN (mouseWheelCount[1] - wheelDelta, maxCount); + mouseWheelCount[1] = std::min (mouseWheelCount[1] - wheelDelta, maxCount); currentMouseState.ScrolledDown = true; } } break; + default: break; } } return CallNextHookEx(keyboardHook, nCode, wParam, lParam); @@ -150,14 +151,12 @@ DisposeKeyboard () { if (mouseHook) UnhookWindowsHookEx(mouseHook); } -// void -// UpdateLoop () { -// LogMessage (LogLevel::DEBUG, "Enter Controller UpdateLoop"); - -// while (!exited) { - -// } -// } +void +CheckFlipped (uint32_t which, SDL_Gamepad *gamepad) { + if (SDL_GetGamepadButtonLabel(gamepad, SDL_GAMEPAD_BUTTON_SOUTH) == SDL_GAMEPAD_BUTTON_LABEL_B) { + flipped[which] = true; + } else flipped[which] = false; +} bool InitializePoll (HWND windowHandle) { @@ -171,44 +170,53 @@ InitializePoll (HWND windowHandle) { SDL_SetHint (SDL_HINT_JOYSTICK_HIDAPI_PS5, "1"); SDL_SetHint (SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1"); - if (SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS | SDL_INIT_VIDEO) != 0) { - if (SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS | SDL_INIT_VIDEO) == 0) { + if (!SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMEPAD | SDL_INIT_EVENTS | SDL_INIT_VIDEO)) { + if (SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD | SDL_INIT_EVENTS | SDL_INIT_VIDEO)) { hasRumble = false; } else { - LogMessage (LogLevel::ERROR, - std::string ("SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS | SDL_INIT_VIDEO): ") - + SDL_GetError ()); + LogMessage (LogLevel::ERROR, std::string ("SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMEPAD | SDL_INIT_EVENTS | SDL_INIT_VIDEO): ") + SDL_GetError ()); return false; } } auto configPath = std::filesystem::current_path () / "gamecontrollerdb.txt"; - if (SDL_GameControllerAddMappingsFromFile (configPath.string ().c_str ()) == -1) + if (SDL_AddGamepadMappingsFromFile (configPath.string ().c_str ()) == -1) LogMessage (LogLevel::ERROR, "Cannot read gamecontrollerdb.txt"); - SDL_GameControllerEventState (SDL_ENABLE); - SDL_JoystickEventState (SDL_ENABLE); + SDL_SetGamepadEventsEnabled (true); + SDL_SetJoystickEventsEnabled (true); - for (int i = 0; i < SDL_NumJoysticks (); i++) { - if (!SDL_IsGameController (i)) continue; + int numJoysticks = 0; + auto* joyStickIds = SDL_GetJoysticks(&numJoysticks); + if (joyStickIds == nullptr) { + LogMessage (LogLevel::ERROR, "Error getting joystick ids"); + exit(1); + } + for (int i = 0; i < numJoysticks; i++) { + auto id = joyStickIds[i]; + if (!SDL_IsGamepad (id)) continue; + SDL_Gamepad *controller = SDL_OpenGamepad (id); - SDL_GameController *controller = SDL_GameControllerOpen (i); if (!controller) { - LogMessage (LogLevel::WARN, std::string ("Could not open gamecontroller ") + SDL_GameControllerNameForIndex (i) + ": " + SDL_GetError ()); + LogMessage (LogLevel::WARN, std::string ("Could not open gamecontroller ") + SDL_GetGamepadNameForID (id) + ": " + SDL_GetError ()); continue; } LogMessage (LogLevel::DEBUG, "Init Controller connected!"); - controllers[i] = controller; + CheckFlipped (id, controller); + controllers[id] = controller; } + SDL_free (joyStickIds); - window = SDL_CreateWindowFrom (windowHandle); + SDL_PropertiesID props = SDL_CreateProperties(); + if(props == 0) { + LogMessage (LogLevel::ERROR, "Unable to create SDL_Properties"); + exit(1); + } + SDL_SetPointerProperty (props, SDL_PROP_WINDOW_CREATE_WIN32_HWND_POINTER, windowHandle); + window = SDL_CreateWindowWithProperties (props); if (window == NULL) LogMessage (LogLevel::ERROR, std::string ("SDL_CreateWindowFrom (windowHandle): ") + SDL_GetError ()); atexit (DisposePoll); - - // updatePollThread = std::thread (UpdateLoop); - // updatePollThread.detach (); - return hasRumble; } @@ -222,6 +230,18 @@ CheckForegroundWindow (HWND processWindow) { return wndForeground; } +uint8_t +CorrectButton (uint32_t which, uint8_t button) { + if (!flipped[which]) return button; + switch (button) { + case SDL_GAMEPAD_BUTTON_SOUTH: return SDL_GAMEPAD_BUTTON_EAST; + case SDL_GAMEPAD_BUTTON_EAST: return SDL_GAMEPAD_BUTTON_SOUTH; + case SDL_GAMEPAD_BUTTON_WEST: return SDL_GAMEPAD_BUTTON_NORTH; + case SDL_GAMEPAD_BUTTON_NORTH: return SDL_GAMEPAD_BUTTON_WEST; + default: return button; + } +} + void UpdatePoll (HWND windowHandle, bool useController) { if (!CheckForegroundWindow (windowHandle)) return; @@ -240,50 +260,52 @@ UpdatePoll (HWND windowHandle, bool useController) { // GetCursorPos (¤tMouseState.Position); // ScreenToClient (windowHandle, ¤tMouseState.Position); if (useController) { - for (int i=0; i 0 ? 32767.0f : -32768.0f); + case SDL_EVENT_GAMEPAD_AXIS_MOTION: + float sensorValue = event.gaxis.value == 0 ? 0 : event.gaxis.value / (event.gaxis.value > 0 ? 32767.0f : -32768.0f); if (wndForeground || sensorValue == 0) { - switch (event.caxis.axis) { - case SDL_CONTROLLER_AXIS_LEFTX: currentControllerAxisState.LeftRight = sensorValue; break; - case SDL_CONTROLLER_AXIS_LEFTY: currentControllerAxisState.LeftDown = sensorValue; break; - case SDL_CONTROLLER_AXIS_RIGHTX: currentControllerAxisState.RightRight = sensorValue; break; - case SDL_CONTROLLER_AXIS_RIGHTY: currentControllerAxisState.RightDown = sensorValue; break; - case SDL_CONTROLLER_AXIS_TRIGGERLEFT: currentControllerAxisState.LTriggerDown = sensorValue; break; - case SDL_CONTROLLER_AXIS_TRIGGERRIGHT: currentControllerAxisState.RTriggerDown = sensorValue; break; + switch (event.gaxis.axis) { + case SDL_GAMEPAD_AXIS_LEFTX: currentControllerAxisState.LeftRight = sensorValue; break; + case SDL_GAMEPAD_AXIS_LEFTY: currentControllerAxisState.LeftDown = sensorValue; break; + case SDL_GAMEPAD_AXIS_RIGHTX: currentControllerAxisState.RightRight = sensorValue; break; + case SDL_GAMEPAD_AXIS_RIGHTY: currentControllerAxisState.RightDown = sensorValue; break; + case SDL_GAMEPAD_AXIS_LEFT_TRIGGER: currentControllerAxisState.LTriggerDown = sensorValue; break; + case SDL_GAMEPAD_AXIS_RIGHT_TRIGGER: currentControllerAxisState.RTriggerDown = sensorValue; break; } } break; @@ -333,8 +355,10 @@ StringToConfigEnum (const char *value) { void SetRumble (int left, int right, int length) { for (auto &controller : controllers) { - if (!controller || !SDL_GameControllerHasRumble (controller)) continue; - SDL_GameControllerRumble (controller, left, right, length); + const auto props = SDL_GetGamepadProperties(controller); + const bool hasRumble = SDL_GetBooleanProperty (props, SDL_PROP_GAMEPAD_CAP_RUMBLE_BOOLEAN, false); + if (!controller || !hasRumble) continue; + SDL_RumbleGamepad (controller, left, right, length); } } @@ -388,13 +412,13 @@ GetMouseScrollIsTapped (const Scroll scroll) { } bool -ControllerButtonIsDown (const SDL_GameControllerButton button) { +ControllerButtonIsDown (const SDL_GamepadButton button) { return currentControllerButtonsState[button]; } int maxButtonCount = 1; bool -ControllerButtonIsTapped (const SDL_GameControllerButton button) { +ControllerButtonIsTapped (const SDL_GamepadButton button) { if (controllerCount[button] > 0) { // if (maxButtonCount < controllerCount[button]) { // maxButtonCount = controllerCount[button]; @@ -435,7 +459,7 @@ IsButtonTapped (const Keybindings &bindings) { if (KeyboardIsTapped (bindings.keycodes[i])) return true; } for (size_t i = 0; i < std::size (ConfigControllerButtons); i++) { - if (bindings.buttons[i] == SDL_CONTROLLER_BUTTON_INVALID) continue; + if (bindings.buttons[i] == SDL_GAMEPAD_BUTTON_INVALID) continue; if (ControllerButtonIsTapped (bindings.buttons[i])) return true; } for (size_t i = 0; i < std::size (ConfigControllerAXIS); i++) { @@ -457,7 +481,7 @@ IsButtonDown (const Keybindings &bindings) { if (KeyboardIsDown (bindings.keycodes[i])) return 1.0f; } for (size_t i = 0; i < std::size (ConfigControllerButtons); i++) { - if (bindings.buttons[i] == SDL_CONTROLLER_BUTTON_INVALID) continue; + if (bindings.buttons[i] == SDL_GAMEPAD_BUTTON_INVALID) continue; if (ControllerButtonIsDown (bindings.buttons[i])) return 1.0f; } for (size_t i = 0; i < std::size (ConfigControllerAXIS); i++) { diff --git a/src/polldef.h b/src/polldef.h index f1bbe4a..0b1ccce 100644 --- a/src/polldef.h +++ b/src/polldef.h @@ -254,29 +254,29 @@ KeyCodePair ConfigKeyboardButtons_JP[] = { struct { const char *string; - SDL_GameControllerButton button; + SDL_GamepadButton button; } ConfigControllerButtons[] = { - {"SDL_A", SDL_CONTROLLER_BUTTON_A}, - {"SDL_B", SDL_CONTROLLER_BUTTON_B}, - {"SDL_X", SDL_CONTROLLER_BUTTON_X}, - {"SDL_Y", SDL_CONTROLLER_BUTTON_Y}, - {"SDL_BACK", SDL_CONTROLLER_BUTTON_BACK}, - {"SDL_GUIDE", SDL_CONTROLLER_BUTTON_GUIDE}, - {"SDL_START", SDL_CONTROLLER_BUTTON_START}, - {"SDL_LSTICK_PRESS", SDL_CONTROLLER_BUTTON_LEFTSTICK}, - {"SDL_RSTICK_PRESS", SDL_CONTROLLER_BUTTON_RIGHTSTICK}, - {"SDL_LSHOULDER", SDL_CONTROLLER_BUTTON_LEFTSHOULDER}, - {"SDL_RSHOULDER", SDL_CONTROLLER_BUTTON_RIGHTSHOULDER}, - {"SDL_DPAD_UP", SDL_CONTROLLER_BUTTON_DPAD_UP}, - {"SDL_DPAD_DOWN", SDL_CONTROLLER_BUTTON_DPAD_DOWN}, - {"SDL_DPAD_LEFT", SDL_CONTROLLER_BUTTON_DPAD_LEFT}, - {"SDL_DPAD_RIGHT", SDL_CONTROLLER_BUTTON_DPAD_RIGHT}, - {"SDL_MISC", SDL_CONTROLLER_BUTTON_MISC1}, - {"SDL_PADDLE1", SDL_CONTROLLER_BUTTON_PADDLE1}, - {"SDL_PADDLE2", SDL_CONTROLLER_BUTTON_PADDLE2}, - {"SDL_PADDLE3", SDL_CONTROLLER_BUTTON_PADDLE3}, - {"SDL_PADDLE4", SDL_CONTROLLER_BUTTON_PADDLE4}, - {"SDL_TOUCHPAD", SDL_CONTROLLER_BUTTON_TOUCHPAD}, + {"SDL_A", SDL_GAMEPAD_BUTTON_SOUTH}, + {"SDL_B", SDL_GAMEPAD_BUTTON_EAST}, + {"SDL_X", SDL_GAMEPAD_BUTTON_WEST}, + {"SDL_Y", SDL_GAMEPAD_BUTTON_NORTH}, + {"SDL_BACK", SDL_GAMEPAD_BUTTON_BACK}, + {"SDL_GUIDE", SDL_GAMEPAD_BUTTON_GUIDE}, + {"SDL_START", SDL_GAMEPAD_BUTTON_START}, + {"SDL_LSTICK_PRESS", SDL_GAMEPAD_BUTTON_LEFT_STICK}, + {"SDL_RSTICK_PRESS", SDL_GAMEPAD_BUTTON_RIGHT_STICK}, + {"SDL_LSHOULDER", SDL_GAMEPAD_BUTTON_LEFT_SHOULDER}, + {"SDL_RSHOULDER", SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER}, + {"SDL_DPAD_UP", SDL_GAMEPAD_BUTTON_DPAD_UP}, + {"SDL_DPAD_DOWN", SDL_GAMEPAD_BUTTON_DPAD_DOWN}, + {"SDL_DPAD_LEFT", SDL_GAMEPAD_BUTTON_DPAD_LEFT}, + {"SDL_DPAD_RIGHT", SDL_GAMEPAD_BUTTON_DPAD_RIGHT}, + {"SDL_MISC", SDL_GAMEPAD_BUTTON_MISC1}, + {"SDL_PADDLE1", SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1}, + {"SDL_PADDLE2", SDL_GAMEPAD_BUTTON_LEFT_PADDLE1}, + {"SDL_PADDLE3", SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2}, + {"SDL_PADDLE4", SDL_GAMEPAD_BUTTON_LEFT_PADDLE2}, + {"SDL_TOUCHPAD", SDL_GAMEPAD_BUTTON_TOUCHPAD}, }; struct { From ffe2a299668d90ba5d055a07103af6ed5d11966d Mon Sep 17 00:00:00 2001 From: RyuMiyaX <52694802+ryumiyax@users.noreply.github.com> Date: Sat, 14 Dec 2024 04:21:31 +0800 Subject: [PATCH 03/10] Update build.yml --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 93a1f8a..310f033 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,7 +14,7 @@ jobs: - name: Configure CMake run: cmake -B build -S . -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=Release - name: Build - run: cmake --build build --config Release --target bnusio + run: cmake --build build --config Release --target bnusio --verbose --trace-expand - uses: actions/upload-artifact@v4 with: name: TaikoArcadeLoader From d95a5792ab1aea3ebd40d9578c53e71aff7bcc47 Mon Sep 17 00:00:00 2001 From: RyuMiyaX <52694802+ryumiyax@users.noreply.github.com> Date: Sat, 14 Dec 2024 04:24:50 +0800 Subject: [PATCH 04/10] Update build.yml --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 310f033..4f59a04 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,7 +14,7 @@ jobs: - name: Configure CMake run: cmake -B build -S . -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=Release - name: Build - run: cmake --build build --config Release --target bnusio --verbose --trace-expand + run: cmake --build build --config Release --target bnusio --verbose - uses: actions/upload-artifact@v4 with: name: TaikoArcadeLoader From 838ea50630e27a279dde802cfeb45f0d8c741424 Mon Sep 17 00:00:00 2001 From: ptmaster Date: Sat, 14 Dec 2024 04:40:10 +0800 Subject: [PATCH 05/10] Use git to fetch SDL --- CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2d2b41e..eaaad31 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -97,7 +97,9 @@ FetchContent_MakeAvailable(safetyhook) # Fetch SDL3 FetchContent_Declare( SDL3 - URL https://github.com/libsdl-org/SDL/releases/download/preview-3.1.6/SDL3-3.1.6.tar.gz + GIT_REPOSITORY https://github.com/libsdl-org/SDL.git + GIT_TAG 78cc5c173404488d80751af226d1eaf67033bcc4 # v3.1.6 + # URL https://github.com/libsdl-org/SDL/releases/download/preview-3.1.6/SDL3-3.1.6.tar.gz ) set(SDL_SHARED OFF CACHE BOOL "" FORCE) set(SDL_STATIC ON CACHE BOOL "" FORCE) From 5c1af3181065cbb768358932c5702faf55afdbec Mon Sep 17 00:00:00 2001 From: RyuMiyaX <52694802+ryumiyax@users.noreply.github.com> Date: Sat, 14 Dec 2024 04:55:54 +0800 Subject: [PATCH 06/10] Update build.yml --- .github/workflows/build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4f59a04..f3418a3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,6 +9,8 @@ jobs: - uses: actions/checkout@v4 with: submodules: recursive + - name: Add msbuild to PATH + uses: microsoft/setup-msbuild@v2 - name: Set up MSVC uses: ilammy/msvc-dev-cmd@v1 - name: Configure CMake From acb7a529728e60e4c18875f6b3357e935147c935 Mon Sep 17 00:00:00 2001 From: RyuMiyaX <52694802+ryumiyax@users.noreply.github.com> Date: Sat, 14 Dec 2024 05:04:06 +0800 Subject: [PATCH 07/10] Update build.yml --- .github/workflows/build.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f3418a3..29b2fbf 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,6 +11,9 @@ jobs: submodules: recursive - name: Add msbuild to PATH uses: microsoft/setup-msbuild@v2 + - name: Install Windows 10 SDK + run: | + choco install windows-sdk-10.0 --version=19041.0 - name: Set up MSVC uses: ilammy/msvc-dev-cmd@v1 - name: Configure CMake From d9e05d6affa92e6ea06fc48710e4ce0b0c6d6a8b Mon Sep 17 00:00:00 2001 From: RyuMiyaX <52694802+ryumiyax@users.noreply.github.com> Date: Sat, 14 Dec 2024 05:08:37 +0800 Subject: [PATCH 08/10] Update build.yml --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 29b2fbf..4a60703 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,7 +13,7 @@ jobs: uses: microsoft/setup-msbuild@v2 - name: Install Windows 10 SDK run: | - choco install windows-sdk-10.0 --version=19041.0 + choco install windows-sdk-10.0 - name: Set up MSVC uses: ilammy/msvc-dev-cmd@v1 - name: Configure CMake From 8ebe61c727c807b79f7674645d809260c0896568 Mon Sep 17 00:00:00 2001 From: RyuMiyaX <52694802+ryumiyax@users.noreply.github.com> Date: Sat, 14 Dec 2024 05:20:05 +0800 Subject: [PATCH 09/10] Update build.yml --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4a60703..79de069 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,7 +13,7 @@ jobs: uses: microsoft/setup-msbuild@v2 - name: Install Windows 10 SDK run: | - choco install windows-sdk-10.0 + choco install windows-sdk-10.1 - name: Set up MSVC uses: ilammy/msvc-dev-cmd@v1 - name: Configure CMake From a6066d31cfe3b8629f59ad7c076db22699185846 Mon Sep 17 00:00:00 2001 From: RyuMiyaX <52694802+ryumiyax@users.noreply.github.com> Date: Sat, 14 Dec 2024 05:33:57 +0800 Subject: [PATCH 10/10] Update build.yml --- .github/workflows/build.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 79de069..1cfcf43 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,15 +9,10 @@ jobs: - uses: actions/checkout@v4 with: submodules: recursive - - name: Add msbuild to PATH - uses: microsoft/setup-msbuild@v2 - - name: Install Windows 10 SDK - run: | - choco install windows-sdk-10.1 - name: Set up MSVC uses: ilammy/msvc-dev-cmd@v1 - name: Configure CMake - run: cmake -B build -S . -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=Release + run: cmake -B build -S . -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_SYSTEM_VERSION=10.0.26100.0 - name: Build run: cmake --build build --config Release --target bnusio --verbose - uses: actions/upload-artifact@v4