diff --git a/Source/Core/Common/Src/Common.h b/Source/Core/Common/Src/Common.h index 2e8b4ed92c..4ae1b56fc5 100644 --- a/Source/Core/Common/Src/Common.h +++ b/Source/Core/Common/Src/Common.h @@ -235,6 +235,7 @@ void Host_UpdateLogDisplay(); #ifdef LOGGING #define LOG(t, ...) __Log(LogTypes::t, __VA_ARGS__); +#define LOGV(t,v, ...) __Log(LogTypes::t + v*100, __VA_ARGS__); #define _dbg_assert_(_t_, _a_) \ if (!(_a_)){\ @@ -252,6 +253,7 @@ void Host_UpdateLogDisplay(); #else #define LOG(_t_, ...) +#define LOGV(_t_,_v_, ...) #define _dbg_clear_() #ifndef _dbg_assert_ #define _dbg_assert_(_t_, _a_) ; diff --git a/Source/Core/Core/Core.vcproj b/Source/Core/Core/Core.vcproj index bfa0743e54..b6efc3f5ee 100644 --- a/Source/Core/Core/Core.vcproj +++ b/Source/Core/Core/Core.vcproj @@ -45,7 +45,7 @@ %02x", byte); + LOGV(EXPANSIONINTERFACE, 3, "EXI MEMCARD: > %02x", byte); if (m_uPosition == 0) { command = byte; // first byte is command byte = 0xFF; // would be tristate, but we don't care. - LOG(EXPANSIONINTERFACE, "EXI MEMCARD: command %02x", byte) + LOGV(EXPANSIONINTERFACE, 1, "EXI MEMCARD: command %02x", byte) if(command == cmdClearStatus) { @@ -382,5 +382,5 @@ void CEXIMemoryCard::TransferByte(u8 &byte) } } m_uPosition++; - LOG(EXPANSIONINTERFACE, "EXI MEMCARD: < %02x", byte); + LOGV(EXPANSIONINTERFACE, 3, "EXI MEMCARD: < %02x", byte); } diff --git a/Source/Core/Core/Src/HW/PeripheralInterface.cpp b/Source/Core/Core/Src/HW/PeripheralInterface.cpp index e48e495766..2e30eaa1b8 100644 --- a/Source/Core/Core/Src/HW/PeripheralInterface.cpp +++ b/Source/Core/Core/Src/HW/PeripheralInterface.cpp @@ -79,7 +79,7 @@ void CPeripheralInterface::Read32(u32& _uReturnValue, const u32 _iAddress) return; case PI_FIFO_WPTR: - LOG(PERIPHERALINTERFACE,"read writepointer, value = %08x",Fifo_CPUWritePointer); + LOGV(PERIPHERALINTERFACE, 3, "read writepointer, value = %08x",Fifo_CPUWritePointer); _uReturnValue = Fifo_CPUWritePointer; //really writes in 32-byte chunks // Monk's gcube does some crazy align trickery here. @@ -206,12 +206,12 @@ void CPeripheralInterface::SetInterrupt(InterruptCause _causemask, bool _bSet) if (_bSet && !(m_InterruptCause & (u32)_causemask)) { - LOG(PERIPHERALINTERFACE,"Setting Interrupt %s (%s)",Debug_GetInterruptName(_causemask), "set"); + LOGV(PERIPHERALINTERFACE, 2, "Setting Interrupt %s (%s)",Debug_GetInterruptName(_causemask), "set"); } if (!_bSet && (m_InterruptCause & (u32)_causemask)) { - LOG(PERIPHERALINTERFACE,"Setting Interrupt %s (%s)",Debug_GetInterruptName(_causemask), "clear"); + LOGV(PERIPHERALINTERFACE, 2, "Setting Interrupt %s (%s)",Debug_GetInterruptName(_causemask), "clear"); } if (_bSet) diff --git a/Source/Core/Core/Src/HW/PixelEngine.cpp b/Source/Core/Core/Src/HW/PixelEngine.cpp index 290e3a6f71..07be296864 100644 --- a/Source/Core/Core/Src/HW/PixelEngine.cpp +++ b/Source/Core/Core/Src/HW/PixelEngine.cpp @@ -87,7 +87,7 @@ void Init() void Read16(u16& _uReturnValue, const u32 _iAddress) { - LOG(PIXELENGINE, "(r16): 0x%08x", _iAddress); + LOGV(PIXELENGINE, 3, "(r16): 0x%08x", _iAddress); switch (_iAddress & 0xFFF) { @@ -109,12 +109,12 @@ void Read16(u16& _uReturnValue, const u32 _iAddress) void Write32(const u32 _iValue, const u32 _iAddress) { - LOG(PIXELENGINE, "(w32): 0x%08x @ 0x%08x",_iValue,_iAddress); + LOGV(PIXELENGINE, 2, "(w32): 0x%08x @ 0x%08x",_iValue,_iAddress); } void Write16(const u16 _iValue, const u32 _iAddress) { - LOG(PIXELENGINE, "(w16): 0x%04x @ 0x%08x",_iValue,_iAddress); + LOGV(PIXELENGINE, 3, "(w16): 0x%04x @ 0x%08x",_iValue,_iAddress); switch(_iAddress & 0xFFF) { @@ -169,7 +169,7 @@ void SetToken_OnMainThread(u64 userdata, int cyclesLate) if (userdata >> 16) g_bSignalTokenInterrupt = true; g_token = (u16)(userdata & 0xFFFF); - LOG(PIXELENGINE, "VIDEO Plugin wrote token: %i", g_token); + LOGV(PIXELENGINE, 1, "VIDEO Plugin wrote token: %i", g_token); UpdateInterrupts(); } @@ -193,7 +193,7 @@ void SetFinish() { CoreTiming::ScheduleEvent_Threadsafe( 0, et_SetFinishOnMainThread); - LOG(PIXELENGINE, "VIDEO Set Finish"); + LOGV(PIXELENGINE, 2, "VIDEO Set Finish"); } } // end of namespace PixelEngine diff --git a/Source/Core/Core/Src/HW/SerialInterface.cpp b/Source/Core/Core/Src/HW/SerialInterface.cpp index ac33eb92fd..f9f498b138 100644 --- a/Source/Core/Core/Src/HW/SerialInterface.cpp +++ b/Source/Core/Core/Src/HW/SerialInterface.cpp @@ -268,7 +268,7 @@ void Shutdown() void Read32(u32& _uReturnValue, const u32 _iAddress) { - LOG(SERIALINTERFACE, "(r32): 0x%08x", _iAddress); + LOGV(SERIALINTERFACE, 3, "(r32): 0x%08x", _iAddress); // SIBuffer if ((_iAddress >= 0xCC006480 && _iAddress < 0xCC006500) || @@ -375,7 +375,7 @@ void Read32(u32& _uReturnValue, const u32 _iAddress) void Write32(const u32 _iValue, const u32 _iAddress) { - LOG(SERIALINTERFACE, "(w32): 0x%08x 0x%08x", _iValue,_iAddress); + LOGV(SERIALINTERFACE, 3, "(w32): 0x%08x 0x%08x", _iValue,_iAddress); // SIBuffer if ((_iAddress >= 0xCC006480 && _iAddress < 0xCC006500) || @@ -546,7 +546,7 @@ void RunSIBuffer() int numOutput = #endif g_Channel[g_ComCSR.CHANNEL].m_pDevice->RunBuffer(g_SIBuffer, inLength); - LOG(SERIALINTERFACE, "RunSIBuffer (intLen: %i outLen: %i) (processed: %i)", inLength, outLength, numOutput); + LOGV(SERIALINTERFACE, 2, "RunSIBuffer (intLen: %i outLen: %i) (processed: %i)", inLength, outLength, numOutput); // Transfer completed GenerateSIInterrupt(INT_TCINT); diff --git a/Source/Core/Core/Src/HW/VideoInterface.cpp b/Source/Core/Core/Src/HW/VideoInterface.cpp index 51330a73d3..c89f46a8cd 100644 --- a/Source/Core/Core/Src/HW/VideoInterface.cpp +++ b/Source/Core/Core/Src/HW/VideoInterface.cpp @@ -205,7 +205,7 @@ void Read16(u16& _uReturnValue, const u32 _iAddress) return; case VI_CONTROL_REGISTER: - LOG(VIDEOINTERFACE, "VideoInterface(r16): VI_CONTROL_REGISTER 0x%08x", m_VIDisplayControlRegister.Hex); + LOGV(VIDEOINTERFACE, 3, "VideoInterface(r16): VI_CONTROL_REGISTER 0x%08x", m_VIDisplayControlRegister.Hex); _uReturnValue = m_VIDisplayControlRegister.Hex; return; @@ -272,7 +272,7 @@ void Read16(u16& _uReturnValue, const u32 _iAddress) void Write16(const u16 _iValue, const u32 _iAddress) { - LOG(VIDEOINTERFACE, "(w16): 0x%04x, 0x%08x",_iValue,_iAddress); + LOGV(VIDEOINTERFACE, 3, "(w16): 0x%04x, 0x%08x",_iValue,_iAddress); //Somewhere it sets screen width.. we need to communicate this to the gfx plugin... diff --git a/Source/Core/Core/Src/HW/WII_IOB.cpp b/Source/Core/Core/Src/HW/WII_IOB.cpp index 0c96cf69e4..9b9bfe5a3c 100644 --- a/Source/Core/Core/Src/HW/WII_IOB.cpp +++ b/Source/Core/Core/Src/HW/WII_IOB.cpp @@ -38,17 +38,17 @@ void HWCALL Read32(u32& _rReturnValue, const u32 _Address) { case 0xc0: // __VISendI2CData _rReturnValue = 0; - LOG(WII_IOB, "IOP: Read32 from 0xc0 = 0x%08x (__VISendI2CData)", _rReturnValue); + LOGV(WII_IOB, 2, "IOP: Read32 from 0xc0 = 0x%08x (__VISendI2CData)", _rReturnValue); break; case 0xc4: // __VISendI2CData _rReturnValue = 0; - LOG(WII_IOB, "IOP: Read32 from 0xc4 = 0x%08x (__VISendI2CData)", _rReturnValue); + LOGV(WII_IOB, 2, "IOP: Read32 from 0xc4 = 0x%08x (__VISendI2CData)", _rReturnValue); break; case 0xc8: // __VISendI2CData _rReturnValue = 0; - LOG(WII_IOB, "IOP: Read32 from 0xc8 = 0x%08x (__VISendI2CData)", _rReturnValue); + LOGV(WII_IOB, 2, "IOP: Read32 from 0xc8 = 0x%08x (__VISendI2CData)", _rReturnValue); break; case 0x180: // __AIClockInit @@ -92,15 +92,15 @@ void HWCALL Write32(const u32 _Value, const u32 _Address) switch(_Address & 0xFFFF) { case 0xc0: // __VISendI2CData - LOG(WII_IOB, "IOP: Write32 to 0xc0 = 0x%08x (__VISendI2CData)", _Value); + LOGV(WII_IOB, 2, "IOP: Write32 to 0xc0 = 0x%08x (__VISendI2CData)", _Value); break; case 0xc4: // __VISendI2CData - LOG(WII_IOB, "IOP: Write32 to 0xc4 = 0x%08x (__VISendI2CData)", _Value); + LOGV(WII_IOB, 2, "IOP: Write32 to 0xc4 = 0x%08x (__VISendI2CData)", _Value); break; case 0xc8: // __VISendI2CData - LOG(WII_IOB, "IOP: Write32 to 0xc8 = 0x%08x (__VISendI2CData)", _Value); + LOGV(WII_IOB, 2, "IOP: Write32 to 0xc8 = 0x%08x (__VISendI2CData)", _Value); break; case 0x180: // __AIClockInit diff --git a/Source/Core/Core/Src/HW/WII_IPC.cpp b/Source/Core/Core/Src/HW/WII_IPC.cpp index 8e942b6907..efbc978201 100644 --- a/Source/Core/Core/Src/HW/WII_IPC.cpp +++ b/Source/Core/Core/Src/HW/WII_IPC.cpp @@ -129,7 +129,7 @@ void HWCALL Read32(u32& _rReturnValue, const u32 _Address) _rReturnValue = g_IPC_Control.Hex; - LOG(WII_IPC, "IOP: Read32 from IPC_CONTROL_REGISTER(0x04) = 0x%08x", _rReturnValue); + LOGV(WII_IPC, 2, "IOP: Read32 from IPC_CONTROL_REGISTER(0x04) = 0x%08x", _rReturnValue); // CCPU::Break(); // if ((REASON_REG & 0x14) == 0x14) CALL IPCReplayHanlder @@ -139,7 +139,7 @@ void HWCALL Read32(u32& _rReturnValue, const u32 _Address) case IPC_REPLY_REGISTER: // looks a little bit like a callback function _rReturnValue = g_Reply; - LOG(WII_IPC, "IOP: Write32 to IPC_REPLAY_REGISTER(0x08) = 0x%08x ", _rReturnValue); + LOGV(WII_IPC, 2, "IOP: Write32 to IPC_REPLAY_REGISTER(0x08) = 0x%08x ", _rReturnValue); break; case IPC_SENSOR_BAR_POWER_REGISTER: @@ -160,13 +160,13 @@ void HWCALL Write32(const u32 _Value, const u32 _Address) case IPC_COMMAND_REGISTER: // __ios_Ipc2 ... a value from __responses is loaded { g_Address = _Value; - LOG(WII_IPC, "IOP: Write32 to IPC_ADDRESS_REGISTER(0x00) = 0x%08x", g_Address); + LOGV(WII_IPC, 1, "IOP: Write32 to IPC_ADDRESS_REGISTER(0x00) = 0x%08x", g_Address); } break; case IPC_CONTROL_REGISTER: { - LOG(WII_IPC, "IOP: Write32 to IPC_CONTROL_REGISTER(0x04) = 0x%08x (old: 0x%08x)", _Value, g_IPC_Control.Hex); + LOGV(WII_IPC, 1, "IOP: Write32 to IPC_CONTROL_REGISTER(0x04) = 0x%08x (old: 0x%08x)", _Value, g_IPC_Control.Hex); UIPC_Control TempControl(_Value); _dbg_assert_msg_(WII_IPC, TempControl.pad == 0, "IOP: Write to UIPC_Control.pad", _Address); @@ -192,7 +192,7 @@ void HWCALL Write32(const u32 _Value, const u32 _Address) UIPC_Status NewStatus(_Value); if (NewStatus.INTERRUPT) g_IPC_Status.INTERRUPT = 0; // clear interrupt - LOG(WII_IPC, "IOP: Write32 to IPC_STATUS_REGISTER(0x30) = 0x%08x", _Value); + LOGV(WII_IPC, 1, "IOP: Write32 to IPC_STATUS_REGISTER(0x30) = 0x%08x", _Value); } break; diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp index 9653fbcff2..a0f6d45e38 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp @@ -362,7 +362,7 @@ void Update() // check if we have to execute an acknowledged command if (!m_ReplyQueue.empty()) { - LOG(WII_IPC_HLE, "-- Generate Reply %s (0x%08x)", m_ReplyQueue.front().second.c_str(), m_ReplyQueue.front().first); + LOGV(WII_IPC_HLE, 1, "-- Generate Reply %s (0x%08x)", m_ReplyQueue.front().second.c_str(), m_ReplyQueue.front().first); WII_IPCInterface::GenerateReply(m_ReplyQueue.front().first); m_ReplyQueue.pop(); return; @@ -373,7 +373,7 @@ void Update() u32 _Address = m_Ack.front(); m_Ack.pop_front(); ExecuteCommand(_Address); - LOG(WII_IPC_HLE, "-- Generate Ack (0x%08x)", _Address); + LOGV(WII_IPC_HLE, 1, "-- Generate Ack (0x%08x)", _Address); WII_IPCInterface::GenerateAck(_Address); } } diff --git a/Source/Core/Core/Src/LogManager.cpp b/Source/Core/Core/Src/LogManager.cpp index 7998e42b01..5fd47ae3bc 100644 --- a/Source/Core/Core/Src/LogManager.cpp +++ b/Source/Core/Core/Src/LogManager.cpp @@ -16,18 +16,20 @@ // http://code.google.com/p/dolphin-emu/ #include +#include // for the timestamps #include "Common.h" #include "StringUtil.h" #include "LogManager.h" #include "PowerPC/PowerPC.h" +#include "PowerPC/SymbolDB.h" // for g_symbolDB #include "Debugger/Debugger_SymbolMap.h" -LogManager::SMessage *LogManager::m_Messages; -int LogManager::m_nextMessages = 0; +LogManager::SMessage (*LogManager::m_Messages)[MAX_MESSAGES]; +int LogManager::m_nextMessages[LogManager::VERBOSITY_LEVELS + 1]; -CDebugger_Log* LogManager::m_Log[LogTypes::NUMBER_OF_LOGS]; +CDebugger_Log* LogManager::m_Log[LogTypes::NUMBER_OF_LOGS + (LogManager::VERBOSITY_LEVELS * 100)]; int LogManager::m_activeLog = LogTypes::MASTER_LOG; bool LogManager::m_bDirty = true; bool LogManager::m_bInitialized = false; @@ -35,9 +37,6 @@ bool LogManager::m_bInitialized = false; void __Log(int log, const char *format, ...) { - if (!LogManager::IsLogEnabled((LogTypes::LOG_TYPE)log)) - return; - char* temp = (char*)alloca(strlen(format)+512); va_list args; va_start(args, format); @@ -46,15 +45,16 @@ void __Log(int log, const char *format, ...) LogManager::Log((LogTypes::LOG_TYPE)log, temp); } -CDebugger_Log::CDebugger_Log(const char* _szShortName, const char* _szName) : - m_bLogToFile(true), - m_bShowInLog(true), - m_bEnable(true), +CDebugger_Log::CDebugger_Log(const char* _szShortName, const char* _szName, int a) : + m_bLogToFile(true), // write to file or not + m_bShowInLog(false), + m_bEnable(false), m_pFile(NULL) { strcpy((char*)m_szName, _szName); - strcpy((char*)m_szShortName, _szShortName); - sprintf((char*)m_szFilename, "Logs/%s.txt", _szName); + strcpy((char*)m_szShortName_, _szShortName); + sprintf((char*)m_szShortName, "%s%i", _szShortName, a); + sprintf((char*)m_szFilename, "Logs/%s%i.txt", _szName, a); unlink(m_szFilename); } @@ -68,6 +68,10 @@ CDebugger_Log::~CDebugger_Log(void) } } +// we may need to declare these +CDebugger_LogSettings::CDebugger_LogSettings() {} +CDebugger_LogSettings::~CDebugger_LogSettings(void) {} + void CDebugger_Log::Init() { m_pFile = fopen(m_szFilename, "wtb"); @@ -85,44 +89,53 @@ void CDebugger_Log::Shutdown() void LogManager::Init() { - m_Messages = new SMessage[MAX_MESSAGES]; + m_Messages = new SMessage[LogManager::VERBOSITY_LEVELS + 1][MAX_MESSAGES]; m_bDirty = true; - // create Logs - m_Log[LogTypes::MASTER_LOG] = new CDebugger_Log("*", "Master Log"); - m_Log[LogTypes::BOOT] = new CDebugger_Log("BOOT", "Boot"); - m_Log[LogTypes::PIXELENGINE] = new CDebugger_Log("PE", "PixelEngine"); - m_Log[LogTypes::COMMANDPROCESSOR] = new CDebugger_Log("CP", "CommandProc"); - m_Log[LogTypes::VIDEOINTERFACE] = new CDebugger_Log("VI", "VideoInt"); - m_Log[LogTypes::SERIALINTERFACE] = new CDebugger_Log("SI", "SerialInt"); - m_Log[LogTypes::PERIPHERALINTERFACE]= new CDebugger_Log("PI", "PeripheralInt"); - m_Log[LogTypes::MEMMAP] = new CDebugger_Log("MI", "MI & memmap"); - m_Log[LogTypes::STREAMINGINTERFACE] = new CDebugger_Log("Stream", "StreamingInt"); - m_Log[LogTypes::DSPINTERFACE] = new CDebugger_Log("DSP", "DSPInterface"); - m_Log[LogTypes::DVDINTERFACE] = new CDebugger_Log("DVD", "DVDInterface"); - m_Log[LogTypes::GPFIFO] = new CDebugger_Log("GP", "GPFifo"); - m_Log[LogTypes::EXPANSIONINTERFACE] = new CDebugger_Log("EXI", "ExpansionInt."); - m_Log[LogTypes::AUDIO_INTERFACE] = new CDebugger_Log("AI", "AudioInt."); - m_Log[LogTypes::GEKKO] = new CDebugger_Log("GEKKO", "IBM CPU"); - m_Log[LogTypes::HLE] = new CDebugger_Log("HLE", "HLE"); - m_Log[LogTypes::DSPHLE] = new CDebugger_Log("DSPHLE", "DSP HLE"); - m_Log[LogTypes::VIDEO] = new CDebugger_Log("Video", "Video Plugin"); - m_Log[LogTypes::AUDIO] = new CDebugger_Log("Audio", "Audio Plugin"); - m_Log[LogTypes::DYNA_REC] = new CDebugger_Log("DYNA", "Dynamic Recompiler"); - m_Log[LogTypes::CONSOLE] = new CDebugger_Log("CONSOLE", "Dolphin Console"); - m_Log[LogTypes::OSREPORT] = new CDebugger_Log("OSREPORT", "OSReport"); - m_Log[LogTypes::WII_IOB] = new CDebugger_Log("WII_IOB", "WII IO Bridge"); - m_Log[LogTypes::WII_IPC] = new CDebugger_Log("WII_IPC", "WII IPC"); - m_Log[LogTypes::WII_IPC_HLE] = new CDebugger_Log("WII_IPC_HLE", "WII IPC HLE"); - m_Log[LogTypes::WII_IPC_DVD] = new CDebugger_Log("WII_IPC_DVD", "WII IPC DVD"); - m_Log[LogTypes::WII_IPC_ES] = new CDebugger_Log("WII_IPC_ES", "WII IPC ES"); - m_Log[LogTypes::WII_IPC_FILEIO] = new CDebugger_Log("WII_IPC_FILEIO", "WII IPC FILEIO"); - m_Log[LogTypes::WII_IPC_NET] = new CDebugger_Log("WII_IPC_NET", "WII IPC NET"); - m_Log[LogTypes::WII_IPC_WIIMOTE] = new CDebugger_Log("WII_IPC_WIIMOTE", "WII IPC WIIMOTE"); + // create log files + for(int i = 0; i <= LogManager::VERBOSITY_LEVELS; i++) + { + m_Log[LogTypes::MASTER_LOG + i*100] = new CDebugger_Log("*", "Master Log", i); + m_Log[LogTypes::BOOT + i*100] = new CDebugger_Log("BOOT", "Boot", i); + m_Log[LogTypes::PIXELENGINE + i*100] = new CDebugger_Log("PE", "PixelEngine", i); + m_Log[LogTypes::COMMANDPROCESSOR + i*100] = new CDebugger_Log("CP", "CommandProc", i); + m_Log[LogTypes::VIDEOINTERFACE + i*100] = new CDebugger_Log("VI", "VideoInt", i); + m_Log[LogTypes::SERIALINTERFACE + i*100] = new CDebugger_Log("SI", "SerialInt", i); + m_Log[LogTypes::PERIPHERALINTERFACE + i*100]= new CDebugger_Log("PI", "PeripheralInt", i); + m_Log[LogTypes::MEMMAP + i*100] = new CDebugger_Log("MI", "MI & memmap", i); + m_Log[LogTypes::STREAMINGINTERFACE + i*100] = new CDebugger_Log("Stream", "StreamingInt", i); + m_Log[LogTypes::DSPINTERFACE + i*100] = new CDebugger_Log("DSP", "DSPInterface", i); + m_Log[LogTypes::DVDINTERFACE + i*100] = new CDebugger_Log("DVD", "DVDInterface", i); + m_Log[LogTypes::GPFIFO + i*100] = new CDebugger_Log("GP", "GPFifo", i); + m_Log[LogTypes::EXPANSIONINTERFACE + i*100] = new CDebugger_Log("EXI", "ExpansionInt", i); + m_Log[LogTypes::AUDIO_INTERFACE + i*100] = new CDebugger_Log("AI", "AudioInt", i); + m_Log[LogTypes::GEKKO + i*100] = new CDebugger_Log("GEKKO", "IBM CPU", i); + m_Log[LogTypes::HLE + i*100] = new CDebugger_Log("HLE", "HLE", i); + m_Log[LogTypes::DSPHLE + i*100] = new CDebugger_Log("DSPHLE", "DSP HLE", i); + m_Log[LogTypes::VIDEO + i*100] = new CDebugger_Log("Video", "Video Plugin", i); + m_Log[LogTypes::AUDIO + i*100] = new CDebugger_Log("Audio", "Audio Plugin", i); + m_Log[LogTypes::DYNA_REC + i*100] = new CDebugger_Log("DYNA", "Dynamic Recompiler", i); + m_Log[LogTypes::OSREPORT + i*100] = new CDebugger_Log("OSREPORT", "Dolphin Console", i); + m_Log[LogTypes::CONSOLE + i*100] = new CDebugger_Log("CONSOLE", "OSReport", i); + m_Log[LogTypes::WII_IOB + i*100] = new CDebugger_Log("WII_IOB", "WII IO Bridge", i); + m_Log[LogTypes::WII_IPC + i*100] = new CDebugger_Log("WII_IPC", "WII IPC", i); + m_Log[LogTypes::WII_IPC_HLE + i*100] = new CDebugger_Log("WII_IPC_HLE", "WII IPC HLE", i); + m_Log[LogTypes::WII_IPC_DVD + i*100] = new CDebugger_Log("WII_IPC_DVD", "WII IPC DVD", i); + m_Log[LogTypes::WII_IPC_ES + i*100] = new CDebugger_Log("WII_IPC_ES", "WII IPC ES", i); + m_Log[LogTypes::WII_IPC_FILEIO + i*100] = new CDebugger_Log("WII_IPC_FILEIO", "WII IPC FILEIO", i); + m_Log[LogTypes::WII_IPC_NET + i*100] = new CDebugger_Log("WII_IPC_NET", "WII IPC NET", i); + m_Log[LogTypes::WII_IPC_WIIMOTE + i*100] = new CDebugger_Log("WII_IPC_WIIMOTE", "WII IPC WIIMOTE", i); + m_nextMessages[i] = 0; // initiate to zero + } + + // create the files for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; i++) { - m_Log[i]->Init(); + for (int j = 0; j <= LogManager::VERBOSITY_LEVELS; j++) + { + m_Log[j*100 + i]->Init(); + } } m_bInitialized = true; } @@ -130,15 +143,21 @@ void LogManager::Init() void LogManager::Clear() { - for (int i = 0;i < MAX_MESSAGES;i++) + for (int v = 0; v <= LogManager::VERBOSITY_LEVELS; v++) { - strcpy(m_Messages[i].m_szMessage,""); - m_Messages[i].m_dwMsgLen = 0; - m_Messages[i].m_bInUse = false; + for (int i = 0; i < MAX_MESSAGES; i++) + { + strcpy(m_Messages[v][i].m_szMessage,""); + m_Messages[v][i].m_dwMsgLen = 0; + m_Messages[v][i].m_bInUse = false; + } + m_nextMessages[v] = 0; } - m_nextMessages = 0; } +// __________________________________________________________________________________________________ +// Shutdown +// void LogManager::Shutdown() { m_bInitialized = false; @@ -157,68 +176,117 @@ void LogManager::Shutdown() delete [] m_Messages; } -bool LogManager::IsLogEnabled(LogTypes::LOG_TYPE _type) -{ - if (_type >= LogTypes::NUMBER_OF_LOGS) - { - PanicAlert("Try to access unknown log (%i)", _type); - return false; - } - - if (m_Log[_type] == NULL || !m_Log[_type]->m_bEnable) - return false; - - return true; -} +// ========================================================================================== +// The function that finally writes the log. +// --------------- +u32 lastPC; +std::string lastSymbol; void LogManager::Log(LogTypes::LOG_TYPE _type, const char *_fmt, ...) { - if (m_Log[_type] == NULL || !m_Log[_type]->m_bEnable) + if (m_LogSettings == NULL) return; + // declarations + int v; // verbosity level + int type; // the log type, CONSOLE etc. + char cvv[20]; + std::string svv; + + // get the current verbosity level and type + sprintf(cvv, "%03i", (int)_type); + svv = cvv; + v = atoi(svv.substr(0, 1).c_str()); + type = atoi(svv.substr(1, 2).c_str()); + + // security checks + if (m_Log[_type] == NULL || !m_Log[_type]->m_bEnable || PC == 0 + || _type > (LogTypes::NUMBER_OF_LOGS + LogManager::VERBOSITY_LEVELS * 100) + || _type < 0) + return; + + // prepare message char Msg[512]; va_list ap; va_start(ap, _fmt); vsprintf(Msg, _fmt, ap); va_end(ap); - - SMessage& Message = m_Messages[m_nextMessages]; static u32 count = 0; + wxDateTime datetime = wxDateTime::UNow(); // get timestamp char* Msg2 = (char*)alloca(strlen(_fmt)+512); - int Index = 0; //Debugger::FindSymbol(PC); - const char *eol = "\n"; - if (Index > 0) - { - // const Debugger::Symbol& symbol = Debugger::GetSymbol(Index); - sprintf(Msg2, "%i: %x %s (%s, %08x ) : %s%s", - ++count, - PowerPC::ppcState.DebugCount, - m_Log[_type]->m_szShortName, - "", //symbol.GetName().c_str(), - PC, - Msg, eol); + // Here's the old symbol request + //Debugger::FindSymbol(PC); + // const Debugger::Symbol& symbol = Debugger::GetSymbol(Index); + //symbol.GetName().c_str(), + + // Warning: Getting the function name this often is very demanding on the CPU. + // I have limited it to the two lowest verbosity levels because of that. I've also + // added a simple caching function so that we don't search again if we get the same + // question again. + std::string symbol; + + if ((v == 0 || v == 1) && lastPC != PC && LogManager::m_LogSettings->bResolve) + { + symbol = g_symbolDB.GetDescription(PC); + lastSymbol = symbol; + lastPC = PC; + } + else if(lastPC == PC && LogManager::m_LogSettings->bResolve) + { + symbol = lastSymbol; } else { - sprintf(Msg2, "%i: %x %s ( %08x ) : %s%s", ++count, PowerPC::ppcState.DebugCount, m_Log[_type]->m_szShortName, PC, Msg, eol); + symbol = "---"; } - Message.Set(_type, Msg2); + int Index = 1; + const char *eol = "\n"; + if (Index > 0) + { + sprintf(Msg2, "%i %02i:%02i:%03i: %x %s (%s, %08x) : %s%s", + ++count, + datetime.GetMinute(), datetime.GetSecond(), datetime.GetMillisecond(), + PowerPC::ppcState.DebugCount, + m_Log[_type]->m_szShortName_, // (CONSOLE etc) + symbol.c_str(), PC, // current PC location (name, address) + Msg, eol); + } - if (m_Log[_type]->m_pFile && m_Log[_type]->m_bLogToFile) - fprintf(m_Log[_type]->m_pFile, "%s", Msg2); - if (m_Log[LogTypes::MASTER_LOG] && m_Log[LogTypes::MASTER_LOG]->m_pFile && m_Log[_type]->m_bShowInLog) - fprintf(m_Log[LogTypes::MASTER_LOG]->m_pFile, "%s", Msg2); + // ========================================================================================== + // Level 0 verbosity logs will be written to all verbosity levels. Given that logging is enabled + // for that level. Level 1 verbosity will only be written to level 1, 2, 3 and so on. + // --------------- + int id; + for (int i = LogManager::VERBOSITY_LEVELS; i >= v ; i--) + { + // prepare the right id + id = i*100 + type; - printf("%s", Msg2); + // write to memory + m_Messages[i][m_nextMessages[i]].Set((LogTypes::LOG_TYPE)id, Msg2); - m_nextMessages++; - if (m_nextMessages >= MAX_MESSAGES) - m_nextMessages = 0; - m_bDirty = true; + // ---------------------------------------------------------------------------------------- + // write to file + // --------------- + if (m_Log[id]->m_pFile && m_Log[id]->m_bLogToFile) + fprintf(m_Log[id]->m_pFile, "%s", Msg2); + if (m_Log[i*100 + LogTypes::MASTER_LOG] && m_Log[i*100 + LogTypes::MASTER_LOG]->m_pFile + && LogManager::m_LogSettings->bWriteMaster) + fprintf(m_Log[i*100 + LogTypes::MASTER_LOG]->m_pFile, "%s", Msg2); + + printf("%s", Msg2); // write to console screen + + // this limits the memory space used for the memory logs to MAX_MESSAGES rows + m_nextMessages[i]++; + if (m_nextMessages[i] >= MAX_MESSAGES) + m_nextMessages[i] = 0; + // --------------- + } + m_bDirty = true; // tell LogWindow that the log has been updated } bool IsLoggingActivated() @@ -228,4 +296,4 @@ bool IsLoggingActivated() #else return false; #endif -} +} \ No newline at end of file diff --git a/Source/Core/Core/Src/LogManager.h b/Source/Core/Core/Src/LogManager.h index 9d117dfeab..1fbe2bdc57 100644 --- a/Source/Core/Core/Src/LogManager.h +++ b/Source/Core/Core/Src/LogManager.h @@ -30,6 +30,7 @@ struct CDebugger_Log { char m_szName[128]; char m_szShortName[32]; + char m_szShortName_[32]; // save the unadjusted originals here char m_szFilename[256]; bool m_bLogToFile; bool m_bShowInLog; @@ -40,12 +41,26 @@ struct CDebugger_Log void Shutdown(); // constructor - CDebugger_Log(const char* _szShortName, const char* _szName); + CDebugger_Log(const char* _szShortName, const char* _szName, int a); // destructor ~CDebugger_Log(); }; +// make a variable that can be accessed from both LogManager.cpp and LogWindow.cpp +struct CDebugger_LogSettings +{ + int m_iVerbosity; // verbosity level 0 - 2 + bool bResolve; + bool bWriteMaster; + + // constructor + CDebugger_LogSettings(); + + // destructor + ~CDebugger_LogSettings(); +}; + class LogManager { #define MAX_MESSAGES 8000 // the old value was to large @@ -80,26 +95,30 @@ public: m_szMessage[m_dwMsgLen] = 0; m_type = _type; - m_bInUse = true; + m_bInUse = true; // turn on this message line } // static void Log(LogTypes::LOG_TYPE _type, const char *_fmt, ...); }; private: + enum LOG_SETTINGS + { + VERBOSITY_LEVELS = 3 + }; + friend class CDebugger_LogWindow; friend class CLogWindow; - static SMessage *m_Messages; - static int m_nextMessages; + static SMessage (*m_Messages)[MAX_MESSAGES]; + static int m_nextMessages[VERBOSITY_LEVELS + 1]; static int m_activeLog; static bool m_bDirty; static bool m_bInitialized; - static CDebugger_Log* m_Log[LogTypes::NUMBER_OF_LOGS]; + static CDebugger_LogSettings* m_LogSettings; + static CDebugger_Log* m_Log[LogTypes::NUMBER_OF_LOGS + (VERBOSITY_LEVELS * 100)]; // make 326 of them public: static void Init(); static void Clear(void); static void Shutdown(); - - static bool IsLogEnabled(LogTypes::LOG_TYPE _type); static void Log(LogTypes::LOG_TYPE _type, const char *_fmt, ...); }; diff --git a/Source/Core/Core/Src/PowerPC/PowerPC.cpp b/Source/Core/Core/Src/PowerPC/PowerPC.cpp index 62a7eae02b..cc4e7c7da7 100644 --- a/Source/Core/Core/Src/PowerPC/PowerPC.cpp +++ b/Source/Core/Core/Src/PowerPC/PowerPC.cpp @@ -201,7 +201,7 @@ void CheckExceptions() SRR1 = MSR & 0x0780FF77; NPC = 0x80000800; - LOG(GEKKO, "EXCEPTION_FPU_UNAVAILABLE"); + LOGV(GEKKO, 1, "EXCEPTION_FPU_UNAVAILABLE"); ppcState.Exceptions &= ~EXCEPTION_FPU_UNAVAILABLE; SRR1 |= 0x02; //recoverable } @@ -211,7 +211,7 @@ void CheckExceptions() SRR1 = MSR & 0x0780FF77; NPC = 0x80000C00; - LOG(GEKKO, "EXCEPTION_SYSCALL (PC=%08x)",PC); + LOGV(GEKKO, 1, "EXCEPTION_SYSCALL (PC=%08x)",PC); ppcState.Exceptions &= ~EXCEPTION_SYSCALL; SRR1 |= 0x02; //recoverable } @@ -221,7 +221,7 @@ void CheckExceptions() SRR1 = MSR & 0x0780FF77; NPC = 0x80000300; - LOG(GEKKO, "EXCEPTION_DSI"); + LOGV(GEKKO, 1, "EXCEPTION_DSI"); ppcState.Exceptions &= ~EXCEPTION_DSI; //SRR1 |= 0x02; //make recoverable ? } @@ -259,7 +259,7 @@ void CheckExceptions() NPC = 0x80000500; SRR1 = (MSR & 0x0780FF77); - LOG(GEKKO, "EXCEPTION_EXTERNAL_INT"); + LOGV(GEKKO, 1, "EXCEPTION_EXTERNAL_INT"); SRR1 |= 0x02; //set it to recoverable _dbg_assert_msg_(GEKKO, (SRR1 & 0x02) != 0, "GEKKO", "EXTERNAL_INT unrecoverable???"); // unrecoverable exception !?! @@ -272,7 +272,7 @@ void CheckExceptions() ppcState.Exceptions &= ~EXCEPTION_DECREMENTER; - LOG(GEKKO, "EXCEPTION_DECREMENTER"); + LOGV(GEKKO, 1, "EXCEPTION_DECREMENTER"); SRR1 |= 0x02; //make recoverable } else diff --git a/Source/Core/Core/Src/PowerPC/SignatureDB.cpp b/Source/Core/Core/Src/PowerPC/SignatureDB.cpp index 5c955f8632..275caa378a 100644 --- a/Source/Core/Core/Src/PowerPC/SignatureDB.cpp +++ b/Source/Core/Core/Src/PowerPC/SignatureDB.cpp @@ -123,7 +123,7 @@ void SignatureDB::Apply(SymbolDB *symbol_db) if (iter->second.size == (unsigned int)function->size) { function->name = iter->second.name; - LOG(HLE, "Found %s at %08x (size: %08x)!", iter->second.name.c_str(), function->address, function->size); + LOGV(HLE, 1, "Found %s at %08x (size: %08x)!", iter->second.name.c_str(), function->address, function->size); } else { diff --git a/Source/Core/DebuggerWX/Src/Debugger.h b/Source/Core/DebuggerWX/Src/Debugger.h index 62b10b3556..dcc71e40af 100644 --- a/Source/Core/DebuggerWX/Src/Debugger.h +++ b/Source/Core/DebuggerWX/Src/Debugger.h @@ -24,7 +24,9 @@ enum IDM_UPDATELOG, IDM_CLEARLOG, IDM_LOGCHECKS, + IDM_OPTIONS, IDM_ENABLEALL, + IDM_RADIO0, IDM_SUBMITCMD = 300, }; diff --git a/Source/Core/DebuggerWX/Src/LogWindow.cpp b/Source/Core/DebuggerWX/Src/LogWindow.cpp index 7e23dbf19b..9812c21240 100644 --- a/Source/Core/DebuggerWX/Src/LogWindow.cpp +++ b/Source/Core/DebuggerWX/Src/LogWindow.cpp @@ -23,16 +23,22 @@ #include #include +#include "Core.h" // for Core::GetState() #include "LogWindow.h" #include "Console.h" #include "IniFile.h" +// declare this now to be able to use it in Load() +CDebugger_LogSettings* LogManager::m_LogSettings; + BEGIN_EVENT_TABLE(CLogWindow, wxDialog) EVT_BUTTON(IDM_SUBMITCMD, CLogWindow::OnSubmit) EVT_BUTTON(IDM_UPDATELOG, CLogWindow::OnUpdateLog) EVT_BUTTON(IDM_CLEARLOG, CLogWindow::OnClear) EVT_BUTTON(IDM_ENABLEALL, CLogWindow::OnEnableAll) + EVT_CHECKLISTBOX(IDM_OPTIONS, CLogWindow::OnOptionsCheck) EVT_CHECKLISTBOX(IDM_LOGCHECKS, CLogWindow::OnLogCheck) + EVT_RADIOBOX(IDM_RADIO0, CLogWindow::OnRadioChange) END_EVENT_TABLE() @@ -40,19 +46,53 @@ CLogWindow::CLogWindow(wxWindow* parent) : wxDialog(parent, wxID_ANY, _T("Log/Console"), wxPoint(100, 700), wxSize(800, 270), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) { - wxBoxSizer* sizerTop = new wxBoxSizer(wxHORIZONTAL), - * sizerUber = new wxBoxSizer(wxHORIZONTAL), - * sizerBig = new wxBoxSizer(wxVERTICAL), - * sizerBottom = new wxBoxSizer(wxHORIZONTAL); + wxBoxSizer* sizerTop = new wxBoxSizer(wxHORIZONTAL), // buttons + * sizerUber = new wxBoxSizer(wxHORIZONTAL), // whole plane + * sizerBig = new wxBoxSizer(wxVERTICAL), // RIGHT sizer + * sizerBottom = new wxBoxSizer(wxHORIZONTAL), // submit row + * sizerLeft = new wxBoxSizer(wxVERTICAL); // LEFT sizer - m_log = new wxTextCtrl(this, IDM_LOG, _T(""), wxDefaultPosition, wxSize(600, 120), wxTE_MULTILINE | wxTE_READONLY | wxTE_DONTWRAP); + // left checkboxes and radio boxes ----------------------------------- + int m_radioBoxNChoices[1]; + wxString m_radioBoxChoices0[] = { wxT("0"), wxT("1"), wxT("2"), wxT("3") }; + m_radioBoxNChoices[0] = sizeof( m_radioBoxChoices0 ) / sizeof( wxString ); + m_RadioBox[0] = new wxRadioBox( this, IDM_RADIO0, wxT("Verbosity"), + wxDefaultPosition, wxDefaultSize, m_radioBoxNChoices[0], m_radioBoxChoices0, 1, wxRA_SPECIFY_ROWS); + + wxStaticBoxSizer * m_optionsSizer = new wxStaticBoxSizer(wxVERTICAL, this, wxT("Settings")); + m_options = new wxCheckListBox(this, IDM_OPTIONS, wxDefaultPosition, wxDefaultSize, + 0, NULL, wxNO_BORDER); + m_options->Append(wxT("Resolve symbols")); + m_options->Append(wxT("Write master")); + m_optionsSizer->Add(m_options, 0, 0, 0); + + // I could not find any transparency setting and it would not automatically space correctly + m_options->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)); + m_options->SetMinSize(wxSize(m_options->GetSize().GetWidth() - 40, + m_options->GetCount() * 15)); + #ifdef _WIN32 + for (int i = 0; i < m_options->GetCount(); ++i) + m_options->GetItem(i)->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)); + #endif + + m_checks = new wxCheckListBox(this, IDM_LOGCHECKS, wxDefaultPosition, wxSize(120, 280)); + + // finally add it to the sizer + sizerLeft->Add(m_RadioBox[0], 0, wxGROW); + sizerLeft->Add(m_optionsSizer, 0, wxGROW); + sizerLeft->Add(m_checks, 1, wxGROW); + + + // right windows ----------------------------------------------------- + m_log = new wxTextCtrl(this, IDM_LOG, _T(""), wxDefaultPosition, wxSize(600, 120), + wxTE_MULTILINE | wxTE_READONLY | wxTE_DONTWRAP); m_cmdline = new wxTextCtrl(this, wxID_ANY, _T(""), wxDefaultPosition); wxButton* btn = new wxButton(this, IDM_SUBMITCMD, _T("Submit")); sizerTop->Add(new wxButton(this, IDM_UPDATELOG, _T("Update"))); sizerTop->Add(new wxButton(this, IDM_CLEARLOG, _T("Clear"))); sizerTop->Add(new wxButton(this, IDM_ENABLEALL, _T("Enable all"))); - m_checks = new wxCheckListBox(this, IDM_LOGCHECKS, wxDefaultPosition, wxSize(120, 280)); + sizerBottom->Add(m_cmdline, 8, wxGROW | wxRIGHT, 5); sizerBottom->Add(btn, 1, wxGROW, 0); @@ -60,12 +100,15 @@ CLogWindow::CLogWindow(wxWindow* parent) sizerBig->Add(m_log, 1, wxGROW | wxSHRINK); sizerBig->Add(sizerBottom, 0, wxGROW); - sizerUber->Add(m_checks, 0, wxGROW); + sizerUber->Add(sizerLeft, 0, wxGROW); sizerUber->Add(sizerBig, 1, wxGROW); SetSizer(sizerUber); SetAffirmativeId(IDM_SUBMITCMD); + // declare this now to be able to use it in Load() + LogManager::m_LogSettings = new CDebugger_LogSettings; + //sizerTop->SetSizeHints(this); //sizerTop->Fit(this); UpdateChecks(); @@ -91,6 +134,18 @@ void CLogWindow::Load(IniFile& _IniFile) _IniFile.Get("LogWindow", "w", &w, GetSize().GetWidth()); _IniFile.Get("LogWindow", "h", &h, GetSize().GetHeight()); SetSize(x, y, w, h); + + // load verbosity setting + int v; + _IniFile.Get("LogWindow", "Verbosity", &v, m_RadioBox[0]->GetSelection()); + m_RadioBox[0]->SetSelection(v); + LogManager::m_LogSettings->m_iVerbosity = v; + + // load options + _IniFile.Get("LogWindow", "ResolveSymbols", &LogManager::m_LogSettings->bResolve, false); + _IniFile.Get("LogWindow", "WriteMaster", &LogManager::m_LogSettings->bWriteMaster, false); + m_options->Check(0, LogManager::m_LogSettings->bResolve); + m_options->Check(1, LogManager::m_LogSettings->bWriteMaster); } void CLogWindow::OnSubmit(wxCommandEvent& event) @@ -103,56 +158,41 @@ void CLogWindow::OnSubmit(wxCommandEvent& event) void CLogWindow::OnClear(wxCommandEvent& event) { - LogManager::Clear(); - LOG(MASTER_LOG, "(log cleared)."); - NotifyUpdate(); + if (Core::GetState() != Core::CORE_UNINITIALIZED) // avoid crash + { + LogManager::Clear(); + LOG(MASTER_LOG, "(log cleared)."); + NotifyUpdate(); + } } + +// ---------------------------------------------------------------------------------------- +// Enable or disable all boxes for the current verbosity level and save the changes. +// ------------- void CLogWindow::OnEnableAll(wxCommandEvent& event) { if (!LogManager::m_Log[0]) return; static bool enable = true; + int v = LogManager::m_LogSettings->m_iVerbosity; IniFile ini; - ini.Load("Dolphin.ini"); + ini.Load("Debugger.ini"); for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; i++) { m_checks->Check(i, enable); - LogManager::m_Log[i]->m_bEnable = enable; - LogManager::m_Log[i]->m_bShowInLog = enable; - ini.Set("LogManager", LogManager::m_Log[i]->m_szShortName, enable); + LogManager::m_Log[i + v*100]->m_bEnable = enable; + LogManager::m_Log[i + v*100]->m_bShowInLog = enable; + ini.Set("LogManager", LogManager::m_Log[i + v*100]->m_szShortName, enable); } - ini.Save("Dolphin.ini"); + ini.Save("Debugger.ini"); enable = !enable; } -void CLogWindow::OnLogCheck(wxCommandEvent& event) -{ - if (!LogManager::m_bInitialized) - { - return; - } - - IniFile ini; - ini.Load("Dolphin.ini"); - - for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; i++) - { - bool Enabled = m_checks->IsChecked(i); - LogManager::m_Log[i]->m_bEnable = Enabled; - LogManager::m_Log[i]->m_bShowInLog = Enabled; - - ini.Set("LogManager", LogManager::m_Log[i]->m_szShortName, Enabled); - } - - ini.Save("Dolphin.ini"); - - m_bCheckDirty = true; - UpdateLog(); -} - - +// ---------------------------------------------------------------------------------------- +// Append checkboxes and update checked groups. +// ------------- void CLogWindow::UpdateChecks() { if (!LogManager::m_bInitialized) @@ -160,9 +200,11 @@ void CLogWindow::UpdateChecks() return; } + // This is only run once to append checkboxes to the wxCheckListBox. if (m_checks->GetCount() == 0) { - // [F|RES] hide the window while we fill it... wxwidgets gets trouble if you don't do it (at least the win version) + // [F|RES] hide the window while we fill it... wxwidgets gets trouble if you don't do it + // (at least the win version) m_checks->Show(false); for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; i++) @@ -173,28 +215,114 @@ void CLogWindow::UpdateChecks() m_checks->Show(true); } + // ---------------------------------------------------------------------------------------- + // Load the correct values and enable/disable the right groups + // ------------- + int v = LogManager::m_LogSettings->m_iVerbosity; IniFile ini; - ini.Load("Dolphin.ini"); + ini.Load("Debugger.ini"); for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; i++) { - bool Enabled = false; - ini.Get("LogManager", LogManager::m_Log[i]->m_szShortName, &Enabled, false); - - m_checks->Check(i, Enabled); - - LogManager::m_Log[i]->m_bEnable = Enabled; - LogManager::m_Log[i]->m_bShowInLog = Enabled; + for (int j = 0; j <= LogManager::VERBOSITY_LEVELS; j++) + { + bool Enabled = false; + ini.Get("LogManager", LogManager::m_Log[i + j*100]->m_szShortName, &Enabled, false); + LogManager::m_Log[i + j*100]->m_bEnable = Enabled; + LogManager::m_Log[i + j*100]->m_bShowInLog = Enabled; + if(j == v) m_checks->Check(i, Enabled); + } } m_bCheckDirty = true; - UpdateLog(); +} + + +// ---------------------------------------------------------------------------------------- +// When an option is changed +// --------------- +void CLogWindow::OnOptionsCheck(wxCommandEvent& event) +{ + IniFile ini; + ini.Load("Debugger.ini"); + LogManager::m_LogSettings->bResolve = m_options->IsChecked(0); + LogManager::m_LogSettings->bWriteMaster = m_options->IsChecked(1); + ini.Set("LogWindow", "ResolveSymbols", m_options->IsChecked(0)); + ini.Set("LogWindow", "WriteMaster", m_options->IsChecked(1)); + ini.Save("Debugger.ini"); + if (Core::GetState() != Core::CORE_UNINITIALIZED) UpdateLog(); +} + + +// ---------------------------------------------------------------------------------------- +// When a checkbox is changed +// --------------- +void CLogWindow::OnLogCheck(wxCommandEvent& event) +{ + if (!LogManager::m_bInitialized) + { + return; + } + + IniFile ini; + ini.Load("Debugger.ini"); + int v = LogManager::m_LogSettings->m_iVerbosity; + + for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; i++) + { + // update groups to enabled or disabled + bool Enabled = m_checks->IsChecked(i); + LogManager::m_Log[i + 100*v]->m_bEnable = Enabled; + LogManager::m_Log[i + 100*v]->m_bShowInLog = Enabled; + + ini.Set("LogManager", LogManager::m_Log[i + 100*v]->m_szShortName, Enabled); + } + + ini.Save("Debugger.ini"); + + m_bCheckDirty = true; + if (Core::GetState() != Core::CORE_UNINITIALIZED) UpdateLog(); +} + + +// ---------------------------------------------------------------------------------------- +// When the verbosity level is changed +// ------------- +void CLogWindow::OnRadioChange(wxCommandEvent& event) +{ + // get selection + int v = m_RadioBox[0]->GetSelection(); + + // save it + LogManager::m_LogSettings->m_iVerbosity = v; + IniFile ini; + ini.Load("Debugger.ini"); + ini.Set("LogWindow", "Verbosity", v); + ini.Save("Debugger.ini"); + + // This check is because we allow this to be changed before a game has been loaded so + // that the boxes do not exist yet + if (Core::GetState() != Core::CORE_UNINITIALIZED) + { + for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; i++) + { + // update groups to enabled or disabled + bool Enabled; + ini.Get("LogManager", LogManager::m_Log[i + 100*v]->m_szShortName, &Enabled, false); + LogManager::m_Log[i + 100*v]->m_bEnable = Enabled; + LogManager::m_Log[i + 100*v]->m_bShowInLog = Enabled; + m_checks->Check(i, Enabled); + } + + m_bCheckDirty = true; + UpdateLog(); + } } void CLogWindow::OnUpdateLog(wxCommandEvent& event) { - NotifyUpdate(); + if (Core::GetState() != Core::CORE_UNINITIALIZED) UpdateLog(); } @@ -208,32 +336,40 @@ void CLogWindow::NotifyUpdate() void CLogWindow::UpdateLog() { static int last = -1; - int i = LogManager::m_nextMessages; + int v = LogManager::m_LogSettings->m_iVerbosity; + int i = LogManager::m_nextMessages[v]; + // check if the the log has been updated (ie if it's dirty) if ((last == i) && !m_bCheckDirty) { return; } - m_bCheckDirty = false; last = i; - //bash together a log buffer really fast (no slow strcpy here, just memcpys) + + // ---------------------------------------------------------------------------------------- + // Prepare a selection of the memory log to show to screen + // --------------- int count = 0; char* p = m_logBuffer; + // go through all rows while (count < MAX_MESSAGES) { count++; - const LogManager::SMessage& message = LogManager::m_Messages[i]; + const LogManager::SMessage& message = LogManager::m_Messages[v][i]; - if (message.m_bInUse) + if (message.m_bInUse) // check if the line has a value { int len = message.m_dwMsgLen; + // this is what we use, I'm not sure why we have this option if (LogManager::m_activeLog == LogTypes::MASTER_LOG) { + // only show checkboxed logs if (LogManager::m_Log[message.m_type]->m_bShowInLog) { + // memcpy is faster than strcpy memcpy(p, message.m_szMessage, len); p += len; } @@ -255,10 +391,12 @@ void CLogWindow::UpdateLog() i = 0; } } + // --------------- *p = 0; //end the string m_log->SetValue(wxString::FromAscii(m_logBuffer)); m_log->SetInsertionPoint(p - m_logBuffer - 1); + m_log->ShowPosition( m_log->GetLastPosition()); // show last line } diff --git a/Source/Core/DebuggerWX/Src/LogWindow.h b/Source/Core/DebuggerWX/Src/LogWindow.h index 9e43624365..cd1ead4719 100644 --- a/Source/Core/DebuggerWX/Src/LogWindow.h +++ b/Source/Core/DebuggerWX/Src/LogWindow.h @@ -39,12 +39,16 @@ class CLogWindow char m_logBuffer[LogBufferSize]; wxTextCtrl* m_log, * m_cmdline; wxCheckListBox* m_checks; + wxCheckListBox* m_options; + wxRadioBox *m_RadioBox[1]; // radio boxes bool m_bCheckDirty; DECLARE_EVENT_TABLE() void OnSubmit(wxCommandEvent& event); void OnUpdateLog(wxCommandEvent& event); + void OnOptionsCheck(wxCommandEvent& event); void OnLogCheck(wxCommandEvent& event); + void OnRadioChange(wxCommandEvent& event); // verbosity buttons void OnClear(wxCommandEvent& event); void OnEnableAll(wxCommandEvent& event); diff --git a/Source/Dolphin.sln b/Source/Dolphin.sln index 612d104b53..d1bddba3f2 100644 --- a/Source/Dolphin.sln +++ b/Source/Dolphin.sln @@ -2,6 +2,8 @@ Microsoft Visual Studio Solution File, Format Version 10.00 # Visual Studio 2008 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Core", "Core\Core\Core.vcproj", "{F0B874CB-4476-4199-9315-8343D05AE684}" ProjectSection(ProjectDependencies) = postProject + {48AD7E0A-25B1-4974-A1E3-03F8C438D34F} = {48AD7E0A-25B1-4974-A1E3-03F8C438D34F} + {0318BA30-EF48-441A-9E10-DC85EFAE39F0} = {0318BA30-EF48-441A-9E10-DC85EFAE39F0} {29C2ABC1-ADA5-42CD-A5FC-96022D52A510} = {29C2ABC1-ADA5-42CD-A5FC-96022D52A510} {C573CAF7-EE6A-458E-8049-16C0BF34C2E9} = {C573CAF7-EE6A-458E-8049-16C0BF34C2E9} {B7F1A9FB-BEA8-416E-9460-AE35A6A5165C} = {B7F1A9FB-BEA8-416E-9460-AE35A6A5165C}