Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/Common/Log.h
5670 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
Debugger,
57
GeDebugger,
58
UI,
59
IAP,
60
61
sceAudio,
62
sceCtrl,
63
sceDisplay,
64
sceFont,
65
sceGe,
66
sceIntc,
67
sceIo,
68
sceKernel,
69
sceModule,
70
sceNet,
71
sceRtc,
72
sceSas,
73
sceUtility,
74
sceMisc,
75
sceReg,
76
77
NUMBER_OF_LOGS, // Must be last
78
};
79
80
enum class LogLevel : int {
81
LNOTICE = NOTICE_LEVEL,
82
LERROR = ERROR_LEVEL,
83
LWARNING = WARNING_LEVEL,
84
LINFO = INFO_LEVEL,
85
LDEBUG = DEBUG_LEVEL,
86
LVERBOSE = VERBOSE_LEVEL,
87
};
88
89
struct LogChannel {
90
#if defined(_DEBUG)
91
LogLevel level = LogLevel::LDEBUG;
92
#else
93
LogLevel level = LogLevel::LDEBUG;
94
#endif
95
bool enabled = true;
96
97
bool IsEnabled(LogLevel level) const {
98
if (level > this->level || !this->enabled)
99
return false;
100
return true;
101
}
102
};
103
104
extern bool *g_bLogEnabledSetting;
105
extern LogChannel g_log[(size_t)Log::NUMBER_OF_LOGS];
106
107
inline bool GenericLogEnabled(Log type, LogLevel level) {
108
return g_log[(int)type].IsEnabled(level) && (*g_bLogEnabledSetting);
109
}
110
111
void GenericLog(Log type, LogLevel level, const char *file, int line, const char *fmt, ...)
112
#ifdef __GNUC__
113
__attribute__((format(printf, 5, 6)))
114
#endif
115
;
116
117
// If you want to see verbose logs, change this to VERBOSE_LEVEL.
118
119
#define MAX_LOGLEVEL DEBUG_LEVEL
120
121
// Let the compiler optimize this out.
122
// TODO: Compute a dynamic max level as well that can be checked here.
123
#define GENERIC_LOG(t, v, ...) \
124
if ((int)v <= MAX_LOGLEVEL && GenericLogEnabled(t, v)) { \
125
GenericLog(t, v, __FILE__, __LINE__, __VA_ARGS__); \
126
}
127
128
#define ERROR_LOG(t,...) do { GENERIC_LOG(t, LogLevel::LERROR, __VA_ARGS__) } while (false)
129
#define WARN_LOG(t,...) do { GENERIC_LOG(t, LogLevel::LWARNING, __VA_ARGS__) } while (false)
130
#define NOTICE_LOG(t,...) do { GENERIC_LOG(t, LogLevel::LNOTICE, __VA_ARGS__) } while (false)
131
#define INFO_LOG(t,...) do { GENERIC_LOG(t, LogLevel::LINFO, __VA_ARGS__) } while (false)
132
#define DEBUG_LOG(t,...) do { GENERIC_LOG(t, LogLevel::LDEBUG, __VA_ARGS__) } while (false)
133
#define VERBOSE_LOG(t,...) do { GENERIC_LOG(t, LogLevel::LVERBOSE, __VA_ARGS__) } while (false)
134
135
// Currently only actually shows a dialog box on Windows.
136
bool HandleAssert(bool isDebugAssert, const char *function, const char *file, int line, const char *expression, const char* format, ...)
137
#ifdef __GNUC__
138
__attribute__((format(printf, 6, 7)))
139
#endif
140
;
141
142
// These allow us to get a small amount of information into assert messages.
143
// They can have a value between 0 and 15.
144
enum class DebugCounter {
145
APP_BOOT = 0,
146
GAME_BOOT = 1,
147
GAME_SHUTDOWN = 2,
148
CPUCORE_SWITCHES = 3,
149
};
150
151
bool HitAnyAsserts();
152
void ResetHitAnyAsserts();
153
void SetExtraAssertInfo(const char *info);
154
void SetDebugValue(DebugCounter counter, int value);
155
void IncrementDebugCounter(DebugCounter counter);
156
typedef void (*AssertNoCallbackFunc)(const char *message, void *userdata);
157
void SetAssertCancelCallback(AssertNoCallbackFunc callback, void *userdata);
158
void SetCleanExitOnAssert();
159
void BreakIntoPSPDebugger(const char *reason = "(userbreak)");
160
void SetAssertDialogParent(void *handle); // HWND on windows. Ignored on other platforms.
161
162
#if defined(__ANDROID__)
163
// Tricky macro to get the basename, that also works if *built* on Win32.
164
// Doesn't mean this macro can be used on Win32 though.
165
#define __FILENAME__ (__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 : (__builtin_strrchr(__FILE__, '\\') ? __builtin_strrchr(__FILE__, '\\') + 1 : __FILE__))
166
#else
167
#define __FILENAME__ __FILE__
168
#endif
169
170
// If we're a debug build, _dbg_assert_ is active. Not otherwise, even on Windows.
171
#if defined(_DEBUG)
172
173
#define _dbg_assert_(_a_) \
174
if (!(_a_)) {\
175
if (!HandleAssert(true, __FUNCTION__, __FILENAME__, __LINE__, #_a_, "Assert!\n")) Crash(); \
176
}
177
178
#define _dbg_assert_or_log_(_a_) \
179
if (!(_a_)) {\
180
if (!HandleAssert(true, __FUNCTION__, __FILENAME__, __LINE__, #_a_, "Assert!\n")) Crash(); \
181
}
182
183
#define _dbg_assert_msg_(_a_, ...) \
184
if (!(_a_)) { \
185
if (!HandleAssert(true, __FUNCTION__, __FILENAME__, __LINE__, #_a_, __VA_ARGS__)) Crash(); \
186
}
187
188
#define _dbg_assert_msg_or_log_(_a_, log, ...) \
189
if (!(_a_)) { \
190
if (!HandleAssert(true, __FUNCTION__, __FILENAME__, __LINE__, #_a_, __VA_ARGS__)) Crash(); \
191
}
192
193
#else // not debug
194
195
#ifndef _dbg_assert_
196
#define _dbg_assert_(_a_) {}
197
#define _dbg_assert_or_log_(_a_) \
198
if (!(_a_)) { \
199
ERROR_LOG(Log::System, "Assert! " ## #_a_); \
200
}
201
#define _dbg_assert_msg_(_a_, _desc_, ...) {}
202
#define _dbg_assert_msg_or_log_(_a_, log, ...) \
203
if (!(_a_)) { \
204
ERROR_LOG(log, __VA_ARGS__); \
205
}
206
207
#endif // dbg_assert
208
209
#endif // MAX_LOGLEVEL DEBUG
210
211
#define _assert_(_a_) \
212
if (!(_a_)) {\
213
if (!HandleAssert(false, __FUNCTION__, __FILENAME__, __LINE__, #_a_, "Assert!\n")) Crash(); \
214
}
215
216
#define _assert_msg_(_a_, ...) \
217
if (!(_a_)) { \
218
if (!HandleAssert(false, __FUNCTION__, __FILENAME__, __LINE__, #_a_, __VA_ARGS__)) Crash(); \
219
}
220
221
// Just INFO_LOGs on nonWindows. On Windows it outputs to the VS output console.
222
void OutputDebugStringUTF8(const char *p);
223
224