diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 8b97c57429..500126f297 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -5739,6 +5739,21 @@ static void NewSpriteGroup(ByteReader *buf) replace_with_constant_load(0); } else { switch (adjust.operation) { + case DSGA_OP_SUB: + if (adjust.variable == 0x7D && adjust.shift_num == 0 && adjust.and_mask == 0xFFFFFFFF) { + DeterministicSpriteGroupAdjust &prev = group->adjusts[group->adjusts.size() - 2]; + if (group->adjusts.size() >= 3 && prev.operation == DSGA_OP_RST) { + const DeterministicSpriteGroupAdjust &prev2 = group->adjusts[group->adjusts.size() - 3]; + if (prev2.operation == DSGA_OP_STO && prev2.type == DSGA_TYPE_NONE && prev2.variable == 0x1A && + prev2.shift_num == 0 && prev2.and_mask == adjust.parameter) { + /* Convert: store, load var, subtract stored --> (dead) store, reverse subtract var */ + prev.operation = DSGA_OP_RSUB; + group->adjusts.pop_back(); + break; + } + } + } + break; case DSGA_OP_SMIN: if (adjust.variable == 0x1A && adjust.shift_num == 0 && adjust.and_mask == 1) { DeterministicSpriteGroupAdjust &prev = group->adjusts[group->adjusts.size() - 2]; diff --git a/src/newgrf_spritegroup.cpp b/src/newgrf_spritegroup.cpp index dc5cf4c8dc..8703256cfc 100644 --- a/src/newgrf_spritegroup.cpp +++ b/src/newgrf_spritegroup.cpp @@ -189,6 +189,7 @@ static U EvalAdjustT(const DeterministicSpriteGroupAdjust &adjust, ScopeResolver case DSGA_OP_SGE: return ((S)last_value >= (S)value) ? 1 : 0; case DSGA_OP_SLE: return ((S)last_value <= (S)value) ? 1 : 0; case DSGA_OP_SGT: return ((S)last_value > (S)value) ? 1 : 0; + case DSGA_OP_RSUB: return value - last_value; default: return value; } } @@ -556,6 +557,7 @@ static const char *_dsg_op_special_names[] { "SGE", "SLE", "SGT", + "RSUB", }; static_assert(lengthof(_dsg_op_special_names) == DSGA_OP_SPECIAL_END - DSGA_OP_TERNARY); diff --git a/src/newgrf_spritegroup.h b/src/newgrf_spritegroup.h index 583d3446c5..164000e0fb 100644 --- a/src/newgrf_spritegroup.h +++ b/src/newgrf_spritegroup.h @@ -168,6 +168,7 @@ enum DeterministicSpriteGroupAdjustOperation { DSGA_OP_SGE, ///< (signed) a >= b ? 1 : 0, DSGA_OP_SLE, ///< (signed) a <= b ? 1 : 0, DSGA_OP_SGT, ///< (signed) a > b ? 1 : 0, + DSGA_OP_RSUB, ///< b - a DSGA_OP_SPECIAL_END, };