public void Commit(bool cleanCommit)
        {
            if (this.Stream.CanWrite == false)
            {
                throw new NotSupportedException();
            }

            DatabasePackedFile dbpf = new DatabasePackedFile();
            dbpf.Version = new Version(2, 0);

            if (cleanCommit == false)
            {
                if (this.EndOfDataOffset == 0)
                {
                    // new archive
                    this.Stream.Seek(this.BaseOffset, SeekOrigin.Begin);
                    dbpf.WriteHeader(this.Stream, 0, 0);
                    this.EndOfDataOffset = this.Stream.Position - this.BaseOffset;
                }

                foreach (KeyValuePair<MadScience.Wrappers.ResourceKey, Entry> kvp in this._Entries)
                {
                    DatabasePackedFile.Entry entry = new DatabasePackedFile.Entry();
                    entry.Key = kvp.Key;

                    if (kvp.Value is MemoryEntry)
                    {
                        MemoryEntry memory = (MemoryEntry)kvp.Value;

                        byte[] compressed;
                        bool success = MadScience.RefPack.Compression.Compress(memory.Data, out compressed);
                        //bool success = memory.Data.RefPackCompress(out compressed);
                        if (success == true)
                        {
                            entry.DecompressedSize = (uint)(memory.Data.Length);
                            entry.CompressedSize = (uint)(compressed.Length) | 0x80000000;
                            entry.CompressionFlags = -1;
                            entry.Flags = 1;
                            memory.Data = compressed;
                        }
                        else
                        {
                            entry.DecompressedSize = memory.DecompressedSize;
                            entry.CompressedSize = memory.CompressedSize | 0x80000000;
                            entry.CompressionFlags = 0;
                            entry.Flags = 1;
                        }

                        // Is this replacing old data?
                        if (this.OriginalEntries.ContainsKey(kvp.Key) == true)
                        {
                            StreamEntry stream = this.OriginalEntries[kvp.Key];

                            // Let's see if the new data can fit where the old data was
                            if (memory.Data.Length <= stream.CompressedSize)
                            {
                                entry.Offset = stream.Offset;
                                this.Stream.Seek(this.BaseOffset + stream.Offset, SeekOrigin.Begin);
                                this.Stream.Write(memory.Data, 0, memory.Data.Length);
                            }
                            else
                            {
                                entry.Offset = this.EndOfDataOffset;
                                this.Stream.Seek(this.BaseOffset + this.EndOfDataOffset, SeekOrigin.Begin);
                                this.Stream.Write(memory.Data, 0, memory.Data.Length);
                                this.EndOfDataOffset += memory.Data.Length;
                            }
                        }
                        // New data
                        else
                        {
                            entry.Offset = this.EndOfDataOffset;
                            this.Stream.Seek(this.BaseOffset + this.EndOfDataOffset, SeekOrigin.Begin);
                            this.Stream.Write(memory.Data, 0, memory.Data.Length);
                            this.EndOfDataOffset += memory.Data.Length;
                        }
                    }
                    else if (kvp.Value is StreamEntry)
                    {
                        StreamEntry stream = (StreamEntry)kvp.Value;
                        entry.CompressedSize = stream.CompressedSize | 0x80000000;
                        entry.DecompressedSize = stream.DecompressedSize;
                        entry.Offset = stream.Offset;
                        entry.CompressionFlags = stream.CompressedFlags;
                        entry.Flags = stream.Flags;
                    }
                    else
                    {
                        throw new InvalidOperationException();
                    }

                    dbpf.Entries.Add(entry);
                }

                this.Stream.Seek(this.BaseOffset + this.EndOfDataOffset, SeekOrigin.Begin);
                dbpf.WriteIndex(this.Stream);

                long indexSize = (this.Stream.Position - (this.BaseOffset + this.EndOfDataOffset));

                this.Stream.Seek(this.BaseOffset, SeekOrigin.Begin);
                dbpf.WriteHeader(this.Stream, this.EndOfDataOffset, indexSize);
            }
            else
            {
                Stream clean;
                string tempFileName = null;

                // Packages greater than five mb will be cleaned with a file supported stream
                if (this.Stream.Length >= (1024 * 1024) * 5)
                {
                    tempFileName = Path.GetTempFileName();
                    clean = File.Open(tempFileName, FileMode.Create, FileAccess.ReadWrite, FileShare.Read);
                }
                else
                {
                    clean = new MemoryStream();
                }

                dbpf.WriteHeader(clean, 0, 0);
                this.EndOfDataOffset = clean.Position;

                foreach (KeyValuePair<MadScience.Wrappers.ResourceKey, Entry> kvp in this._Entries)
                {
                    DatabasePackedFile.Entry entry = new DatabasePackedFile.Entry();
                    entry.Key = kvp.Key;

                    if (kvp.Value is MemoryEntry)
                    {
                        MemoryEntry memory = (MemoryEntry)kvp.Value;

                        byte[] compressed;
                        bool success = MadScience.RefPack.Compression.Compress(memory.Data, out compressed);
                        //bool success = memory.Data.RefPackCompress(out compressed);
                        if (success == true)
                        {
                            entry.DecompressedSize = (uint)(memory.Data.Length);
                            entry.CompressedSize = (uint)(compressed.Length) | 0x80000000;
                            entry.CompressionFlags = -1;
                            entry.Flags = 1;
                            entry.Offset = this.EndOfDataOffset;
                            memory.Data = compressed;
                        }
                        else
                        {
                            entry.DecompressedSize = memory.DecompressedSize;
                            entry.CompressedSize = memory.CompressedSize | 0x80000000;
                            entry.CompressionFlags = 0;
                            entry.Flags = 1;
                            entry.Offset = this.EndOfDataOffset;
                        }

                        clean.Write(memory.Data, 0, memory.Data.Length);
                        this.EndOfDataOffset += memory.Data.Length;
                    }
                    else if (kvp.Value is StreamEntry)
                    {
                        StreamEntry stream = (StreamEntry)kvp.Value;
                        entry.CompressedSize = stream.CompressedSize | 0x80000000;
                        entry.DecompressedSize = stream.DecompressedSize;
                        entry.CompressionFlags = stream.CompressedFlags;
                        entry.Flags = stream.Flags;

                        entry.Offset = this.EndOfDataOffset;

                        // Copy data
                        this.Stream.Seek(this.BaseOffset + stream.Offset, SeekOrigin.Begin);
                        byte[] data = new byte[4096];
                        int left = (int)stream.CompressedSize;
                        while (left > 0)
                        {
                            int block = Math.Min(left, (int)data.Length);
                            this.Stream.Read(data, 0, block);
                            clean.Write(data, 0, block);
                            left -= block;
                        }

                        this.EndOfDataOffset += stream.CompressedSize;
                    }
                    else
                    {
                        throw new InvalidOperationException();
                    }

                    dbpf.Entries.Add(entry);
                }

                dbpf.WriteIndex(clean);

                long indexSize = clean.Position - this.EndOfDataOffset;

                clean.Seek(0, SeekOrigin.Begin);
                dbpf.WriteHeader(clean, this.EndOfDataOffset, indexSize);

                // copy clean to real stream
                {
                    this.Stream.Seek(this.BaseOffset, SeekOrigin.Begin);
                    clean.Seek(0, SeekOrigin.Begin);

                    byte[] data = new byte[4096];
                    long left = clean.Length;
                    while (left > 0)
                    {
                        int block = (int)Math.Min(left, data.Length);
                        clean.Read(data, 0, block);
                        this.Stream.Write(data, 0, block);
                        left -= block;
                    }
                }

                this.Stream.SetLength(this.BaseOffset + this.EndOfDataOffset + indexSize);
                clean.Close();

                if (tempFileName != null)
                {
                    try
                    {
                        File.Delete(tempFileName);
                    }
                    catch (Exception)
                    {
                    }
                }
            }

            this._Entries.Clear();
            this.OriginalEntries.Clear();

            foreach (DatabasePackedFile.Entry entry in dbpf.Entries)
            {
                this._Entries.Add(entry.Key, new StreamEntry()
                {
                    Compressed = entry.Compressed,
                    Offset = entry.Offset,
                    CompressedSize = entry.CompressedSize,
                    DecompressedSize = entry.DecompressedSize,
                    CompressedFlags = entry.CompressionFlags,
                    Flags = entry.Flags,
                });
            }
        }
        public void readDatabase(Stream stream, bool readExisting, bool throwError)
        {
            if (stream.CanSeek == false || stream.CanRead == false)
            {
                throw new ArgumentException("stream must have seek / read access", "stream");
            }

            this.Stream = stream;
            this.BaseOffset = this.Stream.Position;

            //this._Entries = new Dictionary<string, Entry>();
            this._Entries = new Dictionary<MadScience.Wrappers.ResourceKey, Entry>();

            this.OriginalEntries = new Dictionary<MadScience.Wrappers.ResourceKey, StreamEntry>();

            if (readExisting == true)
            {
                this.dbpf = new MadScience.Wrappers.DatabasePackedFile();
                dbpf.Read(stream, throwError);

                this.EndOfDataOffset = dbpf.EndOfDataOffset;

                if (dbpf.Entries.Count > 0)
                {
                    foreach (MadScience.Wrappers.DatabasePackedFile.Entry entry in dbpf.Entries)
                    {
                        try
                        {
                            this._Entries.Add(entry.Key, new StreamEntry()
                                {
                                    Compressed = entry.Compressed,
                                    Offset = entry.Offset,
                                    CompressedSize = entry.CompressedSize,
                                    DecompressedSize = entry.DecompressedSize,
                                    CompressedFlags = entry.CompressionFlags,
                                    Flags = entry.Flags,
                                });
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message);
                        }
                        //if (entry.Offset + entry.CompressedSize > this.EndOfDataOffset)
                        //{
                        //    this.EndOfDataOffset = entry.Offset + entry.CompressedSize;
                        //}
                    }
                }

            }
            else
            {
                this.EndOfDataOffset = 0;
            }
        }
        private bool checkTXTCEntry(DatabasePackedFile.Entry entry, Database db)
        {
            if (entry.Key.typeId == 0x033A1435)
            {
                //textBox1.Text += "  " + entry.Key.ToString() + Environment.NewLine;
                // textBox1.Text += "    Checking for corrupted TGI offset... ";

                // Quick and dirty way
                Stream TXTC = db.GetResourceStream(entry.Key);
                // Read offset, first 4 bytes after ID
                StreamHelpers.ReadValueU32(TXTC);

                uint offset = StreamHelpers.ReadValueU32(TXTC);
                // textBox1.Text += offset.ToString() + "...";

                // Seek to this offset + 8 and read the number there.
                TXTC.Seek(offset + 8, SeekOrigin.Begin);

                uint numTGIs = StreamHelpers.ReadValueU8(TXTC);
                // textBox1.Text += numTGIs.ToString() + " TGIs... ";

                // Since each TGI is 16 bytes we can calculate how many bytes they are.
                uint tgiSize = numTGIs * 16;
                uint tgiOffsetEnd = offset + 8 + 1 + tgiSize;

                //textBox1.Text += "TGI block end is at " + tgiOffsetEnd.ToString() + "...";

                if (tgiOffsetEnd == TXTC.Length)
                {
                    TXTC = null;
                    return true;
                }
                else
                {
                    TXTC = null;
                    return false;
                }

            }

            return true;
        }
        private int checkValidEntry(DatabasePackedFile.Entry entry, Database db)
        {
            int validEntry = 0; // 0 = valid
            if (!checkTXTCEntry(entry, db))
            {
                validEntry = 2; // 2 = BlueLot TXTC
            }

            return validEntry;
        }
