diff --git a/.gitignore b/.gitignore
index 2f667b3d..d5e6857a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,3 +10,5 @@
/.vs
/JoinFS/Installer/bin
/JoinFS/Installer/obj
+/JoinFS.Tests/bin
+/JoinFS.Tests/obj
diff --git a/JoinFS.Tests/JoinFS.Tests.csproj b/JoinFS.Tests/JoinFS.Tests.csproj
new file mode 100644
index 00000000..972fd3c4
--- /dev/null
+++ b/JoinFS.Tests/JoinFS.Tests.csproj
@@ -0,0 +1,21 @@
+
+
+
+ net8.0
+ enable
+ enable
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JoinFS.Tests/ProgramCode.cs b/JoinFS.Tests/ProgramCode.cs
new file mode 100644
index 00000000..f09fdeb9
--- /dev/null
+++ b/JoinFS.Tests/ProgramCode.cs
@@ -0,0 +1,126 @@
+using System;
+using System.Text;
+
+namespace JoinFS.Tests
+{
+ ///
+ /// Copy of the Program.Code method from JoinFS for testing purposes.
+ /// This allows us to test the encoding/decoding logic independently.
+ ///
+ public static class ProgramCode
+ {
+ public static string? Code(string? s, bool bToCode, int nKey)
+ {
+ if (s == null)
+ return null;
+
+ const char cLow = '!';
+ const char cHigh = '~';
+
+ const int nRange = (int)cHigh - cLow + 1;
+ const string csCaesar = @"THEFIVBOXNGWZARDSJUMPQCKLY" + // Low to High, rearranged (will be nRange in length)
+ @"mywaftvexdzoquipsblchngjrk" +
+ @"1407329685" +
+ @"!""#$%&'()*+,-./:;<=>?@" +
+ @"[\]^_`{|}~";
+
+ if (s.Length == 0)
+ return s;
+
+ StringBuilder sb = new StringBuilder(s);
+
+ // find last valid char & trim ignored ones
+ int nLast = sb.Length - 1;
+ int nEnd = nLast;
+ while (nEnd >= 0 && (sb[nEnd] < cLow || sb[nEnd] > cHigh))
+ --nEnd;
+ if (nEnd != nLast)
+ sb.Remove(nEnd + 1, sb.Length - nEnd - 1);
+
+ // find first valid char & trim ignored ones
+ nLast = sb.Length - 1;
+ int nStart = 0;
+ while (nStart <= nLast && (sb[nStart] < cLow || sb[nStart] > cHigh))
+ ++nStart;
+ if (nStart != 0)
+ sb.Remove(0, nStart);
+
+ if (sb.Length == 0)
+ return sb.ToString();
+
+ nLast = sb.Length - 1;
+
+ // if decoding, reverse-substitute
+ int nChar;
+ if (!bToCode)
+ {
+ for (int i = 0; i <= nLast; ++i)
+ {
+ if (sb[i] < cLow || sb[i] > cHigh)
+ continue;
+
+ nChar = csCaesar.IndexOf(sb[i]);
+
+ if (nChar >= 0)
+ sb[i] = (char)((int)cLow + nChar);
+ }
+ }
+
+ // mangle
+ int nInc = 0;
+ int k;
+ const int nPasses = 11;
+ Random rnd = new Random(nKey);
+ for (int j = 0; j < nPasses; ++j)
+ {
+ k = (bToCode) ? j : nPasses - j - 1;
+ if ((k & 1) == 0)
+ { nStart = nLast; nEnd = -1; nInc = -1; } // from last downto first
+ else
+ { nStart = 0; nEnd = nLast + 1; nInc = 1; } // from first upto last
+
+ for (int i = nStart; i != nEnd; i += nInc)
+ {
+ if (sb[i] < cLow || sb[i] > cHigh)
+ continue;
+
+ nChar = sb[i] - cLow;
+
+ if (bToCode)
+ nChar = nRange - 1 - nChar;
+
+ if (bToCode)
+ nChar += rnd.Next(nRange - 1);
+ else
+ nChar -= rnd.Next(nRange - 1);
+
+ if (nChar >= nRange)
+ nChar -= nRange;
+ else if (nChar < 0)
+ nChar += nRange;
+
+ if (!bToCode)
+ nChar = nRange - 1 - nChar;
+
+ sb[i] = (char)(nChar + cLow);
+ }
+ }
+
+ // if encoding, substitute
+ if (bToCode)
+ {
+ for (int i = 0; i <= nLast; ++i)
+ {
+ if (sb[i] < cLow || sb[i] > cHigh)
+ continue;
+
+ nChar = sb[i] - cLow;
+
+ sb[i] = csCaesar[nChar];
+ }
+ }
+
+ return sb.ToString();
+ }
+ }
+}
diff --git a/JoinFS.Tests/ProgramCodeTests.cs b/JoinFS.Tests/ProgramCodeTests.cs
new file mode 100644
index 00000000..7e177a80
--- /dev/null
+++ b/JoinFS.Tests/ProgramCodeTests.cs
@@ -0,0 +1,345 @@
+namespace JoinFS.Tests;
+
+///
+/// Tests for the Program.Code(...) method which provides encoding/decoding functionality.
+/// The Code method is a bidirectional cipher that uses Caesar substitution and random number generation.
+///
+public class ProgramCodeTests
+{
+ // Standard test key for consistency
+ private const int TestKey = 1234;
+
+ #region Null and Empty String Tests
+
+ [Fact]
+ public void Code_WithNullString_ReturnsNull()
+ {
+ // Arrange
+ string? input = null;
+
+ // Act
+ string? encodedResult = ProgramCode.Code(input, true, TestKey);
+ string? decodedResult = ProgramCode.Code(input, false, TestKey);
+
+ // Assert
+ Assert.Null(encodedResult);
+ Assert.Null(decodedResult);
+ }
+
+ [Fact]
+ public void Code_WithEmptyString_ReturnsEmptyString()
+ {
+ // Arrange
+ string input = string.Empty;
+
+ // Act
+ string encodedResult = ProgramCode.Code(input, true, TestKey);
+ string decodedResult = ProgramCode.Code(input, false, TestKey);
+
+ // Assert
+ Assert.Equal(string.Empty, encodedResult);
+ Assert.Equal(string.Empty, decodedResult);
+ }
+
+ #endregion
+
+ #region Round-Trip Tests
+
+ [Theory]
+ [InlineData("Hello World")]
+ [InlineData("Test123")]
+ [InlineData("https://example.com")]
+ [InlineData("user@email.com")]
+ [InlineData("Path/To/File.txt")]
+ [InlineData("!@#$%^&*()")]
+ [InlineData("ABC")]
+ [InlineData("a")]
+ public void Code_RoundTrip_RestoresOriginalString(string original)
+ {
+ // Act
+ string encoded = ProgramCode.Code(original, true, TestKey);
+ string decoded = ProgramCode.Code(encoded, false, TestKey);
+
+ // Assert
+ Assert.NotEqual(original, encoded); // Encoded should be different
+ Assert.Equal(original, decoded); // Decoded should match original
+ }
+
+ [Fact]
+ public void Code_RoundTrip_WithAllPrintableAsciiCharacters()
+ {
+ // Arrange - Build a string with all printable ASCII characters (! to ~)
+ var sb = new System.Text.StringBuilder();
+ for (char c = '!'; c <= '~'; c++)
+ {
+ sb.Append(c);
+ }
+ string original = sb.ToString();
+
+ // Act
+ string encoded = ProgramCode.Code(original, true, TestKey);
+ string decoded = ProgramCode.Code(encoded, false, TestKey);
+
+ // Assert
+ Assert.NotEqual(original, encoded);
+ Assert.Equal(original, decoded);
+ }
+
+ #endregion
+
+ #region Key Sensitivity Tests
+
+ [Fact]
+ public void Code_DifferentKeys_ProduceDifferentEncodings()
+ {
+ // Arrange
+ string input = "Test String";
+ int key1 = 1234;
+ int key2 = 5678;
+
+ // Act
+ string encoded1 = ProgramCode.Code(input, true, key1);
+ string encoded2 = ProgramCode.Code(input, true, key2);
+
+ // Assert
+ Assert.NotEqual(encoded1, encoded2);
+ }
+
+ [Fact]
+ public void Code_WrongKey_DoesNotRestoreOriginal()
+ {
+ // Arrange
+ string input = "Secret Message";
+ int encodeKey = 1234;
+ int wrongKey = 5678;
+
+ // Act
+ string encoded = ProgramCode.Code(input, true, encodeKey);
+ string decodedWithWrongKey = ProgramCode.Code(encoded, false, wrongKey);
+
+ // Assert
+ Assert.NotEqual(input, decodedWithWrongKey);
+ }
+
+ [Fact]
+ public void Code_SameKeyUsedTwice_RestoresOriginal()
+ {
+ // Arrange
+ string input = "Consistent Key Test";
+ int key = 9999;
+
+ // Act
+ string encoded = ProgramCode.Code(input, true, key);
+ string decoded = ProgramCode.Code(encoded, false, key);
+
+ // Assert
+ Assert.Equal(input, decoded);
+ }
+
+ #endregion
+
+ #region Special Character Tests
+
+ [Theory]
+ [InlineData("!")]
+ [InlineData("~")]
+ [InlineData("!~")]
+ [InlineData("!!!")]
+ [InlineData("~~~")]
+ public void Code_WithBoundaryCharacters_RoundTripsCorrectly(string input)
+ {
+ // Act
+ string encoded = ProgramCode.Code(input, true, TestKey);
+ string decoded = ProgramCode.Code(encoded, false, TestKey);
+
+ // Assert
+ Assert.Equal(input, decoded);
+ }
+
+ [Fact]
+ public void Code_WithMixedSpecialCharacters_RoundTripsCorrectly()
+ {
+ // Arrange
+ string input = "Hello!@#$%^&*()_+-=[]{}|;':\",./<>?`~World";
+
+ // Act
+ string encoded = ProgramCode.Code(input, true, TestKey);
+ string decoded = ProgramCode.Code(encoded, false, TestKey);
+
+ // Assert
+ Assert.Equal(input, decoded);
+ }
+
+ #endregion
+
+ #region Edge Cases with Invalid Characters
+
+ [Fact]
+ public void Code_WithOnlyInvalidCharacters_ReturnsEmptyString()
+ {
+ // Arrange - Characters outside the valid range (! to ~)
+ string input = "\t\n\r";
+
+ // Act
+ string encoded = ProgramCode.Code(input, true, TestKey);
+
+ // Assert
+ Assert.Equal(string.Empty, encoded);
+ }
+
+ [Fact]
+ public void Code_WithInvalidCharactersAtBoundaries_TrimsCorrectly()
+ {
+ // Arrange - Invalid chars at start and end
+ string input = "\t\nHello World\r\n";
+ string expectedTrimmed = "Hello World";
+
+ // Act
+ string encoded = ProgramCode.Code(input, true, TestKey);
+ string decoded = ProgramCode.Code(encoded, false, TestKey);
+
+ // Assert
+ Assert.Equal(expectedTrimmed, decoded);
+ }
+
+ #endregion
+
+ #region Encoding/Decoding Properties
+
+ [Fact]
+ public void Code_Encoding_ProducesDifferentOutput()
+ {
+ // Arrange
+ string input = "This should be different";
+
+ // Act
+ string encoded = ProgramCode.Code(input, true, TestKey);
+
+ // Assert
+ Assert.NotEqual(input, encoded);
+ Assert.NotEmpty(encoded);
+ }
+
+ [Fact]
+ public void Code_EncodingSameStringTwice_ProducesSameResult()
+ {
+ // Arrange
+ string input = "Deterministic Test";
+
+ // Act
+ string encoded1 = ProgramCode.Code(input, true, TestKey);
+ string encoded2 = ProgramCode.Code(input, true, TestKey);
+
+ // Assert
+ Assert.Equal(encoded1, encoded2);
+ }
+
+ [Fact]
+ public void Code_EncodedLength_MatchesValidCharacterCount()
+ {
+ // Arrange
+ string input = "Test";
+
+ // Act
+ string encoded = ProgramCode.Code(input, true, TestKey);
+
+ // Assert
+ // The encoded string should have the same length as the original
+ // (assuming all characters are valid)
+ Assert.Equal(input.Length, encoded.Length);
+ }
+
+ #endregion
+
+ #region Multiple Round-Trips
+
+ [Fact]
+ public void Code_MultipleRoundTrips_MaintainsIntegrity()
+ {
+ // Arrange
+ string original = "Multiple Round Trip Test";
+
+ // Act & Assert - Perform 5 round trips
+ string current = original;
+ for (int i = 0; i < 5; i++)
+ {
+ string encoded = ProgramCode.Code(current, true, TestKey);
+ string decoded = ProgramCode.Code(encoded, false, TestKey);
+ Assert.Equal(current, decoded);
+ current = decoded;
+ }
+
+ Assert.Equal(original, current);
+ }
+
+ #endregion
+
+ #region Real-World Usage Scenarios
+
+ [Fact]
+ public void Code_WithUrl_RoundTripsCorrectly()
+ {
+ // Arrange
+ string url = "https://joinfs.net/download/file.zip";
+
+ // Act
+ string encoded = ProgramCode.Code(url, true, TestKey);
+ string decoded = ProgramCode.Code(encoded, false, TestKey);
+
+ // Assert
+ Assert.Equal(url, decoded);
+ }
+
+ [Fact]
+ public void Code_WithFilePath_RoundTripsCorrectly()
+ {
+ // Arrange
+ string path = "C:/Program Files/JoinFS/config.xml";
+
+ // Act
+ string encoded = ProgramCode.Code(path, true, TestKey);
+ string decoded = ProgramCode.Code(encoded, false, TestKey);
+
+ // Assert
+ Assert.Equal(path, decoded);
+ }
+
+ [Fact]
+ public void Code_WithLongString_RoundTripsCorrectly()
+ {
+ // Arrange
+ string longString = new string('A', 1000) + " test " + new string('Z', 1000);
+
+ // Act
+ string encoded = ProgramCode.Code(longString, true, TestKey);
+ string decoded = ProgramCode.Code(encoded, false, TestKey);
+
+ // Assert
+ Assert.Equal(longString, decoded);
+ }
+
+ #endregion
+
+ #region Key Value Tests
+
+ [Theory]
+ [InlineData(0)]
+ [InlineData(1)]
+ [InlineData(-1)]
+ [InlineData(int.MaxValue)]
+ [InlineData(int.MinValue)]
+ public void Code_WithVariousKeys_RoundTripsCorrectly(int key)
+ {
+ // Arrange
+ string input = "Key variation test";
+
+ // Act
+ string encoded = ProgramCode.Code(input, true, key);
+ string decoded = ProgramCode.Code(encoded, false, key);
+
+ // Assert
+ Assert.Equal(input, decoded);
+ }
+
+ #endregion
+}
diff --git a/JoinFS.Tests/README.md b/JoinFS.Tests/README.md
new file mode 100644
index 00000000..a1db1a83
--- /dev/null
+++ b/JoinFS.Tests/README.md
@@ -0,0 +1,82 @@
+# JoinFS Tests
+
+This test project contains comprehensive unit tests for the JoinFS application.
+
+## Test Coverage
+
+### Program.Code(...) Method
+
+The `Program.Code(...)` method is a bidirectional cipher that implements encoding and decoding functionality using:
+- Caesar substitution cipher
+- Pseudo-random number generation with seeded keys
+- Character range validation (printable ASCII characters from '!' to '~')
+
+#### Test Categories
+
+1. **Null and Empty String Tests**
+ - Validates handling of null inputs
+ - Validates handling of empty strings
+
+2. **Round-Trip Tests**
+ - Ensures encoding followed by decoding restores the original string
+ - Tests various common input patterns (URLs, file paths, email addresses, etc.)
+ - Tests all printable ASCII characters
+
+3. **Key Sensitivity Tests**
+ - Verifies different keys produce different encodings
+ - Confirms wrong keys cannot decode messages
+ - Validates key consistency
+
+4. **Special Character Tests**
+ - Tests boundary characters ('!' and '~')
+ - Tests mixed special character strings
+
+5. **Edge Cases with Invalid Characters**
+ - Handles characters outside the valid range
+ - Properly trims invalid characters at boundaries
+
+6. **Encoding/Decoding Properties**
+ - Verifies encoding produces different output
+ - Confirms deterministic behavior (same input + key = same output)
+ - Validates encoded string length
+
+7. **Multiple Round-Trips**
+ - Ensures data integrity over multiple encode/decode cycles
+
+8. **Real-World Usage Scenarios**
+ - Tests with URLs, file paths, and long strings
+
+9. **Key Value Tests**
+ - Tests with various key values including edge cases (0, negative, max/min int)
+
+## Running Tests
+
+To run all tests:
+```bash
+cd JoinFS.Tests
+dotnet test
+```
+
+To run tests with verbose output:
+```bash
+dotnet test --verbosity normal
+```
+
+To run tests with coverage:
+```bash
+dotnet test --collect:"XPlat Code Coverage"
+```
+
+## Test Results
+
+All 34 tests pass successfully, providing comprehensive coverage of the `Program.Code(...)` method's functionality including:
+- Normal operation
+- Edge cases
+- Error conditions
+- Round-trip encoding/decoding
+- Key sensitivity
+- Character range handling
+
+## Implementation Note
+
+The test project includes a copy of the `Program.Code` method in `ProgramCode.cs` to avoid circular dependencies with the main Windows Forms application. This ensures the tests can run independently on any platform.
diff --git a/JoinFS.sln b/JoinFS.sln
index c9763b68..eddd7cc1 100644
--- a/JoinFS.sln
+++ b/JoinFS.sln
@@ -23,70 +23,210 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Utils", "Utils", "{E6679DD8
util\version.txt = util\version.txt
EndProjectSection
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JoinFS.Tests", "JoinFS.Tests\JoinFS.Tests.csproj", "{6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
CONSOLE|x64 = CONSOLE|x64
CONSOLE|x86 = CONSOLE|x86
+ CONSOLE|Any CPU = CONSOLE|Any CPU
CONSOLE-Debug|x64 = CONSOLE-Debug|x64
CONSOLE-Debug|x86 = CONSOLE-Debug|x86
+ CONSOLE-Debug|Any CPU = CONSOLE-Debug|Any CPU
FS2020|x64 = FS2020|x64
FS2020|x86 = FS2020|x86
+ FS2020|Any CPU = FS2020|Any CPU
FS2020-Debug|x64 = FS2020-Debug|x64
FS2020-Debug|x86 = FS2020-Debug|x86
+ FS2020-Debug|Any CPU = FS2020-Debug|Any CPU
FS2024|x64 = FS2024|x64
FS2024|x86 = FS2024|x86
+ FS2024|Any CPU = FS2024|Any CPU
FS2024-Debug|x64 = FS2024-Debug|x64
FS2024-Debug|x86 = FS2024-Debug|x86
+ FS2024-Debug|Any CPU = FS2024-Debug|Any CPU
FSX|x64 = FSX|x64
FSX|x86 = FSX|x86
+ FSX|Any CPU = FSX|Any CPU
FSX-Debug|x64 = FSX-Debug|x64
FSX-Debug|x86 = FSX-Debug|x86
+ FSX-Debug|Any CPU = FSX-Debug|Any CPU
P3D|x64 = P3D|x64
P3D|x86 = P3D|x86
+ P3D|Any CPU = P3D|Any CPU
P3D-Debug|x64 = P3D-Debug|x64
P3D-Debug|x86 = P3D-Debug|x86
+ P3D-Debug|Any CPU = P3D-Debug|Any CPU
XPLANE|x64 = XPLANE|x64
XPLANE|x86 = XPLANE|x86
+ XPLANE|Any CPU = XPLANE|Any CPU
XPLANE-Debug|x64 = XPLANE-Debug|x64
XPLANE-Debug|x86 = XPLANE-Debug|x86
+ XPLANE-Debug|Any CPU = XPLANE-Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Debug|Any CPU = Debug|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{91153E12-DEC1-1343-F4BF-108E45E61261}.CONSOLE|x64.ActiveCfg = CONSOLE|x64
{91153E12-DEC1-1343-F4BF-108E45E61261}.CONSOLE|x64.Build.0 = CONSOLE|x64
{91153E12-DEC1-1343-F4BF-108E45E61261}.CONSOLE|x86.ActiveCfg = CONSOLE|x86
+ {91153E12-DEC1-1343-F4BF-108E45E61261}.CONSOLE|Any CPU.ActiveCfg = CONSOLE|Any CPU
+ {91153E12-DEC1-1343-F4BF-108E45E61261}.CONSOLE|Any CPU.Build.0 = CONSOLE|Any CPU
{91153E12-DEC1-1343-F4BF-108E45E61261}.CONSOLE-Debug|x64.ActiveCfg = CONSOLE-Debug|x64
{91153E12-DEC1-1343-F4BF-108E45E61261}.CONSOLE-Debug|x64.Build.0 = CONSOLE-Debug|x64
{91153E12-DEC1-1343-F4BF-108E45E61261}.CONSOLE-Debug|x86.ActiveCfg = CONSOLE-Debug|x86
+ {91153E12-DEC1-1343-F4BF-108E45E61261}.CONSOLE-Debug|Any CPU.ActiveCfg = CONSOLE-Debug|Any CPU
+ {91153E12-DEC1-1343-F4BF-108E45E61261}.CONSOLE-Debug|Any CPU.Build.0 = CONSOLE-Debug|Any CPU
{91153E12-DEC1-1343-F4BF-108E45E61261}.FS2020|x64.ActiveCfg = FS2020|x64
{91153E12-DEC1-1343-F4BF-108E45E61261}.FS2020|x64.Build.0 = FS2020|x64
{91153E12-DEC1-1343-F4BF-108E45E61261}.FS2020|x86.ActiveCfg = FS2020|x86
+ {91153E12-DEC1-1343-F4BF-108E45E61261}.FS2020|Any CPU.ActiveCfg = FS2020|Any CPU
+ {91153E12-DEC1-1343-F4BF-108E45E61261}.FS2020|Any CPU.Build.0 = FS2020|Any CPU
{91153E12-DEC1-1343-F4BF-108E45E61261}.FS2020-Debug|x64.ActiveCfg = FS2020-Debug|x64
{91153E12-DEC1-1343-F4BF-108E45E61261}.FS2020-Debug|x64.Build.0 = FS2020-Debug|x64
{91153E12-DEC1-1343-F4BF-108E45E61261}.FS2020-Debug|x86.ActiveCfg = FS2020-Debug|x86
+ {91153E12-DEC1-1343-F4BF-108E45E61261}.FS2020-Debug|Any CPU.ActiveCfg = FS2020-Debug|Any CPU
+ {91153E12-DEC1-1343-F4BF-108E45E61261}.FS2020-Debug|Any CPU.Build.0 = FS2020-Debug|Any CPU
{91153E12-DEC1-1343-F4BF-108E45E61261}.FS2024|x64.ActiveCfg = FS2024|x64
{91153E12-DEC1-1343-F4BF-108E45E61261}.FS2024|x64.Build.0 = FS2024|x64
{91153E12-DEC1-1343-F4BF-108E45E61261}.FS2024|x86.ActiveCfg = FS2024|x86
+ {91153E12-DEC1-1343-F4BF-108E45E61261}.FS2024|Any CPU.ActiveCfg = FS2024|Any CPU
+ {91153E12-DEC1-1343-F4BF-108E45E61261}.FS2024|Any CPU.Build.0 = FS2024|Any CPU
{91153E12-DEC1-1343-F4BF-108E45E61261}.FS2024-Debug|x64.ActiveCfg = FS2024-Debug|x64
{91153E12-DEC1-1343-F4BF-108E45E61261}.FS2024-Debug|x64.Build.0 = FS2024-Debug|x64
{91153E12-DEC1-1343-F4BF-108E45E61261}.FS2024-Debug|x86.ActiveCfg = FS2024-Debug|x86
+ {91153E12-DEC1-1343-F4BF-108E45E61261}.FS2024-Debug|Any CPU.ActiveCfg = FS2024-Debug|Any CPU
+ {91153E12-DEC1-1343-F4BF-108E45E61261}.FS2024-Debug|Any CPU.Build.0 = FS2024-Debug|Any CPU
{91153E12-DEC1-1343-F4BF-108E45E61261}.FSX|x64.ActiveCfg = FSX|x86
{91153E12-DEC1-1343-F4BF-108E45E61261}.FSX|x86.ActiveCfg = FSX|x86
{91153E12-DEC1-1343-F4BF-108E45E61261}.FSX|x86.Build.0 = FSX|x86
+ {91153E12-DEC1-1343-F4BF-108E45E61261}.FSX|Any CPU.ActiveCfg = FSX|Any CPU
+ {91153E12-DEC1-1343-F4BF-108E45E61261}.FSX|Any CPU.Build.0 = FSX|Any CPU
{91153E12-DEC1-1343-F4BF-108E45E61261}.FSX-Debug|x64.ActiveCfg = FSX-Debug|x86
{91153E12-DEC1-1343-F4BF-108E45E61261}.FSX-Debug|x86.ActiveCfg = FSX-Debug|x86
{91153E12-DEC1-1343-F4BF-108E45E61261}.FSX-Debug|x86.Build.0 = FSX-Debug|x86
+ {91153E12-DEC1-1343-F4BF-108E45E61261}.FSX-Debug|Any CPU.ActiveCfg = FSX-Debug|Any CPU
+ {91153E12-DEC1-1343-F4BF-108E45E61261}.FSX-Debug|Any CPU.Build.0 = FSX-Debug|Any CPU
{91153E12-DEC1-1343-F4BF-108E45E61261}.P3D|x64.ActiveCfg = FSX|x86
{91153E12-DEC1-1343-F4BF-108E45E61261}.P3D|x86.ActiveCfg = P3D|x86
{91153E12-DEC1-1343-F4BF-108E45E61261}.P3D|x86.Build.0 = P3D|x86
+ {91153E12-DEC1-1343-F4BF-108E45E61261}.P3D|Any CPU.ActiveCfg = P3D|Any CPU
+ {91153E12-DEC1-1343-F4BF-108E45E61261}.P3D|Any CPU.Build.0 = P3D|Any CPU
{91153E12-DEC1-1343-F4BF-108E45E61261}.P3D-Debug|x64.ActiveCfg = FSX-Debug|x86
{91153E12-DEC1-1343-F4BF-108E45E61261}.P3D-Debug|x86.ActiveCfg = FSX-Debug|x86
{91153E12-DEC1-1343-F4BF-108E45E61261}.P3D-Debug|x86.Build.0 = FSX-Debug|x86
+ {91153E12-DEC1-1343-F4BF-108E45E61261}.P3D-Debug|Any CPU.ActiveCfg = P3D-Debug|Any CPU
+ {91153E12-DEC1-1343-F4BF-108E45E61261}.P3D-Debug|Any CPU.Build.0 = P3D-Debug|Any CPU
{91153E12-DEC1-1343-F4BF-108E45E61261}.XPLANE|x64.ActiveCfg = XPLANE|x64
{91153E12-DEC1-1343-F4BF-108E45E61261}.XPLANE|x64.Build.0 = XPLANE|x64
{91153E12-DEC1-1343-F4BF-108E45E61261}.XPLANE|x86.ActiveCfg = XPLANE|x86
+ {91153E12-DEC1-1343-F4BF-108E45E61261}.XPLANE|Any CPU.ActiveCfg = XPLANE|Any CPU
+ {91153E12-DEC1-1343-F4BF-108E45E61261}.XPLANE|Any CPU.Build.0 = XPLANE|Any CPU
{91153E12-DEC1-1343-F4BF-108E45E61261}.XPLANE-Debug|x64.ActiveCfg = XPLANE-Debug|x64
{91153E12-DEC1-1343-F4BF-108E45E61261}.XPLANE-Debug|x64.Build.0 = XPLANE-Debug|x64
{91153E12-DEC1-1343-F4BF-108E45E61261}.XPLANE-Debug|x86.ActiveCfg = XPLANE-Debug|x86
+ {91153E12-DEC1-1343-F4BF-108E45E61261}.XPLANE-Debug|Any CPU.ActiveCfg = XPLANE-Debug|Any CPU
+ {91153E12-DEC1-1343-F4BF-108E45E61261}.XPLANE-Debug|Any CPU.Build.0 = XPLANE-Debug|Any CPU
+ {91153E12-DEC1-1343-F4BF-108E45E61261}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {91153E12-DEC1-1343-F4BF-108E45E61261}.Debug|x64.Build.0 = Debug|Any CPU
+ {91153E12-DEC1-1343-F4BF-108E45E61261}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {91153E12-DEC1-1343-F4BF-108E45E61261}.Debug|x86.Build.0 = Debug|Any CPU
+ {91153E12-DEC1-1343-F4BF-108E45E61261}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {91153E12-DEC1-1343-F4BF-108E45E61261}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {91153E12-DEC1-1343-F4BF-108E45E61261}.Release|x64.ActiveCfg = Release|Any CPU
+ {91153E12-DEC1-1343-F4BF-108E45E61261}.Release|x64.Build.0 = Release|Any CPU
+ {91153E12-DEC1-1343-F4BF-108E45E61261}.Release|x86.ActiveCfg = Release|Any CPU
+ {91153E12-DEC1-1343-F4BF-108E45E61261}.Release|x86.Build.0 = Release|Any CPU
+ {91153E12-DEC1-1343-F4BF-108E45E61261}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {91153E12-DEC1-1343-F4BF-108E45E61261}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.CONSOLE|x64.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.CONSOLE|x64.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.CONSOLE|x86.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.CONSOLE|x86.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.CONSOLE|Any CPU.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.CONSOLE|Any CPU.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.CONSOLE-Debug|x64.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.CONSOLE-Debug|x64.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.CONSOLE-Debug|x86.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.CONSOLE-Debug|x86.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.CONSOLE-Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.CONSOLE-Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.FS2020|x64.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.FS2020|x64.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.FS2020|x86.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.FS2020|x86.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.FS2020|Any CPU.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.FS2020|Any CPU.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.FS2020-Debug|x64.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.FS2020-Debug|x64.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.FS2020-Debug|x86.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.FS2020-Debug|x86.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.FS2020-Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.FS2020-Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.FS2024|x64.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.FS2024|x64.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.FS2024|x86.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.FS2024|x86.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.FS2024|Any CPU.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.FS2024|Any CPU.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.FS2024-Debug|x64.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.FS2024-Debug|x64.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.FS2024-Debug|x86.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.FS2024-Debug|x86.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.FS2024-Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.FS2024-Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.FSX|x64.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.FSX|x64.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.FSX|x86.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.FSX|x86.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.FSX|Any CPU.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.FSX|Any CPU.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.FSX-Debug|x64.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.FSX-Debug|x64.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.FSX-Debug|x86.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.FSX-Debug|x86.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.FSX-Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.FSX-Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.P3D|x64.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.P3D|x64.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.P3D|x86.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.P3D|x86.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.P3D|Any CPU.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.P3D|Any CPU.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.P3D-Debug|x64.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.P3D-Debug|x64.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.P3D-Debug|x86.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.P3D-Debug|x86.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.P3D-Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.P3D-Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.XPLANE|x64.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.XPLANE|x64.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.XPLANE|x86.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.XPLANE|x86.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.XPLANE|Any CPU.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.XPLANE|Any CPU.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.XPLANE-Debug|x64.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.XPLANE-Debug|x64.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.XPLANE-Debug|x86.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.XPLANE-Debug|x86.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.XPLANE-Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.XPLANE-Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.Debug|x64.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.Debug|x86.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.Release|x64.ActiveCfg = Release|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.Release|x64.Build.0 = Release|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.Release|x86.ActiveCfg = Release|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.Release|x86.Build.0 = Release|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6BFEC8A5-2FA0-4E77-AC0F-7B57D91D1882}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE