diff --git a/BizHawk.Client.ApiHawk/Classes/ExternalToolManager.cs b/BizHawk.Client.ApiHawk/Classes/ExternalToolManager.cs
index 8565448739..01c1c104be 100644
--- a/BizHawk.Client.ApiHawk/Classes/ExternalToolManager.cs
+++ b/BizHawk.Client.ApiHawk/Classes/ExternalToolManager.cs
@@ -85,7 +85,7 @@ namespace BizHawk.Client.ApiHawk
try
{
- BizHawk.Common.Win32Hacks.RemoveMOTW(fileName);
+ BizHawk.Common.MotWHack.RemoveMOTW(fileName);
var externalToolFile = Assembly.LoadFrom(fileName);
object[] attributes = externalToolFile.GetCustomAttributes(typeof(BizHawkExternalToolAttribute), false);
if (attributes != null && attributes.Count() == 1)
diff --git a/BizHawk.Client.Common/lua/LuaSandbox.cs b/BizHawk.Client.Common/lua/LuaSandbox.cs
index 9559949d10..ccf28bc50e 100644
--- a/BizHawk.Client.Common/lua/LuaSandbox.cs
+++ b/BizHawk.Client.Common/lua/LuaSandbox.cs
@@ -21,13 +21,18 @@ namespace BizHawk.Client.Common
private string _currentDirectory;
- [DllImport("kernel32.dll", SetLastError = true)]
- static extern bool SetCurrentDirectoryW(byte* lpPathName);
- [DllImport("kernel32.dll", SetLastError=true)]
- static extern uint GetCurrentDirectoryW(uint nBufferLength, byte* pBuffer);
-
private bool CoolSetCurrentDirectory(string path, string currDirSpeedHack = null)
{
+ static string CoolGetCurrentDirectory()
+ {
+ if (OSTailoredCode.IsUnixHost) return Environment.CurrentDirectory;
+
+ //HACK to bypass Windows security checks triggered by *getting* the current directory (why), which only slow us down
+ var buf = new byte[32768];
+ fixed (byte* pBuf = &buf[0])
+ return System.Text.Encoding.Unicode.GetString(buf, 0, 2 * (int) Win32Imports.GetCurrentDirectoryW(32767, pBuf));
+ }
+
string target = $"{_currentDirectory}\\";
// first we'll bypass it with a general hack: don't do any setting if the value's already there (even at the OS level, setting the directory can be slow)
@@ -56,17 +61,7 @@ namespace BizHawk.Client.Common
//HACK to bypass Windows security checks triggered by setting the current directory, which only slow us down
fixed (byte* pstr = &System.Text.Encoding.Unicode.GetBytes($"{target}\0")[0])
- return SetCurrentDirectoryW(pstr);
- }
-
- private string CoolGetCurrentDirectory()
- {
- if (OSTailoredCode.IsUnixHost) return Environment.CurrentDirectory;
-
- //HACK to bypass Windows security checks triggered by *getting* the current directory (why), which only slow us down
- var buf = new byte[32768];
- fixed (byte* pBuf = &buf[0])
- return System.Text.Encoding.Unicode.GetString(buf, 0, 2 * (int) GetCurrentDirectoryW(32767, pBuf));
+ return Win32Imports.SetCurrentDirectoryW(pstr);
}
private void Sandbox(Action callback, Action exceptionCallback)
diff --git a/BizHawk.Client.EmuHawk/AVOut/AviWriter.cs b/BizHawk.Client.EmuHawk/AVOut/AviWriter.cs
index 706382c3ec..4501278523 100644
--- a/BizHawk.Client.EmuHawk/AVOut/AviWriter.cs
+++ b/BizHawk.Client.EmuHawk/AVOut/AviWriter.cs
@@ -5,6 +5,7 @@ using System.Runtime.InteropServices;
using System.Windows.Forms;
using BizHawk.Client.Common;
+using BizHawk.Common;
using BizHawk.Emulation.Common;
// some helpful p/invoke from http://www.codeproject.com/KB/audio-video/Motion_Detection.aspx?msg=1142967
@@ -434,20 +435,12 @@ namespace BizHawk.Client.EmuHawk
return ret;
}
- [DllImport("kernel32.dll", SetLastError = true)]
- public static extern bool HeapFree(IntPtr hHeap, uint dwFlags, IntPtr lpMem);
-
- [DllImport("kernel32.dll", SetLastError = true)]
- public static extern IntPtr GetProcessHeap();
-
- [DllImport("kernel32.dll", SetLastError = false)]
- public static extern IntPtr HeapAlloc(IntPtr hHeap, uint dwFlags, int dwBytes);
-
public static void DeallocateAVICOMPRESSOPTIONS(ref Win32.AVICOMPRESSOPTIONS opts)
{
- // test: increase stability by never freeing anything, ever
- // if (opts.lpParms != IntPtr.Zero) CodecToken.HeapFree(CodecToken.GetProcessHeap(), 0, opts.lpParms);
- // if (opts.lpFormat != IntPtr.Zero) CodecToken.HeapFree(CodecToken.GetProcessHeap(), 0, opts.lpFormat);
+#if false // test: increase stability by never freeing anything, ever
+ if (opts.lpParms != IntPtr.Zero) Win32Imports.HeapFree(Win32Imports.GetProcessHeap(), 0, opts.lpParms);
+ if (opts.lpFormat != IntPtr.Zero) Win32Imports.HeapFree(Win32Imports.GetProcessHeap(), 0, opts.lpFormat);
+#endif
opts.lpParms = IntPtr.Zero;
opts.lpFormat = IntPtr.Zero;
}
@@ -457,12 +450,12 @@ namespace BizHawk.Client.EmuHawk
opts = comprOptions;
if (opts.cbParms != 0)
{
- opts.lpParms = HeapAlloc(GetProcessHeap(), 0, opts.cbParms);
+ opts.lpParms = Win32Imports.HeapAlloc(Win32Imports.GetProcessHeap(), 0, opts.cbParms);
Marshal.Copy(Parms, 0, opts.lpParms, opts.cbParms);
}
if (opts.cbFormat != 0)
{
- opts.lpFormat = HeapAlloc(GetProcessHeap(), 0, opts.cbFormat);
+ opts.lpFormat = Win32Imports.HeapAlloc(Win32Imports.GetProcessHeap(), 0, opts.cbFormat);
Marshal.Copy(Format, 0, opts.lpFormat, opts.cbFormat);
}
}
diff --git a/BizHawk.Client.EmuHawk/CustomControls/InputWidget.cs b/BizHawk.Client.EmuHawk/CustomControls/InputWidget.cs
index 9599e544e2..0b02272bf7 100644
--- a/BizHawk.Client.EmuHawk/CustomControls/InputWidget.cs
+++ b/BizHawk.Client.EmuHawk/CustomControls/InputWidget.cs
@@ -62,12 +62,9 @@ namespace BizHawk.Client.EmuHawk
}
}
- [DllImport("user32")]
- private static extern bool HideCaret(IntPtr hWnd);
-
protected override void OnMouseClick(MouseEventArgs e)
{
- if (!OSTailoredCode.IsUnixHost) HideCaret(Handle);
+ if (!OSTailoredCode.IsUnixHost) Win32Imports.HideCaret(Handle);
base.OnMouseClick(e);
}
@@ -259,7 +256,7 @@ namespace BizHawk.Client.EmuHawk
protected override void OnGotFocus(EventArgs e)
{
- if (!OSTailoredCode.IsUnixHost) HideCaret(Handle);
+ if (!OSTailoredCode.IsUnixHost) Win32Imports.HideCaret(Handle);
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
diff --git a/BizHawk.Client.EmuHawk/EmuHawkUtil.cs b/BizHawk.Client.EmuHawk/EmuHawkUtil.cs
index ca0879fd32..9d1ae1ad32 100644
--- a/BizHawk.Client.EmuHawk/EmuHawkUtil.cs
+++ b/BizHawk.Client.EmuHawk/EmuHawkUtil.cs
@@ -1,8 +1,11 @@
using System;
using System.Drawing;
+using System.IO;
+using System.Text;
using System.Windows.Forms;
using BizHawk.Client.Common;
using BizHawk.Client.EmuHawk.CustomControls;
+using BizHawk.Common;
using BizHawk.Emulation.Common;
using Cores = BizHawk.Emulation.Cores;
@@ -49,5 +52,21 @@ namespace BizHawk.Client.EmuHawk
return true;
}
+
+ /// http://stackoverflow.com/questions/139010/how-to-resolve-a-lnk-in-c-sharp
+ public static string ResolveShortcut(string filename)
+ {
+ if (filename.Contains("|") || OSTailoredCode.IsUnixHost || !".lnk".Equals(Path.GetExtension(filename), StringComparison.InvariantCultureIgnoreCase)) return filename; // archive internal files are never shortcuts (and choke when analyzing any further)
+ var link = new ShellLinkImports.ShellLink();
+ const uint STGM_READ = 0;
+ ((ShellLinkImports.IPersistFile) link).Load(filename, STGM_READ);
+#if false
+ // TODO: if I can get hold of the hwnd call resolve first. This handles moved and renamed files.
+ ((ShellLinkImports.IShellLinkW) link).Resolve(hwnd, 0);
+#endif
+ var sb = new StringBuilder(Win32Imports.MAX_PATH);
+ ((ShellLinkImports.IShellLinkW) link).GetPath(sb, sb.Capacity, out _, 0);
+ return sb.Length == 0 ? filename : sb.ToString(); // maybe? what if it's invalid?
+ }
}
}
diff --git a/BizHawk.Client.EmuHawk/Input/GamePad360.cs b/BizHawk.Client.EmuHawk/Input/GamePad360.cs
index 2d77a44485..e28a5d6833 100644
--- a/BizHawk.Client.EmuHawk/Input/GamePad360.cs
+++ b/BizHawk.Client.EmuHawk/Input/GamePad360.cs
@@ -16,9 +16,6 @@ namespace BizHawk.Client.EmuHawk
private static readonly List _devices = new List();
private static readonly bool _isAvailable;
- [DllImport("kernel32", SetLastError = true, EntryPoint = "GetProcAddress")]
- static extern IntPtr GetProcAddressOrdinal(IntPtr hModule, IntPtr procName);
-
delegate uint XInputGetStateExProcDelegate(uint dwUserIndex, out XINPUT_STATE state);
static bool HasGetInputStateEx;
@@ -61,7 +58,7 @@ namespace BizHawk.Client.EmuHawk
{
if (HasGetInputStateEx)
{
- IntPtr proc = GetProcAddressOrdinal(LibraryHandle, new IntPtr(100));
+ var proc = BizHawk.Common.Win32Imports.GetProcAddressOrdinal(LibraryHandle, new IntPtr(100));
XInputGetStateExProc = (XInputGetStateExProcDelegate)Marshal.GetDelegateForFunctionPointer(proc, typeof(XInputGetStateExProcDelegate));
}
diff --git a/BizHawk.Client.EmuHawk/Input/KeyboardMapping.cs b/BizHawk.Client.EmuHawk/Input/KeyboardMapping.cs
index 4e73b5450f..69990fb286 100644
--- a/BizHawk.Client.EmuHawk/Input/KeyboardMapping.cs
+++ b/BizHawk.Client.EmuHawk/Input/KeyboardMapping.cs
@@ -1,6 +1,5 @@
using System.Collections.Generic;
using System.Linq;
-using System.Runtime.InteropServices;
using System.Windows.Forms;
using BizHawk.Client.Common;
using SlimDX.DirectInput;
@@ -9,16 +8,13 @@ namespace BizHawk.Client.EmuHawk
{
internal static class KeyboardMapping
{
- [DllImport("user32.dll", CharSet = CharSet.Auto)]
- private static extern uint MapVirtualKey(uint uCode, uint uMapType);
-
private const uint MAPVK_VSC_TO_VK_EX = 0x03;
public static Key Handle(Key key)
{
if (!Global.Config.HandleAlternateKeyboardLayouts) return key;
ScanCode inputScanCode = SlimDXScanCodeMap[(int)key];
- Keys virtualKey = (Keys)MapVirtualKey((uint)inputScanCode, MAPVK_VSC_TO_VK_EX);
+ Keys virtualKey = (Keys)BizHawk.Common.Win32Imports.MapVirtualKey((uint)inputScanCode, MAPVK_VSC_TO_VK_EX);
ScanCode standardScanCode = GetStandardScanCode(virtualKey);
if (standardScanCode == 0)
standardScanCode = inputScanCode;
diff --git a/BizHawk.Client.EmuHawk/MainForm.FileLoader.cs b/BizHawk.Client.EmuHawk/MainForm.FileLoader.cs
index fa1d499314..52f1a4be75 100644
--- a/BizHawk.Client.EmuHawk/MainForm.FileLoader.cs
+++ b/BizHawk.Client.EmuHawk/MainForm.FileLoader.cs
@@ -266,7 +266,7 @@ namespace BizHawk.Client.EmuHawk
sortedFiles.Add(value, new List());
}
- ProcessFileList(HawkFile.Util_ResolveLinks(filePaths), ref sortedFiles);
+ ProcessFileList(filePaths.Select(EmuHawkUtil.ResolveShortcut), ref sortedFiles);
// For each of the different types of item, if there are no items of that type, skip them.
// If there is exactly one of that type of item, load it.
diff --git a/BizHawk.Client.EmuHawk/MainForm.cs b/BizHawk.Client.EmuHawk/MainForm.cs
index 5b51f947c0..cc9dda8021 100644
--- a/BizHawk.Client.EmuHawk/MainForm.cs
+++ b/BizHawk.Client.EmuHawk/MainForm.cs
@@ -3644,7 +3644,7 @@ namespace BizHawk.Client.EmuHawk
if (args == null)
throw new ArgumentNullException(nameof(args));
- path = HawkFile.Util_ResolveLink(path);
+ path = EmuHawkUtil.ResolveShortcut(path);
// if this is the first call to LoadRom (they will come in recursively) then stash the args
bool firstCall = false;
diff --git a/BizHawk.Client.EmuHawk/ScreenSaver.cs b/BizHawk.Client.EmuHawk/ScreenSaver.cs
index 70147bfa75..f9018e2921 100644
--- a/BizHawk.Client.EmuHawk/ScreenSaver.cs
+++ b/BizHawk.Client.EmuHawk/ScreenSaver.cs
@@ -1,6 +1,4 @@
-using System.Runtime.InteropServices;
-
-using BizHawk.Common;
+using BizHawk.Common;
namespace BizHawk.Client.EmuHawk
{
@@ -17,25 +15,21 @@ namespace BizHawk.Client.EmuHawk
private class Win32ScreenBlankTimer : IScreenBlankTimer
{
- [DllImport("user32.dll", CharSet = CharSet.Auto)]
- private static extern bool SystemParametersInfo(int uAction, int uParam, ref int lpvParam, int flags);
-
- private const int SPI_GETSCREENSAVERTIMEOUT = 14;
- private const int SPI_SETSCREENSAVERTIMEOUT = 15;
- private const int SPIF_SENDWININICHANGE = 2;
-
public int Duration
{
get
{
- var value = 0;
- SystemParametersInfo(SPI_GETSCREENSAVERTIMEOUT, 0, ref value, 0);
+ const int SPI_GETSCREENSAVERTIMEOUT = 14;
+ int value = default;
+ Win32Imports.SystemParametersInfo(SPI_GETSCREENSAVERTIMEOUT, 0, ref value, 0);
return value;
}
set
{
- var nullVar = 0;
- SystemParametersInfo(SPI_SETSCREENSAVERTIMEOUT, value, ref nullVar, SPIF_SENDWININICHANGE);
+ const int SPI_SETSCREENSAVERTIMEOUT = 15;
+ const int SPIF_SENDWININICHANGE = 2;
+ int nullVar = default;
+ Win32Imports.SystemParametersInfo(SPI_SETSCREENSAVERTIMEOUT, value, ref nullVar, SPIF_SENDWININICHANGE);
}
}
}
diff --git a/BizHawk.Client.EmuHawk/Throttle.cs b/BizHawk.Client.EmuHawk/Throttle.cs
index 251a2ad408..ce473927b1 100644
--- a/BizHawk.Client.EmuHawk/Throttle.cs
+++ b/BizHawk.Client.EmuHawk/Throttle.cs
@@ -1,6 +1,5 @@
using System;
using System.Diagnostics;
-using System.Runtime.InteropServices;
using System.Threading;
using BizHawk.Client.Common;
@@ -138,33 +137,9 @@ namespace BizHawk.Client.EmuHawk
return (ulong)Environment.TickCount;
}
- private interface PlatformSpecificSysTimer
- {
- uint TimeBeginPeriod(uint ms);
- }
- private class WinSysTimer : PlatformSpecificSysTimer
- {
- [DllImport("winmm.dll", EntryPoint = "timeBeginPeriod")]
- private static extern uint timeBeginPeriod(uint uMilliseconds);
- public uint TimeBeginPeriod(uint ms)
- {
- return timeBeginPeriod(ms);
- }
- }
- private class UnixMonoSysTimer : PlatformSpecificSysTimer
- {
- public uint TimeBeginPeriod(uint ms)
- {
- // we are not going to bother trying to set a minimum resolution for periodic timers
- // (on linux I don't think you can set this in user code)
- return ms;
- }
- }
- static readonly PlatformSpecificSysTimer sysTimer = OSTailoredCode.IsUnixHost ? (PlatformSpecificSysTimer) new UnixMonoSysTimer() : new WinSysTimer();
- static uint TimeBeginPeriod(uint ms)
- {
- return sysTimer.TimeBeginPeriod(ms);
- }
+ static readonly Func TimeBeginPeriod = OSTailoredCode.IsUnixHost
+ ? u => u
+ : (Func) Win32Imports.timeBeginPeriod;
static readonly int tmethod;
static readonly ulong afsfreq;
diff --git a/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskFileSelector.cs b/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskFileSelector.cs
index b15ad65787..4028309ca6 100644
--- a/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskFileSelector.cs
+++ b/BizHawk.Client.EmuHawk/tools/MultiDiskBundler/MultiDiskFileSelector.cs
@@ -91,7 +91,7 @@ namespace BizHawk.Client.EmuHawk
try
{
var file = new FileInfo(ofd.FileName);
- var path = BizHawk.Common.HawkFile.Util_ResolveLink(file.FullName);
+ var path = EmuHawkUtil.ResolveShortcut(file.FullName);
using (var hf = new BizHawk.Common.HawkFile(path))
{
diff --git a/BizHawk.Common/BizHawk.Common.csproj b/BizHawk.Common/BizHawk.Common.csproj
index e791e6fda4..17c37d26de 100644
--- a/BizHawk.Common/BizHawk.Common.csproj
+++ b/BizHawk.Common/BizHawk.Common.csproj
@@ -97,7 +97,11 @@
-
+
+
+
+
+
diff --git a/BizHawk.Common/HawkFile.cs b/BizHawk.Common/HawkFile.cs
index adc5f559eb..0e2c78c3e6 100644
--- a/BizHawk.Common/HawkFile.cs
+++ b/BizHawk.Common/HawkFile.cs
@@ -519,16 +519,6 @@ namespace BizHawk.Common
return $"{root}|{member}";
}
-
- public static IEnumerable Util_ResolveLinks(IEnumerable paths)
- {
- return paths.Select(f => Win32PInvokes.ResolveShortcut(f));
- }
-
- public static string Util_ResolveLink(string path)
- {
- return Win32PInvokes.ResolveShortcut(path);
- }
}
///
diff --git a/BizHawk.Common/TempFileManager.cs b/BizHawk.Common/TempFileManager.cs
index fc2be63a97..5c899fbb21 100644
--- a/BizHawk.Common/TempFileManager.cs
+++ b/BizHawk.Common/TempFileManager.cs
@@ -59,9 +59,6 @@ namespace BizHawk.Common
}
}
- [DllImport("kernel32.dll", EntryPoint = "DeleteFileW", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true)]
- static extern bool DeleteFileW([MarshalAs(UnmanagedType.LPWStr)]string lpFileName);
-
static void ThreadProc()
{
//squirrely logic, trying not to create garbage
@@ -99,7 +96,7 @@ namespace BizHawk.Common
}
else
{
- DeleteFileW(fi.FullName); // SHUT. UP. THE. EXCEPTIONS.
+ Win32Imports.DeleteFileW(fi.FullName); // SHUT. UP. THE. EXCEPTIONS.
}
}
catch
diff --git a/BizHawk.Common/Win32/MotWHack.cs b/BizHawk.Common/Win32/MotWHack.cs
new file mode 100644
index 0000000000..0a122cc438
--- /dev/null
+++ b/BizHawk.Common/Win32/MotWHack.cs
@@ -0,0 +1,8 @@
+namespace BizHawk.Common
+{
+ /// This code (and an import for ) is duplicated in each executable project because it needs to be used before loading assemblies.
+ public static class MotWHack
+ {
+ public static void RemoveMOTW(string path) => Win32Imports.DeleteFileW($"{path}:Zone.Identifier");
+ }
+}
diff --git a/BizHawk.Common/Win32/ProcessorFeatureImports.cs b/BizHawk.Common/Win32/ProcessorFeatureImports.cs
new file mode 100644
index 0000000000..e6082d006d
--- /dev/null
+++ b/BizHawk.Common/Win32/ProcessorFeatureImports.cs
@@ -0,0 +1,24 @@
+using System.Runtime.InteropServices;
+
+namespace BizHawk.Common
+{
+ /// used by commented-out code in LibretroApi ctor, don't delete
+ public static class ProcessorFeatureImports
+ {
+ [DllImport("kernel32.dll")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool IsProcessorFeaturePresent(ProcessorFeature processorFeature);
+
+ public enum ProcessorFeature : uint
+ {
+ /// The MMX instruction set is available
+ InstructionsMMXAvailable = 3,
+ /// The SSE instruction set is available
+ InstructionsXMMIAvailable = 6,
+ /// The SSE2 instruction set is available
+ InstructionsXMMI64Available = 10,
+ /// The SSE3 instruction set is available. (This feature is not supported until Windows Vista)
+ InstructionsSSE3Available = 13
+ }
+ }
+}
diff --git a/BizHawk.Common/Win32/ShellLinkImports.cs b/BizHawk.Common/Win32/ShellLinkImports.cs
new file mode 100644
index 0000000000..24c88af156
--- /dev/null
+++ b/BizHawk.Common/Win32/ShellLinkImports.cs
@@ -0,0 +1,104 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace BizHawk.Common
+{
+ public static class ShellLinkImports
+ {
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
+ public struct WIN32_FIND_DATAW
+ {
+ public uint dwFileAttributes;
+ public long ftCreationTime;
+ public long ftLastAccessTime;
+ public long ftLastWriteTime;
+ public uint nFileSizeHigh;
+ public uint nFileSizeLow;
+ public uint dwReserved0;
+ public uint dwReserved1;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string cFileName;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] public string cAlternateFileName;
+ }
+
+ [Flags]
+ public enum SLGP_FLAGS {}
+
+ [Flags]
+ public enum SLR_FLAGS {}
+
+ /// The IShellLink interface allows Shell links to be created, modified, and resolved
+ [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("000214F9-0000-0000-C000-000000000046")]
+ public interface IShellLinkW
+ {
+ /// Retrieves the path and file name of a Shell link object
+ void GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxPath, out WIN32_FIND_DATAW pfd, SLGP_FLAGS fFlags);
+ /// Retrieves the list of item identifiers for a Shell link object
+ void GetIDList(out IntPtr ppidl);
+ /// Sets the pointer to an item identifier list (PIDL) for a Shell link object.
+ void SetIDList(IntPtr pidl);
+ /// Retrieves the description string for a Shell link object
+ void GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, int cchMaxName);
+ /// Sets the description for a Shell link object. The description can be any application-defined string
+ void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
+ /// Retrieves the name of the working directory for a Shell link object
+ void GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath);
+ /// Sets the name of the working directory for a Shell link object
+ void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
+ /// Retrieves the command-line arguments associated with a Shell link object
+ void GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath);
+ /// Sets the command-line arguments for a Shell link object
+ void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
+ /// Retrieves the hot key for a Shell link object
+ void GetHotkey(out short pwHotkey);
+ /// Sets a hot key for a Shell link object
+ void SetHotkey(short wHotkey);
+ /// Retrieves the show command for a Shell link object
+ void GetShowCmd(out int piShowCmd);
+ /// Sets the show command for a Shell link object. The show command sets the initial show state of the window.
+ void SetShowCmd(int iShowCmd);
+ /// Retrieves the location (path and index) of the icon for a Shell link object
+ void GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, int cchIconPath, out int piIcon);
+ /// Sets the location (path and index) of the icon for a Shell link object
+ void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
+ /// Sets the relative path to the Shell link object
+ void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, int dwReserved);
+ /// Attempts to find the target of a Shell link, even if it has been moved or renamed
+ void Resolve(IntPtr hwnd, SLR_FLAGS fFlags);
+ /// Sets the path and file name of a Shell link object
+ void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
+ }
+
+ [ComImport, Guid("0000010c-0000-0000-c000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ public interface IPersist
+ {
+ [PreserveSig]
+ void GetClassID(out Guid pClassID);
+ }
+
+ [ComImport, Guid("0000010b-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ public interface IPersistFile : IPersist
+ {
+ new void GetClassID(out Guid pClassID);
+
+ [PreserveSig]
+ int IsDirty();
+
+ [PreserveSig]
+ void Load([In, MarshalAs(UnmanagedType.LPWStr)]string pszFileName, uint dwMode);
+
+ [PreserveSig]
+ void Save([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName, [In, MarshalAs(UnmanagedType.Bool)] bool fRemember);
+
+ [PreserveSig]
+ void SaveCompleted([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName);
+
+ [PreserveSig]
+ void GetCurFile([In, MarshalAs(UnmanagedType.LPWStr)] string ppszFileName);
+ }
+
+ /// CLSID_ShellLink from ShlGuid.h
+ [ComImport, Guid("00021401-0000-0000-C000-000000000046")]
+ public class ShellLink /* : IPersistFile, IShellLinkW */ {}
+ }
+}
diff --git a/BizHawk.Common/Win32/ThreadHacks.cs b/BizHawk.Common/Win32/ThreadHacks.cs
new file mode 100644
index 0000000000..6dca599ec2
--- /dev/null
+++ b/BizHawk.Common/Win32/ThreadHacks.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Runtime.InteropServices;
+
+using Microsoft.Win32.SafeHandles;
+
+namespace BizHawk.Common
+{
+ ///
+ /// largely from https://raw.githubusercontent.com/noserati/tpl/master/ThreadAffinityTaskScheduler.cs (MIT license)
+ /// most of this is used in #if false code in mupen64plusApi.frame_advance(), don't delete it
+ ///
+ public static class ThreadHacks
+ {
+ public const uint QS_ALLINPUT = 0x4FFU;
+ public const uint MWMO_INPUTAVAILABLE = 0x0004U;
+ public const uint PM_REMOVE = 0x0001U;
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct MSG
+ {
+ public IntPtr hwnd;
+ public uint message;
+ public IntPtr wParam;
+ public IntPtr lParam;
+ public uint time;
+ public int x;
+ public int y;
+ }
+
+ [DllImport("user32.dll")]
+ public static extern IntPtr DispatchMessage([In] ref MSG lpMsg);
+
+ [DllImport("user32.dll", SetLastError = true)]
+ public static extern uint MsgWaitForMultipleObjectsEx(uint nCount, IntPtr[] pHandles, uint dwMilliseconds, uint dwWakeMask, uint dwFlags);
+
+ [DllImport("user32.dll")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool PeekMessage(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax, uint wRemoveMsg);
+
+ [DllImport("user32.dll")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool TranslateMessage([In] ref MSG lpMsg);
+
+ [DllImport("kernel32", SetLastError = true, ExactSpelling = true)]
+ public static extern int WaitForSingleObject(SafeWaitHandle handle, uint milliseconds);
+ }
+}
diff --git a/BizHawk.Common/Win32/Win32Imports.cs b/BizHawk.Common/Win32/Win32Imports.cs
new file mode 100644
index 0000000000..192dce9459
--- /dev/null
+++ b/BizHawk.Common/Win32/Win32Imports.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace BizHawk.Common
+{
+ public static class Win32Imports
+ {
+ public const int MAX_PATH = 260;
+
+ [DllImport("kernel32.dll", EntryPoint = "DeleteFileW", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true)]
+ public static extern bool DeleteFileW([MarshalAs(UnmanagedType.LPWStr)] string lpFileName);
+
+ [DllImport("kernel32.dll", SetLastError=true)]
+ public static extern unsafe uint GetCurrentDirectoryW(uint nBufferLength, byte* pBuffer);
+
+ [DllImport("kernel32", SetLastError = true, EntryPoint = "GetProcAddress")]
+ public static extern IntPtr GetProcAddressOrdinal(IntPtr hModule, IntPtr procName);
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ public static extern IntPtr GetProcessHeap();
+
+ [DllImport("kernel32.dll", SetLastError = false)]
+ public static extern IntPtr HeapAlloc(IntPtr hHeap, uint dwFlags, int dwBytes);
+
+ /// used in #if false code in AviWriter.CodecToken.DeallocateAVICOMPRESSOPTIONS, don't delete it
+ [DllImport("kernel32.dll", SetLastError = true)]
+ public static extern bool HeapFree(IntPtr hHeap, uint dwFlags, IntPtr lpMem);
+
+ [DllImport("user32")]
+ public static extern bool HideCaret(IntPtr hWnd);
+
+ [DllImport("kernel32.dll")]
+ public static extern bool IsDebuggerPresent();
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto)]
+ public static extern uint MapVirtualKey(uint uCode, uint uMapType);
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ public static extern unsafe bool SetCurrentDirectoryW(byte* lpPathName);
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto)]
+ public static extern bool SystemParametersInfo(int uAction, int uParam, ref int lpvParam, int flags);
+
+ [DllImport("winmm.dll", EntryPoint = "timeBeginPeriod")]
+ public static extern uint timeBeginPeriod(uint uMilliseconds);
+ }
+}
diff --git a/BizHawk.Common/Win32Hacks.cs b/BizHawk.Common/Win32Hacks.cs
deleted file mode 100644
index 7a20f6a95d..0000000000
--- a/BizHawk.Common/Win32Hacks.cs
+++ /dev/null
@@ -1,470 +0,0 @@
-using System;
-using System.IO;
-using System.Text;
-using System.Threading;
-using System.Runtime.InteropServices;
-
-namespace BizHawk.Common
-{
- static class PInvokes
- {
- [DllImport("shfolder.dll", CharSet = CharSet.Auto)]
- internal static extern int SHGetFolderPath(IntPtr hwndOwner, int nFolder, IntPtr hToken, int dwFlags, StringBuilder lpszPath);
-
- [Flags()]
- public enum SLGP_FLAGS
- {
- /// Retrieves the standard short (8.3 format) file name
- SLGP_SHORTPATH = 0x1,
- /// Retrieves the Universal Naming Convention (UNC) path name of the file
- SLGP_UNCPRIORITY = 0x2,
- /// Retrieves the raw path name. A raw path is something that might not exist and may include environment variables that need to be expanded
- SLGP_RAWPATH = 0x4
- }
-
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
- public struct WIN32_FIND_DATAW
- {
- public uint dwFileAttributes;
- public long ftCreationTime;
- public long ftLastAccessTime;
- public long ftLastWriteTime;
- public uint nFileSizeHigh;
- public uint nFileSizeLow;
- public uint dwReserved0;
- public uint dwReserved1;
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
- public string cFileName;
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
- public string cAlternateFileName;
- }
-
- [Flags()]
- public enum SLR_FLAGS
- {
- ///
- /// Do not display a dialog box if the link cannot be resolved. When SLR_NO_UI is set,
- /// the high-order word of fFlags can be set to a time-out value that specifies the
- /// maximum amount of time to be spent resolving the link. The function returns if the
- /// link cannot be resolved within the time-out duration. If the high-order word is set
- /// to zero, the time-out duration will be set to the default value of 3,000 milliseconds
- /// (3 seconds). To specify a value, set the high word of fFlags to the desired time-out
- /// duration, in milliseconds.
- ///
- SLR_NO_UI = 0x1,
- /// Obsolete and no longer used
- SLR_ANY_MATCH = 0x2,
- /// If the link object has changed, update its path and list of identifiers.
- /// If SLR_UPDATE is set, you do not need to call IPersistFile::IsDirty to determine
- /// whether or not the link object has changed.
- SLR_UPDATE = 0x4,
- /// Do not update the link information
- SLR_NOUPDATE = 0x8,
- /// Do not execute the search heuristics
- SLR_NOSEARCH = 0x10,
- /// Do not use distributed link tracking
- SLR_NOTRACK = 0x20,
- /// Disable distributed link tracking. By default, distributed link tracking tracks
- /// removable media across multiple devices based on the volume name. It also uses the
- /// Universal Naming Convention (UNC) path to track remote file systems whose drive letter
- /// has changed. Setting SLR_NOLINKINFO disables both types of tracking.
- SLR_NOLINKINFO = 0x40,
- /// Call the Microsoft Windows Installer
- SLR_INVOKE_MSI = 0x80
- }
-
-
- /// The IShellLink interface allows Shell links to be created, modified, and resolved
- [ComImport(), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("000214F9-0000-0000-C000-000000000046")]
- public interface IShellLinkW
- {
- /// Retrieves the path and file name of a Shell link object
- void GetPath([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxPath, out WIN32_FIND_DATAW pfd, SLGP_FLAGS fFlags);
- /// Retrieves the list of item identifiers for a Shell link object
- void GetIDList(out IntPtr ppidl);
- /// Sets the pointer to an item identifier list (PIDL) for a Shell link object.
- void SetIDList(IntPtr pidl);
- /// Retrieves the description string for a Shell link object
- void GetDescription([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, int cchMaxName);
- /// Sets the description for a Shell link object. The description can be any application-defined string
- void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
- /// Retrieves the name of the working directory for a Shell link object
- void GetWorkingDirectory([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath);
- /// Sets the name of the working directory for a Shell link object
- void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
- /// Retrieves the command-line arguments associated with a Shell link object
- void GetArguments([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath);
- /// Sets the command-line arguments for a Shell link object
- void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
- /// Retrieves the hot key for a Shell link object
- void GetHotkey(out short pwHotkey);
- /// Sets a hot key for a Shell link object
- void SetHotkey(short wHotkey);
- /// Retrieves the show command for a Shell link object
- void GetShowCmd(out int piShowCmd);
- /// Sets the show command for a Shell link object. The show command sets the initial show state of the window.
- void SetShowCmd(int iShowCmd);
- /// Retrieves the location (path and index) of the icon for a Shell link object
- void GetIconLocation([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath,
- int cchIconPath, out int piIcon);
- /// Sets the location (path and index) of the icon for a Shell link object
- void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
- /// Sets the relative path to the Shell link object
- void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, int dwReserved);
- /// Attempts to find the target of a Shell link, even if it has been moved or renamed
- void Resolve(IntPtr hwnd, SLR_FLAGS fFlags);
- /// Sets the path and file name of a Shell link object
- void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
-
- }
-
- [ComImport, Guid("0000010c-0000-0000-c000-000000000046"),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface IPersist
- {
- [PreserveSig]
- void GetClassID(out Guid pClassID);
- }
-
-
- [ComImport, Guid("0000010b-0000-0000-C000-000000000046"),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface IPersistFile : IPersist
- {
- new void GetClassID(out Guid pClassID);
- [PreserveSig]
- int IsDirty();
-
- [PreserveSig]
- void Load([In, MarshalAs(UnmanagedType.LPWStr)]string pszFileName, uint dwMode);
-
- [PreserveSig]
- void Save([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName,
- [In, MarshalAs(UnmanagedType.Bool)] bool fRemember);
-
- [PreserveSig]
- void SaveCompleted([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName);
-
- [PreserveSig]
- void GetCurFile([In, MarshalAs(UnmanagedType.LPWStr)] string ppszFileName);
- }
-
- public const uint STGM_READ = 0;
- public const int MAX_PATH = 260;
-
- // CLSID_ShellLink from ShlGuid.h
- [
- ComImport(),
- Guid("00021401-0000-0000-C000-000000000046")
- ]
- public class ShellLink
- {
- }
- }
-
- public static class Win32PInvokes
- {
- //http://stackoverflow.com/questions/139010/how-to-resolve-a-lnk-in-c-sharp
- public static string ResolveShortcut(string filename)
- {
- // archive internal files are never shortcuts (and choke when analyzing any further)
- if (filename.Contains("|"))
- {
- return filename;
- }
-
- if (Path.GetExtension(filename).ToLowerInvariant() != ".lnk")
- {
- return filename;
- }
-
- PInvokes.ShellLink link = new PInvokes.ShellLink();
- ((PInvokes.IPersistFile)link).Load(filename, PInvokes.STGM_READ);
- // TODO: if I can get hold of the hwnd call resolve first. This handles moved and renamed files.
- // ((IShellLinkW)link).Resolve(hwnd, 0)
- StringBuilder sb = new StringBuilder(PInvokes.MAX_PATH);
- PInvokes.WIN32_FIND_DATAW data = new PInvokes.WIN32_FIND_DATAW();
- ((PInvokes.IShellLinkW)link).GetPath(sb, sb.Capacity, out data, 0);
-
- //maybe? what if it's invalid?
- if (sb.Length == 0)
- return filename;
- return sb.ToString();
- }
-
- [DllImport("kernel32.dll")]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool IsProcessorFeaturePresent(ProcessorFeature processorFeature);
-
- public enum ProcessorFeature : uint
- {
- ///
- /// On a Pentium, a floating-point precision error can occur in rare circumstances
- ///
- FloatingPointPrecisionErrata = 0,
- ///
- /// Floating-point operations are emulated using a software emulator.
- /// This function returns a nonzero value if floating-point operations are emulated; otherwise, it returns zero.
- ///
- FloatingPointEmulated = 1,
- ///
- /// The atomic compare and exchange operation (cmpxchg) is available
- ///
- CompareExchangeDouble = 2,
- ///
- /// The MMX instruction set is available
- ///
- InstructionsMMXAvailable = 3,
- ///
- /// The SSE instruction set is available
- ///
- InstructionsXMMIAvailable = 6,
- ///
- /// The 3D-Now instruction set is available.
- ///
- Instruction3DNowAvailable = 7,
- ///
- /// The RDTSC instruction is available
- ///
- InstructionRDTSCAvailable = 8,
- ///
- /// The processor is PAE-enabled
- ///
- PAEEnabled = 9,
- ///
- /// The SSE2 instruction set is available
- ///
- InstructionsXMMI64Available = 10,
- ///
- /// Data execution prevention is enabled. (This feature is not supported until Windows XP SP2 and Windows Server 2003 SP1)
- ///
- NXEnabled = 12,
- ///
- /// The SSE3 instruction set is available. (This feature is not supported until Windows Vista)
- ///
- InstructionsSSE3Available = 13,
- ///
- /// The atomic compare and exchange 128-bit operation (cmpxchg16b) is available. (This feature is not supported until Windows Vista)
- ///
- CompareExchange128 = 14,
- ///
- /// The atomic compare 64 and exchange 128-bit operation (cmp8xchg16) is available (This feature is not supported until Windows Vista.)
- ///
- Compare64Exchange128 = 15,
- ///
- /// TBD
- ///
- ChannelsEnabled = 16,
- }
-
-
-
- }
-
- //largely from https://raw.githubusercontent.com/noserati/tpl/master/ThreadAffinityTaskScheduler.cs (MIT license)
- public static class Win32ThreadHacks
- {
- internal static class NativeMethods
- {
- [DllImport("kernel32", SetLastError = true, ExactSpelling = true)]
- public static extern Int32 WaitForSingleObject(Microsoft.Win32.SafeHandles.SafeWaitHandle handle, uint milliseconds);
-
- public const uint QS_KEY = 0x0001;
- public const uint QS_MOUSEMOVE = 0x0002;
- public const uint QS_MOUSEBUTTON = 0x0004;
- public const uint QS_POSTMESSAGE = 0x0008;
- public const uint QS_TIMER = 0x0010;
- public const uint QS_PAINT = 0x0020;
- public const uint QS_SENDMESSAGE = 0x0040;
- public const uint QS_HOTKEY = 0x0080;
- public const uint QS_ALLPOSTMESSAGE = 0x0100;
- public const uint QS_RAWINPUT = 0x0400;
-
- public const uint QS_MOUSE = (QS_MOUSEMOVE | QS_MOUSEBUTTON);
- public const uint QS_INPUT = (QS_MOUSE | QS_KEY | QS_RAWINPUT);
- public const uint QS_ALLEVENTS = (QS_INPUT | QS_POSTMESSAGE | QS_TIMER | QS_PAINT | QS_HOTKEY);
- public const uint QS_ALLINPUT = (QS_INPUT | QS_POSTMESSAGE | QS_TIMER | QS_PAINT | QS_HOTKEY | QS_SENDMESSAGE);
-
- public const uint MWMO_INPUTAVAILABLE = 0x0004;
- public const uint MWMO_WAITALL = 0x0001;
-
- public const uint PM_REMOVE = 0x0001;
- public const uint PM_NOREMOVE = 0;
-
- public const uint WAIT_TIMEOUT = 0x00000102;
- public const uint WAIT_FAILED = 0xFFFFFFFF;
- public const uint INFINITE = 0xFFFFFFFF;
- public const uint WAIT_OBJECT_0 = 0;
- public const uint WAIT_ABANDONED_0 = 0x00000080;
- public const uint WAIT_IO_COMPLETION = 0x000000C0;
-
- [StructLayout(LayoutKind.Sequential)]
- public struct MSG
- {
- public IntPtr hwnd;
- public uint message;
- public IntPtr wParam;
- public IntPtr lParam;
- public uint time;
- public int x;
- public int y;
- }
-
- [DllImport("user32.dll")]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool PeekMessage(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax, uint wRemoveMsg);
-
- [DllImport("user32.dll")]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool PostMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
-
- [DllImport("user32.dll")]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
-
- [DllImport("user32.dll")]
- public static extern IntPtr DispatchMessage([In] ref MSG lpMsg);
-
- [DllImport("user32.dll")]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool TranslateMessage([In] ref MSG lpMsg);
-
- [DllImport("ole32.dll", PreserveSig = false)]
- public static extern void OleInitialize(IntPtr pvReserved);
-
- [DllImport("ole32.dll", PreserveSig = true)]
- public static extern void OleUninitialize();
-
- [DllImport("kernel32.dll")]
- public static extern uint GetTickCount();
-
- [DllImport("user32.dll")]
- public static extern uint GetQueueStatus(uint flags);
-
- [DllImport("user32.dll", SetLastError = true)]
- public static extern uint MsgWaitForMultipleObjectsEx(
- uint nCount, IntPtr[] pHandles, uint dwMilliseconds, uint dwWakeMask, uint dwFlags);
-
- [DllImport("kernel32.dll", SetLastError = true)]
- public static extern uint WaitForMultipleObjects(
- uint nCount, IntPtr[] lpHandles, bool bWaitAll, uint dwMilliseconds);
-
- [DllImport("kernel32.dll", SetLastError = true)]
- public static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds);
-
- [DllImport("kernel32.dll", SetLastError = true)]
- public static extern IntPtr CreateEvent(IntPtr lpEventAttributes, bool bManualReset, bool bInitialState, string lpName);
-
- [DllImport("kernel32.dll", SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool SetEvent(IntPtr hEvent);
-
- [DllImport("kernel32.dll", SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool CloseHandle(IntPtr hObject);
- }
-
- ///
- /// Analyze the result of the native wait API
- ///
- static bool IsNativeWaitSuccessful(uint count, uint nativeResult, out int managedResult)
- {
- if (nativeResult == (NativeMethods.WAIT_OBJECT_0 + count))
- {
- // a is message pending, only valid for MsgWaitForMultipleObjectsEx
- managedResult = unchecked((int)nativeResult);
- return false;
- }
-
- if (nativeResult >= NativeMethods.WAIT_OBJECT_0 && nativeResult < (NativeMethods.WAIT_OBJECT_0 + count))
- {
- managedResult = unchecked((int)(nativeResult - NativeMethods.WAIT_OBJECT_0));
- return true;
- }
-
- if (nativeResult >= NativeMethods.WAIT_ABANDONED_0 && nativeResult < (NativeMethods.WAIT_ABANDONED_0 + count))
- {
- managedResult = unchecked((int)(nativeResult - NativeMethods.WAIT_ABANDONED_0));
- throw new AbandonedMutexException();
- }
-
- if (nativeResult == NativeMethods.WAIT_TIMEOUT)
- {
- managedResult = WaitHandle.WaitTimeout;
- return false;
- }
-
- throw new InvalidOperationException();
- }
-
- ///
- /// functionally the same as WaitOne, but does not message pump
- ///
- public static void HackyPinvokeWaitOne(WaitHandle handle, uint timeout = 0xFFFFFFFF)
- {
- NativeMethods.WaitForSingleObject(handle.SafeWaitHandle, timeout);
- }
-
- ///
- /// Functionally the same as WaitOne(), but pumps com messa
- ///
- public static void HackyComWaitOne(WaitHandle handle)
- {
- uint nativeResult; // result of the native wait API (WaitForMultipleObjects or MsgWaitForMultipleObjectsEx)
- int managedResult; // result to return from WaitHelper
-
- IntPtr[] waitHandles = new IntPtr[]{
- handle.SafeWaitHandle.DangerousGetHandle() };
- uint count = 1;
-
- uint QS_MASK = NativeMethods.QS_ALLINPUT; // message queue status
- QS_MASK = 0; //bizhawk edit?? did we need any messages here?? apparently not???
-
- // the core loop
- var msg = new NativeMethods.MSG();
- while (true)
- {
- // MsgWaitForMultipleObjectsEx with MWMO_INPUTAVAILABLE returns,
- // even if there's a message already seen but not removed in the message queue
- nativeResult = NativeMethods.MsgWaitForMultipleObjectsEx(
- count, waitHandles,
- (uint)0xFFFFFFFF,
- QS_MASK,
- NativeMethods.MWMO_INPUTAVAILABLE);
-
- if (IsNativeWaitSuccessful(count, nativeResult, out managedResult) || WaitHandle.WaitTimeout == managedResult)
- break;
- // there is a message, pump and dispatch it
- if (NativeMethods.PeekMessage(out msg, IntPtr.Zero, 0, 0, NativeMethods.PM_REMOVE))
- {
- NativeMethods.TranslateMessage(ref msg);
- NativeMethods.DispatchMessage(ref msg);
- }
- }
- //m64pFrameComplete.WaitOne();
- }
-
- }
-
- public static class Win32Hacks
- {
- [DllImport("kernel32.dll", EntryPoint = "DeleteFileW", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true)]
- static extern bool DeleteFileW([MarshalAs(UnmanagedType.LPWStr)]string lpFileName);
-
- //warning: youll have to copy this into the main assembly for your exes in order to run it when booting.
- //I only put this for use here by external cores
- public static void RemoveMOTW(string path)
- {
- DeleteFileW($"{path}:Zone.Identifier");
- }
-
- [DllImport("kernel32.dll")]
- static extern bool IsDebuggerPresent();
-
- public static bool IsDebuggerReallyPresent()
- {
- return IsDebuggerPresent();
- }
- }
-
-}
\ No newline at end of file
diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/NativeApi/mupen64plusCoreApi.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/NativeApi/mupen64plusCoreApi.cs
index 3601c271f3..ab33b1f433 100644
--- a/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/NativeApi/mupen64plusCoreApi.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/NativeApi/mupen64plusCoreApi.cs
@@ -711,28 +711,81 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64.NativeApi
public void frame_advance()
{
- if (!emulator_running)
- return;
+#if false // for alt. method #2 below
+ static bool IsNativeWaitSuccessful(uint count, uint nativeResult, out int managedResult)
+ {
+ const uint WAIT_OBJECT_0 = 0x00000000U;
+ const uint WAIT_ABANDONED_0 = 0x00000080U;
+ const uint WAIT_TIMEOUT = 0x00000102U;
+ if (/* WAIT_OBJECT_0 <= nativeResult && */ nativeResult < WAIT_OBJECT_0 + count)
+ {
+ managedResult = unchecked((int) (nativeResult - WAIT_OBJECT_0));
+ return true;
+ }
+ else if (nativeResult == WAIT_OBJECT_0 + count)
+ {
+ // a is message pending, only valid for MsgWaitForMultipleObjectsEx
+ managedResult = unchecked((int) nativeResult);
+ return false;
+ }
+ else if (WAIT_ABANDONED_0 <= nativeResult && nativeResult < WAIT_ABANDONED_0 + count)
+ {
+ managedResult = unchecked((int) (nativeResult - WAIT_ABANDONED_0));
+ throw new AbandonedMutexException();
+ }
+ else if (nativeResult == WAIT_TIMEOUT)
+ {
+ managedResult = WaitHandle.WaitTimeout;
+ return false;
+ }
+ else
+ {
+ throw new InvalidOperationException();
+ }
+ }
+
+ static void HackyComWaitOne(WaitHandle handle)
+ {
+ IntPtr[] waitHandles = { handle.SafeWaitHandle.DangerousGetHandle() };
+ const uint count = 1;
+ var QS_MASK = ThreadHacks.QS_ALLINPUT; // message queue status
+ QS_MASK = 0; //bizhawk edit?? did we need any messages here?? apparently not???
+ uint nativeResult;
+ ThreadHacks.MSG msg;
+ while (true)
+ {
+ // MsgWaitForMultipleObjectsEx with MWMO_INPUTAVAILABLE returns,
+ // even if there's a message already seen but not removed in the message queue
+ nativeResult = ThreadHacks.MsgWaitForMultipleObjectsEx(count, waitHandles, 0xFFFFFFFF, QS_MASK, ThreadHacks.MWMO_INPUTAVAILABLE);
+ if (IsNativeWaitSuccessful(count, nativeResult, out int managedResult) || WaitHandle.WaitTimeout == managedResult) break;
+ // there is a message, pump and dispatch it
+ if (ThreadHacks.PeekMessage(out msg, IntPtr.Zero, 0, 0, ThreadHacks.PM_REMOVE))
+ {
+ ThreadHacks.TranslateMessage(ref msg);
+ ThreadHacks.DispatchMessage(ref msg);
+ }
+ }
+// handle.WaitOne();
+ }
+#endif
+
+ if (!emulator_running) return;
event_frameend = false;
m64pCoreDoCommandPtr(m64p_command.M64CMD_ADVANCE_FRAME, 0, IntPtr.Zero);
- //the way we should be able to do it:
- //m64pFrameComplete.WaitOne();
-
- //however. since this is probably an STAThread, this call results in message pumps running.
- //those message pumps are only supposed to respond to critical COM stuff, but in fact they interfere with other things.
- //so here are two workaround methods.
-
- //method 1.
- //BizHawk.Common.Win32ThreadHacks.HackyPinvokeWaitOne(m64pFrameComplete);
-
- //method 2.
- //BizHawk.Common.Win32ThreadHacks.HackyComWaitOne(m64pFrameComplete);
-
for(;;)
{
- BizHawk.Common.Win32ThreadHacks.HackyPinvokeWaitOne(m64pEvent, 200);
+#if false // the way we should be able to do it
+ m64pEvent.WaitOne();
+ // however. since this is probably an STAThread, this call results in message pumps running.
+ // those message pumps are only supposed to respond to critical COM stuff, but in fact they interfere with other things.
+ // so here are two workaround methods:
+#elif true // alt. method #1 - functionally the same as WaitOne, but does not message pump
+ ThreadHacks.WaitForSingleObject(m64pEvent.SafeWaitHandle, 200);
+#else // alt. method #2 - functionally the same as WaitOne(), but pumps com messages
+ HackyComWaitOne(m64pEvent);
+#endif
if (event_frameend)
break;
if (event_breakpoint)
diff --git a/BizHawk.Emulation.Cores/Libretro/LibretroApi.cs b/BizHawk.Emulation.Cores/Libretro/LibretroApi.cs
index db2286cd84..ecd25b3354 100644
--- a/BizHawk.Emulation.Cores/Libretro/LibretroApi.cs
+++ b/BizHawk.Emulation.Cores/Libretro/LibretroApi.cs
@@ -68,10 +68,10 @@ namespace BizHawk.Emulation.Cores.Libretro
//ALSO: this should be done by the core, I think, not the API. No smarts should be in here
comm->env.retro_perf_callback.get_cpu_features = IntPtr.Zero;
//retro_perf_callback.get_cpu_features = new LibRetro.retro_get_cpu_features_t(() => (ulong)(
- // (Win32PInvokes.IsProcessorFeaturePresent(Win32PInvokes.ProcessorFeature.InstructionsXMMIAvailable) ? LibRetro.RETRO_SIMD.SSE : 0) |
- // (Win32PInvokes.IsProcessorFeaturePresent(Win32PInvokes.ProcessorFeature.InstructionsXMMI64Available) ? LibRetro.RETRO_SIMD.SSE2 : 0) |
- // (Win32PInvokes.IsProcessorFeaturePresent(Win32PInvokes.ProcessorFeature.InstructionsSSE3Available) ? LibRetro.RETRO_SIMD.SSE3 : 0) |
- // (Win32PInvokes.IsProcessorFeaturePresent(Win32PInvokes.ProcessorFeature.InstructionsMMXAvailable) ? LibRetro.RETRO_SIMD.MMX : 0)
+ // (ProcessorFeatureImports.IsProcessorFeaturePresent(ProcessorFeatureImports.ProcessorFeature.InstructionsXMMIAvailable) ? LibRetro.RETRO_SIMD.SSE : 0) |
+ // (ProcessorFeatureImports.IsProcessorFeaturePresent(ProcessorFeatureImports.ProcessorFeature.InstructionsXMMI64Available) ? LibRetro.RETRO_SIMD.SSE2 : 0) |
+ // (ProcessorFeatureImports.IsProcessorFeaturePresent(ProcessorFeatureImports.ProcessorFeature.InstructionsSSE3Available) ? LibRetro.RETRO_SIMD.SSE3 : 0) |
+ // (ProcessorFeatureImports.IsProcessorFeaturePresent(ProcessorFeatureImports.ProcessorFeature.InstructionsMMXAvailable) ? LibRetro.RETRO_SIMD.MMX : 0)
// ));
//retro_perf_callback.get_perf_counter = new LibRetro.retro_perf_get_counter_t(() => System.Diagnostics.Stopwatch.GetTimestamp());
//retro_perf_callback.get_time_usec = new LibRetro.retro_perf_get_time_usec_t(() => DateTime.Now.Ticks / 10);
diff --git a/BizHawk.Emulation.Cores/Waterbox/PeRunner.cs b/BizHawk.Emulation.Cores/Waterbox/PeRunner.cs
index 68f25da2f4..a39a2b47ab 100644
--- a/BizHawk.Emulation.Cores/Waterbox/PeRunner.cs
+++ b/BizHawk.Emulation.Cores/Waterbox/PeRunner.cs
@@ -1063,7 +1063,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
_syscalls.Init();
Console.WriteLine("About to enter unmanaged code");
- if (Win32Hacks.IsDebuggerReallyPresent() && !System.Diagnostics.Debugger.IsAttached)
+ if (!OSTailoredCode.IsUnixHost && !System.Diagnostics.Debugger.IsAttached && Win32Imports.IsDebuggerPresent())
{
// this means that GDB or another unconventional debugger is attached.
// if that's the case, and it's observing this core, it probably wants a break