Add AsyncUpdate/AsyncIO (experimental)

Fix something to enhance stablility
This commit is contained in:
ptmaster
2024-12-04 01:03:51 +08:00
parent 11ef0f4b84
commit aa9b535b4f
10 changed files with 910 additions and 409 deletions
+3 -1
View File
@@ -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
+67 -33
View File
@@ -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<std::mutex> 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<uint8_t> 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<uint8_t> 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
+1
View File
@@ -1,4 +1,5 @@
#pragma once
// #define ASYNC_UPDATE
namespace bnusio {
void Init ();
void Update ();
+8 -1
View File
@@ -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<toml_table_t, void (*) (toml_table_t *)> 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;
}
+16 -4
View File
@@ -253,6 +253,7 @@ LayeredFsHandler (const std::string &originalFileName, const std::string &curren
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);
}
+42 -42
View File
@@ -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);
+3 -304
View File
@@ -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
+36 -24
View File
@@ -1,6 +1,13 @@
#pragma once
#include <SDL.h>
#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
+429
View File
@@ -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<KeyCodePair *> (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<KBDLLHOOKSTRUCT*>(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<SDL_CONTROLLER_BUTTON_MAX; i++) controllerCount[i] -= (bool)controllerDiff[i];
std::fill_n (keyboardDiff, 0xFF, 0);
std::fill_n (controllerDiff, SDL_CONTROLLER_BUTTON_MAX, 0);
// GetCursorPos (&currentMouseState.Position);
// ScreenToClient (windowHandle, &currentMouseState.Position);
}
void
DisposePoll () {
SDL_DestroyWindow (window);
SDL_Quit ();
}
ConfigValue
StringToConfigEnum (const char *value) {
ConfigValue rval = {};
for (size_t i = 0; i < ConfigKeyboardButtonsCount; ++i)
if (!strcmp (value, ConfigKeyboardButtons[i].string)) {
rval.type = keycode;
rval.keycode = ConfigKeyboardButtons[i].keycode;
return rval;
}
for (const auto &[string, button_] : ConfigControllerButtons)
if (!strcmp (value, string)) {
rval.type = button;
rval.button = button_;
return rval;
}
for (const auto &[string, axis_] : ConfigControllerAXIS)
if (!strcmp (value, string)) {
rval.type = axis;
rval.axis = axis_;
return rval;
}
for (auto &[string, scroll_] : ConfigMouseScroll)
if (!strcmp (value, string)) {
rval.type = scroll;
rval.scroll = scroll_;
return rval;
}
LogMessage (LogLevel::ERROR, std::string (value) + ": Unknown value");
return rval;
}
void
SetRumble (int left, int right, int length) {
for (auto &controller : controllers) {
if (!controller || !SDL_GameControllerHasRumble (controller)) continue;
SDL_GameControllerRumble (controller, left, right, length);
}
}
bool
KeyboardIsDown (const uint8_t keycode) {
return currentKeyboardState[keycode];
}
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);
}
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
+305
View File
@@ -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;