public TableStreamRun Append(TableStreamRun run, ModelDelta token, int length)
        {
            var naturalLength = run.Length - EndCode.Count;
            var newRun        = model.RelocateForExpansion(token, run, naturalLength + length * run.ElementLength + EndCode.Count);

            if (naturalLength == 0)
            {
                for (int i = 0; i < run.ElementLength * length; i++)
                {
                    token.ChangeData(model, newRun.Start + naturalLength + i, 0);
                }
            }
            else
            {
                for (int i = 0; i < run.ElementLength * length; i++)
                {
                    token.ChangeData(model, newRun.Start + naturalLength + i, model[newRun.Start + naturalLength + i - run.ElementLength]);
                }
            }
            for (int i = naturalLength + length * run.ElementLength; i < naturalLength; i++)
            {
                if (model[newRun.Start + i] != 0xFF)
                {
                    token.ChangeData(model, newRun.Start + i, 0xFF);
                }
            }
            for (int i = 0; i < EndCode.Count; i++)
            {
                token.ChangeData(model, newRun.Start + naturalLength + length * run.ElementLength + i, EndCode[i]);
            }
            return(new TableStreamRun(model, newRun.Start, run.PointerSources, run.FormatString, run.ElementContent, this, run.ElementCount + length));
        }
Beispiel #2
0
        public static ITilesetRun SetPixels(ITilesetRun run, IDataModel model, ModelDelta token, IReadOnlyList <int[, ]> tiles, Func <int, SortedSpan <int>, ITilesetRun> construct)
        {
            var tileSize = 8 * run.TilesetFormat.BitsPerPixel;
            var data     = new byte[tiles.Count * tileSize];

            for (int i = 0; i < tiles.Count; i++)
            {
                SpriteRun.SetPixels(data, i * tileSize, tiles[i], run.TilesetFormat.BitsPerPixel);
            }

            var newModelData = Compress(data, 0, data.Length);
            var newRun       = model.RelocateForExpansion(token, run, newModelData.Count);

            for (int i = 0; i < newModelData.Count; i++)
            {
                token.ChangeData(model, newRun.Start + i, newModelData[i]);
            }
            for (int i = newModelData.Count; i < run.Length; i++)
            {
                token.ChangeData(model, newRun.Start + i, 0xFF);
            }
            newRun = construct(newRun.Start, newRun.PointerSources);
            model.ObserveRunWritten(token, newRun);
            return(newRun);
        }
        public TableStreamRun Append(TableStreamRun run, ModelDelta token, int length)
        {
            var parentIndex = GetParentIndex(run.PointerSources);
            var parent      = model.GetNextRun(parentIndex) as ITableRun;

            if (parent == null)
            {
                return(run);
            }
            var segmentIndex = GetSegmentIndex(parent.ElementContent, parentFieldForLength);

            if (segmentIndex == -1)
            {
                return(run);
            }

            UpdateParents(token, parent, segmentIndex, run.ElementCount + length, run.PointerSources);

            var naturalLength = run.Length;
            var newRun        = (TableStreamRun)model.RelocateForExpansion(token, run, naturalLength + length * run.ElementLength);

            for (int i = 0; i < run.ElementLength * length; i++)
            {
                token.ChangeData(model, newRun.Start + naturalLength + i, 0x00);
            }
            for (int i = naturalLength + length * run.ElementLength; i < naturalLength; i++)
            {
                if (model[newRun.Start + i] != 0xFF)
                {
                    token.ChangeData(model, newRun.Start + i, 0xFF);
                }
            }
            return(new TableStreamRun(model, newRun.Start, run.PointerSources, run.FormatString, run.ElementContent, this));
        }
Beispiel #4
0
        public ISpriteRun SetPixels(IDataModel model, ModelDelta token, int[][,] tiles)
        {
            var tileSize = 8 * Format.BitsPerPixel;
            var data     = new byte[tiles.Length * tileSize];

            for (int i = 0; i < tiles.Length; i++)
            {
                SpriteRun.SetPixels(data, i * tileSize, tiles[i], Format.BitsPerPixel);
            }

            var newModelData = Compress(data, 0, data.Length);
            var newRun       = (LzTilesetRun)model.RelocateForExpansion(token, this, newModelData.Count);

            for (int i = 0; i < newModelData.Count; i++)
            {
                token.ChangeData(model, newRun.Start + i, newModelData[i]);
            }
            for (int i = newModelData.Count; i < Length; i++)
            {
                token.ChangeData(model, newRun.Start + i, 0xFF);
            }
            newRun = new LzTilesetRun(Format, model, newRun.Start, newRun.PointerSources);
            model.ObserveRunWritten(token, newRun);
            return(newRun);
        }
Beispiel #5
0
        public ISpriteRun SetPixels(IDataModel model, ModelDelta token, int page, int[,] pixels)
        {
            var data = Decompress(model, Start, allowLengthErrors: true);

            page %= Pages;

            var pageLength = SpriteFormat.TileWidth * SpriteFormat.TileHeight * 8 * SpriteFormat.BitsPerPixel;

            SpriteRun.SetPixels(data, page * pageLength, pixels, SpriteFormat.BitsPerPixel);

            var newModelData = Compress(data, 0, data.Length);
            var newRun       = (ISpriteRun)model.RelocateForExpansion(token, this, newModelData.Count);

            for (int i = 0; i < newModelData.Count; i++)
            {
                token.ChangeData(model, newRun.Start + i, newModelData[i]);
            }
            for (int i = newModelData.Count; i < Length; i++)
            {
                token.ChangeData(model, newRun.Start + i, 0xFF);
            }
            newRun = new LzSpriteRun(SpriteFormat, model, newRun.Start, newRun.PointerSources);
            model.ObserveRunWritten(token, newRun);
            return(newRun);
        }
Beispiel #6
0
        public IStreamRun DeserializeRun(string content, ModelDelta token)
        {
            var uncompressed = new List <byte>();

            foreach (var textByte in content.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries))
            {
                if (byte.TryParse(textByte, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out byte value))
                {
                    uncompressed.Add(value);
                }
            }
            var        compressed = Compress(uncompressed, 0, uncompressed.Count);
            IStreamRun run        = this;

            if (compressed.Count > Length)
            {
                run = (IStreamRun)Model.RelocateForExpansion(token, this, compressed.Count);
            }
            for (int i = 0; i < compressed.Count; i++)
            {
                token.ChangeData(Model, run.Start + i, compressed[i]);
            }
            for (int i = compressed.Count; i < Length; i++)
            {
                token.ChangeData(Model, run.Start + i, 0xFF);
            }
            return((LZRun)Duplicate(run.Start, PointerSources));
        }
Beispiel #7
0
        public ISpriteRun SetPixels(IDataModel model, ModelDelta token, int page, int[,] pixels)
        {
            // TODO handle the fact that pixels[,] may contain a different number of tiles compared to the existing tileset
            var data = Decompress(model, Start);

            for (int x = 0; x < pixels.GetLength(0); x++)
            {
                for (int y = 0; y < pixels.GetLength(1); y++)
                {
                    pixels[x, y] %= (int)Math.Pow(2, TilesetFormat.BitsPerPixel);
                }
            }
            SpriteRun.SetPixels(data, 0, pixels, TilesetFormat.BitsPerPixel);
            var newModelData = Compress(data, 0, data.Length);
            var newRun       = model.RelocateForExpansion(token, this, newModelData.Count);

            for (int i = 0; i < newModelData.Count; i++)
            {
                token.ChangeData(model, newRun.Start + i, newModelData[i]);
            }
            for (int i = newModelData.Count; i < Length; i++)
            {
                token.ChangeData(model, newRun.Start + i, 0xFF);
            }
            newRun = new LzTilesetRun(TilesetFormat, model, newRun.Start, newRun.PointerSources);
            model.ObserveRunWritten(token, newRun);
            return(newRun);
        }
        public ISpriteRun SetPixels(IDataModel model, ModelDelta token, int page, int[,] pixels)
        {
            var tileData       = Tilize(pixels);
            var tiles          = GetUniqueTiles(tileData);
            var tilesetAddress = model.GetAddressFromAnchor(new NoDataChangeDeltaModel(), -1, Format.MatchingTileset);
            var tileset        = model.GetNextRun(tilesetAddress) as LzTilesetRun;

            if (tileset == null)
            {
                tileset = model.GetNextRun(arrayTilesetAddress) as LzTilesetRun;
            }
            tileset.SetPixels(model, token, tiles);
            if (tiles.Length > 0x400)
            {
                // TODO fail: too many unique tiles
                return(this);
            }
            var mapData = Decompress(model, Start);

            var tileWidth  = tileData.GetLength(0);
            var tileHeight = tileData.GetLength(1);

            for (int y = 0; y < tileHeight; y++)
            {
                for (int x = 0; x < tileWidth; x++)
                {
                    var i = y * tileWidth + x;
                    var(tile, paletteIndex)   = tileData[x, y];
                    var(tileIndex, matchType) = FindMatch(tile, tiles);
                    var mapping = PackMapping(paletteIndex, matchType, tileIndex);
                    mapData[i * 2 + 0] = (byte)mapping;
                    mapData[i * 2 + 1] = (byte)(mapping >> 8);
                }
            }

            var newModelData = Compress(mapData, 0, mapData.Length);
            var newRun       = (ISpriteRun)model.RelocateForExpansion(token, this, newModelData.Count);

            for (int i = 0; i < newModelData.Count; i++)
            {
                token.ChangeData(model, newRun.Start + i, newModelData[i]);
            }
            for (int i = newModelData.Count; i < Length; i++)
            {
                token.ChangeData(model, newRun.Start + i, 0xFF);
            }
            newRun = new LzTilemapRun(Format, model, newRun.Start, newRun.PointerSources);
            model.ObserveRunWritten(token, newRun);
            return(newRun);
        }
