diff --git a/README.md b/README.md index 04201aa..d95247e 100644 --- a/README.md +++ b/README.md @@ -9,12 +9,6 @@ This program patches **The Sims 1** to a custom resolution. * NoCD/Cracked Sims Executable * This exe cannot be previously patched to a custom resolution. For example, if you downloaded a crack that was patched to 1080p, this program will not work. -**Linux** - -* xrandr - * Ubuntu ```sudo apt install xrandr``` - * Fedora ```sudo dnf install xrandr``` - ### OS Version Compatability | Windows | diff --git a/Sims1WidescreenPatcher.Core/Models/AspectRatio.cs b/Sims1WidescreenPatcher.Core/Models/AspectRatio.cs index 40b5088..344bb4e 100644 --- a/Sims1WidescreenPatcher.Core/Models/AspectRatio.cs +++ b/Sims1WidescreenPatcher.Core/Models/AspectRatio.cs @@ -2,83 +2,41 @@ namespace Sims1WidescreenPatcher.Core.Models; -public class AspectRatio : IEqualityComparer, IComparable +public record AspectRatio : IComparable { - protected bool Equals(AspectRatio other) - { - return Numerator == other.Numerator && Denominator == other.Denominator; - } + private readonly BigInteger _gcd; - public override bool Equals(object? obj) + public AspectRatio(int Width, int Height) { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; - return Equals((AspectRatio) obj); + this.Width = Width; + this.Height = Height; + _gcd = BigInteger.GreatestCommonDivisor(Width, Height); } - public override int GetHashCode() - { - unchecked - { - return (Numerator * 397) ^ Denominator; - } - } + public int Numerator => Width / (int)_gcd; + public int Denominator => Height / (int)_gcd; + public int Width { get; init; } + public int Height { get; init; } - public int Numerator; - public int Denominator; - - public AspectRatio(int width, int height) - { - CalculateAspectRatio(width, height); - } + public override string ToString() => $"{Numerator}:{Denominator}"; - public override string ToString() - { - return $"{Numerator}:{Denominator}"; - } - - public static bool operator ==(AspectRatio obj1, AspectRatio obj2) - { - return (obj1.Numerator == obj2.Numerator - && obj1.Denominator == obj2.Denominator); - } + public virtual bool Equals(AspectRatio? other) => + other is not null && Numerator == other.Numerator && Denominator == other.Denominator; - public static bool operator !=(AspectRatio obj1, AspectRatio obj2) - { - return !(obj1 == obj2); - } - - private void CalculateAspectRatio(int width, int height) - { - var gcd = BigInteger.GreatestCommonDivisor(width, height); - Numerator = width / (int)gcd; - Denominator = height / (int)gcd; - } - - public bool Equals(AspectRatio x, AspectRatio y) - { - if (ReferenceEquals(x, y)) return true; - if (ReferenceEquals(x, null)) return false; - if (ReferenceEquals(y, null)) return false; - if (x.GetType() != y.GetType()) return false; - return x.Numerator == y.Numerator && x.Denominator == y.Denominator; - } - - public int GetHashCode(AspectRatio obj) - { - unchecked - { - return (obj.Numerator * 397) ^ obj.Denominator; - } - } + public override int GetHashCode() => HashCode.Combine(Numerator, Denominator); public int CompareTo(AspectRatio? other) { if (ReferenceEquals(this, other)) return 0; - if (ReferenceEquals(null, other)) return 1; + if (other is null) return 1; var numeratorComparison = Numerator.CompareTo(other.Numerator); if (numeratorComparison != 0) return numeratorComparison; return Denominator.CompareTo(other.Denominator); } + + public void Deconstruct(out int Width, out int Height) + { + Width = this.Width; + Height = this.Height; + } } \ No newline at end of file diff --git a/Sims1WidescreenPatcher.Core/Models/CheckboxSelectionSnapshot.cs b/Sims1WidescreenPatcher.Core/Models/CheckboxSelectionSnapshot.cs index 835c2f6..24fd93b 100644 --- a/Sims1WidescreenPatcher.Core/Models/CheckboxSelectionSnapshot.cs +++ b/Sims1WidescreenPatcher.Core/Models/CheckboxSelectionSnapshot.cs @@ -1,6 +1,4 @@ -using Sims1WidescreenPatcher.Core.ViewModels; - -namespace Sims1WidescreenPatcher.Core.Models; +namespace Sims1WidescreenPatcher.Core.Models; public class CheckboxSelectionSnapshot : IEquatable { diff --git a/Sims1WidescreenPatcher.Core/Models/CompositeImageJob.cs b/Sims1WidescreenPatcher.Core/Models/CompositeImageJob.cs index fc0e2dd..4c09fac 100644 --- a/Sims1WidescreenPatcher.Core/Models/CompositeImageJob.cs +++ b/Sims1WidescreenPatcher.Core/Models/CompositeImageJob.cs @@ -19,7 +19,7 @@ public override void Run() } using var image = new MagickImage(ImageBytes!); - using var background = new MagickImage(new MagickColor(Color), Width, Height); + using var background = new MagickImage(new MagickColor(Color), (uint)Width, (uint)Height); background.Composite(image, Gravity.Center); SetCommonBmpSettings(background); background.Write(Output!); diff --git a/Sims1WidescreenPatcher.Core/Models/Resolution.cs b/Sims1WidescreenPatcher.Core/Models/Resolution.cs index b1899f5..63fa346 100644 --- a/Sims1WidescreenPatcher.Core/Models/Resolution.cs +++ b/Sims1WidescreenPatcher.Core/Models/Resolution.cs @@ -1,53 +1,38 @@ -using System.Numerics; +namespace Sims1WidescreenPatcher.Core.Models; -namespace Sims1WidescreenPatcher.Core.Models; - -public class Resolution : IComparable +public record Resolution : IComparable { - private sealed class WidthHeightEqualityComparer : IEqualityComparer + public readonly AspectRatio AspectRatio; + + public Resolution(int Width, int Height) { - public bool Equals(Resolution x, Resolution y) - { - if (ReferenceEquals(x, y)) return true; - if (ReferenceEquals(x, null)) return false; - if (ReferenceEquals(y, null)) return false; - if (x.GetType() != y.GetType()) return false; - return x.Width == y.Width && x.Height == y.Height; - } - - public int GetHashCode(Resolution obj) - { - unchecked - { - return (obj.Width * 397) ^ obj.Height; - } - } + this.Width = Width; + this.Height = Height; + AspectRatio = new AspectRatio(Width, Height); } - public static IEqualityComparer? WidthHeightComparer { get; } = new WidthHeightEqualityComparer(); + public int Width { get; init; } + public int Height { get; init; } - public int Width { get; } - public int Height { get; } - public AspectRatio AspectRatio { get; } + public override string ToString() => $"{Width}x{Height} ({AspectRatio})"; - public Resolution(int width, int height) - { - Width = width; - Height = height; - AspectRatio = new AspectRatio(width, height); - } + public virtual bool Equals(Resolution? other) => other is not null && Width == other.Width && + Height == other.Height && AspectRatio.Equals(other.AspectRatio); - public override string ToString() - { - return $"{Width}x{Height} ({AspectRatio})"; - } + public override int GetHashCode() => HashCode.Combine(AspectRatio, Width, Height); public int CompareTo(Resolution? other) { if (ReferenceEquals(this, other)) return 0; - if (ReferenceEquals(null, other)) return 1; + if (other is null) return 1; var widthComparison = Width.CompareTo(other.Width); if (widthComparison != 0) return widthComparison; return Height.CompareTo(other.Height); } + + public void Deconstruct(out int Width, out int Height) + { + Width = this.Width; + Height = this.Height; + } } \ No newline at end of file diff --git a/Sims1WidescreenPatcher.Core/Models/ScalePanelBackJob.cs b/Sims1WidescreenPatcher.Core/Models/ScalePanelBackJob.cs index e90db33..0919266 100644 --- a/Sims1WidescreenPatcher.Core/Models/ScalePanelBackJob.cs +++ b/Sims1WidescreenPatcher.Core/Models/ScalePanelBackJob.cs @@ -10,9 +10,9 @@ public override void Run() using var image = new MagickImage(ImageBytes!); var left = image.Clone(0, 0, 286, 100); - var middle = image.Clone(left.Width, 0, 500, 100); - var right = image.Clone(left.Width + middle.Width, 0, 18, 100); - middle.Resize(new MagickGeometry(Width - left.Width - right.Width, Height) { IgnoreAspectRatio = true }); + var middle = image.Clone((int)left.Width, 0, 500, 100); + var right = image.Clone((int)left.Width + (int)middle.Width, 0, 18, 100); + middle.Resize(new MagickGeometry((uint)Width - left.Width - right.Width, (uint)Height) { IgnoreAspectRatio = true }); left.Page = new MagickGeometry("+0+0"); middle.Page = new MagickGeometry($"+{left.Width}+0"); right.Page = new MagickGeometry($"+{left.Width + middle.Width}+0"); diff --git a/Sims1WidescreenPatcher.Core/Models/ScaleTallSubPanelJob.cs b/Sims1WidescreenPatcher.Core/Models/ScaleTallSubPanelJob.cs index b3c2b64..1c96c27 100644 --- a/Sims1WidescreenPatcher.Core/Models/ScaleTallSubPanelJob.cs +++ b/Sims1WidescreenPatcher.Core/Models/ScaleTallSubPanelJob.cs @@ -9,7 +9,7 @@ public override void Run() base.Run(); using var image = new MagickImage(ImageBytes!, MagickFormat.Tga); - image.Resize(new MagickGeometry(Width, Height) { IgnoreAspectRatio = true }); + image.Resize(new MagickGeometry((uint)Width, (uint)Height) { IgnoreAspectRatio = true }); image.Depth = 32; image.Settings.Compression = CompressionMethod.RLE; image.Settings.Format = MagickFormat.Tga; diff --git a/Sims1WidescreenPatcher.Core/Services/CheatsService.cs b/Sims1WidescreenPatcher.Core/Services/CheatsService.cs index 802eaab..099c490 100644 --- a/Sims1WidescreenPatcher.Core/Services/CheatsService.cs +++ b/Sims1WidescreenPatcher.Core/Services/CheatsService.cs @@ -5,8 +5,6 @@ namespace Sims1WidescreenPatcher.Core.Services; public class CheatsService : ICheatsService { - private const string DisableCheatsPattern = "00 56 90 90"; - private const string EnableCheatsPattern = "00 56 75 04"; private readonly IAppState _appState; private readonly IPatchFileService _patchFileService; @@ -16,8 +14,15 @@ public CheatsService(IAppState appState, IPatchFileService patchFileService) _patchFileService = patchFileService; } + private const string DisableCheatsPattern = "00 56 90 90"; + private const string EnableCheatsPattern = "00 56 75 04"; + public bool CheatsEnabled() { + if (string.IsNullOrWhiteSpace(_appState.SimsExePath)) + { + return false; + } var (found, _, _) = _patchFileService.FindPattern(_appState.SimsExePath, DisableCheatsPattern); return found; } @@ -28,6 +33,10 @@ public bool CheatsEnabled() /// public bool CanEnableCheats() { + if (string.IsNullOrWhiteSpace(_appState.SimsExePath)) + { + return false; + } var (disablePatternFound, _, _) = _patchFileService.FindPattern(_appState.SimsExePath, DisableCheatsPattern); var (enablePatternFound, _, _) = _patchFileService.FindPattern(_appState.SimsExePath,EnableCheatsPattern); return disablePatternFound || enablePatternFound; @@ -45,6 +54,10 @@ public void DisableCheats() private void EditSimsExe(string pattern, Tuple replacementBytes) { + if (string.IsNullOrWhiteSpace(_appState.SimsExePath)) + { + return; + } var (found, offset, bytes) = _patchFileService.FindPattern(_appState.SimsExePath, pattern); if (!found) { diff --git a/Sims1WidescreenPatcher.Core/Services/ImagesService.cs b/Sims1WidescreenPatcher.Core/Services/ImagesService.cs index b3a7eae..14d6e47 100644 --- a/Sims1WidescreenPatcher.Core/Services/ImagesService.cs +++ b/Sims1WidescreenPatcher.Core/Services/ImagesService.cs @@ -7,9 +7,6 @@ namespace Sims1WidescreenPatcher.Core.Services; public class ImagesService : IImagesService { private string? _uiGraphicsPath; - private readonly IAppState _appState; - private readonly IProgressService _progressService; - private readonly IFar _far; private readonly string[] _blackBackground = { @@ -35,9 +32,9 @@ public class ImagesService : IImagesService @"Studiotown\dlgframe_1024x768.bmp", }; - private const string TallSubPanel = @"cpanel\Backgrounds\TallSubPanel.TGA"; - - private const string PanelBack = @"cpanel\Backgrounds\PanelBack.bmp"; + private readonly IAppState _appState; + private readonly IProgressService _progressService; + private readonly IFar _far; public ImagesService(IAppState appState, IProgressService progressService, IFar far) { @@ -46,6 +43,10 @@ public ImagesService(IAppState appState, IProgressService progressService, IFar _far = far; } + private const string TallSubPanel = @"cpanel\Backgrounds\TallSubPanel.TGA"; + + private const string PanelBack = @"cpanel\Backgrounds\PanelBack.bmp"; + public void Install() { _uiGraphicsPath = GetUiGraphicsFolder(); @@ -74,7 +75,7 @@ public void Uninstall() foreach (var i in _blackBackground .Concat(_blueBackground) - .Concat(new[] { TallSubPanel, PanelBack })) + .Concat(new List { TallSubPanel, PanelBack }.AsReadOnly())) { DeleteUiGraphicsFile(i); } @@ -85,6 +86,11 @@ private List GetJobs() _far.ParseFar(); var jobs = new List(); + if (_appState.Resolution is null) + { + return jobs; + } + if (_far.TryGetBytes(PanelBack, out var bytes)) { jobs.Add(new ScalePanelBackJob @@ -116,6 +122,10 @@ private List GetJobs() private IEnumerable GetCompositeJobs(IEnumerable images, string color) { + if (_appState.Resolution is null) + { + throw new Exception("Resolution is null"); + } foreach (var i in images) { if (_far.TryGetBytes(i, out var bytes)) @@ -134,7 +144,15 @@ private IEnumerable GetCompositeJobs(IEnumerable private string GetUiGraphicsFolder() { - var simsInstallDir = Directory.GetParent(_appState.SimsExePath).ToString(); + if (string.IsNullOrWhiteSpace(_appState.SimsExePath)) + { + throw new Exception("SimsExePath is null or empty"); + } + var simsInstallDir = Directory.GetParent(_appState.SimsExePath)?.ToString(); + if (string.IsNullOrWhiteSpace(simsInstallDir)) + { + throw new Exception("SimsExePath is null or empty"); + } return Path.Combine(simsInstallDir, "UIGraphics"); } diff --git a/Sims1WidescreenPatcher.Core/Services/Interfaces/IProgressService.cs b/Sims1WidescreenPatcher.Core/Services/Interfaces/IProgressService.cs index 3bc8538..dccd72b 100644 --- a/Sims1WidescreenPatcher.Core/Services/Interfaces/IProgressService.cs +++ b/Sims1WidescreenPatcher.Core/Services/Interfaces/IProgressService.cs @@ -1,15 +1,14 @@ -using Sims1WidescreenPatcher.Core.Events; -using Sims1WidescreenPatcher.Core.Models; +using System.Reactive; +using Sims1WidescreenPatcher.Core.Events; namespace Sims1WidescreenPatcher.Core.Services.Interfaces { public interface IProgressService { - event EventHandler? NewProgressEventHandler; - void UpdateProgress(double pct); void UpdateProgress(double pct, string status, string status2); - event EventHandler? NewUninstallEventHandler; void UpdateUninstall(); + IObservable Uninstall { get; } + IObservable NewProgressObservable { get; } } } \ No newline at end of file diff --git a/Sims1WidescreenPatcher.Core/Services/ProgressService.cs b/Sims1WidescreenPatcher.Core/Services/ProgressService.cs index 3fbd9b1..e89939f 100644 --- a/Sims1WidescreenPatcher.Core/Services/ProgressService.cs +++ b/Sims1WidescreenPatcher.Core/Services/ProgressService.cs @@ -1,30 +1,22 @@ -using Sims1WidescreenPatcher.Core.Events; -using Sims1WidescreenPatcher.Core.Models; +using System.Reactive; +using System.Reactive.Linq; +using System.Reactive.Subjects; +using Sims1WidescreenPatcher.Core.Events; using Sims1WidescreenPatcher.Core.Services.Interfaces; namespace Sims1WidescreenPatcher.Core.Services; public class ProgressService : IProgressService { - public event EventHandler? NewProgressEventHandler; - public event EventHandler? NewUninstallEventHandler; + private readonly Subject _uninstallSubject = new(); + public IObservable Uninstall => _uninstallSubject.AsObservable(); + + private readonly Subject _progressSubject = new(); + public IObservable NewProgressObservable => _progressSubject.AsObservable(); - public void UpdateProgress(double pct, string status, string status2) - { - var args = new NewProgressEventArgs(pct, status, status2); - var handler = NewProgressEventHandler; - handler?.Invoke(this, args); - } + public void UpdateProgress(double pct, string status, string status2) => _progressSubject.OnNext(new NewProgressEventArgs(pct, status, status2)); - public void UpdateProgress(double pct) - { - UpdateProgress(pct, string.Empty, string.Empty); - } + public void UpdateProgress(double pct) => _progressSubject.OnNext(new NewProgressEventArgs(pct, "", "")); - public void UpdateUninstall() - { - var arg = new NewUninstallEventArgs(); - var handler = NewUninstallEventHandler; - handler?.Invoke(this, arg); - } + public void UpdateUninstall() => _uninstallSubject.OnNext(Unit.Default); } diff --git a/Sims1WidescreenPatcher.Core/Services/ResolutionPatchService.cs b/Sims1WidescreenPatcher.Core/Services/ResolutionPatchService.cs index c3a2ed0..4878fdc 100644 --- a/Sims1WidescreenPatcher.Core/Services/ResolutionPatchService.cs +++ b/Sims1WidescreenPatcher.Core/Services/ResolutionPatchService.cs @@ -5,8 +5,7 @@ namespace Sims1WidescreenPatcher.Core.Services; public class ResolutionPatchService : IResolutionPatchService { - private IAppState _appState; - private const string ResolutionPattern = "20 03 ?? ?? ?? ?? ?? 58 02"; + private readonly IAppState _appState; private readonly IPatchFileService _patchFileService; public ResolutionPatchService(IAppState appState, IPatchFileService patchFileService) @@ -15,26 +14,36 @@ public ResolutionPatchService(IAppState appState, IPatchFileService patchFileSer _patchFileService = patchFileService; } + private const string ResolutionPattern = "20 03 ?? ?? ?? ?? ?? 58 02"; + public bool CanPatchResolution() { + if (string.IsNullOrWhiteSpace(_appState.SimsExePath)) + { + return false; + } var (resolutionPatternFound, _, _) = _patchFileService.FindPattern(_appState.SimsExePath, ResolutionPattern); return resolutionPatternFound; } public void EditSimsExe() { + if (string.IsNullOrWhiteSpace(_appState.SimsExePath) || _appState.Resolution is null) + { + return; + } var (found, offset, bytes) = _patchFileService.FindPattern(_appState.SimsExePath, ResolutionPattern); - if (!found) + if (!found || bytes is null) { return; } var widthBytes = BitConverter.GetBytes(_appState.Resolution.Width); - bytes![offset] = widthBytes[0]; + bytes[offset] = widthBytes[0]; bytes[offset + 1] = widthBytes[1]; var heightBytes = BitConverter.GetBytes(_appState.Resolution.Height); - bytes![offset + 2 + 5] = heightBytes[0]; + bytes[offset + 2 + 5] = heightBytes[0]; bytes[offset + 2 + 5 + 1] = heightBytes[1]; _patchFileService.WriteChanges(_appState.SimsExePath, bytes); @@ -53,6 +62,10 @@ public bool BackupExists() public void CreateBackup() { + if (string.IsNullOrWhiteSpace(_appState.SimsExePath)) + { + return; + } var backupPath = GetSimsBackupPath(); if (!string.IsNullOrWhiteSpace(backupPath) && !File.Exists(backupPath)) { diff --git a/Sims1WidescreenPatcher.Core/Services/UninstallService.cs b/Sims1WidescreenPatcher.Core/Services/UninstallService.cs index 9bc7d41..15ae09d 100644 --- a/Sims1WidescreenPatcher.Core/Services/UninstallService.cs +++ b/Sims1WidescreenPatcher.Core/Services/UninstallService.cs @@ -10,7 +10,10 @@ public class UninstallService : IUninstallService private readonly IProgressService _progressService; private readonly IWrapperService _wrapperService; - public UninstallService(IAppState appState, IImagesService imagesService, IProgressService progressService, IWrapperService wrapperService) + public UninstallService(IAppState appState, + IImagesService imagesService, + IProgressService progressService, + IWrapperService wrapperService) { _appState = appState; _imagesService = imagesService; @@ -20,6 +23,10 @@ public UninstallService(IAppState appState, IImagesService imagesService, IProgr public void Uninstall() { + if (string.IsNullOrWhiteSpace(_appState.SimsExePath)) + { + return; + } if (_appState.SimsBackupExists) { File.SetAttributes(_appState.SimsExePath, FileAttributes.Normal); diff --git a/Sims1WidescreenPatcher.Core/Services/WrapperService.cs b/Sims1WidescreenPatcher.Core/Services/WrapperService.cs index cbdeb9d..36192fb 100644 --- a/Sims1WidescreenPatcher.Core/Services/WrapperService.cs +++ b/Sims1WidescreenPatcher.Core/Services/WrapperService.cs @@ -6,6 +6,13 @@ namespace Sims1WidescreenPatcher.Core.Services; public class WrapperService : IWrapperService { + private readonly IAppState _appState; + + public WrapperService(IAppState appState) + { + _appState = appState; + } + private static string[] _ddrawCompat051Resources = { @"DDrawCompat._0._5._1.ddraw.dll" }; private static string[] _ddrawCompat032Resources = { @"DDrawCompat._0._3._2.ddraw.dll" }; @@ -15,13 +22,6 @@ public class WrapperService : IWrapperService @"DgVoodoo2.dgVoodooCpl.exe" }; - private readonly IAppState _appState; - - public WrapperService(IAppState appState) - { - _appState = appState; - } - public List GetWrappers() { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) diff --git a/Sims1WidescreenPatcher.Core/Sims1WidescreenPatcher.Core.csproj b/Sims1WidescreenPatcher.Core/Sims1WidescreenPatcher.Core.csproj index 0bd31f3..aa1cb38 100644 --- a/Sims1WidescreenPatcher.Core/Sims1WidescreenPatcher.Core.csproj +++ b/Sims1WidescreenPatcher.Core/Sims1WidescreenPatcher.Core.csproj @@ -7,12 +7,20 @@ default + + true + + + + true + + - - - + + + - + diff --git a/Sims1WidescreenPatcher.Core/Tabs/ExtrasTabViewModel.cs b/Sims1WidescreenPatcher.Core/Tabs/ExtrasTabViewModel.cs index 6a7ec46..632f98a 100644 --- a/Sims1WidescreenPatcher.Core/Tabs/ExtrasTabViewModel.cs +++ b/Sims1WidescreenPatcher.Core/Tabs/ExtrasTabViewModel.cs @@ -1,10 +1,8 @@ using System.Reactive; using System.Reactive.Linq; using ReactiveUI; -using Sims1WidescreenPatcher.Core.Events; using Sims1WidescreenPatcher.Core.Factories; using Sims1WidescreenPatcher.Core.Models; -using Sims1WidescreenPatcher.Core.Services; using Sims1WidescreenPatcher.Core.Services.Interfaces; using Sims1WidescreenPatcher.Core.ViewModels; @@ -43,16 +41,11 @@ public ExtrasTabViewModel(CheckboxViewModelFactory creator, ICheatsService cheat .Select(_ => AppState.SimsExePathExists && _cheatsService.CanEnableCheats()) .Subscribe(x => UnlockCheatsViewModel.IsEnabled = x); - var uninstallEvt = Observable - .FromEventPattern(progressService, "NewUninstallEventHandler"); - // When the sims exe is uninstalled, check for the validity of these checkboxes - uninstallEvt - .ObserveOn(RxApp.MainThreadScheduler) - .Subscribe(_ => - { - UnlockCheatsViewModel.Checked = _cheatsService.CheatsEnabled(); - PreviousSnapshot = new CheckboxSelectionSnapshot(UnlockCheatsViewModel.Checked); - }); + progressService.Uninstall.Subscribe(_ => + { + UnlockCheatsViewModel.Checked = _cheatsService.CheatsEnabled(); + PreviousSnapshot = new CheckboxSelectionSnapshot(UnlockCheatsViewModel.Checked); + }); ApplyCommand = ReactiveCommand.CreateFromTask(OnApplyClickedAsync); } diff --git a/Sims1WidescreenPatcher.Core/Tabs/MainTabViewModel.cs b/Sims1WidescreenPatcher.Core/Tabs/MainTabViewModel.cs index 009fdb9..3015101 100644 --- a/Sims1WidescreenPatcher.Core/Tabs/MainTabViewModel.cs +++ b/Sims1WidescreenPatcher.Core/Tabs/MainTabViewModel.cs @@ -8,7 +8,6 @@ using DynamicData.Binding; using ReactiveUI; using Sims1WidescreenPatcher.Core.Enums; -using Sims1WidescreenPatcher.Core.Events; using Sims1WidescreenPatcher.Core.Factories; using Sims1WidescreenPatcher.Core.Models; using Sims1WidescreenPatcher.Core.Services; @@ -32,10 +31,10 @@ public class MainTabViewModel : ViewModelBase, IMainTabViewModel private bool _isBusy; private readonly ObservableAsPropertyHelper _hasBackup; private readonly ObservableAsPropertyHelper _isValidSimsExe; - private readonly List _previouslyPatched = new(); - private readonly ObservableAsPropertyHelper _progressPct; - private readonly ObservableAsPropertyHelper _progressStatus; - private readonly ObservableAsPropertyHelper _progressStatus2; + private readonly List _previouslyPatched = new() { }; + private double _progressPct; + private string? _progressStatus; + private string? _progressStatus2; private readonly SourceList _resolutionSource = new(); private readonly IProgressService _progressService; private readonly IWrapperService _wrapperService; @@ -142,17 +141,12 @@ public MainTabViewModel(IResolutionsService resolutionsService, ShowCustomInformationDialog = new Interaction(); Path = findSimsPathService.FindSimsPath(); - var progressEvt = Observable - .FromEventPattern(progressService, "NewProgressEventHandler"); - _progressPct = progressEvt - .Select(x => x.EventArgs.Progress) - .ToProperty(this, x => x.Progress); - _progressStatus = progressEvt - .Select(x => x.EventArgs.Status) - .ToProperty(this, x => x.ProgressStatus); - _progressStatus2 = progressEvt - .Select(x => x.EventArgs.Status2) - .ToProperty(this, x => x.ProgressStatus2); + progressService.NewProgressObservable.Subscribe(x => + { + Progress = x.Progress; + ProgressStatus = x.Status; + ProgressStatus2 = x.Status2; + }); } #endregion @@ -225,9 +219,23 @@ public int SelectedWrapperIndex set => this.RaiseAndSetIfChanged(ref _selectedWrapperIndex, value); } - public double Progress => _progressPct.Value; - public string ProgressStatus => _progressStatus.Value; - public string ProgressStatus2 => _progressStatus2.Value; + public double Progress + { + get => _progressPct; + set => this.RaiseAndSetIfChanged(ref _progressPct, value); + } + + public string? ProgressStatus + { + get => _progressStatus; + set => this.RaiseAndSetIfChanged(ref _progressStatus, value); + } + + public string? ProgressStatus2 + { + get => _progressStatus2; + set => this.RaiseAndSetIfChanged(ref _progressStatus2, value); + } #endregion diff --git a/Sims1WidescreenPatcher.Core/Validations/FileExistsAttribute.cs b/Sims1WidescreenPatcher.Core/Validations/FileExistsAttribute.cs index 3c45818..bc314ba 100644 --- a/Sims1WidescreenPatcher.Core/Validations/FileExistsAttribute.cs +++ b/Sims1WidescreenPatcher.Core/Validations/FileExistsAttribute.cs @@ -4,7 +4,7 @@ namespace Sims1WidescreenPatcher.Core.Validations; public class FileExistsAttribute : ValidationAttribute { - protected override ValidationResult IsValid(object value, ValidationContext validationContext) + protected override ValidationResult? IsValid(object? value, ValidationContext validationContext) { var path = value as string; diff --git a/Sims1WidescreenPatcher.Core/Validations/RequiredAltAttribute.cs b/Sims1WidescreenPatcher.Core/Validations/RequiredAltAttribute.cs index 41d58ff..7266876 100644 --- a/Sims1WidescreenPatcher.Core/Validations/RequiredAltAttribute.cs +++ b/Sims1WidescreenPatcher.Core/Validations/RequiredAltAttribute.cs @@ -7,13 +7,13 @@ namespace Sims1WidescreenPatcher.Core.Validations; /// public class RequiredAltAttribute : RequiredAttribute { - private static bool Visited; + private static bool _visited; - protected override ValidationResult IsValid(object value, ValidationContext validationContext) + protected override ValidationResult? IsValid(object? value, ValidationContext validationContext) { - if (!Visited) + if (!_visited) { - Visited = true; + _visited = true; return ValidationResult.Success; } diff --git a/Sims1WidescreenPatcher.Core/ViewModels/CheckboxViewModel.cs b/Sims1WidescreenPatcher.Core/ViewModels/CheckboxViewModel.cs index 8b0fd5b..6a406b4 100644 --- a/Sims1WidescreenPatcher.Core/ViewModels/CheckboxViewModel.cs +++ b/Sims1WidescreenPatcher.Core/ViewModels/CheckboxViewModel.cs @@ -14,9 +14,9 @@ public CheckboxViewModel(string label, string toolTipText) } public string Label { get; set; } - + public string ToolTipText { get; set; } - + public bool Checked { get => _checked; diff --git a/Sims1WidescreenPatcher.Core/ViewModels/CustomInformationDialogViewModel.cs b/Sims1WidescreenPatcher.Core/ViewModels/CustomInformationDialogViewModel.cs index 5c29bca..f4e1de7 100644 --- a/Sims1WidescreenPatcher.Core/ViewModels/CustomInformationDialogViewModel.cs +++ b/Sims1WidescreenPatcher.Core/ViewModels/CustomInformationDialogViewModel.cs @@ -7,7 +7,7 @@ public CustomInformationDialogViewModel(string title, string message) Title = title; Message = message; } - + public string Title { get; } public string Message { get; } } \ No newline at end of file diff --git a/Sims1WidescreenPatcher.Core/ViewModels/CustomYesNoDialogViewModel.cs b/Sims1WidescreenPatcher.Core/ViewModels/CustomYesNoDialogViewModel.cs index 34a8c0b..2fd8505 100644 --- a/Sims1WidescreenPatcher.Core/ViewModels/CustomYesNoDialogViewModel.cs +++ b/Sims1WidescreenPatcher.Core/ViewModels/CustomYesNoDialogViewModel.cs @@ -6,14 +6,8 @@ namespace Sims1WidescreenPatcher.Core.ViewModels; public class CustomYesNoDialogViewModel : ViewModelBase { - public CustomYesNoDialogViewModel() - { - YesCommand = ReactiveCommand.Create(() => new YesNoDialogResponse { Result = true }); - NoCommand = ReactiveCommand.Create(() => new YesNoDialogResponse { Result = false }); - } - - public ReactiveCommand YesCommand { get; } - public ReactiveCommand NoCommand { get; } + public ReactiveCommand YesCommand { get; } = ReactiveCommand.Create(() => new YesNoDialogResponse { Result = true }); + public ReactiveCommand NoCommand { get; } = ReactiveCommand.Create(() => new YesNoDialogResponse { Result = false }); public string Title { get; set; } = "Default Title"; public string Message { get; set; } = "Default message."; diff --git a/Sims1WidescreenPatcher.Core/ViewModels/MainWindowViewModel.cs b/Sims1WidescreenPatcher.Core/ViewModels/MainWindowViewModel.cs index aac0743..256b6da 100644 --- a/Sims1WidescreenPatcher.Core/ViewModels/MainWindowViewModel.cs +++ b/Sims1WidescreenPatcher.Core/ViewModels/MainWindowViewModel.cs @@ -5,7 +5,8 @@ namespace Sims1WidescreenPatcher.Core.ViewModels; public class MainWindowViewModel : ViewModelBase, IMainWindowViewModel { - public MainWindowViewModel(IMainTabViewModel mainTabViewModel, IExtrasTabViewModel extrasTabViewModel, + public MainWindowViewModel(IMainTabViewModel mainTabViewModel, + IExtrasTabViewModel extrasTabViewModel, INotificationViewModel notificationViewModel) { MainTabViewModel = mainTabViewModel; diff --git a/Sims1WidescreenPatcher.Linux/Services/LinuxResolutionService.cs b/Sims1WidescreenPatcher.Linux/Services/LinuxResolutionService.cs index 78f729e..4d07bd0 100644 --- a/Sims1WidescreenPatcher.Linux/Services/LinuxResolutionService.cs +++ b/Sims1WidescreenPatcher.Linux/Services/LinuxResolutionService.cs @@ -1,59 +1,114 @@ +using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; -using System.Text.RegularExpressions; +using System.Runtime.InteropServices; using Serilog; using Sims1WidescreenPatcher.Core.Models; -using Sims1WidescreenPatcher.Core.Services; using Sims1WidescreenPatcher.Core.Services.Interfaces; namespace Sims1WidescreenPatcher.Linux.Services { - public class LinuxResolutionService : IResolutionsService - { - private const string FileName = "/bin/bash"; - private const string Cmd = "-c xrandr"; - private readonly Regex _resolutionRx = new Regex(@"\d{3,}x\d{3,}", RegexOptions.Compiled | RegexOptions.IgnoreCase); - - public IEnumerable GetResolutions() - { - Log.Information("Begin enumerate resolutions"); - var psi = new ProcessStartInfo() - { - FileName = FileName, - Arguments = Cmd, - RedirectStandardOutput = true, - UseShellExecute = false, - CreateNoWindow = true - }; - using (var process = Process.Start(psi)) - { - var output = ""; - if (process != null) - { - process.WaitForExit(); - output = process.StandardOutput.ReadToEnd(); - } - var resolutions = new List(); - if (string.IsNullOrWhiteSpace(output)) - { - return resolutions; - } - - var matches = _resolutionRx.Matches(output); - foreach (Match m in matches) - { - var split = m.Value.Split('x'); - var newRes = new Resolution(int.Parse(split[0]), int.Parse(split[1])); - if (!resolutions.Contains(newRes, Resolution.WidthHeightComparer) && newRes.Width >= 800 && newRes.Height >= 600) - { - resolutions.Add(newRes); - } - } - Log.Debug("Resolutions {@Resolutions}", resolutions); - Log.Information("End enumerate resolutions"); - return resolutions.OrderBy(x => x.Height * x.Width); - } - } - } + public class LinuxResolutionService : IResolutionsService + { + public IEnumerable GetResolutions() + { + Log.Information("Begin enumerate resolutions"); + HashSet resolutions; + + var display = X11.XOpenDisplay(IntPtr.Zero); + if (display == IntPtr.Zero) + { + throw new Exception("Failed to open display"); + } + + try + { + var root = X11.XDefaultRootWindow(display); + resolutions = EnumerateResolutions(display, root); + } + finally + { + X11.XCloseDisplay(display); + } + + Log.Debug("Resolutions {@Resolutions}", resolutions); + Log.Information("End enumerate resolutions"); + return resolutions; + } + + private static HashSet EnumerateResolutions(IntPtr display, IntPtr root) + { + var screenResourcesPtr = X11.XRRGetScreenResources(display, root); + if (screenResourcesPtr == IntPtr.Zero) + { + throw new Exception("Failed to get screen resources"); + } + + var screenResources = Marshal.PtrToStructure(screenResourcesPtr); + var sizeXrrModeInfo = Marshal.SizeOf(); + var modesArr = new X11.XrrModeInfo[screenResources.nmode]; + var curPtr = screenResources.modes; + for (var i = 0; i < screenResources.nmode; i++) + { + modesArr[i] = Marshal.PtrToStructure(curPtr + sizeXrrModeInfo * i); + } + + X11.XRRFreeScreenResources(screenResourcesPtr); + return modesArr + .Where(x => x is { width: >= 800, height: >= 600 }) + .Select(x => new Resolution((int)x.width, (int)x.height)) + .OrderBy(x => x.Height * x.Width) + .ToHashSet(); + } + } +} + +internal static class X11 +{ + [DllImport("libX11.so")] + internal static extern IntPtr XOpenDisplay(IntPtr display); + + [DllImport("libX11.so")] + internal static extern void XCloseDisplay(IntPtr display); + + [DllImport("libX11.so")] + internal static extern IntPtr XDefaultRootWindow(IntPtr display); + + [DllImport("libXrandr.so")] + internal static extern IntPtr XRRGetScreenResources(IntPtr display, IntPtr root); + + [DllImport("libXrandr.so")] + internal static extern IntPtr XRRFreeScreenResources(IntPtr resources); + + [StructLayout(LayoutKind.Sequential)] + internal struct XrrScreenResources + { + public ulong timestamp; + public ulong configTimestamp; + public int ncrtc; + public IntPtr crtcs; + public int noutput; + public IntPtr outputs; + public int nmode; + public IntPtr modes; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct XrrModeInfo + { + public ulong id; + public uint width; + public uint height; + public ulong dotClock; + public uint hSyncStart; + public uint hSyncEnd; + public uint hTotal; + public uint hSkew; + public uint vSyncStart; + public uint vSyncEnd; + public uint vTotal; + public IntPtr name; + public uint nameLen; + public ulong modeFlags; + } } \ No newline at end of file diff --git a/Sims1WidescreenPatcher.Linux/Sims1WidescreenPatcher.Linux.csproj b/Sims1WidescreenPatcher.Linux/Sims1WidescreenPatcher.Linux.csproj index dca8394..146bca0 100644 --- a/Sims1WidescreenPatcher.Linux/Sims1WidescreenPatcher.Linux.csproj +++ b/Sims1WidescreenPatcher.Linux/Sims1WidescreenPatcher.Linux.csproj @@ -14,6 +14,12 @@ ..\Sims1WidescreenPatcher.UI\Assets\SimsICO.ico default + + true + + + true + @@ -27,8 +33,8 @@ - - + + diff --git a/Sims1WidescreenPatcher.MacOS/Services/MacOSResolutionService.cs b/Sims1WidescreenPatcher.MacOS/Services/MacOSResolutionService.cs index 7bc3133..e49117c 100644 --- a/Sims1WidescreenPatcher.MacOS/Services/MacOSResolutionService.cs +++ b/Sims1WidescreenPatcher.MacOS/Services/MacOSResolutionService.cs @@ -22,7 +22,7 @@ public class MacOsResolutionService : IResolutionsService public IEnumerable GetResolutions() { - var resolutions = new List(); + var resolutions = new HashSet(); var nModes = 0; var id = CGMainDisplayID(); CGSGetNumberOfDisplayModes(id, ref nModes); @@ -31,7 +31,7 @@ public IEnumerable GetResolutions() CgsDisplayMode mode = default; CGSGetDisplayModeDescriptionOfLength(id, i, ref mode, Marshal.SizeOf(mode)); var newRes = new Resolution((int)mode.width, (int)mode.height); - if (!resolutions.Contains(newRes, Resolution.WidthHeightComparer) && newRes.Width >= 800 & newRes.Height >= 600) + if (newRes.Width >= 800 & newRes.Height >= 600) { resolutions.Add(newRes); } diff --git a/Sims1WidescreenPatcher.MacOS/Sims1WidescreenPatcher.MacOS.csproj b/Sims1WidescreenPatcher.MacOS/Sims1WidescreenPatcher.MacOS.csproj index a6546af..e557bb1 100644 --- a/Sims1WidescreenPatcher.MacOS/Sims1WidescreenPatcher.MacOS.csproj +++ b/Sims1WidescreenPatcher.MacOS/Sims1WidescreenPatcher.MacOS.csproj @@ -4,11 +4,17 @@ net6.0 default + + true + + + true + - - + + diff --git a/Sims1WidescreenPatcher.UI/Converters/ResolutionColorCodingConverter.cs b/Sims1WidescreenPatcher.UI/Converters/ResolutionColorCodingConverter.cs index 3329afc..101bfab 100644 --- a/Sims1WidescreenPatcher.UI/Converters/ResolutionColorCodingConverter.cs +++ b/Sims1WidescreenPatcher.UI/Converters/ResolutionColorCodingConverter.cs @@ -37,110 +37,117 @@ public class ResolutionColorCodingConverter : IValueConverter return null; } - if (s == "Background") + switch (s) { - if (r.Width == 1600) + case "Background": { - if (Application.Current?.ActualThemeVariant == ThemeVariant.Light) - { - return BackgroundBadLight; - } - - if (Application.Current?.ActualThemeVariant == ThemeVariant.Dark) + if (r.Width == 1600) { - return BackgroundBadDark; + if (Application.Current?.ActualThemeVariant == ThemeVariant.Light) + { + return BackgroundBadLight; + } + + if (Application.Current?.ActualThemeVariant == ThemeVariant.Dark) + { + return BackgroundBadDark; + } } - } - if (r.AspectRatio is { Numerator: 4, Denominator: 3 }) - { - if (Application.Current?.ActualThemeVariant == ThemeVariant.Light) + if (r.AspectRatio is { Numerator: 4, Denominator: 3 }) { - return BackgroundGoodLight; + if (Application.Current?.ActualThemeVariant == ThemeVariant.Light) + { + return BackgroundGoodLight; + } + + if (Application.Current?.ActualThemeVariant == ThemeVariant.Dark) + { + return BackgroundGoodDark; + } } - if (Application.Current?.ActualThemeVariant == ThemeVariant.Dark) - { - return BackgroundGoodDark; - } + break; } - } - - if (s == "Pointerover") - { - if (r.Width == 1600) + case "Pointerover": { - if (Application.Current?.ActualThemeVariant == ThemeVariant.Light) + if (r.Width == 1600) { - return PointeroverBadLight; + if (Application.Current?.ActualThemeVariant == ThemeVariant.Light) + { + return PointeroverBadLight; + } + + if (Application.Current?.ActualThemeVariant == ThemeVariant.Dark) + { + return PointeroverBadDark; + } } - - if (Application.Current?.ActualThemeVariant == ThemeVariant.Dark) + + if (r.AspectRatio is { Numerator: 4, Denominator: 3 }) { - return PointeroverBadDark; + if (Application.Current?.ActualThemeVariant == ThemeVariant.Light) + { + return PointeroverGoodLight; + } + + if (Application.Current?.ActualThemeVariant == ThemeVariant.Dark) + { + return PointeroverGoodDark; + } } - } - - if (r.AspectRatio is { Numerator: 4, Denominator: 3 }) - { + if (Application.Current?.ActualThemeVariant == ThemeVariant.Light) { - return PointeroverGoodLight; + return Brush.Parse("#19000000"); } - + if (Application.Current?.ActualThemeVariant == ThemeVariant.Dark) { - return PointeroverGoodDark; + return Brush.Parse("#19FFFFFF"); } - } - if (Application.Current?.ActualThemeVariant == ThemeVariant.Light) - { - return Brush.Parse("#19000000"); - } - - if (Application.Current?.ActualThemeVariant == ThemeVariant.Dark) - { - return Brush.Parse("#19FFFFFF"); + break; } - } - - if (s == "Selected") - { - if (r.Width == 1600) + case "Selected": { - if (Application.Current?.ActualThemeVariant == ThemeVariant.Light) + if (r.Width == 1600) { - return SelectedBadLight; + if (Application.Current?.ActualThemeVariant == ThemeVariant.Light) + { + return SelectedBadLight; + } + + if (Application.Current?.ActualThemeVariant == ThemeVariant.Dark) + { + return SelectedBadDark; + } } - - if (Application.Current?.ActualThemeVariant == ThemeVariant.Dark) + + if (r.AspectRatio is { Numerator: 4, Denominator: 3 }) { - return SelectedBadDark; + if (Application.Current?.ActualThemeVariant == ThemeVariant.Light) + { + return SelectedGoodLight; + } + + if (Application.Current?.ActualThemeVariant == ThemeVariant.Dark) + { + return SelectedGoodDark; + } } - } - - if (r.AspectRatio is { Numerator: 4, Denominator: 3 }) - { + if (Application.Current?.ActualThemeVariant == ThemeVariant.Light) { - return SelectedGoodLight; + return Brush.Parse("#29000000"); } - + if (Application.Current?.ActualThemeVariant == ThemeVariant.Dark) { - return SelectedGoodDark; + return Brush.Parse("#09FFFFFF"); } - } - if (Application.Current?.ActualThemeVariant == ThemeVariant.Light) - { - return Brush.Parse("#29000000"); - } - - if (Application.Current?.ActualThemeVariant == ThemeVariant.Dark) - { - return Brush.Parse("#09FFFFFF"); + break; } } diff --git a/Sims1WidescreenPatcher.UI/Sims1WidescreenPatcher.UI.csproj b/Sims1WidescreenPatcher.UI/Sims1WidescreenPatcher.UI.csproj index 772fc9a..98888d7 100644 --- a/Sims1WidescreenPatcher.UI/Sims1WidescreenPatcher.UI.csproj +++ b/Sims1WidescreenPatcher.UI/Sims1WidescreenPatcher.UI.csproj @@ -6,6 +6,14 @@ default + + true + + + + true + + @@ -16,11 +24,11 @@ - - - - - + + + + + diff --git a/Sims1WidescreenPatcher.Windows/NativeMethods.txt b/Sims1WidescreenPatcher.Windows/NativeMethods.txt new file mode 100644 index 0000000..67fb342 --- /dev/null +++ b/Sims1WidescreenPatcher.Windows/NativeMethods.txt @@ -0,0 +1 @@ +EnumDisplaySettings \ No newline at end of file diff --git a/Sims1WidescreenPatcher.Windows/Services/FindSimsPathService.cs b/Sims1WidescreenPatcher.Windows/Services/FindSimsPathService.cs index 2aaf2b3..46759d6 100644 --- a/Sims1WidescreenPatcher.Windows/Services/FindSimsPathService.cs +++ b/Sims1WidescreenPatcher.Windows/Services/FindSimsPathService.cs @@ -1,10 +1,12 @@ using System; using System.IO; +using System.Runtime.Versioning; using Microsoft.Win32; using Sims1WidescreenPatcher.Core.Services.Interfaces; namespace Sims1WidescreenPatcher.Windows.Services; +[SupportedOSPlatform("windows")] public class FindSimsPathService : IFindSimsPathService { public string FindSimsPath() diff --git a/Sims1WidescreenPatcher.Windows/Services/ResolutionsService.cs b/Sims1WidescreenPatcher.Windows/Services/ResolutionsService.cs index e045229..c69e9d5 100644 --- a/Sims1WidescreenPatcher.Windows/Services/ResolutionsService.cs +++ b/Sims1WidescreenPatcher.Windows/Services/ResolutionsService.cs @@ -1,75 +1,37 @@ using System.Collections.Generic; using System.Linq; -using System.Runtime.InteropServices; +using System.Runtime.Versioning; +using Windows.Win32; +using Windows.Win32.Graphics.Gdi; using Serilog; using Sims1WidescreenPatcher.Core.Models; -using Sims1WidescreenPatcher.Core.Services; using Sims1WidescreenPatcher.Core.Services.Interfaces; namespace Sims1WidescreenPatcher.Windows.Services { + [SupportedOSPlatform("windows5.0")] public class WindowsResolutionsService : IResolutionsService { - [DllImport("user32.dll")] - private static extern bool EnumDisplaySettings(string deviceName, int modeNum, ref DEVMODE devMode); - - [StructLayout(LayoutKind.Sequential)] - private struct DEVMODE - { - private const int CCHDEVICENAME = 0x20; - private const int CCHFORMNAME = 0x20; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)] - private string dmDeviceName; - public short dmSpecVersion; - public short dmDriverVersion; - public short dmSize; - public short dmDriverExtra; - public int dmFields; - public int dmPositionX; - public int dmPositionY; - public int dmDisplayOrientation; - public int dmDisplayFixedOutput; - public short dmColor; - public short dmDuplex; - public short dmYResolution; - public short dmTTOption; - public short dmCollate; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)] - public string dmFormName; - public short dmLogPixels; - public int dmBitsPerPel; - public int dmPelsWidth; - public int dmPelsHeight; - public int dmDisplayFlags; - public int dmDisplayFrequency; - public int dmICMMethod; - public int dmICMIntent; - public int dmMediaType; - public int dmDitherType; - public int dmReserved1; - public int dmReserved2; - public int dmPanningWidth; - public int dmPanningHeight; - } - public IEnumerable GetResolutions() { Log.Information("Begin enumerate resolutions"); - var resolutions = new List(); - var vDevMode = new DEVMODE(); + var resolutions = new HashSet(); + var vDevMode = new DEVMODEW(); var i = 0; - while (EnumDisplaySettings(null, i, ref vDevMode)) + while (PInvoke.EnumDisplaySettings(null, (ENUM_DISPLAY_SETTINGS_MODE)i, ref vDevMode)) { - var newRes = new Resolution(vDevMode.dmPelsWidth, vDevMode.dmPelsHeight); - if (!resolutions.Contains(newRes, Resolution.WidthHeightComparer) && newRes.Width >= 800 && newRes.Height >= 600) + var newRes = new Resolution((int)vDevMode.dmPelsWidth, (int)vDevMode.dmPelsHeight); + if (newRes.Width >= 800 && newRes.Height >= 600) { resolutions.Add(newRes); } + i++; } + Log.Debug("Resolutions {@Resolutions}", resolutions); Log.Information("End enumerate resolutions"); - return resolutions.OrderBy(x => x.Height * x.Width).ToList(); + return resolutions.OrderBy(x => x.Height * x.Width); } } } \ No newline at end of file diff --git a/Sims1WidescreenPatcher.Windows/Sims1WidescreenPatcher.Windows.csproj b/Sims1WidescreenPatcher.Windows/Sims1WidescreenPatcher.Windows.csproj index 437e6b7..882f764 100644 --- a/Sims1WidescreenPatcher.Windows/Sims1WidescreenPatcher.Windows.csproj +++ b/Sims1WidescreenPatcher.Windows/Sims1WidescreenPatcher.Windows.csproj @@ -14,6 +14,12 @@ ..\Sims1WidescreenPatcher.UI\Assets\SimsICO.ico default + + true + + + true + @@ -26,9 +32,13 @@ - - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/Sims1WidescreenPatcher/DependencyInjection/Bootstrapper.cs b/Sims1WidescreenPatcher/DependencyInjection/Bootstrapper.cs index f54aafd..eb1f9ad 100644 --- a/Sims1WidescreenPatcher/DependencyInjection/Bootstrapper.cs +++ b/Sims1WidescreenPatcher/DependencyInjection/Bootstrapper.cs @@ -1,10 +1,10 @@ -using Autofac; +using Microsoft.Extensions.DependencyInjection; namespace Sims1WidescreenPatcher.DependencyInjection; public static class Bootstrapper { - public static void Register(ContainerBuilder services) + public static void Register(IServiceCollection services) { StateBootstrapper.RegisterState(services); ServicesBootstrapper.RegisterServices(services); diff --git a/Sims1WidescreenPatcher/DependencyInjection/FactoryBootstrapper.cs b/Sims1WidescreenPatcher/DependencyInjection/FactoryBootstrapper.cs index 6e97e53..cb98e41 100644 --- a/Sims1WidescreenPatcher/DependencyInjection/FactoryBootstrapper.cs +++ b/Sims1WidescreenPatcher/DependencyInjection/FactoryBootstrapper.cs @@ -1,12 +1,12 @@ -using Autofac; +using Microsoft.Extensions.DependencyInjection; using Sims1WidescreenPatcher.Core.Factories; namespace Sims1WidescreenPatcher.DependencyInjection; public static class FactoryBootstrapper { - public static void RegisterFactories(ContainerBuilder services) + public static void RegisterFactories(IServiceCollection services) { - services.RegisterType().AsSelf(); + services.AddScoped(); } } \ No newline at end of file diff --git a/Sims1WidescreenPatcher/DependencyInjection/ServicesBootstrapper.cs b/Sims1WidescreenPatcher/DependencyInjection/ServicesBootstrapper.cs index aefb12b..c0b1ea2 100644 --- a/Sims1WidescreenPatcher/DependencyInjection/ServicesBootstrapper.cs +++ b/Sims1WidescreenPatcher/DependencyInjection/ServicesBootstrapper.cs @@ -3,7 +3,7 @@ using Sims1WidescreenPatcher.MacOS.Services; using Sims1WidescreenPatcher.Windows.Services; using System.Runtime.InteropServices; -using Autofac; +using Microsoft.Extensions.DependencyInjection; using Sims.Far; using Sims1WidescreenPatcher.Core.Services.Interfaces; using FindSimsPathService = Sims1WidescreenPatcher.Windows.Services.FindSimsPathService; @@ -12,28 +12,28 @@ namespace Sims1WidescreenPatcher.DependencyInjection { public static class ServicesBootstrapper { - public static void RegisterServices(ContainerBuilder services) + public static void RegisterServices(IServiceCollection services) { RegisterCommonServices(services); RegisterPlatformSpecificServices(services); } - private static void RegisterPlatformSpecificServices(ContainerBuilder services) + private static void RegisterPlatformSpecificServices(IServiceCollection services) { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + if (OperatingSystem.IsWindowsVersionAtLeast(5)) { - services.RegisterType().As().SingleInstance(); - services.RegisterType().As(); + services.AddScoped() + .AddScoped(); } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + else if (OperatingSystem.IsMacOS()) { - services.RegisterType().As().SingleInstance(); - services.RegisterType().As(); + services.AddScoped() + .AddScoped(); } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + else if (OperatingSystem.IsLinux()) { - services.RegisterType().As().SingleInstance(); - services.RegisterType().As(); + services.AddScoped() + .AddScoped(); } else { @@ -41,16 +41,16 @@ private static void RegisterPlatformSpecificServices(ContainerBuilder services) } } - private static void RegisterCommonServices(ContainerBuilder services) + private static void RegisterCommonServices(IServiceCollection services) { - services.RegisterType().As(); - services.RegisterType().As(); - services.RegisterType().As().SingleInstance(); - services.RegisterType().As(); - services.RegisterType().As(); - services.RegisterType().As(); - services.RegisterType().As(); - services.RegisterType().As(); + services.AddScoped() + .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped(); } } -} +} \ No newline at end of file diff --git a/Sims1WidescreenPatcher/DependencyInjection/StateBootstrapper.cs b/Sims1WidescreenPatcher/DependencyInjection/StateBootstrapper.cs index 4bdc0c1..f17694b 100644 --- a/Sims1WidescreenPatcher/DependencyInjection/StateBootstrapper.cs +++ b/Sims1WidescreenPatcher/DependencyInjection/StateBootstrapper.cs @@ -1,12 +1,12 @@ -using Autofac; +using Microsoft.Extensions.DependencyInjection; using Sims1WidescreenPatcher.Core.Models; namespace Sims1WidescreenPatcher.DependencyInjection; public static class StateBootstrapper { - public static void RegisterState(ContainerBuilder services) + public static void RegisterState(IServiceCollection services) { - services.RegisterType().As().SingleInstance(); + services.AddSingleton(); } } \ No newline at end of file diff --git a/Sims1WidescreenPatcher/DependencyInjection/ViewModelBootstrapper.cs b/Sims1WidescreenPatcher/DependencyInjection/ViewModelBootstrapper.cs index bed46bc..b53d2c5 100644 --- a/Sims1WidescreenPatcher/DependencyInjection/ViewModelBootstrapper.cs +++ b/Sims1WidescreenPatcher/DependencyInjection/ViewModelBootstrapper.cs @@ -1,4 +1,4 @@ -using Autofac; +using Microsoft.Extensions.DependencyInjection; using Sims1WidescreenPatcher.Core.Tabs; using Sims1WidescreenPatcher.Core.ViewModels; @@ -6,14 +6,14 @@ namespace Sims1WidescreenPatcher.DependencyInjection { public static class ViewModelBootstrapper { - public static void RegisterViewModels(ContainerBuilder services) + public static void RegisterViewModels(IServiceCollection services) { - services.RegisterType().As(); - services.RegisterType().AsSelf(); - services.RegisterType().As(); - services.RegisterType().As(); - services.RegisterType().As(); - services.RegisterType().As(); + services.AddScoped() + .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped() + .AddScoped(); } } } diff --git a/Sims1WidescreenPatcher/Program.cs b/Sims1WidescreenPatcher/Program.cs index 5c0b24f..75cf3ae 100644 --- a/Sims1WidescreenPatcher/Program.cs +++ b/Sims1WidescreenPatcher/Program.cs @@ -1,18 +1,22 @@ using System.Reflection; -using Autofac; using Avalonia; using Avalonia.ReactiveUI; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; using ReactiveUI; using Serilog; using Serilog.Formatting.Compact; using Sims1WidescreenPatcher.DependencyInjection; using Sims1WidescreenPatcher.UI; -using Splat.Autofac; +using Splat; +using Splat.Microsoft.Extensions.DependencyInjection; namespace Sims1WidescreenPatcher; internal static class Program { + private static IServiceProvider? Container { get; set; } + [STAThread] public static void Main(string[] args) { @@ -30,14 +34,25 @@ public static void Main(string[] args) Log.Information("{@Name}", name); Log.Information("{@Version}", informationalVersion); Log.Information("{@OSInformation}", osNameAndVersion); - var builder = new ContainerBuilder(); - Bootstrapper.Register(builder); - builder.RegisterType().As().SingleInstance(); - var autofacResolver = builder.UseAutofacDependencyResolver(); - builder.RegisterInstance(autofacResolver); - autofacResolver.InitializeReactiveUI(); - var container = builder.Build(); - autofacResolver.SetLifetimeScope(container); + var host = Host.CreateDefaultBuilder(args) + .ConfigureServices(services => + { + services.UseMicrosoftDependencyResolver(); + var resolver = Locator.CurrentMutable; + resolver.InitializeSplat(); + resolver.InitializeReactiveUI(); + Bootstrapper.Register(services); + + services.AddSingleton< + IActivationForViewFetcher, + AvaloniaActivationForViewFetcher + >(); + services.AddSingleton(); + }).Build(); + + Container = host.Services; + Container.UseMicrosoftDependencyResolver(); + RxApp.MainThreadScheduler = AvaloniaScheduler.Instance; try diff --git a/Sims1WidescreenPatcher/Sims1WidescreenPatcher.csproj b/Sims1WidescreenPatcher/Sims1WidescreenPatcher.csproj index 6cfe206..a3b2a6c 100644 --- a/Sims1WidescreenPatcher/Sims1WidescreenPatcher.csproj +++ b/Sims1WidescreenPatcher/Sims1WidescreenPatcher.csproj @@ -7,6 +7,10 @@ enable SimsICO.ico app.manifest + default + true + copyused + true @@ -14,13 +18,14 @@ - - - + + + - - - + + + + @@ -45,4 +50,13 @@ true + + true + + + + true + 1701;1702;IL2121;IL2104;IL2121;IL2026 + +