Ejemplo n.º 1
0
        public static byte[] BytesFrom(this IDataModel model, IFormattedRun run)
        {
            var data = new byte[run.Length];

            Array.Copy(model.RawData, run.Start, data, 0, run.Length);
            return(data);
        }
Ejemplo n.º 2
0
 public void RemoveRun(IFormattedRun run)
 {
     if (addedRuns.ContainsKey(run.Start))
     {
         addedRuns.Remove(run.Start);
     }
     else if (!removedRuns.ContainsKey(run.Start))
     {
         removedRuns[run.Start] = run;
     }
 }
Ejemplo n.º 3
0
 public void RemoveRun(IFormattedRun run)
 {
     using (CaptureNonDataChange())
         if (addedRuns.ContainsKey(run.Start))
         {
             addedRuns.Remove(run.Start);
         }
         else if (!removedRuns.ContainsKey(run.Start))
         {
             removedRuns[run.Start] = run;
         }
 }
Ejemplo n.º 4
0
        public static bool ContainsOnlyPointerToSelf(this IFormattedRun run)
        {
            if (run.PointerSources == null)
            {
                return(false);
            }
            if (run.PointerSources.Count != 1)
            {
                return(false);
            }
            var source = run.PointerSources[0];

            return(source >= run.Start && source < run.Start + run.Length);
        }
Ejemplo n.º 5
0
 public override bool Matches(IFormattedRun run)
 {
     if (run is not TableStreamRun tableRun)
     {
         return(false);
     }
     if (!tableRun.AllowsZeroElements)
     {
         return(false);
     }
     if (tableRun.ElementContent.Count != 1)
     {
         return(false);
     }
     if (tableRun.ElementContent[0] is not ArrayRunPointerSegment pointerSegment)
     {
         return(false);
     }
     return(pointerSegment.InnerFormat.StartsWith("`uct4x") && pointerSegment.InnerFormat.EndsWith("`"));
 }
Ejemplo n.º 6
0
 public override bool Matches(IFormattedRun run)
 {
     if (!(run is TilemapRun tilemapRun))
     {
         return(false);
     }
     if (tilemapRun.Format.TileWidth != format.TileWidth)
     {
         return(false);
     }
     if (tilemapRun.Format.TileHeight != format.TileHeight)
     {
         return(false);
     }
     if (tilemapRun.Format.BitsPerPixel != format.BitsPerPixel)
     {
         return(false);
     }
     return(tilemapRun.Format.ExpectedUncompressedLength == format.ExpectedUncompressedLength);
 }
Ejemplo n.º 7
0
        public override ErrorInfo TryParseData(IDataModel model, string name, int dataIndex, ref IFormattedRun run)
        {
            var error = SpriteRunContentStrategy.IsValid(format.BitsPerPixel);

            if (error.HasError)
            {
                return(error);
            }
            var newRun = new TilemapRun(model, dataIndex, format);

            run = newRun;
            return(ErrorInfo.NoError);
        }
 public override ErrorInfo TryParseData(IDataModel model, string name, int dataIndex, ref IFormattedRun run)
 {
     run = new EggMoveRun(model, dataIndex);
     return(ErrorInfo.NoError);
 }
