diff --git a/Source/Core/Common/CMakeLists.txt b/Source/Core/Common/CMakeLists.txt index 21f894cd7a62..4614c7d266e5 100644 --- a/Source/Core/Common/CMakeLists.txt +++ b/Source/Core/Common/CMakeLists.txt @@ -1,6 +1,7 @@ set(SRCS BreakPoints.cpp CDUtils.cpp ColorUtil.cpp + ConsoleListener.cpp FileSearch.cpp FileUtil.cpp Hash.cpp diff --git a/Source/Core/Common/Common.vcxproj b/Source/Core/Common/Common.vcxproj index 1cd34547bde1..87865d51e2d7 100644 --- a/Source/Core/Common/Common.vcxproj +++ b/Source/Core/Common/Common.vcxproj @@ -1,4 +1,4 @@ - + @@ -54,6 +54,7 @@ + @@ -92,6 +93,7 @@ + @@ -137,4 +139,4 @@ - \ No newline at end of file + diff --git a/Source/Core/Common/Common.vcxproj.filters b/Source/Core/Common/Common.vcxproj.filters index cb9e28436e0b..4af869c07010 100644 --- a/Source/Core/Common/Common.vcxproj.filters +++ b/Source/Core/Common/Common.vcxproj.filters @@ -1,4 +1,4 @@ - + @@ -52,6 +52,9 @@ Crypto + + Logging + Logging @@ -94,6 +97,9 @@ Crypto + + Logging + Logging @@ -102,4 +108,4 @@ - \ No newline at end of file + diff --git a/Source/Core/Common/ConsoleListener.cpp b/Source/Core/Common/ConsoleListener.cpp new file mode 100644 index 000000000000..5c4fbfd940d6 --- /dev/null +++ b/Source/Core/Common/ConsoleListener.cpp @@ -0,0 +1,335 @@ +// Copyright 2013 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include // min +#include +#include +#include +#include // System: To be able to add strings with "+" +#ifdef _WIN32 +#include +#include +#endif + +#include "Common/ConsoleListener.h" +#include "Common/StringUtil.h" + +ConsoleListener::ConsoleListener() +{ +#ifdef _WIN32 + hConsole = NULL; + bUseColor = true; +#else + bUseColor = isatty(fileno(stdout)); +#endif +} + +ConsoleListener::~ConsoleListener() +{ + Close(); +} + +// 100, 100, "Dolphin Log Console" +// Open console window - width and height is the size of console window +// Name is the window title +void ConsoleListener::Open(bool Hidden, int Width, int Height, const char *Title) +{ +#ifdef _WIN32 + if (!GetConsoleWindow()) + { + // Open the console window and create the window handle for GetStdHandle() + AllocConsole(); + // Hide + if (Hidden) ShowWindow(GetConsoleWindow(), SW_HIDE); + // Save the window handle that AllocConsole() created + hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + // Set the console window title + SetConsoleTitle(UTF8ToTStr(Title).c_str()); + // Set letter space + LetterSpace(80, 4000); + //MoveWindow(GetConsoleWindow(), 200,200, 800,800, true); + } + else + { + hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + } +#endif +} + +void ConsoleListener::UpdateHandle() +{ +#ifdef _WIN32 + hConsole = GetStdHandle(STD_OUTPUT_HANDLE); +#endif +} + +// Close the console window and close the eventual file handle +void ConsoleListener::Close() +{ +#ifdef _WIN32 + if (hConsole == NULL) + return; + FreeConsole(); + hConsole = NULL; +#else + fflush(NULL); +#endif +} + +bool ConsoleListener::IsOpen() +{ +#ifdef _WIN32 + return (hConsole != NULL); +#else + return true; +#endif +} + +/* + LetterSpace: SetConsoleScreenBufferSize and SetConsoleWindowInfo are + dependent on each other, that's the reason for the additional checks. +*/ +void ConsoleListener::BufferWidthHeight(int BufferWidth, int BufferHeight, int ScreenWidth, int ScreenHeight, bool BufferFirst) +{ +#ifdef _WIN32 + BOOL SB, SW; + if (BufferFirst) + { + // Change screen buffer size + COORD Co = {BufferWidth, BufferHeight}; + SB = SetConsoleScreenBufferSize(hConsole, Co); + // Change the screen buffer window size + SMALL_RECT coo = {0,0,ScreenWidth, ScreenHeight}; // top, left, right, bottom + SW = SetConsoleWindowInfo(hConsole, TRUE, &coo); + } + else + { + // Change the screen buffer window size + SMALL_RECT coo = {0,0, ScreenWidth, ScreenHeight}; // top, left, right, bottom + SW = SetConsoleWindowInfo(hConsole, TRUE, &coo); + // Change screen buffer size + COORD Co = {BufferWidth, BufferHeight}; + SB = SetConsoleScreenBufferSize(hConsole, Co); + } +#endif +} +void ConsoleListener::LetterSpace(int Width, int Height) +{ +#ifdef _WIN32 + // Get console info + CONSOLE_SCREEN_BUFFER_INFO ConInfo; + GetConsoleScreenBufferInfo(hConsole, &ConInfo); + + // + int OldBufferWidth = ConInfo.dwSize.X; + int OldBufferHeight = ConInfo.dwSize.Y; + int OldScreenWidth = (ConInfo.srWindow.Right - ConInfo.srWindow.Left); + int OldScreenHeight = (ConInfo.srWindow.Bottom - ConInfo.srWindow.Top); + // + int NewBufferWidth = Width; + int NewBufferHeight = Height; + int NewScreenWidth = NewBufferWidth - 1; + int NewScreenHeight = OldScreenHeight; + + // Width + BufferWidthHeight(NewBufferWidth, OldBufferHeight, NewScreenWidth, OldScreenHeight, (NewBufferWidth > OldScreenWidth-1)); + // Height + BufferWidthHeight(NewBufferWidth, NewBufferHeight, NewScreenWidth, NewScreenHeight, (NewBufferHeight > OldScreenHeight-1)); + + // Resize the window too + //MoveWindow(GetConsoleWindow(), 200,200, (Width*8 + 50),(NewScreenHeight*12 + 200), true); +#endif +} +#ifdef _WIN32 +COORD ConsoleListener::GetCoordinates(int BytesRead, int BufferWidth) +{ + COORD Ret = {0, 0}; + // Full rows + int Step = (int)floor((float)BytesRead / (float)BufferWidth); + Ret.Y += Step; + // Partial row + Ret.X = BytesRead - (BufferWidth * Step); + return Ret; +} +#endif +void ConsoleListener::PixelSpace(int Left, int Top, int Width, int Height, bool Resize) +{ +#ifdef _WIN32 + // Check size + if (Width < 8 || Height < 12) return; + + bool DBef = true; + bool DAft = true; + std::string SLog = ""; + + const HWND hWnd = GetConsoleWindow(); + const HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + + // Get console info + CONSOLE_SCREEN_BUFFER_INFO ConInfo; + GetConsoleScreenBufferInfo(hConsole, &ConInfo); + DWORD BufferSize = ConInfo.dwSize.X * ConInfo.dwSize.Y; + + // --------------------------------------------------------------------- + // Save the current text + // ------------------------ + DWORD cCharsRead = 0; + COORD coordScreen = { 0, 0 }; + + static const int MAX_BYTES = 1024 * 16; + + std::vector> Str; + std::vector> Attr; + + // ReadConsoleOutputAttribute seems to have a limit at this level + static const int ReadBufferSize = MAX_BYTES - 32; + + DWORD cAttrRead = ReadBufferSize; + DWORD BytesRead = 0; + while (BytesRead < BufferSize) + { + Str.resize(Str.size() + 1); + if (!ReadConsoleOutputCharacter(hConsole, Str.back().data(), ReadBufferSize, coordScreen, &cCharsRead)) + SLog += StringFromFormat("WriteConsoleOutputCharacter error"); + + Attr.resize(Attr.size() + 1); + if (!ReadConsoleOutputAttribute(hConsole, Attr.back().data(), ReadBufferSize, coordScreen, &cAttrRead)) + SLog += StringFromFormat("WriteConsoleOutputAttribute error"); + + // Break on error + if (cAttrRead == 0) break; + BytesRead += cAttrRead; + coordScreen = GetCoordinates(BytesRead, ConInfo.dwSize.X); + } + // Letter space + int LWidth = (int)(floor((float)Width / 8.0f) - 1.0f); + int LHeight = (int)(floor((float)Height / 12.0f) - 1.0f); + int LBufWidth = LWidth + 1; + int LBufHeight = (int)floor((float)BufferSize / (float)LBufWidth); + // Change screen buffer size + LetterSpace(LBufWidth, LBufHeight); + + + ClearScreen(true); + coordScreen.Y = 0; + coordScreen.X = 0; + DWORD cCharsWritten = 0; + + int BytesWritten = 0; + DWORD cAttrWritten = 0; + for (size_t i = 0; i < Attr.size(); i++) + { + if (!WriteConsoleOutputCharacter(hConsole, Str[i].data(), ReadBufferSize, coordScreen, &cCharsWritten)) + SLog += StringFromFormat("WriteConsoleOutputCharacter error"); + if (!WriteConsoleOutputAttribute(hConsole, Attr[i].data(), ReadBufferSize, coordScreen, &cAttrWritten)) + SLog += StringFromFormat("WriteConsoleOutputAttribute error"); + + BytesWritten += cAttrWritten; + coordScreen = GetCoordinates(BytesWritten, LBufWidth); + } + + const int OldCursor = ConInfo.dwCursorPosition.Y * ConInfo.dwSize.X + ConInfo.dwCursorPosition.X; + COORD Coo = GetCoordinates(OldCursor, LBufWidth); + SetConsoleCursorPosition(hConsole, Coo); + + if (SLog.length() > 0) Log(LogTypes::LNOTICE, SLog.c_str()); + + // Resize the window too + if (Resize) MoveWindow(GetConsoleWindow(), Left,Top, (Width + 100),Height, true); +#endif +} + +void ConsoleListener::Log(LogTypes::LOG_LEVELS Level, const char *Text) +{ +#if defined(_WIN32) + /* + const int MAX_BYTES = 1024*10; + char Str[MAX_BYTES]; + va_list ArgPtr; + int Cnt; + va_start(ArgPtr, Text); + Cnt = vsnprintf(Str, MAX_BYTES, Text, ArgPtr); + va_end(ArgPtr); + */ + DWORD cCharsWritten; + WORD Color; + + switch (Level) + { + case NOTICE_LEVEL: // light green + Color = FOREGROUND_GREEN | FOREGROUND_INTENSITY; + break; + case ERROR_LEVEL: // light red + Color = FOREGROUND_RED | FOREGROUND_INTENSITY; + break; + case WARNING_LEVEL: // light yellow + Color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY; + break; + case INFO_LEVEL: // cyan + Color = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY; + break; + case DEBUG_LEVEL: // gray + Color = FOREGROUND_INTENSITY; + break; + default: // off-white + Color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; + break; + } + if (strlen(Text) > 10) + { + // First 10 chars white + SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY); + WriteConsole(hConsole, Text, 10, &cCharsWritten, NULL); + Text += 10; + } + SetConsoleTextAttribute(hConsole, Color); + WriteConsole(hConsole, Text, (DWORD)strlen(Text), &cCharsWritten, NULL); +#else + char ColorAttr[16] = ""; + char ResetAttr[16] = ""; + + if (bUseColor) + { + strcpy(ResetAttr, "\033[0m"); + switch (Level) + { + case NOTICE_LEVEL: // light green + strcpy(ColorAttr, "\033[92m"); + break; + case ERROR_LEVEL: // light red + strcpy(ColorAttr, "\033[91m"); + break; + case WARNING_LEVEL: // light yellow + strcpy(ColorAttr, "\033[93m"); + break; + default: + break; + } + } + fprintf(stderr, "%s%s%s", ColorAttr, Text, ResetAttr); +#endif +} +// Clear console screen +void ConsoleListener::ClearScreen(bool Cursor) +{ +#if defined(_WIN32) + COORD coordScreen = { 0, 0 }; + DWORD cCharsWritten; + CONSOLE_SCREEN_BUFFER_INFO csbi; + DWORD dwConSize; + + HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + + GetConsoleScreenBufferInfo(hConsole, &csbi); + dwConSize = csbi.dwSize.X * csbi.dwSize.Y; + // Write space to the entire console + FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize, coordScreen, &cCharsWritten); + GetConsoleScreenBufferInfo(hConsole, &csbi); + FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten); + // Reset cursor + if (Cursor) SetConsoleCursorPosition(hConsole, coordScreen); +#endif +} + + diff --git a/Source/Core/Common/ConsoleListener.h b/Source/Core/Common/ConsoleListener.h new file mode 100644 index 000000000000..1d61a6811e36 --- /dev/null +++ b/Source/Core/Common/ConsoleListener.h @@ -0,0 +1,38 @@ +// Copyright 2013 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#pragma once + +#include "Common/LogManager.h" + +#ifdef _WIN32 +#include +#endif + +class ConsoleListener : public LogListener +{ +public: + ConsoleListener(); + ~ConsoleListener(); + + void Open(bool Hidden = false, int Width = 100, int Height = 100, const char * Name = "Console"); + void UpdateHandle(); + void Close(); + bool IsOpen(); + void LetterSpace(int Width, int Height); + void BufferWidthHeight(int BufferWidth, int BufferHeight, int ScreenWidth, int ScreenHeight, bool BufferFirst); + void PixelSpace(int Left, int Top, int Width, int Height, bool); +#ifdef _WIN32 + COORD GetCoordinates(int BytesRead, int BufferWidth); +#endif + void Log(LogTypes::LOG_LEVELS, const char *Text); + void ClearScreen(bool Cursor = true); + +private: +#ifdef _WIN32 + HWND GetHwnd(void); + HANDLE hConsole; +#endif + bool bUseColor; +}; diff --git a/Source/Core/Common/LogManager.cpp b/Source/Core/Common/LogManager.cpp index 860ad49ec44a..f87bd0c3d95b 100644 --- a/Source/Core/Common/LogManager.cpp +++ b/Source/Core/Common/LogManager.cpp @@ -12,6 +12,7 @@ #ifdef ANDROID #include "Core/Host.h" #endif +#include "Common/ConsoleListener.h" #include "Common/FileUtil.h" #include "Common/Log.h" #include "Common/LogManager.h" @@ -82,11 +83,18 @@ LogManager::LogManager() m_Log[LogTypes::NETPLAY] = new LogContainer("NETPLAY", "Netplay"); m_fileLog = new FileLogListener(File::GetUserPath(F_MAINLOG_IDX).c_str()); + m_consoleLog = new ConsoleListener(); + m_debuggerLog = new DebuggerLogListener(); for (LogContainer* container : m_Log) { container->SetEnable(true); container->AddListener(m_fileLog); + container->AddListener(m_consoleLog); +#ifdef _MSC_VER + if (IsDebuggerPresent()) + container->AddListener(m_debuggerLog); +#endif } } @@ -95,12 +103,16 @@ LogManager::~LogManager() for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i) { m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_fileLog); + m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_consoleLog); + m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_debuggerLog); } for (LogContainer* container : m_Log) delete container; delete m_fileLog; + delete m_consoleLog; + delete m_debuggerLog; } void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, @@ -181,3 +193,10 @@ void FileLogListener::Log(LogTypes::LOG_LEVELS, const char *msg) std::lock_guard lk(m_log_lock); m_logfile << msg << std::flush; } + +void DebuggerLogListener::Log(LogTypes::LOG_LEVELS, const char *msg) +{ +#if _MSC_VER + ::OutputDebugStringA(msg); +#endif +} diff --git a/Source/Core/Common/LogManager.h b/Source/Core/Common/LogManager.h index 7ca1da31e160..7484d878d08d 100644 --- a/Source/Core/Common/LogManager.h +++ b/Source/Core/Common/LogManager.h @@ -43,6 +43,12 @@ class FileLogListener : public LogListener bool m_enable; }; +class DebuggerLogListener : public LogListener +{ +public: + void Log(LogTypes::LOG_LEVELS, const char *msg); +}; + class LogContainer { public: @@ -74,11 +80,15 @@ class LogContainer std::set m_listeners; }; +class ConsoleListener; + class LogManager : NonCopyable { private: LogContainer* m_Log[LogTypes::NUMBER_OF_LOGS]; FileLogListener *m_fileLog; + ConsoleListener *m_consoleLog; + DebuggerLogListener *m_debuggerLog; static LogManager *m_logManager; // Singleton. Ugh. LogManager(); @@ -130,6 +140,16 @@ class LogManager : NonCopyable return m_fileLog; } + ConsoleListener *GetConsoleListener() const + { + return m_consoleLog; + } + + DebuggerLogListener *GetDebuggerListener() const + { + return m_debuggerLog; + } + static LogManager* GetInstance() { return m_logManager; diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt index 0b9c77489731..71f9a8eb7b46 100644 --- a/Source/Core/Core/CMakeLists.txt +++ b/Source/Core/Core/CMakeLists.txt @@ -2,6 +2,7 @@ set(SRCS ActionReplay.cpp ARDecrypt.cpp BootManager.cpp ConfigManager.cpp + Console.cpp Core.cpp CoreParameter.cpp CoreTiming.cpp diff --git a/Source/Core/Core/ConfigManager.cpp b/Source/Core/Core/ConfigManager.cpp index 156892972cf7..7e2d3335346b 100644 --- a/Source/Core/Core/ConfigManager.cpp +++ b/Source/Core/Core/ConfigManager.cpp @@ -184,6 +184,7 @@ void SConfig::SaveSettings() ini.Set("Interface", "ShowStatusbar", m_InterfaceStatusbar); ini.Set("Interface", "ShowLogWindow", m_InterfaceLogWindow); ini.Set("Interface", "ShowLogConfigWindow", m_InterfaceLogConfigWindow); + ini.Set("Interface", "ShowConsole", m_InterfaceConsole); ini.Set("Interface", "ThemeName40", m_LocalCoreStartupParameter.theme_name); // Hotkeys @@ -331,6 +332,7 @@ void SConfig::LoadSettings() ini.Get("Interface", "ShowStatusbar", &m_InterfaceStatusbar, true); ini.Get("Interface", "ShowLogWindow", &m_InterfaceLogWindow, false); ini.Get("Interface", "ShowLogConfigWindow", &m_InterfaceLogConfigWindow, false); + ini.Get("Interface", "ShowConsole", &m_InterfaceConsole, false); ini.Get("Interface", "ThemeName40", &m_LocalCoreStartupParameter.theme_name, "Clean"); // Hotkeys diff --git a/Source/Core/Core/ConfigManager.h b/Source/Core/Core/ConfigManager.h index b3c1f4a3f1ea..53bf2f592a75 100644 --- a/Source/Core/Core/ConfigManager.h +++ b/Source/Core/Core/ConfigManager.h @@ -55,6 +55,7 @@ struct SConfig : NonCopyable bool m_InterfaceStatusbar; bool m_InterfaceLogWindow; bool m_InterfaceLogConfigWindow; + bool m_InterfaceConsole; bool m_ListDrives; bool m_ListWad; diff --git a/Source/Core/Core/Console.cpp b/Source/Core/Core/Console.cpp new file mode 100644 index 000000000000..ced128c4027d --- /dev/null +++ b/Source/Core/Core/Console.cpp @@ -0,0 +1,146 @@ +// Copyright 2013 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include +#include +#include // Bochs + +#include "Common/Common.h" +#include "Common/Thread.h" +#include "Core/Console.h" +#include "Core/Core.h" +#include "Core/CoreTiming.h" +#include "Core/HW/Memmap.h" +#include "Core/PowerPC/PPCAnalyst.h" +#include "Core/PowerPC/PPCSymbolDB.h" +#include "Core/PowerPC/PPCTables.h" +#include "Core/PowerPC/JitCommon/JitBase.h" + +#define CASE1(x) if (!strcmp(cmd, (x))) +#define CASE(x) else if (!strcmp(cmd, (x))) + +void Console_Submit(const char *cmd) +{ + CASE1("r") + { + Core::StartTrace(false); + INFO_LOG(CONSOLE, "Read tracing started."); + } + CASE("w") + { + Core::StartTrace(true); + INFO_LOG(CONSOLE, "Write tracing started."); + } + CASE("trans") + { + TCHAR temp[256]; + u32 addr; + sscanf(cmd, "%s %08x", temp, &addr); + + if (addr) + { +#if MAX_LOGLEVEL >= INFO_LEVEL + u32 EA = + Memory::TranslateAddress(addr, Memory::FLAG_NO_EXCEPTION); + INFO_LOG(CONSOLE, "EA 0x%08x to 0x%08x", addr, EA); +#endif + } + else + { + DEBUG_LOG(CONSOLE, "Syntax: trans ADDR"); + } + } + CASE("call") + { + TCHAR temp[256]; + u32 addr; + sscanf(cmd, "%s %08x", temp, &addr); + if (addr) + { + g_symbolDB.PrintCalls(addr); + } + else + { + DEBUG_LOG(CONSOLE, "Syntax: call ADDR"); + } + } + CASE("llac") + { + TCHAR temp[256]; + u32 addr; + sscanf(cmd, "%s %08x", temp, &addr); + if (addr) + { + g_symbolDB.PrintCallers(addr); + } + else + { + DEBUG_LOG(CONSOLE, "Syntax: llac ADDR"); + } + } + CASE("pend") + { + CoreTiming::LogPendingEvents(); + } + CASE("dump") + { + char temp[256]; + char filename[256]; + u32 start; + u32 end; + sscanf(cmd, "%s %08x %08x %s", temp, &start, &end, filename); + + File::IOFile f(filename, "wb"); + for (u32 i = start; i < end; i++) + { + u8 b = Memory::ReadUnchecked_U8(i); + fputc(b, f.GetHandle()); + } + INFO_LOG(CONSOLE, "Dumped from %08x to %08x to %s",start,end,filename); + } + CASE("disa") + { + u32 start; + u32 end; + TCHAR temp[256]; + sscanf(cmd, "%s %08x %08x", temp, &start, &end); + char disasm[256]; + for (u32 addr = start; addr <= end; addr += 4) + { + u32 data = Memory::ReadUnchecked_U32(addr); + DisassembleGekko(data, addr, disasm, 256); + DEBUG_LOG(CONSOLE, "%08x: %08x: %s\n", addr, data, disasm); + } + } + CASE("help") + { + ERROR_LOG(CONSOLE, "Dolphin Console Command List"); + ERROR_LOG(CONSOLE, "scan ADDR - will find functions that are called by this function"); + ERROR_LOG(CONSOLE, "call ADDR - will find functions that call this function"); + ERROR_LOG(CONSOLE, "dump START_A END_A FILENAME - will dump memory between START_A and END_A"); + ERROR_LOG(CONSOLE, "help - guess what this does :P"); + ERROR_LOG(CONSOLE, "lisd - list signature database"); + ERROR_LOG(CONSOLE, "lisf - list functions"); + ERROR_LOG(CONSOLE, "trans ADDR - translate address"); + } + CASE("lisd") + { + // PPCAnalyst::ListDB(); + } + CASE("ipro") + { + PPCTables::PrintInstructionRunCounts(); + } + CASE("lisf") + { + g_symbolDB.List(); + } + else + { + ERROR_LOG(CONSOLE, "Invalid command"); + } +} + +#undef CASE1 +#undef CASE diff --git a/Source/Core/Core/Console.h b/Source/Core/Core/Console.h new file mode 100644 index 000000000000..64779aad264b --- /dev/null +++ b/Source/Core/Core/Console.h @@ -0,0 +1,10 @@ +// Copyright 2013 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + + +// Simple debugging console currently residing in the Logging window. Not used much. + +#pragma once + +void Console_Submit(const char *cmd); diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj index c1286f76cafc..c5d85d6bf3cc 100644 --- a/Source/Core/Core/Core.vcxproj +++ b/Source/Core/Core/Core.vcxproj @@ -1,4 +1,4 @@ - + @@ -53,6 +53,7 @@ + @@ -257,6 +258,7 @@ + diff --git a/Source/Core/Core/Core.vcxproj.filters b/Source/Core/Core/Core.vcxproj.filters index a943f2aade71..a6b859167623 100644 --- a/Source/Core/Core/Core.vcxproj.filters +++ b/Source/Core/Core/Core.vcxproj.filters @@ -1,4 +1,4 @@ - + @@ -137,6 +137,7 @@ + @@ -709,6 +710,7 @@ + @@ -1217,4 +1219,4 @@ - \ No newline at end of file + diff --git a/Source/Core/DolphinWX/Debugger/CodeWindowFunctions.cpp b/Source/Core/DolphinWX/Debugger/CodeWindowFunctions.cpp index d42d227c94c0..f7b6006534fa 100644 --- a/Source/Core/DolphinWX/Debugger/CodeWindowFunctions.cpp +++ b/Source/Core/DolphinWX/Debugger/CodeWindowFunctions.cpp @@ -418,6 +418,8 @@ void CCodeWindow::OpenPages() Parent->ToggleLogWindow(true); if (bShowOnStart[IDM_LOGCONFIGWINDOW - IDM_LOGWINDOW]) Parent->ToggleLogConfigWindow(true); + if (bShowOnStart[IDM_CONSOLEWINDOW - IDM_LOGWINDOW]) + Parent->ToggleConsole(true); if (bShowOnStart[IDM_REGISTERWINDOW - IDM_LOGWINDOW]) ToggleRegisterWindow(true); if (bShowOnStart[IDM_BREAKPOINTWINDOW - IDM_LOGWINDOW]) diff --git a/Source/Core/DolphinWX/Frame.cpp b/Source/Core/DolphinWX/Frame.cpp index f1c27733b213..d348c5617fdc 100644 --- a/Source/Core/DolphinWX/Frame.cpp +++ b/Source/Core/DolphinWX/Frame.cpp @@ -44,6 +44,7 @@ #include #include "Common/Common.h" +#include "Common/ConsoleListener.h" #include "Common/FileUtil.h" #include "Common/Thread.h" @@ -309,8 +310,11 @@ CFrame::CFrame(wxFrame* parent, for (int i = 0; i <= IDM_CODEWINDOW - IDM_LOGWINDOW; i++) bFloatWindow[i] = false; - if (ShowLogWindow) - SConfig::GetInstance().m_InterfaceLogWindow = true; + if (ShowLogWindow) SConfig::GetInstance().m_InterfaceLogWindow = true; + + // Give it a console early to show potential messages from this onward + ConsoleListener *Console = LogManager::GetInstance()->GetConsoleListener(); + if (SConfig::GetInstance().m_InterfaceConsole) Console->Open(); // Start debugging maximized if (UseDebugger) this->Maximize(true); @@ -388,6 +392,8 @@ CFrame::CFrame(wxFrame* parent, ToggleLogWindow(true); if (SConfig::GetInstance().m_InterfaceLogConfigWindow) ToggleLogConfigWindow(true); + if (SConfig::GetInstance().m_InterfaceConsole) + ToggleConsole(true); } // Show window @@ -675,6 +681,7 @@ void CFrame::OnRenderWindowSizeRequest(int width, int height) // Add space for the log/console/debugger window if (SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain && (SConfig::GetInstance().m_InterfaceLogWindow || + SConfig::GetInstance().m_InterfaceConsole || SConfig::GetInstance().m_InterfaceLogConfigWindow) && !m_Mgr->GetPane(wxT("Pane 1")).IsFloating()) { diff --git a/Source/Core/DolphinWX/Frame.h b/Source/Core/DolphinWX/Frame.h index 9cfbdb6e7b0b..c6fbcb51e11e 100644 --- a/Source/Core/DolphinWX/Frame.h +++ b/Source/Core/DolphinWX/Frame.h @@ -127,6 +127,7 @@ class CFrame : public CRenderFrame void UpdateGameList(); void ToggleLogWindow(bool bShow); void ToggleLogConfigWindow(bool bShow); + void ToggleConsole(bool bShow); void PostEvent(wxCommandEvent& event); void StatusBarMessage(const char * Text, ...); void ClearStatusBar(); @@ -237,6 +238,7 @@ class CFrame : public CRenderFrame void ResetToolbarStyle(); void TogglePaneStyle(bool On, int EventId); void ToggleNotebookStyle(bool On, long Style); + void ResizeConsole(); // Float window void DoUnfloatPage(int Id); void OnFloatingPageClosed(wxCloseEvent& event); diff --git a/Source/Core/DolphinWX/FrameAui.cpp b/Source/Core/DolphinWX/FrameAui.cpp index faa3a7e1db75..55190dd51baa 100644 --- a/Source/Core/DolphinWX/FrameAui.cpp +++ b/Source/Core/DolphinWX/FrameAui.cpp @@ -31,6 +31,7 @@ #include #include "Common/Common.h" +#include "Common/ConsoleListener.h" #include "Common/FileUtil.h" #include "Common/IniFile.h" #include "Common/StringUtil.h" @@ -56,6 +57,7 @@ void CFrame::OnManagerResize(wxAuiManagerEvent& event) m_LogWindow->winpos = m_Mgr->GetPane(_T("Pane 1")).dock_direction; } event.Skip(); + ResizeConsole(); } void CFrame::OnPaneClose(wxAuiManagerEvent& event) @@ -68,10 +70,14 @@ void CFrame::OnPaneClose(wxAuiManagerEvent& event) if (!g_pCodeWindow) { if (nb->GetPage(0)->GetId() == IDM_LOGWINDOW || - nb->GetPage(0)->GetId() == IDM_LOGCONFIGWINDOW) + nb->GetPage(0)->GetId() == IDM_LOGCONFIGWINDOW || + nb->GetPage(0)->GetId() == IDM_CONSOLEWINDOW) { + // Closing a pane containing the logwindow or a console closes both + SConfig::GetInstance().m_InterfaceConsole = false; SConfig::GetInstance().m_InterfaceLogWindow = false; SConfig::GetInstance().m_InterfaceLogConfigWindow = false; + ToggleConsole(false); ToggleLogWindow(false); ToggleLogConfigWindow(false); } @@ -157,6 +163,59 @@ void CFrame::ToggleLogConfigWindow(bool bShow) TogglePane(); } +void CFrame::ToggleConsole(bool bShow) +{ +#ifdef _WIN32 + GetMenuBar()->FindItem(IDM_CONSOLEWINDOW)->Check(bShow); + + if (bShow) + { + // If the console doesn't exist, we create it + if (!GetConsoleWindow()) + { + ConsoleListener *Console = LogManager::GetInstance()->GetConsoleListener(); + Console->Open(); + } + else + { + ShowWindow(GetConsoleWindow(), SW_SHOW); + } + + // Create the parent window if it doesn't exist + wxPanel *ConsoleParent = (wxPanel*)FindWindowById(IDM_CONSOLEWINDOW); + if (!ConsoleParent) ConsoleParent = new wxPanel(this, IDM_CONSOLEWINDOW, + wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, _("Console")); + + wxWindow *ConsoleWin = new wxWindow(); + ConsoleWin->SetHWND((WXHWND)GetConsoleWindow()); + ConsoleWin->AdoptAttributesFromHWND(); + ConsoleWin->Reparent(ConsoleParent); + + ConsoleParent->Enable(); + const int nbIndex = IDM_CONSOLEWINDOW - IDM_LOGWINDOW; + DoAddPage(ConsoleParent, + g_pCodeWindow ? g_pCodeWindow->iNbAffiliation[nbIndex] : 0, + g_pCodeWindow ? bFloatWindow[nbIndex] : false); + } + else // Hide + { + if(GetConsoleWindow()) + ShowWindow(GetConsoleWindow(), SW_HIDE); // WIN32 + + wxPanel *ConsoleParent = (wxPanel*)FindWindowById(IDM_CONSOLEWINDOW); + if (ConsoleParent) + ConsoleParent->Disable(); + + // Then close the page + DoRemovePage(ConsoleParent, true); + } + + // Hide or Show the pane + if (!g_pCodeWindow) + TogglePane(); +#endif +} + void CFrame::OnToggleWindow(wxCommandEvent& event) { bool bShow = GetMenuBar()->IsChecked(event.GetId()); @@ -173,6 +232,11 @@ void CFrame::OnToggleWindow(wxCommandEvent& event) SConfig::GetInstance().m_InterfaceLogConfigWindow = bShow; ToggleLogConfigWindow(bShow); break; + case IDM_CONSOLEWINDOW: + if (!g_pCodeWindow) + SConfig::GetInstance().m_InterfaceConsole = bShow; + ToggleConsole(bShow); + break; case IDM_REGISTERWINDOW: g_pCodeWindow->ToggleRegisterWindow(bShow); break; @@ -200,7 +264,7 @@ void CFrame::ClosePages() { ToggleLogWindow(false); ToggleLogConfigWindow(false); - + ToggleConsole(false); if (g_pCodeWindow) { g_pCodeWindow->ToggleCodeWindow(false); @@ -242,6 +306,8 @@ void CFrame::OnNotebookPageClose(wxAuiNotebookEvent& event) ToggleLogWindow(false); if (Ctrl->GetPage(event.GetSelection())->GetId() == IDM_LOGCONFIGWINDOW) ToggleLogConfigWindow(false); + if (Ctrl->GetPage(event.GetSelection())->GetId() == IDM_CONSOLEWINDOW) + ToggleConsole(false); if (Ctrl->GetPage(event.GetSelection())->GetId() == IDM_REGISTERWINDOW) g_pCodeWindow->ToggleRegisterWindow(false); if (Ctrl->GetPage(event.GetSelection())->GetId() == IDM_BREAKPOINTWINDOW) @@ -264,6 +330,7 @@ void CFrame::OnFloatingPageClosed(wxCloseEvent& event) void CFrame::OnFloatingPageSize(wxSizeEvent& event) { event.Skip(); + ResizeConsole(); } void CFrame::OnFloatWindow(wxCommandEvent& event) @@ -356,6 +423,7 @@ void CFrame::OnAllowNotebookDnD(wxAuiNotebookEvent& event) { event.Skip(); event.Allow(); + ResizeConsole(); } void CFrame::ShowResizePane() @@ -735,6 +803,33 @@ void CFrame::OnSelectPerspective(wxCommandEvent& event) DoLoadPerspective(); } +void CFrame::ResizeConsole() +{ +#ifdef _WIN32 + // Get the console parent window + wxWindow * Win = FindWindowById(IDM_CONSOLEWINDOW); + if (!Win) return; + + const int wxBorder = 2, Border = 4, + MenuBar = 30, ScrollBar = 19; + + // Get the client size + int X = Win->GetSize().GetX(); + int Y = Win->GetSize().GetY(); + int InternalWidth = X - wxBorder*2 - ScrollBar; + int InternalHeight = Y - wxBorder*2; + int WindowWidth = InternalWidth + Border*2 + + /*max out the width in the word wrap mode*/ 100; + int WindowHeight = InternalHeight + MenuBar; + // Resize buffer + ConsoleListener* Console = LogManager::GetInstance()->GetConsoleListener(); + Console->PixelSpace(0,0, InternalWidth, InternalHeight, false); + // Move the window to hide the border + MoveWindow(GetConsoleWindow(), -Border-wxBorder, -MenuBar-wxBorder, + WindowWidth + 100, WindowHeight, true); +#endif +} + static int Limit(int i, int Low, int High) { if (i < Low) return Low; @@ -999,6 +1094,11 @@ wxFrame * CFrame::CreateParentFrame(wxWindowID Id, const wxString& Title, Frame->Bind(wxEVT_CLOSE_WINDOW, &CFrame::OnFloatingPageClosed, this); + if (Id == IDM_CONSOLEWINDOW_PARENT) + { + Frame->Bind(wxEVT_SIZE, &CFrame::OnFloatingPageSize, this); + } + // Main sizer Frame->SetSizer(m_MainSizer); // Minimum frame size diff --git a/Source/Core/DolphinWX/FrameTools.cpp b/Source/Core/DolphinWX/FrameTools.cpp index 06ae7b962b09..e8eff865b729 100644 --- a/Source/Core/DolphinWX/FrameTools.cpp +++ b/Source/Core/DolphinWX/FrameTools.cpp @@ -258,11 +258,17 @@ void CFrame::CreateMenu() viewMenu->AppendSeparator(); viewMenu->AppendCheckItem(IDM_LOGWINDOW, _("Show &Log")); viewMenu->AppendCheckItem(IDM_LOGCONFIGWINDOW, _("Show Log &Configuration")); + viewMenu->AppendCheckItem(IDM_CONSOLEWINDOW, _("Show &Console")); viewMenu->AppendSeparator(); +#ifndef _WIN32 + viewMenu->Enable(IDM_CONSOLEWINDOW, false); +#endif + if (g_pCodeWindow) { viewMenu->Check(IDM_LOGWINDOW, g_pCodeWindow->bShowOnStart[0]); + viewMenu->Check(IDM_CONSOLEWINDOW, g_pCodeWindow->bShowOnStart[1]); const wxString MenuText[] = { wxTRANSLATE("&Registers"), @@ -285,6 +291,7 @@ void CFrame::CreateMenu() { viewMenu->Check(IDM_LOGWINDOW, SConfig::GetInstance().m_InterfaceLogWindow); viewMenu->Check(IDM_LOGCONFIGWINDOW, SConfig::GetInstance().m_InterfaceLogConfigWindow); + viewMenu->Check(IDM_CONSOLEWINDOW, SConfig::GetInstance().m_InterfaceConsole); } wxMenu *platformMenu = new wxMenu; diff --git a/Source/Core/DolphinWX/Globals.h b/Source/Core/DolphinWX/Globals.h index 9b60c4554edf..713f8ff0abfc 100644 --- a/Source/Core/DolphinWX/Globals.h +++ b/Source/Core/DolphinWX/Globals.h @@ -130,6 +130,7 @@ enum // Views IDM_LOGWINDOW, IDM_LOGCONFIGWINDOW, + IDM_CONSOLEWINDOW, IDM_REGISTERWINDOW, IDM_BREAKPOINTWINDOW, IDM_MEMORYWINDOW, @@ -141,6 +142,7 @@ enum // Float Window IDs IDM_LOGWINDOW_PARENT, IDM_LOGCONFIGWINDOW_PARENT, + IDM_CONSOLEWINDOW_PARENT, IDM_REGISTERWINDOW_PARENT, IDM_BREAKPOINTWINDOW_PARENT, IDM_MEMORYWINDOW_PARENT, diff --git a/Source/Core/DolphinWX/LogConfigWindow.cpp b/Source/Core/DolphinWX/LogConfigWindow.cpp index 26cd3c1d517e..389acb81f9b3 100644 --- a/Source/Core/DolphinWX/LogConfigWindow.cpp +++ b/Source/Core/DolphinWX/LogConfigWindow.cpp @@ -18,6 +18,7 @@ #include #include +#include "Common/ConsoleListener.h" #include "Common/FileUtil.h" #include "Common/IniFile.h" #include "Common/Log.h" @@ -62,8 +63,18 @@ void LogConfigWindow::CreateGUIControls() // Options m_writeFileCB = new wxCheckBox(this, wxID_ANY, _("Write to File")); m_writeFileCB->Bind(wxEVT_COMMAND_CHECKBOX_CLICKED, &LogConfigWindow::OnWriteFileChecked, this); + m_writeConsoleCB = new wxCheckBox(this, wxID_ANY, _("Write to Console")); + m_writeConsoleCB->Bind(wxEVT_COMMAND_CHECKBOX_CLICKED, &LogConfigWindow::OnWriteConsoleChecked, this); m_writeWindowCB = new wxCheckBox(this, wxID_ANY, _("Write to Window")); m_writeWindowCB->Bind(wxEVT_COMMAND_CHECKBOX_CLICKED, &LogConfigWindow::OnWriteWindowChecked, this); + m_writeDebuggerCB = NULL; +#ifdef _MSC_VER + if (IsDebuggerPresent()) + { + m_writeDebuggerCB = new wxCheckBox(this, wxID_ANY, _("Write to Debugger")); + m_writeDebuggerCB->Bind(wxEVT_COMMAND_CHECKBOX_CLICKED, &LogConfigWindow::OnWriteDebuggerChecked, this); + } +#endif wxButton *btn_toggle_all = new wxButton(this, wxID_ANY, _("Toggle All Log Types"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT); @@ -76,7 +87,18 @@ void LogConfigWindow::CreateGUIControls() // Sizers wxStaticBoxSizer* sbOutputs = new wxStaticBoxSizer(wxVERTICAL, this, _("Logger Outputs")); sbOutputs->Add(m_writeFileCB, 0, wxDOWN, 1); - sbOutputs->Add(m_writeWindowCB, 0); + sbOutputs->Add(m_writeConsoleCB, 0, wxDOWN, 1); +#ifdef _MSC_VER + if (m_writeDebuggerCB) + { + sbOutputs->Add(m_writeWindowCB, 0, wxDOWN, 1); + sbOutputs->Add(m_writeDebuggerCB, 0); + } + else +#endif + { + sbOutputs->Add(m_writeWindowCB, 0); + } wxStaticBoxSizer* sbLogTypes = new wxStaticBoxSizer(wxVERTICAL, this, _("Log Types")); sbLogTypes->Add(m_checks, 1, wxEXPAND); @@ -112,8 +134,21 @@ void LogConfigWindow::LoadSettings() // Get the logger output settings from the config ini file. ini.Get("Options", "WriteToFile", &m_writeFile, false); m_writeFileCB->SetValue(m_writeFile); + ini.Get("Options", "WriteToConsole", &m_writeConsole, true); + m_writeConsoleCB->SetValue(m_writeConsole); ini.Get("Options", "WriteToWindow", &m_writeWindow, true); m_writeWindowCB->SetValue(m_writeWindow); +#ifdef _MSC_VER + if (IsDebuggerPresent()) + { + ini.Get("Options", "WriteToDebugger", &m_writeDebugger, true); + m_writeDebuggerCB->SetValue(m_writeDebugger); + } + else +#endif + { + m_writeDebugger = false; + } // Run through all of the log types and check each checkbox for each logging type // depending on its set value within the config ini. @@ -139,7 +174,12 @@ void LogConfigWindow::SaveSettings() // Save the enabled/disabled states of the logger outputs to the config ini. ini.Set("Options", "WriteToFile", m_writeFile); + ini.Set("Options", "WriteToConsole", m_writeConsole); ini.Set("Options", "WriteToWindow", m_writeWindow); +#ifdef _MSC_VER + if (IsDebuggerPresent()) + ini.Set("Options", "WriteToDebugger", m_writeDebugger); +#endif // Save all enabled/disabled states of the log types to the config ini. for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i) @@ -180,6 +220,21 @@ void LogConfigWindow::OnWriteFileChecked(wxCommandEvent& event) } } +void LogConfigWindow::OnWriteConsoleChecked(wxCommandEvent& event) +{ + for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i) + { + m_writeConsole = event.IsChecked(); + if (m_checks->IsChecked(i)) + { + if (m_writeConsole) + m_LogManager->AddListener((LogTypes::LOG_TYPE)i, m_LogManager->GetConsoleListener()); + else + m_LogManager->RemoveListener((LogTypes::LOG_TYPE)i, m_LogManager->GetConsoleListener()); + } + } +} + void LogConfigWindow::OnWriteWindowChecked(wxCommandEvent& event) { for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i) @@ -195,6 +250,21 @@ void LogConfigWindow::OnWriteWindowChecked(wxCommandEvent& event) } } +void LogConfigWindow::OnWriteDebuggerChecked(wxCommandEvent& event) +{ + for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i) + { + m_writeDebugger = event.IsChecked(); + if (m_checks->IsChecked(i)) + { + if (m_writeDebugger) + m_LogManager->AddListener((LogTypes::LOG_TYPE)i, (LogListener *)m_LogManager->GetDebuggerListener()); + else + m_LogManager->RemoveListener((LogTypes::LOG_TYPE)i, (LogListener *)m_LogManager->GetDebuggerListener()); + } + } +} + void LogConfigWindow::OnToggleAll(wxCommandEvent& WXUNUSED(event)) { for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i) @@ -215,14 +285,19 @@ void LogConfigWindow::ToggleLog(int _logType, bool enable) { if (m_writeWindow) m_LogManager->AddListener(logType, (LogListener *)m_LogWindow); - if (m_writeFile) m_LogManager->AddListener(logType, m_LogManager->GetFileListener()); + if (m_writeConsole) + m_LogManager->AddListener(logType, m_LogManager->GetConsoleListener()); + if (m_writeDebugger) + m_LogManager->AddListener(logType, m_LogManager->GetDebuggerListener()); } else { m_LogManager->RemoveListener(logType, (LogListener *)m_LogWindow); m_LogManager->RemoveListener(logType, m_LogManager->GetFileListener()); + m_LogManager->RemoveListener(logType, m_LogManager->GetConsoleListener()); + m_LogManager->RemoveListener(logType, m_LogManager->GetDebuggerListener()); } } diff --git a/Source/Core/DolphinWX/LogConfigWindow.h b/Source/Core/DolphinWX/LogConfigWindow.h index 50d2b39981e4..29d2560b070d 100644 --- a/Source/Core/DolphinWX/LogConfigWindow.h +++ b/Source/Core/DolphinWX/LogConfigWindow.h @@ -28,18 +28,20 @@ class LogConfigWindow : public wxPanel private: LogManager *m_LogManager; CLogWindow *m_LogWindow; - bool m_writeFile, m_writeWindow; + bool m_writeFile, m_writeConsole, m_writeWindow, m_writeDebugger; bool enableAll; // Controls - wxCheckBox *m_writeFileCB, *m_writeWindowCB; + wxCheckBox *m_writeFileCB, *m_writeConsoleCB, *m_writeWindowCB, *m_writeDebuggerCB; wxCheckListBox* m_checks; wxRadioBox *m_verbosity; void CreateGUIControls(); void OnVerbosityChange(wxCommandEvent& event); void OnWriteFileChecked(wxCommandEvent& event); + void OnWriteConsoleChecked(wxCommandEvent& event); void OnWriteWindowChecked(wxCommandEvent& event); + void OnWriteDebuggerChecked(wxCommandEvent& event); void OnToggleAll(wxCommandEvent& event); void ToggleLog(int _logType, bool enable); void OnLogCheck(wxCommandEvent& event); diff --git a/Source/Core/DolphinWX/LogWindow.cpp b/Source/Core/DolphinWX/LogWindow.cpp index 5a8be5e9fe29..0f752feb2843 100644 --- a/Source/Core/DolphinWX/LogWindow.cpp +++ b/Source/Core/DolphinWX/LogWindow.cpp @@ -29,9 +29,11 @@ #include #include "Common/Common.h" +#include "Common/ConsoleListener.h" #include "Common/FileUtil.h" #include "Common/IniFile.h" #include "Common/LogManager.h" +#include "Core/Console.h" #include "DolphinWX/Frame.h" #include "DolphinWX/LogWindow.h" #include "DolphinWX/WxUtils.h" @@ -42,6 +44,7 @@ BEGIN_EVENT_TABLE(CLogWindow, wxPanel) EVT_CLOSE(CLogWindow::OnClose) + EVT_TEXT_ENTER(IDM_SUBMITCMD, CLogWindow::OnSubmit) EVT_BUTTON(IDM_CLEARLOG, CLogWindow::OnClear) EVT_CHOICE(IDM_FONT, CLogWindow::OnFontChange) EVT_CHECKBOX(IDM_WRAPLINE, CLogWindow::OnWrapLineCheck) @@ -84,7 +87,18 @@ void CLogWindow::CreateGUIControls() // Get the logger output settings from the config ini file. ini.Get("Options", "WriteToFile", &m_writeFile, false); + ini.Get("Options", "WriteToConsole", &m_writeConsole, true); ini.Get("Options", "WriteToWindow", &m_writeWindow, true); +#ifdef _MSC_VER + if (IsDebuggerPresent()) + { + ini.Get("Options", "WriteToDebugger", &m_writeDebugger, true); + } + else +#endif + { + m_writeDebugger = false; + } for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i) { @@ -101,6 +115,16 @@ void CLogWindow::CreateGUIControls() else m_LogManager->RemoveListener((LogTypes::LOG_TYPE)i, m_LogManager->GetFileListener()); + if (m_writeConsole && enable) + m_LogManager->AddListener((LogTypes::LOG_TYPE)i, m_LogManager->GetConsoleListener()); + else + m_LogManager->RemoveListener((LogTypes::LOG_TYPE)i, m_LogManager->GetConsoleListener()); + + if (m_writeDebugger && enable) + m_LogManager->AddListener((LogTypes::LOG_TYPE)i, m_LogManager->GetDebuggerListener()); + else + m_LogManager->RemoveListener((LogTypes::LOG_TYPE)i, m_LogManager->GetDebuggerListener()); + m_LogManager->SetLogLevel((LogTypes::LOG_TYPE)i, (LogTypes::LOG_LEVELS)(verbosity)); } @@ -185,15 +209,25 @@ void CLogWindow::SaveSettings() ini.Save(File::GetUserPath(F_LOGGERCONFIG_IDX)); } +void CLogWindow::OnSubmit(wxCommandEvent& WXUNUSED (event)) +{ + if (!m_cmdline) return; + Console_Submit(WxStrToStr(m_cmdline->GetValue()).c_str()); + m_cmdline->SetValue(wxEmptyString); +} + void CLogWindow::OnClear(wxCommandEvent& WXUNUSED (event)) { m_Log->Clear(); - + { std::lock_guard lk(m_LogSection); int msgQueueSize = (int)msgQueue.size(); for (int i = 0; i < msgQueueSize; i++) msgQueue.pop(); + } + + m_LogManager->GetConsoleListener()->ClearScreen(); } void CLogWindow::UnPopulateBottom() diff --git a/Source/Core/DolphinWX/LogWindow.h b/Source/Core/DolphinWX/LogWindow.h index 2d92e16329c1..00fb703cdbac 100644 --- a/Source/Core/DolphinWX/LogWindow.h +++ b/Source/Core/DolphinWX/LogWindow.h @@ -65,7 +65,7 @@ class CLogWindow : public wxPanel, LogListener bool m_ignoreLogTimer; LogManager *m_LogManager; std::queue > msgQueue; - bool m_writeFile, m_writeWindow, m_LogAccess; + bool m_writeFile, m_writeConsole, m_writeWindow, m_writeDebugger, m_LogAccess; // Controls wxBoxSizer *sBottom; @@ -82,6 +82,7 @@ class CLogWindow : public wxPanel, LogListener void PopulateBottom(); void UnPopulateBottom(); void OnClose(wxCloseEvent& event); + void OnSubmit(wxCommandEvent& event); void OnFontChange(wxCommandEvent& event); void OnWrapLineCheck(wxCommandEvent& event); void OnClear(wxCommandEvent& event);