diff --git a/GLScreen.cs b/GLScreen.cs
index 3e16f7f1da..982816931d 100644
--- a/GLScreen.cs
+++ b/GLScreen.cs
@@ -351,7 +351,9 @@ void main(void) {
         protected override void OnRenderFrame(FrameEventArgs e)
         {
             GL.Viewport(0, 0, 1280, 720);
-            
+
+            Title = $"Ryujinx Screen - (Vsync: {VSync} - FPS: {1f / e.Time:0})";
+
             GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
 
             RenderFb();
diff --git a/Program.cs b/Program.cs
index 44dc67c1fd..79a4f70714 100644
--- a/Program.cs
+++ b/Program.cs
@@ -9,6 +9,8 @@ namespace Ryujinx
     {
         static void Main(string[] args)
         {
+            Console.Title = "Ryujinx Console";
+
             IGalRenderer Renderer = new OpenGLRenderer();
 
             Switch Ns = new Switch(Renderer);
@@ -21,27 +23,30 @@ namespace Ryujinx
 
                     if (RomFsFiles.Length > 0)
                     {
-                        Console.WriteLine("Loading as cart with RomFS.");
+                        Logging.Info("Loading as cart with RomFS.");
 
+                        Console.Title += " - Cart (with RomFS) - " + args[0];
                         Ns.Os.LoadCart(args[0], RomFsFiles[0]);
                     }
                     else
                     {
-                        Console.WriteLine("Loading as cart WITHOUT RomFS.");
+                        Logging.Info("Loading as cart WITHOUT RomFS.");
 
+                        Console.Title += " - Cart (without RomFS) - " + args[0];
                         Ns.Os.LoadCart(args[0]);
                     }
                 }
                 else if (File.Exists(args[0]))
                 {
-                    Console.WriteLine("Loading as homebrew.");
+                    Logging.Info("Loading as homebrew.");
 
+                    Console.Title += " - Homebrew - " + args[0];
                     Ns.Os.LoadProgram(args[0]);
                 }
             }
             else
             {
-                Console.WriteLine("Please specify the folder with the NSOs/IStorage or a NSO/NRO.");
+                Logging.Error("Please specify the folder with the NSOs/IStorage or a NSO/NRO.");
             }
 
             using (GLScreen Screen = new GLScreen(Ns, Renderer))
diff --git a/Ryujinx/Logging.cs b/Ryujinx/Logging.cs
new file mode 100644
index 0000000000..bdb6ad06ae
--- /dev/null
+++ b/Ryujinx/Logging.cs
@@ -0,0 +1,128 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Text;
+
+namespace Ryujinx
+{
+    public static class Logging
+    {
+        private static Stopwatch ExecutionTime = new Stopwatch();
+        private static string LogFileName = "Ryujinx.log";
+
+        public static bool EnableInfo = true;
+        public static bool EnableTrace = true;
+        public static bool EnableDebug = true;
+        public static bool EnableWarn = true;
+        public static bool EnableError = true;
+        public static bool EnableFatal = true;
+        public static bool EnableLogFile = false;
+
+        static Logging()
+        {
+            ExecutionTime.Start();
+
+            if (File.Exists(LogFileName)) File.Delete(LogFileName);
+        }
+
+        public static string GetExecutionTime()
+        {
+            return ExecutionTime.ElapsedMilliseconds.ToString().PadLeft(8, '0') + "ms";
+        }
+
+        private static void LogFile(string Message)
+        {
+            if (EnableLogFile)
+            {
+                using (StreamWriter Writer = File.AppendText(LogFileName))
+                {
+                    Writer.WriteLine(Message);
+                }
+            }
+        }
+
+        public static void Info(string Message)
+        {
+            if (EnableInfo)
+            {
+                string Text = $"{GetExecutionTime()} | INFO  > {Message}";
+
+                Console.ForegroundColor = ConsoleColor.White;
+                Console.WriteLine(Text.PadLeft(Text.Length + 1, ' '));
+                Console.ResetColor();
+
+                LogFile(Text);
+            }
+        }
+
+        public static void Trace(string Message)
+        {
+            if (EnableTrace)
+            {
+                string Text = $"{GetExecutionTime()} | TRACE > {Message}";
+
+                Console.ForegroundColor = ConsoleColor.DarkGray;
+                Console.WriteLine(Text.PadLeft(Text.Length + 1, ' '));
+                Console.ResetColor();
+
+                LogFile(Text);
+            }
+        }
+
+        public static void Debug(string Message)
+        {
+            if (EnableDebug)
+            {
+                string Text = $"{GetExecutionTime()} | DEBUG > {Message}";
+
+                Console.ForegroundColor = ConsoleColor.Gray;
+                Console.WriteLine(Text.PadLeft(Text.Length + 1, ' '));
+                Console.ResetColor();
+
+                LogFile(Text);
+            }
+        }
+
+        public static void Warn(string Message)
+        {
+            if (EnableWarn)
+            {
+                string Text = $"{GetExecutionTime()} | WARN  > {Message}";
+
+                Console.ForegroundColor = ConsoleColor.Yellow;
+                Console.WriteLine(Text.PadLeft(Text.Length + 1, ' '));
+                Console.ResetColor();
+
+                LogFile(Text);
+            }
+        }
+
+        public static void Error(string Message)
+        {
+            if (EnableError)
+            {
+                string Text = $"{GetExecutionTime()} | ERROR > {Message}";
+
+                Console.ForegroundColor = ConsoleColor.Red;
+                Console.WriteLine(Text.PadLeft(Text.Length + 1, ' '));
+                Console.ResetColor();
+
+                LogFile(Text);
+            }
+        }
+
+        public static void Fatal(string Message)
+        {
+            if (EnableFatal)
+            {
+                string Text = $"{GetExecutionTime()} | FATAL > {Message}";
+
+                Console.ForegroundColor = ConsoleColor.Magenta;
+                Console.WriteLine(Text.PadLeft(Text.Length + 1, ' '));
+                Console.ResetColor();
+
+                LogFile(Text);
+            }
+        }
+    }
+}
diff --git a/Ryujinx/OsHle/Ipc/IpcHandler.cs b/Ryujinx/OsHle/Ipc/IpcHandler.cs
index 4e57889a4c..c8b26dba67 100644
--- a/Ryujinx/OsHle/Ipc/IpcHandler.cs
+++ b/Ryujinx/OsHle/Ipc/IpcHandler.cs
@@ -262,6 +262,8 @@ namespace Ryujinx.OsHle.Ipc
                         }
                     }
 
