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);
            }
        }
Exemple #2
0
        private static void AlignWorldChildren(
            IMutagenReadStream reader,
            MutagenWriter writer)
        {
            reader.WriteTo(writer.BaseStream, 4);
            ReadOnlyMemorySlice <byte>?roadStorage = null;
            ReadOnlyMemorySlice <byte>?cellStorage = null;
            var grupBytes = new List <ReadOnlyMemorySlice <byte> >();

            for (int i = 0; i < 3; i++)
            {
                MajorRecordHeader majorMeta = reader.GetMajorRecord();
                switch (majorMeta.RecordType.Type)
                {
                case "ROAD":
                    roadStorage = reader.ReadMemory(checked ((int)majorMeta.TotalLength));
                    break;

                case "CELL":
                    if (cellStorage != null)
                    {
                        throw new ArgumentException();
                    }
                    var startPos = reader.Position;
                    var cellMeta = reader.GetMajorRecord();
                    reader.Position += cellMeta.TotalLength;
                    var  cellGroupMeta = reader.GetGroup();
                    long cellGrupLen;
                    if (cellGroupMeta.IsGroup &&
                        cellGroupMeta.GroupType == (int)GroupTypeEnum.CellChildren)
                    {
                        cellGrupLen = cellGroupMeta.TotalLength;
                    }
                    else
                    {
                        cellGrupLen = 0;
                    }
                    reader.Position = startPos;
                    cellStorage     = reader.ReadMemory(checked ((int)(cellMeta.TotalLength + cellGrupLen)));
                    break;

                case "GRUP":
                    if (roadStorage != null &&
                        cellStorage != null)
                    {
                        i = 3;     // end loop
                        continue;
                    }
                    var groupMeta = reader.GetGroup();
                    grupBytes.Add(reader.ReadMemory(checked ((int)groupMeta.TotalLength)));
                    break;

                case "WRLD":
                    i = 3;     // end loop
                    continue;

                default:
                    throw new NotImplementedException();
                }
            }
            if (roadStorage != null)
            {
                writer.Write(roadStorage.Value);
            }
            if (cellStorage != null)
            {
                writer.Write(cellStorage.Value);
            }
            foreach (var item in grupBytes)
            {
                writer.Write(item);
            }
        }
        private static void AlignMajorRecordsByRules(
            IMutagenReadStream inputStream,
            MutagenWriter writer,
            AlignmentRules alignmentRules,
            RecordLocatorResults fileLocs)
        {
            while (!inputStream.Complete)
            {
                // Import until next listed major record
                long noRecordLength;
                if (fileLocs.ListedRecords.TryGetInDirection(
                        inputStream.Position,
                        higher: true,
                        result: out var nextRec))
                {
                    var recordLocation = fileLocs.ListedRecords.Keys[nextRec.Key];
                    noRecordLength = recordLocation - inputStream.Position;
                }
                else
                {
                    noRecordLength = inputStream.Remaining;
                }
                inputStream.WriteTo(writer.BaseStream, (int)noRecordLength);

                // If complete overall, return
                if (inputStream.Complete)
                {
                    break;
                }

                var recType = HeaderTranslation.ReadNextRecordType(
                    inputStream,
                    out var len);
                if (!alignmentRules.StopMarkers.TryGetValue(recType, out var stopMarkers))
                {
                    stopMarkers = null;
                }
                writer.Write(recType.TypeInt);
                writer.Write(len);
                if (!alignmentRules.Alignments.TryGetValue(recType, out var alignments))
                {
                    inputStream.WriteTo(writer.BaseStream, inputStream.MetaData.Constants.MajorConstants.LengthAfterLength + len);
                    continue;
                }
                inputStream.WriteTo(writer.BaseStream, inputStream.MetaData.Constants.MajorConstants.LengthAfterLength);
                var writerEndPos = writer.Position + len;
                var endPos       = inputStream.Position + len;
                var dataDict     = new Dictionary <RecordType, ReadOnlyMemorySlice <byte> >();
                ReadOnlyMemorySlice <byte>?rest = null;
                while (inputStream.Position < endPos)
                {
                    var subType = HeaderTranslation.GetNextSubrecordType(
                        inputStream,
                        out var _);
                    if (stopMarkers?.Contains(subType) ?? false)
                    {
                        rest = inputStream.ReadMemory((int)(endPos - inputStream.Position), readSafe: true);
                        break;
                    }
                    if (!alignments.TryGetValue(subType, out var rule))
                    {
                        throw new ArgumentException($"Encountered an unknown record: {subType}");
                    }
                    dataDict.Add(subType, rule.GetBytes(inputStream));
                }
                foreach (var alignment in alignmentRules.Alignments[recType])
                {
                    if (dataDict.TryGetValue(
                            alignment.Key,
                            out var data))
                    {
                        writer.Write(data);
                        dataDict.Remove(alignment.Key);
                    }
                }
                if (dataDict.Count > 0)
                {
                    throw new ArgumentException($"Encountered an unknown record: {dataDict.First().Key}");
                }
                if (rest != null)
                {
                    writer.Write(rest.Value);
                }
                if (writer.Position != writerEndPos)
                {
                    throw new ArgumentException("Record alignment changed length");
                }
            }
        }
Exemple #4
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);
    }