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; } }
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(); }
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, }); } }
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..."); } } }
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); } }
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(); } }