From 6a4814b931b4d4acfbc95e7b244ba60a303897d7 Mon Sep 17 00:00:00 2001 From: ptmaster Date: Mon, 30 Dec 2024 23:21:06 +0800 Subject: [PATCH] fullscreen & enhance auto_ime & language & several clean up & remove dxgi (seems will cause strange behavior only if you included it) --- CMakeLists.txt | 10 ++++-- dist/config.toml | 13 ++++--- src/bnusio.cpp | 24 ++----------- src/dllmain.cpp | 51 +++++++++++++++++++++++++-- src/patches/language.cpp | 63 +++++++++++++++++++++------------- src/patches/patches.h | 5 ++- src/patches/versions/CHN00.cpp | 14 ++------ src/patches/versions/JPN00.cpp | 15 +++----- src/patches/versions/JPN08.cpp | 14 ++------ src/patches/versions/JPN39.cpp | 15 +++----- src/pollasync.cpp | 14 +++++++- 11 files changed, 137 insertions(+), 101 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8a6e9db..97b7a64 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,11 @@ cmake_minimum_required(VERSION 3.25) project(TaikoArcadeLoader VERSION 1.0.0 LANGUAGES C CXX) +# Set runtime library to static +if(MSVC) + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" CACHE INTERNAL "") +endif() + # Set C and C++ standards set(CMAKE_C_STANDARD 11) set(CMAKE_CXX_STANDARD 23) @@ -134,8 +139,8 @@ set(SOURCES src/pollasync.cpp src/bnusio.cpp src/patches/amauth.cpp - src/patches/dxgi.cpp - src/patches/fpslimiter.cpp + # src/patches/dxgi.cpp + # src/patches/fpslimiter.cpp src/patches/audio.cpp src/patches/plugins.cpp src/patches/scanner.cpp @@ -143,6 +148,7 @@ set(SOURCES src/patches/testmode.cpp src/patches/timer.cpp src/patches/language.cpp + # src/patches/unlimitsong.cpp src/patches/versions/JPN00.cpp src/patches/versions/JPN08.cpp src/patches/versions/JPN39.cpp diff --git a/dist/config.toml b/dist/config.toml index 484baaa..31306a2 100644 --- a/dist/config.toml +++ b/dist/config.toml @@ -15,7 +15,6 @@ version = "auto" # Patch version # | - JPN39: For use with Taiko JPN 39.06 # | - CHN00: For use with Taiko CHN 00.32 unlock_songs = true -high_res_timer = true # (experimental) Enable High Resolution Timer, which might improve judgement timing [patches.chn00] # These patches are only available for version CHN00 fix_language = false # Sync test mode language to attract etc @@ -33,14 +32,14 @@ qr = true # Disable this if you want to use an original Namco [graphics] res = { x = 1920, y = 1080 } -windowed = false +windowed = false # not windowed will automatically fullscreen cursor = true -vsync = false -fpslimit = 120 +vsync = false # enable this if you are using a 120fps screen (and use "Let Application Decide" in Nvidia panel) +# fpslimit = 0 # temporoly remove it, limit it to 120 in Nvidia panel instead! [audio] -wasapi_shared = true # Wasapi shared mode, allows you to have multiple audio sources at once at a cost of having higher latency. +wasapi_shared = false # Wasapi shared mode, allows you to have multiple audio sources at once at a cost of having higher latency. asio = false # Use asio audio mode asio_driver = "ASIO4ALL v2" # Asio driver name # | If you're not using asio4all, open up regedit then navigate to HKEY_LOCAL_MACHINE\SOFTWARE\ASIO for your driver's name. @@ -60,12 +59,12 @@ song_no = [] # Song noes used for custom folder [controller] -wait_period = 4 # Input interval (if using taiko drum controller, should be set to 0) +wait_period = 0 # Input interval (if using taiko drum controller, should be set to 0) analog_input = false # Use analog input (you need a compatible controller, this allows playing small and big notes like on arcade cabinets) [keyboard] -auto_ime = false # Automatically change to english ime mode upon game startup +auto_ime = true # Automatically change to english ime mode upon game startup jp_layout = false # Use jp layout scan code (if using jp layout keyboard, must be set to true) diff --git a/src/bnusio.cpp b/src/bnusio.cpp index 624ae70..1c7b663 100644 --- a/src/bnusio.cpp +++ b/src/bnusio.cpp @@ -13,22 +13,11 @@ extern char accessCode1[21]; extern char accessCode2[21]; extern char chipId1[33]; extern char chipId2[33]; -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); -typedef void event (); -typedef void waitTouchEvent (callbackTouch, u64); -bool waitingForTouch = false; -callbackTouch touchCallback; -u64 touchData; -callbackAttach attachCallback; -i32 *attachData; - Keybindings EXIT = {.keycodes = {VK_ESCAPE}}; Keybindings TEST = {.keycodes = {VK_F1}}; Keybindings SERVICE = {.keycodes = {VK_F2}}; @@ -64,8 +53,7 @@ bool updateByCoin = false; HWND windowHandle = nullptr; float axisThreshold = 0.6f; u8 inputState = 1 | (1 << 2); -bool globalKeyboard = false;; -HKL currentLayout; +bool globalKeyboard = false; namespace bnusio { #define RETURN_FALSE(returnType, functionName, ...) \ @@ -132,7 +120,7 @@ bnusio_GetSwIn () { } bool waitAll = false; -short drumWaitPeriod = 4; +short drumWaitPeriod = 0; bool analogInput = false; bool valueStates[] = {false, false, false, false, false, false, false, false}; @@ -405,11 +393,6 @@ Update () { 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; } @@ -439,7 +422,6 @@ Update () { void Close () { - if (autoIme) ActivateKeyboardLayout (currentLayout, KLF_SETFORPROCESS); // patches::Plugins::Exit (); CleanupLogger (); } diff --git a/src/dllmain.cpp b/src/dllmain.cpp index 1852129..b998ca3 100644 --- a/src/dllmain.cpp +++ b/src/dllmain.cpp @@ -24,13 +24,17 @@ char accessCode2[21] = "00000000000000000002"; char chipId1[33] = "00000000000000000000000000000001"; char chipId2[33] = "00000000000000000000000000000002"; bool windowed = false; -bool autoIme = false; +bool autoIme = true; bool jpLayout = false; bool cursor = true; bool emulateUsio = true; bool emulateCardReader = true; bool emulateQr = true; bool acceptInvalidCards = false; +HKL currentLayout = nullptr; +i32 xRes = 1920; +i32 yRes = 1080; +bool vsync = false; std::string logLevelStr = "INFO"; bool logToFile = true; @@ -189,6 +193,11 @@ DllMain (HMODULE module, const DWORD reason, LPVOID reserved) { if (const auto graphics = openConfigSection (config, "graphics")) { windowed = readConfigBool (graphics, "windowed", windowed); cursor = readConfigBool (graphics, "cursor", cursor); + if (auto res = openConfigSection (graphics, "res")) { + xRes = static_cast (readConfigInt (res, "x", xRes)); + yRes = static_cast (readConfigInt (res, "y", yRes)); + } + vsync = readConfigBool (graphics, "vsync", vsync); } if (const auto keyboard = openConfigSection (config, "keyboard")) { autoIme = readConfigBool (keyboard, "auto_ime", autoIme); @@ -201,6 +210,43 @@ DllMain (HMODULE module, const DWORD reason, LPVOID reserved) { } } + auto activeWindow = GetActiveWindow(); + HMONITOR monitor = MonitorFromWindow(activeWindow, MONITOR_DEFAULTTONEAREST); + + // Get the logical width and height of the monitor + MONITORINFOEX monitorInfoEx; + monitorInfoEx.cbSize = sizeof(monitorInfoEx); + GetMonitorInfo(monitor, &monitorInfoEx); + auto cxLogical = monitorInfoEx.rcMonitor.right - monitorInfoEx.rcMonitor.left; + auto cyLogical = monitorInfoEx.rcMonitor.bottom - monitorInfoEx.rcMonitor.top; + + // Get the physical width and height of the monitor + DEVMODE devMode; + devMode.dmSize = sizeof(devMode); + devMode.dmDriverExtra = 0; + EnumDisplaySettings(monitorInfoEx.szDevice, ENUM_CURRENT_SETTINGS, &devMode); + auto cxPhysical = devMode.dmPelsWidth; + auto cyPhysical = devMode.dmPelsHeight; + + // Calculate the scaling factor + auto horizontalScale = (static_cast (cxPhysical) / static_cast (cxLogical)); + auto verticalScale = (static_cast (cyPhysical) / static_cast (cyLogical)); + if (windowed) { + xRes = (int)(xRes / horizontalScale); + yRes = (int)(yRes / verticalScale); + } else { + xRes = cxLogical; + yRes = cyLogical; + } + LogMessage (LogLevel::INFO, "Boot with {} mode ({}x{})", windowed ? "window" : "fullscreen", xRes, yRes); + + if (autoIme) { + currentLayout = GetKeyboardLayout (0); + auto engLayout = LoadKeyboardLayout (TEXT ("00000409"), KLF_ACTIVATE); + ActivateKeyboardLayout (engLayout, KLF_SETFORPROCESS); + LogMessage (LogLevel::DEBUG, "Initial change KeyboardLayout {}", LOWORD(engLayout)); + } + // Update the logger with the level read from config file. InitializeLogger (GetLogLevel (logLevelStr), logToFile); LogMessage (LogLevel::INFO, "Application started."); @@ -264,11 +310,12 @@ DllMain (HMODULE module, const DWORD reason, LPVOID reserved) { patches::Scanner::Init (); patches::Audio::Init (); - patches::Dxgi::Init (); + // patches::Dxgi::Init (); patches::AmAuth::Init (); patches::Language::Init (); patches::TestMode::Init (); patches::LayeredFs::Init (); + // patches::UnlimitSong::Init (); std::chrono::duration duration = std::chrono::high_resolution_clock::now() - start; LogMessage (LogLevel::INFO, "==== Finished Loading patches! using: {:.2f}ms", duration.count () * 1000); diff --git a/src/patches/language.cpp b/src/patches/language.cpp index c3a5121..5261ff6 100644 --- a/src/patches/language.cpp +++ b/src/patches/language.cpp @@ -375,8 +375,11 @@ FAST_HOOK_DYNAMIC (u64, GraphicBaseGetLanguageType, u64 a1, void *a2) { return (u64)GetLanguageType (taiko_assign, language, a2); } -std::string *season_nulm = nullptr; -std::string *season_nutexb = nullptr; +bool titleExistSeason = true, titleExistMaid = true, titleExistMaidCn = true; +std::string seasonNulm = "title_season.nulm", seasonNutexb = "title_" + season () + ".nutexb"; +std::string maidNulmCn = "title_maid.nulm", maidNutexbCn = "title_maid.nutexb"; +std::string maidNulm = "title_maid.nulm", maidNutexb = "title_maid.nutexb"; +TestMode::Value *titleScreen = TestMode::CreateValue (L"ModTitleScreen"); void Init () { switch (gameVersion) { @@ -419,35 +422,49 @@ Init () { language_patch.push_back (safetyhook::create_mid (ASLR (0x14012B8C8), [](SafetyHookContext &ctx) { InjectLanguageType (ctx.rbp + 0x180 + ctx.rax * 8, ctx.rdx); ctx.rip = ASLR (0x14012B8D0); })); // ScoreGetLanguageType LayeredFs::RegisterBefore ([&] (const std::string &originalFileName, const std::string ¤tFileName) -> std::string { - if (language != 4 || currentFileName.starts_with ("F:\\") || currentFileName.find ("\\lumen\\") == std::string::npos) return ""; + if (language != 4 || currentFileName.starts_with ("F:\\lumen\\") || currentFileName.find ("\\lumen\\") == std::string::npos) return ""; std::string fileName = std::string (currentFileName); fileName = replace (fileName, "\\lumen\\", "\\lumen_cn\\"); if (std::filesystem::exists (fileName)) return fileName; return ""; }); - LayeredFs::RegisterBefore ([&] (const std::string &originalFileName, const std::string ¤tFileName) -> std::string { - if (language != 4 || currentFileName.starts_with ("F:\\")) return ""; - if (currentFileName.ends_with ("title.nulm")) { - std::string fileName = std::string (currentFileName); - if (season_nulm == nullptr) { - fileName = replace (fileName, "title.nulm", "title_season.nulm"); - if (std::filesystem::exists (fileName)) { - std::string nutexb = std::string (currentFileName); - nutexb = replace (nutexb, "title.nulm", "title_" + season () + ".nutexb"); - if (std::filesystem::exists (nutexb)) { - season_nulm = new std::string (fileName), season_nutexb = new std::string (nutexb); - return *season_nulm; - } + TestMode::RegisterItem ( + L"", + [&](){ + std::string base[] = {"..\\..\\Data\\x64\\lumen\\000_default\\attract\\", "..\\..\\Data_mods\\x64\\lumen\\000_default\\attract\\"}; + std::string baseCn[] = {"..\\..\\Data\\x64\\lumen_cn\\000_default\\attract\\", "..\\..\\Data_mods\\x64\\lumen_cn\\000_default\\attract\\"}; + for (std::string prefix : baseCn) { + if (!seasonNulm.starts_with ("..\\") && std::filesystem::exists (prefix + seasonNulm)) seasonNulm = prefix + seasonNulm; + if (!seasonNutexb.starts_with ("..\\") && std::filesystem::exists (prefix + seasonNutexb)) seasonNutexb = prefix + seasonNutexb; + } + if (!seasonNulm.starts_with ("..\\") || !seasonNutexb.starts_with ("..\\")) titleExistSeason = false; + for (std::string prefix : baseCn) { + if (!maidNulmCn.starts_with ("..\\") && std::filesystem::exists (prefix + maidNulmCn)) maidNulmCn = prefix + maidNulmCn; + if (!maidNutexbCn.starts_with ("..\\") && std::filesystem::exists (prefix + maidNutexbCn)) maidNutexbCn = prefix + maidNutexbCn; + } + if (!maidNulmCn.starts_with ("..\\") || !maidNutexbCn.starts_with ("..\\")) titleExistMaidCn = false; + for (std::string prefix : base) { + if (!maidNulm.starts_with ("..\\") && std::filesystem::exists (prefix + maidNulm)) maidNulm = prefix + maidNulm; + if (!maidNutexb.starts_with ("..\\") && std::filesystem::exists (prefix + maidNutexb)) maidNutexb = prefix + maidNutexb; + } + if (!maidNulm.starts_with ("..\\") || !maidNutexb.starts_with ("..\\")) titleExistMaid = false; + LayeredFs::RegisterBefore ([&] (const std::string &originalFileName, const std::string ¤tFileName) -> std::string { + if (currentFileName.starts_with ("F:\\lumen\\") || currentFileName.find ("title") == std::string::npos) return ""; + if (currentFileName.ends_with ("title.nulm")) { + if (language == 4 && titleScreen->Read () == 1 && titleExistSeason) return seasonNulm; + if (language == 4 && titleScreen->Read () == 2 && titleExistMaidCn) return maidNulmCn; + if (titleScreen->Read () == 2 && titleExistMaid) return maidNulm; + } else if (currentFileName.ends_with ("title.nutexb")) { + LogMessage (LogLevel::DEBUG, "nutexb"); + if (language == 4 && titleScreen->Read () == 1 && titleExistSeason) return seasonNutexb; + if (language == 4 && titleScreen->Read () == 2 && titleExistMaidCn) return maidNutexbCn; + if (titleScreen->Read () == 2 && titleExistMaid) return maidNutexb; } - season_nulm = new std::string (""), season_nutexb = new std::string (""); return ""; - } else return *season_nulm; - } else if (currentFileName.ends_with ("title.nutexb") && season_nutexb != nullptr) { - return *season_nutexb; - } else return ""; - }); - + }); + }); } break; } } diff --git a/src/patches/patches.h b/src/patches/patches.h index 7410622..e0ecf0b 100644 --- a/src/patches/patches.h +++ b/src/patches/patches.h @@ -129,5 +129,8 @@ void Init (); namespace Language { boolean CnFontPatches (); void Init (); -} +} // namespace Language +namespace UnlimitSong { +void Init (); +} // namespace UnlimitSong } // namespace patches diff --git a/src/patches/versions/CHN00.cpp b/src/patches/versions/CHN00.cpp index 6ae159e..9996ecb 100644 --- a/src/patches/versions/CHN00.cpp +++ b/src/patches/versions/CHN00.cpp @@ -2,6 +2,9 @@ #include "../patches.h" extern std::string chassisId; +extern i32 xRes; +extern i32 yRes; +extern bool vsync; namespace patches::CHN00 { int language = 0; @@ -101,9 +104,6 @@ ReplaceLeaBufferAddress (const std::vector &bufferAddresses, void *ne void Init () { LogMessage (LogLevel::INFO, "Init CHN00 patches"); - i32 xRes = 1920; - i32 yRes = 1080; - bool vsync = false; bool unlockSongs = true; bool fixLanguage = false; bool demoMovie = true; @@ -139,14 +139,6 @@ Init () { modeCollabo026 = readConfigBool (chn00, "mode_collabo026", modeCollabo026); } } - - if (const auto graphics = openConfigSection (config_ptr.get (), "graphics")) { - if (const auto res = openConfigSection (graphics, "res")) { - xRes = static_cast (readConfigInt (res, "x", xRes)); - yRes = static_cast (readConfigInt (res, "y", yRes)); - } - vsync = readConfigBool (graphics, "vsync", vsync); - } } // Apply common config patch diff --git a/src/patches/versions/JPN00.cpp b/src/patches/versions/JPN00.cpp index 301f595..fe1e492 100644 --- a/src/patches/versions/JPN00.cpp +++ b/src/patches/versions/JPN00.cpp @@ -1,6 +1,10 @@ #include "helpers.h" #include "../patches.h" +extern i32 xRes; +extern i32 yRes; +extern bool vsync; + namespace patches::JPN00 { HOOK_DYNAMIC (char, AMFWTerminate, i64) { return 0; } @@ -37,9 +41,6 @@ ReplaceLeaBufferAddress (const std::vector &bufferAddresses, void *ne void Init () { LogMessage (LogLevel::INFO, "Init JNP00 patches"); - i32 xRes = 1920; - i32 yRes = 1080; - bool vsync = false; bool unlockSongs = true; const auto configPath = std::filesystem::current_path () / "config.toml"; @@ -47,14 +48,6 @@ Init () { if (config_ptr) { if (const auto patches = openConfigSection (config_ptr.get (), "patches")) unlockSongs = readConfigBool (patches, "unlock_songs", unlockSongs); - - if (const auto graphics = openConfigSection (config_ptr.get (), "graphics")) { - if (const auto res = openConfigSection (graphics, "res")) { - xRes = static_cast (readConfigInt (res, "x", xRes)); - yRes = static_cast (readConfigInt (res, "y", yRes)); - } - vsync = readConfigBool (graphics, "vsync", vsync); - } } // Apply common config patch diff --git a/src/patches/versions/JPN08.cpp b/src/patches/versions/JPN08.cpp index 9a4d04b..851b4f3 100644 --- a/src/patches/versions/JPN08.cpp +++ b/src/patches/versions/JPN08.cpp @@ -3,6 +3,9 @@ extern u64 song_data_size; extern void *song_data; +extern i32 xRes; +extern i32 yRes; +extern bool vsync; #define RDX_MOV 0x48, 0xBA #define R8_MOV 0x49, 0xB8 @@ -48,23 +51,12 @@ ReplaceLeaBufferAddress (const std::vector &bufferAddresses, void *ne void Init () { LogMessage (LogLevel::INFO, "Init JPN08 patches"); - i32 xRes = 1920; - i32 yRes = 1080; - bool vsync = false; bool unlockSongs = true; auto configPath = std::filesystem::current_path () / "config.toml"; std::unique_ptr config_ptr (openConfig (configPath), toml_free); if (config_ptr) { if (auto patches = openConfigSection (config_ptr.get (), "patches")) unlockSongs = readConfigBool (patches, "unlock_songs", unlockSongs); - - if (auto graphics = openConfigSection (config_ptr.get (), "graphics")) { - if (auto res = openConfigSection (graphics, "res")) { - xRes = static_cast (readConfigInt (res, "x", xRes)); - yRes = static_cast (readConfigInt (res, "y", yRes)); - } - vsync = readConfigBool (graphics, "vsync", vsync); - } } // Apply common config patch diff --git a/src/patches/versions/JPN39.cpp b/src/patches/versions/JPN39.cpp index 62a79d4..0820be4 100644 --- a/src/patches/versions/JPN39.cpp +++ b/src/patches/versions/JPN39.cpp @@ -3,6 +3,10 @@ #include "../patches.h" #include +extern i32 xRes; +extern i32 yRes; +extern bool vsync; + namespace patches::JPN39 { int language = 0; FAST_HOOK_DYNAMIC (char, AMFWTerminate, i64) { @@ -281,9 +285,6 @@ ReplaceDatatableBufferAddresses () { void Init () { LogMessage (LogLevel::INFO, "Init JPN39 patches"); - i32 xRes = 1920; - i32 yRes = 1080; - bool vsync = false; bool unlockSongs = true; auto configPath = std::filesystem::current_path () / "config.toml"; @@ -292,14 +293,6 @@ Init () { if (auto patches = openConfigSection (config_ptr.get (), "patches")) { unlockSongs = readConfigBool (patches, "unlock_songs", unlockSongs); } - - if (auto graphics = openConfigSection (config_ptr.get (), "graphics")) { - if (auto res = openConfigSection (graphics, "res")) { - xRes = static_cast (readConfigInt (res, "x", xRes)); - yRes = static_cast (readConfigInt (res, "y", yRes)); - } - vsync = readConfigBool (graphics, "vsync", vsync); - } } // Hook to get AppAccessor and ComponentAccessor diff --git a/src/pollasync.cpp b/src/pollasync.cpp index f4e6132..1758da7 100644 --- a/src/pollasync.cpp +++ b/src/pollasync.cpp @@ -10,6 +10,8 @@ extern int exited; extern u8 inputState; extern float axisThreshold; extern bool globalKeyboardInput; +extern bool autoIme; +extern HKL currentLayout; bool wndForeground = false; bool usingKeyboard = false; @@ -201,6 +203,7 @@ InitializePoll (HWND windowHandle) { usingController = inputState & (1 << 2); usingSDLEvent = usingMouse || usingController; + atexit ([](){ if (currentLayout != nullptr) ActivateKeyboardLayout (currentLayout, KLF_SETFORPROCESS);}); InitializeKeyboard (); if (usingSDLEvent) { LogMessage (LogLevel::DEBUG, "InitializePoll"); @@ -267,9 +270,18 @@ InitializePoll (HWND windowHandle) { bool CheckForegroundWindow (HWND processWindow) { if (processWindow == nullptr) return false; - if (wndForeground ^ (processWindow == GetForegroundWindow ())) { + HWND foregroundWnd = GetForegroundWindow (); + if (wndForeground ^ (processWindow == foregroundWnd)) { wndForeground = !wndForeground; LogMessage (LogLevel::DEBUG, "window focus={}", wndForeground); + if (autoIme) { + if (wndForeground) { + currentLayout = GetKeyboardLayout (0); + auto engLayout = LoadKeyboardLayout (TEXT ("00000409"), KLF_ACTIVATE); + ActivateKeyboardLayout (engLayout, KLF_SETFORPROCESS); + LogMessage (LogLevel::DEBUG, "(experimental) auto change KeyboardLayout {}", LOWORD(engLayout)); + } + } } return wndForeground; }