(view as text)
diff --git a/Source/Core/Common/CMakeLists.txt b/Source/Core/Common/CMakeLists.txt
index 21f894c..4614c7d 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 1cd3454..87865d5 100644
--- a/Source/Core/Common/Common.vcxproj
+++ b/Source/Core/Common/Common.vcxproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup Label="ProjectConfigurations">
     <ProjectConfiguration Include="Debug|Win32">
@@ -54,6 +54,7 @@
     <ClInclude Include="CommonFuncs.h" />
     <ClInclude Include="CommonPaths.h" />
     <ClInclude Include="CommonTypes.h" />
+    <ClInclude Include="ConsoleListener.h" />
     <ClInclude Include="CPUDetect.h" />
     <ClInclude Include="Crypto\tools.h" />
     <ClInclude Include="DebugInterface.h" />
@@ -92,6 +93,7 @@
     <ClCompile Include="BreakPoints.cpp" />
     <ClCompile Include="CDUtils.cpp" />
     <ClCompile Include="ColorUtil.cpp" />
+    <ClCompile Include="ConsoleListener.cpp" />
     <ClCompile Include="Crypto\bn.cpp" />
     <ClCompile Include="Crypto\ec.cpp" />
     <ClCompile Include="ExtendedTrace.cpp" />
@@ -137,4 +139,4 @@
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>
-</Project>
\ No newline at end of file
+</Project>
diff --git a/Source/Core/Common/Common.vcxproj.filters b/Source/Core/Common/Common.vcxproj.filters
index cb9e284..4af869c 100644
--- a/Source/Core/Common/Common.vcxproj.filters
+++ b/Source/Core/Common/Common.vcxproj.filters
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup>
     <Filter Include="Crypto">
@@ -52,6 +52,9 @@
     <ClInclude Include="Crypto\tools.h">
       <Filter>Crypto</Filter>
     </ClInclude>
+    <ClInclude Include="ConsoleListener.h">
+      <Filter>Logging</Filter>
+    </ClInclude>
     <ClInclude Include="Log.h">
       <Filter>Logging</Filter>
     </ClInclude>
@@ -94,6 +97,9 @@
     <ClCompile Include="Crypto\ec.cpp">
       <Filter>Crypto</Filter>
     </ClCompile>
+    <ClCompile Include="ConsoleListener.cpp">
+      <Filter>Logging</Filter>
+    </ClCompile>
     <ClCompile Include="LogManager.cpp">
       <Filter>Logging</Filter>
     </ClCompile>
@@ -102,4 +108,4 @@
   <ItemGroup>
     <Text Include="CMakeLists.txt" />
   </ItemGroup>
-</Project>
\ No newline at end of file
+</Project>
diff --git a/Source/Core/Common/ConsoleListener.cpp b/Source/Core/Common/ConsoleListener.cpp
new file mode 100644
index 0000000..e1203fa
--- /dev/null
+++ b/Source/Core/Common/ConsoleListener.cpp
@@ -0,0 +1,334 @@
+// Copyright 2013 Dolphin Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#include <algorithm>  // min
+#include <cmath>
+#include <cstdio>
+#include <cstdlib>
+#include <string> // System: To be able to add strings with "+"
+#ifdef _WIN32
+#include <windows.h>
+#include <array>
+#endif
+
+#include "Common/ConsoleListener.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<std::array<TCHAR, MAX_BYTES>> Str;
+	std::vector<std::array<WORD, MAX_BYTES>> 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 0000000..1d61a68
--- /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 <windows.h>
+#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 860ad49..f87bd0c 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<std::mutex> 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 7ca1da3..7484d87 100644
--- a/Source/Core/Common/LogManager.h
+++ b/Source/Core/Common/LogManager.h
@@ -43,6 +43,12 @@ private:
 	bool m_enable;
 };
 
