Example #1
0
        public static bool pack(string indir, string outfile, uint padding)
        {
            if (!System.IO.Directory.Exists(indir))
            {
                return(false);
            }

            string[] indir_files = System.IO.Directory.GetFiles(indir == "" ? System.Environment.CurrentDirectory : indir, "*.*", System.IO.SearchOption.AllDirectories);

            filedata[] filedatalist = new filedata[indir_files.Length];
            int        lenfiles = 0, numfiles = indir_files.Length, lennames = 0;
            uint       filesize;

            for (int c = 0; c < indir_files.Length; c++)
            {
                string realname = indir_files[c];
                string filename = indir_files[c].Replace(indir + System.IO.Path.DirectorySeparatorChar.ToString(), "");

                filesize = getfilesize(realname);
                if (filesize % padding > 0)
                {
                    filesize += (padding - (filesize % padding));
                }
                int namesize = filename.Length;
                namesize       += (4 - (namesize % 4));
                lennames       += namesize;
                filedatalist[c] = new filedata(filename, realname, (int)filesize, namesize, numfiles);
            }

            filehash[] hashes_unsorted = new filehash[numfiles];

            for (int c = 0; c < numfiles; c++)
            {
                hashes_unsorted[c] = new filehash(calchash(filedatalist[c].filename), c);
            }

            uint lhash;

            bool[]     hashes_done = new bool[hashes_unsorted.Length];
            filehash[] hashes      = new filehash[hashes_unsorted.Length];
            int        dhi         = 0;

            for (int c = 0; c < hashes.Length; c++)
            {
                lhash = uint.MaxValue;
                for (int cc = 0; cc < hashes_unsorted.Length; cc++)
                {
                    if (hashes_done[cc])
                    {
                        continue;
                    }
                    if (hashes_unsorted[cc].hash < lhash)
                    {
                        dhi   = cc;
                        lhash = hashes_unsorted[cc].hash;
                    }
                }
                hashes_done[dhi] = true;
                hashes[c]        = hashes_unsorted[dhi];
            }

            for (int c = 0; c < numfiles; c++)
            {
                lenfiles += (int)filedatalist[hashes[c].index].filesize;
            }
            uint lastfile = getfilesize(filedatalist[hashes[hashes.Length - 1].index].realname);

            lenfiles += (int)lastfile;
            filesize  = (uint)(32 + (16 * numfiles) + 8 + lennames);
            uint padSFAT   = (padding - (filesize % padding));
            uint datastart = padSFAT + filesize;

            filesize += (uint)(padSFAT + lenfiles);

            System.IO.StreamWriter sw = new System.IO.StreamWriter(outfile);
            sw.BaseStream.Write(new byte[] { 83, 65, 82, 67, 0x00, 0x14, 0xFE, 0xFF }, 0, 8);
            sw.BaseStream.Write(breaku32(filesize), 0, 4);
            sw.BaseStream.Write(breaku32(datastart), 0, 4);
            sw.BaseStream.Write(new byte[] { 0x01, 0x00, 0x00, 0x00, 83, 70, 65, 84, 0x00, 0x0C }, 0, 10);
            sw.BaseStream.Write(breaku16((ushort)numfiles), 0, 2);
            sw.BaseStream.Write(breaku32(0x65), 0, 4);
            int strpos = 0, filepos = 0;

            for (int c = 0; c < numfiles; c++)
            {
                sw.BaseStream.Write(breaku32(hashes[c].hash), 0, 4);
                sw.BaseStream.WriteByte(0x01); // Unknown, see http://mk8.tockdom.com/wiki/SARC_%28File_Format%29
                sw.BaseStream.Write(breaku32((uint)(strpos >> 2)), 1, 3);
                strpos += filedatalist[hashes[c].index].namesize;
                sw.BaseStream.Write(breaku32((uint)filepos), 0, 4);
                filesize = getfilesize(filedatalist[hashes[c].index].realname);
                sw.BaseStream.Write(breaku32((uint)filepos + (uint)filesize), 0, 4);
                filepos += filedatalist[hashes[c].index].filesize;
            }
            sw.BaseStream.Write(new byte[] { 83, 70, 78, 84, 0x00, 0x08, 0x00, 0x00 }, 0, 8);
            for (int c = 0; c < numfiles; c++)
            {
                string tn = filedatalist[hashes[c].index].filename;
                for (int cc = 0; cc < tn.Length; cc++)
                {
                    sw.BaseStream.WriteByte((byte)tn[cc]);
                }
                int numpad0 = filedatalist[hashes[c].index].namesize - filedatalist[hashes[c].index].filename.Length;
                for (int cc = 0; cc < numpad0; cc++)
                {
                    sw.BaseStream.WriteByte(0);
                }
            }
            for (int cc = 0; cc < padSFAT; cc++)
            {
                sw.BaseStream.WriteByte(0);
            }

            byte[] tmp;
            for (int c = 0; c < numfiles; c++)
            {
                tmp = System.IO.File.ReadAllBytes(filedatalist[hashes[c].index].realname);
                sw.BaseStream.Write(tmp, 0, tmp.Length);
                filesize = (uint)tmp.Length;
                if (c < numfiles - 1)
                {
                    int numpad0 = (int)(filedatalist[hashes[c].index].filesize - filesize);
                    for (int cc = 0; cc < numpad0; cc++)
                    {
                        sw.BaseStream.WriteByte(0);
                    }
                }
            }

            sw.Close();
            sw.Dispose();

            return(true);
        }
