public void GameSettingStringHandler( IMutagenReadStream stream, MajorRecordHeader major, BinaryFileProcessor.ConfigConstructor instr, List <KeyValuePair <uint, uint> > processedStrings, IStringsLookup overlay, ref uint newIndex) { stream.Position -= major.HeaderLength; var majorRec = stream.GetMajorRecordFrame(); if (!majorRec.TryLocateSubrecordFrame("EDID", out var edidRec)) { throw new ArgumentException(); } if (edidRec.Content[0] != (byte)'s') { return; } if (!majorRec.TryLocateSubrecordPinFrame("DATA", out var dataRec)) { throw new ArgumentException(); } stream.Position += dataRec.Location; AStringsAlignment.ProcessStringLink(stream, instr, processedStrings, overlay, ref newIndex); }
public void FillMajorRecords( OverlayStream stream, int finalPos, int offset, RecordTypeConverter?recordTypeConverter, RecordTypeFillWrapper fill) { int?lastParsed = null; Dictionary <RecordType, int>?recordParseCount = null; while (!stream.Complete && stream.Position < finalPos) { MajorRecordHeader majorMeta = stream.GetMajorRecord(); var minimumFinalPos = stream.Position + majorMeta.TotalLength; var parsed = fill( stream: stream, finalPos: finalPos, offset: offset, recordParseCount: recordParseCount, type: majorMeta.RecordType, lastParsed: lastParsed, recordTypeConverter: recordTypeConverter); if (!parsed.KeepParsing) { break; } if (parsed.DuplicateParseMarker != null) { if (recordParseCount == null) { recordParseCount = new Dictionary <RecordType, int>(); } recordParseCount[parsed.DuplicateParseMarker !.Value] = recordParseCount.GetOrAdd(parsed.DuplicateParseMarker !.Value) + 1;
public static void Sort( Func <IMutagenReadStream> streamCreator, Stream outputStream, GameRelease release) { using var inputStream = streamCreator(); using var locatorStream = streamCreator(); using var writer = new MutagenWriter(outputStream, release, dispose: false); while (!inputStream.Complete) { long noRecordLength; foreach (var grupLoc in RecordLocator.IterateBaseGroupLocations(locatorStream)) { noRecordLength = grupLoc.Value - inputStream.Position; inputStream.WriteTo(writer.BaseStream, (int)noRecordLength); // If complete overall, return if (inputStream.Complete) { return; } var groupMeta = inputStream.GetGroup(); var storage = new Dictionary <FormKey, List <ReadOnlyMemorySlice <byte> > >(); using (var grupFrame = new MutagenFrame(inputStream).SpawnWithLength(groupMeta.TotalLength)) { inputStream.WriteTo(writer.BaseStream, inputStream.MetaData.Constants.GroupConstants.HeaderLength); locatorStream.Position = grupLoc.Value; foreach (var rec in RecordLocator.ParseTopLevelGRUP(locatorStream)) { MajorRecordHeader majorMeta = inputStream.GetMajorRecord(); storage.GetOrAdd(rec.FormKey).Add(inputStream.ReadMemory(checked ((int)majorMeta.TotalLength), readSafe: true)); if (grupFrame.Complete) { continue; } if (inputStream.TryGetGroup(out var subGroupMeta)) { storage.GetOrAdd(rec.FormKey).Add(inputStream.ReadMemory(checked ((int)subGroupMeta.TotalLength), readSafe: true)); } } } // Sorts via Record ID (as opposed to just the first 6 bytes) foreach (var item in storage.OrderBy((i) => i.Key.ID)) { foreach (var bytes in item.Value) { writer.Write(bytes); } } } inputStream.WriteTo(writer.BaseStream, (int)inputStream.Remaining); } }
public static GroupMajorRecordCacheWrapper <T> Factory( IBinaryReadStream stream, ReadOnlyMemorySlice <byte> data, BinaryOverlayFactoryPackage package, int offset) { Dictionary <FormKey, int> locationDict = new Dictionary <FormKey, int>(); stream.Position -= package.MetaData.Constants.GroupConstants.HeaderLength; var groupMeta = stream.GetGroup(package.MetaData); var finalPos = stream.Position + groupMeta.TotalLength; stream.Position += package.MetaData.Constants.GroupConstants.HeaderLength; // Parse MajorRecord locations ObjectType?lastParsed = default; while (stream.Position < finalPos) { VariableHeader varMeta = package.MetaData.Constants.NextRecordVariableMeta(stream.RemainingMemory); if (varMeta.IsGroup) { if (lastParsed != ObjectType.Record) { throw new DataMisalignedException("Unexpected Group encountered which was not after a major record: " + GroupRecordTypeGetter <T> .GRUP_RECORD_TYPE); } stream.Position += checked ((int)varMeta.TotalLength); lastParsed = ObjectType.Group; } else { MajorRecordHeader majorMeta = package.MetaData.Constants.MajorRecord(stream.RemainingMemory); if (majorMeta.RecordType != GroupRecordTypeGetter <T> .GRUP_RECORD_TYPE) { throw new DataMisalignedException("Unexpected type encountered when parsing MajorRecord locations: " + majorMeta.RecordType); } var formKey = FormKey.Factory(package.MetaData.MasterReferences !, majorMeta.FormID.Raw); locationDict.Add(formKey, checked ((int)(stream.Position - offset))); stream.Position += checked ((int)majorMeta.TotalLength); lastParsed = ObjectType.Record; } } return(new GroupMajorRecordCacheWrapper <T>( locationDict, data, package)); }
public void PerkStringHandler( IMutagenReadStream stream, MajorRecordHeader major, BinaryFileProcessor.ConfigConstructor instr, List <KeyValuePair <uint, uint> > processedStrings, IStringsLookup overlay, ref uint newIndex) { var majorCompletePos = stream.Position + major.ContentLength; long?lastepft = null; while (stream.Position < majorCompletePos) { var sub = stream.GetSubrecord(); switch (sub.RecordTypeInt) { case RecordTypeInts.FULL: case RecordTypeInts.EPF2: AStringsAlignment.ProcessStringLink(stream, instr, processedStrings, overlay, ref newIndex); break; case RecordTypeInts.EPFT: lastepft = stream.Position; break; case RecordTypeInts.EPFD: var pos = stream.Position; stream.Position = lastepft.Value; var epftFrame = stream.ReadSubrecordFrame(); if (epftFrame.Content[0] == (byte)APerkEntryPointEffect.ParameterType.LString) { stream.Position = pos; AStringsAlignment.ProcessStringLink(stream, instr, processedStrings, overlay, ref newIndex); } stream.Position = pos; break; default: break; } stream.Position += sub.TotalLength; } }
private void Align( IMutagenReadStream stream, MajorRecordHeader major, BinaryFileProcessor.ConfigConstructor instr, List <KeyValuePair <uint, uint> > processedStrings, IStringsLookup overlay, ref uint newIndex) { var majorCompletePos = stream.Position + major.ContentLength; while (stream.Position < majorCompletePos) { var sub = stream.GetSubrecord(); if (StringTypes.Contains(sub.RecordType)) { ProcessStringLink(stream, instr, processedStrings, overlay, ref newIndex); } stream.Position += sub.TotalLength; } }
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); } }
public static void Sort( Func <Stream> streamCreator, Stream outputStream, GameMode gameMode) { var meta = new ParsingBundle(GameConstants.Get(gameMode)); using var inputStream = new MutagenBinaryReadStream(streamCreator(), meta); using var locatorStream = new MutagenBinaryReadStream(streamCreator(), meta); using var writer = new MutagenWriter(outputStream, gameMode, dispose: false); while (!inputStream.Complete) { long noRecordLength; foreach (var grupLoc in RecordLocator.IterateBaseGroupLocations(locatorStream)) { noRecordLength = grupLoc.Value - inputStream.Position; inputStream.WriteTo(writer.BaseStream, (int)noRecordLength); // If complete overall, return if (inputStream.Complete) { return; } var groupMeta = inputStream.GetGroup(); if (!groupMeta.IsGroup) { throw new ArgumentException(); } var storage = new Dictionary <FormID, List <ReadOnlyMemorySlice <byte> > >(); using (var grupFrame = new MutagenFrame(inputStream).SpawnWithLength(groupMeta.TotalLength)) { inputStream.WriteTo(writer.BaseStream, meta.Constants.GroupConstants.HeaderLength); locatorStream.Position = grupLoc.Value; foreach (var rec in RecordLocator.ParseTopLevelGRUP(locatorStream)) { MajorRecordHeader majorMeta = inputStream.GetMajorRecord(); storage.TryCreateValue(rec.FormID).Add(inputStream.ReadMemory(checked ((int)majorMeta.TotalLength), readSafe: true)); if (grupFrame.Complete) { continue; } GroupHeader subGroupMeta = inputStream.GetGroup(); if (subGroupMeta.IsGroup) { storage.TryCreateValue(rec.FormID).Add(inputStream.ReadMemory(checked ((int)subGroupMeta.TotalLength), readSafe: true)); } } } foreach (var item in storage.OrderBy((i) => i.Key.ID)) { foreach (var bytes in item.Value) { writer.Write(bytes); } } } inputStream.WriteTo(writer.BaseStream, (int)inputStream.Remaining); } }