Beispiel #5
0
        public void Commit(bool cleanCommit)
        {
            if (this.Stream.CanWrite == false)
            {
                throw new NotSupportedException();
            }

            DatabasePackedFile dbpf = new DatabasePackedFile();

            dbpf.Version = new Version(2, 0);

            if (cleanCommit == false)
            {
                if (this.EndOfDataOffset == 0)
                {
                    // new archive
                    this.Stream.Seek(this.BaseOffset, SeekOrigin.Begin);
                    dbpf.WriteHeader(this.Stream, 0, 0);
                    this.EndOfDataOffset = this.Stream.Position - this.BaseOffset;
                }

                foreach (KeyValuePair <MadScience.Wrappers.ResourceKey, Entry> kvp in this._Entries)
                {
                    DatabasePackedFile.Entry entry = new DatabasePackedFile.Entry();
                    entry.Key = kvp.Key;

                    if (kvp.Value is MemoryEntry)
                    {
                        MemoryEntry memory = (MemoryEntry)kvp.Value;

                        byte[] compressed;
                        bool   success = MadScience.RefPack.Compression.Compress(memory.Data, out compressed);
                        //bool success = memory.Data.RefPackCompress(out compressed);
                        if (success == true)
                        {
                            entry.DecompressedSize = (uint)(memory.Data.Length);
                            entry.CompressedSize   = (uint)(compressed.Length) | 0x80000000;
                            entry.CompressionFlags = -1;
                            entry.Flags            = 1;
                            memory.Data            = compressed;
                        }
                        else
                        {
                            entry.DecompressedSize = memory.DecompressedSize;
                            entry.CompressedSize   = memory.CompressedSize | 0x80000000;
                            entry.CompressionFlags = 0;
                            entry.Flags            = 1;
                        }

                        // Is this replacing old data?
                        if (this.OriginalEntries.ContainsKey(kvp.Key) == true)
                        {
                            StreamEntry stream = this.OriginalEntries[kvp.Key];

                            // Let's see if the new data can fit where the old data was
                            if (memory.Data.Length <= stream.CompressedSize)
                            {
                                entry.Offset = stream.Offset;
                                this.Stream.Seek(this.BaseOffset + stream.Offset, SeekOrigin.Begin);
                                this.Stream.Write(memory.Data, 0, memory.Data.Length);
                            }
                            else
                            {
                                entry.Offset = this.EndOfDataOffset;
                                this.Stream.Seek(this.BaseOffset + this.EndOfDataOffset, SeekOrigin.Begin);
                                this.Stream.Write(memory.Data, 0, memory.Data.Length);
                                this.EndOfDataOffset += memory.Data.Length;
                            }
                        }
                        // New data
                        else
                        {
                            entry.Offset = this.EndOfDataOffset;
                            this.Stream.Seek(this.BaseOffset + this.EndOfDataOffset, SeekOrigin.Begin);
                            this.Stream.Write(memory.Data, 0, memory.Data.Length);
                            this.EndOfDataOffset += memory.Data.Length;
                        }
                    }
                    else if (kvp.Value is StreamEntry)
                    {
                        StreamEntry stream = (StreamEntry)kvp.Value;
                        entry.CompressedSize   = stream.CompressedSize | 0x80000000;
                        entry.DecompressedSize = stream.DecompressedSize;
                        entry.Offset           = stream.Offset;
                        entry.CompressionFlags = stream.CompressedFlags;
                        entry.Flags            = stream.Flags;
                    }
                    else
                    {
                        throw new InvalidOperationException();
                    }

                    dbpf.Entries.Add(entry);
                }

                this.Stream.Seek(this.BaseOffset + this.EndOfDataOffset, SeekOrigin.Begin);
                dbpf.WriteIndex(this.Stream);

                long indexSize = (this.Stream.Position - (this.BaseOffset + this.EndOfDataOffset));

                this.Stream.Seek(this.BaseOffset, SeekOrigin.Begin);
                dbpf.WriteHeader(this.Stream, this.EndOfDataOffset, indexSize);
            }
            else
            {
                Stream clean;
                string tempFileName = null;

                // Packages greater than five mb will be cleaned with a file supported stream
                if (this.Stream.Length >= (1024 * 1024) * 5)
                {
                    tempFileName = Path.GetTempFileName();
                    clean        = File.Open(tempFileName, FileMode.Create, FileAccess.ReadWrite, FileShare.Read);
                }
                else
                {
                    clean = new MemoryStream();
                }

                dbpf.WriteHeader(clean, 0, 0);
                this.EndOfDataOffset = clean.Position;

                foreach (KeyValuePair <MadScience.Wrappers.ResourceKey, Entry> kvp in this._Entries)
                {
                    DatabasePackedFile.Entry entry = new DatabasePackedFile.Entry();
                    entry.Key = kvp.Key;

                    if (kvp.Value is MemoryEntry)
                    {
                        MemoryEntry memory = (MemoryEntry)kvp.Value;

                        byte[] compressed;
                        bool   success = MadScience.RefPack.Compression.Compress(memory.Data, out compressed);
                        //bool success = memory.Data.RefPackCompress(out compressed);
                        if (success == true)
                        {
                            entry.DecompressedSize = (uint)(memory.Data.Length);
                            entry.CompressedSize   = (uint)(compressed.Length) | 0x80000000;
                            entry.CompressionFlags = -1;
                            entry.Flags            = 1;
                            entry.Offset           = this.EndOfDataOffset;
                            memory.Data            = compressed;
                        }
                        else
                        {
                            entry.DecompressedSize = memory.DecompressedSize;
                            entry.CompressedSize   = memory.CompressedSize | 0x80000000;
                            entry.CompressionFlags = 0;
                            entry.Flags            = 1;
                            entry.Offset           = this.EndOfDataOffset;
                        }

                        clean.Write(memory.Data, 0, memory.Data.Length);
                        this.EndOfDataOffset += memory.Data.Length;
                    }
                    else if (kvp.Value is StreamEntry)
                    {
                        StreamEntry stream = (StreamEntry)kvp.Value;
                        entry.CompressedSize   = stream.CompressedSize | 0x80000000;
                        entry.DecompressedSize = stream.DecompressedSize;
                        entry.CompressionFlags = stream.CompressedFlags;
                        entry.Flags            = stream.Flags;

                        entry.Offset = this.EndOfDataOffset;

                        // Copy data
                        this.Stream.Seek(this.BaseOffset + stream.Offset, SeekOrigin.Begin);
                        byte[] data = new byte[4096];
                        int    left = (int)stream.CompressedSize;
                        while (left > 0)
                        {
                            int block = Math.Min(left, (int)data.Length);
                            this.Stream.Read(data, 0, block);
                            clean.Write(data, 0, block);
                            left -= block;
                        }

                        this.EndOfDataOffset += stream.CompressedSize;
                    }
                    else
                    {
                        throw new InvalidOperationException();
                    }

                    dbpf.Entries.Add(entry);
                }

                dbpf.WriteIndex(clean);

                long indexSize = clean.Position - this.EndOfDataOffset;

                clean.Seek(0, SeekOrigin.Begin);
                dbpf.WriteHeader(clean, this.EndOfDataOffset, indexSize);

                // copy clean to real stream
                {
                    this.Stream.Seek(this.BaseOffset, SeekOrigin.Begin);
                    clean.Seek(0, SeekOrigin.Begin);

                    byte[] data = new byte[4096];
                    long   left = clean.Length;
                    while (left > 0)
                    {
                        int block = (int)Math.Min(left, data.Length);
                        clean.Read(data, 0, block);
                        this.Stream.Write(data, 0, block);
                        left -= block;
                    }
                }

                this.Stream.SetLength(this.BaseOffset + this.EndOfDataOffset + indexSize);
                clean.Close();

                if (tempFileName != null)
                {
                    try
                    {
                        File.Delete(tempFileName);
                    }
                    catch (Exception)
                    {
                    }
                }
            }

            this._Entries.Clear();
            this.OriginalEntries.Clear();

            foreach (DatabasePackedFile.Entry entry in dbpf.Entries)
            {
                this._Entries.Add(entry.Key, new StreamEntry()
                {
                    Compressed       = entry.Compressed,
                    Offset           = entry.Offset,
                    CompressedSize   = entry.CompressedSize,
                    DecompressedSize = entry.DecompressedSize,
                    CompressedFlags  = entry.CompressionFlags,
                    Flags            = entry.Flags,
                });
            }
        }