Beispiel #1
0
        public void Save(System.IO.Stream stream)
        {
            using (var writer = new FileWriter(stream))
            {
                writer.SetByteOrder(true);
                writer.Write(Unknowns); //ID list?
                long currentOffset = 0;
                for (int i = 0; i < Files.Count; i++)
                {
                    if (currentOffset != 0)
                    {
                        long nextOffset = writer.Position;
                        using (writer.TemporarySeek(currentOffset + 8, System.IO.SeekOrigin.Begin)) {
                            writer.Write((uint)nextOffset);
                        }
                    }

                    currentOffset = writer.Position;
                    writer.Write((uint)Files[i].Type);
                    writer.Write((uint)Files[i].FileData.Length);
                    writer.Write((uint)0);
                    writer.Write(new byte[20]);
                    writer.Write(Files[i].AsBytes());
                    writer.AlignBytes(32);
                }
            }
        }
Beispiel #2
0
        //Align the last set of bytes so everything gets encrypted back correctly
        static byte[] IntoBytes(string contents)
        {
            var mem = new MemoryStream();

            using (var writer = new FileWriter(mem))
            {
                writer.Write(Encoding.UTF8.GetBytes(contents));
                writer.AlignBytes(128);
            }
            return(mem.ToArray());
        }
Beispiel #3
0
        private void WriteMessageData(FileWriter writer, MessageData messData, Encoding encoding, uint version)
        {
            if (messData.Entries.Count == 0)
            {
                writer.Write(messData.Data);
            }
            else
            {
                if (version <= 5)
                {
                    long startPos = writer.Position;
                    writer.Write(messData.Entries.Count);
                    writer.Write(new uint[messData.Entries.Count]);
                    long sectionSizePos = writer.Position;
                    writer.Write(uint.MaxValue);
                    for (int i = 0; i < messData.Entries.Count; i++)
                    {
                        writer.WriteUint32Offset(startPos + 4 + (i * 4), startPos);
                        writer.Write((byte)0xB);
                        WriteString(writer, messData.Entries[i].Value);
                        writer.AlignBytes(4);
                    }

                    writer.WriteSectionSizeU32(sectionSizePos, writer.Position - startPos);
                }
                else
                {
                    long startPos = writer.Position;
                    writer.Write(messData.Entries.Count);
                    writer.Write(new uint[messData.Entries.Count]);
                    long sectionSizePos = writer.Position;
                    for (int i = 0; i < messData.Entries.Count; i++)
                    {
                        writer.WriteUint32Offset(startPos + 4 + (i * 4), startPos + 4);
                        writer.Write(((MessageEntryV2)messData.Entries[i]).ID);
                        WriteString(writer, messData.Entries[i].Value);
                        writer.AlignBytes(4);
                    }
                }
            }
        }
Beispiel #4
0
        public static void WriteSection(FileWriter writer, Header header, string magic, MSBTEntry section)
        {
            long startPos = writer.Position;

            writer.WriteSignature(magic);
            writer.Write(uint.MaxValue);
            section.Write(writer, header);
            long endPos = writer.Position;

            writer.AlignBytes(16, 0xAB);
            //Skip 20 bytes from the header
            writer.WriteSectionSizeU32(startPos + 4, startPos + 0x10, endPos);
        }
        //Saves data in recusive order
        private void SaveFileData(FileWriter writer, ref uint dataPos, DirectoryEntry parentDir)
        {
            for (int i = 0; i < parentDir.Children.Count; i++)
            {
                if (parentDir.Children[i] is FileEntry)
                {
                    var  entry = (FileEntry)parentDir.Children[i];
                    long pos   = writer.Position;
                    using (writer.TemporarySeek(entry._dataOffsetPos, SeekOrigin.Begin)) {
                        writer.Write((uint)dataPos);
                    }
                    writer.Write(entry.AsBytes());
                    writer.AlignBytes(32);

                    dataPos += (uint)(writer.Position - pos);
                }
                if (parentDir.Children[i] is DirectoryEntry)
                {
                    SaveFileData(writer, ref dataPos, (DirectoryEntry)parentDir.Children[i]);
                }
            }
        }
Beispiel #6
0
            public void Write(FileWriter writer, List <APAKFileInfo> files)
            {
                writer.SetByteOrder(IsBigEndian);
                writer.WriteSignature("APAK");
                writer.Write((ushort)0);
                writer.Write(Version);
                writer.Write(files.Count);
                writer.Write(Unknown1);
                writer.Write(files.Count * 64);
                writer.Write(uint.MaxValue);

                long fileInfoPos = writer.Position;

                for (int i = 0; i < files.Count; i++)
                {
                    files[i].SaveFileFormat();
                    writer.Write(files[i].Hash);
                    writer.Write(uint.MaxValue);
                    writer.Write(files[i].FileData.Length);
                    writer.Write(files[i].FileData.Length);
                    writer.Write(files[i].Alignment);
                    writer.Write(files[i].Unknown1);
                    writer.Write(files[i].Unknown2);
                    writer.Write(files[i].Unknown3);
                    writer.WriteString(files[i].FileName, 0x20);
                }

                //The data gets ordered by largest alignment size to lowest
                //Then by the file name
                var filesSorted = files.OrderByDescending(x => x.Alignment)
                                  .ThenBy(x => x.FileName)
                                  .ToList();

                writer.Align((int)files.Max(x => x.Alignment));

                long pos = writer.Position;

                for (int i = 0; i < files.Count; i++)
                {
                    var file  = filesSorted[i];
                    int index = files.IndexOf(file);

                    long dataPos = writer.Position;
                    writer.WriteUint32Offset((fileInfoPos + 4) + index * 64);
                    writer.Write(file.FileData);
                    writer.AlignBytes((int)file.Alignment);
                    long dataEndPos = writer.Position;

                    using (writer.TemporarySeek((fileInfoPos + 12) + index * 64, SeekOrigin.Begin)) {
                        writer.Write((uint)(dataEndPos - dataPos));
                    }
                }

                long endPos   = writer.Position;
                uint dataSize = (uint)(endPos - pos);

                using (writer.TemporarySeek(0x14, SeekOrigin.Begin)) {
                    writer.Write(dataSize);
                }

                //Idk what this format is doing but there's tons of padding at the end and idk why :(
                //Even combining all the alignments it can still be too small
                writer.AlignBytes((int)files.Sum(x => x.Alignment));
            }
        private void Write(FileWriter writer)
        {
            OrderLists();

            writer.SetByteOrder(true);
            writer.Write(Version);
            writer.WriteString(InternalName, 0xB);
            writer.Write(new uint[21]); //reserve space for offsets

            List <Texture>        textures  = Textures.Values.ToList();
            List <Sampler>        samplers  = Samplers.Values.ToList();
            List <Material>       materials = Materials.Values.ToList();
            List <SceneGraphNode> nodes     = SceneGraphs.Values.ToList();
            List <ShapeBatch>     batches   = Batches.Values.ToList();

            //Save texture header
            writer.WriteUint32Offset(12);
            long texturePos = writer.Position;

            for (int i = 0; i < textures.Count; i++)
            {
                textures[i].Write(writer, this);
            }
            writer.Align(32);

            //Save texture data
            for (int i = 0; i < textures.Count; i++)
            {
                writer.WriteUint32Offset(texturePos + 8 + (i * hTextureSize), texturePos);
                writer.Write(textures[i].ImageData);
                writer.Align(32);
            }

            //Save samplers
            writer.WriteUint32Offset(16);
            for (int i = 0; i < samplers.Count; i++)
            {
                samplers[i].TextureIndex = (short)textures.IndexOf(samplers[i].Texture);
                samplers[i].Write(writer, this);
            }

            //Save vertices
            List <Vector3> positions = new List <Vector3>();
            List <Vector3> normals   = new List <Vector3>();
            List <Vector4> colors    = new List <Vector4>();
            List <Vector2> texcoords = new List <Vector2>();

            for (int i = 0; i < batches.Count; i++)
            {
                foreach (var packet in batches[i].Packets)
                {
                    for (int v = 0; v < packet.Vertices.Length; v++)
                    {
                        var     vert     = packet.Vertices[v];
                        Vector3 shortPos = new Vector3(
                            (short)vert.Position.X,
                            (short)vert.Position.Y,
                            (short)vert.Position.Z);

                        if (!positions.Contains(shortPos))
                        {
                            positions.Add(shortPos);
                        }
                        if (!normals.Contains(vert.Normal) && vert.Normal != null)
                        {
                            normals.Add(vert.Normal);
                        }
                        if (!texcoords.Contains(vert.Texcoord) && vert.Texcoord != null)
                        {
                            texcoords.Add(vert.Texcoord);
                        }
                        if (!colors.Contains(vert.Color0) && vert.Color0 != null)
                        {
                            colors.Add(vert.Color0);
                        }

                        vert.PositionIndex    = (short)positions.IndexOf(vert.Position);
                        vert.NormalIndex      = (short)normals.IndexOf(vert.Normal);
                        vert.TexCoordIndex[0] = (short)texcoords.IndexOf(vert.Texcoord);
                        vert.Color0Index      = (short)colors.IndexOf(vert.Color0);
                    }
                }
            }

            writer.WriteUint32Offset(20);
            for (int i = 0; i < positions.Count; i++)
            {
                writer.Write((short)positions[i].X);
                writer.Write((short)positions[i].Y);
                writer.Write((short)positions[i].Z);
            }
            writer.Align(32);

            if (normals.Count > 0)
            {
                writer.WriteUint32Offset(24);
                for (int i = 0; i < normals.Count; i++)
                {
                    writer.Write(normals[i].X);
                    writer.Write(normals[i].Y);
                    writer.Write(normals[i].Z);
                }
                writer.Align(32);
            }

            if (colors.Count > 0)
            {
                writer.WriteUint32Offset(28);
                for (int i = 0; i < colors.Count; i++)
                {
                    writer.Write((byte)(colors[i].X * 255));
                    writer.Write((byte)(colors[i].Y * 255));
                    writer.Write((byte)(colors[i].Z * 255));
                    writer.Write((byte)(colors[i].W * 255));
                }
                writer.Align(32);
            }

            if (texcoords.Count > 0)
            {
                writer.WriteUint32Offset(36);
                for (int i = 0; i < texcoords.Count; i++)
                {
                    writer.Write(texcoords[i].X);
                    writer.Write(texcoords[i].Y);
                }
                writer.Align(32);
            }

            writer.WriteUint32Offset(52);
            for (int i = 0; i < materials.Count; i++)
            {
                for (int j = 0; j < materials[i].Samplers.Count; j++)
                {
                    materials[i].SamplerIndices[j] = (short)samplers.IndexOf(materials[i].Samplers[j]);
                }

                materials[i].Write(writer, this);
            }

            long batchPos = writer.Position;

            writer.WriteUint32Offset(56);
            for (int i = 0; i < Batches.Count; i++)
            {
                Batches[i].Write(writer, this);
            }

            for (int i = 0; i < Batches.Count; i++)
            {
                writer.WriteUint32Offset(batchPos + 12 + (i * hShapeBatchSize), batchPos);

                long pos = writer.Position;
                for (int d = 0; d < Batches[i].Packets.Count; d++)
                {
                    Batches[i].Packets[d].Write(Batches[i], writer, this);
                }

                writer.Align(32);

                long endpos = writer.Position;
                using (writer.TemporarySeek(batchPos + 2 + (i * hShapeBatchSize), SeekOrigin.Begin)) {
                    writer.Write((ushort)((endpos - pos) / 0x20));
                }
            }

            long sceneGraphPos = writer.Position;

            writer.WriteUint32Offset(60);
            for (int i = 0; i < nodes.Count; i++)
            {
                nodes[i].Write(writer, this);
            }
            for (int i = 0; i < nodes.Count; i++)
            {
                writer.WriteUint32Offset(sceneGraphPos + 80 + (hSceneGraphSize * i), sceneGraphPos);
                for (int d = 0; d < nodes[i].DrawnParts.Count; d++)
                {
                    var part = nodes[i].DrawnParts[d];
                    part.MaterialIndex   = (short)materials.IndexOf(part.Material);
                    part.ShapeBatchIndex = (short)batches.IndexOf(part.Batch);
                    part.Write(writer, this);
                }
            }
            writer.AlignBytes(16);
        }
