public void WriteHeader(Stream output, long indexOffset, long indexSize) { if (this.Big == true) { MadScience.StreamHelpers.WriteStringASCII(output, "DBBF"); BigHeader header = new BigHeader(); header.MajorVersion = this.Version.Major; header.MinorVersion = this.Version.Minor; header.IndexVersion = 3; header.IndexCount = this.Entries.Count; header.IndexOffset = indexOffset; header.IndexSize = indexSize; MadScience.StreamHelpers.WriteStructure <BigHeader>(output, header); } else { MadScience.StreamHelpers.WriteStringASCII(output, "DBPF"); Header header = new Header(); header.MajorVersion = this.Version.Major; header.MinorVersion = this.Version.Minor; header.IndexVersion = 3; header.IndexCount = this.Entries.Count; header.IndexOffset = (int)indexOffset; header.IndexSize = (int)indexSize; MadScience.StreamHelpers.WriteStructure <Header>(output, header); } }
public void WriteHeader(Stream output, long indexOffset, uint indexSize) { if (this.IsBig == false) { var header = new Header { Magic = Header.Signature, MajorVersion = this._Version.Major, MinorVersion = this._Version.Minor, IndexType = 3, IndexCount = this._Entries.Count, IndexOffset = (int)indexOffset, IndexSize = indexSize }; output.WriteStructure(header); } else { var header = new BigHeader { Magic = BigHeader.Signature, MajorVersion = this._Version.Major, MinorVersion = this._Version.Minor, IndexType = 3, IndexCount = this._Entries.Count, IndexOffset = indexOffset, IndexSize = indexSize }; output.WriteStructure(header); } }
public void WriteHeader(Stream output, long indexOffset, long indexSize) { if (this.Big == true) { output.WriteString("DBBF", Encoding.ASCII); BigHeader header = new BigHeader(); header.MajorVersion = this.Version.Major; header.MinorVersion = this.Version.Minor; header.IndexVersion = 3; header.IndexCount = this.Entries.Count; header.IndexOffset = indexOffset; header.IndexSize = indexSize; output.WriteStructure <BigHeader>(header); } else { output.WriteString("DBPF", Encoding.ASCII); Header header = new Header(); header.MajorVersion = this.Version.Major; header.MinorVersion = this.Version.Minor; header.IndexVersion = 3; header.IndexCount = this.Entries.Count; header.IndexOffset = (int)indexOffset; header.IndexSize = (int)indexSize; output.WriteStructure <Header>(header); } }
public void Read(Stream input, bool throwError) { Int64 indexCount; Int64 indexSize; Int64 indexOffset; bool hasError = false; this.magic = MadScience.StreamHelpers.ReadStringASCII(input, 4); if (this.magic != "DBPF" && this.magic != "DBBF") // DBPF & DBBF { if (this.magic == "DBPP") { if (throwError) { throw new MadScience.Exceptions.UnsupportedPackageVersionException("protected store content"); } else { // We don't do anything with Store files, so just return this.packageType = Detective.PackageTypes.sims3Store; return; } } else { if (magic.EndsWith("PNG")) { this.packageType = Detective.PackageTypes.pngThumbnail; return; } if (throwError) { throw new MadScience.Exceptions.NotAPackageException("not a valid package file"); } else { hasError = true; } } } // If we have an error already then it's not a DBPF file, so no point in going on if (hasError && !throwError) { this.packageType = Detective.PackageTypes.corruptNotADBPF; return; } this.Big = this.magic == "DBBF"; if (this.Big == true) { BigHeader header = MadScience.StreamHelpers.ReadStructure <BigHeader>(input); this.bigHeader = header; // Nab useful stuff this.Version = new Version(header.MajorVersion, header.MinorVersion); indexCount = header.IndexCount; indexOffset = header.IndexOffset; indexSize = header.IndexSize; if (header.MajorVersion == 2 && header.MinorVersion == 0) { if (header.IndexVersion < 2) { if (throwError) { throw new MadScience.Exceptions.UnsupportedPackageVersionException("index version was not 2 or 3"); } else { hasError = true; } } } else { if (throwError) { throw new MadScience.Exceptions.UnsupportedPackageVersionException("package version was not 2.0 - possibly TS2 content?"); } else { hasError = true; } } } else { Header header = MadScience.StreamHelpers.ReadStructure <Header>(input); this.smallHeader = header; // Nab useful stuff this.Version = new Version(header.MajorVersion, header.MinorVersion); indexCount = header.IndexCount; indexOffset = header.IndexOffset; indexSize = header.IndexSize; if (header.MajorVersion == 2 && header.MinorVersion == 0) { if (header.IndexVersion < 2) { if (throwError) { throw new MadScience.Exceptions.DatabasePackedFileException("index version was not 2 or 3"); } else { hasError = true; } } } else { if (throwError) { throw new MadScience.Exceptions.DatabasePackedFileException("package version was not 2.0 - possibly TS2 content?"); } else { this.packageType = Detective.PackageTypes.sims2Package; hasError = true; } } } this.IndexOffset = indexOffset; // Check for invalid indexOffsets if (indexOffset > input.Length) { // This is a corrupted file. We can do nothing. this.packageType = Detective.PackageTypes.corruptBadDownload; return; } this.Entries.Clear(); // Do some stuff for TS2 if (this.Version.Major == 1) { if (this.IndexOffset == 0) { this.IndexOffset = this.smallHeader.IndexOffsetTS2; } } if (this.Version.Major == 538976258) { // This is seen in some of Chaavik's packages - spaces in the header. // We can do nothing with these, so just give up this.packageType = Detective.PackageTypes.corruptChaavik; return; } // If we get this far, DONT have throw errors on, and have an error, then just plain exit. //if (!throwError && hasError) return; if (indexCount > 0) { // Read index int presentPackageValues = 0; bool hasPackageTypeId = false; bool hasPackageGroupId = false; bool hasPackageHiInstanceId = false; uint packageTypeId = 0; uint packageGroupId = 0; uint packageHiInstanceId = 0; input.Seek(this.IndexOffset, SeekOrigin.Begin); // Do some stuff for TS2 if (this.Version.Major == 2) { presentPackageValues = MadScience.StreamHelpers.ReadValueS32(input); this.IndexType = presentPackageValues; if ((presentPackageValues & ~7) != 0) { this.packageType = Detective.PackageTypes.corruptIndex; // Check backwards 3 bytes (some files from peggy have invalid input.Seek(this.IndexOffset - 3, SeekOrigin.Begin); presentPackageValues = MadScience.StreamHelpers.ReadValueS32(input); this.IndexType = presentPackageValues; if ((presentPackageValues & ~7) != 0) { if (throwError) { throw new InvalidDataException("don't know how to handle this index data"); } else { this.packageType = Detective.PackageTypes.corruptPeggy; return; } } } hasPackageTypeId = (presentPackageValues & (1 << 0)) == 1 << 0; hasPackageGroupId = (presentPackageValues & (1 << 1)) == 1 << 1; hasPackageHiInstanceId = (presentPackageValues & (1 << 2)) == 1 << 2; packageTypeId = hasPackageTypeId ? MadScience.StreamHelpers.ReadValueU32(input) : 0xFFFFFFFF; packageGroupId = hasPackageGroupId ? MadScience.StreamHelpers.ReadValueU32(input) : 0xFFFFFFFF; packageHiInstanceId = hasPackageHiInstanceId ? MadScience.StreamHelpers.ReadValueU32(input) : 0xFFFFFFFF; } for (int i = 0; i < indexCount; i++) { Entry entry = new Entry(); entry.Key = new ResourceKey(); if (hasPackageTypeId) { entry.Key.typeId = packageTypeId; } else { entry.Key.typeId = MadScience.StreamHelpers.ReadValueU32(input); } if (hasPackageGroupId) { entry.Key.groupId = packageGroupId; } else { entry.Key.groupId = MadScience.StreamHelpers.ReadValueU32(input); } entry.Key.instanceId = 0; entry.Key.instanceId |= (hasPackageHiInstanceId ? packageHiInstanceId : MadScience.StreamHelpers.ReadValueU32(input)); entry.Key.instanceId <<= 32; entry.Key.instanceId |= MadScience.StreamHelpers.ReadValueU32(input); entry.Offset = (this.Big == true) ? MadScience.StreamHelpers.ReadValueS64(input) : MadScience.StreamHelpers.ReadValueS32(input); entry.CompressedSize = MadScience.StreamHelpers.ReadValueU32(input); // Detect game type /* * if (entry.Key.groupId != 0xDEADBEEF) * { * switch (this.gameNumber) * { * case MadScience.Helpers.GameNumber.ambitions: * break; * case MadScience.Helpers.GameNumber.highEndLoftStuff: * if ((entry.Key.groupId & (uint)MadScience.Helpers.ContentCategory.kEP2Content) == (uint)MadScience.Helpers.ContentCategory.kEP2Content) * { * this.gameNumber = MadScience.Helpers.GameNumber.ambitions; * } * break; * case MadScience.Helpers.GameNumber.worldAdventures: * if ((entry.Key.groupId & (uint)MadScience.Helpers.ContentCategory.kSP1Content) == (uint)MadScience.Helpers.ContentCategory.kSP1Content) * { * this.gameNumber = MadScience.Helpers.GameNumber.highEndLoftStuff; * } * if ((entry.Key.groupId & (uint)MadScience.Helpers.ContentCategory.kEP2Content) == (uint)MadScience.Helpers.ContentCategory.kEP2Content) * { * this.gameNumber = MadScience.Helpers.GameNumber.ambitions; * } * break; * case MadScience.Helpers.GameNumber.baseGame: * if ((entry.Key.groupId & (uint)MadScience.Helpers.ContentCategory.kEP1Content) == (uint)MadScience.Helpers.ContentCategory.kEP1Content) * { * this.gameNumber = MadScience.Helpers.GameNumber.worldAdventures; * } * if ((entry.Key.groupId & (uint)MadScience.Helpers.ContentCategory.kSP1Content) == (uint)MadScience.Helpers.ContentCategory.kSP1Content) * { * this.gameNumber = MadScience.Helpers.GameNumber.highEndLoftStuff; * } * if ((entry.Key.groupId & (uint)MadScience.Helpers.ContentCategory.kEP2Content) == (uint)MadScience.Helpers.ContentCategory.kEP2Content) * { * this.gameNumber = MadScience.Helpers.GameNumber.ambitions; * } * break; * } * } */ if (this.Version.Major == 2) { entry.DecompressedSize = MadScience.StreamHelpers.ReadValueU32(input); // compressed bit if ((entry.CompressedSize & 0x80000000) == 0x80000000) { entry.CompressedSize &= ~0x80000000; entry.CompressionFlags = MadScience.StreamHelpers.ReadValueS16(input); entry.Flags = MadScience.StreamHelpers.ReadValueU16(input); } else { if (entry.CompressedSize != entry.DecompressedSize) { entry.CompressionFlags = -1; } else { entry.CompressionFlags = 0; } entry.Flags = 0; if (throwError) { throw new MadScience.Exceptions.DatabasePackedFileException("strange index data"); } else { this.packageType = Detective.PackageTypes.corruptIndex; return; } } if (entry.CompressionFlags != 0 && entry.CompressionFlags != -1) { throw new MadScience.Exceptions.DatabasePackedFileException("bad compression flags"); } } if (entry.Offset + entry.CompressedSize > this.EndOfDataOffset) { this.EndOfDataOffset = entry.Offset + entry.CompressedSize; } this.Entries.Add(entry); } } }
public void WriteHeader(Stream output, long indexOffset, long indexSize) { if (this.Big == true) { MadScience.StreamHelpers.WriteStringASCII(output, "DBBF"); BigHeader header = new BigHeader(); header.MajorVersion = this.Version.Major; header.MinorVersion = this.Version.Minor; header.IndexVersion = 3; header.IndexCount = this.Entries.Count; header.IndexOffset = indexOffset; header.IndexSize = indexSize; MadScience.StreamHelpers.WriteStructure<BigHeader>(output, header); } else { MadScience.StreamHelpers.WriteStringASCII(output, "DBPF"); Header header = new Header(); header.MajorVersion = this.Version.Major; header.MinorVersion = this.Version.Minor; header.IndexVersion = 3; header.IndexCount = this.Entries.Count; header.IndexOffset = (int)indexOffset; header.IndexSize = (int)indexSize; MadScience.StreamHelpers.WriteStructure<Header>(output, header); } }
public void Read(Stream input, bool throwError) { Int64 indexCount; Int64 indexSize; Int64 indexOffset; bool hasError = false; this.magic = MadScience.StreamHelpers.ReadStringASCII(input, 4); if (this.magic != "DBPF" && this.magic != "DBBF") // DBPF & DBBF { if (this.magic == "DBPP") { if (throwError) { throw new MadScience.Exceptions.UnsupportedPackageVersionException("protected store content"); } else { // We don't do anything with Store files, so just return this.packageType = Detective.PackageTypes.sims3Store; return; } } else { if (magic.EndsWith("PNG")) { this.packageType = Detective.PackageTypes.pngThumbnail; return; } if (throwError) { throw new MadScience.Exceptions.NotAPackageException("not a valid package file"); } else { hasError = true; } } } // If we have an error already then it's not a DBPF file, so no point in going on if (hasError && !throwError) { this.packageType = Detective.PackageTypes.corruptNotADBPF; return; } this.Big = this.magic == "DBBF"; if (this.Big == true) { BigHeader header = MadScience.StreamHelpers.ReadStructure<BigHeader>(input); this.bigHeader = header; // Nab useful stuff this.Version = new Version(header.MajorVersion, header.MinorVersion); indexCount = header.IndexCount; indexOffset = header.IndexOffset; indexSize = header.IndexSize; if (header.MajorVersion == 2 && header.MinorVersion == 0) { if (header.IndexVersion < 2) { if (throwError) { throw new MadScience.Exceptions.UnsupportedPackageVersionException("index version was not 2 or 3"); } else { hasError = true; } } } else { if (throwError) { throw new MadScience.Exceptions.UnsupportedPackageVersionException("package version was not 2.0 - possibly TS2 content?"); } else { hasError = true; } } } else { Header header = MadScience.StreamHelpers.ReadStructure<Header>(input); this.smallHeader = header; // Nab useful stuff this.Version = new Version(header.MajorVersion, header.MinorVersion); indexCount = header.IndexCount; indexOffset = header.IndexOffset; indexSize = header.IndexSize; if (header.MajorVersion == 2 && header.MinorVersion == 0) { if (header.IndexVersion < 2) { if (throwError) { throw new MadScience.Exceptions.DatabasePackedFileException("index version was not 2 or 3"); } else { hasError = true; } } } else { if (throwError) { throw new MadScience.Exceptions.DatabasePackedFileException("package version was not 2.0 - possibly TS2 content?"); } else { this.packageType = Detective.PackageTypes.sims2Package; hasError = true; } } } this.IndexOffset = indexOffset; // Check for invalid indexOffsets if (indexOffset > input.Length) { // This is a corrupted file. We can do nothing. this.packageType = Detective.PackageTypes.corruptBadDownload; return; } this.Entries.Clear(); // Do some stuff for TS2 if (this.Version.Major == 1) { if (this.IndexOffset == 0) { this.IndexOffset = this.smallHeader.IndexOffsetTS2; } } if (this.Version.Major == 538976258) { // This is seen in some of Chaavik's packages - spaces in the header. // We can do nothing with these, so just give up this.packageType = Detective.PackageTypes.corruptChaavik; return; } // If we get this far, DONT have throw errors on, and have an error, then just plain exit. //if (!throwError && hasError) return; if (indexCount > 0) { // Read index int presentPackageValues = 0; bool hasPackageTypeId = false; bool hasPackageGroupId = false; bool hasPackageHiInstanceId = false; uint packageTypeId = 0; uint packageGroupId = 0; uint packageHiInstanceId = 0; input.Seek(this.IndexOffset, SeekOrigin.Begin); // Do some stuff for TS2 if (this.Version.Major == 2) { presentPackageValues = MadScience.StreamHelpers.ReadValueS32(input); this.IndexType = presentPackageValues; if ((presentPackageValues & ~7) != 0) { this.packageType = Detective.PackageTypes.corruptIndex; // Check backwards 3 bytes (some files from peggy have invalid input.Seek(this.IndexOffset - 3, SeekOrigin.Begin); presentPackageValues = MadScience.StreamHelpers.ReadValueS32(input); this.IndexType = presentPackageValues; if ((presentPackageValues & ~7) != 0) { if (throwError) { throw new InvalidDataException("don't know how to handle this index data"); } else { this.packageType = Detective.PackageTypes.corruptPeggy; return; } } } hasPackageTypeId = (presentPackageValues & (1 << 0)) == 1 << 0; hasPackageGroupId = (presentPackageValues & (1 << 1)) == 1 << 1; hasPackageHiInstanceId = (presentPackageValues & (1 << 2)) == 1 << 2; packageTypeId = hasPackageTypeId ? MadScience.StreamHelpers.ReadValueU32(input) : 0xFFFFFFFF; packageGroupId = hasPackageGroupId ? MadScience.StreamHelpers.ReadValueU32(input) : 0xFFFFFFFF; packageHiInstanceId = hasPackageHiInstanceId ? MadScience.StreamHelpers.ReadValueU32(input) : 0xFFFFFFFF; } for (int i = 0; i < indexCount; i++) { Entry entry = new Entry(); entry.Key = new ResourceKey(); if (hasPackageTypeId) entry.Key.typeId = packageTypeId; else entry.Key.typeId = MadScience.StreamHelpers.ReadValueU32(input); if (hasPackageGroupId) entry.Key.groupId = packageGroupId; else entry.Key.groupId = MadScience.StreamHelpers.ReadValueU32(input); entry.Key.instanceId = 0; entry.Key.instanceId |= (hasPackageHiInstanceId ? packageHiInstanceId : MadScience.StreamHelpers.ReadValueU32(input)); entry.Key.instanceId <<= 32; entry.Key.instanceId |= MadScience.StreamHelpers.ReadValueU32(input); entry.Offset = (this.Big == true) ? MadScience.StreamHelpers.ReadValueS64(input) : MadScience.StreamHelpers.ReadValueS32(input); entry.CompressedSize = MadScience.StreamHelpers.ReadValueU32(input); // Detect game type /* if (entry.Key.groupId != 0xDEADBEEF) { switch (this.gameNumber) { case MadScience.Helpers.GameNumber.ambitions: break; case MadScience.Helpers.GameNumber.highEndLoftStuff: if ((entry.Key.groupId & (uint)MadScience.Helpers.ContentCategory.kEP2Content) == (uint)MadScience.Helpers.ContentCategory.kEP2Content) { this.gameNumber = MadScience.Helpers.GameNumber.ambitions; } break; case MadScience.Helpers.GameNumber.worldAdventures: if ((entry.Key.groupId & (uint)MadScience.Helpers.ContentCategory.kSP1Content) == (uint)MadScience.Helpers.ContentCategory.kSP1Content) { this.gameNumber = MadScience.Helpers.GameNumber.highEndLoftStuff; } if ((entry.Key.groupId & (uint)MadScience.Helpers.ContentCategory.kEP2Content) == (uint)MadScience.Helpers.ContentCategory.kEP2Content) { this.gameNumber = MadScience.Helpers.GameNumber.ambitions; } break; case MadScience.Helpers.GameNumber.baseGame: if ((entry.Key.groupId & (uint)MadScience.Helpers.ContentCategory.kEP1Content) == (uint)MadScience.Helpers.ContentCategory.kEP1Content) { this.gameNumber = MadScience.Helpers.GameNumber.worldAdventures; } if ((entry.Key.groupId & (uint)MadScience.Helpers.ContentCategory.kSP1Content) == (uint)MadScience.Helpers.ContentCategory.kSP1Content) { this.gameNumber = MadScience.Helpers.GameNumber.highEndLoftStuff; } if ((entry.Key.groupId & (uint)MadScience.Helpers.ContentCategory.kEP2Content) == (uint)MadScience.Helpers.ContentCategory.kEP2Content) { this.gameNumber = MadScience.Helpers.GameNumber.ambitions; } break; } } */ if (this.Version.Major == 2) { entry.DecompressedSize = MadScience.StreamHelpers.ReadValueU32(input); // compressed bit if ((entry.CompressedSize & 0x80000000) == 0x80000000) { entry.CompressedSize &= ~0x80000000; entry.CompressionFlags = MadScience.StreamHelpers.ReadValueS16(input); entry.Flags = MadScience.StreamHelpers.ReadValueU16(input); } else { if (entry.CompressedSize != entry.DecompressedSize) { entry.CompressionFlags = -1; } else { entry.CompressionFlags = 0; } entry.Flags = 0; if (throwError) { throw new MadScience.Exceptions.DatabasePackedFileException("strange index data"); } else { this.packageType = Detective.PackageTypes.corruptIndex; return; } } if (entry.CompressionFlags != 0 && entry.CompressionFlags != -1) { throw new MadScience.Exceptions.DatabasePackedFileException("bad compression flags"); } } if (entry.Offset + entry.CompressedSize > this.EndOfDataOffset) { this.EndOfDataOffset = entry.Offset + entry.CompressedSize; } this.Entries.Add(entry); } } }
public void Read(Stream input) { Int64 indexCount; Int64 indexSize; Int64 indexOffset; string magic = input.ReadStringASCII(4); if (magic != "DBPF" && magic != "DBBF") // DBPF & DBBF { throw new NotAPackageException(); } this.Big = magic == "DBBF"; if (this.Big == true) { BigHeader header = input.ReadStructure <BigHeader>(); if (header.IndexVersion != 3) { throw new DatabasePackedFileException("index version was not 3"); } // Nab useful stuff this.Version = new Version(header.MajorVersion, header.MinorVersion); indexCount = header.IndexCount; indexOffset = header.IndexOffset; indexSize = header.IndexSize; } else { Header header = input.ReadStructure <Header>(); if (header.IndexVersion != 3) { throw new DatabasePackedFileException("index version was not 3"); } // Nab useful stuff this.Version = new Version(header.MajorVersion, header.MinorVersion); indexCount = header.IndexCount; indexOffset = header.IndexOffset; indexSize = header.IndexSize; } this.IndexOffset = indexOffset; this.Entries.Clear(); if (indexCount > 0) { // Read index input.Seek(indexOffset, SeekOrigin.Begin); int presentPackageValues = input.ReadValueS32(); this.IndexType = presentPackageValues; if ((presentPackageValues & ~7) != 0) { throw new InvalidDataException("don't know how to handle this index data"); } bool hasPackageTypeId = (presentPackageValues & (1 << 0)) == 1 << 0; bool hasPackageGroupId = (presentPackageValues & (1 << 1)) == 1 << 1; bool hasPackageHiInstanceId = (presentPackageValues & (1 << 2)) == 1 << 2; uint packageTypeId = hasPackageTypeId ? input.ReadValueU32() : 0xFFFFFFFF; uint packageGroupId = hasPackageGroupId ? input.ReadValueU32() : 0xFFFFFFFF; uint packageHiInstanceId = hasPackageHiInstanceId ? input.ReadValueU32() : 0xFFFFFFFF; for (int i = 0; i < indexCount; i++) { Entry entry = new Entry(); entry.Key.TypeId = hasPackageTypeId ? packageTypeId : input.ReadValueU32(); entry.Key.GroupId = hasPackageGroupId ? packageGroupId : input.ReadValueU32(); entry.Key.InstanceId = 0; entry.Key.InstanceId |= (hasPackageHiInstanceId ? packageHiInstanceId : input.ReadValueU32()); entry.Key.InstanceId <<= 32; entry.Key.InstanceId |= input.ReadValueU32(); entry.Offset = (this.Big == true) ? input.ReadValueS64() : input.ReadValueS32(); entry.CompressedSize = input.ReadValueU32(); entry.DecompressedSize = input.ReadValueU32(); // compressed bit if ((entry.CompressedSize & 0x80000000) == 0x80000000) { entry.CompressedSize &= ~0x80000000; entry.CompressionFlags = input.ReadValueS16(); entry.Flags = input.ReadValueU16(); } else { if (entry.CompressedSize != entry.DecompressedSize) { entry.CompressionFlags = -1; } else { entry.CompressionFlags = 0; } entry.Flags = 0; throw new DatabasePackedFileException("strange index data"); } if (entry.CompressionFlags != 0 && entry.CompressionFlags != -1) { throw new DatabasePackedFileException("bad compression flags"); } this.Entries.Add(entry); } } }