diff --git a/src/newgrf.cpp b/src/newgrf.cpp index a4ca147fab..1f73c75c9f 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -5929,10 +5929,25 @@ static void NewSpriteGroup(ByteReader *buf) break; case DSGA_OP_SDIV: if ((prev_inference & VA2AIF_SIGNED_NON_NEGATIVE) && adjust.variable == 0x1A && adjust.shift_num == 0 && HasExactlyOneBit(adjust.and_mask)) { + uint shift_count = FindFirstBit(adjust.and_mask); + if (group->adjusts.size() >= 3 && shift_count == 16 && varsize == 4 && (feature == GSF_TRAINS || feature == GSF_ROADVEHICLES || feature == GSF_SHIPS)) { + const DeterministicSpriteGroupAdjust &prev = group->adjusts[group->adjusts.size() - 2]; + DeterministicSpriteGroupAdjust &prev2 = group->adjusts[group->adjusts.size() - 3]; + if (prev.operation == DSGA_OP_MUL && prev.type == DSGA_TYPE_NONE && prev.variable == 0x1A && prev.shift_num == 0 && prev.and_mask <= 0xFFFF && + (prev2.operation == DSGA_OP_RST || group->adjusts.size() == 3) && prev2.type == DSGA_TYPE_NONE && prev2.variable == 0xB4 && prev2.shift_num == 0 && prev2.and_mask == 0xFFFF) { + /* Replace with scaled current speed */ + prev2.variable = A2VRI_VEHICLE_CURRENT_SPEED_SCALED; + prev2.parameter = prev.and_mask; + group->adjusts.pop_back(); + group->adjusts.pop_back(); + inference = VA2AIF_SIGNED_NON_NEGATIVE; + break; + } + } /* Convert to a shift */ adjust.operation = DSGA_OP_SHR; - adjust.and_mask = FindFirstBit(adjust.and_mask); - inference |= VA2AIF_SIGNED_NON_NEGATIVE; + adjust.and_mask = shift_count; + inference = VA2AIF_SIGNED_NON_NEGATIVE; } default: break; diff --git a/src/newgrf_engine.cpp b/src/newgrf_engine.cpp index 500ad757b2..e2fcdd8987 100644 --- a/src/newgrf_engine.cpp +++ b/src/newgrf_engine.cpp @@ -25,6 +25,7 @@ #include "newgrf_cache_check.h" #include "ship.h" #include "scope_info.h" +#include "newgrf_extension.h" #include "safeguards.h" @@ -477,6 +478,7 @@ static uint32 VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *object, case 0x80 + 0x34: case 0x80 + 0x35: + case A2VRI_VEHICLE_CURRENT_SPEED_SCALED: if (v->type == VEH_AIRCRAFT) { _sprite_group_resolve_check_veh_check = false; } else { @@ -878,6 +880,9 @@ static uint32 VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *object, return variable == 0xFE ? modflags : GB(modflags, 8, 8); } + + case A2VRI_VEHICLE_CURRENT_SPEED_SCALED: + return (v->cur_speed * parameter) >> 16; } /* diff --git a/src/newgrf_extension.h b/src/newgrf_extension.h index d8c82d1c5a..6698fce4c2 100644 --- a/src/newgrf_extension.h +++ b/src/newgrf_extension.h @@ -60,6 +60,7 @@ enum Action0RemapPropertyIds { enum Action2VariableRemapIds { A2VRI_OBJECT_FOUNDATION_SLOPE = 0x100, A2VRI_OBJECT_FOUNDATION_SLOPE_CHANGE, + A2VRI_VEHICLE_CURRENT_SPEED_SCALED, }; /** Action14 feature definition */ diff --git a/src/newgrf_spritegroup.cpp b/src/newgrf_spritegroup.cpp index 5613aca3fd..dc5cf4c8dc 100644 --- a/src/newgrf_spritegroup.cpp +++ b/src/newgrf_spritegroup.cpp @@ -15,6 +15,7 @@ #include "vehicle_type.h" #include "newgrf_cache_check.h" #include "string_func.h" +#include "newgrf_extension.h" #include "safeguards.h" @@ -634,7 +635,9 @@ void SpriteGroupDumper::DumpSpriteGroup(const SpriteGroup *sg, int padding, uint continue; } p += seprintf(p, lastof(this->buffer), "%*svar: %X", padding, "", adjust.variable); - if (adjust.variable >= 0x100) { + if (adjust.variable == A2VRI_VEHICLE_CURRENT_SPEED_SCALED) { + p += seprintf(p, lastof(this->buffer), " (current_speed_scaled)"); + } else if (adjust.variable >= 0x100) { extern const GRFVariableMapDefinition _grf_action2_remappable_variables[]; for (const GRFVariableMapDefinition *info = _grf_action2_remappable_variables; info->name != nullptr; info++) { if (adjust.variable == info->id) {