Beispiel #1
0
 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);
     }
 }
Beispiel #2
0
 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);
     }
 }
Beispiel #4
0
        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);
                }
            }
        }
Beispiel #7
0
        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);
                }
            }
        }