Ejemplo n.º 1
0
        public override Stream Encode(bool _ = false)
        {
            Stream fSysStream = $"{Path}/{FileName}.repak".GetNewStream();

            if (ExtractedEntries.Count == 0)
            {
                // nothing extracted, nothing changed
                // just copy the existing stream back
                ExtractedFile.Seek(0, SeekOrigin.Begin);
                ExtractedFile.CopyTo(fSysStream);
                return(fSysStream);
            }

            // unpack the entire fsys archive for easier repacking
            if (ExtractedEntries.Count < NumberOfEntries)
            {
                FSysExtractor.ExtractFSys(this, false);
            }


            // copy the header back, we'll update the sizes later
            NumberOfEntries = ExtractedEntries.Count;
            ExtractedFile.Seek(0, SeekOrigin.Begin);
            ExtractedFile.CopySubStream(fSysStream, 0, 0x60);

            var sizeOfDetailsPointers = (fSysDetailsHeaders.Count * 4);
            var startNameOffset       = 0x60 + sizeOfDetailsPointers + sizeOfDetailsPointers.GetAlignBytesCount(16);

            fSysStream.Seek(startNameOffset, SeekOrigin.Begin);

            // write the name table
            var startDataOffset = uint.MaxValue;

            foreach (var detailHeader in fSysDetailsHeaders)
            {
                fSysStream.Write(detailHeader.FileName.ToByteArray());
                fSysStream.WriteByte(0);

                if (detailHeader.StartOffset < startDataOffset)
                {
                    startDataOffset = detailHeader.StartOffset;
                }
            }

            // align names
            fSysStream.AlignStream(0x10);
            var lastNameOffset      = (int)fSysStream.Position;
            var startDetailsOffsewt = 0x60;

            // write pointers to details offset
            fSysStream.Seek(startDetailsOffsewt, SeekOrigin.Begin);
            for (int x = 0; x < fSysDetailsHeaders.Count; x++)
            {
                fSysStream.Write((lastNameOffset + (x * 0x70)).GetBytes());
            }

            // write our data, update offsets along the way if we find mismatches
            for (int i = 0; i < fSysDetailsHeaders.Count; i++)
            {
                var detailHeader = fSysDetailsHeaders[i];

                var entryFileName = detailHeader.FileName.ToString();
                if (!entryFileName.EndsWith(detailHeader.Filetype.FileTypeName()))
                {
                    entryFileName = $"{entryFileName}{detailHeader.Filetype.FileTypeName()}";
                }

                var entry = ExtractedEntries[entryFileName];

                using var encodeStream = entry.Encode(detailHeader.IsCompressed);
                fSysStream.Seek(detailHeader.StartOffset, SeekOrigin.Begin);
                encodeStream.CopyTo(fSysStream);
                fSysStream.Flush();

                detailHeader.UncompressedSize = (uint)entry.ExtractedFile.Length;
                if (encodeStream.Length != detailHeader.CompressedSize)
                {
                    var adjustedSize = (int)(encodeStream.Length - detailHeader.CompressedSize);
                    detailHeader.CompressedSize = (uint)encodeStream.Length;

                    if (adjustedSize < 0)
                    {
                        continue; // probably wasteful, but meh
                    }
                    for (int j = i + 1; j < fSysDetailsHeaders.Count; j++)
                    {
                        var adjDetailsHeader = fSysDetailsHeaders[j];
                        adjDetailsHeader.StartOffset += (uint)adjustedSize;
                        adjDetailsHeader.StartOffset += adjDetailsHeader.StartOffset.GetAlignBytesCount(0x10);
                    }
                }
            }

            fSysStream.AlignStream(0x10);
            fSysStream.Write(new byte[0x10]);
            fSysStream.Seek(-4, SeekOrigin.Current);
            fSysStream.Write(FSYSbytes.GetBytes());
            fSysStream.Flush();

            fSysStream.WriteBytesAtOffset(FSYSFileSizeOffset, ((int)fSysStream.Length).GetBytes());

            // go back and re-write our file details table
            fSysStream.Seek(lastNameOffset, SeekOrigin.Begin);
            foreach (var detailHeader in fSysDetailsHeaders)
            {
                fSysStream.Write(detailHeader.Encode());
            }

            fSysStream.Flush();
            fSysStream.Seek(0, SeekOrigin.Begin);
            return(fSysStream);
        }