Progressive Update

21Feb240200Z
This commit is contained in:
ResetXPDR 2024-02-21 14:45:40 +11:00
parent 00f2a158f7
commit 311170593a
8 changed files with 218 additions and 254 deletions

4
.editorconfig Normal file
View File

@ -0,0 +1,4 @@
[*.cs]
# SYSLIB0014: Type or member is obsolete
dotnet_diagnostic.SYSLIB0014.severity = silent

View File

@ -7,6 +7,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MSFS2020_AutoFPS", "MSFS202
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Installer", "Installer\Installer.csproj", "{BF3DD08A-7547-4352-B1DD-9A343D757421}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{56EEBD53-3FD4-47E2-B099-27299C687467}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU

View File

@ -6,6 +6,7 @@ using System.Drawing.Printing;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using System.Windows.Media.Media3D;
namespace MSFS2020_AutoFPS
{
@ -22,8 +23,6 @@ namespace MSFS2020_AutoFPS
private float tlod = 0;
private int cloudQ = 0;
private int cloudQ_VR = 0;
private int fpsModeTicks = 0;
private int fpsModeDelayTicks = 0;
private float vs;
public LODController(ServiceModel model)
@ -36,26 +35,17 @@ namespace MSFS2020_AutoFPS
SimConnect.SubscribeSimVar("PLANE ALT ABOVE GROUND MINUS CG", "feet");
SimConnect.SubscribeSimVar("SIM ON GROUND", "Bool");
SimConnect.SubscribeSimVar("GROUND VELOCITY", "knots");
tlod = Model.MemoryAccess.GetTLOD_PC();
cloudQ = Model.MemoryAccess.GetCloudQ_PC();
cloudQ_VR = Model.MemoryAccess.GetCloudQ_VR();
if (cloudQ > Model.DefaultCloudQ) Model.DefaultCloudQ = cloudQ;
if (cloudQ_VR > Model.DefaultCloudQ_VR) Model.DefaultCloudQ_VR = cloudQ_VR;
Model.CurrentPairTLOD = 0;
Model.CurrentPairOLOD = 0;
Model.fpsMode = false;
Model.tlod_step = false;
Model.olod_step = false;
}
GetMSFSState();
}
private void UpdateVariables()
private void UpdateVariables()
{
vs = SimConnect.ReadSimVar("VERTICAL SPEED", "feet per second");
Model.OnGround = SimConnect.ReadSimVar("SIM ON GROUND", "Bool") == 1.0f;
verticalStatsVS[verticalIndex] = vs;
if (vs >= 8.0f)
if (vs >= 4.0f)
verticalStats[verticalIndex] = 1;
else if (vs <= -8.0f)
else if (vs <= -4.0f)
verticalStats[verticalIndex] = -1;
else
verticalStats[verticalIndex] = 0;
@ -71,94 +61,97 @@ namespace MSFS2020_AutoFPS
altAboveGnd = (int)SimConnect.ReadSimVar("PLANE ALT ABOVE GROUND MINUS CG", "feet");
groundSpeed = (int)SimConnect.ReadSimVar("GROUND VELOCITY", "knots");
tlod = Model.MemoryAccess.GetTLOD_PC();
cloudQ = Model.MemoryAccess.GetCloudQ_PC();
cloudQ_VR = Model.MemoryAccess.GetCloudQ_VR();
GetMSFSState();
}
public void RunTick()
{
UpdateVariables();
int FPSTolerance;
bool TLODMinGndLanding;
bool DecCloudQ;
float MinTLOD;
float MaxTLOD;
float newTLOD;
float CloudRecoveryTLOD;
if (Model.UseExpertOptions)
if (!(!Model.ActiveWindowMSFS && (!Model.UseExpertOptions || Model.PauseMSFSFocusLost)) && Model.FPSSettleCounter == 0)
{
FPSTolerance = Model.FPSTolerance;
TLODMinGndLanding = Model.TLODMinGndLanding;
MinTLOD = Model.MinTLOD;
MaxTLOD = Model.MaxTLOD;
DecCloudQ = Model.DecCloudQ;
CloudRecoveryTLOD = Model.CloudRecoveryTLOD;
}
else
{
FPSTolerance = 5;
TLODMinGndLanding = false;
if (Model.MemoryAccess.IsVrModeActive())
bool TLODMinGndLanding;
bool DecCloudQ;
float FPSTolerance;
float TLODStep;
float MinTLOD;
float MaxTLOD;
float newTLOD;
float CloudRecoveryTLOD;
if (Model.UseExpertOptions)
{
MinTLOD = Math.Max(Model.DefaultTLOD_VR * 0.5f, 10);
MaxTLOD = Model.DefaultTLOD_VR * 2.0f;
FPSTolerance = (float)Model.FPSTolerance;
TLODMinGndLanding = Model.TLODMinGndLanding;
MinTLOD = Model.MinTLOD;
MaxTLOD = Model.MaxTLOD;
DecCloudQ = Model.DecCloudQ;
CloudRecoveryTLOD = Model.CloudRecoveryTLOD;
}
else
{
MinTLOD = Math.Max(Model.DefaultTLOD * 0.5f, 10);
MaxTLOD = Model.DefaultTLOD * 2.0f;
FPSTolerance = 5.0f;
TLODMinGndLanding = false;
if (Model.VrModeActive)
{
MinTLOD = Math.Max(Model.DefaultTLOD_VR * 0.5f, 10.0f);
MaxTLOD = Model.DefaultTLOD_VR * 2.0f;
}
else
{
MinTLOD = Math.Max(Model.DefaultTLOD * 0.5f, 10.0f);
MaxTLOD = Model.DefaultTLOD * 2.0f;
}
DecCloudQ = true;
CloudRecoveryTLOD = Model.DefaultTLOD - 1;
}
DecCloudQ = true;
CloudRecoveryTLOD = Model.DefaultTLOD - 1;
}
if ((!Model.UseExpertOptions || Model.TLODMinGndLanding) && altAboveGnd < 2000 && (VSAverage() <= 0 || Model.OnGround)) Model.IsAppPriorityFPS = false;
else Model.IsAppPriorityFPS = true;
float deltaFPS = GetAverageFPS() - Model.TargetFPS;
if (Math.Abs(deltaFPS) >= Model.TargetFPS * FPSTolerance / 100 || (TLODMinGndLanding && altAboveGnd < 2000))
{
if (TLODMinGndLanding)
TLODStep = Math.Max(2.0f, FPSTolerance);
if (!Model.UseExpertOptions || !Model.TLODMinGndLanding || altAboveGnd >= 2000 || (VerticalAverage() >= 3 && !Model.OnGround)) Model.IsAppPriorityFPS = true;
else Model.IsAppPriorityFPS = false;
float deltaFPS = GetAverageFPS() - Model.TargetFPS;
if (Math.Abs(deltaFPS) >= Model.TargetFPS * FPSTolerance / 100 || (TLODMinGndLanding && altAboveGnd < 2000))
{
if ((VSAverage() <= 0 || Model.OnGround) && altAboveGnd < 2000) newTLOD = tlod + (altAboveGnd - 1000 > 0 ? (tlod - MinTLOD) / (altAboveGnd - 1000) * VSAverage(): MinTLOD - tlod);
else newTLOD = tlod + (!Model.OnGround ? Math.Sign(deltaFPS) * FPSTolerance * (Math.Abs(deltaFPS) >= Model.TargetFPS * 2 * FPSTolerance / 100 ? 2 : 1) * (altAboveGnd < 1000 && !Model.OnGround ? (float)altAboveGnd / 1000 : 1) : 0);
if (TLODMinGndLanding)
{
if ((VerticalAverage() <= -3 || Model.OnGround) && altAboveGnd < 2000) newTLOD = tlod + (altAboveGnd - 1000 > 0 ? Math.Max((tlod - MinTLOD) / (altAboveGnd - 1000) * VSAverage(), -20) : (Model.OnGround ? MinTLOD - tlod : -20));
else newTLOD = tlod + (!Model.OnGround ? Math.Sign(deltaFPS) * TLODStep * (Math.Abs(deltaFPS) >= Model.TargetFPS * 2 * FPSTolerance / 100 ? 2 : 1) * (altAboveGnd < 1000 && !Model.OnGround && VerticalAverage() >= 3 ? (float)altAboveGnd / 1000 : (altAboveGnd > 1000 ? 1 : -1)) * (altAboveGnd < 100 ? 0 : 1) : 0);
}
else
newTLOD = tlod + Math.Sign(deltaFPS) * (Model.OnGround && groundSpeed > 1 ? 2 : TLODStep * (Math.Abs(deltaFPS) >= Model.TargetFPS * 2 * FPSTolerance / 100 && (groundSpeed < 1 || !Model.OnGround) ? 2 : 1) * (altAboveGnd < 1000 && !Model.OnGround ? (float)altAboveGnd / 1000 : 1));
newTLOD = (float)Math.Round(Math.Min(MaxTLOD, Math.Max(MinTLOD, newTLOD)));
if (Math.Abs(tlod - newTLOD) >= 1)
{
Model.MemoryAccess.SetTLOD(newTLOD);
Model.tlod_step = true;
}
else Model.tlod_step = false;
if (DecCloudQ && newTLOD == MinTLOD && ((!TLODMinGndLanding && Model.tlod_step) || (TLODMinGndLanding && deltaFPS <= -Model.TargetFPS * FPSTolerance / 100)))
{
if (Model.VrModeActive && Model.DefaultCloudQ_VR >= 1)
{
Model.MemoryAccess.SetCloudQ_VR(Model.DefaultCloudQ_VR - 1);
Model.DecCloudQActive = true;
}
if (!Model.VrModeActive && Model.DefaultCloudQ >= 1)
{
Model.MemoryAccess.SetCloudQ(Model.DefaultCloudQ - 1);
Model.DecCloudQActive = true;
}
}
if (DecCloudQ && Model.DecCloudQActive && ((!TLODMinGndLanding && newTLOD >= CloudRecoveryTLOD && Model.tlod_step) || (TLODMinGndLanding && deltaFPS >= Model.TargetFPS * FPSTolerance / 100)))
{
if (Model.VrModeActive) Model.MemoryAccess.SetCloudQ_VR(Model.DefaultCloudQ_VR);
else Model.MemoryAccess.SetCloudQ(Model.DefaultCloudQ);
Model.DecCloudQActive = false;
}
}
else
newTLOD = tlod + Math.Sign(deltaFPS) * (Model.OnGround && groundSpeed > 1 ? 1 : FPSTolerance * (Math.Abs(deltaFPS) >= Model.TargetFPS * 2 * FPSTolerance / 100 && (groundSpeed < 1 || !Model.OnGround) ? 2 : 1) * (altAboveGnd < 1000 && !Model.OnGround ? (float)altAboveGnd / 1000 : 1));
newTLOD = (float)Math.Round(Math.Min(MaxTLOD, Math.Max(MinTLOD, newTLOD)));
if (Math.Abs(tlod - newTLOD) >= 1)
{
Model.MemoryAccess.SetTLOD(newTLOD);
Model.tlod_step = true;
}
else Model.tlod_step = false;
if (DecCloudQ && newTLOD == MinTLOD && ((!TLODMinGndLanding && Model.tlod_step) || (TLODMinGndLanding && deltaFPS <= -Model.TargetFPS * FPSTolerance / 100)))
{
if (Model.MemoryAccess.IsVrModeActive() && Model.DefaultCloudQ_VR >= 1)
{
Model.MemoryAccess.SetCloudQ_VR(Model.DefaultCloudQ_VR - 1);
Model.DecCloudQActive = true;
}
if (!Model.MemoryAccess.IsVrModeActive() && Model.DefaultCloudQ >= 1)
{
Model.MemoryAccess.SetCloudQ(Model.DefaultCloudQ - 1);
Model.DecCloudQActive = true;
}
}
if (DecCloudQ && Model.DecCloudQActive && ((!TLODMinGndLanding && newTLOD >= CloudRecoveryTLOD && Model.tlod_step) || (TLODMinGndLanding && deltaFPS >= Model.TargetFPS * FPSTolerance / 100)))
{
if (Model.MemoryAccess.IsVrModeActive()) Model.MemoryAccess.SetCloudQ_VR(Model.DefaultCloudQ_VR);
else Model.MemoryAccess.SetCloudQ(Model.DefaultCloudQ);
Model.DecCloudQActive = false;
Model.tlod_step = false;
Model.olod_step = false;
}
}
else
{
Model.tlod_step = false;
Model.olod_step = false;
}
}
else if (--Model.FPSSettleCounter < 0) Model.FPSSettleCounter = 0;
}
public int VerticalAverage()
{
return verticalStats.Sum();
@ -170,10 +163,41 @@ namespace MSFS2020_AutoFPS
public float GetAverageFPS()
{
if (Model.MemoryAccess.IsFgModeActive())
if (Model.FgModeActive)
return (float)Math.Round(IPCManager.SimConnect.GetAverageFPS() * 2.0f);
else
return (float)Math.Round(IPCManager.SimConnect.GetAverageFPS());
}
private void GetMSFSState()
{
tlod = Model.tlod = Model.MemoryAccess.GetTLOD_PC();
cloudQ = Model.cloudQ = Model.MemoryAccess.GetCloudQ_PC();
cloudQ_VR = Model.cloudQ_VR = Model.MemoryAccess.GetCloudQ_VR();
Model.VrModeActive = Model.MemoryAccess.IsVrModeActive();
Model.FgModeActive = Model.MemoryAccess.IsFgModeActive();
if (Model.ActiveWindowMSFS != Model.MemoryAccess.IsActiveWindowMSFS() && (!Model.UseExpertOptions || Model.PauseMSFSFocusLost)) Model.FPSSettleCounter = ServiceModel.FPSSettleSeconds;
Model.ActiveWindowMSFS = Model.MemoryAccess.IsActiveWindowMSFS();
string ActiveGraphicsMode = Model.ActiveGraphicsMode;
if (Model.VrModeActive)
{
Model.ActiveGraphicsMode = "VR";
Model.TargetFPS = Model.TargetFPS_VR;
}
else if (Model.FgModeActive)
{
Model.ActiveGraphicsMode = "FG";
Model.TargetFPS = Model.TargetFPS_FG;
}
else
{
Model.ActiveGraphicsMode = "PC";
Model.TargetFPS = Model.TargetFPS_PC;
}
if (Model.ActiveGraphicsMode != ActiveGraphicsMode)
{
Model.FPSSettleCounter = ServiceModel.FPSSettleSeconds;
Model.ActiveGraphicsModeChanged = true;
}
}
}
}

