Skip to content

Commit

Permalink
Implemented view model FOV correction
Browse files Browse the repository at this point in the history
  • Loading branch information
hyperbx committed Jul 22, 2024
1 parent 2ca3bbf commit a759779
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 37 deletions.
4 changes: 2 additions & 2 deletions Ausar/Ausar.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows</TargetFramework>
<Version>1.1.0</Version>
<InformationalVersion>1.1.0</InformationalVersion>
<Version>1.2.0</Version>
<InformationalVersion>1.2.0</InformationalVersion>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UseWPF>True</UseWPF>
Expand Down
5 changes: 5 additions & 0 deletions Ausar/Configuration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ public class Configuration : INotifyPropertyChanged

public bool IsApplyCustomFOVToVehicles { get; set; } = false;

public bool IsApplyCustomFOVToViewModel { get; set; } = false;

public byte CrosshairScaleMode { get; set; } = (byte)ECrosshairScaleMode.Default;

public bool IsDynamicAspectRatio { get; set; } = false;
Expand Down Expand Up @@ -125,6 +127,9 @@ public int PerformancePreset
[JsonIgnore]
public bool IsCrosshairScaleModeAvailable { get; set; } = true;

[JsonIgnore]
public bool IsApplyCustomFOVToViewModelAvailable { get; set; } = true;

[JsonIgnore]
public bool IsDynamicAspectRatioAvailable { get; set; } = true;

Expand Down
123 changes: 91 additions & 32 deletions Ausar/Game/Memory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public class Memory : IDisposable
private const float _minFOV = 60.0f;

private static bool _isScaleCrosshairToFOVInitialised = false;
private static bool _isApplyCustomFOVToViewModelInitialised = false;
private static bool _isDynamicAspectRatioInitialised = false;

private bool _isUpdating = true;
Expand Down Expand Up @@ -273,6 +274,67 @@ private void PatchApplyCustomFOVToVehicles(bool in_isEnabled)
}
}

private void PatchApplyCustomFOVToViewModel(bool in_isEnabled)
{
/* HACK: The mid-ASM hook is written in a function that is run
so frequently in-game that it can cause a crash if the
code is jumped to whilst still being written. */
if (Map.Contains("mainmenu"))
{
App.Settings.IsApplyCustomFOVToViewModelAvailable = true;
}
else
{
App.Settings.IsApplyCustomFOVToViewModelAvailable = false;
return;
}

var viewModelFOVHookAddr = Process.ToASLR(0x1415BBD7B);

if (in_isEnabled)
{
if (!_isApplyCustomFOVToViewModelInitialised)
{
_isApplyCustomFOVToViewModelInitialised = Process.TryWriteAsmHook
(
$@"
movss xmm7, xmm0
mov eax, 0x43160000 ; Store maximum FOV value (150.0f) in EAX.
movd xmm0, eax ; Copy EAX to XMM0.
mov rax, {(long)Process.ToASLR(0x14590E210)} ; Store address to FOV value in RAX.
movss xmm1, dword ptr [rax] ; Copy FOV value to XMM1.
movss xmm2, xmm0 ; XMM2 = _maxFOV
subss xmm2, xmm1 ; XMM2 = _maxFOV - FOV
mov eax, 0x42700000 ; Store minimum FOV value (60.0f) in EAX.
movd xmm1, eax ; Copy EAX to XMM1.
subss xmm0, xmm1 ; XMM0 = _maxFOV - _minFOV
divss xmm2, xmm0 ; XMM2 = (_maxFOV - FOV) / (_maxFOV - _minFOV)
mov eax, 0x3F800000 ; Store maximum weapon FOV value (1.0f) in EAX.
movd xmm0, eax ; Copy EAX to XMM0.
mov eax, 0x3ECCCCCD ; Store minimum weapon FOV value (0.4f) in EAX.
movd xmm1, eax ; Copy EAX to XMM1.
subss xmm0, xmm1 ; XMM0 = _maxWeaponFOV - _minWeaponFOV
mulss xmm2, xmm0 ; XMM2 = (_maxFOV - FOV) / (_maxFOV - _minFOV) * (_maxWeaponFOV - _minWeaponFOV)
addss xmm2, xmm1 ; XMM2 += _minWeaponFOV
mov rax, {(long)Process.ToASLR(0x144857858)} ; Store address to FOV zoom scalar value in RAX.
mulss xmm7, dword ptr [rax] ; Multiply FOV zoom scalar value with original weapon FOV value.
mulss xmm2, xmm7 ; Multiply both results to create the final weapon FOV value.
mov rax, {(long)Process.ToASLR(0x14485E558)} ; Store address to weapon FOV value in RAX.
movss dword ptr [rax], xmm2 ; Copy XMM2 to weapon FOV offset.
",

viewModelFOVHookAddr
);
}
}
else
{
Process.RemoveAsmHook(viewModelFOVHookAddr);

_isApplyCustomFOVToViewModelInitialised = false;
}
}

private unsafe void PatchCrosshairScaleMode(ECrosshairScaleMode in_mode)
{
/* HACK: The mid-ASM hook is written in a function that is run
Expand Down Expand Up @@ -376,6 +438,29 @@ code is jumped to whilst still being written. */

private void PatchDynamicAspectRatio(bool in_isEnabled)
{
if (App.Settings.IsAllowDynamicAspectRatioInGame)
{
App.Settings.IsDynamicAspectRatioAvailable = true;
}
else
{
/* HACK: Don't update aspect ratio unless we're on the main
menu where we can safely refresh the graphics device
without destroying the fast HUD font renderer.
The base game already forces you to quit out to the
main menu just to change the resolution anyway. */
if (Map.Contains("mainmenu"))
{
App.Settings.IsDynamicAspectRatioAvailable = true;
}
else
{
App.Settings.IsDynamicAspectRatioAvailable = false;
return;
}
}

var smartLinkAspectRatioHookAddr = Process.ToASLR(0x14162D4BC);

if (in_isEnabled)
Expand Down Expand Up @@ -403,39 +488,7 @@ private void PatchDynamicAspectRatio(bool in_isEnabled)
smartLinkAspectRatioHookAddr
);
}
}
else
{
Process.RemoveAsmHook(smartLinkAspectRatioHookAddr);

_isDynamicAspectRatioInitialised = false;
}