Example #2
0
        public static bool pack(string indir, string outfile, uint padding)
        {
            if (!System.IO.Directory.Exists(indir)) return false;

            string[] indir_files = System.IO.Directory.GetFiles(indir=="" ? System.Environment.CurrentDirectory : indir, "*.*", System.IO.SearchOption.AllDirectories);

            filedata[] filedatalist = new filedata[indir_files.Length];
            int lenfiles=0, numfiles=indir_files.Length, lennames=0;
            uint filesize;
            for (int c = 0; c < indir_files.Length; c++) {
                string realname = indir_files[c];
                string filename = indir_files[c].Replace(indir + System.IO.Path.DirectorySeparatorChar.ToString(), "");

                filesize = getfilesize(realname);
                if (filesize % padding > 0) filesize += (padding - (filesize % padding));
                int namesize = filename.Length;
                namesize += (4 - (namesize % 4));
                lennames += namesize;
                filedatalist[c] = new filedata(filename, realname, (int)filesize, namesize, numfiles);
            }

            filehash[] hashes_unsorted = new filehash[numfiles];

            for (int c = 0; c < numfiles; c++) {
                hashes_unsorted[c] = new filehash(calchash(filedatalist[c].filename), c);
            }

            uint lhash;
            bool[] hashes_done = new bool[hashes_unsorted.Length];
            filehash[] hashes = new filehash[hashes_unsorted.Length];
            int dhi=0;

            for (int c=0; c < hashes.Length; c++) {
                lhash = uint.MaxValue;
                for (int cc=0; cc < hashes_unsorted.Length; cc++) {
                    if (hashes_done[cc]) continue;
                    if (hashes_unsorted[cc].hash < lhash) {
                        dhi=cc;
                        lhash = hashes_unsorted[cc].hash;
                    }
                }
                hashes_done[dhi] = true;
                hashes[c] = hashes_unsorted[dhi];
            }

            for (int c = 0; c < numfiles; c++) {
                lenfiles += (int)filedatalist[hashes[c].index].filesize;
            }
            uint lastfile = getfilesize(filedatalist[hashes[hashes.Length-1].index].realname);
            lenfiles += (int)lastfile;
            filesize = (uint) (32 + (16 * numfiles) + 8 + lennames);
            uint padSFAT = (padding - (filesize % padding));
            uint datastart = padSFAT + filesize;
            filesize += (uint) (padSFAT + lenfiles);

            System.IO.StreamWriter sw = new System.IO.StreamWriter(outfile);
            sw.BaseStream.Write(new byte[] {83, 65, 82, 67, 0x00, 0x14, 0xFE, 0xFF}, 0, 8);
            sw.BaseStream.Write(breaku32(filesize), 0, 4);
            sw.BaseStream.Write(breaku32(datastart), 0, 4);
            sw.BaseStream.Write(new byte[] {0x01, 0x00, 0x00, 0x00, 83, 70, 65, 84, 0x00, 0x0C}, 0, 10);
            sw.BaseStream.Write(breaku16((ushort)numfiles), 0, 2);
            sw.BaseStream.Write(breaku32(0x65), 0, 4);
            int strpos=0, filepos=0;
            for (int c=0; c < numfiles; c++) {
                sw.BaseStream.Write(breaku32(hashes[c].hash), 0, 4);
                sw.BaseStream.WriteByte(0x01); // Unknown, see http://mk8.tockdom.com/wiki/SARC_%28File_Format%29
                sw.BaseStream.Write(breaku32((uint)(strpos >> 2)), 1, 3);
                strpos += filedatalist[hashes[c].index].namesize;
                sw.BaseStream.Write(breaku32((uint)filepos), 0, 4);
                filesize = getfilesize(filedatalist[hashes[c].index].realname);
                sw.BaseStream.Write(breaku32((uint) filepos+(uint) filesize), 0, 4);
                filepos += filedatalist[hashes[c].index].filesize;
            }
            sw.BaseStream.Write(new byte[] {83, 70, 78, 84, 0x00, 0x08, 0x00, 0x00}, 0, 8);
            for (int c=0; c < numfiles; c++) {
                string tn = filedatalist[hashes[c].index].filename;
                for (int cc = 0; cc < tn.Length; cc++) {
                    sw.BaseStream.WriteByte((byte) tn[cc]);
                }
                int numpad0 = filedatalist[hashes[c].index].namesize - filedatalist[hashes[c].index].filename.Length;
                for (int cc = 0; cc < numpad0; cc++)
                    sw.BaseStream.WriteByte(0);
            }
            for (int cc = 0; cc < padSFAT; cc++)
                sw.BaseStream.WriteByte(0);

            byte[] tmp;
            for (int c=0; c < numfiles; c++) {
                tmp = System.IO.File.ReadAllBytes(filedatalist[hashes[c].index].realname);
                sw.BaseStream.Write(tmp, 0, tmp.Length);
                filesize = (uint)tmp.Length;
                if (c < numfiles-1) {
                    int numpad0 = (int)(filedatalist[hashes[c].index].filesize - filesize);
                    for (int cc=0; cc < numpad0; cc++)
                        sw.BaseStream.WriteByte(0);
                }
            }

            sw.Close();
            sw.Dispose();

            return true;
        }