Beispiel #9
0
        /// <returns>The first offset that was edited</returns>
        public static int ApplyIPSPatch(IDataModel model, byte[] patch, ModelDelta token)
        {
            // 5 byte header (PATCH) and 3 byte footer (EOF)
            // hunk type 1: offset (3 bytes), length (2 bytes), payload (length bytes). Write the payload at offset.
            // RLE hunk:    offset (3 bytes), 00 00, length (2 bytes), target (1 byte). Write the target, length times, at offset

            var start       = 5;
            var firstOffset = -1;

            while (patch.Length - start >= 6)
            {
                var offset = (patch[start] << 16) + (patch[start + 1] << 8) + patch[start + 2];
                if (firstOffset < 0)
                {
                    firstOffset = offset;
                }
                start += 3;
                var length = (patch[start] << 8) + patch[start + 1];
                start += 2;
                if (length > 0)
                {
                    // normal
                    model.ExpandData(token, offset + length - 1);
                    while (length > 0)
                    {
                        token.ChangeData(model, offset, patch[start]);
                        offset += 1;
                        start  += 1;
                        length -= 1;
                    }
                }
                else
                {
                    length = (patch[start] << 8) + patch[start + 1];
                    start += 2;
                    model.ExpandData(token, offset + length - 1);
                    // rle
                    while (length > 0)
                    {
                        token.ChangeData(model, offset, patch[start]);
                        offset += 1;
                        length -= 1;
                    }
                    start += 1;
                }
            }

            return(firstOffset);
        }
        public void ArraysSupportEnums()
        {
            var changeToken = new ModelDelta();

            var(model, viewPort) = (Model, ViewPort);

            // arrange: setup the anchor used for the enums
            WriteStrings(model.RawData, 0x00, "cat", "bat", "hat", "sat");
            ArrayRun.TryParse(model, "^[name\"\"4]4", 0x00, null, out var arrayRun);
            model.ObserveAnchorWritten(changeToken, "sample", arrayRun);

            // arrange: setup the anchor with the data
            ArrayRun.TryParse(model, "[option:sample]4", 0x40, null, out arrayRun);
            model.ObserveAnchorWritten(changeToken, "data", arrayRun);

            changeToken.ChangeData(model, 0x42, 2);

            // act: see that the arrayRun can parse according to the enum
            arrayRun = (ArrayRun)model.GetNextRun(0x40);
            Assert.Equal("cat", arrayRun.ElementContent[0].ToText(model, 0x40));
            Assert.Equal("hat", arrayRun.ElementContent[0].ToText(model, 0x42));

            viewPort.Refresh();
            var enumViewModel = (IntegerEnum)((Anchor)viewPort[0, 4].Format).OriginalFormat;

            Assert.Equal("cat", enumViewModel.Value);
        }
