internal override void Write(BinaryWriter writer) { // Save the start position to calculate the filesize and // to write out the header after we know where all the structure offsets are Stream stream = writer.BaseStream; int posFileStart = (int)stream.Position; stream.Seek(Spr4Header.SIZE, SeekOrigin.Current); // Create initial header and tables Spr4Header header = new Spr4Header(TextureCount, KeyFrameCount); TypePointerTable[] keyFramePointerTable = new TypePointerTable[header.numKeyFrames]; TypePointerTable[] texturePointerTable = new TypePointerTable[header.numTextures]; // Set the pointer table offsets and seek past the entries // as the entries will be written later header.texturePointerTableOffset = (int)(stream.Position - posFileStart); stream.Seek(TypePointerTable.SIZE * header.numTextures, SeekOrigin.Current); header.keyFramePointerTableOffset = (int)(stream.Position - posFileStart); stream.Seek(TypePointerTable.SIZE * header.numKeyFrames, SeekOrigin.Current); // Write out the keyframe data and fill up the pointer table for (int i = 0; i < header.numKeyFrames; i++) { writer.AlignPosition(16); keyFramePointerTable[i].offset = (int)(stream.Position - posFileStart); mKeyFrames[i].Write(writer); } writer.Seek(16, SeekOrigin.Current); writer.AlignPosition(16); // Write out the texture data and fill up the pointer table for (int i = 0; i < header.numTextures; i++) { texturePointerTable[i].offset = (int)(stream.Position - posFileStart); mTextures[i].Write(writer); writer.Seek(16, SeekOrigin.Current); } // Save the end position long posFileEnd = stream.Position; // Seek back to the tables and write out the tables stream.Seek(posFileStart + header.texturePointerTableOffset, SeekOrigin.Begin); stream.WriteStructures(texturePointerTable, header.numTextures); stream.Seek(posFileStart + header.keyFramePointerTableOffset, SeekOrigin.Begin); stream.WriteStructures(keyFramePointerTable, header.numKeyFrames); // Seek back to the file and write out the header with // the offsets to the structures in the file writer.BaseStream.Seek(posFileStart, SeekOrigin.Begin); writer.BaseStream.WriteStructure(header); // Set the file pointer back to the end of the file as expected writer.BaseStream.Seek(posFileEnd, SeekOrigin.Begin); }
public byte[] Repack(string baseDir, string lbName, string srcDir, string patchDir, List <SubItem> subItems) { byte[] dst; this.Load(IOHelper.PathCombine(srcDir, lbName)); using (MemoryStream dstStream = new MemoryStream()) { using (BinaryWriter bw = new BinaryWriter(dstStream)) { bw.Seek(0, SeekOrigin.Begin); for (int i = 0; i < subItems.Count; i++) { SubItem vItem = subItems[i]; byte[] vDataBytes; if (File.Exists(IOHelper.PathCombine(patchDir, baseDir, vItem.FileName))) { //如果存在补丁文件,从补丁目录读取并压缩数据 vDataBytes = File.ReadAllBytes(IOHelper.PathCombine(patchDir, baseDir, vItem.FileName)); } else { //如果不存在补丁文件,从原始目录读取 vDataBytes = File.ReadAllBytes(IOHelper.PathCombine(srcDir, baseDir, vItem.FileName)); } if ((vItem.NeedReCompress == true) && (vItem.IsCompressed == true)) { byte[] compressDataBytes; int compressLenght = 0; LBC.Compress(vDataBytes, out compressDataBytes, out compressLenght); bw.Write((int)vItem.FileID); bw.Write((int)compressLenght + 0x10); bw.Write((uint)vItem.ExtMagic); bw.Write((int)vDataBytes.Length); bw.Write(compressDataBytes); bw.AlignPosition(0x40); } else if ((vItem.NeedReCompress == false) && (vItem.IsCompressed == true)) { bw.Write(vDataBytes); bw.AlignPosition(0x40); } else { bw.Write(vDataBytes); bw.AlignPosition(0x40); } } bw.Write((int)0xff); bw.Write((int)0x10); bw.Write((uint)0x30444e45); bw.Write((int)0); bw.Write(Enumerable.Repeat((byte)0, 0x30).ToArray()); dst = dstStream.ToArray(); } } return(dst); }
internal override void Write(BinaryWriter writer) { // Save the position of the file in the stream long posFileStart = writer.GetPosition(); // Precalculate the first offset long posPrevDataEnd = (Entries.Count) * BvpEntry.SIZE; // Write the entry table for (int i = 0; i < Entries.Count; i++) { // The offset is the position where the last data write ended, aligned to the 16 byte boundary Entries[i].FileDataOffset = (int)AlignmentHelper.Align(posPrevDataEnd, 16); // Write table entry Entries[i].WriteEntryHeader(writer); // Write data at offset writer.Write(Entries[i].Data, posFileStart + Entries[i].FileDataOffset); // Update the previous data end position posPrevDataEnd = Entries[i].FileDataOffset + Entries[i].DataLength; } // Seek to the last data write position, and align the file to 64 bytes writer.BaseStream.Seek(posPrevDataEnd, SeekOrigin.Begin); writer.AlignPosition(32); }
// Methods internal void InternalWrite(BinaryWriter writer) { int size = GetSize(); writer.Write(size); writer.Write(mNumAssignedFrames); writer.Write(mType); for (int i = 0; i < mNumAssignedFrames; i++) { writer.Write(mAssignedFrameIndices[i]); } writer.AlignPosition(4); for (int i = 0; i < mNumAssignedFrames; i++) { switch (mType) { case 0x04: { for (int j = 0; j < 2; j++) { writer.Write((ushort)(mBoneKeyData[i][j] * FIXED_POINT)); } } break; case 0x08: { for (int j = 0; j < 4; j++) { writer.Write((ushort)(mBoneKeyData[i][j] * FIXED_POINT)); } } break; case 0x0C: { for (int j = 0; j < 3; j++) { writer.Write(mBoneKeyData[i][j]); } } break; default: break; } } }
internal void InternalWrite(BinaryWriter writer) { writer.WriteStructure(mHeader); for (int i = 0; i < mHeader.entryCount; i++) { mSubEntries[i].InternalWrite(writer); } writer.AlignPosition(16); for (int i = 0; i < mHeader.entryCount; i++) { if (i > 1 && mSubEntries[i].Flags.HasFlagUnchecked(RecordFlags.DirectoryRecord)) { mSubEntries[i].DirectoryListing.InternalWrite(writer); } } }
// Internal Methods internal override void Write(BinaryWriter writer) { int posFileStart = (int)writer.BaseStream.Position; // Seek past chunk header writer.BaseStream.Seek(HEADER_SIZE + 4, SeekOrigin.Current); // Seek past texture pack header writer.BaseStream.Seek(TextureCount * sizeof(int), SeekOrigin.Current); int[] texturePointerTable = new int[TextureCount]; // Write texture data for (int i = 0; i < TextureCount; i++) { writer.AlignPosition(64); texturePointerTable[i] = (int)(writer.BaseStream.Position - posFileStart); mTextures[i].Write(writer); } // Calculate length long posFileEnd = writer.BaseStream.Position; int length = (int)(posFileEnd - posFileStart); // Write header writer.BaseStream.Seek(posFileStart, SeekOrigin.Begin); writer.Write(FLAG); writer.Write((short)0); // userID writer.Write(length); writer.WriteCString(TAG, 4); writer.Write(0); writer.Write(TextureCount); // Write pointer table writer.Write(texturePointerTable); // Seek to end writer.BaseStream.Seek(posFileEnd, SeekOrigin.Begin); }
public static void WriteCStringAligned(this BinaryWriter writer, string value) { writer.Write(_sjisEncoding.GetBytes(value)); writer.AlignPosition(4); }
// Methods internal override void Write(BinaryWriter writer) { // Skip header long posFileStart = (int)writer.BaseStream.Position; writer.Seek(MT00Header.SIZE, SeekOrigin.Current); MT00Header header = new MT00Header(AnimationCount, KeyCount); // Create address list for reloc table List <int> addressList = new List <int>(); // Calculate size of key info table & anim pointer table offset int keyInfoTableSize = header.numKeys * AbKeyInfo.SIZE; header.animPointerTableOffset = (int)(((writer.GetPosition() + keyInfoTableSize) - DATA_START_ADDRESS) - posFileStart); addressList.Add((int)(writer.GetPosition() - 4 - posFileStart)); // animPointerTableOffset // Write key info for (int i = 0; i < mAnimKeyInfo.Length; i++) { writer.Write((ushort)mAnimKeyInfo[i].KeyType); writer.Write(mAnimKeyInfo[i].UnkMorph); writer.Write(mAnimKeyInfo[i].BoneIndex); } // Calculate anim pointer table size long posAnimPointerTable = writer.GetPosition(); int animPointerTableSize = header.numAnims * sizeof(int); int animPointerBase = (int)posAnimPointerTable + animPointerTableSize; // Write anims int[] animPointers = new int[header.numAnims]; for (int i = 0; i < animPointers.Length; i++) { if (mAnims[i] == null) { animPointers[i] = 0; } else { animPointers[i] = (int)((animPointerBase - DATA_START_ADDRESS) - posFileStart); writer.Seek(animPointerBase, SeekOrigin.Begin); mAnims[i].Write(writer); animPointerBase = (int)writer.GetPosition(); } } // Write pointer table writer.Seek(posAnimPointerTable, SeekOrigin.Begin); for (int i = 0; i < animPointers.Length; i++) { if (mAnims[i] != null) { addressList.Add((int)(writer.GetPosition() - posFileStart)); writer.Write(animPointers[i]); } } writer.Seek(animPointerBase, SeekOrigin.Begin); // Calculate address reloc table values byte[] addressRelocTable = PointerRelocationTableCompression.Compress(addressList, DATA_START_ADDRESS); header.addressRelocTableSize = addressRelocTable.Length; header.addressRelocTableOffset = (int)((writer.GetPosition() - DATA_START_ADDRESS) - posFileStart); // Write address reloc table writer.Write(addressRelocTable); long posFileEnd = writer.GetPosition(); // Calculate length header.length = (int)(posFileEnd - posFileStart); // Write header writer.Seek(posFileStart, SeekOrigin.Begin); writer.WriteStructure(header); writer.BaseStream.Seek(posFileEnd, SeekOrigin.Begin); writer.AlignPosition(64); }
public void Repack(string srcFolder, string patchFolder, string importFolder) { Logger.Print("正在读取索引数据"); DDTFileTable table = JsonHelper.Deserialize <DDTFileTable>(File.ReadAllText("./dds3_table.json", Encoding.UTF8)); this.GetEntry(); Logger.Print("正在复制package"); if (File.Exists(Path.Combine(importFolder, Path.GetFileName(this.ImgName)))) { File.Delete(Path.Combine(importFolder, Path.GetFileName(this.ImgName))); } if (File.Exists(Path.Combine(importFolder, Path.GetFileName(this.DDTName)))) { File.Delete(Path.Combine(importFolder, Path.GetFileName(this.DDTName))); } IOHelper.CopyFile(this.ImgName, Path.Combine(importFolder, Path.GetFileName(this.ImgName))); IOHelper.CopyFile(this.DDTName, Path.Combine(importFolder, Path.GetFileName(this.DDTName))); Logger.Print("开始对资源打补丁"); List <string> pFileList = SearchPatchingFiles(table, patchFolder); Logger.Print(string.Format("有 {0} 个资源文件需要打补丁", pFileList.Count)); FileStream imgStream = File.Open(Path.Combine(importFolder, Path.GetFileName(this.ImgName)), FileMode.Open, FileAccess.ReadWrite); FileStream ddtStream = File.Open(Path.Combine(importFolder, Path.GetFileName(this.DDTName)), FileMode.Open, FileAccess.ReadWrite); BinaryWriter imgWriter = new BinaryWriter(imgStream); BinaryWriter ddtWriter = new BinaryWriter(ddtStream); Entry vEntry; SubFile vSubFile; for (int i = 0; i < pFileList.Count; i++) { if (fDictionary.ContainsKey(pFileList[i])) { byte[] data = null; vEntry = fDictionary[pFileList[i]]; vSubFile = tempSubFileDictionary[pFileList[i]]; if (Path.GetExtension(vSubFile.FileName).ToLower().Equals(".lb") && vSubFile.SubItems.Count > 0) { //lb包有子文件,启动压缩 LB lbContainer = new LB(); byte[] packedBytes = lbContainer.Repack(getBaseDir(vSubFile.FileName), vSubFile.FileName, srcFolder, patchFolder, vSubFile.SubItems); //File.WriteAllBytes("temp/" + Path.GetFileName(vSubFile.FileName), packedBytes); data = packedBytes; } else { string tmpPath = ""; if (File.Exists(patchFolder + "/" + vSubFile.FileName)) { tmpPath = patchFolder + "/" + vSubFile.FileName; } else { tmpPath = srcFolder + "/" + vSubFile.FileName; } data = File.ReadAllBytes(tmpPath); } if (data != null) { var t_length = data.Length; var chunk_size = 0; if ((t_length % 0x800) == 0) { chunk_size = t_length; } else { chunk_size = t_length + 0x800 - t_length % 0x800; } var o_chunk_sz = 0; if ((vEntry.Size % 0x800) == 0) { o_chunk_sz = vEntry.Size; } else { o_chunk_sz = vEntry.Size + 0x800 - vEntry.Size % 0x800; } if (chunk_size > o_chunk_sz) { //追加补丁 imgWriter.Seek(0, SeekOrigin.End); var offset = imgWriter.BaseStream.Position / 0x800; Logger.Print(string.Format("Append res file{0} to offfset {1:x8}", vSubFile.FileName, offset * 0x800, t_length)); imgWriter.Write(data); imgWriter.AlignPosition(0x800); ddtWriter.Seek(vEntry.Ptr, SeekOrigin.Begin); ddtWriter.Seek(4, SeekOrigin.Current); ddtWriter.Write((int)offset); ddtWriter.Write((int)t_length); } else { //原位替换 imgWriter.Seek(vEntry.Offset, SeekOrigin.Begin); imgWriter.Write(Enumerable.Repeat((byte)0, vEntry.Size).ToArray()); imgWriter.Seek(vEntry.Offset, SeekOrigin.Begin); var offset = vEntry.Offset / 0x800; Logger.Print(string.Format("overrite res file{0} to offfset {1:x8}", vSubFile.FileName, offset * 0x800, t_length)); imgWriter.Write(data); ddtWriter.Seek(vEntry.Ptr, SeekOrigin.Begin); ddtWriter.Seek(4, SeekOrigin.Current); ddtWriter.Write((int)offset); ddtWriter.Write((int)t_length); } } } } imgWriter.Close(); ddtWriter.Close(); Logger.Print("补丁结束。Have Fun"); }