From 8997055fc0511681885f1bd273239a9936e08300 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 9 Jul 2022 02:17:03 -0700 Subject: [PATCH] Core: Migrate SDL logging enhancements into core --- include/mgba/core/log.h | 10 ++++ include/mgba/core/thread.h | 1 + src/core/log.c | 61 ++++++++++++++++++++++ src/core/thread.c | 40 ++++++++------- src/platform/qt/CoreController.cpp | 14 ++--- src/platform/qt/CoreController.h | 3 ++ src/platform/sdl/main.c | 82 +++--------------------------- 7 files changed, 111 insertions(+), 100 deletions(-) diff --git a/include/mgba/core/log.h b/include/mgba/core/log.h index d6217aca1..9f55ec772 100644 --- a/include/mgba/core/log.h +++ b/include/mgba/core/log.h @@ -36,6 +36,12 @@ struct mLogger { struct mLogFilter* filter; }; +struct mStandardLogger { + struct mLogger d; + bool logToStdout; + struct VFile* logFile; +}; + struct mLogger* mLogGetContext(void); void mLogSetDefaultLogger(struct mLogger*); int mLogGenerateCategory(const char*, const char*); @@ -44,6 +50,10 @@ const char* mLogCategoryId(int); int mLogCategoryById(const char*); struct mCoreConfig; +void mStandardLoggerInit(struct mStandardLogger*); +void mStandardLoggerDeinit(struct mStandardLogger*); +void mStandardLoggerConfig(struct mStandardLogger*, struct mCoreConfig* config); + void mLogFilterInit(struct mLogFilter*); void mLogFilterDeinit(struct mLogFilter*); void mLogFilterLoad(struct mLogFilter*, const struct mCoreConfig*); diff --git a/include/mgba/core/thread.h b/include/mgba/core/thread.h index aa059f652..55d6a99e8 100644 --- a/include/mgba/core/thread.h +++ b/include/mgba/core/thread.h @@ -21,6 +21,7 @@ struct mCoreThread; struct mThreadLogger { struct mLogger d; struct mCoreThread* p; + struct mLogger* logger; }; #ifdef ENABLE_SCRIPTING diff --git a/src/core/log.c b/src/core/log.c index 4612c02b9..2d90fe05e 100644 --- a/src/core/log.c +++ b/src/core/log.c @@ -7,8 +7,10 @@ #include #include +#include #define MAX_CATEGORY 64 +#define MAX_LOG_BUF 1024 static struct mLogger* _defaultLogger = NULL; @@ -183,4 +185,63 @@ int mLogFilterLevels(const struct mLogFilter* filter , int category) { return value; } +void _mCoreStandardLog(struct mLogger* logger, int category, enum mLogLevel level, const char* format, va_list args) { + struct mStandardLogger* stdlog = (struct mStandardLogger*) logger; + + if (!mLogFilterTest(logger->filter, category, level)) { + return; + } + + char buffer[MAX_LOG_BUF]; + + // Prepare the string + size_t length = snprintf(buffer, sizeof(buffer), "%s: ", mLogCategoryName(category)); + if (length < sizeof(buffer)) { + length += vsnprintf(buffer + length, sizeof(buffer) - length, format, args); + } + if (length < sizeof(buffer)) { + length += snprintf(buffer + length, sizeof(buffer) - length, "\n"); + } + + // Make sure the length doesn't exceed the size of the buffer when actually writing + if (length > sizeof(buffer)) { + length = sizeof(buffer); + } + + if (stdlog->logToStdout) { + printf("%s", buffer); + } + + if (stdlog->logFile) { + stdlog->logFile->write(stdlog->logFile, buffer, length); + } +} + +void mStandardLoggerInit(struct mStandardLogger* logger) { + logger->d.log = _mCoreStandardLog; + logger->d.filter = malloc(sizeof(struct mLogFilter)); + mLogFilterInit(logger->d.filter); +} + +void mStandardLoggerDeinit(struct mStandardLogger* logger) { + if (logger->d.filter) { + mLogFilterDeinit(logger->d.filter); + free(logger->d.filter); + logger->d.filter = NULL; + } +} + +void mStandardLoggerConfig(struct mStandardLogger* logger, struct mCoreConfig* config) { + bool logToFile = false; + const char* logFile = mCoreConfigGetValue(config, "logFile"); + mCoreConfigGetBoolValue(config, "logToStdout", &logger->logToStdout); + mCoreConfigGetBoolValue(config, "logToFile", &logToFile); + + if (logToFile && logFile) { + logger->logFile = VFileOpen(logFile, O_WRONLY | O_CREAT | O_APPEND); + } + + mLogFilterLoad(logger->d.filter, config); +} + mLOG_DEFINE_CATEGORY(STATUS, "Status", "core.status") diff --git a/src/core/thread.c b/src/core/thread.c index 530ee6f6f..ad65ae51d 100644 --- a/src/core/thread.c +++ b/src/core/thread.c @@ -253,10 +253,13 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) { core->setSync(core, &threadContext->impl->sync); struct mLogFilter filter; - if (!threadContext->logger.d.filter) { - threadContext->logger.d.filter = &filter; - mLogFilterInit(threadContext->logger.d.filter); - mLogFilterLoad(threadContext->logger.d.filter, &core->config); + struct mLogger* logger = &threadContext->logger.d; + if (threadContext->logger.logger) { + logger->filter = threadContext->logger.logger->filter; + } else { + logger->filter = &filter; + mLogFilterInit(logger->filter); + mLogFilterLoad(logger->filter, &core->config); } #ifdef ENABLE_SCRIPTING @@ -431,10 +434,10 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) { #endif core->clearCoreCallbacks(core); - if (threadContext->logger.d.filter == &filter) { + if (logger->filter == &filter) { mLogFilterDeinit(&filter); } - threadContext->logger.d.filter = NULL; + logger->filter = NULL; return 0; } @@ -444,10 +447,8 @@ bool mCoreThreadStart(struct mCoreThread* threadContext) { threadContext->impl->state = mTHREAD_INITIALIZED; threadContext->impl->requested = 0; threadContext->logger.p = threadContext; - if (!threadContext->logger.d.log) { - threadContext->logger.d.log = _mCoreLog; - threadContext->logger.d.filter = NULL; - } + threadContext->logger.d.log = _mCoreLog; + threadContext->logger.d.filter = NULL; if (!threadContext->impl->sync.fpsTarget) { threadContext->impl->sync.fpsTarget = _defaultFPSTarget; @@ -718,14 +719,17 @@ struct mCoreThread* mCoreThreadGet(void) { } static void _mCoreLog(struct mLogger* logger, int category, enum mLogLevel level, const char* format, va_list args) { - UNUSED(logger); - UNUSED(level); - printf("%s: ", mLogCategoryName(category)); - vprintf(format, args); - printf("\n"); - struct mCoreThread* thread = mCoreThreadGet(); - if (thread && level == mLOG_FATAL) { - mCoreThreadMarkCrashed(thread); + struct mThreadLogger* threadLogger = (struct mThreadLogger*) logger; + if (level == mLOG_FATAL) { + mCoreThreadMarkCrashed(threadLogger->p); + } + if (!threadLogger->p->logger.logger) { + printf("%s: ", mLogCategoryName(category)); + vprintf(format, args); + printf("\n"); + } else { + logger = threadLogger->p->logger.logger; + logger->log(logger, category, level, format, args); } } #else diff --git a/src/platform/qt/CoreController.cpp b/src/platform/qt/CoreController.cpp index 5e3ecad84..421433191 100644 --- a/src/platform/qt/CoreController.cpp +++ b/src/platform/qt/CoreController.cpp @@ -144,19 +144,19 @@ CoreController::CoreController(mCore* core, QObject* parent) QMetaObject::invokeMethod(controller, "unpaused"); }; - m_threadContext.logger.d.log = [](mLogger* logger, int category, enum mLogLevel level, const char* format, va_list args) { - mThreadLogger* logContext = reinterpret_cast(logger); - mCoreThread* context = logContext->p; + m_logger.self = this; + m_logger.log = [](mLogger* logger, int category, enum mLogLevel level, const char* format, va_list args) { + CoreLogger* logContext = static_cast(logger); static const char* savestateMessage = "State %i saved"; static const char* loadstateMessage = "State %i loaded"; static const char* savestateFailedMessage = "State %i failed to load"; static int biosCat = -1; static int statusCat = -1; - if (!context) { + if (!logContext) { return; } - CoreController* controller = static_cast(context->userData); + CoreController* controller = logContext->self; QString message; if (biosCat < 0) { biosCat = mLogCategoryById("gba.bios"); @@ -201,10 +201,10 @@ CoreController::CoreController(mCore* core, QObject* parent) message = QString::vasprintf(format, args); QMetaObject::invokeMethod(controller, "logPosted", Q_ARG(int, level), Q_ARG(int, category), Q_ARG(const QString&, message)); if (level == mLOG_FATAL) { - mCoreThreadMarkCrashed(controller->thread()); QMetaObject::invokeMethod(controller, "crashed", Q_ARG(const QString&, message)); } }; + m_threadContext.logger.logger = &m_logger; } CoreController::~CoreController() { @@ -424,7 +424,7 @@ void CoreController::setInputController(InputController* inputController) { void CoreController::setLogger(LogController* logger) { disconnect(m_log); m_log = logger; - m_threadContext.logger.d.filter = logger->filter(); + m_logger.filter = logger->filter(); connect(this, &CoreController::logPosted, m_log, &LogController::postLog); } diff --git a/src/platform/qt/CoreController.h b/src/platform/qt/CoreController.h index 557e8e890..e2cd03c12 100644 --- a/src/platform/qt/CoreController.h +++ b/src/platform/qt/CoreController.h @@ -241,6 +241,9 @@ private: void updateROMInfo(); mCoreThread m_threadContext{}; + struct CoreLogger : public mLogger { + CoreController* self; + } m_logger{}; bool m_patched = false; bool m_preload = false; diff --git a/src/platform/sdl/main.c b/src/platform/sdl/main.c index b53f9b5ed..ad7ed4250 100644 --- a/src/platform/sdl/main.c +++ b/src/platform/sdl/main.c @@ -38,19 +38,12 @@ #include #define PORT "sdl" -#define MAX_LOG_BUF 1024 static void mSDLDeinit(struct mSDLRenderer* renderer); static int mSDLRun(struct mSDLRenderer* renderer, struct mArguments* args); -static void _setLogger(struct mCore* core); -static void _mCoreLog(struct mLogger* logger, int category, enum mLogLevel level, const char* format, va_list args); - -static bool _logToStdout = true; -static struct VFile* _logFile = NULL; -static struct mLogFilter _filter; -static struct mLogger _logger; +static struct mStandardLogger _logger; static struct VFile* _state = NULL; @@ -136,6 +129,7 @@ int main(int argc, char** argv) { mCoreInitConfig(renderer.core, PORT); mArgumentsApply(&args, &subparser, 1, &renderer.core->config); + mCoreConfigSetDefaultIntValue(&renderer.core->config, "logToStdout", true); mCoreConfigLoadDefaults(&renderer.core->config, &opts); mCoreLoadConfig(renderer.core); @@ -188,7 +182,8 @@ int main(int argc, char** argv) { int ret; // TODO: Use opts and config - _setLogger(renderer.core); + mStandardLoggerInit(&_logger); + mStandardLoggerConfig(&_logger, &renderer.core->config); ret = mSDLRun(&renderer, &args); mSDLDetachPlayer(&renderer.events, &renderer.player); mInputMapDeinit(&renderer.core->inputMap); @@ -198,6 +193,7 @@ int main(int argc, char** argv) { } mSDLDeinit(&renderer); + mStandardLoggerDeinit(&_logger); mArgumentsDeinit(&args); mCoreConfigFreeOpts(&opts); @@ -273,12 +269,8 @@ int mSDLRun(struct mSDLRenderer* renderer, struct mArguments* args) { renderer->audio.samples = renderer->core->opts.audioBuffers; renderer->audio.sampleRate = 44100; - - struct mThreadLogger threadLogger; - threadLogger.d = _logger; - threadLogger.p = &thread; - thread.logger = threadLogger; - + thread.logger.logger = &_logger.d; + bool didFail = !mCoreThreadStart(&thread); if (!didFail) { @@ -342,63 +334,3 @@ static void mSDLDeinit(struct mSDLRenderer* renderer) { SDL_Quit(); } - -static void _setLogger(struct mCore* core) { - int fakeBool = 0; - bool logToFile = false; - - if (mCoreConfigGetIntValue(&core->config, "logToStdout", &fakeBool)) { - _logToStdout = fakeBool; - } - if (mCoreConfigGetIntValue(&core->config, "logToFile", &fakeBool)) { - logToFile = fakeBool; - } - const char* logFile = mCoreConfigGetValue(&core->config, "logFile"); - - if (logToFile && logFile) { - _logFile = VFileOpen(logFile, O_WRONLY | O_CREAT | O_APPEND); - } - - // Create the filter - mLogFilterInit(&_filter); - mLogFilterLoad(&_filter, &core->config); - - // Fill the logger - _logger.log = _mCoreLog; - _logger.filter = &_filter; -} - -static void _mCoreLog(struct mLogger* logger, int category, enum mLogLevel level, const char* format, va_list args) { - struct mCoreThread* thread = mCoreThreadGet(); - if (thread && level == mLOG_FATAL) { - mCoreThreadMarkCrashed(thread); - } - - if (!mLogFilterTest(logger->filter, category, level)) { - return; - } - - char buffer[MAX_LOG_BUF]; - - // Prepare the string - size_t length = snprintf(buffer, sizeof(buffer), "%s: ", mLogCategoryName(category)); - if (length < sizeof(buffer)) { - length += vsnprintf(buffer + length, sizeof(buffer) - length, format, args); - } - if (length < sizeof(buffer)) { - length += snprintf(buffer + length, sizeof(buffer) - length, "\n"); - } - - // Make sure the length doesn't exceed the size of the buffer when actually writing - if (length > sizeof(buffer)) { - length = sizeof(buffer); - } - - if (_logToStdout) { - printf("%s", buffer); - } - - if (_logFile) { - _logFile->write(_logFile, buffer, length); - } -}