public MYP(MythicPackage package, Stream stream)
        {
            _stream = stream;
            Package = package;
            BinaryReader reader = new BinaryReader(stream);

            Header = new MYPHeader();
            Header.Load(reader);

            MFTTables.Add(new MFTHeader()
            {
                Length        = Header.EntriesPerMFT,
                NextMFTOffset = Header.MFTOffset
            });

            var mftOffset     = Header.MFTOffset;
            var mftEntryCount = Header.EntriesPerMFT;

            reader.BaseStream.Position = mftOffset;

            while (mftOffset > 0)
            {
                reader.BaseStream.Position = mftOffset;
                MFT        = new MFTHeader();
                MFT.Offset = reader.BaseStream.Position;
                MFT.Load(reader);

                MFTTables.Add(MFT);

                mftOffset = MFT.NextMFTOffset;
                int entryIndex = 0;

                while (entryIndex < mftEntryCount)
                {
                    var entry = new MFTEntry();
                    entry.Changed = false;
                    entry.Load(this, reader, entryIndex);

                    if (entry.Hash != 0)
                    {
                        Enteries[entry.Hash] = entry;
                    }

                    entryIndex++;
                }
                mftEntryCount = MFT.Length;
            }
        }
 public void UpdateFile(long hash, byte[] data)
 {
     if (Enteries.ContainsKey(hash))
     {
         Enteries[hash].Changed = true;
         Enteries[hash].Data    = data;
     }
     else
     {
         Enteries[hash] = new MFTEntry()
         {
             Changed    = true,
             Data       = data,
             Compressed = 1,
             Hash       = hash
         };
     }
 }
        public byte[] ReadFile(MFTEntry entry)
        {
            if (entry.Compressed == 1)
            {
                byte[] output_buffer = new byte[entry.UnCompressedSize];

                _stream.Position = (long)(entry.Offset + entry.HeaderSize + 2);
                MemoryStream ms = new MemoryStream(output_buffer);
                using (DeflateStream decompressionStream = new DeflateStream(_stream, CompressionMode.Decompress, true))
                    decompressionStream.Read(output_buffer, 0, output_buffer.Length);

                return(output_buffer);
            }
            else
            {
                byte[] output_buffer = new byte[entry.CompressedSize];
                _stream.Position = (long)(entry.Offset + entry.HeaderSize);
                _stream.Read(output_buffer, 0, (int)entry.CompressedSize);
                return(output_buffer);
            }
        }
        public void AddEntries(List <Tuple <string, byte[]> > files)
        {
            _stream.Position = 0x18;
            BinaryWriter writer = new BinaryWriter(_stream);

            //update total file count in myp header
            writer.Write((uint)Enteries.Count + files.Count);


            //update last MFT entry to point to next
            if (MFTTables.Count > 0)
            {
                _stream.Position = MFTTables.Last().Offset + 4;
                writer.Write((ulong)writer.BaseStream.Length);
            }

            //move to end of the archive and add new MFT entry
            writer.BaseStream.Position = writer.BaseStream.Length;

            var  packed     = 0;
            var  toPack     = new List <MFTEntry>();
            int  remaining  = files.Count;
            long nextMftPos = 0;

            while (remaining > 0)
            {
                writer.Write((uint)1000);        //1000 entries per mft
                if (files.Count - packed > 1000) //another MFT entry after this?
                {
                    nextMftPos = _stream.Position;
                    writer.Write((long)0); //next mft position
                }
                else
                {
                    writer.Write((long)0);
                }

                for (int i = 0; i < 1000; i++)
                {
                    //every 1000 files, write out MFT header, and dump files after it
                    if (packed < files.Count)
                    {
                        remaining--;
                        var entry = new MFTEntry();

                        MemoryStream ms = new MemoryStream();

                        using (DeflateStream compressStream = new DeflateStream(ms, CompressionMode.Compress, true))
                        {
                            compressStream.Write(files[packed].Item2, 0, files[packed].Item2.Length);
                        }

                        entry.Data    = new byte[ms.Length + 2];
                        entry.Data[0] = 0x78;
                        entry.Data[1] = 0x9C;
                        Buffer.BlockCopy(ms.ToArray(), 0, entry.Data, 2, (int)ms.Length);
                        entry.CompressedSize   = (uint)entry.Data.Length;
                        entry.Hash             = HashWAR(files[packed].Item1);
                        entry.CRC32            = CRC32.ComputeChecksum(files[packed].Item2);
                        entry.Compressed       = 1;
                        entry.UnCompressedSize = (uint)files[packed].Item2.Length;

                        entry.MFTEntryOffset = _stream.Position;
                        writer.Write((long)0);                      //will determine data offset on second pass
                        writer.Write((uint)entry.HeaderSize);
                        writer.Write((uint)entry.CompressedSize);   //compressed size
                        writer.Write((uint)entry.UnCompressedSize); //uncompressed size
                        writer.Write((long)entry.Hash);

                        writer.Write((uint)entry.CRC32);      //CRC
                        writer.Write((byte)entry.Compressed); //compress
                        writer.Write((byte)0);                //unknown
                        toPack.Add(entry);
                        packed++;
                    }
                    else
                    {
                        writer.Write((long)0); //offset
                        writer.Write((uint)0); //headersize
                        writer.Write((uint)0); //compressed size
                        writer.Write((uint)0); //uncompressed size
                        writer.Write((long)0); //hash
                        writer.Write((uint)0); //CRC
                        writer.Write((byte)0); //compression
                        writer.Write((byte)0); //unknown
                    }
                }

                int packing = 0;

                foreach (var entry in toPack)
                {
                    var pos = _stream.Position;
                    _stream.Position = entry.MFTEntryOffset;
                    writer.Write((long)pos);
                    _stream.Position = pos;

                    byte[] data = entry.Data;

                    _stream.Write(data, 0, data.Length);

                    if (entry.Compressed == 1)
                    {
                        var output_buffer = new byte[entry.UnCompressedSize];

                        MemoryStream ms = new MemoryStream(data);
                        ms.Position = (long)(entry.HeaderSize + 2);
                        using (DeflateStream decompressionStream = new DeflateStream(ms, CompressionMode.Decompress, true))
                        {
                            decompressionStream.Read(output_buffer, 0, output_buffer.Length);
                        }
                    }
                    packing++;
                }


                if (packed < files.Count)
                {
                    var lastPos = _stream.Position;
                    _stream.Position = nextMftPos;
                    writer.Write((long)lastPos); //next mft position
                    _stream.Position = lastPos;
                }

                toPack.Clear();
            }
        }