Exemple #1
0
            public static void CustomStringImports(MutagenFrame frame, IConditionData item)
            {
                if (!frame.Reader.TryGetSubrecordFrame(out var subMeta))
                {
                    return;
                }
                if (!(item is IFunctionConditionData funcData))
                {
                    return;
                }
                switch (subMeta.RecordType.TypeInt)
                {
                case 0x31534943:     // CIS1
                    funcData.ParameterOneString = BinaryStringUtility.ProcessWholeToZString(subMeta.Content);
                    break;

                case 0x32534943:     // CIS2
                    funcData.ParameterTwoString = BinaryStringUtility.ProcessWholeToZString(subMeta.Content);
                    break;

                default:
                    return;
                }
                frame.Position += subMeta.TotalLength;
            }
Exemple #2
0
 string?GetIconCustom()
 {
     if (_IconLocation.HasValue)
     {
         return(BinaryStringUtility.ProcessWholeToZString(HeaderTranslation.ExtractSubrecordMemory(_data, _IconLocation.Value, _package.MetaData.Constants)));
     }
     if (_SecondaryIconLocation.HasValue)
     {
         return(BinaryStringUtility.ProcessWholeToZString(HeaderTranslation.ExtractSubrecordMemory(_data, _SecondaryIconLocation.Value, _package.MetaData.Constants)));
     }
     return(default);
Exemple #3
0
            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);
            }
Exemple #4
0
        public void GetMemorySlice()
        {
            var archive = Archive.CreateReader(GameRelease.SkyrimSE, TestBsa);

            archive.TryGetFolder("derp\\some_FoldeR", out var folder)
            .Should().BeTrue();
            if (folder == null)
            {
                throw new NullReferenceException();
            }
            var file = folder.Files.First();

            BinaryStringUtility.ProcessWholeToZString(file.GetMemorySlice())
            .Should().Be("Found me");
        }
Exemple #5
0
 public static partial void FillBinaryBipedObjectNamesCustom(MutagenFrame frame, IRaceInternal item)
 {
     for (int i = 0; i < NumBipedObjectNames; i++)
     {
         if (!frame.Reader.TryReadSubrecordFrame(RecordTypes.NAME, out var subHeader))
         {
             break;
         }
         BipedObject type = (BipedObject)i;
         var         val  = BinaryStringUtility.ProcessWholeToZString(subHeader.Content, frame.MetaData.Encodings.NonTranslated);
         if (!string.IsNullOrEmpty(val))
         {
             item.BipedObjectNames[type] = val;
         }
     }
 }
Exemple #6
0
        public void AsStream()
        {
            var archive = Archive.CreateReader(GameRelease.SkyrimSE, TestBsa);

            archive.TryGetFolder("derp\\some_FoldeR", out var folder)
            .Should().BeTrue();
            if (folder == null)
            {
                throw new NullReferenceException();
            }
            var file   = folder.Files.First();
            var stream = file.AsStream();

            byte[] b = new byte[stream.Length];
            stream.Remaining().Should().Be(8);
            stream.Read(b);
            stream.Remaining().Should().Be(0);
            BinaryStringUtility.ProcessWholeToZString(b)
            .Should().Be("Found me");
        }
        /// <summary>
        /// Takes a span aligned to a major record, and attempts to locate the game setting type.
        /// Will throw if the span is misaligned or doesn't start at a valid major record header.
        /// </summary>
        /// <param name="span">Data beginning at the start of a major record</param>
        /// <param name="meta">Game meta information to use in parsing</param>
        /// <returns>A response of the GameSettingType if found, or a reason if not.</returns>
        public static GetResponse <GameSettingType> GetGameSettingType(ReadOnlyMemorySlice <byte> span, GameConstants meta)
        {
            var majorMeta = meta.MajorRecordFrame(span);
            var edidLoc   = UtilityTranslation.FindFirstSubrecord(majorMeta.Content, meta, Constants.EditorID);

            if (edidLoc == null)
            {
                return(GetResponse <GameSettingType> .Fail($"EDID was not located"));
            }
            var edidMeta = meta.SubrecordFrame(majorMeta.Content.Slice(edidLoc.Value));
            var edid     = BinaryStringUtility.ProcessWholeToZString(edidMeta.Content);

            if (edid.Length == 0)
            {
                return(GetResponse <GameSettingType> .Fail("No EDID parsed."));
            }
            if (!TryGetGameSettingType(edid[0], out var settingType))
            {
                return(GetResponse <GameSettingType> .Fail($"Unknown game setting type: {edid[0]}"));
            }
            return(GetResponse <GameSettingType> .Succeed(settingType));
        }
