Example #1
0
        /* Compress */
        public override MemoryStream Compress(ref Stream data, string filename)
        {
            try
            {
                uint DecompressedSize = (uint)data.Length;

                MemoryStream CompressedData = new MemoryStream();
                byte[] DecompressedData     = data.ToByteArray();

                uint SourcePointer = 0x0;
                uint DestPointer   = 0x10;

                // Test if the file is too large to be compressed
                if (data.Length > 0xFFFFFFFF)
                    throw new Exception("Input file is too large to compress.");

                // Set up the Lz Compression Dictionary
                LzBufferDictionary LzDictionary = new LzBufferDictionary();
                LzDictionary.SetBufferSize(0x1000);
                LzDictionary.SetBufferStart(0xFEE);
                LzDictionary.SetMaxMatchAmount(0xF + 3);

                // Start compression
                CompressedData.Write("LZ01");
                CompressedData.Write((uint)0); // Will be filled in later
                CompressedData.Write(DecompressedSize);
                CompressedData.Seek(4, SeekOrigin.Current); // Advance 4 bytes

                while (SourcePointer < DecompressedSize)
                {
                    byte Flag = 0x0;
                    uint FlagPosition = DestPointer;
                    CompressedData.WriteByte(Flag); // It will be filled in later
                    DestPointer++;

                    for (int i = 0; i < 8; i++)
                    {
                        int[] LzSearchMatch = LzDictionary.Search(DecompressedData, SourcePointer, DecompressedSize);
                        if (LzSearchMatch[1] > 0) // There is a compression match
                        {
                            Flag |= (byte)(0 << i);

                            CompressedData.WriteByte((byte)(LzSearchMatch[0] & 0xFF));
                            CompressedData.WriteByte((byte)(((LzSearchMatch[0] & 0xF00) >> 4) | ((LzSearchMatch[1] - 3) & 0xF)));

                            LzDictionary.AddEntryRange(DecompressedData, (int)SourcePointer, LzSearchMatch[1]);

                            SourcePointer += (uint)LzSearchMatch[1];
                            DestPointer   += 2;
                        }
                        else // There wasn't a match
                        {
                            Flag |= (byte)(1 << i);

                            CompressedData.WriteByte(DecompressedData[SourcePointer]);

                            LzDictionary.AddEntry(DecompressedData, (int)SourcePointer);

                            SourcePointer++;
                            DestPointer++;
                        }

                        // Check for out of bounds
                        if (SourcePointer >= DecompressedSize)
                            break;
                    }

                    // Write the flag.
                    // Note that the original position gets reset after writing.
                    CompressedData.Seek(FlagPosition, SeekOrigin.Begin);
                    CompressedData.WriteByte(Flag);
                    CompressedData.Seek(DestPointer, SeekOrigin.Begin);
                }

                CompressedData.Seek(0x4, SeekOrigin.Begin);
                CompressedData.Write((uint)CompressedData.Length);
                CompressedData.Seek(0, SeekOrigin.End);

                return CompressedData;
            }
            catch
            {
                return null; // An error occured while compressing
            }
        }
Example #2
0
        /* Compress */
        public override MemoryStream Compress(ref Stream data, string filename)
        {
            try
            {
                uint DecompressedSize = (uint)data.Length;

                MemoryStream CompressedData = new MemoryStream();
                byte[] DecompressedData     = data.ToByteArray();

                uint SourcePointer = 0x0;
                uint DestPointer   = 0x40;

                uint MagicValue = (uint)(DateTime.Now - new DateTime(1970, 1, 1)).TotalSeconds;

                // Test if the file is too large to be compressed
                if (data.Length > 0xFFFFFFFF)
                    throw new Exception("Input file is too large to compress.");

                // Set up the Lz Compression Dictionary
                LzBufferDictionary LzDictionary = new LzBufferDictionary();
                LzDictionary.SetBufferSize(0x1000);
                LzDictionary.SetBufferStart(0xFEE);
                LzDictionary.SetMaxMatchAmount(0xF + 3);

                // Start compression
                CompressedData.Write("LZ00");
                CompressedData.Write(0u); // Will be filled in later
                CompressedData.Seek(8, SeekOrigin.Current); // Advance 8 bytes

                // If the file extension is MRZ or TEZ, we probably want to change it
                if (Path.GetExtension(filename).ToLower() == ".mrz")
                    filename = Path.GetFileNameWithoutExtension(filename) + ".mrg";
                else if (Path.GetExtension(filename).ToLower() == ".tez")
                    filename = Path.GetFileNameWithoutExtension(filename) + ".tex";

                CompressedData.Write(filename, 31, 32, Encoding.GetEncoding("Shift_JIS"));
                CompressedData.Write(DecompressedSize);
                CompressedData.Write(MagicValue);
                CompressedData.Seek(8, SeekOrigin.Current); // Advance 8 bytes

                while (SourcePointer < DecompressedSize)
                {
                    MagicValue = GetNewMagicValue(MagicValue);

                    byte Flag = 0x0;
                    uint FlagPosition   = DestPointer;
                    uint FlagMagicValue = MagicValue; // Since it won't be filled in now
                    CompressedData.WriteByte(Flag); // It will be filled in later
                    DestPointer++;

                    for (int i = 0; i < 8; i++)
                    {
                        int[] LzSearchMatch = LzDictionary.Search(DecompressedData, SourcePointer, DecompressedSize);
                        if (LzSearchMatch[1] > 0) // There is a compression match
                        {
                            Flag |= (byte)(0 << i);

                            MagicValue = GetNewMagicValue(MagicValue);
                            CompressedData.WriteByte(EncryptByte((byte)(LzSearchMatch[0] & 0xFF), MagicValue));
                            MagicValue = GetNewMagicValue(MagicValue);
                            CompressedData.WriteByte(EncryptByte((byte)(((LzSearchMatch[0] & 0xF00) >> 4) | ((LzSearchMatch[1] - 3) & 0xF)), MagicValue));

                            LzDictionary.AddEntryRange(DecompressedData, (int)SourcePointer, LzSearchMatch[1]);

                            SourcePointer += (uint)LzSearchMatch[1];
                            DestPointer   += 2;
                        }
                        else // There wasn't a match
                        {
                            Flag |= (byte)(1 << i);

                            MagicValue = GetNewMagicValue(MagicValue);
                            CompressedData.WriteByte(EncryptByte(DecompressedData[SourcePointer], MagicValue));

                            LzDictionary.AddEntry(DecompressedData, (int)SourcePointer);

                            SourcePointer++;
                            DestPointer++;
                        }

                        // Check for out of bounds
                        if (SourcePointer >= DecompressedSize)
                            break;
                    }

                    // Write the flag.
                    // Note that the original position gets reset after writing.
                    CompressedData.Seek(FlagPosition, SeekOrigin.Begin);
                    CompressedData.WriteByte(EncryptByte(Flag, FlagMagicValue));
                    CompressedData.Seek(DestPointer, SeekOrigin.Begin);
                }

                CompressedData.Seek(0x4, SeekOrigin.Begin);
                CompressedData.Write((uint)CompressedData.Length);
                CompressedData.Seek(0, SeekOrigin.End);

                return CompressedData;
            }
            catch
            {
                return null; // An error occured while compressing
            }
        }