public PropertyFile(Gibbed.Spore.Package.DatabaseIndex index) { byte[] data = index.GetIndexData(true); using (Stream s = new MemoryStream(data, 0, data.Length)) { this.Read(s); } }
public void Read(Stream stream) { bool big = false; Int64 indexCount; Int64 indexSize; Int64 indexOffset; uint magic = stream.ReadU32(); if (magic != 0x46504244 && magic != 0x46424244) // DBPF & DBBF { throw new NotAPackageException(); } if (magic == 0x46424244) // DBBF { big = true; DatabaseBigPackageFileHeader header; byte[] data = new byte[Marshal.SizeOf(typeof(DatabaseBigPackageFileHeader))]; if (data.Length != (120 - 4)) { throw new Exception("DatabaseBigPackageFileHeader is wrong size (" + data.Length.ToString() + ")"); } stream.Read(data, 0, data.Length); header = (DatabaseBigPackageFileHeader)data.BytesToStructure(typeof(DatabaseBigPackageFileHeader)); if (header.Always3 != 3) { throw new Exception("the value in the DBBF header that is always 3 was not 3"); } // Nab useful stuff this.Version = new Version(header.MajorVersion, header.MinorVersion); indexCount = header.IndexCount; indexOffset = header.IndexOffset; indexSize = header.IndexSize; } else { big = false; DatabasePackedFileHeader header; byte[] data = new byte[Marshal.SizeOf(typeof(DatabasePackedFileHeader))]; if (data.Length != (96 - 4)) { throw new Exception("DatabasePackageFileHeader is wrong size (" + data.Length.ToString() + ")"); } stream.Read(data, 0, data.Length); header = (DatabasePackedFileHeader)data.BytesToStructure(typeof(DatabasePackedFileHeader)); if (header.Always3 != 3) { throw new Exception("the value in the DBPF header that is always 3 was not 3"); } // Nab useful stuff this.Version = new Version(header.MajorVersion, header.MinorVersion); indexCount = header.IndexCount; indexOffset = header.IndexOffset; indexSize = header.IndexSize; } this.Indices = new List<DatabaseIndex>(); if (indexCount > 0) { // Read index stream.Seek(indexOffset, SeekOrigin.Begin); int indexHeaderValues = stream.ReadS32(); if (indexHeaderValues < 4 || indexHeaderValues > 7) { throw new InvalidDataException("don't know how to handle this index data"); } uint indexTypeId = 0xCAFEBABE; // type id if ((indexHeaderValues & (1 << 0)) == 1 << 0) { indexTypeId = stream.ReadU32(); } uint indexGroupId = 0xCAFEBABE; // group id if ((indexHeaderValues & (1 << 1)) == 1 << 1) { indexGroupId = stream.ReadU32(); } uint indexUnknown = 0xCAFEBABE; // unknown value if ((indexHeaderValues & (1 << 2)) == 1 << 2) { indexUnknown = stream.ReadU32(); } for (int i = 0; i < indexCount; i++) { DatabaseIndex index = new DatabaseIndex(); #region index.TypeId if ((indexHeaderValues & (1 << 0)) == 1 << 0) { index.TypeId = indexTypeId; } else { index.TypeId = stream.ReadU32(); } #endregion #region index.GroupId if ((indexHeaderValues & (1 << 1)) == 1 << 1) { index.GroupId = indexGroupId; } else { index.GroupId = stream.ReadU32(); } #endregion #region index.Unknown if ((indexHeaderValues & (1 << 2)) == 1 << 2) { index.Unknown = indexUnknown; } else { index.Unknown = stream.ReadU32(); } #endregion index.InstanceId = stream.ReadU32(); if (big == true) { index.Offset = stream.ReadS64(); } else { index.Offset = stream.ReadS32(); } index.CompressedSize = stream.ReadU32(); index.DecompressedSize = stream.ReadU32(); index.CompressedFlags = stream.ReadS16(); index.Flags = stream.ReadU16(); index.CheckCompressed(); this.Indices.Add(index); } } }
public void Read(Stream stream) { bool big = false; Int64 indexCount; Int64 indexSize; Int64 indexOffset; uint magic = stream.ReadU32(); if (magic != 0x46504244 && magic != 0x46424244) // DBPF & DBBF { throw new NotAPackageException(); } if (magic == 0x46424244) // DBBF { big = true; DatabaseBigPackageFileHeader header; byte[] data = new byte[Marshal.SizeOf(typeof(DatabaseBigPackageFileHeader))]; if (data.Length != (120 - 4)) { throw new Exception("DatabaseBigPackageFileHeader is wrong size (" + data.Length.ToString() + ")"); } stream.Read(data, 0, data.Length); header = (DatabaseBigPackageFileHeader)data.BytesToStructure(typeof(DatabaseBigPackageFileHeader)); if (header.Always3 != 3) { throw new Exception("the value in the DBBF header that is always 3 was not 3"); } // Nab useful stuff this.Version = new Version(header.MajorVersion, header.MinorVersion); indexCount = header.IndexCount; indexOffset = header.IndexOffset; indexSize = header.IndexSize; } else { big = false; DatabasePackedFileHeader header; byte[] data = new byte[Marshal.SizeOf(typeof(DatabasePackedFileHeader))]; if (data.Length != (96 - 4)) { throw new Exception("DatabasePackageFileHeader is wrong size (" + data.Length.ToString() + ")"); } stream.Read(data, 0, data.Length); header = (DatabasePackedFileHeader)data.BytesToStructure(typeof(DatabasePackedFileHeader)); if (header.Always3 != 3) { throw new Exception("the value in the DBPF header that is always 3 was not 3"); } // Nab useful stuff this.Version = new Version(header.MajorVersion, header.MinorVersion); indexCount = header.IndexCount; indexOffset = header.IndexOffset; indexSize = header.IndexSize; } this.Indices = new List <DatabaseIndex>(); if (indexCount > 0) { // Read index stream.Seek(indexOffset, SeekOrigin.Begin); int indexHeaderValues = stream.ReadS32(); if (indexHeaderValues < 4 || indexHeaderValues > 7) { throw new InvalidDataException("don't know how to handle this index data"); } uint indexTypeId = 0xCAFEBABE; // type id if ((indexHeaderValues & (1 << 0)) == 1 << 0) { indexTypeId = stream.ReadU32(); } uint indexGroupId = 0xCAFEBABE; // group id if ((indexHeaderValues & (1 << 1)) == 1 << 1) { indexGroupId = stream.ReadU32(); } uint indexUnknown = 0xCAFEBABE; // unknown value if ((indexHeaderValues & (1 << 2)) == 1 << 2) { indexUnknown = stream.ReadU32(); } for (int i = 0; i < indexCount; i++) { DatabaseIndex index = new DatabaseIndex(); #region index.TypeId if ((indexHeaderValues & (1 << 0)) == 1 << 0) { index.TypeId = indexTypeId; } else { index.TypeId = stream.ReadU32(); } #endregion #region index.GroupId if ((indexHeaderValues & (1 << 1)) == 1 << 1) { index.GroupId = indexGroupId; } else { index.GroupId = stream.ReadU32(); } #endregion #region index.Unknown if ((indexHeaderValues & (1 << 2)) == 1 << 2) { index.Unknown = indexUnknown; } else { index.Unknown = stream.ReadU32(); } #endregion index.InstanceId = stream.ReadU32(); if (big == true) { index.Offset = stream.ReadS64(); } else { index.Offset = stream.ReadS32(); } index.CompressedSize = stream.ReadU32(); index.DecompressedSize = stream.ReadU32(); index.CompressedFlags = stream.ReadS16(); index.Flags = stream.ReadU16(); index.CheckCompressed(); this.Indices.Add(index); } } }
public PackagePack(Stream output, string sourceFolder, PleaseWait progress) { NameRegistry.Files.UsedHashes = new List<UInt32>(); var group_dirs = Directory.GetDirectories(sourceFolder); var file_query = from d in group_dirs where d != sourceFolder + "\\sporemaster\\" from f in Directory.GetFileSystemEntries(d) where !f.EndsWith(".search_index") // < these might appear in group directories if there are indexable files in subdirectories select f; var files = file_query.ToList(); files.Add(sourceFolder + "\\sporemaster\\names.txt"); if (progress != null) progress.beginTask(1.0, files.Count); DatabasePackedFile dbf = new DatabasePackedFile(); dbf.Version = new Version(2, 0); dbf.WriteHeader(output, 0, 0); var rw4_hash = NameRegistry.Types.toHash("rw4"); uint size, start = (uint)output.Position; foreach( var f in files ) { string relativePath = f.Substring(sourceFolder.Length + 1); bool additionalOutputFiles; byte[] autoLocale = null; do { additionalOutputFiles = false; var parts = relativePath.Split(new char[] { '\\' }); if (parts.Length != 2) continue; var group = parts[0]; parts = parts[1].Split(new char[] { '.' }, 2); var instance = parts[0]; var extension = parts[1]; var index = new DatabaseIndex(); index.GroupId = NameRegistry.Groups.toHash(group); index.InstanceId = NameRegistry.Files.toHash(instance); try { if (relativePath == "sporemaster\\names.txt") { writeNamesFile(output); } else if (autoLocale != null) { output.Write(autoLocale, 0, autoLocale.Length); } else if (extension == "prop.xml") { extension = "prop"; writePropFile(group, instance, f, output, out autoLocale); if (autoLocale.Length != 0) { additionalOutputFiles = true; relativePath = "locale~\\auto_" + group + "_" + instance + ".locale"; } } else if (NameRegistry.Types.toHash(extension)==rw4_hash && Directory.Exists(f)) { writeRW4File(f, output); } else writeBinaryFile(f, output); } catch (Exception e) { throw new Exception("Error packing file '" + relativePath + "'.", e); } size = (uint)output.Position - start; index.TypeId = NameRegistry.Types.toHash(extension); index.Compressed = false; index.Flags = 1; index.DecompressedSize = size; index.CompressedSize = size | 0x80000000; index.Offset = start; dbf.Indices.Add(index); start += size; } while (additionalOutputFiles); progress.addProgress(1.0); } dbf.WriteIndex(output); size = (uint)output.Position - start; output.Seek(0, SeekOrigin.Begin); dbf.WriteHeader(output, (int)start, (int)size); output.Close(); if (progress != null) progress.endTask(); }
private byte[] unpack(Stream archive, DatabaseIndex index) { if (index.Compressed) { archive.Seek(index.Offset, SeekOrigin.Begin); return archive.RefPackDecompress(index.CompressedSize, index.DecompressedSize); } else { archive.Seek(index.Offset, SeekOrigin.Begin); byte[] d = new byte[index.DecompressedSize]; archive.Read(d, 0, d.Length); return d; } }