public void Read(byte[] file)
        {
            FileInput f = new FileInput(file);

            f.byteOrder = byteOrder;
            f.Seek(8);             // SARC+Endianness

            int archiveSize = f.ReadInt();
            int startOffset = f.ReadInt();

            padding = startOffset;
            f.Skip(10);             // SFAT
            int nodeCount      = f.ReadShort();
            int hashMultiplier = f.ReadInt();

            List <SFATNode> sfatNodes = new List <SFATNode>();

            for (int i = 0; i < nodeCount; i++)
            {
                SFATNode temp;
                temp.nameHash        = f.ReadInt();
                temp.nameTableOffset = f.ReadInt() - 0x1000000;
                if (temp.nameTableOffset == -0x1000000)
                {
                    temp.hasString = false;
                }
                else
                {
                    temp.hasString = true;
                }
                temp.fileDataOffset    = f.ReadInt();
                temp.endFileDataOffset = f.ReadInt();
                sfatNodes.Add(temp);
            }

            f.Skip(8);

            int nameTableStart = f.Position();

            foreach (SFATNode sfat in sfatNodes)
            {
                string tempName;
                if (sfat.hasString)
                {
                    f.Seek(sfat.nameTableOffset * 4 + nameTableStart);
                    tempName = f.ReadString();
                }
                else
                {
                    tempName = "0x" + sfat.nameHash.ToString("X8");
                }
                f.Seek(sfat.fileDataOffset + startOffset);
                byte[] tempFile = f.Read(sfat.endFileDataOffset - sfat.fileDataOffset);
                files.Add(tempName, tempFile);
            }
        }
Beispiel #2
0
        public static byte[] Decompress(byte[] data)
        {
            FileInput f = new FileInput(data);

            f.byteOrder = ByteOrder.BigEndian;
            f.Seek(4);
            int uncompressedSize = f.ReadInt();

            byte[] flags = f.Read(8);

            byte[] src = f.Read(data.Length - 0x10);
            byte[] dst = new byte[uncompressedSize];

            int srcPlace = 0, dstPlace = 0;     // Current read/write positions

            uint validBitCount = 0;             // Number of valid bits left in "code" byte
            byte currCodeByte  = 0;

            while (dstPlace < uncompressedSize)
            {
                // Read new "code" byte if the current one is used up
                if (validBitCount == 0)
                {
                    currCodeByte = src[srcPlace];
                    ++srcPlace;
                    validBitCount = 8;
                }

                if ((currCodeByte & 0x80) != 0)
                {
                    // Straight copy
                    dst[dstPlace] = src[srcPlace];
                    dstPlace++;
                    srcPlace++;
                }
                else
                {
                    // RLE part
                    byte byte1 = src[srcPlace];
                    byte byte2 = src[srcPlace + 1];
                    srcPlace += 2;

                    uint dist       = (uint)(((byte1 & 0xF) << 8) | byte2);
                    uint copySource = (uint)(dstPlace - (dist + 1));

                    uint numBytes = (uint)(byte1 >> 4);
                    if (numBytes == 0)
                    {
                        numBytes = (uint)(src[srcPlace] + 0x12);
                        srcPlace++;
                    }
                    else
                    {
                        numBytes += 2;
                    }

                    // Copy run
                    for (int i = 0; i < numBytes; ++i)
                    {
                        dst[dstPlace] = dst[copySource];
                        copySource++;
                        dstPlace++;
                    }
                }

                // Use next bit from "code" byte
                currCodeByte <<= 1;
                validBitCount -= 1;
            }

            return(dst);
        }