Allow bizhawk to be built and run w/ MSBuild and Wine+Mono on GNU+Linux (#1237)

- Update to latest OpenTK, add input code from `mono-stable` branch
(kudos), and fix bugs arisen from version differences
- Move some functionality into Win-specific classes and add Wine+Mono
implementation where simple
- Add conditions to main loop so some things only run on Windows
This commit is contained in:
James Groom 2018-11-05 04:05:20 +11:00 committed by feos
parent 30bf94e68d
commit ca021d96cc
12 changed files with 549 additions and 132 deletions

View File

@ -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;
@ -158,5 +159,7 @@ namespace BizHawk.Client.Common
}
public static Dictionary<string, object> UserBag = new Dictionary<string, object>();
public static bool RunningOnUnix = Environment.OSVersion.Platform == PlatformID.Unix || Environment.OSVersion.Platform == PlatformID.MacOSX;
}
}

View File

@ -662,6 +662,8 @@
<Compile Include="Input\GamePad.cs" />
<Compile Include="Input\GamePad360.cs" />
<Compile Include="Input\Input.cs" />
<Compile Include="Input\OTK_Gamepad.cs" />
<Compile Include="Input\OTK_Keyboard.cs" />
<Compile Include="IControlMainform.cs" />
<Compile Include="Input\IPCKeyInput.cs" />
<Compile Include="JumpLists.cs" />

View File

@ -4,6 +4,8 @@ using System.Collections.Generic;
using System.Threading;
#if WINDOWS
using SlimDX.DirectInput;
#else
using OpenTK.Input;
#endif
using BizHawk.Common;
@ -126,12 +128,18 @@ namespace BizHawk.Client.EmuHawk
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();
}

View File

@ -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<OTK_GamePad> 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<OTK_GamePad>();
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<Tuple<string, float>> GetFloats()
{
for (int pi = 0; pi < 64; pi++)
yield return new Tuple<string, float>(pi.ToString(), 10.0f * state.GetAxis(pi));
}
/// <summary>FOR DEBUGGING ONLY</summary>
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<string> names = new List<string>();
private readonly List<Func<bool>> actions = new List<Func<bool>>();
void AddItem(string _name, Func<bool> 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.
}
}
}

View File

@ -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;
}
}
}

View File

@ -23,16 +23,18 @@ namespace BizHawk.Client.EmuHawk
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 @@ namespace BizHawk.Client.EmuHawk
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 @@ namespace BizHawk.Client.EmuHawk
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 @@ namespace BizHawk.Client.EmuHawk
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,71 +368,19 @@ namespace BizHawk.Client.EmuHawk
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);
if (!Global.RunningOnUnix)
{
//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 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();
}
// 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

View File

@ -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 @@ namespace BizHawk.Client.EmuHawk
// 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);
}
}
}

View File

@ -24,17 +24,15 @@ namespace BizHawk.Client.EmuHawk
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);
}

View File

@ -137,10 +137,33 @@ namespace BizHawk.Client.EmuHawk
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 @@ namespace BizHawk.Client.EmuHawk
static Throttle()
{
#if WINDOWS
timeBeginPeriod(1);
#endif
TimeBeginPeriod(1);
if (Stopwatch.IsHighResolution)
{
afsfreq = (ulong)Stopwatch.Frequency;
@ -341,7 +362,7 @@ namespace BizHawk.Client.EmuHawk
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

View File

@ -287,10 +287,10 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.OpenTK
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 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.OpenTK
{
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

View File

@ -311,18 +311,20 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.SlimDX
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();
}

Binary file not shown.