From 1c4c5fb4a345f3073c7bbdce6d1e92a3954a4ce8 Mon Sep 17 00:00:00 2001
From: nattthebear <goyuken@gmail.com>
Date: Sat, 20 Feb 2016 11:54:44 -0500
Subject: [PATCH] Rough in some code for BizInvoke in mono

---
 .../BizHawk.Emulation.Common.csproj           |  2 +-
 ...ver.cs => DynamicLibraryImportResolver.cs} | 32 +++++++++++++++++--
 .../Consoles/Nintendo/QuickNES/QuickNES.cs    |  4 +--
 3 files changed, 32 insertions(+), 6 deletions(-)
 rename BizHawk.Emulation.Common/BizInvoke/{Win32LibraryImportResolver.cs => DynamicLibraryImportResolver.cs} (56%)

diff --git a/BizHawk.Emulation.Common/BizHawk.Emulation.Common.csproj b/BizHawk.Emulation.Common/BizHawk.Emulation.Common.csproj
index 17510a2b30..4389a2effe 100644
--- a/BizHawk.Emulation.Common/BizHawk.Emulation.Common.csproj
+++ b/BizHawk.Emulation.Common/BizHawk.Emulation.Common.csproj
@@ -65,8 +65,8 @@
     <Compile Include="Base Implementations\TraceBuffer.cs" />
     <Compile Include="BinaryQuickSerializer.cs" />
     <Compile Include="BizInvoke\BizInvoker.cs" />
+    <Compile Include="BizInvoke\DynamicLibraryImportResolver.cs" />
     <Compile Include="BizInvoke\IImportResolver.cs" />
-    <Compile Include="BizInvoke\Win32LibraryImportResolver.cs" />
     <Compile Include="CodeDataLog.cs" />
     <Compile Include="CoreAttributes.cs" />
     <Compile Include="CoreComms.cs" />
diff --git a/BizHawk.Emulation.Common/BizInvoke/Win32LibraryImportResolver.cs b/BizHawk.Emulation.Common/BizInvoke/DynamicLibraryImportResolver.cs
similarity index 56%
rename from BizHawk.Emulation.Common/BizInvoke/Win32LibraryImportResolver.cs
rename to BizHawk.Emulation.Common/BizInvoke/DynamicLibraryImportResolver.cs
index 5bc21d8763..a437e8a6cd 100644
--- a/BizHawk.Emulation.Common/BizInvoke/Win32LibraryImportResolver.cs
+++ b/BizHawk.Emulation.Common/BizInvoke/DynamicLibraryImportResolver.cs
@@ -6,27 +6,40 @@ using System.Runtime.InteropServices;
 
 namespace BizHawk.Emulation.Common.BizInvoke
 {
-	public class Win32LibraryImportResolver : IImportResolver, IDisposable
+	public class DynamicLibraryImportResolver : IImportResolver, IDisposable
 	{
 		private IntPtr _p;
 
-		public Win32LibraryImportResolver(string dllName)
+		public DynamicLibraryImportResolver(string dllName)
 		{
+#if !MONO
 			_p = Win32.LoadLibrary(dllName);
+#else
+			// TODO: how can we read name remaps out of app.confg <dllmap> ?
+			_p = Libdl.dlopen(dllName, Libdl.RTLD_NOW);
+#endif
 			if (_p == IntPtr.Zero)
 				throw new InvalidOperationException("LoadLibrary returned NULL");
 		}
 
 		public IntPtr Resolve(string entryPoint)
 		{
+#if !MONO
 			return Win32.GetProcAddress(_p, entryPoint);
+#else
+			return Libdl.dlsym(_p, entryPoint);
+#endif
 		}
 
 		private void Free()
 		{
 			if (_p != IntPtr.Zero)
 			{
+#if !MONO
 				Win32.FreeLibrary(_p);
+#else
+				Libdl.dlclose(_p);
+#endif
 				_p = IntPtr.Zero;
 			}
 		}
@@ -37,11 +50,12 @@ namespace BizHawk.Emulation.Common.BizInvoke
 			GC.SuppressFinalize(this);
 		}
 
-		~Win32LibraryImportResolver()
+		~DynamicLibraryImportResolver()
 		{
 			Free();
 		}
 
+#if !MONO
 		private static class Win32
 		{
 			[DllImport("kernel32.dll")]
@@ -51,5 +65,17 @@ namespace BizHawk.Emulation.Common.BizInvoke
 			[DllImport("kernel32.dll")]
 			public static extern bool FreeLibrary(IntPtr hModule);
 		}
+#else
+		private static class Libdl
+		{
+			[DllImport("libdl.so")]
+			public static extern IntPtr dlopen(string filename, int flags);
+			[DllImport("libdl.so")]
+			public static extern IntPtr dlsym(IntPtr handle, string symbol);
+			[DllImport("libdl.so")]
+			public static extern int dlclose(IntPtr handle);
+			public const int RTLD_NOW = 2;
+		}
+#endif
 	}
 }
diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.cs
index c52fc7934b..2aa59b5d6e 100644
--- a/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.cs
@@ -28,12 +28,12 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES
 		IStatable, IDebuggable, ISettable<QuickNES.QuickNESSettings, QuickNES.QuickNESSyncSettings>, Cores.Nintendo.NES.INESPPUViewable
 	{
 		static readonly LibQuickNES QN;
-		static readonly Win32LibraryImportResolver Resolver;
+		static readonly DynamicLibraryImportResolver Resolver;
 
 
 		static QuickNES()
 		{
-			Resolver = new Win32LibraryImportResolver(LibQuickNES.dllname);
+			Resolver = new DynamicLibraryImportResolver(LibQuickNES.dllname);
 			QN = BizInvoker.GetInvoker<LibQuickNES>(Resolver);
 		}