public static BodyTemplate ParseBod2(ushort version, IMutagenReadStream frame, SubrecordHeader subrecordHeader) { var len = subrecordHeader.ContentLength; if (version <= 22 && len <= 8) { throw SubrecordException.Create("BOD2 can not be parsed on Form Versions <= 22 with length <= 8", RecordTypes.BOD2); } var item = new BodyTemplate(); item.ActsLike44 = true; item.FirstPersonFlags = EnumBinaryTranslation <BipedObjectFlag, IMutagenReadStream, MutagenWriter> .Instance.Parse( reader : frame, length : 4); if (len == 8) { item.ArmorType = EnumBinaryTranslation <ArmorType, IMutagenReadStream, MutagenWriter> .Instance.Parse( reader : frame, length : 4); } else { item.Flags = EnumBinaryTranslation <BodyTemplate.Flag, IMutagenReadStream, MutagenWriter> .Instance.Parse( reader : frame, length : 4); item.ArmorType = EnumBinaryTranslation <ArmorType, IMutagenReadStream, MutagenWriter> .Instance.Parse( reader : frame, length : 4); } return(item); }
public static int[] GetListCounts(IMutagenReadStream frame) { var subFrame = frame.ReadSubrecord(RecordTypes.XCNT); if (subFrame.ContentLength != 20) { throw new ArgumentException($"XCNT record had unexpected length {subFrame.ContentLength} != 20"); } int[] ret = new int[5]; for (int i = 0; i < ret.Length; i++) { ret[i] = checked ((int)frame.ReadUInt32()); } var formIDCount = ret.Sum(); var dataHeader = frame.ReadSubrecord(RecordTypes.DATA); var expectedLen = formIDCount * 4; if (dataHeader.ContentLength != expectedLen) { throw new ArgumentException($"DATA record had unexpected length that did not match previous counts {dataHeader.ContentLength} != {expectedLen}"); } return(ret); }
public static long ParseRecord(IMutagenReadStream reader) { reader.Position += 4; var len = checked ((int)reader.ReadUInt32()); return(reader.Position + len + reader.MetaData.Constants.MajorConstants.LengthAfterLength); }
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 static Furniture.Flag FillBinaryFlags2(IMutagenReadStream stream, Func <int, FurnitureMarker> getter, Furniture.Flag?existingFlag) { var subFrame = stream.ReadSubrecordFrame(); uint raw = BinaryPrimitives.ReadUInt32LittleEndian(subFrame.Content); // Clear out upper bytes of existing flags var curFlags = (uint)(existingFlag ?? 0); curFlags &= ~UpperFlagsMask; // Add in new upper flags uint upperFlags = raw & UpperFlagsMask; var ret = (Furniture.Flag)(curFlags | upperFlags); // Create marker objects for sit flags uint markers = raw & 0x00FF_FFFF; uint indexToCheck = 1; for (int i = 0; i < NumSits; i++) { var has = EnumExt.HasFlag(markers, indexToCheck); indexToCheck <<= 1; if (!has) { continue; } var marker = getter(i); marker.Enabled = true; } return(ret); }
public static void ProcessStringLink( IMutagenReadStream stream, BinaryFileProcessor.ConfigConstructor instr, List <KeyValuePair <uint, uint> > processedStrings, IStringsLookup overlay, ref uint newIndex) { var sub = stream.ReadSubrecord(); if (sub.ContentLength != 4) { throw new ArgumentException(); } var curIndex = BinaryPrimitives.ReadUInt32LittleEndian(stream.GetSpan(4)); if (!overlay.TryLookup(curIndex, out var str)) { instr.SetSubstitution(stream.Position, new byte[4]); } else if (curIndex != 0) { var assignedIndex = newIndex++; processedStrings.Add(new KeyValuePair <uint, uint>(curIndex, assignedIndex)); byte[] b = new byte[4]; BinaryPrimitives.WriteUInt32LittleEndian(b, assignedIndex); instr.SetSubstitution(stream.Position, b); } stream.Position -= sub.HeaderLength; }
public override ReadOnlyMemorySlice <byte> GetBytes(IMutagenReadStream inputStream) { var dataList = new List <byte[]>(); MutagenWriter stream; while (!inputStream.Complete) { var subType = HeaderTranslation.ReadNextSubrecordType( inputStream, out var subLen); if (!SubTypes.Contains(subType)) { inputStream.Position -= 6; break; } var data = new byte[subLen + 6]; stream = new MutagenWriter(new MemoryStream(data), inputStream.MetaData.Constants); using (HeaderExport.Subrecord(stream, subType)) { inputStream.WriteTo(stream.BaseStream, subLen); } dataList.Add(data); } byte[] ret = new byte[dataList.Sum((d) => d.Length)]; stream = new MutagenWriter(new MemoryStream(ret), inputStream.MetaData.Constants); foreach (var data in dataList) { stream.Write(data); } return(ret); }
private void ProcessCells( IMutagenReadStream stream, MajorRecordFrame majorFrame, long fileOffset) { var formKey = FormKey.Factory(stream.MetaData.MasterReferences !, majorFrame.FormID.Raw); CleanEmptyCellGroups( stream, formKey, fileOffset, numSubGroups: 2); // Process odd length changing flags var sizeChange = 0; if (majorFrame.TryLocateSubrecordFrame(RecordTypes.DATA, out var dataRec, out var dataIndex)) { if (dataRec.ContentLength == 1) { _Instructions.SetSubstitution( fileOffset + dataIndex + 4, 2); _Instructions.SetAddition( fileOffset + dataIndex + stream.MetaData.Constants.SubConstants.HeaderLength + 1, new byte[] { 0 }); sizeChange++; } } ProcessLengths( majorFrame, sizeChange, fileOffset); }
public static RecordType ReadNextSubrecordType( IMutagenReadStream reader, out int contentLength) { return(ReadNextRecordType( reader, reader.MetaData.Constants.SubConstants.LengthLength, out contentLength)); }
public static long GetSubrecord( IMutagenReadStream reader, RecordType expectedHeader) { var ret = ParseSubrecord( reader, expectedHeader); reader.Position -= reader.MetaData.Constants.SubConstants.HeaderLength; return(ret); }
private void FixVMADScriptIDs(IMutagenReadStream stream, long fileOffset, ushort objectFormat) { // skip name var len = stream.ReadUInt16(); stream.Position += len; // Skip flags stream.Position += 1; var propCount = stream.ReadUInt16(); for (int j = 0; j < propCount; j++) { // skip name len = stream.ReadUInt16(); stream.Position += len; var type = (ScriptProperty.Type)stream.ReadUInt8(); // skip flags stream.Position += 1; // Going to cheat here, and use the autogenerated records ScriptProperty prop = type switch { ScriptProperty.Type.None => new ScriptProperty(), ScriptProperty.Type.Object => new ScriptObjectProperty(), ScriptProperty.Type.String => new ScriptStringProperty(), ScriptProperty.Type.Int => new ScriptIntProperty(), ScriptProperty.Type.Float => new ScriptFloatProperty(), ScriptProperty.Type.Bool => new ScriptBoolProperty(), ScriptProperty.Type.ArrayOfObject => new ScriptObjectListProperty(), ScriptProperty.Type.ArrayOfString => new ScriptStringListProperty(), ScriptProperty.Type.ArrayOfInt => new ScriptIntListProperty(), ScriptProperty.Type.ArrayOfFloat => new ScriptFloatListProperty(), ScriptProperty.Type.ArrayOfBool => new ScriptBoolListProperty(), _ => throw new NotImplementedException(), }; switch (prop) { case ScriptObjectProperty obj: FixObjectPropertyIDs(stream, fileOffset, objectFormat); break; case ScriptObjectListProperty objList: var count = stream.ReadUInt32(); for (int i = 0; i < count; i++) { FixObjectPropertyIDs(stream, fileOffset, objectFormat); } break; default: prop.CopyInFromBinary(new MutagenFrame(stream)); break; } } }
public static void FillCloudTexture(IMutagenReadStream stream, RecordType nextRecordType, string?[] textures) { int layer = nextRecordType.TypeInt - TextureIntBase; if (layer > 29 || layer < 0) { throw new ArgumentException(); } var subRec = stream.ReadSubrecordFrame(); textures[layer] = BinaryStringUtility.ProcessWholeToZString(subRec.Content, stream.MetaData.Encodings.NonTranslated); }
private void ProcessDialogTopics( IMutagenReadStream stream, MajorRecordFrame majorFrame, long fileOffset) { var formKey = FormKey.Factory(stream.MetaData.MasterReferences !, majorFrame.FormID.Raw); CleanEmptyDialogGroups( stream, formKey, fileOffset); }
public static RecordType GetNextSubrecordType( IMutagenReadStream reader, out int contentLength, int offset = 0) { var ret = new RecordType(reader.GetInt32(offset)); contentLength = GetContentLength( reader: reader, lengthLength: reader.MetaData.Constants.SubConstants.LengthLength, offset: Constants.HeaderLength + offset); return(ret); }
private void ProcessCells( IMutagenReadStream stream, MajorRecordFrame majorFrame, long fileOffset) { var formKey = FormKey.Factory(stream.MetaData.MasterReferences !, majorFrame.FormID.Raw); CleanEmptyCellGroups( stream, formKey, fileOffset, numSubGroups: 3); }
public static long ParseRecord( IMutagenReadStream reader, RecordType expectedHeader) { if (!TryParse( reader, expectedHeader, out var contentLength, reader.MetaData.Constants.MajorConstants.LengthLength)) { throw new ArgumentException($"Expected header was not read in: {expectedHeader}"); } return(reader.Position + contentLength + reader.MetaData.Constants.MajorConstants.LengthAfterLength); }
public static long ParseSubrecord( IMutagenReadStream reader, RecordType expectedHeader, int?lengthOverride = null) { if (!TryParse( reader, expectedHeader, out var contentLength, reader.MetaData.Constants.SubConstants.LengthLength)) { throw new ArgumentException($"Expected header was not read in: {expectedHeader}"); } return(reader.Position + (lengthOverride ?? contentLength)); }
private static void CopyOverHeader(RecordLocatorResults fileLocs, IMutagenReadStream inputStream, BinaryWriter writer) { long noRecordLength; if (fileLocs.GrupLocations.TryGetInDirection( inputStream.Position, higher: true, result: out var nextRec)) { noRecordLength = nextRec.Value.Location.Min - inputStream.Position; } else { noRecordLength = inputStream.Remaining; } inputStream.WriteTo(writer.BaseStream, (int)noRecordLength); }
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; } }
public override ReadOnlyMemorySlice <byte> GetBytes(IMutagenReadStream inputStream) { var subType = HeaderTranslation.ReadNextSubrecordType( inputStream, out var subLen); if (!subType.Equals(_recordType)) { throw new ArgumentException(); } var ret = new byte[subLen + 6]; MutagenWriter stream = new MutagenWriter(new MemoryStream(ret), inputStream.MetaData.Constants); using (HeaderExport.Subrecord(stream, _recordType)) { inputStream.WriteTo(stream.BaseStream, subLen); } return(ret); }
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 void ProcessDialogs( IMutagenReadStream stream, MajorRecordFrame majorFrame, long fileOffset) { var formKey = FormKey.Factory(stream.MetaData.MasterReferences !, majorFrame.FormID.Raw); CleanEmptyDialogGroups( stream, formKey, fileOffset); // Reset misnumbered counter if (majorFrame.TryLocateSubrecordFrame(RecordTypes.TIFC, out var tifcRec, out var tifcIndex)) { var count = tifcRec.AsUInt32(); uint actualCount = 0; stream.Position = fileOffset + majorFrame.TotalLength; if (stream.TryReadGroupFrame(out var groupFrame)) { int groupPos = 0; while (groupPos < groupFrame.Content.Length) { var majorMeta = stream.MetaData.Constants.MajorRecord(groupFrame.Content.Slice(groupPos)); actualCount++; groupPos += checked ((int)majorMeta.TotalLength); } } if (actualCount != count) { byte[] b = new byte[4]; BinaryPrimitives.WriteUInt32LittleEndian(b, actualCount); _Instructions.SetSubstitution( fileOffset + tifcIndex + stream.MetaData.Constants.SubConstants.HeaderLength, b); } } }
public static RecordType GetNextType( IMutagenReadStream reader, out int contentLength, out long finalPos, bool hopGroup = true) { GroupHeader groupMeta = reader.GetGroup(); RecordType ret = groupMeta.RecordType; contentLength = checked ((int)groupMeta.TotalLength); if (groupMeta.IsGroup) { if (hopGroup) { ret = groupMeta.ContainedRecordType; } finalPos = reader.Position + groupMeta.TotalLength; } else { finalPos = reader.Position + reader.MetaData.Constants.MajorConstants.HeaderLength + contentLength; } return(ret); }
public override ReadOnlyMemorySlice <byte> GetBytes(IMutagenReadStream inputStream) { Dictionary <RecordType, byte[]> dataDict = new Dictionary <RecordType, byte[]>(); MutagenWriter stream; while (!inputStream.Complete) { var subType = HeaderTranslation.ReadNextSubrecordType( inputStream, out var subLen); if (!SubTypes.Contains(subType)) { inputStream.Position -= 6; break; } var data = new byte[subLen + 6]; stream = new MutagenWriter(new MemoryStream(data), inputStream.MetaData.Constants); using (HeaderExport.Subrecord(stream, subType)) { inputStream.WriteTo(stream.BaseStream, subLen); } dataDict[subType] = data; } byte[] ret = new byte[dataDict.Values.Sum((d) => d.Length)]; stream = new MutagenWriter(new MemoryStream(ret), inputStream.MetaData.Constants); foreach (var alignment in SubTypes) { if (dataDict.TryGetValue( alignment, out var data)) { stream.Write(data); } } return(ret); }
private void FixObjectPropertyIDs(IMutagenReadStream stream, long fileOffset, ushort objectFormat) { switch (objectFormat) { case 2: { stream.Position += 4; long offset = fileOffset + stream.Position; ProcessFormIDOverflow(stream.ReadSpan(4), ref offset); } break; case 1: { long offset = fileOffset + stream.Position; ProcessFormIDOverflow(stream.ReadSpan(4), ref offset); stream.Position += 4; } break; default: throw new NotImplementedException(); } }
public abstract ReadOnlyMemorySlice <byte> GetBytes(IMutagenReadStream inputStream);
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 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"); } } }
public static ExtendedList <IFormLinkGetter <IIdleAnimationGetter> > ParseAnimations(IMutagenReadStream stream) { var subFrame = stream.ReadSubrecordFrame(); var ret = new ExtendedList <IFormLinkGetter <IIdleAnimationGetter> >(); int pos = 0; while (pos < subFrame.Content.Length) { ret.Add( new FormLink <IIdleAnimationGetter>( FormKeyBinaryTranslation.Instance.Parse(subFrame.Content.Slice(pos), stream.MetaData.MasterReferences !))); pos += 4; } return(ret); }
public static VariableHeader ReadNextRecordVariableMeta(this IMutagenReadStream stream) => stream.MetaData.Constants.ReadNextRecordVariableMeta(stream);