public Database(Stream stream, bool readExisting)
        {
            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<ResourceKey, Entry>();
            this.Entries = new ReadOnlyDictionary<ResourceKey, Entry>(this._Entries);

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

            if (readExisting == true)
            {
                DatabasePackedFile dbpf = new DatabasePackedFile();
                dbpf.Read(stream);

                this.EndOfDataOffset = dbpf.IndexOffset;

                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,
                        });
                }
            }
            else
            {
                this.EndOfDataOffset = 0;
            }
        }
Exemplo n.º 2
0
        private void button3_Click(object sender, EventArgs e)
        {
            progressBar1.Minimum = 0;
            progressBar1.Value = 0;

            string openPath = "";
            if (comboBox1.Text.StartsWith("\\"))
            {
                openPath = MadScience.Helpers.findSims3Root() + comboBox1.Text;
            }
            else
            {
                openPath = comboBox1.Text;
            }

            if (openPath == "") return;

            Stream input = File.OpenRead(openPath);

            Database db = new Database(input, true);

            input.Seek(0, SeekOrigin.Begin);

            DatabasePackedFile dbpf = new DatabasePackedFile();
            try
            {
                dbpf.Read(input);
            }
            catch (NotAPackageException)
            {
                MessageBox.Show("bad file: {0}", comboBox1.Text);
                input.Close();
                return;
            }

            this.currentFile = new FileInfo(openPath);

            lookupTypes();
            indexEntries.Clear();
            listView1.Items.Clear();

            txtPkgIndexType.Text = dbpf.IndexType.ToString();
            txtPkgNumChunks.Text = dbpf.Entries.Count.ToString();

            uint searchTypeID = 0;
            if (comboBox2.Text != "") { searchTypeID = Gibbed.Helpers.StringHelpers.ParseHex32(comboBox2.Text); }
            ulong instanceID = 0;
            bool searchInstance = false;
            if (textBox8.Text != "")
            {
                instanceID = Gibbed.Helpers.StringHelpers.ParseHex64(textBox8.Text);
                searchInstance = true;
            }

            string tempChunk = "";
            int count = 0;

            progressBar1.Maximum = dbpf.Entries.Count;

            for (int i = 0; i < dbpf.Entries.Count; i++)
            {
                ListViewItem item = new ListViewItem();
                DatabasePackedFile.Entry entry = dbpf.Entries[i];
                progressBar1.Value++;

                bool searchChunk = false;

                if (entry.Key.TypeId == searchTypeID)
                {
                    if (searchInstance == true)
                    {
                        if (entry.Key.InstanceId == instanceID)
                        {
                            searchChunk = true;
                        }
                    }
                    else
                    {
                        searchChunk = true;
                    }
                }
                else
                {
                    if (searchInstance == true)
                    {
                        if (entry.Key.InstanceId == instanceID)
                        {
                            searchChunk = true;
                        }
                    }
                }
                //if (searchTypeID == 0) { searchChunk = true; }

                if (searchChunk)
                {

                    tempChunk = Encoding.UTF8.GetString(db.GetResource(entry.Key));
                    bool addChunk = false;

                    // If everything is blank we just list... everything
                    if (textBox3.Text == "" && textBox6.Text == "" && textBox7.Text == "")
                    {
                        addChunk = true;
                    }
                    else
                    {

                        if (tempChunk.Contains(textBox3.Text))
                        {
                            if (textBox6.Text != "")
                            {
                                if (tempChunk.Contains(textBox6.Text))
                                {
                                    if (textBox7.Text != "")
                                    {
                                        if (tempChunk.Contains(textBox7.Text))
                                        {
                                            addChunk = true;
                                        }
                                    }
                                    else
                                    {
                                        addChunk = true;
                                    }
                                }
                            }
                            else
                            {
                                addChunk = true;
                            }

                        }

                    }

                    if (addChunk == true)
                    {
                        item.Text = this.lookupList.lookup(entry.Key.TypeId).shortName;
                        item.SubItems.Add(entry.Key.TypeId.ToString("X8"));
                        item.SubItems.Add(entry.Key.GroupId.ToString("X8"));
                        item.SubItems.Add(entry.Key.InstanceId.ToString("X16"));
                        item.SubItems.Add(entry.DecompressedSize.ToString());
                        item.SubItems.Add(count.ToString());
                        listView1.Items.Add(item);
                        indexEntries.Add(entry);
                        count++;
                    }
                }
            }

            input.Close();
        }
