From 81a44afbb4f42297d5a6eac2ea836aa36f93278b Mon Sep 17 00:00:00 2001 From: Myles Busig Date: Wed, 27 Mar 2024 00:32:54 -0600 Subject: [PATCH] Add log --- include/mtl/log.hpp | 62 +++++++++++++++++++++++++++++++++++++++++++++ src/gba/log.cpp | 62 +++++++++++++++++++++++++++++++++++++++++++++ src/log.cpp | 29 +++++++++++++++++++++ 3 files changed, 153 insertions(+) create mode 100644 include/mtl/log.hpp create mode 100644 src/gba/log.cpp create mode 100644 src/log.cpp diff --git a/include/mtl/log.hpp b/include/mtl/log.hpp new file mode 100644 index 0000000..e5f74ad --- /dev/null +++ b/include/mtl/log.hpp @@ -0,0 +1,62 @@ +#pragma once + +#include + +#include "mtl/string_stream.hpp" + +namespace mtl { + +namespace log { + +/** + * \brief Log stream + * + * String stream that overrides sync() to flush the stream to the correct + * output depending on the platform. Each flush is treated as a separate message. + * The capacity of the stream depends on the platform. + * + * See mtl::string_stream for information on when the stream is flushed. + */ +class stream : public string_stream { +private: + uint32_t m_log_level; + +public: + stream(istring& str, uint32_t log_level); + ~stream(); + + using string_stream::operator=; + using string_stream::operator<<; + + void flush() override; +}; + +/** + * \brief Stub log stream + * + * Implements all of the log stream functions as a NOP. Replaces all of + * the log streams when logging is disabled. + * + * TODO: Enable logging disabling. + */ +class stream_stub { +public: + stream_stub(istring&, uint32_t) { } + + void flush() { } + void clear() { } + + template + stream_stub& operator<<(T) { + return *this; + } +}; + +extern stream debug; +extern stream info; +extern stream warn; +extern stream error; + +} // namespace log + +} // namespace mtl diff --git a/src/gba/log.cpp b/src/gba/log.cpp new file mode 100644 index 0000000..8f7fa14 --- /dev/null +++ b/src/gba/log.cpp @@ -0,0 +1,62 @@ +#include "mtl/log.hpp" + +#include "mtl/string.hpp" +#include "mtl/string_view.hpp" +#include "mtl/string_stream.hpp" + +namespace mtl { + +namespace log { +/** + * \brief MGBA debug registers and constants + */ +namespace reg { +/** + * \brief MGBA debug enable register. + * + * When 0xC0DE is written to the register, debug output is enabled. + * When 0 is written to the register, debug output is disabled. + * Will be set to 0x1DEA when successfully enabled. + */ +static volatile uint16_t& enable = *reinterpret_cast(0x4FFF780); +/** + * \brief MGBA debug flags register. + * + * When 0x100 | LOG_LEVEL, the message buffer is flushed. MGBA levels are: + * + * Fatal: 0 (stops the emulator, unused) + * Error: 1 + * Warn: 2 + * Info: 3 + * Debug: 4 + */ +static volatile uint16_t& flags = *reinterpret_cast(0x4FFF700); +/** + * \brief MGBA debug string register. + * + * Max length of 0x100 (256) including null terminator. + */ +static string_ext string(reinterpret_cast(0x4FFF600), 256); +}; // namespace reg + +stream::stream(istring& buf, uint32_t log_level) + : string_stream(buf), m_log_level(log_level) { + reg::enable = 0xC0DE; +} +stream::~stream() { + reg::enable = 0; +} + +void stream::flush() { + reg::flags = 0x100 | m_log_level; + clear(); +} + +stream debug(reg::string, 4); +stream info(reg::string, 3); +stream warn(reg::string, 2); +stream error(reg::string, 1); + +} // namespace log + +} // namespace mtl diff --git a/src/log.cpp b/src/log.cpp new file mode 100644 index 0000000..9103e26 --- /dev/null +++ b/src/log.cpp @@ -0,0 +1,29 @@ +#include "mtl/log.hpp" + +#include +#include + +namespace mtl { + +namespace log { + +static string<512> buffer; + +stream::stream(istring& buf, uint32_t log_level) + : string_stream(buf), m_log_level(log_level) { } +stream::~stream() { } + +void stream::flush() { + fwrite(buffer.c_str(), 1, buffer.length(), stdin); + clear(); +} + +stream debug(buffer, 4); +stream info(buffer, 3); +stream warn(buffer, 2); +stream error(buffer, 1); + +} // namespace log + +} // namespace mtl +