Ejemplo n.º 9
0
        private static bool DataMatchesSegmentFormat(IDataModel owner, int start, ArrayRunElementSegment segment, FormatMatchFlags flags, IFormattedRun nextAnchor)
        {
            if (start + segment.Length > nextAnchor.Start && nextAnchor is ArrayRun)
            {
                return(false);                                                                  // don't blap over existing arrays
            }
            switch (segment.Type)
            {
            case ElementContentType.PCS:
                int readLength = PCSString.ReadString(owner, start, true, segment.Length);
                if (readLength < 2)
                {
                    return(false);
                }
                if (readLength > segment.Length)
                {
                    return(false);
                }
                if (Enumerable.Range(start, segment.Length).All(i => owner[i] == 0xFF))
                {
                    return(false);
                }

                // if we end with a space, and the next one starts with a space, we probably have the data width wrong.
                // We might be the start of a different data segment that is no longer pointed to. (Example: Vega/pokenames)
                // only do this check if the current element seems useful
                var isBlank = Enumerable.Range(start, segment.Length).All(i => owner[i] == 0x00 || owner[i] == 0xFF);
                if (!isBlank && flags.HasFlag(FormatMatchFlags.IsSingleSegment) && start % 4 == 0 && owner[start + segment.Length - 1] == 0x00 && owner[start + segment.Length] == 0x00)
                {
                    // if the next one starts on a 4-byte boundary, then we probably just skipped a few bytes between different data types, and _this_ section is still part of the _last_ run (example, Emerald Ability names)
                    // if the next one doesn't start on a 4-byte boundary, then we probably have the length wrong
                    var nextWordStart = (start + segment.Length + 3) / 4 * 4;
                    if (Enumerable.Range(start + segment.Length, nextWordStart - start - segment.Length).Any(i => owner[i] != 0x00) || owner[nextWordStart] == 0x00)
                    {
                        return(false);
                    }
                }

                // require that the overall thing still ends with 'FF' or '00' to avoid finding text of the wrong width.
                // the width check is less important if we have more complex data, so relax the condition (example: Clover)
                // the width check is less important if we're already known to be in a long run (example: Gaia moves)
                var lastByteInText         = owner[start + segment.Length - 1];
                var lastByteIsReasonablEnd = lastByteInText == 0x00 || lastByteInText == 0xFF;
                if (!flags.HasFlag(FormatMatchFlags.AllowJunkAfterText) && !lastByteIsReasonablEnd && flags.HasFlag(FormatMatchFlags.IsSingleSegment))
                {
                    return(false);
                }

                return(true);

            case ElementContentType.Integer:
                if (segment is ArrayRunEnumSegment enumSegment)
                {
                    return(owner.ReadMultiByteValue(start, segment.Length) < enumSegment.GetOptions(owner).Count);
                }
                else
                {
                    return(true);
                }

            case ElementContentType.Pointer:
                var destination = owner.ReadPointer(start);
                if (destination == Pointer.NULL)
                {
                    return(true);
                }
                if (0 > destination || destination > owner.Count)
                {
                    return(false);
                }
                if (segment is ArrayRunPointerSegment pointerSegment)
                {
                    if (!pointerSegment.DestinationDataMatchesPointerFormat(owner, new NoDataChangeDeltaModel(), destination))
                    {
                        return(false);
                    }
                }
                return(true);

            case ElementContentType.BitArray:
                var bitArraySegment = (ArrayRunBitArraySegment)segment;
                var bits            = bitArraySegment.GetOptions(owner).Count;
                bits %= 8;
                if (bits == 0)
                {
                    return(true);
                }
                var finalByte = owner[start + bitArraySegment.Length - 1];
                finalByte >>= bits;
                return(finalByte == 0); // all the unneeded bits should be set to zero

            default:
                throw new NotImplementedException();
            }
        }
Ejemplo n.º 10
0
 /// <summary>
 /// A pointer format in a table has changed.
 /// Replace the given run with a new run of the appropriate format.
 /// </summary>
 public abstract void UpdateNewRunFromPointerFormat(IDataModel model, ModelDelta token, string name, IReadOnlyList <ArrayRunElementSegment> sourceSegments, int parentIndex, ref IFormattedRun run);
Ejemplo n.º 11
0
        public override void UpdateNewRunFromPointerFormat(IDataModel model, ModelDelta token, string name, ref IFormattedRun run)
        {
            var runAttempt = new TrainerPokemonTeamRun(model, run.Start, run.PointerSources);

            model.ClearFormat(token, run.Start, runAttempt.Length);
            run = runAttempt;
        }
Ejemplo n.º 12
0
        public override ErrorInfo TryParseData(IDataModel model, string name, int dataIndex, ref IFormattedRun run)
        {
            if (int.TryParse(Format.Substring(5), out var length))
            {
                run = new AsciiRun(model, dataIndex, length);
            }
            else
            {
                return(new ErrorInfo($"Ascii runs must include a length."));
            }

            return(ErrorInfo.NoError);
        }