Exemplo n.º 3
0
        private void loadFile(string filename)
        {
            toolStripStatusLabel1.Text = filename;
            Stream input = File.OpenRead(filename);

            DatabasePackedFile dbpf = new DatabasePackedFile();
            try
            {
                dbpf.Read(input);
            }
            catch (NotAPackageException)
            {
                MessageBox.Show("bad file: {0}", filename);
                input.Close();
                return;
            }

            this.currentFile = new FileInfo(filename);

            input.Seek(0, SeekOrigin.Begin);

            lookupTypes();
            indexEntries.Clear();
            listView1.Items.Clear();

            txtPkgIndexType.Text = dbpf.IndexType.ToString();
            txtPkgNumChunks.Text = dbpf.Entries.Count.ToString();

            for (int i = 0; i < dbpf.Entries.Count; i++)
            {
                ListViewItem item = new ListViewItem();
                DatabasePackedFile.Entry entry = dbpf.Entries[i];
                item.Text = this.lookupList.lookup(entry.Key.TypeId).shortName;
                item.SubItems.Add(entry.Key.TypeId.ToString("X8"));
                item.SubItems.Add(entry.Key.GroupId.ToString("X8"));
                item.SubItems.Add(entry.Key.InstanceId.ToString("X16"));
                item.SubItems.Add(entry.DecompressedSize.ToString());
                item.SubItems.Add(i.ToString());
                listView1.Items.Add(item);
                indexEntries.Add(entry);

            }

            input.Close();
        }
        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<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;

                        entry.DecompressedSize = memory.DecompressedSize;
                        entry.CompressedSize = memory.CompressedSize | 0x80000000;
                        entry.Flags = 1;
                        entry.Compressed = false;

                        // 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.CompressedSize <= stream.CompressedSize)
                            {
                                entry.Offset = stream.Offset;
                                this.Stream.Seek(this.BaseOffset + stream.Offset, SeekOrigin.Begin);
                                this.Stream.Write(memory.Data, 0, (int)memory.CompressedSize);
                            }
                            else
                            {
                                entry.Offset = this.EndOfDataOffset;
                                this.Stream.Seek(this.BaseOffset + this.EndOfDataOffset, SeekOrigin.Begin);
                                this.Stream.Write(memory.Data, 0, (int)memory.CompressedSize);
                                this.EndOfDataOffset += memory.CompressedSize;
                            }
                        }
                        // New data
                        else
                        {
                            entry.Offset = this.EndOfDataOffset;
                            this.Stream.Seek(this.BaseOffset + this.EndOfDataOffset, SeekOrigin.Begin);
                            this.Stream.Write(memory.Data, 0, (int)memory.CompressedSize);
                            this.EndOfDataOffset += memory.CompressedSize;
                        }
                    }
                    else if (kvp.Value is StreamEntry)
                    {
                        StreamEntry stream = (StreamEntry)kvp.Value;
                        entry.Compressed = stream.Compressed;
                        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<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;

                        entry.DecompressedSize = memory.DecompressedSize;
                        entry.CompressedSize = memory.CompressedSize | 0x80000000;
                        entry.Flags = 1;
                        entry.Compressed = false;
                        entry.Offset = this.EndOfDataOffset;

                        clean.Write(memory.Data, 0, (int)memory.CompressedSize);
                        this.EndOfDataOffset += memory.CompressedSize;
                    }
                    else if (kvp.Value is StreamEntry)
                    {
                        StreamEntry stream = (StreamEntry)kvp.Value;
                        entry.Compressed = stream.Compressed;
                        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);

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

            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,
                });
            }
        }
