Skip to content

Commit 9951f64

Browse files
committed
Fix IL matching
1 parent 8fa3761 commit 9951f64

File tree

1 file changed

+18
-15
lines changed

1 file changed

+18
-15
lines changed

src/DashStates/DreamTunnelDash/DreamTunnelDash.cs

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -452,29 +452,31 @@ private static void CheckState(ILCursor cursor, int state, bool equal)
452452
// `player.StateMachine.State == state` -> `player.StateMachine.State == state || player.StateMachine.State == St.DreamTunnelDash`
453453
// `player.StateMachine.State != state` -> `player.StateMachine.State != state && player.StateMachine.State != St.DreamTunnelDash`
454454

455-
// variables to grab stuff later
456-
Instruction afterMatch = null;
455+
// go to before the state check
456+
if (!cursor.TryGotoNextFirstFitReversed(MoveType.AfterLabel, 0x10,
457+
instr => instr.MatchLdfld<Player>("StateMachine"),
458+
instr => instr.MatchCallvirt<StateMachine>("get_State"),
459+
instr => instr.MatchLdcI4(state)))
460+
return;
457461

462+
// variables to grab various things
458463
bool matchedBeqOrBne = false, matchedCeq = false;
459464
ILLabel failedCheck = null;
460465
Instruction ceqInstr = null;
461466

462-
if (!cursor.TryGotoNextFirstFitReversed(MoveType.AfterLabel, 0x10,
463-
instr => instr.MatchLdfld<Player>("StateMachine"),
464-
instr => instr.MatchCallvirt<StateMachine>("get_State"),
465-
instr => instr.MatchLdcI4(state),
466-
instr =>
467+
// retrieve the instruction after the current check
468+
ILCursor cloned = cursor.Clone();
469+
if (!cloned.TryGotoNext(MoveType.After, instr =>
467470
{
468-
// we grab a lot of stuff here: the instruction directly after this match, whether we matched a beq/bne.un or a ceq,
469-
// the "fail state" label of the beq/bne.un (if we matched one of those) and the actual ceq instruction (if we matched that).
470-
471-
afterMatch = instr.Next;
472-
// equality checks usually use bne.un (for ==) or beq (for !=) to branch past the block of the if statement if the values don't match
471+
// we grab a lot of stuff here: whether we matched a beq/bne.un or a ceq, the "fail state" label of the beq/bne.un
472+
// (if we matched one of those) and the actual ceq instruction (if we matched that).
473+
474+
// equality checks usually use bne.un (for ==) or beq (for !=) in order to branch past the block of the if statement if the values don't match
473475
matchedBeqOrBne = equal ? instr.MatchBneUn(out failedCheck) : instr.MatchBeq(out failedCheck);
474476
matchedCeq = (ceqInstr = instr).MatchCeq();
475477
return matchedBeqOrBne || matchedCeq;
476-
}))
477-
return;
478+
})) return;
479+
Instruction afterMatch = cloned.Next!;
478480

479481
// beq and bne.un work with labels, whereas ceq just leaves a bool so we need to deal with them differently
480482
if (matchedBeqOrBne)
@@ -503,6 +505,7 @@ private static void CheckState(ILCursor cursor, int state, bool equal)
503505
cursor.Emit(OpCodes.Pop);
504506
cursor.MarkLabel(pastCleanUpPlayer);
505507
cursor.Index--;
508+
// mark label to short-circuit to
506509
cursor.MarkLabel(cleanUpPlayer);
507510
}
508511
else if (matchedCeq)
@@ -515,7 +518,7 @@ private static void CheckState(ILCursor cursor, int state, bool equal)
515518
// to solve this, our desired conditions can be shown equivalent to `player.StateMachine.State == state || player.StateMachine.State == St.DreamTunnelDash` (for equality) and
516519
// `!(player.StateMachine.State == state || player.StateMachine.State == St.DreamTunnelDash)` (for inequality). notice how the desired condition for inequality is simply
517520
// the inverse of the one for equality. this is great, because the brtrue/brfalse after the ceq will do the required inversion (or lack thereof) for the check, and all
518-
// we need to do is calculate the thing on the inside. conveniently, the ceq is already checking for the left term (so that is its return value), and we just need to or it with the right.
521+
// we need to do is calculate the thing on the inside. conveniently, the ceq is already checking for the left term, and we just need to or it with the right.
519522
cursor.EmitDelegate<Func<Player, bool, bool>>((player, orig) => orig || player.StateMachine.State == St.DreamTunnelDash);
520523
}
521524

0 commit comments

Comments
 (0)