diff --git a/src/newgrf.cpp b/src/newgrf.cpp index a4c7aa1fbb..385af858e7 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -7694,6 +7694,16 @@ static void OptimiseVarAction2DeterministicSpriteGroupInsertJumps(DeterministicS group->adjusts.erase(group->adjusts.begin() + j); j--; i--; + } else if (current.type == DSGA_TYPE_NONE && current.shift_num == 0 && current.and_mask == 0xFFFFFFFF && + prev.operation == DSGA_OP_STO && prev.variable == 0x1A && prev.shift_num == 0 && prev.and_mask == (current.parameter & 0xFF)) { + /* Reading from immediately prior store, which can now be removed */ + current.operation = (current.operation == DSGA_OP_JNZ) ? DSGA_OP_JNZ_LV : DSGA_OP_JZ_LV; + current.adjust_flags &= ~DSGAF_LAST_VAR_READ; + current.and_mask = 0; + current.variable = 0x1A; + group->adjusts.erase(group->adjusts.begin() + j); + j--; + i--; } } group->adjusts.insert(group->adjusts.begin() + j + 1, current); diff --git a/src/newgrf_spritegroup.cpp b/src/newgrf_spritegroup.cpp index 97f16c41e4..a86eb27bbe 100644 --- a/src/newgrf_spritegroup.cpp +++ b/src/newgrf_spritegroup.cpp @@ -169,6 +169,17 @@ static U EvalAdjustT(const DeterministicSpriteGroupAdjust &adjust, ScopeResolver case DSGA_TYPE_NONE: break; } + auto handle_jump = [&](bool jump, U jump_return_value) -> U { + if (jump && adjust_iter != nullptr) { + /* Jump */ + (*adjust_iter) += adjust.jump; + return jump_return_value; + } else { + /* Don't jump */ + return last_value; + } + }; + switch (adjust.operation) { case DSGA_OP_ADD: return last_value + value; case DSGA_OP_SUB: return last_value - value; @@ -202,26 +213,10 @@ static U EvalAdjustT(const DeterministicSpriteGroupAdjust &adjust, ScopeResolver case DSGA_OP_RSUB: return value - last_value; case DSGA_OP_STO_NC: _temp_store.StoreValue(adjust.divmod_val, (S)value); return last_value; case DSGA_OP_ABS: return ((S)last_value < 0) ? -((S)last_value) : (S)last_value; - case DSGA_OP_JZ: { - if (value == 0 && adjust_iter != nullptr) { - /* Jump */ - (*adjust_iter) += adjust.jump; - return 0; - } else { - /* Don't jump */ - 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; - } - } + case DSGA_OP_JZ: return handle_jump(value == 0, value); + case DSGA_OP_JNZ: return handle_jump(value != 0, value); + case DSGA_OP_JZ_LV: return handle_jump(last_value == 0, last_value); + case DSGA_OP_JNZ_LV: return handle_jump(last_value != 0, last_value); default: return value; } } @@ -711,6 +706,8 @@ static const char *_dsg_op_special_names[] { "ABS", "JZ", "JNZ", + "JZ_LV", + "JNZ_LV", }; static_assert(lengthof(_dsg_op_special_names) == DSGA_OP_SPECIAL_END - DSGA_OP_TERNARY); @@ -781,6 +778,12 @@ static char *DumpSpriteGroupAdjust(char *p, const char *last, const Deterministi append_flags(); return p; } + if (adjust.operation == DSGA_OP_JZ_LV || adjust.operation == DSGA_OP_JNZ_LV) { + p = GetAdjustOperationName(p, last, adjust.operation); + p += seprintf(p, last, " +%u", adjust.jump); + append_flags(); + return p; + } if (adjust.operation == DSGA_OP_STO && adjust.type == DSGA_TYPE_NONE && adjust.variable == 0x1A && adjust.shift_num == 0) { /* Temp storage store */ highlight_tag = (1 << 16) | (adjust.and_mask & 0xFFFF); diff --git a/src/newgrf_spritegroup.h b/src/newgrf_spritegroup.h index 920c1a5dfd..361846e1f6 100644 --- a/src/newgrf_spritegroup.h +++ b/src/newgrf_spritegroup.h @@ -208,6 +208,8 @@ enum DeterministicSpriteGroupAdjustOperation : uint8 { 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_JZ_LV, ///< jump forward fixed number of adjusts (to adjust after DSGAF_END_BLOCK marker (taking into account nesting)) if a is zero. return a + DSGA_OP_JNZ_LV, ///< jump forward fixed number of adjusts (to adjust after DSGAF_END_BLOCK marker (taking into account nesting)) if a is non-zero. return a DSGA_OP_SPECIAL_END, }; @@ -408,6 +410,8 @@ inline bool IsEvalAdjustJumpOperation(DeterministicSpriteGroupAdjustOperation op switch (op) { case DSGA_OP_JZ: case DSGA_OP_JNZ: + case DSGA_OP_JZ_LV: + case DSGA_OP_JNZ_LV: return true; default: