diff --git a/CMakeLists.txt b/CMakeLists.txt index 8ad4037..253385b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,8 @@ else() add_compile_options(-Wall -Wextra -Wpedantic) endif() -# Add project definitions +# Add project definitions (Add ASYNC_UPDATE/ASYNC_IO to enable new async feature [experimental]) +# add_definitions(-DNOMINMAX -DLTC_NO_PROTOTYPES -D_CRT_SECURE_NO_WARNINGS -DASYNC_UPDATE) add_definitions(-DNOMINMAX -DLTC_NO_PROTOTYPES -D_CRT_SECURE_NO_WARNINGS) # Include FetchContent module @@ -128,6 +129,7 @@ set(SOURCES src/helpers.cpp src/logger.cpp src/poll.cpp + src/pollasync.cpp src/bnusio.cpp src/patches/amauth.cpp src/patches/dxgi.cpp diff --git a/src/bnusio.cpp b/src/bnusio.cpp index 7fcef72..faee21d 100644 --- a/src/bnusio.cpp +++ b/src/bnusio.cpp @@ -17,6 +17,7 @@ extern bool autoIme; extern bool emulateUsio; extern bool emulateCardReader; extern bool acceptInvalidCards; +extern HWND hGameWnd; typedef i32 (*callbackAttach) (i32, i32, i32 *); typedef void (*callbackTouch) (i32, i32, u8[168], u64); @@ -263,6 +264,61 @@ 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")); +#ifndef ASYNC_UPDATE +void +Update () { +#else +std::thread pollThread; +std::thread updateThread; +std::mutex syncMtx; +std::condition_variable syncCV; + +void +UpdateLoop () { + LogMessage (LogLevel::WARN, "Using Async Update (experimental)!"); + std::unique_lock syncLock(syncMtx); + while (exited < 50) { + syncCV.wait (syncLock); +#endif + if (exited && ++exited >= 50) ExitProcess (0); + if (!inited) { + windowHandle = FindWindowA ("nuFoundation.Window", nullptr); + InitializePoll (windowHandle); + if (autoIme) { + currentLayout = GetKeyboardLayout (0); + auto engLayout = LoadKeyboardLayout (TEXT ("00000409"), KLF_ACTIVATE); + ActivateKeyboardLayout (engLayout, KLF_SETFORPROCESS); + } + + patches::Plugins::Init (); + inited = true; + } + +#ifndef ASYNC_UPDATE + UpdatePoll (windowHandle); +#endif + std::vector buffer = {}; + if (IsButtonTapped (COIN_ADD)) coin_count++; + if (IsButtonTapped (SERVICE) && !testEnabled) service_count++; + if (IsButtonTapped (TEST)) testEnabled = !testEnabled; + if (IsButtonTapped (EXIT)) { exited += 1; testEnabled = 1; patches::Plugins::Exit (); } + if (GameVersion::CHN00 == gameVersion) { + if (IsButtonTapped (CARD_INSERT_1)) patches::Scanner::Qr::CommitLogin (accessCode1); + if (IsButtonTapped (CARD_INSERT_2)) patches::Scanner::Qr::CommitLogin (accessCode2); + } else { + if (IsButtonTapped (CARD_INSERT_1)) patches::Scanner::Card::Commit (accessCode1, chipId1); + if (IsButtonTapped (CARD_INSERT_2)) patches::Scanner::Card::Commit (accessCode2, chipId2); + } + if (IsButtonTapped (QR_DATA_READ)) patches::Scanner::Qr::Commit (patches::Scanner::Qr::ReadQRData (buffer)); + if (IsButtonTapped (QR_IMAGE_READ)) patches::Scanner::Qr::Commit (patches::Scanner::Qr::ReadQRImage (buffer)); + + patches::Plugins::Update (); + patches::Scanner::Update (); +#ifdef ASYNC_UPDATE + } +#endif +} + void Init () { SetKeyboardButtons (); @@ -369,48 +425,26 @@ Init () { INSTALL_HOOK_DIRECT (bnusio_ResetCoin, bnusio_ResetCoin_Original); LogMessage (LogLevel::WARN, "USIO emulation disabled"); } +#ifdef ASYNC_UPDATE + else { + updateThread = std::thread (bnusio::UpdateLoop); + updateThread.detach (); + } +#endif } +#ifdef ASYNC_UPDATE void Update () { - if (exited && ++exited >= 50) ExitProcess (0); - if (!inited) { - windowHandle = FindWindowA ("nuFoundation.Window", nullptr); - InitializePoll (windowHandle); - if (autoIme) { - currentLayout = GetKeyboardLayout (0); - auto engLayout = LoadKeyboardLayout (TEXT ("00000409"), KLF_ACTIVATE); - ActivateKeyboardLayout (engLayout, KLF_SETFORPROCESS); - } - - patches::Plugins::Init (); - inited = true; - } - - UpdatePoll (windowHandle); - std::vector buffer = {}; - if (IsButtonTapped (COIN_ADD) && !testEnabled) coin_count++; - if (IsButtonTapped (SERVICE) && !testEnabled) service_count++; - if (IsButtonTapped (TEST)) testEnabled = !testEnabled; - if (IsButtonTapped (EXIT)) { exited += 1; testEnabled = 1; } - if (GameVersion::CHN00 == gameVersion) { - if (IsButtonTapped (CARD_INSERT_1)) patches::Scanner::Qr::CommitLogin (accessCode1); - if (IsButtonTapped (CARD_INSERT_2)) patches::Scanner::Qr::CommitLogin (accessCode2); - } else { - if (IsButtonTapped (CARD_INSERT_1)) patches::Scanner::Card::Commit (accessCode1, chipId1); - if (IsButtonTapped (CARD_INSERT_2)) patches::Scanner::Card::Commit (accessCode2, chipId2); - } - if (IsButtonTapped (QR_DATA_READ)) patches::Scanner::Qr::Commit (patches::Scanner::Qr::ReadQRData (buffer)); - if (IsButtonTapped (QR_IMAGE_READ)) patches::Scanner::Qr::Commit (patches::Scanner::Qr::ReadQRImage (buffer)); - - patches::Plugins::Update (); - patches::Scanner::Update (); + if (inited) UpdatePoll (windowHandle); + syncCV.notify_all (); } +#endif void Close () { if (autoIme) ActivateKeyboardLayout (currentLayout, KLF_SETFORPROCESS); - patches::Plugins::Exit (); + // patches::Plugins::Exit (); CleanupLogger (); } } // namespace bnusio diff --git a/src/bnusio.h b/src/bnusio.h index 2a9aa53..c964101 100644 --- a/src/bnusio.h +++ b/src/bnusio.h @@ -1,4 +1,5 @@ #pragma once +// #define ASYNC_UPDATE namespace bnusio { void Init (); void Update (); diff --git a/src/dllmain.cpp b/src/dllmain.cpp index 40fa66f..1642b67 100644 --- a/src/dllmain.cpp +++ b/src/dllmain.cpp @@ -149,6 +149,11 @@ DllMain (HMODULE module, const DWORD reason, LPVOID reserved) { InitializeLogger (GetLogLevel (logLevelStr), logToFile); LogMessage (LogLevel::INFO, "Loading config..."); + #ifdef ASYNC_IO + LogMessage (LogLevel::WARN, "Using Async IO (experimental)!"); + InitializeKeyboard (); + #endif + 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); @@ -223,7 +228,7 @@ DllMain (HMODULE module, const DWORD reason, LPVOID reserved) { GetPrivateProfileStringA ("card", "accessCode2", accessCode2, accessCode2, 21, ".\\card.ini"); GetPrivateProfileStringA ("card", "chipId2", chipId2, chipId2, 33, ".\\card.ini"); - LogMessage (LogLevel::WARN, "Loading patches, please wait..."); + LogMessage (LogLevel::INFO, "==== Loading patches, please wait..."); if (cursor) INSTALL_HOOK (ShowMouse); INSTALL_HOOK (ExitWindows); @@ -260,6 +265,8 @@ DllMain (HMODULE module, const DWORD reason, LPVOID reserved) { patches::AmAuth::Init (); patches::LayeredFs::Init (); patches::TestMode::Init (); + + LogMessage (LogLevel::INFO, "==== Finished Loading patches!"); } return true; } diff --git a/src/patches/layeredfs.cpp b/src/patches/layeredfs.cpp index 0dbd3ab..434dbbe 100644 --- a/src/patches/layeredfs.cpp +++ b/src/patches/layeredfs.cpp @@ -253,6 +253,7 @@ LayeredFsHandler (const std::string &originalFileName, const std::string ¤ HOOK (HANDLE, CreateFileAHook, PROC_ADDRESS ("kernel32.dll", "CreateFileA"), LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) { + bool changed = false; const auto originalFileName = std::string (lpFileName); std::string currentFileName = originalFileName; LogMessage (LogLevel::HOOKS, ("CreateFileA: " + originalFileName).c_str ()); @@ -260,23 +261,34 @@ HOOK (HANDLE, CreateFileAHook, PROC_ADDRESS ("kernel32.dll", "CreateFileA"), LPC if (!beforeHandlers.empty ()) { for (const auto handler : beforeHandlers) { std::string result = handler->handlerMethod (originalFileName, currentFileName); - if (result != "") currentFileName = result; + if (result != "") { + currentFileName = result; + changed = true; + } } } if (useLayeredFs) { const std::string result = LayeredFsHandler (originalFileName, currentFileName); - if (result != "") currentFileName = result; + if (result != "") { + currentFileName = result; + changed = true; + } } if (!afterHandlers.empty ()) { for (const auto handler : afterHandlers) { std::string result = handler->handlerMethod (originalFileName, currentFileName); - if (result != "") currentFileName = result; + if (result != "") { + currentFileName = result; + changed = true; + } } } - return originalCreateFileAHook (currentFileName.c_str (), dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, + LPCSTR pFinalFileName = changed ? currentFileName.c_str () : lpFileName; + if (changed) LogMessage (LogLevel::DEBUG, "Final Redirect: {}", currentFileName); + return originalCreateFileAHook (pFinalFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); } diff --git a/src/patches/versions/JPN39.cpp b/src/patches/versions/JPN39.cpp index 7489607..468beb3 100644 --- a/src/patches/versions/JPN39.cpp +++ b/src/patches/versions/JPN39.cpp @@ -394,48 +394,48 @@ 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) { -// LogMessage (LogLevel::DEBUG, "Begin EnsoGameManagerInitialize"); -// u64 result = originalEnsoGameManagerInitialize (a1, a2, a3); -// LogMessage (LogLevel::DEBUG, "End EnsoGameManagerInitialize result={}", result); -// return result; -// } +HOOK (u64, EnsoGameManagerInitialize, ASLR (0x1400E2520), u64 a1, u64 a2, u64 a3) { + LogMessage (LogLevel::DEBUG, "Begin EnsoGameManagerInitialize"); + u64 result = originalEnsoGameManagerInitialize (a1, a2, a3); + LogMessage (LogLevel::DEBUG, "End EnsoGameManagerInitialize result={}", result); + return result; +} -// HOOK (u64, EnsoGameManagerLoading, ASLR (0x1400E2750), u64 a1, u64 a2, u64 a3) { -// LogMessage (LogLevel::DEBUG, "Begin EnsoGameManagerLoading"); -// u64 result = originalEnsoGameManagerLoading (a1, a2, a3); -// LogMessage (LogLevel::DEBUG, "End EnsoGameManagerLoading result={}", result); -// return result; -// } +HOOK (u64, EnsoGameManagerLoading, ASLR (0x1400E2750), u64 a1, u64 a2, u64 a3) { + LogMessage (LogLevel::DEBUG, "Begin EnsoGameManagerLoading"); + u64 result = originalEnsoGameManagerLoading (a1, a2, a3); + LogMessage (LogLevel::DEBUG, "End EnsoGameManagerLoading result={}", result); + return result; +} -// HOOK (bool, EnsoGameManagerPreparing, ASLR (0x1400E2990), u64 a1) { -// LogMessage (LogLevel::DEBUG, "Begin EnsoGameManagerPreparing"); -// bool result = originalEnsoGameManagerPreparing (a1); // crashes here -// LogMessage (LogLevel::DEBUG, "End EnsoGameManagerPreparing result={}", result); -// return result; -// } +HOOK (bool, EnsoGameManagerPreparing, ASLR (0x1400E2990), u64 a1, u64 a2, u64 a3) { + LogMessage (LogLevel::DEBUG, "Begin EnsoGameManagerPreparing"); + bool result = originalEnsoGameManagerPreparing (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) { -// LogMessage (LogLevel::DEBUG, "Begin EnsoGraphicManagerPreparing"); -// u64 result = originalEnsoGraphicManagerPreparing (a1, a2, a3); -// LogMessage (LogLevel::DEBUG, "End EnsoGraphicManagerPreparing result={}", result); -// return result; -// } +HOOK (u64, EnsoGraphicManagerPreparing, ASLR (0x1400F0AB0), u64 a1, u64 a2, u64 a3) { + LogMessage (LogLevel::DEBUG, "Begin EnsoGraphicManagerPreparing"); + u64 result = originalEnsoGraphicManagerPreparing (a1, a2, a3); + LogMessage (LogLevel::DEBUG, "End EnsoGraphicManagerPreparing result={}", result); + return result; +} -// HOOK (u64, EnsoGameManagerStart, ASLR (0x1400E2A10), u64 a1, u64 a2, u64 a3) { -// LogMessage (LogLevel::DEBUG, "Begin EnsoGameManagerStart"); -// u64 result = originalEnsoGameManagerStart (a1, a2, a3); -// LogMessage (LogLevel::DEBUG, "End EnsoGameManagerStart result={}", result); -// return result; -// } +HOOK (u64, EnsoGameManagerStart, ASLR (0x1400E2A10), u64 a1, u64 a2, u64 a3) { + LogMessage (LogLevel::DEBUG, "Begin EnsoGameManagerStart"); + u64 result = originalEnsoGameManagerStart (a1, a2, a3); + LogMessage (LogLevel::DEBUG, "End EnsoGameManagerStart result={}", result); + return result; +} -// HOOK (u64, EnsoGameManagerChechEnsoEnd, ASLR (0x1400E2A10), u64 a1, u64 a2, u64 a3) { -// LogMessage (LogLevel::DEBUG, "Begin EnsoGameManagerChechEnsoEnd"); -// u64 result = originalEnsoGameManagerChechEnsoEnd (a1, a2, a3); -// LogMessage (LogLevel::DEBUG, "End EnsoGameManagerChechEnsoEnd result={}", result); -// return result; -// } +HOOK (u64, EnsoGameManagerChechEnsoEnd, ASLR (0x1400E2A10), u64 a1, u64 a2, u64 a3) { + LogMessage (LogLevel::DEBUG, "Begin EnsoGameManagerChechEnsoEnd"); + u64 result = originalEnsoGameManagerChechEnsoEnd (a1, a2, a3); + LogMessage (LogLevel::DEBUG, "End EnsoGameManagerChechEnsoEnd result={}", result); + return result; +} constexpr i32 datatableBufferSize = 1024 * 1024 * 12; safetyhook::Allocation datatableBuffer1; @@ -500,12 +500,12 @@ 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_HOOK (EnsoGameManagerInitialize); + INSTALL_HOOK (EnsoGameManagerLoading); + INSTALL_HOOK (EnsoGameManagerPreparing); + INSTALL_HOOK (EnsoGraphicManagerPreparing); + INSTALL_HOOK (EnsoGameManagerStart); + INSTALL_HOOK (EnsoGameManagerChechEnsoEnd); // Apply common config patch WRITE_MEMORY (ASLR (0x140494533), i32, xRes); diff --git a/src/poll.cpp b/src/poll.cpp index 64cbfb5..ae6887e 100644 --- a/src/poll.cpp +++ b/src/poll.cpp @@ -1,311 +1,9 @@ #include "poll.h" +#ifndef ASYNC_IO +#include "polldef.h" extern bool jpLayout; -struct KeyCodePair { - const char *string; - u8 keycode; -}; -size_t ConfigKeyboardButtonsCount = 0; -KeyCodePair *ConfigKeyboardButtons = nullptr; -KeyCodePair ConfigKeyboardButtons_US[] = { - // Reference:https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes - // Wayback Machine:https://web.archive.org/web/20231223135232/https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes - // Row 1 - {"ESCAPE", VK_ESCAPE}, - {"F1", VK_F1}, - {"F2", VK_F2}, - {"F3", VK_F3}, - {"F4", VK_F4}, - {"F5", VK_F5}, - {"F6", VK_F6}, - {"F7", VK_F7}, - {"F8", VK_F8}, - {"F9", VK_F9}, - {"F10", VK_F10}, - {"F11", VK_F11}, - {"F12", VK_F12}, - - // Row 2 - {"`", VK_OEM_3}, - {"1", '1'}, - {"2", '2'}, - {"3", '3'}, - {"4", '4'}, - {"5", '5'}, - {"6", '6'}, - {"7", '7'}, - {"8", '8'}, - {"9", '9'}, - {"0", '0'}, - {"-", VK_OEM_MINUS}, - {"=", VK_OEM_PLUS}, - {"BACKSPACE", VK_BACK}, - - // Row 3 - {"TAB", VK_TAB}, - {"Q", 'Q'}, - {"W", 'W'}, - {"E", 'E'}, - {"R", 'R'}, - {"T", 'T'}, - {"Y", 'Y'}, - {"U", 'U'}, - {"I", 'I'}, - {"O", 'O'}, - {"P", 'P'}, - {"[", VK_OEM_4}, - {"]", VK_OEM_6}, - {"BACKSLASH", VK_OEM_5}, - - // Row 4 - {"CAPS_LOCK", VK_CAPITAL}, - {"A", 'A'}, - {"S", 'S'}, - {"D", 'D'}, - {"F", 'F'}, - {"G", 'G'}, - {"H", 'H'}, - {"J", 'J'}, - {"K", 'K'}, - {"L", 'L'}, - {";", VK_OEM_1}, - {"'", VK_OEM_7}, - {"ENTER", VK_RETURN}, - - // Row 5 - {"SHIFT", VK_SHIFT}, - {"Z", 'Z'}, - {"X", 'X'}, - {"C", 'C'}, - {"V", 'V'}, - {"B", 'B'}, - {"N", 'N'}, - {"M", 'M'}, - {",", VK_OEM_COMMA}, - {".", VK_OEM_PERIOD}, - {"SLASH", VK_OEM_2}, - - // Row 6 - {"CONTROL", VK_CONTROL}, - {"L_WIN", VK_LWIN}, - {"ALT", VK_MENU}, - {"SPACE", VK_SPACE}, - {"R_WIN", VK_RWIN}, - {"MENU", VK_APPS}, - - // Other Keys - // PrtSc is more important when making snapshots, therefore comment it as reserved - //{"PRINT_SCREEN", VK_SNAPSHOT}, - {"SCROLL_LOCK", VK_SCROLL}, - {"PAUSE", VK_PAUSE}, - {"INSERT", VK_INSERT}, - {"DELETE", VK_DELETE}, - {"HOME", VK_HOME}, - {"END", VK_END}, - {"PAGE_UP", VK_PRIOR}, - {"PAGE_DOWN", VK_NEXT}, - - // Arrow Keys - {"UPARROW", VK_UP}, - {"LEFTARROW", VK_LEFT}, - {"DOWNARROW", VK_DOWN}, - {"RIGHTARROW", VK_RIGHT}, - - // NUMPAD Keys - {"NUM_LOCK", VK_NUMLOCK}, - {"DIVIDE", VK_DIVIDE}, - {"MULTIPLY", VK_MULTIPLY}, - {"SUBTRACT", VK_SUBTRACT}, - {"NUM7", VK_NUMPAD7}, - {"NUM8", VK_NUMPAD8}, - {"NUM9", VK_NUMPAD9}, - {"ADD", VK_ADD}, - {"NUM4", VK_NUMPAD4}, - {"NUM5", VK_NUMPAD5}, - {"NUM6", VK_NUMPAD6}, - {"NUM1", VK_NUMPAD1}, - {"NUM2", VK_NUMPAD2}, - {"NUM3", VK_NUMPAD3}, - {"NUM0", VK_NUMPAD0}, - {"DECIMAL", VK_DECIMAL}, -}; -KeyCodePair ConfigKeyboardButtons_JP[] = { - // Reference:https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes - // Wayback Machine:https://web.archive.org/web/20231223135232/https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes - // Row 1 - {"ESCAPE", VK_ESCAPE}, - {"F1", VK_F1}, - {"F2", VK_F2}, - {"F3", VK_F3}, - {"F4", VK_F4}, - {"F5", VK_F5}, - {"F6", VK_F6}, - {"F7", VK_F7}, - {"F8", VK_F8}, - {"F9", VK_F9}, - {"F10", VK_F10}, - {"F11", VK_F11}, - {"F12", VK_F12}, - - // Row 2 - {"1", '1'}, - {"2", '2'}, - {"3", '3'}, - {"4", '4'}, - {"5", '5'}, - {"6", '6'}, - {"7", '7'}, - {"8", '8'}, - {"9", '9'}, - {"0", '0'}, - {"-", VK_OEM_MINUS}, - {"^", VK_OEM_7}, - {"YEN", VK_OEM_5}, - {"BACKSPACE", VK_BACK}, - - // Row 3 - {"TAB", VK_TAB}, - {"Q", 'Q'}, - {"W", 'W'}, - {"E", 'E'}, - {"R", 'R'}, - {"T", 'T'}, - {"Y", 'Y'}, - {"U", 'U'}, - {"I", 'I'}, - {"O", 'O'}, - {"P", 'P'}, - {"@", VK_OEM_3}, - {"[", VK_OEM_4}, - - // Row 4 - {"CAPS_LOCK", VK_CAPITAL}, - {"A", 'A'}, - {"S", 'S'}, - {"D", 'D'}, - {"F", 'F'}, - {"G", 'G'}, - {"H", 'H'}, - {"J", 'J'}, - {"K", 'K'}, - {"L", 'L'}, - {";", VK_OEM_PLUS}, - {":", VK_OEM_1}, - {"]", VK_OEM_6}, - {"ENTER", VK_RETURN}, - - // Row 5 - {"SHIFT", VK_SHIFT}, - {"Z", 'Z'}, - {"X", 'X'}, - {"C", 'C'}, - {"V", 'V'}, - {"B", 'B'}, - {"N", 'N'}, - {"M", 'M'}, - {",", VK_OEM_COMMA}, - {".", VK_OEM_PERIOD}, - {"SLASH", VK_OEM_2}, - {"BACKSLASH", VK_OEM_102}, - - // Row 6 - {"CONTROL", VK_CONTROL}, - {"L_WIN", VK_LWIN}, - {"ALT", VK_MENU}, - {"SPACE", VK_SPACE}, - {"R_WIN", VK_RWIN}, - {"MENU", VK_APPS}, - - // Other Keys - // PrtSc is more important when making snapshots, therefore comment it as reserved - //{"PRINT_SCREEN", VK_SNAPSHOT}, - {"SCROLL_LOCK", VK_SCROLL}, - {"PAUSE", VK_PAUSE}, - {"INSERT", VK_INSERT}, - {"DELETE", VK_DELETE}, - {"HOME", VK_HOME}, - {"END", VK_END}, - {"PAGE_UP", VK_PRIOR}, - {"PAGE_DOWN", VK_NEXT}, - - // Arrow Keys - {"UPARROW", VK_UP}, - {"LEFTARROW", VK_LEFT}, - {"DOWNARROW", VK_DOWN}, - {"RIGHTARROW", VK_RIGHT}, - - // NUMPAD Keys - {"NUM_LOCK", VK_NUMLOCK}, - {"DIVIDE", VK_DIVIDE}, - {"MULTIPLY", VK_MULTIPLY}, - {"SUBTRACT", VK_SUBTRACT}, - {"NUM7", VK_NUMPAD7}, - {"NUM8", VK_NUMPAD8}, - {"NUM9", VK_NUMPAD9}, - {"ADD", VK_ADD}, - {"NUM4", VK_NUMPAD4}, - {"NUM5", VK_NUMPAD5}, - {"NUM6", VK_NUMPAD6}, - {"NUM1", VK_NUMPAD1}, - {"NUM2", VK_NUMPAD2}, - {"NUM3", VK_NUMPAD3}, - {"NUM0", VK_NUMPAD0}, - {"DECIMAL", VK_DECIMAL}, -}; - -struct { - const char *string; - SDL_GameControllerButton 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}, -}; - -struct { - const char *string; - SDLAxis axis; -} ConfigControllerAXIS[] = { - {"SDL_LSTICK_LEFT", SDL_AXIS_LEFT_LEFT}, {"SDL_LSTICK_UP", SDL_AXIS_LEFT_UP}, {"SDL_LSTICK_DOWN", SDL_AXIS_LEFT_DOWN}, - {"SDL_LSTICK_RIGHT", SDL_AXIS_LEFT_RIGHT}, {"SDL_RSTICK_LEFT", SDL_AXIS_RIGHT_LEFT}, {"SDL_RSTICK_UP", SDL_AXIS_RIGHT_UP}, - {"SDL_RSTICK_DOWN", SDL_AXIS_RIGHT_DOWN}, {"SDL_RSTICK_RIGHT", SDL_AXIS_RIGHT_RIGHT}, {"SDL_LTRIGGER", SDL_AXIS_LTRIGGER_DOWN}, - {"SDL_RTRIGGER", SDL_AXIS_RTRIGGER_DOWN}, -}; - -struct { - const char *string; - Scroll scroll; -} ConfigMouseScroll[] = { - {"SCROLL_UP", MOUSE_SCROLL_UP}, - {"SCROLL_DOWN", MOUSE_SCROLL_DOWN}, -}; - -struct MouseState { - POINT Position; - POINT RelativePosition; - bool ScrolledUp; - bool ScrolledDown; -} currentMouseState, lastMouseState; - bool currentKeyboardState[0xFF]; bool lastKeyboardState[0xFF]; @@ -784,3 +482,4 @@ float IsButtonDown (const Keybindings &bindings) { return GetInternalButtonState (bindings).Down; } +#endif \ No newline at end of file diff --git a/src/poll.h b/src/poll.h index 8487aaf..e16d1f3 100644 --- a/src/poll.h +++ b/src/poll.h @@ -1,6 +1,13 @@ #pragma once #include #include "helpers.h" +#include "bnusio.h" + +#ifdef ASYNC_UPDATE +#define ASYNC_IO +#endif + +// #define ASYNC_IO enum SDLAxis { SDL_AXIS_NULL, @@ -62,13 +69,25 @@ void UpdatePoll (HWND windowHandle); void DisposePoll (); void SetKeyboardButtons (); ConfigValue StringToConfigEnum (const char *value); -void SetConfigValue (const toml_table_t *table, const char *key, Keybindings *key_bind); +void SetConfigValue (const toml_table_t *table, const char *key, Keybindings *keybind); InternalButtonState GetInternalButtonState (const Keybindings &bindings); void SetRumble (int left, int right, int length); -bool KeyboardIsDown (u8 keycode); -bool KeyboardIsUp (u8 keycode); -bool KeyboardIsTapped (u8 keycode); +bool KeyboardIsDown (const uint8_t keycode); +bool KeyboardIsTapped (const 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 IsButtonTapped (const Keybindings &bindings); +float IsButtonDown (const Keybindings &bindings); + +#ifndef ASYNC_IO +bool KeyboardIsUp (const u8 keycode); bool KeyboardIsReleased (u8 keycode); bool KeyboardWasDown (u8 keycode); bool KeyboardWasUp (u8 keycode); @@ -76,26 +95,19 @@ POINT GetMousePosition (); POINT GetLastMousePosition (); POINT GetMouseRelativePosition (); POINT GetLastMouseRelativePosition (); -void SetMousePosition (POINT newPosition); -bool GetMouseScrollUp (); -bool GetMouseScrollDown (); +void SetMousePosition (const POINT newPosition); bool GetWasMouseScrollUp (); bool GetWasMouseScrollDown (); -bool GetMouseScrollIsReleased (Scroll scroll); -bool GetMouseScrollIsDown (Scroll scroll); -bool GetMouseScrollIsTapped (Scroll scroll); -bool ControllerButtonIsDown (SDL_GameControllerButton button); -bool ControllerButtonIsUp (SDL_GameControllerButton button); -bool ControllerButtonWasDown (SDL_GameControllerButton button); -bool ControllerButtonWasUp (SDL_GameControllerButton button); -bool ControllerButtonIsTapped (SDL_GameControllerButton button); -bool ControllerButtonIsReleased (SDL_GameControllerButton button); -float ControllerAxisIsDown (SDLAxis axis); -bool ControllerAxisIsUp (SDLAxis axis); -float ControllerAxisWasDown (SDLAxis axis); -bool ControllerAxisWasUp (SDLAxis axis); -bool ControllerAxisIsTapped (SDLAxis axis); -bool ControllerAxisIsReleased (SDLAxis axis); -bool IsButtonTapped (const Keybindings &bindings); +bool GetMouseScrollIsReleased (const Scroll scroll); +bool ControllerButtonWasDown (const SDL_GameControllerButton button); +bool ControllerButtonWasUp (const SDL_GameControllerButton button); +bool ControllerButtonIsReleased (const SDL_GameControllerButton button); +bool ControllerAxisIsUp (const SDLAxis axis); +float ControllerAxisWasDown (const SDLAxis axis); +bool ControllerAxisWasUp (const SDLAxis axis); +bool ControllerAxisIsReleased (const SDLAxis axis); bool IsButtonReleased (const Keybindings &bindings); -float IsButtonDown (const Keybindings &bindings); +#else +void InitializeKeyboard (); +void DisposeKeyboard (); +#endif \ No newline at end of file diff --git a/src/pollasync.cpp b/src/pollasync.cpp new file mode 100644 index 0000000..51608b8 --- /dev/null +++ b/src/pollasync.cpp @@ -0,0 +1,429 @@ +#include "poll.h" + +#ifdef ASYNC_IO +#include "polldef.h" +extern bool jpLayout; +extern int exited; + +bool wndForeground = false; + +bool currentKeyboardState[0xFF] = { false }; +int keyboardCount[0xFF] = { 0 }; +int keyboardDiff[0xFF] = { 0 }; +bool currentControllerButtonsState[SDL_CONTROLLER_BUTTON_MAX] = { false }; +int controllerCount[SDL_CONTROLLER_BUTTON_MAX] = { 0 }; +int controllerDiff[SDL_CONTROLLER_BUTTON_MAX] = { 0 }; +SDLAxisState currentControllerAxisState; + +SDL_Window *window; +SDL_GameController *controllers[255]; + +std::thread updatePollThread; + +void +SetKeyboardButtons () { + ConfigKeyboardButtonsCount = jpLayout ? std::size (ConfigKeyboardButtons_JP) : std::size (ConfigKeyboardButtons_US); + ConfigKeyboardButtons = static_cast (malloc (ConfigKeyboardButtonsCount * sizeof (KeyCodePair))); + memcpy (ConfigKeyboardButtons, jpLayout ? ConfigKeyboardButtons_JP : ConfigKeyboardButtons_US, ConfigKeyboardButtonsCount * sizeof (KeyCodePair)); +} + +void +SetConfigValue (const toml_table_t *table, const char *key, Keybindings *key_bind) { + const toml_array_t *array = toml_array_in (table, key); + if (!array) { + LogMessage (LogLevel::WARN, std::string (key) + ": Cannot find array"); + return; + } + + 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; + + for (int idx = 0;; idx++) { + const auto [ok, u] = toml_string_at (array, idx); + if (!ok) break; + const ConfigValue value = StringToConfigEnum (u.s); + free (u.s); + + switch (value.type) { + case keycode: { + for (int i = 0; i < std::size (key_bind->keycodes); i++) { + if (key_bind->keycodes[i] == 0) { + key_bind->keycodes[i] = value.keycode; + break; + } + } + break; + } + case button: { + for (int i = 0; i < std::size (key_bind->buttons); i++) { + if (key_bind->buttons[i] == SDL_CONTROLLER_BUTTON_INVALID) { + key_bind->buttons[i] = value.button; + break; + } + } + break; + } + case axis: { + for (int i = 0; i < std::size (key_bind->axis); i++) { + if (key_bind->axis[i] == 0) { + key_bind->axis[i] = value.axis; + break; + } + } + } + case scroll: { + for (int i = 0; i < std::size (key_bind->scroll); i++) { + if (key_bind->scroll[i] == 0) { + key_bind->scroll[i] = value.scroll; + break; + } + } + break; + } + default: break; + } + } +} + +// 钩子句柄 +HHOOK keyboardHook; + +// 钩子回调函数 +LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) { + if (nCode == HC_ACTION) { + KBDLLHOOKSTRUCT* pKeyboard = reinterpret_cast(lParam); + DWORD keyCode = pKeyboard->vkCode; + switch (wParam) { + case WM_KEYDOWN: if (wndForeground) { + if (!currentKeyboardState[keyCode]) keyboardCount[keyCode] ++; + currentKeyboardState[keyCode] = true; + } break; + // keyup will accepted even if you're not focus in this window + case WM_KEYUP: currentKeyboardState[keyCode] = false; break; + } + } + return CallNextHookEx(keyboardHook, nCode, wParam, lParam); +} + +void +InitializeKeyboard () { + keyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardProc, nullptr, 0); + if (keyboardHook == nullptr) LogMessage (LogLevel::ERROR, "Failed to install keyboard hook!\n"); + atexit (DisposeKeyboard); +} + +void +DisposeKeyboard () { + if (keyboardHook) UnhookWindowsHookEx(keyboardHook); +} + +void +UpdateLoop () { + LogMessage (LogLevel::DEBUG, "Enter Controller UpdateLoop"); + SDL_Event event; + SDL_GameController *controller; + while (!exited) { + while (SDL_WaitEvent (&event) != 0) { + switch (event.type) { + case SDL_CONTROLLERDEVICEADDED: + if (!SDL_IsGameController (event.cdevice.which)) break; + + controller = SDL_GameControllerOpen (event.cdevice.which); + if (!controller) { + LogMessage (LogLevel::ERROR, std::string ("Could not open gamecontroller ") + SDL_GameControllerNameForIndex (event.cdevice.which) + + ": " + SDL_GetError ()); + continue; + } + LogMessage (LogLevel::DEBUG, "Controller connected!"); + controllers[event.cdevice.which] = controller; + break; + case SDL_CONTROLLERDEVICEREMOVED: + LogMessage (LogLevel::DEBUG, "Controller removed!"); + if (!SDL_IsGameController (event.cdevice.which)) break; + SDL_GameControllerClose (controllers[event.cdevice.which]); + break; + case SDL_MOUSEWHEEL: + if (wndForeground) { + if (event.wheel.y > 0) currentMouseState.ScrolledUp = true; + else if (event.wheel.y < 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; + case SDL_CONTROLLERBUTTONDOWN: + if (wndForeground) { + if (!currentControllerButtonsState[event.cbutton.button]) controllerCount[event.cbutton.button]++; + currentControllerButtonsState[event.cbutton.button] = true; + } else LogMessage (LogLevel::WARN, "Controller button pressed but window not focused!"); + break; + case SDL_CONTROLLERAXISMOTION: + float sensorValue = event.caxis.value == 0 ? 0 : event.caxis.value / (event.caxis.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; + } + } + break; + } + } + } +} + +bool +InitializePoll (HWND windowHandle) { + LogMessage (LogLevel::DEBUG, "InitializePoll"); + bool hasRumble = true; + wndForeground = windowHandle == GetForegroundWindow (); + SDL_SetMainReady (); + + SDL_SetHint (SDL_HINT_JOYSTICK_HIDAPI_PS4, "1"); + SDL_SetHint (SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, "1"); + 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) { + 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 ()); + return false; + } + } + + auto configPath = std::filesystem::current_path () / "gamecontrollerdb.txt"; + if (SDL_GameControllerAddMappingsFromFile (configPath.string ().c_str ()) == -1) + LogMessage (LogLevel::ERROR, "Cannot read gamecontrollerdb.txt"); + SDL_GameControllerEventState (SDL_ENABLE); + SDL_JoystickEventState (SDL_ENABLE); + + for (int i = 0; i < SDL_NumJoysticks (); i++) { + if (!SDL_IsGameController (i)) continue; + + SDL_GameController *controller = SDL_GameControllerOpen (i); + if (!controller) { + LogMessage (LogLevel::WARN, std::string ("Could not open gamecontroller ") + SDL_GameControllerNameForIndex (i) + ": " + SDL_GetError ()); + continue; + } + + LogMessage (LogLevel::DEBUG, "Init Controller connected!"); + controllers[i] = controller; + } + + window = SDL_CreateWindowFrom (windowHandle); + if (window == NULL) LogMessage (LogLevel::ERROR, std::string ("SDL_CreateWindowFrom (windowHandle): ") + SDL_GetError ()); + + atexit (DisposePoll); + + updatePollThread = std::thread (UpdateLoop); + updatePollThread.detach (); + + return hasRumble; +} + +bool +CheckForegroundWindow (HWND processWindow) { + if (processWindow == nullptr) return false; + if (wndForeground ^ (processWindow == GetForegroundWindow ())) { + wndForeground = !wndForeground; + LogMessage (LogLevel::DEBUG, "window focus={}", wndForeground); + } + return wndForeground; +} + +void +UpdatePoll (HWND windowHandle) { + if (!CheckForegroundWindow (windowHandle)) return; + + // currentMouseState.ScrolledUp = false; + // currentMouseState.ScrolledDown = false; + for (int i=0; i<255; i++) keyboardCount[i] -= (bool)keyboardDiff[i]; + for (int i=0; i 0) { + if (maxKeyboardCount < keyboardCount[keycode]) { + maxKeyboardCount = keyboardCount[keycode]; + LogMessage (LogLevel::DEBUG, "MAX KEYBOARD COLLECTED {} {}", keycode, maxKeyboardCount); + } + keyboardDiff[keycode] = 1; + return true; + } return false; +} + +bool +GetMouseScrollUp () { + return currentMouseState.ScrolledUp; +} + +bool +GetMouseScrollDown () { + return currentMouseState.ScrolledDown; +} + +bool +GetMouseScrollIsDown (const Scroll scroll) { + return false; + // if (scroll == MOUSE_SCROLL_UP) return GetMouseScrollUp (); + // else return GetMouseScrollDown (); +} + +bool +GetMouseScrollIsTapped (const Scroll scroll) { + return false; + // if (scroll == MOUSE_SCROLL_UP) return GetMouseScrollUp () && !GetWasMouseScrollUp (); + // else return GetMouseScrollDown () && !GetWasMouseScrollDown (); +} + +bool +ControllerButtonIsDown (const SDL_GameControllerButton button) { + return currentControllerButtonsState[button]; +} + +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); + } + controllerDiff[button] = 1; + return true; + } return false; +} + +float +ControllerAxisIsDown (const SDLAxis axis) { + switch (axis) { + case SDL_AXIS_LEFT_LEFT: return currentControllerAxisState.LeftLeft; + case SDL_AXIS_LEFT_RIGHT: return currentControllerAxisState.LeftRight; + case SDL_AXIS_LEFT_UP: return currentControllerAxisState.LeftUp; + case SDL_AXIS_LEFT_DOWN: return currentControllerAxisState.LeftDown; + case SDL_AXIS_RIGHT_LEFT: return currentControllerAxisState.RightLeft; + case SDL_AXIS_RIGHT_RIGHT: return currentControllerAxisState.RightRight; + case SDL_AXIS_RIGHT_UP: return currentControllerAxisState.RightUp; + case SDL_AXIS_RIGHT_DOWN: return currentControllerAxisState.RightDown; + case SDL_AXIS_LTRIGGER_DOWN: return currentControllerAxisState.LTriggerDown; + case SDL_AXIS_RTRIGGER_DOWN: return currentControllerAxisState.RTriggerDown; + default: return false; + } +} + +bool +ControllerAxisIsTapped (const SDLAxis axis) { + return ControllerAxisIsDown (axis); +} + +bool +IsButtonTapped (const Keybindings &bindings) { + + for (size_t i = 0; i < ConfigKeyboardButtonsCount; i++) { + if (bindings.keycodes[i] == 0) continue; + 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 (ControllerButtonIsTapped (bindings.buttons[i])) return true; + } + for (size_t i = 0; i < std::size (ConfigControllerAXIS); i++) { + if (bindings.axis[i] == 0) continue; + if (float val = ControllerAxisIsTapped (bindings.axis[i]); val > 0) return true; + } + for (size_t i = 0; i < std::size (ConfigMouseScroll); i++) { + if (bindings.scroll[i] == 0) continue; + if (GetMouseScrollIsTapped (bindings.scroll[i])) return true; + } + return false; + // return GetInternalButtonState (bindings).Tapped; +} + +float +IsButtonDown (const Keybindings &bindings) { + for (size_t i = 0; i < ConfigKeyboardButtonsCount; i++) { + if (bindings.keycodes[i] == 0) continue; + 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 (ControllerButtonIsDown (bindings.buttons[i])) return 1.0f; + } + for (size_t i = 0; i < std::size (ConfigControllerAXIS); i++) { + if (bindings.axis[i] == 0) continue; + if (float val = ControllerAxisIsDown (bindings.axis[i]); val > 0) return val; + } + for (size_t i = 0; i < std::size (ConfigMouseScroll); i++) { + if (bindings.scroll[i] == 0) continue; + if (GetMouseScrollIsDown (bindings.scroll[i])) return 1.0f; + } + return 0.0f; + // return GetInternalButtonState (bindings).Down; +} +#endif \ No newline at end of file diff --git a/src/polldef.h b/src/polldef.h new file mode 100644 index 0000000..f1bbe4a --- /dev/null +++ b/src/polldef.h @@ -0,0 +1,305 @@ +#include "poll.h" + +struct KeyCodePair { + const char *string; + u8 keycode; +}; +size_t ConfigKeyboardButtonsCount = 0; +KeyCodePair *ConfigKeyboardButtons = nullptr; +KeyCodePair ConfigKeyboardButtons_US[] = { + // Reference:https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes + // Wayback Machine:https://web.archive.org/web/20231223135232/https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes + // Row 1 + {"ESCAPE", VK_ESCAPE}, + {"F1", VK_F1}, + {"F2", VK_F2}, + {"F3", VK_F3}, + {"F4", VK_F4}, + {"F5", VK_F5}, + {"F6", VK_F6}, + {"F7", VK_F7}, + {"F8", VK_F8}, + {"F9", VK_F9}, + {"F10", VK_F10}, + {"F11", VK_F11}, + {"F12", VK_F12}, + + // Row 2 + {"`", VK_OEM_3}, + {"1", '1'}, + {"2", '2'}, + {"3", '3'}, + {"4", '4'}, + {"5", '5'}, + {"6", '6'}, + {"7", '7'}, + {"8", '8'}, + {"9", '9'}, + {"0", '0'}, + {"-", VK_OEM_MINUS}, + {"=", VK_OEM_PLUS}, + {"BACKSPACE", VK_BACK}, + + // Row 3 + {"TAB", VK_TAB}, + {"Q", 'Q'}, + {"W", 'W'}, + {"E", 'E'}, + {"R", 'R'}, + {"T", 'T'}, + {"Y", 'Y'}, + {"U", 'U'}, + {"I", 'I'}, + {"O", 'O'}, + {"P", 'P'}, + {"[", VK_OEM_4}, + {"]", VK_OEM_6}, + {"BACKSLASH", VK_OEM_5}, + + // Row 4 + {"CAPS_LOCK", VK_CAPITAL}, + {"A", 'A'}, + {"S", 'S'}, + {"D", 'D'}, + {"F", 'F'}, + {"G", 'G'}, + {"H", 'H'}, + {"J", 'J'}, + {"K", 'K'}, + {"L", 'L'}, + {";", VK_OEM_1}, + {"'", VK_OEM_7}, + {"ENTER", VK_RETURN}, + + // Row 5 + {"SHIFT", VK_SHIFT}, + {"Z", 'Z'}, + {"X", 'X'}, + {"C", 'C'}, + {"V", 'V'}, + {"B", 'B'}, + {"N", 'N'}, + {"M", 'M'}, + {",", VK_OEM_COMMA}, + {".", VK_OEM_PERIOD}, + {"SLASH", VK_OEM_2}, + + // Row 6 + {"CONTROL", VK_CONTROL}, + {"L_WIN", VK_LWIN}, + {"ALT", VK_MENU}, + {"SPACE", VK_SPACE}, + {"R_WIN", VK_RWIN}, + {"MENU", VK_APPS}, + + // Other Keys + // PrtSc is more important when making snapshots, therefore comment it as reserved + //{"PRINT_SCREEN", VK_SNAPSHOT}, + {"SCROLL_LOCK", VK_SCROLL}, + {"PAUSE", VK_PAUSE}, + {"INSERT", VK_INSERT}, + {"DELETE", VK_DELETE}, + {"HOME", VK_HOME}, + {"END", VK_END}, + {"PAGE_UP", VK_PRIOR}, + {"PAGE_DOWN", VK_NEXT}, + + // Arrow Keys + {"UPARROW", VK_UP}, + {"LEFTARROW", VK_LEFT}, + {"DOWNARROW", VK_DOWN}, + {"RIGHTARROW", VK_RIGHT}, + + // NUMPAD Keys + {"NUM_LOCK", VK_NUMLOCK}, + {"DIVIDE", VK_DIVIDE}, + {"MULTIPLY", VK_MULTIPLY}, + {"SUBTRACT", VK_SUBTRACT}, + {"NUM7", VK_NUMPAD7}, + {"NUM8", VK_NUMPAD8}, + {"NUM9", VK_NUMPAD9}, + {"ADD", VK_ADD}, + {"NUM4", VK_NUMPAD4}, + {"NUM5", VK_NUMPAD5}, + {"NUM6", VK_NUMPAD6}, + {"NUM1", VK_NUMPAD1}, + {"NUM2", VK_NUMPAD2}, + {"NUM3", VK_NUMPAD3}, + {"NUM0", VK_NUMPAD0}, + {"DECIMAL", VK_DECIMAL}, +}; +KeyCodePair ConfigKeyboardButtons_JP[] = { + // Reference:https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes + // Wayback Machine:https://web.archive.org/web/20231223135232/https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes + // Row 1 + {"ESCAPE", VK_ESCAPE}, + {"F1", VK_F1}, + {"F2", VK_F2}, + {"F3", VK_F3}, + {"F4", VK_F4}, + {"F5", VK_F5}, + {"F6", VK_F6}, + {"F7", VK_F7}, + {"F8", VK_F8}, + {"F9", VK_F9}, + {"F10", VK_F10}, + {"F11", VK_F11}, + {"F12", VK_F12}, + + // Row 2 + {"1", '1'}, + {"2", '2'}, + {"3", '3'}, + {"4", '4'}, + {"5", '5'}, + {"6", '6'}, + {"7", '7'}, + {"8", '8'}, + {"9", '9'}, + {"0", '0'}, + {"-", VK_OEM_MINUS}, + {"^", VK_OEM_7}, + {"YEN", VK_OEM_5}, + {"BACKSPACE", VK_BACK}, + + // Row 3 + {"TAB", VK_TAB}, + {"Q", 'Q'}, + {"W", 'W'}, + {"E", 'E'}, + {"R", 'R'}, + {"T", 'T'}, + {"Y", 'Y'}, + {"U", 'U'}, + {"I", 'I'}, + {"O", 'O'}, + {"P", 'P'}, + {"@", VK_OEM_3}, + {"[", VK_OEM_4}, + + // Row 4 + {"CAPS_LOCK", VK_CAPITAL}, + {"A", 'A'}, + {"S", 'S'}, + {"D", 'D'}, + {"F", 'F'}, + {"G", 'G'}, + {"H", 'H'}, + {"J", 'J'}, + {"K", 'K'}, + {"L", 'L'}, + {";", VK_OEM_PLUS}, + {":", VK_OEM_1}, + {"]", VK_OEM_6}, + {"ENTER", VK_RETURN}, + + // Row 5 + {"SHIFT", VK_SHIFT}, + {"Z", 'Z'}, + {"X", 'X'}, + {"C", 'C'}, + {"V", 'V'}, + {"B", 'B'}, + {"N", 'N'}, + {"M", 'M'}, + {",", VK_OEM_COMMA}, + {".", VK_OEM_PERIOD}, + {"SLASH", VK_OEM_2}, + {"BACKSLASH", VK_OEM_102}, + + // Row 6 + {"CONTROL", VK_CONTROL}, + {"L_WIN", VK_LWIN}, + {"ALT", VK_MENU}, + {"SPACE", VK_SPACE}, + {"R_WIN", VK_RWIN}, + {"MENU", VK_APPS}, + + // Other Keys + // PrtSc is more important when making snapshots, therefore comment it as reserved + //{"PRINT_SCREEN", VK_SNAPSHOT}, + {"SCROLL_LOCK", VK_SCROLL}, + {"PAUSE", VK_PAUSE}, + {"INSERT", VK_INSERT}, + {"DELETE", VK_DELETE}, + {"HOME", VK_HOME}, + {"END", VK_END}, + {"PAGE_UP", VK_PRIOR}, + {"PAGE_DOWN", VK_NEXT}, + + // Arrow Keys + {"UPARROW", VK_UP}, + {"LEFTARROW", VK_LEFT}, + {"DOWNARROW", VK_DOWN}, + {"RIGHTARROW", VK_RIGHT}, + + // NUMPAD Keys + {"NUM_LOCK", VK_NUMLOCK}, + {"DIVIDE", VK_DIVIDE}, + {"MULTIPLY", VK_MULTIPLY}, + {"SUBTRACT", VK_SUBTRACT}, + {"NUM7", VK_NUMPAD7}, + {"NUM8", VK_NUMPAD8}, + {"NUM9", VK_NUMPAD9}, + {"ADD", VK_ADD}, + {"NUM4", VK_NUMPAD4}, + {"NUM5", VK_NUMPAD5}, + {"NUM6", VK_NUMPAD6}, + {"NUM1", VK_NUMPAD1}, + {"NUM2", VK_NUMPAD2}, + {"NUM3", VK_NUMPAD3}, + {"NUM0", VK_NUMPAD0}, + {"DECIMAL", VK_DECIMAL}, +}; + +struct { + const char *string; + SDL_GameControllerButton 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}, +}; + +struct { + const char *string; + SDLAxis axis; +} ConfigControllerAXIS[] = { + {"SDL_LSTICK_LEFT", SDL_AXIS_LEFT_LEFT}, {"SDL_LSTICK_UP", SDL_AXIS_LEFT_UP}, {"SDL_LSTICK_DOWN", SDL_AXIS_LEFT_DOWN}, + {"SDL_LSTICK_RIGHT", SDL_AXIS_LEFT_RIGHT}, {"SDL_RSTICK_LEFT", SDL_AXIS_RIGHT_LEFT}, {"SDL_RSTICK_UP", SDL_AXIS_RIGHT_UP}, + {"SDL_RSTICK_DOWN", SDL_AXIS_RIGHT_DOWN}, {"SDL_RSTICK_RIGHT", SDL_AXIS_RIGHT_RIGHT}, {"SDL_LTRIGGER", SDL_AXIS_LTRIGGER_DOWN}, + {"SDL_RTRIGGER", SDL_AXIS_RTRIGGER_DOWN}, +}; + +struct { + const char *string; + Scroll scroll; +} ConfigMouseScroll[] = { + {"SCROLL_UP", MOUSE_SCROLL_UP}, + {"SCROLL_DOWN", MOUSE_SCROLL_DOWN}, +}; + +struct MouseState { + POINT Position; + POINT RelativePosition; + bool ScrolledUp; + bool ScrolledDown; +} currentMouseState, lastMouseState; \ No newline at end of file