Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/Common/Log.h
3185 views
1
// Copyright (C) 2003 Dolphin Project.
2
3
// This program is free software: you can redistribute it and/or modify
4
// it under the terms of the GNU General Public License as published by
5
// the Free Software Foundation, version 2.0 or later versions.
6
7
// This program is distributed in the hope that it will be useful,
8
// but WITHOUT ANY WARRANTY; without even the implied warranty of
9
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
// GNU General Public License 2.0 for more details.
11
12
// A copy of the GPL 2.0 should have been included with the program.
13
// If not, see http://www.gnu.org/licenses/
14
15
// Official SVN repository and contact information can be found at
16
// http://code.google.com/p/dolphin-emu/
17
18
#pragma once
19
20
#include <cstddef>
21
22
#include "ppsspp_config.h"
23
#include "CommonFuncs.h"
24
25
#define NOTICE_LEVEL 1 // VERY important information that is NOT errors. Like startup and debugprintfs from the game itself.
26
#define ERROR_LEVEL 2 // Important errors.
27
#define WARNING_LEVEL 3 // Something is suspicious.
28
#define INFO_LEVEL 4 // General information.
29
#define DEBUG_LEVEL 5 // Detailed debugging - might make things slow.
30
#define VERBOSE_LEVEL 6 // Noisy debugging - sometimes needed but usually unimportant.
31
32
// NOTE: Needs to be kept in sync with the g_logTypeNames array.
33
enum class Log {
34
System = 0, // Catch-all for uncategorized things
35
Boot,
36
Common,
37
CPU,
38
FileSystem,
39
G3D,
40
HLE,
41
JIT,
42
Loader,
43
Mpeg,
44
Atrac,
45
ME,
46
MemMap,
47
SasMix,
48
SaveState,
49
FrameBuf,
50
Audio,
51
IO,
52
Achievements,
53
HTTP,
54
Printf,
55
TexReplacement,
56
GeDebugger,
57
UI,
58
IAP,
59
60
sceAudio,
61
sceCtrl,
62
sceDisplay,
63
sceFont,
64
sceGe,
65
sceIntc,
66
sceIo,
67
sceKernel,
68
sceModule,
69
sceNet,
70
sceRtc,
71
sceSas,
72
sceUtility,
73
sceMisc,
74
sceReg,
75
76
NUMBER_OF_LOGS, // Must be last
77
};
78
79
enum class LogLevel : int {
80
LNOTICE = NOTICE_LEVEL,
81
LERROR = ERROR_LEVEL,
82
LWARNING = WARNING_LEVEL,
83
LINFO = INFO_LEVEL,
84
LDEBUG = DEBUG_LEVEL,
85
LVERBOSE = VERBOSE_LEVEL,
86
};
87
88
struct LogChannel {
89
#if defined(_DEBUG)
90
LogLevel level = LogLevel::LDEBUG;
91
#else
92
LogLevel level = LogLevel::LDEBUG;
93
#endif
94
bool enabled = true;
95
96
bool IsEnabled(LogLevel level) const {
97
if (level > this->level || !this->enabled)
98
return false;
99
return true;
100
}
101
};
102
103
extern bool *g_bLogEnabledSetting;
104
extern LogChannel g_log[(size_t)Log::NUMBER_OF_LOGS];
105
106
inline bool GenericLogEnabled(Log type, LogLevel level) {
107
return g_log[(int)type].IsEnabled(level) && (*g_bLogEnabledSetting);
108
}
109
110
void GenericLog(Log type, LogLevel level, const char *file, int line, const char *fmt, ...)
111
#ifdef __GNUC__
112
__attribute__((format(printf, 5, 6)))
113
#endif
114
;
115
116
// If you want to see verbose logs, change this to VERBOSE_LEVEL.
117
118
#define MAX_LOGLEVEL DEBUG_LEVEL
119
120
// Let the compiler optimize this out.
121
// TODO: Compute a dynamic max level as well that can be checked here.
122
#define GENERIC_LOG(t, v, ...) \
123
if ((int)v <= MAX_LOGLEVEL && GenericLogEnabled(t, v)) { \
124
GenericLog(t, v, __FILE__, __LINE__, __VA_ARGS__); \
125
}
126
127
#define ERROR_LOG(t,...) do { GENERIC_LOG(t, LogLevel::LERROR, __VA_ARGS__) } while (false)
128
#define WARN_LOG(t,...) do { GENERIC_LOG(t, LogLevel::LWARNING, __VA_ARGS__) } while (false)
129
#define NOTICE_LOG(t,...) do { GENERIC_LOG(t, LogLevel::LNOTICE, __VA_ARGS__) } while (false)
130
#define INFO_LOG(t,...) do { GENERIC_LOG(t, LogLevel::LINFO, __VA_ARGS__) } while (false)
131
#define DEBUG_LOG(t,...) do { GENERIC_LOG(t, LogLevel::LDEBUG, __VA_ARGS__) } while (false)
132
#define VERBOSE_LOG(t,...) do { GENERIC_LOG(t, LogLevel::LVERBOSE, __VA_ARGS__) } while (false)
133
134
// Currently only actually shows a dialog box on Windows.
135
bool HandleAssert(const char *function, const char *file, int line, const char *expression, const char* format, ...)
136
#ifdef __GNUC__
137
__attribute__((format(printf, 5, 6)))
138
#endif
139
;
140
141
// These allow us to get a small amount of information into assert messages.
142
// They can have a value between 0 and 15.
143
enum class DebugCounter {
144
APP_BOOT = 0,
145
GAME_BOOT = 1,
146
GAME_SHUTDOWN = 2,
147
CPUCORE_SWITCHES = 3,
148
};
149
150
bool HitAnyAsserts();
151
void ResetHitAnyAsserts();
152
void SetExtraAssertInfo(const char *info);
153
void SetDebugValue(DebugCounter counter, int value);
154
void IncrementDebugCounter(DebugCounter counter);
155
typedef void (*AssertNoCallbackFunc)(const char *message, void *userdata);
156
void SetAssertCancelCallback(AssertNoCallbackFunc callback, void *userdata);
157
void SetCleanExitOnAssert();
158
void BreakIntoPSPDebugger(const char *reason = "(userbreak)");
159
void SetAssertDialogParent(void *handle); // HWND on windows. Ignored on other platforms.
160
161
#if defined(__ANDROID__)
162
// Tricky macro to get the basename, that also works if *built* on Win32.
163
// Doesn't mean this macro can be used on Win32 though.
164
#define __FILENAME__ (__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 : (__builtin_strrchr(__FILE__, '\\') ? __builtin_strrchr(__FILE__, '\\') + 1 : __FILE__))
165
#else
166
#define __FILENAME__ __FILE__
167
#endif
168
169
// If we're a debug build, _dbg_assert_ is active. Not otherwise, even on Windows.
170
#if defined(_DEBUG)
171
172
#define _dbg_assert_(_a_) \
173
if (!(_a_)) {\
174
if (!HandleAssert(__FUNCTION__, __FILENAME__, __LINE__, #_a_, "Assert!\n")) Crash(); \
175
}
176
177
#define _dbg_assert_or_log_(_a_) \
178
if (!(_a_)) {\
179
if (!HandleAssert(__FUNCTION__, __FILENAME__, __LINE__, #_a_, "Assert!\n")) Crash(); \
180
}
181
182
#define _dbg_assert_msg_(_a_, ...) \
183
if (!(_a_)) { \
184
if (!HandleAssert(__FUNCTION__, __FILENAME__, __LINE__, #_a_, __VA_ARGS__)) Crash(); \
185
}
186
187
#define _dbg_assert_msg_or_log_(_a_, log, ...) \
188
if (!(_a_)) { \
189
if (!HandleAssert(__FUNCTION__, __FILENAME__, __LINE__, #_a_, __VA_ARGS__)) Crash(); \
190
}
191
192
#else // not debug
193
194
#ifndef _dbg_assert_
195
#define _dbg_assert_(_a_) {}
196
#define _dbg_assert_or_log_(_a_) \
197
if (!(_a_)) { \
198
ERROR_LOG(Log::System, "Assert! " ## #_a_); \
199
}
200
#define _dbg_assert_msg_(_a_, _desc_, ...) {}
201
#define _dbg_assert_msg_or_log_(_a_, log, ...) \
202
if (!(_a_)) { \
203
ERROR_LOG(log, __VA_ARGS__); \
204
}
205
206
#endif // dbg_assert
207
208
#endif // MAX_LOGLEVEL DEBUG
209
210
#define _assert_(_a_) \
211
if (!(_a_)) {\
212
if (!HandleAssert(__FUNCTION__, __FILENAME__, __LINE__, #_a_, "Assert!\n")) Crash(); \
213
}
214
215
#define _assert_msg_(_a_, ...) \
216
if (!(_a_)) { \
217
if (!HandleAssert(__FUNCTION__, __FILENAME__, __LINE__, #_a_, __VA_ARGS__)) Crash(); \
218
}
219
220
// Just INFO_LOGs on nonWindows. On Windows it outputs to the VS output console.
221
void OutputDebugStringUTF8(const char *p);
222
223