diff --git a/Ryujinx.Common/Logging/Targets/AsyncLogTargetWrapper.cs b/Ryujinx.Common/Logging/Targets/AsyncLogTargetWrapper.cs
new file mode 100644
index 0000000000..7528275590
--- /dev/null
+++ b/Ryujinx.Common/Logging/Targets/AsyncLogTargetWrapper.cs
@@ -0,0 +1,81 @@
+using System;
+using System.Collections.Concurrent;
+using System.Threading;
+
+namespace Ryujinx.Common.Logging
+{
+ public enum AsyncLogTargetOverflowAction
+ {
+ ///
+ /// Block until there's more room in the queue
+ ///
+ Block = 0,
+
+ ///
+ /// Discard the overflowing item
+ ///
+ Discard = 1
+ }
+
+ public class AsyncLogTargetWrapper : ILogTarget
+ {
+ private ILogTarget _target;
+
+ private Thread _messageThread;
+
+ private BlockingCollection _messageQueue;
+
+ private AsyncLogTargetOverflowAction _overflowAction;
+
+ public AsyncLogTargetWrapper(ILogTarget target)
+ : this(target, -1, AsyncLogTargetOverflowAction.Block)
+ { }
+
+ public AsyncLogTargetWrapper(ILogTarget target, int queueLimit, AsyncLogTargetOverflowAction overflowAction)
+ {
+ _target = target;
+
+ _overflowAction = overflowAction;
+
+ _messageQueue = new BlockingCollection(queueLimit);
+
+ _messageThread = new Thread(() => {
+ while (!_messageQueue.IsCompleted)
+ {
+ try
+ {
+ _target.Log(this, _messageQueue.Take());
+ }
+ catch (InvalidOperationException)
+ {
+ // IOE means that Take() was called on a completed collection.
+ // Some other thread can call CompleteAdding after we pass the
+ // IsCompleted check but before we call Take.
+ // We can simply catch the exception since the loop will break
+ // on the next iteration.
+ }
+ }
+ });
+
+ _messageThread.IsBackground = true;
+ _messageThread.Start();
+ }
+
+ public void Log(object sender, LogEventArgs e)
+ {
+ if (!_messageQueue.IsAddingCompleted)
+ {
+ if(!_messageQueue.TryAdd(e) && _overflowAction == AsyncLogTargetOverflowAction.Block)
+ {
+ _messageQueue.Add(e);
+ }
+ }
+ }
+
+ public void Dispose()
+ {
+ _messageQueue.CompleteAdding();
+ _messageThread.Join();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Ryujinx.Common/Logging/Targets/ConsoleLogTarget.cs b/Ryujinx.Common/Logging/Targets/ConsoleLogTarget.cs
new file mode 100644
index 0000000000..18c554a121
--- /dev/null
+++ b/Ryujinx.Common/Logging/Targets/ConsoleLogTarget.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Text;
+
+namespace Ryujinx.Common.Logging
+{
+ public class ConsoleLogTarget : ILogTarget
+ {
+ private static readonly ConcurrentDictionary _logColors;
+
+ static ConsoleLogTarget()
+ {
+ _logColors = new ConcurrentDictionary {
+ [ LogLevel.Stub ] = ConsoleColor.DarkGray,
+ [ LogLevel.Info ] = ConsoleColor.White,
+ [ LogLevel.Warning ] = ConsoleColor.Yellow,
+ [ LogLevel.Error ] = ConsoleColor.Red
+ };
+ }
+
+ public void Log(object sender, LogEventArgs e)
+ {
+ StringBuilder sb = new StringBuilder();
+
+ sb.AppendFormat(@"{0:hh\:mm\:ss\.fff}", e.Time);
+ sb.Append(" | ");
+ sb.AppendFormat("{0:d4}", e.ThreadId);
+ sb.Append(' ');
+ sb.Append(e.Message);
+
+ if (e.Data != null)
+ {
+ PropertyInfo[] props = e.Data.GetType().GetProperties();
+
+ sb.Append(' ');
+
+ foreach (var prop in props)
+ {
+ sb.Append(prop.Name);
+ sb.Append(": ");
+ sb.Append(prop.GetValue(e.Data));
+ sb.Append(" - ");
+ }
+
+ // We remove the final '-' from the string
+ if (props.Length > 0)
+ {
+ sb.Remove(sb.Length - 3, 3);
+ }
+ }
+
+ if (_logColors.TryGetValue(e.Level, out ConsoleColor color))
+ {
+ Console.ForegroundColor = color;
+
+ Console.WriteLine(sb.ToString());
+
+ Console.ResetColor();
+ }
+ else
+ {
+ Console.WriteLine(sb.ToString());
+ }
+ }
+
+ public void Dispose()
+ {
+ Console.ResetColor();
+ }
+ }
+}
diff --git a/Ryujinx.Common/Logging/Targets/FileLogTarget.cs b/Ryujinx.Common/Logging/Targets/FileLogTarget.cs
new file mode 100644
index 0000000000..153106c33b
--- /dev/null
+++ b/Ryujinx.Common/Logging/Targets/FileLogTarget.cs
@@ -0,0 +1,66 @@
+using System.IO;
+using System.Reflection;
+using System.Text;
+
+namespace Ryujinx.Common.Logging
+{
+ public class FileLogTarget : ILogTarget
+ {
+ private StreamWriter _logWriter;
+
+ public string Path { get; private set; }
+
+ public FileLogTarget(string path)
+ : this(path, FileShare.Read, FileMode.Append)
+ { }
+
+ public FileLogTarget(string path, FileShare fileShare, FileMode fileMode)
+ {
+ this.Path = path;
+
+ this._logWriter = new StreamWriter(File.Open(path, fileMode, FileAccess.Write, fileShare));
+ }
+
+ public void Log(object sender, LogEventArgs e)
+ {
+ StringBuilder sb = new StringBuilder();
+
+ sb.AppendFormat(@"{0:hh\:mm\:ss\.fff}", e.Time);
+ sb.Append(" | ");
+ sb.AppendFormat("{0:d4}", e.ThreadId);
+ sb.Append(' ');
+ sb.Append(e.Message);
+
+ if (e.Data != null)
+ {
+ PropertyInfo[] props = e.Data.GetType().GetProperties();
+
+ sb.Append(' ');
+
+ foreach (var prop in props)
+ {
+ sb.Append(prop.Name);
+ sb.Append(": ");
+ sb.Append(prop.GetValue(e.Data));
+ sb.Append(" - ");
+ }
+
+ // We remove the final '-' from the string
+ if (props.Length > 0)
+ {
+ sb.Remove(sb.Length - 3, 3);
+ }
+ }
+
+ _logWriter.WriteLine(sb.ToString());
+ _logWriter.Flush();
+ }
+
+ public void Dispose()
+ {
+ _logWriter.WriteLine("---- End of Log ----");
+ _logWriter.Flush();
+ _logWriter.Dispose();
+ }
+ }
+}
diff --git a/Ryujinx.Common/Logging/Targets/ILogTarget.cs b/Ryujinx.Common/Logging/Targets/ILogTarget.cs
new file mode 100644
index 0000000000..6143b2bf93
--- /dev/null
+++ b/Ryujinx.Common/Logging/Targets/ILogTarget.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace Ryujinx.Common.Logging
+{
+ public interface ILogTarget : IDisposable
+ {
+ void Log(object sender, LogEventArgs e);
+ }
+}
diff --git a/Ryujinx.Common/Logging/Targets/JsonLogTarget.cs b/Ryujinx.Common/Logging/Targets/JsonLogTarget.cs
new file mode 100644
index 0000000000..0cca5a79b6
--- /dev/null
+++ b/Ryujinx.Common/Logging/Targets/JsonLogTarget.cs
@@ -0,0 +1,15 @@
+namespace Ryujinx.Common.Logging
+{
+ public class JsonLogTarget : ILogTarget
+ {
+ public void Log(object sender, LogEventArgs e)
+ {
+
+ }
+
+ public void Dispose()
+ {
+
+ }
+ }
+}
diff --git a/Ryujinx.HLE/Switch.cs b/Ryujinx.HLE/Switch.cs
index d661b273ad..5172c6a986 100644
--- a/Ryujinx.HLE/Switch.cs
+++ b/Ryujinx.HLE/Switch.cs
@@ -111,9 +111,9 @@ namespace Ryujinx.HLE
{
if (disposing)
{
- System.Dispose();
+ //System.Dispose();
- VsyncEvent.Dispose();
+ //VsyncEvent.Dispose();
}
}
}
diff --git a/Ryujinx/Program.cs b/Ryujinx/Program.cs
index 335aa0ea8e..8492e58a30 100644
--- a/Ryujinx/Program.cs
+++ b/Ryujinx/Program.cs
@@ -10,6 +10,9 @@ namespace Ryujinx
{
class Program
{
+ static ILogTarget _fileTarget;
+ static ILogTarget _consoleTarget;
+
static void Main(string[] args)
{
Console.Title = "Ryujinx Console";
@@ -22,7 +25,11 @@ namespace Ryujinx
Config.Read(device);
- Logger.Updated += Log.LogMessage;
+ _fileTarget = new AsyncLogTargetWrapper(new FileLogTarget("Ryujinx.log"), 1000, AsyncLogTargetOverflowAction.Block);
+ _consoleTarget = new AsyncLogTargetWrapper(new ConsoleLogTarget(), 1000, AsyncLogTargetOverflowAction.Block);
+
+ Logger.Updated += _fileTarget.Log;
+ Logger.Updated += _consoleTarget.Log;
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit;
@@ -92,7 +99,8 @@ namespace Ryujinx
private static void CurrentDomain_ProcessExit(object sender, EventArgs e)
{
- Log.Close();
+ _fileTarget.Dispose();
+ _consoleTarget.Dispose();
}
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
@@ -103,7 +111,8 @@ namespace Ryujinx
if (e.IsTerminating)
{
- Log.Close();
+ _fileTarget.Dispose();
+ _consoleTarget.Dispose();
}
}
diff --git a/Ryujinx/Ui/Log.cs b/Ryujinx/Ui/Log.cs
deleted file mode 100644
index 5daae14026..0000000000
--- a/Ryujinx/Ui/Log.cs
+++ /dev/null
@@ -1,140 +0,0 @@
-using Ryujinx.Common.Logging;
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.IO;
-using System.Reflection;
-using System.Text;
-using System.Threading;
-
-namespace Ryujinx
-{
- static class Log
- {
- private static readonly string _path;
-
- private static StreamWriter _logWriter;
-
- private static Thread _messageThread;
-
- private static BlockingCollection _messageQueue;
-
- private static Dictionary _logColors;
-
- static Log()
- {
- _logColors = new Dictionary()
- {
- { LogLevel.Stub, ConsoleColor.DarkGray },
- { LogLevel.Info, ConsoleColor.White },
- { LogLevel.Warning, ConsoleColor.Yellow },
- { LogLevel.Error, ConsoleColor.Red }
- };
-
- _messageQueue = new BlockingCollection(10);
-
- _messageThread = new Thread(() =>
- {
- while (!_messageQueue.IsCompleted)
- {
- try
- {
- PrintLog(_messageQueue.Take());
- }
- catch (InvalidOperationException)
- {
- // IOE means that Take() was called on a completed collection.
- // Some other thread can call CompleteAdding after we pass the
- // IsCompleted check but before we call Take.
- // We can simply catch the exception since the loop will break
- // on the next iteration.
- }
- }
- });
-
- _path = Path.Combine(Environment.CurrentDirectory, "Ryujinx.log");
-
- if (Logger.EnableFileLog)
- {
- _logWriter = new StreamWriter(File.Open(_path,FileMode.Create, FileAccess.Write));
- }
-
- _messageThread.IsBackground = true;
- _messageThread.Start();
- }
-
- private static void PrintLog(LogEventArgs e)
- {
- StringBuilder sb = new StringBuilder();
-
- sb.AppendFormat(@"{0:hh\:mm\:ss\.fff}", e.Time);
- sb.Append(" | ");
- sb.AppendFormat("{0:d4}", e.ThreadId);
- sb.Append(' ');
- sb.Append(e.Message);
-
- if (e.Data != null)
- {
- PropertyInfo[] props = e.Data.GetType().GetProperties();
-
- sb.Append(' ');
-
- foreach (var prop in props)
- {
- sb.Append(prop.Name);
- sb.Append(": ");
- sb.Append(prop.GetValue(e.Data));
- sb.Append(" - ");
- }
-
- // We remove the final '-' from the string
- if (props.Length > 0)
- {
- sb.Remove(sb.Length - 3, 3);
- }
- }
-
- string message = sb.ToString();
-
- if (_logColors.TryGetValue(e.Level, out ConsoleColor color))
- {
- Console.ForegroundColor = color;
-
- Console.WriteLine(message);
-
- Console.ResetColor();
- }
- else
- {
- Console.WriteLine(message);
- }
-
- if (Logger.EnableFileLog)
- {
- _logWriter.WriteLine(message);
- }
- }
-
- public static void LogMessage(object sender, LogEventArgs e)
- {
- if (!_messageQueue.IsAddingCompleted)
- {
- _messageQueue.Add(e);
- }
- }
-
- public static void Close()
- {
- _messageQueue.CompleteAdding();
-
- _messageThread.Join();
-
- if (Logger.EnableFileLog)
- {
- _logWriter.Flush();
- _logWriter.Close();
- _logWriter.Dispose();
- }
- }
- }
-}