diff --git a/src/debug_settings.h b/src/debug_settings.h index 477b88940a..9085f925c6 100644 --- a/src/debug_settings.h +++ b/src/debug_settings.h @@ -22,6 +22,7 @@ enum ChickenBitFlags { DCBF_DESYNC_CHECK_PERIODIC_SIGNALS = 5, DCBF_NO_OPTIMISE_VARACT2 = 6, DCBF_NO_OPTIMISE_VARACT2_DSE = 7, + DCBF_NO_OPTIMISE_VARACT2_PRUNE = 8, }; inline bool HasChickenBit(ChickenBitFlags flag) diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 4f377923ee..2b7bbaec0a 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -5522,13 +5522,13 @@ static const SpriteGroup *GetGroupFromGroupID(byte setid, byte type, uint16 grou } const SpriteGroup *result = _cur.spritegroups[groupid]; - if (HasChickenBit(DCBF_NO_OPTIMISE_VARACT2)) return result; + if (HasChickenBit(DCBF_NO_OPTIMISE_VARACT2) || HasChickenBit(DCBF_NO_OPTIMISE_VARACT2_PRUNE)) return result; while (result != nullptr) { if (result->type == SGT_DETERMINISTIC) { const DeterministicSpriteGroup *sg = static_cast(result); - if (sg->adjusts.size() == 1 && sg->adjusts[0].variable == 0x1A) { + if (sg->adjusts.size() == 0 || (sg->adjusts.size() == 1 && sg->adjusts[0].variable == 0x1A && (sg->adjusts[0].operation == DSGA_OP_ADD || sg->adjusts[0].operation == DSGA_OP_RST))) { /* Deterministic sprite group can be trivially resolved, skip it */ - uint32 value = EvaluateDeterministicSpriteGroupAdjust(sg->size, sg->adjusts[0], nullptr, 0, UINT_MAX); + uint32 value = (sg->adjusts.size() == 1) ? EvaluateDeterministicSpriteGroupAdjust(sg->size, sg->adjusts[0], nullptr, 0, UINT_MAX) : 0; result = sg->default_group; for (const auto &range : sg->ranges) { if (range.low <= value && value <= range.high) { @@ -6074,6 +6074,19 @@ static void OptimiseVarAction2DeterministicSpriteGroup(VarAction2OptimiseState & { if (unlikely(HasChickenBit(DCBF_NO_OPTIMISE_VARACT2))) return; + if (!HasChickenBit(DCBF_NO_OPTIMISE_VARACT2_PRUNE) && (state.inference & VA2AIF_HAVE_CONSTANT) && !group->calculated_result) { + /* Result of this sprite group is always the same, discard the unused branches */ + const SpriteGroup *target = group->default_group; + for (const auto &range : group->ranges) { + if (range.low <= state.current_constant && state.current_constant <= range.high) { + target = range.group; + } + } + group->default_group = target; + group->error_group = target; + group->ranges.clear(); + } + std::bitset<256> bits; if (!group->calculated_result) { auto handle_group = [&](const SpriteGroup *sg) {