From 3a394355c9fca9a13c691c5d605b04b35453a5db Mon Sep 17 00:00:00 2001 From: ZNH <35349300+kingsznhone@users.noreply.github.com> Date: Tue, 28 Apr 2026 02:12:12 +0800 Subject: [PATCH 1/7] merge project upgrade dotnet 10. merge project. using system.text.json --- RePKG.Application/RePKG.Application.csproj | 18 -------- .../RePKG.Application.csproj.DotSettings | 2 - .../Constants.cs | 2 +- .../Exceptions/EnumNotValidException.cs | 2 +- .../Exceptions/UnknownMagicException.cs | 2 +- .../Exceptions/UnsafeTexException.cs | 2 +- .../Extensions.cs | 2 +- .../Package/PackageReader.cs | 2 +- .../Package/PackageWriter.cs | 2 +- RePKG.Core/RePKG.Core.csproj | 11 ++++- .../Texture/Helpers/DXT.cs | 2 +- .../Texture/Helpers/RG88.cs | 2 +- .../Texture/TexFrameInfoContainerReader.cs | 4 +- .../Texture/TexHeaderReader.cs | 4 +- .../Texture/TexImageContainerReader.cs | 4 +- .../Texture/TexImageReader.cs | 4 +- .../Texture/TexJsonInfoGenerator.cs | 16 +++---- .../Texture/TexMipmapDecompressor.cs | 4 +- .../Texture/TexReader.cs | 4 +- .../Texture/TexToImageConverter.cs | 4 +- .../Writer/TexFrameInfoContainerWriter.cs | 4 +- .../Texture/Writer/TexHeaderWriter.cs | 2 +- .../Texture/Writer/TexImageContainerWriter.cs | 4 +- .../Texture/Writer/TexImageWriter.cs | 2 +- .../Texture/Writer/TexMipmapCompressor.cs | 2 +- .../Texture/Writer/TexWriter.cs | 4 +- RePKG.Tests/PkgWriterTests.cs | 3 +- RePKG.Tests/RePKG.Tests.csproj | 6 ++- RePKG.Tests/TexDecompressingTests.cs | 3 +- RePKG.Tests/TexWriterTests.cs | 3 +- RePKG.sln | 43 ------------------- RePKG.slnx | 5 +++ RePKG/Command/Extract.cs | 23 +++++----- RePKG/Command/Info.cs | 34 ++++++++------- RePKG/Helper.cs | 17 +++----- RePKG/RePKG.csproj | 13 +++--- 36 files changed, 102 insertions(+), 159 deletions(-) delete mode 100644 RePKG.Application/RePKG.Application.csproj delete mode 100644 RePKG.Application/RePKG.Application.csproj.DotSettings rename {RePKG.Application => RePKG.Core}/Constants.cs (90%) rename {RePKG.Application => RePKG.Core}/Exceptions/EnumNotValidException.cs (90%) rename {RePKG.Application => RePKG.Core}/Exceptions/UnknownMagicException.cs (92%) rename {RePKG.Application => RePKG.Core}/Exceptions/UnsafeTexException.cs (89%) rename {RePKG.Application => RePKG.Core}/Extensions.cs (98%) rename {RePKG.Application => RePKG.Core}/Package/PackageReader.cs (98%) rename {RePKG.Application => RePKG.Core}/Package/PackageWriter.cs (98%) rename {RePKG.Application => RePKG.Core}/Texture/Helpers/DXT.cs (99%) rename {RePKG.Application => RePKG.Core}/Texture/Helpers/RG88.cs (99%) rename {RePKG.Application => RePKG.Core}/Texture/TexFrameInfoContainerReader.cs (97%) rename {RePKG.Application => RePKG.Core}/Texture/TexHeaderReader.cs (92%) rename {RePKG.Application => RePKG.Core}/Texture/TexImageContainerReader.cs (97%) rename {RePKG.Application => RePKG.Core}/Texture/TexImageReader.cs (98%) rename {RePKG.Application => RePKG.Core}/Texture/TexJsonInfoGenerator.cs (85%) rename {RePKG.Application => RePKG.Core}/Texture/TexMipmapDecompressor.cs (95%) rename {RePKG.Application => RePKG.Core}/Texture/TexReader.cs (96%) rename {RePKG.Application => RePKG.Core}/Texture/TexToImageConverter.cs (98%) rename {RePKG.Application => RePKG.Core}/Texture/Writer/TexFrameInfoContainerWriter.cs (97%) rename {RePKG.Application => RePKG.Core}/Texture/Writer/TexHeaderWriter.cs (95%) rename {RePKG.Application => RePKG.Core}/Texture/Writer/TexImageContainerWriter.cs (95%) rename {RePKG.Application => RePKG.Core}/Texture/Writer/TexImageWriter.cs (98%) rename {RePKG.Application => RePKG.Core}/Texture/Writer/TexMipmapCompressor.cs (97%) rename {RePKG.Application => RePKG.Core}/Texture/Writer/TexWriter.cs (96%) delete mode 100644 RePKG.sln create mode 100644 RePKG.slnx diff --git a/RePKG.Application/RePKG.Application.csproj b/RePKG.Application/RePKG.Application.csproj deleted file mode 100644 index 64b2f6b..0000000 --- a/RePKG.Application/RePKG.Application.csproj +++ /dev/null @@ -1,18 +0,0 @@ - - - netstandard2.0 - 0.4.0 - Copyright © NotScuffed 2025 - - - - - - - - - - - - - diff --git a/RePKG.Application/RePKG.Application.csproj.DotSettings b/RePKG.Application/RePKG.Application.csproj.DotSettings deleted file mode 100644 index 65899f2..0000000 --- a/RePKG.Application/RePKG.Application.csproj.DotSettings +++ /dev/null @@ -1,2 +0,0 @@ - - True \ No newline at end of file diff --git a/RePKG.Application/Constants.cs b/RePKG.Core/Constants.cs similarity index 90% rename from RePKG.Application/Constants.cs rename to RePKG.Core/Constants.cs index 225bdb2..a2670c0 100644 --- a/RePKG.Application/Constants.cs +++ b/RePKG.Core/Constants.cs @@ -1,4 +1,4 @@ -namespace RePKG.Application +namespace RePKG.Core { internal static class Constants { diff --git a/RePKG.Application/Exceptions/EnumNotValidException.cs b/RePKG.Core/Exceptions/EnumNotValidException.cs similarity index 90% rename from RePKG.Application/Exceptions/EnumNotValidException.cs rename to RePKG.Core/Exceptions/EnumNotValidException.cs index 234e919..1d721f5 100644 --- a/RePKG.Application/Exceptions/EnumNotValidException.cs +++ b/RePKG.Core/Exceptions/EnumNotValidException.cs @@ -1,6 +1,6 @@ using System; -namespace RePKG.Application.Exceptions +namespace RePKG.Core.Exceptions { /// /// Thrown when enum raw value doesn't match any label diff --git a/RePKG.Application/Exceptions/UnknownMagicException.cs b/RePKG.Core/Exceptions/UnknownMagicException.cs similarity index 92% rename from RePKG.Application/Exceptions/UnknownMagicException.cs rename to RePKG.Core/Exceptions/UnknownMagicException.cs index 62db092..b2f0c61 100644 --- a/RePKG.Application/Exceptions/UnknownMagicException.cs +++ b/RePKG.Core/Exceptions/UnknownMagicException.cs @@ -1,6 +1,6 @@ using System; -namespace RePKG.Application.Exceptions +namespace RePKG.Core.Exceptions { /// /// Thrown on magic values that have not been tested before diff --git a/RePKG.Application/Exceptions/UnsafeTexException.cs b/RePKG.Core/Exceptions/UnsafeTexException.cs similarity index 89% rename from RePKG.Application/Exceptions/UnsafeTexException.cs rename to RePKG.Core/Exceptions/UnsafeTexException.cs index 6dded54..a1d29f3 100644 --- a/RePKG.Application/Exceptions/UnsafeTexException.cs +++ b/RePKG.Core/Exceptions/UnsafeTexException.cs @@ -1,6 +1,6 @@ using System; -namespace RePKG.Application.Exceptions +namespace RePKG.Core.Exceptions { /// /// Thrown on unorganic values. diff --git a/RePKG.Application/Extensions.cs b/RePKG.Core/Extensions.cs similarity index 98% rename from RePKG.Application/Extensions.cs rename to RePKG.Core/Extensions.cs index 5a8924f..8d7a56f 100644 --- a/RePKG.Application/Extensions.cs +++ b/RePKG.Core/Extensions.cs @@ -2,7 +2,7 @@ using System.IO; using System.Text; -namespace RePKG.Application +namespace RePKG.Core { internal static class Extensions { diff --git a/RePKG.Application/Package/PackageReader.cs b/RePKG.Core/Package/PackageReader.cs similarity index 98% rename from RePKG.Application/Package/PackageReader.cs rename to RePKG.Core/Package/PackageReader.cs index a7e9a3e..f580ca2 100644 --- a/RePKG.Application/Package/PackageReader.cs +++ b/RePKG.Core/Package/PackageReader.cs @@ -4,7 +4,7 @@ using RePKG.Core.Package; using RePKG.Core.Package.Interfaces; -namespace RePKG.Application.Package +namespace RePKG.Core.Package { public class PackageReader : IPackageReader { diff --git a/RePKG.Application/Package/PackageWriter.cs b/RePKG.Core/Package/PackageWriter.cs similarity index 98% rename from RePKG.Application/Package/PackageWriter.cs rename to RePKG.Core/Package/PackageWriter.cs index 18f02d7..88a0783 100644 --- a/RePKG.Application/Package/PackageWriter.cs +++ b/RePKG.Core/Package/PackageWriter.cs @@ -4,7 +4,7 @@ using RePKG.Core.Package; using RePKG.Core.Package.Interfaces; -namespace RePKG.Application.Package +namespace RePKG.Core.Package { public class PackageWriter : IPackageWriter { diff --git a/RePKG.Core/RePKG.Core.csproj b/RePKG.Core/RePKG.Core.csproj index 17562c0..b22c0b5 100644 --- a/RePKG.Core/RePKG.Core.csproj +++ b/RePKG.Core/RePKG.Core.csproj @@ -1,7 +1,14 @@  - netstandard2.0 - 0.4.0 + net10.0 + 0.5.0 Copyright © NotScuffed 2025 + enable + enable + + + + + diff --git a/RePKG.Application/Texture/Helpers/DXT.cs b/RePKG.Core/Texture/Helpers/DXT.cs similarity index 99% rename from RePKG.Application/Texture/Helpers/DXT.cs rename to RePKG.Core/Texture/Helpers/DXT.cs index bea30a9..3457921 100644 --- a/RePKG.Application/Texture/Helpers/DXT.cs +++ b/RePKG.Core/Texture/Helpers/DXT.cs @@ -23,7 +23,7 @@ using RePKG.Core.Texture; -namespace RePKG.Application.Texture.Helpers +namespace RePKG.Core.Texture.Helpers { public static class DXT { diff --git a/RePKG.Application/Texture/Helpers/RG88.cs b/RePKG.Core/Texture/Helpers/RG88.cs similarity index 99% rename from RePKG.Application/Texture/Helpers/RG88.cs rename to RePKG.Core/Texture/Helpers/RG88.cs index e1caf47..7ed0d09 100644 --- a/RePKG.Application/Texture/Helpers/RG88.cs +++ b/RePKG.Core/Texture/Helpers/RG88.cs @@ -4,7 +4,7 @@ using SixLabors.ImageSharp; using SixLabors.ImageSharp.PixelFormats; -namespace RePKG.Application.Texture.Helpers +namespace RePKG.Core.Texture.Helpers { [StructLayout(LayoutKind.Sequential)] internal struct RG88 : IPixel, IPackedVector diff --git a/RePKG.Application/Texture/TexFrameInfoContainerReader.cs b/RePKG.Core/Texture/TexFrameInfoContainerReader.cs similarity index 97% rename from RePKG.Application/Texture/TexFrameInfoContainerReader.cs rename to RePKG.Core/Texture/TexFrameInfoContainerReader.cs index 7134d24..147cd12 100644 --- a/RePKG.Application/Texture/TexFrameInfoContainerReader.cs +++ b/RePKG.Core/Texture/TexFrameInfoContainerReader.cs @@ -1,9 +1,9 @@ using System; using System.IO; -using RePKG.Application.Exceptions; +using RePKG.Core.Exceptions; using RePKG.Core.Texture; -namespace RePKG.Application.Texture +namespace RePKG.Core.Texture { public class TexFrameInfoContainerReader : ITexFrameInfoContainerReader { diff --git a/RePKG.Application/Texture/TexHeaderReader.cs b/RePKG.Core/Texture/TexHeaderReader.cs similarity index 92% rename from RePKG.Application/Texture/TexHeaderReader.cs rename to RePKG.Core/Texture/TexHeaderReader.cs index 39963b0..b127bdd 100644 --- a/RePKG.Application/Texture/TexHeaderReader.cs +++ b/RePKG.Core/Texture/TexHeaderReader.cs @@ -1,9 +1,9 @@ using System; using System.IO; -using RePKG.Application.Exceptions; +using RePKG.Core.Exceptions; using RePKG.Core.Texture; -namespace RePKG.Application.Texture +namespace RePKG.Core.Texture { public class TexHeaderReader : ITexHeaderReader { diff --git a/RePKG.Application/Texture/TexImageContainerReader.cs b/RePKG.Core/Texture/TexImageContainerReader.cs similarity index 97% rename from RePKG.Application/Texture/TexImageContainerReader.cs rename to RePKG.Core/Texture/TexImageContainerReader.cs index dfb1ed3..6cfe3e2 100644 --- a/RePKG.Application/Texture/TexImageContainerReader.cs +++ b/RePKG.Core/Texture/TexImageContainerReader.cs @@ -1,9 +1,9 @@ using System; using System.IO; -using RePKG.Application.Exceptions; +using RePKG.Core.Exceptions; using RePKG.Core.Texture; -namespace RePKG.Application.Texture +namespace RePKG.Core.Texture { public class TexImageContainerReader : ITexImageContainerReader { diff --git a/RePKG.Application/Texture/TexImageReader.cs b/RePKG.Core/Texture/TexImageReader.cs similarity index 98% rename from RePKG.Application/Texture/TexImageReader.cs rename to RePKG.Core/Texture/TexImageReader.cs index 7c5fa5e..495b467 100644 --- a/RePKG.Application/Texture/TexImageReader.cs +++ b/RePKG.Core/Texture/TexImageReader.cs @@ -1,9 +1,9 @@ using System; using System.IO; -using RePKG.Application.Exceptions; +using RePKG.Core.Exceptions; using RePKG.Core.Texture; -namespace RePKG.Application.Texture +namespace RePKG.Core.Texture { public class TexImageReader : ITexImageReader { diff --git a/RePKG.Application/Texture/TexJsonInfoGenerator.cs b/RePKG.Core/Texture/TexJsonInfoGenerator.cs similarity index 85% rename from RePKG.Application/Texture/TexJsonInfoGenerator.cs rename to RePKG.Core/Texture/TexJsonInfoGenerator.cs index 0383bc1..ae862bf 100644 --- a/RePKG.Application/Texture/TexJsonInfoGenerator.cs +++ b/RePKG.Core/Texture/TexJsonInfoGenerator.cs @@ -1,9 +1,9 @@ using System; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; +using System.Text.Json; +using System.Text.Json.Nodes; using RePKG.Core.Texture; -namespace RePKG.Application.Texture +namespace RePKG.Core.Texture { public class TexJsonInfoGenerator : ITexJsonInfoGenerator { @@ -11,7 +11,7 @@ public string GenerateInfo(ITex tex) { if (tex == null) throw new ArgumentNullException(nameof(tex)); - var json = new JObject + var json = new JsonObject { ["bleedtransparentcolors"] = true, ["clampuvs"] = tex.HasFlag(TexFlags.ClampUVs), @@ -27,9 +27,9 @@ public string GenerateInfo(ITex tex) if (tex.FrameInfoContainer == null) throw new InvalidOperationException("TEX is animated but doesn't have frame info container"); - json["spritesheetsequences"] = new JArray + json["spritesheetsequences"] = new JsonArray { - new JObject + new JsonObject { ["duration"] = 1, // not sure what this value is used for ["frames"] = tex.FrameInfoContainer.Frames.Count, @@ -39,7 +39,7 @@ public string GenerateInfo(ITex tex) }; } - return JsonConvert.SerializeObject(json, Formatting.Indented); + return json.ToJsonString(new JsonSerializerOptions { WriteIndented = true }); } private static bool NumberIsPowerOfTwo(int n) @@ -58,4 +58,4 @@ private static bool NumberIsPowerOfTwo(int n) return true; } } -} \ No newline at end of file +} diff --git a/RePKG.Application/Texture/TexMipmapDecompressor.cs b/RePKG.Core/Texture/TexMipmapDecompressor.cs similarity index 95% rename from RePKG.Application/Texture/TexMipmapDecompressor.cs rename to RePKG.Core/Texture/TexMipmapDecompressor.cs index b036b9a..f0137b2 100644 --- a/RePKG.Application/Texture/TexMipmapDecompressor.cs +++ b/RePKG.Core/Texture/TexMipmapDecompressor.cs @@ -1,9 +1,9 @@ using System; using K4os.Compression.LZ4; -using RePKG.Application.Texture.Helpers; +using RePKG.Core.Texture.Helpers; using RePKG.Core.Texture; -namespace RePKG.Application.Texture +namespace RePKG.Core.Texture { public class TexMipmapDecompressor : ITexMipmapDecompressor { diff --git a/RePKG.Application/Texture/TexReader.cs b/RePKG.Core/Texture/TexReader.cs similarity index 96% rename from RePKG.Application/Texture/TexReader.cs rename to RePKG.Core/Texture/TexReader.cs index 82a8c4b..308c16c 100644 --- a/RePKG.Application/Texture/TexReader.cs +++ b/RePKG.Core/Texture/TexReader.cs @@ -1,9 +1,9 @@ using System; using System.IO; -using RePKG.Application.Exceptions; +using RePKG.Core.Exceptions; using RePKG.Core.Texture; -namespace RePKG.Application.Texture +namespace RePKG.Core.Texture { public class TexReader : ITexReader { diff --git a/RePKG.Application/Texture/TexToImageConverter.cs b/RePKG.Core/Texture/TexToImageConverter.cs similarity index 98% rename from RePKG.Application/Texture/TexToImageConverter.cs rename to RePKG.Core/Texture/TexToImageConverter.cs index 2839e25..81e6207 100644 --- a/RePKG.Application/Texture/TexToImageConverter.cs +++ b/RePKG.Core/Texture/TexToImageConverter.cs @@ -1,14 +1,14 @@ using System; using System.IO; using System.Text; -using RePKG.Application.Texture.Helpers; +using RePKG.Core.Texture.Helpers; using RePKG.Core.Texture; using SixLabors.ImageSharp; using SixLabors.ImageSharp.Formats.Gif; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; -namespace RePKG.Application.Texture +namespace RePKG.Core.Texture { public class TexToImageConverter { diff --git a/RePKG.Application/Texture/Writer/TexFrameInfoContainerWriter.cs b/RePKG.Core/Texture/Writer/TexFrameInfoContainerWriter.cs similarity index 97% rename from RePKG.Application/Texture/Writer/TexFrameInfoContainerWriter.cs rename to RePKG.Core/Texture/Writer/TexFrameInfoContainerWriter.cs index 2356633..dbbdb95 100644 --- a/RePKG.Application/Texture/Writer/TexFrameInfoContainerWriter.cs +++ b/RePKG.Core/Texture/Writer/TexFrameInfoContainerWriter.cs @@ -1,9 +1,9 @@ using System; using System.IO; -using RePKG.Application.Exceptions; +using RePKG.Core.Exceptions; using RePKG.Core.Texture; -namespace RePKG.Application.Texture +namespace RePKG.Core.Texture { public class TexFrameInfoContainerWriter : ITexFrameInfoContainerWriter { diff --git a/RePKG.Application/Texture/Writer/TexHeaderWriter.cs b/RePKG.Core/Texture/Writer/TexHeaderWriter.cs similarity index 95% rename from RePKG.Application/Texture/Writer/TexHeaderWriter.cs rename to RePKG.Core/Texture/Writer/TexHeaderWriter.cs index 45915b7..8e88895 100644 --- a/RePKG.Application/Texture/Writer/TexHeaderWriter.cs +++ b/RePKG.Core/Texture/Writer/TexHeaderWriter.cs @@ -2,7 +2,7 @@ using System.IO; using RePKG.Core.Texture; -namespace RePKG.Application.Texture +namespace RePKG.Core.Texture { public class TexHeaderWriter : ITexHeaderWriter { diff --git a/RePKG.Application/Texture/Writer/TexImageContainerWriter.cs b/RePKG.Core/Texture/Writer/TexImageContainerWriter.cs similarity index 95% rename from RePKG.Application/Texture/Writer/TexImageContainerWriter.cs rename to RePKG.Core/Texture/Writer/TexImageContainerWriter.cs index b422296..8ae021e 100644 --- a/RePKG.Application/Texture/Writer/TexImageContainerWriter.cs +++ b/RePKG.Core/Texture/Writer/TexImageContainerWriter.cs @@ -1,9 +1,9 @@ using System; using System.IO; -using RePKG.Application.Exceptions; +using RePKG.Core.Exceptions; using RePKG.Core.Texture; -namespace RePKG.Application.Texture +namespace RePKG.Core.Texture { public class TexImageContainerWriter : ITexImageContainerWriter { diff --git a/RePKG.Application/Texture/Writer/TexImageWriter.cs b/RePKG.Core/Texture/Writer/TexImageWriter.cs similarity index 98% rename from RePKG.Application/Texture/Writer/TexImageWriter.cs rename to RePKG.Core/Texture/Writer/TexImageWriter.cs index 954452f..682eb54 100644 --- a/RePKG.Application/Texture/Writer/TexImageWriter.cs +++ b/RePKG.Core/Texture/Writer/TexImageWriter.cs @@ -2,7 +2,7 @@ using System.IO; using RePKG.Core.Texture; -namespace RePKG.Application.Texture +namespace RePKG.Core.Texture { public class TexImageWriter : ITexImageWriter { diff --git a/RePKG.Application/Texture/Writer/TexMipmapCompressor.cs b/RePKG.Core/Texture/Writer/TexMipmapCompressor.cs similarity index 97% rename from RePKG.Application/Texture/Writer/TexMipmapCompressor.cs rename to RePKG.Core/Texture/Writer/TexMipmapCompressor.cs index cb69ec0..edc8ded 100644 --- a/RePKG.Application/Texture/Writer/TexMipmapCompressor.cs +++ b/RePKG.Core/Texture/Writer/TexMipmapCompressor.cs @@ -2,7 +2,7 @@ using K4os.Compression.LZ4; using RePKG.Core.Texture; -namespace RePKG.Application.Texture +namespace RePKG.Core.Texture { public class TexMipmapCompressor : ITexMipmapCompressor { diff --git a/RePKG.Application/Texture/Writer/TexWriter.cs b/RePKG.Core/Texture/Writer/TexWriter.cs similarity index 96% rename from RePKG.Application/Texture/Writer/TexWriter.cs rename to RePKG.Core/Texture/Writer/TexWriter.cs index d0f164a..d491d7e 100644 --- a/RePKG.Application/Texture/Writer/TexWriter.cs +++ b/RePKG.Core/Texture/Writer/TexWriter.cs @@ -1,9 +1,9 @@ using System; using System.IO; -using RePKG.Application.Exceptions; +using RePKG.Core.Exceptions; using RePKG.Core.Texture; -namespace RePKG.Application.Texture +namespace RePKG.Core.Texture { public class TexWriter : ITexWriter { diff --git a/RePKG.Tests/PkgWriterTests.cs b/RePKG.Tests/PkgWriterTests.cs index b7ec8ec..40bc197 100644 --- a/RePKG.Tests/PkgWriterTests.cs +++ b/RePKG.Tests/PkgWriterTests.cs @@ -1,7 +1,6 @@ using System.IO; using System.Text; using NUnit.Framework; -using RePKG.Application.Package; using RePKG.Core.Package; using RePKG.Core.Package.Interfaces; @@ -61,4 +60,4 @@ public void TestWriteAndRead() } } } -} \ No newline at end of file +} diff --git a/RePKG.Tests/RePKG.Tests.csproj b/RePKG.Tests/RePKG.Tests.csproj index b5df6b5..d7ac70e 100644 --- a/RePKG.Tests/RePKG.Tests.csproj +++ b/RePKG.Tests/RePKG.Tests.csproj @@ -1,8 +1,10 @@  - net472 + net10.0 false true + enable + enable @@ -12,6 +14,6 @@ - + diff --git a/RePKG.Tests/TexDecompressingTests.cs b/RePKG.Tests/TexDecompressingTests.cs index 72bab05..4cb44f3 100644 --- a/RePKG.Tests/TexDecompressingTests.cs +++ b/RePKG.Tests/TexDecompressingTests.cs @@ -2,7 +2,6 @@ using System.IO; using System.Text; using NUnit.Framework; -using RePKG.Application.Texture; using RePKG.Core.Texture; namespace RePKG.Tests @@ -116,4 +115,4 @@ public static void ValidateBytes(byte[] bytes, string name) } } } -} \ No newline at end of file +} diff --git a/RePKG.Tests/TexWriterTests.cs b/RePKG.Tests/TexWriterTests.cs index cfc6935..3cba3f8 100644 --- a/RePKG.Tests/TexWriterTests.cs +++ b/RePKG.Tests/TexWriterTests.cs @@ -2,7 +2,6 @@ using System.IO; using System.Text; using NUnit.Framework; -using RePKG.Application.Texture; using RePKG.Core.Texture; namespace RePKG.Tests @@ -83,4 +82,4 @@ public void TestWriteAndRead(string name) } } } -} \ No newline at end of file +} diff --git a/RePKG.sln b/RePKG.sln deleted file mode 100644 index 788a73a..0000000 --- a/RePKG.sln +++ /dev/null @@ -1,43 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.28307.271 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RePKG", "RePKG\RePKG.csproj", "{A014E252-FB25-4388-B17A-8DD1956B2093}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RePKG.Tests", "RePKG.Tests\RePKG.Tests.csproj", "{00DDEB73-18AF-463B-BEDC-7BA3DCBFA223}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RePKG.Core", "RePKG.Core\RePKG.Core.csproj", "{43CFFA8A-BDB4-4A09-9D07-95FA09CCCEC9}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RePKG.Application", "RePKG.Application\RePKG.Application.csproj", "{DDFFD8D1-3961-4F1B-B778-1CAC5622AA19}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {A014E252-FB25-4388-B17A-8DD1956B2093}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A014E252-FB25-4388-B17A-8DD1956B2093}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A014E252-FB25-4388-B17A-8DD1956B2093}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A014E252-FB25-4388-B17A-8DD1956B2093}.Release|Any CPU.Build.0 = Release|Any CPU - {00DDEB73-18AF-463B-BEDC-7BA3DCBFA223}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {00DDEB73-18AF-463B-BEDC-7BA3DCBFA223}.Debug|Any CPU.Build.0 = Debug|Any CPU - {00DDEB73-18AF-463B-BEDC-7BA3DCBFA223}.Release|Any CPU.ActiveCfg = Release|Any CPU - {00DDEB73-18AF-463B-BEDC-7BA3DCBFA223}.Release|Any CPU.Build.0 = Release|Any CPU - {43CFFA8A-BDB4-4A09-9D07-95FA09CCCEC9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {43CFFA8A-BDB4-4A09-9D07-95FA09CCCEC9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {43CFFA8A-BDB4-4A09-9D07-95FA09CCCEC9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {43CFFA8A-BDB4-4A09-9D07-95FA09CCCEC9}.Release|Any CPU.Build.0 = Release|Any CPU - {DDFFD8D1-3961-4F1B-B778-1CAC5622AA19}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DDFFD8D1-3961-4F1B-B778-1CAC5622AA19}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DDFFD8D1-3961-4F1B-B778-1CAC5622AA19}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DDFFD8D1-3961-4F1B-B778-1CAC5622AA19}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {6B20EA40-8A64-4322-911F-56D09593E7E2} - EndGlobalSection -EndGlobal diff --git a/RePKG.slnx b/RePKG.slnx new file mode 100644 index 0000000..8aeeaa3 --- /dev/null +++ b/RePKG.slnx @@ -0,0 +1,5 @@ + + + + + diff --git a/RePKG/Command/Extract.cs b/RePKG/Command/Extract.cs index 8e4efce..d99d230 100644 --- a/RePKG/Command/Extract.cs +++ b/RePKG/Command/Extract.cs @@ -4,14 +4,12 @@ using System.IO; using System.Linq; using System.Text; +using System.Text.Json.Nodes; using CommandLine; -using Newtonsoft.Json; -using RePKG.Application.Package; -using RePKG.Application.Texture; using RePKG.Core.Package; +using RePKG.Core.Texture; using RePKG.Core.Package.Enums; using RePKG.Core.Package.Interfaces; -using RePKG.Core.Texture; namespace RePKG.Command { @@ -186,7 +184,7 @@ private static void ExtractPkg(FileInfo file, bool appendFolderName = false, str Console.WriteLine($"\r\n### Extracting package: {file.FullName}"); // Load package - Package package; + Core.Package.Package package; using (var reader = new BinaryReader(file.Open(FileMode.Open, FileAccess.Read, FileShare.Read))) { @@ -310,9 +308,12 @@ private static void GetProjectInfo(FileInfo packageFile, ref string title, ref s if (projectJson.Length == 0 || !projectJson[0].Exists) return; - dynamic json = JsonConvert.DeserializeObject(File.ReadAllText(projectJson[0].FullName)); - title = json.title; - preview = json.preview; + var json = JsonNode.Parse(File.ReadAllText(projectJson[0].FullName)); + if (json is JsonObject obj) + { + title = obj["title"]?.GetValue() ?? title; + preview = obj["preview"]?.GetValue() ?? preview; + } } private static void GetProjectFolderNameAndPreviewImage(FileInfo packageFile, string defaultProjectName, @@ -381,10 +382,10 @@ public class ExtractOptions public string OutputDirectory { get; set; } [Option('i', "ignoreexts", HelpText = - "Don't extract files with specified extensions (delimited by comma \",\")")] + "Don't extract files with specified extensions (delimited by comma \",\"")] public string IgnoreExts { get; set; } - [Option('e', "onlyexts", HelpText = "Only extract files with specified extensions (delimited by comma \",\")")] + [Option('e', "onlyexts", HelpText = "Only extract files with specified extensions (delimited by comma \",\"")] public string OnlyExts { get; set; } [Option('t', "tex", HelpText = "Convert all tex files into images from specified directory in input")] @@ -413,4 +414,4 @@ public class ExtractOptions [Value(0, Required = true, HelpText = "Path to file/directory", MetaName = "Input")] public string Input { get; set; } } -} \ No newline at end of file +} diff --git a/RePKG/Command/Info.cs b/RePKG/Command/Info.cs index 2a105a2..e16b1be 100644 --- a/RePKG/Command/Info.cs +++ b/RePKG/Command/Info.cs @@ -2,9 +2,8 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Text.Json.Nodes; using CommandLine; -using Newtonsoft.Json; -using RePKG.Application.Package; using RePKG.Core.Package; using RePKG.Core.Package.Interfaces; @@ -92,25 +91,26 @@ private static void InfoPkg(FileInfo file, string name) Console.WriteLine($"\r\n### Package info: {name}"); - if (projectInfo != null && _projectInfoToPrint?.Length > 0) + if (projectInfo is JsonObject projectJson && _projectInfoToPrint?.Length > 0) { IEnumerable projectInfoEnumerator; if (_projectInfoToPrint.Length == 1 && _projectInfoToPrint[0] == "*") - projectInfoEnumerator = Helper.GetPropertyKeysForDynamic(projectInfo); + projectInfoEnumerator = Helper.GetPropertyKeysForDynamic(projectJson); else { - projectInfoEnumerator = Helper.GetPropertyKeysForDynamic(projectInfo); + projectInfoEnumerator = Helper.GetPropertyKeysForDynamic(projectJson); projectInfoEnumerator = projectInfoEnumerator.Where(x => _projectInfoToPrint.Contains(x, StringComparer.OrdinalIgnoreCase)); } foreach (var key in projectInfoEnumerator) { - if (projectInfo[key] == null) + var value = projectJson[key]; + if (value == null) Console.WriteLine(key + @": null"); else - Console.WriteLine(key + @": " + projectInfo[key].ToString()); + Console.WriteLine(key + @": " + value.ToString()); } } @@ -118,7 +118,7 @@ private static void InfoPkg(FileInfo file, string name) { Console.WriteLine("Package entries:"); - Package package; + Core.Package.Package package; using (var reader = new BinaryReader(file.Open(FileMode.Open, FileAccess.Read, FileShare.Read))) { package = _reader.ReadFrom(reader); @@ -149,7 +149,7 @@ private static void InfoTex(FileInfo file) { } - private static dynamic GetProjectInfo(FileInfo packageFile) + private static JsonNode? GetProjectInfo(FileInfo packageFile) { var directory = packageFile.Directory; if (directory == null) @@ -159,19 +159,23 @@ private static dynamic GetProjectInfo(FileInfo packageFile) if (projectJson.Length == 0 || !projectJson[0].Exists) return null; - return JsonConvert.DeserializeObject(File.ReadAllText(projectJson[0].FullName)); + return JsonNode.Parse(File.ReadAllText(projectJson[0].FullName)); } - private static bool MatchesFilter(dynamic project) + private static bool MatchesFilter(JsonNode? project) { if (project == null) return true; if (!string.IsNullOrEmpty(_options.TitleFilter)) { - var title = (string) project.title; - if (!title.Contains(_options.TitleFilter, StringComparison.OrdinalIgnoreCase)) - return false; + var titleNode = project["title"]; + if (titleNode != null) + { + var title = titleNode.GetValue(); + if (!title.Contains(_options.TitleFilter, StringComparison.OrdinalIgnoreCase)) + return false; + } } return true; @@ -202,4 +206,4 @@ public class InfoOptions [Option("title-filter", HelpText = "Title filter")] public string TitleFilter { get; set; } } -} \ No newline at end of file +} diff --git a/RePKG/Helper.cs b/RePKG/Helper.cs index 316beaf..93835e0 100644 --- a/RePKG/Helper.cs +++ b/RePKG/Helper.cs @@ -1,21 +1,14 @@ using System.Collections.Generic; -using Newtonsoft.Json.Linq; +using System.Linq; +using System.Text.Json.Nodes; namespace RePKG { public static class Helper { - public static IEnumerable GetPropertyKeysForDynamic(dynamic dynamicToGetPropertiesFor) + public static IEnumerable GetPropertyKeysForDynamic(JsonObject jsonObject) { - JObject attributesAsJObject = dynamicToGetPropertiesFor; - var values = attributesAsJObject.ToObject>(); - var toReturn = new List(); - foreach (var key in values.Keys) - { - toReturn.Add(key); - } - - return toReturn; + return jsonObject.Select(x => x.Key); } } -} \ No newline at end of file +} diff --git a/RePKG/RePKG.csproj b/RePKG/RePKG.csproj index 892f7ac..06ed68c 100644 --- a/RePKG/RePKG.csproj +++ b/RePKG/RePKG.csproj @@ -2,25 +2,22 @@ RePKG Exe - net472 - 0.4.0 + net10.0 + 0.5.0 Copyright © NotScuffed 2025 + enable + enable - - - - - - \ No newline at end of file + From 448657e59f6596ddb7dd3bc1602e0e8dd0221fbe Mon Sep 17 00:00:00 2001 From: ZNH <35349300+kingsznhone@users.noreply.github.com> Date: Tue, 28 Apr 2026 02:33:25 +0800 Subject: [PATCH 2/7] Update .gitignore --- .gitignore | 438 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 429 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index 7db3595..ccdb8f7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,429 @@ -packages -.vs -.idea -obj -bin -Publish -RePKG.Tests/Output/* -RePKG.Tests/TestTextures/* -RePKG.Tests/TestTexturesValidated/* \ No newline at end of file +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates +*.env + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ + +[Dd]ebug/x64/ +[Dd]ebugPublic/x64/ +[Rr]elease/x64/ +[Rr]eleases/x64/ +bin/x64/ +obj/x64/ + +[Dd]ebug/x86/ +[Dd]ebugPublic/x86/ +[Rr]elease/x86/ +[Rr]eleases/x86/ +bin/x86/ +obj/x86/ + +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +[Aa][Rr][Mm]64[Ee][Cc]/ +bld/ +[Oo]bj/ +[Oo]ut/ +[Ll]og/ +[Ll]ogs/ + +# Build results on 'Bin' directories +**/[Bb]in/* +# Uncomment if you have tasks that rely on *.refresh files to move binaries +# (https://github.com/github/gitignore/pull/3736) +#!**/[Bb]in/*.refresh + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* +*.trx + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Approval Tests result files +*.received.* + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ +.artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.idb +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +# but not Directory.Build.rsp, as it configures directory-level build defaults +!Directory.Build.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +**/.paket/paket.exe +paket-files/ + +# FAKE - F# Make +**/.fake/ + +# CodeRush personal settings +**/.cr/personal + +# Python Tools for Visual Studio (PTVS) +**/__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +#tools/** +#!tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog +MSBuild_Logs/ + +# AWS SAM Build and Temporary Artifacts folder +.aws-sam + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +**/.mfractor/ + +# Local History for Visual Studio +**/.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +**/.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp \ No newline at end of file From 06aab6b2c1aa866303c146e0e3b6217f4e4d7383 Mon Sep 17 00:00:00 2001 From: ZNH <35349300+kingsznhone@users.noreply.github.com> Date: Tue, 28 Apr 2026 03:39:48 +0800 Subject: [PATCH 3/7] use system commandline --- .gitignore | 2 +- RePKG.Tests/RePKG.Tests.csproj | 6 +- RePKG/Command/Extract.cs | 341 ++++++++++++++------------------- RePKG/Command/Info.cs | 192 ++++++++----------- RePKG/Extensions.cs | 26 --- RePKG/Program.cs | 40 +--- RePKG/RePKG.csproj | 2 +- 7 files changed, 245 insertions(+), 364 deletions(-) diff --git a/.gitignore b/.gitignore index ccdb8f7..5e8b1a8 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,7 @@ ## files generated by popular Visual Studio add-ons. ## ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore - +/tmp # User-specific files *.rsuser *.suo diff --git a/RePKG.Tests/RePKG.Tests.csproj b/RePKG.Tests/RePKG.Tests.csproj index d7ac70e..53ea47f 100644 --- a/RePKG.Tests/RePKG.Tests.csproj +++ b/RePKG.Tests/RePKG.Tests.csproj @@ -8,9 +8,9 @@ - - - + + + diff --git a/RePKG/Command/Extract.cs b/RePKG/Command/Extract.cs index d99d230..51f1701 100644 --- a/RePKG/Command/Extract.cs +++ b/RePKG/Command/Extract.cs @@ -1,99 +1,61 @@ using System; using System.Collections.Generic; +using System.CommandLine; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Text; using System.Text.Json.Nodes; -using CommandLine; using RePKG.Core.Package; using RePKG.Core.Texture; using RePKG.Core.Package.Enums; using RePKG.Core.Package.Interfaces; -namespace RePKG.Command +namespace RePKG.Commands { public static class Extract { - private static ExtractOptions _options; - private static string[] _skipExtArray; - private static string[] _onlyExtArray; - private static readonly string[] ProjectFiles = {"project.json"}; + private static readonly string[] ProjectFiles = { "project.json" }; + private static readonly ITexReader _texReader = TexReader.Default; + private static readonly ITexJsonInfoGenerator _texJsonInfoGenerator = new TexJsonInfoGenerator(); + private static readonly IPackageReader _packageReader = new PackageReader(); + private static readonly TexToImageConverter _texToImageConverter = new TexToImageConverter(); - private static readonly ITexReader _texReader; - private static readonly ITexJsonInfoGenerator _texJsonInfoGenerator; - private static readonly IPackageReader _packageReader; - private static readonly TexToImageConverter _texToImageConverter; - - static Extract() - { - _texReader = TexReader.Default; - _texJsonInfoGenerator = new TexJsonInfoGenerator(); - _texToImageConverter = new TexToImageConverter(); - - _packageReader = new PackageReader(); - } - - public static void Action(ExtractOptions options) + public static void Action(ExtractOptions o) { - _options = options; - - if (string.IsNullOrEmpty(options.OutputDirectory)) - { - options.OutputDirectory = Directory.GetCurrentDirectory(); - } - - if (!string.IsNullOrEmpty(_options.IgnoreExts)) - _skipExtArray = NormalizeExtensions(_options.IgnoreExts.Split(',')); + if (string.IsNullOrEmpty(o.OutputDirectory)) + o.OutputDirectory = Directory.GetCurrentDirectory(); - if (!string.IsNullOrEmpty(_options.OnlyExts)) - _onlyExtArray = NormalizeExtensions(_options.OnlyExts.Split(',')); - - var fileInfo = new FileInfo(options.Input); - var directoryInfo = new DirectoryInfo(options.Input); + var fileInfo = new FileInfo(o.Input); + var directoryInfo = new DirectoryInfo(o.Input); if (!fileInfo.Exists) { if (directoryInfo.Exists) { - if (_options.TexDirectory) - ExtractTexDirectory(directoryInfo); + if (o.TexDirectory) + ExtractTexDirectory(o, directoryInfo); else - ExtractPkgDirectory(directoryInfo); + ExtractPkgDirectory(o, directoryInfo); Console.WriteLine("Done"); return; } Console.WriteLine("Input file not found"); - Console.WriteLine(options.Input); + Console.WriteLine(o.Input); return; } - ExtractFile(fileInfo); + ExtractFile(o, fileInfo); Console.WriteLine("Done"); } - private static string[] NormalizeExtensions(string[] array) - { - for (int i = 0; i < array.Length; i++) - { - if (array[i].StartsWith(".")) - continue; - array[i] = '.' + array[i]; - } - - return array; - } - - private static void ExtractTexDirectory(DirectoryInfo directoryInfo) + private static void ExtractTexDirectory(ExtractOptions o, DirectoryInfo directoryInfo) { - var flags = SearchOption.TopDirectoryOnly; - - if (_options.Recursive) - flags = SearchOption.AllDirectories; + var flags = o.Recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; - Directory.CreateDirectory(_options.OutputDirectory); + Directory.CreateDirectory(o.OutputDirectory); foreach (var fileInfo in directoryInfo.EnumerateFiles("*.tex", flags)) { @@ -102,17 +64,13 @@ private static void ExtractTexDirectory(DirectoryInfo directoryInfo) try { - var tex = LoadTex(File.ReadAllBytes(fileInfo.FullName), fileInfo.FullName); - + var tex = LoadTex(o, File.ReadAllBytes(fileInfo.FullName), fileInfo.FullName); if (tex == null) continue; - var filePath = Path.Combine(_options.OutputDirectory, - Path.GetFileNameWithoutExtension(fileInfo.Name)); - - ConvertToImageAndSave(tex, filePath, _options.Overwrite); - var jsonInfo = _texJsonInfoGenerator.GenerateInfo(tex); - File.WriteAllText($"{filePath}.tex-json", jsonInfo); + var filePath = Path.Combine(o.OutputDirectory, Path.GetFileNameWithoutExtension(fileInfo.Name)); + ConvertToImageAndSave(o, tex, filePath); + File.WriteAllText($"{filePath}.tex-json", _texJsonInfoGenerator.GenerateInfo(tex)); } catch (Exception e) { @@ -122,53 +80,48 @@ private static void ExtractTexDirectory(DirectoryInfo directoryInfo) } } - private static void ExtractPkgDirectory(DirectoryInfo directoryInfo) + private static void ExtractPkgDirectory(ExtractOptions o, DirectoryInfo directoryInfo) { - var rootDirectoryLength = directoryInfo.FullName.Length + 1; + var rootLen = directoryInfo.FullName.Length + 1; - if (_options.Recursive) + if (o.Recursive) { foreach (var file in directoryInfo.EnumerateFiles("*.pkg", SearchOption.AllDirectories)) { - if (file.Directory == null || file.Directory.FullName.Length < rootDirectoryLength) - ExtractPkg(file); + if (file.Directory == null || file.Directory.FullName.Length < rootLen) + ExtractPkg(o, file); else - ExtractPkg(file, true, file.Directory.FullName.Substring(rootDirectoryLength)); + ExtractPkg(o, file, true, file.Directory.FullName.Substring(rootLen)); } - return; } foreach (var directory in directoryInfo.EnumerateDirectories()) { foreach (var file in directory.EnumerateFiles("*.pkg")) - { - ExtractPkg(file, true, directory.FullName.Substring(rootDirectoryLength)); - } + ExtractPkg(o, file, true, directory.FullName.Substring(rootLen)); } } - private static void ExtractFile(FileInfo fileInfo) + private static void ExtractFile(ExtractOptions o, FileInfo fileInfo) { - Directory.CreateDirectory(_options.OutputDirectory); + Directory.CreateDirectory(o.OutputDirectory); if (fileInfo.Extension.Equals(".pkg", StringComparison.OrdinalIgnoreCase)) - ExtractPkg(fileInfo); + { + ExtractPkg(o, fileInfo); + } else if (fileInfo.Extension.Equals(".tex", StringComparison.OrdinalIgnoreCase)) { - var tex = LoadTex(File.ReadAllBytes(fileInfo.FullName), fileInfo.FullName); - + var tex = LoadTex(o, File.ReadAllBytes(fileInfo.FullName), fileInfo.FullName); if (tex == null) return; try { - var filePath = Path.Combine(_options.OutputDirectory, - Path.GetFileNameWithoutExtension(fileInfo.Name)); - - ConvertToImageAndSave(tex, filePath, _options.Overwrite); - var jsonInfo = _texJsonInfoGenerator.GenerateInfo(tex); - File.WriteAllText($"{filePath}.tex-json", jsonInfo); + var filePath = Path.Combine(o.OutputDirectory, Path.GetFileNameWithoutExtension(fileInfo.Name)); + ConvertToImageAndSave(o, tex, filePath); + File.WriteAllText($"{filePath}.tex-json", _texJsonInfoGenerator.GenerateInfo(tex)); } catch (Exception e) { @@ -176,54 +129,45 @@ private static void ExtractFile(FileInfo fileInfo) } } else + { Console.WriteLine($"Unrecognized file extension: {fileInfo.Extension}"); + } } - private static void ExtractPkg(FileInfo file, bool appendFolderName = false, string defaultProjectName = "") + private static void ExtractPkg(ExtractOptions o, FileInfo file, bool appendFolderName = false, string defaultProjectName = "") { Console.WriteLine($"\r\n### Extracting package: {file.FullName}"); - // Load package Core.Package.Package package; - using (var reader = new BinaryReader(file.Open(FileMode.Open, FileAccess.Read, FileShare.Read))) - { package = _packageReader.ReadFrom(reader); - } - // Get output directory string outputDirectory; var preview = string.Empty; if (appendFolderName) - GetProjectFolderNameAndPreviewImage(file, defaultProjectName, out outputDirectory, out preview); + GetProjectFolderNameAndPreviewImage(o, file, defaultProjectName, out outputDirectory, out preview); else - outputDirectory = _options.OutputDirectory; + outputDirectory = o.OutputDirectory; - // Extract package entries - var entries = FilterEntries(package.Entries); - foreach (var entry in entries) - { - ExtractEntry(entry, ref outputDirectory); - } + foreach (var entry in FilterEntries(o, package.Entries)) + ExtractEntry(o, entry, ref outputDirectory); - // Copy project files project.json/preview image - if (!_options.CopyProject || _options.SingleDir || file.Directory == null) + if (!o.CopyProject || o.SingleDir || file.Directory == null) return; var files = file.Directory.GetFiles().Where(x => x.Name.Equals(preview, StringComparison.OrdinalIgnoreCase) || ProjectFiles.Contains(x.Name, StringComparer.OrdinalIgnoreCase)); - CopyFiles(files, outputDirectory); + CopyFiles(o, files, outputDirectory); } - private static void CopyFiles(IEnumerable files, string outputDirectory) + private static void CopyFiles(ExtractOptions o, IEnumerable files, string outputDirectory) { foreach (var file in files) { var outputPath = Path.Combine(outputDirectory, file.Name); - - if (!_options.Overwrite && File.Exists(outputPath)) + if (!o.Overwrite && File.Exists(outputPath)) Console.WriteLine($"* Skipping, already exists: {outputPath}"); else { @@ -233,63 +177,56 @@ private static void CopyFiles(IEnumerable files, string outputDirector } } - private static IEnumerable FilterEntries(IEnumerable entries) + private static IEnumerable FilterEntries(ExtractOptions o, IEnumerable entries) { - if (!string.IsNullOrEmpty(_options.IgnoreExts)) + if (!string.IsNullOrEmpty(o.IgnoreExts)) { - return from entry in entries - where !_skipExtArray.Any(s => entry.FullPath.EndsWith(s, StringComparison.OrdinalIgnoreCase)) - select entry; + var skip = NormalizeExtensions(o.IgnoreExts.Split(',')); + return entries.Where(e => !skip.Any(s => e.FullPath.EndsWith(s, StringComparison.OrdinalIgnoreCase))); } - if (!string.IsNullOrEmpty(_options.OnlyExts)) + if (!string.IsNullOrEmpty(o.OnlyExts)) { - return from entry in entries - where _onlyExtArray.Any(s => entry.FullPath.EndsWith(s, StringComparison.OrdinalIgnoreCase)) - select entry; + var only = NormalizeExtensions(o.OnlyExts.Split(',')); + return entries.Where(e => only.Any(s => e.FullPath.EndsWith(s, StringComparison.OrdinalIgnoreCase))); } return entries; } [SuppressMessage("ReSharper", "AssignNullToNotNullAttribute")] - private static void ExtractEntry(PackageEntry entry, ref string outputDirectory) + private static void ExtractEntry(ExtractOptions o, PackageEntry entry, ref string outputDirectory) { if (Program.Closing) Environment.Exit(0); - // save raw - var filePathWithoutExtension = _options.SingleDir + var filePathNoExt = o.SingleDir ? Path.Combine(outputDirectory, entry.Name) : Path.Combine(outputDirectory, entry.DirectoryPath, entry.Name); - var filePath = filePathWithoutExtension + entry.Extension; + var filePath = filePathNoExt + entry.Extension; - Directory.CreateDirectory(Path.GetDirectoryName(filePathWithoutExtension)); + Directory.CreateDirectory(Path.GetDirectoryName(filePathNoExt)); - if (!_options.Overwrite && File.Exists(filePath)) + if (!o.Overwrite && File.Exists(filePath)) Console.WriteLine($"* Skipping, already exists: {filePath}"); else { Console.WriteLine($"* Extracting: {entry.FullPath}"); - File.WriteAllBytes(filePath, entry.Bytes); } - // convert and save - if (_options.NoTexConvert || entry.Type != EntryType.Tex) + if (o.NoTexConvert || entry.Type != EntryType.Tex) return; - var tex = LoadTex(entry.Bytes, entry.FullPath); - + var tex = LoadTex(o, entry.Bytes, entry.FullPath); if (tex == null) return; try { - ConvertToImageAndSave(tex, filePathWithoutExtension, _options.Overwrite); - var jsonInfo = _texJsonInfoGenerator.GenerateInfo(tex); - File.WriteAllText($"{filePathWithoutExtension}.tex-json", jsonInfo); + ConvertToImageAndSave(o, tex, filePathNoExt); + File.WriteAllText($"{filePathNoExt}.tex-json", _texJsonInfoGenerator.GenerateInfo(tex)); } catch (Exception e) { @@ -298,6 +235,28 @@ private static void ExtractEntry(PackageEntry entry, ref string outputDirectory) } } + private static void GetProjectFolderNameAndPreviewImage(ExtractOptions o, FileInfo packageFile, + string defaultProjectName, out string outputDirectory, out string preview) + { + preview = string.Empty; + + if (o.SingleDir) + { + outputDirectory = o.OutputDirectory; + return; + } + + if (o.UseName) + { + var name = defaultProjectName; + GetProjectInfo(packageFile, ref name, ref preview); + outputDirectory = Path.Combine(o.OutputDirectory, name.GetSafeFilename()); + return; + } + + outputDirectory = Path.Combine(o.OutputDirectory, defaultProjectName); + } + private static void GetProjectInfo(FileInfo packageFile, ref string title, ref string preview) { var directory = packageFile.Directory; @@ -316,29 +275,7 @@ private static void GetProjectInfo(FileInfo packageFile, ref string title, ref s } } - private static void GetProjectFolderNameAndPreviewImage(FileInfo packageFile, string defaultProjectName, - out string outputDirectory, out string preview) - { - preview = string.Empty; - - if (_options.SingleDir) - { - outputDirectory = _options.OutputDirectory; - return; - } - - if (_options.UseName) - { - var name = defaultProjectName; - GetProjectInfo(packageFile, ref name, ref preview); - outputDirectory = Path.Combine(_options.OutputDirectory, name.GetSafeFilename()); - return; - } - - outputDirectory = Path.Combine(_options.OutputDirectory, defaultProjectName); - } - - private static ITex LoadTex(byte[] bytes, string name) + private static ITex? LoadTex(ExtractOptions o, byte[] bytes, string name) { if (Program.Closing) Environment.Exit(0); @@ -347,10 +284,8 @@ private static ITex LoadTex(byte[] bytes, string name) try { - using (var reader = new BinaryReader(new MemoryStream(bytes), Encoding.UTF8)) - { - return _texReader.ReadFrom(reader); - } + using var reader = new BinaryReader(new MemoryStream(bytes), Encoding.UTF8); + return _texReader.ReadFrom(reader); } catch (Exception e) { @@ -360,58 +295,78 @@ private static ITex LoadTex(byte[] bytes, string name) return null; } - - private static void ConvertToImageAndSave(ITex tex, string path, bool overwrite) + + private static void ConvertToImageAndSave(ExtractOptions o, ITex tex, string path) { var format = _texToImageConverter.GetConvertedFormat(tex); var outputPath = $"{path}.{format.GetFileExtension()}"; - if (!overwrite && File.Exists(outputPath)) + if (!o.Overwrite && File.Exists(outputPath)) return; - - var resultImage = _texToImageConverter.ConvertToImage(tex); - File.WriteAllBytes(outputPath, resultImage.Bytes); + File.WriteAllBytes(outputPath, _texToImageConverter.ConvertToImage(tex).Bytes); + } + + private static string[] NormalizeExtensions(string[] array) + { + for (int i = 0; i < array.Length; i++) + if (!array[i].StartsWith(".")) + array[i] = '.' + array[i]; + return array; + } + + public static Command BuildCommand() + { + var inputArg = new Argument("input") { Description = "Path to file/directory" }; + var outputOpt = new Option("--output", ["-o"]) { Description = "Output directory", DefaultValueFactory = _ => "./output" }; + var ignoreOpt = new Option("--ignoreexts", ["-i"]) { Description = "Don't extract files with these extensions (comma-separated)" }; + var onlyOpt = new Option("--onlyexts", ["-e"]) { Description = "Only extract files with these extensions (comma-separated)" }; + var texOpt = new Option("--tex", ["-t"]) { Description = "Convert all tex files into images from specified directory" }; + var sdirOpt = new Option("--singledir", ["-s"]) { Description = "Put all extracted files in one directory" }; + var recurOpt = new Option("--recursive", ["-r"]) { Description = "Recursive search in all subfolders" }; + var copyOpt = new Option("--copyproject", ["-c"]) { Description = "Copy project.json and preview.jpg into output directory" }; + var nameOpt = new Option("--usename", ["-n"]) { Description = "Use project.json title as subfolder name instead of id" }; + var noTexOpt = new Option("--no-tex-convert") { Description = "Don't convert TEX files into images while extracting PKG" }; + var overOpt = new Option("--overwrite") { Description = "Overwrite all existing files" }; + + var cmd = new Command("extract", "Extract PKG / Convert TEX into image"); + cmd.Add(inputArg); + cmd.Add(outputOpt); cmd.Add(ignoreOpt); cmd.Add(onlyOpt); + cmd.Add(texOpt); cmd.Add(sdirOpt); cmd.Add(recurOpt); + cmd.Add(copyOpt); cmd.Add(nameOpt); cmd.Add(noTexOpt); + cmd.Add(overOpt); + + cmd.SetAction((ParseResult pr) => Action(new ExtractOptions + { + Input = pr.GetValue(inputArg)!, + OutputDirectory = pr.GetValue(outputOpt) ?? "./output", + IgnoreExts = pr.GetValue(ignoreOpt), + OnlyExts = pr.GetValue(onlyOpt), + TexDirectory = pr.GetValue(texOpt), + SingleDir = pr.GetValue(sdirOpt), + Recursive = pr.GetValue(recurOpt), + CopyProject = pr.GetValue(copyOpt), + UseName = pr.GetValue(nameOpt), + NoTexConvert = pr.GetValue(noTexOpt), + Overwrite = pr.GetValue(overOpt), + })); + + return cmd; } } - [Verb("extract", HelpText = "Extract PKG/Convert TEX into image.")] public class ExtractOptions { - [Option('o', "output", Required = false, HelpText = "Output directory", Default = "./output")] - public string OutputDirectory { get; set; } - - [Option('i', "ignoreexts", HelpText = - "Don't extract files with specified extensions (delimited by comma \",\"")] - public string IgnoreExts { get; set; } - - [Option('e', "onlyexts", HelpText = "Only extract files with specified extensions (delimited by comma \",\"")] - public string OnlyExts { get; set; } - - [Option('t', "tex", HelpText = "Convert all tex files into images from specified directory in input")] + public string Input { get; set; } = string.Empty; + public string OutputDirectory { get; set; } = string.Empty; + public string? IgnoreExts { get; set; } + public string? OnlyExts { get; set; } public bool TexDirectory { get; set; } - - [Option('s', "singledir", HelpText = - "Should all extracted files be put in one directory instead of their entry path")] public bool SingleDir { get; set; } - - [Option('r', "recursive", HelpText = "Recursive search in all subfolders of specified directory")] public bool Recursive { get; set; } - - [Option('c', "copyproject", HelpText = - "Copy project.json and preview.jpg from beside PKG into output directory")] public bool CopyProject { get; set; } - - [Option('n', "usename", HelpText = "Use name from project.json as project subfolder name instead of id")] public bool UseName { get; set; } - - [Option("no-tex-convert", HelpText = "Don't convert TEX files into images while extracting PKG")] public bool NoTexConvert { get; set; } - - [Option("overwrite", HelpText = "Overwrite all existing files")] public bool Overwrite { get; set; } - - [Value(0, Required = true, HelpText = "Path to file/directory", MetaName = "Input")] - public string Input { get; set; } } -} +} \ No newline at end of file diff --git a/RePKG/Command/Info.cs b/RePKG/Command/Info.cs index e16b1be..161d6b4 100644 --- a/RePKG/Command/Info.cs +++ b/RePKG/Command/Info.cs @@ -1,151 +1,118 @@ using System; using System.Collections.Generic; +using System.CommandLine; using System.IO; using System.Linq; using System.Text.Json.Nodes; -using CommandLine; using RePKG.Core.Package; using RePKG.Core.Package.Interfaces; -namespace RePKG.Command +namespace RePKG.Commands { - public class Info + public static class Info { - private static InfoOptions _options; - private static string[] _projectInfoToPrint; + private static readonly IPackageReader _reader = new PackageReader(); - private static readonly IPackageReader _reader; - - static Info() + public static void Action(InfoOptions o) { - _reader = new PackageReader(); - } + var projectInfoToPrint = string.IsNullOrEmpty(o.ProjectInfo) ? null : o.ProjectInfo.Split(','); - public static void Action(InfoOptions options) - { - _options = options; - - if (string.IsNullOrEmpty(_options.ProjectInfo)) - _projectInfoToPrint = null; - else - _projectInfoToPrint = _options.ProjectInfo.Split(','); - - var fileInfo = new FileInfo(options.Input); - var directoryInfo = new DirectoryInfo(options.Input); + var fileInfo = new FileInfo(o.Input); + var directoryInfo = new DirectoryInfo(o.Input); if (!fileInfo.Exists) { if (directoryInfo.Exists) { - if (_options.TexDirectory) - InfoTexDirectory(directoryInfo); + if (o.TexDirectory) + InfoTexDirectory(o, directoryInfo); else - InfoPkgDirectory(directoryInfo); + InfoPkgDirectory(o, directoryInfo, projectInfoToPrint); Console.WriteLine("Done"); return; } - Console.WriteLine("Input file/directory doesn't exist!"); - Console.WriteLine(options.Input); + Console.WriteLine("Input file/directory doesn''t exist!"); + Console.WriteLine(o.Input); return; } - InfoFile(fileInfo); + InfoFile(o, fileInfo, projectInfoToPrint); Console.WriteLine("Done"); } - private static void InfoPkgDirectory(DirectoryInfo directoryInfo) + private static void InfoPkgDirectory(InfoOptions o, DirectoryInfo directoryInfo, string[]? projectInfoToPrint) { - var rootDirectoryLength = directoryInfo.FullName.Length; + var rootLen = directoryInfo.FullName.Length; foreach (var directory in directoryInfo.EnumerateDirectories()) { foreach (var file in directory.EnumerateFiles("*.pkg")) - { - InfoPkg(file, file.FullName.Substring(rootDirectoryLength)); - } + InfoPkg(o, file, file.FullName.Substring(rootLen), projectInfoToPrint); } } - private static void InfoTexDirectory(DirectoryInfo directoryInfo) + private static void InfoTexDirectory(InfoOptions o, DirectoryInfo directoryInfo) { } - private static void InfoFile(FileInfo file) + private static void InfoFile(InfoOptions o, FileInfo file, string[]? projectInfoToPrint) { if (file.Extension.Equals(".pkg", StringComparison.OrdinalIgnoreCase)) - InfoPkg(file, Path.GetFullPath(file.Name)); + InfoPkg(o, file, Path.GetFullPath(file.Name), projectInfoToPrint); else if (file.Extension.Equals(".tex", StringComparison.OrdinalIgnoreCase)) - InfoTex(file); + InfoTex(o, file); else Console.WriteLine($"Unrecognized file extension: {file.Extension}"); } - private static void InfoPkg(FileInfo file, string name) + private static void InfoPkg(InfoOptions o, FileInfo file, string name, string[]? projectInfoToPrint) { var projectInfo = GetProjectInfo(file); - if (!MatchesFilter(projectInfo)) + if (!MatchesFilter(o, projectInfo)) return; Console.WriteLine($"\r\n### Package info: {name}"); - if (projectInfo is JsonObject projectJson && _projectInfoToPrint?.Length > 0) + if (projectInfo is JsonObject projectJson && projectInfoToPrint?.Length > 0) { - IEnumerable projectInfoEnumerator; + var keys = Helper.GetPropertyKeysForDynamic(projectJson); - if (_projectInfoToPrint.Length == 1 && _projectInfoToPrint[0] == "*") - projectInfoEnumerator = Helper.GetPropertyKeysForDynamic(projectJson); - else - { - projectInfoEnumerator = Helper.GetPropertyKeysForDynamic(projectJson); - projectInfoEnumerator = projectInfoEnumerator.Where(x => - _projectInfoToPrint.Contains(x, StringComparer.OrdinalIgnoreCase)); - } + if (!(projectInfoToPrint.Length == 1 && projectInfoToPrint[0] == "*")) + keys = keys.Where(x => projectInfoToPrint.Contains(x, StringComparer.OrdinalIgnoreCase)); - foreach (var key in projectInfoEnumerator) + foreach (var key in keys) { var value = projectJson[key]; - if (value == null) - Console.WriteLine(key + @": null"); - else - Console.WriteLine(key + @": " + value.ToString()); + Console.WriteLine(value == null ? $"{key}: null" : $"{key}: {value}"); } } - if (_options.PrintEntries) - { - Console.WriteLine("Package entries:"); + if (!o.PrintEntries) + return; - Core.Package.Package package; - using (var reader = new BinaryReader(file.Open(FileMode.Open, FileAccess.Read, FileShare.Read))) - { - package = _reader.ReadFrom(reader); - } + Console.WriteLine("Package entries:"); - var entries = package.Entries; + Core.Package.Package package; + using (var reader = new BinaryReader(file.Open(FileMode.Open, FileAccess.Read, FileShare.Read))) + package = _reader.ReadFrom(reader); - if (_options.Sort) - { - if (_options.SortBy == "extension") - entries.Sort((a, b) => - String.Compare(a.FullPath, b.FullPath, StringComparison.OrdinalIgnoreCase)); - else if (_options.SortBy == "size") - entries.Sort((a, b) => a.Length.CompareTo(b.Length)); - else - entries.Sort((a, b) => - String.Compare(a.FullPath, b.FullPath, StringComparison.OrdinalIgnoreCase)); - } + var entries = package.Entries; - foreach (var entry in entries) - { - Console.WriteLine(@"* " + entry.FullPath + $@" - {entry.Length} bytes"); - } + if (o.Sort) + { + entries.Sort(o.SortBy == "size" + ? (a, b) => a.Length.CompareTo(b.Length) + : (a, b) => String.Compare(a.FullPath, b.FullPath, StringComparison.OrdinalIgnoreCase)); } + + foreach (var entry in entries) + Console.WriteLine($"* {entry.FullPath} - {entry.Length} bytes"); } - private static void InfoTex(FileInfo file) + private static void InfoTex(InfoOptions o, FileInfo file) { } @@ -162,48 +129,53 @@ private static void InfoTex(FileInfo file) return JsonNode.Parse(File.ReadAllText(projectJson[0].FullName)); } - private static bool MatchesFilter(JsonNode? project) + private static bool MatchesFilter(InfoOptions o, JsonNode? project) { - if (project == null) + if (project == null || string.IsNullOrEmpty(o.TitleFilter)) return true; - if (!string.IsNullOrEmpty(_options.TitleFilter)) - { - var titleNode = project["title"]; - if (titleNode != null) - { - var title = titleNode.GetValue(); - if (!title.Contains(_options.TitleFilter, StringComparison.OrdinalIgnoreCase)) - return false; - } - } + var title = project["title"]?.GetValue(); + return title == null || title.Contains(o.TitleFilter, StringComparison.OrdinalIgnoreCase); + } - return true; + public static Command BuildCommand() + { + var inputArg = new Argument("input") { Description = "Path to file/directory" }; + var sortOpt = new Option("--sort", ["-s"]) { Description = "Sort entries a-z" }; + var sortByOpt = new Option("--sortby", ["-b"]) { Description = "Sort by name/extension/size", DefaultValueFactory = _ => "name" }; + var texOpt = new Option("--tex", ["-t"]) { Description = "Dump info about all tex files from specified directory" }; + var projOpt = new Option("--projectinfo", ["-p"]) { Description = "Keys from project.json (comma-separated, * for all)" }; + var printOpt = new Option("--printentries", ["-e"]) { Description = "Print entries in packages" }; + var filterOpt = new Option("--title-filter") { Description = "Title filter" }; + + var cmd = new Command("info", "Dumps PKG/TEX info"); + cmd.Add(inputArg); + cmd.Add(sortOpt); cmd.Add(sortByOpt); cmd.Add(texOpt); + cmd.Add(projOpt); cmd.Add(printOpt); cmd.Add(filterOpt); + + cmd.SetAction((ParseResult pr) => Action(new InfoOptions + { + Input = pr.GetValue(inputArg)!, + Sort = pr.GetValue(sortOpt), + SortBy = pr.GetValue(sortByOpt)!, + TexDirectory = pr.GetValue(texOpt), + ProjectInfo = pr.GetValue(projOpt), + PrintEntries = pr.GetValue(printOpt), + TitleFilter = pr.GetValue(filterOpt), + })); + + return cmd; } } - [Verb("info", HelpText = "Dumps PKG/TEX info.")] public class InfoOptions { - [Value(0, Required = true, HelpText = "Path to file which you want to get info about", MetaName = "Input file")] - public string Input { get; set; } - - [Option('s', "sort", HelpText = "Sort entries a-z", Default = false)] + public string Input { get; set; } = string.Empty; public bool Sort { get; set; } - - [Option('b', "sortby", HelpText = "Sort by ... (available options: name, extension, size)", Default = "name")] - public string SortBy { get; set; } - - [Option('t', "tex", HelpText = "Dump info about all tex files from specified directory")] + public string SortBy { get; set; } = "name"; public bool TexDirectory { get; set; } - - [Option('p', "projectinfo", HelpText = "Keys to dump from project.json (delimit using comma) (* for all)")] - public string ProjectInfo { get; set; } - - [Option('e', "printentries", HelpText = "Print entries in packages")] + public string? ProjectInfo { get; set; } public bool PrintEntries { get; set; } - - [Option("title-filter", HelpText = "Title filter")] - public string TitleFilter { get; set; } + public string? TitleFilter { get; set; } } -} +} \ No newline at end of file diff --git a/RePKG/Extensions.cs b/RePKG/Extensions.cs index 3d8f3ea..dc8bec5 100644 --- a/RePKG/Extensions.cs +++ b/RePKG/Extensions.cs @@ -12,33 +12,7 @@ public static bool Contains(this string haystack, string needle, StringCompariso public static string GetSafeFilename(this string filename) { - return string.Join("_", filename.Split(Path.GetInvalidFileNameChars())); - - } - - public static string[] SplitArguments(this string commandLine) - { - var parmChars = commandLine.ToCharArray(); - var inSingleQuote = false; - var inDoubleQuote = false; - - for (var index = 0; index < parmChars.Length; index++) - { - if (parmChars[index] == '"' && !inSingleQuote) - { - inDoubleQuote = !inDoubleQuote; - parmChars[index] = '\n'; - } - if (parmChars[index] == '\'' && !inDoubleQuote) - { - inSingleQuote = !inSingleQuote; - parmChars[index] = '\n'; - } - if (!inSingleQuote && !inDoubleQuote && parmChars[index] == ' ') - parmChars[index] = '\n'; - } - return new string(parmChars).Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); } } } diff --git a/RePKG/Program.cs b/RePKG/Program.cs index bf7a1a3..588e8e4 100644 --- a/RePKG/Program.cs +++ b/RePKG/Program.cs @@ -1,6 +1,7 @@ using System; -using CommandLine; -using RePKG.Command; +using System.CommandLine; +using System.CommandLine.Help; +using RePKG.Commands; namespace RePKG { @@ -8,43 +9,22 @@ internal class Program { public static bool Closing; - private static void Main(string[] args) + private static int Main(string[] args) { Console.CancelKeyPress += Cancel; - if (args.Length > 0 && args[0] == "interactive") - { - InteractiveConsole(); - return; - } - - Parser.Default.ParseArguments(args) - .WithParsed(Extract.Action) - .WithParsed(Info.Action); + var root = new RootCommand("RePKG - Wallpaper Engine package tool"); + root.Add(Extract.BuildCommand()); + root.Add(Info.BuildCommand()); + root.Action = new HelpAction(); + return root.Parse(args).Invoke(); } - private static void Cancel(object sender, ConsoleCancelEventArgs e) + private static void Cancel(object? sender, ConsoleCancelEventArgs e) { Closing = true; e.Cancel = true; Console.WriteLine("Terminating..."); } - - private static void InteractiveConsole() - { - Console.WriteLine("RePKG started in interactive mode. You can now type commands"); - Console.WriteLine("Type \"help\" for commands"); - - string line; - - while (!string.IsNullOrEmpty(line = Console.ReadLine())) - { - var interactiveArgs = line.SplitArguments(); - - Parser.Default.ParseArguments(interactiveArgs) - .WithParsed(Extract.Action) - .WithParsed(Info.Action); - } - } } } diff --git a/RePKG/RePKG.csproj b/RePKG/RePKG.csproj index 06ed68c..390eeaf 100644 --- a/RePKG/RePKG.csproj +++ b/RePKG/RePKG.csproj @@ -14,7 +14,7 @@ - + From 5c5a754533d6077f014979e1b9c315439fd8d8e1 Mon Sep 17 00:00:00 2001 From: ZNH <35349300+kingsznhone@users.noreply.github.com> Date: Tue, 28 Apr 2026 03:54:02 +0800 Subject: [PATCH 4/7] use span --- RePKG.Core/Texture/TexImageReader.cs | 6 +----- RePKG.Core/Texture/TexMipmapDecompressor.cs | 6 +----- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/RePKG.Core/Texture/TexImageReader.cs b/RePKG.Core/Texture/TexImageReader.cs index 495b467..227cad2 100644 --- a/RePKG.Core/Texture/TexImageReader.cs +++ b/RePKG.Core/Texture/TexImageReader.cs @@ -122,11 +122,7 @@ private byte[] ReadBytes(BinaryReader reader) } var bytes = new byte[byteCount]; - var bytesRead = reader.Read(bytes, 0, byteCount); - - if (bytesRead != byteCount) - throw new Exception("Failed to read bytes from stream while reading mipmap"); - + reader.BaseStream.ReadExactly(bytes); return bytes; } diff --git a/RePKG.Core/Texture/TexMipmapDecompressor.cs b/RePKG.Core/Texture/TexMipmapDecompressor.cs index f0137b2..3ef5f09 100644 --- a/RePKG.Core/Texture/TexMipmapDecompressor.cs +++ b/RePKG.Core/Texture/TexMipmapDecompressor.cs @@ -40,11 +40,7 @@ public void DecompressMipmap(ITexMipmap mipmap) private byte[] Lz4Decompress(byte[] bytes, int knownLength) { var buffer = new byte[knownLength]; - - LZ4Codec.Decode( - bytes, 0, bytes.Length, - buffer, 0, buffer.Length); - + LZ4Codec.Decode(bytes.AsSpan(), buffer.AsSpan()); return buffer; } } From 9aba7b386bf71326d54f3abcdc67e3d003897e87 Mon Sep 17 00:00:00 2001 From: ZNH <35349300+kingsznhone@users.noreply.github.com> Date: Tue, 28 Apr 2026 04:01:18 +0800 Subject: [PATCH 5/7] Create publish.yml --- .github/workflows/publish.yml | 119 ++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 .github/workflows/publish.yml diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..fb45e5e --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,119 @@ +on: + workflow_dispatch: + release: + types: + - published + +permissions: + contents: write + +jobs: + get-version: + name: Extract Version + runs-on: ubuntu-latest + outputs: + version: ${{ steps.version.outputs.version }} + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Extract version tag + id: version + run: | + git fetch --tags --force + VERSION_TAG=$(git tag --points-at "$GITHUB_SHA" | grep -E '^v?[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$' | head -n 1 || echo "") + if [ -n "$VERSION_TAG" ]; then + echo "version=$VERSION_TAG" >> $GITHUB_OUTPUT + echo "Found version tag: $VERSION_TAG" + else + SHORT_SHA=$(git rev-parse --short HEAD) + echo "version=${SHORT_SHA}" >> $GITHUB_OUTPUT + echo "No version tag found, using: ${SHORT_SHA}" + fi + + build: + name: ${{ matrix.rid }} + needs: get-version + strategy: + fail-fast: false + matrix: + rid: + - win-x64 + - linux-x64 + - linux-arm64 + - osx-arm64 + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v6 + + - name: Setup .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: '10' + + - name: Publish + run: > + dotnet publish RePKG/RePKG.csproj + -c Release + -r ${{ matrix.rid }} + --no-self-contained + -p:PublishSingleFile=true + -p:PublishReadyToRun=true + -p:GeneratePackageOnBuild=false + -o publish/out + + - name: Upload artifact + uses: actions/upload-artifact@v7 + with: + name: repkg-${{ needs.get-version.outputs.version }}-${{ matrix.rid }} + path: publish/out/ + if-no-files-found: error + + verify-builds: + name: Verify All Builds Passed + if: github.event_name == 'workflow_dispatch' + needs: + - get-version + - build + runs-on: ubuntu-latest + steps: + - name: All builds succeeded + run: | + echo "✅ All matrix builds passed for version: ${{ needs.get-version.outputs.version }}" + echo "Artifacts are NOT uploaded to any release (manual trigger)." + + publish-release: + name: Upload to Release + if: github.event_name == 'release' + needs: + - get-version + - build + runs-on: ubuntu-latest + steps: + - name: Download all artifacts + uses: actions/download-artifact@v7 + with: + path: release-assets + merge-multiple: false + + - name: Package artifacts + run: | + mkdir -p packaged + for dir in release-assets/*/; do + name=$(basename "$dir") + if [[ "$name" == *win-x64* ]]; then + (cd "$dir" && zip -r "${GITHUB_WORKSPACE}/packaged/${name}.zip" .) + else + tar -czf "packaged/${name}.tar.gz" -C "$dir" . + fi + done + echo "--- Packaged files ---" + ls -lh packaged/ + + - name: Upload release assets + uses: softprops/action-gh-release@v3 + with: + files: packaged/* + token: ${{ secrets.GITHUB_TOKEN }} From 11341194aa56d0974cee858c3c27aa8d8331c786 Mon Sep 17 00:00:00 2001 From: ZNH <35349300+kingsznhone@users.noreply.github.com> Date: Tue, 28 Apr 2026 04:13:30 +0800 Subject: [PATCH 6/7] code clean --- .../Exceptions/EnumNotValidException.cs | 2 - .../Exceptions/UnknownMagicException.cs | 4 +- RePKG.Core/Exceptions/UnsafeTexException.cs | 4 +- RePKG.Core/Extensions.cs | 14 ++-- .../Package/Interfaces/IPackageReader.cs | 2 - .../Package/Interfaces/IPackageWriter.cs | 2 - RePKG.Core/Package/Package.cs | 2 - RePKG.Core/Package/PackageEntryTypeGetter.cs | 1 - RePKG.Core/Package/PackageReader.cs | 10 +-- RePKG.Core/Package/PackageWriter.cs | 6 +- RePKG.Core/Texture/Enums/DXTFlags.cs | 2 - RePKG.Core/Texture/Enums/MipmapFormat.cs | 4 +- RePKG.Core/Texture/Enums/TexFlags.cs | 4 +- RePKG.Core/Texture/Helpers/DXT.cs | 8 +- RePKG.Core/Texture/Helpers/EnumExtensions.cs | 5 +- .../Texture/Helpers/MipmapFormatExtensions.cs | 46 ++++++++-- .../Texture/Helpers/TexMipmapFormatGetter.cs | 84 ++++++++++--------- .../Interfaces/Data/ITexFrameInfoContainer.cs | 2 - .../Texture/Interfaces/Data/ITexImage.cs | 2 - .../Interfaces/Data/ITexImageContainer.cs | 2 - .../Texture/Interfaces/Data/ITexMipmap.cs | 2 - .../ITexFrameInfoContainerReader.cs | 2 - .../Texture/Interfaces/ITexHeaderReader.cs | 2 - .../Interfaces/ITexImageContainerReader.cs | 2 - .../Texture/Interfaces/ITexImageReader.cs | 2 - .../Interfaces/ITexMipmapDecompressor.cs | 2 +- RePKG.Core/Texture/Interfaces/ITexReader.cs | 2 - .../Writer/ITexFrameInfoContainerWriter.cs | 2 - .../Interfaces/Writer/ITexHeaderWriter.cs | 2 - .../Writer/ITexImageContainerWriter.cs | 2 - .../Interfaces/Writer/ITexImageWriter.cs | 2 - .../Texture/Interfaces/Writer/ITexWriter.cs | 2 - RePKG.Core/Texture/Tex.cs | 6 +- RePKG.Core/Texture/TexFrameInfoContainer.cs | 2 - .../Texture/TexFrameInfoContainerReader.cs | 2 +- RePKG.Core/Texture/TexHeaderReader.cs | 11 +-- RePKG.Core/Texture/TexImage.cs | 3 - RePKG.Core/Texture/TexImageContainer.cs | 4 +- RePKG.Core/Texture/TexImageContainerReader.cs | 4 +- RePKG.Core/Texture/TexImageReader.cs | 27 +++--- RePKG.Core/Texture/TexJsonInfoGenerator.cs | 6 +- RePKG.Core/Texture/TexMipmap.cs | 4 +- RePKG.Core/Texture/TexMipmapDecompressor.cs | 6 +- RePKG.Core/Texture/TexReader.cs | 2 +- RePKG.Core/Texture/TexToImageConverter.cs | 25 +++--- .../Writer/TexFrameInfoContainerWriter.cs | 15 ++-- RePKG.Core/Texture/Writer/TexHeaderWriter.cs | 8 +- .../Texture/Writer/TexImageContainerWriter.cs | 9 +- RePKG.Core/Texture/Writer/TexImageWriter.cs | 8 +- .../Texture/Writer/TexMipmapCompressor.cs | 8 +- RePKG.Core/Texture/Writer/TexWriter.cs | 3 - RePKG.Tests/PkgWriterTests.cs | 11 ++- RePKG.Tests/TestHelper.cs | 6 +- RePKG.Tests/TexDecompressingTests.cs | 10 +-- RePKG.Tests/TexWriterTests.cs | 10 +-- RePKG/{Command => Commands}/Extract.cs | 34 +++++--- RePKG/{Command => Commands}/Info.cs | 30 +++---- RePKG/Helper.cs | 6 +- RePKG/Program.cs | 8 +- 59 files changed, 219 insertions(+), 279 deletions(-) rename RePKG/{Command => Commands}/Extract.cs (96%) rename RePKG/{Command => Commands}/Info.cs (84%) diff --git a/RePKG.Core/Exceptions/EnumNotValidException.cs b/RePKG.Core/Exceptions/EnumNotValidException.cs index 1d721f5..8f55f8b 100644 --- a/RePKG.Core/Exceptions/EnumNotValidException.cs +++ b/RePKG.Core/Exceptions/EnumNotValidException.cs @@ -1,5 +1,3 @@ -using System; - namespace RePKG.Core.Exceptions { /// diff --git a/RePKG.Core/Exceptions/UnknownMagicException.cs b/RePKG.Core/Exceptions/UnknownMagicException.cs index b2f0c61..fe5cde7 100644 --- a/RePKG.Core/Exceptions/UnknownMagicException.cs +++ b/RePKG.Core/Exceptions/UnknownMagicException.cs @@ -1,5 +1,3 @@ -using System; - namespace RePKG.Core.Exceptions { /// @@ -11,7 +9,7 @@ public UnknownMagicException(string source, string magic) : base( $"Unknown magic: '{magic}' in '{source}'") { } - + public UnknownMagicException(string source, string property, string magic) : base( $"Unknown magic: '{magic}' in '{source}:{property}'") { diff --git a/RePKG.Core/Exceptions/UnsafeTexException.cs b/RePKG.Core/Exceptions/UnsafeTexException.cs index a1d29f3..7826bc3 100644 --- a/RePKG.Core/Exceptions/UnsafeTexException.cs +++ b/RePKG.Core/Exceptions/UnsafeTexException.cs @@ -1,5 +1,3 @@ -using System; - namespace RePKG.Core.Exceptions { /// @@ -9,6 +7,6 @@ namespace RePKG.Core.Exceptions public class UnsafeTexException : Exception { public UnsafeTexException(string reason) : base($"Unsafe TEX detected, reason: {reason}") - {} + { } } } \ No newline at end of file diff --git a/RePKG.Core/Extensions.cs b/RePKG.Core/Extensions.cs index 8d7a56f..d97f090 100644 --- a/RePKG.Core/Extensions.cs +++ b/RePKG.Core/Extensions.cs @@ -8,8 +8,8 @@ internal static class Extensions { public static string ReadNString(this BinaryReader reader, int maxLength = -1) { - if (reader == null) throw new ArgumentNullException(nameof(reader)); - + ArgumentNullException.ThrowIfNull(reader); + var builder = new StringBuilder(maxLength <= 0 ? 16 : maxLength); var c = reader.ReadChar(); @@ -24,8 +24,8 @@ public static string ReadNString(this BinaryReader reader, int maxLength = -1) public static void WriteNString(this BinaryWriter writer, string input) { - if (writer == null) throw new ArgumentNullException(nameof(writer)); - if (input == null) throw new ArgumentNullException(nameof(input)); + ArgumentNullException.ThrowIfNull(writer); + ArgumentNullException.ThrowIfNull(input); writer.Write(Encoding.UTF8.GetBytes(input)); writer.Write((byte) 0); @@ -33,7 +33,7 @@ public static void WriteNString(this BinaryWriter writer, string input) public static string ReadStringI32Size(this BinaryReader reader, int maxLength = -1) { - if (reader == null) throw new ArgumentNullException(nameof(reader)); + ArgumentNullException.ThrowIfNull(reader); var size = reader.ReadInt32(); @@ -50,8 +50,8 @@ public static string ReadStringI32Size(this BinaryReader reader, int maxLength = public static void WriteStringI32Size(this BinaryWriter writer, string input) { - if (writer == null) throw new ArgumentNullException(nameof(writer)); - if (input == null) throw new ArgumentNullException(nameof(input)); + ArgumentNullException.ThrowIfNull(writer); + ArgumentNullException.ThrowIfNull(input); writer.Write(input.Length); writer.Write(Encoding.UTF8.GetBytes(input)); diff --git a/RePKG.Core/Package/Interfaces/IPackageReader.cs b/RePKG.Core/Package/Interfaces/IPackageReader.cs index 184dd93..62cd416 100644 --- a/RePKG.Core/Package/Interfaces/IPackageReader.cs +++ b/RePKG.Core/Package/Interfaces/IPackageReader.cs @@ -1,5 +1,3 @@ -using System.IO; - namespace RePKG.Core.Package.Interfaces { public interface IPackageReader diff --git a/RePKG.Core/Package/Interfaces/IPackageWriter.cs b/RePKG.Core/Package/Interfaces/IPackageWriter.cs index 4cd0061..5c9cc30 100644 --- a/RePKG.Core/Package/Interfaces/IPackageWriter.cs +++ b/RePKG.Core/Package/Interfaces/IPackageWriter.cs @@ -1,5 +1,3 @@ -using System.IO; - namespace RePKG.Core.Package.Interfaces { public interface IPackageWriter diff --git a/RePKG.Core/Package/Package.cs b/RePKG.Core/Package/Package.cs index bc15656..8d730a8 100644 --- a/RePKG.Core/Package/Package.cs +++ b/RePKG.Core/Package/Package.cs @@ -1,5 +1,3 @@ -using System.Collections.Generic; - namespace RePKG.Core.Package { public class Package diff --git a/RePKG.Core/Package/PackageEntryTypeGetter.cs b/RePKG.Core/Package/PackageEntryTypeGetter.cs index 9b22e1b..8e4b234 100644 --- a/RePKG.Core/Package/PackageEntryTypeGetter.cs +++ b/RePKG.Core/Package/PackageEntryTypeGetter.cs @@ -1,4 +1,3 @@ -using System.IO; using RePKG.Core.Package.Enums; namespace RePKG.Core.Package diff --git a/RePKG.Core/Package/PackageReader.cs b/RePKG.Core/Package/PackageReader.cs index f580ca2..9422262 100644 --- a/RePKG.Core/Package/PackageReader.cs +++ b/RePKG.Core/Package/PackageReader.cs @@ -1,7 +1,3 @@ -using System; -using System.Collections.Generic; -using System.IO; -using RePKG.Core.Package; using RePKG.Core.Package.Interfaces; namespace RePKG.Core.Package @@ -13,7 +9,7 @@ public class PackageReader : IPackageReader public Core.Package.Package ReadFrom(BinaryReader reader) { if (reader == null) throw new ArgumentNullException(nameof(reader)); - + var packageStart = reader.BaseStream.Position; var package = new Core.Package.Package { @@ -22,8 +18,8 @@ public Core.Package.Package ReadFrom(BinaryReader reader) ReadEntries(package.Entries, reader); - var dataStart = (int) reader.BaseStream.Position; - package.HeaderSize = (int) (dataStart - packageStart); + var dataStart = (int)reader.BaseStream.Position; + package.HeaderSize = (int)(dataStart - packageStart); if (!ReadEntryBytes) return package; diff --git a/RePKG.Core/Package/PackageWriter.cs b/RePKG.Core/Package/PackageWriter.cs index 88a0783..183a237 100644 --- a/RePKG.Core/Package/PackageWriter.cs +++ b/RePKG.Core/Package/PackageWriter.cs @@ -1,7 +1,3 @@ -using System; -using System.Collections.Generic; -using System.IO; -using RePKG.Core.Package; using RePKG.Core.Package.Interfaces; namespace RePKG.Core.Package @@ -15,7 +11,7 @@ public void WriteTo(BinaryWriter writer, Core.Package.Package package) if (package.Entries.Count == 0) throw new Exception("Package entries is empty"); - + writer.WriteStringI32Size(package.Magic); WriteEntriesHeader(package.Entries, writer); WriteBody(package.Entries, writer); diff --git a/RePKG.Core/Texture/Enums/DXTFlags.cs b/RePKG.Core/Texture/Enums/DXTFlags.cs index ed2e909..f7fcb3c 100644 --- a/RePKG.Core/Texture/Enums/DXTFlags.cs +++ b/RePKG.Core/Texture/Enums/DXTFlags.cs @@ -1,5 +1,3 @@ -using System; - namespace RePKG.Core.Texture { [Flags] diff --git a/RePKG.Core/Texture/Enums/MipmapFormat.cs b/RePKG.Core/Texture/Enums/MipmapFormat.cs index 93ca4c2..dff0ba8 100644 --- a/RePKG.Core/Texture/Enums/MipmapFormat.cs +++ b/RePKG.Core/Texture/Enums/MipmapFormat.cs @@ -3,7 +3,7 @@ namespace RePKG.Core.Texture public enum MipmapFormat { Invalid = 0, - + /// /// Raw pixels (4 bytes per pixel) (RGBA8888) /// @@ -33,7 +33,7 @@ public enum MipmapFormat /// Raw pixels compressed using DXT1 /// CompressedDXT1, - + /// /// MP4 Video /// diff --git a/RePKG.Core/Texture/Enums/TexFlags.cs b/RePKG.Core/Texture/Enums/TexFlags.cs index 63bed4d..b130603 100644 --- a/RePKG.Core/Texture/Enums/TexFlags.cs +++ b/RePKG.Core/Texture/Enums/TexFlags.cs @@ -1,5 +1,3 @@ -using System; - namespace RePKG.Core.Texture { [Flags] @@ -9,8 +7,10 @@ public enum TexFlags NoInterpolation = 1, ClampUVs = 2, IsGif = 4, + // Placeholders Unk3 = 8, + Unk4 = 16, IsVideoTexture = 32, Unk6 = 64, diff --git a/RePKG.Core/Texture/Helpers/DXT.cs b/RePKG.Core/Texture/Helpers/DXT.cs index 3457921..42a87df 100644 --- a/RePKG.Core/Texture/Helpers/DXT.cs +++ b/RePKG.Core/Texture/Helpers/DXT.cs @@ -6,10 +6,10 @@ * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR @@ -21,8 +21,6 @@ // most of the algorithms and data used in this Class-file has been ported from LibSquish! // http://code.google.com/p/libsquish/ -using RePKG.Core.Texture; - namespace RePKG.Core.Texture.Helpers { public static class DXT @@ -243,4 +241,4 @@ public static byte[] DecompressImage(int width, int height, byte[] data, DXTFlag return rgba; } } -} +} \ No newline at end of file diff --git a/RePKG.Core/Texture/Helpers/EnumExtensions.cs b/RePKG.Core/Texture/Helpers/EnumExtensions.cs index e814ec7..dc30212 100644 --- a/RePKG.Core/Texture/Helpers/EnumExtensions.cs +++ b/RePKG.Core/Texture/Helpers/EnumExtensions.cs @@ -14,14 +14,15 @@ public static bool IsValid(this TexFormat format) case TexFormat.RG88: case TexFormat.R8: return true; + default: return false; } } - + public static bool IsValid(this FreeImageFormat format) { - var formatId = (int) format; + var formatId = (int)format; return formatId >= -1 && formatId <= 35; } diff --git a/RePKG.Core/Texture/Helpers/MipmapFormatExtensions.cs b/RePKG.Core/Texture/Helpers/MipmapFormatExtensions.cs index 6b91509..8cfbe6a 100644 --- a/RePKG.Core/Texture/Helpers/MipmapFormatExtensions.cs +++ b/RePKG.Core/Texture/Helpers/MipmapFormatExtensions.cs @@ -1,5 +1,3 @@ -using System; - namespace RePKG.Core.Texture { public static class MipmapFormatExtensions @@ -9,18 +7,18 @@ public static class MipmapFormatExtensions /// public static bool IsImage(this MipmapFormat format) { - return (int) format >= 1000; + return (int)format >= 1000; } - + /// /// Checks if the mipmap format is an raw uncompressed format /// public static bool IsRawFormat(this MipmapFormat format) { - var formatId = (int) format; + var formatId = (int)format; return formatId >= 1 && formatId <= 3; } - + /// /// Checks if the mipmap format is an raw compressed format /// @@ -32,7 +30,7 @@ public static bool IsCompressed(this MipmapFormat format) case MipmapFormat.CompressedDXT3: case MipmapFormat.CompressedDXT1: return true; - + default: return false; } @@ -48,75 +46,109 @@ public static string GetFileExtension(this MipmapFormat format) { case MipmapFormat.ImageBMP: return "bmp"; + case MipmapFormat.ImageICO: return "ico"; + case MipmapFormat.ImageJPEG: return "jpg"; + case MipmapFormat.ImageJNG: return "jng"; + case MipmapFormat.ImageKOALA: return "koa"; + case MipmapFormat.ImageLBM: return "lbm"; + case MipmapFormat.ImageIFF: return "iff"; + case MipmapFormat.ImageMNG: return "mng"; + case MipmapFormat.ImagePBM: case MipmapFormat.ImagePBMRAW: return "pbm"; + case MipmapFormat.ImagePCD: return "pcd"; + case MipmapFormat.ImagePCX: return "pcx"; + case MipmapFormat.ImagePGM: case MipmapFormat.ImagePGMRAW: return "pgm"; + case MipmapFormat.ImagePNG: return "png"; + case MipmapFormat.ImagePPM: case MipmapFormat.ImagePPMRAW: return "ppm"; + case MipmapFormat.ImageRAS: return "ras"; + case MipmapFormat.ImageTARGA: return "tga"; + case MipmapFormat.ImageTIFF: return "tif"; + case MipmapFormat.ImageWBMP: return "wbmp"; + case MipmapFormat.ImagePSD: return "psd"; + case MipmapFormat.ImageCUT: return "cut"; + case MipmapFormat.ImageXBM: return "xbm"; + case MipmapFormat.ImageXPM: return "xpm"; + case MipmapFormat.ImageDDS: return "dds"; + case MipmapFormat.ImageGIF: return "gif"; + case MipmapFormat.ImageHDR: return "hdr"; + case MipmapFormat.ImageFAXG3: return "g3"; + case MipmapFormat.ImageSGI: return "sgi"; + case MipmapFormat.ImageEXR: return "exr"; + case MipmapFormat.ImageJ2K: return "j2k"; + case MipmapFormat.ImageJP2: return "jp2"; + case MipmapFormat.ImagePFM: return "pfm"; + case MipmapFormat.ImagePICT: return "pict"; + case MipmapFormat.ImageRAW: return "raw"; + case MipmapFormat.VideoMp4: return "mp4"; + default: throw new ArgumentOutOfRangeException(nameof(format), format, null); } diff --git a/RePKG.Core/Texture/Helpers/TexMipmapFormatGetter.cs b/RePKG.Core/Texture/Helpers/TexMipmapFormatGetter.cs index 2f0fd83..6df4c46 100644 --- a/RePKG.Core/Texture/Helpers/TexMipmapFormatGetter.cs +++ b/RePKG.Core/Texture/Helpers/TexMipmapFormatGetter.cs @@ -1,5 +1,3 @@ -using System; - namespace RePKG.Core.Texture { public static class TexMipmapFormatGetter @@ -8,26 +6,32 @@ public static MipmapFormat GetFormatForTex(Tex tex) { return GetFormatForTex(tex.ImagesContainer.ImageFormat, tex.Header.Format); } - + public static MipmapFormat GetFormatForTex(FreeImageFormat imageFormat, TexFormat texFormat) { if (imageFormat != FreeImageFormat.FIF_UNKNOWN) return FreeImageFormatToMipmapFormat(imageFormat); - + switch (texFormat) { case TexFormat.RGBA8888: return MipmapFormat.RGBA8888; + case TexFormat.DXT5: return MipmapFormat.CompressedDXT5; + case TexFormat.DXT3: return MipmapFormat.CompressedDXT3; + case TexFormat.DXT1: return MipmapFormat.CompressedDXT1; + case TexFormat.R8: return MipmapFormat.R8; + case TexFormat.RG88: return MipmapFormat.RG88; + default: throw new ArgumentOutOfRangeException(); } @@ -39,113 +43,115 @@ private static MipmapFormat FreeImageFormatToMipmapFormat(FreeImageFormat freeIm { case FreeImageFormat.FIF_UNKNOWN: throw new Exception($"Can't convert '{freeImageFormat}' to '{typeof(MipmapFormat)}'"); - + case FreeImageFormat.FIF_BMP: return MipmapFormat.ImageBMP; - + case FreeImageFormat.FIF_ICO: return MipmapFormat.ImageICO; - + case FreeImageFormat.FIF_JPEG: return MipmapFormat.ImageJPEG; - + case FreeImageFormat.FIF_JNG: return MipmapFormat.ImageJNG; - + case FreeImageFormat.FIF_KOALA: return MipmapFormat.ImageKOALA; - + case FreeImageFormat.FIF_LBM: return MipmapFormat.ImageLBM; - + case FreeImageFormat.FIF_MNG: return MipmapFormat.ImageMNG; - + case FreeImageFormat.FIF_PBM: return MipmapFormat.ImagePBM; - + case FreeImageFormat.FIF_PBMRAW: return MipmapFormat.ImagePBMRAW; - + case FreeImageFormat.FIF_PCD: return MipmapFormat.ImagePCD; - + case FreeImageFormat.FIF_PCX: return MipmapFormat.ImagePCX; - + case FreeImageFormat.FIF_PGM: return MipmapFormat.ImagePGM; - + case FreeImageFormat.FIF_PGMRAW: return MipmapFormat.ImagePGMRAW; - + case FreeImageFormat.FIF_PNG: return MipmapFormat.ImagePNG; - + case FreeImageFormat.FIF_PPM: return MipmapFormat.ImagePPM; - + case FreeImageFormat.FIF_PPMRAW: return MipmapFormat.ImagePPMRAW; - + case FreeImageFormat.FIF_RAS: return MipmapFormat.ImageRAS; - + case FreeImageFormat.FIF_TARGA: return MipmapFormat.ImageTARGA; - + case FreeImageFormat.FIF_TIFF: return MipmapFormat.ImageTIFF; - + case FreeImageFormat.FIF_WBMP: return MipmapFormat.ImageWBMP; - + case FreeImageFormat.FIF_PSD: return MipmapFormat.ImagePSD; - + case FreeImageFormat.FIF_CUT: return MipmapFormat.ImageCUT; - + case FreeImageFormat.FIF_XBM: return MipmapFormat.ImageXBM; - + case FreeImageFormat.FIF_XPM: return MipmapFormat.ImageXPM; - + case FreeImageFormat.FIF_DDS: return MipmapFormat.ImageDDS; - + case FreeImageFormat.FIF_GIF: return MipmapFormat.ImageGIF; - + case FreeImageFormat.FIF_HDR: return MipmapFormat.ImageHDR; - + case FreeImageFormat.FIF_FAXG3: return MipmapFormat.ImageFAXG3; - + case FreeImageFormat.FIF_SGI: return MipmapFormat.ImageSGI; - + case FreeImageFormat.FIF_EXR: return MipmapFormat.ImageEXR; - + case FreeImageFormat.FIF_J2K: return MipmapFormat.ImageJ2K; - + case FreeImageFormat.FIF_JP2: return MipmapFormat.ImageJP2; - + case FreeImageFormat.FIF_PFM: return MipmapFormat.ImagePFM; - + case FreeImageFormat.FIF_PICT: return MipmapFormat.ImagePICT; - + case FreeImageFormat.FIF_RAW: return MipmapFormat.ImageRAW; + case FreeImageFormat.FIF_MP4: return MipmapFormat.VideoMp4; + default: throw new ArgumentOutOfRangeException(nameof(freeImageFormat), freeImageFormat, null); } diff --git a/RePKG.Core/Texture/Interfaces/Data/ITexFrameInfoContainer.cs b/RePKG.Core/Texture/Interfaces/Data/ITexFrameInfoContainer.cs index dba1e68..b678cf0 100644 --- a/RePKG.Core/Texture/Interfaces/Data/ITexFrameInfoContainer.cs +++ b/RePKG.Core/Texture/Interfaces/Data/ITexFrameInfoContainer.cs @@ -1,5 +1,3 @@ -using System.Collections.Generic; - namespace RePKG.Core.Texture { public interface ITexFrameInfoContainer diff --git a/RePKG.Core/Texture/Interfaces/Data/ITexImage.cs b/RePKG.Core/Texture/Interfaces/Data/ITexImage.cs index 1a22092..7c35dee 100644 --- a/RePKG.Core/Texture/Interfaces/Data/ITexImage.cs +++ b/RePKG.Core/Texture/Interfaces/Data/ITexImage.cs @@ -1,5 +1,3 @@ -using System.Collections.Generic; - namespace RePKG.Core.Texture { public interface ITexImage diff --git a/RePKG.Core/Texture/Interfaces/Data/ITexImageContainer.cs b/RePKG.Core/Texture/Interfaces/Data/ITexImageContainer.cs index f1eff15..593623c 100644 --- a/RePKG.Core/Texture/Interfaces/Data/ITexImageContainer.cs +++ b/RePKG.Core/Texture/Interfaces/Data/ITexImageContainer.cs @@ -1,5 +1,3 @@ -using System.Collections.Generic; - namespace RePKG.Core.Texture { public interface ITexImageContainer diff --git a/RePKG.Core/Texture/Interfaces/Data/ITexMipmap.cs b/RePKG.Core/Texture/Interfaces/Data/ITexMipmap.cs index ffcfc61..c64970b 100644 --- a/RePKG.Core/Texture/Interfaces/Data/ITexMipmap.cs +++ b/RePKG.Core/Texture/Interfaces/Data/ITexMipmap.cs @@ -1,5 +1,3 @@ -using System.IO; - namespace RePKG.Core.Texture { public interface ITexMipmap diff --git a/RePKG.Core/Texture/Interfaces/ITexFrameInfoContainerReader.cs b/RePKG.Core/Texture/Interfaces/ITexFrameInfoContainerReader.cs index 59f85cd..ec8aa3f 100644 --- a/RePKG.Core/Texture/Interfaces/ITexFrameInfoContainerReader.cs +++ b/RePKG.Core/Texture/Interfaces/ITexFrameInfoContainerReader.cs @@ -1,5 +1,3 @@ -using System.IO; - namespace RePKG.Core.Texture { public interface ITexFrameInfoContainerReader diff --git a/RePKG.Core/Texture/Interfaces/ITexHeaderReader.cs b/RePKG.Core/Texture/Interfaces/ITexHeaderReader.cs index 7d8a6aa..437d6da 100644 --- a/RePKG.Core/Texture/Interfaces/ITexHeaderReader.cs +++ b/RePKG.Core/Texture/Interfaces/ITexHeaderReader.cs @@ -1,5 +1,3 @@ -using System.IO; - namespace RePKG.Core.Texture { public interface ITexHeaderReader diff --git a/RePKG.Core/Texture/Interfaces/ITexImageContainerReader.cs b/RePKG.Core/Texture/Interfaces/ITexImageContainerReader.cs index 8b3ca66..cffe1d6 100644 --- a/RePKG.Core/Texture/Interfaces/ITexImageContainerReader.cs +++ b/RePKG.Core/Texture/Interfaces/ITexImageContainerReader.cs @@ -1,5 +1,3 @@ -using System.IO; - namespace RePKG.Core.Texture { public interface ITexImageContainerReader diff --git a/RePKG.Core/Texture/Interfaces/ITexImageReader.cs b/RePKG.Core/Texture/Interfaces/ITexImageReader.cs index fca3f59..6bb02f2 100644 --- a/RePKG.Core/Texture/Interfaces/ITexImageReader.cs +++ b/RePKG.Core/Texture/Interfaces/ITexImageReader.cs @@ -1,5 +1,3 @@ -using System.IO; - namespace RePKG.Core.Texture { public interface ITexImageReader diff --git a/RePKG.Core/Texture/Interfaces/ITexMipmapDecompressor.cs b/RePKG.Core/Texture/Interfaces/ITexMipmapDecompressor.cs index 8ceedbe..0a02996 100644 --- a/RePKG.Core/Texture/Interfaces/ITexMipmapDecompressor.cs +++ b/RePKG.Core/Texture/Interfaces/ITexMipmapDecompressor.cs @@ -1,4 +1,4 @@ -namespace RePKG.Core.Texture +namespace RePKG.Core.Texture.Interfaces { public interface ITexMipmapDecompressor { diff --git a/RePKG.Core/Texture/Interfaces/ITexReader.cs b/RePKG.Core/Texture/Interfaces/ITexReader.cs index 5273125..8346917 100644 --- a/RePKG.Core/Texture/Interfaces/ITexReader.cs +++ b/RePKG.Core/Texture/Interfaces/ITexReader.cs @@ -1,5 +1,3 @@ -using System.IO; - namespace RePKG.Core.Texture { public interface ITexReader diff --git a/RePKG.Core/Texture/Interfaces/Writer/ITexFrameInfoContainerWriter.cs b/RePKG.Core/Texture/Interfaces/Writer/ITexFrameInfoContainerWriter.cs index 0d98425..af5b069 100644 --- a/RePKG.Core/Texture/Interfaces/Writer/ITexFrameInfoContainerWriter.cs +++ b/RePKG.Core/Texture/Interfaces/Writer/ITexFrameInfoContainerWriter.cs @@ -1,5 +1,3 @@ -using System.IO; - namespace RePKG.Core.Texture { public interface ITexFrameInfoContainerWriter diff --git a/RePKG.Core/Texture/Interfaces/Writer/ITexHeaderWriter.cs b/RePKG.Core/Texture/Interfaces/Writer/ITexHeaderWriter.cs index a002aef..d2c4854 100644 --- a/RePKG.Core/Texture/Interfaces/Writer/ITexHeaderWriter.cs +++ b/RePKG.Core/Texture/Interfaces/Writer/ITexHeaderWriter.cs @@ -1,5 +1,3 @@ -using System.IO; - namespace RePKG.Core.Texture { public interface ITexHeaderWriter diff --git a/RePKG.Core/Texture/Interfaces/Writer/ITexImageContainerWriter.cs b/RePKG.Core/Texture/Interfaces/Writer/ITexImageContainerWriter.cs index a7ad172..57a6063 100644 --- a/RePKG.Core/Texture/Interfaces/Writer/ITexImageContainerWriter.cs +++ b/RePKG.Core/Texture/Interfaces/Writer/ITexImageContainerWriter.cs @@ -1,5 +1,3 @@ -using System.IO; - namespace RePKG.Core.Texture { public interface ITexImageContainerWriter diff --git a/RePKG.Core/Texture/Interfaces/Writer/ITexImageWriter.cs b/RePKG.Core/Texture/Interfaces/Writer/ITexImageWriter.cs index 7b6a4f8..2a4c0c8 100644 --- a/RePKG.Core/Texture/Interfaces/Writer/ITexImageWriter.cs +++ b/RePKG.Core/Texture/Interfaces/Writer/ITexImageWriter.cs @@ -1,5 +1,3 @@ -using System.IO; - namespace RePKG.Core.Texture { public interface ITexImageWriter diff --git a/RePKG.Core/Texture/Interfaces/Writer/ITexWriter.cs b/RePKG.Core/Texture/Interfaces/Writer/ITexWriter.cs index de75769..71ea6d3 100644 --- a/RePKG.Core/Texture/Interfaces/Writer/ITexWriter.cs +++ b/RePKG.Core/Texture/Interfaces/Writer/ITexWriter.cs @@ -1,5 +1,3 @@ -using System.IO; - namespace RePKG.Core.Texture { public interface ITexWriter diff --git a/RePKG.Core/Texture/Tex.cs b/RePKG.Core/Texture/Tex.cs index ec633a8..60c04ef 100644 --- a/RePKG.Core/Texture/Tex.cs +++ b/RePKG.Core/Texture/Tex.cs @@ -1,5 +1,3 @@ -using System.Linq; - namespace RePKG.Core.Texture { public class Tex : ITex @@ -9,11 +7,11 @@ public class Tex : ITex public ITexHeader Header { get; set; } public ITexImageContainer ImagesContainer { get; set; } public ITexFrameInfoContainer FrameInfoContainer { get; set; } - + public bool IsGif => HasFlag(TexFlags.IsGif); public bool IsVideoTexture => HasFlag(TexFlags.IsVideoTexture); public ITexImage FirstImage => ImagesContainer?.Images.FirstOrDefault(); - + public bool HasFlag(TexFlags flag) { if (Header == null) diff --git a/RePKG.Core/Texture/TexFrameInfoContainer.cs b/RePKG.Core/Texture/TexFrameInfoContainer.cs index 48516c7..a5d1d10 100644 --- a/RePKG.Core/Texture/TexFrameInfoContainer.cs +++ b/RePKG.Core/Texture/TexFrameInfoContainer.cs @@ -1,5 +1,3 @@ -using System.Collections.Generic; - namespace RePKG.Core.Texture { public class TexFrameInfoContainer : ITexFrameInfoContainer diff --git a/RePKG.Core/Texture/TexFrameInfoContainerReader.cs b/RePKG.Core/Texture/TexFrameInfoContainerReader.cs index 147cd12..6668cbc 100644 --- a/RePKG.Core/Texture/TexFrameInfoContainerReader.cs +++ b/RePKG.Core/Texture/TexFrameInfoContainerReader.cs @@ -9,7 +9,7 @@ public class TexFrameInfoContainerReader : ITexFrameInfoContainerReader { public ITexFrameInfoContainer ReadFrom(BinaryReader reader) { - if (reader == null) throw new ArgumentNullException(nameof(reader)); + ArgumentNullException.ThrowIfNull(reader); var container = new TexFrameInfoContainer { diff --git a/RePKG.Core/Texture/TexHeaderReader.cs b/RePKG.Core/Texture/TexHeaderReader.cs index b127bdd..9c3fce0 100644 --- a/RePKG.Core/Texture/TexHeaderReader.cs +++ b/RePKG.Core/Texture/TexHeaderReader.cs @@ -1,7 +1,4 @@ -using System; -using System.IO; using RePKG.Core.Exceptions; -using RePKG.Core.Texture; namespace RePKG.Core.Texture { @@ -10,11 +7,11 @@ public class TexHeaderReader : ITexHeaderReader public ITexHeader ReadFrom(BinaryReader reader) { if (reader == null) throw new ArgumentNullException(nameof(reader)); - + var header = new TexHeader { - Format = (TexFormat) reader.ReadInt32(), - Flags = (TexFlags) reader.ReadInt32(), + Format = (TexFormat)reader.ReadInt32(), + Flags = (TexFlags)reader.ReadInt32(), TextureWidth = reader.ReadInt32(), TextureHeight = reader.ReadInt32(), ImageWidth = reader.ReadInt32(), @@ -24,7 +21,7 @@ public ITexHeader ReadFrom(BinaryReader reader) if (!header.Format.IsValid()) throw new EnumNotValidException(header.Format); - + return header; } } diff --git a/RePKG.Core/Texture/TexImage.cs b/RePKG.Core/Texture/TexImage.cs index f21f379..5aba22c 100644 --- a/RePKG.Core/Texture/TexImage.cs +++ b/RePKG.Core/Texture/TexImage.cs @@ -1,6 +1,3 @@ -using System.Collections.Generic; -using System.Linq; - namespace RePKG.Core.Texture { public class TexImage : ITexImage diff --git a/RePKG.Core/Texture/TexImageContainer.cs b/RePKG.Core/Texture/TexImageContainer.cs index ffc551f..c59fc5d 100644 --- a/RePKG.Core/Texture/TexImageContainer.cs +++ b/RePKG.Core/Texture/TexImageContainer.cs @@ -1,5 +1,3 @@ -using System.Collections.Generic; - namespace RePKG.Core.Texture { public class TexImageContainer : ITexImageContainer @@ -7,7 +5,7 @@ public class TexImageContainer : ITexImageContainer public string Magic { get; set; } public FreeImageFormat ImageFormat { get; set; } = FreeImageFormat.FIF_UNKNOWN; public IList Images { get; } = new List(); - + public TexImageContainerVersion ImageContainerVersion { get; set; } } } \ No newline at end of file diff --git a/RePKG.Core/Texture/TexImageContainerReader.cs b/RePKG.Core/Texture/TexImageContainerReader.cs index 6cfe3e2..451b5e6 100644 --- a/RePKG.Core/Texture/TexImageContainerReader.cs +++ b/RePKG.Core/Texture/TexImageContainerReader.cs @@ -16,7 +16,7 @@ public TexImageContainerReader(ITexImageReader texImageReader) public ITexImageContainer ReadFrom(BinaryReader reader, TexFormat texFormat) { - if (reader == null) throw new ArgumentNullException(nameof(reader)); + ArgumentNullException.ThrowIfNull(reader); if (!texFormat.IsValid()) throw new EnumNotValidException(texFormat); @@ -56,7 +56,7 @@ public ITexImageContainer ReadFrom(BinaryReader reader, TexFormat texFormat) throw new UnknownMagicException(nameof(TexImageContainerReader), container.Magic); } - int version = Convert.ToInt32(container.Magic.Substring(4)); + int version = Convert.ToInt32(container.Magic[4..]); container.ImageContainerVersion = (TexImageContainerVersion)version; if(container.ImageContainerVersion == TexImageContainerVersion.Version4 diff --git a/RePKG.Core/Texture/TexImageReader.cs b/RePKG.Core/Texture/TexImageReader.cs index 227cad2..5521747 100644 --- a/RePKG.Core/Texture/TexImageReader.cs +++ b/RePKG.Core/Texture/TexImageReader.cs @@ -1,7 +1,7 @@ using System; using System.IO; using RePKG.Core.Exceptions; -using RePKG.Core.Texture; +using RePKG.Core.Texture.Interfaces; namespace RePKG.Core.Texture { @@ -21,8 +21,8 @@ public ITexImage ReadFrom( ITexImageContainer container, TexFormat texFormat) { - if (reader == null) throw new ArgumentNullException(nameof(reader)); - if (container == null) throw new ArgumentNullException(nameof(container)); + ArgumentNullException.ThrowIfNull(reader); + ArgumentNullException.ThrowIfNull(container); if (!texFormat.IsValid()) throw new EnumNotValidException(texFormat); @@ -128,21 +128,14 @@ private byte[] ReadBytes(BinaryReader reader) private Func PickMipmapReader(TexImageContainerVersion containerVersion) { - switch (containerVersion) + return containerVersion switch { - case TexImageContainerVersion.Version1: - return ReadMipmapV1; - - case TexImageContainerVersion.Version2: - case TexImageContainerVersion.Version3: - return ReadMipmapV2And3; - - case TexImageContainerVersion.Version4: - return ReadMipmapV4; - default: - throw new InvalidOperationException( - $"Tex image container version: {containerVersion} is not supported!"); - } + TexImageContainerVersion.Version1 => ReadMipmapV1, + TexImageContainerVersion.Version2 or TexImageContainerVersion.Version3 => ReadMipmapV2And3, + TexImageContainerVersion.Version4 => ReadMipmapV4, + _ => throw new InvalidOperationException( + $"Tex image container version: {containerVersion} is not supported!"), + }; } } } diff --git a/RePKG.Core/Texture/TexJsonInfoGenerator.cs b/RePKG.Core/Texture/TexJsonInfoGenerator.cs index ae862bf..00b1e5d 100644 --- a/RePKG.Core/Texture/TexJsonInfoGenerator.cs +++ b/RePKG.Core/Texture/TexJsonInfoGenerator.cs @@ -1,7 +1,5 @@ -using System; using System.Text.Json; using System.Text.Json.Nodes; -using RePKG.Core.Texture; namespace RePKG.Core.Texture { @@ -26,7 +24,7 @@ public string GenerateInfo(ITex tex) { if (tex.FrameInfoContainer == null) throw new InvalidOperationException("TEX is animated but doesn't have frame info container"); - + json["spritesheetsequences"] = new JsonArray { new JsonObject @@ -58,4 +56,4 @@ private static bool NumberIsPowerOfTwo(int n) return true; } } -} +} \ No newline at end of file diff --git a/RePKG.Core/Texture/TexMipmap.cs b/RePKG.Core/Texture/TexMipmap.cs index 4a7140e..05f7cb0 100644 --- a/RePKG.Core/Texture/TexMipmap.cs +++ b/RePKG.Core/Texture/TexMipmap.cs @@ -1,5 +1,3 @@ -using System.IO; - namespace RePKG.Core.Texture { public class TexMipmap : ITexMipmap @@ -10,7 +8,7 @@ public class TexMipmap : ITexMipmap public int DecompressedBytesCount { get; set; } public bool IsLZ4Compressed { get; set; } public MipmapFormat Format { get; set; } - + public Stream GetBytesStream() { return new MemoryStream(Bytes); diff --git a/RePKG.Core/Texture/TexMipmapDecompressor.cs b/RePKG.Core/Texture/TexMipmapDecompressor.cs index 3ef5f09..8fef1fb 100644 --- a/RePKG.Core/Texture/TexMipmapDecompressor.cs +++ b/RePKG.Core/Texture/TexMipmapDecompressor.cs @@ -1,7 +1,7 @@ using System; using K4os.Compression.LZ4; using RePKG.Core.Texture.Helpers; -using RePKG.Core.Texture; +using RePKG.Core.Texture.Interfaces; namespace RePKG.Core.Texture { @@ -9,7 +9,7 @@ public class TexMipmapDecompressor : ITexMipmapDecompressor { public void DecompressMipmap(ITexMipmap mipmap) { - if (mipmap == null) throw new ArgumentNullException(nameof(mipmap)); + ArgumentNullException.ThrowIfNull(mipmap); if (mipmap.IsLZ4Compressed) { @@ -39,6 +39,8 @@ public void DecompressMipmap(ITexMipmap mipmap) private byte[] Lz4Decompress(byte[] bytes, int knownLength) { + ArgumentNullException.ThrowIfNull(bytes); + var buffer = new byte[knownLength]; LZ4Codec.Decode(bytes.AsSpan(), buffer.AsSpan()); return buffer; diff --git a/RePKG.Core/Texture/TexReader.cs b/RePKG.Core/Texture/TexReader.cs index 308c16c..f5637e1 100644 --- a/RePKG.Core/Texture/TexReader.cs +++ b/RePKG.Core/Texture/TexReader.cs @@ -37,7 +37,7 @@ public static TexReader Default public ITex ReadFrom(BinaryReader reader) { - if (reader == null) throw new ArgumentNullException(nameof(reader)); + ArgumentNullException.ThrowIfNull(reader); var tex = new Tex {Magic1 = reader.ReadNString(maxLength: 16)}; diff --git a/RePKG.Core/Texture/TexToImageConverter.cs b/RePKG.Core/Texture/TexToImageConverter.cs index 81e6207..7d487b2 100644 --- a/RePKG.Core/Texture/TexToImageConverter.cs +++ b/RePKG.Core/Texture/TexToImageConverter.cs @@ -1,12 +1,9 @@ -using System; -using System.IO; -using System.Text; using RePKG.Core.Texture.Helpers; -using RePKG.Core.Texture; using SixLabors.ImageSharp; using SixLabors.ImageSharp.Formats.Gif; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; +using System.Text; namespace RePKG.Core.Texture { @@ -18,7 +15,7 @@ public ImageResult ConvertToImage(ITex tex) if (tex.IsGif) return ConvertToGif(tex); - + var sourceMipmap = tex.FirstImage.FirstMipmap; if (tex.IsVideoTexture) @@ -36,7 +33,7 @@ public ImageResult ConvertToImage(ITex tex) { throw new InvalidOperationException("Expected mp4 magic header"); } - + return new ImageResult { Bytes = sourceMipmap.Bytes, @@ -104,7 +101,7 @@ private static ImageResult ConvertToGif(ITex tex) var image = ImageFromRawFormat(frameFormat, null, tex.FrameInfoContainer.GifWidth, tex.FrameInfoContainer.GifHeight); - + var sequenceImages = new Image[tex.ImagesContainer.Images.Count]; for (var i = 0; i < sequenceImages.Length; i++) @@ -128,14 +125,14 @@ private static ImageResult ConvertToGif(ITex tex) var frame = sequenceImages[frameInfo.ImageId].Clone( context => context.Crop(new Rectangle( - (int) x, - (int) y, - (int) Math.Abs(width), - (int) Math.Abs(height)) - ).Rotate((float) Math.Round(rotationAngle * 180 / Math.PI))); + (int)x, + (int)y, + (int)Math.Abs(width), + (int)Math.Abs(height)) + ).Rotate((float)Math.Round(rotationAngle * 180 / Math.PI))); var metadata = frame.Frames.RootFrame.Metadata.GetFormatMetadata(GifFormat.Instance); - metadata.FrameDelay = (int) Math.Round(frameInfo.Frametime * 100.0f); + metadata.FrameDelay = (int)Math.Round(frameInfo.Frametime * 100.0f); image.Frames.AddFrame(frame.Frames[0]); } @@ -145,7 +142,7 @@ private static ImageResult ConvertToGif(ITex tex) using (var memoryStream = new MemoryStream()) { - image.SaveAsGif(memoryStream, new GifEncoder {ColorTableMode = GifColorTableMode.Local}); + image.SaveAsGif(memoryStream, new GifEncoder { ColorTableMode = GifColorTableMode.Local }); return new ImageResult { diff --git a/RePKG.Core/Texture/Writer/TexFrameInfoContainerWriter.cs b/RePKG.Core/Texture/Writer/TexFrameInfoContainerWriter.cs index dbbdb95..2cecbd7 100644 --- a/RePKG.Core/Texture/Writer/TexFrameInfoContainerWriter.cs +++ b/RePKG.Core/Texture/Writer/TexFrameInfoContainerWriter.cs @@ -1,7 +1,4 @@ -using System; -using System.IO; using RePKG.Core.Exceptions; -using RePKG.Core.Texture; namespace RePKG.Core.Texture { @@ -40,12 +37,12 @@ private static void WriteV1(ITexFrameInfoContainer container, BinaryWriter write { writer.Write(frame.ImageId); writer.Write(frame.Frametime); - writer.Write((int) frame.X); - writer.Write((int) frame.Y); - writer.Write((int) frame.Width); - writer.Write((int) frame.WidthY); - writer.Write((int) frame.HeightX); - writer.Write((int) frame.Height); + writer.Write((int)frame.X); + writer.Write((int)frame.Y); + writer.Write((int)frame.Width); + writer.Write((int)frame.WidthY); + writer.Write((int)frame.HeightX); + writer.Write((int)frame.Height); } } diff --git a/RePKG.Core/Texture/Writer/TexHeaderWriter.cs b/RePKG.Core/Texture/Writer/TexHeaderWriter.cs index 8e88895..259fc99 100644 --- a/RePKG.Core/Texture/Writer/TexHeaderWriter.cs +++ b/RePKG.Core/Texture/Writer/TexHeaderWriter.cs @@ -1,7 +1,3 @@ -using System; -using System.IO; -using RePKG.Core.Texture; - namespace RePKG.Core.Texture { public class TexHeaderWriter : ITexHeaderWriter @@ -11,8 +7,8 @@ public void WriteTo(BinaryWriter writer, ITexHeader header) if (writer == null) throw new ArgumentNullException(nameof(writer)); if (header == null) throw new ArgumentNullException(nameof(header)); - writer.Write((int) header.Format); - writer.Write((int) header.Flags); + writer.Write((int)header.Format); + writer.Write((int)header.Flags); writer.Write(header.TextureWidth); writer.Write(header.TextureHeight); writer.Write(header.ImageWidth); diff --git a/RePKG.Core/Texture/Writer/TexImageContainerWriter.cs b/RePKG.Core/Texture/Writer/TexImageContainerWriter.cs index 8ae021e..ca366e2 100644 --- a/RePKG.Core/Texture/Writer/TexImageContainerWriter.cs +++ b/RePKG.Core/Texture/Writer/TexImageContainerWriter.cs @@ -1,7 +1,4 @@ -using System; -using System.IO; using RePKG.Core.Exceptions; -using RePKG.Core.Texture; namespace RePKG.Core.Texture { @@ -18,7 +15,7 @@ public void WriteTo(BinaryWriter writer, ITexImageContainer imageContainer) { if (writer == null) throw new ArgumentNullException(nameof(writer)); if (imageContainer == null) throw new ArgumentNullException(nameof(imageContainer)); - + writer.WriteNString(imageContainer.Magic); writer.Write(imageContainer.Images.Count); @@ -29,13 +26,13 @@ public void WriteTo(BinaryWriter writer, ITexImageContainer imageContainer) break; case TexImageContainerVersion.Version3: - writer.Write((int) imageContainer.ImageFormat); + writer.Write((int)imageContainer.ImageFormat); break; default: throw new UnknownMagicException(nameof(TexImageContainerWriter), imageContainer.Magic); } - + foreach (var image in imageContainer.Images) { _texImageWriter.WriteTo(writer, imageContainer.ImageContainerVersion, image); diff --git a/RePKG.Core/Texture/Writer/TexImageWriter.cs b/RePKG.Core/Texture/Writer/TexImageWriter.cs index 682eb54..794c900 100644 --- a/RePKG.Core/Texture/Writer/TexImageWriter.cs +++ b/RePKG.Core/Texture/Writer/TexImageWriter.cs @@ -1,7 +1,3 @@ -using System; -using System.IO; -using RePKG.Core.Texture; - namespace RePKG.Core.Texture { public class TexImageWriter : ITexImageWriter @@ -32,7 +28,7 @@ private static void WriteMipmapV1(BinaryWriter writer, ITexMipmap mipmap) using (var stream = mipmap.GetBytesStream()) { - writer.Write((int) stream.Length); + writer.Write((int)stream.Length); writer.Flush(); stream.CopyTo(writer.BaseStream); } @@ -47,7 +43,7 @@ private static void WriteMipmapV2And3(BinaryWriter writer, ITexMipmap mipmap) using (var stream = mipmap.GetBytesStream()) { - writer.Write((int) stream.Length); + writer.Write((int)stream.Length); writer.Flush(); stream.CopyTo(writer.BaseStream); } diff --git a/RePKG.Core/Texture/Writer/TexMipmapCompressor.cs b/RePKG.Core/Texture/Writer/TexMipmapCompressor.cs index edc8ded..af45983 100644 --- a/RePKG.Core/Texture/Writer/TexMipmapCompressor.cs +++ b/RePKG.Core/Texture/Writer/TexMipmapCompressor.cs @@ -1,6 +1,4 @@ -using System; using K4os.Compression.LZ4; -using RePKG.Core.Texture; namespace RePKG.Core.Texture { @@ -16,7 +14,7 @@ public void CompressMipmap( if (targetCompressFormat != mipmap.Format) throw new NotSupportedException("Changing mipmap format is not yet supported"); - + if (lz4Compress) LZ4Compress(mipmap); } @@ -29,10 +27,10 @@ private static void LZ4Compress(ITexMipmap mipmap) var compressedSize = LZ4Codec.Encode( bytes, 0, bytes.Length, buffer, 0, buffer.Length); - + if (compressedSize < maximumSize) Array.Resize(ref buffer, compressedSize); - + mipmap.DecompressedBytesCount = bytes.Length; mipmap.Bytes = buffer; mipmap.IsLZ4Compressed = true; diff --git a/RePKG.Core/Texture/Writer/TexWriter.cs b/RePKG.Core/Texture/Writer/TexWriter.cs index d491d7e..76491f7 100644 --- a/RePKG.Core/Texture/Writer/TexWriter.cs +++ b/RePKG.Core/Texture/Writer/TexWriter.cs @@ -1,7 +1,4 @@ -using System; -using System.IO; using RePKG.Core.Exceptions; -using RePKG.Core.Texture; namespace RePKG.Core.Texture { diff --git a/RePKG.Tests/PkgWriterTests.cs b/RePKG.Tests/PkgWriterTests.cs index 40bc197..52345ce 100644 --- a/RePKG.Tests/PkgWriterTests.cs +++ b/RePKG.Tests/PkgWriterTests.cs @@ -1,8 +1,7 @@ -using System.IO; -using System.Text; using NUnit.Framework; using RePKG.Core.Package; using RePKG.Core.Package.Interfaces; +using System.Text; namespace RePKG.Tests { @@ -12,7 +11,7 @@ public class PkgWriterTests [Test] public void TestWriteAndRead() { - var package = new Package {Magic = "PKGV0005"}; + var package = new Package { Magic = "PKGV0005" }; package.Entries.Add(new PackageEntry { @@ -36,8 +35,8 @@ public void TestWriteAndRead() // Read stream.Position = 0; - var packageReader = new PackageReader {ReadEntryBytes = true}; - + var packageReader = new PackageReader { ReadEntryBytes = true }; + Package readPackage; using (var binaryReader = new BinaryReader(stream, Encoding.UTF8, true)) { @@ -60,4 +59,4 @@ public void TestWriteAndRead() } } } -} +} \ No newline at end of file diff --git a/RePKG.Tests/TestHelper.cs b/RePKG.Tests/TestHelper.cs index 4356eca..1f8dabd 100644 --- a/RePKG.Tests/TestHelper.cs +++ b/RePKG.Tests/TestHelper.cs @@ -1,5 +1,3 @@ -using System; - namespace RePKG.Tests { public static class TestHelper @@ -7,10 +5,10 @@ public static class TestHelper static TestHelper() { BasePath = AppContext.BaseDirectory.Split( - new[] {"RePKG.Tests"}, + new[] { "RePKG.Tests" }, StringSplitOptions.RemoveEmptyEntries)[0] + "RePKG.Tests"; } - + public static string BasePath { get; } } } \ No newline at end of file diff --git a/RePKG.Tests/TexDecompressingTests.cs b/RePKG.Tests/TexDecompressingTests.cs index 4cb44f3..afb61a5 100644 --- a/RePKG.Tests/TexDecompressingTests.cs +++ b/RePKG.Tests/TexDecompressingTests.cs @@ -1,8 +1,6 @@ -using System; -using System.IO; -using System.Text; using NUnit.Framework; using RePKG.Core.Texture; +using System.Text; namespace RePKG.Tests { @@ -70,9 +68,9 @@ public void TestTexDecompressing( private void ConvertToImageAndSave(ITex tex, string name) { var resultImage = _texToImageConverter.ConvertToImage(tex); - + var path = $"{TestHelper.BasePath}\\{OutputDirectoryName}\\{name}.{resultImage.Format.GetFileExtension()}"; - + File.WriteAllBytes(path, resultImage.Bytes); } @@ -115,4 +113,4 @@ public static void ValidateBytes(byte[] bytes, string name) } } } -} +} \ No newline at end of file diff --git a/RePKG.Tests/TexWriterTests.cs b/RePKG.Tests/TexWriterTests.cs index 3cba3f8..1d04dd0 100644 --- a/RePKG.Tests/TexWriterTests.cs +++ b/RePKG.Tests/TexWriterTests.cs @@ -1,8 +1,6 @@ -using System; -using System.IO; -using System.Text; using NUnit.Framework; using RePKG.Core.Texture; +using System.Text; namespace RePKG.Tests { @@ -30,7 +28,6 @@ public void Setup() _writer = TexWriter.Default; } - // V%i - The number is TexImageContainer.ImageContainerVersion [Test] [TestCase("V1_DXT5")] @@ -47,13 +44,12 @@ public void Setup() [TestCase("V3_DXT5")] [TestCase("V3_RGBA8888_GIF_TEXS0003")] [TestCase("V3_VIDEOTEXTURE_MP4")] - // TODO: V4_ ones are failing but we don't really need writing functionality public void TestWriteAndRead(string name) { // Load file var inputFileReader = TexDecompressingTests.LoadTestFile(name); var inputBytes = new byte[inputFileReader.BaseStream.Length]; - var bytesRead = inputFileReader.Read(inputBytes, 0, (int) inputFileReader.BaseStream.Length); + var bytesRead = inputFileReader.Read(inputBytes, 0, (int)inputFileReader.BaseStream.Length); Assert.AreEqual(inputFileReader.BaseStream.Length, bytesRead, "Failed to read input file"); inputFileReader.Close(); @@ -82,4 +78,4 @@ public void TestWriteAndRead(string name) } } } -} +} \ No newline at end of file diff --git a/RePKG/Command/Extract.cs b/RePKG/Commands/Extract.cs similarity index 96% rename from RePKG/Command/Extract.cs rename to RePKG/Commands/Extract.cs index 51f1701..dccf163 100644 --- a/RePKG/Command/Extract.cs +++ b/RePKG/Commands/Extract.cs @@ -15,11 +15,11 @@ namespace RePKG.Commands { public static class Extract { - private static readonly string[] ProjectFiles = { "project.json" }; + private static readonly string[] ProjectFiles = ["project.json"]; private static readonly ITexReader _texReader = TexReader.Default; private static readonly ITexJsonInfoGenerator _texJsonInfoGenerator = new TexJsonInfoGenerator(); private static readonly IPackageReader _packageReader = new PackageReader(); - private static readonly TexToImageConverter _texToImageConverter = new TexToImageConverter(); + private static readonly TexToImageConverter _texToImageConverter = new(); public static void Action(ExtractOptions o) { @@ -91,7 +91,7 @@ private static void ExtractPkgDirectory(ExtractOptions o, DirectoryInfo director if (file.Directory == null || file.Directory.FullName.Length < rootLen) ExtractPkg(o, file); else - ExtractPkg(o, file, true, file.Directory.FullName.Substring(rootLen)); + ExtractPkg(o, file, true, file.Directory.FullName[rootLen..]); } return; } @@ -99,7 +99,7 @@ private static void ExtractPkgDirectory(ExtractOptions o, DirectoryInfo director foreach (var directory in directoryInfo.EnumerateDirectories()) { foreach (var file in directory.EnumerateFiles("*.pkg")) - ExtractPkg(o, file, true, directory.FullName.Substring(rootLen)); + ExtractPkg(o, file, true, directory.FullName[rootLen..]); } } @@ -309,6 +309,8 @@ private static void ConvertToImageAndSave(ExtractOptions o, ITex tex, string pat private static string[] NormalizeExtensions(string[] array) { + ArgumentNullException.ThrowIfNull(array); + for (int i = 0; i < array.Length; i++) if (!array[i].StartsWith(".")) array[i] = '.' + array[i]; @@ -329,14 +331,22 @@ public static Command BuildCommand() var noTexOpt = new Option("--no-tex-convert") { Description = "Don't convert TEX files into images while extracting PKG" }; var overOpt = new Option("--overwrite") { Description = "Overwrite all existing files" }; - var cmd = new Command("extract", "Extract PKG / Convert TEX into image"); - cmd.Add(inputArg); - cmd.Add(outputOpt); cmd.Add(ignoreOpt); cmd.Add(onlyOpt); - cmd.Add(texOpt); cmd.Add(sdirOpt); cmd.Add(recurOpt); - cmd.Add(copyOpt); cmd.Add(nameOpt); cmd.Add(noTexOpt); - cmd.Add(overOpt); - - cmd.SetAction((ParseResult pr) => Action(new ExtractOptions + var cmd = new Command("extract", "Extract PKG / Convert TEX into image") + { + inputArg, + outputOpt, + ignoreOpt, + onlyOpt, + texOpt, + sdirOpt, + recurOpt, + copyOpt, + nameOpt, + noTexOpt, + overOpt + }; + + cmd.SetAction(pr => Action(new ExtractOptions { Input = pr.GetValue(inputArg)!, OutputDirectory = pr.GetValue(outputOpt) ?? "./output", diff --git a/RePKG/Command/Info.cs b/RePKG/Commands/Info.cs similarity index 84% rename from RePKG/Command/Info.cs rename to RePKG/Commands/Info.cs index 161d6b4..d0ffeed 100644 --- a/RePKG/Command/Info.cs +++ b/RePKG/Commands/Info.cs @@ -1,11 +1,7 @@ -using System; -using System.Collections.Generic; +using RePKG.Core.Package; +using RePKG.Core.Package.Interfaces; using System.CommandLine; -using System.IO; -using System.Linq; using System.Text.Json.Nodes; -using RePKG.Core.Package; -using RePKG.Core.Package.Interfaces; namespace RePKG.Commands { @@ -140,28 +136,28 @@ private static bool MatchesFilter(InfoOptions o, JsonNode? project) public static Command BuildCommand() { - var inputArg = new Argument("input") { Description = "Path to file/directory" }; - var sortOpt = new Option("--sort", ["-s"]) { Description = "Sort entries a-z" }; + var inputArg = new Argument("input") { Description = "Path to file/directory" }; + var sortOpt = new Option("--sort", ["-s"]) { Description = "Sort entries a-z" }; var sortByOpt = new Option("--sortby", ["-b"]) { Description = "Sort by name/extension/size", DefaultValueFactory = _ => "name" }; - var texOpt = new Option("--tex", ["-t"]) { Description = "Dump info about all tex files from specified directory" }; - var projOpt = new Option("--projectinfo", ["-p"]) { Description = "Keys from project.json (comma-separated, * for all)" }; - var printOpt = new Option("--printentries", ["-e"]) { Description = "Print entries in packages" }; + var texOpt = new Option("--tex", ["-t"]) { Description = "Dump info about all tex files from specified directory" }; + var projOpt = new Option("--projectinfo", ["-p"]) { Description = "Keys from project.json (comma-separated, * for all)" }; + var printOpt = new Option("--printentries", ["-e"]) { Description = "Print entries in packages" }; var filterOpt = new Option("--title-filter") { Description = "Title filter" }; var cmd = new Command("info", "Dumps PKG/TEX info"); cmd.Add(inputArg); cmd.Add(sortOpt); cmd.Add(sortByOpt); cmd.Add(texOpt); - cmd.Add(projOpt); cmd.Add(printOpt); cmd.Add(filterOpt); + cmd.Add(projOpt); cmd.Add(printOpt); cmd.Add(filterOpt); cmd.SetAction((ParseResult pr) => Action(new InfoOptions { - Input = pr.GetValue(inputArg)!, - Sort = pr.GetValue(sortOpt), - SortBy = pr.GetValue(sortByOpt)!, + Input = pr.GetValue(inputArg)!, + Sort = pr.GetValue(sortOpt), + SortBy = pr.GetValue(sortByOpt)!, TexDirectory = pr.GetValue(texOpt), - ProjectInfo = pr.GetValue(projOpt), + ProjectInfo = pr.GetValue(projOpt), PrintEntries = pr.GetValue(printOpt), - TitleFilter = pr.GetValue(filterOpt), + TitleFilter = pr.GetValue(filterOpt), })); return cmd; diff --git a/RePKG/Helper.cs b/RePKG/Helper.cs index 93835e0..adf1f37 100644 --- a/RePKG/Helper.cs +++ b/RePKG/Helper.cs @@ -1,6 +1,4 @@ -using System.Collections.Generic; -using System.Linq; -using System.Text.Json.Nodes; +using System.Text.Json.Nodes; namespace RePKG { @@ -11,4 +9,4 @@ public static IEnumerable GetPropertyKeysForDynamic(JsonObject jsonObjec return jsonObject.Select(x => x.Key); } } -} +} \ No newline at end of file diff --git a/RePKG/Program.cs b/RePKG/Program.cs index 588e8e4..94598fd 100644 --- a/RePKG/Program.cs +++ b/RePKG/Program.cs @@ -13,9 +13,11 @@ private static int Main(string[] args) { Console.CancelKeyPress += Cancel; - var root = new RootCommand("RePKG - Wallpaper Engine package tool"); - root.Add(Extract.BuildCommand()); - root.Add(Info.BuildCommand()); + var root = new RootCommand("RePKG - Wallpaper Engine package tool") + { + Extract.BuildCommand(), + Info.BuildCommand() + }; root.Action = new HelpAction(); return root.Parse(args).Invoke(); } From 76d1f8e834c33d2f15a4bdbc093a2e75f1d917b0 Mon Sep 17 00:00:00 2001 From: ZNH <35349300+kingsznhone@users.noreply.github.com> Date: Tue, 28 Apr 2026 04:32:15 +0800 Subject: [PATCH 7/7] code clean --- RePKG.Core/Extensions.cs | 4 +- RePKG.Core/Package/PackageEntry.cs | 3 +- RePKG.Core/Texture/Helpers/RG88.cs | 13 ++--- .../Texture/TexFrameInfoContainerReader.cs | 13 ++--- RePKG.Core/Texture/TexImageContainerReader.cs | 12 ++--- RePKG.Core/Texture/TexImageReader.cs | 24 ++++----- RePKG.Core/Texture/TexMipmapDecompressor.cs | 3 +- RePKG.Core/Texture/TexReader.cs | 5 +- RePKG/Commands/Extract.cs | 50 +++++++++---------- RePKG/Extensions.cs | 7 +-- RePKG/Program.cs | 5 +- 11 files changed, 62 insertions(+), 77 deletions(-) diff --git a/RePKG.Core/Extensions.cs b/RePKG.Core/Extensions.cs index d97f090..ccc91d4 100644 --- a/RePKG.Core/Extensions.cs +++ b/RePKG.Core/Extensions.cs @@ -1,5 +1,3 @@ -using System; -using System.IO; using System.Text; namespace RePKG.Core @@ -28,7 +26,7 @@ public static void WriteNString(this BinaryWriter writer, string input) ArgumentNullException.ThrowIfNull(input); writer.Write(Encoding.UTF8.GetBytes(input)); - writer.Write((byte) 0); + writer.Write((byte)0); } public static string ReadStringI32Size(this BinaryReader reader, int maxLength = -1) diff --git a/RePKG.Core/Package/PackageEntry.cs b/RePKG.Core/Package/PackageEntry.cs index 409e324..166181b 100644 --- a/RePKG.Core/Package/PackageEntry.cs +++ b/RePKG.Core/Package/PackageEntry.cs @@ -1,4 +1,3 @@ -using System.IO; using RePKG.Core.Package.Enums; namespace RePKG.Core.Package @@ -10,7 +9,7 @@ public class PackageEntry public int Length { get; set; } public byte[] Bytes { get; set; } public EntryType Type { get; set; } - + public string Name => Path.GetFileNameWithoutExtension(FullPath); public string Extension => Path.GetExtension(FullPath); public string DirectoryPath => Path.GetDirectoryName(FullPath); diff --git a/RePKG.Core/Texture/Helpers/RG88.cs b/RePKG.Core/Texture/Helpers/RG88.cs index 7ed0d09..2ddd283 100644 --- a/RePKG.Core/Texture/Helpers/RG88.cs +++ b/RePKG.Core/Texture/Helpers/RG88.cs @@ -1,8 +1,8 @@ +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.PixelFormats; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using SixLabors.ImageSharp; -using SixLabors.ImageSharp.PixelFormats; namespace RePKG.Core.Texture.Helpers { @@ -21,6 +21,7 @@ public RG88(byte r, byte g) R = r; G = g; } + public ushort Rg { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -33,7 +34,7 @@ public ushort Rg public uint PackedValue { get => Rg; - set => Rg = (ushort) value; + set => Rg = (ushort)value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -136,7 +137,7 @@ public void ToRgba32(ref Rgba32 dest) public static byte DownScaleFrom16BitTo8Bit(ushort component) { - return (byte) (component * byte.MaxValue + 32895 >> 16); + return (byte)(component * byte.MaxValue + 32895 >> 16); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -170,8 +171,8 @@ private void Pack(ref Vector4 vector) vector += Half; vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); - R = (byte) vector.X; - G = (byte) vector.Y; + R = (byte)vector.X; + G = (byte)vector.Y; } } } \ No newline at end of file diff --git a/RePKG.Core/Texture/TexFrameInfoContainerReader.cs b/RePKG.Core/Texture/TexFrameInfoContainerReader.cs index 6668cbc..84c88d5 100644 --- a/RePKG.Core/Texture/TexFrameInfoContainerReader.cs +++ b/RePKG.Core/Texture/TexFrameInfoContainerReader.cs @@ -1,7 +1,4 @@ -using System; -using System.IO; using RePKG.Core.Exceptions; -using RePKG.Core.Texture; namespace RePKG.Core.Texture { @@ -10,7 +7,7 @@ public class TexFrameInfoContainerReader : ITexFrameInfoContainerReader public ITexFrameInfoContainer ReadFrom(BinaryReader reader) { ArgumentNullException.ThrowIfNull(reader); - + var container = new TexFrameInfoContainer { Magic = reader.ReadNString(maxLength: 16) @@ -54,7 +51,7 @@ public ITexFrameInfoContainer ReadFrom(BinaryReader reader) }); } break; - + case "TEXS0002": case "TEXS0003": for (var i = 0; i < frameCount; i++) @@ -72,7 +69,7 @@ public ITexFrameInfoContainer ReadFrom(BinaryReader reader) }); } break; - + default: throw new UnknownMagicException(nameof(TexFrameInfoContainerReader), container.Magic); } @@ -82,8 +79,8 @@ public ITexFrameInfoContainer ReadFrom(BinaryReader reader) if (container.GifWidth == 0 || container.GifHeight == 0) { - container.GifWidth = (int) container.Frames[0].Width; - container.GifHeight = (int) container.Frames[0].Height; + container.GifWidth = (int)container.Frames[0].Width; + container.GifHeight = (int)container.Frames[0].Height; } return container; diff --git a/RePKG.Core/Texture/TexImageContainerReader.cs b/RePKG.Core/Texture/TexImageContainerReader.cs index 451b5e6..2b0fc2f 100644 --- a/RePKG.Core/Texture/TexImageContainerReader.cs +++ b/RePKG.Core/Texture/TexImageContainerReader.cs @@ -1,7 +1,4 @@ -using System; -using System.IO; using RePKG.Core.Exceptions; -using RePKG.Core.Texture; namespace RePKG.Core.Texture { @@ -37,9 +34,11 @@ public ITexImageContainer ReadFrom(BinaryReader reader, TexFormat texFormat) case "TEXB0001": case "TEXB0002": break; + case "TEXB0003": - container.ImageFormat = (FreeImageFormat) reader.ReadInt32(); + container.ImageFormat = (FreeImageFormat)reader.ReadInt32(); break; + case "TEXB0004": var format = (FreeImageFormat)reader.ReadInt32(); var isVideoMp4 = reader.ReadInt32() == 1; @@ -52,6 +51,7 @@ public ITexImageContainer ReadFrom(BinaryReader reader, TexFormat texFormat) } container.ImageFormat = format; break; + default: throw new UnknownMagicException(nameof(TexImageContainerReader), container.Magic); } @@ -59,12 +59,12 @@ public ITexImageContainer ReadFrom(BinaryReader reader, TexFormat texFormat) int version = Convert.ToInt32(container.Magic[4..]); container.ImageContainerVersion = (TexImageContainerVersion)version; - if(container.ImageContainerVersion == TexImageContainerVersion.Version4 + if (container.ImageContainerVersion == TexImageContainerVersion.Version4 && container.ImageFormat != FreeImageFormat.FIF_MP4) { container.ImageContainerVersion = TexImageContainerVersion.Version3; } - + if (!container.ImageFormat.IsValid()) throw new EnumNotValidException(container.ImageFormat); diff --git a/RePKG.Core/Texture/TexImageReader.cs b/RePKG.Core/Texture/TexImageReader.cs index 5521747..b47d790 100644 --- a/RePKG.Core/Texture/TexImageReader.cs +++ b/RePKG.Core/Texture/TexImageReader.cs @@ -1,5 +1,3 @@ -using System; -using System.IO; using RePKG.Core.Exceptions; using RePKG.Core.Texture.Interfaces; @@ -23,20 +21,20 @@ public ITexImage ReadFrom( { ArgumentNullException.ThrowIfNull(reader); ArgumentNullException.ThrowIfNull(container); - + if (!texFormat.IsValid()) throw new EnumNotValidException(texFormat); var mipmapCount = reader.ReadInt32(); - + if (mipmapCount > Constants.MaximumMipmapCount) throw new UnsafeTexException( $"Mipmap count exceeds limit: {mipmapCount}/{Constants.MaximumMipmapCount}"); - + var readFunction = PickMipmapReader(container.ImageContainerVersion); var format = TexMipmapFormatGetter.GetFormatForTex(container.ImageFormat, texFormat); var image = new TexImage(); - + for (var i = 0; i < mipmapCount; i++) { var mipmap = readFunction(reader); @@ -72,24 +70,25 @@ private TexMipmap ReadMipmapV2And3(BinaryReader reader) Bytes = ReadBytes(reader) }; } + private TexMipmap ReadMipmapV4(BinaryReader reader) { /**FIXME - * The role of the following param* parameters cannot be confirmed, + * The role of the following param* parameters cannot be confirmed, * it may be a parameter used in the built-in display of the wallpaper editor and does not need to be processed */ var param1 = reader.ReadInt32(); - if(param1 != 1) + if (param1 != 1) { throw new UnsafeTexException($"ReadMipmapV4 unknow param1 :{param1}"); } - var param2= reader.ReadInt32(); + var param2 = reader.ReadInt32(); if (param2 != 2) { throw new UnsafeTexException($"ReadMipmapV4 unknow param2 :{param2}"); } var conditionJson = reader.ReadNString(); - + var param3 = reader.ReadInt32(); if (param3 != 1) { @@ -104,10 +103,11 @@ private TexMipmap ReadMipmapV4(BinaryReader reader) Bytes = ReadBytes(reader) }; } + private byte[] ReadBytes(BinaryReader reader) { var byteCount = reader.ReadInt32(); - + if (reader.BaseStream.Position + byteCount > reader.BaseStream.Length) throw new UnsafeTexException("Detected invalid mipmap byte count - exceeds stream length"); @@ -138,4 +138,4 @@ private Func PickMipmapReader(TexImageContainerVersion }; } } -} +} \ No newline at end of file diff --git a/RePKG.Core/Texture/TexMipmapDecompressor.cs b/RePKG.Core/Texture/TexMipmapDecompressor.cs index 8fef1fb..5cd52e4 100644 --- a/RePKG.Core/Texture/TexMipmapDecompressor.cs +++ b/RePKG.Core/Texture/TexMipmapDecompressor.cs @@ -1,4 +1,3 @@ -using System; using K4os.Compression.LZ4; using RePKG.Core.Texture.Helpers; using RePKG.Core.Texture.Interfaces; @@ -26,10 +25,12 @@ public void DecompressMipmap(ITexMipmap mipmap) mipmap.Bytes = DXT.DecompressImage(mipmap.Width, mipmap.Height, mipmap.Bytes, DXTFlags.DXT5); mipmap.Format = MipmapFormat.RGBA8888; break; + case MipmapFormat.CompressedDXT3: mipmap.Bytes = DXT.DecompressImage(mipmap.Width, mipmap.Height, mipmap.Bytes, DXTFlags.DXT3); mipmap.Format = MipmapFormat.RGBA8888; break; + case MipmapFormat.CompressedDXT1: mipmap.Bytes = DXT.DecompressImage(mipmap.Width, mipmap.Height, mipmap.Bytes, DXTFlags.DXT1); mipmap.Format = MipmapFormat.RGBA8888; diff --git a/RePKG.Core/Texture/TexReader.cs b/RePKG.Core/Texture/TexReader.cs index f5637e1..499bc19 100644 --- a/RePKG.Core/Texture/TexReader.cs +++ b/RePKG.Core/Texture/TexReader.cs @@ -1,7 +1,4 @@ -using System; -using System.IO; using RePKG.Core.Exceptions; -using RePKG.Core.Texture; namespace RePKG.Core.Texture { @@ -39,7 +36,7 @@ public ITex ReadFrom(BinaryReader reader) { ArgumentNullException.ThrowIfNull(reader); - var tex = new Tex {Magic1 = reader.ReadNString(maxLength: 16)}; + var tex = new Tex { Magic1 = reader.ReadNString(maxLength: 16) }; if (tex.Magic1 != "TEXV0005") throw new UnknownMagicException(nameof(TexReader), nameof(tex.Magic1), tex.Magic1); diff --git a/RePKG/Commands/Extract.cs b/RePKG/Commands/Extract.cs index dccf163..4451854 100644 --- a/RePKG/Commands/Extract.cs +++ b/RePKG/Commands/Extract.cs @@ -1,15 +1,11 @@ -using System; -using System.Collections.Generic; +using RePKG.Core.Package; +using RePKG.Core.Package.Enums; +using RePKG.Core.Package.Interfaces; +using RePKG.Core.Texture; using System.CommandLine; using System.Diagnostics.CodeAnalysis; -using System.IO; -using System.Linq; using System.Text; using System.Text.Json.Nodes; -using RePKG.Core.Package; -using RePKG.Core.Texture; -using RePKG.Core.Package.Enums; -using RePKG.Core.Package.Interfaces; namespace RePKG.Commands { @@ -319,17 +315,17 @@ private static string[] NormalizeExtensions(string[] array) public static Command BuildCommand() { - var inputArg = new Argument("input") { Description = "Path to file/directory" }; + var inputArg = new Argument("input") { Description = "Path to file/directory" }; var outputOpt = new Option("--output", ["-o"]) { Description = "Output directory", DefaultValueFactory = _ => "./output" }; var ignoreOpt = new Option("--ignoreexts", ["-i"]) { Description = "Don't extract files with these extensions (comma-separated)" }; - var onlyOpt = new Option("--onlyexts", ["-e"]) { Description = "Only extract files with these extensions (comma-separated)" }; - var texOpt = new Option("--tex", ["-t"]) { Description = "Convert all tex files into images from specified directory" }; - var sdirOpt = new Option("--singledir", ["-s"]) { Description = "Put all extracted files in one directory" }; - var recurOpt = new Option("--recursive", ["-r"]) { Description = "Recursive search in all subfolders" }; - var copyOpt = new Option("--copyproject", ["-c"]) { Description = "Copy project.json and preview.jpg into output directory" }; - var nameOpt = new Option("--usename", ["-n"]) { Description = "Use project.json title as subfolder name instead of id" }; - var noTexOpt = new Option("--no-tex-convert") { Description = "Don't convert TEX files into images while extracting PKG" }; - var overOpt = new Option("--overwrite") { Description = "Overwrite all existing files" }; + var onlyOpt = new Option("--onlyexts", ["-e"]) { Description = "Only extract files with these extensions (comma-separated)" }; + var texOpt = new Option("--tex", ["-t"]) { Description = "Convert all tex files into images from specified directory" }; + var sdirOpt = new Option("--singledir", ["-s"]) { Description = "Put all extracted files in one directory" }; + var recurOpt = new Option("--recursive", ["-r"]) { Description = "Recursive search in all subfolders" }; + var copyOpt = new Option("--copyproject", ["-c"]) { Description = "Copy project.json and preview.jpg into output directory" }; + var nameOpt = new Option("--usename", ["-n"]) { Description = "Use project.json title as subfolder name instead of id" }; + var noTexOpt = new Option("--no-tex-convert") { Description = "Don't convert TEX files into images while extracting PKG" }; + var overOpt = new Option("--overwrite") { Description = "Overwrite all existing files" }; var cmd = new Command("extract", "Extract PKG / Convert TEX into image") { @@ -348,17 +344,17 @@ public static Command BuildCommand() cmd.SetAction(pr => Action(new ExtractOptions { - Input = pr.GetValue(inputArg)!, + Input = pr.GetValue(inputArg)!, OutputDirectory = pr.GetValue(outputOpt) ?? "./output", - IgnoreExts = pr.GetValue(ignoreOpt), - OnlyExts = pr.GetValue(onlyOpt), - TexDirectory = pr.GetValue(texOpt), - SingleDir = pr.GetValue(sdirOpt), - Recursive = pr.GetValue(recurOpt), - CopyProject = pr.GetValue(copyOpt), - UseName = pr.GetValue(nameOpt), - NoTexConvert = pr.GetValue(noTexOpt), - Overwrite = pr.GetValue(overOpt), + IgnoreExts = pr.GetValue(ignoreOpt), + OnlyExts = pr.GetValue(onlyOpt), + TexDirectory = pr.GetValue(texOpt), + SingleDir = pr.GetValue(sdirOpt), + Recursive = pr.GetValue(recurOpt), + CopyProject = pr.GetValue(copyOpt), + UseName = pr.GetValue(nameOpt), + NoTexConvert = pr.GetValue(noTexOpt), + Overwrite = pr.GetValue(overOpt), })); return cmd; diff --git a/RePKG/Extensions.cs b/RePKG/Extensions.cs index dc8bec5..77995b8 100644 --- a/RePKG/Extensions.cs +++ b/RePKG/Extensions.cs @@ -1,7 +1,4 @@ -using System; -using System.IO; - -namespace RePKG +namespace RePKG { public static class Extensions { @@ -15,4 +12,4 @@ public static string GetSafeFilename(this string filename) return string.Join("_", filename.Split(Path.GetInvalidFileNameChars())); } } -} +} \ No newline at end of file diff --git a/RePKG/Program.cs b/RePKG/Program.cs index 94598fd..b34ac80 100644 --- a/RePKG/Program.cs +++ b/RePKG/Program.cs @@ -1,7 +1,6 @@ -using System; +using RePKG.Commands; using System.CommandLine; using System.CommandLine.Help; -using RePKG.Commands; namespace RePKG { @@ -29,4 +28,4 @@ private static void Cancel(object? sender, ConsoleCancelEventArgs e) Console.WriteLine("Terminating..."); } } -} +} \ No newline at end of file