Ejemplo n.º 13
0
 public override bool Matches(IFormattedRun run) => throw new NotImplementedException();
Ejemplo n.º 14
0
        public override ErrorInfo TryParseData(IDataModel model, string name, int dataIndex, ref IFormattedRun run)
        {
            var newRun = new OverworldSpriteListRun(model, parentTemplate, Hint, 0, dataIndex, run.PointerSources);

            if (newRun.Length > 0)
            {
                run = newRun;
                return(ErrorInfo.NoError);
            }
            newRun = new OverworldSpriteListRun(model, parentTemplate2, Hint, 0, dataIndex, run.PointerSources);
            if (newRun.Length > 0)
            {
                run = newRun;
                return(ErrorInfo.NoError);
            }
            return(new ErrorInfo($"Could not at overworld sprite at {dataIndex}"));
        }
Ejemplo n.º 15
0
        public override void UpdateNewRunFromPointerFormat(IDataModel model, ModelDelta token, string name, IReadOnlyList <ArrayRunElementSegment> sourceSegments, int parentIndex, ref IFormattedRun run)
        {
            var newRun = new TilemapRun(model, run.Start, format, run.PointerSources);

            model.ClearFormat(token, newRun.Start, newRun.Length);
            run = newRun;
        }
Ejemplo n.º 16
0
 public static NoInfoRun Proxy(IFormattedRun run) => new NoInfoRun(run.Start, run.PointerSources);
 public static object BuildContentForRun(IDataModel model, int source, int destination, IFormattedRun destinationRun, int preferredPaletteStart = -1, int preferredSpritePage = 0)
 {
     if (destination != destinationRun.Start)
     {
         return(null);
     }
     if (destinationRun is PCSRun pcs)
     {
         return(PCSString.Convert(model, pcs.Start, pcs.Length));
     }
     else if (destinationRun is ISpriteRun sprite)
     {
         if (sprite is LzTilemapRun tilemap)
         {
             tilemap.FindMatchingTileset(model);
         }
         var paletteRuns = sprite.FindRelatedPalettes(model, source);
         var paletteRun  = paletteRuns.FirstOrDefault();
         if (preferredPaletteStart >= 0)
         {
             paletteRun = paletteRuns.FirstOrDefault(pRun => pRun.Start == preferredPaletteStart) ?? model.GetNextRun(preferredPaletteStart) as IPaletteRun;
         }
         var pixels = sprite.GetPixels(model, preferredSpritePage);
         if (pixels == null)
         {
             return(null);
         }
         var colors    = paletteRun?.AllColors(model) ?? TileViewModel.CreateDefaultPalette((int)Math.Pow(2, sprite.SpriteFormat.BitsPerPixel));
         var imageData = SpriteTool.Render(pixels, colors, paletteRun?.PaletteFormat.InitialBlankPages ?? 0, 0);
         return(new ReadonlyPixelViewModel(sprite.SpriteFormat, imageData));
     }
     else if (destinationRun is IPaletteRun paletteRun)
     {
         var colors = paletteRun.GetPalette(model, 0);
         return(new ReadonlyPaletteCollection(colors));
     }
     else if (destinationRun is IStreamRun streamRun)
     {
         using (ModelCacheScope.CreateScope(model)) {
             var lines = streamRun.SerializeRun().Split(Environment.NewLine);
             if (lines.Length > 20)
             {
                 lines = lines.Take(20).ToArray();
             }
             return(Environment.NewLine.Join(lines));
         }
     }
     else if (destinationRun is ArrayRun arrayRun)
     {
         var stream = new StringBuilder();
         arrayRun.AppendTo(model, stream, arrayRun.Start, arrayRun.ElementLength * Math.Min(20, arrayRun.ElementCount), false);
         return(stream.ToString());
     }
     else
     {
         return(null);
     }
 }
 public override void UpdateNewRunFromPointerFormat(IDataModel model, ModelDelta token, string name, ref IFormattedRun run) => throw new NotImplementedException();
