diff --git a/BizHawk.Client.Common/Global.cs b/BizHawk.Client.Common/Global.cs index edd287ef491..6a303c5ff78 100644 --- a/BizHawk.Client.Common/Global.cs +++ b/BizHawk.Client.Common/Global.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Consoles.Nintendo.Gameboy; @@ -156,5 +157,7 @@ public static SystemInfo SystemInfo } public static Dictionary UserBag = new Dictionary(); + + public static bool RunningOnUnix = Environment.OSVersion.Platform == PlatformID.Unix || Environment.OSVersion.Platform == PlatformID.MacOSX; } } diff --git a/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj b/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj index a5b9eaf9d65..62c94d1246f 100644 --- a/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj +++ b/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj @@ -638,6 +638,8 @@ + + diff --git a/BizHawk.Client.EmuHawk/Input/Input.cs b/BizHawk.Client.EmuHawk/Input/Input.cs index cc8d2fa6a87..a812d550170 100644 --- a/BizHawk.Client.EmuHawk/Input/Input.cs +++ b/BizHawk.Client.EmuHawk/Input/Input.cs @@ -4,6 +4,8 @@ using System.Threading; #if WINDOWS using SlimDX.DirectInput; +#else +using OpenTK.Input; #endif using BizHawk.Common; @@ -126,12 +128,18 @@ private Input() public static void Initialize() { -#if WINDOWS - KeyInput.Initialize(); - IPCKeyInput.Initialize(); - GamePad.Initialize(); - GamePad360.Initialize(); -#endif + if (Global.RunningOnUnix) + { + OTK_Keyboard.Initialize(); +// OTK_Gamepad.Initialize(); + } + else + { + KeyInput.Initialize(); + IPCKeyInput.Initialize(); + GamePad.Initialize(); + GamePad360.Initialize(); + } Instance = new Input(); } diff --git a/BizHawk.Client.EmuHawk/Input/OTK_Gamepad.cs b/BizHawk.Client.EmuHawk/Input/OTK_Gamepad.cs new file mode 100644 index 00000000000..e9b5fb575fe --- /dev/null +++ b/BizHawk.Client.EmuHawk/Input/OTK_Gamepad.cs @@ -0,0 +1,148 @@ +using System; +using System.Collections.Generic; +using OpenTK.Input; + +namespace BizHawk.Client.EmuHawk +{ + public class OTK_GamePad + { + //Note: OpenTK has both Gamepad and Joystick classes. An OpenTK Gamepad is a simplified version of Joystick + //with pre-defined features that match an XInput controller. They did this to mimic XNA's controller API. + //We're going to use Joystick directly, because it gives us full access to all possible buttons. + //And it looks like GamePad itself isn't supported on OpenTK OS X. + + public static List Devices; + private const int MAX_JOYSTICKS = 4; //They don't have a way to query this for some reason. 4 is the minimum promised. + + public static void Initialize() + { + Devices = new List(); + + for (int i = 0; i < MAX_JOYSTICKS; i++) + { + JoystickState jss = Joystick.GetState(i); + if (jss.IsConnected) + { + Console.WriteLine(string.Format("joydevice index: {0}", i)); //OpenTK doesn't expose the GUID, even though it stores it internally... + + OTK_GamePad ogp = new OTK_GamePad(i); + Devices.Add(ogp); + } + } + + } + + public static void UpdateAll() + { + foreach (var device in Devices) + device.Update(); + } + + public static void CloseAll() + { + if (Devices != null) + { + Devices.Clear(); + } + } + + // ********************************** Instance Members ********************************** + + readonly Guid _guid; + readonly int _stickIdx; + JoystickState state = new JoystickState(); + + OTK_GamePad(int index) + { + _guid = Guid.NewGuid(); + _stickIdx = index; + Update(); + InitializeCallbacks(); + } + + public void Update() + { + state = Joystick.GetState(_stickIdx); + } + + public IEnumerable> GetFloats() + { + for (int pi = 0; pi < 64; pi++) + yield return new Tuple(pi.ToString(), 10.0f * state.GetAxis(pi)); + } + + /// FOR DEBUGGING ONLY + public JoystickState GetInternalState() + { + return state; + } + + public string Name { get { return "Joystick " + _stickIdx; } } + public Guid Guid { get { return _guid; } } + + + public string ButtonName(int index) + { + return names[index]; + } + public bool Pressed(int index) + { + return actions[index](); + } + public int NumButtons { get; private set; } + + private readonly List names = new List(); + private readonly List> actions = new List>(); + + void AddItem(string _name, Func callback) + { + names.Add(_name); + actions.Add(callback); + NumButtons++; + } + + void InitializeCallbacks() + { + const int dzp = 400; + const int dzn = -400; + + names.Clear(); + actions.Clear(); + NumButtons = 0; + + AddItem("X+", () => state.GetAxis(0) >= dzp); + AddItem("X-", () => state.GetAxis(0) <= dzn); + AddItem("Y+", () => state.GetAxis(1) >= dzp); + AddItem("Y-", () => state.GetAxis(1) <= dzn); + AddItem("Z+", () => state.GetAxis(2) >= dzp); + AddItem("Z-", () => state.GetAxis(2) <= dzn); + + // Enjoy our delicious sliders. They're smaller than regular burgers but cost more. + + int jb = 1; + for (int i = 0; i < 64; i++) + { + AddItem(string.Format("B{0}", jb), () => state.GetButton(i)==ButtonState.Pressed); + jb++; + } + + jb = 1; + foreach (JoystickHat enval in Enum.GetValues(typeof(JoystickHat))) + { + AddItem(string.Format("POV{0}U", jb), () => state.GetHat(enval).IsUp); + AddItem(string.Format("POV{0}D", jb), () => state.GetHat(enval).IsDown); + AddItem(string.Format("POV{0}L", jb), () => state.GetHat(enval).IsLeft); + AddItem(string.Format("POV{0}R", jb), () => state.GetHat(enval).IsRight); + jb++; + } + } + + // Note that this does not appear to work at this time. I probably need to have more infos. + public void SetVibration(int left, int right) + { + //Not supported in OTK Joystick. It is supported for OTK Gamepad, but I have to use Joystick for reasons mentioned above. + } + + } +} + diff --git a/BizHawk.Client.EmuHawk/Input/OTK_Keyboard.cs b/BizHawk.Client.EmuHawk/Input/OTK_Keyboard.cs new file mode 100644 index 00000000000..2c8faa7cbbd --- /dev/null +++ b/BizHawk.Client.EmuHawk/Input/OTK_Keyboard.cs @@ -0,0 +1,90 @@ +using System.Collections.Generic; +using System.Text; +using OpenTK.Input; + +namespace BizHawk.Client.EmuHawk +{ + public static class OTK_Keyboard + { + private static OpenTK.Input.KeyboardState _kbState; + + public static void Initialize () + { + _kbState = OpenTK.Input.Keyboard.GetState(); + } + + public static void Update () + { + try + { + _kbState = OpenTK.Input.Keyboard.GetState(); + } + catch + { + //OpenTK's keyboard class isn't thread safe. + //In rare cases (sometimes it takes up to 10 minutes to occur) it will + //be updating the keyboard state when we call GetState() and choke. + //Until I fix OpenTK, it's fine to just swallow it because input continues working. + if(System.Diagnostics.Debugger.IsAttached) + { + System.Console.WriteLine("OpenTK Keyboard thread is angry."); + } + } + } + + public static bool IsPressed (Key key) + { + return _kbState.IsKeyDown(key); + } + + public static bool ShiftModifier { + get { + return IsPressed(Key.ShiftLeft) || IsPressed(Key.ShiftRight); + } + } + + public static bool CtrlModifier { + get { + return IsPressed(Key.ControlLeft) || IsPressed(Key.ControlRight); + } + } + + public static bool AltModifier { + get { + return IsPressed(Key.AltLeft) || IsPressed(Key.AltRight); + } + } + + public static Input.ModifierKey GetModifierKeysAsKeys () + { + Input.ModifierKey ret = Input.ModifierKey.None; + if (ShiftModifier) + ret |= Input.ModifierKey.Shift; + if (CtrlModifier) + ret |= Input.ModifierKey.Control; + if (AltModifier) + ret |= Input.ModifierKey.Alt; + return ret; + } + } + + internal static class KeyExtensions + { + public static bool IsModifier (this Key key) + { + if (key == Key.ShiftLeft) + return true; + if (key == Key.ShiftRight) + return true; + if (key == Key.ControlLeft) + return true; + if (key == Key.ControlRight) + return true; + if (key == Key.AltLeft) + return true; + if (key == Key.AltRight) + return true; + return false; + } + } +} diff --git a/BizHawk.Client.EmuHawk/Program.cs b/BizHawk.Client.EmuHawk/Program.cs index 47d97f0f1b9..7ff63f404ac 100644 --- a/BizHawk.Client.EmuHawk/Program.cs +++ b/BizHawk.Client.EmuHawk/Program.cs @@ -23,16 +23,18 @@ static Program() Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); + PlatformSpecificLinkedLibs libLoader = Global.RunningOnUnix ? (PlatformSpecificLinkedLibs) new UnixMono() : (PlatformSpecificLinkedLibs) new Win32(); + //http://www.codeproject.com/Articles/310675/AppDomain-AssemblyResolve-Event-Tips -#if WINDOWS + //try loading libraries we know we'll need //something in the winforms, etc. code below will cause .net to popup a missing msvcr100.dll in case that one's missing //but oddly it lets us proceed and we'll then catch it here - var d3dx9 = Win32.LoadLibrary("d3dx9_43.dll"); - var vc2015 = Win32.LoadLibrary("vcruntime140.dll"); - var vc2012 = Win32.LoadLibrary("msvcr120.dll"); //TODO - check version? - var vc2010 = Win32.LoadLibrary("msvcr100.dll"); //TODO - check version? - var vc2010p = Win32.LoadLibrary("msvcp100.dll"); + var d3dx9 = libLoader.LoadPlatformSpecific("d3dx9_43.dll"); + var vc2015 = libLoader.LoadPlatformSpecific("vcruntime140.dll"); + var vc2012 = libLoader.LoadPlatformSpecific("msvcr120.dll"); //TODO - check version? + var vc2010 = libLoader.LoadPlatformSpecific("msvcr100.dll"); //TODO - check version? + var vc2010p = libLoader.LoadPlatformSpecific("msvcp100.dll"); bool fail = false, warn = false; warn |= d3dx9 == IntPtr.Zero; fail |= vc2015 == IntPtr.Zero; @@ -56,27 +58,28 @@ static Program() System.Diagnostics.Process.GetCurrentProcess().Kill(); } - Win32.FreeLibrary(d3dx9); - Win32.FreeLibrary(vc2015); - Win32.FreeLibrary(vc2012); - Win32.FreeLibrary(vc2010); - Win32.FreeLibrary(vc2010p); + libLoader.FreePlatformSpecific(d3dx9); + libLoader.FreePlatformSpecific(vc2015); + libLoader.FreePlatformSpecific(vc2012); + libLoader.FreePlatformSpecific(vc2010); + libLoader.FreePlatformSpecific(vc2010p); - // this will look in subdirectory "dll" to load pinvoked stuff - string dllDir = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "dll"); - SetDllDirectory(dllDir); - - //in case assembly resolution fails, such as if we moved them into the dll subdiretory, this event handler can reroute to them - AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); + if (!Global.RunningOnUnix) + { + // this will look in subdirectory "dll" to load pinvoked stuff + string dllDir = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "dll"); + SetDllDirectory(dllDir); - //but before we even try doing that, whack the MOTW from everything in that directory (thats a dll) - //otherwise, some people will have crashes at boot-up due to .net security disliking MOTW. - //some people are getting MOTW through a combination of browser used to download bizhawk, and program used to dearchive it - WhackAllMOTW(dllDir); + //in case assembly resolution fails, such as if we moved them into the dll subdiretory, this event handler can reroute to them + AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); - //We need to do it here too... otherwise people get exceptions when externaltools we distribute try to startup + //but before we even try doing that, whack the MOTW from everything in that directory (thats a dll) + //otherwise, some people will have crashes at boot-up due to .net security disliking MOTW. + //some people are getting MOTW through a combination of browser used to download bizhawk, and program used to dearchive it + WhackAllMOTW(dllDir); -#endif + //We need to do it here too... otherwise people get exceptions when externaltools we distribute try to startup + } } [STAThread] @@ -85,15 +88,177 @@ static int Main(string[] args) return SubMain(args); } - private static class Win32 + private interface PlatformSpecificLinkedLibs + { + IntPtr LoadPlatformSpecific(string dllToLoad); + IntPtr GetProcAddr(IntPtr hModule, string procName); + void FreePlatformSpecific(IntPtr hModule); + } + private class Win32 : PlatformSpecificLinkedLibs { [DllImport("kernel32.dll")] - public static extern IntPtr LoadLibrary(string dllToLoad); + private static extern IntPtr LoadLibrary(string dllToLoad); [DllImport("kernel32.dll")] - public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName); + private static extern IntPtr GetProcAddress(IntPtr hModule, string procName); [DllImport("kernel32.dll")] - public static extern bool FreeLibrary(IntPtr hModule); + private static extern void FreeLibrary(IntPtr hModule); + public IntPtr LoadPlatformSpecific(string dllToLoad) + { + return LoadLibrary(dllToLoad); + } + public IntPtr GetProcAddr(IntPtr hModule, string procName) + { + return GetProcAddress(hModule, procName); + } + public void FreePlatformSpecific(IntPtr hModule) + { + FreeLibrary(hModule); + } + } + private class UnixMono : PlatformSpecificLinkedLibs + { + // This class is copied from a tutorial, so don't git blame and then email me expecting insight. + const int RTLD_NOW = 2; + [DllImport("libdl.so")] + private static extern IntPtr dlopen(String fileName, int flags); + [DllImport("libdl.so")] + private static extern IntPtr dlerror(); + [DllImport("libdl.so")] + private static extern IntPtr dlsym(IntPtr handle, String symbol); + [DllImport("libdl.so")] + private static extern int dlclose(IntPtr handle); + public IntPtr LoadPlatformSpecific(string dllToLoad) + { + return dlopen(dllToLoad + ".so", RTLD_NOW); + } + public IntPtr GetProcAddr(IntPtr hModule, string procName) + { + dlerror(); + var res = dlsym(hModule, procName); + var errPtr = dlerror(); + if (errPtr != IntPtr.Zero) throw new Exception("dlsym: " + Marshal.PtrToStringAnsi(errPtr)); + return res; + } + public void FreePlatformSpecific(IntPtr hModule) + { + dlclose(hModule); + } + } + + private interface PlatformSpecificMainLoopCrashHandler + { + void TryCatchFinally(string[] args); + } + private class Win32MainLoopCrashHandler : PlatformSpecificMainLoopCrashHandler + { + public void TryCatchFinally(string[] args) + { + try + { + if (Global.Config.SingleInstanceMode) + { + try + { + new SingleInstanceController(args).Run(args); + } + catch (ObjectDisposedException) + { + // Eat it, MainForm disposed itself and Run attempts to dispose of itself. Eventually we would want to figure out a way to prevent that, but in the meantime it is harmless, so just eat the error + } + } + else + { + using (var mf = new MainForm(args)) + { + var title = mf.Text; + mf.Show(); + mf.Text = title; + try + { + GlobalWin.ExitCode = mf.ProgramRunLoop(); + } + catch (Exception e) when (!Debugger.IsAttached && !VersionInfo.DeveloperBuild && Global.MovieSession.Movie.IsActive) + { + var result = MessageBox.Show( + "EmuHawk has thrown a fatal exception and is about to close.\nA movie has been detected. Would you like to try to save?\n(Note: Depending on what caused this error, this may or may not succeed)", + "Fatal error: " + e.GetType().Name, + MessageBoxButtons.YesNo, + MessageBoxIcon.Exclamation + ); + if (result == DialogResult.Yes) + { + Global.MovieSession.Movie.Save(); + } + } + } + } + } + catch (Exception e) when (!Debugger.IsAttached) + { + new ExceptionBox(e).ShowDialog(); + } + finally + { + if (GlobalWin.Sound != null) + { + GlobalWin.Sound.Dispose(); + GlobalWin.Sound = null; + } + GlobalWin.GL.Dispose(); + Input.Cleanup(); + } + } + } + private class UnixMonoMainLoopCrashHandler : PlatformSpecificMainLoopCrashHandler + { + // Identical to the implementation in Win32MainLoopCrashHandler sans the single-instance check. + public void TryCatchFinally(string[] args) + { + try + { + using (var mf = new MainForm(args)) + { + var title = mf.Text; + mf.Show(); + mf.Text = title; + try + { + GlobalWin.ExitCode = mf.ProgramRunLoop(); + } + catch (Exception e) when (!Debugger.IsAttached && !VersionInfo.DeveloperBuild && Global.MovieSession.Movie.IsActive) + { + var result = MessageBox.Show( + "EmuHawk has thrown a fatal exception and is about to close.\nA movie has been detected. Would you like to try to save?\n(Note: Depending on what caused this error, this may or may not succeed)", + "Fatal error: " + e.GetType().Name, + MessageBoxButtons.YesNo, + MessageBoxIcon.Exclamation + ); + if (result == DialogResult.Yes) + { + Global.MovieSession.Movie.Save(); + } + } + } + } + catch (Exception e) when (!Debugger.IsAttached) + { + new ExceptionBox(e).ShowDialog(); + } + finally + { + if (GlobalWin.Sound != null) + { + GlobalWin.Sound.Dispose(); + GlobalWin.Sound = null; + } + GlobalWin.GL.Dispose(); + Input.Cleanup(); + } + } } + private static PlatformSpecificMainLoopCrashHandler mainLoopCrashHandler = Global.RunningOnUnix + ? (PlatformSpecificMainLoopCrashHandler) new UnixMonoMainLoopCrashHandler() + : (PlatformSpecificMainLoopCrashHandler) new Win32MainLoopCrashHandler(); //NoInlining should keep this code from getting jammed into Main() which would create dependencies on types which havent been setup by the resolver yet... or something like that [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] @@ -155,6 +320,7 @@ static int SubMain(string[] args) GlobalWin.GLManager = GLManager.Instance; //now create the "GL" context for the display method. we can reuse the IGL_TK context if opengl display method is chosen + if (Global.RunningOnUnix) Global.Config.DispMethod = Config.EDispMethod.GdiPlus; REDO_DISPMETHOD: if (Global.Config.DispMethod == Config.EDispMethod.GdiPlus) GlobalWin.GL = new Bizware.BizwareGL.Drivers.GdiPlus.IGL_GdiPlus(); @@ -202,72 +368,20 @@ static int SubMain(string[] args) goto REDO_DISPMETHOD; } - //WHY do we have to do this? some intel graphics drivers (ig7icd64.dll 10.18.10.3304 on an unknown chip on win8.1) are calling SetDllDirectory() for the process, which ruins stuff. - //The relevant initialization happened just before in "create IGL context". - //It isn't clear whether we need the earlier SetDllDirectory(), but I think we do. - //note: this is pasted instead of being put in a static method due to this initialization code being sensitive to things like that, and not wanting to cause it to break - //pasting should be safe (not affecting the jit order of things) - string dllDir = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "dll"); - SetDllDirectory(dllDir); - - try + if (!Global.RunningOnUnix) { -#if WINDOWS - if (Global.Config.SingleInstanceMode) - { - try - { - new SingleInstanceController(args).Run(args); - } - catch (ObjectDisposedException) - { - /*Eat it, MainForm disposed itself and Run attempts to dispose of itself. Eventually we would want to figure out a way to prevent that, but in the meantime it is harmless, so just eat the error*/ - } - } - else -#endif - { - using (var mf = new MainForm(args)) - { - var title = mf.Text; - mf.Show(); - mf.Text = title; - - try - { - GlobalWin.ExitCode = mf.ProgramRunLoop(); - } - catch (Exception e) when (!Debugger.IsAttached && !VersionInfo.DeveloperBuild && Global.MovieSession.Movie.IsActive) - { - var result = MessageBox.Show( - "EmuHawk has thrown a fatal exception and is about to close.\nA movie has been detected. Would you like to try to save?\n(Note: Depending on what caused this error, this may or may not succeed)", - "Fatal error: " + e.GetType().Name, - MessageBoxButtons.YesNo, - MessageBoxIcon.Exclamation - ); - if (result == DialogResult.Yes) - { - Global.MovieSession.Movie.Save(); - } - } - } - } - } - catch (Exception e) when (!Debugger.IsAttached) - { - new ExceptionBox(e).ShowDialog(); - } - finally - { - if (GlobalWin.Sound != null) - { - GlobalWin.Sound.Dispose(); - GlobalWin.Sound = null; - } - GlobalWin.GL.Dispose(); - Input.Cleanup(); + //WHY do we have to do this? some intel graphics drivers (ig7icd64.dll 10.18.10.3304 on an unknown chip on win8.1) are calling SetDllDirectory() for the process, which ruins stuff. + //The relevant initialization happened just before in "create IGL context". + //It isn't clear whether we need the earlier SetDllDirectory(), but I think we do. + //note: this is pasted instead of being put in a static method due to this initialization code being sensitive to things like that, and not wanting to cause it to break + //pasting should be safe (not affecting the jit order of things) + string dllDir = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "dll"); + SetDllDirectory(dllDir); } + // Using a simple conditional to skip the single-instancing step caused crashes on GNU+Linux, even though the single-instancing step wasn't being executed. Something about the way instantiation works in C# means this workaround is possible. + mainLoopCrashHandler.TryCatchFinally(args); + //cleanup: //cleanup IGL stuff so we can get better refcounts when exiting process, for debugging //DOESNT WORK FOR SOME REASON diff --git a/BizHawk.Client.EmuHawk/ScreenSaver.cs b/BizHawk.Client.EmuHawk/ScreenSaver.cs index dc799763472..70aedf15401 100644 --- a/BizHawk.Client.EmuHawk/ScreenSaver.cs +++ b/BizHawk.Client.EmuHawk/ScreenSaver.cs @@ -1,13 +1,48 @@ using System; using System.Runtime.InteropServices; +using BizHawk.Client.Common; + namespace BizHawk.Client.EmuHawk { // Derived from http://www.codeproject.com/KB/cs/ScreenSaverControl.aspx public static class ScreenSaver { - [DllImport("user32.dll", CharSet = CharSet.Auto)] - private static extern bool SystemParametersInfo(int uAction, int uParam, ref int lpvParam, int flags); + private interface PlatformSpecificScreenBlankInterface + { + Int32 Get(); + void Set(Int32 v); + } + private class WinScreenBlankInterface : PlatformSpecificScreenBlankInterface + { + [DllImport("user32.dll", CharSet = CharSet.Auto)] + private static extern bool SystemParametersInfo(int uAction, int uParam, ref int lpvParam, int flags); + public Int32 Get() + { + Int32 value = 0; + SystemParametersInfo(SPI_GETSCREENSAVERTIMEOUT, 0, ref value, 0); + return value; + } + public void Set(Int32 v) + { + int nullVar = 0; + SystemParametersInfo(SPI_SETSCREENSAVERTIMEOUT, v, ref nullVar, SPIF_SENDWININICHANGE); + } + } + private class MiscUnixScreenBlankInterface : PlatformSpecificScreenBlankInterface + { + public Int32 Get() + { + return 0; //TODO implement + } + public void Set(Int32 v) + { + //TODO implement + } + } + private static PlatformSpecificScreenBlankInterface screenBlankInterface = Global.RunningOnUnix + ? (PlatformSpecificScreenBlankInterface) new MiscUnixScreenBlankInterface() + : (PlatformSpecificScreenBlankInterface) new WinScreenBlankInterface(); private const int SPI_GETSCREENSAVERTIMEOUT = 14; private const int SPI_SETSCREENSAVERTIMEOUT = 15; @@ -32,16 +67,13 @@ public static void ResetTimerPeriodically() // Returns the screen saver timeout setting, in seconds private static Int32 GetScreenSaverTimeout() { - Int32 value = 0; - SystemParametersInfo(SPI_GETSCREENSAVERTIMEOUT, 0, ref value, 0); - return value; + return screenBlankInterface.Get(); } // Pass in the number of seconds to set the screen saver timeout value. private static void SetScreenSaverTimeout(Int32 Value) { - int nullVar = 0; - SystemParametersInfo(SPI_SETSCREENSAVERTIMEOUT, Value, ref nullVar, SPIF_SENDWININICHANGE); + screenBlankInterface.Set(Value); } } } diff --git a/BizHawk.Client.EmuHawk/Sound/Sound.cs b/BizHawk.Client.EmuHawk/Sound/Sound.cs index 88a94e44c96..93abdb7f402 100644 --- a/BizHawk.Client.EmuHawk/Sound/Sound.cs +++ b/BizHawk.Client.EmuHawk/Sound/Sound.cs @@ -24,17 +24,15 @@ public class Sound : IDisposable public Sound(IntPtr mainWindowHandle) { -#if WINDOWS - if (Global.Config.SoundOutputMethod == Config.ESoundOutputMethod.DirectSound) - _outputDevice = new DirectSoundSoundOutput(this, mainWindowHandle); - - if (Global.Config.SoundOutputMethod == Config.ESoundOutputMethod.XAudio2) - _outputDevice = new XAudio2SoundOutput(this); -#endif - if (Global.Config.SoundOutputMethod == Config.ESoundOutputMethod.OpenAL) _outputDevice = new OpenALSoundOutput(this); - + if (!Global.RunningOnUnix) + { + if (Global.Config.SoundOutputMethod == Config.ESoundOutputMethod.DirectSound) + _outputDevice = new DirectSoundSoundOutput(this, mainWindowHandle); + if (Global.Config.SoundOutputMethod == Config.ESoundOutputMethod.XAudio2) + _outputDevice = new XAudio2SoundOutput(this); + } if (_outputDevice == null) _outputDevice = new DummySoundOutput(this); } diff --git a/BizHawk.Client.EmuHawk/Throttle.cs b/BizHawk.Client.EmuHawk/Throttle.cs index 66be309a648..3ae65cdc703 100644 --- a/BizHawk.Client.EmuHawk/Throttle.cs +++ b/BizHawk.Client.EmuHawk/Throttle.cs @@ -137,10 +137,33 @@ static ulong GetCurTime() return (ulong)Environment.TickCount; } -#if WINDOWS - [DllImport("winmm.dll", EntryPoint = "timeBeginPeriod")] - static extern uint timeBeginPeriod(uint uMilliseconds); -#endif + 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 + { + [DllImport("winmm.dll.so", EntryPoint = "timeBeginPeriod")] + private static extern uint timeBeginPeriod(uint uMilliseconds); + public uint TimeBeginPeriod(uint ms) + { + return timeBeginPeriod(ms); + } + } + static PlatformSpecificSysTimer sysTimer = Global.RunningOnUnix ? (PlatformSpecificSysTimer) new UnixMonoSysTimer() : (PlatformSpecificSysTimer) new WinSysTimer(); + static uint TimeBeginPeriod(uint ms) + { + return sysTimer.TimeBeginPeriod(ms); + } static readonly int tmethod; static readonly ulong afsfreq; @@ -148,9 +171,7 @@ static ulong GetCurTime() static Throttle() { -#if WINDOWS - timeBeginPeriod(1); -#endif + TimeBeginPeriod(1); if (Stopwatch.IsHighResolution) { afsfreq = (ulong)Stopwatch.Frequency; @@ -341,7 +362,7 @@ void SpeedThrottle(bool paused) if (sleepTime >= 2 || paused) { #if WINDOWS - // Assuming a timer period of 1 ms (i.e. timeBeginPeriod(1)): The actual sleep time + // Assuming a timer period of 1 ms (i.e. TimeBeginPeriod(1)): The actual sleep time // on Windows XP is generally within a half millisecond either way of the requested // time. The actual sleep time on Windows 8 is generally between the requested time // and up to a millisecond over. So we'll subtract 1 ms from the time to avoid diff --git a/Bizware/BizHawk.Bizware.BizwareGL.OpenTK/IGL_TK.cs b/Bizware/BizHawk.Bizware.BizwareGL.OpenTK/IGL_TK.cs index 0dd236b7b71..349bc678195 100644 --- a/Bizware/BizHawk.Bizware.BizwareGL.OpenTK/IGL_TK.cs +++ b/Bizware/BizHawk.Bizware.BizwareGL.OpenTK/IGL_TK.cs @@ -287,10 +287,10 @@ public Pipeline CreatePipeline(VertexLayout vertexLayout, Shader vertexShader, S for (int i = 0; i < nAttributes; i++) { int size, length; - var sbName = new System.Text.StringBuilder(1024); + string name = new System.Text.StringBuilder(1024).ToString(); ActiveAttribType type; - GL.GetActiveAttrib(pid, i, 1024, out length, out size, out type, sbName); - attributes.Add(new AttributeInfo() { Handle = new IntPtr(i), Name = sbName.ToString() }); + GL.GetActiveAttrib(pid, i, 1024, out length, out size, out type, out name); + attributes.Add(new AttributeInfo() { Handle = new IntPtr(i), Name = name }); } //get all the uniforms @@ -303,10 +303,9 @@ public Pipeline CreatePipeline(VertexLayout vertexLayout, Shader vertexShader, S { int size, length; ActiveUniformType type; - var sbName = new System.Text.StringBuilder(1024); - GL.GetActiveUniform(pid, i, 1024, out length, out size, out type, sbName); + string name = new System.Text.StringBuilder(1024).ToString().ToString(); + GL.GetActiveUniform(pid, i, 1024, out length, out size, out type, out name); errcode = GL.GetError(); - string name = sbName.ToString(); int loc = GL.GetUniformLocation(pid, name); //translate name if appropriate diff --git a/Bizware/BizHawk.Bizware.BizwareGL.SlimDX/IGL_SlimDX9.cs b/Bizware/BizHawk.Bizware.BizwareGL.SlimDX/IGL_SlimDX9.cs index 6447c3e2a4c..e4378753038 100644 --- a/Bizware/BizHawk.Bizware.BizwareGL.SlimDX/IGL_SlimDX9.cs +++ b/Bizware/BizHawk.Bizware.BizwareGL.SlimDX/IGL_SlimDX9.cs @@ -311,18 +311,20 @@ Blend ConvertBlendArg(gl.BlendingFactorSrc glmode) if(glmode == gl.BlendingFactorSrc.DstColor) return Blend.DestinationColor; if(glmode == gl.BlendingFactorSrc.OneMinusDstColor) return Blend.InverseDestinationColor; if(glmode == gl.BlendingFactorSrc.SrcAlphaSaturate) return Blend.SourceAlphaSaturated; - if(glmode == gl.BlendingFactorSrc.ConstantColorExt) throw new NotSupportedException(); if(glmode == gl.BlendingFactorSrc.ConstantColor) return Blend.BlendFactor; if(glmode == gl.BlendingFactorSrc.OneMinusConstantColor) return Blend.InverseBlendFactor; - if(glmode == gl.BlendingFactorSrc.OneMinusConstantColorExt) throw new NotSupportedException(); if(glmode == gl.BlendingFactorSrc.ConstantAlpha) throw new NotSupportedException(); - if(glmode == gl.BlendingFactorSrc.ConstantAlphaExt) throw new NotSupportedException(); - if(glmode == gl.BlendingFactorSrc.OneMinusConstantAlphaExt) throw new NotSupportedException(); if(glmode == gl.BlendingFactorSrc.OneMinusConstantAlpha) throw new NotSupportedException(); if(glmode == gl.BlendingFactorSrc.Src1Alpha) throw new NotSupportedException(); if(glmode == gl.BlendingFactorSrc.Src1Color) throw new NotSupportedException(); if(glmode == gl.BlendingFactorSrc.OneMinusSrc1Color) throw new NotSupportedException(); if (glmode == gl.BlendingFactorSrc.OneMinusSrc1Alpha) throw new NotSupportedException(); + /* Compiles when commented + if(glmode == gl.BlendingFactorSrc.ConstantColorExt) throw new NotSupportedException(); + if(glmode == gl.BlendingFactorSrc.OneMinusConstantColorExt) throw new NotSupportedException(); + if(glmode == gl.BlendingFactorSrc.ConstantAlphaExt) throw new NotSupportedException(); + if(glmode == gl.BlendingFactorSrc.OneMinusConstantAlphaExt) throw new NotSupportedException(); + */ throw new ArgumentOutOfRangeException(); } diff --git a/References/OpenTK.dll b/References/OpenTK.dll index 9e34c2f1e42..4ded127209e 100644 Binary files a/References/OpenTK.dll and b/References/OpenTK.dll differ