diff --git a/CMakeLists.txt b/CMakeLists.txt index d2dddd6..10a4a1e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,7 +61,7 @@ endif() # Fetch zxing-cpp FetchContent_Declare( zxing_cpp - URL https://github.com/zxing-cpp/zxing-cpp/archive/refs/tags/v2.2.1.zip + URL https://github.com/zxing-cpp/zxing-cpp/archive/refs/tags/v2.3.0.zip ) set(BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) FetchContent_MakeAvailable(zxing_cpp) @@ -171,6 +171,8 @@ set(SOURCES src/patches/testmode.cpp src/patches/timer.cpp src/patches/language.cpp + src/patches/lua.cpp + src/patches/statusmonitor.cpp # src/patches/unlimitsong.cpp src/patches/versions/JPN00.cpp src/patches/versions/JPN08.cpp diff --git a/logger.cpp b/logger.cpp deleted file mode 100644 index b024a44..0000000 --- a/logger.cpp +++ /dev/null @@ -1,113 +0,0 @@ -#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 deleted file mode 100644 index d8f5f19..0000000 --- a/logger.h +++ /dev/null @@ -1,123 +0,0 @@ -#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/src/config.cpp b/src/config.cpp index 51d84de..7c5d2f3 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -149,9 +149,9 @@ ConfigManager::updateQrConfig () { return false; } - auto result = rfl::toml::read (stream); + auto result = rfl::toml::read (stream); if (result) { - config.qr = result.value (); + config.qr = result.value ().qr; return true; } diff --git a/src/constants.h b/src/constants.h index 4bbf46d..2bd61bc 100644 --- a/src/constants.h +++ b/src/constants.h @@ -12,4 +12,40 @@ enum class GameVersion : XXH64_hash_t { enum StatusType { CardStatus = 1, QrStatus = 2 +}; + +enum SceneStatus { + SceneNone = -1, + SceneLoading = 0, + SceneTestMode, + SceneNotice, + SceneCopyright, + SceneBNLogo, + SceneTitle, + SceneAttractMovie, + SceneMusicIntro, + SceneCaution, + SceneEntry = 50, + SceneSelectAiEnso = 100, + SceneStartAiEnso, + SceneResultAiEnso, + SceneResultAllAiEnso, + SceneSelectKimetsu = 200, + SceneStartKimetsu, + SceneResultKimetsu, + SceneSelectOnePiece = 300, + SceneStartOnePiece, + SceneResultOnePiece, + SceneSelectAiSoshina = 400, + SceneStartAiSoshina, + SceneResultAiSoshina, + SceneSelectAoharu = 500, + SceneStartAoharu, + SceneResultAoharu, + SceneSelectEnso = 10000, + SceneStartEnso, + SceneResultEnso, + SceneSelectDani = 20000, + SceneStartDani, + SceneResultDani, }; \ No newline at end of file diff --git a/src/dllmain.cpp b/src/dllmain.cpp index 0f3c178..41360f3 100644 --- a/src/dllmain.cpp +++ b/src/dllmain.cpp @@ -274,6 +274,7 @@ DllMain (HMODULE module, const DWORD reason, LPVOID reserved) { case GameVersion::CHN00: patches::CHN00::Init (); break; } + patches::Lua::Init (); patches::Scanner::Init (); patches::Audio::Init (); // patches::Dxgi::Init (); @@ -282,6 +283,7 @@ DllMain (HMODULE module, const DWORD reason, LPVOID reserved) { patches::TestMode::Init (); patches::LayeredFs::Init (); // patches::UnlimitSong::Init (); + patches::StatusMonitor::Init (); std::chrono::duration duration = std::chrono::high_resolution_clock::now() - start; LogMessage (LogLevel::DEBUG, "=== Finished Loading patches!"); diff --git a/src/patches/lua.cpp b/src/patches/lua.cpp new file mode 100644 index 0000000..25b7a4b --- /dev/null +++ b/src/patches/lua.cpp @@ -0,0 +1,158 @@ +#include "constants.h" +#include "helpers.h" +#include "patches.h" + +namespace patches::Lua { + #define LUA_GLOBALSINDEX -10002 + typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); + + LuaState globalLuaState = 0; + + FUNCTION_PTR (lua_CFunction, lua_atpanic, PROC_ADDRESS ("lua51.dll", "lua_atpanic"), LuaState, lua_CFunction); + FUNCTION_PTR (void, lua_call, PROC_ADDRESS ("lua51.dll", "lua_call"), LuaState, int, int); + FUNCTION_PTR (int, lua_checkstack, PROC_ADDRESS ("lua51.dll", "lua_checkstack"), LuaState, int); + FUNCTION_PTR (void, lua_concat, PROC_ADDRESS ("lua51.dll", "lua_concat"), LuaState, int); + FUNCTION_PTR (int, lua_cpcall, PROC_ADDRESS ("lua51.dll", "lua_cpcall"), LuaState, lua_CFunction, void *); + FUNCTION_PTR (void, lua_createtable, PROC_ADDRESS ("lua51.dll", "lua_createtable"), LuaState, int, int); + FUNCTION_PTR (int, lua_equal, PROC_ADDRESS ("lua51.dll", "lua_equal"), LuaState, int, int); + FUNCTION_PTR (int, lua_error, PROC_ADDRESS ("lua51.dll", "lua_error"), LuaState); + FUNCTION_PTR (void, lua_getfenv, PROC_ADDRESS ("lua51.dll", "lua_getfenv"), LuaState, int); + FUNCTION_PTR (void, lua_getfield, PROC_ADDRESS ("lua51.dll", "lua_getfield"), LuaState, int, const char *); + #define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, s) + // FUNCTION_PTR (void, lua_getglobal, PROC_ADDRESS ("lua51.dll", "lua_getglobal"), LuaState, const char *); + FUNCTION_PTR (void, lua_getlocal, PROC_ADDRESS ("lua51.dll", "lua_getlocal"), LuaState, const char *); + FUNCTION_PTR (int, lua_getmetatable, PROC_ADDRESS ("lua51.dll", "lua_getmetatable"), LuaState, int); + FUNCTION_PTR (void, lua_gettable, PROC_ADDRESS ("lua51.dll", "lua_gettable"), LuaState, int); + FUNCTION_PTR (int, lua_gettop, PROC_ADDRESS ("lua51.dll", "lua_gettop"), LuaState); + FUNCTION_PTR (void, lua_insert, PROC_ADDRESS ("lua51.dll", "lua_gettop"), LuaState, int); + FUNCTION_PTR (int, lua_isboolean, PROC_ADDRESS ("lua51.dll", "lua_isboolean"), LuaState, int); + FUNCTION_PTR (int, lua_iscfunction, PROC_ADDRESS ("lua51.dll", "lua_iscfunction"), LuaState, int); + FUNCTION_PTR (int, lua_isfunction, PROC_ADDRESS ("lua51.dll", "lua_isfunction"), LuaState, int); + FUNCTION_PTR (int, lua_islightuserdata, PROC_ADDRESS ("lua51.dll", "lua_islightuserdata"), LuaState, int); + FUNCTION_PTR (int, lua_isnil, PROC_ADDRESS ("lua51.dll", "lua_isnil"), LuaState, int); + FUNCTION_PTR (int, lua_isnone, PROC_ADDRESS ("lua51.dll", "lua_isnone"), LuaState, int); + FUNCTION_PTR (int, lua_isnoneornil, PROC_ADDRESS ("lua51.dll", "lua_isnoneornil"), LuaState, int); + FUNCTION_PTR (int, lua_isnumber, PROC_ADDRESS ("lua51.dll", "lua_isnumber"), LuaState, int); + FUNCTION_PTR (int, lua_isstring, PROC_ADDRESS ("lua51.dll", "lua_isstring"), LuaState, int); + FUNCTION_PTR (int, lua_istable, PROC_ADDRESS ("lua51.dll", "lua_istable"), LuaState, int); + FUNCTION_PTR (int, lua_isthread, PROC_ADDRESS ("lua51.dll", "lua_isthread"), LuaState, int); + FUNCTION_PTR (int, lua_isuserdata, PROC_ADDRESS ("lua51.dll", "lua_isuserdata"), LuaState, int); + FUNCTION_PTR (int, lua_lessthan, PROC_ADDRESS ("lua51.dll", "lua_lessthan"), LuaState, int, int); + FUNCTION_PTR (void, lua_newtable, PROC_ADDRESS ("lua51.dll", "lua_newtable"), LuaState); + FUNCTION_PTR (LuaState, lua_newthread, PROC_ADDRESS ("lua51.dll", "lua_newthread"), LuaState); + FUNCTION_PTR (void *, lua_newuserdata, PROC_ADDRESS ("lua51.dll", "lua_newuserdata"), LuaState, size_t); + FUNCTION_PTR (int, lua_next, PROC_ADDRESS ("lua51.dll", "lua_next"), LuaState, int); + FUNCTION_PTR (size_t, lua_objlen, PROC_ADDRESS ("lua51.dll", "lua_objlen"), LuaState, int); + FUNCTION_PTR (int, lua_pcall, PROC_ADDRESS ("lua51.dll", "lua_pcall"), LuaState, int, int, int); + FUNCTION_PTR (void, lua_pop, PROC_ADDRESS ("lua51.dll", "lua_pop"), LuaState, int); + FUNCTION_PTR (void, lua_pushboolean, PROC_ADDRESS ("lua51.dll", "lua_pushboolean"), LuaState, int); + FUNCTION_PTR (void, lua_pushcclosure, PROC_ADDRESS ("lua51.dll", "lua_pushcclosure"), LuaState, lua_CFunction, int); + FUNCTION_PTR (void, lua_pushcfunction, PROC_ADDRESS ("lua51.dll", "lua_pushcfunction"), LuaState, lua_CFunction); + FUNCTION_PTR (const char *, lua_pushfstring, PROC_ADDRESS ("lua51.dll", "lua_pushfstring"), LuaState, const char *, ...); + FUNCTION_PTR (void, lua_pushinteger, PROC_ADDRESS ("lua51.dll", "lua_pushinteger"), LuaState, i64); + FUNCTION_PTR (void, lua_pushlightuserdata, PROC_ADDRESS ("lua51.dll", "lua_pushlightuserdata"), LuaState, void *); + FUNCTION_PTR (void, lua_pushliteral, PROC_ADDRESS ("lua51.dll", "lua_pushliteral"), LuaState, const char *); + FUNCTION_PTR (void, lua_pushlstring, PROC_ADDRESS ("lua51.dll", "lua_pushlstring"), LuaState, const char *, size_t); + FUNCTION_PTR (void, lua_pushnil, PROC_ADDRESS ("lua51.dll", "lua_pushnil"), LuaState); + FUNCTION_PTR (void, lua_pushnumber, PROC_ADDRESS ("lua51.dll", "lua_pushnumber"), LuaState, double); + FUNCTION_PTR (void, lua_pushstring, PROC_ADDRESS ("lua51.dll", "lua_pushstring"), LuaState, const char *); + FUNCTION_PTR (int, lua_pushthread, PROC_ADDRESS ("lua51.dll", "lua_pushthread"), LuaState); + FUNCTION_PTR (void, lua_pushvalue, PROC_ADDRESS ("lua51.dll", "lua_pushvalue"), LuaState, int); + FUNCTION_PTR (void, lua_pushvfstring, PROC_ADDRESS ("lua51.dll", "lua_pushvfstring"), LuaState, const char *, va_list); + FUNCTION_PTR (void, lua_rawget, PROC_ADDRESS ("lua51.dll", "lua_rawget"), LuaState, int); + FUNCTION_PTR (void, lua_rawgeti, PROC_ADDRESS ("lua51.dll", "lua_rawgeti"), LuaState, int, int); + FUNCTION_PTR (void, lua_rawset, PROC_ADDRESS ("lua51.dll", "lua_rawset"), LuaState, int); + FUNCTION_PTR (void, lua_rawseti, PROC_ADDRESS ("lua51.dll", "lua_rawseti"), LuaState, int, int); + FUNCTION_PTR (void, lua_remove, PROC_ADDRESS ("lua51.dll", "lua_remove"), LuaState, int); + FUNCTION_PTR (void, lua_replace, PROC_ADDRESS ("lua51.dll", "lua_replace"), LuaState, int); + FUNCTION_PTR (int, lua_resume, PROC_ADDRESS ("lua51.dll", "lua_resume"), LuaState, int); + FUNCTION_PTR (int, lua_setfenv, PROC_ADDRESS ("lua51.dll", "lua_setfenv"), LuaState, int); + FUNCTION_PTR (void, lua_setfield, PROC_ADDRESS ("lua51.dll", "lua_setfield"), LuaState, int, const char *); + FUNCTION_PTR (void, lua_setglobal, PROC_ADDRESS ("lua51.dll", "lua_setglobal"), LuaState, const char *); + FUNCTION_PTR (int, lua_setmetatable, PROC_ADDRESS ("lua51.dll", "lua_setmetatable"), LuaState, int); + FUNCTION_PTR (void, lua_settable, PROC_ADDRESS ("lua51.dll", "lua_settable"), LuaState, int); + FUNCTION_PTR (void, lua_settop, PROC_ADDRESS ("lua51.dll", "lua_settop"), LuaState, int); + FUNCTION_PTR (int, lua_status, PROC_ADDRESS ("lua51.dll", "lua_status"), LuaState); + FUNCTION_PTR (int, lua_toboolean, PROC_ADDRESS ("lua51.dll", "lua_toboolean"), LuaState, int); + FUNCTION_PTR (lua_CFunction, lua_tocfunction, PROC_ADDRESS ("lua51.dll", "lua_tocfunction"), LuaState, int); + FUNCTION_PTR (i64, lua_tointeger, PROC_ADDRESS ("lua51.dll", "lua_tointeger"), LuaState, int); + FUNCTION_PTR (const char *, lua_tolstring, PROC_ADDRESS ("lua51.dll", "lua_tolstring"), LuaState, int, size_t *); + FUNCTION_PTR (double, lua_tonumber, PROC_ADDRESS ("lua51.dll", "lua_tonumber"), LuaState, int); + FUNCTION_PTR (void *, lua_topointer, PROC_ADDRESS ("lua51.dll", "lua_topointer"), LuaState, int); + FUNCTION_PTR (const char *, lua_tostring, PROC_ADDRESS ("lua51.dll", "lua_tostring"), LuaState, int); + FUNCTION_PTR (LuaState, lua_tothread, PROC_ADDRESS ("lua51.dll", "lua_tothread"), LuaState, int); + FUNCTION_PTR (void *, lua_touserdata, PROC_ADDRESS ("lua51.dll", "lua_touserdata"), LuaState, int); + FUNCTION_PTR (int, lua_type, PROC_ADDRESS ("lua51.dll", "lua_type"), LuaState, int); + FUNCTION_PTR (const char *, lua_typename, PROC_ADDRESS ("lua51.dll", "lua_typename"), LuaState, int); + FUNCTION_PTR (i32, luaL_loadstring, PROC_ADDRESS ("lua51.dll", "luaL_loadstring"), i64, const char *); + + FAST_HOOK (i64, luaL_newstate, PROC_ADDRESS ("lua51.dll", "luaL_newstate")) { + // LogMessage (LogLevel::INFO, "Lua::NewState"); + globalLuaState = originalluaL_newstate.call (); + + // LogMessage (LogLevel::INFO, "1"); + // lua_getglobal (globalLuaState, "package"); + // LogMessage (LogLevel::INFO, "2"); + // lua_getfield (globalLuaState, -1, "path"); + // LogMessage (LogLevel::INFO, "3"); + // const char *path = lua_tostring(globalLuaState, -1); + // LogMessage (LogLevel::INFO, "4"); + // lua_pop (globalLuaState, 2); + + // LogMessage (LogLevel::INFO, "Lua package.path={}", path); + + return globalLuaState; + } + #define LUA_MULTRET (-1) + #define luaL_dostring(L, s) (luaL_loadstring (L, s) || lua_pcall (L, 0, LUA_MULTRET, 0)) + + void + Init () { + INSTALL_FAST_HOOK (luaL_newstate); + } + + void + Execute (std::string code) { + luaL_dostring (globalLuaState, code.c_str ()); + } + + void + RegisterMethod (std::string base, std::string methodName, lua_CFunction method) { + return; // WAIT IMPLEMENT + } + + void + SetTop (i64 lua_State, i32 index) { + lua_settop (lua_State, index); + } + + void + Replace (i64 lua_State, i32 index) { + lua_replace (lua_State, index); + } + + void + PushCClosure (i64 lua_State, lua_CFunction func, i32 index) { + lua_pushcclosure (lua_State, func, index); + } + + void + PushBoolean (i64 lua_State, bool value) { + lua_pushboolean (lua_State, value); + } + + void + PushString (i64 lua_State, std::string value) { + lua_pushstring (lua_State, value.c_str()); + } + + bool + ToBoolean (i64 lua_State, i32 index) { + return lua_toboolean (lua_State, index); + } + + const char * + ToLString (i64 lua_State, i32 index, size_t *size) { + return lua_tolstring(lua_State, index, size); + } +} \ No newline at end of file diff --git a/src/patches/patches.h b/src/patches/patches.h index 1d72c7f..47b1c6c 100644 --- a/src/patches/patches.h +++ b/src/patches/patches.h @@ -95,24 +95,25 @@ void InitCardReader (CommitCardCallback touch); void InitQRScanner (CommitQrCallback scan); void InitQRLogin (CommitQrLoginCallback login); void UpdateStatus (size_t type, bool status); +void UpdateScene (SceneStatus last, SceneStatus next); // Plugins Loader void LoadPlugins (); } // namespace Plugins namespace Scanner { enum class State { Disable, Ready, CopyWait }; -void Init (); -void Update (); +void Init (); +void Update (); namespace Card { typedef int32_t (*CallbackAttach) (int32_t, int32_t, int32_t *); typedef void (*CallbackTouch) (int32_t, int32_t, uint8_t[168], uint64_t); -void Init (); -void Update (); -bool Commit (std::string accessCode, std::string chipId); +void Init (); +void Update (); +bool Commit (std::string accessCode, std::string chipId); } // namespace Card namespace Qr { -void Init (); -void Update (); -bool Commit (std::vector &buffer); +void Init (); +void Update (); +bool Commit (std::vector &buffer); bool CommitLogin (std::string accessCode); std::vector &ReadQRData (std::vector &buffer); std::vector &ReadQRImage (std::vector &buffer); @@ -135,9 +136,26 @@ typedef struct { std::string text; int fontType; } WordInfo; -void Init (); -void SetupAccessor (u64 appAccessor, RefDataTableManager refDataTableManager); +void Init (); +void SetupAccessor (u64 appAccessor, RefDataTableManager refDataTableManager); WordInfo *GetWordInfo (std::string &key); -void SetWordInfo (WordInfo *wordInfo); +void SetWordInfo (WordInfo *wordInfo); } +namespace Lua { +typedef i64 LuaState; +typedef int (*lua_CFunction) (LuaState L); +void Init (); +void Execute (std::string code); +void RegisterMethod (std::string base, std::string methodName, std::function method); +void SetTop (i64 lua_State, i32 index); +void Replace (i64 lua_State, i32 index); +void PushCClosure (i64 lua_State, lua_CFunction func, i32 index); +void PushBoolean (i64 lua_State, bool value); +void PushString (i64 lua_State, std::string value); +bool ToBoolean (i64 lua_State, i32 index); +const char *ToLString (i64 lua_State, i32 index, size_t *size); +} // namespace lua +namespace StatusMonitor { +void Init(); +} // namespace StatusMonitor } // namespace patches diff --git a/src/patches/plugins.cpp b/src/patches/plugins.cpp index 318f8d6..b410585 100644 --- a/src/patches/plugins.cpp +++ b/src/patches/plugins.cpp @@ -16,6 +16,7 @@ namespace patches::Plugins { typedef void (*SendQRScannerEvent) (CommitQrCallback scan); typedef void (*SendQRLoginEvent) (CommitQrLoginCallback login); typedef void (*StatusChangeEvent) (size_t type, bool status); + typedef void (*SceneChangeEvent) (SceneStatus last, SceneStatus next); std::mutex updateMutex; std::condition_variable updateCV; @@ -84,6 +85,14 @@ namespace patches::Plugins { if (event) ((StatusChangeEvent)event) (type, status); } } + void + UpdateScene (SceneStatus last, SceneStatus next) { + // printWarning ("Send UpdateScene last=%d next=%d", last, next); + for (auto plugin : plugins) { + auto event = GetProcAddress (plugin, "UpdateScene"); + if (event) ((SceneChangeEvent)event) (last, next); + } + } // Plugins Loader void LoadPlugins () { diff --git a/src/patches/scanner.cpp b/src/patches/scanner.cpp index aa5ab28..95a5099 100644 --- a/src/patches/scanner.cpp +++ b/src/patches/scanner.cpp @@ -378,6 +378,8 @@ namespace Qr { u16 type = Config::ConfigManager::instance ().getQrConfig ().data.type; std::vector songNoes = Config::ConfigManager::instance ().getQrConfig ().data.song_no; + LogMessage (LogLevel::INFO, "Read QRData, serial: {}", serial); + buffer.clear (); std::vector header = { 0x53, 0x31, 0x32, 0x00, 0x00, 0xFF, 0xFF, (uint8_t)serial.size (), 0x01, 0x00 }; @@ -400,6 +402,8 @@ namespace Qr { ReadQRImage (std::vector &buffer) { std::string imagePath = Config::ConfigManager::instance ().getQrConfig ().image_path; + LogMessage (LogLevel::INFO, "Read QRImage, pathpath: {}", imagePath); + buffer.clear (); std::u8string u8PathStr (imagePath.begin (), imagePath.end ()); std::filesystem::path u8Path (u8PathStr); diff --git a/src/patches/statusmonitor.cpp b/src/patches/statusmonitor.cpp new file mode 100644 index 0000000..e3570fa --- /dev/null +++ b/src/patches/statusmonitor.cpp @@ -0,0 +1,110 @@ +#include "constants.h" +#include "helpers.h" +#include "patches.h" + +extern GameVersion gameVersion; + +namespace patches::StatusMonitor { + +SceneStatus currentScene = SceneStatus::SceneNone; + +#define DEFINE_SCENE(sceneName) \ +typedef char (*sceneName) (i64 a1, i64 a2, i64 a3); \ +SafetyHookInline original##sceneName; \ +char implOf##sceneName (i64 a1, i64 a2, i64 a3) { \ + char result = original##sceneName.fastcall (a1, a2, a3); \ + if (currentScene != SceneStatus::##sceneName) { \ + LogMessage (LogLevel::INFO, "Switch to {}", #sceneName); \ + Plugins::UpdateScene (currentScene, SceneStatus::##sceneName); \ + currentScene = SceneStatus::##sceneName; \ + } \ + return result; \ +} +// Attract +DEFINE_SCENE (SceneLoading) +DEFINE_SCENE (SceneTestMode) +DEFINE_SCENE (SceneNotice) +DEFINE_SCENE (SceneCopyright) +DEFINE_SCENE (SceneBNLogo) +DEFINE_SCENE (SceneTitle) +DEFINE_SCENE (SceneAttractMovie) +DEFINE_SCENE (SceneMusicIntro) +DEFINE_SCENE (SceneCaution) +// Entry +DEFINE_SCENE (SceneEntry) +// AiEnso +DEFINE_SCENE (SceneSelectAiEnso) +DEFINE_SCENE (SceneStartAiEnso) +DEFINE_SCENE (SceneResultAiEnso) +DEFINE_SCENE (SceneResultAllAiEnso) +// Kimetsu +DEFINE_SCENE (SceneSelectKimetsu) +DEFINE_SCENE (SceneStartKimetsu) +DEFINE_SCENE (SceneResultKimetsu) +// OnePiece +DEFINE_SCENE (SceneSelectOnePiece) +DEFINE_SCENE (SceneStartOnePiece) +DEFINE_SCENE (SceneResultOnePiece) +// AiSoshina +DEFINE_SCENE (SceneSelectAiSoshina) +DEFINE_SCENE (SceneStartAiSoshina) +DEFINE_SCENE (SceneResultAiSoshina) +// Aoharu +DEFINE_SCENE (SceneSelectAoharu) +DEFINE_SCENE (SceneStartAoharu) +DEFINE_SCENE (SceneResultAoharu) +// Enso +DEFINE_SCENE (SceneSelectEnso) +DEFINE_SCENE (SceneStartEnso) +DEFINE_SCENE (SceneResultEnso) +// Dani +DEFINE_SCENE (SceneSelectDani) +DEFINE_SCENE (SceneStartDani) +DEFINE_SCENE (SceneResultDani) + +void Init() { + switch (gameVersion) { + case GameVersion::JPN39: { + // Attract + INSTALL_FAST_HOOK_DYNAMIC (SceneTestMode, ASLR (0x140479520)); + INSTALL_FAST_HOOK_DYNAMIC (SceneCopyright, ASLR (0x140446B90)); + INSTALL_FAST_HOOK_DYNAMIC (SceneBNLogo, ASLR (0x140433960)); + INSTALL_FAST_HOOK_DYNAMIC (SceneTitle, ASLR (0x14045A4F0)); + INSTALL_FAST_HOOK_DYNAMIC (SceneAttractMovie, ASLR (0x1404320C0)); + INSTALL_FAST_HOOK_DYNAMIC (SceneMusicIntro, ASLR (0x1404572B0)); + INSTALL_FAST_HOOK_DYNAMIC (SceneCaution, ASLR (0x140433E60)); + // Entry + INSTALL_FAST_HOOK_DYNAMIC (SceneEntry, ASLR (0x14044EBD0)); + // AiEnso + INSTALL_FAST_HOOK_DYNAMIC (SceneSelectAiEnso, ASLR (0x140424E20)); + INSTALL_FAST_HOOK_DYNAMIC (SceneStartAiEnso, ASLR (0x14040F7B0)); + INSTALL_FAST_HOOK_DYNAMIC (SceneResultAiEnso, ASLR (0x14041F130)); + INSTALL_FAST_HOOK_DYNAMIC (SceneResultAllAiEnso, ASLR (0x14041C900)); + // Kimetsu + INSTALL_FAST_HOOK_DYNAMIC (SceneSelectKimetsu, ASLR (0x140452DB0)); + INSTALL_FAST_HOOK_DYNAMIC (SceneStartKimetsu, ASLR (0x14041B760)); + INSTALL_FAST_HOOK_DYNAMIC (SceneResultKimetsu, ASLR (0x140450020)); + // OnePiece + INSTALL_FAST_HOOK_DYNAMIC (SceneSelectOnePiece, ASLR (0x140436770)); + INSTALL_FAST_HOOK_DYNAMIC (SceneSelectOnePiece, ASLR (0x14041BA50)); + INSTALL_FAST_HOOK_DYNAMIC (SceneResultOnePiece, ASLR (0x140434940)); + // AiSoshina + INSTALL_FAST_HOOK_DYNAMIC (SceneSelectAiSoshina, ASLR (0x14043B3D0)); + INSTALL_FAST_HOOK_DYNAMIC (SceneStartAiSoshina, ASLR (0x140410610)); + INSTALL_FAST_HOOK_DYNAMIC (SceneResultAiSoshina, ASLR (0x140439510)); + // Aoharu + INSTALL_FAST_HOOK_DYNAMIC (SceneSelectAoharu, ASLR (0x14042EA90)); + INSTALL_FAST_HOOK_DYNAMIC (SceneStartAoharu, ASLR (0x14040FE50)); + INSTALL_FAST_HOOK_DYNAMIC (SceneResultAoharu, ASLR (0x14042DB00)); + // Enso + INSTALL_FAST_HOOK_DYNAMIC (SceneSelectEnso, ASLR (0x1404584C0)); + INSTALL_FAST_HOOK_DYNAMIC (SceneStartEnso, ASLR (0x1404114E0)); + INSTALL_FAST_HOOK_DYNAMIC (SceneResultEnso, ASLR (0x140416760)); + // Dani + INSTALL_FAST_HOOK_DYNAMIC (SceneSelectDani, ASLR (0x14044BBA0)); + INSTALL_FAST_HOOK_DYNAMIC (SceneStartDani, ASLR (0x140410BA0)); + INSTALL_FAST_HOOK_DYNAMIC (SceneResultDani, ASLR (0x1404478B0)); + } + } +} +} \ No newline at end of file diff --git a/src/patches/versions/CHN00.cpp b/src/patches/versions/CHN00.cpp index 81821ec..73488ca 100644 --- a/src/patches/versions/CHN00.cpp +++ b/src/patches/versions/CHN00.cpp @@ -28,14 +28,14 @@ HOOK (i32, HaspRead, PROC_ADDRESS ("hasp_windows_x64.dll", "hasp_read"), i32, i3 return 0; } -FUNCTION_PTR (i64, lua_settop, PROC_ADDRESS ("lua51.dll", "lua_settop"), u64, u64); -FUNCTION_PTR (i64, lua_pushboolean, PROC_ADDRESS ("lua51.dll", "lua_pushboolean"), u64, u64); -FUNCTION_PTR (i64, lua_pushstring, PROC_ADDRESS ("lua51.dll", "lua_pushstring"), u64, u64); +// FUNCTION_PTR (i64, lua_settop, PROC_ADDRESS ("lua51.dll", "lua_settop"), u64, u64); +// FUNCTION_PTR (i64, lua_pushboolean, PROC_ADDRESS ("lua51.dll", "lua_pushboolean"), u64, u64); +// FUNCTION_PTR (i64, lua_pushstring, PROC_ADDRESS ("lua51.dll", "lua_pushstring"), u64, u64); i64 lua_pushtrue (const i64 a1) { - lua_settop (a1, 0); - lua_pushboolean (a1, 1); + Lua::SetTop (a1, 0); + Lua::PushBoolean (a1, 1); return 1; } @@ -60,14 +60,14 @@ HOOK (i64, GetLanguage, ASLR (0x140023720), i64 a1) { } HOOK (i64, GetRegionLanguage, ASLR (0x1401AC300), i64 a1) { LogMessage (LogLevel::HOOKS, "GetRegionLanguage was called"); - lua_settop (a1, 0); - lua_pushstring (a1, reinterpret_cast (languageStr (language))); + Lua::SetTop (a1, 0); + Lua::PushString (a1, languageStr (language)); return 1; } HOOK (i64, GetCabinetLanguage, ASLR (0x1401AF270), i64, i64 a2) { LogMessage (LogLevel::HOOKS, "GetCabinetLanguage was called"); - lua_settop (a2, 0); - lua_pushstring (a2, reinterpret_cast (languageStr (language))); + Lua::SetTop (a2, 0); + Lua::PushString (a2, languageStr (language)); return 1; } diff --git a/src/patches/versions/JPN39.cpp b/src/patches/versions/JPN39.cpp index 8913827..22d5d28 100644 --- a/src/patches/versions/JPN39.cpp +++ b/src/patches/versions/JPN39.cpp @@ -29,28 +29,14 @@ FAST_HOOK_DYNAMIC (void, garmc_logger_log, i64 a1, int a2, void *a3, char a4) { FUNCTION_PTR (i64, GetPlayDataManagerRef, ASLR (0x140024AC0), i64); -i64 lua_State = 0; -FAST_HOOK (i64, luaL_newstate, PROC_ADDRESS ("lua51.dll", "luaL_newstate")) { return lua_State = originalluaL_newstate.call (); } -FUNCTION_PTR (void, lua_settop, PROC_ADDRESS ("lua51.dll", "lua_settop"), i64, i32); -FUNCTION_PTR (void, lua_replace, PROC_ADDRESS ("lua51.dll", "lua_replace"), i64, i32); -FUNCTION_PTR (void, lua_pushcclosure, PROC_ADDRESS ("lua51.dll", "lua_pushcclosure"), i64, i64, i32); -FUNCTION_PTR (void, lua_pushboolean, PROC_ADDRESS ("lua51.dll", "lua_pushboolean"), i64, i32); -FUNCTION_PTR (const char *, lua_pushstring, PROC_ADDRESS ("lua51.dll", "lua_pushstring"), i64, const char *); -FUNCTION_PTR (i32, lua_toboolean, PROC_ADDRESS ("lua51.dll", "lua_toboolean"), i64, i32); -FUNCTION_PTR (const char *, lua_tolstring, PROC_ADDRESS ("lua51.dll", "lua_tolstring"), u64, i32, size_t *); -FUNCTION_PTR (i32, lua_pcall, PROC_ADDRESS ("lua51.dll", "lua_pcall"), i64, i32, i32, i32); -FUNCTION_PTR (i32, luaL_loadstring, PROC_ADDRESS ("lua51.dll", "luaL_loadstring"), i64, const char *); -#define LUA_MULTRET (-1) -#define luaL_dostring(L, s) (luaL_loadstring (L, s) || lua_pcall (L, 0, LUA_MULTRET, 0)) - FUNCTION_PTR (u64, RefTestModeMain, ASLR (0x1400337C0), u64); FUNCTION_PTR (u64, RefPlayDataManager, ASLR (0x140024AC0), u64); FUNCTION_PTR (i64, GetUserCount, ASLR (0x1403F1080), u64); i64 -lua_pushbool (const i64 a1, const bool val) { - lua_settop (a1, 0); - lua_pushboolean (a1, val); +lua_pushbool (Lua::LuaState a1, const bool val) { + Lua::SetTop (a1, 0); + Lua::PushBoolean (a1, val); return 1; } @@ -138,67 +124,67 @@ FAST_HOOK (i64, AvailableMode_AprilFool001, ASLR (0x1402DE5B0), i64 a1) { return originalAvailableMode_AprilFool001.fastcall (a1); } TestMode::Value *freezeTimer = TestMode::CreateValue (L"ModFreezeTimer"); -i64 __fastcall lua_freeze_timer (const i64 a1) { +int lua_freeze_timer (Lua::LuaState a1) { LogMessage (LogLevel::HOOKS, "lua_freeze_timer was called"); const int tournamentMode = tournmentMode->Read (); - if (tournamentMode == 1) return lua_pushbool (a1, true); + if (tournamentMode == 1) return (int)lua_pushbool (a1, true); const int status = freezeTimer-> Read (); - if (status == 1) return lua_pushbool (a1, true); - return lua_pushbool (a1, false); + if (status == 1) return (int)lua_pushbool (a1, true); + return (int)lua_pushbool (a1, false); } MID_HOOK (FreezeTimer, ASLR (0x14019FF51), SafetyHookContext &ctx) { LogMessage (LogLevel::HOOKS, "FreezeTimer was called"); const auto a1 = ctx.rdi; const int v9 = static_cast (ctx.rax + 1); - lua_pushcclosure (a1, reinterpret_cast (&lua_freeze_timer), v9); + Lua::PushCClosure (a1, lua_freeze_timer, v9); ctx.rip = ASLR (0x14019FF65); } void ExecuteSendResultData () { - luaL_dostring(lua_State, R"( - local currentGameMode = PlayDataManager.GetPlayMode() + Lua::Execute(R"( + local currentGameMode = PlayDataManager.GetPlayMode() - if currentGameMode == GameMode.kEnso then - if g_entryType == 0 then - NetAccess.SendResultData(0) - elseif g_entryType == 1 then - NetAccess.SendResultData(1) - else - NetAccess.SendResultData(0) - NetAccess.SendResultData(1) + if currentGameMode == GameMode.kEnso then + if g_entryType == 0 then + NetAccess.SendResultData(0) + elseif g_entryType == 1 then + NetAccess.SendResultData(1) + else + NetAccess.SendResultData(0) + NetAccess.SendResultData(1) + end + elseif currentGameMode == GameMode.kAI then + if g_joinSide_ == 1 then + NetAccess.SendAiResultData(0) + elseif g_joinSide_ == 2 then + NetAccess.SendAiResultData(1) + end + elseif currentGameMode == GameMode.kCollabo025 then + if g_joinSide_ == 1 then + NetAccess.SendCollabo025AiResultData(0) + elseif g_joinSide_ == 2 then + NetAccess.SendCollabo025AiResultData(1) + end + elseif currentGameMode == GameMode.kCollabo026 then + if g_joinSide_ == 1 then + NetAccess.SendCollabo026AiResultData(0) + elseif g_joinSide_ == 2 then + NetAccess.SendCollabo026AiResultData(1) + end + elseif currentGameMode == GameMode.kAprilFool001 then + if g_entryType == 0 then + NetAccess.SendAprilFoolResultData(0) + elseif g_entryType == 1 then + NetAccess.SendAprilFoolResultData(1) + else + NetAccess.SendAprilFoolResultData(0) + NetAccess.SendAprilFoolResultData(1) + end end - elseif currentGameMode == GameMode.kAI then - if g_joinSide_ == 1 then - NetAccess.SendAiResultData(0) - elseif g_joinSide_ == 2 then - NetAccess.SendAiResultData(1) - end - elseif currentGameMode == GameMode.kCollabo025 then - if g_joinSide_ == 1 then - NetAccess.SendCollabo025AiResultData(0) - elseif g_joinSide_ == 2 then - NetAccess.SendCollabo025AiResultData(1) - end - elseif currentGameMode == GameMode.kCollabo026 then - if g_joinSide_ == 1 then - NetAccess.SendCollabo026AiResultData(0) - elseif g_joinSide_ == 2 then - NetAccess.SendCollabo026AiResultData(1) - end - elseif currentGameMode == GameMode.kAprilFool001 then - if g_entryType == 0 then - NetAccess.SendAprilFoolResultData(0) - elseif g_entryType == 1 then - NetAccess.SendAprilFoolResultData(1) - else - NetAccess.SendAprilFoolResultData(0) - NetAccess.SendAprilFoolResultData(1) - end - end - QR.StartQRExecAll(SceneType.kResult) - )" + QR.StartQRExecAll(SceneType.kResult) + )" ); } @@ -340,7 +326,7 @@ Init () { // Hook to get AppAccessor and ComponentAccessor INSTALL_FAST_HOOK (DeviceCheck); - INSTALL_FAST_HOOK (luaL_newstate); + // INSTALL_FAST_HOOK (luaL_newstate); // INSTALL_FAST_HOOK (AcquireMostCompatibleDisplayMode); // Window Size