View File

@ -13,34 +13,17 @@
<add key="offsetPointerTlod" value="0xC" />
<add key="offsetPointerTlodVr" value="0x114" />
<add key="offsetPointerOlod" value="0xC" />
<add key="offsetPointerCloudQ" value="0x44" />
<add key="offsetPointerCloudQVr" value="0x108" />
<add key="offsetPointerVrMode" value="0x1C" />
<add key="offsetPointerFgMode" value="0x4A" />
<add key="simMinLod" value="10" />
<add key="selectedProfile" value="0" />
<add key="tlodPairs0" value="0:100|1500:150|5000:200" />
<add key="olodPairs0" value="0:100|2500:150|7500:200" />
<add key="isVr0" value="false" />
<add key="tlodPairs1" value="0:100|500:125|2000:150|7500:175|15000:200|20000:225" />
<add key="olodPairs1" value="0:100|500:125|2500:150|5000:175|9500:200" />
<add key="isVr1" value="false" />
<add key="tlodPairs2" value="0:100|1500:150|5000:200" />
<add key="olodPairs2" value="0:100|2500:150|7500:200" />
<add key="isVr2" value="true" />
<add key="tlodPairs3" value="0:100|1000:150|2000:200|3000:250|4000:300" />
<add key="olodPairs3" value="0:100|1000:70|2000:50|3000:30|4000:10" />
<add key="tlodPairs4" value="0:100|1000:200|2000:300|3000:400" />
<add key="olodPairs4" value="0:200|1000:150|2000:100|3000:50" />
<add key="tlodPairs5" value="0:100|1500:150|5000:200" />
<add key="olodPairs5" value="0:100|2500:150|7500:200" />
<add key="useExpertOptions" value="false" />
<add key="targetFps" value="40" />
<add key="FpsTolerance" value="5" />
<add key="minLod" value="100" />
<add key="DecCloudQ" value="true" />
<add key="TLODMinGndLanding" value="false" />
<add key="CloudRecoveryTLOD" value="100" />
<add key="minTLod" value="50" />
<add key="maxTLod" value="200" />
<add key="offsetPointerCloudQ" value="0x44" />
<add key="offsetPointerCloudQVr" value="0x108" />
<add key="offsetPointerVrMode" value="0x1C" />
<add key="offsetPointerFgMode" value="0x4A" />
</appSettings>