+class DebuggerLogListener : public LogListener
+{
+public:
+	void Log(LogTypes::LOG_LEVELS, const char *msg);
+};
+
 class LogContainer
 {
 public:
@@ -74,11 +80,15 @@ private:
 	std::set<LogListener*> 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 @@ public:
 		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 0b9c774..71f9a8e 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 1568929..7e2d333 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 b3c1f4a..53bf2f5 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 0000000..ced128c
--- /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 <cstring>
+#include <iostream>
+#include <PowerPCDisasm.h> // 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 0000000..64779aa
--- /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 c1286f7..c5d85d6 100644
--- a/Source/Core/Core/Core.vcxproj
+++ b/Source/Core/Core/Core.vcxproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup Label="ProjectConfigurations">
     <ProjectConfiguration Include="Debug|Win32">
@@ -53,6 +53,7 @@
     <ClCompile Include="Boot\Boot_WiiWAD.cpp" />
     <ClCompile Include="Boot\ElfReader.cpp" />
     <ClCompile Include="ConfigManager.cpp" />
+    <ClCompile Include="Console.cpp" />
     <ClCompile Include="Core.cpp" />
     <ClCompile Include="CoreParameter.cpp" />
     <ClCompile Include="CoreTiming.cpp" />
@@ -257,6 +258,7 @@
     <ClInclude Include="Boot\ElfReader.h" />
     <ClInclude Include="Boot\ElfTypes.h" />
     <ClInclude Include="ConfigManager.h" />
+    <ClInclude Include="Console.h" />
     <ClInclude Include="Core.h" />
     <ClInclude Include="CoreParameter.h" />
     <ClInclude Include="CoreTiming.h" />
diff --git a/Source/Core/Core/Core.vcxproj.filters b/Source/Core/Core/Core.vcxproj.filters
index a943f2a..a6b8591 100644
--- a/Source/Core/Core/Core.vcxproj.filters
+++ b/Source/Core/Core/Core.vcxproj.filters
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup>
     <Filter Include="ActionReplay">
@@ -137,6 +137,7 @@
   <ItemGroup>
     <ClCompile Include="BootManager.cpp" />
     <ClCompile Include="ConfigManager.cpp" />
+    <ClCompile Include="Console.cpp" />
     <ClCompile Include="Core.cpp" />
     <ClCompile Include="CoreParameter.cpp" />
     <ClCompile Include="CoreTiming.cpp" />
@@ -709,6 +710,7 @@
   <ItemGroup>
     <ClInclude Include="BootManager.h" />
     <ClInclude Include="ConfigManager.h" />
+    <ClInclude Include="Console.h" />
     <ClInclude Include="Core.h" />
     <ClInclude Include="CoreParameter.h" />
     <ClInclude Include="CoreTiming.h" />
@@ -1217,4 +1219,4 @@
   <ItemGroup>
     <Text Include="CMakeLists.txt" />
   </ItemGroup>
-</Project>
\ No newline at end of file
+</Project>
diff --git a/Source/Core/DolphinWX/Debugger/CodeWindowFunctions.cpp b/Source/Core/DolphinWX/Debugger/CodeWindowFunctions.cpp
index d42d227..f7b6006 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 f1c2773..d348c56 100644
--- a/Source/Core/DolphinWX/Frame.cpp
+++ b/Source/Core/DolphinWX/Frame.cpp
@@ -44,6 +44,7 @@
 #include <wx/aui/framemanager.h>
 
 #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 9cfbdb6..c6fbcb5 100644
--- a/Source/Core/DolphinWX/Frame.h
+++ b/Source/Core/DolphinWX/Frame.h
@@ -127,6 +127,7 @@ public:
 	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 @@ private:
 	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 faa3a7e..55190dd 100644
--- a/Source/Core/DolphinWX/FrameAui.cpp
+++ b/Source/Core/DolphinWX/FrameAui.cpp
@@ -31,6 +31,7 @@
 #include <wx/aui/framemanager.h>
 
 #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 06ae7b9..e8eff86 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 9b60c45..713f8ff 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 26cd3c1..389acb8 100644
--- a/Source/Core/DolphinWX/LogConfigWindow.cpp
+++ b/Source/Core/DolphinWX/LogConfigWindow.cpp
@@ -18,6 +18,7 @@
 #include <wx/validate.h>
 #include <wx/windowid.h>
 
+#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 50d2b39..29d2560 100644
--- a/Source/Core/DolphinWX/LogConfigWindow.h
+++ b/Source/Core/DolphinWX/LogConfigWindow.h
@@ -28,18 +28,20 @@ public:
 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 5a8be5e..0f752fe 100644
--- a/Source/Core/DolphinWX/LogWindow.cpp
+++ b/Source/Core/DolphinWX/LogWindow.cpp
@@ -29,9 +29,11 @@
 #include <wx/aui/framemanager.h>
 
 #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<std::mutex> 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 2d92e16..00fb703 100644
--- a/Source/Core/DolphinWX/LogWindow.h
+++ b/Source/Core/DolphinWX/LogWindow.h
@@ -65,7 +65,7 @@ private:
 	bool m_ignoreLogTimer;
 	LogManager *m_LogManager;
 	std::queue<std::pair<u8, wxString> > 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 @@ private:
 	void PopulateBottom();
 	void UnPopulateBottom();
 	void OnClose(wxCloseEvent& event);
+	void OnSubmit(wxCommandEvent& event);
 	void OnFontChange(wxCommandEvent& event);
 	void OnWrapLineCheck(wxCommandEvent& event);
 	void OnClear(wxCommandEvent& event);