diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 5bed7d75d7..62b7a76a60 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -133,6 +133,7 @@ void __KernelInit() __HeapInit(); SaveState::Init(); // Must be after IO, as it may create a directory + Reporting::Init(); // "Internal" PSP libraries __PPGeInit(); diff --git a/Core/Reporting.cpp b/Core/Reporting.cpp index 9b03cb106e..9698cc5e35 100644 --- a/Core/Reporting.cpp +++ b/Core/Reporting.cpp @@ -36,6 +36,7 @@ #include "base/buffer.h" #include "thread/thread.h" +#include #include #include @@ -49,6 +50,8 @@ namespace Reporting static u32 spamProtectionCount = 0; // Temporarily stores a reference to the hostname. static std::string lastHostname; + // Keeps track of report-only-once identifiers. + static std::set logOnceUsed; enum RequestType { @@ -190,6 +193,19 @@ namespace Reporting #endif } + void Init() + { + // New game, clean slate. + spamProtectionCount = 0; + logOnceUsed.clear(); + } + + bool ShouldLogOnce(const char *identifier) + { + // True if it wasn't there already -> so yes, log. + return logOnceUsed.insert(identifier).second; + } + int Process(int pos) { Payload &payload = payloadBuffer[pos]; diff --git a/Core/Reporting.h b/Core/Reporting.h index 103bb388ad..b2598e6db4 100644 --- a/Core/Reporting.h +++ b/Core/Reporting.h @@ -24,19 +24,22 @@ #define NOTICE_LOG_REPORT(t,...) { NOTICE_LOG(t, __VA_ARGS__); Reporting::ReportMessage(__VA_ARGS__); } #define INFO_LOG_REPORT(t,...) { INFO_LOG(t, __VA_ARGS__); Reporting::ReportMessage(__VA_ARGS__); } -#define DEBUG_LOG_REPORT_ONCE(n,t,...) { static bool n = false; if (!n) { n = true; DEBUG_LOG(t, __VA_ARGS__); Reporting::ReportMessage(__VA_ARGS__); } } -#define ERROR_LOG_REPORT_ONCE(n,t,...) { static bool n = false; if (!n) { n = true; ERROR_LOG(t, __VA_ARGS__); Reporting::ReportMessage(__VA_ARGS__); } } -#define WARN_LOG_REPORT_ONCE(n,t,...) { static bool n = false; if (!n) { n = true; WARN_LOG(t, __VA_ARGS__); Reporting::ReportMessage(__VA_ARGS__); } } -#define NOTICE_LOG_REPORT_ONCE(n,t,...) { static bool n = false; if (!n) { n = true; NOTICE_LOG(t, __VA_ARGS__); Reporting::ReportMessage(__VA_ARGS__); } } -#define INFO_LOG_REPORT_ONCE(n,t,...) { static bool n = false; if (!n) { n = true; INFO_LOG(t, __VA_ARGS__); Reporting::ReportMessage(__VA_ARGS__); } } +#define DEBUG_LOG_REPORT_ONCE(n,t,...) { if (Reporting::ShouldLogOnce(#n)) { DEBUG_LOG_REPORT(t, __VA_ARGS__); } } +#define ERROR_LOG_REPORT_ONCE(n,t,...) { if (Reporting::ShouldLogOnce(#n)) { ERROR_LOG_REPORT(t, __VA_ARGS__); } } +#define WARN_LOG_REPORT_ONCE(n,t,...) { if (Reporting::ShouldLogOnce(#n)) { WARN_LOG_REPORT(t, __VA_ARGS__); } } +#define NOTICE_LOG_REPORT_ONCE(n,t,...) { if (Reporting::ShouldLogOnce(#n)) { NOTICE_LOG_REPORT(t, __VA_ARGS__); } } +#define INFO_LOG_REPORT_ONCE(n,t,...) { if (Reporting::ShouldLogOnce(#n)) { INFO_LOG_REPORT(t, __VA_ARGS__); } } -#define ERROR_LOG_ONCE(n,t,...) { static bool n = false; if (!n) { n = true; ERROR_LOG(t, __VA_ARGS__); } } -#define WARN_LOG_ONCE(n,t,...) { static bool n = false; if (!n) { n = true; WARN_LOG(t, __VA_ARGS__); } } -#define NOTICE_LOG_ONCE(n,t,...) { static bool n = false; if (!n) { n = true; NOTICE_LOG(t, __VA_ARGS__); } } -#define INFO_LOG_ONCE(n,t,...) { static bool n = false; if (!n) { n = true; INFO_LOG(t, __VA_ARGS__); } } +#define ERROR_LOG_ONCE(n,t,...) { if (Reporting::ShouldLogOnce(#n)) { ERROR_LOG(t, __VA_ARGS__); } } +#define WARN_LOG_ONCE(n,t,...) { if (Reporting::ShouldLogOnce(#n)) { WARN_LOG(t, __VA_ARGS__); } } +#define NOTICE_LOG_ONCE(n,t,...) { if (Reporting::ShouldLogOnce(#n)) { NOTICE_LOG(t, __VA_ARGS__); } } +#define INFO_LOG_ONCE(n,t,...) { if (Reporting::ShouldLogOnce(#n)) { INFO_LOG(t, __VA_ARGS__); } } namespace Reporting { + // Should be called whenever a new game is loaded to forget things. + void Init(); + // Returns whether or not the reporting system is currently enabled. bool IsEnabled(); @@ -51,4 +54,6 @@ namespace Reporting // Report a message string, using the format string as a key. void ReportMessage(const char *message, ...); + + bool ShouldLogOnce(const char *identifier); } \ No newline at end of file diff --git a/GPU/Common/VertexDecoderCommon.h b/GPU/Common/VertexDecoderCommon.h index 032935fa60..dcea1c6932 100644 --- a/GPU/Common/VertexDecoderCommon.h +++ b/GPU/Common/VertexDecoderCommon.h @@ -132,7 +132,7 @@ public: } break; default: - ERROR_LOG_REPORT_ONCE(fmt, G3D, "Reader: Unsupported Pos Format %d", decFmt_.posfmt); + ERROR_LOG_REPORT_ONCE(fmtpos, G3D, "Reader: Unsupported Pos Format %d", decFmt_.posfmt); memset(pos, 0, sizeof(float) * 3); break; } @@ -180,7 +180,7 @@ public: } break; default: - ERROR_LOG_REPORT_ONCE(fmt, G3D, "Reader: Unsupported Pos Format %d", decFmt_.posfmt); + ERROR_LOG_REPORT_ONCE(fmtz16, G3D, "Reader: Unsupported Pos Format %d", decFmt_.posfmt); memset(pos, 0, sizeof(float) * 3); break; } @@ -211,7 +211,7 @@ public: } break; default: - ERROR_LOG_REPORT_ONCE(fmt, G3D, "Reader: Unsupported Nrm Format %d", decFmt_.nrmfmt); + ERROR_LOG_REPORT_ONCE(fmtnrm, G3D, "Reader: Unsupported Nrm Format %d", decFmt_.nrmfmt); memset(nrm, 0, sizeof(float) * 3); break; } @@ -259,7 +259,7 @@ public: } break; default: - ERROR_LOG_REPORT_ONCE(fmt, G3D, "Reader: Unsupported UV Format %d", decFmt_.uvfmt); + ERROR_LOG_REPORT_ONCE(fmtuv, G3D, "Reader: Unsupported UV Format %d", decFmt_.uvfmt); memset(uv, 0, sizeof(float) * 2); break; } @@ -278,7 +278,7 @@ public: memcpy(color, data_ + decFmt_.c0off, 16); break; default: - ERROR_LOG_REPORT_ONCE(fmt, G3D, "Reader: Unsupported C0 Format %d", decFmt_.c0fmt); + ERROR_LOG_REPORT_ONCE(fmtc0, G3D, "Reader: Unsupported C0 Format %d", decFmt_.c0fmt); memset(color, 0, sizeof(float) * 4); break; } @@ -301,7 +301,7 @@ public: } break; default: - ERROR_LOG_REPORT_ONCE(fmt, G3D, "Reader: Unsupported C0 Format %d", decFmt_.c0fmt); + ERROR_LOG_REPORT_ONCE(fmtc0_8888, G3D, "Reader: Unsupported C0 Format %d", decFmt_.c0fmt); memset(color, 0, sizeof(float) * 4); break; } @@ -321,7 +321,7 @@ public: memcpy(color, data_ + decFmt_.c1off, 12); break; default: - ERROR_LOG_REPORT_ONCE(fmt, G3D, "Reader: Unsupported C1 Format %d", decFmt_.c1fmt); + ERROR_LOG_REPORT_ONCE(fmtc1, G3D, "Reader: Unsupported C1 Format %d", decFmt_.c1fmt); memset(color, 0, sizeof(float) * 3); break; } @@ -348,7 +348,7 @@ public: case DEC_U16_3: for (int i = 0; i < 3; i++) weights[i] = s[i] * (1.f / 32768.f); break; case DEC_U16_4: for (int i = 0; i < 4; i++) weights[i] = s[i] * (1.f / 32768.f); break; default: - ERROR_LOG_REPORT_ONCE(fmt0, G3D, "Reader: Unsupported W0 Format %d", decFmt_.w0fmt); + ERROR_LOG_REPORT_ONCE(fmtw0, G3D, "Reader: Unsupported W0 Format %d", decFmt_.w0fmt); memset(weights, 0, sizeof(float) * 4); break; } @@ -376,7 +376,7 @@ public: case DEC_U16_3: for (int i = 0; i < 3; i++) weights[i+4] = s[i] * (1.f / 32768.f); break; case DEC_U16_4: for (int i = 0; i < 4; i++) weights[i+4] = s[i] * (1.f / 32768.f); break; default: - ERROR_LOG_REPORT_ONCE(fmt1, G3D, "Reader: Unsupported W1 Format %d", decFmt_.w1fmt); + ERROR_LOG_REPORT_ONCE(fmtw1, G3D, "Reader: Unsupported W1 Format %d", decFmt_.w1fmt); memset(weights + 4, 0, sizeof(float) * 4); break; } diff --git a/GPU/GLES/VertexDecoder.cpp b/GPU/GLES/VertexDecoder.cpp index a32db086bb..4ccb67f6e6 100644 --- a/GPU/GLES/VertexDecoder.cpp +++ b/GPU/GLES/VertexDecoder.cpp @@ -647,7 +647,7 @@ void VertexDecoder::SetVertexType(u32 fmt, VertexDecoderJitCache *jitCache) { memset(&decFmt, 0, sizeof(decFmt)); if (morphcount > 1) { - DEBUG_LOG_REPORT_ONCE(m, G3D,"VTYPE with morph used: THRU=%i TC=%i COL=%i POS=%i NRM=%i WT=%i NW=%i IDX=%i MC=%i", (int)throughmode, tc,col,pos,nrm,weighttype,nweights,idx,morphcount); + DEBUG_LOG_REPORT_ONCE(vtypeM, G3D,"VTYPE with morph used: THRU=%i TC=%i COL=%i POS=%i NRM=%i WT=%i NW=%i IDX=%i MC=%i", (int)throughmode, tc,col,pos,nrm,weighttype,nweights,idx,morphcount); } else { DEBUG_LOG(G3D,"VTYPE: THRU=%i TC=%i COL=%i POS=%i NRM=%i WT=%i NW=%i IDX=%i MC=%i", (int)throughmode, tc,col,pos,nrm,weighttype,nweights,idx,morphcount); }