peter1138@3595: /* $Id$ */ peter1138@3595: glx@9505: /** @file newgrf_spritegroup.h */ glx@9505: peter1138@3595: #ifndef NEWGRF_SPRITEGROUP_H peter1138@3595: #define NEWGRF_SPRITEGROUP_H peter1138@3595: rubidium@9723: #include "town_type.h" rubidium@9723: #include "industry_type.h" rubidium@9723: #include "core/bitmath_func.hpp" rubidium@9723: #include "gfx_type.h" rubidium@9837: #include "engine_type.h" rubidium@9837: #include "tile_type.h" rubidium@9837: rubidium@9837: #include "newgrf_cargo.h" rubidium@9837: #include "newgrf_callbacks.h" glx@9732: #include "newgrf_generic.h" rubidium@9837: #include "newgrf_storage.h" peter1138@3664: rubidium@9631: /** rubidium@9631: * Gets the value of a so-called newgrf "register". rubidium@9631: * @param i index of the register rubidium@9631: * @pre i < 0x110 rubidium@9631: * @return the value of the register rubidium@9631: */ rubidium@9631: static inline uint32 GetRegister(uint i) rubidium@9631: { rubidium@9703: extern TemporaryStorageArray _temp_store; rubidium@9703: return _temp_store.Get(i); rubidium@9631: } rubidium@9631: rubidium@6574: struct SpriteGroup; peter1138@3664: peter1138@3668: peter1138@3668: /* 'Real' sprite groups contain a list of other result or callback sprite peter1138@3668: * groups. */ rubidium@6574: struct RealSpriteGroup { glx@9505: /* Loaded = in motion, loading = not moving glx@9505: * Each group contains several spritesets, for various loading stages */ peter1138@3664: glx@9505: /* XXX: For stations the meaning is different - loaded is for stations glx@9505: * with small amount of cargo whilst loading is for stations with a lot glx@9505: * of da stuff. */ peter1138@3664: peter1138@3668: byte num_loaded; ///< Number of loaded groups peter1138@3668: byte num_loading; ///< Number of loading groups peter1138@4892: const SpriteGroup **loaded; ///< List of loaded groups (can be SpriteIDs or Callback results) peter1138@4892: const SpriteGroup **loading; ///< List of loading groups (can be SpriteIDs or Callback results) rubidium@6574: }; peter1138@3664: peter1138@3664: /* Shared by deterministic and random groups. */ rubidium@6574: enum VarSpriteGroupScope { peter1138@3664: VSG_SCOPE_SELF, glx@9505: /* Engine of consists for vehicles, city for stations. */ peter1138@3664: VSG_SCOPE_PARENT, rubidium@9826: /* Any vehicle in the consist (vehicles only) */ rubidium@9826: VSG_SCOPE_RELATIVE, rubidium@6574: }; peter1138@3664: rubidium@6574: enum DeterministicSpriteGroupSize { peter1138@3668: DSG_SIZE_BYTE, peter1138@3668: DSG_SIZE_WORD, peter1138@3668: DSG_SIZE_DWORD, rubidium@6574: }; peter1138@3664: rubidium@6574: enum DeterministicSpriteGroupAdjustType { peter1138@3668: DSGA_TYPE_NONE, peter1138@3668: DSGA_TYPE_DIV, peter1138@3668: DSGA_TYPE_MOD, rubidium@6574: }; peter1138@3664: rubidium@6574: enum DeterministicSpriteGroupAdjustOperation { glx@9505: DSGA_OP_ADD, ///< a + b glx@9505: DSGA_OP_SUB, ///< a - b glx@9505: DSGA_OP_SMIN, ///< (signed) min(a, b) glx@9505: DSGA_OP_SMAX, ///< (signed) max(a, b) glx@9505: DSGA_OP_UMIN, ///< (unsigned) min(a, b) glx@9505: DSGA_OP_UMAX, ///< (unsigned) max(a, b) glx@9505: DSGA_OP_SDIV, ///< (signed) a / b glx@9505: DSGA_OP_SMOD, ///< (signed) a % b glx@9505: DSGA_OP_UDIV, ///< (unsigned) a / b glx@9505: DSGA_OP_UMOD, ///< (unsigned) a & b glx@9505: DSGA_OP_MUL, ///< a * b glx@9505: DSGA_OP_AND, ///< a & b glx@9505: DSGA_OP_OR, ///< a | b glx@9505: DSGA_OP_XOR, ///< a ^ b rubidium@9601: DSGA_OP_STO, ///< store a into temporary storage, indexed by b. return a rubidium@9601: DSGA_OP_RST, ///< return b rubidium@9703: DSGA_OP_STOP, ///< store a into persistent storage, indexed by b, return a rubidium@9703: DSGA_OP_ROR, ///< rotate a b positions to the right rubidium@9703: DSGA_OP_SCMP, ///< (signed) comparision (a < b -> 0, a == b = 1, a > b = 2) rubidium@9703: DSGA_OP_UCMP, ///< (unsigned) comparision (a < b -> 0, a == b = 1, a > b = 2) rubidium@6574: }; peter1138@3668: peter1138@3668: rubidium@6574: struct DeterministicSpriteGroupAdjust { peter1138@3668: DeterministicSpriteGroupAdjustOperation operation; peter1138@3668: DeterministicSpriteGroupAdjustType type; peter1138@3668: byte variable; peter1138@3668: byte parameter; ///< Used for variables between 0x60 and 0x7F inclusive. peter1138@3668: byte shift_num; peter1138@3668: uint32 and_mask; peter1138@3668: uint32 add_val; peter1138@3668: uint32 divmod_val; maedhros@5868: const SpriteGroup *subroutine; rubidium@6574: }; peter1138@3668: peter1138@3668: rubidium@6574: struct DeterministicSpriteGroupRange { peter1138@4892: const SpriteGroup *group; peter1138@3668: uint32 low; peter1138@3668: uint32 high; rubidium@6574: }; peter1138@3668: peter1138@3664: rubidium@6574: struct DeterministicSpriteGroup { peter1138@3664: VarSpriteGroupScope var_scope; peter1138@3668: DeterministicSpriteGroupSize size; peter1138@3668: byte num_adjusts; peter1138@3664: byte num_ranges; peter1138@3668: DeterministicSpriteGroupAdjust *adjusts; peter1138@3664: DeterministicSpriteGroupRange *ranges; // Dynamically allocated peter1138@3664: glx@9505: /* Dynamically allocated, this is the sole owner */ peter1138@4892: const SpriteGroup *default_group; rubidium@6574: }; peter1138@3664: rubidium@6574: enum RandomizedSpriteGroupCompareMode { peter1138@3664: RSG_CMP_ANY, peter1138@3664: RSG_CMP_ALL, rubidium@6574: }; peter1138@3664: rubidium@6574: struct RandomizedSpriteGroup { glx@9505: VarSpriteGroupScope var_scope; ///< Take this object: peter1138@3664: glx@9505: RandomizedSpriteGroupCompareMode cmp_mode; ///< Check for these triggers: peter1138@3664: byte triggers; rubidium@9826: byte count; peter1138@3664: glx@9505: byte lowest_randbit; ///< Look for this in the per-object randomized bitmask: glx@9505: byte num_groups; ///< must be power of 2 peter1138@3664: glx@9505: const SpriteGroup **groups; ///< Take the group with appropriate index: rubidium@6574: }; peter1138@3664: peter1138@3668: peter1138@3668: /* This contains a callback result. A failed callback has a value of peter1138@3668: * CALLBACK_FAILED */ rubidium@6574: struct CallbackResultSpriteGroup { peter1138@3664: uint16 result; rubidium@6574: }; peter1138@3664: peter1138@3668: peter1138@3668: /* A result sprite group returns the first SpriteID and the number of peter1138@3668: * sprites in the set */ rubidium@6574: struct ResultSpriteGroup { peter1138@3668: SpriteID sprite; peter1138@3668: byte num_sprites; rubidium@6574: }; peter1138@3664: truelight@9476: struct TileLayoutSpriteGroup { glx@9505: byte num_sprites; ///< Number of sprites in the spriteset, used for loading stages truelight@9476: struct DrawTileSprites *dts; truelight@9476: }; truelight@9476: rubidium@9631: struct IndustryProductionSpriteGroup { rubidium@9631: uint8 version; rubidium@9631: uint16 substract_input[3]; rubidium@9631: uint16 add_output[2]; rubidium@9631: uint8 again; rubidium@9631: }; rubidium@9631: peter1138@3668: /* List of different sprite group types */ rubidium@6574: enum SpriteGroupType { peter1138@3664: SGT_INVALID, peter1138@3664: SGT_REAL, peter1138@3664: SGT_DETERMINISTIC, peter1138@3664: SGT_RANDOMIZED, peter1138@3664: SGT_CALLBACK, peter1138@3664: SGT_RESULT, truelight@9476: SGT_TILELAYOUT, rubidium@9631: SGT_INDUSTRY_PRODUCTION, rubidium@6574: }; peter1138@3664: peter1138@3668: /* Common wrapper for all the different sprite group types */ peter1138@3664: struct SpriteGroup { peter1138@3664: SpriteGroupType type; peter1138@3664: peter1138@3664: union { peter1138@3664: RealSpriteGroup real; peter1138@3664: DeterministicSpriteGroup determ; peter1138@3664: RandomizedSpriteGroup random; peter1138@3664: CallbackResultSpriteGroup callback; peter1138@3664: ResultSpriteGroup result; truelight@9476: TileLayoutSpriteGroup layout; rubidium@9631: IndustryProductionSpriteGroup indprod; peter1138@3664: } g; peter1138@3664: }; peter1138@3664: peter1138@3664: rubidium@6573: SpriteGroup *AllocateSpriteGroup(); rubidium@6573: void InitializeSpriteGroupPool(); peter1138@3595: peter1138@3677: rubidium@6574: struct ResolverObject { rubidium@9694: CallbackID callback; peter1138@3677: uint32 callback_param1; peter1138@3677: uint32 callback_param2; rubidium@9826: bool procedure_call; ///< true if we are currently resolving a var 0x7E procedure result. peter1138@3677: peter1138@3677: byte trigger; rubidium@9826: byte count; peter1138@3677: uint32 last_value; peter1138@3677: uint32 reseed; peter1138@3677: VarSpriteGroupScope scope; peter1138@3677: peter1138@4056: bool info_view; ///< Indicates if the item is being drawn in an info window peter1138@4056: rubidium@9703: BaseStorageArray *psa; ///< The persistent storage array of this resolved object. rubidium@9703: peter1138@3677: union { peter1138@3677: struct { peter1138@3677: const struct Vehicle *self; peter1138@3677: const struct Vehicle *parent; peter1138@4057: EngineID self_type; peter1138@3677: } vehicle; peter1138@3677: struct { peter1138@3677: TileIndex tile; rubidium@9620: } canal; rubidium@9620: struct { rubidium@9620: TileIndex tile; peter1138@3677: const struct Station *st; peter1138@3677: const struct StationSpec *statspec; peter1138@4817: CargoID cargo_type; peter1138@3677: } station; truelight@9476: struct { truelight@9476: TileIndex tile; truelight@9476: Town *town; truelight@9476: HouseID house_id; truelight@9476: } house; truelight@9517: struct { glx@9626: TileIndex tile; glx@9626: Industry *ind; rubidium@9628: IndustryGfx gfx; rubidium@9724: IndustryType type; glx@9626: } industry; glx@9626: struct { truelight@9517: const struct CargoSpec *cs; truelight@9517: } cargo; glx@9732: struct { glx@9732: CargoID cargo_type; glx@9732: uint8 default_selection; glx@9732: IndustryType src_industry; glx@9732: IndustryType dst_industry; glx@9732: uint8 distance; glx@9732: AIConstructionEvent event; glx@9732: uint8 count; glx@9732: uint8 station_size; glx@9732: } generic; peter1138@3720: } u; peter1138@3677: peter1138@3677: uint32 (*GetRandomBits)(const struct ResolverObject*); peter1138@3677: uint32 (*GetTriggers)(const struct ResolverObject*); peter1138@3677: void (*SetTriggers)(const struct ResolverObject*, int); peter1138@3893: uint32 (*GetVariable)(const struct ResolverObject*, byte, byte, bool*); peter1138@3734: const SpriteGroup *(*ResolveReal)(const struct ResolverObject*, const SpriteGroup*); rubidium@9826: rubidium@9826: ResolverObject() : procedure_call(false) { } rubidium@6574: }; peter1138@3677: peter1138@3677: peter1138@3677: /* Base sprite group resolver */ peter1138@3677: const SpriteGroup *Resolve(const SpriteGroup *group, ResolverObject *object); peter1138@3677: peter1138@3677: peter1138@3595: #endif /* NEWGRF_SPRITEGROUP_H */