if (App.Settings.IsAllowDynamicAspectRatioInGame)
{
App.Settings.IsDynamicAspectRatioAvailable = true;
}
else
{
/* HACK: Don't update aspect ratio unless we're on the main
menu where we can safely refresh the graphics device
without destroying the fast HUD font renderer.
The base game already forces you to quit out to the
main menu just to change the resolution anyway. */
if (Map.Contains("mainmenu"))
{
App.Settings.IsDynamicAspectRatioAvailable = true;
}
else
{
App.Settings.IsDynamicAspectRatioAvailable = false;
return;
}
}

if (in_isEnabled)
{
var newAspectRatio = (float)DisplayParameters.WindowWidth / (float)DisplayParameters.WindowHeight;

if (IsResolutionScaleUpdated)
Expand Down Expand Up @@ -468,6 +521,10 @@ main menu just to change the resolution anyway. */
}
else
{
Process.RemoveAsmHook(smartLinkAspectRatioHookAddr);

_isDynamicAspectRatioInitialised = false;

if (AspectRatio == _defaultAspectRatio)
return;

Expand Down Expand Up @@ -567,6 +624,7 @@ public void InstallPatches()
return;

PatchApplyCustomFOVToVehicles(App.Settings.IsApplyCustomFOVToVehicles);
PatchApplyCustomFOVToViewModel(App.Settings.IsApplyCustomFOVToViewModel);
PatchCrosshairScaleMode((ECrosshairScaleMode)App.Settings.CrosshairScaleMode);
PatchDynamicAspectRatio(App.Settings.IsDynamicAspectRatio);
PatchNetworkIntegrity(FPS > 60);
Expand Down Expand Up @@ -604,6 +662,7 @@ public void UninstallPatches()
_isUpdating = false;

PatchApplyCustomFOVToVehicles(false);
PatchApplyCustomFOVToViewModel(false);
PatchCrosshairScaleMode(ECrosshairScaleMode.Default);
PatchDynamicAspectRatio(false);
PatchNetworkIntegrity(false);
Expand Down
10 changes: 7 additions & 3 deletions Ausar/UI/Trainer.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
<StackPanel Margin="23,65,0,10">

<StackPanel Margin="0,5,0,20">
<au:HorizontalFieldLabel Caption="Crosshair Scale Mode" Description="Determines how the crosshair will scale to this value (only accessible from main menu)."/>
<au:HorizontalFieldLabel Caption="Crosshair Scale Mode" Description="Determines how the crosshair will scale to this value (only accessible at the main menu)."/>
<ComboBox Name="CrosshairScaleModeField" HorizontalAlignment="Stretch"
IsEnabled="{Binding Source={x:Static local:App.Settings}, Path=IsCrosshairScaleModeAvailable}"
SelectedIndex="{Binding Mode=TwoWay, Source={x:Static local:App.Settings}, Path=CrosshairScaleMode}">
Expand All @@ -71,14 +71,18 @@
</ComboBox>
</StackPanel>

<au:DescribedCheckBox Content="Apply Custom FOV to Vehicles" Description="Determines whether to use this value for the vehicle camera."
<au:DescribedCheckBox Content="Apply FOV to Vehicles" Description="Use this value for the vehicle camera."
IsChecked="{Binding Mode=TwoWay, Source={x:Static local:App.Settings}, Path=IsApplyCustomFOVToVehicles}"/>

<au:DescribedCheckBox Content="Apply FOV to View Model" Description="Use this value for correcting the view model (recommended for high FOV)."
IsEnabled="{Binding Source={x:Static local:App.Settings}, Path=IsApplyCustomFOVToViewModelAvailable}"
IsChecked="{Binding Mode=TwoWay, Source={x:Static local:App.Settings}, Path=IsApplyCustomFOVToViewModel}"/>

</StackPanel>
</Expander>

<StackPanel Margin="24,0,0,20">
<au:HorizontalFieldLabel Caption="FOV" Description="The desired field of view (recommended 110 FOV max to prevent view model clipping)."/>
<au:HorizontalFieldLabel Caption="FOV" Description="The desired field of view."/>
<ui:NumberBox Value="{Binding Mode=TwoWay, Source={x:Static local:App.Settings}, Path=FOV}"
Minimum="60" Maximum="150" SpinButtonPlacementMode="Inline"/>
</StackPanel>
Expand Down
2 changes: 2 additions & 0 deletions Ausar/UI/Trainer.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ protected override void OnSourceInitialized(EventArgs e)
protected override void OnClosing(CancelEventArgs e)
{
if (!App.Settings.IsCrosshairScaleModeAvailable ||
!App.Settings.IsApplyCustomFOVToViewModelAvailable ||
!App.Settings.IsDynamicAspectRatioAvailable)
{
var result = MessageBox.Show
Expand Down Expand Up @@ -150,6 +151,7 @@ private async void OnProcessFound(Process in_process)
private void OnProcessWait()
{
App.Settings.IsCrosshairScaleModeAvailable = true;
App.Settings.IsApplyCustomFOVToViewModelAvailable = true;
App.Settings.IsDynamicAspectRatioAvailable = true;
App.Settings.ResolutionString = string.Empty;

Expand Down

0 comments on commit a759779

Please sign in to comment.