+                    Logging.Debug($"IpcMessage: {DbgServiceName}");
+
                     if (ProcReq != null)
                     {
                         using (MemoryStream ResMS = new MemoryStream())
diff --git a/Ryujinx/OsHle/Objects/AudIAudioOut.cs b/Ryujinx/OsHle/Objects/AudIAudioOut.cs
index 965e840d45..c04a23ad1d 100644
--- a/Ryujinx/OsHle/Objects/AudIAudioOut.cs
+++ b/Ryujinx/OsHle/Objects/AudIAudioOut.cs
@@ -22,7 +22,7 @@ namespace Ryujinx.OsHle.Objects
 
         //IAudioOut
         private static AudioOutState State = AudioOutState.Stopped;
-        private static List<long> KeysQueue = new List<long>();
+        private static Queue<long> KeysQueue = new Queue<long>();
 
         //OpenAL
         private static bool OpenALInstalled = true;
@@ -48,9 +48,9 @@ namespace Ryujinx.OsHle.Objects
                 { 
                     AudioCtx = new AudioContext(); //Create the audio context
                 }
-                catch (Exception ex)
+                catch (Exception)
                 {
-                    Console.WriteLine("OpenAL Error! PS: Install OpenAL Core SDK!");
+                    Logging.Warning("OpenAL Error! PS: Install OpenAL Core SDK!");
                     OpenALInstalled = false;
                 }
 
@@ -82,7 +82,7 @@ namespace Ryujinx.OsHle.Objects
         {
             long BufferId = Context.RequestData.ReadInt64();
 
-            KeysQueue.Insert(0, BufferId);
+            KeysQueue.Enqueue(BufferId);
 
             byte[] AudioOutBuffer = AMemoryHelper.ReadBytes(Context.Memory, Context.Request.SendBuff[0].Position, 0x28);
             using (MemoryStream MS = new MemoryStream(AudioOutBuffer))
@@ -125,13 +125,9 @@ namespace Ryujinx.OsHle.Objects
         {
             long TempKey = 0;
 
-            if (KeysQueue.Count > 0)
-            {
-                TempKey = KeysQueue[KeysQueue.Count - 1];
-                KeysQueue.Remove(KeysQueue[KeysQueue.Count - 1]);
-            }
+            if (KeysQueue.Count > 0) TempKey = KeysQueue.Dequeue();
 
-            AMemoryHelper.WriteBytes(Context.Memory, Context.Request.ReceiveBuff[0].Position, System.BitConverter.GetBytes(TempKey));
+            AMemoryHelper.WriteBytes(Context.Memory, Context.Request.ReceiveBuff[0].Position, BitConverter.GetBytes(TempKey));
 
             Context.ResponseData.Write((int)TempKey);
 
diff --git a/Ryujinx/OsHle/Services/ServiceNvDrv.cs b/Ryujinx/OsHle/Services/ServiceNvDrv.cs
index f410e1ab0c..405eace2b9 100644
--- a/Ryujinx/OsHle/Services/ServiceNvDrv.cs
+++ b/Ryujinx/OsHle/Services/ServiceNvDrv.cs
@@ -563,7 +563,7 @@ namespace Ryujinx.OsHle.Services
                 NvMap.Kind    = Kind;
             }
 
-            Console.WriteLine($"NvMapIocAlloc at {NvMap.Address:x16}");
+            Logging.Debug($"NvMapIocAlloc at {NvMap.Address:x16}");
 
             return 0;
         }
diff --git a/Ryujinx/OsHle/Svc/SvcSystem.cs b/Ryujinx/OsHle/Svc/SvcSystem.cs
index fa39f51812..3c541381b6 100644
--- a/Ryujinx/OsHle/Svc/SvcSystem.cs
+++ b/Ryujinx/OsHle/Svc/SvcSystem.cs
@@ -121,7 +121,7 @@ namespace Ryujinx.OsHle.Svc
 
             string Str = AMemoryHelper.ReadAsciiString(Memory, Position, (int)Size);
 
-            Console.WriteLine($"SvcOutputDebugString: {Str}");
+            Logging.Info($"SvcOutputDebugString: {Str}");
 
             Registers.X0 = (int)SvcResult.Success;
         }