diff --git a/CSharp/DSDecmp/DSDecmp.csproj b/CSharp/DSDecmp/DSDecmp.csproj index afdfb04..778bfcf 100644 --- a/CSharp/DSDecmp/DSDecmp.csproj +++ b/CSharp/DSDecmp/DSDecmp.csproj @@ -56,6 +56,7 @@ + diff --git a/CSharp/DSDecmp/Formats/Nitro/NitroCFormat.cs b/CSharp/DSDecmp/Formats/Nitro/NitroCFormat.cs index 5621cfc..e00e7d1 100644 --- a/CSharp/DSDecmp/Formats/Nitro/NitroCFormat.cs +++ b/CSharp/DSDecmp/Formats/Nitro/NitroCFormat.cs @@ -39,7 +39,7 @@ namespace DSDecmp.Formats.Nitro } /// - /// Checks if the first four bytes match the format used in nitro compression formats. + /// Checks if the first four (or eight) bytes match the format used in nitro compression formats. /// public override bool Supports(System.IO.Stream stream, long inLength) { diff --git a/CSharp/DSDecmp/Formats/Nitro/NullCompression.cs b/CSharp/DSDecmp/Formats/Nitro/NullCompression.cs new file mode 100644 index 0000000..0fc966d --- /dev/null +++ b/CSharp/DSDecmp/Formats/Nitro/NullCompression.cs @@ -0,0 +1,158 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.IO; + +namespace DSDecmp.Formats.Nitro +{ + /// + /// 'Compression' format without any compression whatsoever. + /// Compression using this format will only prepend 0x00 plus the original file size to the file. + /// + public class NullCompression : NitroCFormat + { + /// + /// Gets a short string identifying this compression format. + /// + public override string ShortFormatString + { + get { return "NULL"; } + } + + /// + /// Gets a short description of this compression format (used in the program usage). + /// + public override string Description + { + get { return "NULL-'compression' format. Prefixes file with 0x00 and filesize."; } + } + + /// + /// Gets if this format supports compressing a file. + /// + public override bool SupportsCompression + { + get { return true; } + } + + /// + /// Gets the value that must be given on the command line in order to compress using this format. + /// + public override string CompressionFlag + { + get { return "null"; } + } + + /// + /// Creates a new instance of the NULL-compression format. + /// + public NullCompression() + : base(0) { } + + /// + /// Checks if the given stream is (or could be) 'compressed' using the NULL compression format. + /// + public override bool Supports(System.IO.Stream stream, long inLength) + { + long startPosition = stream.Position; + try + { + int firstByte = stream.ReadByte(); + if (firstByte != 0) + return false; + byte[] sizeBytes = new byte[3]; + stream.Read(sizeBytes, 0, 3); + int outSize = IOUtils.ToNDSu24(sizeBytes, 0); + int headerSize = 4; + if (outSize == 0) + { + sizeBytes = new byte[4]; + stream.Read(sizeBytes, 0, 4); + outSize = (int)IOUtils.ToNDSu32(sizeBytes, 0); + headerSize = 8; + } + return outSize == inLength - headerSize; + } + finally + { + stream.Position = startPosition; + } + } + + /// + /// 'Decompresses' the given input stream using the NULL format. + /// + public override long Decompress(System.IO.Stream instream, long inLength, System.IO.Stream outstream) + { + long readBytes = 0; + + byte type = (byte)instream.ReadByte(); + if (type != base.magicByte) + throw new InvalidDataException("The provided stream is not a valid Null " + + "compressed stream (invalid type 0x" + type.ToString("X") + ")"); + byte[] sizeBytes = new byte[3]; + instream.Read(sizeBytes, 0, 3); + int decompressedSize = IOUtils.ToNDSu24(sizeBytes, 0); + readBytes += 4; + if (decompressedSize == 0) + { + sizeBytes = new byte[4]; + instream.Read(sizeBytes, 0, 4); + decompressedSize = IOUtils.ToNDSs32(sizeBytes, 0); + readBytes += 4; + } + + byte[] data = new byte[decompressedSize]; + int readLength = instream.Read(data, 0, decompressedSize); + outstream.Write(data, 0, readLength); + if (readLength < decompressedSize) + throw new NotEnoughDataException(readLength, decompressedSize); + + return readLength; + } + + /// + /// 'Compresses' the given input stream using the NULL format. + /// + public override int Compress(System.IO.Stream instream, long inLength, System.IO.Stream outstream) + { + if (inLength > 0xFFFFFFFF) + throw new InputTooLargeException(); + + long outSize = 4; + + outstream.WriteByte(0); + if (inLength <= 0xFFFFFF) + { + outstream.WriteByte((byte)(inLength & 0xFF)); + outstream.WriteByte((byte)((inLength >> 8) & 0xFF)); + outstream.WriteByte((byte)((inLength >> 16) & 0xFF)); + } + else + { + outstream.WriteByte(0); + outstream.WriteByte(0); + outstream.WriteByte(0); + outstream.WriteByte((byte)(inLength & 0xFF)); + outstream.WriteByte((byte)((inLength >> 8) & 0xFF)); + outstream.WriteByte((byte)((inLength >> 16) & 0xFF)); + outstream.WriteByte((byte)((inLength >> 24) & 0xFF)); + outSize = 8; + } + + byte[] buffer = new byte[Math.Min(int.MaxValue, inLength)]; + long remaining = inLength; + while (remaining > 0) + { + int readLength = instream.Read(buffer, 0, (int)Math.Min(buffer.Length, remaining)); + if (readLength == 0) + throw new StreamTooShortException(); + remaining -= readLength; + outstream.Write(buffer, 0, readLength); + outSize += readLength; + } + + return (int)Math.Min(int.MaxValue, outSize); + } + } +} diff --git a/CSharp/DSDecmp/NewestProgram.cs b/CSharp/DSDecmp/NewestProgram.cs index ffe20eb..8010cd2 100644 --- a/CSharp/DSDecmp/NewestProgram.cs +++ b/CSharp/DSDecmp/NewestProgram.cs @@ -8,7 +8,7 @@ using DSDecmp.Formats.Nitro; namespace DSDecmp { - class NewestProgram + public class NewestProgram { #if DEBUG public static string PluginFolder = "./Plugins/Debug"; @@ -177,7 +177,7 @@ namespace DSDecmp using (MemoryStream inStr = new MemoryStream(inputData), outStr = new MemoryStream()) { - if (!format.Supports(inStr, input.Length)) + if (!format.Supports(inStr, inputData.Length)) continue; try { @@ -549,9 +549,12 @@ namespace DSDecmp yield return new Huffman4(); yield return new Huffman8(); yield return new RLE(); + yield return new NullCompression(); if (alsoCompositeFormats) { - + yield return new HuffmanAny(); + yield return new CompositeGBAFormat(); + yield return new CompositeNDSFormat(); } } /// diff --git a/CSharp/PluginDistro/DSDecmp.xml b/CSharp/PluginDistro/DSDecmp.xml index 8a02d3f..67746ba 100644 --- a/CSharp/PluginDistro/DSDecmp.xml +++ b/CSharp/PluginDistro/DSDecmp.xml @@ -257,7 +257,7 @@ - Checks if the first four bytes match the format used in nitro compression formats. + Checks if the first four (or eight) bytes match the format used in nitro compression formats. @@ -1090,5 +1090,51 @@ Gets the value that must be given on the command line in order to compress using this format. + + + 'Compression' format without any compression whatsoever. + Compression using this format will only prepend 0x00 plus the original file size to the file. + + + + + Creates a new instance of the NULL-compression format. + + + + + Checks if the given stream is (or could be) 'compressed' using the NULL compression format. + + + + + 'Decompresses' the given input stream using the NULL format. + + + + + 'Compresses' the given input stream using the NULL format. + + + + + Gets a short string identifying this compression format. + + + + + Gets a short description of this compression format (used in the program usage). + + + + + Gets if this format supports compressing a file. + + + + + Gets the value that must be given on the command line in order to compress using this format. + + diff --git a/CSharp/PluginDistro/GoldenSunDD.dll b/CSharp/PluginDistro/GoldenSunDD.dll index 66dac93..0b07164 100644 Binary files a/CSharp/PluginDistro/GoldenSunDD.dll and b/CSharp/PluginDistro/GoldenSunDD.dll differ diff --git a/CSharp/PluginDistro/LuminousArc.dll b/CSharp/PluginDistro/LuminousArc.dll index 3c6ea5d..8b97086 100644 Binary files a/CSharp/PluginDistro/LuminousArc.dll and b/CSharp/PluginDistro/LuminousArc.dll differ