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(); }
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); }
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); }
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)); }
/// <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))
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); }
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)); } }
/// <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); }
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); }
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); }
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); }
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()); }