Beispiel #11
0
        public void ViewPortWarnsIfLoadedMatchedWordValueDoesNotMatch()
        {
            // Arrange
            var data   = new byte[0x200];
            var model  = new PokemonModel(data);
            var change = new ModelDelta();

            ArrayRun.TryParse(model, "[a:]8", 0x10, null, out var table);
            model.ObserveAnchorWritten(change, "table", table);
            change.AddMatchedWord(model, 0, "table");
            model.ObserveRunWritten(change, new WordRun(0, "table"));

            fileSystem.MetadataFor = name => model.ExportMetadata().Serialize();
            fileSystem.OpenFile    = (name, extensions) => new LoadedFile(name, data);
            var editor = new EditorViewModel(fileSystem);

            // change the data so that the viewPort will notice something weird
            change.ChangeData(model, 0, 4);

            // Act
            editor.Open.Execute("text.gba");

            // Assert
            Assert.True(editor.ShowMessage);
        }
Beispiel #12
0
        public void Visit(BitArray array, byte data)
        {
            var currentText = CurrentText.Replace(" ", "");

            if (currentText.Length < array.Length * 2)
            {
                return;
            }
            Result = true;
            var parseArray = new byte[array.Length];

            for (int i = 0; i < array.Length; i++)
            {
                if (!byte.TryParse(currentText.Substring(i * 2, 2), NumberStyles.HexNumber, CultureInfo.CurrentCulture.NumberFormat, out var result))
                {
                    ErrorText = $"Could not parse {CurrentText} as a bit-array.";
                    return;
                }
                parseArray[i] = result;
            }
            for (int i = 0; i < array.Length; i++)
            {
                CurrentChange.ChangeData(Model, memoryLocation + i, parseArray[i]);
            }

            NewDataIndex = memoryLocation + array.Length;
            Result       = true;
        }
Beispiel #13
0
 public void Clear(IDataModel model, ModelDelta changeToken, int start, int length)
 {
     for (int i = 0; i < length; i++)
     {
         changeToken.ChangeData(model, start + i, 0x00);
     }
 }
Beispiel #14
0
        private static int RunUPSPatchAlgorithm(IDataModel model, byte[] patch, ModelDelta token, int writeLength, int destinationSize, ref int readIndex)
        {
            int writeIndex = 0;
            int firstEdit  = int.MaxValue;

            while (readIndex < patch.Length - 12 && writeIndex < destinationSize)
            {
                var skipSize = ReadVariableWidthInteger(patch, ref readIndex);
                writeIndex += skipSize;
                if (writeIndex > writeLength)
                {
                    return(-7);
                }
                if (firstEdit == int.MaxValue)
                {
                    firstEdit = skipSize;
                }

                while (patch[readIndex] != 0 && writeIndex < destinationSize)
                {
                    token.ChangeData(model, writeIndex, (byte)(patch[readIndex] ^ model[writeIndex]));
                    readIndex  += 1;
                    writeIndex += 1;
                    if (writeIndex > writeLength)
                    {
                        return(-7);
                    }
                }
                readIndex  += 1;
                writeIndex += 1;
            }

            return(firstEdit);
        }
Beispiel #15
0
        /// <param name="newRawData">Uncompressed data that we want to compress and insert.</param>
        public ITilemapRun ReplaceData(byte[] newRawData, ModelDelta token)
        {
            var newModelData = newRawData.ToList();
            var newRun       = Model.RelocateForExpansion(token, this, newModelData.Count);

            for (int i = 0; i < newModelData.Count; i++)
            {
                token.ChangeData(Model, newRun.Start + i, newModelData[i]);
            }
            for (int i = newModelData.Count; i < Length; i++)
            {
                token.ChangeData(Model, newRun.Start + i, 0xFF);
            }
            newRun = new TilemapRun(Model, newRun.Start, Format, newRun.PointerSources);
            Model.ObserveRunWritten(token, newRun);
            return(newRun);
        }
