public void ExtendingTableWithLengthMinusOneFromParentOnlyAddsOneElement() { var data = new byte[0x200]; var model = new PokemonModel(data); var token = new ModelDelta(); // Arrange - 2 tables, a parent and a child. The child is one shorter than the parent. ArrayRun.TryParse(model, "[element:]10", 0x20, null, out var parent); model.ObserveAnchorWritten(token, "parent", parent); ArrayRun.TryParse(model, "[element:]parent-1", 0x40, null, out var child); model.ObserveAnchorWritten(token, "child", child); Assert.Equal(9, child.ElementCount); // Adding via the child should extend the child by 1. child = model.GetTable("child"); var errorInfo = model.CompleteArrayExtension(token, 1, ref child); Assert.Equal(ErrorInfo.NoError, errorInfo); Assert.Equal(10, child.ElementCount); // Adding via the parent should extend the child by 1. parent = model.GetTable("parent"); errorInfo = model.CompleteArrayExtension(token, 1, ref parent); child = model.GetTable("child"); Assert.Equal(ErrorInfo.NoError, errorInfo); Assert.Equal(11, child.ElementCount); }
// example serialized pokemon: // // 50 Butterfree (31)@"Silk Powder" // - "Stun Spore" // - "Super Sonic" // - "Aerial Ace" // - "Silver Wind" public IStreamRun DeserializeRun(string content, ModelDelta token) { var lines = content.Split(Environment.NewLine).Select(line => line.Trim()).ToArray(); // step 1: parse it into some data containers var data = new TeamData(ModelCacheScope.GetCache(model), lines); // step 2: figure out what I need based on the data var elementLength = data.MovesIncluded ? 16 : 8; var totalLength = elementLength * data.Pokemon.Count; var workingRun = this; if (totalLength > workingRun.Length) { workingRun = (TrainerPokemonTeamRun)model.RelocateForExpansion(token, workingRun, totalLength); } // step 3: write the run data WriteData(token, workingRun.Start, data); // step 4: write the parent data var structType = (data.ItemsIncluded ? INCLUDE_ITEM : 0) ^ (data.MovesIncluded ? INCLUDE_MOVES : 0); UpdateParents(token, structType, data.Pokemon.Count, workingRun.PointerSources); return(new TrainerPokemonTeamRun(model, workingRun.Start, workingRun.PointerSources)); }
public void PointerModelFindsPointersInRange() { var rnd = new Random(0xCafe); var buffer = new byte[0x10000]; // 64KB rnd.NextBytes(buffer); for (int i = 0; i < buffer.Length; i++) { if (buffer[i] == 0x08) { buffer[i] = 0x10; } } // write two specific pointers var model = new PokemonModel(buffer); var token = new ModelDelta(); model.WritePointer(token, 0x204, 0x4050); model.WritePointer(token, 0x4070, 0x101C); model = new PokemonModel(buffer); Assert.Equal(0x204, model.GetNextRun(0).Start); Assert.IsType <PointerRun>(model.GetNextRun(0x206)); Assert.IsType <NoInfoRun>(model.GetNextRun(0x208)); Assert.Single(model.GetNextRun(0x400).PointerSources); Assert.Equal(0x4050, model.GetNextRun(0x4050).Start); Assert.Equal(4, model.GetNextRun(0x4071).Length); }
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); }
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; }
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; }
private TableStreamRun DeserializeSingleElementStream(string content, ModelDelta token, out IReadOnlyList <int> changedOffsets) { Debug.Assert(endStream is FixedLengthStreamStrategy flss && flss.Count == 1); var fields = content.SplitLines(); int segmentOffset = 0; int fieldIndex = 0; var changeAddresses = new List <int>(); for (int j = 0; j < ElementContent.Count; j++) { while (fieldIndex < fields.Length && string.IsNullOrWhiteSpace(fields[fieldIndex])) { fieldIndex += 1; } if (fieldIndex >= fields.Length) { break; } var data = j < fields.Length ? fields[fieldIndex].Split(new[] { ':' }, 2).Last() : string.Empty; if (ElementContent[j].Write(model, token, Start + segmentOffset, ref data)) { changeAddresses.Add(Start + segmentOffset); } segmentOffset += ElementContent[j].Length; fieldIndex += 1; } changedOffsets = changeAddresses; return(this); }
public void EditingMainContentUpdatesTableTool() { Model[0x42] = 3; // sat var changeToken = new ModelDelta(); var(model, viewPort) = (Model, ViewPort); // arrange: setup the anchor used for the enums WriteStrings(model.RawData, 0x00, "cat", "bat", "bat", "sat"); var error = ArrayRun.TryParse(model, "^[name\"\"4]4", 0x00, null, out var arrayRun); model.ObserveAnchorWritten(changeToken, "sample", arrayRun); // act: setup a viewmodel and show table tool ViewPort.Refresh(); viewPort.Tools.SelectedIndex = 1; // act: change the table contents viewPort.SelectionStart = new Point(1, 0); viewPort.Edit("u"); // assert: main view was updated var element = (FieldArrayElementViewModel)viewPort.Tools.TableTool.Children.Single(child => child is FieldArrayElementViewModel faevm && faevm.Name == "name"); Assert.Equal("cut", element.Content); }
public static ITilemapRun SetPixels(ITilemapRun run, IDataModel model, ModelDelta token, int page, int[,] pixels, ref int arrayTilesetAddress, Func <byte[], ModelDelta, ITilemapRun> replaceData) { var tileData = Tilize(pixels, run.Format.BitsPerPixel); var tiles = GetUniqueTiles(tileData, run.BytesPerTile == 2); var tilesetAddress = model.GetAddressFromAnchor(new NoDataChangeDeltaModel(), -1, run.Format.MatchingTileset); var tileset = model.GetNextRun(tilesetAddress) as ITilesetRun; if (tileset == null) { FindMatchingTileset(run, model, ref arrayTilesetAddress); tileset = model.GetNextRun(arrayTilesetAddress) as ITilesetRun; } var tilesToKeep = new HashSet <int>((tileset.DecompressedLength / tileset.TilesetFormat.BitsPerPixel / 8).Range()); var originalUsedTiles = GetUsedTiles(run).ToHashSet(); foreach (var tile in originalUsedTiles) { tilesToKeep.Remove(tile); } foreach (var tilemap in tileset.FindDependentTilemaps(model).Except(run)) { tilesToKeep.AddRange(GetUsedTiles(tilemap)); } var oldTileDataRaw = tileset.GetData(); var previousTiles = Tilize(oldTileDataRaw, run.Format.BitsPerPixel); tiles = MergeTilesets(previousTiles, tilesToKeep, tiles, run.BytesPerTile == 2); tileset.SetPixels(model, token, tiles); var mapData = run.GetTilemapData(); 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, run.BytesPerTile == 2); if (tileIndex == -1) { tileIndex = 0; } if (run.BytesPerTile == 2) { var mapping = PackMapping(paletteIndex, matchType, tileIndex); mapData[i * 2 + 0] = (byte)mapping; mapData[i * 2 + 1] = (byte)(mapping >> 8); } else { mapData[i] = (byte)tileIndex; } } } return(replaceData(mapData, token)); }
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); }
public void ViewModelReturnsErrorWhenEnumIsNotValidValue() { Model[0x42] = 2; // hat 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"); var error = ArrayRun.TryParse(model, "^[name\"\"4]4", 0x00, null, out var arrayRun); model.ObserveAnchorWritten(changeToken, "sample", arrayRun); // arrange: setup the anchor with the data error = ArrayRun.TryParse(model, "[option.sample]4", 0x40, null, out arrayRun); model.ObserveAnchorWritten(changeToken, "data", arrayRun); // act: use a viewmodel to try to change 41 to 'pat' (invalid) ViewPort.Refresh(); viewPort.SelectionStart = new Point(1, 4); // select space 0x41 var errors = new List <string>(); viewPort.OnError += (sender, e) => errors.Add(e); viewPort.Edit("pat "); Assert.Single(errors); }
public void CanRemovePointerToWithinArray() { var data = new byte[0x200]; var changeToken = new ModelDelta(); // arrange: setup data with a bunch of pointers pointing into an array of strings var model = new PokemonModel(data); model.WritePointer(changeToken, 0x00, 0x80); model.ObserveRunWritten(changeToken, new PointerRun(0x00)); model.WritePointer(changeToken, 0x08, 0x84); model.ObserveRunWritten(changeToken, new PointerRun(0x08)); model.WritePointer(changeToken, 0x10, 0x88); model.ObserveRunWritten(changeToken, new PointerRun(0x10)); model.WritePointer(changeToken, 0x18, 0x8C); model.ObserveRunWritten(changeToken, new PointerRun(0x18)); // arrange: setup the array of strings WriteStrings(data, 0x80, "cat", "bat", "hat", "sat"); var existingAnchor = model.GetNextAnchor(0x80); ArrayRun.TryParse(model, "^[name\"\"4]4", 0x80, existingAnchor.PointerSources, out var arrayRun); model.ObserveAnchorWritten(changeToken, "sample", arrayRun); // act: clear the pointer model.ClearFormat(changeToken, 0x08, 4); // assert: array doesn't have pointer anymore var array = (ArrayRun)model.GetNextAnchor(0x80); Assert.Empty(array.PointerSourcesForInnerElements[1]); }
public void AddingToAnArrayWithFixedLengthUpdatesTheAnchorFormat() { // arrange var(model, viewPort) = (Model, ViewPort); var delta = new ModelDelta(); var errors = new List <string>(); var elements = new[] { "123", "alice", "candy land", "hello world", "fortify" }; for (int i = 0; i < elements.Length; i++) { var content = PCSString.Convert(elements[i]); while (content.Count < 0x10) { content.Add(0x00); } Array.Copy(content.ToArray(), 0, model.RawData, 0x10 * i + 0x20, 0x10); } model.WritePointer(delta, 0x00, 0x20); model.ObserveRunWritten(delta, new PointerRun(0x00)); model.WritePointer(delta, 0x04, 0x90); model.ObserveRunWritten(delta, new PointerRun(0x04)); // the anchor at 0x90 should prevent a paste overwrite viewPort.SelectionStart = new Point(0, 2); viewPort.Edit("^testdata[name\"\"16]5 "); viewPort.Goto.Execute("000000"); viewPort.OnError += (sender, message) => errors.Add(message); // act -> add an element viewPort.SelectionStart = new Point(0, 7); viewPort.Edit("+\"crab\""); // assert -> length changed viewPort.SelectionStart = new Point(0, 2); Assert.True(viewPort.AnchorTextVisible); Assert.Equal("^testdata[name\"\"16]6", viewPort.AnchorText); }
public void ArrayIsRecognizedByStringTool() { var changeToken = new ModelDelta(); var(model, viewPort) = (Model, ViewPort); WriteStrings(model.RawData, 100, "bobb", "tomm", "samm", "carr", "pall", "eggg"); model.WritePointer(changeToken, 200, 100); model.ObserveRunWritten(changeToken, new PointerRun(200)); ArrayRun.TryParse(model, "[word\"\"5]", 100, null, out var arrayRun); model.ObserveAnchorWritten(new ModelDelta(), "words", arrayRun); viewPort.FollowLink(0, 7); // 7*16 = 112, right in the middle of our data // note that this will change our width to 15, because we're linking to data of width 5 when our maxwidth is 16. Assert.Equal(viewPort.Tools.IndexOf(viewPort.Tools.StringTool), viewPort.Tools.SelectedIndex); // string tool is selected Assert.Equal(100, viewPort.Tools.StringTool.Address); var lineCount = viewPort.Tools.StringTool.Content.Split(Environment.NewLine).Length; Assert.Equal(6, lineCount); viewPort.Tools.StringTool.ContentIndex = viewPort.Tools.StringTool.Content.IndexOf("pall"); Assert.Equal(new Point(120 % 16, 120 / 16), viewPort.SelectionStart); }
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 ITableRun Append(ModelDelta token, int length) { var parent = PointerSources[0]; model.WriteMultiByteValue(parent + 4, 2, token, ElementCount + length); return(UpdateFromParent(token, 1, parent, out var _)); }
public bool UpdateLimiter(ModelDelta token) { if (PointerSources?.Count != 2) return false; var address = PointerSources.Last() - 4; var limiter = Length / 2 - 2; model.WriteMultiByteValue(address, 4, token, limiter); return true; }
public IStreamRun DeserializeRun(string content, ModelDelta token) { var cache = ModelCacheScope.GetCache(model); var cachedPokenames = cache.GetOptions(PokemonNameTable); var cachedMovenames = cache.GetOptions(MoveNamesTable); var data = new List<int>(); var pokemonNames = cachedPokenames.Select(name => $"{GroupStart}{name.Trim('"').ToLower()}{GroupEnd}").ToList(); var moveNames = cachedMovenames.Select(name => name.Trim('"').ToLower()).ToList(); var lines = content.ToLower().Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); foreach (var line in lines) { var index = pokemonNames.IndexOf(line); if (index != -1) { data.Add(index + MagicNumber); continue; } index = moveNames.IndexOf(line); if (index != -1) { data.Add(index); continue; } // didn't find an exact match... look for a partial pokemon match var matchFound = false; for (int i = 0; i < pokemonNames.Count; i++) { if (pokemonNames[i].Contains(line)) { data.Add(i + MagicNumber); matchFound = true; break; } } if (matchFound) continue; // look for a partial move match for (int i = 0; i < moveNames.Count; i++) { if (moveNames[i].Contains(line)) { data.Add(i); break; } } } var run = model.RelocateForExpansion(token, this, data.Count * 2 + 2); for (int i = 0; i < data.Count; i++) model.WriteMultiByteValue(run.Start + i * 2, 2, token, data[i]); model.WriteMultiByteValue(run.Start + data.Count * 2, 2, token, EndStream); // write the new end token for (int i = data.Count + 2; i < Length / 2; i++) model.WriteMultiByteValue(run.Start + i * 2, 2, token, EndStream); // fill any remaining old space with FF return new EggMoveRun(model, run.Start); }
public ArrayRun AddSourcesPointingWithinArray(ModelDelta changeToken) { if (ElementCount < 2) { return(this); } var destinations = new int[ElementCount - 1]; for (int i = 1; i < ElementCount; i++) { destinations[i - 1] = Start + ElementLength * i; } var sources = owner.SearchForPointersToAnchor(changeToken, destinations); var results = new List <List <int> >(); results.Add(PointerSources?.ToList() ?? new List <int>()); for (int i = 1; i < ElementCount; i++) { results.Add(new List <int>()); } foreach (var source in sources) { var destination = owner.ReadPointer(source); int destinationIndex = (destination - Start) / ElementLength; results[destinationIndex].Add(source); } var pointerSourcesForInnerElements = results.Cast <IReadOnlyList <int> >().ToList(); return(new ArrayRun(owner, FormatString, LengthFromAnchor, Start, ElementCount, ElementContent, PointerSources, pointerSourcesForInnerElements)); }
public void WriteNewFormat(IDataModel owner, ModelDelta token, int source, int destination, IReadOnlyList <ArrayRunElementSegment> sourceSegments) { owner.WritePointer(token, source, destination); var newRun = Factory.GetStrategy(InnerFormat).WriteNewRun(owner, token, source, destination, Name, sourceSegments); owner.ObserveRunWritten(token, newRun.MergeAnchor(new SortedSpan <int>(source))); }
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)); }
public override bool Write(IDataModel model, ModelDelta token, int start, ref string data) { if (data.StartsWith("(") && data.EndsWith(")")) { data = data.Substring(1, data.Length - 2); } var tokens = TableStreamRun.Tokenize(data); var remainder = ", ".Join(tokens.Skip(1)); if (tokens.Count == 0) { return(false); } data = tokens[0]; bool result; if (!TryParse(model, data, out int value)) { result = base.Write(model, token, start, ref data); } else { data = value.ToString(); result = base.Write(model, token, start, ref data); } data = remainder; return(result); }
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; }
public override bool Write(IDataModel model, ModelDelta token, int start, ref string data) { if (data.StartsWith("(") && data.EndsWith(")")) { data = data.Substring(1, data.Length - 2); } var remainder = string.Empty; if (Type != ElementContentType.PCS) { var tokens = TableStreamRun.Tokenize(data); remainder = ", ".Join(tokens.Skip(1)); data = tokens[0]; } data = data.Trim(); if (data.StartsWith("0x")) { data = data.Substring(2); } if (!int.TryParse(data, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out var intValue)) { intValue = 0; } data = remainder; return(model.WriteMultiByteValue(start, Length, token, intValue)); }
public void Clear(IDataModel model, ModelDelta changeToken, int start, int length) { for (int i = 0; i < length; i++) { changeToken.ChangeData(model, start + i, 0x00); } }
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)); }
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); }
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 void AddingAnchorShouldSearchForPointersToThatLocation() { var data = new byte[0x200]; var model = new PokemonModel(data); var change = new ModelDelta(); model.WritePointer(change, 0x23, 0x050); // a pointer that isn't 4-byte aligned, pointing to data that is model.WritePointer(change, 0x10, 0x087); // a pointer that is 4-byte aligned, but pointing to something that isn't model.WritePointer(change, 2, 0xA2); // a pointer that isn't 4-byte aligned, pointing to something not 4-byte aligned var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; // got to 50 and write an anchor viewPort.SelectionStart = new Point(0x0, 0x5); viewPort.Edit("^test1 "); Assert.IsType <Pointer>(viewPort[0x3, 0x2].Format); Assert.Single(((Anchor)viewPort[0x0, 0x5].Format).Sources); // go to 87 and write an anchor viewPort.SelectionStart = new Point(0x7, 0x8); viewPort.Edit("^test2 "); Assert.IsType <Pointer>(viewPort[0x0, 0x1].Format); Assert.Single(((Anchor)viewPort[0x7, 0x8].Format).Sources); // go to A2 and write an anchor viewPort.SelectionStart = new Point(0x2, 0xA); viewPort.Edit("^test3 "); Assert.IsType <Pointer>(viewPort[0x2, 0x0].Format); Assert.Single(((Anchor)viewPort[0x2, 0xA].Format).Sources); }
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)); }