private Header ReadHeader() { var header = new Header(); header.version = InputReader.ReadUInt32(); header.fileSize = InputReader.ReadUInt32(); header.crc = InputReader.ReadUInt32(); header.sectionsOffset = InputReader.ReadUInt32(); header.numSections = InputReader.ReadUInt32(); header.rootType = ReadSectionReferenceUnchecked(); header.rootNode = ReadSectionReferenceUnchecked(); header.tag = InputReader.ReadUInt32(); header.extraTags = new UInt32[Header.ExtraTagCount]; for (int i = 0; i < Header.ExtraTagCount; i++) { header.extraTags[i] = InputReader.ReadUInt32(); } if (header.version >= 7) { header.stringTableCrc = InputReader.ReadUInt32(); header.reserved1 = InputReader.ReadUInt32(); header.reserved2 = InputReader.ReadUInt32(); header.reserved3 = InputReader.ReadUInt32(); } if (header.version < 6 || header.version > 7) { throw new ParsingException(String.Format("Unsupported GR2 version; file is version {0}, supported versions are 6 and 7", header.version)); } // if (header.tag != Header.Tag) // throw new ParsingException(String.Format("Incorrect header tag; expected {0:X8}, got {1:X8}", Header.Tag, header.tag)); Debug.Assert(header.fileSize <= InputStream.Length); Debug.Assert(header.CalculateCRC(InputStream) == header.crc); Debug.Assert(header.sectionsOffset == header.Size()); Debug.Assert(header.rootType.Section < header.numSections); // TODO: check rootTypeOffset after serialization Debug.Assert(header.stringTableCrc == 0); Debug.Assert(header.reserved1 == 0); Debug.Assert(header.reserved2 == 0); Debug.Assert(header.reserved3 == 0); #if DEBUG_GR2_SERIALIZATION System.Console.WriteLine(" ===== GR2 Header ===== "); System.Console.WriteLine(String.Format("Version {0}, Size {1}, CRC {2:X8}", header.version, header.fileSize, header.crc)); System.Console.WriteLine(String.Format("Offset of sections: {0}, num sections: {1}", header.sectionsOffset, header.numSections)); System.Console.WriteLine(String.Format("Root type section {0}, Root type offset {1:X8}", header.rootType.Section, header.rootType.Offset)); System.Console.WriteLine(String.Format("Root node section {0} {1:X8}", header.rootNode.Section, header.rootNode.Offset)); System.Console.WriteLine(String.Format("Tag: {0:X8}, Strings CRC: {1:X8}", header.tag, header.stringTableCrc)); System.Console.WriteLine(String.Format("Extra tags: {0:X8} {1:X8} {2:X8} {3:X8}", header.extraTags[0], header.extraTags[1], header.extraTags[2], header.extraTags[3])); System.Console.WriteLine(String.Format("Reserved: {0:X8} {1:X8} {2:X8}", new object[] { header.reserved1, header.reserved2, header.reserved3 })); #endif return(header); }
public byte[] Write(object root) { using (this.Writer = new BinaryWriter(Stream)) { this.Magic = InitMagic(); WriteMagic(Magic); this.Header = InitHeader(); WriteHeader(Header); for (int i = 0; i < Header.numSections; i++) { var section = new WritableSection((SectionType)i, this); WriteSectionHeader(section.Header); Sections.Add(section); } Magic.headersSize = (UInt32)Stream.Position; CurrentSection = Sections[(int)SectionType.Main]; CurrentSection.WriteStruct(root); while (ArrayWrites.Count > 0 || StructWrites.Count > 0 || StringWrites.Count > 0) { FlushPendingWrites(); } foreach (var defn in Types.Values) { Sections[(int)SectionType.Discardable].WriteStructDefinition(defn); } // We need to do this again to flush strings written by WriteMemberDefinition() FlushPendingWrites(); FinalizeOffsets(); foreach (var section in Sections) { section.Header.first16bit = (UInt32)section.MainStream.Length; section.Header.first8bit = (UInt32)section.MainStream.Length; section.Finish(); } var relocSection = Sections[(int)SectionType.Discardable]; foreach (var section in Sections) { relocSection.WriteSectionRelocations(section); } foreach (var section in Sections) { relocSection.WriteSectionMixedMarshallingRelocations(section); } foreach (var section in Sections) { // Pad section size to a multiple of the section alignment while ((section.MainStream.Position % section.Header.alignment) > 0) { section.Writer.Write((Byte)0); } section.MainStream.Flush(); section.Header.offsetInFile = (UInt32)Stream.Position; section.Header.uncompressedSize = (UInt32)section.MainStream.Length; section.Header.compressedSize = (UInt32)section.MainStream.Length; Writer.Write(section.MainStream.ToArray()); } foreach (var section in Sections) { section.Header.relocationsOffset += relocSection.Header.offsetInFile; section.Header.mixedMarshallingDataOffset += relocSection.Header.offsetInFile; } var rootStruct = LookupStructDefinition(root.GetType(), root); Header.rootType = ObjectOffsets[rootStruct]; Header.rootNode = new SectionReference(SectionType.Main, 0); Header.fileSize = (UInt32)Stream.Length; Stream.Seek(Magic.MagicSize + Header.Size(), SeekOrigin.Begin); foreach (var section in Sections) { WriteSectionHeader(section.Header); } Header.crc = Header.CalculateCRC(Stream); Stream.Seek(0, SeekOrigin.Begin); WriteMagic(Magic); WriteHeader(Header); return(Stream.ToArray()); } }