Beispiel #16
0
        private static ISpriteRun Resize(IDataModel model, ModelDelta token, ISpriteRun spriteRun, int tileWidth, int tileHeight)
        {
            if (spriteRun == null)
            {
                return(spriteRun);
            }
            spriteRun = model.RelocateForExpansion(token, spriteRun, tileWidth * tileHeight * TileSize);
            var format = spriteRun.SpriteFormat;

            // extract existing tile data
            var existingTiles = new byte[format.TileWidth, format.TileHeight][];

            for (int x = 0; x < format.TileWidth; x++)
            {
                for (int y = 0; y < format.TileHeight; y++)
                {
                    var tileIndex = y * format.TileWidth + x;
                    existingTiles[x, y] = new byte[TileSize];
                    Array.Copy(model.RawData, spriteRun.Start + tileIndex * TileSize, existingTiles[x, y], 0, TileSize);
                }
            }

            // rewrite it with the new dimensions
            for (int x = 0; x < tileWidth; x++)
            {
                for (int y = 0; y < tileHeight; y++)
                {
                    var tileIndex = y * tileWidth + x;
                    var start     = spriteRun.Start + tileIndex * TileSize;
                    for (int i = 0; i < TileSize; i++)
                    {
                        if (x < format.TileWidth && y < format.TileHeight)
                        {
                            token.ChangeData(model, start + i, existingTiles[x, y][i]);
                        }
                        else
                        {
                            token.ChangeData(model, start + i, 0);
                        }
                    }
                }
            }

            return(spriteRun);
        }
        private void UpdatePokemonThumbConstants(IEditableViewPort viewPort, ModelDelta token, int pokecountFunctionAddress)
        {
            var model = viewPort.Model;

            byte[] compile(int adr, int reg) => viewPort.Tools.CodeTool.Parser.Compile(token, model, adr, $"bl <{pokecountFunctionAddress + reg * 4:X6}>").ToArray();

            var registerUpdates = new[] {
                new[] { 0x00FFFA, 0x0118D0, 0x02A81A, 0x02CEAC, 0x07FE12, // r0
                        0x0E6590, 0x0A0470, 0x0F31B2, 0x0FBFD6, 0x0DABB4,
                        0x0DAC1A, 0x094A1A, 0x043766, 0x043C42, 0x043E5C,
                        0x0440FE, 0x113EC0, 0x113EE0, 0x05148E, 0x052174,
                        0x05287E, 0x0535D0, 0x04FAA2, 0x04FC5E, 0x04FC8C,
                        0x04FCA2, 0x04FD04, 0x11AC1E, 0x11ADD4, 0x11ADF0,
                        0x11B030, 0x11B19A, 0x074658, 0x074728, 0x074788,
                        0x076BEC, 0x076CC8, 0x011F74, 0x0459CC, 0x00EC94,
                        0x00ED6C, 0x00F0E4, 0x00F1B0, 0x096E72, 0x096F86,
                        0x0970A6, 0x09713E, 0x0971D2, 0x0971FE, 0x040FDA,
                        0x09700A, },
                new[] { 0x0C839C, 0x0C8756, 0x0C882C, 0x0392CE, 0x0394FC, // r1
                        0x03994C, 0x039BC0, 0x03A234, 0x00D7E4, 0x00D854,
                        0x01196A, 0x013384, 0x013400, 0x01348C, 0x025BF8,
                        0x026DF0, 0x02B9A8, 0x02C9C8, 0x019CA4, 0x019D5A,
                        0x0CAD20, 0x0F23E4, 0x0F2E32, 0x0F32A4, 0x0F32E6,
                        0x040D0C, 0x15EBE0, 0x1193FA, 0x11B11C, 0x074624,
                        0x0746F0, 0x076BD8, 0x076C98, 0x011F3C, 0x096F78, },
                new[] { 0x026E8E, 0x00ED3E, 0x00F182, 0x096FFC, }, // r2
                new[] { 0x04FAE6 },                                // r3
                new[] { 0x040036, 0x0401A6, 0x12EAA4 },            // r4
                new int[0],                                        // r5
                new int[0],                                        // r6
                new int[] { 0x0A0224 },                            // r7
            };

            for (int register = 0; register < 8; register++)
            {
                foreach (var address in registerUpdates[register])
                {
                    token.ChangeData(model, address, compile(address, register));
                }
            }

            token.ChangeData(model, 0x103726, viewPort.Tools.CodeTool.Parser.Compile(token, model, 0x103726, $"bl <{pokecountFunctionAddress + 32:X6}>").ToArray()); // pokedex_screen
            token.ChangeData(model, 0x0BECA2, viewPort.Tools.CodeTool.Parser.Compile(token, model, 0x0BECA2, $"bl <{pokecountFunctionAddress + 36:X6}>").ToArray()); // ReadMail
            token.ChangeData(model, 0x12EAB4, viewPort.Tools.CodeTool.Parser.Compile(token, model, 0x12EAB4, $"bl <{pokecountFunctionAddress + 40:X6}>").ToArray()); // Menu2_GetMonSpriteAnchorCoord, species = SPECIES_OLD_UNOWN_B + unownLetter - 1
        }
Beispiel #18
0
        public ITableRun Append(ModelDelta token, int length)
        {
            var totalLength = ElementLength * (ElementCount + length);
            var workingRun  = this;

            if (totalLength > workingRun.Length)
            {
                workingRun = model.RelocateForExpansion(token, workingRun, totalLength);
            }

            // delete old elements
            for (int i = -1; i >= length; i--)
            {
                var start = workingRun.Start + Length + i * ElementLength;
                for (int j = 0; j < ElementLength; j++)
                {
                    token.ChangeData(model, start + j, 0xFF);
                }
            }

            // add new elements
            for (int i = 0; i < length; i++)
            {
                var start = workingRun.Start + Length + i * ElementLength;
                for (int j = 0; j < ElementLength; j++)
                {
                    if (ElementCount > 0)
                    {
                        var previousMemberValue = model[start + j - ElementLength];
                        token.ChangeData(model, start + j, previousMemberValue);
                    }
                    else
                    {
                        token.ChangeData(model, start + j, 0x00);
                    }
                }
            }

            // update parent
            var parent = workingRun.PointerSources[0] - TrainerFormat_PointerOffset;

            model.WriteMultiByteValue(parent + TrainerFormat_PokemonCountOffset, 4, token, ElementCount + length);
            return(new TrainerPokemonTeamRun(model, workingRun.Start, showFullIVByteRange, workingRun.PointerSources));
        }
Beispiel #19
0
        private void WriteData(ModelDelta token, int runStart, TeamData data, HashSet <int> changedAddresses)
        {
            var elementLength = data.MovesIncluded ? 16 : 8;

            for (int i = 0; i < data.Pokemon.Count; i++)
            {
                int start = runStart + elementLength * i;
                if (model.WriteMultiByteValue(start + 0, 2, token, data.IVs[i]))
                {
                    changedAddresses.Add(start);
                }
                if (model.WriteMultiByteValue(start + 2, 2, token, data.Levels[i]))
                {
                    changedAddresses.Add(start + 2);
                }
                if (model.WriteMultiByteValue(start + 4, 2, token, data.Pokemon[i]))
                {
                    changedAddresses.Add(start + 4);
                }
                start += 6;
                if (data.ItemsIncluded)
                {
                    if (model.WriteMultiByteValue(start, 2, token, data.Items[i]))
                    {
                        changedAddresses.Add(start + 2);
                    }
                    start += 2;
                }
                if (data.MovesIncluded)
                {
                    for (int j = 0; j < 4; j++)
                    {
                        if (model.WriteMultiByteValue(start + j * 2, 2, token, data.Moves[i * 4 + j]))
                        {
                            changedAddresses.Add(start + j * 2);
                        }
                    }
                    start += 8;
                }

                // if there's no item, add 2 more bytes to get to the next multiple of 4.
                if (!data.ItemsIncluded)
                {
                    if (model.WriteMultiByteValue(start, 2, token, 0))
                    {
                        changedAddresses.Add(start);
                    }
                }
            }

            // free space from the original run that's not needed by the new run
            for (int i = elementLength * data.Pokemon.Count; i < Length; i++)
            {
                token.ChangeData(model, runStart + i, 0xFF); // intentionally don't notify, these elements don't exist anymore.
            }
        }
