Files
SourMesen 40335ce735 UI: Update to Avalonia 12, .NET 10 and replace ReactiveUI with MVVM community toolkit (#142)
Also fixes DX11.0 support (for Win7 PCs that aren't fully updated), which stopped working after the recent variable refresh rate changes
2026-07-03 16:04:42 +09:00

286 lines
9.6 KiB
C#

using CommunityToolkit.Mvvm.ComponentModel;
using Mesen.Interop;
using Mesen.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace Mesen.Config
{
public partial class VideoConfig : BaseConfig<VideoConfig>
{
[ObservableProperty][MinMax(0.1, 5.0)] public partial double CustomAspectRatio { get; set; } = 1.0;
[ObservableProperty] public partial VideoFilterType VideoFilter { get; set; } = VideoFilterType.None;
[ObservableProperty] public partial VideoAspectRatio AspectRatio { get; set; } = VideoAspectRatio.NoStretching;
[ObservableProperty] public partial bool UseBilinearInterpolation { get; set; } = false;
[ObservableProperty] public partial bool UseSoftwareRenderer { get; set; } = false;
[ObservableProperty] public partial bool UseSrgbTextureFormat { get; set; } = false;
[ObservableProperty] public partial bool VerticalSync { get; set; } = false;
[ObservableProperty] public partial bool IntegerFpsMode { get; set; } = false;
[ObservableProperty][MinMax(-100, 100)] public partial int Brightness { get; set; } = 0;
[ObservableProperty][MinMax(-100, 100)] public partial int Contrast { get; set; } = 0;
[ObservableProperty][MinMax(-100, 100)] public partial int Hue { get; set; } = 0;
[ObservableProperty][MinMax(-100, 100)] public partial int Saturation { get; set; } = 0;
[ObservableProperty][MinMax(0, 100)] public partial int ScanlineIntensity { get; set; } = 0;
[ObservableProperty][MinMax(0, 100)] public partial int LcdGridTopLeftBrightness { get; set; } = 100;
[ObservableProperty][MinMax(0, 100)] public partial int LcdGridTopRightBrightness { get; set; } = 85;
[ObservableProperty][MinMax(0, 100)] public partial int LcdGridBottomLeftBrightness { get; set; } = 85;
[ObservableProperty][MinMax(0, 100)] public partial int LcdGridBottomRightBrightness { get; set; } = 85;
[ObservableProperty][MinMax(-100, 100)] public partial int NtscArtifacts { get; set; } = 0;
[ObservableProperty][MinMax(-100, 100)] public partial int NtscBleed { get; set; } = 0;
[ObservableProperty][MinMax(-100, 100)] public partial int NtscFringing { get; set; } = 0;
[ObservableProperty][MinMax(-100, 100)] public partial int NtscGamma { get; set; } = 0;
[ObservableProperty][MinMax(-100, 100)] public partial int NtscResolution { get; set; } = 0;
[ObservableProperty][MinMax(-100, 100)] public partial int NtscSharpness { get; set; } = 0;
[ObservableProperty] public partial bool NtscMergeFields { get; set; } = false;
[ObservableProperty] public partial NtscBisqwitFilterScale NtscScale { get; set; } = NtscBisqwitFilterScale._2x;
[ObservableProperty][MinMax(-50, 400)] public partial Int32 NtscYFilterLength { get; set; } = 0;
[ObservableProperty][MinMax(0, 400)] public partial Int32 NtscIFilterLength { get; set; } = 50;
[ObservableProperty][MinMax(0, 400)] public partial Int32 NtscQFilterLength { get; set; } = 50;
[ObservableProperty] public partial bool EnableVariableRefreshRate { get; set; } = false;
[ObservableProperty] public partial bool FullscreenForceIntegerScale { get; set; } = false;
[ObservableProperty] public partial bool UseExclusiveFullscreen { get; set; } = false;
[ObservableProperty] public partial UInt32 ExclusiveFullscreenRefreshRateNtsc { get; set; } = 60;
[ObservableProperty] public partial UInt32 ExclusiveFullscreenRefreshRatePal { get; set; } = 50;
[ObservableProperty] public partial FullscreenResolution ExclusiveFullscreenResolution { get; set; } = 0;
[ObservableProperty] public partial ScreenRotation ScreenRotation { get; set; } = ScreenRotation.None;
[ObservableProperty] public partial bool DisableHighPrecisionFramePacing { get; set; } = false;
public VideoConfig()
{
}
public void ApplyConfig()
{
double customAspectRatio = CustomAspectRatio;
VideoAspectRatio aspectRatio = AspectRatio;
VideoFilterType videoFilter = VideoFilter;
ConsoleOverrideConfig? overrides = ConsoleOverrideConfig.GetActiveOverride();
if(overrides?.OverrideVideoFilter == true) {
videoFilter = overrides.VideoFilter;
}
if(overrides?.OverrideAspectRatio == true) {
aspectRatio = overrides.AspectRatio;
customAspectRatio = overrides.CustomAspectRatio;
}
ConfigApi.SetVideoConfig(new InteropVideoConfig() {
CustomAspectRatio = customAspectRatio,
VideoFilter = videoFilter,
AspectRatio = aspectRatio,
UseBilinearInterpolation = this.UseBilinearInterpolation,
UseSrgbTextureFormat = this.UseSrgbTextureFormat && this.UseBilinearInterpolation,
VerticalSync = this.VerticalSync,
IntegerFpsMode = this.IntegerFpsMode,
Brightness = this.Brightness / 100.0,
Contrast = this.Contrast / 100.0,
Hue = this.Hue / 100.0,
Saturation = this.Saturation / 100.0,
ScanlineIntensity = this.ScanlineIntensity / 100.0,
LcdGridTopLeftBrightness = this.LcdGridTopLeftBrightness / 100.0,
LcdGridTopRightBrightness = this.LcdGridTopRightBrightness / 100.0,
LcdGridBottomLeftBrightness = this.LcdGridBottomLeftBrightness / 100.0,
LcdGridBottomRightBrightness = this.LcdGridBottomRightBrightness / 100.0,
NtscArtifacts = this.NtscArtifacts / 100.0,
NtscBleed = this.NtscBleed / 100.0,
NtscFringing = this.NtscFringing / 100.0,
NtscGamma = this.NtscGamma / 100.0,
NtscResolution = this.NtscResolution / 100.0,
NtscSharpness = this.NtscSharpness / 100.0,
NtscMergeFields = this.NtscMergeFields,
NtscScale = this.NtscScale,
NtscYFilterLength = this.NtscYFilterLength / 100.0,
NtscIFilterLength = this.NtscIFilterLength / 100.0,
NtscQFilterLength = this.NtscQFilterLength / 100.0,
EnableVariableRefreshRate = this.EnableVariableRefreshRate,
FullscreenForceIntegerScale = this.FullscreenForceIntegerScale,
UseExclusiveFullscreen = this.UseExclusiveFullscreen,
ExclusiveFullscreenRefreshRateNtsc = this.ExclusiveFullscreenRefreshRateNtsc,
ExclusiveFullscreenRefreshRatePal = this.ExclusiveFullscreenRefreshRatePal,
ScreenRotation = (uint)ScreenRotation,
DisableHighPrecisionFramePacing = this.DisableHighPrecisionFramePacing
});
}
public UInt32 GetFullscreenWidth()
{
uint monitorWidth = (uint)(ApplicationHelper.GetMainWindow()?.Screens.Primary?.Bounds.Width ?? 1920);
if(UseExclusiveFullscreen) {
return ExclusiveFullscreenResolution == FullscreenResolution.Default ? monitorWidth : (uint)ExclusiveFullscreenResolution.GetWidth();
} else {
return monitorWidth;
}
}
public UInt32 GetFullscreenHeight()
{
uint monitorHeight = (uint)(ApplicationHelper.GetMainWindow()?.Screens.Primary?.Bounds.Height ?? 1080);
if(UseExclusiveFullscreen) {
return ExclusiveFullscreenResolution == FullscreenResolution.Default ? monitorHeight : (uint)ExclusiveFullscreenResolution.GetHeight();
} else {
return monitorHeight;
}
}
}
[StructLayout(LayoutKind.Sequential)]
public struct InteropVideoConfig
{
public double CustomAspectRatio;
public VideoFilterType VideoFilter;
public VideoAspectRatio AspectRatio;
[MarshalAs(UnmanagedType.I1)] public bool UseBilinearInterpolation;
[MarshalAs(UnmanagedType.I1)] public bool UseSrgbTextureFormat;
[MarshalAs(UnmanagedType.I1)] public bool VerticalSync;
[MarshalAs(UnmanagedType.I1)] public bool IntegerFpsMode;
public double Brightness;
public double Contrast;
public double Hue;
public double Saturation;
public double ScanlineIntensity;
public double LcdGridTopLeftBrightness;
public double LcdGridTopRightBrightness;
public double LcdGridBottomLeftBrightness;
public double LcdGridBottomRightBrightness;
public double NtscArtifacts;
public double NtscBleed;
public double NtscFringing;
public double NtscGamma;
public double NtscResolution;
public double NtscSharpness;
[MarshalAs(UnmanagedType.I1)] public bool NtscMergeFields;
public NtscBisqwitFilterScale NtscScale;
public double NtscYFilterLength;
public double NtscIFilterLength;
public double NtscQFilterLength;
[MarshalAs(UnmanagedType.I1)] public bool EnableVariableRefreshRate;
[MarshalAs(UnmanagedType.I1)] public bool FullscreenForceIntegerScale;
[MarshalAs(UnmanagedType.I1)] public bool UseExclusiveFullscreen;
public UInt32 ExclusiveFullscreenRefreshRateNtsc;
public UInt32 ExclusiveFullscreenRefreshRatePal;
public UInt32 ScreenRotation;
[MarshalAs(UnmanagedType.I1)] public bool DisableHighPrecisionFramePacing;
}
public enum VideoFilterType
{
None = 0,
NtscBlargg,
NtscBisqwit,
LcdGrid,
xBRZ2x,
xBRZ3x,
xBRZ4x,
xBRZ5x,
xBRZ6x,
HQ2x,
HQ3x,
HQ4x,
Scale2x,
Scale3x,
Scale4x,
_2xSai,
Super2xSai,
SuperEagle,
Prescale2x,
Prescale3x,
Prescale4x,
Prescale6x,
Prescale8x,
Prescale10x
}
public enum VideoAspectRatio
{
NoStretching = 0,
Auto = 1,
NTSC = 2,
PAL = 3,
Standard = 4,
Widescreen = 5,
Custom = 6
}
public enum ScreenRotation
{
None = 0,
_90Degrees = 90,
_180Degrees = 180,
_270Degrees = 270
}
public enum NtscBisqwitFilterScale
{
_2x,
_4x,
_8x
}
public enum FullscreenResolution
{
Default,
_3840x2160,
_2560x1440,
_2160x1200,
_1920x1440,
_1920x1200,
_1920x1080,
_1680x1050,
_1600x1200,
_1600x1024,
_1600x900,
_1366x768,
_1360x768,
_1280x1024,
_1280x960,
_1280x800,
_1280x768,
_1280x720,
_1152x864,
_1024x768,
_800x600,
_640x480
}
public static class FullscreenResolutionExtensions
{
public static int GetWidth(this FullscreenResolution res)
{
return Int32.Parse(res.ToString().Substring(1, res.ToString().IndexOf("x") - 1));
}
public static int GetHeight(this FullscreenResolution res)
{
return Int32.Parse(res.ToString().Substring(res.ToString().IndexOf("x") + 1));
}
}
}