View File

@ -87,11 +87,11 @@
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="369*"/>
<ColumnDefinition Width="369*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="6*"/>
<RowDefinition Height="29*"/>
<RowDefinition Height="29*"/>
<RowDefinition Height="33.96"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Margin="0,0,0,34" Grid.RowSpan="2"/>
@ -99,18 +99,16 @@
<Label Name="lblTargetFPS" Content="Target FPS" MinWidth="100"/>
<TextBox x:Name="txtTargetFPS" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Height="24" MaxHeight="24" MinHeight="24" Width="42" LostFocus="TextBox_LostFocus" KeyUp="TextBox_KeyUp" Margin="0,0,30,0"/>
</StackPanel>
<StackPanel Grid.Row="1" Grid.Column="1" Orientation="Horizontal" Margin="0,8,0,0" Grid.ColumnSpan="2">
<CheckBox Name="chkUseExpertOptions" VerticalContentAlignment="Center" Height="24" MaxHeight="24" MinHeight="24" Click="chkUseExpertOptions_Click">Use Expert Options</CheckBox>
</StackPanel>
<StackPanel Grid.Row="2" Grid.Column="0" Orientation="Horizontal" Margin="0,8,0,0">
<CheckBox Name="chkUseExpertOptions" VerticalContentAlignment="Center" Width="170" Height="24" MaxHeight="24" MinHeight="24" Click="chkUseExpertOptions_Click" Margin="5,0,0,0">Use Expert Options</CheckBox>
<CheckBox x:Name="chkOpenWindow" VerticalContentAlignment="Center" Click="chkOpenWindow_Click" Content="Open Window on App Start" Height="15" Width="220"/>
</StackPanel>
<StackPanel Grid.Row="3" Grid.Column="0" Orientation="Horizontal" Margin="0,8,0,0">
<Label Name="lblStatusMessage" MinWidth="50" VerticalContentAlignment="Center" Content=""/>
<TextBlock x:Name="lblappUrl" VerticalAlignment="Center"> <Hyperlink NavigateUri="https://github.com/ResetXPDR/MSFS_AutoLOD/releases/latest" RequestNavigate="Hyperlink_RequestNavigate">
here</Hyperlink>
</TextBlock>
</StackPanel>
<StackPanel Grid.Row="2" Grid.Column="1" Orientation="Horizontal" Margin="0,8,0,0">
<CheckBox x:Name="chkOpenWindow" VerticalContentAlignment="Center" Click="chkOpenWindow_Click" Content="Open Window on App Start" Height="15" Width="220"/>
</StackPanel>
</Grid>
</GroupBox>
</StackPanel>
@ -139,18 +137,14 @@
<Label Content="TLOD Maximum" MinWidth="100"/>
<TextBox x:Name="txtMaxTLod" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Height="24" MaxHeight="24" MinHeight="24" Width="42" LostFocus="TextBox_LostFocus" KeyUp="TextBox_KeyUp" Margin="5,0,0,0"/>
</StackPanel>
<StackPanel Grid.Row="1" Grid.Column="0" Orientation="Horizontal" Margin="0,2,0,0" Visibility="Collapsed">
<Label Name="lblLodStepMax" VerticalContentAlignment="Center" Width ="96" Padding="5,5,0,5">TLOD Steps</Label>
<TextBox Name="txtLodStepMaxInc" Margin="4,0,0,0" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Height="24" MaxHeight="24" MinHeight="24" Width="42" LostFocus="TextBox_LostFocus" KeyUp="TextBox_KeyUp" TextChanged="txtLodStepMaxInc_TextChanged"></TextBox>
<Label VerticalContentAlignment="Center" Width ="133" Padding="5,5,0,5">Up</Label>
<TextBox x:Name="txtLodStepMaxDec" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Height="24" MaxHeight="24" MinHeight="24" Width="42" LostFocus="TextBox_LostFocus" KeyUp="TextBox_KeyUp" TextChanged="txtLodStepMaxDec_TextChanged" Margin="2,0,5,0"/>
<Label VerticalContentAlignment="Center" Padding="5,5,0,5">Down</Label>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,2,0,0">
<CheckBox x:Name="chkDecCloudQ" VerticalContentAlignment="Center" Click="chkDecCloudQ_Click" Width="152" Content="Decrease Cloud Quality" Checked="chkDecCloudQ_Checked" Padding="4,0,0,0"/>
<Label Name= "lblCloudRecoveryTLOD" >Cloud Recovery TLOD</Label>
<TextBox Name="txtCloudRecoveryTLOD" Margin="1,0,0,0" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Height="24" MaxHeight="24" MinHeight="24" Width="42" LostFocus="TextBox_LostFocus" KeyUp="TextBox_KeyUp"></TextBox>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,2,0,0">
<CheckBox x:Name="chkPauseMSFSFocusLost" VerticalContentAlignment="Center" Click="chkPauseMSFSFocusLost_Click" Width="270" Content="Pause when MSFS loses focus" Checked="chkPauseMSFSFocusLost_Checked" Padding="4,0,0,0"/>
</StackPanel>
</StackPanel>
</Grid>

