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
36 changes: 25 additions & 11 deletions Source/Parser/Expressions/Trigger/MemoryValueExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1548,23 +1548,37 @@ public ErrorExpression BuildTrigger(TriggerBuilderContext context, ExpressionBas
for (int i = 0; i < memoryAccessors.Count; i++)
{
var memoryAccessor = memoryAccessors[i];
var memoryAccessorRememberedExpression = memoryAccessor.RememberedValue;
if (memoryAccessorRememberedExpression != null)
for (int j = 0; j < 2; j++)
{
if (rememberedExpression == null)
MemoryValueExpression memoryAccessorRememberedExpression = null;
if (j == 0)
{
rememberedExpression = memoryAccessorRememberedExpression;
memoryAccessorRememberedExpression = memoryAccessor.RememberedValue;
}
else
{
var rememberExpression = memoryAccessor.MemoryAccessor as RememberRecallExpression;
if (rememberExpression != null)
memoryAccessorRememberedExpression = rememberExpression.RememberedValue;
}

if (memoryAccessorRememberedExpression != null)
{
if (rememberedExpression == null)
{
rememberedExpression = memoryAccessorRememberedExpression;

if (i != 0)
if (i != 0)
{
memoryAccessors.RemoveAt(i);
memoryAccessors.Insert(0, memoryAccessor);
}
}
else if (rememberedExpression != memoryAccessorRememberedExpression)
{
memoryAccessors.RemoveAt(i);
memoryAccessors.Insert(0, memoryAccessor);
return new ErrorExpression("Cannot combine multiple expressions with unique Remembered requirements", memoryAccessor);
}
}
else if (rememberedExpression != memoryAccessorRememberedExpression)
{
return new ErrorExpression("Cannot combine multiple expressions with unique Remembered requirements", memoryAccessor);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,17 @@ public ExpressionBase ApplyMathematic(ExpressionBase right, MathematicOperation
field = FieldFactory.CreateField(right);
if (field.Type == FieldType.None)
{
// cannot simplify to a single field.
// going to need to use remember/recall to generate the value.
if (ModifyingOperator != RequirementOperator.None)
{
// if the "this" object is modified, it also needs to be remember/recalled
// which only works if both sides match. that will be determined later.
// for now, just remember/recall both sides.
MemoryAccessor = RememberRecallExpression.WrapInRemember(this.Clone());
ModifyingOperator = RequirementOperator.None;
}

_rememberModifier = RememberRecallExpression.WrapInRemember(right);
if (_rememberModifier != null)
{
Expand Down Expand Up @@ -912,8 +923,6 @@ public ErrorExpression BuildTrigger(TriggerBuilderContext context)
{
if (_rememberModifier.RememberedValue != context.RememberedValue)
{
context.RememberedValue = _rememberModifier.RememberedValue;

var error = _rememberModifier.BuildTrigger(context);
if (error != null)
return error;
Expand All @@ -922,6 +931,10 @@ public ErrorExpression BuildTrigger(TriggerBuilderContext context)
// into the next expression. remove it. we'll add it back soon.
context.Trigger.Remove(context.LastRequirement);
}

var rememberExpression = MemoryAccessor as RememberRecallExpression;
if (rememberExpression != null && rememberExpression.RememberedValue != _rememberModifier.RememberedValue)
return new ErrorExpression("Cannot combine multiple expressions with unique Remembered requirements", this);
}

MemoryAccessor.BuildTrigger(context);
Expand Down
19 changes: 17 additions & 2 deletions Source/Parser/Expressions/Trigger/RememberRecallExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,23 @@ public override void GetMinMax(out long min, out long max)
}

public override ErrorExpression BuildTrigger(TriggerBuilderContext context)
{
// if the RememberedValue is already being Remembered, just output the {recall}
if (context.RememberedValue != RememberedValue)
{
var error = AppendRemember(context);
if (error != null)
return error;
}

// this outputs the {recall}
return base.BuildTrigger(context);
}

private ErrorExpression AppendRemember(TriggerBuilderContext context)
{
RememberedValue.BuildTrigger(context);
context.RememberedValue = RememberedValue;

// if the RememberedValue only contains ModifiedMemoryReferences, BuildTrigger
// will append an extra condition so the result can be compared to.
Expand All @@ -121,9 +136,9 @@ public override ErrorExpression BuildTrigger(TriggerBuilderContext context)

if (lastRequirement.Type != RequirementType.None)
return new ErrorExpression("Cannot remember requirement", RememberedValue);
lastRequirement.Type = RequirementType.Remember;

return base.BuildTrigger(context);
lastRequirement.Type = RequirementType.Remember;
return null;
}
}
}
2 changes: 2 additions & 0 deletions Source/Parser/Internal/TriggerBuilderContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,8 @@ public void BeginAlt()
{
Trigger = new List<Requirement>();
Achievement.AlternateRequirements.Add(Trigger);

RememberedValue = null;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ public void TestAppendString(string input)
[TestCase("prior(bit0(0x001234))", "p0xM001234")]
[TestCase("dword(dword(0x1234) + ((word(0x2345) & 0x3FF) * 8 + 4))",
"K:0x 002345&1023_A:{recall}*8_K:0xX001234_I:{recall}_0xX000004")]
[TestCase("byte(0x3B0038 - ((dword_be(0x3180) & 0x15) / (dword_be(0x3180) & 0x15)) * 0x4C068)",
"K:0xG003180&21_K:{recall}/{recall}_I:{recall}*4294655896_0xH3b0038")]
public void TestBuildTrigger(string input, string expected)
{
var accessor = TriggerExpressionTests.Parse<MemoryAccessorExpression>(input);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public void TestBuildTrigger(string input, string expected)
[TestCase("byte(0x001234) == 3 && trigger_when(__ornext(byte(word(0x002345) + 8) == 4 || (byte(word(0x002345) + 8) >= 7 && byte(word(0x002345) + 8) <= 10)))",
"0xH001234=3_I:0x 002345_N:0xH000008>=7_I:0x 002345_O:0xH000008<=10_I:0x 002345_T:0xH000008=4")]
[TestCase("dword(dword(0x1234) + ((word(0x2345) & 0x3FF) * 8 + 4)) == 6 && prev(dword(dword(0x1234) + ((word(0x2345) & 0x3FF) * 8 + 4))) == 0",
"K:0x 002345&1023_A:{recall}*8_K:0xX001234_I:{recall}_0xX000004=6_K:0x 002345&1023_A:{recall}*8_K:0xX001234_I:{recall}_d0xX000004=0")] // remember chain will be duplicated here, it'll get optimized out later
"K:0x 002345&1023_A:{recall}*8_K:0xX001234_I:{recall}_0xX000004=6_I:{recall}_d0xX000004=0")]
public void TestBuildAchievement(string input, string expected)
{
var clause = TriggerExpressionTests.Parse<RequirementClauseExpression>(input);
Expand Down
Loading