From a3631a865974e2ea081037e51088d583c8b6b288 Mon Sep 17 00:00:00 2001 From: ptmaster Date: Thu, 23 Jan 2025 23:43:38 +0800 Subject: [PATCH 1/5] config Refactor | use rfl (Thanks to asesidaa) --- CMakeLists.txt | 165 +++++++---- res.patch | 88 ++++++ src/bnusio.cpp | 125 +++------ src/config.cpp | 245 +++++++++++++++++ src/config.h | 481 +++++++++++++++++++++++++++++++++ src/configValidator.cpp | 21 ++ src/dllmain.cpp | 53 ++-- src/helpers.cpp | 4 +- src/helpers.h | 6 +- src/patches/amauth.cpp | 38 +-- src/patches/audio.cpp | 16 +- src/patches/language.cpp | 3 +- src/patches/layeredfs.cpp | 7 +- src/patches/scanner.cpp | 37 +-- src/patches/testmode.cpp | 3 +- src/patches/versions/CHN00.cpp | 25 +- src/patches/versions/JPN00.cpp | 16 +- src/patches/versions/JPN08.cpp | 16 +- src/patches/versions/JPN39.cpp | 17 +- src/poll.h | 32 ++- src/pollasync.cpp | 216 ++++----------- src/polldef.h | 306 --------------------- 22 files changed, 1173 insertions(+), 747 deletions(-) create mode 100644 res.patch create mode 100644 src/config.cpp create mode 100644 src/config.h create mode 100644 src/configValidator.cpp delete mode 100644 src/polldef.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f4aee58..6acea74 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,19 +29,6 @@ add_definitions(-DNOMINMAX -DLTC_NO_PROTOTYPES -D_CRT_SECURE_NO_WARNINGS) # Include FetchContent module include(FetchContent) -# Fetch tomlc99 (no built-in CMake support) -FetchContent_Declare( - tomlc99 - GIT_REPOSITORY https://github.com/cktan/tomlc99.git - GIT_TAG master -) -FetchContent_GetProperties(tomlc99) -if(NOT tomlc99_POPULATED) - FetchContent_MakeAvailable(tomlc99) - add_library(tomlc99 STATIC ${tomlc99_SOURCE_DIR}/toml.c) - target_include_directories(tomlc99 PUBLIC ${tomlc99_SOURCE_DIR}) -endif() - # Fetch stb (header-only library, no built-in CMake support) FetchContent_Declare( stb @@ -130,48 +117,93 @@ FetchContent_Declare( ) FetchContent_MakeAvailable(minhook) +FetchContent_Declare( + tomlplusplus + GIT_REPOSITORY https://github.com/marzer/tomlplusplus.git + GIT_TAG v3.4.0 +) +FetchContent_MakeAvailable(tomlplusplus) +export(TARGETS tomlplusplus_tomlplusplus FILE "${CMAKE_BINARY_DIR}/tomlplusplus-config.cmake") +set(tomlplusplus_DIR "${CMAKE_BINARY_DIR}") + +FetchContent_Declare( + reflectcpp + URL https://github.com/getml/reflect-cpp/archive/refs/tags/v0.17.0.zip +) +set(REFLECTCPP_TOML ON CACHE BOOL "" FORCE) +set(REFLECTCPP_XML OFF CACHE BOOL "" FORCE) +set(REFLECTCPP_USE_VCPKG OFF CACHE BOOL "" FORCE) +FetchContent_MakeAvailable(reflectcpp) + # Source files set(SOURCES - src/dllmain.cpp - src/helpers.cpp - src/logger.cpp - src/poll.cpp - src/pollasync.cpp - src/bnusio.cpp - src/Windows/WindowsError.cpp - src/Windows/MinimumLatencyAudioClient.cpp - src/patches/amauth.cpp - # src/patches/dxgi.cpp - # src/patches/fpslimiter.cpp - src/patches/audio.cpp - src/patches/plugins.cpp - src/patches/scanner.cpp - src/patches/layeredfs.cpp - 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 - src/patches/versions/CHN00.cpp + src/dllmain.cpp + src/helpers.cpp + src/logger.cpp + src/poll.cpp + src/pollasync.cpp + src/bnusio.cpp + src/Windows/WindowsError.cpp + src/Windows/MinimumLatencyAudioClient.cpp + src/patches/amauth.cpp + # src/patches/dxgi.cpp + # src/patches/fpslimiter.cpp + src/patches/audio.cpp + src/patches/plugins.cpp + src/patches/scanner.cpp + src/patches/layeredfs.cpp + 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 + src/patches/versions/CHN00.cpp + src/config.cpp +) + +set(VALIDATOR_SOURCES + src/configValidator.cpp + src/helpers.cpp + src/config.cpp + src/logger.cpp ) # Create the library add_library(bnusio SHARED ${SOURCES}) +add_executable(validator ${VALIDATOR_SOURCES}) + +# Remove 'lib' prefix from the library name, make sure the output directory is expected +set_target_properties(bnusio PROPERTIES + PREFIX "" + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/$" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/$") + +set_target_properties(validator PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/$" +) -# Remove 'lib' prefix from the library name -set_target_properties(bnusio PROPERTIES PREFIX "") # Include directories target_include_directories(bnusio PRIVATE - src - ${tomlc99_SOURCE_DIR} - ${SDL3_SOURCE_DIR}/include - ${xxhash_SOURCE_DIR} - ${zlib_SOURCE_DIR} - ${libtomcrypt_SOURCE_DIR}/src/headers - ${minhook_SOURCE_DIR}/include + src + ${SDL3_SOURCE_DIR}/include + ${xxhash_SOURCE_DIR} + ${zlib_SOURCE_DIR} + ${libtomcrypt_SOURCE_DIR}/src/headers + ${minhook_SOURCE_DIR}/include + ${reflectcpp_SOURCE_DIR}/include +) + +target_include_directories(validator PRIVATE + src + ${SDL3_SOURCE_DIR}/include + ${xxhash_SOURCE_DIR} + ${zlib_SOURCE_DIR} + ${libtomcrypt_SOURCE_DIR}/src/headers + ${minhook_SOURCE_DIR}/include + ${reflectcpp_SOURCE_DIR}/include ) # Compiler definitions @@ -186,18 +218,35 @@ endif() # Link libraries target_link_libraries(bnusio PRIVATE - tomlc99 - SDL3-static - xxhash - zlibstatic - libtomcrypt - safetyhook - ZXing::ZXing - pugixml - stb - ws2_32 - ntdll - minhook + SDL3-static + xxhash + zlibstatic + libtomcrypt + safetyhook + ZXing::ZXing + pugixml + stb + ws2_32 + ntdll + minhook + tomlplusplus::tomlplusplus + reflectcpp +) + +target_link_libraries(validator PRIVATE + SDL3-static + xxhash + zlibstatic + libtomcrypt + safetyhook + ZXing::ZXing + pugixml + stb + ws2_32 + ntdll + minhook + tomlplusplus::tomlplusplus + reflectcpp ) # Define log path; used to make the file path relative in the log calls. @@ -220,7 +269,7 @@ endif() add_custom_command( TARGET bnusio POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different - "${CMAKE_BINARY_DIR}/${CMAKE_BUILD_TYPE}/bnusio.dll" + "${CMAKE_BINARY_DIR}/$/bnusio.dll" "${CMAKE_SOURCE_DIR}/dist/bnusio.dll" COMMENT "Copying bnusio.dll to dist directory" ) diff --git a/res.patch b/res.patch new file mode 100644 index 0000000..e2a0e1f --- /dev/null +++ b/res.patch @@ -0,0 +1,88 @@ +diff --git a/src/config.h b/src/config.h +index be682de..7d3388c 100644 +--- a/src/config.h ++++ b/src/config.h +@@ -459,6 +459,11 @@ public: + const loggingConfig& getLoggingConfig() const { return config.logging; } + const keybindingConfig& getKeyBindings() const { return keyBindings; } + ++ void setRes(i32 x, i32 y) { ++ config.graphics.res.x = x; ++ config.graphics.res.y = y; ++ } ++ + private: + + ConfigManager(); +diff --git a/src/dllmain.cpp b/src/dllmain.cpp +index 6cb5b49..673663c 100644 +--- a/src/dllmain.cpp ++++ b/src/dllmain.cpp +@@ -265,6 +265,7 @@ DllMain (HMODULE module, const DWORD reason, LPVOID reserved) { + if (yRes * 16 > xRes * 9) yRes = (int)(xRes * 9.0 / 16.0); + else if (yRes * 16 < xRes * 9) xRes = (int)(yRes * 16.0 / 9.0); + } ++ Config::ConfigManager::instance ().setRes (xRes, yRes); + + LogMessage (LogLevel::INFO, "Scale Rate: x={} y={}", horizontalScale, verticalScale); + LogMessage (LogLevel::INFO, "Boot with {} mode ({}x{})", windowed ? "window" : "fullscreen", xRes, yRes); +diff --git a/src/patches/versions/CHN00.cpp b/src/patches/versions/CHN00.cpp +index 2d59616..31ca3c1 100644 +--- a/src/patches/versions/CHN00.cpp ++++ b/src/patches/versions/CHN00.cpp +@@ -3,8 +3,8 @@ + #include "config.h" + + static std::string chassisId = Config::ConfigManager::instance ().getAmauthConfig ().chassis_id.value (); +-static i32 xRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.x; +-static i32 yRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.y; ++static const i32& xRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.x; ++static const i32& yRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.y; + static bool vsync = Config::ConfigManager::instance ().getGraphicsConfig ().vsync; + static bool localFiles = Config::ConfigManager::instance ().getPatchesConfig ().local_files; + +diff --git a/src/patches/versions/JPN00.cpp b/src/patches/versions/JPN00.cpp +index 1490c8f..c4580c1 100644 +--- a/src/patches/versions/JPN00.cpp ++++ b/src/patches/versions/JPN00.cpp +@@ -2,8 +2,8 @@ + #include "../patches.h" + #include "config.h" + +-static i32 xRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.x; +-static i32 yRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.y; ++static const i32& xRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.x; ++static const i32& yRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.y; + static bool vsync = Config::ConfigManager::instance ().getGraphicsConfig ().vsync; + static bool localFiles = Config::ConfigManager::instance ().getPatchesConfig ().local_files; + namespace patches::JPN00 { +diff --git a/src/patches/versions/JPN08.cpp b/src/patches/versions/JPN08.cpp +index 0dac8f0..bc07616 100644 +--- a/src/patches/versions/JPN08.cpp ++++ b/src/patches/versions/JPN08.cpp +@@ -4,8 +4,8 @@ + + extern u64 song_data_size; + extern void *song_data; +-static i32 xRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.x; +-static i32 yRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.y; ++static const i32& xRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.x; ++static const i32& yRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.y; + static bool vsync = Config::ConfigManager::instance ().getGraphicsConfig ().vsync; + static bool localFiles = Config::ConfigManager::instance ().getPatchesConfig ().local_files; + #define RDX_MOV 0x48, 0xBA +diff --git a/src/patches/versions/JPN39.cpp b/src/patches/versions/JPN39.cpp +index 2b37ac7..e5edbd1 100644 +--- a/src/patches/versions/JPN39.cpp ++++ b/src/patches/versions/JPN39.cpp +@@ -4,8 +4,8 @@ + #include + #include "config.h" + +-static i32 xRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.x; +-static i32 yRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.y; ++static const i32& xRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.x; ++static const i32& yRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.y; + static bool vsync = Config::ConfigManager::instance ().getGraphicsConfig ().vsync; + static bool localFiles = Config::ConfigManager::instance ().getPatchesConfig ().local_files; + diff --git a/src/bnusio.cpp b/src/bnusio.cpp index b7ce835..016b53e 100644 --- a/src/bnusio.cpp +++ b/src/bnusio.cpp @@ -1,9 +1,11 @@ +// ReSharper disable CppDFAUnreachableCode #include #include "constants.h" #include "helpers.h" #include "patches/patches.h" #include "bnusio.h" #include "poll.h" +#include "config.h" extern GameVersion gameVersion; extern std::vector plugins; @@ -14,29 +16,29 @@ extern char accessCode2[21]; extern char chipId1[33]; extern char chipId2[33]; -extern bool emulateUsio; -extern bool acceptInvalidCards; +static bool emulateUsio = Config::ConfigManager::instance ().getEmulationConfig ().usio; +static bool acceptInvalidCards = Config::ConfigManager::instance ().getEmulationConfig ().accept_invalid; extern HWND hGameWnd; -Keybindings EXIT = {.keycodes = {VK_ESCAPE}}; -Keybindings TEST = {.keycodes = {VK_F1}}; -Keybindings SERVICE = {.keycodes = {VK_F2}}; -Keybindings DEBUG_UP = {.keycodes = {VK_UP}}; -Keybindings DEBUG_DOWN = {.keycodes = {VK_DOWN}}; -Keybindings DEBUG_ENTER = {.keycodes = {VK_RETURN}}; -Keybindings COIN_ADD = {.keycodes = {VK_RETURN}, .buttons = {SDL_GAMEPAD_BUTTON_START}}; -Keybindings CARD_INSERT_1 = {.keycodes = {'P'}}; -Keybindings CARD_INSERT_2 = {}; -Keybindings QR_DATA_READ = {.keycodes = {'Q'}}; -Keybindings QR_IMAGE_READ = {.keycodes = {'W'}}; -Keybindings P1_LEFT_BLUE = {.keycodes = {'D'}, .axis = {SDL_AXIS_LEFT_DOWN}}; -Keybindings P1_LEFT_RED = {.keycodes = {'F'}, .axis = {SDL_AXIS_LEFT_RIGHT}}; -Keybindings P1_RIGHT_RED = {.keycodes = {'J'}, .axis = {SDL_AXIS_RIGHT_RIGHT}}; -Keybindings P1_RIGHT_BLUE = {.keycodes = {'K'}, .axis = {SDL_AXIS_RIGHT_DOWN}}; -Keybindings P2_LEFT_BLUE = {.keycodes = {'Z'}}; -Keybindings P2_LEFT_RED = {.keycodes = {'X'}}; -Keybindings P2_RIGHT_RED = {.keycodes = {'C'}}; -Keybindings P2_RIGHT_BLUE = {.keycodes = {'V'}}; +static const Keybindings & EXIT = Config::ConfigManager::instance ().getKeyBindings ().exit(); +static const Keybindings & TEST = Config::ConfigManager::instance ().getKeyBindings ().test(); +static const Keybindings & SERVICE = Config::ConfigManager::instance ().getKeyBindings ().service(); +static const Keybindings & DEBUG_UP = Config::ConfigManager::instance ().getKeyBindings ().debug_up(); +static const Keybindings & DEBUG_DOWN = Config::ConfigManager::instance ().getKeyBindings ().debug_down(); +static const Keybindings & DEBUG_ENTER = Config::ConfigManager::instance ().getKeyBindings ().debug_enter(); +static const Keybindings & COIN_ADD = Config::ConfigManager::instance ().getKeyBindings ().coin_add(); +static const Keybindings & CARD_INSERT_1 = Config::ConfigManager::instance ().getKeyBindings ().card_insert_1(); +static const Keybindings & CARD_INSERT_2 = Config::ConfigManager::instance ().getKeyBindings ().card_insert_2(); +static const Keybindings & QR_DATA_READ = Config::ConfigManager::instance ().getKeyBindings ().qr_data_read(); +static const Keybindings & QR_IMAGE_READ = Config::ConfigManager::instance ().getKeyBindings ().qr_image_read(); +static const Keybindings & P1_LEFT_BLUE = Config::ConfigManager::instance ().getKeyBindings ().p1_left_blue(); +static const Keybindings & P1_LEFT_RED = Config::ConfigManager::instance ().getKeyBindings ().p1_left_red(); +static const Keybindings & P1_RIGHT_RED = Config::ConfigManager::instance ().getKeyBindings ().p1_right_red(); +static const Keybindings & P1_RIGHT_BLUE = Config::ConfigManager::instance ().getKeyBindings ().p1_right_blue(); +static const Keybindings & P2_LEFT_BLUE = Config::ConfigManager::instance ().getKeyBindings ().p2_left_blue(); +static const Keybindings & P2_LEFT_RED = Config::ConfigManager::instance ().getKeyBindings ().p2_left_red(); +static const Keybindings & P2_RIGHT_RED = Config::ConfigManager::instance ().getKeyBindings ().p2_right_red(); +static const Keybindings & P2_RIGHT_BLUE = Config::ConfigManager::instance ().getKeyBindings ().p2_right_blue(); const int exitWait = 100; int exited = 0; @@ -50,7 +52,16 @@ bool updateByCoin = false; HWND windowHandle = nullptr; float axisThreshold = 0.6f; u8 inputState = 1 | (1 << 2); -bool globalKeyboard = false; +bool globalKeyboard = Config::ConfigManager::instance ().getControllerConfig ().global_keyboard; +bool waitAll = false; +short drumWaitPeriod = Config::ConfigManager::instance ().getControllerConfig ().wait_period; +bool analogInput = Config::ConfigManager::instance ().getControllerConfig ().analog_input; +u16 buttonWaitPeriod[] = { 0, 0 }; +std::queue buttonQueue[] = { {}, {} }; +bool valueStates[] = {false, false, false, false, false, false, false, false}; +const Keybindings *analogButtons[] = { + &P1_LEFT_BLUE, &P1_LEFT_RED, &P1_RIGHT_RED, &P1_RIGHT_BLUE, &P2_LEFT_BLUE, &P2_LEFT_RED, &P2_RIGHT_RED, &P2_RIGHT_BLUE +}; namespace bnusio { HMODULE bnusioOriginal = LoadLibrary ("bnusio_original.dll"); @@ -136,10 +147,9 @@ BNUSIO_EXPORT (u16, bnusio_GetService, i32 a1) { } } -bool analogInput = false; SDLAxis analogBindings[] = { - SDL_AXIS_LEFT_LEFT, SDL_AXIS_LEFT_RIGHT, SDL_AXIS_LEFT_DOWN, SDL_AXIS_LEFT_UP, // P1: LB, LR, RR, RB - SDL_AXIS_RIGHT_LEFT, SDL_AXIS_RIGHT_RIGHT, SDL_AXIS_RIGHT_DOWN, SDL_AXIS_RIGHT_UP, // P2: LB, LR, RR, RB + SDLAxis::SDL_AXIS_LEFT_LEFT, SDLAxis::SDL_AXIS_LEFT_RIGHT, SDLAxis::SDL_AXIS_LEFT_DOWN, SDLAxis::SDL_AXIS_LEFT_UP, // P1: LB, LR, RR, RB + SDLAxis::SDL_AXIS_RIGHT_LEFT, SDLAxis::SDL_AXIS_RIGHT_RIGHT, SDLAxis::SDL_AXIS_RIGHT_DOWN, SDLAxis::SDL_AXIS_RIGHT_UP, // P2: LB, LR, RR, RB }; u16 __fastcall AnalogInputAxis (const u8 which) { @@ -147,14 +157,6 @@ AnalogInputAxis (const u8 which) { return analogIn > 100 ? analogIn : 0; } -bool waitAll = false; -short drumWaitPeriod = 0; -u16 buttonWaitPeriod[] = { 0, 0 }; -std::queue buttonQueue[] = { {}, {} }; -bool valueStates[] = {false, false, false, false, false, false, false, false}; -Keybindings *analogButtons[] = { - &P1_LEFT_BLUE, &P1_LEFT_RED, &P1_RIGHT_RED, &P1_RIGHT_BLUE, &P2_LEFT_BLUE, &P2_LEFT_RED, &P2_RIGHT_RED, &P2_RIGHT_BLUE -}; u16 __fastcall AnalogInputWaitPeriod (const u8 which) { const auto button = analogButtons[which]; @@ -215,24 +217,8 @@ AnalogInputSimple (const u8 which) { void Init () { - SetKeyboardButtons (); - int fpsLimit = 0; - const auto configPath = std::filesystem::current_path () / "config.toml"; - const std::unique_ptr config_ptr (openConfig (configPath), toml_free); - if (config_ptr) { - const toml_table_t *config = config_ptr.get (); - if (const auto controller = openConfigSection (config, "controller")) { - drumWaitPeriod = static_cast (readConfigInt (controller, "wait_period", drumWaitPeriod)); - analogInput = readConfigBool (controller, "analog_input", analogInput); - globalKeyboard = readConfigBool (controller, "global_keyboard", globalKeyboard); - } - // auto graphics = openConfigSection (config, "graphics"); - // if (graphics) { - // fpsLimit = (int)readConfigInt (graphics, "fpslimit", fpsLimit); - // } - } updateByCoin = fpsLimit == 0; // if (updateByCoin) { // LogMessage (LogLevel::INFO, "fpsLimit is set to 0, bnusio::Update() will invoke in getCoin callback"); @@ -252,39 +238,6 @@ Init () { analogMethod = AnalogInputSimple; } - const auto keyConfigPath = std::filesystem::current_path () / "keyconfig.toml"; - const std::unique_ptr keyConfig_ptr (openConfig (keyConfigPath), toml_free); - if (keyConfig_ptr) { - inputState = 0; - if (analogInput) inputState |= (1 << 2); - const toml_table_t *keyConfig = keyConfig_ptr.get (); - SetConfigValue (keyConfig, "EXIT", &EXIT, &inputState); - - SetConfigValue (keyConfig, "TEST", &TEST, &inputState); - SetConfigValue (keyConfig, "SERVICE", &SERVICE, &inputState); - SetConfigValue (keyConfig, "DEBUG_UP", &DEBUG_UP, &inputState); - SetConfigValue (keyConfig, "DEBUG_DOWN", &DEBUG_DOWN, &inputState); - SetConfigValue (keyConfig, "DEBUG_ENTER", &DEBUG_ENTER, &inputState); - - SetConfigValue (keyConfig, "COIN_ADD", &COIN_ADD, &inputState); - SetConfigValue (keyConfig, "CARD_INSERT_1", &CARD_INSERT_1, &inputState); - SetConfigValue (keyConfig, "CARD_INSERT_2", &CARD_INSERT_2, &inputState); - SetConfigValue (keyConfig, "QR_DATA_READ", &QR_DATA_READ, &inputState); - SetConfigValue (keyConfig, "QR_IMAGE_READ", &QR_IMAGE_READ, &inputState); - - SetConfigValue (keyConfig, "P1_LEFT_BLUE", &P1_LEFT_BLUE, &inputState); - SetConfigValue (keyConfig, "P1_LEFT_RED", &P1_LEFT_RED, &inputState); - SetConfigValue (keyConfig, "P1_RIGHT_RED", &P1_RIGHT_RED, &inputState); - SetConfigValue (keyConfig, "P1_RIGHT_BLUE", &P1_RIGHT_BLUE, &inputState); - SetConfigValue (keyConfig, "P2_LEFT_BLUE", &P2_LEFT_BLUE, &inputState); - SetConfigValue (keyConfig, "P2_LEFT_RED", &P2_LEFT_RED, &inputState); - SetConfigValue (keyConfig, "P2_RIGHT_RED", &P2_RIGHT_RED, &inputState); - SetConfigValue (keyConfig, "P2_RIGHT_BLUE", &P2_RIGHT_BLUE, &inputState); - } - - LogMessage (LogLevel::INFO, "Finish Loading keyconfig.toml useKeyboard={} useMouse={} useController={}", - (inputState & 1) ? "true" : "false", (inputState & (1 << 1)) ? "true" : "false", (inputState & (1 << 2)) ? "true" : "false"); - if (!emulateUsio && !exists (std::filesystem::current_path () / "bnusio_original.dll")) { emulateUsio = true; LogMessage (LogLevel::ERROR, "bnusio_original.dll not found! usio emulation enabled"); @@ -307,8 +260,12 @@ Update () { UpdatePoll (windowHandle); std::vector buffer = {}; - if (IsButtonTapped (COIN_ADD)) coin_count++; - if (IsButtonTapped (SERVICE)) service_count++; + 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!"); diff --git a/src/config.cpp b/src/config.cpp new file mode 100644 index 0000000..3abfc7c --- /dev/null +++ b/src/config.cpp @@ -0,0 +1,245 @@ +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "logger.h" + +static bool usingKeyboard = false; +static bool usingMouse = false; +static bool usingController = false; + + +namespace Config { +bool +ConfigManager::validateConfigfile (std::string path) { + std::filesystem::path configPath = path; + if (!exists (configPath) || !configPath.has_filename ()) { + std::cerr << configPath.string () << ": file does not exist" << std::endl; + return false; + } + + std::ifstream stream (configPath); + if (!stream.is_open ()) { + std::cerr << "Could not open " << configPath.string () << std::endl; + return false; + } + + auto result = rfl::toml::read (stream); + if (result) { + return true; + } + auto error = result.error ().value (); + std::cerr << "Validate config failed with error: " << error.what () << std::endl; + return false; +} + +bool +ConfigManager::loadConfig () { + std::lock_guard lock (mutex); + + InitializeLogger (LogLevel::INFO, true, "TaikoArcadeLoader.log"); + if (isLoaded) { return true; } + + const auto configPath = std::filesystem::current_path () / "config.toml"; + + if (!exists (configPath) || !configPath.has_filename ()) { + LogMessage (LogLevel::WARN, std::string (configPath.string ()) + ": file does not exist"); + return false; + } + + std::ifstream stream (configPath); + if (!stream.is_open ()) { + LogMessage (LogLevel::WARN, "Could not open " + std::string (configPath.string ())); + return false; + } + + auto result = rfl::toml::read (stream); + if (result) { + config = result.value (); + bool success = loadKeyBindings (); + if (!success) { + LogMessage (LogLevel::ERROR, "Failed to load keybindings"); + MessageBoxA (nullptr, "Failed to load keybindings, check logs for error", nullptr, MB_OK); + ExitProcess (0); + } + isLoaded = true; + return true; + } + + auto error = result.error ().value (); + LogMessage (LogLevel::WARN, "Read config failed with error: " + error.what ()); + return false; +} + +const qrConfig & +ConfigManager::getQrConfig () { + auto result = updateQrConfig (); + if (!result) { + LogMessage (LogLevel::ERROR, "Failed to update QR config"); + MessageBoxA (nullptr, "Failed to update QR config", nullptr, MB_OK); + ExitProcess (0); + } + return config.qr; + +} + +ConfigManager::ConfigManager () { + auto result = loadConfig (); + if (!result) { + LogMessage (LogLevel::ERROR, "Failed to load config file"); + MessageBoxA (nullptr, "Failed to load config", nullptr, MB_OK); + ExitProcess (0); + } +} + +bool +ConfigManager::loadKeyBindings () { + LogMessage (LogLevel::INFO, "Layout: {}", config.keyboard.jp_layout ? "JP" : "US"); + ConfigKeyboardButtons = config.keyboard.jp_layout ? std::map(ConfigKeyboardButtons_JP) : std::map(ConfigKeyboardButtons_US); + + const auto configPath = std::filesystem::current_path () / "keyconfig.toml"; + if (!exists (configPath) || !configPath.has_filename ()) { + LogMessage (LogLevel::WARN, std::string (configPath.string ()) + ": file does not exist"); + return false; + } + + std::ifstream stream (configPath); + if (!stream.is_open ()) { + LogMessage (LogLevel::WARN, "Could not open " + std::string (configPath.string ())); + return false; + } + + auto result = rfl::toml::read (stream); + if (result) { + keyBindings = result.value (); + keyBindings.usingKeyboard = usingKeyboard; + keyBindings.usingMouse = usingMouse; + keyBindings.usingController = usingController; + LogMessage (LogLevel::INFO, "Finish Loading keyconfig.toml useKeyboard={} useMouse={} useController={}", + usingKeyboard ? "true" : "false", usingMouse ? "true" : "false", usingController ? "true" : "false"); + return true; + } + + auto error = result.error ().value (); + LogMessage (LogLevel::WARN, "Read keybindings failed with error: " + error.what ()); + return false; +} + +bool +ConfigManager::updateQrConfig () { + const auto configPath = std::filesystem::current_path () / "config.toml"; + if (!exists (configPath) || !configPath.has_filename ()) { + LogMessage (LogLevel::WARN, std::string (configPath.string ()) + ": file does not exist"); + return false; + } + + std::ifstream stream (configPath); + if (!stream.is_open ()) { + LogMessage (LogLevel::WARN, "Could not open " + std::string (configPath.string ())); + return false; + } + + auto result = rfl::toml::read (stream); + if (result) { + config.qr = result.value (); + return true; + } + + auto error = result.error ().value (); + LogMessage (LogLevel::WARN, "Read config failed with error: " + error.what ()); + return false; +} +} + +template <> +struct rfl::Reflector { + using ReflType = std::vector; + + static ConfigValue StringToConfigEnum(const std::string& value) { + ConfigValue ret = {}; + if (Config::ConfigManager::ConfigKeyboardButtons.contains (value)) { + usingKeyboard = true; + ret.type = EnumType::keycode; + ret.keycode = Config::ConfigManager::ConfigKeyboardButtons.at (value); + return ret; + } + + if (Config::ConfigManager::ConfigControllerButtons.contains (value)) { + usingController = true; + ret.type = EnumType::button; + ret.button = Config::ConfigManager::ConfigControllerButtons.at (value); + return ret; + } + + if (Config::ConfigManager::ConfigControllerAXIS.contains (value)) { + usingController = true; + ret.type = EnumType::axis; + ret.axis = Config::ConfigManager::ConfigControllerAXIS.at (value); + return ret; + } + + if (Config::ConfigManager::ConfigMouseScroll.contains (value)) { + usingMouse = true; + ret.type = EnumType::scroll; + ret.scroll = Config::ConfigManager::ConfigMouseScroll.at (value); + return ret; + } + + LogMessage(LogLevel::ERROR, "Unknown key config value: {}", value); + throw std::exception(std::format ("Unknown key config value: {}", value).c_str()); + } + + static Keybindings to(const ReflType& value) { + Keybindings result {}; + result.buttons.fill (SDL_GAMEPAD_BUTTON_INVALID); + for (const auto& key : value) { + const auto config = StringToConfigEnum(key); + switch (config.type) { + case EnumType::keycode: + LogMessage (LogLevel::DEBUG, "config {} type=keycode value={}", key, static_cast(config.keycode)); + for (auto &keycode : result.keycodes) { + if (keycode == 0) { + keycode = config.keycode; + break; + } + } + break; + case EnumType::button: + LogMessage(LogLevel::DEBUG, "config {} type=button value={}", key, static_cast(config.button)); + for (auto &button : result.buttons) { + if (button == SDL_GAMEPAD_BUTTON_INVALID) { + button = config.button; + break; + } + } + break; + case EnumType::axis: + LogMessage (LogLevel::DEBUG, "config {} type=axis value={}", key, static_cast(config.axis)); + for (auto &axis : result.axis) { + if (axis == SDLAxis::SDL_AXIS_NULL) { + axis = config.axis; + break; + } + } + break; + case EnumType::scroll: + LogMessage (LogLevel::DEBUG, "config {} type=scroll value={}", key, static_cast(config.scroll)); + for (auto &scroll : result.scroll) { + if (scroll == Scroll::MOUSE_SCROLL_INVALID) { + scroll = config.scroll; + break; + } + } + break; + case EnumType::none: + default: + throw std::exception("Invalid keybinding type"); + } + } + return result; + } +}; \ No newline at end of file diff --git a/src/config.h b/src/config.h new file mode 100644 index 0000000..be682de --- /dev/null +++ b/src/config.h @@ -0,0 +1,481 @@ +#pragma once + +#include +#include +#include +#include + +#include "poll.h" + +namespace Config { + +using chassisIdLimit = rfl::Validator>>; +struct amauthConfig { + std::string server = "127.0.0.1"; + std::string port = "54430"; + chassisIdLimit chassis_id = "284111080000"; + std::string shop_id = "TAIKO ARCADE LOADER"; + std::string game_ver = "00.00"; + std::string country_code = "JPN"; + + std::string full_address() const { + auto result = server + (port.empty() ? "" : ":" + port); + if (result.size() > 255) { + result.resize(255); + } + return result; + } + + std::string place_id() const { + // Truncate to max 15 characters + auto result = country_code + "0FF0"; + if (result.size() > 15) { + result.resize(15); + } + return result; + } +}; + +using patchVersions = rfl::Literal<"auto", "JPN00", "JPN08", "JPN39", "CHN00">; + +struct patchesConfig { + patchVersions version{"auto"}; + bool unlock_songs = true; + bool local_files = true; + struct chn00Config { + bool fix_language = false; + bool demo_movie = true; + bool mode_collabo025 = false; + bool mode_collabo026 = false; + }; + chn00Config chn00; +}; + +struct emulationConfig { + bool usio = true; + bool card_reader = true; + bool accept_invalid = false; + bool qr = true; +}; + +struct graphicsConfig { + bool windowed = false; + bool cursor = true; + struct resConfig { + int x = 1920; + int y = 1080; + }; + resConfig res; + bool vsync = false; + float model_res_rate = 1.0f; +}; + +struct audioConfig { + bool real = true; + bool wasapi_shared = true; + bool asio = false; + std::string asio_driver = "ASIO4ALL v2"; +}; + +struct qrConfig { + std::string image_path = ""; + struct qrDataConfig { + std::string serial = ""; + int type = 0; + std::vector song_no; + }; + qrDataConfig data; +}; + +struct controllerConfig { + int wait_period = 0; + bool analog_input = false; + bool global_keyboard = false; +}; + +struct keyboardConfig { + bool auto_ime = true; + bool jp_layout = false; +}; + +struct layeredfsConfig { + bool enabled = false; +}; + +using logLevels = rfl::Literal<"NONE", "ERROR", "WARN", "INFO", "DEBUG", "HOOKS">; + +struct loggingConfig { + logLevels log_level{ "INFO"}; + bool log_to_file = true; + std::string log_path = "TaikoArcadeLoader.log"; +}; + +struct globalConfig { + amauthConfig amauth; + patchesConfig patches; + emulationConfig emulation; + graphicsConfig graphics; + audioConfig audio; + qrConfig qr; + controllerConfig controller; + keyboardConfig keyboard; + layeredfsConfig layeredfs; + loggingConfig logging; +}; + +struct keybindingConfig { + rfl::Rename<"EXIT", Keybindings> exit = Keybindings{.keycodes = {VK_ESCAPE}}; + rfl::Rename<"TEST", Keybindings> test = Keybindings{.keycodes = {VK_F1}}; + rfl::Rename<"SERVICE", Keybindings> service = Keybindings{.keycodes = {VK_F2}}; + rfl::Rename<"DEBUG_UP", Keybindings> debug_up = Keybindings{.keycodes = {VK_UP}}; + rfl::Rename<"DEBUG_DOWN", Keybindings> debug_down = Keybindings{.keycodes = {VK_DOWN}}; + rfl::Rename<"DEBUG_ENTER", Keybindings> debug_enter = Keybindings{.keycodes = {VK_RETURN}}; + rfl::Rename<"COIN_ADD", Keybindings> coin_add = Keybindings{.keycodes = {VK_RETURN}, .buttons = {SDL_GAMEPAD_BUTTON_START}}; + rfl::Rename<"CARD_INSERT_1", Keybindings> card_insert_1 = Keybindings{.keycodes = {'P'}}; + rfl::Rename<"CARD_INSERT_2", Keybindings> card_insert_2 = Keybindings{.keycodes = {}}; + rfl::Rename<"QR_DATA_READ", Keybindings> qr_data_read = Keybindings{.keycodes = {'Q'}}; + rfl::Rename<"QR_IMAGE_READ", Keybindings> qr_image_read = Keybindings{.keycodes = {'W'}}; + rfl::Rename<"P1_LEFT_BLUE", Keybindings> p1_left_blue = Keybindings{.keycodes = {'D'}, .axis = {SDLAxis::SDL_AXIS_LEFT_DOWN}}; + rfl::Rename<"P1_LEFT_RED", Keybindings> p1_left_red = Keybindings{.keycodes = {'F'}, .axis = {SDLAxis::SDL_AXIS_LEFT_RIGHT}}; + rfl::Rename<"P1_RIGHT_RED", Keybindings> p1_right_red = Keybindings{.keycodes = {'J'}, .axis = {SDLAxis::SDL_AXIS_RIGHT_RIGHT}}; + rfl::Rename<"P1_RIGHT_BLUE", Keybindings> p1_right_blue = Keybindings{.keycodes = {'K'}, .axis = {SDLAxis::SDL_AXIS_RIGHT_DOWN}}; + rfl::Rename<"P2_LEFT_BLUE", Keybindings> p2_left_blue = Keybindings{.keycodes = {'Z'}}; + rfl::Rename<"P2_LEFT_RED", Keybindings> p2_left_red = Keybindings{.keycodes = {'X'}}; + rfl::Rename<"P2_RIGHT_RED", Keybindings> p2_right_red = Keybindings{.keycodes = {'C'}}; + rfl::Rename<"P2_RIGHT_BLUE", Keybindings> p2_right_blue = Keybindings{.keycodes = {'V'}}; + rfl::Skip usingKeyboard; + rfl::Skip usingMouse; + rfl::Skip usingController; +}; + +class ConfigManager { +public: + inline static const std::map 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}, +}; + inline static const std::map 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}, +}; + + inline static std::map ConfigKeyboardButtons{}; + + inline static const std::map ConfigControllerButtons = { + {"SDL_A", SDL_GAMEPAD_BUTTON_SOUTH}, + {"SDL_B", SDL_GAMEPAD_BUTTON_EAST}, + {"SDL_X", SDL_GAMEPAD_BUTTON_WEST}, + {"SDL_Y", SDL_GAMEPAD_BUTTON_NORTH}, + {"SDL_BACK", SDL_GAMEPAD_BUTTON_BACK}, + {"SDL_GUIDE", SDL_GAMEPAD_BUTTON_GUIDE}, + {"SDL_START", SDL_GAMEPAD_BUTTON_START}, + {"SDL_LSTICK_PRESS", SDL_GAMEPAD_BUTTON_LEFT_STICK}, + {"SDL_RSTICK_PRESS", SDL_GAMEPAD_BUTTON_RIGHT_STICK}, + {"SDL_LSHOULDER", SDL_GAMEPAD_BUTTON_LEFT_SHOULDER}, + {"SDL_RSHOULDER", SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER}, + {"SDL_DPAD_UP", SDL_GAMEPAD_BUTTON_DPAD_UP}, + {"SDL_DPAD_DOWN", SDL_GAMEPAD_BUTTON_DPAD_DOWN}, + {"SDL_DPAD_LEFT", SDL_GAMEPAD_BUTTON_DPAD_LEFT}, + {"SDL_DPAD_RIGHT", SDL_GAMEPAD_BUTTON_DPAD_RIGHT}, + {"SDL_MISC", SDL_GAMEPAD_BUTTON_MISC1}, + {"SDL_PADDLE1", SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1}, + {"SDL_PADDLE2", SDL_GAMEPAD_BUTTON_LEFT_PADDLE1}, + {"SDL_PADDLE3", SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2}, + {"SDL_PADDLE4", SDL_GAMEPAD_BUTTON_LEFT_PADDLE2}, + {"SDL_TOUCHPAD", SDL_GAMEPAD_BUTTON_TOUCHPAD}, + }; + inline static const std::map ConfigControllerAXIS = { + {"SDL_LSTICK_LEFT", SDLAxis::SDL_AXIS_LEFT_LEFT}, {"SDL_LSTICK_UP", SDLAxis::SDL_AXIS_LEFT_UP}, {"SDL_LSTICK_DOWN", SDLAxis::SDL_AXIS_LEFT_DOWN}, + {"SDL_LSTICK_RIGHT", SDLAxis::SDL_AXIS_LEFT_RIGHT}, {"SDL_RSTICK_LEFT", SDLAxis::SDL_AXIS_RIGHT_LEFT}, {"SDL_RSTICK_UP", SDLAxis::SDL_AXIS_RIGHT_UP}, + {"SDL_RSTICK_DOWN", SDLAxis::SDL_AXIS_RIGHT_DOWN}, {"SDL_RSTICK_RIGHT", SDLAxis::SDL_AXIS_RIGHT_RIGHT}, {"SDL_LTRIGGER", SDLAxis::SDL_AXIS_LTRIGGER_DOWN}, + {"SDL_RTRIGGER", SDLAxis::SDL_AXIS_RTRIGGER_DOWN}, + }; + inline static const std::map ConfigMouseScroll = { + {"SCROLL_UP", Scroll::MOUSE_SCROLL_UP}, + {"SCROLL_DOWN", Scroll::MOUSE_SCROLL_DOWN}, + }; + + // Singleton pattern for global access + static ConfigManager& instance() { + static ConfigManager instance; // Guaranteed to be destroyed, instantiated on first use + return instance; + } + + static bool validateConfigfile(std::string path); + + // Load configuration from a file (deserialization happens here) + bool loadConfig(); + + // Accessor methods + const globalConfig& getConfig() const { return config; } + + // To access specific parts of the config + const amauthConfig& getAmauthConfig() const { return config.amauth; } + const patchesConfig& getPatchesConfig() const { return config.patches; } + const emulationConfig& getEmulationConfig() const { return config.emulation; } + const graphicsConfig& getGraphicsConfig() const { return config.graphics; } + const audioConfig& getAudioConfig() const { return config.audio; } + const qrConfig& getQrConfig(); + const controllerConfig& getControllerConfig() const { return config.controller; } + const keyboardConfig& getKeyboardConfig() const { return config.keyboard; } + const layeredfsConfig& getLayeredFsConfig() const { return config.layeredfs; } + const loggingConfig& getLoggingConfig() const { return config.logging; } + const keybindingConfig& getKeyBindings() const { return keyBindings; } + +private: + + ConfigManager(); + ~ConfigManager() = default; + + // Prevent copy/move + ConfigManager(const ConfigManager&) = delete; + ConfigManager& operator=(const ConfigManager&) = delete; + + bool loadKeyBindings(); + bool updateQrConfig(); + + globalConfig config; + keybindingConfig keyBindings; + bool isLoaded; + + // Mutex for thread safety (if needed) + mutable std::mutex mutex; +}; +} diff --git a/src/configValidator.cpp b/src/configValidator.cpp new file mode 100644 index 0000000..eae2327 --- /dev/null +++ b/src/configValidator.cpp @@ -0,0 +1,21 @@ +#include +#include + +#include "config.h" + + +int main(int argc, char **argv) { + if (argc < 2) { + std::cerr << "Usage: " << argv[0] << " " << std::endl; + return 1; + } + + std::string fullPath = argv[1]; + if (!Config::ConfigManager::validateConfigfile(fullPath)) { + std::cerr << "Config file is invalid" << std::endl; + return 1; + } + + std::cout << "Config file is valid" << std::endl; + return 0; +} \ No newline at end of file diff --git a/src/dllmain.cpp b/src/dllmain.cpp index 7556740..673663c 100644 --- a/src/dllmain.cpp +++ b/src/dllmain.cpp @@ -4,6 +4,7 @@ #include "patches/patches.h" #include "poll.h" #include "logger.h" +#include "config.h" #include auto gameVersion = GameVersion::UNKNOWN; @@ -11,35 +12,36 @@ std::vector plugins; u64 song_data_size = 1024 * 1024 * 64; void *song_data; -std::string server = "127.0.0.1"; +/*std::string server = "127.0.0.1"; std::string port = "54430"; std::string chassisId = "284111080000"; std::string shopId = "TAIKO ARCADE LOADER"; std::string gameVerNum = "00.00"; std::string countryCode = "JPN"; char fullAddress[256] = {}; -char placeId[16] = {}; +char placeId[16] = {};*/ char accessCode1[21] = "00000000000000000001"; char accessCode2[21] = "00000000000000000002"; char chipId1[33] = "00000000000000000000000000000001"; char chipId2[33] = "00000000000000000000000000000002"; -bool windowed = false; -bool autoIme = true; -bool jpLayout = false; -bool cursor = true; -bool emulateUsio = true; -bool emulateCardReader = true; -bool emulateQr = true; -bool acceptInvalidCards = false; -bool localFiles = true; -HKL currentLayout = nullptr; -i32 xRes = 1920; -i32 yRes = 1080; -bool vsync = false; +bool windowed = Config::ConfigManager::instance ().getGraphicsConfig ().windowed; +bool autoIme = Config::ConfigManager::instance ().getKeyboardConfig ().auto_ime; +bool jpLayout = Config::ConfigManager::instance ().getKeyboardConfig ().jp_layout; +bool cursor = Config::ConfigManager::instance ().getGraphicsConfig ().cursor; +bool emulateUsio = Config::ConfigManager::instance ().getEmulationConfig ().usio; +bool emulateCardReader = Config::ConfigManager::instance ().getEmulationConfig ().card_reader; +bool emulateQr = Config::ConfigManager::instance ().getEmulationConfig ().qr; +bool acceptInvalidCards = Config::ConfigManager::instance ().getEmulationConfig ().accept_invalid; +bool localFiles = Config::ConfigManager::instance ().getPatchesConfig ().local_files; -std::string logLevelStr = "INFO"; -bool logToFile = true; -std::string logPath = "TaikoArcadeLoader.log"; +HKL currentLayout = nullptr; +i32 xRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.x; +i32 yRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.y; +bool vsync = Config::ConfigManager::instance ().getGraphicsConfig ().vsync; + +std::string logLevelStr = Config::ConfigManager::instance ().getLoggingConfig ().log_level.name (); +bool logToFile = Config::ConfigManager::instance ().getLoggingConfig ().log_to_file; +std::string logPath = Config::ConfigManager::instance ().getLoggingConfig ().log_path; HWND hGameWnd; FAST_HOOK (i32, ShowMouse, PROC_ADDRESS ("user32.dll", "ShowCursor"), bool) { return originalShowMouse.stdcall (true); } @@ -64,7 +66,7 @@ FAST_HOOK (HWND, CreateWindow, PROC_ADDRESS ("user32.dll", "CreateWindowExW"), D i32 X, i32 Y, i32 nWidth, i32 nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam) { if (lpWindowName != nullptr) { if (wcscmp (lpWindowName, L"Taiko") == 0) { - if (windowed) dwStyle = WS_TILEDWINDOW ^ WS_MAXIMIZEBOX ^ WS_THICKFRAME; + if (Config::ConfigManager::instance ().getGraphicsConfig ().windowed) dwStyle = WS_TILEDWINDOW ^ WS_MAXIMIZEBOX ^ WS_THICKFRAME; hGameWnd = originalCreateWindow.stdcall (dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); @@ -99,12 +101,12 @@ FAST_HOOK (i32, ssleay_Shutdown, PROC_ADDRESS ("ssleay32.dll", "SSL_shutdown")) FAST_HOOK (i64, UsbFinderInitialize, PROC_ADDRESS ("nbamUsbFinder.dll", "nbamUsbFinderInitialize")) { return 0; } FAST_HOOK (i64, UsbFinderRelease, PROC_ADDRESS ("nbamUsbFinder.dll", "nbamUsbFinderRelease")) { return 0; } FAST_HOOK (i64, UsbFinderGetSerialNumber, PROC_ADDRESS ("nbamUsbFinder.dll", "nbamUsbFinderGetSerialNumber"), i32 a1, char *a2) { - strcpy (a2, chassisId.c_str ()); + strcpy (a2, Config::ConfigManager::instance ().getAmauthConfig ().chassis_id.value ().c_str ()); return 0; } FAST_HOOK (i32, ws2_getaddrinfo, PROC_ADDRESS ("ws2_32.dll", "getaddrinfo"), const char *node, char *service, void *hints, void *out) { - return originalws2_getaddrinfo.stdcall (server.c_str (), service, hints, out); + return originalws2_getaddrinfo.stdcall (Config::ConfigManager::instance ().getAmauthConfig ().server.c_str (), service, hints, out); } void @@ -176,10 +178,10 @@ DllMain (HMODULE module, const DWORD reason, LPVOID reserved) { InitializeLogger (GetLogLevel (logLevelStr), logToFile, logPath); patches::Timer::Init (); - LogMessage (LogLevel::INFO, "Loading config..."); + // LogMessage (LogLevel::INFO, "Loading config..."); - std::string version = "auto"; - const std::filesystem::path configPath = std::filesystem::current_path () / "config.toml"; + std::string version = Config::ConfigManager::instance ().getPatchesConfig ().version.name (); + /*const std::filesystem::path configPath = std::filesystem::current_path () / "config.toml"; const std::unique_ptr config_ptr (openConfig (configPath), toml_free); if (config_ptr) { const toml_table_t *config = config_ptr.get (); @@ -229,7 +231,7 @@ DllMain (HMODULE module, const DWORD reason, LPVOID reserved) { logToFile = readConfigBool (logging, "log_to_file", logToFile); logPath = readConfigString (logging, "log_path", logPath); } - } + }*/ SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_UNAWARE); auto activeWindow = GetActiveWindow(); @@ -263,6 +265,7 @@ DllMain (HMODULE module, const DWORD reason, LPVOID reserved) { if (yRes * 16 > xRes * 9) yRes = (int)(xRes * 9.0 / 16.0); else if (yRes * 16 < xRes * 9) xRes = (int)(yRes * 16.0 / 9.0); } + Config::ConfigManager::instance ().setRes (xRes, yRes); LogMessage (LogLevel::INFO, "Scale Rate: x={} y={}", horizontalScale, verticalScale); LogMessage (LogLevel::INFO, "Boot with {} mode ({}x{})", windowed ? "window" : "fullscreen", xRes, yRes); diff --git a/src/helpers.cpp b/src/helpers.cpp index 0a05170..3efaf68 100644 --- a/src/helpers.cpp +++ b/src/helpers.cpp @@ -1,7 +1,7 @@ #include #include "helpers.h" -static void +/*static void toml_myfree (void *p) { if (p) free (p); } @@ -108,7 +108,7 @@ readConfigIntArray (const toml_table_t *table, const std::string &key, std::vect } return ret; -} +}*/ std::wstring replace (const std::wstring orignStr, const std::wstring &oldStr, const std::wstring &newStr) { diff --git a/src/helpers.h b/src/helpers.h index 86a110c..8dd72ae 100644 --- a/src/helpers.h +++ b/src/helpers.h @@ -9,9 +9,7 @@ // ReSharper disable once CppUnusedIncludeDirective #include #include -#include #include -#include #include #include "constants.h" #include "logger.h" @@ -168,13 +166,13 @@ const HMODULE MODULE_HANDLE = GetModuleHandle (nullptr); #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 *openConfig (const std::filesystem::path &path); toml_table_t *openConfigSection (const toml_table_t *config, const std::string §ionName); bool readConfigBool (const toml_table_t *table, const std::string &key, bool notFoundValue); i64 readConfigInt (const toml_table_t *table, const std::string &key, i64 notFoundValue); double readConfigDouble (const toml_table_t *table, const std::string &key, const double notFoundValue); std::string readConfigString (const toml_table_t *table, const std::string &key, const std::string ¬FoundValue); -std::vector readConfigIntArray (const toml_table_t *table, const std::string &key, std::vector notFoundValue); +std::vector readConfigIntArray (const toml_table_t *table, const std::string &key, std::vector notFoundValue);*/ std::wstring replace (const std::wstring orignStr, const std::wstring &oldStr, const std::wstring &newStr); std::string replace (const std::string orignStr, const std::string &oldStr, const std::string &newStr); const char *GameVersionToString (GameVersion version); diff --git a/src/patches/amauth.cpp b/src/patches/amauth.cpp index 6b23909..8865399 100644 --- a/src/patches/amauth.cpp +++ b/src/patches/amauth.cpp @@ -1,22 +1,22 @@ #include #include "helpers.h" #include -#include #include #include +#include "config.h" /* * Reference: https://gitea.tendokyu.moe/Hay1tsme/bananatools/src/branch/master/amcus/iauth.c * https://github.com/BroGamer4256/TaikoArcadeLoader/blob/master/plugins/amauth/dllmain.cpp */ -extern std::string server; -extern std::string chassisId; -extern std::string shopId; -extern std::string gameVerNum; -extern std::string countryCode; -extern char fullAddress[256]; -extern char placeId[16]; +static std::string server = Config::ConfigManager::instance ().getAmauthConfig ().server; +static std::string chassisId = Config::ConfigManager::instance ().getAmauthConfig ().chassis_id.value (); +static std::string shopId = Config::ConfigManager::instance ().getAmauthConfig ().shop_id; +static std::string gameVerNum = Config::ConfigManager::instance ().getAmauthConfig ().game_ver; +static std::string countryCode = Config::ConfigManager::instance ().getAmauthConfig ().country_code; +static std::string fullAddress = Config::ConfigManager::instance ().getAmauthConfig ().full_address(); +static std::string placeId = Config::ConfigManager::instance ().getAmauthConfig ().place_id(); namespace patches::AmAuth { @@ -379,10 +379,10 @@ public: strcpy_s (version->game_id, "SBWY"); strcpy_s (version->game_ver, "12.20"); strcpy_s (version->game_cd, "S121"); - strcpy_s (version->cacfg_game_ver, gameVerNum.c_str ()); + strcpy_s (version->cacfg_game_ver, sizeof(version->cacfg_game_ver), gameVerNum.c_str ()); strcpy_s (version->game_board_type, "0"); strcpy_s (version->game_board_id, "PCB"); - strcpy_s (version->auth_url, fullAddress); + strcpy_s (version->auth_url, sizeof(version->auth_url), fullAddress.c_str ()); return 0; } @@ -392,11 +392,11 @@ public: virtual i32 IAuth_GetAuthServerResp (amcus_auth_server_resp_t *resp) { memset (resp, 0, sizeof (*resp)); - strcpy_s (resp->uri, fullAddress); - strcpy_s (resp->host, fullAddress); + strcpy_s (resp->uri, sizeof(resp->uri) , fullAddress.c_str ()); + strcpy_s (resp->host, sizeof(resp->host), fullAddress.c_str ()); - strcpy_s (resp->shop_name, shopId.c_str ()); - strcpy_s (resp->shop_nickname, shopId.c_str ()); + strcpy_s (resp->shop_name, sizeof(resp->shop_name), shopId.c_str ()); + strcpy_s (resp->shop_nickname, sizeof(resp->shop_nickname), shopId.c_str ()); strcpy_s (resp->region0, "01035"); @@ -404,9 +404,9 @@ public: strcpy_s (resp->region_name1, "X"); strcpy_s (resp->region_name2, "Y"); strcpy_s (resp->region_name3, "Z"); - strcpy_s (resp->place_id, placeId); + strcpy_s (resp->place_id, sizeof(resp->place_id), placeId.c_str ()); strcpy_s (resp->setting, ""); - strcpy_s (resp->country, countryCode.c_str ()); + strcpy_s (resp->country, sizeof(resp->country), countryCode.c_str ()); strcpy_s (resp->timezone, "+0900"); strcpy_s (resp->res_class, "PowerOnResponseVer3"); return 0; @@ -424,7 +424,7 @@ public: strcpy_s (arr->shop_name_en, sizeof (arr->shop_name_en), shopId.c_str ()); strcpy_s (arr->shop_nickname, sizeof (arr->shop_nickname), shopId.c_str ()); strcpy_s (arr->shop_nickname_en, sizeof (arr->shop_nickname_en), shopId.c_str ()); - strcpy_s (arr->place_id, sizeof (arr->place_id), placeId); + strcpy_s (arr->place_id, sizeof (arr->place_id), placeId.c_str ()); strcpy_s (arr->country_cd, sizeof (arr->country_cd), countryCode.c_str ()); strcpy_s (arr->area0, sizeof (arr->area0), "008"); @@ -447,8 +447,8 @@ public: strcpy_s (arr->url_charge, sizeof (arr->url_charge), "http://127.0.0.1/charge/"); strcpy_s (arr->url_file, sizeof (arr->url_file), "http://127.0.0.1/file/"); - strcpy_s (arr->url_url1, sizeof (arr->url_url1), fullAddress); - strcpy_s (arr->url_url2, sizeof (arr->url_url2), fullAddress); + strcpy_s (arr->url_url1, sizeof (arr->url_url1), fullAddress.c_str ()); + strcpy_s (arr->url_url2, sizeof (arr->url_url2), fullAddress.c_str ()); strcpy_s (arr->url_url3, sizeof (arr->url_url3), "http://127.0.0.1/url3/"); return 0; } diff --git a/src/patches/audio.cpp b/src/patches/audio.cpp index 00842ba..22f53ea 100644 --- a/src/patches/audio.cpp +++ b/src/patches/audio.cpp @@ -1,6 +1,7 @@ #include "constants.h" #include "helpers.h" #include "patches.h" +#include "config.h" #include "../Windows/MinimumLatencyAudioClient.h" extern GameVersion gameVersion; @@ -19,10 +20,10 @@ typedef struct nusc_init_config { void *wasapi_audioSes; } nusc_init_config_t; -bool real = true; -bool wasapiShared = true; -bool asio = false; -std::string asioDriver; +bool wasapiShared = Config::ConfigManager::instance ().getAudioConfig ().wasapi_shared; +bool asio = Config::ConfigManager::instance ().getAudioConfig ().asio; +std::string asioDriver = Config::ConfigManager::instance ().getAudioConfig ().asio_driver; +bool real = Config::ConfigManager::instance ().getAudioConfig ().real; float volumeRate = 0.0f; @@ -54,7 +55,7 @@ FAST_HOOK_DYNAMIC (u64, NuscBusVolume, u64 a1, u64 a2, float a3) { } void -SetVolumeRate (float rate) { +SetVolumeRate (const float rate) { volumeRate = rate; } @@ -78,17 +79,16 @@ void Init () { LogMessage (LogLevel::INFO, "Init Audio patches"); - const auto configPath = std::filesystem::current_path () / "config.toml"; + /*const auto configPath = std::filesystem::current_path () / "config.toml"; const std::unique_ptr config_ptr (openConfig (configPath), toml_free); if (config_ptr) { if (const auto audio = openConfigSection (config_ptr.get (), "audio")) { - real = readConfigBool (audio, "real", real); wasapiShared = readConfigBool (audio, "wasapi_shared", wasapiShared); asio = readConfigBool (audio, "asio", asio); asioDriver = readConfigString (audio, "asio_driver", asioDriver); } - } + }*/ if (real) ReduceAudioLatency (); diff --git a/src/patches/language.cpp b/src/patches/language.cpp index 9a46dfe..65b0532 100644 --- a/src/patches/language.cpp +++ b/src/patches/language.cpp @@ -1,7 +1,8 @@ #include "constants.h" #include "helpers.h" #include "patches.h" -#include +#include + extern GameVersion gameVersion; diff --git a/src/patches/layeredfs.cpp b/src/patches/layeredfs.cpp index 05035c3..23334f5 100644 --- a/src/patches/layeredfs.cpp +++ b/src/patches/layeredfs.cpp @@ -2,8 +2,9 @@ #include "helpers.h" #include #include +#include "config.h" -bool useLayeredFs = false; +bool useLayeredFs = Config::ConfigManager::instance ().getLayeredFsConfig ().enabled; std::string datatableKey = "3530304242323633353537423431384139353134383346433246464231354534"; std::string fumenKey = "4434423946383537303842433443383030333843444132343339373531353830"; @@ -285,12 +286,12 @@ FAST_HOOK (HANDLE, CreateFileAHook, PROC_ADDRESS ("kernel32.dll", "CreateFileA") void Init () { - const auto configPath = std::filesystem::current_path () / "config.toml"; + /*const auto configPath = std::filesystem::current_path () / "config.toml"; const std::unique_ptr config_ptr (openConfig (configPath), toml_free); if (config_ptr) { if (const auto layeredFs = openConfigSection (config_ptr.get (), "layeredfs")) useLayeredFs = readConfigBool (layeredFs, "enabled", useLayeredFs); - } + }*/ register_cipher (&aes_desc); if (useLayeredFs || !beforeHandlers.empty () || !afterHandlers.empty ()) { LogMessage (LogLevel::INFO, "using LayeredFs! Data_mods={} beforHandlers={} afterHandlers={}", diff --git a/src/patches/scanner.cpp b/src/patches/scanner.cpp index 4d9abf3..1f5eabf 100644 --- a/src/patches/scanner.cpp +++ b/src/patches/scanner.cpp @@ -12,12 +12,13 @@ #define STB_IMAGE_IMPLEMENTATION #define STBI_WINDOWS_UTF8 #include "stb_image.h" +#include "config.h" extern GameVersion gameVersion; extern std::vector plugins; -extern bool acceptInvalidCards; -extern bool emulateCardReader; -extern bool emulateQr; +static bool acceptInvalidCards = Config::ConfigManager::instance ().getEmulationConfig ().accept_invalid; +static bool emulateCardReader = Config::ConfigManager::instance ().getEmulationConfig ().card_reader; +static bool emulateQr = Config::ConfigManager::instance ().getEmulationConfig ().qr; extern char accessCode1[21]; extern char accessCode2[21]; extern char chipId1[33]; @@ -384,24 +385,12 @@ namespace Qr { std::vector & ReadQRData (std::vector &buffer) { - std::string serial = ""; - u16 type = 0; - std::vector songNoes; + std::string serial = Config::ConfigManager::instance ().getQrConfig ().data.serial; + u16 type = Config::ConfigManager::instance ().getQrConfig ().data.type; + std::vector songNoes = Config::ConfigManager::instance ().getQrConfig ().data.song_no; buffer.clear (); - auto configPath = std::filesystem::current_path () / "config.toml"; - std::unique_ptr config_ptr (openConfig (configPath), toml_free); - if (config_ptr) { - auto qr = openConfigSection (config_ptr.get (), "qr"); - if (qr) { - auto data = openConfigSection (qr, "data"); - if (data) { - serial = readConfigString (data, "serial", ""); - type = (u16) readConfigInt (data, "type", 0); - songNoes = readConfigIntArray (data, "song_no", songNoes); - } - } - } + std::vector header = { 0x53, 0x31, 0x32, 0x00, 0x00, 0xFF, 0xFF, (uint8_t)serial.size (), 0x01, 0x00 }; for (uint8_t byte_data : header) buffer.push_back (byte_data); for (char word : serial) buffer.push_back ((uint8_t)word); @@ -420,18 +409,12 @@ namespace Qr { std::vector & ReadQRImage (std::vector &buffer) { - std::string imagePath = ""; + std::string imagePath = Config::ConfigManager::instance ().getQrConfig ().image_path; buffer.clear (); - auto configPath = std::filesystem::current_path () / "config.toml"; - std::unique_ptr config_ptr (openConfig (configPath), toml_free); - if (config_ptr) { - auto qr = openConfigSection (config_ptr.get (), "qr"); - if (qr) imagePath = readConfigString (qr, "image_path", ""); - } std::u8string u8PathStr (imagePath.begin (), imagePath.end ()); std::filesystem::path u8Path (u8PathStr); - if (!std::filesystem::is_regular_file (u8Path)) { + if (!is_regular_file (u8Path)) { LogMessage (LogLevel::ERROR, "Failed to open image: {} (file not found)", u8Path.string()); return buffer; } diff --git a/src/patches/testmode.cpp b/src/patches/testmode.cpp index 9aa7502..fc6abcc 100644 --- a/src/patches/testmode.cpp +++ b/src/patches/testmode.cpp @@ -4,6 +4,7 @@ #include #include #include +#include extern GameVersion gameVersion; @@ -270,7 +271,7 @@ std::wstring replaceFileName (std::wstring fullFileName, std::wstring usingLastFileName) { size_t lastPosition = fullFileName.find_last_of (L"/"); if (lastPosition == -1) return usingLastFileName; - else return fullFileName.substr(0, lastPosition) + usingLastFileName; + else return fullFileName.substr(0, lastPosition + 1) + usingLastFileName; } FAST_HOOK_DYNAMIC (void, TestModeSetMenuHook, u64 testModeLibrary, const wchar_t *lFileName) { diff --git a/src/patches/versions/CHN00.cpp b/src/patches/versions/CHN00.cpp index 110b356..31ca3c1 100644 --- a/src/patches/versions/CHN00.cpp +++ b/src/patches/versions/CHN00.cpp @@ -1,11 +1,12 @@ #include "helpers.h" #include "../patches.h" +#include "config.h" -extern std::string chassisId; -extern i32 xRes; -extern i32 yRes; -extern bool vsync; -extern bool localFiles; +static std::string chassisId = Config::ConfigManager::instance ().getAmauthConfig ().chassis_id.value (); +static const i32& xRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.x; +static const i32& yRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.y; +static bool vsync = Config::ConfigManager::instance ().getGraphicsConfig ().vsync; +static bool localFiles = Config::ConfigManager::instance ().getPatchesConfig ().local_files; namespace patches::CHN00 { int language = 0; @@ -105,11 +106,11 @@ ReplaceLeaBufferAddress (const std::vector &bufferAddresses, void *ne void Init () { LogMessage (LogLevel::INFO, "Init CHN00 patches"); - bool unlockSongs = true; - bool fixLanguage = false; - bool demoMovie = true; - bool modeCollabo025 = false; - bool modeCollabo026 = false; + bool unlockSongs = Config::ConfigManager::instance ().getPatchesConfig ().unlock_songs; + bool fixLanguage = Config::ConfigManager::instance ().getPatchesConfig ().chn00.fix_language; + bool demoMovie = Config::ConfigManager::instance ().getPatchesConfig ().chn00.demo_movie; + bool modeCollabo025 = Config::ConfigManager::instance ().getPatchesConfig ().chn00.mode_collabo025; + bool modeCollabo026 = Config::ConfigManager::instance ().getPatchesConfig ().chn00.mode_collabo026; haspBuffer = static_cast (malloc (0xD40)); memset (haspBuffer, 0, 0xD40); @@ -128,7 +129,7 @@ Init () { INSTALL_HOOK (HaspGetInfo); INSTALL_HOOK (HaspRead); - const auto configPath = std::filesystem::current_path () / "config.toml"; + /*const auto configPath = std::filesystem::current_path () / "config.toml"; const std::unique_ptr config_ptr (openConfig (configPath), toml_free); if (config_ptr) { if (const auto patches = openConfigSection (config_ptr.get (), "patches")) { @@ -140,7 +141,7 @@ Init () { modeCollabo026 = readConfigBool (chn00, "mode_collabo026", modeCollabo026); } } - } + }*/ // Apply common config patch WRITE_MEMORY (ASLR (0x1404A4ED3), i32, xRes); diff --git a/src/patches/versions/JPN00.cpp b/src/patches/versions/JPN00.cpp index 62cedbf..c4580c1 100644 --- a/src/patches/versions/JPN00.cpp +++ b/src/patches/versions/JPN00.cpp @@ -1,11 +1,11 @@ #include "helpers.h" #include "../patches.h" +#include "config.h" -extern i32 xRes; -extern i32 yRes; -extern bool vsync; -extern bool localFiles; - +static const i32& xRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.x; +static const i32& yRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.y; +static bool vsync = Config::ConfigManager::instance ().getGraphicsConfig ().vsync; +static bool localFiles = Config::ConfigManager::instance ().getPatchesConfig ().local_files; namespace patches::JPN00 { HOOK_DYNAMIC (char, AMFWTerminate, i64) { return 0; } @@ -42,14 +42,14 @@ ReplaceLeaBufferAddress (const std::vector &bufferAddresses, void *ne void Init () { LogMessage (LogLevel::INFO, "Init JNP00 patches"); - bool unlockSongs = true; + bool unlockSongs = Config::ConfigManager::instance ().getPatchesConfig ().unlock_songs; - const auto configPath = std::filesystem::current_path () / "config.toml"; + /*const auto configPath = std::filesystem::current_path () / "config.toml"; const std::unique_ptr config_ptr (openConfig (configPath), toml_free); if (config_ptr) { if (const auto patches = openConfigSection (config_ptr.get (), "patches")) unlockSongs = readConfigBool (patches, "unlock_songs", unlockSongs); - } + }*/ // Apply common config patch WRITE_MEMORY (ASLR (0x140224B2B), i32, xRes); diff --git a/src/patches/versions/JPN08.cpp b/src/patches/versions/JPN08.cpp index c2df32e..bc07616 100644 --- a/src/patches/versions/JPN08.cpp +++ b/src/patches/versions/JPN08.cpp @@ -1,13 +1,13 @@ #include "helpers.h" #include "../patches.h" +#include "config.h" extern u64 song_data_size; extern void *song_data; -extern i32 xRes; -extern i32 yRes; -extern bool vsync; -extern bool localFiles; - +static const i32& xRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.x; +static const i32& yRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.y; +static bool vsync = Config::ConfigManager::instance ().getGraphicsConfig ().vsync; +static bool localFiles = Config::ConfigManager::instance ().getPatchesConfig ().local_files; #define RDX_MOV 0x48, 0xBA #define R8_MOV 0x49, 0xB8 #define GENERATE_MOV(instruction, location) \ @@ -52,13 +52,13 @@ ReplaceLeaBufferAddress (const std::vector &bufferAddresses, void *ne void Init () { LogMessage (LogLevel::INFO, "Init JPN08 patches"); - bool unlockSongs = true; + bool unlockSongs = Config::ConfigManager::instance ().getPatchesConfig ().unlock_songs; - auto configPath = std::filesystem::current_path () / "config.toml"; + /*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); - } + }*/ // Apply common config patch WRITE_MEMORY (ASLR (0x14035FC5B), i32, xRes); diff --git a/src/patches/versions/JPN39.cpp b/src/patches/versions/JPN39.cpp index 589ab5f..e5edbd1 100644 --- a/src/patches/versions/JPN39.cpp +++ b/src/patches/versions/JPN39.cpp @@ -2,11 +2,12 @@ #include "helpers.h" #include "../patches.h" #include +#include "config.h" -extern i32 xRes; -extern i32 yRes; -extern bool vsync; -extern bool localFiles; +static const i32& xRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.x; +static const i32& yRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.y; +static bool vsync = Config::ConfigManager::instance ().getGraphicsConfig ().vsync; +static bool localFiles = Config::ConfigManager::instance ().getPatchesConfig ().local_files; namespace patches::JPN39 { int language = 0; @@ -334,10 +335,10 @@ ReplaceDatatableBufferAddresses () { void Init () { LogMessage (LogLevel::INFO, "Init JPN39 patches"); - bool unlockSongs = true; - double modelResRate = 1.0; + bool unlockSongs = Config::ConfigManager::instance ().getPatchesConfig ().unlock_songs; + double modelResRate = Config::ConfigManager::instance ().getGraphicsConfig ().model_res_rate; - auto configPath = std::filesystem::current_path () / "config.toml"; + /*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")) { @@ -346,7 +347,7 @@ Init () { if (auto graphics = openConfigSection (config_ptr.get (), "graphics")) { modelResRate = readConfigDouble (graphics, "model_res_rate", modelResRate); } - } + }*/ // Hook to get AppAccessor and ComponentAccessor INSTALL_FAST_HOOK (DeviceCheck); diff --git a/src/poll.h b/src/poll.h index cf3982d..559825b 100644 --- a/src/poll.h +++ b/src/poll.h @@ -1,5 +1,6 @@ #pragma once #include +#include #include "helpers.h" #include "bnusio.h" @@ -9,8 +10,8 @@ // #define ASYNC_IO -enum SDLAxis { - SDL_AXIS_NULL, +enum class SDLAxis { + SDL_AXIS_NULL = 0, SDL_AXIS_LEFT_LEFT, SDL_AXIS_LEFT_RIGHT, SDL_AXIS_LEFT_UP, @@ -37,16 +38,16 @@ struct SDLAxisState { float RTriggerDown; }; -enum Scroll { MOUSE_SCROLL_INVALID, MOUSE_SCROLL_UP, MOUSE_SCROLL_DOWN }; +enum class Scroll { MOUSE_SCROLL_INVALID = 0, MOUSE_SCROLL_UP, MOUSE_SCROLL_DOWN }; struct Keybindings { - u8 keycodes[255] = { '\0' }; - SDL_GamepadButton buttons[255] = { SDL_GAMEPAD_BUTTON_INVALID }; - SDLAxis axis[255] = { SDL_AXIS_NULL }; - Scroll scroll[2] = { MOUSE_SCROLL_INVALID }; + std::array keycodes = { }; + std::array buttons = { SDL_GAMEPAD_BUTTON_INVALID }; + std::array axis = {SDLAxis::SDL_AXIS_NULL }; + std::array scroll = {Scroll::MOUSE_SCROLL_INVALID }; }; -enum EnumType { none, keycode, button, axis, scroll }; +enum class EnumType { none, keycode, button, axis, scroll }; struct ConfigValue { EnumType type; @@ -64,11 +65,20 @@ struct InternalButtonState { bool Tapped; }; +struct KeyCodePair { + std::string string; + u8 keycode; +}; + +struct MouseState { + POINT Position; + POINT RelativePosition; + bool ScrolledUp; + bool ScrolledDown; +} inline currentMouseState, lastMouseState; + bool InitializePoll (HWND windowHandle); void DisposePoll (); -void SetKeyboardButtons (); -ConfigValue StringToConfigEnum (const char *value); -void SetConfigValue (const toml_table_t *table, const char *key, Keybindings *keybind, u8 *inputState); InternalButtonState GetInternalButtonState (const Keybindings &bindings); void SetRumble (int left, int right, int length); diff --git a/src/pollasync.cpp b/src/pollasync.cpp index 4b7bed2..c466ebb 100644 --- a/src/pollasync.cpp +++ b/src/pollasync.cpp @@ -1,19 +1,18 @@ #include "poll.h" #ifdef ASYNC_IO -#include "polldef.h" #define SDL_MAIN_NOIMPL #include -extern bool jpLayout; -extern int exited; -extern u8 inputState; +#include "config.h" + +static bool jpLayout = Config::ConfigManager::instance ().getKeyboardConfig ().jp_layout; +static bool autoIme = Config::ConfigManager::instance ().getKeyboardConfig ().auto_ime; +static bool globalKeyboard = Config::ConfigManager::instance ().getControllerConfig ().global_keyboard; +static bool emulateUsio = Config::ConfigManager::instance ().getEmulationConfig ().usio; + extern float axisThreshold; -extern bool globalKeyboardInput; -extern bool autoIme; extern HKL currentLayout; -extern bool emulateUsio; -extern bool globalKeyboard; bool wndForeground = false; bool usingKeyboard = false; @@ -32,9 +31,9 @@ char currentMouseWheelDirection = 0; uint8_t mouseWheelCount[2] = { 0 }; uint8_t mouseWheelDiff[2] = { 0 }; // SDLAxisState currentControllerAxisState; -float currentControllerAxisState[SDL_AXIS_MAX] = { 0.0 }; -uint8_t controllerAxisCount[SDL_AXIS_MAX] = { 0 }; -uint8_t controllerAxisDiff[SDL_AXIS_MAX] = { 0 }; +float currentControllerAxisState[static_cast(SDLAxis::SDL_AXIS_MAX)] = { 0.0 }; +uint8_t controllerAxisCount[static_cast(SDLAxis::SDL_AXIS_MAX)] = { 0 }; +uint8_t controllerAxisDiff[static_cast(SDLAxis::SDL_AXIS_MAX)] = { 0 }; int maxCount = 1; @@ -44,81 +43,6 @@ bool flipped[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, u8 *inputState) { - 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_GAMEPAD_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: { - LogMessage (LogLevel::DEBUG, "config {} type=keycode value={}", key, (int)value.keycode); - *inputState |= 1; - 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: { - LogMessage (LogLevel::DEBUG, "config {} type=button value={}", key, (int)value.button); - *inputState |= (1 << 2); - for (int i = 0; i < std::size (key_bind->buttons); i++) { - if (key_bind->buttons[i] == SDL_GAMEPAD_BUTTON_INVALID) { - key_bind->buttons[i] = value.button; - break; - } - } - break; - } - case axis: { - LogMessage (LogLevel::DEBUG, "config {} type=axis value={}", key, (int)value.axis); - *inputState |= (1 << 2); - for (int i = 0; i < std::size (key_bind->axis); i++) { - if (key_bind->axis[i] == 0) { - key_bind->axis[i] = value.axis; - break; - } - } - break; - } - case scroll: { - LogMessage (LogLevel::DEBUG, "config {} type=scroll value={}", key, (int)value.scroll); - *inputState |= (1 << 1); - 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; HHOOK mouseHook; @@ -208,9 +132,9 @@ InitializePoll (HWND windowHandle) { wndForeground = windowHandle == GetForegroundWindow (); if (!emulateUsio) return false; - usingKeyboard = inputState & 1; - usingMouse = inputState & (1 << 1); - usingController = inputState & (1 << 2); + usingKeyboard = Config::ConfigManager::instance ().getKeyBindings ().usingKeyboard(); + usingMouse = Config::ConfigManager::instance ().getKeyBindings ().usingMouse(); + usingController = Config::ConfigManager::instance ().getKeyBindings ().usingController(); usingSDLEvent = usingMouse || usingController; atexit ([](){ if (currentLayout != nullptr) ActivateKeyboardLayout (currentLayout, KLF_SETFORPROCESS);}); @@ -324,9 +248,9 @@ CleanPoll () { if (usingController) { for (int i=0; i(SDLAxis::SDL_AXIS_MAX); i++) controllerAxisCount[i] -= (bool)controllerAxisDiff[i]; memset (controllerDiff, 0, SDL_GAMEPAD_BUTTON_COUNT); - memset (controllerAxisDiff, 0, SDL_AXIS_MAX); + memset (controllerAxisDiff, 0, static_cast(SDLAxis::SDL_AXIS_MAX)); } } @@ -413,38 +337,6 @@ DisposePoll () { 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) { @@ -482,16 +374,16 @@ GetMouseScrollDown () { bool GetMouseScrollIsDown (const Scroll scroll) { - if (scroll == MOUSE_SCROLL_UP) return GetMouseScrollUp (); + if (scroll == Scroll::MOUSE_SCROLL_UP) return GetMouseScrollUp (); else return GetMouseScrollDown (); } int maxWheelCount = 1; bool GetMouseScrollIsTapped (const Scroll scroll) { - if (scroll == MOUSE_SCROLL_INVALID) return false; - if (mouseWheelCount[scroll - 1] > 0) { - mouseWheelDiff[scroll - 1] = 1; + if (scroll == Scroll::MOUSE_SCROLL_INVALID) return false; + if (mouseWheelCount[(int)scroll - 1] > 0) { + mouseWheelDiff[(int)scroll - 1] = 1; return true; } return false; } @@ -512,64 +404,64 @@ ControllerButtonIsTapped (const SDL_GamepadButton button) { float ControllerAxisIsDown (const SDLAxis axis) { - return currentControllerAxisState[axis]; + return currentControllerAxisState[(int)axis]; } bool ControllerAxisIsTapped (const SDLAxis axis) { - if (controllerAxisCount[axis] > 0) { - controllerAxisDiff[axis] = 1; + if (controllerAxisCount[(int)axis] > 0) { + controllerAxisDiff[(int)axis] = 1; return true; } return false; } 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 (const auto keycode : bindings.keycodes) { + if (keycode == 0) continue; + if (KeyboardIsTapped (keycode)) return true; } - for (size_t i = 0; i < std::size (ConfigControllerButtons); i++) { - if (bindings.buttons[i] == SDL_GAMEPAD_BUTTON_INVALID) continue; - if (ControllerButtonIsTapped (bindings.buttons[i])) { - return true; - } + + for (const auto button : bindings.buttons) { + if (button == SDL_GAMEPAD_BUTTON_INVALID) continue; + if (ControllerButtonIsTapped (button)) return true; } - for (size_t i = 0; i < std::size (ConfigControllerAXIS); i++) { - if (bindings.axis[i] == SDL_AXIS_NULL) continue; - if (ControllerAxisIsTapped (bindings.axis[i])) { - return true; - } + + for (const auto axis : bindings.axis) { + if (axis == SDLAxis::SDL_AXIS_NULL) continue; + if (ControllerAxisIsTapped (axis)) return true; } - for (size_t i = 0; i < std::size (ConfigMouseScroll); i++) { - if (bindings.scroll[i] == MOUSE_SCROLL_INVALID) continue; - if (GetMouseScrollIsTapped (bindings.scroll[i])) { - return true; - } + + for (const auto scroll : bindings.scroll) { + if (scroll == Scroll::MOUSE_SCROLL_INVALID) continue; + if (GetMouseScrollIsTapped (scroll)) return true; } + return false; } 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 (const auto keycode : bindings.keycodes) { + if (keycode == 0) continue; + if (KeyboardIsDown (keycode)) return 1.0f; } - for (size_t i = 0; i < std::size (ConfigControllerButtons); i++) { - if (bindings.buttons[i] == SDL_GAMEPAD_BUTTON_INVALID) continue; - if (ControllerButtonIsDown (bindings.buttons[i])) return 1.0f; + + for (const auto button : bindings.buttons) { + if (button == SDL_GAMEPAD_BUTTON_INVALID) continue; + if (ControllerButtonIsDown (button)) 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 (const auto axis : bindings.axis) { + if (axis == SDLAxis::SDL_AXIS_NULL) continue; + if (float val = ControllerAxisIsDown (axis); 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; + + for (const auto scroll : bindings.scroll) { + if (scroll == Scroll::MOUSE_SCROLL_INVALID) continue; + if (GetMouseScrollIsDown (scroll)) return 1.0f; } + return 0.0f; } #endif \ No newline at end of file diff --git a/src/polldef.h b/src/polldef.h deleted file mode 100644 index e09a618..0000000 --- a/src/polldef.h +++ /dev/null @@ -1,306 +0,0 @@ -#pragma once -#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_GamepadButton button; -} ConfigControllerButtons[] = { - {"SDL_A", SDL_GAMEPAD_BUTTON_SOUTH}, - {"SDL_B", SDL_GAMEPAD_BUTTON_EAST}, - {"SDL_X", SDL_GAMEPAD_BUTTON_WEST}, - {"SDL_Y", SDL_GAMEPAD_BUTTON_NORTH}, - {"SDL_BACK", SDL_GAMEPAD_BUTTON_BACK}, - {"SDL_GUIDE", SDL_GAMEPAD_BUTTON_GUIDE}, - {"SDL_START", SDL_GAMEPAD_BUTTON_START}, - {"SDL_LSTICK_PRESS", SDL_GAMEPAD_BUTTON_LEFT_STICK}, - {"SDL_RSTICK_PRESS", SDL_GAMEPAD_BUTTON_RIGHT_STICK}, - {"SDL_LSHOULDER", SDL_GAMEPAD_BUTTON_LEFT_SHOULDER}, - {"SDL_RSHOULDER", SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER}, - {"SDL_DPAD_UP", SDL_GAMEPAD_BUTTON_DPAD_UP}, - {"SDL_DPAD_DOWN", SDL_GAMEPAD_BUTTON_DPAD_DOWN}, - {"SDL_DPAD_LEFT", SDL_GAMEPAD_BUTTON_DPAD_LEFT}, - {"SDL_DPAD_RIGHT", SDL_GAMEPAD_BUTTON_DPAD_RIGHT}, - {"SDL_MISC", SDL_GAMEPAD_BUTTON_MISC1}, - {"SDL_PADDLE1", SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1}, - {"SDL_PADDLE2", SDL_GAMEPAD_BUTTON_LEFT_PADDLE1}, - {"SDL_PADDLE3", SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2}, - {"SDL_PADDLE4", SDL_GAMEPAD_BUTTON_LEFT_PADDLE2}, - {"SDL_TOUCHPAD", SDL_GAMEPAD_BUTTON_TOUCHPAD}, -}; - -struct { - 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 From 685e6d6d093fb98bc89d873b7cef20abe044ead4 Mon Sep 17 00:00:00 2001 From: ptmaster Date: Fri, 24 Jan 2025 01:52:11 +0800 Subject: [PATCH 2/5] fix missing function | scanner original use fasthook --- src/config.h | 5 +++++ src/patches/scanner.cpp | 12 ++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/config.h b/src/config.h index be682de..7d3388c 100644 --- a/src/config.h +++ b/src/config.h @@ -459,6 +459,11 @@ public: const loggingConfig& getLoggingConfig() const { return config.logging; } const keybindingConfig& getKeyBindings() const { return keyBindings; } + void setRes(i32 x, i32 y) { + config.graphics.res.x = x; + config.graphics.res.y = y; + } + private: ConfigManager(); diff --git a/src/patches/scanner.cpp b/src/patches/scanner.cpp index 1f5eabf..1caeb05 100644 --- a/src/patches/scanner.cpp +++ b/src/patches/scanner.cpp @@ -189,19 +189,19 @@ namespace Card { return 1; } - HOOK (i64, bngrw_ReqCancelOfficial, PROC_ADDRESS ("bngrw.dll", "BngRwReqCancel"), u32 a1) { + FAST_HOOK (i64, bngrw_ReqCancelOfficial, PROC_ADDRESS ("bngrw.dll", "BngRwReqCancel"), u32 a1) { if (state != State::Disable) { state = State::Disable; patches::Plugins::UpdateStatus (StatusType::CardStatus, false); } - return originalbngrw_ReqCancelOfficial (a1); + return originalbngrw_ReqCancelOfficial.fastcall (a1); } - HOOK (u64, bngrw_ReqWaitTouchOfficial, PROC_ADDRESS ("bngrw.dll", "BngRwReqWaitTouch"), u32 a1, i32 a2, u32 a3, CallbackTouch callback, u64 a5) { + FAST_HOOK (u64, bngrw_ReqWaitTouchOfficial, PROC_ADDRESS ("bngrw.dll", "BngRwReqWaitTouch"), u32 a1, i32 a2, u32 a3, CallbackTouch callback, u64 a5) { state = State::Ready; patches::Plugins::UpdateStatus (StatusType::CardStatus, true); callbackTouch = callback; touchData = a5; - return originalbngrw_ReqWaitTouchOfficial (a1, a2, a3, Internal::AgentCallbackTouchOfficial, a5); + return originalbngrw_ReqWaitTouchOfficial.fastcall (a1, a2, a3, Internal::AgentCallbackTouchOfficial, a5); } bool @@ -237,8 +237,8 @@ namespace Card { LogMessage (LogLevel::INFO, "Init Card patches"); if (!emulateCardReader) { LogMessage (LogLevel::WARN, "[Card] Card reader emulation disabled!"); - INSTALL_HOOK (bngrw_ReqCancelOfficial); - INSTALL_HOOK (bngrw_ReqWaitTouchOfficial); + INSTALL_FAST_HOOK (bngrw_ReqCancelOfficial); + INSTALL_FAST_HOOK (bngrw_ReqWaitTouchOfficial); // patches::Plugins::InitCardReader (patches::Scanner::Card::Commit); return; } From 9be3980a11d9a1398256fd450516c3cbb99734e3 Mon Sep 17 00:00:00 2001 From: ptmaster Date: Sat, 25 Jan 2025 04:06:29 +0800 Subject: [PATCH 3/5] cleanup & banner & logger & version --- CMakeLists.txt | 19 ++- README.md | 4 - dist/config.toml | 2 +- logger.cpp | 113 +++++++++++++++++ logger.h | 123 ++++++++++++++++++ res.patch | 88 ------------- src/banner.cpp | 22 ++++ src/banner.h | 25 ++++ src/bnusio.cpp | 2 +- src/config.cpp | 11 +- src/config.h | 4 +- src/dllmain.cpp | 81 ++---------- src/helpers.cpp | 109 ---------------- src/helpers.h | 7 -- src/logger.cpp | 219 ++++++++++++++++++++++----------- src/logger.h | 135 ++++++++------------ src/patches/audio.cpp | 11 -- src/patches/layeredfs.cpp | 6 - src/patches/testmode.cpp | 4 + src/patches/timer.cpp | 7 +- src/patches/versions/CHN00.cpp | 14 --- src/patches/versions/JPN00.cpp | 7 -- src/patches/versions/JPN08.cpp | 6 - src/patches/versions/JPN39.cpp | 15 +-- 24 files changed, 531 insertions(+), 503 deletions(-) create mode 100644 logger.cpp create mode 100644 logger.h delete mode 100644 res.patch create mode 100644 src/banner.cpp create mode 100644 src/banner.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 6acea74..d2dddd6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,20 @@ if(MSVC) set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" CACHE INTERNAL "") endif() +find_package(Git REQUIRED) + +# Commands to read each needed variable +set(variablesToRead "GIT_BRANCH;GIT_SHA1;GIT_SHORTSHA1;GIT_DIRTY") +set(CMD_GIT_VERSION ${GIT_EXECUTABLE} describe --tags --dirty) + +execute_process( + COMMAND ${CMD_GIT_VERSION} + RESULT_VARIABLE GIT_VERSION_RESULT + OUTPUT_VARIABLE GIT_VERSION + ERROR_VARIABLE GIT_ERROR + OUTPUT_STRIP_TRAILING_WHITESPACE +) + # Set C and C++ standards set(CMAKE_C_STANDARD 11) set(CMAKE_CXX_STANDARD 23) @@ -24,7 +38,9 @@ endif() # 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) +add_definitions(-DNOMINMAX -DLTC_NO_PROTOTYPES -D_CRT_SECURE_NO_WARNINGS -DTAL_VERSION="${GIT_VERSION}") +MESSAGE( STATUS "Build Version = ${GIT_VERSION}.") + # Include FetchContent module include(FetchContent) @@ -161,6 +177,7 @@ set(SOURCES src/patches/versions/JPN39.cpp src/patches/versions/CHN00.cpp src/config.cpp + src/banner.cpp ) set(VALIDATOR_SOURCES diff --git a/README.md b/README.md index 48fde7a..e2634f7 100644 --- a/README.md +++ b/README.md @@ -34,12 +34,8 @@ version = "auto" # Patch version # | - JPN08: For use with Taiko JPN 08.18 # | - JPN39: For use with Taiko JPN 39.06 # | - CHN00: For use with Taiko CHN 00.32 -<<<<<<< HEAD unlock_songs = true # Self-explanatory local_files = true # Only set this to false if you're using this on a Nijiiro Cabinet, running on BNA1 -======= -unlock_songs = true ->>>>>>> 684ee61 (Several fix & optimize) [patches.chn00] # These patches are only available for version CHN00 fix_language = false # Sync test mode language to attract etc diff --git a/dist/config.toml b/dist/config.toml index 2346e8a..1141296 100644 --- a/dist/config.toml +++ b/dist/config.toml @@ -86,4 +86,4 @@ log_level = "INFO" # Log level, Can be either "NONE", "ERROR", "WARN", # | Keep this as low as possible (Info is usually more than enough) as more logging will slow down your game log_to_file = false # Log to file, set this to true to save the logs from your last session to TaikoArcadeLoader.log # |Again, if you do not have a use for this (debugging mods or whatnot), turn it off. -log_path = "logs.log" # Log file path (Can be both relative and absolute). \ No newline at end of file +log_dir = "./logs/" # Log file path (Can be both relative and absolute). \ No newline at end of file diff --git a/logger.cpp b/logger.cpp new file mode 100644 index 0000000..b024a44 --- /dev/null +++ b/logger.cpp @@ -0,0 +1,113 @@ +#include +#include +#include "logger.h" + +static Logger *loggerInstance = nullptr; +void *consoleHandle = nullptr; +std::mutex logMutex; // Mutex for thread-safe logging + +char timeStr[64]; +time_t rawTime; +tm *timeInfo; +SYSTEMTIME systemTime; + +void +InitializeLogger (const LogLevel level, const bool logToFile, const std::string& logPath) { + if (loggerInstance == nullptr) { + loggerInstance = static_cast (malloc (sizeof (Logger))); + if (consoleHandle == nullptr) consoleHandle = GetStdHandle (STD_OUTPUT_HANDLE); + } + + loggerInstance->logLevel = level; + + if (logToFile) { + loggerInstance->logFile = fopen (logPath.c_str (), "w"); // Open in write mode + if (!loggerInstance->logFile) LogMessage (LogLevel::WARN, std::string ("Failed to open TaikoArcadeLoader.log for writing.")); + } else loggerInstance->logFile = nullptr; // No file logging +} + +void +LogMessageHandler (const char *function, const char *codeFile, int codeLine, LogLevel messageLevel, const char *format, ...) { + // Return if no logger or log level is too high + if (loggerInstance == nullptr || messageLevel > loggerInstance->logLevel) return; + + // Lock for thread safety + std::lock_guard lock (logMutex); + + // Format the user-provided message + va_list args; + va_start (args, format); + int requiredSize = vsnprintf (nullptr, 0, format, args) + 1; // +1 for null terminator + std::unique_ptr buffer (new char[requiredSize]); // Allocate buffer dynamically + vsnprintf (buffer.get (), requiredSize, format, args); // Format the string + std::string formattedMessage (buffer.get ()); // Convert to std::string + va_end (args); + + // Determine log type string + std::string logType = GetLogLevelString (messageLevel); + + // Shrink function name by regex + std::string short_function (function); + std::regex re(R"(.*? (([\w<>]+::)*[\w]+( [()<>+-]+)?)\(\w+.*?\))"); + short_function = std::regex_replace (short_function, re, "$1"); + + // Remove the absolute path of the build dir + constexpr std::string_view build_dir = XSTRING (SOURCE_ROOT); + std::string_view filename = codeFile; + filename.remove_prefix (build_dir.size ()); + + // Get current time and milliseconds + SYSTEMTIME systemTime; + GetSystemTime (&systemTime); + time_t rawTime = time (nullptr); + tm *timeInfo = localtime (&rawTime); + std::ostringstream timeStamp; + timeStamp << std::put_time (timeInfo, "%Y/%m/%d %H:%M:%S") << "." << std::setw (3) << std::setfill ('0') << systemTime.wMilliseconds; + + // Construct the log message + std::ostringstream logStream; + logStream << short_function << " (" << filename << ":" << codeLine << "): " << formattedMessage; + std::string logMessage = logStream.str (); + + // Print the log message + std::cout << "[" << timeStamp.str () << "] "; // Timestamp + SetConsoleTextAttribute (consoleHandle, GetLogLevelColor (messageLevel)); // Set Level color + std::cout << logType; // Level + if (messageLevel != LogLevel::ERROR) { + SetConsoleTextAttribute (consoleHandle, FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY); // Reset console color + } + std::cout << logMessage << std::endl; // Log message + if (messageLevel == LogLevel::ERROR) { + SetConsoleTextAttribute (consoleHandle, FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY); // Reset console color + } + std::cout.flush (); // Flush to ensure immediate writing + + if (loggerInstance->logFile != nullptr) { + fprintf (loggerInstance->logFile, "[%s] %s%s\n", timeStamp.str ().c_str (), logType.c_str (), logMessage.c_str ()); + fflush (loggerInstance->logFile); // Flush to ensure immediate writing + } +} + +void +LogMessageHandler (const char *function, const char *codeFile, const int codeLine, const LogLevel messageLevel, const wchar_t *format, ...) { + const std::string utf8Message = ConvertWideToUtf8 (format); // Convert wide string to UTF-8 + + va_list args; + va_start (args, format); + LogMessageHandler (function, codeFile, codeLine, messageLevel, utf8Message.c_str (), args); // Delegate to the original handler + va_end (args); +} + +bool +EnableLogging (LogLevel messageLevel) { + return loggerInstance != nullptr && messageLevel <= loggerInstance->logLevel; +} + +void +CleanupLogger () { + if (loggerInstance != nullptr) { + if (loggerInstance->logFile) fclose (loggerInstance->logFile); + free (loggerInstance); + loggerInstance = nullptr; + } +} diff --git a/logger.h b/logger.h new file mode 100644 index 0000000..d8f5f19 --- /dev/null +++ b/logger.h @@ -0,0 +1,123 @@ +#pragma once + +#include "helpers.h" +#include +#include +#include +#include + +#define STRING(x) #x +#define XSTRING(x) STRING (x) + +enum class LogLevel { + NONE = 0, +#ifdef ERROR +#undef ERROR + ERROR, +#endif + WARN, + INFO, + DEBUG, + HOOKS +}; + +/** + * Logger Struct Used to Store Logging Preferences and State + */ +typedef struct { + LogLevel logLevel; + FILE *logFile; +} Logger; + +/* Initializes a global Logger instance. */ +void InitializeLogger (LogLevel level, bool logToFile, const std::string& logPath); + +void LogMessageHandler (const char *function, const char *codeFile, int codeLine, LogLevel messageLevel, const char *format, ...); +void LogMessageHandler (const char *function, const char *codeFile, int codeLine, LogLevel messageLevel, const wchar_t *format, ...); + +bool EnableLogging (LogLevel level); + +/* * + * Logs a message with file and line information, if the log level permits. + * + * Use template magic to replace macros and get proper typing support... + */ +template +struct LogMessage { + LogMessage (const LogLevel level, const std::string_view format, Args &&...args, + const std::source_location &loc = std::source_location::current ()) { + if (!EnableLogging (level)) return; + std::string formatted_message = std::vformat(std::string(format), std::make_format_args(args...)); + LogMessageHandler (loc.function_name (), loc.file_name (), loc.line (), level, formatted_message.c_str ()); + } + + LogMessage (const LogLevel level, const std::wstring_view format, Args &&...args, + const std::source_location &loc = std::source_location::current ()) { + if (!EnableLogging (level)) return; + std::wstring formatted_message = std::vformat(std::wstring(format), std::make_wformat_args(args...)); + LogMessageHandler (loc.function_name (), loc.file_name (), loc.line (), level, formatted_message.c_str ()); + } +}; + +/* * + * Logs a message with file and line information, if the log level permits. + */ +template <> +struct LogMessage { + LogMessage (const LogLevel level, const std::string_view format, const std::source_location &loc = std::source_location::current ()) { + LogMessageHandler (loc.function_name (), loc.file_name (), loc.line (), level, format.data ()); + } + + LogMessage (const LogLevel level, const std::wstring_view format, const std::source_location &loc = std::source_location::current ()) { + LogMessageHandler (loc.function_name (), loc.file_name (), loc.line (), level, format.data ()); + } +}; + +LogMessage (LogLevel level, std::string_view format) -> LogMessage; +LogMessage (LogLevel level, std::wstring_view format) -> LogMessage; + +template +LogMessage (LogLevel level, std::string_view format, Args &&...ts) -> LogMessage; +template +LogMessage (LogLevel level, std::wstring_view format, Args &&...ts) -> LogMessage; + +/* Converts a string to a LogLevel type. */ +inline LogLevel +GetLogLevel (const std::string &logLevelStr) { + if (logLevelStr == "DEBUG") return LogLevel::DEBUG; + else if (logLevelStr == "INFO") return LogLevel::INFO; + else if (logLevelStr == "WARN") return LogLevel::WARN; + else if (logLevelStr == "ERROR") return LogLevel::ERROR; + else if (logLevelStr == "HOOKS") return LogLevel::HOOKS; + return LogLevel::NONE; +} + +/* Converts a LogLevel type to a string for logging. */ +inline std::string +GetLogLevelString (LogLevel messageLevel) { + switch (messageLevel) { + case LogLevel::DEBUG: return "DEBUG: "; + case LogLevel::INFO: return "INFO: "; + case LogLevel::WARN: return "WARN: "; + case LogLevel::ERROR: return "ERROR: "; + case LogLevel::HOOKS: return "HOOKS: "; + default: return "NONE: "; + } +} + +/* Converts a LogLevel type to an int for colors display in the console. */ +inline int +GetLogLevelColor (const LogLevel messageLevel) { + // Colors: https://i.sstatic.net/ZG625.png + switch (messageLevel) { + case LogLevel::DEBUG: return FOREGROUND_BLUE | FOREGROUND_INTENSITY; // Pale Blue + case LogLevel::INFO: return FOREGROUND_GREEN | FOREGROUND_INTENSITY; // Pale Green + case LogLevel::WARN: return FOREGROUND_RED | FOREGROUND_GREEN; // Bright Yellow + case LogLevel::ERROR: return FOREGROUND_RED; // Bright RED + case LogLevel::HOOKS: return FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY; // Pale Purple + default: return FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY; + } +} + +/* Cleans up the logger, closing files if necessary. */ +void CleanupLogger (); diff --git a/res.patch b/res.patch deleted file mode 100644 index e2a0e1f..0000000 --- a/res.patch +++ /dev/null @@ -1,88 +0,0 @@ -diff --git a/src/config.h b/src/config.h -index be682de..7d3388c 100644 ---- a/src/config.h -+++ b/src/config.h -@@ -459,6 +459,11 @@ public: - const loggingConfig& getLoggingConfig() const { return config.logging; } - const keybindingConfig& getKeyBindings() const { return keyBindings; } - -+ void setRes(i32 x, i32 y) { -+ config.graphics.res.x = x; -+ config.graphics.res.y = y; -+ } -+ - private: - - ConfigManager(); -diff --git a/src/dllmain.cpp b/src/dllmain.cpp -index 6cb5b49..673663c 100644 ---- a/src/dllmain.cpp -+++ b/src/dllmain.cpp -@@ -265,6 +265,7 @@ DllMain (HMODULE module, const DWORD reason, LPVOID reserved) { - if (yRes * 16 > xRes * 9) yRes = (int)(xRes * 9.0 / 16.0); - else if (yRes * 16 < xRes * 9) xRes = (int)(yRes * 16.0 / 9.0); - } -+ Config::ConfigManager::instance ().setRes (xRes, yRes); - - LogMessage (LogLevel::INFO, "Scale Rate: x={} y={}", horizontalScale, verticalScale); - LogMessage (LogLevel::INFO, "Boot with {} mode ({}x{})", windowed ? "window" : "fullscreen", xRes, yRes); -diff --git a/src/patches/versions/CHN00.cpp b/src/patches/versions/CHN00.cpp -index 2d59616..31ca3c1 100644 ---- a/src/patches/versions/CHN00.cpp -+++ b/src/patches/versions/CHN00.cpp -@@ -3,8 +3,8 @@ - #include "config.h" - - static std::string chassisId = Config::ConfigManager::instance ().getAmauthConfig ().chassis_id.value (); --static i32 xRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.x; --static i32 yRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.y; -+static const i32& xRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.x; -+static const i32& yRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.y; - static bool vsync = Config::ConfigManager::instance ().getGraphicsConfig ().vsync; - static bool localFiles = Config::ConfigManager::instance ().getPatchesConfig ().local_files; - -diff --git a/src/patches/versions/JPN00.cpp b/src/patches/versions/JPN00.cpp -index 1490c8f..c4580c1 100644 ---- a/src/patches/versions/JPN00.cpp -+++ b/src/patches/versions/JPN00.cpp -@@ -2,8 +2,8 @@ - #include "../patches.h" - #include "config.h" - --static i32 xRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.x; --static i32 yRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.y; -+static const i32& xRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.x; -+static const i32& yRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.y; - static bool vsync = Config::ConfigManager::instance ().getGraphicsConfig ().vsync; - static bool localFiles = Config::ConfigManager::instance ().getPatchesConfig ().local_files; - namespace patches::JPN00 { -diff --git a/src/patches/versions/JPN08.cpp b/src/patches/versions/JPN08.cpp -index 0dac8f0..bc07616 100644 ---- a/src/patches/versions/JPN08.cpp -+++ b/src/patches/versions/JPN08.cpp -@@ -4,8 +4,8 @@ - - extern u64 song_data_size; - extern void *song_data; --static i32 xRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.x; --static i32 yRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.y; -+static const i32& xRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.x; -+static const i32& yRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.y; - static bool vsync = Config::ConfigManager::instance ().getGraphicsConfig ().vsync; - static bool localFiles = Config::ConfigManager::instance ().getPatchesConfig ().local_files; - #define RDX_MOV 0x48, 0xBA -diff --git a/src/patches/versions/JPN39.cpp b/src/patches/versions/JPN39.cpp -index 2b37ac7..e5edbd1 100644 ---- a/src/patches/versions/JPN39.cpp -+++ b/src/patches/versions/JPN39.cpp -@@ -4,8 +4,8 @@ - #include - #include "config.h" - --static i32 xRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.x; --static i32 yRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.y; -+static const i32& xRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.x; -+static const i32& yRes = Config::ConfigManager::instance ().getGraphicsConfig ().res.y; - static bool vsync = Config::ConfigManager::instance ().getGraphicsConfig ().vsync; - static bool localFiles = Config::ConfigManager::instance ().getPatchesConfig ().local_files; - diff --git a/src/banner.cpp b/src/banner.cpp new file mode 100644 index 0000000..499223f --- /dev/null +++ b/src/banner.cpp @@ -0,0 +1,22 @@ +#include "banner.h" + +namespace Banner { + +std::string +Version::getVer () { + std::string fullVersion = std::string (TAL_VERSION); + return fullVersion.substr (0, fullVersion.find("-")); +} + +Version::Version () { + // Print a cool logo with version info + std::cout << R"( )" << std::endl; + std::cout << R"( ______ _ __ ___ __ __ __ )" << std::endl; + std::cout << R"(/_ __/__ _(_) /_____ / _ | ___________ ____/ /__ / / ___ ___ ____/ /__ ____)" << std::endl; + std::cout << R"( / / / _ `/ / '_/ _ \/ __ |/ __/ __/ _ `/ _ / -_) /__/ _ \/ _ `/ _ / -_) __/)" << std::endl; + std::cout << R"(/_/ \_,_/_/_/\_\\___/_/ |_/_/ \__/\_,_/\_,_/\__/____/\___/\_,_/\_,_/\__/_/ )" << std::endl; + std::cout << std::format("{: >79}", std::format("::v{}::", TAL_VERSION)) << std::endl; + std::cout << R"( )" << std::endl; +} + +} \ No newline at end of file diff --git a/src/banner.h b/src/banner.h new file mode 100644 index 0000000..78a7d7f --- /dev/null +++ b/src/banner.h @@ -0,0 +1,25 @@ +#pragma once +#include +#include +#include + +namespace Banner { +class Version { +public: + + std::string getVer(); + + // Singleton pattern for global access + static Version& instance() { + static Version instance; // Guaranteed to be destroyed, instantiated on first use + return instance; + } + +private: + + Version(); + ~Version() = default; + +}; + +} \ No newline at end of file diff --git a/src/bnusio.cpp b/src/bnusio.cpp index 016b53e..b70f103 100644 --- a/src/bnusio.cpp +++ b/src/bnusio.cpp @@ -288,6 +288,6 @@ Update () { void Close () { // patches::Plugins::Exit (); - CleanupLogger (); + Logger::CleanupLogger (); } } // namespace bnusio diff --git a/src/config.cpp b/src/config.cpp index 3abfc7c..3e21033 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -5,6 +5,7 @@ #include #include +#include "banner.h" #include "config.h" #include "logger.h" @@ -41,7 +42,6 @@ bool ConfigManager::loadConfig () { std::lock_guard lock (mutex); - InitializeLogger (LogLevel::INFO, true, "TaikoArcadeLoader.log"); if (isLoaded) { return true; } const auto configPath = std::filesystem::current_path () / "config.toml"; @@ -88,12 +88,15 @@ ConfigManager::getQrConfig () { } ConfigManager::ConfigManager () { + Banner::Version::instance (); + Logger::InitializeLogger (LogLevel::INFO, false, ""); auto result = loadConfig (); if (!result) { LogMessage (LogLevel::ERROR, "Failed to load config file"); MessageBoxA (nullptr, "Failed to load config", nullptr, MB_OK); ExitProcess (0); } + Logger::CleanupLogger (); } bool @@ -119,8 +122,10 @@ ConfigManager::loadKeyBindings () { keyBindings.usingKeyboard = usingKeyboard; keyBindings.usingMouse = usingMouse; keyBindings.usingController = usingController; - LogMessage (LogLevel::INFO, "Finish Loading keyconfig.toml useKeyboard={} useMouse={} useController={}", - usingKeyboard ? "true" : "false", usingMouse ? "true" : "false", usingController ? "true" : "false"); + LogMessage (LogLevel::INFO, "Finish Loading keyconfig.toml"); + if (usingKeyboard) LogMessage (LogLevel::DEBUG, ">>>>> Using Keyboard!"); + if (usingMouse) LogMessage (LogLevel::DEBUG, ">>>>> Using Mouse!"); + if (usingController) LogMessage (LogLevel::DEBUG, ">>>>> Using Controller!"); return true; } diff --git a/src/config.h b/src/config.h index 7d3388c..5893259 100644 --- a/src/config.h +++ b/src/config.h @@ -106,8 +106,8 @@ using logLevels = rfl::Literal<"NONE", "ERROR", "WARN", "INFO", "DEBUG", "HOOKS" struct loggingConfig { logLevels log_level{ "INFO"}; - bool log_to_file = true; - std::string log_path = "TaikoArcadeLoader.log"; + bool log_to_file = false; + std::string log_dir = "./logs/"; }; struct globalConfig { diff --git a/src/dllmain.cpp b/src/dllmain.cpp index 673663c..26fa9d5 100644 --- a/src/dllmain.cpp +++ b/src/dllmain.cpp @@ -4,6 +4,7 @@ #include "patches/patches.h" #include "poll.h" #include "logger.h" +#include "banner.h" #include "config.h" #include @@ -12,14 +13,6 @@ std::vector plugins; u64 song_data_size = 1024 * 1024 * 64; void *song_data; -/*std::string server = "127.0.0.1"; -std::string port = "54430"; -std::string chassisId = "284111080000"; -std::string shopId = "TAIKO ARCADE LOADER"; -std::string gameVerNum = "00.00"; -std::string countryCode = "JPN"; -char fullAddress[256] = {}; -char placeId[16] = {};*/ char accessCode1[21] = "00000000000000000001"; char accessCode2[21] = "00000000000000000002"; char chipId1[33] = "00000000000000000000000000000001"; @@ -41,7 +34,7 @@ bool vsync = Config::ConfigManager::instance ().getGraphicsConfig ( std::string logLevelStr = Config::ConfigManager::instance ().getLoggingConfig ().log_level.name (); bool logToFile = Config::ConfigManager::instance ().getLoggingConfig ().log_to_file; -std::string logPath = Config::ConfigManager::instance ().getLoggingConfig ().log_path; +std::string logDir = Config::ConfigManager::instance ().getLoggingConfig ().log_dir; HWND hGameWnd; FAST_HOOK (i32, ShowMouse, PROC_ADDRESS ("user32.dll", "ShowCursor"), bool) { return originalShowMouse.stdcall (true); } @@ -175,63 +168,10 @@ DllMain (HMODULE module, const DWORD reason, LPVOID reserved) { // Init logger for loading config auto start = std::chrono::high_resolution_clock::now(); - InitializeLogger (GetLogLevel (logLevelStr), logToFile, logPath); + Logger::InitializeLogger (Logger::GetLogLevel (logLevelStr), logToFile, logDir); patches::Timer::Init (); - // LogMessage (LogLevel::INFO, "Loading config..."); - - std::string version = Config::ConfigManager::instance ().getPatchesConfig ().version.name (); - /*const std::filesystem::path configPath = std::filesystem::current_path () / "config.toml"; - const std::unique_ptr config_ptr (openConfig (configPath), toml_free); - if (config_ptr) { - const toml_table_t *config = config_ptr.get (); - if (const auto amauthConfig = openConfigSection (config, "amauth")) { - server = readConfigString (amauthConfig, "server", server); - port = readConfigString (amauthConfig, "port", port); - chassisId = readConfigString (amauthConfig, "chassis_id", chassisId); - shopId = readConfigString (amauthConfig, "shop_id", shopId); - gameVerNum = readConfigString (amauthConfig, "game_ver", gameVerNum); - countryCode = readConfigString (amauthConfig, "country_code", countryCode); - - std::strcat (fullAddress, server.c_str ()); - if (!port.empty ()) { - std::strcat (fullAddress, ":"); - std::strcat (fullAddress, port.c_str ()); - } - - std::strcat (placeId, countryCode.c_str ()); - std::strcat (placeId, "0FF0"); - } - if (const auto patches = openConfigSection (config, "patches")) { - version = readConfigString (patches, "version", version); - localFiles = readConfigBool (patches, "local_files", localFiles); - } - if (const auto emulation = openConfigSection (config, "emulation")) { - emulateUsio = readConfigBool (emulation, "usio", emulateUsio); - emulateCardReader = readConfigBool (emulation, "card_reader", emulateCardReader); - acceptInvalidCards = readConfigBool (emulation, "accept_invalid", acceptInvalidCards); - emulateQr = readConfigBool (emulation, "qr", emulateQr); - } - 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); - jpLayout = readConfigBool (keyboard, "jp_layout", jpLayout); - } - - if (const auto logging = openConfigSection (config, "logging")) { - logLevelStr = readConfigString (logging, "log_level", logLevelStr); - logToFile = readConfigBool (logging, "log_to_file", logToFile); - logPath = readConfigString (logging, "log_path", logPath); - } - }*/ + std::string version = Config::ConfigManager::instance ().getPatchesConfig ().version.name (); SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_UNAWARE); auto activeWindow = GetActiveWindow(); @@ -253,12 +193,12 @@ DllMain (HMODULE module, const DWORD reason, LPVOID reserved) { auto cyPhysical = devMode.dmPelsHeight; // Calculate the scaling factor - auto horizontalScale = (static_cast (cxPhysical) / static_cast (cxLogical)); - auto verticalScale = (static_cast (cyPhysical) / static_cast (cyLogical)); + auto hScale = (static_cast (cxPhysical) / static_cast (cxLogical)); + auto vScale = (static_cast (cyPhysical) / static_cast (cyLogical)); if (windowed) { // Game will automatically adjust scale - xRes = (int)(xRes / horizontalScale); - yRes = (int)(yRes / verticalScale); + xRes = (int)(xRes / hScale); + yRes = (int)(yRes / vScale); } else { xRes = cxLogical; yRes = cyLogical; @@ -266,9 +206,7 @@ DllMain (HMODULE module, const DWORD reason, LPVOID reserved) { else if (yRes * 16 < xRes * 9) xRes = (int)(yRes * 16.0 / 9.0); } Config::ConfigManager::instance ().setRes (xRes, yRes); - - LogMessage (LogLevel::INFO, "Scale Rate: x={} y={}", horizontalScale, verticalScale); - LogMessage (LogLevel::INFO, "Boot with {} mode ({}x{})", windowed ? "window" : "fullscreen", xRes, yRes); + LogMessage (LogLevel::INFO, "Boot with {} mode [{}(*{})x{}(*())]", windowed ? "window" : "fullscreen", xRes, hScale, yRes, vScale); if (autoIme) { currentLayout = GetKeyboardLayout (0); @@ -278,7 +216,6 @@ DllMain (HMODULE module, const DWORD reason, LPVOID reserved) { } // Update the logger with the level read from config file. - InitializeLogger (GetLogLevel (logLevelStr), logToFile, logPath); LogMessage (LogLevel::INFO, "Application started."); if (version == "auto") GetGameVersion (); diff --git a/src/helpers.cpp b/src/helpers.cpp index 3efaf68..ed75d2a 100644 --- a/src/helpers.cpp +++ b/src/helpers.cpp @@ -1,115 +1,6 @@ #include #include "helpers.h" -/*static void -toml_myfree (void *p) { - if (p) free (p); -} - -toml_table_t * -openConfig (const std::filesystem::path &path) { - if (!exists (path) || !path.has_filename ()) { - LogMessage (LogLevel::WARN, std::string (path.string ()) + ": file does not exist"); - return nullptr; - } - - std::ifstream stream (path); - if (!stream.is_open ()) { - LogMessage (LogLevel::WARN, ("Could not open " + std::string (path.string ())).c_str ()); - return nullptr; - } - - stream.seekg (0, stream.end); - const size_t length = stream.tellg (); - stream.seekg (0, stream.beg); - - const auto buf = static_cast (calloc (length + 1, sizeof (char))); - stream.read (buf, length); - - char errorBuffer[200]; - toml_table_t *config = toml_parse (buf, errorBuffer, 200); - stream.close (); - free (buf); - - if (!config) { - LogMessage (LogLevel::WARN, (path.string () + ": " + errorBuffer).c_str ()); - return nullptr; - } - - return config; -} - -toml_table_t * -openConfigSection (const toml_table_t *config, const std::string §ionName) { - toml_table_t *section = toml_table_in (config, sectionName.c_str ()); - if (!section) { - LogMessage (LogLevel::ERROR, ("Cannot find section " + sectionName).c_str ()); - return nullptr; - } - - return section; -} - -bool -readConfigBool (const toml_table_t *table, const std::string &key, const bool notFoundValue) { - const auto [ok, u] = toml_bool_in (table, key.c_str ()); - if (!ok) { - LogMessage (LogLevel::WARN, ("Could not find Boolean named " + key).c_str ()); - return notFoundValue; - } - return static_cast (u.b); -} - -i64 -readConfigInt (const toml_table_t *table, const std::string &key, const i64 notFoundValue) { - const auto [ok, u] = toml_int_in (table, key.c_str ()); - if (!ok) { - LogMessage (LogLevel::WARN, ("Could not find Int named " + key).c_str ()); - return notFoundValue; - } - return u.i; -} - -double -readConfigDouble (const toml_table_t *table, const std::string &key, const double notFoundValue) { - const auto [ok, u] = toml_double_in (table, key.c_str ()); - if (!ok) { - LogMessage (LogLevel::WARN, ("Could not find Int named " + key).c_str ()); - return notFoundValue; - } - return u.d; -} - -std::string -readConfigString (const toml_table_t *table, const std::string &key, const std::string ¬FoundValue) { - const auto [ok, u] = toml_string_in (table, key.c_str ()); - if (!ok) { - LogMessage (LogLevel::WARN, ("Could not find String named " + key).c_str ()); - return notFoundValue; - } - std::string str = u.s; - toml_myfree (u.s); - return str; -} - -std::vector -readConfigIntArray (const toml_table_t *table, const std::string &key, std::vector notFoundValue) { - const toml_array_t *array = toml_array_in (table, key.c_str ()); - if (!array) { - LogMessage (LogLevel::WARN, ("Could not find int Array named " + key).c_str ()); - return notFoundValue; - } - - std::vector ret; - for (int i = 0;; i++) { - auto [ok, u] = toml_int_at (array, i); - if (!ok) break; - ret.push_back (u.i); - } - - return ret; -}*/ - std::wstring replace (const std::wstring orignStr, const std::wstring &oldStr, const std::wstring &newStr) { size_t pos = 0; diff --git a/src/helpers.h b/src/helpers.h index 8dd72ae..8193dbc 100644 --- a/src/helpers.h +++ b/src/helpers.h @@ -166,13 +166,6 @@ const HMODULE MODULE_HANDLE = GetModuleHandle (nullptr); #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); -bool readConfigBool (const toml_table_t *table, const std::string &key, bool notFoundValue); -i64 readConfigInt (const toml_table_t *table, const std::string &key, i64 notFoundValue); -double readConfigDouble (const toml_table_t *table, const std::string &key, const double notFoundValue); -std::string readConfigString (const toml_table_t *table, const std::string &key, const std::string ¬FoundValue); -std::vector readConfigIntArray (const toml_table_t *table, const std::string &key, std::vector notFoundValue);*/ std::wstring replace (const std::wstring orignStr, const std::wstring &oldStr, const std::wstring &newStr); std::string replace (const std::string orignStr, const std::string &oldStr, const std::string &newStr); const char *GameVersionToString (GameVersion version); diff --git a/src/logger.cpp b/src/logger.cpp index b024a44..8d95a40 100644 --- a/src/logger.cpp +++ b/src/logger.cpp @@ -1,113 +1,188 @@ -#include -#include #include "logger.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include -static Logger *loggerInstance = nullptr; -void *consoleHandle = nullptr; -std::mutex logMutex; // Mutex for thread-safe logging +// Static member definitions +LogLevel Logger::s_logLevel = LogLevel::NONE; +void* Logger::s_consoleHandle = nullptr; +bool Logger::s_isInitialized = false; +std::fstream* Logger::s_logFile = nullptr; +std::mutex Logger::s_logMutex; -char timeStr[64]; -time_t rawTime; -tm *timeInfo; -SYSTEMTIME systemTime; - -void -InitializeLogger (const LogLevel level, const bool logToFile, const std::string& logPath) { - if (loggerInstance == nullptr) { - loggerInstance = static_cast (malloc (sizeof (Logger))); - if (consoleHandle == nullptr) consoleHandle = GetStdHandle (STD_OUTPUT_HANDLE); - } - - loggerInstance->logLevel = level; - - if (logToFile) { - loggerInstance->logFile = fopen (logPath.c_str (), "w"); // Open in write mode - if (!loggerInstance->logFile) LogMessage (LogLevel::WARN, std::string ("Failed to open TaikoArcadeLoader.log for writing.")); - } else loggerInstance->logFile = nullptr; // No file logging +static std::string +ConvertWideToUtf8(const wchar_t* wstr) +{ + if (!wstr) return {}; + std::wstring ws (wstr); + return {ws.begin (), ws.end ()}; } void -LogMessageHandler (const char *function, const char *codeFile, int codeLine, LogLevel messageLevel, const char *format, ...) { - // Return if no logger or log level is too high - if (loggerInstance == nullptr || messageLevel > loggerInstance->logLevel) return; +Logger::InitializeLogger(const LogLevel level, const bool logToFile, std::string logDir) +{ + if (s_isInitialized) { + return; + } + s_isInitialized = true; - // Lock for thread safety - std::lock_guard lock (logMutex); + s_logLevel = level; + + if (s_consoleHandle == nullptr) { + s_consoleHandle = GetStdHandle (STD_OUTPUT_HANDLE); + } + + if (logToFile) { + try { + const std::filesystem::path logsDir ("logs"); + if (!std::filesystem::exists (logsDir)) std::filesystem::create_directories (logsDir); + } catch (const std::exception& e) { + std::cerr << "[Logger] Failed to create logs directory: " << e.what () << std::endl; + } + + // Construct a daily log filename + const auto now = std::chrono::system_clock::now (); + const auto timeT = std::chrono::system_clock::to_time_t (now); + std::tm localTm = {}; + localtime_s (&localTm, &timeT); + + char dateFilename[256]; + // Example format: "TaikoArcadeLoader-YYYYMMDD.log" + std::strftime (dateFilename, sizeof (dateFilename), "TaikoArcadeLoader-%Y%m%d.log", &localTm); + + if (!logDir.ends_with ("/")) logDir += "/"; + const std::string fullLogPath = logDir + dateFilename; + s_logFile = new std::fstream (fullLogPath.c_str (), std::ios::out | std::ios::app); + if (!s_logFile->is_open ()) { + std::cerr << "[Logg er] Failed to open " << fullLogPath << " for writing.\n"; + s_logFile = nullptr; + } + } +} + +void +Logger::LogMessageHandler (const char* function, const char* codeFile, int codeLine, LogLevel messageLevel, const char* format, ...) { + // Return if logger uninitialized or messageLevel is more verbose than the set level + if (!s_isInitialized || messageLevel > s_logLevel) { + return; + } + + std::lock_guard lock (s_logMutex); - // Format the user-provided message va_list args; va_start (args, format); int requiredSize = vsnprintf (nullptr, 0, format, args) + 1; // +1 for null terminator - std::unique_ptr buffer (new char[requiredSize]); // Allocate buffer dynamically - vsnprintf (buffer.get (), requiredSize, format, args); // Format the string - std::string formattedMessage (buffer.get ()); // Convert to std::string + std::unique_ptr buffer (new char[requiredSize]); + vsnprintf (buffer.get (), requiredSize, format, args); + std::string formattedMessage (buffer.get()); va_end (args); - // Determine log type string - std::string logType = GetLogLevelString (messageLevel); + std::string logType = Logger::GetLogLevelString(messageLevel); - // Shrink function name by regex std::string short_function (function); - std::regex re(R"(.*? (([\w<>]+::)*[\w]+( [()<>+-]+)?)\(\w+.*?\))"); + std::regex re (R"(.*? (([\w<>]+::)*[\w]+( [()<>+-]+)?)\(\w+.*?\))"); short_function = std::regex_replace (short_function, re, "$1"); - // Remove the absolute path of the build dir constexpr std::string_view build_dir = XSTRING (SOURCE_ROOT); - std::string_view filename = codeFile; + std::string_view filename = codeFile; filename.remove_prefix (build_dir.size ()); - // Get current time and milliseconds SYSTEMTIME systemTime; GetSystemTime (&systemTime); time_t rawTime = time (nullptr); - tm *timeInfo = localtime (&rawTime); + tm* timeInfo = localtime (&rawTime); + std::ostringstream timeStamp; - timeStamp << std::put_time (timeInfo, "%Y/%m/%d %H:%M:%S") << "." << std::setw (3) << std::setfill ('0') << systemTime.wMilliseconds; + timeStamp << std::put_time (timeInfo, "%Y-%m-%d %H:%M:%S") << "." + << std::setw (3) << std::setfill ('0') << systemTime.wMilliseconds; // Construct the log message - std::ostringstream logStream; - logStream << short_function << " (" << filename << ":" << codeLine << "): " << formattedMessage; - std::string logMessage = logStream.str (); + std::ostringstream descStream; + descStream << short_function << " (" << filename << ":" << codeLine << "): "; + std::string descMessage = descStream.str(); - // Print the log message - std::cout << "[" << timeStamp.str () << "] "; // Timestamp - SetConsoleTextAttribute (consoleHandle, GetLogLevelColor (messageLevel)); // Set Level color - std::cout << logType; // Level - if (messageLevel != LogLevel::ERROR) { - SetConsoleTextAttribute (consoleHandle, FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY); // Reset console color - } - std::cout << logMessage << std::endl; // Log message - if (messageLevel == LogLevel::ERROR) { - SetConsoleTextAttribute (consoleHandle, FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY); // Reset console color - } - std::cout.flush (); // Flush to ensure immediate writing + // Print to console + std::cout << "[" << timeStamp.str() << "] "; + SetConsoleTextAttribute (s_consoleHandle, Logger::GetLogLevelColor(messageLevel)); + std::cout << logType; + SetConsoleTextAttribute (s_consoleHandle, FOREGROUND_INTENSITY); + std::cout << descMessage; + // Reset console color + SetConsoleTextAttribute (s_consoleHandle, FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY); + std::cout << formattedMessage << std::endl; + std::cout.flush (); - if (loggerInstance->logFile != nullptr) { - fprintf (loggerInstance->logFile, "[%s] %s%s\n", timeStamp.str ().c_str (), logType.c_str (), logMessage.c_str ()); - fflush (loggerInstance->logFile); // Flush to ensure immediate writing + if (s_logFile != nullptr) { + *s_logFile << "[" << timeStamp.str () << "] " << logType << descMessage << formattedMessage << std::endl; + s_logFile->flush (); } } void -LogMessageHandler (const char *function, const char *codeFile, const int codeLine, const LogLevel messageLevel, const wchar_t *format, ...) { - const std::string utf8Message = ConvertWideToUtf8 (format); // Convert wide string to UTF-8 +Logger::LogMessageHandler (const char* function, const char* codeFile, int codeLine, LogLevel messageLevel, const wchar_t* format, ...) { + const std::string utf8Message = ConvertWideToUtf8 (format); va_list args; va_start (args, format); - LogMessageHandler (function, codeFile, codeLine, messageLevel, utf8Message.c_str (), args); // Delegate to the original handler + Logger::LogMessageHandler (function, codeFile, codeLine, messageLevel, utf8Message.c_str(), args); va_end (args); } -bool -EnableLogging (LogLevel messageLevel) { - return loggerInstance != nullptr && messageLevel <= loggerInstance->logLevel; -} - void -CleanupLogger () { - if (loggerInstance != nullptr) { - if (loggerInstance->logFile) fclose (loggerInstance->logFile); - free (loggerInstance); - loggerInstance = nullptr; +Logger::CleanupLogger () { + if (s_isInitialized) { + if (s_logFile) { + s_logFile->close (); + s_logFile = nullptr; + } + s_isInitialized = false; + } +} + +LogLevel +Logger::GetLogLevel (const std::string& logLevelStr) { + if (logLevelStr == "DEBUG") return LogLevel::DEBUG; + if (logLevelStr == "INFO") return LogLevel::INFO; + if (logLevelStr == "WARN") return LogLevel::WARN; + if (logLevelStr == "ERROR") return LogLevel::ERROR; + if (logLevelStr == "HOOKS") return LogLevel::HOOKS; + return LogLevel::NONE; +} + +std::string +Logger::GetLogLevelString (const LogLevel messageLevel) { + switch (messageLevel) { + case LogLevel::DEBUG: return "DEBUG: "; + case LogLevel::INFO: return "INFO: "; + case LogLevel::WARN: return "WARN: "; + case LogLevel::ERROR: return "ERROR: "; + case LogLevel::HOOKS: return "HOOKS: "; + default: return "NONE: "; + } +} + +int +Logger::GetLogLevelColor(const LogLevel messageLevel) +{ + // Colors: https://i.sstatic.net/ZG625.png + switch (messageLevel) { + case LogLevel::DEBUG: + return FOREGROUND_BLUE | FOREGROUND_INTENSITY; // Pale Blue + case LogLevel::INFO: + return FOREGROUND_GREEN | FOREGROUND_INTENSITY; // Pale Green + case LogLevel::WARN: + return FOREGROUND_RED | FOREGROUND_GREEN; // Bright Yellow + case LogLevel::ERROR: + return FOREGROUND_RED; // Bright RED + case LogLevel::HOOKS: + return FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY; // Pale Purple + default: + return FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY; } } diff --git a/src/logger.h b/src/logger.h index d8f5f19..3ad6d7e 100644 --- a/src/logger.h +++ b/src/logger.h @@ -4,120 +4,91 @@ #include #include #include +#include #include +#include +#include + +#ifdef ERROR +#undef ERROR +#endif #define STRING(x) #x #define XSTRING(x) STRING (x) enum class LogLevel { NONE = 0, -#ifdef ERROR -#undef ERROR ERROR, -#endif WARN, INFO, DEBUG, HOOKS }; -/** - * Logger Struct Used to Store Logging Preferences and State - */ -typedef struct { - LogLevel logLevel; - FILE *logFile; -} Logger; +class Logger { +public: + static void InitializeLogger(LogLevel level, bool logToFile, std::string logDir); -/* Initializes a global Logger instance. */ -void InitializeLogger (LogLevel level, bool logToFile, const std::string& logPath); + static void LogMessageHandler(const char* function, const char* codeFile, int codeLine, LogLevel messageLevel, const char* format, ...); -void LogMessageHandler (const char *function, const char *codeFile, int codeLine, LogLevel messageLevel, const char *format, ...); -void LogMessageHandler (const char *function, const char *codeFile, int codeLine, LogLevel messageLevel, const wchar_t *format, ...); + static void LogMessageHandler(const char* function, const char* codeFile, int codeLine, LogLevel messageLevel, const wchar_t* format, ...); -bool EnableLogging (LogLevel level); + static void CleanupLogger(); + + static LogLevel GetLogLevel(const std::string& logLevelStr); + + static std::string GetLogLevelString(LogLevel messageLevel); + + static int GetLogLevelColor(LogLevel messageLevel); + +private: + // Private constructor to disallow instantiation + Logger() = default; + + static LogLevel s_logLevel; + static std::fstream* s_logFile; + static void* s_consoleHandle; + static std::mutex s_logMutex; + static bool s_isInitialized; +}; -/* * - * Logs a message with file and line information, if the log level permits. - * - * Use template magic to replace macros and get proper typing support... - */ template struct LogMessage { - LogMessage (const LogLevel level, const std::string_view format, Args &&...args, - const std::source_location &loc = std::source_location::current ()) { - if (!EnableLogging (level)) return; - std::string formatted_message = std::vformat(std::string(format), std::make_format_args(args...)); - LogMessageHandler (loc.function_name (), loc.file_name (), loc.line (), level, formatted_message.c_str ()); + LogMessage (const LogLevel level, const std::string_view format, Args&&... args, + const std::source_location& loc = std::source_location::current()) { + std::string formatted_message = + std::vformat(std::string(format), std::make_format_args(args...)); + + Logger::LogMessageHandler(loc.function_name(), loc.file_name(), loc.line(), level, formatted_message.c_str()); } - LogMessage (const LogLevel level, const std::wstring_view format, Args &&...args, - const std::source_location &loc = std::source_location::current ()) { - if (!EnableLogging (level)) return; - std::wstring formatted_message = std::vformat(std::wstring(format), std::make_wformat_args(args...)); - LogMessageHandler (loc.function_name (), loc.file_name (), loc.line (), level, formatted_message.c_str ()); + LogMessage (const LogLevel level, const std::wstring_view format, Args&&... args, + const std::source_location& loc = std::source_location::current()) { + std::wstring formatted_message = + std::vformat(std::wstring(format), std::make_wformat_args(args...)); + + Logger::LogMessageHandler(loc.function_name(), loc.file_name(), loc.line(), level, formatted_message.c_str()); } }; -/* * - * Logs a message with file and line information, if the log level permits. - */ template <> struct LogMessage { - LogMessage (const LogLevel level, const std::string_view format, const std::source_location &loc = std::source_location::current ()) { - LogMessageHandler (loc.function_name (), loc.file_name (), loc.line (), level, format.data ()); + LogMessage(const LogLevel level, const std::string_view format, + const std::source_location& loc = std::source_location::current()) { + Logger::LogMessageHandler(loc.function_name(), loc.file_name(), loc.line(), level, format.data()); } - LogMessage (const LogLevel level, const std::wstring_view format, const std::source_location &loc = std::source_location::current ()) { - LogMessageHandler (loc.function_name (), loc.file_name (), loc.line (), level, format.data ()); + LogMessage(const LogLevel level, const std::wstring_view format, + const std::source_location& loc = std::source_location::current()) { + Logger::LogMessageHandler(loc.function_name(), loc.file_name(), loc.line(), level, format.data()); } }; -LogMessage (LogLevel level, std::string_view format) -> LogMessage; -LogMessage (LogLevel level, std::wstring_view format) -> LogMessage; +LogMessage(LogLevel level, std::string_view format) -> LogMessage; +LogMessage(LogLevel level, std::wstring_view format) -> LogMessage; template -LogMessage (LogLevel level, std::string_view format, Args &&...ts) -> LogMessage; +LogMessage(LogLevel level, std::string_view format, Args&&... ts) -> LogMessage; + template -LogMessage (LogLevel level, std::wstring_view format, Args &&...ts) -> LogMessage; - -/* Converts a string to a LogLevel type. */ -inline LogLevel -GetLogLevel (const std::string &logLevelStr) { - if (logLevelStr == "DEBUG") return LogLevel::DEBUG; - else if (logLevelStr == "INFO") return LogLevel::INFO; - else if (logLevelStr == "WARN") return LogLevel::WARN; - else if (logLevelStr == "ERROR") return LogLevel::ERROR; - else if (logLevelStr == "HOOKS") return LogLevel::HOOKS; - return LogLevel::NONE; -} - -/* Converts a LogLevel type to a string for logging. */ -inline std::string -GetLogLevelString (LogLevel messageLevel) { - switch (messageLevel) { - case LogLevel::DEBUG: return "DEBUG: "; - case LogLevel::INFO: return "INFO: "; - case LogLevel::WARN: return "WARN: "; - case LogLevel::ERROR: return "ERROR: "; - case LogLevel::HOOKS: return "HOOKS: "; - default: return "NONE: "; - } -} - -/* Converts a LogLevel type to an int for colors display in the console. */ -inline int -GetLogLevelColor (const LogLevel messageLevel) { - // Colors: https://i.sstatic.net/ZG625.png - switch (messageLevel) { - case LogLevel::DEBUG: return FOREGROUND_BLUE | FOREGROUND_INTENSITY; // Pale Blue - case LogLevel::INFO: return FOREGROUND_GREEN | FOREGROUND_INTENSITY; // Pale Green - case LogLevel::WARN: return FOREGROUND_RED | FOREGROUND_GREEN; // Bright Yellow - case LogLevel::ERROR: return FOREGROUND_RED; // Bright RED - case LogLevel::HOOKS: return FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY; // Pale Purple - default: return FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY; - } -} - -/* Cleans up the logger, closing files if necessary. */ -void CleanupLogger (); +LogMessage(LogLevel level, std::wstring_view format, Args&&... ts) -> LogMessage; diff --git a/src/patches/audio.cpp b/src/patches/audio.cpp index 22f53ea..f43d5ae 100644 --- a/src/patches/audio.cpp +++ b/src/patches/audio.cpp @@ -79,17 +79,6 @@ void Init () { LogMessage (LogLevel::INFO, "Init Audio patches"); - /*const auto configPath = std::filesystem::current_path () / "config.toml"; - const std::unique_ptr config_ptr (openConfig (configPath), toml_free); - if (config_ptr) { - if (const auto audio = openConfigSection (config_ptr.get (), "audio")) { - wasapiShared = readConfigBool (audio, "wasapi_shared", wasapiShared); - asio = readConfigBool (audio, "asio", asio); - asioDriver = readConfigString (audio, "asio_driver", asioDriver); - - } - }*/ - if (real) ReduceAudioLatency (); switch (gameVersion) { diff --git a/src/patches/layeredfs.cpp b/src/patches/layeredfs.cpp index 23334f5..f094187 100644 --- a/src/patches/layeredfs.cpp +++ b/src/patches/layeredfs.cpp @@ -286,12 +286,6 @@ FAST_HOOK (HANDLE, CreateFileAHook, PROC_ADDRESS ("kernel32.dll", "CreateFileA") void Init () { - /*const auto configPath = std::filesystem::current_path () / "config.toml"; - const std::unique_ptr config_ptr (openConfig (configPath), toml_free); - if (config_ptr) { - if (const auto layeredFs = openConfigSection (config_ptr.get (), "layeredfs")) - useLayeredFs = readConfigBool (layeredFs, "enabled", useLayeredFs); - }*/ register_cipher (&aes_desc); if (useLayeredFs || !beforeHandlers.empty () || !afterHandlers.empty ()) { LogMessage (LogLevel::INFO, "using LayeredFs! Data_mods={} beforHandlers={} afterHandlers={}", diff --git a/src/patches/testmode.cpp b/src/patches/testmode.cpp index fc6abcc..5d80bbc 100644 --- a/src/patches/testmode.cpp +++ b/src/patches/testmode.cpp @@ -1,6 +1,7 @@ #include "constants.h" #include "helpers.h" #include "patches.h" +#include "banner.h" #include #include #include @@ -21,6 +22,8 @@ std::vector patches = {}; std::vector values = {}; std::map valueMap = {}; +std::string ver = Banner::Version::instance ().getVer (); + std::wstring mergeCondition (std::wstring original, std::wstring addition, std::wstring value) { size_t pos = original.find (L"/"); @@ -296,6 +299,7 @@ FAST_HOOK_DYNAMIC (void, TestModeSetMenuHook, u64 testModeLibrary, const wchar_t pugi::xml_node talItem = dongleItem.parent ().append_copy (dongleItem); talItem.attribute (L"label").set_value (L"TAIKOARCADELOADER"); talItem.attribute (L"id").set_value (L"TaikoArcadeLoader"); + talItem.attribute (L"replace-text").set_value ((L"1:@Color/Lime;V" + std::wstring ({ver.begin (), ver.end ()})).c_str ()); talItem.append_attribute (L"default") = L"1"; dongleItem.parent ().append_child (L"break-item"); diff --git a/src/patches/timer.cpp b/src/patches/timer.cpp index 5a4d249..cb9c90e 100644 --- a/src/patches/timer.cpp +++ b/src/patches/timer.cpp @@ -29,17 +29,16 @@ namespace patches::Timer { NTSTATUS queryStatus = NtQueryTimerResolution(¤tResolution, &minimumResolution, &maximumResolution); if (queryStatus == 0) { bool setHighResolutionTimer = currentResolution > maximumResolution; - LogMessage (LogLevel::WARN, "(experimental) Timer Resolution current: {}ms maximum: {}ms", currentResolution / 10000.0, maximumResolution / 10000.0); if (setHighResolutionTimer) { NTSTATUS status = NtSetTimerResolution(maximumResolution, TRUE, ¤tResolution); if (status == 0) { - LogMessage (LogLevel::WARN, "(experimental) Successfully change Timer resolution to {}ms", maximumResolution / 10000.0); + LogMessage (LogLevel::INFO, "Timer resolution: {}ms -> {}ms", currentResolution / 10000.0, maximumResolution / 10000.0); } else { - LogMessage (LogLevel::ERROR, "(experimental) Failed to change Timer resolution, status={}", status); + LogMessage (LogLevel::WARN, "Failed to change Timer resolution, status={}", status); } atexit (Release); } - } else LogMessage (LogLevel::ERROR, "(experimental) Failed to query Timer resolution, status={}", queryStatus); + } else LogMessage (LogLevel::WARN, "Failed to query Timer resolution, status={}", queryStatus); } } \ No newline at end of file diff --git a/src/patches/versions/CHN00.cpp b/src/patches/versions/CHN00.cpp index 31ca3c1..81821ec 100644 --- a/src/patches/versions/CHN00.cpp +++ b/src/patches/versions/CHN00.cpp @@ -129,20 +129,6 @@ Init () { INSTALL_HOOK (HaspGetInfo); INSTALL_HOOK (HaspRead); - /*const auto configPath = std::filesystem::current_path () / "config.toml"; - const std::unique_ptr config_ptr (openConfig (configPath), toml_free); - if (config_ptr) { - if (const auto patches = openConfigSection (config_ptr.get (), "patches")) { - unlockSongs = readConfigBool (patches, "unlock_songs", unlockSongs); - if (const auto chn00 = openConfigSection (patches, "chn00")) { - fixLanguage = readConfigBool (chn00, "fix_language", fixLanguage); - demoMovie = readConfigBool (chn00, "demo_movie", demoMovie); - modeCollabo025 = readConfigBool (chn00, "mode_collabo025", modeCollabo025); - modeCollabo026 = readConfigBool (chn00, "mode_collabo026", modeCollabo026); - } - } - }*/ - // Apply common config patch WRITE_MEMORY (ASLR (0x1404A4ED3), i32, xRes); WRITE_MEMORY (ASLR (0x1404A4EDA), i32, yRes); diff --git a/src/patches/versions/JPN00.cpp b/src/patches/versions/JPN00.cpp index c4580c1..917a8b3 100644 --- a/src/patches/versions/JPN00.cpp +++ b/src/patches/versions/JPN00.cpp @@ -44,13 +44,6 @@ Init () { LogMessage (LogLevel::INFO, "Init JNP00 patches"); bool unlockSongs = Config::ConfigManager::instance ().getPatchesConfig ().unlock_songs; - /*const auto configPath = std::filesystem::current_path () / "config.toml"; - const std::unique_ptr config_ptr (openConfig (configPath), toml_free); - if (config_ptr) { - if (const auto patches = openConfigSection (config_ptr.get (), "patches")) - unlockSongs = readConfigBool (patches, "unlock_songs", unlockSongs); - }*/ - // Apply common config patch WRITE_MEMORY (ASLR (0x140224B2B), i32, xRes); WRITE_MEMORY (ASLR (0x140224B32), i32, yRes); diff --git a/src/patches/versions/JPN08.cpp b/src/patches/versions/JPN08.cpp index bc07616..0a5ec7c 100644 --- a/src/patches/versions/JPN08.cpp +++ b/src/patches/versions/JPN08.cpp @@ -54,12 +54,6 @@ Init () { LogMessage (LogLevel::INFO, "Init JPN08 patches"); bool unlockSongs = Config::ConfigManager::instance ().getPatchesConfig ().unlock_songs; - /*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); - }*/ - // Apply common config patch WRITE_MEMORY (ASLR (0x14035FC5B), i32, xRes); WRITE_MEMORY (ASLR (0x14035FC62), i32, yRes); diff --git a/src/patches/versions/JPN39.cpp b/src/patches/versions/JPN39.cpp index e5edbd1..c287116 100644 --- a/src/patches/versions/JPN39.cpp +++ b/src/patches/versions/JPN39.cpp @@ -314,7 +314,7 @@ uint8_t *datatableBuffer[3] = { nullptr }; std::vector datatable_patch = {}; #define DATATABLE_PATCH_REGISTER(location, reg, value, skip) { datatable_patch.push_back(safetyhook::create_mid(location, [](SafetyHookContext &ctx) {ctx.reg = (uintptr_t)(value); ctx.rip = location + skip;})); } void -ReplaceDatatableBufferAddresses () { +PatchDatatable () { LogMessage (LogLevel::INFO, "Set Datatable Size to 12MB"); for (int i = 0; i < 3; i ++) datatableBuffer[i] = (uint8_t *)malloc (datatableBufferSize); DATATABLE_PATCH_REGISTER (ASLR (0x1400ABE26), r8, datatableBufferSize, 6); @@ -338,17 +338,6 @@ Init () { bool unlockSongs = Config::ConfigManager::instance ().getPatchesConfig ().unlock_songs; double modelResRate = Config::ConfigManager::instance ().getGraphicsConfig ().model_res_rate; - /*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")) { - modelResRate = readConfigDouble (graphics, "model_res_rate", modelResRate); - } - }*/ - // Hook to get AppAccessor and ComponentAccessor INSTALL_FAST_HOOK (DeviceCheck); INSTALL_FAST_HOOK (luaL_newstate); @@ -375,7 +364,7 @@ Init () { WRITE_MEMORY (ASLR (0x140580459), u8, 0x10); // Remove datatable size limit - ReplaceDatatableBufferAddresses (); + PatchDatatable (); // Unlock Songs TestMode::RegisterItem ( From 466e6d2e59652ef339c77835be92b147681d094c Mon Sep 17 00:00:00 2001 From: ptmaster Date: Sun, 16 Mar 2025 16:49:07 +0800 Subject: [PATCH 4/5] Log Optimization & add Banner layeredfs add mod_dir option allow uses different folder add simple input option to allow input direct apply to game --- dist/config.toml | 4 ++ src/banner.cpp | 4 +- src/bnusio.cpp | 16 ++--- src/config.cpp | 11 ++-- src/config.h | 18 ++++-- src/dllmain.cpp | 11 ++-- src/logger.cpp | 107 +++++++++++++++++++++++++-------- src/logger.h | 23 ++++--- src/patches/amauth.cpp | 2 +- src/patches/audio.cpp | 12 ++-- src/patches/language.cpp | 8 +-- src/patches/layeredfs.cpp | 16 ++--- src/patches/patches.h | 5 -- src/patches/plugins.cpp | 39 +----------- src/patches/scanner.cpp | 26 +++----- src/patches/testmode.cpp | 45 +++++++------- src/patches/timer.cpp | 5 +- src/patches/versions/JPN39.cpp | 6 +- src/pollasync.cpp | 35 ++++++----- 19 files changed, 223 insertions(+), 170 deletions(-) diff --git a/dist/config.toml b/dist/config.toml index 1141296..a071508 100644 --- a/dist/config.toml +++ b/dist/config.toml @@ -67,6 +67,7 @@ song_no = [] # Song noes used for custom folder 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) global_keyboard = false # Accept keyboard input even if Taiko.exe is not foreground +simple_input = false # Simplified input handler, might decrease game laggy [keyboard] @@ -79,6 +80,7 @@ enabled = false # Replace assets from the game using a layered file # | For example if you want to edit the wordlist, add your edited version like so: # | .\Data_mods\x64\datatable\wordlist.json # | You can provide both unencrypted and encrypted files. +mod_dir = "Data_mods" [logging] @@ -86,4 +88,6 @@ log_level = "INFO" # Log level, Can be either "NONE", "ERROR", "WARN", # | Keep this as low as possible (Info is usually more than enough) as more logging will slow down your game log_to_file = false # Log to file, set this to true to save the logs from your last session to TaikoArcadeLoader.log # |Again, if you do not have a use for this (debugging mods or whatnot), turn it off. +log_method_name = true +log_full_source = true log_dir = "./logs/" # Log file path (Can be both relative and absolute). \ No newline at end of file diff --git a/src/banner.cpp b/src/banner.cpp index 499223f..9320c77 100644 --- a/src/banner.cpp +++ b/src/banner.cpp @@ -12,9 +12,9 @@ Version::Version () { // Print a cool logo with version info std::cout << R"( )" << std::endl; std::cout << R"( ______ _ __ ___ __ __ __ )" << std::endl; - std::cout << R"(/_ __/__ _(_) /_____ / _ | ___________ ____/ /__ / / ___ ___ ____/ /__ ____)" << std::endl; + std::cout << R"(/_ __/__ (_) /_____ / _ | ___________ ___/ /__ / / ___ ___ ___/ /__ ____)" << std::endl; std::cout << R"( / / / _ `/ / '_/ _ \/ __ |/ __/ __/ _ `/ _ / -_) /__/ _ \/ _ `/ _ / -_) __/)" << std::endl; - std::cout << R"(/_/ \_,_/_/_/\_\\___/_/ |_/_/ \__/\_,_/\_,_/\__/____/\___/\_,_/\_,_/\__/_/ )" << std::endl; + std::cout << R"(/_/ \_,_\_/_/\_\\___/_/ |_/_/ \__/\_,_\\_,_/\__/____/\___/\_,_\\_,_/\__/_/ )" << std::endl; std::cout << std::format("{: >79}", std::format("::v{}::", TAL_VERSION)) << std::endl; std::cout << R"( )" << std::endl; } diff --git a/src/bnusio.cpp b/src/bnusio.cpp index b70f103..9041e4e 100644 --- a/src/bnusio.cpp +++ b/src/bnusio.cpp @@ -225,16 +225,16 @@ Init () { // } if (analogInput) { - LogMessage (LogLevel::WARN, "[Analog Type] Axis: All the keyboard drum inputs have been disabled"); + LogMessage (LogLevel::WARN, "Using Axis AnalogIn: All the keyboard drum inputs have been disabled"); analogMethod = AnalogInputAxis; } else if (drumWaitPeriod > 0) { - LogMessage (LogLevel::WARN, "[Analog Type] WaitPeriod: Fast input might be queued"); + LogMessage (LogLevel::WARN, "Using WaitPeriod AnalogIn: Fast input might be queued"); analogMethod = AnalogInputWaitPeriod; - } else if (drumWaitPeriod == 0) { - LogMessage (LogLevel::INFO, "[Analog Type] Cooldown: Fastest and original input"); - analogMethod = AnalogInputCooldown; + // } else if (drumWaitPeriod == 0) { + // LogMessage (LogLevel::INFO, "Using Cooldown AnalogIn: Fastest and original input"); + // analogMethod = AnalogInputCooldown; } else { - LogMessage (LogLevel::INFO, "[Analog Type] Simple: Fastest and original input"); + LogMessage (LogLevel::INFO, "Using Simple AnalogIn: Fastest and original input"); analogMethod = AnalogInputSimple; } @@ -244,7 +244,9 @@ Init () { } if (!emulateUsio && bnusioOriginal) { - LogMessage (LogLevel::WARN, "USIO emulation disabled"); + LogMessage (LogLevel::WARN, "Disable USIO Emulation"); + } else { + LogMessage (LogLevel::INFO, "Using USIO Emulation"); } } diff --git a/src/config.cpp b/src/config.cpp index 3e21033..51d84de 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "banner.h" #include "config.h" @@ -101,7 +102,7 @@ ConfigManager::ConfigManager () { bool ConfigManager::loadKeyBindings () { - LogMessage (LogLevel::INFO, "Layout: {}", config.keyboard.jp_layout ? "JP" : "US"); + LogMessage (LogLevel::INFO, "Using Keyboard Layout: {}", config.keyboard.jp_layout ? "JP" : "US"); ConfigKeyboardButtons = config.keyboard.jp_layout ? std::map(ConfigKeyboardButtons_JP) : std::map(ConfigKeyboardButtons_US); const auto configPath = std::filesystem::current_path () / "keyconfig.toml"; @@ -122,10 +123,10 @@ ConfigManager::loadKeyBindings () { keyBindings.usingKeyboard = usingKeyboard; keyBindings.usingMouse = usingMouse; keyBindings.usingController = usingController; - LogMessage (LogLevel::INFO, "Finish Loading keyconfig.toml"); - if (usingKeyboard) LogMessage (LogLevel::DEBUG, ">>>>> Using Keyboard!"); - if (usingMouse) LogMessage (LogLevel::DEBUG, ">>>>> Using Mouse!"); - if (usingController) LogMessage (LogLevel::DEBUG, ">>>>> Using Controller!"); + LogMessage (LogLevel::DEBUG, "Finish Loading keyconfig.toml"); + if (usingKeyboard) LogMessage (LogLevel::INFO, "Using Input Channel: Keyboard"); + if (usingMouse) LogMessage (LogLevel::INFO, "Using Input Channel: Mouse Wheel"); + if (usingController) LogMessage (LogLevel::INFO, "Using Input Channel: Controller"); return true; } diff --git a/src/config.h b/src/config.h index 5893259..616439d 100644 --- a/src/config.h +++ b/src/config.h @@ -42,6 +42,7 @@ struct patchesConfig { patchVersions version{"auto"}; bool unlock_songs = true; bool local_files = true; + // int maximum_song = 1600; struct chn00Config { bool fix_language = false; bool demo_movie = true; @@ -91,6 +92,7 @@ struct controllerConfig { int wait_period = 0; bool analog_input = false; bool global_keyboard = false; + bool simple_input = false; }; struct keyboardConfig { @@ -100,13 +102,16 @@ struct keyboardConfig { struct layeredfsConfig { bool enabled = false; + std::string mod_dir = "Data_mods"; }; -using logLevels = rfl::Literal<"NONE", "ERROR", "WARN", "INFO", "DEBUG", "HOOKS">; +using logLevels = rfl::Literal<"NONE", "ERROR", "WARN", "INFO", "GAME", "DEBUG", "HOOKS">; struct loggingConfig { - logLevels log_level{ "INFO"}; + logLevels log_level{ "GAME" }; bool log_to_file = false; + bool log_method_name = false; + bool log_full_source = false; std::string log_dir = "./logs/"; }; @@ -434,8 +439,13 @@ public: // Singleton pattern for global access static ConfigManager& instance() { - static ConfigManager instance; // Guaranteed to be destroyed, instantiated on first use - return instance; + try { + static ConfigManager instance; // Guaranteed to be destroyed, instantiated on first use + return instance; + } catch (std::runtime_error &e) { + std::cerr << "[Logger] Failed to parse Default Config: " << e.what () << std::endl; + exit (1); + } } static bool validateConfigfile(std::string path); diff --git a/src/dllmain.cpp b/src/dllmain.cpp index 26fa9d5..0f3c178 100644 --- a/src/dllmain.cpp +++ b/src/dllmain.cpp @@ -206,7 +206,7 @@ DllMain (HMODULE module, const DWORD reason, LPVOID reserved) { else if (yRes * 16 < xRes * 9) xRes = (int)(yRes * 16.0 / 9.0); } Config::ConfigManager::instance ().setRes (xRes, yRes); - LogMessage (LogLevel::INFO, "Boot with {} mode [{}(*{})x{}(*())]", windowed ? "window" : "fullscreen", xRes, hScale, yRes, vScale); + LogMessage (LogLevel::INFO, "Using {} mode [{}(x{}), {}(x{})]", windowed ? "window" : "fullscreen", xRes, hScale, yRes, vScale); if (autoIme) { currentLayout = GetKeyboardLayout (0); @@ -216,7 +216,6 @@ DllMain (HMODULE module, const DWORD reason, LPVOID reserved) { } // Update the logger with the level read from config file. - LogMessage (LogLevel::INFO, "Application started."); if (version == "auto") GetGameVersion (); else if (version == "JPN00") gameVersion = GameVersion::JPN00; @@ -228,7 +227,8 @@ DllMain (HMODULE module, const DWORD reason, LPVOID reserved) { MessageBoxA (nullptr, "Unknown patch version", nullptr, MB_OK); ExitProcess (0); } - LogMessage (LogLevel::INFO, "GameVersion is {}", GameVersionToString (gameVersion)); + LogMessage (LogLevel::INFO, "Using GameVersion: {}", GameVersionToString (gameVersion)); + Logger::InitLoggerHook (); patches::Plugins::LoadPlugins (); patches::Plugins::InitVersion (gameVersion); @@ -239,7 +239,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::INFO, "==== Loading patches, please wait..."); + LogMessage (LogLevel::DEBUG, "=== Loading patches, please wait..."); if (windowed && cursor) INSTALL_FAST_HOOK (ShowMouse); INSTALL_FAST_HOOK (ExitWindows); @@ -284,7 +284,8 @@ DllMain (HMODULE module, const DWORD reason, LPVOID reserved) { // 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); + LogMessage (LogLevel::DEBUG, "=== Finished Loading patches!"); + LogMessage (LogLevel::INFO, "Taiko Starts in {:.2f}ms", duration.count () * 1000); } return true; } diff --git a/src/logger.cpp b/src/logger.cpp index 8d95a40..1552d5d 100644 --- a/src/logger.cpp +++ b/src/logger.cpp @@ -1,4 +1,5 @@ #include "logger.h" +#include "config.h" #include #include #include @@ -9,6 +10,11 @@ #include #include +extern GameVersion gameVersion; + +bool s_logMethodName = Config::ConfigManager::instance ().getLoggingConfig ().log_method_name; +bool s_logFullSource = Config::ConfigManager::instance ().getLoggingConfig ().log_full_source; + // Static member definitions LogLevel Logger::s_logLevel = LogLevel::NONE; void* Logger::s_consoleHandle = nullptr; @@ -16,27 +22,54 @@ bool Logger::s_isInitialized = false; std::fstream* Logger::s_logFile = nullptr; std::mutex Logger::s_logMutex; +bool loggerInited = false; + +// FAST_HOOK_DYNAMIC (int, TaikoPrintf, const char *format, ...) { +// va_list args; +// va_start (args, format); +// int requiredSize = vsnprintf (nullptr, 0, format, args) + 1; // +1 for null terminator +// std::unique_ptr buffer (new char[requiredSize]); +// vsnprintf (buffer.get (), requiredSize, format, args); +// Logger::LogMessageHandler ("printf", "Taiko.exe", -1, LogLevel::GAME, buffer.get ()); +// va_end (args); +// return requiredSize; +// } + +// i64 coutVal = 0; +// FAST_HOOK_DYNAMIC (i64 *, TaikoPrint, i64 *a1, const char *msg) { +// if ((i64) a1 != coutVal) originalTaikoPrint.call (a1, msg); +// Logger::LogMessageHandler ("std::cout", "Taiko.exe", -1, LogLevel::GAME, msg); +// return a1; +// } + +void +Logger::InitLoggerHook () { + if (loggerInited) return; + loggerInited = true; + // switch (gameVersion) { + // case GameVersion::JPN00: case GameVersion::JPN08: case GameVersion::CHN00: default: break; + // case GameVersion::JPN39: { + // coutVal = *(i64 *)ASLR (0x1408CCBF8); + // INSTALL_FAST_HOOK_DYNAMIC (TaikoPrintf, ASLR (0x1400D3EE0)); + // INSTALL_FAST_HOOK_DYNAMIC (TaikoPrint, ASLR (0x14004B4F0)); + // } break; + // } +} + static std::string -ConvertWideToUtf8(const wchar_t* wstr) -{ +ConvertWideToUtf8(const wchar_t* wstr) { if (!wstr) return {}; std::wstring ws (wstr); return {ws.begin (), ws.end ()}; } void -Logger::InitializeLogger(const LogLevel level, const bool logToFile, std::string logDir) -{ - if (s_isInitialized) { - return; - } +Logger::InitializeLogger(const LogLevel level, const bool logToFile, std::string logDir) { + if (s_isInitialized) return; s_isInitialized = true; s_logLevel = level; - - if (s_consoleHandle == nullptr) { - s_consoleHandle = GetStdHandle (STD_OUTPUT_HANDLE); - } + if (s_consoleHandle == nullptr) s_consoleHandle = GetStdHandle (STD_OUTPUT_HANDLE); if (logToFile) { try { @@ -60,12 +93,17 @@ Logger::InitializeLogger(const LogLevel level, const bool logToFile, std::string const std::string fullLogPath = logDir + dateFilename; s_logFile = new std::fstream (fullLogPath.c_str (), std::ios::out | std::ios::app); if (!s_logFile->is_open ()) { - std::cerr << "[Logg er] Failed to open " << fullLogPath << " for writing.\n"; + std::cerr << "[Logger] Failed to open " << fullLogPath << " for writing.\n"; s_logFile = nullptr; } } } +bool +Logger::GuardianOutput (LogLevel messageLevel) { + return !s_isInitialized || messageLevel > s_logLevel; +} + void Logger::LogMessageHandler (const char* function, const char* codeFile, int codeLine, LogLevel messageLevel, const char* format, ...) { // Return if logger uninitialized or messageLevel is more verbose than the set level @@ -81,6 +119,9 @@ Logger::LogMessageHandler (const char* function, const char* codeFile, int codeL std::unique_ptr buffer (new char[requiredSize]); vsnprintf (buffer.get (), requiredSize, format, args); std::string formattedMessage (buffer.get()); + while (formattedMessage.ends_with ("\n")) { + formattedMessage = formattedMessage.substr (0, formattedMessage.size () - 1); + } va_end (args); std::string logType = Logger::GetLogLevelString(messageLevel); @@ -89,10 +130,6 @@ Logger::LogMessageHandler (const char* function, const char* codeFile, int codeL std::regex re (R"(.*? (([\w<>]+::)*[\w]+( [()<>+-]+)?)\(\w+.*?\))"); short_function = std::regex_replace (short_function, re, "$1"); - constexpr std::string_view build_dir = XSTRING (SOURCE_ROOT); - std::string_view filename = codeFile; - filename.remove_prefix (build_dir.size ()); - SYSTEMTIME systemTime; GetSystemTime (&systemTime); time_t rawTime = time (nullptr); @@ -104,7 +141,19 @@ Logger::LogMessageHandler (const char* function, const char* codeFile, int codeL // Construct the log message std::ostringstream descStream; - descStream << short_function << " (" << filename << ":" << codeLine << "): "; + if (s_logMethodName) descStream << short_function << " "; + if (s_logFullSource) { + constexpr std::string_view build_dir = XSTRING (SOURCE_ROOT); + std::string_view filename = codeFile; + filename.remove_prefix (build_dir.size ()); + descStream << "(" << filename << ":" << codeLine << "): "; + } else { + std::string filename = std::string (codeFile); + if (size_t begin = filename.find_last_of ("/\\"); begin != std::string::npos) { + filename = filename.substr (begin + 1, filename.length ()); + } + descStream << "(" << std::format("{: >20}", std::format("{}:{}", filename, codeLine)) << "): "; + } std::string descMessage = descStream.str(); // Print to console @@ -113,9 +162,14 @@ Logger::LogMessageHandler (const char* function, const char* codeFile, int codeL std::cout << logType; SetConsoleTextAttribute (s_consoleHandle, FOREGROUND_INTENSITY); std::cout << descMessage; - // Reset console color - SetConsoleTextAttribute (s_consoleHandle, FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY); - std::cout << formattedMessage << std::endl; + if (messageLevel == LogLevel::WARN || messageLevel == LogLevel::ERROR) { + SetConsoleTextAttribute (s_consoleHandle, Logger::GetLogLevelColor(messageLevel)); + std::cout << formattedMessage << std::endl; + SetConsoleTextAttribute (s_consoleHandle, FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY); + } else { + SetConsoleTextAttribute (s_consoleHandle, FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY); + std::cout << formattedMessage << std::endl; + } std::cout.flush (); if (s_logFile != nullptr) { @@ -151,6 +205,7 @@ Logger::GetLogLevel (const std::string& logLevelStr) { if (logLevelStr == "INFO") return LogLevel::INFO; if (logLevelStr == "WARN") return LogLevel::WARN; if (logLevelStr == "ERROR") return LogLevel::ERROR; + if (logLevelStr == "GAME") return LogLevel::GAME; if (logLevelStr == "HOOKS") return LogLevel::HOOKS; return LogLevel::NONE; } @@ -159,17 +214,17 @@ std::string Logger::GetLogLevelString (const LogLevel messageLevel) { switch (messageLevel) { case LogLevel::DEBUG: return "DEBUG: "; - case LogLevel::INFO: return "INFO: "; - case LogLevel::WARN: return "WARN: "; + case LogLevel::INFO: return "INFO : "; + case LogLevel::WARN: return "WARN : "; case LogLevel::ERROR: return "ERROR: "; case LogLevel::HOOKS: return "HOOKS: "; - default: return "NONE: "; + case LogLevel::GAME: return "GAME : "; + default: return "NONE : "; } } int -Logger::GetLogLevelColor(const LogLevel messageLevel) -{ +Logger::GetLogLevelColor(const LogLevel messageLevel) { // Colors: https://i.sstatic.net/ZG625.png switch (messageLevel) { case LogLevel::DEBUG: @@ -182,6 +237,8 @@ Logger::GetLogLevelColor(const LogLevel messageLevel) return FOREGROUND_RED; // Bright RED case LogLevel::HOOKS: return FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY; // Pale Purple + case LogLevel::GAME: + return FOREGROUND_BLUE | FOREGROUND_RED; // Purple default: return FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY; } diff --git a/src/logger.h b/src/logger.h index 3ad6d7e..5d1d856 100644 --- a/src/logger.h +++ b/src/logger.h @@ -21,25 +21,30 @@ enum class LogLevel { ERROR, WARN, INFO, + GAME, DEBUG, HOOKS }; class Logger { public: - static void InitializeLogger(LogLevel level, bool logToFile, std::string logDir); + static void InitLoggerHook (); - static void LogMessageHandler(const char* function, const char* codeFile, int codeLine, LogLevel messageLevel, const char* format, ...); + static void InitializeLogger (LogLevel level, bool logToFile, std::string logDir); - static void LogMessageHandler(const char* function, const char* codeFile, int codeLine, LogLevel messageLevel, const wchar_t* format, ...); + static bool GuardianOutput (LogLevel messageLevel); - static void CleanupLogger(); + static void LogMessageHandler (const char* function, const char* codeFile, int codeLine, LogLevel messageLevel, const char* format, ...); - static LogLevel GetLogLevel(const std::string& logLevelStr); + static void LogMessageHandler (const char* function, const char* codeFile, int codeLine, LogLevel messageLevel, const wchar_t* format, ...); - static std::string GetLogLevelString(LogLevel messageLevel); + static void CleanupLogger (); - static int GetLogLevelColor(LogLevel messageLevel); + static LogLevel GetLogLevel (const std::string& logLevelStr); + + static std::string GetLogLevelString (LogLevel messageLevel); + + static int GetLogLevelColor (LogLevel messageLevel); private: // Private constructor to disallow instantiation @@ -56,6 +61,7 @@ template struct LogMessage { LogMessage (const LogLevel level, const std::string_view format, Args&&... args, const std::source_location& loc = std::source_location::current()) { + if (Logger::GuardianOutput (level)) return; std::string formatted_message = std::vformat(std::string(format), std::make_format_args(args...)); @@ -64,6 +70,7 @@ struct LogMessage { LogMessage (const LogLevel level, const std::wstring_view format, Args&&... args, const std::source_location& loc = std::source_location::current()) { + if (Logger::GuardianOutput (level)) return; std::wstring formatted_message = std::vformat(std::wstring(format), std::make_wformat_args(args...)); @@ -75,11 +82,13 @@ template <> struct LogMessage { LogMessage(const LogLevel level, const std::string_view format, const std::source_location& loc = std::source_location::current()) { + if (Logger::GuardianOutput (level)) return; Logger::LogMessageHandler(loc.function_name(), loc.file_name(), loc.line(), level, format.data()); } LogMessage(const LogLevel level, const std::wstring_view format, const std::source_location& loc = std::source_location::current()) { + if (Logger::GuardianOutput (level)) return; Logger::LogMessageHandler(loc.function_name(), loc.file_name(), loc.line(), level, format.data()); } }; diff --git a/src/patches/amauth.cpp b/src/patches/amauth.cpp index 8865399..f5c1ee8 100644 --- a/src/patches/amauth.cpp +++ b/src/patches/amauth.cpp @@ -549,7 +549,7 @@ CoCreateInstanceHook (const IID *const rclsid, const LPUNKNOWN pUnkOuter, const void Init () { - LogMessage (LogLevel::INFO, "Init AmAuth patches"); + LogMessage (LogLevel::DEBUG, "Init AmAuth patches"); auto whereCoCreateInstance = GetProcAddress (LoadLibraryW (L"ole32.dll"), "CoCreateInstance"); originalCoCreateInstanceHook = safetyhook::create_inline ((void *)whereCoCreateInstance, CoCreateInstanceHook); diff --git a/src/patches/audio.cpp b/src/patches/audio.cpp index f43d5ae..39ef9f1 100644 --- a/src/patches/audio.cpp +++ b/src/patches/audio.cpp @@ -68,16 +68,20 @@ ReduceAudioLatency () { } else { auto properties = audioClient->GetProperties (); auto prop = properties.value(); - double currentDelay = prop.minimumBufferSize * 1000.0 / prop.sampleRate; - double defaultDelay = prop.defaultBufferSize * 1000.0 / prop.sampleRate; - LogMessage (LogLevel::INFO, "Audio latency: {:.2f}ms -> {:.2f}ms", defaultDelay, currentDelay); + if (prop.minimumBufferSize < prop.defaultBufferSize) { + double currentDelay = prop.minimumBufferSize * 1000.0 / prop.sampleRate; + double defaultDelay = prop.defaultBufferSize * 1000.0 / prop.sampleRate; + LogMessage (LogLevel::INFO, "Using REAL Audio latency: {:.2f}ms -> {:.2f}ms", defaultDelay, currentDelay); + } else { + LogMessage (LogLevel::WARN, "Using REAL Audio Failed, Please Check Audio Driver!"); + } } return 0; } void Init () { - LogMessage (LogLevel::INFO, "Init Audio patches"); + LogMessage (LogLevel::DEBUG, "Init Audio patches"); if (real) ReduceAudioLatency (); diff --git a/src/patches/language.cpp b/src/patches/language.cpp index 65b0532..fe72d19 100644 --- a/src/patches/language.cpp +++ b/src/patches/language.cpp @@ -111,7 +111,7 @@ Init () { fontExistAll = false; } if (fontExistAll == false) return; - LogMessage (LogLevel::INFO, "Detected cn_xx files, Install Font patches"); + LogMessage (LogLevel::INFO, "Using Font patches (Detected cn_xx files)"); languageData = calloc (languages.size () * languages.size () * 0x70 * 0x5, sizeof (u8)); switch (gameVersion) { @@ -389,14 +389,14 @@ Init () { demoMovieExistAll = false; } if (demoMovieExistAll) { - LogMessage (LogLevel::INFO, "Detected attractdemo_cn files, install attractdemo patches!"); + LogMessage (LogLevel::INFO, "Using Attractdemo patches (Detected attractdemo_cn files)"); INSTALL_FAST_HOOK_DYNAMIC (LoadDemoMovie, ASLR (0x1404313F0)); } bool onpCnExist = false; if (std::filesystem::exists (std::string ("..\\..\\Data\\x64\\textures\\onpu_cn\\onp_all.nutexb"))) onpCnExist = true; if (onpCnExist) { - LogMessage (LogLevel::INFO, "Detected onpu_cn files, install onp patches!"); + LogMessage (LogLevel::INFO, "Using Onp patches (Detected onpu_cn files)"); INSTALL_MID_HOOK_DYNAMIC (ChangeOnpFile, ASLR (0x140134D16)); } language_patch.push_back (safetyhook::create_mid (ASLR (0x140134E22), [](SafetyHookContext &ctx){ @@ -638,7 +638,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!"); + LogMessage (LogLevel::INFO, "Using Voice patches (Detected voice files)"); TestMode::RegisterItemAfter( L"/root/menu[@id='OthersMenu']/layout[@type='Center']/select-item[@id='LanguageItem']", L" #include "config.h" -bool useLayeredFs = Config::ConfigManager::instance ().getLayeredFsConfig ().enabled; +bool useLayeredFs = Config::ConfigManager::instance ().getLayeredFsConfig ().enabled; +std::string modDir = Config::ConfigManager::instance ().getLayeredFsConfig ().mod_dir; std::string datatableKey = "3530304242323633353537423431384139353134383346433246464231354534"; std::string fumenKey = "4434423946383537303842433443383030333843444132343339373531353830"; @@ -180,8 +181,8 @@ LayeredFsHandler (const std::string &originalFileName, const std::string ¤ std::filesystem::path path (originalFileName.c_str ()); if (!path.is_absolute ()) path = absolute (path); auto originalDataFolder = std::filesystem::current_path ().parent_path ().parent_path () / "Data" / "x64"; - auto originalLayeredFsFolder = std::filesystem::current_path ().parent_path ().parent_path () / "Data_mods" / "x64"; - auto encryptedLayeredFsFolder = std::filesystem::current_path ().parent_path ().parent_path () / "Data_mods" / "x64_enc"; + auto originalLayeredFsFolder = std::filesystem::current_path ().parent_path ().parent_path () / modDir / "x64"; + auto encryptedLayeredFsFolder = std::filesystem::current_path ().parent_path ().parent_path () / modDir / "x64_enc"; if (path.string ().find (originalDataFolder.string ()) == 0) { auto newPath = path.string (); @@ -288,21 +289,22 @@ void Init () { register_cipher (&aes_desc); if (useLayeredFs || !beforeHandlers.empty () || !afterHandlers.empty ()) { - LogMessage (LogLevel::INFO, "using LayeredFs! Data_mods={} beforHandlers={} afterHandlers={}", - useLayeredFs ? "enabled" : "disabled", beforeHandlers.size (), afterHandlers.size ()); + if (!beforeHandlers.empty ()) LogMessage (LogLevel::INFO, "Using fileHandler beofre size: {}", beforeHandlers.size ()); + if (useLayeredFs) LogMessage (LogLevel::INFO, "Using LayeredFS mods folder: ", modDir); + if (!afterHandlers.empty ()) LogMessage (LogLevel::INFO, "Using fileHandler after size: {}", afterHandlers.size ()); INSTALL_FAST_HOOK (CreateFileAHook); } } void RegisterBefore (const std::function &fileHandler) { - LogMessage (LogLevel::DEBUG, "Registered Before"); + LogMessage (LogLevel::DEBUG, "Registered LayeredFS Before Handler"); beforeHandlers.push_back (new RegisteredHandler (fileHandler)); } void RegisterAfter (const std::function &fileHandler) { - LogMessage (LogLevel::DEBUG, "Registered After"); + LogMessage (LogLevel::DEBUG, "Registered LayeredFS After Handler"); afterHandlers.push_back (new RegisteredHandler (fileHandler)); } diff --git a/src/patches/patches.h b/src/patches/patches.h index 419f7f7..1d72c7f 100644 --- a/src/patches/patches.h +++ b/src/patches/patches.h @@ -89,11 +89,6 @@ void Update (); void Exit (); // Lowlevel Card API void WaitTouch (CallBackTouchCard callback, uint64_t touchData); -// Lowlevel QR API -void InitQr (GameVersion gameVersion); -void UsingQr (); -void * CheckQr (); -size_t GetQr (void *plugin, size_t size, uint8_t *buffer); // New API void InitVersion (GameVersion gameVersion); void InitCardReader (CommitCardCallback touch); diff --git a/src/patches/plugins.cpp b/src/patches/plugins.cpp index 2484645..318f8d6 100644 --- a/src/patches/plugins.cpp +++ b/src/patches/plugins.cpp @@ -39,7 +39,7 @@ namespace patches::Plugins { if (event) ((BasicEvent)event) (); } } - // Card API + // Low Level Card API void WaitTouch (CallBackTouchCard callback, uint64_t touchData) { for (auto plugin : plugins) { @@ -47,35 +47,6 @@ namespace patches::Plugins { if (event) ((WaitTouchEvent)event) (callback, touchData); } } - // QR API (deprecated) - void - InitQr (GameVersion gameVersion) { - for (auto plugin : plugins) { - auto event = GetProcAddress (plugin, "InitQr"); - if (event) ((SendVersionEvent)event) (gameVersion); - } - } - void - UsingQr () { - for (auto plugin : plugins) { - auto event = GetProcAddress (plugin, "UsingQr"); - if (event) ((BasicEvent)event) (); - } - } - void * - CheckQr () { - for (auto plugin : plugins) { - auto event = GetProcAddress (plugin, "UsingQr"); - if (event && ((CheckEvent)event) ()) return plugin; - } - return nullptr; - } - size_t - GetQr (void *plugin, size_t size, uint8_t *buffer) { - auto event = GetProcAddress (*(HMODULE *)plugin, "GetQr"); - if (event) return ((CopyDataEvent)event) (size, buffer); - else return 0; - } // New API void InitVersion (GameVersion gameVersion) { @@ -124,10 +95,10 @@ namespace patches::Plugins { auto name = entry.path ().wstring (); auto shortName = entry.path ().filename ().wstring (); if (HMODULE hModule = LoadLibraryW (name.c_str ()); !hModule) { - LogMessage (LogLevel::ERROR, L"Failed to load plugin " + shortName); + LogMessage (LogLevel::ERROR, L"Failed to load plugin: {}", shortName); } else { plugins.push_back (hModule); - LogMessage (LogLevel::INFO, L"Loaded plugin " + shortName); + LogMessage (LogLevel::INFO, L"Using plugin: {}", shortName); } } } @@ -146,8 +117,4 @@ namespace patches::Plugins { } }).detach (); } - - - - } \ No newline at end of file diff --git a/src/patches/scanner.cpp b/src/patches/scanner.cpp index 1caeb05..aa5ab28 100644 --- a/src/patches/scanner.cpp +++ b/src/patches/scanner.cpp @@ -234,15 +234,16 @@ namespace Card { void Init() { - LogMessage (LogLevel::INFO, "Init Card patches"); + LogMessage (LogLevel::DEBUG, "Init Card patches"); if (!emulateCardReader) { - LogMessage (LogLevel::WARN, "[Card] Card reader emulation disabled!"); + LogMessage (LogLevel::WARN, "Disable Card Reader Emulation"); INSTALL_FAST_HOOK (bngrw_ReqCancelOfficial); INSTALL_FAST_HOOK (bngrw_ReqWaitTouchOfficial); // patches::Plugins::InitCardReader (patches::Scanner::Card::Commit); return; } + LogMessage (LogLevel::INFO, "Using Card Reader Emulation"); INSTALL_FAST_HOOK (bngrw_Init) INSTALL_FAST_HOOK (bngrw_Fin); INSTALL_FAST_HOOK (bngrw_IsCmdExec); @@ -295,7 +296,6 @@ namespace Qr { FAST_HOOK_DYNAMIC (bool, Send3, i64, char) { return true; } FAST_HOOK_DYNAMIC (bool, Send4, i64, const void *, i64) { return true; } FAST_HOOK_DYNAMIC (i64, CopyData, i64, void *dest, int length) { - patches::Plugins::UsingQr (); lastScan = std::chrono::duration_cast(std::chrono::system_clock::now ().time_since_epoch ()).count (); if (state == State::CopyWait && scanQueue.size () > 0) { std::vector *data = scanQueue.front (); @@ -368,17 +368,6 @@ namespace Qr { if ((lastScan + 200) < std::chrono::duration_cast(std::chrono::system_clock::now ().time_since_epoch ()).count ()) { state = State::Disable; patches::Plugins::UpdateStatus (StatusType::QrStatus, false); - } else { - void *plugin = patches::Plugins::CheckQr (); - if (plugin) { - uint8_t *space = (uint8_t *)calloc (600, sizeof (uint8_t)); - size_t size = patches::Plugins::GetQr (plugin, 600, space); - if (size > 0) { - std::vector data = {}; - for (size_t i = 0; i < size; i ++) data.push_back (space[i]); - patches::Scanner::Qr::Commit (data); - } - } } } } @@ -436,13 +425,14 @@ namespace Qr { void Init () { - LogMessage (LogLevel::INFO, "Init Qr patches"); + LogMessage (LogLevel::DEBUG, "Init Qr patches"); if (!emulateQr) { - LogMessage (LogLevel::WARN, "[QR] QR emulation disabled!"); + LogMessage (LogLevel::WARN, "Disable QR Scanner Emulation"); return; } - patches::Plugins::InitQr (gameVersion); + + LogMessage (LogLevel::INFO, "Using QR Scanner Emulation"); SetConsoleOutputCP (CP_UTF8); auto amHandle = reinterpret_cast (GetModuleHandle ("AMFrameWork.dll")); switch (gameVersion) { @@ -511,7 +501,7 @@ Update() { void Init() { - LogMessage (LogLevel::INFO, "Init Scanner patches"); + LogMessage (LogLevel::DEBUG, "Init Scanner patches"); patches::Scanner::Card::Init (); patches::Scanner::Qr::Init (); } diff --git a/src/patches/testmode.cpp b/src/patches/testmode.cpp index 5d80bbc..96fd968 100644 --- a/src/patches/testmode.cpp +++ b/src/patches/testmode.cpp @@ -61,6 +61,8 @@ public: if (!success) { LogMessage (LogLevel::ERROR, L"Failed to parse item: {}\n", this->selectItem); itemDoc.load_string (L""); + } else { + LogMessage (LogLevel::DEBUG, L"[TestMode] Add Item: {}", itemDoc.attribute(L"label").as_string ()); } // if (success) AddHookInLoop (this->registerInit); std::wstring layoutName = L"layout"; @@ -94,7 +96,7 @@ public: size_t size = items.size (); if (size == 0) return node; size_t maxPage = size <= 14 ? 1 : (size / 13 + (size % 13 > 0)); - LogMessage (LogLevel::DEBUG, "Render testmode menu with items(size={}, page={})", size, maxPage); + LogMessage (LogLevel::DEBUG, L"[TestMode] Add Menu {} (items={}, page={})", menuName, size, maxPage); std::wstring menuName = L"menu"; pugi::xml_node parentNode = node->parent (); while (parentNode.name() != menuName) parentNode = parentNode.parent (); @@ -124,12 +126,11 @@ public: std::vector refs = {}; for (size_t page = 0; page < maxPage; page ++) { - LogMessage (LogLevel::DEBUG, "Render testmode menu page ({}/{})", page + 1, maxPage); - + // LogMessage (LogLevel::DEBUG, L"[TestMenu] menu page ({}/{})", page + 1, maxPage); pugi::xml_node ref = passing; size_t maxIndex = MIN(size - page * 13, 13); for (size_t index = 0; index < maxIndex; index ++) { - LogMessage (LogLevel::DEBUG, "Render testmode menu page ({}/{}) item ({}/{})", page + 1, maxPage, index + 1, maxIndex); + // LogMessage (LogLevel::DEBUG, "Render testmode menu page ({}/{}) item ({}/{})", page + 1, maxPage, index + 1, maxIndex); if (index >= refs.size ()) { passing = *(items[page * 13 + index]->Apply (doc, &passing)); if (size > 14) { @@ -149,7 +150,7 @@ public: if (size == 14) passing = *(items[13]->Apply (doc, &passing)); } passing = passing.parent ().last_child (); - LogMessage (LogLevel::DEBUG, "Begin render testmode footer"); + // LogMessage (LogLevel::DEBUG, "Begin render testmode footer"); size_t maxIndex = size == 14 ? 14 : MIN(size, 13); for (size_t i = 0; i < 15 - maxIndex; i++) passing = passing.parent ().insert_child_after (L"break-item", passing); if (maxPage > 1) { @@ -163,7 +164,7 @@ public: exit.load_string (std::format (L"", parentId).c_str ()); passing = passing.parent ().insert_copy_after (exit.first_child ().first_child (), passing); - LogMessage (LogLevel::DEBUG, L"Insert testmode menu menuId: {}, fromId: {}", this->menuId, parentId); + // LogMessage (LogLevel::DEBUG, L"Insert testmode menu menuId: {}, fromId: {}", this->menuId, parentId); pugi::xml_node root = doc->first_child (); root.insert_copy_after (menu.first_child ().first_child (), root.first_child ()); return &temp; @@ -451,7 +452,7 @@ LocalizationCHS () { void Init () { - LogMessage (LogLevel::INFO, "Init TestMode patches"); + LogMessage (LogLevel::DEBUG, "Init TestMode patches"); const u64 testModeLibrary = (u64)GetModuleHandle ("TestModeLibrary.dll"); const u64 testModeSetMenu = testModeLibrary + 0x99D0; @@ -467,6 +468,7 @@ Init () { INSTALL_FAST_HOOK_DYNAMIC (SceneTestModeFinalize, ASLR (0x140479600)); INSTALL_FAST_HOOK_DYNAMIC (SceneFirstInitialize, ASLR (0x1404574B0)); if (Language::CnFontPatches () && std::filesystem::exists ("..\\..\\Data\\x64\\testmode\\DeviceInitialize_china.xml")) { + LogMessage (LogLevel::INFO, L"Using DeviceInitialize: 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); })); // DeviceCheck = Loading Font @@ -478,6 +480,7 @@ Init () { WRITE_MEMORY (ASLR (0x140CD1E50), wchar_t, L"加载中...\0"); } if (Language::CnFontPatches () && std::filesystem::exists ("..\\..\\Data\\x64\\testmode\\TestMode_china.xml")) { + LogMessage (LogLevel::INFO, L"Using 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); })); // TestMode = DeviceInitialize @@ -529,13 +532,13 @@ SetTestModeValue (const wchar_t *itemId, int value) { Menu * CreateMenu (const std::wstring &menuName, const std::wstring &menuId) { - LogMessage (LogLevel::DEBUG, L"Create MenuName: {} MenuId: {}", menuName, menuId); + // LogMessage (LogLevel::DEBUG, L"Create MenuName: {} MenuId: {}", menuName, menuId); return new RegisteredMenu (menuName, menuId); } Value * CreateValue (const std::wstring &key) { - LogMessage (LogLevel::DEBUG, L"Create TestMode Value key: {}", key); + // LogMessage (LogLevel::DEBUG, L"Create TestMode Value key: {}", key); // if (valueMap.count (key)) return valueMap[key]; Value *value = (Value *)(new TestModeValue (key)); values.push_back ((Value *)value); @@ -545,77 +548,77 @@ CreateValue (const std::wstring &key) { void RegisterItem (const std::wstring &item, const std::function &initMethod, Menu *menu) { - LogMessage (LogLevel::DEBUG, L"Register \nItem: {}", item); + // LogMessage (LogLevel::DEBUG, L"Register Item: {}", item); hooks.push_back (initMethod); menu->RegisterItem (new RegisteredItem (item, [](){})); } void RegisterItem (const std::wstring &item, const std::function &initMethod) { - LogMessage (LogLevel::DEBUG, L"Register \nItem: {}", item); + // LogMessage (LogLevel::DEBUG, L"Register Item: {}", item); hooks.push_back (initMethod); modManager->RegisterItem (new RegisteredItem (item, [](){})); } void RegisterItem (const std::wstring &item, Menu *menu) { - LogMessage (LogLevel::DEBUG, L"Register \nItem: {}", item); + // LogMessage (LogLevel::DEBUG, L"Register Item: {}", item); menu->RegisterItem (new RegisteredItem (item, [](){})); } void RegisterItem (const std::wstring &item) { - LogMessage (LogLevel::DEBUG, L"Register \nItem: {}", item); + // LogMessage (LogLevel::DEBUG, L"Register Item: {}", item); modManager->RegisterItem (new RegisteredItem (item, [](){})); } void RegisterItem (Applicable *item, Menu *menu) { - LogMessage (LogLevel::DEBUG, L"Register Item"); + // LogMessage (LogLevel::DEBUG, L"Register Item"); menu->RegisterItem (item); } void RegisterItem (Applicable *item) { - LogMessage (LogLevel::DEBUG, L"Register Item"); + // LogMessage (LogLevel::DEBUG, L"Register Item"); modManager->RegisterItem (item); } void RegisterItemAfter (const std::wstring &query, const std::wstring &item, const std::function &initMethod) { - LogMessage (LogLevel::DEBUG, L"Register \nQuery: {} \nItem: {}", query, item); + // LogMessage (LogLevel::DEBUG, L"Register Query: {} Item: {}", query, item); hooks.push_back (initMethod); registeredSingleItems.push_back (new RegisteredSingleItem (query, new RegisteredItem (item, [](){}))); } void RegisterItemAfter (const std::wstring &query, const std::wstring &item) { - LogMessage (LogLevel::DEBUG, L"Register \nQuery: {} \nItem: {}", query, item); + // LogMessage (LogLevel::DEBUG, L"Register Query: {} Item: {}", query, item); registeredSingleItems.push_back (new RegisteredSingleItem (query, new RegisteredItem (item, [](){}))); } void RegisterItemAfter (const std::wstring &query, Applicable *item) { - LogMessage (LogLevel::DEBUG, L"Register \nQuery: {} \nItem: ptr", query); + // LogMessage (LogLevel::DEBUG, L"Register Query: {} Item: ptr", query); registeredSingleItems.push_back (new RegisteredSingleItem (query, item)); } void RegisterModify (const std::wstring &query, const std::function &nodeModify, const std::function &initMethod) { - LogMessage (LogLevel::DEBUG, L"Register \nModify: {}", query); + // LogMessage (LogLevel::DEBUG, L"Register Modify: {}", query); hooks.push_back (initMethod); registeredModifies.push_back (new RegisteredModify (query, nodeModify, [](){})); } void RegisterModify (const std::wstring &query, const std::function &nodeModify) { - LogMessage (LogLevel::DEBUG, L"Register \nModify: {}", query); + // LogMessage (LogLevel::DEBUG, L"Register Modify: {}", query); registeredModifies.push_back (new RegisteredModify (query, nodeModify, [](){})); } void RegisterHook (const std::function &initMethod) { - LogMessage (LogLevel::DEBUG, L"Register Hook"); + // LogMessage (LogLevel::DEBUG, L"Register Hook"); hooks.push_back (initMethod); } diff --git a/src/patches/timer.cpp b/src/patches/timer.cpp index cb9c90e..b1c6198 100644 --- a/src/patches/timer.cpp +++ b/src/patches/timer.cpp @@ -31,9 +31,10 @@ namespace patches::Timer { bool setHighResolutionTimer = currentResolution > maximumResolution; if (setHighResolutionTimer) { - NTSTATUS status = NtSetTimerResolution(maximumResolution, TRUE, ¤tResolution); + ULONG targetResolution = currentResolution; + NTSTATUS status = NtSetTimerResolution(maximumResolution, TRUE, &targetResolution); if (status == 0) { - LogMessage (LogLevel::INFO, "Timer resolution: {}ms -> {}ms", currentResolution / 10000.0, maximumResolution / 10000.0); + LogMessage (LogLevel::INFO, "Using HiRes Timer: {}ms -> {}ms", currentResolution / 10000.0, targetResolution / 10000.0); } else { LogMessage (LogLevel::WARN, "Failed to change Timer resolution, status={}", status); } diff --git a/src/patches/versions/JPN39.cpp b/src/patches/versions/JPN39.cpp index 0a52220..8913827 100644 --- a/src/patches/versions/JPN39.cpp +++ b/src/patches/versions/JPN39.cpp @@ -315,7 +315,7 @@ std::vector datatable_patch = {}; #define DATATABLE_PATCH_REGISTER(location, reg, value, skip) { datatable_patch.push_back(safetyhook::create_mid(location, [](SafetyHookContext &ctx) {ctx.reg = (uintptr_t)(value); ctx.rip = location + skip;})); } void PatchDatatable () { - LogMessage (LogLevel::INFO, "Set Datatable Size to 12MB"); + LogMessage (LogLevel::INFO, "Using Datatable patch size: 12MB"); for (int i = 0; i < 3; i ++) datatableBuffer[i] = (uint8_t *)malloc (datatableBufferSize); DATATABLE_PATCH_REGISTER (ASLR (0x1400ABE26), r8, datatableBufferSize, 6); DATATABLE_PATCH_REGISTER (ASLR (0x1400ABE3A), r8, datatableBufferSize, 6); @@ -334,7 +334,7 @@ PatchDatatable () { void Init () { - LogMessage (LogLevel::INFO, "Init JPN39 patches"); + LogMessage (LogLevel::DEBUG, "Init JPN39 patches"); bool unlockSongs = Config::ConfigManager::instance ().getPatchesConfig ().unlock_songs; double modelResRate = Config::ConfigManager::instance ().getGraphicsConfig ().model_res_rate; @@ -350,7 +350,7 @@ Init () { if (modelResRate > 0) { i32 donModelX = (i32)(xRes * modelResRate); i32 donModelY = (i32)(yRes * modelResRate); - LogMessage (LogLevel::INFO, "Patch DonModel use resolution {}x{}", donModelX, donModelY); + LogMessage (LogLevel::INFO, "Using DonModel Resolutin: {}x{}", donModelX, donModelY); WRITE_MEMORY (ASLR (0x1404F3D5B), i32, donModelX); WRITE_MEMORY (ASLR (0x1404F3D62), i32, donModelY); } diff --git a/src/pollasync.cpp b/src/pollasync.cpp index c466ebb..b6afe83 100644 --- a/src/pollasync.cpp +++ b/src/pollasync.cpp @@ -9,6 +9,7 @@ static bool jpLayout = Config::ConfigManager::instance ().getKeyboardConfig ().jp_layout; static bool autoIme = Config::ConfigManager::instance ().getKeyboardConfig ().auto_ime; static bool globalKeyboard = Config::ConfigManager::instance ().getControllerConfig ().global_keyboard; +static bool simpleInput = Config::ConfigManager::instance ().getControllerConfig ().simple_input; static bool emulateUsio = Config::ConfigManager::instance ().getEmulationConfig ().usio; extern float axisThreshold; @@ -35,7 +36,7 @@ float currentControllerAxisState[static_cast(SDLAxis::SDL_AXIS_MAX)] = { uint8_t controllerAxisCount[static_cast(SDLAxis::SDL_AXIS_MAX)] = { 0 }; uint8_t controllerAxisDiff[static_cast(SDLAxis::SDL_AXIS_MAX)] = { 0 }; -int maxCount = 1; +int maxCount = 10; SDL_Window *window; SDL_Gamepad *controllers[255]; @@ -101,10 +102,10 @@ void KeyboardMainLoop() { if (usingKeyboard) { keyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, InputProc, nullptr, 0); if (keyboardHook == nullptr) LogMessage (LogLevel::ERROR, "Failed to install keyboard hook!\n"); - else LogMessage (LogLevel::INFO, "KeyboardLL hook installed!"); + else LogMessage (LogLevel::DEBUG, "KeyboardLL hook installed!"); } - if (maxCount > 2) LogMessage (LogLevel::ERROR, "CHEATING MODE! max count is set to {}", maxCount); - LogMessage (LogLevel::WARN, "(experimental) Using Async IO!"); + if (maxCount > 2) LogMessage (LogLevel::WARN, "Using Cache count max={}", maxCount); + LogMessage (LogLevel::INFO, "Using Async Keyboard"); MSG msg; while (GetMessage(&msg, hwnd, 0, 0) > 0) { TranslateMessage(&msg); @@ -115,9 +116,7 @@ void KeyboardMainLoop() { void InitializeKeyboard () { - if (usingKeyboard) { - std::thread (KeyboardMainLoop).detach (); - } + std::thread (KeyboardMainLoop).detach (); } void @@ -137,8 +136,10 @@ InitializePoll (HWND windowHandle) { usingController = Config::ConfigManager::instance ().getKeyBindings ().usingController(); usingSDLEvent = usingMouse || usingController; + if (simpleInput) LogMessage (LogLevel::INFO, "Using Simple Input (1-1 bind)"); + atexit ([](){ if (currentLayout != nullptr) ActivateKeyboardLayout (currentLayout, KLF_SETFORPROCESS);}); - InitializeKeyboard (); + if (usingKeyboard) InitializeKeyboard (); if (usingSDLEvent) { LogMessage (LogLevel::DEBUG, "InitializePoll"); bool hasRumble = true; @@ -258,7 +259,7 @@ void UpdatePoll (HWND windowHandle) { if (!CheckForegroundWindow (windowHandle)) return; if (!emulateUsio) return; - CleanPoll (); + if (!simpleInput) CleanPoll (); if (usingSDLEvent) { SDL_Event event; SDL_Gamepad *controller; @@ -356,8 +357,11 @@ int maxKeyboardCount = 1; bool KeyboardIsTapped (const uint8_t keycode) { if (keyboardCount[keycode] > 0) { - keyboardDiff[keycode] = 1; - keyboardClean = true; + if (simpleInput) keyboardCount[keycode] --; + else { + keyboardDiff[keycode] = 1; + keyboardClean = true; + } return true; } return false; } @@ -383,7 +387,8 @@ bool GetMouseScrollIsTapped (const Scroll scroll) { if (scroll == Scroll::MOUSE_SCROLL_INVALID) return false; if (mouseWheelCount[(int)scroll - 1] > 0) { - mouseWheelDiff[(int)scroll - 1] = 1; + if (simpleInput) mouseWheelCount[(int)scroll - 1] --; + else mouseWheelDiff[(int)scroll - 1] = 1; return true; } return false; } @@ -397,7 +402,8 @@ int maxButtonCount = 1; bool ControllerButtonIsTapped (const SDL_GamepadButton button) { if (controllerCount[button] > 0) { - controllerDiff[button] = 1; + if (simpleInput) controllerCount[button] --; + else controllerDiff[button] = 1; return true; } return false; } @@ -410,7 +416,8 @@ ControllerAxisIsDown (const SDLAxis axis) { bool ControllerAxisIsTapped (const SDLAxis axis) { if (controllerAxisCount[(int)axis] > 0) { - controllerAxisDiff[(int)axis] = 1; + if (simpleInput) controllerAxisCount[(int)axis] --; + else controllerAxisDiff[(int)axis] = 1; return true; } return false; } From 176451d38ae56d9bd8555fcb5e5f65e83eb68b2b Mon Sep 17 00:00:00 2001 From: ptmaster Date: Tue, 18 Mar 2025 23:35:56 +0800 Subject: [PATCH 5/5] fix README.md --- README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e2634f7..57d0fd0 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ song_no = [] # Song noes used for custom folder 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) global_keyboard = false # Accept keyboard input even if Taiko.exe is not foreground - +simple_input = false # Simplified input handler, might decrease game laggy [keyboard] @@ -101,6 +101,7 @@ enabled = false # Replace assets from the game using a layered file # | For example if you want to edit the wordlist, add your edited version like so: # | .\Data_mods\x64\datatable\wordlist.json # | You can provide both unencrypted and encrypted files. +mod_dir = "Data_mods" [logging] @@ -108,12 +109,14 @@ log_level = "INFO" # Log level, Can be either "NONE", "ERROR", "WARN", # | Keep this as low as possible (Info is usually more than enough) as more logging will slow down your game log_to_file = false # Log to file, set this to true to save the logs from your last session to TaikoArcadeLoader.log # |Again, if you do not have a use for this (debugging mods or whatnot), turn it off. -log_path = "logs.log" # Log file path (Can be both relative and absolute). +log_method_name = true +log_full_source = true +log_dir = "./logs/" # Log file path (Can be both relative and absolute). ``` ### TestMode options (JPN39 only) -TaikoArcadeLoader offers several patches to select in TestMode +TaikoArcadeLoader offers several patches to select in TestMode The follow options are available in "MOD MANAGER" menu: