示例#1
0
        public ALRD(byte[] buffer) : base(buffer)
        {
            MemoryStream ms   = new MemoryStream(buffer);
            string       type = ms.ReadString(4);

            if (type != "ALRD")
            {
                throw new Exception("这不是ALRD,笨蛋");
            }
            vers    = ms.ReadWord();
            count   = ms.ReadWord();
            size    = ms.ReadWord();
            Headers = new List <Header>();
            for (int i = 0; i < count; i++)
            {
                Header header = new Header();
                header.Offset = ms.ReadWord();
                header.Type   = ms.ReadByte();
                int emptyLength = ms.ReadByte();
                int lengthEN    = ms.ReadByte();
                int lengthJP    = ms.ReadByte();
                header.NameEN = ms.ReadString(-1);
                header.NameJP = ms.ReadString(-1);
                ms.Align(4);
                ms.Seek(emptyLength, SeekOrigin.Current);
                ms.Align(4);
                Headers.Add(header);
            }
            ms.Close();
        }
示例#2
0
        public override byte[] Package(string path)
        {
            CreateFont("黑体", @"range.txt");
            MemoryStream ms = new MemoryStream();

            ms.Write(Encoding.ASCII.GetBytes("ALFT"), 0, 4);
            ms.WriteByte(Vers);
            ms.Write(Form, 0, 3);
            ms.WriteByte(BlockWidth);
            ms.WriteByte(BlockHeight);
            ms.WriteWord(Unknown1);
            ms.WriteWord(RangeCount);
            for (int i = 0; i < RangeCount; i++)
            {
                Range range = RangeList[i];
                ms.WriteWord(range.CharCodeMin);
                ms.WriteWord(range.CharCodeMax);
                ms.WriteWord(range.ImageOffset);
            }
            ms.WriteWord(WidthFieldCount);
            for (int i = 0; i < WidthFieldCount; i++)
            {
                ms.WriteByte(WidthList[i]);
            }
            ms.Align(4);
            byte[] ALIGByte = FontImage.Package(path);
            ms.Write(ALIGByte, 0, ALIGByte.Length);
            byte[] result = new byte[ms.Position];
            ms.Position = 0;
            ms.Read(result, 0, result.Length);
            return(result);
        }
示例#3
0
        private Entry parseTocEntry(MemoryStream ms, long basePosition)
        {
            Entry entry = new Entry();

            if (Vers == 2)
            {
                entry.Index    = ms.ReadWord();
                entry.Unknown1 = ms.ReadWord();
                entry.Address  = ms.ReadInt32();
                entry.Size     = ms.ReadInt32();
                entry.Unknown2 = BitConverter.GetBytes(ms.ReadInt32());
                long position = ms.Position;
                ms.Seek(basePosition + entry.Address - 0x22, SeekOrigin.Begin);
                entry.Name     = ms.ReadString(-1);
                ms.Position    = basePosition + entry.Address - 0x02;
                entry.Unknown3 = ms.ReadWord();
                ms.Position    = position;
            }
            else
            {
                entry.Index    = ms.ReadWord();
                entry.Unknown1 = ms.ReadWord();
                entry.Address  = ms.ReadInt32();
                entry.Size     = ms.ReadInt32();
                byte[] unk = new byte[6];
                ms.Read(unk, 0, unk.Length);
                entry.Unknown2 = unk;
                entry.Name     = ms.ReadString(-1);
                ms.Align(4);
            }
            return(entry);
        }
示例#4
0
        public ALAR(byte[] buffer) : base(buffer)
        {
            buffer = buffer.Skip(4).Take(buffer.Length - 4).ToArray();
            //初始化
            Files         = new List <Entry>();
            TocOffsetList = new List <ushort>();
            MemoryStream ms           = new MemoryStream(buffer);
            long         basePosition = -4;

            //开始
            Vers    = (byte)ms.ReadByte();
            Unknown = (byte)ms.ReadByte();
            if (Vers != 2 && Vers != 3)
            {
                throw new Exception("ALAR版本错误");
            }
            if (Vers == 2)
            {
                Count = ms.ReadWord();
                byte[] unk = new byte[0x10 - 0x08];
                ms.Read(unk, 0, unk.Length);
                UnknownBytes = unk;
            }
            if (Vers == 3)
            {
                Count    = ms.ReadWord(); //+0x06
                Unknown1 = ms.ReadWord(); //+0x08
                Unknown2 = ms.ReadWord(); //+0x0A
                byte[] unk = new byte[0x10 - 0x0C];
                ms.Read(unk, 0, unk.Length);
                UnknownBytes = unk;
                DataOffset   = ms.ReadWord();
                Console.WriteLine(DataOffset);
                for (int i = 0; i < Count; i++)
                {
                    TocOffsetList.Add(ms.ReadWord());
                }
                ms.Align(4);
            }
            for (int i = 0; i < Count; i++)
            {
                Entry entry    = parseTocEntry(ms, basePosition);
                long  position = ms.Position;
                //拿东西出来
                byte[] data = new byte[entry.Size];
                ms.Position = basePosition + entry.Address;
                ms.Read(data, 0, data.Length);
                entry.Content = data;
                ms.Position   = position;
                Files.Add(entry);
            }
            if (Vers == 2)
            {
                DataOffsetByData = Files[0].Address - 0x22;
            }
            if (Vers == 3)
            {
                DataOffsetByData = Files[0].Address;
            }
        }
        public void Align()
        {
            // Position 0 aligns to everything.
            _stream.Align(3);
            Assert.AreEqual(0, _stream.Position);
            Assert.AreEqual(0, _stream.Length);

            // Align but do not grow.
            _stream.Position++;
            _stream.Align(2);
            Assert.AreEqual(2, _stream.Position);
            Assert.AreEqual(0, _stream.Length);

            // Align and grow.
            _stream.Align(2, true);
            Assert.AreEqual(2, _stream.Position);
            Assert.AreEqual(2, _stream.Length);

            // Align again.
            _stream.Align(4);
            Assert.AreEqual(4, _stream.Position);
            Assert.AreEqual(2, _stream.Length);

            // Alignment must be bigger than 0.
            Assert.ThrowsException <ArgumentOutOfRangeException>(() => _stream.Align(0));
            Assert.ThrowsException <ArgumentOutOfRangeException>(() => _stream.Align(-1));
        }
