Esempio n. 1
0
        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,
            };
        }
Esempio n. 2
0
        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)
            //    {
            //
            //    }
            //}
        }