View File

@ -139,11 +139,15 @@ namespace MSFS2020_AutoFPS
{
chkOpenWindow.IsChecked = serviceModel.OpenWindow;
chkUseExpertOptions.IsChecked = serviceModel.UseExpertOptions;
txtTargetFPS.Text = Convert.ToString(serviceModel.TargetFPS, CultureInfo.CurrentUICulture);
if (serviceModel.ActiveGraphicsMode == "VR") txtTargetFPS.Text = Convert.ToString(serviceModel.TargetFPS_VR, CultureInfo.CurrentUICulture);
else if (serviceModel.ActiveGraphicsMode == "FG") txtTargetFPS.Text = Convert.ToString(serviceModel.TargetFPS_FG, CultureInfo.CurrentUICulture);
else txtTargetFPS.Text = Convert.ToString(serviceModel.TargetFPS_PC, CultureInfo.CurrentUICulture);
serviceModel.ActiveGraphicsModeChanged = false;
txtFPSTolerance.Text = Convert.ToString(serviceModel.FPSTolerance, CultureInfo.CurrentUICulture);
txtMinTLod.Text = Convert.ToString(serviceModel.MinTLOD, CultureInfo.CurrentUICulture);
txtMaxTLod.Text = Convert.ToString(serviceModel.MaxTLOD, CultureInfo.CurrentUICulture);
chkDecCloudQ.IsChecked = serviceModel.DecCloudQ;
chkPauseMSFSFocusLost.IsChecked = serviceModel.PauseMSFSFocusLost;
chkTLODMinGndLanding.IsChecked = serviceModel.TLODMinGndLanding;
txtCloudRecoveryTLOD.Text = Convert.ToString(serviceModel.CloudRecoveryTLOD, CultureInfo.CurrentUICulture);
}
@ -177,7 +181,7 @@ namespace MSFS2020_AutoFPS
protected float GetAverageFPS()
{
if (serviceModel.MemoryAccess != null && serviceModel.MemoryAccess.IsFgModeActive() && serviceModel.MemoryAccess.IsActiveWindowMSFS())
if (serviceModel.MemoryAccess != null && serviceModel.FgModeActive && serviceModel.ActiveWindowMSFS)
return IPCManager.SimConnect.GetAverageFPS() * 2.0f;
else
return IPCManager.SimConnect.GetAverageFPS();
@ -187,35 +191,38 @@ namespace MSFS2020_AutoFPS
if (IPCManager.SimConnect != null && IPCManager.SimConnect.IsConnected)
lblSimFPS.Content = GetAverageFPS().ToString("F0");
else
{
lblSimFPS.Content = "n/a";
lblSimFPS.Foreground = new SolidColorBrush(Colors.Black);
}
if (serviceModel.MemoryAccess != null)
{
lblappUrl.Visibility = Visibility.Hidden;
lblStatusMessage.Foreground = new SolidColorBrush(Colors.Black);
lblSimTLOD.Content = serviceModel.MemoryAccess.GetTLOD_PC().ToString("F0");
lblSimTLOD.Content = serviceModel.tlod.ToString("F0");
if (serviceModel.MemoryAccess.MemoryWritesAllowed())
{
lblStatusMessage.Content = serviceModel.MemoryAccess.IsDX12() ? "DX 12 | " : " DX11 | ";
lblStatusMessage.Content = serviceModel.MemoryAccess.IsDX12() ? "DX12" : " DX11";
if (serviceModel.IsAppPriorityFPS) lblAppPriority.Content = "FPS";
else lblAppPriority.Content = "TLOD Min";
if (serviceModel.MemoryAccess.IsVrModeActive())
if (serviceModel.VrModeActive)
{
//lblAppPriority.Content = serviceModel.MemoryAccess.GetOLOD_VR().ToString("F0");
lblSimCloudQs.Content = CloudQualityLabel(serviceModel.MemoryAccess.GetCloudQ_VR());
lblStatusMessage.Content += " VR Mode";
lblSimCloudQs.Content = CloudQualityLabel(serviceModel.cloudQ_VR);
lblStatusMessage.Content += " | VR Mode";
}
else
{
//lblAppPriority.Content = serviceModel.MemoryAccess.GetOLOD_PC().ToString("F0");
lblSimCloudQs.Content = CloudQualityLabel(serviceModel.MemoryAccess.GetCloudQ_PC());
lblStatusMessage.Content += " PC Mode";
lblStatusMessage.Content += (serviceModel.MemoryAccess.IsFgModeActive() ? (serviceModel.MemoryAccess.IsActiveWindowMSFS() ? " | FG Active" : " | FG Inactive") : "");
lblSimCloudQs.Content = CloudQualityLabel(serviceModel.cloudQ);
lblStatusMessage.Content += " | PC Mode";
lblStatusMessage.Content += (serviceModel.FgModeActive ? (serviceModel.ActiveWindowMSFS ? " | FG Active" : " | FG Inactive") : "");
}
if (!serviceModel.ActiveWindowMSFS && (!serviceModel.UseExpertOptions || serviceModel.PauseMSFSFocusLost)) lblStatusMessage.Content += " | Auto PAUSED";
else if (serviceModel.FPSSettleCounter > 0) lblStatusMessage.Content += " | FPS Settling for " + serviceModel.FPSSettleCounter.ToString("F0") + " second" + (serviceModel.FPSSettleCounter != 1 ? "s" : "");
}
else
{
lblStatusMessage.Content = "Incompatible MSFS version - Sim Values read only";
lblStatusMessage.Content = "Integrity test fail - Read only mode";
lblStatusMessage.Foreground = new SolidColorBrush(Colors.Red);
}
if (serviceModel.IsSessionRunning)
@ -229,7 +236,7 @@ namespace MSFS2020_AutoFPS
}
else
{
if (serviceModel.MemoryAccess.IsVrModeActive())
if (serviceModel.VrModeActive)
{
MinTLOD = Math.Max(serviceModel.DefaultTLOD_VR * 0.5f, 10);
MaxTLOD = serviceModel.DefaultTLOD_VR * 2.0f;
@ -241,16 +248,23 @@ namespace MSFS2020_AutoFPS
}
}
if (serviceModel.MemoryAccess.IsFgModeActive()) lblTargetFPS.Content = "Target FG FPS";
else lblTargetFPS.Content = "Target FPS";
if (GetAverageFPS() < serviceModel.TargetFPS && serviceModel.MemoryAccess.GetTLOD_PC() == MinTLOD)
lblSimFPS.Foreground = new SolidColorBrush(Colors.Red);
else if (GetAverageFPS() > serviceModel.TargetFPS && serviceModel.MemoryAccess.GetTLOD_PC() == MaxTLOD)
lblSimFPS.Foreground = new SolidColorBrush(Colors.DarkGreen);
else lblSimFPS.Foreground = new SolidColorBrush(Colors.Black);
if (serviceModel.MemoryAccess.GetTLOD_PC() == MinTLOD) lblSimTLOD.Foreground = new SolidColorBrush(Colors.Red);
else if (serviceModel.MemoryAccess.GetTLOD_PC() == MaxTLOD) lblSimTLOD.Foreground = new SolidColorBrush(Colors.Green);
lblTargetFPS.Content = "Target " + serviceModel.ActiveGraphicsMode + " FPS";
if (serviceModel.ActiveGraphicsModeChanged) LoadSettings();
float ToleranceFPS = serviceModel.TargetFPS * (serviceModel.UseExpertOptions ? serviceModel.FPSTolerance : 5.0f) / 100.0f;
if (serviceModel.TLODMinGndLanding)
{
if (GetAverageFPS() < serviceModel.TargetFPS - ToleranceFPS) lblSimFPS.Foreground = new SolidColorBrush(Colors.Red);
else if (GetAverageFPS() > serviceModel.TargetFPS + ToleranceFPS) lblSimFPS.Foreground = new SolidColorBrush(Colors.Green);
else lblSimFPS.Foreground = new SolidColorBrush(Colors.Black);
}
else
{
if (GetAverageFPS() < serviceModel.TargetFPS - ToleranceFPS && serviceModel.tlod == MinTLOD) lblSimFPS.Foreground = new SolidColorBrush(Colors.Red);
else if (Math.Abs(GetAverageFPS() - serviceModel.TargetFPS) <= ToleranceFPS) lblSimFPS.Foreground = new SolidColorBrush(Colors.Green);
else lblSimFPS.Foreground = new SolidColorBrush(Colors.Black);
}
if (serviceModel.tlod == MinTLOD && (!serviceModel.TLODMinGndLanding || GetAverageFPS() < serviceModel.TargetFPS)) lblSimTLOD.Foreground = new SolidColorBrush(Colors.Red);
else if ((!serviceModel.TLODMinGndLanding && serviceModel.tlod == MaxTLOD) || (serviceModel.TLODMinGndLanding && serviceModel.tlod == MinTLOD && GetAverageFPS() > serviceModel.TargetFPS)) lblSimTLOD.Foreground = new SolidColorBrush(Colors.Green);
else if (serviceModel.tlod_step) lblSimTLOD.Foreground = new SolidColorBrush(Colors.Orange);
else lblSimTLOD.Foreground = new SolidColorBrush(Colors.Black);
if (serviceModel.DecCloudQ && serviceModel.DecCloudQActive) lblSimCloudQs.Foreground = new SolidColorBrush(Colors.Red);
@ -261,8 +275,11 @@ namespace MSFS2020_AutoFPS
else
{
lblSimTLOD.Content = "n/a";
lblSimTLOD.Foreground = new SolidColorBrush(Colors.Black);
lblAppPriority.Content = "n/a";
lblSimCloudQs.Content = "n/a";
lblSimCloudQs.Foreground = new SolidColorBrush(Colors.Black);
lblSimFPS.Foreground = new SolidColorBrush(Colors.Black);
}
}
@ -273,20 +290,11 @@ namespace MSFS2020_AutoFPS
var simConnect = IPCManager.SimConnect;
lblPlaneAGL.Content = simConnect.ReadSimVar("PLANE ALT ABOVE GROUND", "feet").ToString("F0");
lblPlaneVS.Content = (simConnect.ReadSimVar("VERTICAL SPEED", "feet per second") * 60.0f).ToString("F0");
//if (serviceModel.OnGround)
// lblVSTrend.Content = "Ground";
//else if (serviceModel.VerticalTrend > 0)
// lblVSTrend.Content = "Climb";
//else if (serviceModel.VerticalTrend < 0)
// lblVSTrend.Content = "Descent";
//else
// lblVSTrend.Content = "Cruise";
}
else
{
lblPlaneAGL.Content = "n/a";
lblPlaneVS.Content = "n/a";
//lblVSTrend.Content = "n/a";
}
}
@ -341,7 +349,14 @@ namespace MSFS2020_AutoFPS
private void chkDecCloudQ_Click(object sender, RoutedEventArgs e)
{
serviceModel.SetSetting("DecCloudQ", chkDecCloudQ.IsChecked.ToString().ToLower());
LoadSettings();
LoadSettings();
chkCloudRecoveryTLOD_WindowVisibility();
}
private void chkPauseMSFSFocusLost_Click(object sender, RoutedEventArgs e)
{
serviceModel.SetSetting("PauseMSFSFocusLost", chkPauseMSFSFocusLost.IsChecked.ToString().ToLower());
LoadSettings();
chkCloudRecoveryTLOD_WindowVisibility();
}
@ -386,14 +401,6 @@ namespace MSFS2020_AutoFPS
case "txtMaxTLod":
key = "maxTLod";
break;
//case "txtLodStepMaxInc":
// key = "LodStepMaxInc";
// intValue = true;
// break;
//case "txtLodStepMaxDec":
// key = "LodStepMaxDec";
// intValue = true;
// break;
default:
key = "";
break;
@ -410,6 +417,9 @@ namespace MSFS2020_AutoFPS
{
case "targetFps":
if (iValue < 10 || iValue > 200) iValue = serviceModel.TargetFPS;
if (serviceModel.ActiveGraphicsMode == "VR") key = "targetFpsVR";
else if (serviceModel.ActiveGraphicsMode == "FG") key = "targetFpsFG";
else key = "targetFpsPC";
break;
case "FpsTolerance":
if (iValue > 20) iValue = serviceModel.FPSTolerance;
@ -459,6 +469,11 @@ namespace MSFS2020_AutoFPS
private void chkDecCloudQ_Checked(object sender, RoutedEventArgs e)
{
}
private void chkPauseMSFSFocusLost_Checked(object sender, RoutedEventArgs e)
{
}
private void chkTLODMinGndLanding_Checked(object sender, RoutedEventArgs e)
{

View File

@ -18,34 +18,34 @@ namespace MSFS2020_AutoFPS
public MemoryManager MemoryAccess { get; set; } = null;
public int VerticalTrend { get; set; }
public float AltLead { get; set; }
public bool OnGround { get; set; } = true;
public bool ForceEvaluation { get; set; } = false;
public float tlod { get; set; } = 0;
public int cloudQ { get; set; }
public int cloudQ_VR { get; set; }
public bool VrModeActive { get; set; }
public bool ActiveWindowMSFS { get; set; }
public int SelectedProfile { get; set; } = 0;
public List<List<(float, float)>> PairsTLOD { get; set; }
public int CurrentPairTLOD;
public List<List<(float, float)>> PairsOLOD { get; set; }
public int CurrentPairOLOD;
public bool fpsMode { get; set; }
public const int FPSSettleSeconds = 6;
public int FPSSettleCounter { get; set; } = FPSSettleSeconds;
public string ActiveGraphicsMode { get; set; } = "PC";
public bool ActiveGraphicsModeChanged { get; set; } = false;
public bool FgModeActive { get; set; }
public bool UseExpertOptions { get; set; }
public bool IsAppPriorityFPS { get; set; } = true;
public int TargetFPS { get; set; }
public int TargetFPS_PC { get; set; }
public int TargetFPS_VR { get; set; }
public int TargetFPS_FG { get; set; }
public int FPSTolerance { get; set; }
public int CloudRecoveryTLOD { get; set; }
public bool DecCloudQActive { get; set; }
public bool PauseMSFSFocusLost { get; set; } = true;
public bool TLODMinGndLanding { get; set; }
public int ConstraintTicks { get; set; }
public int ConstraintDelayTicks { get; set; }
public float DecreaseTLOD { get; set; }
public float DecreaseOLOD { get; set; }
public float MinTLOD { get; set; }
public float MaxTLOD { get; set; }
public float SimMinLOD { get; set; }
public float DefaultTLOD { get; set; } = 100;
public float DefaultTLOD_VR { get; set; } = 100;
public float DefaultOLOD { get; set; } = 100;
public float DefaultOLOD_VR { get; set; } = 100;
public int DefaultCloudQ { get; set; } = 2;
public int DefaultCloudQ_VR { get; set; } = 2;
public bool DefaultSettingsRead { get; set; } = false;
@ -78,8 +78,6 @@ namespace MSFS2020_AutoFPS
public ServiceModel()
{
CurrentPairTLOD = 0;
CurrentPairOLOD = 0;
LoadConfiguration();
}
@ -98,17 +96,15 @@ namespace MSFS2020_AutoFPS
SimBinary = Convert.ToString(ConfigurationFile.GetSetting("simBinary", "FlightSimulator"));
SimModule = Convert.ToString(ConfigurationFile.GetSetting("simModule", "WwiseLibPCx64P.dll"));
UseExpertOptions = Convert.ToBoolean(ConfigurationFile.GetSetting("useExpertOptions", "false"));
PauseMSFSFocusLost = Convert.ToBoolean(ConfigurationFile.GetSetting("PauseMSFSFocusLost", "true"));
TargetFPS = Convert.ToInt32(ConfigurationFile.GetSetting("targetFps", "40"));
TargetFPS_PC = Convert.ToInt32(ConfigurationFile.GetSetting("targetFpsPC", "40"));
TargetFPS_VR = Convert.ToInt32(ConfigurationFile.GetSetting("targetFpsVR", "40"));
TargetFPS_FG = Convert.ToInt32(ConfigurationFile.GetSetting("targetFpsFG", "40"));
FPSTolerance = Convert.ToInt32(ConfigurationFile.GetSetting("FpsTolerance", "5"));
CloudRecoveryTLOD = Convert.ToInt32(ConfigurationFile.GetSetting("CloudRecoveryTLOD", "100"));
ConstraintTicks = Convert.ToInt32(ConfigurationFile.GetSetting("constraintTicks", "60"));
ConstraintDelayTicks = Convert.ToInt32(ConfigurationFile.GetSetting("constraintDelayTicks", "1"));
DecreaseTLOD = Convert.ToSingle(ConfigurationFile.GetSetting("decreaseTlod", "50"), new RealInvariantFormat(ConfigurationFile.GetSetting("decreaseTlod", "50")));
DecreaseOLOD = Convert.ToSingle(ConfigurationFile.GetSetting("decreaseOlod", "50"), new RealInvariantFormat(ConfigurationFile.GetSetting("decreaseOlod", "50")));
MinTLOD = Convert.ToSingle(ConfigurationFile.GetSetting("minTLod", "50"), new RealInvariantFormat(ConfigurationFile.GetSetting("minTLod", "50")));
MaxTLOD = Convert.ToSingle(ConfigurationFile.GetSetting("maxTLod", "200"), new RealInvariantFormat(ConfigurationFile.GetSetting("maxTLod", "200")));
LodStepMaxInc = Convert.ToInt32(ConfigurationFile.GetSetting("LodStepMaxInc", "5"));
LodStepMaxDec = Convert.ToInt32(ConfigurationFile.GetSetting("LodStepMaxDec", "5"));
OffsetModuleBase = Convert.ToInt64(ConfigurationFile.GetSetting("offsetModuleBase", "0x004B2368"), 16);
OffsetPointerMain = Convert.ToInt64(ConfigurationFile.GetSetting("offsetPointerMain", "0x3D0"), 16);
OffsetPointerTlod = Convert.ToInt64(ConfigurationFile.GetSetting("offsetPointerTlod", "0xC"), 16);
@ -120,20 +116,6 @@ namespace MSFS2020_AutoFPS
OffsetPointerFgMode = Convert.ToInt64(ConfigurationFile.GetSetting("offsetPointerFgMode", "0x4A"), 16);
SimMinLOD = Convert.ToSingle(ConfigurationFile.GetSetting("simMinLod", "10"), new RealInvariantFormat(ConfigurationFile.GetSetting("simMinLod", "10")));
SelectedProfile = Convert.ToInt32(ConfigurationFile.GetSetting("selectedProfile", "0"));
PairsTLOD = new();
PairsOLOD = new();
for (int i = 0; i < maxProfile; i++)
{
PairsTLOD.Add(LoadPairs(ConfigurationFile.GetSetting($"tlodPairs{i}", "0:100|1500:150|5000:200")));
PairsOLOD.Add(LoadPairs(ConfigurationFile.GetSetting($"olodPairs{i}", "0:100|2500:50|7500:10")));
}
CurrentPairTLOD = 0;
CurrentPairOLOD = 0;
ForceEvaluation = true;
if (ConfigVersion < BuildConfigVersion)
{
//CHANGE SETTINGS IF NEEDED, Example:
@ -141,49 +123,7 @@ namespace MSFS2020_AutoFPS
SetSetting("ConfigVersion", Convert.ToString(BuildConfigVersion));
}
}
public static List<(float, float)> LoadPairs(string settings)
{
List<(float, float)> pairsList = new();
string[] strPairs = settings.Split('|');
int alt;
float lod;
foreach (string pair in strPairs)
{
string[] parts = pair.Split(':');
alt = Convert.ToInt32(parts[0]);
lod = Convert.ToSingle(parts[1], new RealInvariantFormat(parts[1]));
pairsList.Add((alt, lod));
}
SortTupleList(pairsList);
return pairsList;
}
public static void SortTupleList(List<(float, float)> pairsList)
{
pairsList.Sort((x, y) => x.Item1.CompareTo(y.Item1));
}
public static string CreateLodString(List<(float, float)> pairsList)
{
string result = "";
bool first = true;
foreach (var pair in pairsList)
{
if (first)
first = false;
else
result += "|";
result += $"{Convert.ToString((int)pair.Item1)}:{Convert.ToString(pair.Item2, CultureInfo.InvariantCulture)}";
}
return result;
}
public string GetSetting(string key, string defaultValue = "")
{
return ConfigurationFile[key] ?? defaultValue;
@ -196,14 +136,6 @@ namespace MSFS2020_AutoFPS
LoadConfiguration();
}
public void SavePairs()
{
for (int i = 0; i < maxProfile; i++)
{
ConfigurationFile[$"tlodPairs{i}"] = CreateLodString(PairsTLOD[i]);
ConfigurationFile[$"olodPairs{i}"] = CreateLodString(PairsOLOD[i]);
}
LoadConfiguration();
}
}
}

