internal HierarchicalSchemaReference(HierarchicalSchemaVersionInfo versionInfo, uint unknown1, uint unknown2, string uniqueName) { VersionInfo = versionInfo; Unknown1 = unknown1; Unknown2 = unknown2; UniqueName = uniqueName; }
protected override bool ParseSectionContent(BinaryReader binaryReader) { long sectionPosition = (binaryReader.BaseStream as SubStream)?.SubStreamPosition ?? 0; ushort environmentReferencesLength = binaryReader.ReadUInt16(); ushort numEnvironmentReferences = binaryReader.ReadUInt16(); if (!version2) { if (environmentReferencesLength == 0 || numEnvironmentReferences == 0) { throw new InvalidDataException(); } } else { if (environmentReferencesLength != 0 || numEnvironmentReferences != 0) { throw new InvalidDataException(); } } SchemaSection = new SectionRef <HierarchicalSchemaSection>(binaryReader.ReadUInt16()); ushort hierarchicalSchemaReferenceLength = binaryReader.ReadUInt16(); DecisionInfoSection = new SectionRef <DecisionInfoSection>(binaryReader.ReadUInt16()); ushort resourceValueTypeTableSize = binaryReader.ReadUInt16(); ushort ItemToItemInfoGroupCount = binaryReader.ReadUInt16(); ushort itemInfoGroupCount = binaryReader.ReadUInt16(); uint itemInfoCount = binaryReader.ReadUInt32(); uint numCandidates = binaryReader.ReadUInt32(); uint dataLength = binaryReader.ReadUInt32(); uint largeTableLength = binaryReader.ReadUInt32(); if (PriFile.GetSectionByRef(DecisionInfoSection) == null) { return(false); } byte[] environmentReferencesData = binaryReader.ReadBytes(environmentReferencesLength); byte[] schemaReferenceData = binaryReader.ReadBytes(hierarchicalSchemaReferenceLength); if (schemaReferenceData.Length != 0) { using (BinaryReader r = new BinaryReader(new MemoryStream(schemaReferenceData, false))) { ushort majorVersion = r.ReadUInt16(); ushort minorVersion = r.ReadUInt16(); r.ExpectUInt32(0); uint checksum = r.ReadUInt32(); uint numScopes = r.ReadUInt32(); uint numItems = r.ReadUInt32(); HierarchicalSchemaVersionInfo versionInfo = new HierarchicalSchemaVersionInfo(majorVersion, minorVersion, checksum, numScopes, numItems); ushort stringDataLength = r.ReadUInt16(); r.ExpectUInt16(0); uint unknown1 = r.ReadUInt32(); uint unknown2 = r.ReadUInt32(); string uniqueName = r.ReadNullTerminatedString(Encoding.Unicode); if (uniqueName.Length != stringDataLength - 1) { throw new InvalidDataException(); } HierarchicalSchemaReference = new HierarchicalSchemaReference(versionInfo, unknown1, unknown2, uniqueName); } } List <ResourceValueType> resourceValueTypeTable = new List <ResourceValueType>(resourceValueTypeTableSize); for (int i = 0; i < resourceValueTypeTableSize; i++) { binaryReader.ExpectUInt32(4); ResourceValueType resourceValueType = (ResourceValueType)binaryReader.ReadUInt32(); resourceValueTypeTable.Add(resourceValueType); } List <ItemToItemInfoGroup> itemToItemInfoGroups = new List <ItemToItemInfoGroup>(); for (int i = 0; i < ItemToItemInfoGroupCount; i++) { ushort firstItem = binaryReader.ReadUInt16(); ushort itemInfoGroup = binaryReader.ReadUInt16(); itemToItemInfoGroups.Add(new ItemToItemInfoGroup(firstItem, itemInfoGroup)); } List <ItemInfoGroup> itemInfoGroups = new List <ItemInfoGroup>(); for (int i = 0; i < itemInfoGroupCount; i++) { ushort groupSize = binaryReader.ReadUInt16(); ushort firstItemInfo = binaryReader.ReadUInt16(); itemInfoGroups.Add(new ItemInfoGroup(groupSize, firstItemInfo)); } List <ItemInfo> itemInfos = new List <ItemInfo>(); for (int i = 0; i < itemInfoCount; i++) { ushort decision = binaryReader.ReadUInt16(); ushort firstCandidate = binaryReader.ReadUInt16(); itemInfos.Add(new ItemInfo(decision, firstCandidate)); } byte[] largeTable = binaryReader.ReadBytes((int)largeTableLength); if (largeTable.Length != 0) { using (BinaryReader r = new BinaryReader(new MemoryStream(largeTable, false))) { uint ItemToItemInfoGroupCountLarge = r.ReadUInt32(); uint itemInfoGroupCountLarge = r.ReadUInt32(); uint itemInfoCountLarge = r.ReadUInt32(); for (int i = 0; i < ItemToItemInfoGroupCountLarge; i++) { uint firstItem = r.ReadUInt32(); uint itemInfoGroup = r.ReadUInt32(); itemToItemInfoGroups.Add(new ItemToItemInfoGroup(firstItem, itemInfoGroup)); } for (int i = 0; i < itemInfoGroupCountLarge; i++) { uint groupSize = r.ReadUInt32(); uint firstItemInfo = r.ReadUInt32(); itemInfoGroups.Add(new ItemInfoGroup(groupSize, firstItemInfo)); } for (int i = 0; i < itemInfoCountLarge; i++) { uint decision = r.ReadUInt32(); uint firstCandidate = r.ReadUInt32(); itemInfos.Add(new ItemInfo(decision, firstCandidate)); } if (r.BaseStream.Position != r.BaseStream.Length) { throw new InvalidDataException(); } } } List <CandidateInfo> candidateInfos = new List <CandidateInfo>((int)numCandidates); for (int i = 0; i < numCandidates; i++) { byte type = binaryReader.ReadByte(); if (type == 0x01) { ResourceValueType resourceValueType = resourceValueTypeTable[binaryReader.ReadByte()]; ushort sourceFileIndex = binaryReader.ReadUInt16(); ushort valueLocation = binaryReader.ReadUInt16(); ushort dataItemSection = binaryReader.ReadUInt16(); candidateInfos.Add(new CandidateInfo(resourceValueType, sourceFileIndex, valueLocation, dataItemSection)); } else if (type == 0x00) { ResourceValueType resourceValueType = resourceValueTypeTable[binaryReader.ReadByte()]; ushort length = binaryReader.ReadUInt16(); uint stringOffset = binaryReader.ReadUInt32(); candidateInfos.Add(new CandidateInfo(resourceValueType, length, stringOffset)); } else { throw new InvalidDataException(); } } long stringDataStartOffset = binaryReader.BaseStream.Position; Dictionary <ushort, CandidateSet> candidateSets = new Dictionary <ushort, CandidateSet>(); for (int itemToItemInfoGroupIndex = 0; itemToItemInfoGroupIndex < itemToItemInfoGroups.Count; itemToItemInfoGroupIndex++) { ItemToItemInfoGroup itemToItemInfoGroup = itemToItemInfoGroups[itemToItemInfoGroupIndex]; ItemInfoGroup itemInfoGroup; if (itemToItemInfoGroup.ItemInfoGroup < itemInfoGroups.Count) { itemInfoGroup = itemInfoGroups[(int)itemToItemInfoGroup.ItemInfoGroup]; } else { itemInfoGroup = new ItemInfoGroup(1, (uint)(itemToItemInfoGroup.ItemInfoGroup - itemInfoGroups.Count)); } for (uint itemInfoIndex = itemInfoGroup.FirstItemInfo; itemInfoIndex < itemInfoGroup.FirstItemInfo + itemInfoGroup.GroupSize; itemInfoIndex++) { ItemInfo itemInfo = itemInfos[(int)itemInfoIndex]; ushort decisionIndex = (ushort)itemInfo.Decision; Decision decision = PriFile.GetSectionByRef(DecisionInfoSection).Decisions[decisionIndex]; List <Candidate> candidates = new List <Candidate>(decision.QualifierSets.Count); for (int i = 0; i < decision.QualifierSets.Count; i++) { CandidateInfo candidateInfo = candidateInfos[(int)itemInfo.FirstCandidate + i]; if (candidateInfo.Type == 0x01) { ReferencedFileRef?sourceFile; if (candidateInfo.SourceFileIndex == 0) { sourceFile = null; } else { sourceFile = new ReferencedFileRef(candidateInfo.SourceFileIndex - 1); } candidates.Add(new Candidate(decision.QualifierSets[i].Index, candidateInfo.ResourceValueType, sourceFile, new DataItemRef(new SectionRef <DataItemSection>(candidateInfo.DataItemSection), candidateInfo.DataItemIndex))); } else if (candidateInfo.Type == 0x00) { ByteSpan data = new ByteSpan(sectionPosition + stringDataStartOffset + candidateInfo.DataOffset, candidateInfo.DataLength); candidates.Add(new Candidate(decision.QualifierSets[i].Index, candidateInfo.ResourceValueType, data)); } } ushort resourceMapItemIndex = (ushort)(itemToItemInfoGroup.FirstItem + (itemInfoIndex - itemInfoGroup.FirstItemInfo)); CandidateSet candidateSet = new CandidateSet( new ResourceMapItemRef(SchemaSection, resourceMapItemIndex), decisionIndex, candidates); candidateSets.Add(resourceMapItemIndex, candidateSet); } } CandidateSets = candidateSets; return(true); }
protected override bool ParseSectionContent(BinaryReader binaryReader) { if (binaryReader.BaseStream.Length == 0) { Version = null; UniqueName = null; Name = null; Scopes = Array.Empty <ResourceMapScope>(); Items = Array.Empty <ResourceMapItem>(); return(true); } binaryReader.ExpectUInt16(1); ushort uniqueNameLength = binaryReader.ReadUInt16(); ushort nameLength = binaryReader.ReadUInt16(); binaryReader.ExpectUInt16(0); bool extendedHNames; if (extendedVersion) { switch (new string(binaryReader.ReadChars(16))) { case "[def_hnamesx] \0": extendedHNames = true; break; case "[def_hnames] \0": extendedHNames = false; break; default: throw new InvalidDataException(); } } else { extendedHNames = false; } // hierarchical schema version info ushort majorVersion = binaryReader.ReadUInt16(); ushort minorVersion = binaryReader.ReadUInt16(); binaryReader.ExpectUInt32(0); uint checksum = binaryReader.ReadUInt32(); uint numScopes = binaryReader.ReadUInt32(); uint numItems = binaryReader.ReadUInt32(); Version = new HierarchicalSchemaVersionInfo(majorVersion, minorVersion, checksum, numScopes, numItems); UniqueName = binaryReader.ReadNullTerminatedString(Encoding.Unicode); Name = binaryReader.ReadNullTerminatedString(Encoding.Unicode); if (UniqueName.Length != uniqueNameLength - 1 || Name.Length != nameLength - 1) { throw new InvalidDataException(); } binaryReader.ExpectUInt16(0); ushort maxFullPathLength = binaryReader.ReadUInt16(); binaryReader.ExpectUInt16(0); binaryReader.ExpectUInt32(numScopes + numItems); binaryReader.ExpectUInt32(numScopes); binaryReader.ExpectUInt32(numItems); uint unicodeDataLength = binaryReader.ReadUInt32(); binaryReader.ReadUInt32(); // meaning unknown if (extendedHNames) { binaryReader.ReadUInt32(); // meaning unknown } List <ScopeAndItemInfo> scopeAndItemInfos = new List <ScopeAndItemInfo>((int)(numScopes + numItems)); for (int i = 0; i < numScopes + numItems; i++) { ushort parent = binaryReader.ReadUInt16(); ushort fullPathLength = binaryReader.ReadUInt16(); char uppercaseFirstChar = (char)binaryReader.ReadUInt16(); byte nameLength2 = binaryReader.ReadByte(); byte flags = binaryReader.ReadByte(); uint nameOffset = binaryReader.ReadUInt16() | (uint)((flags & 0xF) << 16); ushort index = binaryReader.ReadUInt16(); bool isScope = (flags & 0x10) != 0; bool nameInAscii = (flags & 0x20) != 0; scopeAndItemInfos.Add(new ScopeAndItemInfo(parent, fullPathLength, isScope, nameInAscii, nameOffset, index)); } List <ScopeExInfo> scopeExInfos = new List <ScopeExInfo>((int)numScopes); for (int i = 0; i < numScopes; i++) { ushort scopeIndex = binaryReader.ReadUInt16(); ushort childCount = binaryReader.ReadUInt16(); ushort firstChildIndex = binaryReader.ReadUInt16(); binaryReader.ExpectUInt16(0); scopeExInfos.Add(new ScopeExInfo(scopeIndex, childCount, firstChildIndex)); } ushort[] itemIndexPropertyToIndex = new ushort[numItems]; for (int i = 0; i < numItems; i++) { itemIndexPropertyToIndex[i] = binaryReader.ReadUInt16(); } long unicodeDataOffset = binaryReader.BaseStream.Position; long asciiDataOffset = binaryReader.BaseStream.Position + unicodeDataLength * 2; ResourceMapScope[] scopes = new ResourceMapScope[numScopes]; ResourceMapItem[] items = new ResourceMapItem[numItems]; for (int i = 0; i < numScopes + numItems; i++) { long pos; if (scopeAndItemInfos[i].NameInAscii) { pos = asciiDataOffset + scopeAndItemInfos[i].NameOffset; } else { pos = unicodeDataOffset + scopeAndItemInfos[i].NameOffset * 2; } binaryReader.BaseStream.Seek(pos, SeekOrigin.Begin); string name; if (scopeAndItemInfos[i].FullPathLength != 0) { name = binaryReader.ReadNullTerminatedString(scopeAndItemInfos[i].NameInAscii ? Encoding.ASCII : Encoding.Unicode); } else { name = string.Empty; } ushort index = scopeAndItemInfos[i].Index; if (scopeAndItemInfos[i].IsScope) { if (scopes[index] != null) { throw new InvalidDataException(); } scopes[index] = new ResourceMapScope(index, null, name); } else { if (items[index] != null) { throw new InvalidDataException(); } items[index] = new ResourceMapItem(index, null, name); } } for (int i = 0; i < numScopes + numItems; i++) { ushort index = scopeAndItemInfos[i].Index; ushort parent = scopeAndItemInfos[scopeAndItemInfos[i].Parent].Index; if (parent != 0xFFFF) { if (scopeAndItemInfos[i].IsScope) { if (parent != index) { scopes[index].Parent = scopes[parent]; } } else { items[index].Parent = scopes[parent]; } } } for (int i = 0; i < numScopes; i++) { List <ResourceMapEntry> children = new List <ResourceMapEntry>(scopeExInfos[i].ChildCount); for (int j = 0; j < scopeExInfos[i].ChildCount; j++) { ScopeAndItemInfo saiInfo = scopeAndItemInfos[scopeExInfos[i].FirstChildIndex + j]; if (saiInfo.IsScope) { children.Add(scopes[saiInfo.Index]); } else { children.Add(items[saiInfo.Index]); } } scopes[i].Children = children; } Scopes = scopes; Items = items; //if (checksum != ComputeHierarchicalSchemaVersionInfoChecksum()) // throw new Exception(); return(true); }