Exemple #8
0
 /// <summary>
 /// Interprets a subrecord's content as a string.
 /// </summary>
 /// <param name="frame">Frame to read from</param>
 /// <returns>Subrecord's content as a string, null trimmed if applicable</returns>
 public static string AsString(this SubrecordFrame frame)
 {
     return(BinaryStringUtility.ProcessWholeToZString(frame.Content));
 }
Exemple #9
0
            public static IEnumerable <APerkEffect> ParseEffects(IMutagenReadStream stream)
            {
                while (stream.TryReadSubrecordFrame(RecordTypes.PRKE, out var prkeFrame))
                {
                    var         type     = (Perk.EffectType)prkeFrame.Content[0];
                    var         rank     = prkeFrame.Content[1];
                    var         priority = prkeFrame.Content[2];
                    APerkEffect effect;
                    if (stream.TryReadSubrecordFrame(RecordTypes.DATA, out var dataFrame))
                    {
                        switch (type)
                        {
                        case Perk.EffectType.Quest:
                            effect = new PerkQuestEffect()
                            {
                                Quest   = new FormLink <IQuestGetter>(FormKeyBinaryTranslation.Instance.Parse(dataFrame.Content, stream.MetaData.MasterReferences !)),
                                Stage   = dataFrame.Content[4],
                                Unknown = dataFrame.Content.Slice(5, 3).ToArray(),
                            };
                            effect.Conditions.SetTo(
                                ListBinaryTranslation <PerkCondition> .Instance.Parse(
                                    reader: new MutagenFrame(stream),
                                    transl: (MutagenFrame r, out PerkCondition listSubItem) =>
                            {
                                return(LoquiBinaryTranslation <PerkCondition> .Instance.Parse(
                                           frame: r,
                                           item: out listSubItem !));
                            }));
                            break;

                        case Perk.EffectType.Ability:
                            effect = new PerkAbilityEffect()
                            {
                                Ability = new FormLink <ISpellGetter>(FormKeyBinaryTranslation.Instance.Parse(dataFrame.Content, stream.MetaData.MasterReferences !)),
                            };
                            effect.Conditions.SetTo(
                                ListBinaryTranslation <PerkCondition> .Instance.Parse(
                                    reader: new MutagenFrame(stream),
                                    transl: (MutagenFrame r, out PerkCondition listSubItem) =>
                            {
                                return(LoquiBinaryTranslation <PerkCondition> .Instance.Parse(
                                           frame: r,
                                           item: out listSubItem !));
                            }));
                            break;

                        case Perk.EffectType.EntryPoint:
                            var entryPt    = (APerkEntryPointEffect.EntryType)dataFrame.Content[0];
                            var func       = (APerkEntryPointEffect.FunctionType)dataFrame.Content[1];
                            var tabCount   = dataFrame.Content[2];
                            var conditions = ListBinaryTranslation <PerkCondition> .Instance.Parse(
                                reader : new MutagenFrame(stream),
                                transl : (MutagenFrame r, out PerkCondition listSubItem) =>
                            {
                                return(LoquiBinaryTranslation <PerkCondition> .Instance.Parse(
                                           frame: r,
                                           item: out listSubItem !));
                            })
                                             .ToList();

                            ReadOnlyMemorySlice <byte>?epf2 = null;
                            ReadOnlyMemorySlice <byte>?epf3 = null;
                            ReadOnlyMemorySlice <byte>?epfd = null;
                            ReadOnlyMemorySlice <byte>?epft = null;
                            while (stream.TryReadSubrecordFrame(out var subFrame))
                            {
                                switch (subFrame.RecordTypeInt)
                                {
                                case RecordTypeInts.EPF2:
                                    epf2 = subFrame.Content;
                                    break;

                                case RecordTypeInts.EPF3:
                                    epf3 = subFrame.Content;
                                    break;

                                case RecordTypeInts.EPFD:
                                    epfd = subFrame.Content;
                                    break;

                                case RecordTypeInts.EPFT:
                                    epft = subFrame.Content;
                                    break;

                                default:
                                    stream.Position -= subFrame.Content.Length;
                                    goto searchDone;
                                }
                            }
searchDone:
                            APerkEntryPointEffect entryPointEffect;
                            switch (func)
                            {
                            case APerkEntryPointEffect.FunctionType.SetValue:
                            case APerkEntryPointEffect.FunctionType.AddValue:
                            case APerkEntryPointEffect.FunctionType.MultiplyValue:
                                if (epf2.HasValue)
                                {
                                    stream.MetaData.ReportIssue(RecordTypes.EPF2, $"{nameof(PerkEntryPointModifyValue)} had EPF2 unexpectedly");
                                }
                                if (epf3.HasValue)
                                {
                                    stream.MetaData.ReportIssue(RecordTypes.EPF3, $"{nameof(PerkEntryPointModifyValue)} had EPF3 unexpectedly");
                                }
                                float?f;
                                if (epft == null && epfd == null)
                                {
                                    f = null;
                                }
                                else
                                {
                                    if (!epft.HasValue)
                                    {
                                        throw new ArgumentException($"{nameof(PerkEntryPointModifyValue)} did not have expected EPFT record");
                                    }
                                    if (!epfd.HasValue)
                                    {
                                        throw new ArgumentException($"{nameof(PerkEntryPointModifyValue)} did not have expected EPFD record");
                                    }
                                    if (epft.Value[0] != (byte)APerkEntryPointEffect.ParameterType.Float)
                                    {
                                        throw new ArgumentException($"{nameof(PerkEntryPointModifyValue)} did not have expected parameter type flag: {epft.Value[0]}");
                                    }

                                    f = epfd.Value.Float();
                                }
                                entryPointEffect = new PerkEntryPointModifyValue()
                                {
                                    Value        = f,
                                    Modification = func switch
                                    {
                                        APerkEntryPointEffect.FunctionType.SetValue => PerkEntryPointModifyValue.ModificationType.Set,
                                        APerkEntryPointEffect.FunctionType.MultiplyValue => PerkEntryPointModifyValue.ModificationType.Multiply,
                                        APerkEntryPointEffect.FunctionType.AddValue => PerkEntryPointModifyValue.ModificationType.Add,
                                        _ => throw new ArgumentException(),
                                    }
                                };
                                break;

                            case APerkEntryPointEffect.FunctionType.AddRangeToValue:
                                if (epf2.HasValue)
                                {
                                    stream.MetaData.ReportIssue(RecordTypes.EPF2, $"{nameof(PerkEntryPointModifyValue)} had EPF2 unexpectedly");
                                }
                                if (epf3.HasValue)
                                {
                                    stream.MetaData.ReportIssue(RecordTypes.EPF3, $"{nameof(PerkEntryPointModifyValue)} had EPF3 unexpectedly");
                                }
                                if (!epft.HasValue)
                                {
                                    throw new ArgumentException($"{nameof(PerkEntryPointAddRangeToValue)} did not have expected EPFT record");
                                }
                                if (!epfd.HasValue)
                                {
                                    throw new ArgumentException($"{nameof(PerkEntryPointAddRangeToValue)} did not have expected EPFD record");
                                }
                                if (epft.Value[0] != (byte)APerkEntryPointEffect.ParameterType.FloatFloat)
                                {
                                    throw new ArgumentException($"{nameof(PerkEntryPointAddRangeToValue)} did not have expected parameter type flag: {epft.Value[0]}");
                                }
                                entryPointEffect = new PerkEntryPointAddRangeToValue()
                                {
                                    From = epfd.Value.Float(),
                                    To   = epfd.Value.Slice(4).Float(),
                                };
                                break;

                            case APerkEntryPointEffect.FunctionType.SetToActorValueMult:
                            case APerkEntryPointEffect.FunctionType.MultiplyActorValueMult:
                            case APerkEntryPointEffect.FunctionType.MultiplyOnePlusActorValueMult:
                            case APerkEntryPointEffect.FunctionType.AddActorValueMult:
                                if (epf2.HasValue)
                                {
                                    stream.MetaData.ReportIssue(RecordTypes.EPF2, $"{nameof(PerkEntryPointModifyValue)} had EPF2 unexpectedly");
                                }
                                if (epf3.HasValue)
                                {
                                    stream.MetaData.ReportIssue(RecordTypes.EPF3, $"{nameof(PerkEntryPointModifyValue)} had EPF3 unexpectedly");
                                }
                                if (!epft.HasValue)
                                {
                                    throw new ArgumentException($"{nameof(PerkEntryPointModifyActorValue)} did not have expected EPFT record");
                                }
                                if (!epfd.HasValue)
                                {
                                    throw new ArgumentException($"{nameof(PerkEntryPointModifyActorValue)} did not have expected EPFD record");
                                }
                                if (epft.Value[0] != (byte)APerkEntryPointEffect.ParameterType.FloatFloat)
                                {
                                    throw new ArgumentException($"{nameof(PerkEntryPointModifyActorValue)} did not have expected parameter type flag: {epft.Value[0]}");
                                }
                                entryPointEffect = new PerkEntryPointModifyActorValue()
                                {
                                    ActorValue   = (ActorValue)BinaryPrimitives.ReadInt32LittleEndian(epfd.Value),
                                    Value        = epfd.Value.Slice(4).Float(),
                                    Modification = func switch
                                    {
                                        APerkEntryPointEffect.FunctionType.SetToActorValueMult => PerkEntryPointModifyActorValue.ModificationType.SetToAVMult,
                                        APerkEntryPointEffect.FunctionType.AddActorValueMult => PerkEntryPointModifyActorValue.ModificationType.AddAVMult,
                                        APerkEntryPointEffect.FunctionType.MultiplyActorValueMult => PerkEntryPointModifyActorValue.ModificationType.MultiplyAVMult,
                                        APerkEntryPointEffect.FunctionType.MultiplyOnePlusActorValueMult => PerkEntryPointModifyActorValue.ModificationType.MultiplyOnePlusAVMult,
                                        _ => throw new ArgumentException(),
                                    }
                                };
                                break;

                            case APerkEntryPointEffect.FunctionType.AbsoluteValue:
                            case APerkEntryPointEffect.FunctionType.NegativeAbsoluteValue:
                                if (epf2.HasValue)
                                {
                                    stream.MetaData.ReportIssue(RecordTypes.EPF2, $"{nameof(PerkEntryPointModifyValue)} had EPF2 unexpectedly");
                                }
                                if (epf3.HasValue)
                                {
                                    stream.MetaData.ReportIssue(RecordTypes.EPF3, $"{nameof(PerkEntryPointModifyValue)} had EPF3 unexpectedly");
                                }
                                if (epft.HasValue && epft.Value[0] != (byte)APerkEntryPointEffect.ParameterType.None)
                                {
                                    throw new ArgumentException($"{nameof(PerkEntryPointAbsoluteValue)} did not have expected parameter type flag: {epft.Value[0]}");
                                }
                                entryPointEffect = new PerkEntryPointAbsoluteValue()
                                {
                                    Negative = func == APerkEntryPointEffect.FunctionType.NegativeAbsoluteValue
                                };
                                break;

                            case APerkEntryPointEffect.FunctionType.AddLeveledList:
                                if (epf2.HasValue)
                                {
                                    stream.MetaData.ReportIssue(RecordTypes.EPF2, $"{nameof(PerkEntryPointModifyValue)} had EPF2 unexpectedly");
                                }
                                if (epf3.HasValue)
                                {
                                    stream.MetaData.ReportIssue(RecordTypes.EPF3, $"{nameof(PerkEntryPointModifyValue)} had EPF3 unexpectedly");
                                }
                                if (!epft.HasValue)
                                {
                                    throw new ArgumentException($"{nameof(PerkEntryPointAddLeveledItem)} did not have expected EPFT record");
                                }
                                if (epft.Value[0] != (byte)APerkEntryPointEffect.ParameterType.LeveledItem)
                                {
                                    throw new ArgumentException($"{nameof(PerkEntryPointAddLeveledItem)} did not have expected parameter type flag: {epft.Value[0]}");
                                }
                                entryPointEffect = new PerkEntryPointAddLeveledItem()
                                {
                                    Item = new FormLink <ILeveledItemGetter>(epfd.HasValue ? FormKeyBinaryTranslation.Instance.Parse(epfd.Value, stream.MetaData.MasterReferences !) : FormKey.Null)
                                };
                                break;

                            case APerkEntryPointEffect.FunctionType.AddActivateChoice:
                                if (!epft.HasValue)
                                {
                                    throw new ArgumentException($"{nameof(PerkEntryPointAddActivateChoice)} did not have expected EPFT record");
                                }
                                if (!epf3.HasValue)
                                {
                                    throw new ArgumentException($"{nameof(PerkEntryPointAddActivateChoice)} did not have expected EPF3 record");
                                }
                                if (epft.Value[0] != (byte)APerkEntryPointEffect.ParameterType.SpellWithStrings)
                                {
                                    throw new ArgumentException($"{nameof(PerkEntryPointAddActivateChoice)} did not have expected parameter type flag: {epft.Value[0]}");
                                }
                                entryPointEffect = new PerkEntryPointAddActivateChoice()
                                {
                                    Spell       = new FormLinkNullable <ISpellGetter>(epfd.HasValue ? FormKeyBinaryTranslation.Instance.Parse(epfd.Value, stream.MetaData.MasterReferences !) : default(FormKey?)),
                                    ButtonLabel = epf2.HasValue ? StringBinaryTranslation.Instance.Parse(epf2.Value, StringsSource.Normal, stream.MetaData) : null,
                                    Flags       = new PerkScriptFlag()
                                    {
                                        Flags         = (PerkScriptFlag.Flag)BinaryPrimitives.ReadInt16LittleEndian(epf3.Value),
                                        FragmentIndex = BinaryPrimitives.ReadUInt16LittleEndian(epf3.Value.Slice(2))
                                    },
                                };
                                break;

                            case APerkEntryPointEffect.FunctionType.SelectSpell:
                                if (epf2.HasValue)
                                {
                                    stream.MetaData.ReportIssue(RecordTypes.EPF2, $"{nameof(PerkEntryPointModifyValue)} had EPF2 unexpectedly");
                                }
                                if (epf3.HasValue)
                                {
                                    stream.MetaData.ReportIssue(RecordTypes.EPF3, $"{nameof(PerkEntryPointModifyValue)} had EPF3 unexpectedly");
                                }
                                if (!epft.HasValue)
                                {
                                    throw new ArgumentException($"{nameof(PerkEntryPointSelectSpell)} did not have expected EPFT record");
                                }
                                if (epft.Value[0] != (byte)APerkEntryPointEffect.ParameterType.Spell)
                                {
                                    throw new ArgumentException($"{nameof(PerkEntryPointSelectSpell)} did not have expected parameter type flag: {epft.Value[0]}");
                                }
                                entryPointEffect = new PerkEntryPointSelectSpell()
                                {
                                    Spell = new FormLink <ISpellGetter>(epfd.HasValue ? FormKeyBinaryTranslation.Instance.Parse(epfd.Value, stream.MetaData.MasterReferences !) : FormKey.Null),
                                };
                                break;

                            case APerkEntryPointEffect.FunctionType.SelectText:
                                if (epf2.HasValue)
                                {
                                    stream.MetaData.ReportIssue(RecordTypes.EPF2, $"{nameof(PerkEntryPointModifyValue)} had EPF2 unexpectedly");
                                }
                                if (epf3.HasValue)
                                {
                                    stream.MetaData.ReportIssue(RecordTypes.EPF3, $"{nameof(PerkEntryPointModifyValue)} had EPF3 unexpectedly");
                                }
                                if (!epft.HasValue)
                                {
                                    throw new ArgumentException($"{nameof(PerkEntryPointSelectText)} did not have expected EPFT record");
                                }
                                if (epft.Value[0] != (byte)APerkEntryPointEffect.ParameterType.String)
                                {
                                    throw new ArgumentException($"{nameof(PerkEntryPointSelectText)} did not have expected parameter type flag: {epft.Value[0]}");
                                }
                                entryPointEffect = new PerkEntryPointSelectText()
                                {
                                    Text = epfd.HasValue ? BinaryStringUtility.ProcessWholeToZString(epfd.Value, stream.MetaData.Encodings.NonTranslated) : string.Empty
                                };
                                break;

                            case APerkEntryPointEffect.FunctionType.SetText:
                                if (epf2.HasValue)
                                {
                                    stream.MetaData.ReportIssue(RecordTypes.EPF2, $"{nameof(PerkEntryPointModifyValue)} had EPF2 unexpectedly");
                                }
                                if (epf3.HasValue)
                                {
                                    stream.MetaData.ReportIssue(RecordTypes.EPF3, $"{nameof(PerkEntryPointModifyValue)} had EPF3 unexpectedly");
                                }
                                if (!epft.HasValue)
                                {
                                    throw new ArgumentException($"{nameof(PerkEntryPointSetText)} did not have expected EPFT record");
                                }
                                if (epft.Value[0] != (byte)APerkEntryPointEffect.ParameterType.LString)
                                {
                                    throw new ArgumentException($"{nameof(PerkEntryPointSetText)} did not have expected parameter type flag: {epft.Value[0]}");
                                }
                                entryPointEffect = new PerkEntryPointSetText()
                                {
                                    Text = epfd.HasValue ? StringBinaryTranslation.Instance.Parse(epfd.Value, StringsSource.Normal, stream.MetaData) : (TranslatedString)string.Empty,
                                };
                                break;

                            default:
                                throw new NotImplementedException();
                            }
                            entryPointEffect.EntryPoint            = entryPt;
                            entryPointEffect.PerkConditionTabCount = tabCount;
                            entryPointEffect.Conditions.SetTo(conditions);
                            effect = entryPointEffect;
                            break;

                        default:
                            throw new NotImplementedException();
                        }
                    }
                    else
                    {
                        effect = type switch
                        {
                            Perk.EffectType.Quest => new PerkQuestEffect(),
                            Perk.EffectType.Ability => new PerkAbilityEffect(),
                            _ => throw new ArgumentException($"Expected DATA subrecord that did not exist."),
                        };
                    }
                    effect.Rank     = rank;
                    effect.Priority = priority;
                    if (stream.TryReadSubrecordFrame(RecordTypes.EPFT, out var epftFrame) &&
                        epftFrame.ContentLength != 1 &&
                        epftFrame.Content[0] != (byte)APerkEntryPointEffect.ParameterType.None)
                    {
                        throw new ArgumentException($"Encountered an unexpected epft frame.");
                    }
                    stream.TryReadSubrecordFrame(RecordTypes.PRKF, out var _);
                    yield return(effect);
                }
            }
