diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 6b6b998c5d..8471614d1e 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -5666,6 +5666,15 @@ static void NewSpriteGroup(ByteReader *buf) if (adjust.and_mask <= 1) inference = VA2AIF_SIGNED_NON_NEGATIVE | VA2AIF_ONE_OR_ZERO; break; case DSGA_OP_AND: + if ((prev_inference & VA2AIF_SIGNED_NON_NEGATIVE) && adjust.variable == 0x1A && adjust.shift_num == 0 && adjust.and_mask == 1) { + DeterministicSpriteGroupAdjust &prev = group->adjusts[group->adjusts.size() - 2]; + if (prev.operation == DSGA_OP_SCMP || prev.operation == DSGA_OP_UCMP) { + prev.operation = DSGA_OP_EQ; + group->adjusts.pop_back(); + inference = VA2AIF_SIGNED_NON_NEGATIVE | VA2AIF_ONE_OR_ZERO; + break; + } + } if (adjust.and_mask <= 1) { inference = VA2AIF_SIGNED_NON_NEGATIVE | VA2AIF_ONE_OR_ZERO; } else if ((adjust.and_mask & (1 << ((varsize * 8) - 1))) == 0) { @@ -5700,6 +5709,17 @@ static void NewSpriteGroup(ByteReader *buf) } break; } + if (group->adjusts.size() > 1) { + /* Remove redundant comparison with 0 if applicable */ + const DeterministicSpriteGroupAdjust &prev = group->adjusts[group->adjusts.size() - 2]; + if (prev.type == DSGA_TYPE_NONE && prev.operation == DSGA_OP_EQ && prev.variable == 0x1A && prev.shift_num == 0 && prev.and_mask == 0) { + DeterministicSpriteGroupAdjust current = group->adjusts.back(); + group->adjusts.pop_back(); + group->adjusts.pop_back(); + std::swap(current.and_mask, current.add_val); + group->adjusts.push_back(current); + } + } inference = VA2AIF_PREV_TERNARY; } break; diff --git a/src/newgrf_spritegroup.cpp b/src/newgrf_spritegroup.cpp index 217fdd2c0b..0473311fa3 100644 --- a/src/newgrf_spritegroup.cpp +++ b/src/newgrf_spritegroup.cpp @@ -183,6 +183,7 @@ static U EvalAdjustT(const DeterministicSpriteGroupAdjust &adjust, ScopeResolver case DSGA_OP_SHR: return (uint32)(U)last_value >> ((U)value & 0x1F); case DSGA_OP_SAR: return (int32)(S)last_value >> ((U)value & 0x1F); case DSGA_OP_TERNARY: return (last_value != 0) ? value : adjust.add_val; + case DSGA_OP_EQ: return (last_value == value) ? 1 : 0; default: return value; } } @@ -562,6 +563,14 @@ static const char *_sg_size_names[] { "DWORD", }; +static const char *GetAdjustOperationName(DeterministicSpriteGroupAdjustOperation operation) +{ + if (operation < DSGA_OP_END) return _dsg_op_names[operation]; + if (operation == DSGA_OP_TERNARY) return "TERNARY"; + if (operation == DSGA_OP_EQ) return "EQ"; + return "???"; +} + void SpriteGroupDumper::DumpSpriteGroup(const SpriteGroup *sg, int padding, uint flags) { if (sg == nullptr) { @@ -634,7 +643,7 @@ void SpriteGroupDumper::DumpSpriteGroup(const SpriteGroup *sg, int padding, uint case DSGA_TYPE_MOD: p += seprintf(p, lastof(this->buffer), ", add: %X, mod: %X", adjust.add_val, adjust.divmod_val); break; case DSGA_TYPE_NONE: break; } - p += seprintf(p, lastof(this->buffer), ", op: %X (%s)", adjust.operation, adjust.operation < DSGA_OP_END ? _dsg_op_names[adjust.operation] : "???"); + p += seprintf(p, lastof(this->buffer), ", op: %X (%s)", adjust.operation, GetAdjustOperationName(adjust.operation)); this->print(); } if (dsg->calculated_result) { diff --git a/src/newgrf_spritegroup.h b/src/newgrf_spritegroup.h index 623665ddb4..3c71e7651d 100644 --- a/src/newgrf_spritegroup.h +++ b/src/newgrf_spritegroup.h @@ -163,6 +163,7 @@ enum DeterministicSpriteGroupAdjustOperation { DSGA_OP_END, DSGA_OP_TERNARY = 0x80, ///< a == 0 ? b : c, + DSGA_OP_EQ, ///< a == b ? 1 : 0, DSGA_OP_SPECIAL_END, };