From 9be3980a11d9a1398256fd450516c3cbb99734e3 Mon Sep 17 00:00:00 2001 From: ptmaster Date: Sat, 25 Jan 2025 04:06:29 +0800 Subject: [PATCH] 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 (