Beispiel #20
0
        public override IFormattedRun WriteNewRun(IDataModel owner, ModelDelta token, int source, int destination, string name, IReadOnlyList <ArrayRunElementSegment> sourceSegments)
        {
            var defaultData = new byte[format.TileWidth * format.TileHeight * 2];

            for (int i = 0; i < defaultData.Length; i++)
            {
                token.ChangeData(owner, destination + i, defaultData[i]);
            }
            return(new TilemapRun(owner, destination, format));
        }
Beispiel #21
0
 public override void Write(IDataModel model, ModelDelta token, int start, string data)
 {
     for (int i = 0; i < Length && i * 2 + 1 < data.Length; i++)
     {
         if (!byte.TryParse(data.Substring(i * 2, 2), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out var value))
         {
             value = 0;
         }
         token.ChangeData(model, start + i, value);
     }
 }
Beispiel #22
0
        public ISpriteRun SetPixels(IDataModel model, ModelDelta token, int page, int[,] pixels)
        {
            var data = new byte[pixels.Length * SpriteFormat.BitsPerPixel / 8];

            SetPixels(data, 0, pixels, SpriteFormat.BitsPerPixel);
            for (int i = 0; i < data.Length; i++)
            {
                token.ChangeData(model, Start + i, data[i]);
            }
            return(this);
        }
        public void Visit(BitArray array, byte data)
        {
            if (CurrentText.Length < 2)
            {
                return;
            }
            var byteValue = byte.Parse(CurrentText, NumberStyles.HexNumber);

            CurrentChange.ChangeData(Model, memoryLocation, byteValue);
            NewDataIndex = memoryLocation + 1;
            Result       = true;
        }
Beispiel #24
0
        public IStreamRun DeserializeRun(string content, ModelDelta token, out IReadOnlyList <int> changedOffsets)
        {
            var data             = new List <int>();
            var changedAddresses = new HashSet <int>();
            var moveNames        = model.GetOptions(HardcodeTablesModel.MoveNamesTable);

            moveNames = moveNames.Select(name => name.Trim('"').ToLower()).ToList();

            var lines = content.ToLower().Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);

            foreach (var line in lines)
            {
                var parts = line.Split(new[] { ' ' }, 2);
                if (!int.TryParse(parts[0], out var level))
                {
                    continue;
                }
                var moveName = parts.Length == 1 ? "0" : parts[1];
                moveName = moveName.Trim().Trim('"');

                var index = moveNames.IndexOf(moveName);
                if (index != -1)
                {
                    data.Add(CombineToken(level, index)); continue;
                }

                // look for a partial move match
                for (int i = 0; i < moveNames.Count; i++)
                {
                    if (moveNames[i].MatchesPartial(moveName))
                    {
                        data.Add(CombineToken(level, i)); break;
                    }
                }
            }

            var run = model.RelocateForExpansion(token, this, data.Count * 2 + 2);

            for (int i = 0; i < data.Count; i++)
            {
                if (model.WriteMultiByteValue(run.Start + i * 2, 2, token, data[i]))
                {
                    changedAddresses.Add(run.Start + i * 2);
                }
            }
            model.WriteMultiByteValue(run.Start + data.Count * 2, 2, token, EggMoveRun.EndStream); // write the new end token (not tracked)
            for (int i = data.Count * 2 + 2; i < Length; i++)
            {
                token.ChangeData(model, run.Start + i, 0xFF);                                            // fill any remaining old space with FF (not tracked)
            }
            changedOffsets = new List <int>(changedAddresses);
            return(new PLMRun(model, run.Start));
        }
Beispiel #25
0
        /// <summary>
        /// In response to a change to the raw data,
        /// shorten or lengthen the run.
        /// </summary>
        public LZRun FixupEnd(IDataModel model, ModelDelta token, int fixupStart)
        {
            var newData = RecommendedFixup(fixupStart);

            if (newData == null)
            {
                return(null);
            }
            var newRun   = model.RelocateForExpansion(token, this, newData.Count);
            var newStart = newRun.Start;

            for (int i = 0; i < newData.Count; i++)
            {
                token.ChangeData(model, newStart + i, newData[i]);
            }
            for (int i = newData.Count; i < Length; i++)
            {
                token.ChangeData(model, newStart + i, 0xFF);
            }
            return((LZRun)Duplicate(newStart, newRun.PointerSources));
        }
 public static bool TryWriteNewEndToken(ModelDelta token, ref TableStreamRun tableStream)
 {
     if (!(tableStream.endStream is EndCodeStreamStrategy strategy))
     {
         return(false);
     }
     for (int i = 0; i < strategy.EndCode.Count; i++)
     {
         token.ChangeData(tableStream.model, tableStream.Start + i, strategy.EndCode[i]);
     }
     tableStream = (TableStreamRun)tableStream.Clone(tableStream.PointerSources);
     return(true);
 }
