GBAlatro
A Demake of Balatro for the GBA
Loading...
Searching...
No Matches
mgba_logger.c
1#include "mgba_logger.h"
2
3#include "util.h"
4
5#ifdef MGBA_LOGGING
6
7#include <stdarg.h>
8#include <stdint.h>
9#include <stdio.h>
10#include <string.h>
11#include <tonc.h>
12
13#define MGBA_REG_DEBUG_ENABLE ((vu16*)0x4FFF780)
14#define MGBA_REG_DEBUG_FLAGS ((vu16*)0x4FFF700)
15#define MGBA_REG_DEBUG_STRING ((char*)0x4FFF600)
16
17static const u32 MGBA_ENABLE_MAGIC = 0xC0DE;
18static const u32 MGBA_ENABLE_OK = 0x1DEA;
19static const u32 MGBA_LOG_SEND = 0x100;
20static const u32 MGBA_LOG_BUFFER_SIZE = 0x100;
21static const u16 MGBA_LOG_LEVEL_MASK = 0x7;
22
23static bool s_mgba_logger_available = false;
24
25bool mgba_logger_init(void)
26{
27 *MGBA_REG_DEBUG_ENABLE = MGBA_ENABLE_MAGIC;
28 s_mgba_logger_available = (*MGBA_REG_DEBUG_ENABLE == MGBA_ENABLE_OK);
29 return s_mgba_logger_available;
30}
31
32static void mgba_vprintf(MgbaLogLevel level, const char* fmt, va_list args)
33{
34 if (!s_mgba_logger_available)
35 {
36 // If the logger is not available, we can't log any error at all
37 return;
38 }
39
40 /* This ends up being sort of a recursive call, but it has to stop after one level
41 * because the macro is certain to not pass a NULL message.
42 */
44
45 vsnprintf(MGBA_REG_DEBUG_STRING, MGBA_LOG_BUFFER_SIZE, fmt, args);
46
47 *MGBA_REG_DEBUG_FLAGS = ((uint16_t)level & MGBA_LOG_LEVEL_MASK) | MGBA_LOG_SEND;
48}
49
50void mgba_printf(MgbaLogLevel level, const char* fmt, ...)
51{
52 va_list args;
53 va_start(args, fmt);
54 mgba_vprintf(level, fmt, args);
55 va_end(args);
56}
57
58void mgba_func_printf(MgbaLogLevel level, const char* func_name, const char* fmt, ...)
59{
60 if (!s_mgba_logger_available)
61 {
62 // If the logger is not available, we can't log any error at all
63 return;
64 }
65
66 /* This ends up being a recursive call, but it has to stop after one level
67 * because this does not pass a NULL message.
68 * Not checking func_name, relying both on the macro to pass __func__ and
69 * on the printf function to handle it gracefully even in the off case.
70 */
72 fmt,
74 "%s() passed NULL message at log level %d",
75 func_name,
76 level
77 );
78
79 char printed_str_buff[MGBA_LOG_BUFFER_SIZE];
80
81 // Expand the format first so the full string is truncated in case it's too long
82 va_list args;
83 va_start(args, fmt);
84 vsnprintf(printed_str_buff, sizeof(printed_str_buff), fmt, args);
85 va_end(args);
86 mgba_printf(level, "%s(): %s", func_name, printed_str_buff);
87}
88
89#else
90
91// Noop stubs
93{
94 return false;
95}
96
97void mgba_printf(MgbaLogLevel level, const char* fmt, ...)
98{
99}
100
101void mgba_func_printf(MgbaLogLevel level, const char* func_name, const char* fmt, ...)
102{
103}
104#endif
Interface to interact with the mgba logger.
bool mgba_logger_init(void)
Initialize mgba logger.
Definition mgba_logger.c:92
void mgba_func_printf(MgbaLogLevel level, const char *func_name, const char *fmt,...)
Print to mgba log with a format string and function name.
void mgba_printf(MgbaLogLevel level, const char *fmt,...)
Print to mgba log with a format string.
Definition mgba_logger.c:97
Utilities relating around number string representation and protected arithmatic helper functions.
#define GBAL_CUST_MSG_RETURN_IF_NULL(param, ret_val, message,...)
Returns ret_val and prints error message if param is equal to NULL. Useful for checking arguments or ...
Definition util.h:121
#define GBAL_RETURN_IF_NULL(param, ret_val)
Returns ret_val and prints a default error message if param is equal to NULL. Useful for checking arg...
Definition util.h:138
#define RET_NONE
An empty return value for RETURN_IF macros when used in void functions Expands to nothing because mac...
Definition util.h:146