private void WriteTable <T>(IList <T> array, int index) where T : struct { if (array.Count == 0) { return; } var hash = new Crc32Algorithm(false); var start = Convert.ToUInt32(BaseStream.Position); WriteStructs <T>(array.ToArray(), hash); m_header[index] = new CR2WTable() { offset = start, size = (uint)array.Count, crc32 = hash.HashUInt32, }; }
public void WriteFile(CR2WFile file) { _file = file; BaseStream.WriteStruct(CR2WFile.MAGIC); var fileHeader = new CR2WFileHeader { version = _file.MetaData.Version, buildVersion = _file.MetaData.BuildVersion, numChunks = 6 }; var tableHeaders = new CR2WTable[10]; var headerPos = BaseStream.Position; // Write empty header, fill it later BaseStream.WriteStruct(fileHeader); BaseStream.WriteStructs(tableHeaders); Debug.Assert(BaseStream.Position == 160); var dataCollection = GenerateData(); foreach (var embedded in _file.EmbeddedFiles) { var tuple = ("", (CName)embedded.FileName, (ushort)8); if (!dataCollection.ImportList.Contains(tuple)) { dataCollection.ImportList.Add(tuple); } } fileHeader.objectsEnd = (uint)BaseStream.Position; var combinedList = new List <CName>(dataCollection.StringList); combinedList.AddRange(dataCollection.ImportList.Select(x => x.Item2).ToList()); var(stringBuffer, stringOffsets) = GenerateStringBuffer(combinedList); tableHeaders[0] = new CR2WTable() { offset = (uint)BaseStream.Position, itemCount = (uint)stringBuffer.Length, crc32 = Crc32Algorithm.Compute(stringBuffer) }; BaseWriter.Write(stringBuffer); if (_file.Properties.Count < 1) { _file.Properties.Add(new CR2WProperty()); } var afterHeaderPosition = CalculateHeaderLength(dataCollection); fileHeader.objectsEnd += (uint)afterHeaderPosition; #region Names tableHeaders[1].offset = (uint)BaseStream.Position; tableHeaders[1].itemCount = (uint)dataCollection.StringList.Count; var crc = new Crc32Algorithm(false); foreach (var str in dataCollection.StringList) { if (_file.MetaData.HashVersion == EHashVersion.Pre120) { #pragma warning disable CS0618 // Typ oder Element ist veraltet BaseStream.WriteStruct(new CR2WNameInfo { hash = str.GetOldRedHash(), offset = stringOffsets[str] }, crc); #pragma warning restore CS0618 // Typ oder Element ist veraltet } else { BaseStream.WriteStruct(new CR2WNameInfo { hash = str.GetShortRedHash(), offset = stringOffsets[str] }, crc); } } tableHeaders[1].crc32 = crc.HashUInt32; #endregion Names #region Imports if (dataCollection.ImportList.Count > 0) { tableHeaders[2].offset = (uint)BaseStream.Position; tableHeaders[2].itemCount = (uint)dataCollection.ImportList.Count; crc = new Crc32Algorithm(false); foreach (var import in dataCollection.ImportList) { var entry = new CR2WImportInfo() { className = (ushort)dataCollection.StringList.IndexOf(import.Item1), offset = stringOffsets[import.Item2], flags = import.Item3 }; BaseStream.WriteStruct(entry, crc); } tableHeaders[2].crc32 = crc.HashUInt32; } #endregion Imports #region Properties tableHeaders[3].offset = (uint)BaseStream.Position; tableHeaders[3].itemCount = (uint)_file.Properties.Count; crc = new Crc32Algorithm(false); foreach (var property in _file.Properties) { BaseStream.WriteStruct(new CR2WPropertyInfo(), crc); } tableHeaders[3].crc32 = crc.HashUInt32; #endregion #region Chunks if (dataCollection.ChunkInfoList.Count > 0) { tableHeaders[4].offset = (uint)BaseStream.Position; tableHeaders[4].itemCount = (uint)dataCollection.ChunkInfoList.Count; crc = new Crc32Algorithm(false); foreach (var chunkInfo in dataCollection.ChunkInfoList) { var entry = chunkInfo; entry.dataOffset += (uint)afterHeaderPosition; BaseStream.WriteStruct(entry, crc); } tableHeaders[4].crc32 = crc.HashUInt32; } #endregion Chunks #region Buffers var beforeBufferTablePos = BaseStream.Position; if (dataCollection.BufferInfoList.Count > 0) { tableHeaders[5].offset = (uint)BaseStream.Position; tableHeaders[5].itemCount = (uint)dataCollection.BufferInfoList.Count; foreach (var buffer in dataCollection.BufferInfoList) { BaseStream.WriteStruct(buffer, crc); } } #endregion Buffers #region Embedded var(embeddedInfoList, embeddedData) = GenerateEmbeddedData(dataCollection.ImportList); if (embeddedInfoList.Count > 0) { tableHeaders[6].offset = (uint)BaseStream.Position; tableHeaders[6].itemCount = (uint)embeddedInfoList.Count; crc = new Crc32Algorithm(false); foreach (var embedded in embeddedInfoList) { BaseStream.WriteStruct(embedded, crc); } tableHeaders[6].crc32 = crc.HashUInt32; } #endregion Embedded Debug.Assert(BaseStream.Position == afterHeaderPosition); BaseStream.Write(dataCollection.ChunkData); fileHeader.objectsEnd = (uint)BaseStream.Position; if (dataCollection.BufferInfoList.Count > 0) { BaseStream.Position = beforeBufferTablePos; crc = new Crc32Algorithm(false); for (var i = 0; i < dataCollection.BufferInfoList.Count; i++) { var entry = dataCollection.BufferInfoList[i]; entry.offset += fileHeader.objectsEnd; dataCollection.BufferInfoList[i] = entry; BaseStream.WriteStruct(entry, crc); } tableHeaders[5].crc32 = crc.HashUInt32; } BaseStream.Position = fileHeader.objectsEnd; BaseStream.Write(dataCollection.BufferData); fileHeader.buffersEnd = (uint)BaseStream.Position; fileHeader.crc32 = CalculateHeaderCRC32(fileHeader, tableHeaders); BaseStream.Position = headerPos; BaseStream.WriteStruct(fileHeader); BaseStream.WriteStructs(tableHeaders); //for (int i = 0; i < dataCollection.ChunkInfoList.Count; i++) //{ // var newInfo = dataCollection.ChunkInfoList[i]; // var oldInfo = _file.Info.ExportInfo[i]; // // if ((newInfo.dataOffset + afterHeaderPosition) != oldInfo.dataOffset) // { // // } // // if (newInfo.dataSize != oldInfo.dataSize) // { // // } // // if (newInfo.parentID != oldInfo.parentID) // { // throw new TodoException("Invalid parent id"); // } // // if (newInfo.className != oldInfo.className) // { // // } // // if (newInfo.objectFlags != oldInfo.objectFlags) // { // // } // // if (newInfo.template != oldInfo.template) // { // // } //} // //for (int i = 0; i < dataCollection.BufferInfoList.Count; i++) //{ // var newInfo = dataCollection.BufferInfoList[i]; // var oldInfo = _file.Info.BufferInfo[i]; // // if (newInfo.index != oldInfo.index) // { // // } // // if (newInfo.crc32 != oldInfo.crc32) // { // // } // // if (newInfo.diskSize != oldInfo.diskSize) // { // // } // // if (newInfo.flags != oldInfo.flags) // { // // } // // if (newInfo.memSize != oldInfo.memSize) // { // // } // // if (newInfo.offset != oldInfo.offset) // { // // } //} }