Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pinvoke x11 xrandr for linux resolutions #107

Merged
merged 3 commits into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
Expand Down
84 changes: 21 additions & 63 deletions Sims1WidescreenPatcher.Core/Models/AspectRatio.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,83 +2,41 @@

namespace Sims1WidescreenPatcher.Core.Models;

public class AspectRatio : IEqualityComparer<AspectRatio>, IComparable<AspectRatio>
public record AspectRatio : IComparable<AspectRatio>
{
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;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using Sims1WidescreenPatcher.Core.ViewModels;

namespace Sims1WidescreenPatcher.Core.Models;
namespace Sims1WidescreenPatcher.Core.Models;

public class CheckboxSelectionSnapshot : IEquatable<CheckboxSelectionSnapshot>
{
Expand Down
2 changes: 1 addition & 1 deletion Sims1WidescreenPatcher.Core/Models/CompositeImageJob.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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!);
Expand Down
57 changes: 21 additions & 36 deletions Sims1WidescreenPatcher.Core/Models/Resolution.cs
Original file line number Diff line number Diff line change
@@ -1,53 +1,38 @@
using System.Numerics;
namespace Sims1WidescreenPatcher.Core.Models;

namespace Sims1WidescreenPatcher.Core.Models;

public class Resolution : IComparable<Resolution>
public record Resolution : IComparable<Resolution>
{
private sealed class WidthHeightEqualityComparer : IEqualityComparer<Resolution>
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<Resolution>? 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;
}
}
6 changes: 3 additions & 3 deletions Sims1WidescreenPatcher.Core/Models/ScalePanelBackJob.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
2 changes: 1 addition & 1 deletion Sims1WidescreenPatcher.Core/Models/ScaleTallSubPanelJob.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
17 changes: 15 additions & 2 deletions Sims1WidescreenPatcher.Core/Services/CheatsService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;
}
Expand All @@ -28,6 +33,10 @@ public bool CheatsEnabled()
/// <returns></returns>
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;
Expand All @@ -45,6 +54,10 @@ public void DisableCheats()

private void EditSimsExe(string pattern, Tuple<byte, byte> replacementBytes)
{
if (string.IsNullOrWhiteSpace(_appState.SimsExePath))
{
return;
}
var (found, offset, bytes) = _patchFileService.FindPattern(_appState.SimsExePath, pattern);
if (!found)
{
Expand Down
34 changes: 26 additions & 8 deletions Sims1WidescreenPatcher.Core/Services/ImagesService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
{
Expand All @@ -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)
{
Expand All @@ -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();
Expand Down Expand Up @@ -74,7 +75,7 @@ public void Uninstall()

foreach (var i in _blackBackground
.Concat(_blueBackground)
.Concat(new[] { TallSubPanel, PanelBack }))
.Concat(new List<string> { TallSubPanel, PanelBack }.AsReadOnly()))
{
DeleteUiGraphicsFile(i);
}
Expand All @@ -85,6 +86,11 @@ private List<BaseImageProcessingJob> GetJobs()
_far.ParseFar();
var jobs = new List<BaseImageProcessingJob>();

if (_appState.Resolution is null)
{
return jobs;
}

if (_far.TryGetBytes(PanelBack, out var bytes))
{
jobs.Add(new ScalePanelBackJob
Expand Down Expand Up @@ -116,6 +122,10 @@ private List<BaseImageProcessingJob> GetJobs()

private IEnumerable<BaseImageProcessingJob> GetCompositeJobs(IEnumerable<string> 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))
Expand All @@ -134,7 +144,15 @@ private IEnumerable<BaseImageProcessingJob> GetCompositeJobs(IEnumerable<string>

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");
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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<NewProgressEventArgs>? NewProgressEventHandler;

void UpdateProgress(double pct);
void UpdateProgress(double pct, string status, string status2);
event EventHandler<NewUninstallEventArgs>? NewUninstallEventHandler;
void UpdateUninstall();
IObservable<Unit> Uninstall { get; }
IObservable<NewProgressEventArgs> NewProgressObservable { get; }
}
}
Loading
Loading