peter1138@3595: /* $Id$ */ peter1138@3595: belugas@6674: /** @file newgrf_spritegroup.h */ belugas@6674: peter1138@3595: #ifndef NEWGRF_SPRITEGROUP_H peter1138@3595: #define NEWGRF_SPRITEGROUP_H peter1138@3595: maedhros@6658: #include "town.h" belugas@7331: #include "industry.h" rubidium@8105: #include "newgrf_storage.h" peter1138@3664: rubidium@7664: /** rubidium@7664: * Gets the value of a so-called newgrf "register". rubidium@7664: * @param i index of the register rubidium@7664: * @pre i < 0x110 rubidium@7664: * @return the value of the register rubidium@7664: */ rubidium@7664: static inline uint32 GetRegister(uint i) rubidium@7664: { rubidium@8112: extern TemporaryStorageArray _temp_store; rubidium@8105: return _temp_store.Get(i); rubidium@7664: } rubidium@7664: 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 { belugas@6674: /* Loaded = in motion, loading = not moving belugas@6674: * Each group contains several spritesets, for various loading stages */ peter1138@3664: belugas@6674: /* XXX: For stations the meaning is different - loaded is for stations belugas@6674: * with small amount of cargo whilst loading is for stations with a lot belugas@6674: * 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, belugas@6674: /* Engine of consists for vehicles, city for stations. */ peter1138@3664: VSG_SCOPE_PARENT, 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 { belugas@6674: DSGA_OP_ADD, ///< a + b belugas@6674: DSGA_OP_SUB, ///< a - b belugas@6674: DSGA_OP_SMIN, ///< (signed) min(a, b) belugas@6674: DSGA_OP_SMAX, ///< (signed) max(a, b) belugas@6674: DSGA_OP_UMIN, ///< (unsigned) min(a, b) belugas@6674: DSGA_OP_UMAX, ///< (unsigned) max(a, b) belugas@6674: DSGA_OP_SDIV, ///< (signed) a / b belugas@6674: DSGA_OP_SMOD, ///< (signed) a % b belugas@6674: DSGA_OP_UDIV, ///< (unsigned) a / b belugas@6674: DSGA_OP_UMOD, ///< (unsigned) a & b belugas@6674: DSGA_OP_MUL, ///< a * b belugas@6674: DSGA_OP_AND, ///< a & b belugas@6674: DSGA_OP_OR, ///< a | b belugas@6674: DSGA_OP_XOR, ///< a ^ b peter1138@7017: DSGA_OP_STO, ///< store a into temporary storage, indexed by b. return a peter1138@7017: DSGA_OP_RST, ///< return b rubidium@8106: DSGA_OP_STOP, ///< store a into persistent storage, indexed by b, return a rubidium@8108: DSGA_OP_ROR, ///< rotate a b positions to the right rubidium@8108: DSGA_OP_SCMP, ///< (signed) comparision (a < b -> 0, a == b = 1, a > b = 2) rubidium@8108: 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: belugas@6674: /* 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 { belugas@6674: VarSpriteGroupScope var_scope; ///< Take this object: peter1138@3664: belugas@6674: RandomizedSpriteGroupCompareMode cmp_mode; ///< Check for these triggers: peter1138@3664: byte triggers; peter1138@3664: belugas@6674: byte lowest_randbit; ///< Look for this in the per-object randomized bitmask: belugas@6674: byte num_groups; ///< must be power of 2 peter1138@3664: belugas@6674: 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: maedhros@6658: struct TileLayoutSpriteGroup { belugas@6674: byte num_sprites; ///< Number of sprites in the spriteset, used for loading stages maedhros@6658: struct DrawTileSprites *dts; maedhros@6658: }; maedhros@6658: rubidium@7664: struct IndustryProductionSpriteGroup { rubidium@7664: uint8 version; rubidium@7664: uint16 substract_input[3]; rubidium@7664: uint16 add_output[2]; rubidium@7664: uint8 again; rubidium@7664: }; rubidium@7664: 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, maedhros@6658: SGT_TILELAYOUT, rubidium@7664: 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; maedhros@6658: TileLayoutSpriteGroup layout; rubidium@7664: 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@7823: CallbackID callback; peter1138@3677: uint32 callback_param1; peter1138@3677: uint32 callback_param2; peter1138@3677: peter1138@3677: byte trigger; 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@8106: BaseStorageArray *psa; ///< The persistent storage array of this resolved object. rubidium@8106: 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; peter1138@7079: } canal; peter1138@7079: struct { peter1138@7079: TileIndex tile; peter1138@3677: const struct Station *st; peter1138@3677: const struct StationSpec *statspec; peter1138@4817: CargoID cargo_type; peter1138@3677: } station; maedhros@6658: struct { maedhros@6658: TileIndex tile; maedhros@6658: Town *town; maedhros@6658: HouseID house_id; maedhros@6658: } house; peter1138@6691: struct { belugas@7331: TileIndex tile; belugas@7331: Industry *ind; belugas@7380: IndustryGfx gfx; belugas@7331: } industry; belugas@7331: struct { rubidium@7703: TileIndex tile; rubidium@7703: const IndustrySpec *spec; rubidium@7703: uint itspec_index; rubidium@7703: } industry_location; rubidium@7703: struct { peter1138@6691: const struct CargoSpec *cs; peter1138@6691: } cargo; 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@6574: }; peter1138@3677: peter1138@3677: peter1138@3677: /* Base sprite group resolver */ rubidium@8105: const SpriteGroup *Resolve(const SpriteGroup *group, ResolverObject *object); peter1138@3677: peter1138@3677: peter1138@3595: #endif /* NEWGRF_SPRITEGROUP_H */