コード例 #1
0
        public void Write(Stream stream)
        {
            uint filesSize = (uint)FMDX_DATA_PREFIX.Length;

            foreach (FMDX.File file in this.Files)
            {
                filesSize += NumberUtil.Align((uint)file.Data.Length, 0x10);
            }

            using (BinaryWriter writer = new BinaryWriter(stream, Encoding.UTF8, true)) {
                long fmdxStartOffset = writer.BaseStream.Position;

                writer.WriteFixedString(4, FMDX_MAGIC);
                writer.Write(filesSize);
                writer.Write((uint)this.Files.Length);
                writer.Write((uint)1);      // Always 1.
                writer.Write(new byte[68]); // Padding; always observed to be 0.

                uint offset = FMDX_HEADER_SIZE + (uint)this.Files.Length * FMDX_FILE_HEADER_SIZE + (uint)FMDX_DATA_PREFIX.Length;
                foreach (FMDX.File file in this.Files)
                {
                    WriteFile(writer, file, offset, fmdxStartOffset);
                    offset += NumberUtil.Align((uint)file.Data.Length, 0x10);
                }

                writer.Write(FMDX_DATA_PREFIX);
            }
        }
コード例 #2
0
        private void WriteFileSet(Stream stream, FileSet fileSet)
        {
            PACKFSHD fileSetHeader    = new PACKFSHD();
            GENESTRT fileSetNameTable = new GENESTRT();

            fileSetHeader.Unknown    = 0x10000;
            fileSetHeader.DataOffset = 0; // Filled in later.

            foreach (File file in fileSet.Files)
            {
                PACKFSHD.FileEntry fileEntry = new PACKFSHD.FileEntry();
                fileEntry.NameIndex        = fileSetNameTable.AddString(file.Name);
                fileEntry.Unknown          = 0x2;
                fileEntry.Offset           = 0; // Filled in later.
                fileEntry.UncompressedSize = file.UncompressedSize;
                fileEntry.CompressedSize   = (uint)file.RawData.Length;

                fileSetHeader.Files.Add(fileEntry);
            }

            SectionSet fileSetSections = new SectionSet();

            fileSetSections.Add(new ENDILTLE());
            fileSetSections.Add(fileSetHeader);
            fileSetSections.Add(fileSetNameTable);
            fileSetSections.Add(new GENEEOF());

            ulong headersSize;

            using (MemoryStream sizeTestStream = new MemoryStream()) {
                SectionIO.WriteAll(sizeTestStream, fileSetSections);
                headersSize = (ulong)sizeTestStream.Length;
            }

            ulong currOffset = NumberUtil.Align(headersSize, 0x10);

            fileSetHeader.DataOffset = (uint)currOffset - 0x10;  // Offset excludes ENDILTLE.
            foreach (PACKFSHD.FileEntry fileEntry in fileSetHeader.Files)
            {
                fileEntry.Offset = currOffset;
                currOffset       = NumberUtil.Align(currOffset + fileEntry.CompressedSize, 0x10);
            }

            SectionIO.WriteAll(stream, fileSetSections);

            foreach (File file in fileSet.Files)
            {
                stream.Write(file.RawData);
                stream.PadTo(0x10);
            }
        }
コード例 #3
0
        private static void WriteFile(BinaryWriter writer, FMDX.File file, uint offset, long fmdxStartOffset)
        {
            writer.WriteFixedString(128, file.Path);
            writer.Write(offset);
            writer.Write((uint)file.Data.Length);
            writer.Write(new byte[8]); // Padding; always observed to be 0.

            long pos = writer.BaseStream.Position;

            writer.BaseStream.Seek(fmdxStartOffset + offset, SeekOrigin.Begin);

            writer.Write(file.Data);
            uint padding = NumberUtil.Align((uint)file.Data.Length, 0x10) - (uint)file.Data.Length;

            if (padding > 0)
            {
                writer.Write(new byte[padding]);
            }

            writer.BaseStream.Seek(pos, SeekOrigin.Begin);
        }
コード例 #4
0
        public void Write(Stream stream)
        {
            GENESTRT nameTable = new GENESTRT();

            nameTable.Strings.Add(this.Name);

            PACKHEDR packhedr = new PACKHEDR();

            packhedr.Unknown1   = 0x10000;
            packhedr.NameIndex  = 0;
            packhedr.DataOffset = 0;            // Filled in later.
            packhedr.Unknown3   = 1;
            packhedr.Hash       = new byte[16]; // TODO

            PACKTOC toc = new PACKTOC();

            byte[] fileData;
            using (MemoryStream fileStream = new MemoryStream()) {
                this.WriteFiles(fileStream, toc, nameTable);
                fileData = fileStream.ToArray();
            }

            PACKFSLS      fsls         = new PACKFSLS();
            List <byte[]> fileSetDatas = new List <byte[]>();
            uint          nameIndex    = (uint)nameTable.Strings.Count;

            foreach (FileSet fileSet in this.FileSets)
            {
                byte[] fileSetData;
                using (MemoryStream fileSetStream = new MemoryStream()) {
                    this.WriteFileSet(fileSetStream, fileSet);
                    fileSetData = fileSetStream.ToArray();
                }

                PACKFSLS.FileSetEntry entry = new PACKFSLS.FileSetEntry();
                entry.NameIndex    = nameTable.AddString(fileSet.Name);
                entry.PackageIndex = 0;
                entry.Offset       = 0; // Filled in later.
                entry.Size         = (ulong)fileSetData.Length;
                entry.Hash         = new MD5CryptoServiceProvider().ComputeHash(fileSetData);

                fsls.FileSets.Add(entry);
                fileSetDatas.Add(fileSetData);
            }

            SectionSet set = new SectionSet();

            set.Add(new ENDILTLE());
            set.Add(packhedr);
            set.Add(toc);
            set.Add(fsls);
            set.Add(nameTable);
            set.Add(new GENEEOF());

            ulong headersSize;

            using (MemoryStream sizeTestStream = new MemoryStream()) {
                SectionIO.WriteAll(sizeTestStream, set);
                headersSize = (ulong)sizeTestStream.Length;
            }

            ulong currOffset = NumberUtil.Align(headersSize, 0x800);

            packhedr.DataOffset = (uint)currOffset;
            foreach (PACKTOC.Entry entry in toc.Entries)
            {
                if (entry is PACKTOC.UncompressedFileEntry uFileEntry)
                {
                    uFileEntry.Offset = currOffset;
                    currOffset        = NumberUtil.Align(currOffset + uFileEntry.Size, 0x200);
                }
                else if (entry is PACKTOC.CompressedFileEntry cFileEntry)
                {
                    cFileEntry.Offset = currOffset;
                    currOffset        = NumberUtil.Align(currOffset + cFileEntry.CompressedSize, 0x200);
                }
            }

            currOffset = NumberUtil.Align(currOffset, 0x800);
            foreach (PACKFSLS.FileSetEntry fileSetEntry in fsls.FileSets)
            {
                fileSetEntry.Offset = currOffset;
                currOffset          = NumberUtil.Align(currOffset + fileSetEntry.Size, 0x800);
            }

            SectionIO.WriteAll(stream, set);
            stream.PadTo(0x800);

            stream.Write(fileData);

            foreach (byte[] fileSetData in fileSetDatas)
            {
                stream.PadTo(0x800);
                stream.Write(fileSetData);
            }
        }