diff --git a/LandscapeExplorer/LandscapeExplorer.csproj b/LandscapeExplorer/LandscapeExplorer.csproj new file mode 100644 index 0000000..d7459cb --- /dev/null +++ b/LandscapeExplorer/LandscapeExplorer.csproj @@ -0,0 +1,14 @@ + + + + + + + + Exe + net9.0 + enable + enable + + + diff --git a/LandscapeExplorer/Program.cs b/LandscapeExplorer/Program.cs new file mode 100644 index 0000000..0721b51 --- /dev/null +++ b/LandscapeExplorer/Program.cs @@ -0,0 +1,332 @@ +using System.Buffers.Binary; +using NResLib; +using System.Numerics; +using System.Text; + +namespace LandscapeExplorer; + +public static class Program +{ + private const string MapsDirectory = @"C:\Program Files (x86)\Nikita\Iron Strategy\DATA\MAPS\SC_3"; + + public static void Main(string[] args) + { + Console.OutputEncoding = Encoding.UTF8; + Console.WriteLine("Parkan 1 Landscape Explorer\n"); + + // Get all .map and .msh files in the directory + var mapFiles = Directory.GetFiles(MapsDirectory, "*.map"); + var mshFiles = Directory.GetFiles(MapsDirectory, "*.msh"); + + Console.WriteLine($"Found {mapFiles.Length} .map files and {mshFiles.Length} .msh files in {MapsDirectory}\n"); + + // Process .map files + Console.WriteLine("=== MAP Files Analysis ===\n"); + foreach (var mapFile in mapFiles) + { + AnalyzeNResFile(mapFile); + } + + // Process .msh files + Console.WriteLine("\n=== MSH Files Analysis ===\n"); + foreach (var mshFile in mshFiles) + { + AnalyzeNResFile(mshFile); + + // Perform detailed landscape analysis on MSH files + AnalyzeLandscapeMeshFile(mshFile); + } + + Console.WriteLine("\nAnalysis complete."); + } + + /// + /// Analyzes an NRes file and displays its structure + /// + /// Path to the NRes file + private static void AnalyzeNResFile(string filePath) + { + Console.WriteLine($"Analyzing file: {Path.GetFileName(filePath)}"); + + var parseResult = NResParser.ReadFile(filePath); + + if (parseResult.Error != null) + { + Console.WriteLine($" Error: {parseResult.Error}"); + return; + } + + var archive = parseResult.Archive!; + + Console.WriteLine($" Header: {archive.Header.NRes}, Version: {archive.Header.Version:X}, Files: {archive.Header.FileCount}, Size: {archive.Header.TotalFileLengthBytes} bytes"); + + // Group files by type for better analysis + var filesByType = archive.Files.GroupBy(f => f.FileType); + + foreach (var group in filesByType) + { + Console.WriteLine($" File Type: {group.Key}, Count: {group.Count()}"); + + // Display details of the first file of each type as an example + var example = group.First(); + Console.WriteLine($" Example: {example.FileName}"); + Console.WriteLine($" Elements: {example.ElementCount}, Element Size: {example.ElementSize} bytes"); + Console.WriteLine($" File Length: {example.FileLength} bytes, Offset: {example.OffsetInFile}"); + + // If this is a landscape-related file, provide more detailed analysis + if (IsLandscapeRelatedType(group.Key)) + { + AnalyzeLandscapeData(example, filePath); + } + } + + Console.WriteLine(); + } + + /// + /// Determines if a file type is related to landscape data + /// + private static bool IsLandscapeRelatedType(string fileType) + { + // Based on the Landscape constructor analysis, these types might be related to landscape + return fileType == "LAND" || fileType == "TERR" || fileType == "MSH0" || + fileType == "MESH" || fileType == "MATR" || fileType == "TEXT"; + } + + /// + /// Analyzes landscape-specific data in a file + /// + private static void AnalyzeLandscapeData(ListMetadataItem item, string filePath) + { + Console.WriteLine($" [Landscape Data Analysis]:"); + + // Read the file data for this specific item + using var fs = new FileStream(filePath, FileMode.Open); + fs.Seek(item.OffsetInFile, SeekOrigin.Begin); + + var buffer = new byte[Math.Min(item.FileLength, 256)]; // Read at most 256 bytes for analysis + fs.Read(buffer, 0, buffer.Length); + + // Display some basic statistics based on the file type + if (item.FileType == "LAND" || item.FileType == "TERR") + { + Console.WriteLine($" Terrain data with {item.ElementCount} elements"); + // If element size is known, we can calculate grid dimensions + if (item.ElementCount > 0 && item.ElementSize > 0) + { + // Assuming square terrain, which is common in games from this era + var gridSize = Math.Sqrt(item.ElementCount); + if (Math.Abs(gridSize - Math.Round(gridSize)) < 0.001) // If it's close to a whole number + { + Console.WriteLine($" Terrain grid size: {Math.Round(gridSize)} x {Math.Round(gridSize)}"); + } + } + } + else if (item.FileType == "MSH0" || item.FileType == "MESH") + { + // For mesh data, try to estimate vertex/face counts + Console.WriteLine($" Mesh data, possibly with vertices and faces"); + + // Common sizes: vertices are often 12 bytes (3 floats), faces are often 12 bytes (3 indices) + if (item.ElementSize == 12) + { + Console.WriteLine($" Possibly {item.ElementCount} vertices or faces"); + } + } + + // Display first few bytes as hex for debugging + var hexPreview = BitConverter.ToString( + buffer.Take(32) + .ToArray() + ) + .Replace("-", " "); + Console.WriteLine($" Data preview (hex): {hexPreview}..."); + } + + /// + /// Performs a detailed analysis of a landscape mesh file + /// + /// Path to the MSH file + private static void AnalyzeLandscapeMeshFile(string filePath) + { + Console.WriteLine($"\nDetailed Landscape Analysis for: {Path.GetFileName(filePath)}\n"); + + var parseResult = NResParser.ReadFile(filePath); + if (parseResult.Error != null || parseResult.Archive == null) + { + Console.WriteLine($" Error analyzing file: {parseResult.Error}"); + return; + } + + var archive = parseResult.Archive; + + // Based on the Landscape constructor and the file analysis, we can identify specific sections + // File types in MSH files appear to be numeric values (01, 02, 03, etc.) + + // First, let's extract all the different data sections + var sections = new Dictionary(); + + foreach (var item in archive.Files) + { + using var fs = new FileStream(filePath, FileMode.Open); + fs.Seek(item.OffsetInFile, SeekOrigin.Begin); + + var buffer = new byte[item.FileLength]; + fs.Read(buffer, 0, buffer.Length); + + sections[item.FileType] = (item, buffer); + } + + // Now analyze each section based on what we know from the Landscape constructor + Console.WriteLine(" Landscape Structure Analysis:"); + + // Type 01 appears to be basic landscape information (possibly header/metadata) + if (sections.TryGetValue("01 00 00 00", out var section01)) + { + Console.WriteLine($" Section 01: Basic Landscape Info"); + Console.WriteLine($" Elements: {section01.Meta.ElementCount}, Element Size: {section01.Meta.ElementSize} bytes"); + Console.WriteLine($" Total Size: {section01.Meta.FileLength} bytes"); + + // Try to extract some basic info if the format is as expected + if (section01.Meta.ElementSize == 38 && section01.Data.Length >= 38) + { + // This is speculative based on common terrain formats + var width = BitConverter.ToInt32(section01.Data, 0); + var height = BitConverter.ToInt32(section01.Data, 4); + Console.WriteLine($" Possible Dimensions: {width} x {height}"); + } + } + + // Type 03 appears to be vertex data (based on element size of 12 bytes which is typical for 3D vertices) + if (sections.TryGetValue("03 00 00 00", out var section03)) + { + Console.WriteLine($"\n Section 03: Vertex Data"); + Console.WriteLine($" Vertex Count: {section03.Meta.ElementCount}"); + Console.WriteLine($" Vertex Size: {section03.Meta.ElementSize} bytes"); + + // If we have vertex data in expected format (3 floats per vertex) + if (section03.Meta.ElementSize == 12 && section03.Data.Length >= 36) + { + // Display first 3 vertices as example + Console.WriteLine(" Sample Vertices:"); + for (int i = 0; i < Math.Min(3, section03.Meta.ElementCount); i++) + { + var offset = i * 12; + var x = BitConverter.ToSingle(section03.Data, offset); + var y = BitConverter.ToSingle(section03.Data, offset + 4); + var z = BitConverter.ToSingle(section03.Data, offset + 8); + Console.WriteLine($" Vertex {i}: ({x}, {y}, {z})"); + } + + // Calculate terrain bounds + var minX = float.MaxValue; + var minY = float.MaxValue; + var minZ = float.MaxValue; + var maxX = float.MinValue; + var maxY = float.MinValue; + var maxZ = float.MinValue; + + for (int i = 0; i < section03.Meta.ElementCount; i++) + { + var offset = i * 12; + if (offset + 12 <= section03.Data.Length) + { + var x = BitConverter.ToSingle(section03.Data, offset); + var y = BitConverter.ToSingle(section03.Data, offset + 4); + var z = BitConverter.ToSingle(section03.Data, offset + 8); + + minX = Math.Min(minX, x); + minY = Math.Min(minY, y); + minZ = Math.Min(minZ, z); + maxX = Math.Max(maxX, x); + maxY = Math.Max(maxY, y); + maxZ = Math.Max(maxZ, z); + } + } + + Console.WriteLine(" Terrain Bounds:"); + Console.WriteLine($" Min: ({minX}, {minY}, {minZ})"); + Console.WriteLine($" Max: ({maxX}, {maxY}, {maxZ})"); + Console.WriteLine($" Dimensions: {maxX - minX} x {maxY - minY} x {maxZ - minZ}"); + } + } + + // Type 02 might be face/index data for the mesh + if (sections.TryGetValue("02 00 00 00", out var section02)) + { + Console.WriteLine($"\n Section 02: Possible Face/Index Data"); + Console.WriteLine($" Elements: {section02.Meta.ElementCount}"); + Console.WriteLine($" Element Size: {section02.Meta.ElementSize} bytes"); + + // If element size is divisible by 4 (common for index data) + if (section02.Meta.ElementSize % 4 == 0 && section02.Data.Length >= 12) + { + // Display first triangle as example (assuming 3 indices per triangle) + Console.WriteLine(" Sample Indices (if this is index data):"); + var indicesPerElement = section02.Meta.ElementSize / 4; + for (int i = 0; i < Math.Min(1, section02.Meta.ElementCount); i++) + { + Console.Write($" Element {i}: "); + for (int j = 0; j < indicesPerElement; j++) + { + var offset = i * section02.Meta.ElementSize + j * 4; + if (offset + 4 <= section02.Data.Length) + { + var index = BitConverter.ToInt32(section02.Data, offset); + Console.Write($"{index} "); + } + } + + Console.WriteLine(); + } + } + } + + // Types 04, 05, 12, 0E, 0B might be texture coordinates, normals, colors, etc. + var otherSections = new[] {"04 00 00 00", "05 00 00 00", "12 00 00 00", "0E 00 00 00", "0B 00 00 00"}; + foreach (var sectionType in otherSections) + { + if (sections.TryGetValue(sectionType, out var section)) + { + Console.WriteLine($"\n Section {sectionType.Substring(0, 2)}: Additional Mesh Data"); + Console.WriteLine($" Elements: {section.Meta.ElementCount}"); + Console.WriteLine($" Element Size: {section.Meta.ElementSize} bytes"); + + // If element size is 4 bytes, it could be color data, texture indices, etc. + if (section.Meta.ElementSize == 4 && section.Data.Length >= 12) + { + Console.WriteLine(" Sample Data (as integers):"); + for (int i = 0; i < Math.Min(3, section.Meta.ElementCount); i++) + { + var offset = i * 4; + var value = BitConverter.ToInt32(section.Data, offset); + Console.WriteLine($" Element {i}: {value}"); + } + } + } + } + + // Type 15 might be material or special data (Msh_15 in the decompiled code) + if (sections.TryGetValue("15 00 00 00", out var section15) && sections.TryGetValue("03 00 00 00", out var vertexSection)) + { + Console.WriteLine($"\n Section 15: Special Data (Msh_15 type in decompiled code)"); + Console.WriteLine($" Elements: {section15.Meta.ElementCount}"); + Console.WriteLine($" Element Size: {section15.Meta.ElementSize} bytes"); + + int count = 0; + for (var i = 0; i < section15.Data.Length; i += 28) + { + var first = BinaryPrimitives.ReadUInt32LittleEndian(section15.Data.AsSpan(i)); + + if ((first & 0x20000) != 0) + { + Console.WriteLine($"Found {first}/0x{first:X8} 0x20000 at index {i / 28}. &0x20000={first&0x20000}/0x{first&0x20000:X8} offset: {i:X8}"); + count++; + } + } + + Console.WriteLine($"Total found: {count}"); + + } + } +} \ No newline at end of file diff --git a/MeshUnpacker/MeshUnpacker.csproj b/MeshUnpacker/MeshUnpacker.csproj index 2f4fc77..85b4959 100644 --- a/MeshUnpacker/MeshUnpacker.csproj +++ b/MeshUnpacker/MeshUnpacker.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net9.0 enable enable diff --git a/MissionDataUnpacker/MissionDataUnpacker.csproj b/MissionDataUnpacker/MissionDataUnpacker.csproj index 2f4fc77..85b4959 100644 --- a/MissionDataUnpacker/MissionDataUnpacker.csproj +++ b/MissionDataUnpacker/MissionDataUnpacker.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net9.0 enable enable diff --git a/MissionTmaLib/MissionTmaLib.csproj b/MissionTmaLib/MissionTmaLib.csproj index 3a63532..17b910f 100644 --- a/MissionTmaLib/MissionTmaLib.csproj +++ b/MissionTmaLib/MissionTmaLib.csproj @@ -1,7 +1,7 @@  - net8.0 + net9.0 enable enable diff --git a/NResLib/NResLib.csproj b/NResLib/NResLib.csproj index 3a63532..17b910f 100644 --- a/NResLib/NResLib.csproj +++ b/NResLib/NResLib.csproj @@ -1,7 +1,7 @@  - net8.0 + net9.0 enable enable diff --git a/NResLib/NResPacker.cs b/NResLib/NResPacker.cs new file mode 100644 index 0000000..9942763 --- /dev/null +++ b/NResLib/NResPacker.cs @@ -0,0 +1,151 @@ +using System.Buffers.Binary; +using System.Text; + +namespace NResLib; + +public class NResPacker +{ + public static string Pack(NResArchive archive, string srcNresPath, string contentDirectoryPath, string targetFileDirectoryPath) + { + var diskFiles = Directory.GetFiles(contentDirectoryPath) + .Select(Path.GetFileName) + .ToList(); + + var fileOffset = 16; // 16 по умолчанию, т.к. есть заголовок в 16 байт. + + var metadataItems = new List(); + + foreach (var archiveFile in archive.Files) + { + var extension = Path.GetExtension(archiveFile.FileName); + var fileName = Path.GetFileNameWithoutExtension(archiveFile.FileName); + + if (extension == "") + { + extension = ".bin"; + } + + var targetFileName = $"{archiveFile.Index}_{archiveFile.FileType}_{fileName}{extension}"; + + if (diskFiles.All(x => x != targetFileName)) + { + return $"Не найдён файл {targetFileName}"; + } + + var filePath = Path.Combine(contentDirectoryPath, targetFileName); + + var fileInfo = new FileInfo(filePath); + + if (!fileInfo.Exists) + { + throw new Exception(); + } + + var newFileLength = (int)fileInfo.Length; + + var listItem = new ListMetadataItem( + archiveFile.FileType, + archiveFile.ElementCount, + archiveFile.Magic1, + newFileLength, + archiveFile.ElementSize, + archiveFile.FileName, + archiveFile.Magic3, + archiveFile.Magic4, + archiveFile.Magic5, + archiveFile.Magic6, + fileOffset, + archiveFile.Index + ); + + fileOffset += newFileLength; + + metadataItems.Add(listItem); + } + + var totalFileLength = + 16 + // заголовок + metadataItems.Sum(x => x.FileLength) + // сумма длин всех файлов + metadataItems.Count * 64; // длина всех метаданных + + var header = new NResArchiveHeader(archive.Header.NRes, archive.Header.Version, archive.Header.FileCount, totalFileLength); + + var targetArchive = new NResArchive(header, metadataItems); + + // имя архива = имени папки в которую архив распаковывали + string targetArchiveFileName = Path.GetFileName(srcNresPath)!; + + var targetArchivePath = Path.Combine(targetFileDirectoryPath, targetArchiveFileName); + + using var fs = new FileStream(targetArchivePath, FileMode.CreateNew); + + Span span = stackalloc byte[4]; + + span.Clear(); + Encoding.ASCII.GetBytes(header.NRes, span); + fs.Write(span); + BinaryPrimitives.WriteInt32LittleEndian(span, header.Version); + fs.Write(span); + BinaryPrimitives.WriteInt32LittleEndian(span, header.FileCount); + fs.Write(span); + BinaryPrimitives.WriteInt32LittleEndian(span, header.TotalFileLengthBytes); + fs.Write(span); + + foreach (var archiveFile in targetArchive.Files) + { + var extension = Path.GetExtension(archiveFile.FileName); + var fileName = Path.GetFileNameWithoutExtension(archiveFile.FileName); + + if (extension == "") + { + extension = ".bin"; + } + + var targetFileName = $"{archiveFile.Index}_{archiveFile.FileType}_{fileName}{extension}"; + + var filePath = Path.Combine(contentDirectoryPath, targetFileName); + using var srcFs = new FileStream(filePath, FileMode.Open); + + srcFs.CopyTo(fs); + } + + Span fileNameSpan = stackalloc byte[20]; + + foreach (var archiveFile in targetArchive.Files) + { + span.Clear(); + Encoding.ASCII.GetBytes(archiveFile.FileType, span); + fs.Write(span); + + BinaryPrimitives.WriteUInt32LittleEndian(span, archiveFile.ElementCount); + fs.Write(span); + BinaryPrimitives.WriteInt32LittleEndian(span, archiveFile.Magic1); + fs.Write(span); + BinaryPrimitives.WriteInt32LittleEndian(span, archiveFile.FileLength); + fs.Write(span); + BinaryPrimitives.WriteInt32LittleEndian(span, archiveFile.ElementSize); + fs.Write(span); + + fileNameSpan.Clear(); + Encoding.ASCII.GetBytes(archiveFile.FileName, fileNameSpan); + fs.Write(fileNameSpan); + + BinaryPrimitives.WriteInt32LittleEndian(span, archiveFile.Magic3); + fs.Write(span); + BinaryPrimitives.WriteInt32LittleEndian(span, archiveFile.Magic4); + fs.Write(span); + BinaryPrimitives.WriteInt32LittleEndian(span, archiveFile.Magic5); + fs.Write(span); + BinaryPrimitives.WriteInt32LittleEndian(span, archiveFile.Magic6); + fs.Write(span); + BinaryPrimitives.WriteInt32LittleEndian(span, archiveFile.OffsetInFile); + fs.Write(span); + BinaryPrimitives.WriteInt32LittleEndian(span, archiveFile.Index); + fs.Write(span); + } + + fs.Flush(); + + return "Запакован архив"; + } +} \ No newline at end of file diff --git a/NResUI/ImGuiUI/MainMenuBar.cs b/NResUI/ImGuiUI/MainMenuBar.cs index c005e54..b19a7dd 100644 --- a/NResUI/ImGuiUI/MainMenuBar.cs +++ b/NResUI/ImGuiUI/MainMenuBar.cs @@ -138,6 +138,34 @@ namespace NResUI.ImGuiUI } } + if (nResExplorerViewModel.HasFile) + { + if (ImGui.MenuItem("Запаковать NRes")) + { + messageBox.Show("Выберите папку с контентом NRES"); + var contentDirectoryPicker = Dialog.FolderPicker(); + + if (contentDirectoryPicker.IsOk) + { + var contentDirectoryPath = contentDirectoryPicker.Path; + + var targetFileDirectoryPicker = Dialog.FolderPicker(); + + if (targetFileDirectoryPicker.IsOk) + { + var targetFileDirectory = targetFileDirectoryPicker.Path; + + var packResult = NResPacker.Pack( + nResExplorerViewModel.Archive!, + nResExplorerViewModel.Path!, + contentDirectoryPath, targetFileDirectory); + + messageBox.Show(packResult); + } + } + } + } + ImGui.EndMenu(); } diff --git a/NResUI/ImGuiUI/NResExplorerPanel.cs b/NResUI/ImGuiUI/NResExplorerPanel.cs index 173d0e7..a375043 100644 --- a/NResUI/ImGuiUI/NResExplorerPanel.cs +++ b/NResUI/ImGuiUI/NResExplorerPanel.cs @@ -82,8 +82,8 @@ public class NResExplorerPanel : IImGuiPanel ); ImGui.TableNextColumn(); ImGui.Text( - _viewModel.Archive.Files[i] - .ElementSize.ToString() + "0x" + _viewModel.Archive.Files[i] + .ElementSize.ToString("X2") ); ImGui.TableNextColumn(); ImGui.Text(_viewModel.Archive.Files[i].FileName); diff --git a/NResUI/NResUI.csproj b/NResUI/NResUI.csproj index 17ac16d..8e20410 100644 --- a/NResUI/NResUI.csproj +++ b/NResUI/NResUI.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net9.0 enable enable diff --git a/ParkanPlayground.sln b/ParkanPlayground.sln index 7f26e83..d8118b4 100644 --- a/ParkanPlayground.sln +++ b/ParkanPlayground.sln @@ -32,6 +32,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "X86Disassembler", "X86Disas EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "X86DisassemblerTests", "X86DisassemblerTests\X86DisassemblerTests.csproj", "{D6A1F5A9-0C7A-4F8F-B8C5-83E9D3F3A1D5}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LandscapeExplorer", "LandscapeExplorer\LandscapeExplorer.csproj", "{2700BD3F-DC67-4B58-8F73-F790AA68E4FE}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -94,5 +96,9 @@ Global {D6A1F5A9-0C7A-4F8F-B8C5-83E9D3F3A1D5}.Debug|Any CPU.Build.0 = Debug|Any CPU {D6A1F5A9-0C7A-4F8F-B8C5-83E9D3F3A1D5}.Release|Any CPU.ActiveCfg = Release|Any CPU {D6A1F5A9-0C7A-4F8F-B8C5-83E9D3F3A1D5}.Release|Any CPU.Build.0 = Release|Any CPU + {2700BD3F-DC67-4B58-8F73-F790AA68E4FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2700BD3F-DC67-4B58-8F73-F790AA68E4FE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2700BD3F-DC67-4B58-8F73-F790AA68E4FE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2700BD3F-DC67-4B58-8F73-F790AA68E4FE}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/ParkanPlayground.sln.DotSettings.user b/ParkanPlayground.sln.DotSettings.user index 4d46480..0006605 100644 --- a/ParkanPlayground.sln.DotSettings.user +++ b/ParkanPlayground.sln.DotSettings.user @@ -5,16 +5,18 @@ ForceIncluded ForceIncluded ForceIncluded + ForceIncluded ForceIncluded ForceIncluded ForceIncluded ForceIncluded ForceIncluded + ForceIncluded ForceIncluded ForceIncluded ForceIncluded ForceIncluded - C:\Users\Admin\AppData\Local\JetBrains\Rider2024.3\resharper-host\temp\Rider\vAny\CoverageData\_ParkanPlayground.1073341822\Snapshot\snapshot.utdcvr + <SessionState ContinuousTestingMode="0" IsActive="True" Name="All tests from &lt;X86DisassemblerTests&gt;" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> <Project Location="C:\Projects\CSharp\ParkanPlayground\X86DisassemblerTests" Presentation="&lt;X86DisassemblerTests&gt;" /> </SessionState> diff --git a/ParkanPlayground/ParkanPlayground.csproj b/ParkanPlayground/ParkanPlayground.csproj index 527979a..1d2a154 100644 --- a/ParkanPlayground/ParkanPlayground.csproj +++ b/ParkanPlayground/ParkanPlayground.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net9.0 enable enable diff --git a/ScrLib/ScrLib.csproj b/ScrLib/ScrLib.csproj index 3a63532..17b910f 100644 --- a/ScrLib/ScrLib.csproj +++ b/ScrLib/ScrLib.csproj @@ -1,7 +1,7 @@  - net8.0 + net9.0 enable enable diff --git a/TexmLib/TexmLib.csproj b/TexmLib/TexmLib.csproj index a1fcf00..3f6de9c 100644 --- a/TexmLib/TexmLib.csproj +++ b/TexmLib/TexmLib.csproj @@ -1,7 +1,7 @@  - net8.0 + net9.0 enable enable diff --git a/TextureDecoder/TextureDecoder.csproj b/TextureDecoder/TextureDecoder.csproj index 50c9527..bcf39fc 100644 --- a/TextureDecoder/TextureDecoder.csproj +++ b/TextureDecoder/TextureDecoder.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net9.0 enable enable diff --git a/VarsetLib/VarsetLib.csproj b/VarsetLib/VarsetLib.csproj index 3a63532..17b910f 100644 --- a/VarsetLib/VarsetLib.csproj +++ b/VarsetLib/VarsetLib.csproj @@ -1,7 +1,7 @@  - net8.0 + net9.0 enable enable diff --git a/Visualisator/Visualisator.csproj b/Visualisator/Visualisator.csproj index b9b125f..c4b505b 100644 --- a/Visualisator/Visualisator.csproj +++ b/Visualisator/Visualisator.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net9.0 enable enable true diff --git a/X86Disassembler/X86Disassembler.csproj b/X86Disassembler/X86Disassembler.csproj index 91b464a..694035b 100644 --- a/X86Disassembler/X86Disassembler.csproj +++ b/X86Disassembler/X86Disassembler.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net9.0 enable enable diff --git a/X86DisassemblerTests/X86DisassemblerTests.csproj b/X86DisassemblerTests/X86DisassemblerTests.csproj index 2b293db..2890ae4 100644 --- a/X86DisassemblerTests/X86DisassemblerTests.csproj +++ b/X86DisassemblerTests/X86DisassemblerTests.csproj @@ -1,7 +1,7 @@ - net8.0 + net9.0 enable enable