Beispiel #8
0
        void Write(FileWriter writer)
        {
            writer.SetByteOrder(true);
            writer.Write((ushort)Banks.Count);
            writer.Write((ushort)Patterns.Count);
            writer.Write((ushort)Textures.Count);
            writer.Write(NumReferences);
            writer.Write(0);
            writer.Write(0);
            writer.Write(0);

            if (Patterns.Count > 0)
            {
                long patternsPos = writer.Position;

                writer.WriteUint32Offset(0xC);
                for (int i = 0; i < Patterns.Count; i++)
                {
                    Patterns[i].Write(writer);
                }

                for (int i = 0; i < Patterns.Count; i++)
                {
                    if (Patterns[i].Layers.Count > 0)
                    {
                        writer.WriteUint32Offset(patternsPos + 0xC + (i * 0x10));
                        foreach (var layer in Patterns[i].Layers)
                        {
                            writer.WriteStruct(layer);
                        }
                    }
                }
            }
            if (Banks.Count > 0)
            {
                long banksPos = writer.Position;

                writer.WriteUint32Offset(0x8);
                for (int i = 0; i < Banks.Count; i++)
                {
                    Banks[i].Write(writer);
                }

                for (int i = 0; i < Banks.Count; i++)
                {
                    if (Banks[i].AnimFrames.Count > 0)
                    {
                        writer.WriteUint32Offset(banksPos + 4 + (i * 0x08));
                        foreach (var frame in Banks[i].AnimFrames)
                        {
                            writer.WriteStruct(frame);
                        }
                    }
                }
            }
            if (Textures.Count > 0)
            {
                writer.WriteUint32Offset(0x10);
                long texPos = writer.Position;
                for (int i = 0; i < Textures.Count; i++)
                {
                    writer.Write(Textures[i].Bpp);
                    writer.Write(Textures[i].Format);
                    if (Textures[i].PaletteData != null)
                    {
                        writer.Write((ushort)Textures[i].PaletteData.Length / 2);
                    }
                    else
                    {
                        writer.Write((ushort)0);
                    }
                    writer.Write(Textures[i].Width);
                    writer.Write(Textures[i].Height);
                    writer.Write(Textures[i].ImageData.Length);
                }

                writer.AlignBytes(32, 0x88);
                for (int i = 0; i < Textures.Count; i++)
                {
                    writer.WriteUint32Offset(texPos + 0x0C + (0x14 * i));
                    if (Textures[i].PaletteData != null)
                    {
                        writer.Write(Textures[i].PaletteData);
                    }

                    writer.WriteUint32Offset(texPos + 0x10 + (0x14 * i));
                    writer.Write(Textures[i].ImageData);
                }
            }
        }
