using System.ComponentModel; using System.Diagnostics; using System.Drawing; using System.IO; using System.Windows.Forms; using BizHawk.Client.Common; using BizHawk.Client.EmuHawk.CustomControls; using BizHawk.Client.EmuHawk.Filters; using BizHawk.Common; using BizHawk.Common.NumberExtensions; using BizHawk.Emulation.Common; namespace BizHawk.Client.EmuHawk { /// Fields for controls are declared above the method in which they're initialised. /// public sealed class DisplayConfigLite : Form { public bool NeedReset; //TODO can we use DialogResult.Yes/No/Abort instead of OK/Abort plus this extra bool? /// HACK NullHawk's settings don't normally persist to config private static NullEmulator.NullEmulatorSettings NullHawkSettings { get => (Global.Emulator as NullEmulator)?.GetSettings() ?? (NullEmulator.NullEmulatorSettings) Global.Config.GetCoreSettings(); set { if (Global.Emulator is NullEmulator nullHawk) nullHawk.PutSettings(value); else Global.Config.PutCoreSettings(value); } } private readonly IContainer Components = new Container(); private readonly ComponentResourceManager Resources = new ComponentResourceManager(typeof(DisplayConfigLite)); private string PathSelection = Global.Config.DispUserFilterPath ?? ""; public DisplayConfigLite() { var lnlblDocs = new LinkLabel { Anchor = AnchorStyles.Bottom | AnchorStyles.Left, AutoSize = true, Location = new Point(10, 348), Text = "DisplayConfig wiki page" }; lnlblDocs.LinkClicked += (sender, e) => Process.Start("http://tasvideos.org/Bizhawk/DisplayConfig.html"); var btnOk = new Button { Text = "OK", UseVisualStyleBackColor = true }; btnOk.Click += (sender, e) => SaveControlsTo(Global.Config); var btnCancel = new Button { Text = "Cancel", UseVisualStyleBackColor = true }; SuspendLayout(); AcceptButton = btnOk; AutoScaleDimensions = new SizeF(6f, 13f); AutoScaleMode = AutoScaleMode.Font; CancelButton = btnCancel; ClientSize = new Size(520, 376); Controls.AddRange(new Control[] { new TabControl { Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right, Controls = { CreateDispMethodTab(), CreateWindowTab(), CreateScalingTab(), CreateMiscTab() }, Location = new Point(8, 8), Size = new Size(504, 328) }, lnlblDocs, new SingleRowFLP { Anchor = AnchorStyles.Bottom | AnchorStyles.Right, Controls = { btnOk, btnCancel }, Location = new Point(354, 344) } }); FormBorderStyle = FormBorderStyle.FixedDialog; Name = typeof(DisplayConfigLite).Name; StartPosition = FormStartPosition.CenterParent; Text = "Display Configuration"; ResumeLayout(); } private RadioButton rbD3D9; private CheckBox cbAlternateVsync; private RadioButton rbOpenGL; private RadioButton rbGDIPlus; private TabPage CreateDispMethodTab() { rbD3D9 = new RadioButton { AutoSize = true, Enabled = OSTailoredCode.CurrentOS == OSTailoredCode.DistinctOS.Windows, // SlimDX obviously doesn't work on Unix TabIndex = 1, Text = "Direct3D9", UseVisualStyleBackColor = true }; cbAlternateVsync = new CheckBox { AutoSize = true, Checked = Global.Config.DispAlternateVsync, TabIndex = 0, Text = "Use alternate VSync method", UseVisualStyleBackColor = true }; rbOpenGL = new RadioButton { AutoSize = true, TabIndex = 1, Text = "OpenGL", UseVisualStyleBackColor = true }; rbGDIPlus = new RadioButton { AutoSize = true, TabIndex = 1, Text = "GDI+", UseVisualStyleBackColor = true }; var indent = new Padding(24, 0, 0, 0); var grpDispMethodRadios = new FLPInGroupBox { Controls = { rbD3D9, new SingleColumnFLP { Controls = { new AutosizedLabel("• Probably the best for older graphics cards\n• May cause issues with OpenGL-based cores (i.e. Mupen64Plus)"), cbAlternateVsync, new Label { Margin = indent, Size = new Size(320, 40), Text = Resources.GetString("lblD3DAltVSync.Text") } }, Enabled = rbD3D9.Enabled, // disabled on Unix Margin = indent, Size = new Size(392, 76) }, rbOpenGL, new AutosizedLabel("• May have reduced performance or even malfunction on some systems\n• May have increased performance with OpenGL-based emulation cores (i.e. Mupen64Plus)") { Margin = indent }, rbGDIPlus, new AutosizedLabel("• Slow and missing features, kept in to maximise compatibility\n• Works better over MS' Remote Desktop Protocol") { Margin = indent } }, InnerFLP = { AutoSize = true, Padding = new Padding(3, 0, 3, 0) }, Size = new Size(480, 230) }; var checkedRadio = Global.Config.DispMethod switch { Config.EDispMethod.OpenGL => rbOpenGL, Config.EDispMethod.GdiPlus => rbGDIPlus, Config.EDispMethod.SlimDX9 => rbD3D9, _ => null }; if (checkedRadio != null) checkedRadio.Checked = true; return new TabPage { AutoSize = true, Controls = { new SingleColumnFLP { Controls = { grpDispMethodRadios, new AutosizedLabel("Changes require restart of program to take effect.\n\nPlease note that, for now, Mupen64Plus will use OpenGL regardless of this setting.") }, Size = new Size(416, 304) } }, Text = "Display Method", UseVisualStyleBackColor = true }; } private Label lblFrameTypeWindowed; private TransparentTrackBar tbFrameSizeWindowed; private CheckBox cbStatusBarWindowed; private CheckBox cbCaptionWindowed; private CheckBox cbMenuWindowed; private FLPInGroupBox CreateWindowedGroupBox() { lblFrameTypeWindowed = new Label { AutoSize = true }; tbFrameSizeWindowed = new TransparentTrackBar { LargeChange = 1, Maximum = 2 }; tbFrameSizeWindowed.ValueChanged += (sender, e) => lblFrameTypeWindowed.Text = $"{(Config.FrameWindowThickness) ((TransparentTrackBar) sender).Value:f}"; tbFrameSizeWindowed.Value = Global.Config.DispChrome_FrameWindowed; cbStatusBarWindowed = new CheckBox { AutoSize = true, Checked = Global.Config.DispChrome_StatusBarWindowed, Text = "Status Bar", UseVisualStyleBackColor = true }; cbCaptionWindowed = new CheckBox { AutoSize = true, Checked = Global.Config.DispChrome_CaptionWindowed, Text = "Caption", UseVisualStyleBackColor = true }; cbMenuWindowed = new CheckBox { AutoSize = true, Checked = Global.Config.DispChrome_MenuWindowed, Text = "Menu", UseVisualStyleBackColor = true }; return new FLPInGroupBox { Controls = { new SingleRowFLP { Controls = { new AutosizedLabel("Frame:"), lblFrameTypeWindowed } }, tbFrameSizeWindowed, cbStatusBarWindowed, cbCaptionWindowed, cbMenuWindowed }, Size = new Size(128, 200), Text = "Windowed" }; } private CheckBox cbStatusBarFullscreen; private CheckBox cbFSAutohideMouse; private CheckBox cbMenuFullscreen; private CheckBox cbFullscreenHacks; private FLPInGroupBox CreateFullscreenGroupBox() { cbStatusBarFullscreen = new CheckBox { AutoSize = true, Checked = Global.Config.DispChrome_StatusBarFullscreen, Text = "Status Bar", UseVisualStyleBackColor = true }; cbFSAutohideMouse = new CheckBox { AutoSize = true, Checked = Global.Config.DispChrome_Fullscreen_AutohideMouse, Text = "Auto-Hide Mouse Cursor", UseVisualStyleBackColor = true }; cbMenuFullscreen = new CheckBox { AutoSize = true, Checked = Global.Config.DispChrome_MenuFullscreen, Text = "Menu", UseVisualStyleBackColor = true }; cbFullscreenHacks = new CheckBox { AutoSize = true, Checked = Global.Config.DispFullscreenHacks, Text = "Enable Windows Fullscreen Hacks", UseVisualStyleBackColor = true }; var flpCheckboxes = new FlowLayoutPanel { AutoSize = true, Controls = { cbStatusBarFullscreen, cbFSAutohideMouse, cbMenuFullscreen, cbFullscreenHacks } }; flpCheckboxes.SetFlowBreak(cbFSAutohideMouse, true); flpCheckboxes.SetFlowBreak(cbMenuFullscreen, true); return new FLPInGroupBox { Controls = { flpCheckboxes, new Label { Size = new Size(240, 112), Text = Resources.GetString("lblFullscreenHacks.Text") } }, Size = new Size(256, 200), Text = "Fullscreen" }; } private CheckBox cbAllowDoubleclickFullscreen; private TabPage CreateWindowTab() { cbAllowDoubleclickFullscreen = new CheckBox { AutoSize = true, Checked = Global.Config.DispChrome_AllowDoubleClickFullscreen, Text = "Allow Double-Click Fullscreen (hold shift to force fullscreen to toggle in case using zapper, etc.)", UseVisualStyleBackColor = true }; return new TabPage { AutoSize = true, Controls = { new SingleColumnFLP { AutoSize = true, Controls = { new SingleRowFLP { Controls = { CreateWindowedGroupBox(), CreateFullscreenGroupBox() } }, cbAllowDoubleclickFullscreen }, Dock = DockStyle.Fill } }, Padding = new Padding(3), Text = "Window", UseVisualStyleBackColor = true }; } private void UpdateUserFilterLabel() => lblUserFilterName.Text = Path.GetFileNameWithoutExtension(PathSelection); private RadioButton rbNone; private RadioButton rbHq2x; private Label lblScanlines; private TransparentTrackBar tbScanlineIntensity; private RadioButton rbScanlines; private RadioButton rbUser; private Label lblUserFilterName; private TLPInGroupBox CreateScalingFilterGroupBox() { rbNone = new RadioButton { AutoSize = true, Text = "None", UseVisualStyleBackColor = true }; rbHq2x = new RadioButton { AutoSize = true, Text = "Hq2x", UseVisualStyleBackColor = true }; lblScanlines = new Label { Anchor = AnchorStyles.Top, AutoSize = true, Font = new Font("Microsoft Sans Serif", 8.25f, FontStyle.Regular, GraphicsUnit.Point, 0) }; tbScanlineIntensity = new TransparentTrackBar { LargeChange = 32, Maximum = 256, Size = new Size(80, 32), TickFrequency = 32, TickStyle = TickStyle.TopLeft }; tbScanlineIntensity.ValueChanged += (sender, e) => lblScanlines.Text = $"{((TransparentTrackBar) sender).Value / 256f:P}"; tbScanlineIntensity.Value = Global.Config.TargetScanlineFilterIntensity; var flpScanlinesSliderLabel = new SingleColumnFLP { Controls = { lblScanlines, tbScanlineIntensity } }; rbScanlines = new RadioButton { AutoSize = true, Text = "Scanlines", UseVisualStyleBackColor = true }; rbUser = new RadioButton { AutoSize = true, Text = "User", UseVisualStyleBackColor = true }; var btnSelectUserFilter = new Button { Text = "Select", UseVisualStyleBackColor = true }; btnSelectUserFilter.Click += (sender, e) => { var ofd = new OpenFileDialog { FileName = PathSelection, Filter = ".CGP (*.cgp)|*.cgp" }; if (ofd.ShowDialog() != DialogResult.OK) return; var choice = Path.GetFullPath(ofd.FileName); using var stream = File.OpenRead(choice); // test the preset var cgp = new RetroShaderPreset(stream); if (cgp.ContainsGLSL) { MessageBox.Show("Specified CGP contains references to .glsl files. This is illegal. Use .cg"); return; } RetroShaderChain filter = null; // try compiling it try { filter = new RetroShaderChain(GlobalWin.GL, cgp, Path.GetDirectoryName(choice)); } catch { // ignored } if (filter?.Available != true) { new ExceptionBox(filter?.Errors).ShowDialog(); return; } rbUser.Checked = true; PathSelection = choice; UpdateUserFilterLabel(); }; lblUserFilterName = new Label { AutoSize = true }; UpdateUserFilterLabel(); var grpScalingFilter = new TLPInGroupBox(2, 5) { Margin = new Padding(3, 0, 3, 0), Size = new Size(176, 168), Text = "Scaling Filter" }; grpScalingFilter.Controls.Add(rbNone, 0, 0); grpScalingFilter.Controls.Add(rbHq2x, 0, 1); grpScalingFilter.Controls.Add(flpScanlinesSliderLabel, 1, 1); grpScalingFilter.InnerTLP.SetRowSpan(flpScanlinesSliderLabel, 2); grpScalingFilter.Controls.Add(rbScanlines, 0, 2); grpScalingFilter.Controls.Add(rbUser, 0, 3); grpScalingFilter.Controls.Add(btnSelectUserFilter, 1, 3); grpScalingFilter.Controls.Add(lblUserFilterName, 0, 4); grpScalingFilter.InnerTLP.SetColumnSpan(lblUserFilterName, 2); var checkedRadio = Global.Config.TargetDisplayFilter switch { 0 => rbNone, 1 => rbHq2x, 2 => rbScanlines, 3 => rbUser, _ => null }; if (checkedRadio != null) checkedRadio.Checked = true; return grpScalingFilter; } private RadioButton rbUseRaw; private RadioButton rbUseSystem; private RadioButton rbUseCustom; private TextBox txtCustomARWidth; private TextBox txtCustomARHeight; private RadioButton rbUseCustomRatio; private TextBox txtCustomARX; private TextBox txtCustomARY; private TLPInGroupBox CreateARSelectionGroupBox() { rbUseRaw = new RadioButton { AutoSize = true, Text = "Use 1:1 pixel size (for crispness or debugging)", UseVisualStyleBackColor = true }; var lblNonSquareAR = new AutosizedLabel("Allowing pixel distortion (e.g. 2x1 pixels, for better AR fit):"); rbUseSystem = new RadioButton { AutoSize = true, Text = "Use system's recommendation", UseVisualStyleBackColor = true }; rbUseCustom = new RadioButton { AutoSize = true, Text = "Use custom size:", UseVisualStyleBackColor = true }; var textBoxSize = new Size(48, 19); txtCustomARWidth = new TextBox { Size = textBoxSize }; var labelAlignment = new Padding(0, 5, 0, 0); var lblWHSeparator = new AutosizedLabel("x") { Margin = labelAlignment }; txtCustomARHeight = new TextBox { Size = textBoxSize }; rbUseCustomRatio = new RadioButton { AutoSize = true, Text = "Use custom AR:", UseVisualStyleBackColor = true }; txtCustomARX = new TextBox { Size = textBoxSize }; var lblXYSeparator = new AutosizedLabel(":") { Margin = labelAlignment }; txtCustomARY = new TextBox { Size = textBoxSize }; var grpARSelection = new TLPInGroupBox(4, 5) { Size = new Size(304, 128), Text = "Aspect Ratio Selection" }; grpARSelection.Controls.Add(rbUseRaw, 0, 0); grpARSelection.InnerTLP.SetColumnSpan(rbUseRaw, 4); grpARSelection.Controls.Add(lblNonSquareAR, 0, 1); grpARSelection.InnerTLP.SetColumnSpan(lblNonSquareAR, 4); grpARSelection.Controls.Add(rbUseSystem, 0, 2); grpARSelection.InnerTLP.SetColumnSpan(rbUseSystem, 4); grpARSelection.Controls.Add(rbUseCustom, 0, 3); grpARSelection.Controls.Add(txtCustomARWidth, 1, 3); grpARSelection.Controls.Add(lblWHSeparator, 2, 3); grpARSelection.Controls.Add(txtCustomARHeight, 3, 3); grpARSelection.Controls.Add(rbUseCustomRatio, 0, 4); grpARSelection.Controls.Add(txtCustomARX, 1, 4); grpARSelection.Controls.Add(lblXYSeparator, 2, 4); grpARSelection.Controls.Add(txtCustomARY, 3, 4); if (Global.Config.DispCustomUserARWidth != -1) txtCustomARWidth.Text = Global.Config.DispCustomUserARWidth.ToString(); if (Global.Config.DispCustomUserARHeight != -1) txtCustomARHeight.Text = Global.Config.DispCustomUserARHeight.ToString(); if (!Global.Config.DispCustomUserARX.HawkFloatEquality(-1)) txtCustomARX.Text = Global.Config.DispCustomUserARX.ToString(); if (!Global.Config.DispCustomUserARY.HawkFloatEquality(-1)) txtCustomARY.Text = Global.Config.DispCustomUserARY.ToString(); var checkedRadio = Global.Config.DispManagerAR switch { Config.EDispManagerAR.None => rbUseRaw, Config.EDispManagerAR.System => rbUseSystem, Config.EDispManagerAR.Custom => rbUseCustom, Config.EDispManagerAR.CustomRatio => rbUseCustomRatio, _ => null }; if (checkedRadio != null) checkedRadio.Checked = true; return grpARSelection; } //TODO is there a reason these aren't NumericUpDowns? private TextBox txtCropLeft; private TextBox txtCropTop; private TextBox txtCropRight; private TextBox txtCropBottom; private FLPInGroupBox CreateCropOptionsGroupBox() { var textBoxSize = new Size(32, 19); TextBox CreateCropTextBox(int initValue) => new TextBox { Margin = Padding.Empty, Size = textBoxSize, Text = initValue.ToString() }; txtCropLeft = CreateCropTextBox(Global.Config.DispCropLeft); txtCropTop = CreateCropTextBox(Global.Config.DispCropTop); txtCropRight = CreateCropTextBox(Global.Config.DispCropRight); txtCropBottom = CreateCropTextBox(Global.Config.DispCropBottom); SingleRowFLP CreateCropFLP(string labelText, Control textBox) => new SingleRowFLP { Controls = { new AutosizedLabel(labelText) { Anchor = AnchorStyles.None }, textBox }, Margin = Padding.Empty }; return new FLPInGroupBox { Controls = { CreateCropFLP("Left:", txtCropLeft), CreateCropFLP("Top:", txtCropTop), CreateCropFLP("Right:", txtCropRight), CreateCropFLP("Bottom:", txtCropBottom) }, InnerFLP = { AutoSize = true, FlowDirection = FlowDirection.LeftToRight }, Size = new Size(304, 44), Text = "Cropping" }; } private NumericUpDown nudPrescale; private CheckBox cbAutoPrescale; private RadioButton rbFinalFilterNone; private RadioButton rbFinalFilterBicubic; private RadioButton rbFinalFilterBilinear; private CheckBox cbLetterbox; private CheckBox cbPadInteger; private SingleColumnFLP flpAspectRatio; private TabPage CreateScalingTab() { nudPrescale = new NumericUpDown { Maximum = 16M, Minimum = 1M, Size = new Size(48, 19), Value = Global.Config.DispPrescale }; cbAutoPrescale = new CheckBox { AutoSize = true, Checked = Global.Config.DispAutoPrescale, Margin = new Padding(3, 3, 3, 0), Text = "Auto Prescale", UseVisualStyleBackColor = true }; rbFinalFilterNone = new RadioButton { AutoSize = true, Text = "None", UseVisualStyleBackColor = true }; rbFinalFilterBilinear = new RadioButton { AutoSize = true, Text = "Bilinear", UseVisualStyleBackColor = true }; rbFinalFilterBicubic = new RadioButton { AutoSize = true, Text = "Bicubic (shader. buggy?)", UseVisualStyleBackColor = true }; var grpFinalFilter = new FLPInGroupBox { Controls = { rbFinalFilterNone, rbFinalFilterBilinear, rbFinalFilterBicubic }, InnerFLP = { AutoSize = true }, Margin = new Padding(3, 0, 3, 0), Size = new Size(176, 88), Text = "Final Filter" }; var checkedRadio = Global.Config.DispFinalFilter switch { 0 => rbFinalFilterNone, 1 => rbFinalFilterBilinear, 2 => rbFinalFilterBicubic, _ => null }; if (checkedRadio != null) checkedRadio.Checked = true; cbLetterbox = new CheckBox { AutoSize = true, Text = "Maintain aspect ratio (letterbox)", UseVisualStyleBackColor = true }; cbPadInteger = new CheckBox { AutoSize = true, Checked = Global.Config.DispFixScaleInteger, Text = "Expand pixels by integers only (e.g. no 1.3333x)", UseVisualStyleBackColor = true }; flpAspectRatio = new SingleColumnFLP { Controls = { CreateARSelectionGroupBox(), cbPadInteger } }; cbLetterbox.CheckedChanged += (sender, e) => flpAspectRatio.Enabled = ((CheckBox) sender).Checked; cbLetterbox.Checked = Global.Config.DispFixAspectRatio; var btnDefaults = new Button { Anchor = AnchorStyles.Right, Text = "Defaults", UseVisualStyleBackColor = true }; btnDefaults.Click += (sender, e) => { nudPrescale.Value = 1; rbNone.Checked = true; cbAutoPrescale.Checked = true; rbFinalFilterBilinear.Checked = true; cbLetterbox.Checked = true; rbUseSystem.Checked = true; txtCropLeft.Text = "0"; txtCropTop.Text = "0"; txtCropRight.Text = "0"; txtCropBottom.Text = "0"; }; new ToolTip(Components).SetToolTip(btnDefaults, "Unless someone forgets to update this button's code when they change said defaults..."); var flpScalingTab = new FlowLayoutPanel { AutoSize = true, Controls = { new SingleRowFLP { Controls = { new AutosizedLabel("User Prescale:") { Anchor = AnchorStyles.None }, nudPrescale, new AutosizedLabel("x") { Anchor = AnchorStyles.None } }, Margin = new Padding(3, 0, 3, 0) }, CreateScalingFilterGroupBox(), cbAutoPrescale, grpFinalFilter, cbLetterbox, flpAspectRatio, CreateCropOptionsGroupBox(), btnDefaults }, FlowDirection = FlowDirection.TopDown }; flpScalingTab.SetFlowBreak(grpFinalFilter, true); return new TabPage { AutoSize = true, Controls = { flpScalingTab }, Padding = new Padding(3), Text = "Scaling and Filtering", UseVisualStyleBackColor = true }; } private RadioButton rbDisplayFull; private RadioButton rbDisplayMinimal; private RadioButton rbDisplayAbsoluteZero; private CheckBox cbNullHawkWhiteNoise; private TabPage CreateMiscTab() { rbDisplayFull = new RadioButton { AutoSize = true, Text = "Full - Display Everything", UseVisualStyleBackColor = true }; rbDisplayMinimal = new RadioButton { AutoSize = true, Enabled = false, //TODO how long has this gone unimplemented? --yoshi Text = "Minimal - Display HUD Only (TBD)", UseVisualStyleBackColor = true }; rbDisplayAbsoluteZero = new RadioButton { AutoSize = true, Text = "Absolute Zero - Display Nothing", UseVisualStyleBackColor = true }; var grpDispFeatures = new FLPInGroupBox { Controls = { rbDisplayFull, rbDisplayMinimal, rbDisplayAbsoluteZero }, Size = new Size(224, 88), Text = "Display Features (for speeding up replays)" }; var checkedRadio = Global.Config.DispSpeedupFeatures switch { 0 => rbDisplayAbsoluteZero, 1 => rbDisplayMinimal, 2 => rbDisplayFull, _ => null }; if (checkedRadio != null) checkedRadio.Checked = true; cbNullHawkWhiteNoise = new CheckBox { AutoSize = true, Checked = NullHawkSettings.SnowyDisplay, Text = "Enable Snowy Null Emulator", UseVisualStyleBackColor = true }; return new TabPage { AutoSize = true, Controls = { new SingleColumnFLP { Controls = { grpDispFeatures, cbNullHawkWhiteNoise, new AutosizedLabel("Some people think the white noise is a great idea, and some people don't.\nDisabling this displays black instead.") { Margin = new Padding(24, 0, 0, 0) } } } }, Text = "Misc.", UseVisualStyleBackColor = true }; } private void SaveControlsTo(Config config) { // set config from Scaling and Filtering tab config.DispPrescale = (int) nudPrescale.Value; if (rbNone.Checked) config.TargetDisplayFilter = 0; else if (rbHq2x.Checked) config.TargetDisplayFilter = 1; else if (rbScanlines.Checked) { config.TargetDisplayFilter = 2; config.TargetScanlineFilterIntensity = tbScanlineIntensity.Value; } else if (rbUser.Checked) { config.TargetDisplayFilter = 3; config.DispUserFilterPath = PathSelection; GlobalWin.DisplayManager.RefreshUserShader(); } config.DispAutoPrescale = cbAutoPrescale.Checked; if (rbFinalFilterNone.Checked) config.DispFinalFilter = 0; else if (rbFinalFilterBilinear.Checked) config.DispFinalFilter = 1; else if (rbFinalFilterBicubic.Checked) config.DispFinalFilter = 2; config.DispFixAspectRatio = cbLetterbox.Checked; if (rbUseRaw.Checked) config.DispManagerAR = Config.EDispManagerAR.None; else if (rbUseSystem.Checked) config.DispManagerAR = Config.EDispManagerAR.System; else if (rbUseCustom.Checked) config.DispManagerAR = Config.EDispManagerAR.Custom; else if (rbUseCustomRatio.Checked) config.DispManagerAR = Config.EDispManagerAR.CustomRatio; if (txtCustomARWidth.Text == "") config.DispCustomUserARWidth = -1; else int.TryParse(txtCustomARWidth.Text, out config.DispCustomUserARWidth); if (txtCustomARHeight.Text == "") config.DispCustomUserARHeight = -1; else int.TryParse(txtCustomARHeight.Text, out config.DispCustomUserARHeight); if (txtCustomARX.Text == "") config.DispCustomUserARX = -1; else float.TryParse(txtCustomARX.Text, out config.DispCustomUserARX); if (txtCustomARY.Text == "") config.DispCustomUserARY = -1; else float.TryParse(txtCustomARY.Text, out config.DispCustomUserARY); config.DispFixScaleInteger = cbPadInteger.Checked; int.TryParse(txtCropLeft.Text, out config.DispCropLeft); int.TryParse(txtCropTop.Text, out config.DispCropTop); int.TryParse(txtCropRight.Text, out config.DispCropRight); int.TryParse(txtCropBottom.Text, out config.DispCropBottom); // set config from Display Method tab var prevDispMethod = config.DispMethod; if (rbOpenGL.Checked) config.DispMethod = Config.EDispMethod.OpenGL; else if (rbGDIPlus.Checked) config.DispMethod = Config.EDispMethod.GdiPlus; else if (rbD3D9.Checked) { config.DispMethod = Config.EDispMethod.SlimDX9; config.DispAlternateVsync = cbAlternateVsync.Checked; } if (config.DispMethod != prevDispMethod) NeedReset = true; // set config from Misc. tab if (rbDisplayAbsoluteZero.Checked) config.DispSpeedupFeatures = 0; else if (rbDisplayMinimal.Checked) config.DispSpeedupFeatures = 1; else if (rbDisplayFull.Checked) config.DispSpeedupFeatures = 2; //HACK this cloning is necessary var nhSettings = NullHawkSettings; nhSettings.SnowyDisplay = cbNullHawkWhiteNoise.Checked; NullHawkSettings = nhSettings; // set config from Window tab config.DispChrome_FrameWindowed = tbFrameSizeWindowed.Value; config.DispChrome_StatusBarWindowed = cbStatusBarWindowed.Checked; config.DispChrome_CaptionWindowed = cbCaptionWindowed.Checked; config.DispChrome_MenuWindowed = cbMenuWindowed.Checked; config.DispChrome_StatusBarFullscreen = cbStatusBarFullscreen.Checked; config.DispChrome_Fullscreen_AutohideMouse = cbFSAutohideMouse.Checked; config.DispChrome_MenuFullscreen = cbMenuFullscreen.Checked; config.DispFullscreenHacks = cbFullscreenHacks.Checked; config.DispChrome_AllowDoubleClickFullscreen = cbAllowDoubleclickFullscreen.Checked; DialogResult = DialogResult.OK; } protected override void Dispose(bool disposing) { if (disposing) Components?.Dispose(); base.Dispose(disposing); } } }