From 6e4a4bde2f02e6e329bc1fc42a193b486372cf3f Mon Sep 17 00:00:00 2001 From: Amos <48657826+Mauler125@users.noreply.github.com> Date: Fri, 4 Mar 2022 15:34:09 +0100 Subject: [PATCH] Implement SQVM error rebuild in engine with new Warning and Error loggers --- r5dev/core/logdef.cpp | 4 +- r5dev/engine/sys_utils.cpp | 155 ++++++++++++++++++++++++++++++++++++- r5dev/engine/sys_utils.h | 2 + r5dev/public/utility.cpp | 2 +- r5dev/squirrel/sqvm.cpp | 50 ++++++++++++ r5dev/squirrel/sqvm.h | 25 +++++- 6 files changed, 231 insertions(+), 7 deletions(-) diff --git a/r5dev/core/logdef.cpp b/r5dev/core/logdef.cpp index bfa3cc05..c086b92c 100644 --- a/r5dev/core/logdef.cpp +++ b/r5dev/core/logdef.cpp @@ -48,8 +48,10 @@ void SpdLog_Init(void) spdlog::rotating_logger_mt("sqvm_warn_logger", "platform\\logs\\sqvm_warn.log", SPDLOG_MAX_SIZE, SPDLOG_NUM_FILE)->set_pattern("[%Y-%m-%d %H:%M:%S.%e] %v"); spdlog::rotating_logger_mt("sqvm_print_logger", "platform\\logs\\sqvm_print.log", SPDLOG_MAX_SIZE, SPDLOG_NUM_FILE)->set_pattern("[%Y-%m-%d %H:%M:%S.%e] %v"); spdlog::rotating_logger_mt("dev_message_logger", "platform\\logs\\dev_message.log", SPDLOG_MAX_SIZE, SPDLOG_NUM_FILE)->set_pattern("[%Y-%m-%d %H:%M:%S.%e] %v"); - spdlog::rotating_logger_mt("netchan_pack_logger", "platform\\logs\\net_trace.log", SPDLOG_MAX_SIZE, SPDLOG_NUM_FILE)->set_pattern("[%Y-%m-%d %H:%M:%S.%e] %v"); + spdlog::rotating_logger_mt("warn_message_logger", "platform\\logs\\sdk_warn.log", SPDLOG_MAX_SIZE, SPDLOG_NUM_FILE)->set_pattern("[%Y-%m-%d %H:%M:%S.%e] %v"); + spdlog::rotating_logger_mt("error_message_logger", "platform\\logs\\sdk_error.log", SPDLOG_MAX_SIZE, SPDLOG_NUM_FILE)->set_pattern("[%Y-%m-%d %H:%M:%S.%e] %v"); spdlog::rotating_logger_mt("qhull_debug_logger", "platform\\logs\\qhull_print.log", SPDLOG_MAX_SIZE, SPDLOG_NUM_FILE)->set_pattern("[%Y-%m-%d %H:%M:%S.%e] %v"); + spdlog::rotating_logger_mt("netchan_packet_logger", "platform\\logs\\net_trace.log", SPDLOG_MAX_SIZE, SPDLOG_NUM_FILE)->set_pattern("[%Y-%m-%d %H:%M:%S.%e] %v"); spdlog::rotating_logger_mt("filesystem_warn_logger", "platform\\logs\\fs_warn.log", SPDLOG_MAX_SIZE, SPDLOG_NUM_FILE)->set_pattern("[%Y-%m-%d %H:%M:%S.%e] %v"); } diff --git a/r5dev/engine/sys_utils.cpp b/r5dev/engine/sys_utils.cpp index 85a1ac2d..f879b968 100644 --- a/r5dev/engine/sys_utils.cpp +++ b/r5dev/engine/sys_utils.cpp @@ -95,11 +95,10 @@ void HCon_NPrintf(int pos, const char* fmt, ...) // Purpose: Show logs to all console interfaces // Input : idx - // *fmt - ... - -// Output : void DevMsg //----------------------------------------------------------------------------- void DevMsg(eDLL_T idx, const char* fmt, ...) { - static char szBuf[1024] = {}; + static char szBuf[2048] = {}; static std::string svOut; static std::string svAnsiOut; @@ -170,6 +169,158 @@ void DevMsg(eDLL_T idx, const char* fmt, ...) #endif // !DEDICATED } +//----------------------------------------------------------------------------- +// Purpose: Print engine and SDK errors +// Input : idx - +// *fmt - ... - +//----------------------------------------------------------------------------- +void Warning(eDLL_T idx, const char* fmt, ...) +{ + static char szBuf[2048] = {}; + + static std::string svOut; + static std::string svAnsiOut; + + static std::regex rxAnsiExp("\\\033\\[.*?m"); + + static std::shared_ptr iconsole = spdlog::get("game_console"); + static std::shared_ptr wconsole = spdlog::get("win_console"); + static std::shared_ptr sqlogger = spdlog::get("warn_message_logger"); + + {///////////////////////////// + va_list args{}; + va_start(args, fmt); + + vsnprintf(szBuf, sizeof(szBuf), fmt, args); + + szBuf[sizeof(szBuf) - 1] = 0; + va_end(args); + }///////////////////////////// + + svOut = sDLL_T[static_cast(idx)].c_str(); + svOut.append(szBuf); + svOut = std::regex_replace(svOut, rxAnsiExp, ""); + + char szNewLine = svOut.back(); + if (szNewLine != '\n') + { + svOut.append("\n"); + } + + if (!g_bSpdLog_UseAnsiClr) + { + wconsole->debug(svOut); +#ifdef DEDICATED + g_pRConServer->Send(svOut.c_str()); +#endif // DEDICATED + } + else + { + svAnsiOut = sANSI_DLL_T[static_cast(idx)].c_str(); + svAnsiOut.append(g_svRedF.c_str()); + svAnsiOut.append(szBuf); + + char szNewLine = svAnsiOut.back(); + if (szNewLine != '\n') + { + svAnsiOut.append("\n"); + } + wconsole->debug(svAnsiOut); +#ifdef DEDICATED + g_pRConServer->Send(svAnsiOut.c_str()); +#endif // DEDICATED + } + + sqlogger->debug(svOut); + +#ifndef DEDICATED + iconsole->info(svOut); + std::string s = g_spd_sys_w_oss.str(); + + g_pLogSystem.AddLog(LogType_t::WARNING_C, s); + g_pIConsole->m_ivConLog.push_back(Strdup(s.c_str())); + + g_spd_sys_w_oss.str(""); + g_spd_sys_w_oss.clear(); +#endif // !DEDICATED +} + +//----------------------------------------------------------------------------- +// Purpose: Print engine and SDK errors +// Input : idx - +// *fmt - ... - +//----------------------------------------------------------------------------- +void Error(eDLL_T idx, const char* fmt, ...) +{ + static char szBuf[2048] = {}; + + static std::string svOut; + static std::string svAnsiOut; + + static std::regex rxAnsiExp("\\\033\\[.*?m"); + + static std::shared_ptr iconsole = spdlog::get("game_console"); + static std::shared_ptr wconsole = spdlog::get("win_console"); + static std::shared_ptr sqlogger = spdlog::get("error_message_logger"); + + {///////////////////////////// + va_list args{}; + va_start(args, fmt); + + vsnprintf(szBuf, sizeof(szBuf), fmt, args); + + szBuf[sizeof(szBuf) - 1] = 0; + va_end(args); + }///////////////////////////// + + svOut = sDLL_T[static_cast(idx)].c_str(); + svOut.append(szBuf); + svOut = std::regex_replace(svOut, rxAnsiExp, ""); + + char szNewLine = svOut.back(); + if (szNewLine != '\n') + { + svOut.append("\n"); + } + + if (!g_bSpdLog_UseAnsiClr) + { + wconsole->debug(svOut); +#ifdef DEDICATED + g_pRConServer->Send(svOut.c_str()); +#endif // DEDICATED + } + else + { + svAnsiOut = sANSI_DLL_T[static_cast(idx)].c_str(); + svAnsiOut.append(g_svRedF.c_str()); + svAnsiOut.append(szBuf); + + char szNewLine = svAnsiOut.back(); + if (szNewLine != '\n') + { + svAnsiOut.append("\n"); + } + wconsole->debug(svAnsiOut); +#ifdef DEDICATED + g_pRConServer->Send(svAnsiOut.c_str()); +#endif // DEDICATED + } + + sqlogger->debug(svOut); + +#ifndef DEDICATED + iconsole->info(svOut); + std::string s = g_spd_sys_w_oss.str(); + + g_pLogSystem.AddLog(LogType_t::ERROR_C, s); + g_pIConsole->m_ivConLog.push_back(Strdup(s.c_str())); + + g_spd_sys_w_oss.str(""); + g_spd_sys_w_oss.clear(); +#endif // !DEDICATED +} + //----------------------------------------------------------------------------- // Purpose: Load assets from a custom directory if file exists // Input : *lpFileName - diff --git a/r5dev/engine/sys_utils.h b/r5dev/engine/sys_utils.h index 2dd027b7..67ec2da0 100644 --- a/r5dev/engine/sys_utils.h +++ b/r5dev/engine/sys_utils.h @@ -68,6 +68,8 @@ const static std::string sANSI_DLL_T[8] = /////////////////////////////////////////////////////////////////////////////// void HSys_Error(char* fmt, ...); void DevMsg(eDLL_T idx, const char* fmt, ...); +void Warning(eDLL_T idx, const char* fmt, ...); +void Error(eDLL_T idx, const char* fmt, ...); void SysUtils_Attach(); void SysUtils_Detach(); diff --git a/r5dev/public/utility.cpp b/r5dev/public/utility.cpp index 9cccac81..1dfc4255 100644 --- a/r5dev/public/utility.cpp +++ b/r5dev/public/utility.cpp @@ -172,7 +172,7 @@ void HexDump(const char* szHeader, int nFunc, const void* pData, int nSize) szAscii[16] = '\0'; // Add new loggers here to replace the placeholder. - if (nFunc == 0) { logger = spdlog::get("netchan_pack_logger"); } + if (nFunc == 0) { logger = spdlog::get("netchan_packet_logger"); } // Add timestamp. logger->set_level(spdlog::level::trace); diff --git a/r5dev/squirrel/sqvm.cpp b/r5dev/squirrel/sqvm.cpp index dc339d42..ac348272 100644 --- a/r5dev/squirrel/sqvm.cpp +++ b/r5dev/squirrel/sqvm.cpp @@ -20,6 +20,9 @@ //--------------------------------------------------------------------------------- // Purpose: prints the output of each VM to the console +// Input : *sqvm - +// *fmt - +// ... - //--------------------------------------------------------------------------------- void* HSQVM_PrintFunc(void* sqvm, char* fmt, ...) { @@ -111,6 +114,11 @@ void* HSQVM_PrintFunc(void* sqvm, char* fmt, ...) //--------------------------------------------------------------------------------- // Purpose: prints the warning output of each VM to the console +// Input : *sqvm - +// a2 - +// a3 - +// *nStringSize - +// **ppString - //--------------------------------------------------------------------------------- void* HSQVM_WarningFunc(void* sqvm, int a2, int a3, int* nStringSize, void** ppString) { @@ -178,8 +186,35 @@ void* HSQVM_WarningFunc(void* sqvm, int a2, int a3, int* nStringSize, void** ppS return result; } +//--------------------------------------------------------------------------------- +// Purpose: prints the compile error and context to the console +// Input : *sqvm - +// *pszError - +// *pszFile - +// nLine - +// nColumn - +//--------------------------------------------------------------------------------- +void HSQVM_ErrorFunc(void* sqvm, const char* pszError, const char* pszFile, unsigned int nLine, int nColumn) +{ + static int vmIdx{}; + static char szContextBuf[256]{}; + +#ifdef GAMEDLL_S3 + vmIdx = *reinterpret_cast(reinterpret_cast(sqvm) + 0x18); +#else // TODO [ AMOS ]: nothing equal to 'rdx + 18h' exist in the vm structs for anything below S3. + vmIdx = 3; +#endif + + SQVM_GetErrorLine(pszFile, nLine, szContextBuf, sizeof(szContextBuf)); + + Error(eDLL_T::SERVER, "%s SCRIPT COMPILE ERROR: %s\n", SQVM_TYPE_T[vmIdx].c_str(), pszError); + Error(eDLL_T::SERVER, " -> %s\n\n", szContextBuf); + Error(eDLL_T::SERVER, "%s line [%d] column [%d]\n", pszFile, nLine, nColumn); +} + //--------------------------------------------------------------------------------- // Purpose: prints the global include file the compiler loads for loading scripts +// Input : *szRsonName - //--------------------------------------------------------------------------------- void* HSQVM_LoadRson(const char* szRsonName) { @@ -197,6 +232,9 @@ void* HSQVM_LoadRson(const char* szRsonName) //--------------------------------------------------------------------------------- // Purpose: prints the scripts the compiler loads from global include to be compiled +// Input : *sqvm - +// *szScriptPath - +// nFlag - //--------------------------------------------------------------------------------- bool HSQVM_LoadScript(void* sqvm, const char* szScriptPath, const char* szScriptName, int nFlag) { @@ -211,6 +249,12 @@ bool HSQVM_LoadScript(void* sqvm, const char* szScriptPath, const char* szScript //--------------------------------------------------------------------------------- // Purpose: registers and exposes code functions to target context +// Input : *sqvm - +// *szName - +// *szHelpString - +// *szRetValType - +// *szArgTypes - +// *pFunction - //--------------------------------------------------------------------------------- void HSQVM_RegisterFunction(void* sqvm, const char* szName, const char* szHelpString, const char* szRetValType, const char* szArgTypes, void* pFunction) { @@ -228,6 +272,7 @@ void HSQVM_RegisterFunction(void* sqvm, const char* szName, const char* szHelpSt //--------------------------------------------------------------------------------- // Purpose: registers script functions in SERVER context +// Input : *sqvm - //--------------------------------------------------------------------------------- void RegisterServerScriptFunctions(void* sqvm) { @@ -237,6 +282,7 @@ void RegisterServerScriptFunctions(void* sqvm) #ifndef DEDICATED //--------------------------------------------------------------------------------- // Purpose: registers script functions in CLIENT context +// Input : *sqvm - //--------------------------------------------------------------------------------- void RegisterClientScriptFunctions(void* sqvm) { @@ -245,6 +291,7 @@ void RegisterClientScriptFunctions(void* sqvm) //--------------------------------------------------------------------------------- // Purpose: registers script functions in UI context +// Input : *sqvm - //--------------------------------------------------------------------------------- void RegisterUIScriptFunctions(void* sqvm) { @@ -272,6 +319,7 @@ void RegisterUIScriptFunctions(void* sqvm) //--------------------------------------------------------------------------------- // Purpose: Origin functions are the last to be registered in UI context, we register anything ours below +// Input : *sqvm - // TODO : Hook 'CreateVM' instead //--------------------------------------------------------------------------------- void HSQVM_RegisterOriginFuncs(void* sqvm) @@ -289,6 +337,7 @@ void SQVM_Attach() { DetourAttach((LPVOID*)&SQVM_PrintFunc, &HSQVM_PrintFunc); DetourAttach((LPVOID*)&SQVM_WarningFunc, &HSQVM_WarningFunc); + DetourAttach((LPVOID*)&SQVM_ErrorFunc, &HSQVM_ErrorFunc); DetourAttach((LPVOID*)&SQVM_LoadRson, &HSQVM_LoadRson); DetourAttach((LPVOID*)&SQVM_LoadScript, &HSQVM_LoadScript); #ifndef DEDICATED @@ -300,6 +349,7 @@ void SQVM_Detach() { DetourDetach((LPVOID*)&SQVM_PrintFunc, &HSQVM_PrintFunc); DetourDetach((LPVOID*)&SQVM_WarningFunc, &HSQVM_WarningFunc); + DetourDetach((LPVOID*)&SQVM_ErrorFunc, &HSQVM_ErrorFunc); DetourDetach((LPVOID*)&SQVM_LoadRson, &HSQVM_LoadRson); DetourDetach((LPVOID*)&SQVM_LoadScript, &HSQVM_LoadScript); #ifndef DEDICATED diff --git a/r5dev/squirrel/sqvm.h b/r5dev/squirrel/sqvm.h index 49e8c789..32ff0756 100644 --- a/r5dev/squirrel/sqvm.h +++ b/r5dev/squirrel/sqvm.h @@ -6,6 +6,13 @@ typedef int SQRESULT; #define SQ_FAILED(res) (res<0) #define SQ_SUCCEEDED(res) (res>=0) +const static std::string SQVM_TYPE_T[3] = +{ + "SERVER", + "CLIENT", + "UI", +}; + const static std::string SQVM_LOG_T[4] = { "Script(S):", @@ -74,18 +81,28 @@ namespace ADDRESS p_SQVM_WarningFunc = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x4C\x89\x4C\x24\x20\x44\x89\x44\x24\x18\x89\x54\x24\x10\x53\x55\x56\x57\x41\x54\x41\x55\x41\x56\x41\x57\x48\x83\xEC\x00\x48\x8B", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx?xx"); void* (*SQVM_WarningFunc)(void* sqvm, int a2, int a3, int* nStringSize, void** ppString) = (void* (*)(void*, int, int, int*, void**))p_SQVM_WarningFunc.GetPtr(); /*4C 89 4C 24 20 44 89 44 24 18 89 54 24 10 53 55 56 57 41 54 41 55 41 56 41 57 48 83 EC ?? 48 8B*/ - ADDRESS p_SQVM_WarningCmd = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x40\x53\x48\x83\xEC\x30\x33\xDB\x48\x8D\x44\x24\x00\x4C\x8D\x4C\x24\x00", "xxxxxxxxxxxx?xxxx?"); - void* (*SQVM_WarningCmd)(int a1, int a2) = (void* (*)(int, int))p_SQVM_WarningCmd.GetPtr(); /*40 53 48 83 EC 30 33 DB 48 8D 44 24 ?? 4C 8D 4C 24 ??*/ + ADDRESS p_SQVM_ErrorFunc = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x89\x5C\x24\x00\x48\x89\x6C\x24\x00\x48\x89\x74\x24\x00\x48\x89\x7C\x24\x00\x41\x56\x48\x81\xEC\x00\x00\x00\x00\x48\x8B\xD9\x4C\x8B\xF2", "xxxx?xxxx?xxxx?xxxx?xxxxx????xxxxxx"); + void* (*SQVM_ErrorFunc)(void* sqvm, const char* pszError, const char* pszFile, unsigned int nLine, int nColumn) = (void* (*)(void*, const char*, const char*, unsigned int, int))p_SQVM_ErrorFunc.GetPtr(); /*48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 41 56 48 81 EC ? ? ? ? 48 8B D9 4C 8B F2*/ + #if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) + ADDRESS p_SQVM_GetErrorLine = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x89\x5C\x24\x00\x48\x89\x74\x24\x00\x48\x89\x7C\x24\x00\x55\x41\x54\x41\x55\x41\x56\x41\x57\x48\x8D\xAC\x24\x00\x00\x00\x00\x48\x81\xEC\x00\x00\x00\x00\x83\x65\x90\xFC", "xxxx?xxxx?xxxx?xxxxxxxxxxxxx????xxx????xxxx"); + void* (*SQVM_GetErrorLine)(const char* pszFile, int nLine, char* pszContextBuf, int nBufLen) = (void* (*)(const char*, int, char*, int))p_SQVM_GetErrorLine.GetPtr(); /*48 89 5C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 55 41 54 41 55 41 56 41 57 48 8D AC 24 ? ? ? ? 48 81 EC ? ? ? ? 83 65 90 FC*/ + ADDRESS p_SQVM_LoadScript = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x89\x5C\x24\x10\x48\x89\x74\x24\x18\x48\x89\x7C\x24\x20\x48\x89\x4C\x24\x08\x55\x41\x54\x41\x55\x41\x56\x41\x57\x48\x8D\x6C", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); bool (*SQVM_LoadScript)(void* sqvm, const char* szScriptPath, const char* szScriptName, int nFlag) = (bool (*)(void*, const char*, const char*, int))p_SQVM_LoadScript.GetPtr(); /*48 89 5C 24 10 48 89 74 24 18 48 89 7C 24 20 48 89 4C 24 08 55 41 54 41 55 41 56 41 57 48 8D 6C*/ #elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3) + ADDRESS p_SQVM_GetErrorLine = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x8B\xC4\x55\x56\x48\x8D\xA8\x00\x00\x00\x00\x48\x81\xEC\x00\x00\x00\x00\x83\x65\x90\xFC", "xxxxxxxx????xxx????xxxx"); + void* (*SQVM_GetErrorLine)(const char* pszFile, int nLine, char* pszContextBuf, int nBufLen) = (void* (*)(const char*, int, char*, int))p_SQVM_GetErrorLine.GetPtr(); /*48 8B C4 55 56 48 8D A8 ? ? ? ? 48 81 EC ? ? ? ? 83 65 90 FC*/ + ADDRESS p_SQVM_LoadScript = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x8B\xC4\x48\x89\x48\x08\x55\x41\x56\x48\x8D\x68", "xxxxxxxxxxxxx"); /*48 8B C4 48 89 48 08 55 41 56 48 8D 68*/ bool (*SQVM_LoadScript)(void* sqvm, const char* szScriptPath, const char* szScriptName, int nFlag) = (bool (*)(void*, const char*, const char*, int))p_SQVM_LoadScript.GetPtr(); #endif ADDRESS p_SQVM_LoadRson = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x4C\x8B\xDC\x49\x89\x5B\x08\x57\x48\x81\xEC\xA0\x00\x00\x00\x33", "xxxxxxxxxxxxxxxx"); void* (*SQVM_LoadRson)(const char* szRsonName) = (void* (*)(const char*))p_SQVM_LoadRson.GetPtr(); /*4C 8B DC 49 89 5B 08 57 48 81 EC A0 00 00 00 33*/ + ADDRESS p_SQVM_WarningCmd = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x40\x53\x48\x83\xEC\x30\x33\xDB\x48\x8D\x44\x24\x00\x4C\x8D\x4C\x24\x00", "xxxxxxxxxxxx?xxxx?"); + void* (*SQVM_WarningCmd)(int a1, int a2) = (void* (*)(int, int))p_SQVM_WarningCmd.GetPtr(); /*40 53 48 83 EC 30 33 DB 48 8D 44 24 ?? 4C 8D 4C 24 ??*/ + ADDRESS p_SQVM_RegisterFunc = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x83\xEC\x38\x45\x0F\xB6\xC8", "xxxxxxxx"); /*48 83 EC 38 45 0F B6 C8*/ void* (*SQVM_RegisterFunc)(void* sqvm, SQFuncRegistration* sqFunc, int a1) = (void* (*)(void*, SQFuncRegistration*, int))p_SQVM_RegisterFunc.GetPtr(); @@ -118,9 +135,11 @@ class HSQVM : public IDetour { std::cout << "| FUN: SQVM_PrintFunc : 0x" << std::hex << std::uppercase << p_SQVM_PrintFunc.GetPtr() << std::setw(npad) << " |" << std::endl; std::cout << "| FUN: SQVM_WarningFunc : 0x" << std::hex << std::uppercase << p_SQVM_WarningFunc.GetPtr() << std::setw(npad) << " |" << std::endl; - std::cout << "| FUN: SQVM_WarningCmd : 0x" << std::hex << std::uppercase << p_SQVM_WarningCmd.GetPtr() << std::setw(npad) << " |" << std::endl; + std::cout << "| FUN: SQVM_ErrorFunc : 0x" << std::hex << std::uppercase << p_SQVM_ErrorFunc.GetPtr() << std::setw(npad) << " |" << std::endl; + std::cout << "| FUN: SQVM_GetErrorLine : 0x" << std::hex << std::uppercase << p_SQVM_GetErrorLine.GetPtr() << std::setw(npad) << " |" << std::endl; std::cout << "| FUN: SQVM_LoadScript : 0x" << std::hex << std::uppercase << p_SQVM_LoadScript.GetPtr() << std::setw(npad) << " |" << std::endl; std::cout << "| FUN: SQVM_LoadRson : 0x" << std::hex << std::uppercase << p_SQVM_LoadRson.GetPtr() << std::setw(npad) << " |" << std::endl; + std::cout << "| FUN: SQVM_WarningCmd : 0x" << std::hex << std::uppercase << p_SQVM_WarningCmd.GetPtr() << std::setw(npad) << " |" << std::endl; std::cout << "| FUN: SQVM_RegisterFunc : 0x" << std::hex << std::uppercase << p_SQVM_RegisterFunc.GetPtr() << std::setw(npad) << " |" << std::endl; std::cout << "| FUN: SQVM_CreateUIVM : 0x" << std::hex << std::uppercase << p_SQVM_CreateUIVM.GetPtr() << std::setw(npad) << " |" << std::endl; std::cout << "| FUN: SQVM_CompileError : 0x" << std::hex << std::uppercase << p_SQVM_CompileError.GetPtr() << std::setw(npad) << " |" << std::endl;