Exemplo n.º 5
0
        private void mnuCopy_Click(object sender, RoutedEventArgs e)
        {
            //check if current index is a valid menu item
            if (this.DataContext.GetType() == typeof(DatabaseIndexData))
            {
                DatabaseIndexData menuItemIndex = (DatabaseIndexData)this.DataContext;
                menuItemIndex.Index.IsModified = true;
                if (menuItemIndex.Index.InstanceType == (uint)PropertyFileTypeIds.Menu2)
                {
                    SaveFileDialog dialog = new SaveFileDialog();
                    if (dialog.ShowDialog().GetValueOrDefault(false))
                    {
                        List <DatabaseIndex> indices = new List <DatabaseIndex>();

                        menuItemIndex.Index.ModifiedInstanceId = TGIRandomGenerator.GetNext();
                        indices.Add(menuItemIndex.Index);

                        PropertyFile menuFile = new PropertyFile(menuItemIndex.Index);

                        #region Extract Icon

                        if (menuFile.Values.ContainsKey(PropertyConstants.menuIcon))
                        {
                            KeyProperty   iconProperty = (KeyProperty)menuFile.Values[PropertyConstants.menuIcon];
                            DatabaseIndex iconIndex    = DatabaseIndex.FindIndex(iconProperty.TypeId, null, null, iconProperty.InstanceId, true, false);

                            iconIndex.ModifiedInstanceId = TGIRandomGenerator.GetNext();
                            indices.Add(iconIndex);

                            iconProperty.InstanceId          = iconIndex.ModifiedInstanceId.Value;
                            menuItemIndex.Index.ModifiedData = new ModifiedPropertyFile()
                            {
                                PropertyFile = menuFile
                            };

                            menuFile.Values[PropertyConstants.menuIcon] = iconProperty;
                        }

                        #endregion

                        #region Extract Marquee Image

                        if (menuFile.Values.ContainsKey(PropertyConstants.menuMarqueeImage))
                        {
                            KeyProperty   marqueeProperty = (KeyProperty)menuFile.Values[PropertyConstants.menuMarqueeImage];
                            DatabaseIndex marqueeIndex    = DatabaseIndex.FindIndex(marqueeProperty.TypeId, null, null, marqueeProperty.InstanceId, true, false);

                            marqueeIndex.ModifiedInstanceId = TGIRandomGenerator.GetNext();
                            indices.Add(marqueeIndex);

                            marqueeProperty.InstanceId       = marqueeIndex.ModifiedInstanceId.Value;
                            menuItemIndex.Index.ModifiedData = new ModifiedPropertyFile()
                            {
                                PropertyFile = menuFile
                            };

                            menuFile.Values[PropertyConstants.menuMarqueeImage] = marqueeProperty;
                        }

                        #endregion

                        #region Extract Ecogame Unit

                        if (menuFile.Values.ContainsKey(PropertyConstants.menuUnit))
                        {
                            KeyProperty   unitProperty = (KeyProperty)menuFile.Values[PropertyConstants.menuUnit];
                            DatabaseIndex unitIndex    = DatabaseIndex.FindIndex((uint)TypeIds.PropertyFile, null, 0xe0, unitProperty.InstanceId, false, true);

                            PropertyFile unitFile = new PropertyFile(unitIndex);
                            unitFile.FlattenParentInheritance();

                            #region Extract Unit Display

                            if (unitFile.Values.ContainsKey(PropertyConstants.ecoGameUnitDisplayModel))
                            {
                                KeyProperty   unitDisplayProperty = (KeyProperty)unitFile.Values[PropertyConstants.ecoGameUnitDisplayModel];
                                DatabaseIndex unitDisplayIndex    = DatabaseIndex.FindIndex((uint)TypeIds.PropertyFile, null, 0xe1, unitDisplayProperty.InstanceId, false, true);

                                unitDisplayIndex.ModifiedInstanceId = TGIRandomGenerator.GetNext();
                                unitDisplayProperty.InstanceId      = unitDisplayIndex.ModifiedInstanceId.Value;

                                unitFile.Values[PropertyConstants.ecoGameUnitDisplayModel] = unitDisplayProperty;

                                PropertyFile unitDisplayFile = new PropertyFile(unitDisplayIndex);

                                #region Extract LODs

                                if (unitDisplayFile.Values.ContainsKey(PropertyConstants.UnitLOD1))
                                {
                                    KeyProperty   LOD1Property = (KeyProperty)unitDisplayFile.Values[PropertyConstants.UnitLOD1];
                                    DatabaseIndex LOD1Index    = DatabaseIndex.FindIndex(LOD1Property.TypeId, null, null, LOD1Property.InstanceId, true, false);
                                    LOD1Index.ModifiedInstanceId = TGIRandomGenerator.GetNext();
                                    indices.Add(LOD1Index);
                                    LOD1Property.InstanceId = LOD1Index.ModifiedInstanceId.Value;
                                    unitDisplayFile.Values[PropertyConstants.UnitLOD1] = LOD1Property;
                                }

                                if (unitDisplayFile.Values.ContainsKey(PropertyConstants.UnitLOD2))
                                {
                                    KeyProperty   LOD2Property = (KeyProperty)unitDisplayFile.Values[PropertyConstants.UnitLOD2];
                                    DatabaseIndex LOD2Index    = DatabaseIndex.FindIndex(LOD2Property.TypeId, null, null, LOD2Property.InstanceId, true, false);
                                    LOD2Index.ModifiedInstanceId = TGIRandomGenerator.GetNext();
                                    indices.Add(LOD2Index);
                                    LOD2Property.InstanceId = LOD2Index.ModifiedInstanceId.Value;
                                    unitDisplayFile.Values[PropertyConstants.UnitLOD2] = LOD2Property;
                                }

                                if (unitDisplayFile.Values.ContainsKey(PropertyConstants.UnitLOD3))
                                {
                                    KeyProperty   LOD3Property = (KeyProperty)unitDisplayFile.Values[PropertyConstants.UnitLOD3];
                                    DatabaseIndex LOD3Index    = DatabaseIndex.FindIndex(LOD3Property.TypeId, null, null, LOD3Property.InstanceId, true, false);
                                    LOD3Index.ModifiedInstanceId = TGIRandomGenerator.GetNext();
                                    indices.Add(LOD3Index);
                                    LOD3Property.InstanceId = LOD3Index.ModifiedInstanceId.Value;
                                    unitDisplayFile.Values[PropertyConstants.UnitLOD3] = LOD3Property;
                                }

                                if (unitDisplayFile.Values.ContainsKey(PropertyConstants.UnitLOD4))
                                {
                                    KeyProperty   LOD4Property = (KeyProperty)unitDisplayFile.Values[PropertyConstants.UnitLOD4];
                                    DatabaseIndex LOD4Index    = DatabaseIndex.FindIndex(LOD4Property.TypeId, null, null, LOD4Property.InstanceId, true, false);
                                    LOD4Index.ModifiedInstanceId = TGIRandomGenerator.GetNext();
                                    indices.Add(LOD4Index);
                                    LOD4Property.InstanceId = LOD4Index.ModifiedInstanceId.Value;
                                    unitDisplayFile.Values[PropertyConstants.UnitLOD4] = LOD4Property;
                                }


                                #endregion

                                unitDisplayIndex.ModifiedData = new ModifiedPropertyFile()
                                {
                                    PropertyFile = unitDisplayFile
                                };
                                unitDisplayIndex.IsModified = true;

                                indices.Add(unitDisplayIndex);
                            }

                            #endregion

                            unitIndex.ModifiedInstanceId = TGIRandomGenerator.GetNext();
                            unitIndex.ModifiedData       = new ModifiedPropertyFile()
                            {
                                PropertyFile = unitFile
                            };
                            unitIndex.IsModified = true;

                            indices.Add(unitIndex);

                            unitProperty.InstanceId          = unitIndex.ModifiedInstanceId.Value;
                            menuItemIndex.Index.ModifiedData = new ModifiedPropertyFile()
                            {
                                PropertyFile = menuFile
                            };

                            menuFile.Values[PropertyConstants.menuUnit] = unitProperty;
                        }

                        #endregion
                        DatabasePackedFile.SaveAs(dialog.FileName, indices);
                    }
                }
                else
                {
                    MessageBox.Show("This only works for menu items...");
                }
            }
        }
