diff --git a/src/newgrf.cpp b/src/newgrf.cpp index e25334f662..a4c7aa1fbb 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -6915,7 +6915,13 @@ static void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSp } if (adjust.and_mask <= 1) state.inference = prev_inference & (VA2AIF_SIGNED_NON_NEGATIVE | VA2AIF_ONE_OR_ZERO); state.inference |= prev_inference & (VA2AIF_SIGNED_NON_NEGATIVE | VA2AIF_ONE_OR_ZERO) & non_const_var_inference; - if ((non_const_var_inference & VA2AIF_ONE_OR_ZERO) || (adjust.and_mask <= 1)) adjust.adjust_flags |= DSGAF_SKIP_ON_LSB_SET; + if ((non_const_var_inference & VA2AIF_ONE_OR_ZERO) || (adjust.and_mask <= 1)) { + adjust.adjust_flags |= DSGAF_SKIP_ON_LSB_SET; + if (prev_inference & VA2AIF_ONE_OR_ZERO) { + adjust.adjust_flags |= DSGAF_JUMP_INS_HINT; + group->dsg_flags |= DSGF_CHECK_INSERT_JUMP; + } + } try_merge_with_previous(); break; case DSGA_OP_XOR: @@ -7332,7 +7338,7 @@ static bool OptimiseVarAction2DeterministicSpriteGroupExpensiveVarsInner(Determi bool seen_first = false; for (int j = end; j >= start; j--) { DeterministicSpriteGroupAdjust &adjust = group->adjusts[j]; - if (seen_first && adjust.operation == DSGA_OP_JZ && condition_depth > 0) { + if (seen_first && IsEvalAdjustJumpOperation(adjust.operation) && condition_depth > 0) { /* Do not insert the STO_NC inside a conditional block when it is also needed outside the block */ condition_depth--; insert_pos = j; @@ -7645,7 +7651,7 @@ static void OptimiseVarAction2DeterministicSpriteGroupInsertJumps(DeterministicS if (prev.operation == DSGA_OP_STO && (prev.type != DSGA_TYPE_NONE || prev.variable != 0x1A || prev.shift_num != 0 || prev.and_mask >= 0x100)) break; if (prev.operation == DSGA_OP_STO_NC && prev.divmod_val >= 0x100) break; if (prev.operation == DSGA_OP_STOP) break; - if (prev.operation == DSGA_OP_JZ) break; + if (IsEvalAdjustJumpOperation(prev.operation)) break; if (prev.variable == 0x7E) break; /* Reached a store which can't be skipped over because the value is needed later */ @@ -7676,8 +7682,8 @@ static void OptimiseVarAction2DeterministicSpriteGroupInsertJumps(DeterministicS current.adjust_flags &= ~DSGAF_END_BLOCK; current.jump = 0; } - current.operation = DSGA_OP_JZ; - current.adjust_flags &= ~(DSGAF_JUMP_INS_HINT | DSGAF_SKIP_ON_ZERO); + current.operation = (current.adjust_flags & DSGAF_SKIP_ON_LSB_SET) ? DSGA_OP_JNZ : DSGA_OP_JZ; + current.adjust_flags &= ~(DSGAF_JUMP_INS_HINT | DSGAF_SKIP_ON_ZERO | DSGAF_SKIP_ON_LSB_SET); mark_end_block(group->adjusts[i - 1], 1); group->adjusts.erase(group->adjusts.begin() + i); if (j >= 0 && current.variable == 0x7D && (current.adjust_flags & DSGAF_LAST_VAR_READ)) { @@ -7706,7 +7712,7 @@ struct ResolveJumpInnerResult { static ResolveJumpInnerResult OptimiseVarAction2DeterministicSpriteResolveJumpsInner(DeterministicSpriteGroup *group, const uint start) { for (uint i = start + 1; i < (uint)group->adjusts.size(); i++) { - if (group->adjusts[i].operation == DSGA_OP_JZ) { + if (IsEvalAdjustJumpOperation(group->adjusts[i].operation)) { ResolveJumpInnerResult result = OptimiseVarAction2DeterministicSpriteResolveJumpsInner(group, i); i = result.end_index; if (result.end_block_remaining > 0) { @@ -7727,7 +7733,7 @@ static void OptimiseVarAction2DeterministicSpriteResolveJumps(DeterministicSprit if (HasGrfOptimiserFlag(NGOF_NO_OPT_VARACT2_INSERT_JUMPS)) return; for (uint i = 0; i < (uint)group->adjusts.size(); i++) { - if (group->adjusts[i].operation == DSGA_OP_JZ) { + if (IsEvalAdjustJumpOperation(group->adjusts[i].operation)) { ResolveJumpInnerResult result = OptimiseVarAction2DeterministicSpriteResolveJumpsInner(group, i); i = result.end_index; assert(result.end_block_remaining == 0); diff --git a/src/newgrf_spritegroup.cpp b/src/newgrf_spritegroup.cpp index 9040cd3531..97f16c41e4 100644 --- a/src/newgrf_spritegroup.cpp +++ b/src/newgrf_spritegroup.cpp @@ -212,6 +212,16 @@ static U EvalAdjustT(const DeterministicSpriteGroupAdjust &adjust, ScopeResolver return last_value; } } + case DSGA_OP_JNZ: { + if (value != 0 && adjust_iter != nullptr) { + /* Jump */ + (*adjust_iter) += adjust.jump; + return value; + } else { + /* Don't jump */ + return last_value; + } + } default: return value; } } @@ -700,6 +710,7 @@ static const char *_dsg_op_special_names[] { "STO_NC", "ABS", "JZ", + "JNZ", }; static_assert(lengthof(_dsg_op_special_names) == DSGA_OP_SPECIAL_END - DSGA_OP_TERNARY); @@ -753,7 +764,7 @@ static char *DumpSpriteGroupAdjust(char *p, const char *last, const Deterministi } }; - if (adjust.operation == DSGA_OP_JZ) { + if (IsEvalAdjustJumpOperation(adjust.operation)) { conditional_indent++; } if (adjust.adjust_flags & DSGAF_END_BLOCK) { @@ -801,7 +812,7 @@ static char *DumpSpriteGroupAdjust(char *p, const char *last, const Deterministi } p += seprintf(p, last, ", op: "); p = GetAdjustOperationName(p, last, adjust.operation); - if (adjust.operation == DSGA_OP_JZ) { + if (IsEvalAdjustJumpOperation(adjust.operation)) { p += seprintf(p, last, " +%u", adjust.jump); } append_flags(); diff --git a/src/newgrf_spritegroup.h b/src/newgrf_spritegroup.h index 42990806a6..920c1a5dfd 100644 --- a/src/newgrf_spritegroup.h +++ b/src/newgrf_spritegroup.h @@ -207,6 +207,7 @@ enum DeterministicSpriteGroupAdjustOperation : uint8 { DSGA_OP_STO_NC, ///< store b into temporary storage, indexed by c. return a DSGA_OP_ABS, ///< abs(a) DSGA_OP_JZ, ///< jump forward fixed number of adjusts (to adjust after DSGAF_END_BLOCK marker (taking into account nesting)) if b is zero. return 0 if jumped, return a if not jumped + DSGA_OP_JNZ, ///< jump forward fixed number of adjusts (to adjust after DSGAF_END_BLOCK marker (taking into account nesting)) if b is non-zero. return b if jumped, return a if not jumped DSGA_OP_SPECIAL_END, }; @@ -402,6 +403,18 @@ inline bool IsEvalAdjustWithZeroLastValueAlwaysZero(DeterministicSpriteGroupAdju } } +inline bool IsEvalAdjustJumpOperation(DeterministicSpriteGroupAdjustOperation op) +{ + switch (op) { + case DSGA_OP_JZ: + case DSGA_OP_JNZ: + return true; + + default: + return false; + } +} + inline bool IsConstantComparisonAdjustType(DeterministicSpriteGroupAdjustType adjust_type) { switch (adjust_type) {