Exemple #10
0
            public static void FillPackageData(IMutagenReadStream stream, int expectedCount, IDictionary <sbyte, APackageData> data)
            {
                // Retrieve the expected types, then skip rest of data
                var valuesPosition = stream.Position;
                var types          = new List <string>(expectedCount);

                while (stream.TryReadSubrecordFrame(out var subRecord))
                {
                    switch (subRecord.RecordTypeInt)
                    {
                    case 0x4D414E41:     // ANAM
                        types.Add(BinaryStringUtility.ProcessWholeToZString(subRecord.Content));
                        break;

                    case 0x4D414E43:     // CNAM
                    case 0x4D414E42:     // BNAM
                    case 0x43495054:     // TPIC
                    case 0x41445450:     // PTDA
                    case 0x4F544450:     // PDTO
                    case 0x54444C50:     // PLDT
                        // Skip
                        break;

                    default:
                        stream.Position -= subRecord.TotalLength;
                        goto done_types;
                    }
                }
done_types:

                // Parse package data
                APackageData? lastPackage = null;
                int itemIndex = 0;
                var packages  = new List <APackageData>(expectedCount);

                while (stream.TryGetSubrecordFrame(out var subRecord))
                {
                    switch (subRecord.RecordTypeInt)
                    {
                    case 0x4D414E55:     // UNAM
                        var index = (sbyte)subRecord.Content[0];
                        lastPackage = data.GetOrAdd <sbyte, APackageData>(
                            index,
                            () =>
                        {
                            return((types[itemIndex++]) switch
                            {
                                IntKey => new PackageDataInt(),
                                FloatKey => new PackageDataFloat(),
                                BoolKey => new PackageDataBool(),
                                LocationKey => new PackageDataLocation(),
                                SingleRefKey => new
                                PackageDataTarget()
                                {
                                    Type = PackageDataTarget.Types.SingleRef
                                },
                                TargetSelectorKey => new PackageDataTarget()
                                {
                                    Type = PackageDataTarget.Types.Target
                                },
                                TopicKey => new PackageDataTopic(),
                                ObjectListKey => new PackageDataObjectList(),
                                _ => throw new NotImplementedException(),
                            });
                        });
Exemple #11
0
        private void ProcessPackages(
            MajorRecordFrame majorFrame,
            long fileOffset)
        {
            // Reorder Idle subrecords

            // Reorder data values
            var xnamPos = UtilityTranslation.FindFirstSubrecord(majorFrame.Content, majorFrame.Meta, RecordTypes.XNAM);

            if (xnamPos == null)
            {
                throw new ArgumentException();
            }

            if (!majorFrame.TryLocateSubrecordFrame(RecordTypes.PKCU, out var pkcuRec))
            {
                throw new ArgumentException();
            }
            var count = pkcuRec.Content.Int32();

            if (count == 0)
            {
                return;
            }

            var        anamPos = UtilityTranslation.FindFirstSubrecord(majorFrame.Content, majorFrame.Meta, RecordTypes.ANAM);
            RecordType pldt    = new RecordType("PLDT");
            RecordType ptda    = new RecordType("PTDA");
            RecordType pdto    = new RecordType("PDTO");
            RecordType tpic    = new RecordType("TPIC");
            RecordType unam    = new RecordType("UNAM");
            RecordType bnam    = new RecordType("BNAM");
            RecordType pnam    = new RecordType("PNAM");

            // Reorder data values to be in index ordering
            if (anamPos.HasValue && anamPos.Value < xnamPos.Value)
            {
                var startLoc   = anamPos.Value;
                var dataValues = new List <(sbyte Index, ReadOnlyMemorySlice <byte> Data)>();
                var curLoc     = startLoc;
                while (anamPos.HasValue && anamPos.Value < xnamPos.Value)
                {
                    var anamRecord = majorFrame.Meta.SubrecordFrame(majorFrame.Content.Slice(anamPos.Value));
                    var recs       = UtilityTranslation.FindNextSubrecords(
                        majorFrame.Content.Slice(anamPos.Value + anamRecord.TotalLength),
                        majorFrame.Meta,
                        out var _,
                        RecordTypes.ANAM,
                        RecordTypes.CNAM,
                        pldt,
                        ptda,
                        pdto,
                        tpic);
                    int finalLoc;
                    if (recs[0] == null)
                    {
                        finalLoc = recs.NotNull().Max();
                    }
                    else if (recs[0] == 0)
                    {
                        dataValues.Add(
                            (-1, majorFrame.Content.Slice(anamPos.Value, anamRecord.TotalLength)));
                        curLoc  = anamPos.Value + anamRecord.TotalLength;
                        anamPos = anamPos.Value + anamRecord.TotalLength;
                        continue;
                    }
                    else
                    {
                        finalLoc = recs
                                   .NotNull()
                                   .Where(i => i < recs[0] !.Value)
                                   .Max();
                    }
                    var finalRec  = majorFrame.Meta.Subrecord(majorFrame.Content.Slice(anamPos.Value + anamRecord.TotalLength + finalLoc));
                    var dataSlice = majorFrame.Content.Slice(anamPos.Value, anamRecord.TotalLength + finalLoc + finalRec.TotalLength);
                    if (BinaryStringUtility.ProcessWholeToZString(anamRecord.Content) == "Bool" &&
                        recs[1] != null)
                    {
                        // Ensure bool value is 1 or 0
                        var cnam = majorFrame.Meta.SubrecordFrame(majorFrame.Content.Slice(anamPos.Value + anamRecord.TotalLength + recs[1].Value));
                        if (cnam.Content.Length != 1)
                        {
                            throw new ArgumentException();
                        }
                        if (cnam.Content[0] > 1)
                        {
                            var bytes     = dataSlice.ToArray();
                            int boolIndex = anamRecord.TotalLength + recs[1].Value + cnam.HeaderLength;
                            bytes[boolIndex] = (byte)(bytes[boolIndex] > 0 ? 1 : 0);
                            dataSlice        = bytes;
                        }
                    }
                    dataValues.Add((-1, dataSlice));

                    curLoc  = anamPos.Value + anamRecord.TotalLength + finalLoc + finalRec.TotalLength;
                    anamPos = anamPos.Value + anamRecord.TotalLength + recs[0];
                }

                var unamLocs = UtilityTranslation.ParseRepeatingSubrecord(
                    majorFrame.Content.Slice(curLoc),
                    majorFrame.Meta,
                    unam,
                    out var _);
                if (unamLocs == null ||
                    unamLocs.Length != dataValues.Count ||
                    unamLocs.Length != count)
                {
                    throw new ArgumentException();
                }

                for (sbyte i = 0; i < unamLocs.Length; i++)
                {
                    var unamRec = majorFrame.Meta.SubrecordFrame(majorFrame.Content.Slice(curLoc + unamLocs[i]));
                    dataValues[i] = (
                        (sbyte)unamRec.Content[0],
                        dataValues[i].Data);
                }

                var subLoc = startLoc;
                foreach (var item in dataValues.OrderBy(i => i.Index))
                {
                    _Instructions.SetSubstitution(
                        fileOffset + majorFrame.HeaderLength + subLoc,
                        item.Data.ToArray());
                    subLoc += item.Data.Length;
                }
                foreach (var item in dataValues.OrderBy(i => i.Index))
                {
                    byte[] bytes = new byte[] { 0x55, 0x4E, 0x41, 0x4D, 0x01, 0x00, 0x00 };
                    bytes[6] = (byte)item.Index;
                    _Instructions.SetSubstitution(
                        fileOffset + majorFrame.HeaderLength + subLoc,
                        bytes.ToArray());
                    subLoc += bytes.Length;
                }
            }

            // Reorder inputs
            var unamPos = UtilityTranslation.FindFirstSubrecord(majorFrame.Content.Slice(xnamPos.Value), majorFrame.Meta, unam);

            if (!unamPos.HasValue)
            {
                return;
            }
            unamPos += xnamPos.Value;
            var writeLoc    = fileOffset + majorFrame.HeaderLength + unamPos.Value;
            var inputValues = new List <(sbyte Index, ReadOnlyMemorySlice <byte> Data)>();

            while (unamPos.HasValue)
            {
                var unamRecord = majorFrame.Meta.SubrecordFrame(majorFrame.Content.Slice(unamPos.Value));
                var recs       = UtilityTranslation.FindNextSubrecords(
                    majorFrame.Content.Slice(unamPos.Value + unamRecord.TotalLength),
                    majorFrame.Meta,
                    out var _,
                    unam,
                    bnam,
                    pnam);
                int finalLoc;
                if (recs[0] == null)
                {
                    finalLoc = recs.NotNull().Max();
                }
                else if (recs[0] == 0)
                {
                    inputValues.Add(
                        ((sbyte)unamRecord.Content[0], majorFrame.Content.Slice(unamPos.Value, unamRecord.TotalLength)));
                    unamPos = unamPos.Value + unamRecord.TotalLength;
                    continue;
                }
                else
                {
                    finalLoc = recs
                               .NotNull()
                               .Where(i => i < recs[0] !.Value)
                               .Max();
                }
                var finalRec = majorFrame.Meta.Subrecord(majorFrame.Content.Slice(unamPos.Value + unamRecord.TotalLength + finalLoc));
                inputValues.Add(
                    ((sbyte)unamRecord.Content[0], majorFrame.Content.Slice(unamPos.Value, unamRecord.TotalLength + finalLoc + finalRec.TotalLength)));

                unamPos = unamPos.Value + unamRecord.TotalLength + recs[0];
            }
            foreach (var item in inputValues.OrderBy(i => i.Index))
            {
                _Instructions.SetSubstitution(
                    writeLoc,
                    item.Data.ToArray());
                writeLoc += item.Data.Length;
            }
        }
Exemple #12
0
 /// <summary>
 /// Interprets a subrecord's content as a string.
 /// </summary>
 /// <param name="frame">Frame to read from</param>
 /// <param name="encoding">Encoding to use</param>
 /// <returns>Subrecord's content as a string, null trimmed if applicable</returns>
 public static string AsString(this SubrecordFrame frame, IMutagenEncoding encoding)
 {
     return(BinaryStringUtility.ProcessWholeToZString(frame.Content, encoding));
 }