private static void AlignWorldChildren( IMutagenReadStream reader, MutagenWriter writer) { reader.WriteTo(writer.BaseStream, 4); ReadOnlyMemorySlice <byte>? roadStorage = null; ReadOnlyMemorySlice <byte>? cellStorage = null; List <ReadOnlyMemorySlice <byte> > grupBytes = new List <ReadOnlyMemorySlice <byte> >(); for (int i = 0; i < 3; i++) { RecordType type = HeaderTranslation.GetNextRecordType(reader); switch (type.Type) { case "ROAD": roadStorage = reader.ReadMemory(checked ((int)reader.GetMajorRecord().TotalLength)); break; case "CELL": if (cellStorage != null) { throw new ArgumentException(); } var cellMajorMeta = reader.GetMajorRecord(); var startPos = reader.Position; reader.Position += cellMajorMeta.HeaderLength; long cellGroupLen = 0; if (reader.TryGetGroup(out var cellSubGroupMeta) && cellSubGroupMeta.GroupType == writer.MetaData.Constants.GroupConstants.Cell.TopGroupType) { cellGroupLen = cellSubGroupMeta.TotalLength; } reader.Position = startPos; cellStorage = reader.ReadMemory(checked ((int)(cellMajorMeta.TotalLength + cellGroupLen))); break; case "GRUP": if (roadStorage != null && cellStorage != null) { i = 3; // end loop continue; } grupBytes.Add(reader.ReadMemory(checked ((int)reader.GetGroup().TotalLength))); break; case "WRLD": i = 3; // end loop continue; default: throw new NotImplementedException(); } } if (roadStorage != null) { writer.Write(roadStorage.Value); } if (cellStorage != null) { writer.Write(cellStorage.Value); } foreach (var item in grupBytes) { writer.Write(item); } }
private static void AlignWorldChildren( IMutagenReadStream reader, MutagenWriter writer) { reader.WriteTo(writer.BaseStream, 4); ReadOnlyMemorySlice <byte>?roadStorage = null; ReadOnlyMemorySlice <byte>?cellStorage = null; var grupBytes = new List <ReadOnlyMemorySlice <byte> >(); for (int i = 0; i < 3; i++) { MajorRecordHeader majorMeta = reader.GetMajorRecord(); switch (majorMeta.RecordType.Type) { case "ROAD": roadStorage = reader.ReadMemory(checked ((int)majorMeta.TotalLength)); break; case "CELL": if (cellStorage != null) { throw new ArgumentException(); } var startPos = reader.Position; var cellMeta = reader.GetMajorRecord(); reader.Position += cellMeta.TotalLength; var cellGroupMeta = reader.GetGroup(); long cellGrupLen; if (cellGroupMeta.IsGroup && cellGroupMeta.GroupType == (int)GroupTypeEnum.CellChildren) { cellGrupLen = cellGroupMeta.TotalLength; } else { cellGrupLen = 0; } reader.Position = startPos; cellStorage = reader.ReadMemory(checked ((int)(cellMeta.TotalLength + cellGrupLen))); break; case "GRUP": if (roadStorage != null && cellStorage != null) { i = 3; // end loop continue; } var groupMeta = reader.GetGroup(); grupBytes.Add(reader.ReadMemory(checked ((int)groupMeta.TotalLength))); break; case "WRLD": i = 3; // end loop continue; default: throw new NotImplementedException(); } } if (roadStorage != null) { writer.Write(roadStorage.Value); } if (cellStorage != null) { writer.Write(cellStorage.Value); } foreach (var item in grupBytes) { writer.Write(item); } }
private static void AlignMajorRecordsByRules( IMutagenReadStream inputStream, MutagenWriter writer, AlignmentRules alignmentRules, RecordLocatorResults fileLocs) { while (!inputStream.Complete) { // Import until next listed major record long noRecordLength; if (fileLocs.ListedRecords.TryGetInDirection( inputStream.Position, higher: true, result: out var nextRec)) { var recordLocation = fileLocs.ListedRecords.Keys[nextRec.Key]; noRecordLength = recordLocation - inputStream.Position; } else { noRecordLength = inputStream.Remaining; } inputStream.WriteTo(writer.BaseStream, (int)noRecordLength); // If complete overall, return if (inputStream.Complete) { break; } var recType = HeaderTranslation.ReadNextRecordType( inputStream, out var len); if (!alignmentRules.StopMarkers.TryGetValue(recType, out var stopMarkers)) { stopMarkers = null; } writer.Write(recType.TypeInt); writer.Write(len); if (!alignmentRules.Alignments.TryGetValue(recType, out var alignments)) { inputStream.WriteTo(writer.BaseStream, inputStream.MetaData.Constants.MajorConstants.LengthAfterLength + len); continue; } inputStream.WriteTo(writer.BaseStream, inputStream.MetaData.Constants.MajorConstants.LengthAfterLength); var writerEndPos = writer.Position + len; var endPos = inputStream.Position + len; var dataDict = new Dictionary <RecordType, ReadOnlyMemorySlice <byte> >(); ReadOnlyMemorySlice <byte>?rest = null; while (inputStream.Position < endPos) { var subType = HeaderTranslation.GetNextSubrecordType( inputStream, out var _); if (stopMarkers?.Contains(subType) ?? false) { rest = inputStream.ReadMemory((int)(endPos - inputStream.Position), readSafe: true); break; } if (!alignments.TryGetValue(subType, out var rule)) { throw new ArgumentException($"Encountered an unknown record: {subType}"); } dataDict.Add(subType, rule.GetBytes(inputStream)); } foreach (var alignment in alignmentRules.Alignments[recType]) { if (dataDict.TryGetValue( alignment.Key, out var data)) { writer.Write(data); dataDict.Remove(alignment.Key); } } if (dataDict.Count > 0) { throw new ArgumentException($"Encountered an unknown record: {dataDict.First().Key}"); } if (rest != null) { writer.Write(rest.Value); } if (writer.Position != writerEndPos) { throw new ArgumentException("Record alignment changed length"); } } }
private void ProcessRegions( IMutagenReadStream stream, MajorRecordFrame majorFrame, long fileOffset) { if (!majorFrame.TryLocateSubrecordFrame(RecordTypes.RDAT, out var rdatFrame, out var rdatIndex)) { return; } int amount = 0; SortedList <uint, RangeInt64> rdats = new SortedList <uint, RangeInt64>(); bool foundNext = true; while (foundNext) { foundNext = majorFrame.TryLocateSubrecordFrame(RecordTypes.RDAT, offset: rdatIndex + rdatFrame.TotalLength, out var nextRdatFrame, out var nextRdatIndex); var index = rdatFrame.Content.UInt32(); rdats[index] = new RangeInt64( rdatIndex + fileOffset, foundNext ? nextRdatIndex - 1 + fileOffset : fileOffset + majorFrame.TotalLength - 1); rdatFrame = nextRdatFrame; rdatIndex = nextRdatIndex; } foreach (var item in rdats.Reverse()) { if (item.Key == (int)RegionData.RegionDataType.Icon) { continue; } this._instructions.SetMove( loc: fileOffset + majorFrame.TotalLength, section: item.Value); } if (rdats.ContainsKey((int)RegionData.RegionDataType.Icon)) { // Need to create icon record if (!majorFrame.TryLocateSubrecordFrame("EDID", out var edidFrame, out var edidLoc)) { throw new ArgumentException(); } var locToPlace = fileOffset + edidLoc + edidFrame.TotalLength; // Get icon string var iconLoc = rdats[(int)RegionData.RegionDataType.Icon]; stream.Position = iconLoc.Min + 20; var iconStr = BinaryStringUtility.ToZString(stream.ReadMemory((int)(iconLoc.Max - stream.Position)), MutagenEncodingProvider._1252); // Get icon bytes MemoryStream memStream = new MemoryStream(); using (var writer = new MutagenWriter(memStream, this.GameRelease)) { using (HeaderExport.Header( writer, new RecordType("ICON"), ObjectType.Subrecord)) { StringBinaryTranslation.Instance.Write(writer, iconStr, StringBinaryType.NullTerminate); } } var arr = memStream.ToArray(); this._instructions.SetAddition( loc: locToPlace, addition: arr); this._instructions.SetRemove( section: iconLoc); amount += arr.Length; amount -= (int)iconLoc.Width; } ProcessLengths( majorFrame, amount, fileOffset); }