Exemplo n.º 6
0
        public Dictionary <uint, Property> GetParentProperties(Dictionary <uint, Property> returnProperties, Dictionary <uint, Property> parentProperties)
        {
            if (returnProperties == null)
            {
                returnProperties = new Dictionary <uint, Property>();
            }

            //add keys that didn't exist yet
            foreach (uint index in parentProperties.Keys)
            {
                if (!returnProperties.ContainsKey(index) && index != 0x00B2CCCB)
                {
                    //This property specifies behavior bundles to exclude - instead of adding this property, remove all the bundles from the appropriate arrays

                    returnProperties.Add(index, parentProperties[index]);
                }
            }

            if (parentProperties.ContainsKey(0x00B2CCCB))
            {
                Property    parentProperty      = parentProperties[0x00B2CCCB];
                KeyProperty parentPropertyValue = parentProperty as KeyProperty;

                //search the currently opened package for this type/instance group id. if it doesn't exist, find it in the default simcity packages

                DatabaseIndex parentIndex = null;
                if (DatabaseManager.Instance.Indices.Exists(i => i.InstanceId == parentPropertyValue.InstanceId && i.TypeId == parentPropertyValue.TypeId && i.GroupContainer == parentPropertyValue.GroupContainer))
                {
                    parentIndex = DatabaseManager.Instance.Indices.First(i => i.InstanceId == parentPropertyValue.InstanceId && i.TypeId == parentPropertyValue.TypeId && i.GroupContainer == parentPropertyValue.GroupContainer);
                }
                else
                {
                    string        folderEcoGamePath = Properties.Settings.Default.SimCityFolder + @"\SimCityUserData\EcoGame\";
                    DirectoryInfo folderEcoGame     = new DirectoryInfo(folderEcoGamePath);

                    //search the simcity data packages for this type/instance group id. if it doesn't exist, find it in the default simcity packages
                    FileInfo[]         scriptsFiles   = folderEcoGame.GetFiles("SimCity-Scripts_*.package", SearchOption.TopDirectoryOnly);
                    FileInfo           scriptsFile    = scriptsFiles.First(sf => sf.LastWriteTime == scriptsFiles.Max(sf2 => sf2.LastWriteTime));
                    DatabasePackedFile ScriptsPackage = DatabasePackedFile.LoadFromFile(scriptsFile.FullName);

                    parentIndex = ScriptsPackage.Indices.FirstOrDefault(i => i.InstanceId == parentPropertyValue.InstanceId && i.TypeId == parentPropertyValue.TypeId && i.GroupContainer == parentPropertyValue.GroupContainer);
                }

                // if(parentIndex != null)
                // {
                byte[] data = parentIndex.GetIndexData(true);

                using (Stream s = new MemoryStream(data, 0, data.Length))
                {
                    PropertyFile propertyFile = new PropertyFile();
                    propertyFile.Read(s);

                    return(GetParentProperties(returnProperties, propertyFile.Values));
                }



                throw new Exception("Inheritance not found!");
                return(returnProperties);
            }
            else
            {
                return(returnProperties);
            }
        }
