Beispiel #1
0
    private void ProcessPlacedCreature(
        MajorRecordFrame majorFrame,
        long fileOffset)
    {
        int amount = 0;

        if (majorFrame.TryLocateSubrecordPinFrame(RecordTypes.DATA, out var dataRec))
        {
            ProcessZeroFloats(dataRec, fileOffset, 6);
        }

        ProcessLengths(
            majorFrame,
            amount,
            fileOffset);
    }
Beispiel #2
0
        /// <summary>
        /// Retrieves the character representing a Global's data type from a MajorRecordFrame
        /// </summary>
        /// <param name="frame">Frame to retrieve from</param>
        /// <returns>Character representing data type</returns>
        /// <exception cref="ArgumentException">If FNAM not present or malformed</exception>
        public static char GetGlobalChar(MajorRecordFrame frame)
        {
            var subrecordSpan = frame.Content;
            var fnamLocation  = UtilityTranslation.FindFirstSubrecord(subrecordSpan, frame.Header.Meta, FNAM);

            if (fnamLocation == null)
            {
                throw new ArgumentException($"Could not find FNAM.");
            }
            var fnamMeta = frame.Header.Meta.SubrecordFrame(subrecordSpan.Slice(fnamLocation.Value));

            if (fnamMeta.Content.Length != 1)
            {
                throw new ArgumentException($"FNAM had non 1 length: {fnamMeta.Content.Length}");
            }
            return((char)fnamMeta.Content[0]);
        }
Beispiel #3
0
    private void ProcessGameSettings(
        MajorRecordFrame majorFrame,
        long fileOffset)
    {
        var edidRec = majorFrame.LocateSubrecordFrame("EDID");

        if ((char)edidRec.Content[0] != 'f')
        {
            return;
        }

        if (majorFrame.TryLocateSubrecord(RecordTypes.DATA, out var dataRec, out var dataIndex))
        {
            dataIndex += dataRec.HeaderLength;
            ProcessZeroFloat(majorFrame, fileOffset, ref dataIndex);
        }
    }
Beispiel #4
0
        /// <summary>
        /// Finds and iterates subrecords of a given type
        /// </summary>
        /// <param name="majorFrame">Frame to read from</param>
        /// <param name="type">Type to search for</param>
        /// <param name="onlyFirstSet">
        /// If true, iteration will stop after finding the first non-applicable record after some applicable ones.<br/>
        /// If false, records will continue to be searched in their entirety for all matching subrecords.
        /// </param>
        /// <returns>First encountered SubrecordFrame with the given type</returns>
        public static IEnumerable <SubrecordPinFrame> FindEnumerateSubrecords(this MajorRecordFrame majorFrame, RecordType type, bool onlyFirstSet = false)
        {
            bool encountered = false;

            foreach (var subrecord in majorFrame)
            {
                if (subrecord.RecordType == type)
                {
                    encountered = true;
                    yield return(subrecord);
                }
                else if (onlyFirstSet && encountered)
                {
                    yield break;
                }
            }
        }
Beispiel #5
0
    private void ProcessAIPackages(
        MajorRecordFrame majorFrame,
        long fileOffset)
    {
        int amount = 0;

        foreach (var ctdt in majorFrame.FindEnumerateSubrecords(RecordTypes.CTDT))
        {
            this._instructions.SetSubstitution(
                loc: ctdt.Location + fileOffset + 3,
                sub: new byte[] { (byte)'A', 0x18 });
            this._instructions.SetAddition(
                addition: new byte[4],
                loc: ctdt.Location + fileOffset + 0x1A);
            amount += 4;
        }

        foreach (var ctdt in majorFrame.FindEnumerateSubrecords(RecordTypes.PKDT))
        {
            if (ctdt.ContentLength != 4)
            {
                continue;
            }
            this._instructions.SetSubstitution(
                loc: fileOffset + ctdt.Location + 4,
                sub: new byte[] { 0x8 });
            var first1  = ctdt.Content[0];
            var first2  = ctdt.Content[1];
            var second1 = ctdt.Content[2];
            var second2 = ctdt.Content[3];
            this._instructions.SetSubstitution(
                loc: fileOffset + ctdt.Location + 6,
                sub: new byte[] { first1, first2, 0, 0 });
            this._instructions.SetAddition(
                loc: fileOffset + ctdt.Location + 10,
                addition: new byte[] { second1, 0, 0, 0 });
            amount += 4;
        }

        ProcessLengths(
            majorFrame,
            amount,
            fileOffset);
    }