Beispiel #27
0
        public PagedLZRun DeletePage(int page, ModelDelta token)
        {
            var data       = Decompress(Model, Start);
            var pageLength = UncompressedPageLength;
            var newData    = new byte[data.Length - pageLength];

            Array.Copy(data, newData, page * pageLength);
            Array.Copy(data, (page + 1) * pageLength, newData, page * pageLength, (Pages - page - 1) * pageLength);
            var newModelData = Compress(newData, 0, newData.Length);

            for (int i = 0; i < newModelData.Count; i++)
            {
                token.ChangeData(Model, Start + i, newModelData[i]);
            }
            for (int i = newModelData.Count; i < Length; i++)
            {
                token.ChangeData(Model, Start + i, 0xFF);
            }
            var newRun = (PagedLZRun)Duplicate(Start, PointerSources);

            Model.ObserveRunWritten(token, newRun);
            return(newRun);
        }
Beispiel #28
0
        public LzSpriteRun IncreaseHeight(int tiles, ModelDelta token)
        {
            var data         = Decompress(Model, Start);
            var longerData   = data.Concat(new byte[SpriteFormat.ExpectedByteLength / SpriteFormat.TileHeight * tiles]).ToArray();
            var newModelData = Compress(longerData, 0, longerData.Length);

            var newRun = Model.RelocateForExpansion(token, this, newModelData.Count);

            for (int i = 0; i < newModelData.Count; i++)
            {
                token.ChangeData(Model, newRun.Start + i, newModelData[i]);
            }
            for (int i = newModelData.Count; i < Length; i++)
            {
                token.ChangeData(Model, newRun.Start + i, 0xFF);
            }

            var newFormat = new SpriteFormat(SpriteFormat.BitsPerPixel, SpriteFormat.TileWidth, SpriteFormat.TileHeight + tiles, SpriteFormat.PaletteHint, SpriteFormat.AllowLengthErrors);

            newRun = new LzSpriteRun(newFormat, Model, newRun.Start, newRun.PointerSources);
            Model.ObserveRunWritten(token, newRun);
            return(newRun);
        }
        public IPaletteRun SetPalette(IDataModel model, ModelDelta token, int page, IReadOnlyList <short> colors)
        {
            page %= Pages;
            var pageLength = PaletteFormat.ExpectedByteLengthPerPage;
            var start      = Start + page * pageLength;

            var data = new byte[pageLength];

            SetPalette(data, 0, colors);
            for (int i = 0; i < data.Length; i++)
            {
                token.ChangeData(model, start + i, data[i]);
            }
            return(this);
        }
        public IPaletteRun SetPalette(IDataModel model, ModelDelta token, int page, IReadOnlyList <short> colors)
        {
            var data       = Decompress(model, Start);
            var colorCount = (int)Math.Pow(2, PaletteFormat.Bits);
            var pageLength = colorCount * 2;

            page %= Pages;
            PaletteRun.SetPalette(data, page * pageLength, colors);

            var newModelData = Compress(data, 0, data.Length);
            var newRun       = (IPaletteRun)model.RelocateForExpansion(token, this, newModelData.Count);

            for (int i = 0; i < newModelData.Count; i++)
            {
                token.ChangeData(model, newRun.Start + i, newModelData[i]);
            }
            for (int i = newModelData.Count; i < Length; i++)
            {
                token.ChangeData(model, newRun.Start + i, 0xFF);
            }
            newRun = new LzPaletteRun(PaletteFormat, model, newRun.Start, newRun.PointerSources);
            model.ObserveRunWritten(token, newRun);
            return(newRun);
        }