public void VisitReflexive(ReflexiveData field) { SeekToOffset(field.Offset); StructureValueCollection values = StructureReader.ReadStructure(_reader, _tagBlockLayout); var length = (int)values.GetInteger("entry count"); uint pointer = values.GetInteger("pointer"); // Make sure the pointer looks valid if (length < 0 || (_cache.Engine != EngineType.FourthGeneration && !_cache.MetaArea.ContainsBlockPointer(pointer, (int)(length * field.EntrySize))) || (_cache.Engine == EngineType.FourthGeneration && (pointer < 0x40000000 || pointer > 0x50000000))) { if (length != 0 && pointer != 0) { //field.Opacity = 0.5f; MetroMessageBox.Show("Bad Block!", "Block \"" + field.Name + "\", plugin line " + field.PluginLine + " appears to be invalid. The block has been ignored to prevent crashing."); } length = 0; pointer = 0; } field.Length = length; if (pointer != field.FirstEntryAddress) { field.FirstEntryAddress = pointer; } }
public override Program Load(Address addrLoad) { var ext = new StructureReader <SOM_Header>(MakeReader(0)); var somHeader = ext.Read(); if (somHeader.aux_header_location == 0) { throw new BadImageFormatException(); } var spaces = ReadSpaces(somHeader.space_location, somHeader.space_total, somHeader.space_strings_location); var subspaces = ReadSubspaces(somHeader.subspace_location, somHeader.subspace_total, somHeader.space_strings_location); var rdr = MakeReader(somHeader.aux_header_location); var auxReader = new StructureReader <aux_id>(rdr); var aux = auxReader.Read(); switch (aux.type) { case aux_id_type.exec_aux_header: var program = LoadExecSegments(rdr); SetProgramOptions(somHeader, program); return(program); default: throw new BadImageFormatException(); } }
private SecondGenHeader LoadHeader(IReader reader, EngineDescription buildInfo, string buildString) { reader.SeekTo(0); StructureValueCollection values = StructureReader.ReadStructure(reader, buildInfo.Layouts.GetLayout("header")); return(new SecondGenHeader(values, buildInfo, buildString, _segmenter)); }
public List <ImageSymbol> GetAllSymbols() { var symbols = new List <ImageSymbol>(); for (uint i = 0; i < hdr.n_symbols; i++) { rdr.BaseStream.Seek(syms_offset + Marshal.SizeOf(typeof(SymEntry)) * i, SeekOrigin.Begin); SymEntry?s = new StructureReader <SymEntry>(rdr).Read(); if (s == null) { break; } var sym = s.Value; rdr.BaseStream.Seek(sym_names_offset + sym.sym_name_off, SeekOrigin.Begin); string sym_name = rdr.ReadNullTerminatedString(); symbols.Add(new ImageSymbol(new Address32(sym.addr)) { Size = sym.end - sym.addr, Name = sym_name }); } return(symbols); }
private void ReadLocalePointer(IReader reader, out StringID id, out int offset) { StructureValueCollection values = StructureReader.ReadStructure(reader, _pointerLayout); id = new StringID(values.GetInteger("stringid")); offset = (int)values.GetInteger("offset"); }
private void ReadResourceBuffers(BlamCacheFile cacheFile, ref Resource resourceRef) { bool[] convertedVertexBuffers = new bool[100]; bool[] convertedIndexBuffers = new bool[100]; using (EndianWriter writer = new EndianWriter(new MemoryStream(resourceRef.Info), Endian.LittleEndian)) { foreach (ResourceFixup fixup in resourceRef.ResourceFixups) { BlamCacheAddress address = new BlamCacheAddress(fixup.Address); writer.SeekTo(fixup.Offset); writer.WriteUInt32(address.Value); } } byte[] primaryResource = ReadResourcePageData(cacheFile, resourceRef.Location.PrimaryPage); byte[] secondaryResource = ReadResourcePageData(cacheFile, resourceRef.Location.SecondaryPage); using (EndianReader definitionReader = new EndianReader(new MemoryStream(resourceRef.Info), Endian.LittleEndian)) using (EndianReader primaryReader = new EndianReader(new MemoryStream(primaryResource), Endian.LittleEndian)) using (EndianReader secondaryReader = new EndianReader(new MemoryStream(secondaryResource), Endian.LittleEndian)) { BlamCacheAddress cacheAddress = new BlamCacheAddress((uint)resourceRef.BaseDefinitionAddress); Logger.AssertMsg(cacheAddress.Type == BlamCacheAddressType.Definition, "INVALID CACHE ADDRESS"); definitionReader.SeekTo(cacheAddress.Offset); StructureLayout layout = cacheFile.GetLayout("render geometry api resource definition"); StructureValueCollection values = StructureReader.ReadStructure(definitionReader, layout); BlamCacheAddress uselessCrap3Address = new BlamCacheAddress((uint)values.GetInteger("address of useless crap3")); BlamCacheAddress uselessCrap4Address = new BlamCacheAddress((uint)values.GetInteger("address of useless crap4")); } }
public static StructureValueCollection[] ReadReflexive(IReader reader, int count, uint address, StructureLayout entryLayout, FileSegmentGroup metaArea) { if (entryLayout.Size == 0) { throw new ArgumentException("The entry layout must have a size associated with it."); } // Handle null pointers if (count <= 0) { return(new StructureValueCollection[0]); } // Convert the address to an offset and seek to it int offset = metaArea.PointerToOffset(address); reader.SeekTo(offset); // Read the entries var result = new StructureValueCollection[count]; for (int i = 0; i < count; i++) { result[i] = StructureReader.ReadStructure(reader, entryLayout); } return(result); }
private List <ITag> ReadTags(IReader reader, uint tagTableOffset, int numTags, EngineDescription buildInfo, FileSegmentGroup metaArea, StructureValueCollection headerValues) { StructureLayout layout = buildInfo.Layouts.GetLayout("tag element"); var result = new List <ITag>(); reader.SeekTo(tagTableOffset); ulong metaOffset = 0; if (headerValues.HasInteger("meta header mask")) { metaOffset = (ulong)metaArea.BasePointer - headerValues.GetInteger("meta header mask"); } for (int i = 0; i < numTags; i++) { StructureValueCollection values = StructureReader.ReadStructure(reader, layout); //h2 alpha/beta store names differently, convert it to something expected if (metaOffset > 0) { ulong nameOffset = values.GetInteger("name offset"); nameOffset += metaOffset; values.SetInteger("name offset", nameOffset); } result.Add(new FirstGenTag(values, metaArea, _groupsById)); } return(result); }
private SecondGenHeader LoadHeader(IReader reader) { reader.SeekTo(0); StructureValueCollection values = StructureReader.ReadStructure(reader, _buildInfo.Layouts.GetLayout("header")); return(new SecondGenHeader(values, _buildInfo, _segmenter)); }
private static CompressionState AnalyzeSecondGen(IReader reader, EngineDescription engineInfo) { // H2 header is uncompressed, so the cache file needs to be loaded enough to check if the tag table is readable var segmenter = new FileSegmenter(engineInfo.SegmentAlignment); reader.SeekTo(0); StructureValueCollection headerValues = StructureReader.ReadStructure(reader, engineInfo.Layouts.GetLayout("header")); var metaOffset = (int)headerValues.GetInteger("meta offset"); var metaSize = (int)headerValues.GetInteger("meta size"); uint metaOffsetMask = (uint)headerValues.GetInteger("meta offset mask"); var metaSegment = new FileSegment( segmenter.DefineSegment(metaOffset, metaSize, 0x200, SegmentResizeOrigin.Beginning), segmenter); var MetaArea = new FileSegmentGroup(new MetaOffsetConverter(metaSegment, metaOffsetMask)); MetaArea.AddSegment(metaSegment); if (MetaArea.Offset >= reader.Length) { return(CompressionState.Compressed); } reader.SeekTo(MetaArea.Offset); StructureValueCollection tagTableValues = StructureReader.ReadStructure(reader, engineInfo.Layouts.GetLayout("meta header")); if ((uint)tagTableValues.GetInteger("magic") != CharConstant.FromString("tags")) { return(CompressionState.Compressed); } return(CompressionState.Decompressed); }
private StructureValueCollection LoadHeader(IReader reader) { if (_metaArea == null) { return(null); } reader.SeekTo(_metaArea.Offset); StructureValueCollection result = StructureReader.ReadStructure(reader, _metaHeaderLayout); if ((uint)result.GetInteger("magic") != CharConstant.FromString("tags")) { throw new ArgumentException("Invalid index table header magic. This map could be compressed, try the Compressor in the Tools menu before reporting."); } //see if header values are memory (xbox) or local (everything after) and store the result if needed uint metaMask = (uint)result.GetInteger("tag group table offset") - (uint)_metaHeaderLayout.Size; if (metaMask > 0) { result.SetInteger("meta header mask", metaMask); } return(result); }
private static CompressionState AnalyzeFirstGen(IReader reader, EngineDescription engineInfo, out StructureValueCollection headerValues) { reader.SeekTo(0); var headerLayout = engineInfo.Layouts.GetLayout("header"); headerValues = StructureReader.ReadStructure(reader, headerLayout); //hax headerValues.SetInteger("_header_length_", (ulong)headerLayout.Size); var metaOffset = (int)headerValues.GetInteger("meta offset"); if (metaOffset >= reader.Length) { return(CompressionState.Compressed); } reader.SeekTo(metaOffset); StructureValueCollection tagTableValues = StructureReader.ReadStructure(reader, engineInfo.Layouts.GetLayout("meta header")); if ((uint)tagTableValues.GetInteger("magic") != CharConstant.FromString("tags")) { return(CompressionState.Compressed); } return(CompressionState.Decompressed); }
private void ReadTagReference(DataBlock block, uint offset, bool withClass) { SeekToOffset(block, offset); DatumIndex index; int fixupOffset; bool valid; if (withClass) { // Class info - do a flexible structure read to get the index StructureValueCollection values = StructureReader.ReadStructure(_reader, _tagRefLayout); var classMagic = (int)values.GetInteger("class magic"); index = new DatumIndex(values.GetInteger("datum index")); fixupOffset = (int)offset + _tagRefLayout.GetFieldOffset("datum index"); valid = _cacheFile.Tags.IsValidIndex(index, classMagic); } else { // No tag class - the datum index is at the offset index = new DatumIndex(_reader.ReadUInt32()); fixupOffset = (int)offset; valid = _cacheFile.Tags.IsValidIndex(index); } if (valid) { // Add the tagref fixup to the block var fixup = new DataBlockTagFixup(index, fixupOffset); block.TagFixups.Add(fixup); ReferencedTags.Add(index); } }
private List <ITag> ReadTags(IReader reader, uint tagTableOffset, int numTags, EngineDescription buildInfo, FileSegmentGroup metaArea) { StructureLayout layout = buildInfo.Layouts.GetLayout("tag element"); var result = new List <ITag>(); reader.SeekTo(tagTableOffset); // TODO (Dragon): DUDE long oldpos = reader.Position; reader.SeekTo(metaArea.Offset); uint metafuck = reader.ReadUInt32(); metafuck -= (uint)(tagTableOffset - metaArea.Offset); reader.SeekTo(oldpos); for (int i = 0; i < numTags; i++) { StructureValueCollection values = StructureReader.ReadStructure(reader, layout); // TODO (Dragon): SERIOUSLY // JUST F*****G FIX THE FILE SEGMENTS OH MY GOD if (buildInfo.Version == "02.01.07.4998" || buildInfo.Version == "02.06.28.07902") { ulong omg = values.GetInteger("name offset"); //omg += ((ulong)metaArea.BasePointer - metafuck) - (ulong)metaArea.BasePointer + (ulong)metaArea.Offset; omg += ((ulong)metaArea.BasePointer - metafuck); values.SetInteger("name offset", omg); } result.Add(new FirstGenTag(values, metaArea, _groupsById)); } return(result); }
private void Load(IReader reader) { //might need to tweak once more MCC games come out reader.SeekTo(_scenario.MetaLocation.AsOffset()); var scenarioLayout = _buildInfo.Layouts.GetLayout("scnr"); var scenarioData = StructureReader.ReadStructure(reader, scenarioLayout); var count = (int)scenarioData.GetInteger("structured effect interops count"); var address = (uint)scenarioData.GetInteger("structured effect interop address"); long expand = _expander.Expand(address); reader.SeekTo(_metaArea.PointerToOffset(expand)); var entryLayout = _buildInfo.Layouts.GetLayout("structured effect interop element"); var pointerBlock = StructureReader.ReadStructure(reader, entryLayout); var effeAddr = (uint)pointerBlock.GetInteger("effect pointer"); var beamAddr = (uint)pointerBlock.GetInteger("beam pointer"); var cntlAddr = (uint)pointerBlock.GetInteger("contrail pointer"); var ltvlAddr = (uint)pointerBlock.GetInteger("light volume pointer"); var pointerLayout = _buildInfo.Layouts.GetLayout("data reference"); LoadData(reader, EffectInteropType.Effect, _expander.Expand(effeAddr), pointerLayout, "effect data"); LoadData(reader, EffectInteropType.Beam, _expander.Expand(beamAddr), pointerLayout, "beam data"); LoadData(reader, EffectInteropType.Contrail, _expander.Expand(cntlAddr), pointerLayout, "contrail data"); LoadData(reader, EffectInteropType.LightVolume, _expander.Expand(ltvlAddr), pointerLayout, "light volume data"); }
private FirstGenTagTable LoadTagTable(IReader reader, EngineDescription buildInfo) { reader.SeekTo(MetaArea.Offset); StructureValueCollection values = StructureReader.ReadStructure(reader, buildInfo.Layouts.GetLayout("meta header")); return(new FirstGenTagTable(reader, values, MetaArea, buildInfo)); }
public List <ImageSymbol> GetAllSymbols() { var symbols = new List <ImageSymbol>(); for (uint i = 0; i < hdr.n_symbols; i++) { rdr.BaseStream.Seek(syms_offset + Marshal.SizeOf(typeof(SymEntry)) * i, SeekOrigin.Begin); SymEntry?s = new StructureReader <SymEntry>(rdr).Read(); if (s == null) { break; } var sym = s.Value; rdr.BaseStream.Seek(sym_names_offset + sym.sym_name_off, SeekOrigin.Begin); string sym_name = rdr.ReadNullTerminatedString(); //$BUG: how do we get the architecture? symbols.Add(ImageSymbol.Create( SymbolType.Unknown, null, Address.Ptr32(sym.addr), sym_name, new UnknownType((int)(sym.end - sym.addr)))); } return(symbols); }
private static IndexStats GetIndexStats(StructureReader <IndexingWorkStatsFields> indexingStats, StructureReader <ReducingWorkStatsFields> reduceStats, StructureReader <LastIndexedStatsFields> lastIndexedEtags, int priority, int touches) { var lastReducedEtag = Etag.Parse(reduceStats.ReadBytes(ReducingWorkStatsFields.LastReducedEtag)); var reduceAttempts = reduceStats.ReadInt(ReducingWorkStatsFields.ReduceAttempts); var reduceErrors = reduceStats.ReadInt(ReducingWorkStatsFields.ReduceErrors); var reduceSuccesses = reduceStats.ReadInt(ReducingWorkStatsFields.ReduceSuccesses); var lastReducedTimestamp = reduceStats.ReadLong(ReducingWorkStatsFields.LastReducedTimestamp); return(new IndexStats { TouchCount = touches, IndexingAttempts = indexingStats.ReadInt(IndexingWorkStatsFields.IndexingAttempts), IndexingErrors = indexingStats.ReadInt(IndexingWorkStatsFields.IndexingErrors), IndexingSuccesses = indexingStats.ReadInt(IndexingWorkStatsFields.IndexingSuccesses), ReduceIndexingAttempts = reduceAttempts == -1 ? (int?)null : reduceAttempts, ReduceIndexingErrors = reduceErrors == -1 ? (int?)null : reduceErrors, ReduceIndexingSuccesses = reduceSuccesses == -1 ? (int?)null : reduceSuccesses, Id = indexingStats.ReadInt(IndexingWorkStatsFields.IndexId), Priority = (IndexingPriority)priority, LastIndexedEtag = Etag.Parse(lastIndexedEtags.ReadBytes(LastIndexedStatsFields.LastEtag)), LastIndexedTimestamp = DateTime.FromBinary(lastIndexedEtags.ReadLong(LastIndexedStatsFields.LastTimestamp)), CreatedTimestamp = DateTime.FromBinary(indexingStats.ReadLong(IndexingWorkStatsFields.CreatedTimestamp)), LastIndexingTime = DateTime.FromBinary(indexingStats.ReadLong(IndexingWorkStatsFields.LastIndexingTime)), LastReducedEtag = lastReducedEtag.CompareTo(Etag.InvalidEtag) != 0 ? lastReducedEtag : null, LastReducedTimestamp = lastReducedTimestamp == -1 ? (DateTime?)null : DateTime.FromBinary(lastReducedTimestamp) }); }
public void VisitReflexive(ReflexiveData field) { SeekToOffset(field.Offset); StructureValueCollection values = StructureReader.ReadStructure(_reader, _tagBlockLayout); var length = (int)values.GetInteger("entry count"); uint pointer = values.GetInteger("pointer"); if (_cache.Engine == EngineType.ThirdGenMCC) { pointer = NewPointerConverter.ConvertToPointer(pointer); } // Make sure the pointer looks valid if (length < 0 || !_cache.MetaArea.ContainsTagBlockPointer(pointer, (int)(length * field.EntrySize))) { length = 0; pointer = 0; } field.Length = length; if (pointer != field.FirstEntryAddress) { field.FirstEntryAddress = pointer; } }
private bool TryLoadHeader(BeImageReader rdr, out PrgHeader hdr) { var sr = new StructureReader <PrgHeader>(rdr); hdr = sr.Read(); return(hdr.Magic == 0x601A); }
public DescriptorStructure(PsdReader reader, bool hasVersion) { if (hasVersion == true) { this.version = reader.ReadInt32(); } this.Add("Name", reader.ReadString()); this.Add("ClassID", reader.ReadKey()); int count = reader.ReadInt32(); for (int i = 0; i < count; i++) { string key = reader.ReadKey(); string osType = reader.ReadType(); if (key == "EngineData") { this.Add(key.Trim(), new StructureEngineData(reader)); } else { object value = StructureReader.Read(osType, reader); this.Add(key.Trim(), value); } } }
public void Sr_ReadLeInt32_Field() { var rdr = new LeImageReader(new byte[] { 0x34, 0x12, 0xAB, 0xCD, 0x78, 0x56, 0x34, 0x12 }); var test = new StructureReader <TestStruct2>(rdr).Read(); Assert.AreEqual((int)0x12345678, test.lField); }
private void ReadTagBlock(DataBlock block, uint offset, uint entrySize, int align, bool sort) { // Read the count and pointer SeekToOffset(block, offset); var values = StructureReader.ReadStructure(_reader, _tagBlockLayout); var count = (int)values.GetInteger("entry count"); var pointer = (uint)values.GetInteger("pointer"); long expand = _cacheFile.PointerExpander.Expand(pointer); if (count <= 0 || !_cacheFile.MetaArea.ContainsBlockPointer(expand, (int)(count * entrySize))) { return; } var newBlock = ReadDataBlock(expand, (int)entrySize, count, align, sort); // Now create a fixup for the block var fixup = new DataBlockAddressFixup(pointer, (int)offset + _tagBlockLayout.GetFieldOffset("pointer")); block.AddressFixups.Add(fixup); // Add it to _tagBlocks so it'll be recursed into _tagBlocks.Add(newBlock); }
public void Sr_ReadArray() { var rdr = new LeImageReader(new byte[] { 0x4A, 0x4B, // signature 0x08, 0x00, 0x00, 0x00, // pointer to directory 0xFF, 0xFF, // padding 0x10, 0, // Directory slot 0 0x13, 0, // Directory slot 1 0x16, 0, // Directory slot 2 0x19, 0, // Directory slot 3 0x61, 0x62, 0x00, 0x63, 0x64, 0x00, 0x65, 0x66, 0x00, 0x65, 0x78, 0x00, }); var test = new TestStruct6(); var sr = new StructureReader(test); sr.Read(rdr); Assert.IsNotNull(test.directory); Assert.IsNotNull(test.directory.sections); Assert.AreEqual(4, test.directory.sections.Length); Assert.AreEqual("ab", test.directory.sections[0].name); Assert.AreEqual("cd", test.directory.sections[1].name); Assert.AreEqual("ef", test.directory.sections[2].name); Assert.AreEqual("ex", test.directory.sections[3].name); }
public void Sr_ReadLeUInt16_Field() { var rdr = new LeImageReader(new byte[] { 0x34, 0x12 }); var test = new StructureReader <TestStruct>(rdr).Read(); Assert.AreEqual((ushort)0x1234, test.usField); }
private void LoadHeader(IReader reader, string buildString) { reader.SeekTo(0); StructureValueCollection values = StructureReader.ReadStructure(reader, _buildInfo.Layouts.GetLayout("header")); _header = new ThirdGenHeader(values, _buildInfo, buildString, _segmenter, _expander); }
private void LoadRegions(ITag modelTag, BlamCacheFile blamCacheFile) { IReader reader = blamCacheFile.Reader; StructureLayout renderModelLayout = blamCacheFile.GetLayout("render model"); reader.SeekTo(modelTag.MetaLocation.AsOffset()); renderModelValues = StructureReader.ReadStructure(blamCacheFile.Reader, renderModelLayout); ulong numRegions = renderModelValues.GetInteger("number of regions"); ulong regionTableAddress = renderModelValues.GetInteger("region table address"); long expandedRegionTableOffset = blamCacheFile.PointerToFileOffset((uint)regionTableAddress); StructureLayout modelRegionLayout = blamCacheFile.GetLayout("model region"); ResourceDatumIndex = new DatumIndex(renderModelValues.GetInteger("resource datum index")); Regions = new List <BlamRenderModelRegion>(); var x = blamCacheFile.Get().Resources.LoadResourceTable(blamCacheFile.Reader).Resources[ResourceDatumIndex.Index]; for (ulong regionNum = 0ul; regionNum < numRegions; regionNum++) { long regionPointer = expandedRegionTableOffset + (long)((ulong)modelRegionLayout.Size * regionNum); Regions.Add(new BlamRenderModelRegion(regionPointer, blamCacheFile)); } }
private void LoadMeshData(BlamCacheFile cacheFile, StructureLayout meshLayout) { IReader reader = cacheFile.Reader; StructureValueCollection meshValueCollection = StructureReader.ReadStructure(reader, meshLayout); ulong numSubmeshes = meshValueCollection.GetInteger("number of submeshes"); ulong numVertexGroups = meshValueCollection.GetInteger("number of vertex groups"); uint submeshTableOffset = (uint)cacheFile.PointerToFileOffset((uint)meshValueCollection.GetInteger("submesh table address")); uint vertexGroupTableOffset = (uint)cacheFile.PointerToFileOffset((uint)meshValueCollection.GetInteger("vertex group table address")); Submeshes = new List <BlamModelSubmesh>((int)numSubmeshes); for (int i = 0; i < Submeshes.Capacity; i++) { Submeshes.Add(new BlamModelSubmesh(submeshTableOffset, i, cacheFile)); } VertexGroups = new List <BlamModelVertexGroup>((int)numVertexGroups); for (int i = 0; i < VertexGroups.Capacity; i++) { VertexGroups.Add(new BlamModelVertexGroup(vertexGroupTableOffset, i, cacheFile)); } VertexType = (MeshVertexType)meshValueCollection.GetInteger("vertex format"); for (int i = 1; i <= VertexBufferIndices.Length; i++) { string indexerString = string.Format("vertex buffer {0}", i); VertexBufferIndices[i - 1] = (Int16)meshValueCollection.GetInteger(indexerString); } for (int i = 1; i <= IndexBufferIndices.Length; i++) { string indexerString = string.Format("index buffer {0}", i); IndexBufferIndices[i - 1] = (Int16)meshValueCollection.GetInteger(indexerString); } }
public void SaveChanges(IStream stream) { if (!_changed) { return; } var scenarioLayout = _buildInfo.Layouts.GetLayout("scnr"); stream.SeekTo(_scenario.MetaLocation.AsOffset()); var scenarioData = StructureReader.ReadStructure(stream, scenarioLayout); var oldCount = (int)scenarioData.GetInteger("simulation definition table count"); var oldAddress = (uint)scenarioData.GetInteger("simulation definition table address"); var entryLayout = _buildInfo.Layouts.GetLayout("simulation definition table element"); var newTable = _table.Select(SerializeTag); var newAddr = TagBlockWriter.WriteTagBlock(newTable, oldCount, oldAddress, _table.Count, entryLayout, _metaArea, _allocator, stream); scenarioData.SetInteger("simulation definition table count", (uint)_table.Count); scenarioData.SetInteger("simulation definition table address", (uint)newAddr); stream.SeekTo(_scenario.MetaLocation.AsOffset()); StructureWriter.WriteStructure(scenarioData, scenarioLayout, stream); _changed = false; }
/// <summary> /// Loads the string list. /// </summary> /// <param name="reader">The stream to read from.</param> private void Load(IReader reader) { reader.SeekTo(Tag.MetaLocation.AsOffset()); StructureValueCollection values = StructureReader.ReadStructure(reader, _layout); StructureValueCollection[] rangeValues = values.GetArray("language ranges"); Ranges = rangeValues.Select(v => StringRange.Deserialize(v)).ToArray(); }