Beispiel #9
0
        public void Write(FileWriter writer, FFNT Header)
        {
            Header.BlockCounter += 1;

            long pos = writer.Position;

            writer.WriteSignature("CMAP");
            writer.Write(uint.MaxValue); //Section Size
            if (Header.Platform == FFNT.PlatformType.NX)
            {
                writer.Write((uint)CharacterCodeBegin);
                writer.Write((uint)CharacterCodeEnd);
            }
            else
            {
                writer.Write((ushort)CharacterCodeBegin);
                writer.Write((ushort)CharacterCodeEnd);
            }

            writer.Write(MappingMethod, true);
            writer.Seek(2);

            long DataPos = writer.Position;
            writer.Write(0); //Next Section Offset

            //Write the data
            switch (MappingMethod)
            {
                case Mapping.Direct:
                    writer.Write(((CMAPDirect)MappingData).Offset);
                    break;
                case Mapping.Table:
                    for (int i = 0; i < ((CMAPIndexTable)MappingData).Table.Length; i++)
                    {
                        writer.Write(((CMAPIndexTable)MappingData).Table[i]);
                    }
                    break;
                case Mapping.Scan:
                    writer.Write((ushort)((CMAPScanMapping)MappingData).Codes.Length);
                    if (Header.Platform == FFNT.PlatformType.NX)
                        writer.Seek(2); //Padding

                    for (int i = 0; i < ((CMAPScanMapping)MappingData).Codes.Length; i++)
                    {
                        if (Header.Platform == FFNT.PlatformType.NX)
                        {
                            writer.Write((uint)((CMAPScanMapping)MappingData).Codes[i]);
                            writer.Write(((CMAPScanMapping)MappingData).Indexes[i]);
                            writer.Write((ushort)0); //Padding
                        }
                        else
                        {
                            writer.Write((ushort)((CMAPScanMapping)MappingData).Codes[i]);
                            writer.Write(((CMAPScanMapping)MappingData).Indexes[i]);
                        }
                    }
                    break;
            }
            writer.AlignBytes(4); //Padding

            //Save section size
            long endPos = writer.Position;
            using (writer.TemporarySeek(pos + 4, SeekOrigin.Begin))
            {
                writer.Write((uint)(endPos - pos));
            }

            if (NextCodeMapSection != null)
            {
                writer.WriteUint32Offset(DataPos, -8);
                NextCodeMapSection.Write(writer, Header);
            }
        }