Beispiel #6
0
        private void ProcessRegions(
            MajorRecordFrame majorFrame,
            long fileOffset)
        {
            var rdat = UtilityTranslation.FindFirstSubrecord(majorFrame.Content, majorFrame.Meta, RecordTypes.RDAT, navigateToContent: false);

            if (rdat == null)
            {
                return;
            }

            // Order RDATs by index
            SortedList <uint, RangeInt64> rdats = new SortedList <uint, RangeInt64>();
            List <uint> raw = new List <uint>();

            while (rdat != null)
            {
                var rdatHeader = majorFrame.Meta.SubrecordFrame(majorFrame.Content.Slice(rdat.Value));
                var index      = BinaryPrimitives.ReadUInt32LittleEndian(rdatHeader.Content);
                var nextRdat   = UtilityTranslation.FindFirstSubrecord(
                    majorFrame.Content,
                    majorFrame.Meta,
                    RecordTypes.RDAT,
                    navigateToContent: false,
                    offset: rdat.Value + rdatHeader.TotalLength);
                rdats[index] =
                    new RangeInt64(
                        fileOffset + majorFrame.HeaderLength + rdat.Value,
                        nextRdat == null ? fileOffset + majorFrame.TotalLength - 1 : nextRdat.Value - 1 + fileOffset + majorFrame.HeaderLength);
                raw.Add(index);
                rdat = nextRdat;
            }
            if (raw.SequenceEqual(rdats.Keys))
            {
                return;
            }
            foreach (var item in rdats.Reverse())
            {
                this._Instructions.SetMove(
                    loc: fileOffset + majorFrame.TotalLength,
                    section: item.Value);
            }
        }
        private void ProcessGameSettings(
            MajorRecordFrame majorFrame,
            long fileOffset)
        {
            if (!majorFrame.TryLocateSubrecordFrame("EDID", out var edidFrame))
            {
                return;
            }
            if ((char)edidFrame.Content[0] != 'f')
            {
                return;
            }

            if (!majorFrame.TryLocateSubrecordPinFrame(RecordTypes.DATA, out var dataRec))
            {
                return;
            }
            ProcessZeroFloat(dataRec, fileOffset);
        }
Beispiel #8
0
        private void ProcessPlaced(
            MajorRecordFrame majorFrame,
            long fileOffset)
        {
            var sizeChange = 0;

            if (majorFrame.TryLocateSubrecordPinFrame(RecordTypes.DATA, out var dataRec))
            {
                ProcessZeroFloats(dataRec, fileOffset, 6);
            }

            if (majorFrame.TryLocateSubrecordPinFrame(RecordTypes.XTEL, out var xtelRec))
            {
                var offset = 4;
                ProcessZeroFloats(xtelRec, fileOffset, ref offset, 6);
            }

            if (majorFrame.TryLocateSubrecordPinFrame(RecordTypes.XPRM, out var xprmRec))
            {
                int offset = 0;
                ProcessZeroFloats(xprmRec, fileOffset, ref offset, 3);
                ProcessColorFloat(xprmRec, fileOffset, ref offset);
                ProcessZeroFloat(xprmRec, fileOffset, ref offset);
            }

            if (majorFrame.TryLocateSubrecordFrame(RecordTypes.XRMR, out var xrmrRec, out var xrmrIndex))
            {
                if (xrmrRec.AsInt32() == 0)
                {
                    _Instructions.SetRemove(
                        RangeInt64.FactoryFromLength(
                            fileOffset + xrmrIndex,
                            10));
                    sizeChange -= 10;
                }
            }

            ProcessLengths(
                majorFrame,
                sizeChange,
                fileOffset);
        }
