Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Source/Data/CodeNote.cs
Original file line number Diff line number Diff line change
Expand Up @@ -894,5 +894,14 @@ private static bool GetBitRange(Token token, out char lowBit, out char highBit)

return false;
}

public static CodeNote ResolveNote(uint address, IDictionary<uint, CodeNote> notes, CodeNote parentNote)
{
if (parentNote != null)
return parentNote.OffsetNotes.FirstOrDefault(n => n.Address == address);

notes.TryGetValue(address, out CodeNote note);
return note;
}
}
}
4 changes: 2 additions & 2 deletions Source/ViewModels/RequirementComparisonViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ namespace RATools.ViewModels
{
public class RequirementComparisonViewModel : RequirementViewModel
{
public RequirementComparisonViewModel(Requirement requirement, Requirement compareRequirement, NumberFormat numberFormat, IDictionary<uint, CodeNote> notes)
: base(requirement, numberFormat, notes)
public RequirementComparisonViewModel(Requirement requirement, Requirement compareRequirement, NumberFormat numberFormat, IDictionary<uint, CodeNote> notes, CodeNote parentNote)
: base(requirement, numberFormat, notes, parentNote)
{
if (compareRequirement == null)
{
Expand Down
44 changes: 36 additions & 8 deletions Source/ViewModels/RequirementGroupViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,12 @@ public RequirementGroupViewModel(string label,
Label = label;

var list = new List<RequirementViewModel>();
CodeNote parentNote = null;
foreach (var requirement in requirements)
list.Add(new RequirementViewModel(requirement, numberFormat, notes));
{
list.Add(new RequirementViewModel(requirement, numberFormat, notes, parentNote));
parentNote = UpdateParentNote(requirement, parentNote, notes);
}

UpdateDependencies(list);
Requirements = list;
Expand Down Expand Up @@ -200,22 +204,44 @@ private static void UpdateDependencies(List<RequirementViewModel> list)
}
}

private static CodeNote UpdateParentNote(Requirement requirement, CodeNote parentNote, IDictionary<uint, CodeNote> notes)
{
if (requirement.Type == RequirementType.AddAddress && requirement.Left.IsMemoryReference)
{
var leftNote = CodeNote.ResolveNote(requirement.Left.Value, notes, parentNote);
return (leftNote != null && leftNote.IsPointer) ? leftNote : null;
}
else if (requirement.Type != RequirementType.AddAddress)
{
return null;
}
return parentNote;
}

private static void AppendRequirements(List<RequirementViewModel> list, RequirementEx left, RequirementEx right, NumberFormat numberFormat, IDictionary<uint, CodeNote> notes)
{
if (right == null)
{
CodeNote parentNote = null;
foreach (var requirement in left.Requirements)
list.Add(new RequirementComparisonViewModel(requirement, null, numberFormat, notes));
{
list.Add(new RequirementComparisonViewModel(requirement, null, numberFormat, notes, parentNote));
parentNote = UpdateParentNote(requirement, parentNote, notes);
}
}
else if (left == null)
{
foreach (var requirement in right.Requirements)
list.Add(new RequirementComparisonViewModel(null, requirement, numberFormat, notes));
list.Add(new RequirementComparisonViewModel(null, requirement, numberFormat, notes, null));
}
else if (left.Requirements.Count == right.Requirements.Count)
{
CodeNote parentNote = null;
for (int i = 0; i < left.Requirements.Count; ++i)
list.Add(new RequirementComparisonViewModel(left.Requirements[i], right.Requirements[i], numberFormat, notes));
{
list.Add(new RequirementComparisonViewModel(left.Requirements[i], right.Requirements[i], numberFormat, notes, parentNote));
parentNote = UpdateParentNote(left.Requirements[i], parentNote, notes);
}
}
else
{
Expand Down Expand Up @@ -272,6 +298,7 @@ private static void AppendRequirements(List<RequirementViewModel> list, Requirem
}

var rightIndex = 0;
CodeNote parentNote = null;

foreach (var requirement in left.Requirements)
{
Expand All @@ -283,17 +310,18 @@ private static void AppendRequirements(List<RequirementViewModel> list, Requirem
{
var rightRequirement = right.Requirements[rightIndex++];
if (unmatchedCompareRequirements.Remove(rightRequirement))
list.Add(new RequirementComparisonViewModel(null, rightRequirement, numberFormat, notes));
list.Add(new RequirementComparisonViewModel(null, rightRequirement, numberFormat, notes, null));
}

rightIndex++;
}

list.Add(new RequirementComparisonViewModel(requirement, match, numberFormat, notes));
list.Add(new RequirementComparisonViewModel(requirement, match, numberFormat, notes, parentNote));
parentNote = UpdateParentNote(requirement, parentNote, notes);
}

foreach (var requirement in unmatchedCompareRequirements)
list.Add(new RequirementComparisonViewModel(null, requirement, numberFormat, notes));
list.Add(new RequirementComparisonViewModel(null, requirement, numberFormat, notes, null));
}
}

Expand Down Expand Up @@ -450,7 +478,7 @@ public RequirementGroupViewModel(string label, IEnumerable<Requirement> requirem
while (GetBestMerge(list, out leftIndex, out rightIndex))
{
list[leftIndex] = new RequirementComparisonViewModel(list[leftIndex].Requirement,
((RequirementComparisonViewModel)list[rightIndex]).CompareRequirement, numberFormat, notes);
((RequirementComparisonViewModel)list[rightIndex]).CompareRequirement, numberFormat, notes, null);
list.RemoveAt(rightIndex);
}

Expand Down
17 changes: 9 additions & 8 deletions Source/ViewModels/RequirementViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace RATools.ViewModels
[DebuggerDisplay("{Requirement}")]
public class RequirementViewModel : ViewModelBase
{
public RequirementViewModel(Requirement requirement, NumberFormat numberFormat, IDictionary<uint, CodeNote> notes)
public RequirementViewModel(Requirement requirement, NumberFormat numberFormat, IDictionary<uint, CodeNote> notes, CodeNote parentNote)
{
Requirement = requirement;

Expand All @@ -28,14 +28,15 @@ public RequirementViewModel(Requirement requirement, NumberFormat numberFormat,
{
var builder = new StringBuilder();

CodeNote note;
if (notes.TryGetValue(requirement.Left.Value, out note))
var note = CodeNote.ResolveNote(requirement.Left.Value, notes, parentNote);
if (note != null)
{
var subNote = note.GetSubNote(requirement.Left.Size);
builder.AppendFormat("0x{0:x6}:{1}", requirement.Left.Value, subNote ?? note.Summary);
}

if (notes.TryGetValue(requirement.Right.Value, out note))
note = CodeNote.ResolveNote(requirement.Right.Value, notes, parentNote);
if (note != null)
{
if (builder.Length > 0)
builder.AppendLine();
Expand All @@ -48,8 +49,8 @@ public RequirementViewModel(Requirement requirement, NumberFormat numberFormat,
}
else
{
CodeNote note;
if (notes.TryGetValue(requirement.Left.Value, out note))
var note = CodeNote.ResolveNote(requirement.Left.Value, notes, parentNote);
if (note != null)
{
Notes = note.Note;
var subNote = note.GetSubNote(requirement.Left.Size);
Expand All @@ -63,8 +64,8 @@ public RequirementViewModel(Requirement requirement, NumberFormat numberFormat,
}
else if (requirement.Right.IsMemoryReference)
{
CodeNote note;
if (notes.TryGetValue(requirement.Right.Value, out note))
var note = CodeNote.ResolveNote(requirement.Right.Value, notes, parentNote);
if (note != null)
{
Notes = note.Note;
var subNote = note.GetSubNote(requirement.Left.Size);
Expand Down
6 changes: 3 additions & 3 deletions Tests/ViewModels/RequirementComparisonViewModelTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public void TestDefinitions(string leftSerialized, string rightSerialized,
builder.ParseRequirements(Tokenizer.CreateTokenizer(rightSerialized));
var compareRequirement = builder.ToAchievement().CoreRequirements.First();

var vmRequirement = new RequirementComparisonViewModel(requirement, compareRequirement, NumberFormat.Decimal, notes);
var vmRequirement = new RequirementComparisonViewModel(requirement, compareRequirement, NumberFormat.Decimal, notes, null);

Assert.That(vmRequirement.Definition, Is.EqualTo(expectedDefinition));
Assert.That(vmRequirement.OtherDefinition, Is.EqualTo(expectedOtherDefinition));
Expand All @@ -52,7 +52,7 @@ public void TestAddedRequirement()
builder.ParseRequirements(Tokenizer.CreateTokenizer("0xH1234=7"));
var requirement = builder.ToAchievement().CoreRequirements.First();

var vmRequirement = new RequirementComparisonViewModel(requirement, null, NumberFormat.Decimal, notes);
var vmRequirement = new RequirementComparisonViewModel(requirement, null, NumberFormat.Decimal, notes, null);

Assert.That(vmRequirement.Definition, Is.EqualTo("byte(0x001234) == 7"));
Assert.That(vmRequirement.OtherDefinition, Is.EqualTo(""));
Expand All @@ -68,7 +68,7 @@ public void TestRemovedRequirement()
builder.ParseRequirements(Tokenizer.CreateTokenizer("0xH1234=7"));
var requirement = builder.ToAchievement().CoreRequirements.First();

var vmRequirement = new RequirementComparisonViewModel(null, requirement, NumberFormat.Decimal, notes);
var vmRequirement = new RequirementComparisonViewModel(null, requirement, NumberFormat.Decimal, notes, null);

Assert.That(vmRequirement.Definition, Is.EqualTo(""));
Assert.That(vmRequirement.OtherDefinition, Is.EqualTo("byte(0x001234) == 7"));
Expand Down
35 changes: 34 additions & 1 deletion Tests/ViewModels/RequirementGroupViewModelTests.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
using Jamiras.Components;
using Jamiras.Components;
using Moq;
using NUnit.Framework;
using RATools.Data;
using RATools.Parser;
using RATools.Services;
using RATools.ViewModels;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RATools.Tests.ViewModels
Expand Down Expand Up @@ -106,5 +107,37 @@ public void TestDisplay(string serialized, string expected)

Assert.That(strBuilder.ToString(), Is.EqualTo(expected));
}

[Test]
[TestCase("I:0xX1000_I:0xX0068_0xH0004=1", // nested pointer
new[] { "[32-bit pointer] root\n+0x68 | [32-bit pointer] nested\n++0x4 | [8-bit] value" },
new[] { "[32-bit pointer] root\n+0x68 | [32-bit pointer] nested\n++0x4 | [8-bit] value", "[32-bit pointer] nested\n+0x4 | [8-bit] value", "[8-bit] value" })]
[TestCase("I:0xX1000_0xH0004=1_0xH2000=2", // resets after pointer chain
new[] { "[32-bit pointer] root\n+0x4 | [8-bit] hp", "unrelated" },
new[] { "[32-bit pointer] root\n+0x4 | [8-bit] hp", "[8-bit] hp", "unrelated" })]
public void TestNotes(string serialized, string[] notes, string[] expectedNotes)
{
var mockSettings = new Mock<ISettings>();
mockSettings.Setup(s => s.HexValues).Returns(false);
ServiceRepository.Reset();
ServiceRepository.Instance.RegisterInstance(mockSettings.Object);

var builder = new AchievementBuilder();
builder.ParseRequirements(Tokenizer.CreateTokenizer(serialized));
var requirements = builder.ToAchievement().CoreRequirements;

// notes are for 0x1000, 0x2000, ...
var notesDict = new Dictionary<uint, CodeNote>();
for (int i = 0; i < notes.Length; i++)
{
uint address = (uint)(0x1000 * (i + 1));
notesDict[address] = new CodeNote(address, notes[i]);
}

var vmRequirementGroup = new RequirementGroupViewModel("Group", requirements, NumberFormat.Decimal, notesDict);

for (int i = 0; i < expectedNotes.Length; i++)
Assert.That(vmRequirementGroup.Requirements.ElementAt(i).Notes, Is.EqualTo(expectedNotes[i]));
}
}
}
12 changes: 6 additions & 6 deletions Tests/ViewModels/RequirementViewModelTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Jamiras.Components;
using Jamiras.Components;
using Moq;
using NUnit.Framework;
using RATools.Data;
Expand Down Expand Up @@ -33,7 +33,7 @@ public void TestDefinition(string serialized, string expected)

var requirement = builder.ToAchievement().CoreRequirements.First();
var notes = new Dictionary<uint, CodeNote>();
var vmRequirement = new RequirementViewModel(requirement, NumberFormat.Decimal, notes);
var vmRequirement = new RequirementViewModel(requirement, NumberFormat.Decimal, notes, null);

Assert.That(vmRequirement.Definition, Is.EqualTo(expected));
}
Expand Down Expand Up @@ -64,7 +64,7 @@ public void TestNotes(string serialized, string expectedNote, string expectedSho
var builder = new AchievementBuilder();
builder.ParseRequirements(Tokenizer.CreateTokenizer(serialized));
var requirement = builder.ToAchievement().CoreRequirements.First();
var vmRequirement = new RequirementViewModel(requirement, NumberFormat.Decimal, notes);
var vmRequirement = new RequirementViewModel(requirement, NumberFormat.Decimal, notes, null);

Assert.That(vmRequirement.Notes, Is.EqualTo(expectedNote));

Expand Down Expand Up @@ -92,7 +92,7 @@ public void TestNoteShortening(string serialized, string expected)
var builder = new AchievementBuilder();
builder.ParseRequirements(Tokenizer.CreateTokenizer(serialized));
var requirement = builder.ToAchievement().CoreRequirements.First();
var vmRequirement = new RequirementViewModel(requirement, NumberFormat.Decimal, notes);
var vmRequirement = new RequirementViewModel(requirement, NumberFormat.Decimal, notes, null);

Assert.That(vmRequirement.NotesShort, Is.EqualTo(expected));

Expand All @@ -118,7 +118,7 @@ public void TestAddSourceTrailingConstantComparison()
};

var notes = new Dictionary<uint, CodeNote>();
var vmRequirement = new RequirementViewModel(requirement, NumberFormat.Decimal, notes);
var vmRequirement = new RequirementViewModel(requirement, NumberFormat.Decimal, notes, null);

Assert.That(vmRequirement.Definition, Is.EqualTo("always_false()"));

Expand All @@ -145,7 +145,7 @@ public void TestAddSourceTrailingConstantComparisonWithHits()
};

var notes = new Dictionary<uint, CodeNote>();
var vmRequirement = new RequirementViewModel(requirement, NumberFormat.Decimal, notes);
var vmRequirement = new RequirementViewModel(requirement, NumberFormat.Decimal, notes, null);

Assert.That(vmRequirement.Definition, Is.EqualTo("repeated(10, always_false())"));

Expand Down
Loading