36 if (group ==
nullptr)
return std::monostate{};
38 const GRFFile *grf =
object.grffile;
41 if (profiler == _newgrf_profilers.end() || !profiler->active) {
43 }
else if (top_level) {
44 profiler->BeginResolve(
object);
45 auto result = group->
Resolve(
object);
46 profiler->EndResolve(result);
49 profiler->RecursiveResolve();
54static inline uint32_t GetVariable(
const ResolverObject &
object,
ScopeResolver *scope, uint8_t variable, uint32_t parameter,
bool &available)
58 case 0x0C:
return object.callback;
59 case 0x10:
return object.callback_param1;
60 case 0x18:
return object.callback_param2;
61 case 0x1C:
return object.last_value;
65 case 0x7D:
return object.GetRegister(parameter);
68 if (
object.grffile ==
nullptr)
return 0;
69 return object.grffile->GetParam(parameter);
73 if (variable < 0x40 &&
GetGlobalVariable(variable, &value,
object.grffile))
return value;
75 return scope->
GetVariable(variable, parameter, available);
106 Debug(grf, 1,
"Unhandled scope variable 0x{:X}", variable);
140template <
typename U,
typename S>
143 value >>= adjust.shift_num;
144 value &= adjust.and_mask;
146 switch (adjust.type) {
147 case DSGA_TYPE_DIV: value = ((S)value + (S)adjust.add_val) / (S)adjust.divmod_val;
break;
148 case DSGA_TYPE_MOD: value = ((S)value + (S)adjust.add_val) % (S)adjust.divmod_val;
break;
149 case DSGA_TYPE_NONE:
break;
152 switch (adjust.operation) {
155 case DSGA_OP_SMIN:
return std::min<S>(last_value, value);
156 case DSGA_OP_SMAX:
return std::max<S>(last_value, value);
157 case DSGA_OP_UMIN:
return std::min<U>(last_value, value);
158 case DSGA_OP_UMAX:
return std::max<U>(last_value, value);
159 case DSGA_OP_SDIV:
return value == 0 ? (S)last_value : (S)last_value / (S)value;
160 case DSGA_OP_SMOD:
return value == 0 ? (S)last_value : (S)last_value % (S)value;
161 case DSGA_OP_UDIV:
return value == 0 ? (U)last_value : (U)last_value / (U)value;
162 case DSGA_OP_UMOD:
return value == 0 ? (U)last_value : (U)last_value % (U)value;
167 case DSGA_OP_STO:
object.SetRegister((U)value, (S)last_value);
return last_value;
170 case DSGA_OP_ROR:
return std::rotr<uint32_t>((U)last_value, (U)value & 0x1F);
171 case DSGA_OP_SCMP:
return ((S)last_value == (S)value) ? 1 : ((S)last_value < (S)value ? 0 : 2);
172 case DSGA_OP_UCMP:
return ((U)last_value == (U)value) ? 1 : ((U)last_value < (U)value ? 0 : 2);
173 case DSGA_OP_SHL:
return (uint32_t)(U)last_value << ((U)value & 0x1F);
174 case DSGA_OP_SHR:
return (uint32_t)(U)last_value >> ((U)value & 0x1F);
175 case DSGA_OP_SAR:
return (int32_t)(S)last_value >> ((U)value & 0x1F);
176 default:
return value;
183 return range.high < value;
188 uint32_t last_value = 0;
193 for (
const auto &adjust : this->adjusts) {
195 bool available =
true;
196 if (adjust.variable == 0x7E) {
198 auto *subvalue = std::get_if<CallbackResult>(&subgroup);
199 value = subvalue !=
nullptr ? *subvalue : UINT16_MAX;
202 }
else if (adjust.variable == 0x7B) {
203 value = GetVariable(
object, scope, adjust.
parameter, last_value, available);
205 value = GetVariable(
object, scope, adjust.variable, adjust.
parameter, available);
214 switch (this->size) {
215 case DSG_SIZE_BYTE: value = EvalAdjustT<uint8_t, int8_t> (adjust,
object, scope, last_value, value);
break;
216 case DSG_SIZE_WORD: value = EvalAdjustT<uint16_t, int16_t>(adjust,
object, scope, last_value, value);
break;
217 case DSG_SIZE_DWORD: value = EvalAdjustT<uint32_t, int32_t>(adjust,
object, scope, last_value, value);
break;
218 default: NOT_REACHED();
223 object.last_value = last_value;
225 auto result = this->default_result;
227 if (this->ranges.size() > 4) {
228 const auto &lower = std::lower_bound(this->ranges.begin(), this->ranges.end(), value, RangeHighComparator);
229 if (lower != this->ranges.end() && lower->low <= value) {
230 assert(lower->low <= value && value <= lower->high);
231 result = lower->result;
234 for (
const auto &range : this->ranges) {
235 if (range.low <= value && value <= range.high) {
236 result = range.result;
242 if (result.calculated_result) {
243 return static_cast<CallbackResult
>(
GB(value, 0, 15));
254 uint8_t match = this->triggers &
object.GetWaitingRandomTriggers();
255 bool res = (this->
cmp_mode == RSG_CMP_ANY) ? (match != 0) : (match == this->triggers);
258 object.AddUsedRandomTriggers(match);
297 uint8_t actual_stage = stage !=
nullptr ? *stage : 0;
302 if (stage !=
nullptr) *stage = 0;
debug_inline static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
Add dynamic register values to a sprite layout.
void ProcessRegisters(const struct ResolverObject &object, uint8_t resolved_var10, uint32_t resolved_sprite)
Evaluates the register modifiers and integrates them into the preprocessed sprite layout.
Functions related to debugging.
#define Debug(category, level, format_string,...)
Output a line of debugging information.
bool GetGlobalVariable(uint8_t param, uint32_t *value, const GRFFile *grffile)
Reads a variable common to VarAction2 and Action7/9/D.
@ CBID_RANDOM_TRIGGER
Set when calling a randomizing trigger (almost undocumented).
uint GetConstructionStageOffset(uint construction_stage, uint num_sprites)
Determines which sprite to use from a spriteset for a specific construction stage.
Profiling of NewGRF action 2 handling.
@ DSGA_OP_STOP
store a into persistent storage, indexed by b, return a
@ DSGA_OP_ROR
rotate a b positions to the right
@ DSGA_OP_UCMP
(unsigned) comparison (a < b -> 0, a == b = 1, a > b = 2)
@ DSGA_OP_SAR
(signed) a >> b
@ DSGA_OP_STO
store a into temporary storage, indexed by b. return a
@ DSGA_OP_SMOD
(signed) a % b
@ DSGA_OP_UDIV
(unsigned) a / b
@ DSGA_OP_UMAX
(unsigned) max(a, b)
@ DSGA_OP_SMIN
(signed) min(a, b)
@ DSGA_OP_UMOD
(unsigned) a & b
@ DSGA_OP_SHR
(unsigned) a >> b
@ DSGA_OP_SDIV
(signed) a / b
@ DSGA_OP_SCMP
(signed) comparison (a < b -> 0, a == b = 1, a > b = 2)
@ DSGA_OP_UMIN
(unsigned) min(a, b)
@ DSGA_OP_SMAX
(signed) max(a, b)
std::variant< std::monostate, CallbackResult, const SpriteGroup * > ResolverResult
Result of resolving sprite groups:
Some methods of Pool are placed here in order to reduce compilation time and binary size.
#define INSTANTIATE_POOL_METHODS(name)
Force instantiation of pool methods so we don't get linker errors.
A number of safeguards to prevent using unsafe methods.
Definition of base types and functions in a cross-platform compatible way.
ResolverResult Resolve(ResolverObject &object) const override
Base sprite group resolver.
uint8_t parameter
Used for variables between 0x60 and 0x7F inclusive.
ResolverResult Resolve(ResolverObject &object) const override
Base sprite group resolver.
Dynamic data of a loaded NewGRF.
const GRFFile * grffile
Which GRF is being profiled.
uint consistent_max_offset
Number of sprites in all referenced spritesets.
bool NeedsPreprocessing() const
Tests whether this spritelayout needs preprocessing by SpriteLayoutProcessor, or whether it can be us...
Tindex index
Index of this pool item.
Base class for all pools.
uint8_t lowest_randbit
Look for this in the per-object randomized bitmask:
VarSpriteGroupScope var_scope
Take this object:
std::vector< const SpriteGroup * > groups
Take the group with appropriate index:
ResolverResult Resolve(ResolverObject &object) const override
Base sprite group resolver.
RandomizedSpriteGroupCompareMode cmp_mode
Check for these triggers:
ResolverResult Resolve(ResolverObject &object) const override
Base sprite group resolver.
std::vector< const SpriteGroup * > loaded
List of loaded groups (can be SpriteIDs or Callback results)
std::vector< const SpriteGroup * > loading
List of loading groups (can be SpriteIDs or Callback results)
Interface for SpriteGroup-s to access the gamestate.
ScopeResolver default_scope
Default implementation of the grf scope.
virtual const SpriteGroup * ResolveReal(const RealSpriteGroup &group) const
Get the real sprites of the grf.
virtual ScopeResolver * GetScope(VarSpriteGroupScope scope=VSG_SCOPE_SELF, uint8_t relative=0)
Get a resolver for the scope.
Interface to query and set values specific to a single VarSpriteGroupScope (action 2 scope).
virtual void StorePSA(uint reg, int32_t value)
Store a value into the persistent storage area (PSA).
virtual uint32_t GetVariable(uint8_t variable, uint32_t parameter, bool &available) const
Get a variable value.
virtual uint32_t GetRandomTriggers() const
Get the triggers.
virtual uint32_t GetRandomBits() const
Get a few random bits.
virtual ResolverResult Resolve(ResolverObject &object) const
Base sprite group resolver.
Class for temporary storage of data.
SpriteLayoutProcessor ProcessRegisters(const ResolverObject &object, uint8_t *stage) const
Process registers and the construction stage into the sprite layout.