Beispiel #9
0
    private void ProcessDialogItems(
        MajorRecordFrame majorFrame,
        long fileOffset)
    {
        int amount = 0;

        foreach (var ctdt in majorFrame.FindEnumerateSubrecords(RecordTypes.CTDT))
        {
            this._instructions.SetSubstitution(
                loc: ctdt.Location + fileOffset + 3,
                sub: new byte[] { (byte)'A', 0x18 });
            this._instructions.SetAddition(
                addition: new byte[4],
                loc: ctdt.Location + fileOffset + 0x1A);
            amount += 4;
        }

        foreach (var schd in majorFrame.FindEnumerateSubrecords(RecordTypes.SCHD))
        {
            var existingLen = schd.ContentLength;
            var diff        = existingLen - 0x14;
            this._instructions.SetSubstitution(
                loc: schd.Location + fileOffset + 3,
                sub: new byte[] { (byte)'R', 0x14 });
            if (diff == 0)
            {
                continue;
            }
            var locToRemove = fileOffset + schd.Location + schd.HeaderLength + 0x14;
            this._instructions.SetRemove(
                section: new RangeInt64(
                    locToRemove,
                    locToRemove + diff - 1));
            amount -= diff;
        }

        ProcessLengths(
            majorFrame,
            amount,
            fileOffset);
    }
Beispiel #10
0
        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);
                }
            }
        }
Beispiel #11
0
 private void ProcessNPC(
     MajorRecordFrame majorFrame,
     long fileOffset)
 {
     this.DynamicMove(
         majorFrame,
         fileOffset,
         offendingIndices: new RecordType[]
     {
         new RecordType("CNTO"),
         new RecordType("SCRI"),
         new RecordType("AIDT")
     },
         offendingLimits: new RecordType[]
     {
         new RecordType("ACBS")
     },
         locationsToMove: new RecordType[]
     {
         new RecordType("CNAM")
     });
 }
Beispiel #12
0
    private void ProcessIdleAnimations(
        MajorRecordFrame majorFrame,
        long fileOffset)
    {
        int amount = 0;

        foreach (var ctdt in majorFrame.FindEnumerateSubrecords(RecordTypes.CTDT))
        {
            this._instructions.SetSubstitution(
                loc: ctdt.Location + fileOffset + 3,
                sub: new byte[] { (byte)'A', 0x18 });
            this._instructions.SetAddition(
                addition: new byte[4],
                loc: ctdt.Location + fileOffset + 0x1A);
            amount += 4;
        }

        ProcessLengths(
            majorFrame,
            amount,
            fileOffset);
    }
Beispiel #13
0
        /// <summary>
        /// Enumerates locations of the contained subrecords, while considering some specified RecordTypes as special length overflow subrecords.<br/>
        /// These length overflow subrecords will be skipped, and simply used to parse the next subrecord properly.<br />
        /// Locations are relative to the RecordType of the MajorRecordFrame.
        /// </summary>
        /// <param name="majorFrame">MajorRecordFrame to iterate</param>
        /// <param name="lengthOverflowTypes">Collection of known RecordTypes that signify a length overflow subrecord</param>
        public static IEnumerable <SubrecordPinFrame> EnumerateSubrecords(this MajorRecordFrame majorFrame, ICollection <RecordType> lengthOverflowTypes)
        {
            int loc = majorFrame.HeaderLength;

            while (loc < majorFrame.HeaderAndContentData.Length)
            {
                var subFrame = new SubrecordPinFrame(majorFrame.Meta, majorFrame.HeaderAndContentData.Slice(loc), loc);
                if (lengthOverflowTypes.Contains(subFrame.RecordType))
                { // Length overflow record
                    var nextLen = subFrame.AsUInt32();
                    loc += subFrame.TotalLength;
                    var span      = majorFrame.HeaderAndContentData.Slice(loc, checked ((int)(nextLen + majorFrame.Meta.SubConstants.HeaderLength)));
                    var subHeader = new SubrecordHeader(majorFrame.Meta, span);
                    yield return(SubrecordPinFrame.FactoryNoTrim(subHeader, span, loc));

                    continue;
                }
                yield return(subFrame);

                loc += subFrame.TotalLength;
            }
        }
