Esempio n. 1
0
        public byte[] Rebuild()
        {
            FileOutput f = new FileOutput();

            f.Endian = endian;

            f.writeString("SARC");
            f.writeShort(0x14);
            f.Endian = endian;
            f.writeShort(65279);

            byte[] sfat = RebuildSFATArchive();

            f.writeInt(sfat.Length + 0x14);
            f.writeInt(sfatStartOffset + 0x14);
            f.writeInt(0x1000000);
            f.writeBytes(sfat);

            return(f.getBytes());
        }
Esempio n. 2
0
        public static byte[] Decompress(byte[] data)
        {
            FileData   f      = new FileData(data);
            FileOutput output = new FileOutput();

            f.Endian = Endianness.Big;
            f.seek(4);
            int uncompressedSize = f.readInt();

            byte[] flags = f.read(8);
            //if ((flags[3] & 0x80) != 0)
            //    f.Endian = Endianness.Little;

            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);
        }
Esempio n. 3
0
        private byte[] RebuildSFATArchive()
        {
            FileOutput f = new FileOutput();

            f.Endian = endian;

            f.writeString("SFAT");
            f.writeShort(0xC);
            f.writeShort(files.Count);
            f.writeInt(0x65);

            int  stringPos = 0;
            int  dataPos   = 0;
            bool isString  = true;

            foreach (string filename in files.Keys)
            {
                if (filename.Contains("0x"))
                {
                    isString = false;
                    f.writeInt((int)Convert.ToInt32(filename, 16));
                    f.writeInt(0);
                }
                else
                {
                    f.writeInt((int)GetHash(filename.ToArray(), filename.Length, 0x65));
                    f.writeInt(stringPos + 0x1000000);
                    stringPos += GetSizeInChunks(filename.Length + 1, 4) / 4;
                }
                f.writeInt(dataPos);
                f.writeInt(dataPos + files[filename].Length);
                dataPos += files[filename].Length % padding == 0 ? files[filename].Length : files[filename].Length + (padding - files[filename].Length % padding);
            }

            f.writeHex("53464E5400080000");
            if (isString)
            {
                foreach (string filename in files.Keys)
                {
                    f.writeString(filename);
                    f.writeByte(0);
                    while (f.pos() % 4 != 0)
                    {
                        f.writeByte(0);
                    }
                }
            }
            if (padding == -1 || padding < f.pos())
            {
                while ((f.pos() + 0x14) % 0x100 != 0)
                {
                    f.writeByte(0);
                }
            }
            else
            {
                f.writeBytes(new byte[padding - (f.pos() + 0x14)]);
            }

            sfatStartOffset = f.pos();
            int cur = 0;

            foreach (string filename in files.Keys)
            {
                f.writeIntAt(f.pos() - sfatStartOffset, 0x14 + (cur * 0x10));
                f.writeBytes(files[filename]);
                f.writeIntAt(f.pos() - sfatStartOffset, 0x18 + (cur * 0x10));
                while ((f.pos() + 0x14) % padding != 0)
                {
                    f.writeByte(0);
                }

                cur++;
            }

            return(f.getBytes());
        }