diff --git a/src/bnusio.cpp b/src/bnusio.cpp index b8f93e9..624ae70 100644 --- a/src/bnusio.cpp +++ b/src/bnusio.cpp @@ -150,12 +150,14 @@ SDLAxis analogBindings[] = { u16 bnusio_GetAnalogIn (const u8 which) { + // LogMessage (LogLevel::DEBUG, "GetAnalogIn p={}", which); if (analogMethod) return analogMethod (which); else return 0; } u16 __fastcall bnusio_GetCoin (i32 a1) { - if (updateByCoin) bnusio::Update (); + // LogMessage (LogLevel::DEBUG, "GetCoin p={}", a1); + if (updateByCoin && a1 == 1) bnusio::Update (); return coin_count; } u16 __fastcall bnusio_GetService (i32 a1) { return service_count; } @@ -270,74 +272,6 @@ AnalogInputSimple (const u8 which) { return 0; } -#ifndef ASYNC_UPDATE -void -Update () { -#else -std::thread pollThread; -std::thread updateThread; -std::mutex syncMtx; -std::condition_variable syncCV; - -void -UpdateLoop () { - LogMessage (LogLevel::WARN, "(experimental) Using Async Update!"); - std::unique_lock syncLock(syncMtx); - while (exited < exitWait) { - syncCV.wait (syncLock); -#endif - if (exited && ++exited >= exitWait) ExitProcess (0); - -#ifndef ASYNC_IO - 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); -#endif - std::vector buffer = {}; - if (IsButtonTapped (COIN_ADD)) { - LogMessage (LogLevel::DEBUG, "Insert Coin!"); - coin_count++; - } - if (IsButtonTapped (SERVICE)) { - LogMessage (LogLevel::DEBUG, "Insert Severice Coin!"); - service_count++; - } - if (IsButtonTapped (TEST)) { - LogMessage (LogLevel::INFO, "Enter TestMode by Press TestMode Button!"); - testEnabled = !testEnabled; - } - if (exited == 0 && IsButtonTapped (EXIT)) { - LogMessage (LogLevel::INFO, "Exit by Press Exit Button!"); - exited += 1; testEnabled = 1; std::thread([](){patches::Plugins::Exit ();}).detach(); - } - 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 (); @@ -463,17 +397,11 @@ 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 >= exitWait) ExitProcess (0); if (!inited) { windowHandle = FindWindowA ("nuFoundation.Window", nullptr); InitializePoll (windowHandle); @@ -482,14 +410,32 @@ Update () { auto engLayout = LoadKeyboardLayout (TEXT ("00000409"), KLF_ACTIVATE); ActivateKeyboardLayout (engLayout, KLF_SETFORPROCESS); } - patches::Plugins::Init (); inited = true; } UpdatePoll (windowHandle); - syncCV.notify_all (); + + std::vector buffer = {}; + if (IsButtonTapped (COIN_ADD)) coin_count++; + if (IsButtonTapped (SERVICE)) service_count++; + if (IsButtonTapped (TEST)) testEnabled = !testEnabled; + if (exited == 0 && IsButtonTapped (EXIT)) { + LogMessage (LogLevel::INFO, "Exit by Press Exit Button!"); + exited += 1; testEnabled = 1; std::thread([](){patches::Plugins::Exit ();}).detach(); + } + 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 (); } -#endif void Close () { diff --git a/src/helpers.h b/src/helpers.h index e0b1eeb..b2983d7 100644 --- a/src/helpers.h +++ b/src/helpers.h @@ -210,6 +210,7 @@ inline bool sendFlag = false; } #define round(num) ((num > 0) ? (int)(num + 0.5) : (int)(num - 0.5)) +#define timestamp() (std::chrono::duration_cast(std::chrono::system_clock::now ().time_since_epoch ()).count ()) toml_table_t *openConfig (const std::filesystem::path &path); toml_table_t *openConfigSection (const toml_table_t *config, const std::string §ionName); diff --git a/src/patches/language.cpp b/src/patches/language.cpp index 513eb18..c3a5121 100644 --- a/src/patches/language.cpp +++ b/src/patches/language.cpp @@ -52,7 +52,7 @@ const LanguageItem languageItems[5][5] = { {{"en", "64", "en_64"},{"en", "30", "en_30"},{"en", "32_EB", "en_32" },{"en", "32_B", "en_32" },{"en", "32_DB", "en_32" }}, {{"tw", "64", "tw_64"},{"tw", "30", "tw_30"},{"tw", "32_EB", "tw_32" },{"tw", "32_B", "tw_32" },{"tw", "32_DB", "tw_32" }}, {{"kr", "64", "kr_64"},{"kr", "30", "kr_30"},{"kr", "32_EB", "kr_32" },{"kr", "32_B", "kr_32" },{"kr", "32_DB", "kr_32" }}, - {{"cn", "64", "cn_64"},{"cn", "30", "cn_30"},{"cn", "32_EB", "cn_32" },{"cn", "32_B", "cn_32" },{"cn", "32_DB", "cn_32" }}, + {{"cn", "64", "cn_64"},{"cn", "30", "cn_30"},{"cn", "32_EB", "cn_32_EB"},{"cn", "32_B", "cn_32_B"},{"cn", "32_DB", "cn_32_DB"}}, }; FAST_HOOK_DYNAMIC (int, initial_load_setting) { @@ -100,7 +100,10 @@ FAST_HOOK_DYNAMIC (double, GetCorrectionOffsetY, u64 a1, u32 a2) { void Init () { bool fontExistAll = true; - const char *fontToCheck[]{"cn_30.nutexb", "cn_30.xml", "cn_32.nutexb", "cn_32.xml", "cn_64.nutexb", "cn_64.xml"}; + const char *fontToCheck[]{ + "cn_30.nutexb", "cn_30.xml", "cn_32_EB.nutexb", "cn_32_EB.xml", "cn_32_B.nutexb", + "cn_32_B.xml", "cn_32_DB.nutexb", "cn_32_DB.xml", "cn_64.nutexb", "cn_64.xml" + }; for (int i = 0; i < 6; i++) { if (std::filesystem::exists (std::string ("..\\..\\Data\\x64\\font\\") + fontToCheck[i])) continue; fontExistAll = false; @@ -174,10 +177,8 @@ const std::vector languageFlas = {"taikoSelectFla", "taikoSelectFla typedef bool (*JsonHasMember) (u64, const char *); typedef u64 *(*JsonGetMember) (u64, const char *); -typedef void (*VectorIterator) (char *, u64, u64, u64); JsonHasMember jsonHasMember = nullptr; JsonGetMember jsonGetMember = nullptr; -VectorIterator vectorIterator = nullptr; uintptr_t WordlistLanguageTypeRIP = 0; MID_HOOK_DYNAMIC (WordlistLanguageType, SafetyHookContext &ctx) { @@ -274,7 +275,6 @@ Init () { case GameVersion::JPN39: { jsonHasMember = (JsonHasMember)ASLR (0x1400B5A30); jsonGetMember = (JsonGetMember)ASLR (0x1400B6080); - vectorIterator = (VectorIterator)ASLR (0x14079C430); // App::DataTableHolder::Serialize WordlistLanguageTypeRIP = ASLR (0x1400B20B8); INSTALL_MID_HOOK_DYNAMIC (WordlistLanguageType, ASLR (0x1400B1E47)); @@ -614,6 +614,7 @@ Init () { }; for (std::string voiceFile : voiceFiles) checkVoiceFile (("..\\..\\Data\\x64\\sound\\" + voiceFile).c_str ()); if (enableSwitchVoice) { + LogMessage (LogLevel::INFO, "Detected voice files, install voice patches!"); TestMode::RegisterItemAfter( L"/root/menu[@id='OthersMenu']/layout[@type='Center']/select-item[@id='LanguageItem']", L" plugins = {}; @@ -15,6 +17,9 @@ namespace patches::Plugins { typedef void (*SendQRLoginEvent) (CommitQrLoginCallback login); typedef void (*StatusChangeEvent) (size_t type, bool status); + std::mutex updateMutex; + std::condition_variable updateCV; + void Init () { for (auto plugin : plugins) { @@ -24,13 +29,11 @@ namespace patches::Plugins { } void Update () { - for (auto plugin : plugins) { - auto event = GetProcAddress (plugin, "Update"); - if (event) ((BasicEvent)event) (); - } + updateCV.notify_all (); } void Exit () { + updateCV.notify_all (); for (auto plugin : plugins) { auto event = GetProcAddress (plugin, "Exit"); if (event) ((BasicEvent)event) (); @@ -129,6 +132,19 @@ namespace patches::Plugins { } } } + + std::thread ([&](){ + std::unique_lock updateLock(updateMutex); + while (exited == 0) { + updateCV.wait (updateLock); + if (exited == 0) { + for (auto plugin : plugins) { + auto event = GetProcAddress (plugin, "Update"); + if (event) ((BasicEvent)event) (); + } + } + } + }).detach (); } diff --git a/src/patches/testmode.cpp b/src/patches/testmode.cpp index 937a135..42b3477 100644 --- a/src/patches/testmode.cpp +++ b/src/patches/testmode.cpp @@ -483,33 +483,25 @@ Init () { INSTALL_FAST_HOOK_DYNAMIC (SceneTestModeLoading, ASLR (0x1404793D0)); INSTALL_FAST_HOOK_DYNAMIC (SceneTestModeFinalize, ASLR (0x140479600)); INSTALL_FAST_HOOK_DYNAMIC (SceneFirstInitialize, ASLR (0x1404574B0)); + bool originalDeviceInitialize = L"DeviceInitialize.xml"; if (Language::CnFontPatches () && std::filesystem::exists ("..\\..\\Data\\x64\\testmode\\DeviceInitialize_china.xml")) { usingDeviceInitialize = L"DeviceInitialize_china.xml"; patches.push_back (safetyhook::create_mid (ASLR (0x140465549), [](SafetyHookContext &ctx) - { ctx.r8 = 2; ctx.rdx = (uintptr_t)"cn"; ctx.rip = ASLR (0x140465556); })); + { ctx.r8 = 2; ctx.rdx = (uintptr_t)"cn"; ctx.rip = ASLR (0x140465556); })); // DeviceCheck = Loading Font + patches.push_back (safetyhook::create_mid (ASLR (0x1404676E7), [](SafetyHookContext &ctx) + { ctx.r8 = 2; ctx.rdx = (uintptr_t)"cn"; ctx.rip = ASLR (0x1404676F4); })); // ?? 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"); - } else if (std::filesystem::exists ("..\\..\\Data\\x64\\testmode\\DeviceInitialize_chspatch.xml")) { - usingDeviceInitialize = L"DeviceInitialize_chspatch.xml"; - 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"); } else usingDeviceInitialize = originalDeviceInitialize; originalTestMode = L"TestMode.xml"; if (Language::CnFontPatches () && std::filesystem::exists ("..\\..\\Data\\x64\\testmode\\TestMode_china.xml")) { usingTestMode = L"TestMode_china.xml"; patches.push_back (safetyhook::create_mid (ASLR (0x14047C603), [](SafetyHookContext &ctx) - { ctx.r8 = 2; ctx.rdx = (uintptr_t)"cn"; ctx.rip = ASLR (0x14047C610); })); - patches.push_back (safetyhook::create_mid (ASLR (0x1404676E7), [](SafetyHookContext &ctx) - { ctx.r8 = 2; ctx.rdx = (uintptr_t)"cn"; ctx.rip = ASLR (0x1404676F4); })); - } else if (std::filesystem::exists ("..\\..\\Data\\x64\\testmode\\TestMode_chspatch.xml")) { - usingTestMode = L"TestMode_chspatch.xml"; + { ctx.r8 = 2; ctx.rdx = (uintptr_t)"cn"; ctx.rip = ASLR (0x14047C610); })); // TestMode = DeviceInitialize } else usingTestMode = originalTestMode; - } break; case GameVersion::CHN00: break; } diff --git a/src/poll.h b/src/poll.h index dc92682..9b7edb4 100644 --- a/src/poll.h +++ b/src/poll.h @@ -109,5 +109,6 @@ bool ControllerAxisIsReleased (const SDLAxis axis); bool IsButtonReleased (const Keybindings &bindings); #else void UpdatePoll (HWND windowHandle); +void CleanPoll (); void InitializeKeyboard (); #endif \ No newline at end of file diff --git a/src/pollasync.cpp b/src/pollasync.cpp index 9bc5422..f4e6132 100644 --- a/src/pollasync.cpp +++ b/src/pollasync.cpp @@ -287,32 +287,33 @@ CorrectButton (uint32_t which, uint8_t button) { } void -UpdatePoll (HWND windowHandle) { - if (!CheckForegroundWindow (windowHandle)) return; - +CleanPoll () { if (usingKeyboard && keyboardClean) { keyboardClean = false; for (int i=0; i<0xFF; i++) keyboardCount[i] -= (bool)keyboardDiff[i]; memset (keyboardDiff, 0, 0XFF); } + if (usingMouse) { + currentMouseState.ScrolledUp = false; + currentMouseState.ScrolledDown = false; + 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 (usingController) { + for (int i=0; i 0) mouseWheelCount[0] -= (bool)mouseWheelDiff[0]; - if (mouseWheelCount[1] > 0) mouseWheelCount[1] -= (bool)mouseWheelDiff[1]; - memset (mouseWheelDiff, 0, 2); - } - - if (usingController) { - for (int i=0; i