public static void Initialize() { if (dinput == null) dinput = new DirectInput(); Devices = new List<GamePad>(); foreach (DeviceInstance device in dinput.GetDevices(DeviceClass.GameController, DeviceEnumerationFlags.AttachedOnly)) { Console.WriteLine("joydevice: {0} `{1}`", device.InstanceGuid, device.ProductName); if (device.ProductName.Contains("XBOX 360")) continue; // Don't input XBOX 360 controllers into here; we'll process them via XInput (there are limitations in some trigger axes when xbox pads go over xinput) var joystick = new Joystick(dinput, device.InstanceGuid); joystick.SetCooperativeLevel(GlobalWin.MainForm.Handle, CooperativeLevel.Background | CooperativeLevel.Nonexclusive); foreach (DeviceObjectInstance deviceObject in joystick.GetObjects()) { if ((deviceObject.ObjectType & ObjectDeviceType.Axis) != 0) joystick.GetObjectPropertiesById((int)deviceObject.ObjectType).SetRange(-1000, 1000); } joystick.Acquire(); GamePad p = new GamePad(device.InstanceName, device.InstanceGuid, joystick); Devices.Add(p); } }
private void UpdateThreadProc() { while (true) { var keyEvents = OSTailoredCode.IsUnixHost ? OTK_Keyboard.Update() : KeyInput.Update().Concat(IPCKeyInput.Update()); if (OSTailoredCode.IsUnixHost) { OTK_GamePad.UpdateAll(); } else { GamePad.UpdateAll(); GamePad360.UpdateAll(); } //this block is going to massively modify data structures that the binding method uses, so we have to lock it all lock (this) { _newEvents.Clear(); //analyze keys foreach (var ke in keyEvents) { HandleButton(ke.Key.ToString(), ke.Pressed, InputFocus.Keyboard); } lock (_floatValues) { //FloatValues.Clear(); // analyze OpenTK xinput (or is it libinput?) foreach (var pad in OTK_GamePad.EnumerateDevices()) { foreach (var but in pad.buttonObjects) { HandleButton(pad.InputNamePrefix + but.ButtonName, but.ButtonAction(), InputFocus.Pad); } foreach (var sv in pad.GetFloats()) { var n = $"{pad.InputNamePrefix}{sv.Item1} Axis"; var f = sv.Item2; if (_trackDeltas) { _floatDeltas[n] += Math.Abs(f - _floatValues[n]); } _floatValues[n] = f; } } // analyze xinput foreach (var pad in GamePad360.EnumerateDevices()) { string xName = $"X{pad.PlayerNumber} "; for (int b = 0; b < pad.NumButtons; b++) { HandleButton(xName + pad.ButtonName(b), pad.Pressed(b), InputFocus.Pad); } foreach (var sv in pad.GetFloats()) { string n = xName + sv.Item1; float f = sv.Item2; if (_trackDeltas) { _floatDeltas[n] += Math.Abs(f - _floatValues[n]); } _floatValues[n] = f; } } // analyze joysticks foreach (var pad in GamePad.EnumerateDevices()) { string jName = $"J{pad.PlayerNumber} "; for (int b = 0; b < pad.NumButtons; b++) { HandleButton(jName + pad.ButtonName(b), pad.Pressed(b), InputFocus.Pad); } foreach (var sv in pad.GetFloats()) { string n = jName + sv.Item1; float f = sv.Item2; //if (n == "J5 RotationZ") // System.Diagnostics.Debugger.Break(); if (_trackDeltas) { _floatDeltas[n] += Math.Abs(f - _floatValues[n]); } _floatValues[n] = f; } } // analyze moose // other sorts of mouse api (raw input) could easily be added as a separate listing under a different class if (_wantingMouseFocus.Contains(Form.ActiveForm)) { var mousePos = Control.MousePosition; if (_trackDeltas) { // these are relative to screen coordinates, but that's not terribly important _floatDeltas["WMouse X"] += Math.Abs(mousePos.X - _floatValues["WMouse X"]) * 50; _floatDeltas["WMouse Y"] += Math.Abs(mousePos.Y - _floatValues["WMouse Y"]) * 50; } // coordinate translation happens later _floatValues["WMouse X"] = mousePos.X; _floatValues["WMouse Y"] = mousePos.Y; var mouseBtns = Control.MouseButtons; HandleButton("WMouse L", (mouseBtns & MouseButtons.Left) != 0, InputFocus.Mouse); HandleButton("WMouse C", (mouseBtns & MouseButtons.Middle) != 0, InputFocus.Mouse); HandleButton("WMouse R", (mouseBtns & MouseButtons.Right) != 0, InputFocus.Mouse); HandleButton("WMouse 1", (mouseBtns & MouseButtons.XButton1) != 0, InputFocus.Mouse); HandleButton("WMouse 2", (mouseBtns & MouseButtons.XButton2) != 0, InputFocus.Mouse); } else { // don't do this: for now, it will interfere with the virtualpad. don't do something similar for the mouse position either // unpress all buttons //HandleButton("WMouse L", false); //HandleButton("WMouse C", false); //HandleButton("WMouse R", false); //HandleButton("WMouse 1", false); //HandleButton("WMouse 2", false); } } if (_newEvents.Count != 0) { //WHAT!? WE SHOULD NOT BE SO NAIVELY TOUCHING MAINFORM FROM THE INPUTTHREAD. ITS BUSY RUNNING. AllowInput allowInput = GlobalWin.MainForm.AllowInput(false); foreach (var ie in _newEvents) { //events are swallowed in some cases: if (ie.LogicalButton.Alt && ShouldSwallow(GlobalWin.MainForm.AllowInput(true), ie)) { continue; } if (ie.EventType == InputEventType.Press && ShouldSwallow(allowInput, ie)) { continue; } EnqueueEvent(ie); } } _ignoreEventsNextPoll = false; } //lock(this) //arbitrary selection of polling frequency: Thread.Sleep(10); } }
static void SubMain(string[] args) { // this check has to be done VERY early. i stepped through a debug build with wrong .dll versions purposely used, // and there was a TypeLoadException before the first line of SubMain was reached (some static ColorType init?) // zero 25-dec-2012 - only do for public builds. its annoying during development if (!VersionInfo.DeveloperBuild) { var thisversion = typeof(Program).Assembly.GetName().Version; var utilversion = Assembly.LoadWithPartialName("Bizhawk.Client.Common").GetName().Version; var emulversion = Assembly.LoadWithPartialName("Bizhawk.Emulation.Cores").GetName().Version; if (thisversion != utilversion || thisversion != emulversion) { MessageBox.Show("Conflicting revisions found! Don't mix .dll versions!"); return; } } Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); string iniPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "config.ini"); Global.Config = ConfigService.Load <Config>(iniPath); Global.Config.ResolveDefaults(); HawkFile.ArchiveHandlerFactory = new SevenZipSharpArchiveHandler(); #if WINDOWS try { GlobalWin.DSound = SoundEnumeration.Create(); } catch { MessageBox.Show("Couldn't initialize DirectSound! Things may go poorly for you. Try changing your sound driver to 41khz instead of 48khz in mmsys.cpl.", "Initialization Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } #endif //create IGL context. //at some point in the future, we may need to select from several drivers GlobalWin.GL = new Bizware.BizwareGL.Drivers.OpenTK.IGL_TK(); GlobalWin.GLManager = new GLManager(); GlobalWin.CR_GL = GlobalWin.GLManager.GetContextForIGL(GlobalWin.GL); //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 { mf.ProgramRunLoop(); } catch (Exception e) { #if WINDOWS if (!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 succeed)", "Fatal error: " + e.GetType().Name, MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation ); if (result == DialogResult.Yes) { Global.MovieSession.Movie.Save(); } } #endif throw; } } #if WINDOWS } #endif } catch (Exception e) { string message = e.ToString(); if (e.InnerException != null) { message += "\n\nInner Exception:\n\n" + e.InnerException; } message += "\n\nStackTrace:\n" + e.StackTrace; MessageBox.Show(message); } #if WINDOWS finally { if (GlobalWin.DSound != null && GlobalWin.DSound.Disposed == false) { GlobalWin.DSound.Dispose(); } GlobalWin.GL.Dispose(); GamePad.CloseAll(); } #endif }
static int SubMain(string[] args) { // this check has to be done VERY early. i stepped through a debug build with wrong .dll versions purposely used, // and there was a TypeLoadException before the first line of SubMain was reached (some static ColorType init?) // zero 25-dec-2012 - only do for public builds. its annoying during development if (!VersionInfo.DeveloperBuild) { var thisversion = typeof(Program).Assembly.GetName().Version; var utilversion = Assembly.Load(new AssemblyName("Bizhawk.Client.Common")).GetName().Version; var emulversion = Assembly.Load(new AssemblyName("Bizhawk.Emulation.Cores")).GetName().Version; if (thisversion != utilversion || thisversion != emulversion) { MessageBox.Show("Conflicting revisions found! Don't mix .dll versions!"); return(-1); } } BizHawk.Common.TempFileCleaner.Start(); HawkFile.ArchiveHandlerFactory = new SevenZipSharpArchiveHandler(); string iniPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "config.ini"); Global.Config = ConfigService.Load <Config>(iniPath); Global.Config.ResolveDefaults(); BizHawk.Client.Common.StringLogUtil.DefaultToDisk = Global.Config.MoviesOnDisk; BizHawk.Client.Common.StringLogUtil.DefaultToAWE = Global.Config.MoviesInAWE; //super hacky! this needs to be done first. still not worth the trouble to make this system fully proper for (int i = 0; i < args.Length; i++) { var arg = args[i].ToLower(); if (arg.StartsWith("--gdi")) { Global.Config.DispMethod = Config.EDispMethod.GdiPlus; } } //create IGL context. we do this whether or not the user has selected OpenGL, so that we can run opengl-based emulator cores GlobalWin.IGL_GL = new Bizware.BizwareGL.Drivers.OpenTK.IGL_TK(2, 0, false); //setup the GL context manager, needed for coping with multiple opengl cores vs opengl display method GLManager.CreateInstance(GlobalWin.IGL_GL); GlobalWin.GLManager = GLManager.Instance; GlobalWin.CR_GL = GlobalWin.GLManager.GetContextForIGL(GlobalWin.GL); //now create the "GL" context for the display method. we can reuse the IGL_TK context if opengl display method is chosen REDO_DISPMETHOD: if (Global.Config.DispMethod == Config.EDispMethod.GdiPlus) { GlobalWin.GL = new Bizware.BizwareGL.Drivers.GdiPlus.IGL_GdiPlus(); } else if (Global.Config.DispMethod == Config.EDispMethod.SlimDX9) { try { GlobalWin.GL = new Bizware.BizwareGL.Drivers.SlimDX.IGL_SlimDX9(); } catch (Exception ex) { var e2 = new Exception("Initialization of Direct3d 9 Display Method failed; falling back to GDI+", ex); new ExceptionBox(e2).ShowDialog(); //fallback Global.Config.DispMethod = Config.EDispMethod.GdiPlus; goto REDO_DISPMETHOD; } } else { GlobalWin.GL = GlobalWin.IGL_GL; //check the opengl version and dont even try to boot this crap up if its too old int version = GlobalWin.IGL_GL.Version; if (version < 200) { //fallback Global.Config.DispMethod = Config.EDispMethod.GdiPlus; goto REDO_DISPMETHOD; } } //try creating a GUI Renderer. If that doesn't succeed. we fallback //TODO - need a factory for the GUI Renderer, I hate pasting this code try { BizHawk.Bizware.BizwareGL.IGuiRenderer Renderer; if (GlobalWin.GL is BizHawk.Bizware.BizwareGL.Drivers.OpenTK.IGL_TK) { Renderer = new BizHawk.Bizware.BizwareGL.GuiRenderer(GlobalWin.GL); } else if (GlobalWin.GL is BizHawk.Bizware.BizwareGL.Drivers.SlimDX.IGL_SlimDX9) { Renderer = new BizHawk.Bizware.BizwareGL.GuiRenderer(GlobalWin.GL); } else { Renderer = new BizHawk.Bizware.BizwareGL.Drivers.GdiPlus.GDIPlusGuiRenderer((BizHawk.Bizware.BizwareGL.Drivers.GdiPlus.IGL_GdiPlus)GlobalWin.GL); } } catch (Exception ex) { var e2 = new Exception("Initialization of Display Method failed; falling back to GDI+", ex); new ExceptionBox(e2).ShowDialog(); //fallback Global.Config.DispMethod = Config.EDispMethod.GdiPlus; 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 (System.Diagnostics.Debugger.IsAttached) { // Let the debugger handle errors #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; GlobalWin.ExitCode = mf.ProgramRunLoop(); } } } else { // Display error message windows 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; if (System.Diagnostics.Debugger.IsAttached) { GlobalWin.ExitCode = mf.ProgramRunLoop(); } else { try { GlobalWin.ExitCode = mf.ProgramRunLoop(); } catch (Exception e) { #if WINDOWS if (!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(); } } #endif throw; } } } } } catch (Exception e) { new ExceptionBox(e).ShowDialog(); } #if WINDOWS finally { if (GlobalWin.Sound != null) { GlobalWin.Sound.Dispose(); GlobalWin.Sound = null; } GlobalWin.GL.Dispose(); GamePad.CloseAll(); } #endif } //cleanup: //cleanup IGL stuff so we can get better refcounts when exiting process, for debugging //DOESNT WORK FOR SOME REASON //GlobalWin.IGL_GL = new Bizware.BizwareGL.Drivers.OpenTK.IGL_TK(); //GLManager.Instance.Dispose(); //if (GlobalWin.IGL_GL != GlobalWin.GL) // GlobalWin.GL.Dispose(); //((IDisposable)GlobalWin.IGL_GL).Dispose(); //return 0 assuming things have gone well, non-zero values could be used as error codes or for scripting purposes return(GlobalWin.ExitCode); } //SubMain