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.TempFileManager.Start(); HawkFile.ArchiveHandlerFactory = new SevenZipSharpArchiveHandler(); ArgParser argParser = new ArgParser(); argParser.ParseArguments(args); if (argParser.cmdConfigFile != null) { PathManager.SetDefaultIniPath(argParser.cmdConfigFile); } try { Global.Config = ConfigService.Load <Config>(PathManager.DefaultIniPath); } catch (Exception e) { new ExceptionBox(e).ShowDialog(); new ExceptionBox("Since your config file is corrupted, we're going to recreate it. Back it up before proceeding if you want to investigate further.").ShowDialog(); File.Delete(PathManager.DefaultIniPath); Global.Config = ConfigService.Load <Config>(PathManager.DefaultIniPath); } 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; //now create the "GL" context for the display method. we can reuse the IGL_TK context if opengl display method is chosen if (EXE_PROJECT.PlatformLinkedLibSingleton.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(); } 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 try { using (GlobalWin.GL.CreateRenderer()) { } } 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; } if (!EXE_PROJECT.PlatformLinkedLibSingleton.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); } // 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 //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
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(); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); 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) { GlobalWin.GL = new Bizware.BizwareGL.Drivers.SlimDX.IGL_SlimDX9(); } 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; } } //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 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
private 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 // and don't bother when installed from a package manager i.e. not Windows --yoshi if (!VersionInfo.DeveloperBuild && EXE_PROJECT.OSTailoredCode.CurrentOS == EXE_PROJECT.OSTailoredCode.DistinctOS.Windows) { 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); } } TempFileManager.Start(); HawkFile.ArchiveHandlerFactory = new SevenZipSharpArchiveHandler(); string cmdConfigFile = ArgParser.GetCmdConfigFile(args); if (cmdConfigFile != null) { PathManager.SetDefaultIniPath(cmdConfigFile); } try { Global.Config = ConfigService.Load <Config>(PathManager.DefaultIniPath); } catch (Exception e) { new ExceptionBox(e).ShowDialog(); new ExceptionBox("Since your config file is corrupted, we're going to recreate it. Back it up before proceeding if you want to investigate further.").ShowDialog(); File.Delete(PathManager.DefaultIniPath); Global.Config = ConfigService.Load <Config>(PathManager.DefaultIniPath); } Global.Config.ResolveDefaults(); StringLogUtil.DefaultToDisk = Global.Config.MoviesOnDisk; StringLogUtil.DefaultToAWE = Global.Config.MoviesInAWE; // super hacky! this needs to be done first. still not worth the trouble to make this system fully proper if (Array.Exists(args, arg => arg.StartsWith("--gdi", StringComparison.InvariantCultureIgnoreCase))) { 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; //now create the "GL" context for the display method. we can reuse the IGL_TK context if opengl display method is chosen if (EXE_PROJECT.OSTailoredCode.CurrentOS != EXE_PROJECT.OSTailoredCode.DistinctOS.Windows) { Global.Config.DispMethod = Config.EDispMethod.GdiPlus; } 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) { new ExceptionBox(new Exception("Initialization of Direct3d 9 Display Method failed; falling back to GDI+", ex)).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 if (GlobalWin.IGL_GL.Version < 200) { // fallback Global.Config.DispMethod = Config.EDispMethod.GdiPlus; goto REDO_DISPMETHOD; } } // try creating a GUI Renderer. If that doesn't succeed. we fallback try { using (GlobalWin.GL.CreateRenderer()) { } } catch (Exception ex) { new ExceptionBox(new Exception("Initialization of Display Method failed; falling back to GDI+", ex)).ShowDialog(); //fallback Global.Config.DispMethod = Config.EDispMethod.GdiPlus; goto REDO_DISPMETHOD; } if (EXE_PROJECT.OSTailoredCode.CurrentOS == EXE_PROJECT.OSTailoredCode.DistinctOS.Windows) { //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) var dllDir = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "dll"); SetDllDirectory(dllDir); } try { if (Global.Config.SingleInstanceMode) { try { new SingleInstanceController(args).Run(); } 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(Global.MovieSession.Movie.IsActive && !(Debugger.IsAttached || VersionInfo.DeveloperBuild)) { 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 { GlobalWin.Sound?.Dispose(); GlobalWin.Sound = null; GlobalWin.GL.Dispose(); Input.Cleanup(); } //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