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); }
public void ArrayLengthUpdatesWhenSourceTableLengthChanges() { // Arrange var data = new byte[0x200]; var model = new PokemonModel(data); // Act ArrayRun.TryParse(model, "[a: b:]names", 0, null, out var table); model.ObserveAnchorWritten(new ModelDelta(), "table", table); ArrayRun.TryParse(model, "[name\"\"8]8", 0x30, null, out var names); model.ObserveAnchorWritten(new ModelDelta(), "names", names); // Assert that the table is now longer based on the names table Assert.Equal(8 * 4, model.GetNextRun(0).Length); }
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 void ThumbCode_MultipleInlineLoads_OnlyOneValueAdded() { var model = new PokemonModel(new byte[0x200]); model.ObserveAnchorWritten(new ModelDelta(), "destination", new NoInfoRun(0x20)); var result = parser.Compile(model, 0x100, " ldr r0, =256", " ldr r0, =256", " b <end>", // implict nop for alignment // implicit .word 256 (only once!) "end:", " pop pc, {}"); var expected = new byte[] { 0x01, 0b01001_000, // payload is 4 instructions away: ceil(4/2)-1 = 0x01 0x01, 0b01001_000, // payload is 3 instructions away: ceil(3/2)-1 = 0x01 0x02, 0b11100_000, 0, 0, // inserted nop to align for .word value 0, 1, 0, 0, // word inserted only once 0x00, 0b1011110_1, }; Assert.All(expected.Length.Range(), i => Assert.Equal(expected[i], result[i])); }
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 CopyTextArrayEntryDoesNotCopyMultipleEndOfStreams() { var model = new PokemonModel(Enumerable.Repeat((byte)0xFF, 0x200).ToArray()); ArrayRun.TryParse(model, "[name\"\"6]4", 0, null, out var run); model.ObserveAnchorWritten(new ModelDelta(), "table", run); var text = model.Copy(() => new ModelDelta(), 6, 6).Trim(); Assert.Equal("+\"\"", text); }
public void UnmappedPointerInMetadata_WriteAnchor_ModelUpdates() { var pointers = new[] { new StoredUnmappedPointer(0x20, "name") }; var metadata = new StoredMetadata(unmappedPointers: pointers); var model = new PokemonModel(new byte[0x200], metadata, Singletons); model.ObserveAnchorWritten(Token, "name", new NoInfoRun(0x80)); Assert.Equal(0x80, model.ReadPointer(0x20)); }
public void WritingAnchorIntoAPointerRemovesThatPointer() { var buffer = new byte[0x100]; var model = new PokemonModel(buffer); var token = new ModelDelta(); model.WritePointer(token, 16, 12); model.ObserveRunWritten(token, new PointerRun(16)); model.ObserveAnchorWritten(token, "bob", new NoInfoRun(18)); Assert.Equal(18, model.GetNextRun(10).Start); }
public void AnchorTextAlwaysCoercesToStartWithAnchorCharacter() { var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); var model = new PokemonModel(buffer); model.ObserveAnchorWritten(new ModelDelta(), "bob", new NoInfoRun(0x08)); var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.SelectionStart = new Point(0x08, 0); viewPort.AnchorText = "tom\"\""; Assert.Equal("^tom\"\"", viewPort.AnchorText); // not that the ^ was added to the front }
public void ModifyingAnchorTextUpdatesTheAnchor() { var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); var model = new PokemonModel(buffer); model.ObserveAnchorWritten(new ModelDelta(), "bob", new NoInfoRun(0x08)); var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.SelectionStart = new Point(0x08, 0); viewPort.AnchorText = "^bob\"\""; Assert.IsType <PCSRun>(model.GetNextRun(0x08)); }
public void AnchorEditTextUpdatesWithSelectionChange() { var buffer = Enumerable.Repeat((byte)0xFF, 0x200).ToArray(); var model = new PokemonModel(buffer); model.ObserveAnchorWritten(new ModelDelta(), "bob", new NoInfoRun(0x08)); var viewPort = new ViewPort("file.txt", model) { Width = 0x10, Height = 0x10 }; viewPort.SelectionStart = new Point(0x08, 0); Assert.True(viewPort.AnchorTextVisible); Assert.Equal("^bob", viewPort.AnchorText); }
public void ThumbCompilerTests(string input, uint output) { var bytes = new List <byte> { (byte)output, (byte)(output >> 8) }; var model = new PokemonModel(new byte[0x200]); model.ObserveAnchorWritten(new ModelDelta(), "bob", new NoInfoRun(0x80)); // random anchor so we can test stuff that points to anchors var result = parser.Compile(model, 0x100, new string[] { input }); Assert.Equal(bytes[0], result[0]); Assert.Equal(bytes[1], result[1]); if (result.Count > 2) { bytes.Add((byte)(output >> 16)); bytes.Add((byte)(output >> 24)); Assert.Equal(bytes[2], result[2]); Assert.Equal(bytes[3], result[3]); } }
public void ThumbCompilerLabelTest() { var model = new PokemonModel(new byte[0x200]); model.ObserveAnchorWritten(new ModelDelta(), "DoStuff", new NoInfoRun(0x40)); var result = parser.Compile(model, 0x100 // sums all numbers from 1 to 10 in a loop // then calls the routine at "DoStuff" // then returns , "push lr, {}" , "mov r1, #1" , "mov r0, #0" , "Loop:" , "add r0, r0, r1" , "cmp r1, #10" , "bne <loop>" , "bl <DoStuff>" , "pop pc, {}" ); var expected = new byte[] { 0x00, 0b10110101, 0x01, 0b00100_001, 0x00, 0b00100_000, // loop 0b01_000_000, 0b0001100_0, // 0001100_001_000_000 0x0A, 0b00101_001, 0xFC, 0b1101_0001, 0xFF, 0b11110_111, 0x98, 0b11111_111, // (sbyte)0x98 = -68 0x00, 0b10111101, }; Assert.Equal(expected.Length, result.Count); for (int i = 0; i < expected.Length; i++) { Assert.Equal(expected[i], result[i]); } }
public void SupportNestedTextStreams() { // can parse var info = ArrayRun.TryParse(model, "[description<\"\">]4", 0, null, out var table); Assert.False(info.HasError); model.ObserveAnchorWritten(token, "table", table); // displays pointers viewPort.Goto.Execute("000100"); viewPort.Goto.Execute("000000"); Assert.IsType <Pointer>(viewPort[4, 0].Format); // can't update to point to non-text viewPort.SelectionStart = new Point(5, 0); errors.Clear(); viewPort.Edit("000100 "); // expected failure point Assert.Single(errors); // can update to point to text viewPort.SelectionStart = new Point(0, 4); viewPort.Edit("FF"); // have to put the FF first, or trying to create a text run will fail viewPort.SelectionStart = new Point(0, 4); viewPort.Edit("^text\"\" Hello World!\""); viewPort.SelectionStart = new Point(5, 0); errors.Clear(); viewPort.Edit("000040 "); Assert.Empty(errors); // can update to point to null viewPort.SelectionStart = new Point(5, 0); errors.Clear(); viewPort.Edit("null "); Assert.Empty(errors); }