Beispiel #14
0
 /// <summary>
 /// Enumerates locations of the contained subrecords.<br/>
 /// Locations are relative to the RecordType of the MajorRecordFrame.
 /// </summary>
 /// <param name="majorFrame">MajorRecordFrame to iterate</param>
 public static IEnumerable <SubrecordPinFrame> EnumerateSubrecords(this MajorRecordFrame majorFrame) => EnumerateSubrecords(majorFrame.HeaderAndContentData, majorFrame.Meta, majorFrame.HeaderLength);
Beispiel #15
0
    private void ProcessWater(
        MajorRecordFrame majorFrame,
        long fileOffset)
    {
        var amount = 0;

        if (majorFrame.TryLocateSubrecord(RecordTypes.DATA, out var dataRec, out var dataLoc))
        {
            var len = dataRec.ContentLength;
            if (len == 0x02)
            {
                this._instructions.SetSubstitution(
                    loc: fileOffset + dataLoc + Plugins.Internals.Constants.HeaderLength,
                    sub: new byte[] { 0, 0 });
                this._instructions.SetRemove(
                    section: RangeInt64.FactoryFromLength(
                        loc: fileOffset + dataLoc + dataRec.HeaderLength,
                        length: 2));
                amount -= 2;
            }

            if (len == 0x56)
            {
                this._instructions.SetSubstitution(
                    loc: fileOffset + dataLoc + Plugins.Internals.Constants.HeaderLength,
                    sub: new byte[] { 0x54, 0 });
                this._instructions.SetRemove(
                    section: RangeInt64.FactoryFromLength(
                        loc: fileOffset + dataLoc + dataRec.HeaderLength + 0x54,
                        length: 2));
                amount -= 2;
            }

            if (len == 0x2A)
            {
                this._instructions.SetSubstitution(
                    loc: fileOffset + dataLoc + Plugins.Internals.Constants.HeaderLength,
                    sub: new byte[] { 0x28, 0 });
                this._instructions.SetRemove(
                    section: RangeInt64.FactoryFromLength(
                        loc: fileOffset + dataLoc + dataRec.HeaderLength + 0x28,
                        length: 2));
                amount -= 2;
            }

            if (len == 0x3E)
            {
                this._instructions.SetSubstitution(
                    loc: fileOffset + dataLoc + Plugins.Internals.Constants.HeaderLength,
                    sub: new byte[] { 0x3C, 0 });
                this._instructions.SetRemove(
                    section: RangeInt64.FactoryFromLength(
                        loc: fileOffset + dataLoc + dataRec.HeaderLength + 0x3C,
                        length: 2));
                amount -= 2;
            }

            var move = 0x39;
            if (len >= 3 + move)
            {
                this._instructions.SetSubstitution(
                    sub: new byte[] { 0, 0, 0 },
                    loc: fileOffset + dataLoc + dataRec.HeaderLength + move);
            }
        }

        ProcessLengths(
            majorFrame,
            amount,
            fileOffset);
    }
Beispiel #16
0
 /// <summary>
 /// Iterates a MajorRecordFrame's subrecords and locates the first occurance of the desired type
 /// </summary>
 /// <param name="majorFrame">Frame to read from</param>
 /// <param name="type">Type to search for</param>
 /// <exception cref="System.ArgumentException">Thrown if target type cannot be found.</exception>
 /// <returns>First encountered SubrecordHeader with the given type</returns>
 public static SubrecordHeader LocateSubrecord(this MajorRecordFrame majorFrame, RecordType type)
 {
     return(majorFrame.LocateSubrecord(type, loc: out var _));
 }
Beispiel #17
0
 /// <summary>
 /// Iterates a MajorRecordFrame's contents and locates the first occurance of the desired type
 /// </summary>
 /// <param name="majorFrame">Frame to read from</param>
 /// <param name="type">Type to search for</param>
 /// <param name="header">SubrecordHeader if found</param>
 /// <returns>True if matching subrecord is found</returns>
 public static bool TryLocateSubrecord(this MajorRecordFrame majorFrame, RecordType type, out SubrecordHeader header)
 {
     return(majorFrame.TryLocateSubrecord(type, header: out header, loc: out var _));
 }