Ejemplo n.º 19
0
        public override ErrorInfo TryParseData(IDataModel model, string name, int dataIndex, ref IFormattedRun run)
        {
            var newRun = new TilemapRun(model, dataIndex, format);

            run = newRun;
            return(ErrorInfo.NoError);
        }
Ejemplo n.º 20
0
 /// <summary>
 /// Attempt to parse the existing data into a run of the desired type.
 /// </summary>
 public abstract ErrorInfo TryParseData(IDataModel model, string name, int dataIndex, ref IFormattedRun run);
Ejemplo n.º 21
0
 public override bool Matches(IFormattedRun run) => run is OverworldSpriteListRun;
Ejemplo n.º 22
0
 public override bool Matches(IFormattedRun run) => run is PCSRun;
Ejemplo n.º 23
0
        public override void UpdateNewRunFromPointerFormat(IDataModel model, ModelDelta token, string name, IReadOnlyList <ArrayRunElementSegment> sourceSegments, int parentIndex, ref IFormattedRun run)
        {
            run = new OverworldSpriteListRun(model, sourceSegments, Hint, parentIndex, run.Start, run.PointerSources);

            // backup: we may get asked to make a pointer format even when it's not an overworld sprite list.
            // if that happens, fall back to a NoInfoRun.
            if (run.Length == 0)
            {
                run = new NoInfoRun(run.Start, run.PointerSources);
            }
        }
Ejemplo n.º 24
0
        public override void UpdateNewRunFromPointerFormat(IDataModel model, ModelDelta token, string name, ref IFormattedRun run)
        {
            var length = PCSString.ReadString(model, run.Start, true);

            if (length > 0)
            {
                var newRun = new PCSRun(model, run.Start, length, run.PointerSources);
                if (!newRun.Equals(run))
                {
                    model.ClearFormat(token, newRun.Start, newRun.Length);
                }
                run = newRun;
            }
        }
Ejemplo n.º 25
0
 public override void UpdateNewRunFromPointerFormat(IDataModel model, ModelDelta token, string name, IReadOnlyList <ArrayRunElementSegment> sourceSegments, int parentIndex, ref IFormattedRun run) => throw new NotImplementedException();
Ejemplo n.º 26
0
        public override ErrorInfo TryParseData(IDataModel model, string name, int dataIndex, ref IFormattedRun run)
        {
            var length = PCSString.ReadString(model, dataIndex, true);

            if (length < 0)
            {
                return(new ErrorInfo($"Format was specified as a string, but no string was recognized."));
            }
            else if (PokemonModel.SpanContainsAnchor(model, dataIndex, length))
            {
                return(new ErrorInfo($"Format was specified as a string, but a string would overlap the next anchor."));
            }
            run = new PCSRun(model, dataIndex, length);

            return(ErrorInfo.NoError);
        }
Ejemplo n.º 27
0
 public override bool Matches(IFormattedRun run) => run is TrainerPokemonTeamRun;
Ejemplo n.º 28
0
        public override void UpdateNewRunFromPointerFormat(IDataModel model, ModelDelta token, string name, IReadOnlyList <ArrayRunElementSegment> sourceSegments, int parentIndex, ref IFormattedRun run)
        {
            var runAttempt = new TrainerPokemonTeamRun(model, run.Start, run.PointerSources);

            model.ClearFormat(token, run.Start, runAttempt.Length);
            run = runAttempt;
        }
Ejemplo n.º 29
0
 public override ErrorInfo TryParseData(IDataModel model, string name, int dataIndex, ref IFormattedRun run)
 {
     run = new TrainerPokemonTeamRun(model, dataIndex, run.PointerSources);
     return(ErrorInfo.NoError);
 }
Ejemplo n.º 30
0
 private static bool DataMatchesElementFormat(IDataModel owner, int start, IReadOnlyList <ArrayRunElementSegment> segments, FormatMatchFlags flags, IFormattedRun nextAnchor)
 {
     foreach (var segment in segments)
     {
         if (start + segment.Length > owner.Count)
         {
             return(false);
         }
         if (!DataMatchesSegmentFormat(owner, start, segment, flags, nextAnchor))
         {
             return(false);
         }
         start += segment.Length;
     }
     return(true);
 }