示例#6
0
        /// <summary>
        /// Writes a <code>Schema.Gltf</code> model to a writable binary writer and pack all data into the model
        /// </summary>
        /// <param name="model"><code>Schema.Gltf</code> model</param>
        /// <param name="binaryWriter">Binary Writer</param>
        /// <param name="gltfFilePath">Source file path used to load the model</param>
        /// <param name="glbBinChunck">optional GLB-stored Buffer (BIN data file). If null, then the first buffer Uri must point to a BIN file.</param>
        public static void SaveBinaryModelPacked(this Gltf model, BinaryWriter binaryWriter, string gltfFilePath, byte[] glbBinChunck = null)
        {
            if (model == null)
            {
                throw new ArgumentNullException(nameof(model));
            }

            byte[] binBufferData = null;

            using (var memoryStream = new MemoryStream())
            {
                var bufferViews = new List <BufferView>();
                var bufferData  = new Dictionary <int, byte[]>();

                if (model.BufferViews != null)
                {
                    foreach (var bufferView in model.BufferViews)
                    {
                        memoryStream.Align(4);

                        var byteOffset = memoryStream.Position;

                        if (!bufferData.TryGetValue(bufferView.Buffer, out byte[] data))
示例#7
0
        public ALFT(byte[] buffer) : base(buffer)
        {
            RangeList = new List <Range>();
            WidthList = new List <byte>();

            buffer = buffer.Skip(4).Take(buffer.Length - 4).ToArray();
            MemoryStream ms = new MemoryStream(buffer);

            Vers = (byte)ms.ReadByte();
            Form = new byte[3];
            ms.Read(Form, 0, 3);
            BlockWidth  = (byte)ms.ReadByte();
            BlockHeight = (byte)ms.ReadByte();
            Unknown1    = ms.ReadWord();
            RangeCount  = ms.ReadWord();
            for (int i = 0; i < RangeCount; i++)
            {
                Range range = new Range();
                range.CharCodeMin = ms.ReadWord();
                range.CharCodeMax = ms.ReadWord();
                range.ImageOffset = ms.ReadWord();
                RangeList.Add(range);
            }
            WidthFieldCount = ms.ReadWord();
            Console.WriteLine(WidthFieldCount);
            for (int i = 0; i < WidthFieldCount; i++)
            {
                WidthList.Add((byte)ms.ReadByte());
            }
            ms.Align(4);
            byte[] ALIGByte = new byte[ms.Length - ms.Position];
            ms.Read(ALIGByte, 0, ALIGByte.Length);
            int CharCount = RangeList[RangeList.Count - 1].ImageOffset + (RangeList[RangeList.Count - 1].CharCodeMax - RangeList[RangeList.Count - 1].CharCodeMin) + 1;

            //处理ALIG
            FontImage = new ALIG(ALIGByte);
        }
示例#8
0
        public void Align()
        {
            using (MemoryStream stream = new MemoryStream())
            {
                stream.Position = 13;
                Assert.AreEqual(16, stream.Align(4));

                stream.Position = 13;
                Assert.AreEqual(12, stream.Align(-4));

                stream.Position = 13;
                Assert.AreEqual(13, stream.Align(1));

                stream.Position = 12;
                Assert.AreEqual(12, stream.Align(4));

                stream.Position = 12;
                Assert.AreEqual(12, stream.Align(-4));

                stream.Position = 12;
                Assert.ThrowsException <ArgumentOutOfRangeException>(() => stream.Align(0));
            }
        }
示例#9
0
        /// <summary>
        /// Writes a <code>Schema.Gltf</code> model to a writable binary writer and pack all data into the model
        /// </summary>
        /// <param name="model"><code>Schema.Gltf</code> model</param>
        /// <param name="binaryWriter">Binary Writer</param>
        /// <param name="gltfFilePath">Source file path used to load the model</param>
        /// <param name="glbBinChunck">optional GLB-stored Buffer (BIN data file). If null, then the first buffer Uri must point to a BIN file.</param>
        public static void SaveBinaryModelPacked(this Gltf model, BinaryWriter binaryWriter, string gltfFilePath, byte[] glbBinChunck = null)
        {
            if (model == null)
            {
                throw new ArgumentNullException(nameof(model));
            }

            byte[] binBufferData = null;

            using (var memoryStream = new MemoryStream())
            {
                var bufferViews = new List <BufferView>();
                var bufferData  = new Dictionary <int, byte[]>();

                if (model.BufferViews != null)
                {
                    foreach (var bufferView in model.BufferViews)
                    {
                        memoryStream.Align(4);

                        var byteOffset = memoryStream.Position;

                        byte[] data;
                        if (!bufferData.TryGetValue(bufferView.Buffer, out data))
                        {
                            // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#glb-stored-buffer
                            /// "glTF Buffer referring to GLB-stored BIN chunk, must have buffer.uri
                            /// property undefined, and it must be the first element of buffers array"
                            data = bufferView.Buffer == 0 && glbBinChunck != null
                                        ? glbBinChunck
                                        : model.LoadBinaryBuffer(bufferView.Buffer, gltfFilePath, bufferView.ByteOffset);

                            bufferData.Add(bufferView.Buffer, data);
                        }

                        memoryStream.Write(data, bufferView.ByteOffset, bufferView.ByteLength);

                        bufferView.Buffer     = 0;
                        bufferView.ByteOffset = (int)byteOffset;
                        bufferViews.Add(bufferView);
                    }
                }

                if (model.Images != null)
                {
                    for (var index = 0; index < model.Images.Length; index++)
                    {
                        var byteOffset = memoryStream.Position;

                        var data = model.OpenImageFile(index, gltfFilePath);
                        data.CopyTo(memoryStream);

                        var image = model.Images[index];
                        image.BufferView = bufferViews.Count;
                        image.MimeType   = GetMimeType(image.Uri);
                        image.Uri        = null;

                        bufferViews.Add(new BufferView
                        {
                            Buffer     = 0,
                            ByteOffset = (int)byteOffset,
                            ByteLength = (int)data.Length,
                        });
                    }
                }

                if (bufferViews.Any())
                {
                    model.BufferViews = bufferViews.ToArray();

                    model.Buffers = new[]
                    {
                        new glTFLoader.Schema.Buffer
                        {
                            ByteLength = (int)memoryStream.Length
                        }
                    };

                    binBufferData = memoryStream.ToArray();
                }
            }

            Interface.SaveBinaryModel(model, binBufferData, binaryWriter);
        }
        public static void Pack(string path)
        {
            var inputFilePath      = path;
            var inputDirectoryPath = Path.GetDirectoryName(inputFilePath);
            var inputFileName      = Path.GetFileNameWithoutExtension(inputFilePath);

            var model = Interface.LoadModel(inputFilePath);

            byte[] binBufferData = null;

            using (var memoryStream = new MemoryStream())
            {
                var bufferViews = new List <BufferView>();
                var bufferData  = new Dictionary <int, byte[]>();

                if (model.BufferViews != null)
                {
                    foreach (var bufferView in model.BufferViews)
                    {
                        memoryStream.Align(4);

                        var byteOffset = memoryStream.Position;

                        byte[] data;
                        if (!bufferData.TryGetValue(bufferView.Buffer, out data))
                        {
                            data = model.LoadBinaryBuffer(bufferView.Buffer, inputFilePath);
                            bufferData.Add(bufferView.Buffer, data);
                        }

                        memoryStream.Write(data, bufferView.ByteOffset, bufferView.ByteLength);

                        bufferView.Buffer     = 0;
                        bufferView.ByteOffset = (int)byteOffset;
                        bufferViews.Add(bufferView);
                    }
                }

                if (model.Images != null)
                {
                    for (var index = 0; index < model.Images.Length; index++)
                    {
                        if (model.Images[index].Extras != null && model.Images[index].Extras["embed"] != null)
                        {
                            //var jsonSerializer = Newtonsoft.Json.JsonSerializer.Create();
                            bool embedTexture = (bool)model.Images[index].Extras["embed"];
                            if (!embedTexture)
                            {
                                continue;
                            }
                        }

                        var byteOffset = memoryStream.Position;

                        var data = model.OpenImageFile(index, inputFilePath);
                        data.CopyTo(memoryStream);

                        var image = model.Images[index];
                        image.BufferView = bufferViews.Count;
                        image.MimeType   = GetMimeType(image.Uri);
                        image.Uri        = null;

                        bufferViews.Add(new BufferView
                        {
                            Buffer     = 0,
                            ByteOffset = (int)byteOffset,
                            ByteLength = (int)data.Length,
                        });
                    }
                }

                if (bufferViews.Any())
                {
                    model.BufferViews = bufferViews.ToArray();

                    model.Buffers = new[]
                    {
                        new glTFLoader.Schema.Buffer
                        {
                            ByteLength = (int)memoryStream.Length
                        }
                    };

                    binBufferData = memoryStream.ToArray();
                }
            }

            var outputFilePath = GetUniqueFilePath(inputDirectoryPath, inputFileName, ".glb");

            Console.WriteLine("Saving binary to: " + outputFilePath);
            Interface.SaveBinaryModel(model, binBufferData, outputFilePath);
            //SelectFileInExplorer(outputFilePath, true);
        }
示例#11
0
        public StaticMesh(Stream s)
        {
            s.Align(4);

            s.Align(8);

            Header = s.ReadStruct <StaticMeshHeader>();

            // Read texture names
            int textureNameSize = s.ReadInt32();

            s.Align(16);

            s.ReadByte();

            byte[] textureNameData = new byte[textureNameSize];
            s.Read(textureNameData, 0, textureNameSize);
            MemoryStream textureNameStream = new MemoryStream(textureNameData);

            while (textureNameStream.Position < textureNameData.Length)
            {
                textureNameStream.Align(2);

                int    position    = (int)textureNameStream.Position;
                string textureName = textureNameStream.ReadAsciiNullTerminatedString();
                byte   paddingByte = textureNameStream.ReadUInt8();

                TextureNames.Add(textureName, position);

                if (paddingByte != 0)
                {
                    throw new Exception();
                }

                textureNameStream.Align(2);
            }

            if (Header.Version < 0x2A)
            {
                Header.NumSubmeshVIDs = (ushort)Header.NumLogicalSubmeshes;
            }

            if (Header.NumNavpoints > 0)
            {
                s.Align(16);

                for (int i = 0; i < Header.NumNavpoints; i++)
                {
                    StaticMeshNavpoint navpoint = s.ReadStruct <StaticMeshNavpoint>();
                    Navpoints.Add(navpoint);
                }
            }

            if (Header.NumCSpheres > 0)
            {
                s.Align(16);

                for (int i = 0; i < Header.NumCSpheres; i++)
                {
                    CMeshCSphere cmeshCSphere = s.ReadStruct <CMeshCSphere>();
                    CSpheres.Add(cmeshCSphere);
                }
            }

            if (Header.NumCCylinders > 0)
            {
                s.Align(16);

                for (int i = 0; i < Header.NumCCylinders; i++)
                {
                    CMeshCCylinder cylinder = s.ReadStruct <CMeshCCylinder>();
                    CCylinders.Add(cylinder);
                }
            }

            if (Header.NumRigBones > 0)
            {
                s.Align(16);

                for (int i = 0; i < Header.NumRigBones; i++)
                {
                    UInt32 rigBone = s.ReadUInt32();
                    RigBones.Add(rigBone);
                }
            }

            s.Align(8);

            long originalOffset = s.Position;

            MeshVersion = s.ReadUInt16();

            s.Align(4);

            MeshGpuDataCrc  = s.ReadUInt32();
            MeshCpuDataSize = s.ReadUInt32();

            MiscData = new byte[(originalOffset + MeshCpuDataSize) - s.Position];
            s.Read(MiscData, 0, MiscData.Length);

            if (Header.NumMaterialMaps > 0)
            {
                s.Align(8);

                // Skip pointer tables?
                s.Seek(8 * Header.NumMaterialMaps, SeekOrigin.Current);

                MaterialMapCrcs = new uint[Header.NumMaterialMaps];
                for (int i = 0; i < Header.NumMaterialMaps; i++)
                {
                    MaterialMapCrcs[i] = s.ReadUInt32();
                }
            }

            if (Header.NumMaterials > 0)
            {
                s.Align(8);

                // Skip more pointers
                s.Seek(8 * Header.NumMaterials, SeekOrigin.Current);

                for (int i = 0; i < Header.NumMaterials; i++)
                {
                    StaticMeshMaterial material = new StaticMeshMaterial();
                    Materials.Add(material);

                    long materialStart = s.Position;

                    material.DataSize = s.ReadUInt32();

                    s.Align(8);

                    material.Data = s.ReadStruct <RenderLibMaterialData>();

                    s.Align(4);

                    for (int j = 0; j < material.Data.NumTextures; j++)
                    {
                        RenderLibMaterialTextureDesc textureDesc = s.ReadStruct <RenderLibMaterialTextureDesc>();
                        material.TextureDescriptions.Add(textureDesc);
                    }

                    s.Align(4);

                    for (int j = 0; j < material.Data.NumConstants; j++)
                    {
                        uint constantNameChecksum = s.ReadUInt32();
                        material.NameChecksums.Add(constantNameChecksum);
                    }

                    s.Align(16);

                    for (int j = 0; j < material.Data.NumConstants; j++)
                    {
                        RenderLibMaterialConstants constant = s.ReadStruct <RenderLibMaterialConstants>();
                        material.Constants.Add(constant);
                    }

                    uint materialSize = (uint)(s.Position - materialStart);
                    if (materialSize != material.DataSize)
                    {
                        throw new Exception(String.Format("materialSize != material.DataSize - {0} != {1}", materialSize, material.DataSize));
                    }

                    if (material.Data.NumTextures > 0)
                    {
                        for (int j = 0; j < material.Data.NumTextures; j++)
                        {
                            RenderLibMaterialTextureDesc textureDesc = material.TextureDescriptions[j];
                            textureNameStream.Seek(textureDesc.TextureHandle, SeekOrigin.Begin);
                            string textureName = textureNameStream.ReadAsciiNullTerminatedString();
                            material.TextureNames.Add(textureName);
                        }
                    }
                }
            }

            MaterialMapData = new byte[s.Length - s.Position];
            s.Read(MaterialMapData, 0, MaterialMapData.Length);
        }
示例#12
0
        public void Save(Stream s)
        {
            s.Align(4);

            s.Align(8);

            Header.NumNavpoints = (short)Navpoints.Count;
            Header.NumRigBones  = (short)RigBones.Count;
            // Header.NumMaterials
            // Header.NumMaterialMaps
            // Header.NumLODsPerSubmesh
            // Header.NumSubmeshVIDs
            Header.NumCSpheres   = (ushort)CSpheres.Count;
            Header.NumCCylinders = (ushort)CCylinders.Count;
            // NumLogicalSubmeshes

            s.WriteStruct(Header);

            using (MemoryStream textureNameStream = new MemoryStream())
            {
                string[] textureNames = new string[TextureNames.Count];
                TextureNames.Keys.CopyTo(textureNames, 0);
                foreach (var textureName in textureNames)
                {
                    textureNameStream.Align(2);
                    TextureNames[textureName] = (int)textureNameStream.Position;
                    textureNameStream.WriteAsciiNullTerminatedString(textureName);
                    textureNameStream.WriteUInt8(0); // padding byte?
                    textureNameStream.Align(2);
                }

                s.WriteInt32((int)textureNameStream.Length);
                s.Align(16);
                s.WriteUInt8(0);
                textureNameStream.Seek(0, SeekOrigin.Begin);
                textureNameStream.CopyTo(s);
            }

            if (Header.NumNavpoints > 0)
            {
                s.Align(16);

                foreach (StaticMeshNavpoint navpoint in Navpoints)
                {
                    s.WriteStruct(navpoint);
                }
            }

            if (Header.NumCSpheres > 0)
            {
                s.Align(16);

                foreach (CMeshCSphere csphere in CSpheres)
                {
                    s.WriteStruct(csphere);
                }
            }

            if (Header.NumCCylinders > 0)
            {
                s.Align(16);

                foreach (CMeshCCylinder ccylinder in CCylinders)
                {
                    s.WriteStruct(ccylinder);
                }
            }

            if (Header.NumRigBones > 0)
            {
                s.Align(16);

                foreach (uint rigBone in RigBones)
                {
                    s.WriteUInt32(rigBone);
                }
            }

            s.Align(8);

            s.WriteUInt16(MeshVersion);

            s.Align(4);
            s.WriteUInt32(MeshGpuDataCrc);
            s.WriteUInt32(MeshCpuDataSize);

            s.Write(MiscData, 0, MiscData.Length);

            if (Header.NumMaterialMaps > 0)
            {
                s.Align(8);

                // Skip pointer tables?
                s.Seek(8 * Header.NumMaterialMaps, SeekOrigin.Current);

                for (int i = 0; i < Header.NumMaterialMaps; i++)
                {
                    s.WriteUInt32(MaterialMapCrcs[i]);
                }
            }

            if (Header.NumMaterials > 0)
            {
                s.Align(8);

                // Skip more pointers
                s.Seek(8 * Header.NumMaterials, SeekOrigin.Current);

                for (int i = 0; i < Header.NumMaterials; i++)
                {
                    StaticMeshMaterial material = Materials[i];
                    s.WriteUInt32(material.DataSize);

                    s.Align(8);
                    s.WriteStruct(material.Data);

                    for (int j = 0; j < material.Data.NumTextures; j++)
                    {
                        string textureName = material.TextureNames[j];
                        RenderLibMaterialTextureDesc textureDesc = material.TextureDescriptions[j];
                        int textureNameOffset = TextureNames[textureName];
                        textureDesc.TextureHandle = textureNameOffset;

                        s.WriteStruct(textureDesc);
                    }

                    for (int j = 0; j < material.Data.NumConstants; j++)
                    {
                        uint constantNameChecksum = material.NameChecksums[j];
                        s.WriteUInt32(constantNameChecksum);
                    }

                    s.Align(16);

                    for (int j = 0; j < material.Data.NumConstants; j++)
                    {
                        RenderLibMaterialConstants constant = material.Constants[j];
                        s.WriteStruct(constant);
                    }
                }
            }

            s.Write(MaterialMapData, 0, MaterialMapData.Length);
        }
示例#13
0
        public override byte[] Package(string path)
        {
            if (!Directory.Exists(Path.Combine(Path.GetDirectoryName(path), Path.GetFileNameWithoutExtension(path))))
            {
                return(RawBuffer);
            }
            //ALAR的package
            //ALAR文件分为三部分,头、索引、主体。
            //这里换个方法吧。把源文件的所有东西都读出来,然后在不依赖源文件的基础上,写新文件出来。美滋滋不是么(直接filestream写,强无敌

            //处理新的入口和乱七八糟的东西
            for (int i = 0; i < Files.Count; i++)
            {
                Entry  entry    = Files[i];
                string filePath = Path.Combine(
                    Path.GetDirectoryName(path),
                    Path.GetFileNameWithoutExtension(path),
                    entry.Name
                    );
                byte[] newContent = entry.ParsedContent.Package(filePath);
                entry.Content = newContent;
                entry.Size    = newContent.Length;
            }

            MemoryStream ms = new MemoryStream();

            ms.Write(Encoding.ASCII.GetBytes("ALAR"), 0, 4);
            ms.WriteByte(Vers);
            ms.WriteByte(Unknown);
            if (Vers == 2)
            {
                ms.WriteWord(Count);
                ms.Write(UnknownBytes, 0, UnknownBytes.Length);
            }
            if (Vers == 3)
            {
                ms.WriteWord(Count);
                ms.WriteWord(Unknown1);
                ms.WriteWord(Unknown2);
                ms.Write(UnknownBytes, 0, UnknownBytes.Length);
                ms.WriteWord(DataOffset);
                for (int i = 0; i < Count; i++)
                {
                    ms.WriteWord(TocOffsetList[i]);
                }
                ms.Align(4);
            }
            List <int> offsetAddressList = new List <int>();

            for (int i = 0; i < Count; i++)
            {
                Entry entry = Files[i];
                //一边写Entry一边写内容,要写address的地方,空出来。
                if (Vers == 2)
                {
                    //名字写在文件前面的,固定长度16字节
                    ms.WriteWord(entry.Index);                              //0x00
                    ms.WriteWord(entry.Unknown1);                           //0x02
                    offsetAddressList.Add((int)ms.Position);
                    ms.WriteInt32(0);                                       //0x04
                    ms.WriteInt32(entry.Size);                              //0x08
                    ms.Write(entry.Unknown2, 0, entry.Unknown2.Length);     //0x0C
                }
                if (Vers == 3)
                {
                    //名字写在Entry里
                    ms.WriteWord(entry.Index);
                    ms.WriteWord(entry.Unknown1);
                    offsetAddressList.Add((int)ms.Position);
                    ms.WriteInt32(0);
                    ms.WriteInt32(entry.Size);
                    ms.Write(entry.Unknown2, 0, entry.Unknown2.Length);
                    ms.WriteString(entry.Name, 0);
                    ms.Align(4);
                }
            }
            if (Vers == 2)
            {
                ms.WriteWord(0);
            }
            //接下来写内容,写内容的时候把address写到相应位置去
            for (int i = 0; i < Count; i++)
            {
                Entry entry = Files[i];
                if (Vers == 2)
                {
                    //这边还要写名字进去,蛋疼
                    ms.WriteString(entry.Name, 0x20);
                    ms.WriteWord(entry.Unknown3);
                }
                int position = (int)ms.Position;
                ms.Position = offsetAddressList[i];
                ms.WriteInt32(position);
                ms.Position = position;
                ms.Write(entry.Content, 0, entry.Content.Length);
                if (i == Count - 1)
                {
                    continue;
                }
                ms.Align(4);
                if (Vers == 2)
                {
                    ms.WriteWord(0);
                }
            }
            int length = (int)ms.Position;

            byte[] result = new byte[length];
            ms.Position = 0;
            ms.Read(result, 0, length);
            return(result);
        }
示例#14
0
        public byte[] CreateNewALTBFileWithStringField(string[] strings)
        {
            byte[] newStringFieldBytes = GenerateStringFieldBytes(strings.ToArray());
            Dictionary <long, string> newStringDictionary = GetStringDictionary(newStringFieldBytes);

            if (stringDictionary.Count != newStringDictionary.Count)
            {
                throw new Exception("长度错误");
            }

            //创建StringField的Offset变化表
            List <long> oldOffsets = new List <long>();
            List <long> newOffsets = new List <long>();

            foreach (long offset in stringDictionary.Keys)
            {
                oldOffsets.Add(offset);
            }
            foreach (long offset in newStringDictionary.Keys)
            {
                newOffsets.Add(offset);
            }
            Dictionary <long, long> offsetChangeDictionary = new Dictionary <long, long>();

            for (int i = 0; i < oldOffsets.Count; i++)
            {
                offsetChangeDictionary.Add(oldOffsets[i], newOffsets[i]);
            }

            //按照字典修改Filed部分所有type为"0x20"的值
            MemoryStream ms = new MemoryStream(rowBuffer);

            ms.Position = tableEntry;
            for (int i = 0; i < count; i++)
            {
                long rowEntry = ms.Position;
                foreach (ALRD.Header header in headers)
                {
                    ms.Position = rowEntry + header.Offset;
                    if (header.Type == 0x20)
                    {
                        long offset = ms.ReadInt32();
                        ms.Seek(-4, SeekOrigin.Current);
                        if (offsetChangeDictionary.ContainsKey(offset))
                        {
                            ms.Write(BitConverter.GetBytes((int)offsetChangeDictionary[offset]), 0, 4);
                        }
                        else
                        {
                            throw new Exception("没有该offset");
                        }
                    }
                }
                ms.Position = rowEntry + size;
            }
            //把strings块的大小写入相应位置
            ms.Position = stringsSizePosition;
            ms.Write(BitConverter.GetBytes(newStringFieldBytes.Length), 0, 4);
            //制作新strings块
            //首先对齐
            int alignLength = newStringFieldBytes.Length + (4 - newStringFieldBytes.Length % 4);

            if (namesStart != -1)
            {
                //计算新name块的位置
                //nameStart - stringStart = oldStringLengthWithAlign
                //alignLength - oldStringLengthWithAlign = delta
                //nameStart + delta = newNameStart
                //写入buffer
                int newNameStart = namesStart + (alignLength - (namesStart - stringsStart)) + 4;
                ms.Position = namesOffset;
                ms.Write(BitConverter.GetBytes(newNameStart), 0, 4);
            }
            //准备搬运
            //先把最头的部分拿出来
            byte[] literal = rowBuffer.Take(stringsStart).ToArray();
            //然后制作新的带Align的Strings块
            byte[] alignedStrings = new byte[alignLength];
            newStringFieldBytes.CopyTo(alignedStrings, 0);
            //最后拿出尾巴
            ms.Position = stringsStart + stringsSize;
            ms.Align(4);
            byte[] tail = new byte[ms.Length - ms.Position];
            ms.Read(tail, 0, tail.Length);

            //声明最终Byte的List
            List <byte> result = new List <byte>();

            //开始搬运
            result.AddRange(Encoding.ASCII.GetBytes("ALTB"));
            result.AddRange(literal);
            result.AddRange(alignedStrings);
            result.AddRange(tail);
            ms.Close();
            return(result.ToArray());
        }