View File

@ -50,6 +50,7 @@ Some Notes:
- Binary in %appdata%\MSFS2020_AutoFPS\bin
- Logs in %appdata%\MSFS2020_AutoFPS\log
- Config: %appdata%\MSFS2020_AutoFPS\MSFS2020_AutoFPS.config
- If after installing and running the app your simconnect always stays red, try downloading and installing a Microsoft official version of “Microsoft Visual C++ 2015 - 2022 Redistributable”, which may be missing from your Windows installation.
<br/><br/>
@ -65,8 +66,14 @@ This section is currently TBD
- Red values indicate not connected, green is connected.
- Sim Values
- Will not show valid values unless all three connections are green.
- Red values mean FPS Adaption is active, orange means LOD stepping is active, black means steady state, n/a means not available right now.
- Red values mean your FPS, TLOD or cloud quality is at its lower limit, green means they are at their upper limit, orange means TLOD stepping is active, black means steady state, n/a means not available right now.
- Priority will show whether FPS or TLOD Min are the current automation priority, with the latter only being shown if the TLOD min for ground/landing is enabled and conditions are such that working towards TLOD Min because of your flight phase (on or near the ground) now has priority over maintaining FPS.
- General
- Target FPS - The most important setting in this app. Set it to what FPS you want the app to target while running, noting that this value should be at the mid to lower end of what your system is capable of otherwise the app will be unlikely to achieve it.
- Use Expert Options - when disabled allows the app to use default settings in conjuction with your chosen target FPS that should produce good automated FPS tracking provided you have set a realisting FPS target in the first place. When enabled, the UI expands to show additional MSFS settings to adjust. If you do not understand these settings and their impact on MSFS performance and graphics quality, it is strongly recommended that you do not use these expert options and you should uncheck this option.
- MSFS Settings
-
- You can have (exactly) six different Sets/Profiles for the AGL/LOD Pairs to switch between (manually but dynamically).
- Cruise LOD Updates, when checked, will continue to update LOD values based on AGL in the cruise phase, which is useful for VFR flights over undulating terrain and has an otherwise negligble impact on high level or IFR flights so it is recommended to enable this.
- LOD Step Max, when checked, allows the utility to slow the rate of change in LOD per second, with increase and decrease being individually settable, to smooth out LOD table changes. This allows you to have large steps in your LOD tables without experiencing abrupt changes like having it disabled would do, hence it is recommended to turn it on and start out with the default steps of 5.