Exemplo n.º 7
0
        private void OnOpen(object sender, EventArgs e)
        {
            if (this.openDialog.ShowDialog() != DialogResult.OK)
            {
                return;
            }

            if (this.openDialog.InitialDirectory != null)
            {
                this.openDialog.InitialDirectory = null;
            }

            Stream input = this.openDialog.OpenFile();

            DatabasePackedFile dbpf = new DatabasePackedFile();

            dbpf.Read(input);

            this.AddMapNames(dbpf, input);

            this.DatabaseFiles = dbpf.Entries.ToArray();

            Dictionary <string, TreeNode> categoryNodes    = new Dictionary <string, TreeNode>();
            Dictionary <uint, TreeNode>   unknownTypeNodes = new Dictionary <uint, TreeNode>();

            this.typeList.Nodes.Clear();
            this.typeList.BeginUpdate();

            TreeNode knownNode   = new TreeNode("Known");
            TreeNode unknownNode = new TreeNode("Unknown");

            for (int i = 0; i < this.DatabaseFiles.Length; i++)
            {
                DatabasePackedFile.Entry index = this.DatabaseFiles[i];

                TreeNode typeNode = null;

                if (Lookup.Types.ContainsKey(index.Key.TypeId) == true)
                {
                    TypeLookup type = Lookup.Types[index.Key.TypeId];

                    TreeNode categoryNode;

                    if (categoryNodes.ContainsKey(type.Category) == false)
                    {
                        categoryNode      = new TreeNode();
                        categoryNode.Text = type.Category;
                        categoryNode.Tag  = new Dictionary <uint, TreeNode>();
                        knownNode.Nodes.Add(categoryNode);
                        categoryNodes[type.Category] = categoryNode;
                    }
                    else
                    {
                        categoryNode = categoryNodes[type.Category];
                    }

                    Dictionary <uint, TreeNode> typeNodes = categoryNode.Tag as Dictionary <uint, TreeNode>;

                    if (typeNodes.ContainsKey(index.Key.TypeId) == false)
                    {
                        typeNode          = new TreeNode();
                        typeNode.Text     = type.Description == null ? type.Directory : type.Description;
                        typeNode.Tag      = new List <DatabasePackedFile.Entry>();
                        typeNode.NodeFont = this.MonospaceFont;
                        categoryNode.Nodes.Add(typeNode);
                        typeNodes[index.Key.TypeId] = typeNode;
                    }
                    else
                    {
                        typeNode = typeNodes[index.Key.TypeId];
                    }
                }
                else
                {
                    if (unknownTypeNodes.ContainsKey(index.Key.TypeId) == false)
                    {
                        typeNode          = new TreeNode();
                        typeNode.Text     = "#" + index.Key.TypeId.ToString("X8");
                        typeNode.Tag      = new List <DatabasePackedFile.Entry>();
                        typeNode.NodeFont = this.MonospaceFont;
                        unknownNode.Nodes.Add(typeNode);
                        unknownTypeNodes[index.Key.TypeId] = typeNode;
                    }
                    else
                    {
                        typeNode = unknownTypeNodes[index.Key.TypeId];
                    }
                }

                List <DatabasePackedFile.Entry> files = typeNode.Tag as List <DatabasePackedFile.Entry>;
                files.Add(index);
            }

            if (knownNode.Nodes.Count > 0)
            {
                this.typeList.Nodes.Add(knownNode);
            }

            if (unknownNode.Nodes.Count > 0)
            {
                this.typeList.Nodes.Add(unknownNode);
            }

            this.typeList.Sort();
            this.typeList.EndUpdate();

            if (knownNode.Nodes.Count > 0)
            {
                knownNode.Expand();
            }
            else if (unknownNode.Nodes.Count > 0)
            {
                unknownNode.Expand();
            }
        }