public override void WriteLocationBundle(string outPath, LocationBundle bundle, List <StreamSection> sections) { // Write master stream var streamPath = Path.Combine( Path.GetDirectoryName(outPath), $"STREAM{bundle.Name}.BUN"); //File.Delete(streamPath); var offsetTable = new List <long>(); using (var mfs = File.Open(streamPath, FileMode.Create, FileAccess.Write, FileShare.Read)) { for (var index = 0; index < sections.Count; index++) { var bundleSection = sections[index]; offsetTable.Add(mfs.Position); mfs.Write(bundleSection.Data, 0, bundleSection.Data.Length); if (mfs.Position % 0x800 != 0 && index != sections.Count - 1) { var align = 0x800 - mfs.Position % 0x800; align -= 8; mfs.Write(new byte[] { 0x00, 0x00, 0x00, 0x00 }, 0, 4); mfs.Write(BitConverter.GetBytes(align), 0, 4); mfs.Write(new byte[align], 0, (int)align); } } } //File.Delete(outPath); // Write location bundle using (var bw = new BinaryWriter(File.Open(outPath, FileMode.Create, FileAccess.Write, FileShare.Read))) using (var cs = new ChunkStream(bw)) { // We have to skip null chunks in order to avoid weirdness. foreach (var chunk in bundle.Chunks.Where(c => c.Id != 0)) { if (chunk.PrePadding > 8) // 0x10 - 8 = 8; greater than 8 = align 0x80 { cs.PaddingAlignment2(0x80); } else if (chunk.PrePadding > 0) { cs.PaddingAlignment2(0x10); } if (chunk.Id == 0x00034110) { // Write sections list cs.BeginChunk(0x00034110); for (var index = 0; index < sections.Count; index++) { var bundleSection = sections[index]; var sectionStruct = new MostWantedSection(); sectionStruct.ModelGroupName = bundleSection.Name; sectionStruct.Hash = bundleSection.Hash; sectionStruct.MasterStreamChunkOffset = (uint)offsetTable[index]; sectionStruct.MasterStreamChunkNumber = 1; sectionStruct.StreamChunkNumber = bundleSection.Number; sectionStruct.Size1 = sectionStruct.Size2 = bundleSection.Size; //sectionStruct.Unknown2 = bundleSection.UnknownSectionNumber; sectionStruct.Unknown2 = 0; sectionStruct.X = bundleSection.Position.X; sectionStruct.Y = bundleSection.Position.Y; sectionStruct.Z = bundleSection.Position.Z; cs.WriteStruct(sectionStruct); } cs.EndChunk(); } else { cs.WriteChunk(chunk); } } } }
public override void WriteLocationBundle(string outPath, LocationBundle bundle, List <StreamSection> sections) { using (var bw = new BinaryWriter(File.Open(outPath, FileMode.Create, FileAccess.Write, FileShare.Read))) using (var cs = new ChunkStream(bw)) { // We have to skip null chunks in order to avoid weirdness. foreach (var chunk in bundle.Chunks.Where(c => c.Id != 0)) { if (chunk.PrePadding > 8) // 0x10 - 8 = 8; greater than 8 = align 0x80 { cs.PaddingAlignment2(0x80); } else if (chunk.PrePadding > 0) { cs.PaddingAlignment2(0x10); } if (chunk.Id == 0x00034110) { // Write sections list cs.BeginChunk(0x00034110); foreach (var bundleSection in sections.Cast <WorldStreamSection>()) { var secStruct = new World15Section(); secStruct.Hash = bundleSection.Hash; secStruct.ModelGroupName = bundleSection.Name; secStruct.Blank = new uint[3]; secStruct.Blank2 = new byte[36]; secStruct.StreamChunkNumber = bundleSection.Number; secStruct.StreamChunkNumber2 = bundleSection./*UnknownSectionNumber*/ Number; secStruct.FragmentFileId = bundleSection.FragmentFileId; secStruct.Unknown1 = 2; secStruct.X = bundleSection.Position.X; secStruct.Y = bundleSection.Position.Y; secStruct.Z = bundleSection.Position.Z; secStruct.Type = bundleSection.Type; unchecked { secStruct.Unknown2 = (int)0xffffffff; } secStruct.Parameters = new uint[28]; secStruct.Parameters[(4 * 3 * (secStruct.Type - 1)) >> 2] = bundleSection.Size; secStruct.Parameters[((4 * 3 * (secStruct.Type - 1)) >> 2) + 1] = bundleSection.Size; secStruct.Parameters[((4 * 3 * (secStruct.Type - 1)) >> 2) + 2] = bundleSection.PermSize; //worldSection.Size = section.Parameters[(4 * 3 * (section.Type - 1)) >> 2]; //worldSection.PermSize = section.Parameters[((4 * 3 * (section.Type - 1)) >> 2) + 2]; //if (section.Type == 1) //{ // // if type 1, params[0..2] = size1, size2, size3 // worldSection.Size = section.Parameters[0]; // worldSection.OtherSize = section.Parameters[2]; // worldSection.ParamSize1 = section.Parameters[0]; // worldSection.ParamSize2 = section.Parameters[1]; // worldSection.ParamSize3 = section.Parameters[2]; //} //else //{ // worldSection.ParamTpkDataOff = section.Parameters[2]; // worldSection.ParamTpkNullOff = section.Parameters[0]; // worldSection.TextureContainerOffsets.Add(section.Parameters[3]); // worldSection.TextureContainerOffsets.Add(section.Parameters[6]); // worldSection.TextureContainerOffsets.Add(section.Parameters[9]); // //worldSection.TextureContainerOffsets.Add(section.Parameters[12]); // worldSection.ParamSize1 = worldSection.Size = section.Parameters[12]; //} cs.WriteStruct(secStruct); } cs.EndChunk(); } else { cs.WriteChunk(chunk); } } } }
public override void WriteLocationBundle(string outPath, LocationBundle bundle, List <StreamSection> sections) { var chunkManager = new ChunkManager(GameDetector.Game.Undercover); chunkManager.Read(bundle.File); var masterStreamPath = Path.Combine(Path.GetDirectoryName(outPath), $"STREAM{bundle.Name}.BUN"); var sectionInfoMap = new Dictionary <uint, StreamChunkInfo>(); var sectionDataMap = new Dictionary <uint, byte[]>(); using (var fs = new FileStream(masterStreamPath, FileMode.Open)) using (var br = new BinaryReader(fs)) { foreach (var section in bundle.Sections) { sectionDataMap[section.Number] = new byte[0]; //var sectionPath = Path.Combine(sectionsPath, $"STREAM{bundle.Name}_{section.Number}.BUN"); //if (File.Exists(sectionPath)) //{ // sectionDataMap[section.Number] = File.ReadAllBytes(sectionPath); //} //else //{ // br.BaseStream.Position = section.Offset; // sectionDataMap[section.Number] = new byte[section.Size]; // br.Read(sectionDataMap[section.Number], 0, (int)section.Size); //} } } using (var fs = new FileStream(masterStreamPath, FileMode.Create)) using (var bw = new BinaryWriter(fs)) { for (var index = 0; index < bundle.Sections.Count; index++) { var section = bundle.Sections[index]; sectionInfoMap[section.Number] = new StreamChunkInfo { Offset = bw.BaseStream.Position, Size = (uint)sectionDataMap[section.Number].Length }; bw.Write(sectionDataMap[section.Number]); if (index != bundle.Sections.Count - 1) { // calculate and write alignment chunk, align by 0x800 bytes var alignSize = sectionDataMap[section.Number].Length + 8 - (sectionDataMap[section.Number].Length + 8) % 0x800 + 0x1000; alignSize -= sectionDataMap[section.Number].Length + 8; bw.Write(0x00000000); bw.Write(alignSize); bw.BaseStream.Position += alignSize; } } } using (var fs = new FileStream(outPath, FileMode.Create)) { using (var chunkStream = new ChunkStream(new BinaryWriter(fs))) { Chunk previousChunk = null; foreach (var chunk in chunkManager.Chunks.Where(c => c.Id != 0)) { if (previousChunk != null && previousChunk.Size > 0) { chunkStream.PaddingAlignment(0x10); } chunkStream.BeginChunk(chunk.Id); if (chunk.Id == 0x00034110) { // write sections foreach (var bundleSection in bundle.Sections) { var sectionStruct = new UndercoverSection { Hash = bundleSection.Hash, ModelGroupName = bundleSection.Name, MasterStreamChunkNumber = 0, StreamChunkNumber = bundleSection.Number, Size1 = sectionInfoMap[bundleSection.Number].Size, Size2 = sectionInfoMap[bundleSection.Number].Size, Size3 = sectionInfoMap[bundleSection.Number].Size, X = bundleSection.Position.X, Y = bundleSection.Position.Y, Z = bundleSection.Position.Z, MasterStreamChunkOffset = (uint)sectionInfoMap[bundleSection.Number].Offset }; chunkStream.WriteStruct(sectionStruct); } } else { chunkStream.Write(chunk.Data); } chunkStream.EndChunk(); previousChunk = chunk; } } } }