4 * This file is part of OpenTTD.
5 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
6 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
10 /** @file newgrf_spritegroup.h Action 2 handling. */
12 #ifndef NEWGRF_SPRITEGROUP_H
13 #define NEWGRF_SPRITEGROUP_H
17 #include "core/align.h"
18 #include "core/pointer.h"
19 #include "core/flexarray.h"
21 #include "town_type.h"
22 #include "engine_type.h"
23 #include "house_type.h"
25 #include "newgrf_callbacks.h"
26 #include "newgrf_generic.h"
27 #include "newgrf_storage.h"
28 #include "newgrf_commons.h"
31 * Gets the value of a so-called newgrf "register".
32 * @param i index of the register
34 * @return the value of the register
36 static inline uint32
GetRegister(uint i
)
38 extern TemporaryStorageArray
<int32
, 0x110> _temp_store
;
39 return _temp_store
.GetValue(i
);
42 /* List of different sprite group types */
43 enum SpriteGroupType
{
50 SGT_INDUSTRY_PRODUCTION
,
54 typedef uint32 SpriteGroupID
;
55 struct ResolverObject
;
57 /* SPRITE_WIDTH is 24. ECS has roughly 30 sprite groups per real sprite.
58 * Adding an 'extra' margin would be assuming 64 sprite groups per real
59 * sprite. 64 = 2^6, so 2^30 should be enough (for now) */
61 /* Common wrapper for all the different sprite group types */
64 static const size_t MAX_SIZE
= 1 << 30;
66 static std::deque
<ttd_unique_ptr
<SpriteGroup
> > pool
;
69 * Append a new sprite group to the pool.
70 * @param group The sprite group to append.
71 * @return The sprite group itself, for the convenience of our callers.
74 static T
*append (T
*group
)
76 assert (pool
.size() < MAX_SIZE
);
77 pool
.push_back (ttd_unique_ptr
<SpriteGroup
> (group
));
81 const SpriteGroupType type
; ///< Type of the sprite group
83 CONSTEXPR
SpriteGroup (SpriteGroupType type
) : type (type
)
87 /** Base sprite group resolver */
88 virtual const SpriteGroup
*Resolve (ResolverObject
&object
) const
94 virtual ~SpriteGroup()
98 bool IsType (SpriteGroupType type
) const
100 return this->type
== type
;
103 virtual SpriteID
GetResult (void) const
108 virtual byte
GetNumResults (void) const
113 virtual uint16
GetCallbackResult (void) const
115 return CALLBACK_FAILED
;
118 static const SpriteGroup
*Resolve(const SpriteGroup
*group
, ResolverObject
&object
, bool top_level
= true);
121 * Get a callback result from a SpriteGroup.
122 * @return Callback result.
124 static uint16
CallbackResult (const SpriteGroup
*result
)
126 return result
!= NULL
? result
->GetCallbackResult() : CALLBACK_FAILED
;
129 /** Clear the sprite group pool. */
130 static void clear (void)
137 /* 'Real' sprite groups contain a list of other result or callback sprite
139 struct RealSpriteGroup
: SpriteGroup
, FlexArray
<SpriteGroup
*> {
141 /* Loaded = in motion, loading = not moving
142 * Each group contains several spritesets, for various loading stages */
144 /* XXX: For stations the meaning is different - loaded is for stations
145 * with small amount of cargo whilst loading is for stations with a lot
148 const uint16 n
; ///< Total number of groups
149 const byte n1
; ///< Number of loaded groups
150 const byte n2
; ///< Number of loading groups
151 const SpriteGroup
*groups
[]; ///< List of groups (can be SpriteIDs or Callback results)
153 RealSpriteGroup (uint16 n
, byte n1
, byte n2
)
154 : SpriteGroup (SGT_REAL
), n (n
), n1 (n1
), n2 (n2
)
156 memset (this->groups
, 0, n
* sizeof(SpriteGroup
*));
160 const SpriteGroup
*Resolve (ResolverObject
&object
) const OVERRIDE
;
163 static RealSpriteGroup
*create (byte n1
, byte n2
)
165 uint16 total
= (uint16
)n1
+ (uint16
)n2
;
166 return SpriteGroup::append (new (total
) RealSpriteGroup (total
, n1
, n2
));
169 void set (uint i
, const SpriteGroup
*group
)
171 this->groups
[i
] = group
;
175 * Get the count of sprite groups.
176 * @param alt Count the groups in the second (loading) set.
177 * @return The count of sprite groups in the set.
179 uint
get_count (bool alt
) const
181 return alt
? this->n2
: this->n1
;
185 * Get a particular sprite group.
186 * @param alt Look for the group in the second (loading) set.
187 * @param i Index of the sprite group to get.
188 * @return The requested sprite group.
190 const SpriteGroup
*get_group (bool alt
, uint i
) const
192 if (alt
) i
+= this->n1
;
193 return this->groups
[i
];
197 * Get the first available sprite group from the first set.
198 * @return The first sprite group, or NULL if there isn't any.
200 const SpriteGroup
*get_first (void) const
202 return (this->n1
!= 0) ? this->groups
[0] : NULL
;
206 * Get the first available sprite group from either set.
207 * @param alt Try the second (loading) set of groups first.
208 * @return The first sprite group, or NULL if there isn't any.
210 const SpriteGroup
*get_first (bool alt
) const
212 return (alt
&& (this->n2
!= 0)) ? this->groups
[this->n1
] :
213 (this->n
!= 0) ? this->groups
[0] : NULL
;
217 /* Shared by deterministic and random groups. */
218 enum VarSpriteGroupScope
{
221 VSG_SCOPE_SELF
= VSG_BEGIN
, ///< Resolved object itself
222 VSG_SCOPE_PARENT
, ///< Related object of the resolved one
223 VSG_SCOPE_RELATIVE
, ///< Relative position (vehicles only)
227 DECLARE_POSTFIX_INCREMENT(VarSpriteGroupScope
)
230 struct DeterministicSpriteGroup
: SpriteGroup
, FlexArrayBase
{
241 byte parameter
; ///< Used for variables between 0x60 and 0x7F inclusive, except 0x7E.
242 const SpriteGroup
*subroutine
; ///< Used for variable 0x7E.
247 const SpriteGroup
*group
;
253 template <typename T
>
254 static CONSTEXPR T
*offset_pointer (void *ptr
, size_t offset
)
256 return (T
*) (((char*)ptr
) + offset
);
259 const VarSpriteGroupScope var_scope
; ///< Scope.
260 const byte size
; ///< Logarithmic size of accumulator (0 for int8, 1 for int16, 2 for int32).
261 const SpriteGroup
*default_group
; ///< Default result group.
262 Adjust
*const adjusts
; ///< Vector of adjusts.
263 Range
*const ranges
; ///< Vector of result ranges.
264 const uint num_adjusts
; ///< Adjust count.
265 const byte num_ranges
; ///< Result range count.
267 static CONSTEXPR
size_t adjusts_offset (void)
269 return ttd_align_up
<Adjust
> (sizeof(DeterministicSpriteGroup
));
272 DeterministicSpriteGroup (bool parent_scope
,
273 byte size
, uint num_adjusts
,
274 byte num_ranges
, size_t ranges_offset
)
275 : SpriteGroup (SGT_DETERMINISTIC
),
276 var_scope (parent_scope
? VSG_SCOPE_PARENT
: VSG_SCOPE_SELF
),
277 size (size
), default_group (NULL
),
278 adjusts (offset_pointer
<Adjust
> (this, adjusts_offset())),
279 ranges (offset_pointer
<Range
> (this, ranges_offset
)),
280 num_adjusts (num_adjusts
), num_ranges (num_ranges
)
282 memset (this->adjusts
, 0, num_adjusts
* sizeof(Adjust
));
283 memset (this->ranges
, 0, num_ranges
* sizeof(Range
));
286 /** Custom operator new to account for the extra storage. */
287 void *operator new (size_t size
, size_t total
, size_t = 1)
289 assert (total
>= size
);
290 return ::operator new (total
);
294 const SpriteGroup
*Resolve(ResolverObject
&object
) const;
297 static DeterministicSpriteGroup
*create (bool parent_scope
, byte size
,
298 uint num_adjusts
, byte num_ranges
)
300 size_t adjusts_end
= adjusts_offset() + num_adjusts
* sizeof(Adjust
);
301 size_t ranges_offset
= ttd_align_up
<Range
> (adjusts_end
);
302 size_t ranges_end
= ranges_offset
+ num_ranges
* sizeof(Range
);
303 size_t total_size
= ttd_align_up
<DeterministicSpriteGroup
> (ranges_end
);
304 DeterministicSpriteGroup
*group
= new (total_size
)
305 DeterministicSpriteGroup (parent_scope
, size
,
306 num_adjusts
, num_ranges
,
308 return SpriteGroup::append (group
);
311 Adjust
*get_adjust (uint i
)
313 return &this->adjusts
[i
];
316 void set_range (byte i
, const SpriteGroup
*group
, uint32 low
, uint32 high
)
318 Range
*range
= &this->ranges
[i
];
319 range
->group
= group
;
324 void set_default (const SpriteGroup
*group
)
326 this->default_group
= group
;
331 struct RandomizedSpriteGroup
: SpriteGroup
, FlexArray
<SpriteGroup
*> {
333 const VarSpriteGroupScope var_scope
; ///< Take this object.
334 const bool cmp_mode
; ///< Match all triggers, else any.
335 const byte triggers
; ///< Check for these triggers.
337 const byte lowest_randbit
; ///< Look for this in the per-object randomized bitmask.
338 const byte num_groups
; ///< Group count; must be power of 2.
339 const SpriteGroup
*groups
[]; ///< Take the group with appropriate index.
341 RandomizedSpriteGroup (VarSpriteGroupScope scope
, bool cmp_mode
,
342 byte triggers
, byte count
, byte bit
, byte num
)
343 : SpriteGroup (SGT_RANDOMIZED
), var_scope (scope
),
344 cmp_mode (cmp_mode
), triggers (triggers
), count (count
),
345 lowest_randbit (bit
), num_groups (num
)
347 memset (this->groups
, 0, num
* sizeof(SpriteGroup
*));
351 const SpriteGroup
*Resolve (ResolverObject
&object
) const OVERRIDE
;
355 static RandomizedSpriteGroup
*create (VarSpriteGroupScope scope
,
356 bool cmp_mode
, byte triggers
, byte count
, byte bit
, byte num
)
358 return SpriteGroup::append (new (num
)
359 RandomizedSpriteGroup (scope
, cmp_mode
,
360 triggers
, count
, bit
, num
));
363 void set_group (uint i
, const SpriteGroup
*group
)
365 this->groups
[i
] = group
;
370 /* This contains a callback result. A failed callback has a value of
372 struct CallbackResultSpriteGroup
: SpriteGroup
{
375 /** Compute the result value to store based on GRF version. */
376 static CONSTEXPR uint16
compute_result (uint16 value
, bool grf_version8
)
378 /* Old style callback results (only valid for version < 8)
379 * have the highest byte 0xFF to signify it is a callback
380 * result. New style ones only have the highest bit set
381 * (allows 15-bit results, instead of just 8). */
382 return (!grf_version8
&& (value
>> 8) == 0xFF) ?
383 (value
& 0xFF) : (value
& 0x7FFF);
387 * Creates a spritegroup representing a callback result
388 * @param value The value that was used to represent this callback result
389 * @param grf_version8 True, if we are dealing with a new NewGRF which uses GRF version >= 8.
391 CONSTEXPR
CallbackResultSpriteGroup (uint16 value
, bool grf_version8
)
392 : SpriteGroup (SGT_CALLBACK
),
393 result (compute_result (value
, grf_version8
))
397 uint16
GetCallbackResult (void) const
402 static CallbackResultSpriteGroup
*create (uint16 value
, bool v8
)
404 return SpriteGroup::append (new CallbackResultSpriteGroup (value
, v8
));
409 /* A result sprite group returns the first SpriteID and the number of
410 * sprites in the set */
411 struct ResultSpriteGroup
: SpriteGroup
{
413 * Creates a spritegroup representing a sprite number result.
414 * @param sprite The sprite number.
415 * @param num_sprites The number of sprites per set.
416 * @return A spritegroup representing the sprite number result.
418 ResultSpriteGroup(SpriteID sprite
, byte num_sprites
) :
419 SpriteGroup(SGT_RESULT
),
421 num_sprites(num_sprites
)
427 SpriteID
GetResult() const { return this->sprite
; }
428 byte
GetNumResults() const { return this->num_sprites
; }
430 static ResultSpriteGroup
*create (SpriteID sprite
, byte num_sprites
)
432 return SpriteGroup::append (new ResultSpriteGroup (sprite
, num_sprites
));
437 * Action 2 sprite layout for houses, industry tiles, objects and airport tiles.
439 struct TileLayoutSpriteGroup
: SpriteGroup
, FlexArrayBase
{
441 NewGRFSpriteLayout dts
;
443 template <typename T
>
444 static CONSTEXPR T
*offset_pointer (void *ptr
, size_t offset
)
446 return (T
*) (((char*)ptr
) + offset
);
449 static CONSTEXPR
size_t seq_offset (void)
451 return ttd_align_up
<DrawTileSeqStruct
> (sizeof(TileLayoutSpriteGroup
));
454 TileLayoutSpriteGroup (const PalSpriteID
&ground
, uint n
,
455 const DrawTileSeqStruct
*seq
, size_t regs_offset
,
456 const TileLayoutRegisters
*regs
,
457 uint consistent_max_offset
)
458 : SpriteGroup (SGT_TILELAYOUT
)
460 this->dts
.ground
= ground
;
462 DrawTileSeqStruct
*q
= offset_pointer
<DrawTileSeqStruct
> (this, seq_offset());
463 memcpy (q
, seq
, n
* sizeof(DrawTileSeqStruct
));
464 q
[n
].MakeTerminator();
468 TileLayoutRegisters
*r
= offset_pointer
<TileLayoutRegisters
> (this, regs_offset
);
469 memcpy (r
, regs
, (n
+ 1) * sizeof(TileLayoutRegisters
));
470 this->dts
.registers
= r
;
472 this->dts
.registers
= NULL
;
475 this->dts
.consistent_max_offset
= consistent_max_offset
;
478 /** Custom operator new to account for the extra storage. */
479 void *operator new (size_t size
, size_t total
, size_t = 1)
481 assert (total
>= size
);
482 return ::operator new (total
);
486 static TileLayoutSpriteGroup
*create (const PalSpriteID
&ground
,
487 uint n
, const DrawTileSeqStruct
*seq
,
488 const TileLayoutRegisters
*regs
, uint consistent_max_offset
)
490 /* Make room for terminator. */
491 size_t seq_end
= seq_offset() + (n
+ 1) * sizeof(DrawTileSeqStruct
);
493 size_t regs_offset
, regs_end
;
495 regs_offset
= ttd_align_up
<TileLayoutRegisters
> (seq_end
);
496 regs_end
= regs_offset
+ (n
+ 1) * sizeof(TileLayoutRegisters
);
502 size_t total_size
= ttd_align_up
<TileLayoutSpriteGroup
> (regs_end
);
503 TileLayoutSpriteGroup
*group
= new (total_size
)
504 TileLayoutSpriteGroup (ground
, n
,
505 seq
, regs_offset
, regs
,
506 consistent_max_offset
);
507 return SpriteGroup::append (group
);
510 /** Struct for resolving layouts that may need preprocessing. */
511 struct Result
: private NewGRFSpriteLayout::Result
{
512 const DrawTileSeqStruct
*seq
; ///< Array of child sprites.
513 PalSpriteID ground
; ///< Ground sprite and palette.
514 byte stage
; ///< Stage offset for sprites.
516 Result (const TileLayoutSpriteGroup
*group
, byte stage
= 0);
520 struct IndustryProductionSpriteGroup
: SpriteGroup
{
521 int16 subtract_input
[3]; // signed
522 uint16 add_output
[2]; // unsigned
526 IndustryProductionSpriteGroup (uint8 version
)
527 : SpriteGroup (SGT_INDUSTRY_PRODUCTION
),
528 version (version
), again (0)
530 memset (this->subtract_input
, 0, sizeof(this->subtract_input
));
531 memset (this->add_output
, 0, sizeof(this->add_output
));
534 static IndustryProductionSpriteGroup
*create (uint8 version
)
536 return SpriteGroup::append (new IndustryProductionSpriteGroup (version
));
541 * Interface to query and set values specific to a single #VarSpriteGroupScope (action 2 scope).
543 * Multiple of these interfaces are combined into a #ResolverObject to allow access
544 * to different game entities from a #SpriteGroup-chain (action 1-2-3 chain).
546 struct ScopeResolver
{
547 virtual ~ScopeResolver()
551 virtual uint32
GetRandomBits() const;
552 virtual uint32
GetTriggers() const;
554 virtual uint32
GetVariable(byte variable
, uint32 parameter
, bool *available
) const;
555 virtual void StorePSA(uint reg
, int32 value
);
559 * Interface for #SpriteGroup-s to access the gamestate.
561 * Using this interface #SpriteGroup-chains (action 1-2-3 chains) can be resolved,
562 * to get the results of callbacks, rerandomisations or normal sprite lookups.
564 struct ResolverObject
{
565 const GRFFile
*const grffile
; ///< GRFFile the resolved SpriteGroup belongs to
567 ResolverObject(const GRFFile
*grffile
, CallbackID callback
= CBID_NO_CALLBACK
, uint32 callback_param1
= 0, uint32 callback_param2
= 0);
568 virtual ~ResolverObject();
570 ScopeResolver default_scope
; ///< Default implementation of the grf scope.
572 CallbackID callback
; ///< Callback being resolved.
573 uint32 callback_param1
; ///< First parameter (var 10) of the callback.
574 uint32 callback_param2
; ///< Second parameter (var 18) of the callback.
576 uint32 last_value
; ///< Result of most recent DeterministicSpriteGroup (including procedure calls)
578 uint32 waiting_triggers
; ///< Waiting triggers to be used by any rerandomisation. (scope independent)
579 uint32 used_triggers
; ///< Subset of cur_triggers, which actually triggered some rerandomisation. (scope independent)
580 uint32 reseed
[VSG_END
]; ///< Collects bits to rerandomise while triggering triggers.
582 virtual const SpriteGroup
*ResolveReal(const RealSpriteGroup
*group
) const;
584 virtual ScopeResolver
*GetScope(VarSpriteGroupScope scope
= VSG_SCOPE_SELF
, byte relative
= 0);
587 * Returns the waiting triggers that did not trigger any rerandomisation.
589 uint32
GetRemainingTriggers() const
591 return this->waiting_triggers
& ~this->used_triggers
;
595 * Returns the OR-sum of all bits that need reseeding
596 * independent of the scope they were accessed with.
597 * @return OR-sum of the bits.
599 uint32
GetReseedSum() const
602 for (VarSpriteGroupScope vsg
= VSG_BEGIN
; vsg
< VSG_END
; vsg
++) {
603 sum
|= this->reseed
[vsg
];
609 * Resets the dynamic state of the resolver object.
610 * To be called before resolving an Action-1-2-3 chain.
614 this->last_value
= 0;
615 this->waiting_triggers
= 0;
616 this->used_triggers
= 0;
617 memset(this->reseed
, 0, sizeof(this->reseed
));
621 #endif /* NEWGRF_SPRITEGROUP_H */