diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 0000000..73d1437
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,59 @@
+name: Build Simitone
+
+on:
+ workflow_dispatch:
+ inputs:
+ configuration:
+ description: 'Build configuration'
+ required: false
+ default: 'Release'
+ type: choice
+ options:
+ - Release
+ - Debug
+
+jobs:
+ build:
+ runs-on: windows-latest
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+ with:
+ submodules: recursive
+
+ - name: Setup .NET 9
+ uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: '9.0.x'
+
+ - name: Run Protobuild
+ shell: pwsh
+ run: |
+ cd FreeSO/Other/libs/FSOMonoGame/
+ ./protobuild.exe --generate
+ continue-on-error: true
+
+ - name: Restore Simitone dependencies
+ run: dotnet restore Client/Simitone/Simitone.sln
+
+ - name: Restore FreeSO dependencies
+ run: dotnet restore FreeSO/TSOClient/FreeSO.sln
+ continue-on-error: true
+
+ - name: Restore Roslyn dependencies
+ shell: pwsh
+ run: |
+ cd FreeSO/TSOClient/FSO.SimAntics.JIT.Roslyn/
+ dotnet restore
+ continue-on-error: true
+
+ - name: Build
+ run: dotnet build Client/Simitone/Simitone.sln -c ${{ inputs.configuration || 'Release' }} --no-restore
+
+ - name: Upload build artifacts
+ uses: actions/upload-artifact@v4
+ with:
+ name: SimitoneWindows-${{ inputs.configuration || 'Release' }}
+ path: Client/Simitone/Simitone.Windows/bin/${{ inputs.configuration || 'Release' }}/net9.0-windows/
+ if-no-files-found: error
diff --git a/Client/Simitone/Simitone.Client/GameController.cs b/Client/Simitone/Simitone.Client/GameController.cs
index f127879..43b01f9 100644
--- a/Client/Simitone/Simitone.Client/GameController.cs
+++ b/Client/Simitone/Simitone.Client/GameController.cs
@@ -1,7 +1,10 @@
using FSO.Client;
using FSO.Client.UI.Framework;
+using FSO.Client.UI.Controls;
using FSO.Common.Utils;
+using FSO.Content;
using Simitone.Client.UI.Screens;
+using Simitone.Client.UI.Panels;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -56,8 +59,75 @@ public static void EnterGameMode(string lotName, bool external)
}
}
screen.Initialize(lotName, external);
+
+ // Show notification about any failed content files
+ ShowFailedContentNotification();
});
}
+
+ ///
+ /// Shows a notification to the user about any content files that failed to load.
+ /// This is called after entering game mode so the user can see which custom content
+ /// files are problematic.
+ ///
+ private static void ShowFailedContentNotification()
+ {
+ var failedFiles = Content.FailedContentFiles;
+ if (failedFiles == null || failedFiles.Count == 0)
+ return;
+
+ var realFailures = failedFiles
+ .Where(f => f.ErrorType != "DebugInfo")
+ .GroupBy(f => f.Filename)
+ .Select(g => g.First())
+ .ToList();
+
+ if (realFailures.Count == 0)
+ return;
+
+ var message = new StringBuilder();
+ message.AppendLine("Some custom content files could not be loaded:");
+ message.AppendLine();
+
+ int displayCount = Math.Min(realFailures.Count, 3);
+ for (int i = 0; i < displayCount; i++)
+ {
+ var file = realFailures[i];
+ string shortReason = file.ErrorType switch
+ {
+ "EndOfStream" => "truncated",
+ "InvalidData" => "invalid format",
+ "IOException" => "I/O error",
+ "CatalogError" => "catalog error",
+ "DecodeError" => "decode failed",
+ _ => file.ErrorType
+ };
+ message.AppendLine($"• {file.Filename} ({shortReason})");
+ }
+
+ if (realFailures.Count > 3)
+ {
+ message.AppendLine($"... and {realFailures.Count - 3} more");
+ }
+
+ message.AppendLine();
+ message.AppendLine("Common causes: corrupted files, missing .cfp files, or wrong format.");
+ message.AppendLine("The game will continue without these items.");
+
+ // Show the alert
+ UIMobileAlert alert = null;
+ alert = new UIMobileAlert(new UIAlertOptions
+ {
+ Title = "Custom Content Warning",
+ Message = message.ToString(),
+ Buttons = UIAlertButton.Ok((btn) =>
+ {
+ alert.Close();
+ })
+ });
+
+ UIScreen.GlobalShowDialog(alert, true);
+ }
public static void EnterCAS()
{
diff --git a/Client/Simitone/Simitone.Client/SimitoneGame.cs b/Client/Simitone/Simitone.Client/SimitoneGame.cs
index 52ca85b..c892112 100644
--- a/Client/Simitone/Simitone.Client/SimitoneGame.cs
+++ b/Client/Simitone/Simitone.Client/SimitoneGame.cs
@@ -47,11 +47,13 @@ public SimitoneGame() : base()
FSOEnvironment.TexCompress = false;
UILotControl.ShowSimanticsExceptions = !FSOEnvironment.Args.Contains("nosimantics-exc");
+ FSOEnvironment.DPIScaleFactor = GlobalSettings.Default.DPIScaleFactor;
+
if (!FSOEnvironment.SoftwareKeyboard)
{
Graphics.SynchronizeWithVerticalRetrace = true;
- Graphics.PreferredBackBufferWidth = GlobalSettings.Default.GraphicsWidth;
- Graphics.PreferredBackBufferHeight = GlobalSettings.Default.GraphicsHeight;
+ Graphics.PreferredBackBufferWidth = (int)(GlobalSettings.Default.GraphicsWidth * FSOEnvironment.DPIScaleFactor);
+ Graphics.PreferredBackBufferHeight = (int)(GlobalSettings.Default.GraphicsHeight * FSOEnvironment.DPIScaleFactor);
Graphics.HardwareModeSwitch = false;
Graphics.ApplyChanges();
}
@@ -82,6 +84,8 @@ void Window_ClientSizeChanged(object sender, EventArgs e)
if (uiLayer?.CurrentUIScreen == null) return;
uiLayer.SpriteBatch.ResizeBuffer(GlobalSettings.Default.GraphicsWidth, GlobalSettings.Default.GraphicsHeight);
+ GlobalSettings.Default.GraphicsWidth = (int)(width / FSOEnvironment.DPIScaleFactor);
+ GlobalSettings.Default.GraphicsHeight = (int)(height / FSOEnvironment.DPIScaleFactor);
uiLayer.CurrentUIScreen.GameResized();
}
diff --git a/Client/Simitone/Simitone.Windows/Simitone.Windows.csproj b/Client/Simitone/Simitone.Windows/Simitone.Windows.csproj
index edbb044..f71772c 100644
--- a/Client/Simitone/Simitone.Windows/Simitone.Windows.csproj
+++ b/Client/Simitone/Simitone.Windows/Simitone.Windows.csproj
@@ -9,6 +9,7 @@
Simitone
512
Icon.ico
+ app.manifest
true
diff --git a/Client/Simitone/Simitone.Windows/app.manifest b/Client/Simitone/Simitone.Windows/app.manifest
new file mode 100644
index 0000000..36ed651
--- /dev/null
+++ b/Client/Simitone/Simitone.Windows/app.manifest
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true/pm
+
+
+
+
diff --git a/FreeSO b/FreeSO
index f86bbd3..fc2781d 160000
--- a/FreeSO
+++ b/FreeSO
@@ -1 +1 @@
-Subproject commit f86bbd34b2112296ed786741f640a0535886d180
+Subproject commit fc2781dac55b2214d77da1b7f376e0e8b0f10869