Beispiel #18
0
 /// <summary>
 /// Enumerates locations of the contained subrecords, while considering some specified RecordTypes as special length overflow subrecords.<br/>
 /// These length overflow subrecords will be skipped, and simply used to parse the next subrecord properly.<br />
 /// Locations are relative to the RecordType of the MajorRecordFrame.
 /// </summary>
 /// <param name="majorFrame">MajorRecordFrame to iterate</param>
 /// <param name="lengthOverflowTypes">Known RecordTypes that signify a length overflow subrecord</param>
 public static IEnumerable <SubrecordPinFrame> EnumerateSubrecordsWithLengthOverflow(this MajorRecordFrame majorFrame, params RecordType[] lengthOverflowTypes)
 {
     return(EnumerateSubrecords(majorFrame, (ICollection <RecordType>)lengthOverflowTypes.ToHashSet()));
 }
Beispiel #19
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;
            }
        }
Beispiel #20
0
        private void ProcessQuests(
            MajorRecordFrame majorFrame,
            long fileOffset)
        {
            if (majorFrame.TryLocateSubrecordFrame(RecordTypes.ANAM, out var anamRec, out var anamIndex))
            {
                var next    = anamRec.AsUInt32();
                var targets = new RecordType[]
                {
                    RecordTypes.ALST,
                    RecordTypes.ALLS
                };
                var locs = UtilityTranslation.FindAllOfSubrecords(
                    majorFrame.Content,
                    majorFrame.Meta,
                    targets.ToGetter(),
                    navigateToContent: true);
                uint actualNext = 0;
                if (locs.Length > 0)
                {
                    actualNext = locs
                                 .Select(l =>
                    {
                        return(BinaryPrimitives.ReadUInt32LittleEndian(majorFrame.Content.Slice(l)));
                    })
                                 .Max();
                    actualNext++;
                }
                if (actualNext != next)
                {
                    byte[] sub = new byte[4];
                    BinaryPrimitives.WriteUInt32LittleEndian(sub, actualNext);
                    _Instructions.SetSubstitution(
                        fileOffset + anamIndex + anamRec.HeaderLength,
                        sub);
                }
            }

            var sizeChange = FixMissingCounters(
                majorFrame,
                fileOffset,
                new RecordType("COCT"),
                new RecordType("CNTO"));

            ProcessLengths(
                majorFrame,
                sizeChange,
                fileOffset);

            FixVMADFormIDs(
                majorFrame,
                fileOffset,
                out var vmadPos,
                out var objectFormat,
                out var processedLen);
            if (vmadPos != null)
            {
                var vmadFrame = Meta.SubrecordFrame(majorFrame.Content.Slice(vmadPos.Value));
                var stream    = new MutagenMemoryReadStream(vmadFrame.Content, Bundle)
                {
                    Position = processedLen - vmadFrame.HeaderLength
                };
                if (stream.Complete)
                {
                    return;
                }
                // skip unknown
                stream.Position += 1;
                var fragCount = stream.ReadUInt16();
                // skip name
                var len = stream.ReadUInt16();
                stream.Position += len;
                for (int i = 0; i < fragCount; i++)
                {
                    stream.Position += 9;
                    // skip name
                    len              = stream.ReadUInt16();
                    stream.Position += len;
                    // skip name
                    len              = stream.ReadUInt16();
                    stream.Position += len;
                }
                var aliasCount = stream.ReadUInt16();
                for (int i = 0; i < aliasCount; i++)
                {
                    FixObjectPropertyIDs(stream, fileOffset, objectFormat);
                    // skip version
                    stream.Position += 2;
                    objectFormat     = stream.ReadUInt16();
                    var numScripts = stream.ReadUInt16();
                    for (int j = 0; j < numScripts; j++)
                    {
                        FixVMADScriptIDs(stream, fileOffset, objectFormat);
                    }
                }
            }
        }
Beispiel #21
0
    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);
    }